@kangsicj/dcinsideenhancer 1.1.1 โ 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +4 -1
- package/README.md +4 -1
- package/dist/DCInsideEnhancer.meta.js +1 -1
- package/dist/DCInsideEnhancer.user.js +1007 -9
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -53,6 +53,7 @@ One userscript for DCInside on mobile and PC: smart blocking, endless lists, ima
|
|
|
53
53
|
- Hide **post tags**, notices, polls, ads and sticker-only comments
|
|
54
54
|
- Catches posts whose **body** contains a blocked word, right in the list
|
|
55
55
|
- Blocked by mistake? **Undo** straight from the notification
|
|
56
|
+
- A **cleanup helper** suggests blocks that never trigger and overlapping words
|
|
56
57
|
|
|
57
58
|
</td>
|
|
58
59
|
<td width="50%" valign="top">
|
|
@@ -62,7 +63,8 @@ One userscript for DCInside on mobile and PC: smart blocking, endless lists, ima
|
|
|
62
63
|
- Gaps left by blocked posts are **refilled** from the next page
|
|
63
64
|
- Come back from a post and you're **right where you left off**
|
|
64
65
|
- Cleaner read-post colors and a back-to-top button
|
|
65
|
-
- Keyboard shortcuts on PC: **J/K** next/previous post, Enter to open, S to scrap, / to search
|
|
66
|
+
- Keyboard shortcuts on PC: **J/K** next/previous post, Enter to open, P to preview, S to scrap, / to search
|
|
67
|
+
- On PC, hover a title to **preview the whole post** โ blocked images and words stay hidden there too
|
|
66
68
|
|
|
67
69
|
</td>
|
|
68
70
|
</tr>
|
|
@@ -101,6 +103,7 @@ One userscript for DCInside on mobile and PC: smart blocking, endless lists, ima
|
|
|
101
103
|
#### ๐ Alerts ยท ๐ Scraps ยท ๐ Theme
|
|
102
104
|
- Comment and reply alerts appear as **bubbles** by the button โ tap to open, swipe to dismiss
|
|
103
105
|
- Unread count on the button; past alerts and recent galleries in one view
|
|
106
|
+
- On PC, optional **desktop notifications** while you're on another tab
|
|
104
107
|
- Unlimited scraps, right in the floating menu
|
|
105
108
|
- Follows your device's dark mode automatically
|
|
106
109
|
- Every feature can be switched on or off
|
package/README.md
CHANGED
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
- **๋ง๋จธ๋ฆฌ**, ๊ณต์งยท์ค๋ฌธยทAD, ๋์์ฝ๋ง ์๋ ๋๊ธ ์จ๊น
|
|
54
54
|
- ๋ณธ๋ฌธ์๋ง ๊ธ์ง์ด๊ฐ ์๋ ๊ธ๋ **๋ชฉ๋ก์์ ๋ฏธ๋ฆฌ** ๊ฑธ๋ฌ ๋
|
|
55
55
|
- ์ค์๋ก ๋ง์๋ค๋ฉด ์๋ฆผ์์ ๋ฐ๋ก **์คํ ์ทจ์**
|
|
56
|
+
- **์ ๋ฆฌ ๋์ฐ๋ฏธ**๊ฐ ์ค๋ ์ ์ฐ์ธ ์ฐจ๋จยท๊ฒน์น๋ ๋จ์ด๋ฅผ ๊ณจ๋ผ ์ค
|
|
56
57
|
|
|
57
58
|
</td>
|
|
58
59
|
<td width="50%" valign="top">
|
|
@@ -62,7 +63,8 @@
|
|
|
62
63
|
- ์ฐจ๋จ์ผ๋ก ๋น ์๋ฆฌ๋ ๋ค์ ํ์ด์ง ๊ธ๋ก **์ฑ์ ๋ **
|
|
63
64
|
- ๊ธ์ ๋ณด๊ณ ๋์์ค๋ฉด **๋ณด๋ ์์น ๊ทธ๋๋ก**
|
|
64
65
|
- ์ฝ์ ๊ธ ์ ์ ๋ฆฌ, ๋งจ ์๋ก ๋ฒํผ
|
|
65
|
-
- PC ํค๋ณด๋ ๋จ์ถํค: **J/K** ๋ค์ยท์ด์ ๊ธ, Enter ์ด๊ธฐ, S ์คํฌ๋ฉ, / ๊ฒ์
|
|
66
|
+
- PC ํค๋ณด๋ ๋จ์ถํค: **J/K** ๋ค์ยท์ด์ ๊ธ, Enter ์ด๊ธฐ, P ๋ฏธ๋ฆฌ๋ณด๊ธฐ, S ์คํฌ๋ฉ, / ๊ฒ์
|
|
67
|
+
- PC๋ ์ ๋ชฉ์ ๋ง์ฐ์ค๋ฅผ ์ฌ๋ฆฌ๋ฉด **๊ธ ์ ์ฒด ๋ฏธ๋ฆฌ๋ณด๊ธฐ** โ ์ฐจ๋จ ์ด๋ฏธ์งยท๋จ์ด๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์๋ ๊ฐ๋ฆผ
|
|
66
68
|
|
|
67
69
|
</td>
|
|
68
70
|
</tr>
|
|
@@ -101,6 +103,7 @@
|
|
|
101
103
|
#### ๐ ์๋ฆผ ยท ๐ ์คํฌ๋ฉ ยท ๐ ํ
๋ง
|
|
102
104
|
- ๋๊ธยท๋ต๊ธ ์๋ฆผ์ ๋ฒํผ ๊ณ **๋งํ์ **์ผ๋ก โ ๋๋ฅด๋ฉด ์ด๋, ๋ฐ๋ฉด ๋ซํ
|
|
103
105
|
- ์ฝ์ง ์์ ์๋ฆผ ์๋ฅผ ๋ฒํผ์ ํ์, ์ง๋ ์๋ฆผ๊ณผ ์ต๊ทผ ๊ฐค๋ฌ๋ฆฌ๋ ํ ํ๋ฉด์
|
|
106
|
+
- PC๋ ๋ค๋ฅธ ํญ์ ๋ณผ ๋ **๊ธฐ๊ธฐ ์๋ฆผ**์ผ๋ก๋ (์ ํ)
|
|
104
107
|
- ๊ฐ์ ์ ํ ์๋ ์คํฌ๋ฉ, ํ๋กํ
๋ฉ๋ด์์ ๋ฐ๋ก ๋ณด๊ธฐ
|
|
105
108
|
- ๊ธฐ๊ธฐ ๋คํฌ ๋ชจ๋์ ๋ง์ถฐ ์ฌ์ดํธ ์ผ๊ฐ ๋ชจ๋ ์๋ ์ ํ
|
|
106
109
|
- ๋ชจ๋ ์ค์ ์ ์ผ๊ณ ๋ ์ ์์
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @name DCInside Enhancer
|
|
3
3
|
// @name:ko ๋์ ์ธํธ์
|
|
4
4
|
// @namespace https://github.com/kangsicj/DCInsideEnhancer
|
|
5
|
-
// @version 1.
|
|
5
|
+
// @version 1.2.0
|
|
6
6
|
// @description DCInside filter & enhancer โ mobile & PC. Block users/words/heads/notices/images & GIFs across posts, infinite list, zoom viewer, theme sync, encrypted multi-device sync.
|
|
7
7
|
// @description:ko ๋์์ธ์ฌ์ด๋ ์ฐจ๋จยทํธ์ ๊ธฐ๋ฅ (๋ชจ๋ฐ์ผยทPC) - ์ ์ ยท๋จ์ด(์ ๋ชฉ/๋ณธ๋ฌธ)ยท๋ง๋จธ๋ฆฌยท๊ณต์ง ์ฐจ๋จ, ๊ฐ์/๋น์ทํ ์ด๋ฏธ์งยท์์งค ๋ชจ๋ ๊ธ ์ฐจ๋จ, ๋์์ฝ ์ ๊ฑฐ, ์ฐจ๋จ ๋ฏธ๋์ด ๋ฐ์ดํฐ ์ ์ฝ, ๋ชฉ๋ก ์๋ ๋ณด์ถฉยท๋ฌดํ ์คํฌ๋กคยท๋ค๋ก ๊ฐ๊ธฐ ์์น ๋ณต์, ์คํฌ๋ฉ, ์ด๋ฏธ์ง ํ๋๋ทฐ ๊ฐ์ , ์ผ๊ฐ๋ชจ๋ ์๋ ์ฐ๋, ์ํธํ ๊ธฐ๊ธฐ ๊ฐ ๋๊ธฐํ
|
|
8
8
|
// @author kangsicj
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// @name DCInside Enhancer
|
|
3
3
|
// @name:ko ๋์ ์ธํธ์
|
|
4
4
|
// @namespace https://github.com/kangsicj/DCInsideEnhancer
|
|
5
|
-
// @version 1.
|
|
5
|
+
// @version 1.2.0
|
|
6
6
|
// @description DCInside filter & enhancer โ mobile & PC. Block users/words/heads/notices/images & GIFs across posts, infinite list, zoom viewer, theme sync, encrypted multi-device sync.
|
|
7
7
|
// @description:ko ๋์์ธ์ฌ์ด๋ ์ฐจ๋จยทํธ์ ๊ธฐ๋ฅ (๋ชจ๋ฐ์ผยทPC) - ์ ์ ยท๋จ์ด(์ ๋ชฉ/๋ณธ๋ฌธ)ยท๋ง๋จธ๋ฆฌยท๊ณต์ง ์ฐจ๋จ, ๊ฐ์/๋น์ทํ ์ด๋ฏธ์งยท์์งค ๋ชจ๋ ๊ธ ์ฐจ๋จ, ๋์์ฝ ์ ๊ฑฐ, ์ฐจ๋จ ๋ฏธ๋์ด ๋ฐ์ดํฐ ์ ์ฝ, ๋ชฉ๋ก ์๋ ๋ณด์ถฉยท๋ฌดํ ์คํฌ๋กคยท๋ค๋ก ๊ฐ๊ธฐ ์์น ๋ณต์, ์คํฌ๋ฉ, ์ด๋ฏธ์ง ํ๋๋ทฐ ๊ฐ์ , ์ผ๊ฐ๋ชจ๋ ์๋ ์ฐ๋, ์ํธํ ๊ธฐ๊ธฐ ๊ฐ ๋๊ธฐํ
|
|
8
8
|
// @author kangsicj
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
// 0. ์ค์ ยท์์
|
|
76
76
|
// =========================================================
|
|
77
77
|
|
|
78
|
-
const SCRIPT_VERSION = '1.
|
|
78
|
+
const SCRIPT_VERSION = '1.2.0';
|
|
79
79
|
const PROJECT_URL = 'https://github.com/kangsicj/DCInsideEnhancer';
|
|
80
80
|
const DONATE_URL = 'https://fairy.hada.io/@jinny#support';
|
|
81
81
|
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
recent: 'dc_recent_galls',
|
|
109
109
|
recentNative: 'dc_recent_native',
|
|
110
110
|
searchHistory: 'dc_search_history',
|
|
111
|
+
blockHits: 'dc_block_hits',
|
|
111
112
|
alarmSeen: 'dc_alarm_marks',
|
|
112
113
|
seenVersion: 'dc_seen_version'
|
|
113
114
|
};
|
|
@@ -224,6 +225,8 @@
|
|
|
224
225
|
alarmBubble: true,
|
|
225
226
|
alarmKeepPolling: true,
|
|
226
227
|
keyboardShortcuts: true,
|
|
228
|
+
hoverPreview: true,
|
|
229
|
+
alarmSystemNotify: false,
|
|
227
230
|
pcFitWidth: true,
|
|
228
231
|
autoHideScrollbar: true,
|
|
229
232
|
scrapIntercept: true,
|
|
@@ -1851,6 +1854,159 @@
|
|
|
1851
1854
|
|
|
1852
1855
|
#dc-custom-modal .dc-row.dc-row-new .dc-row-title { font-weight: 800; }
|
|
1853
1856
|
|
|
1857
|
+
#dc-preview {
|
|
1858
|
+
position: fixed;
|
|
1859
|
+
z-index: 99997;
|
|
1860
|
+
display: flex;
|
|
1861
|
+
flex-direction: column;
|
|
1862
|
+
box-sizing: border-box;
|
|
1863
|
+
border: 1px solid var(--dc-border);
|
|
1864
|
+
border-radius: 14px;
|
|
1865
|
+
background: var(--dc-surface);
|
|
1866
|
+
color: var(--dc-text);
|
|
1867
|
+
box-shadow: var(--dc-shadow);
|
|
1868
|
+
font-size: 14px;
|
|
1869
|
+
line-height: 1.65;
|
|
1870
|
+
opacity: 0;
|
|
1871
|
+
visibility: hidden;
|
|
1872
|
+
pointer-events: none;
|
|
1873
|
+
transform: translateY(4px);
|
|
1874
|
+
transition: opacity .15s ease, transform .15s ease, visibility 0s linear .15s;
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
#dc-preview.show {
|
|
1878
|
+
opacity: 1;
|
|
1879
|
+
visibility: visible;
|
|
1880
|
+
pointer-events: auto;
|
|
1881
|
+
transform: none;
|
|
1882
|
+
transition: opacity .15s ease, transform .15s ease, visibility 0s;
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
#dc-preview .dc-pv-head {
|
|
1886
|
+
flex: 0 0 auto;
|
|
1887
|
+
padding: 14px 16px 10px;
|
|
1888
|
+
border-bottom: 1px solid var(--dc-border);
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
#dc-preview .dc-pv-title {
|
|
1892
|
+
font-size: 15px;
|
|
1893
|
+
font-weight: 800;
|
|
1894
|
+
line-height: 1.4;
|
|
1895
|
+
word-break: break-all;
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
#dc-preview .dc-pv-meta {
|
|
1899
|
+
margin-top: 3px;
|
|
1900
|
+
color: var(--dc-text-dim);
|
|
1901
|
+
font-size: 12px;
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
#dc-preview .dc-pv-actions {
|
|
1905
|
+
display: flex;
|
|
1906
|
+
flex-wrap: wrap;
|
|
1907
|
+
align-items: center;
|
|
1908
|
+
gap: 6px;
|
|
1909
|
+
margin-top: 8px;
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1912
|
+
#dc-preview .dc-btn {
|
|
1913
|
+
display: inline-flex;
|
|
1914
|
+
align-items: center;
|
|
1915
|
+
justify-content: center;
|
|
1916
|
+
box-sizing: border-box;
|
|
1917
|
+
height: 28px;
|
|
1918
|
+
padding: 0 11px;
|
|
1919
|
+
border: 1px solid var(--dc-border);
|
|
1920
|
+
border-radius: 999px;
|
|
1921
|
+
background: var(--dc-surface-2);
|
|
1922
|
+
color: var(--dc-text);
|
|
1923
|
+
font-size: 12px;
|
|
1924
|
+
font-weight: 700;
|
|
1925
|
+
line-height: 1;
|
|
1926
|
+
text-decoration: none;
|
|
1927
|
+
cursor: pointer;
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
#dc-preview .dc-btn:hover { border-color: var(--dc-accent-ink); color: var(--dc-accent-ink); }
|
|
1931
|
+
#dc-preview .dc-btn.danger-ghost { color: var(--dc-danger-ink); }
|
|
1932
|
+
#dc-preview .dc-btn.dc-pv-close { margin-left: auto; width: 28px; padding: 0; }
|
|
1933
|
+
|
|
1934
|
+
#dc-preview .dc-pv-body {
|
|
1935
|
+
flex: 1 1 auto;
|
|
1936
|
+
min-height: 60px;
|
|
1937
|
+
padding: 12px 16px 18px;
|
|
1938
|
+
overflow-y: auto;
|
|
1939
|
+
overscroll-behavior: contain;
|
|
1940
|
+
word-break: break-word;
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
#dc-preview .dc-pv-body img,
|
|
1944
|
+
#dc-preview .dc-pv-body video { max-width: 100% !important; height: auto !important; border-radius: 6px; }
|
|
1945
|
+
#dc-preview .dc-pv-body p { margin: 0 0 4px; }
|
|
1946
|
+
#dc-preview .dc-pv-body { overflow-x: hidden; overflow-wrap: anywhere; }
|
|
1947
|
+
#dc-preview .dc-pv-body .write_div,
|
|
1948
|
+
#dc-preview .dc-pv-body [style*="width"] { width: auto !important; max-width: 100% !important; }
|
|
1949
|
+
#dc-preview .dc-pv-body * { white-space: normal !important; }
|
|
1950
|
+
#dc-preview .dc-pv-body pre, #dc-preview .dc-pv-body pre * { white-space: pre-wrap !important; }
|
|
1951
|
+
#dc-preview .dc-pv-body a { color: var(--dc-accent-ink); }
|
|
1952
|
+
#dc-preview .dc-pv-body table { max-width: 100%; }
|
|
1953
|
+
|
|
1954
|
+
html.dc-dark #dc-preview .dc-pv-body [style*="background"] { background: transparent !important; }
|
|
1955
|
+
html.dc-dark #dc-preview .dc-pv-body [style*="color: rgb(0, 0, 0)"],
|
|
1956
|
+
html.dc-dark #dc-preview .dc-pv-body [style*="color:#000"],
|
|
1957
|
+
html.dc-dark #dc-preview .dc-pv-body [style*="color: #000"],
|
|
1958
|
+
html.dc-dark #dc-preview .dc-pv-body [style*="color:black"],
|
|
1959
|
+
html.dc-dark #dc-preview .dc-pv-body font[color="#000000"] { color: inherit !important; }
|
|
1960
|
+
|
|
1961
|
+
#dc-preview .dc-pv-loading,
|
|
1962
|
+
#dc-preview .dc-pv-note {
|
|
1963
|
+
padding: 10px 0;
|
|
1964
|
+
color: var(--dc-text-dim);
|
|
1965
|
+
font-size: 13px;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
#dc-preview .dc-pv-loading::before {
|
|
1969
|
+
content: '';
|
|
1970
|
+
display: inline-block;
|
|
1971
|
+
width: 12px;
|
|
1972
|
+
height: 12px;
|
|
1973
|
+
margin-right: 8px;
|
|
1974
|
+
border: 2px solid var(--dc-border);
|
|
1975
|
+
border-top-color: var(--dc-accent-ink);
|
|
1976
|
+
border-radius: 50%;
|
|
1977
|
+
vertical-align: -1px;
|
|
1978
|
+
animation: dc-spin .7s linear infinite;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
@keyframes dc-spin { to { transform: rotate(360deg); } }
|
|
1982
|
+
|
|
1983
|
+
#dc-preview .dc-pv-warn {
|
|
1984
|
+
display: flex;
|
|
1985
|
+
flex-wrap: wrap;
|
|
1986
|
+
align-items: center;
|
|
1987
|
+
gap: 8px;
|
|
1988
|
+
padding: 10px 12px;
|
|
1989
|
+
border-radius: 10px;
|
|
1990
|
+
background: var(--dc-danger-soft);
|
|
1991
|
+
color: var(--dc-danger-ink);
|
|
1992
|
+
font-size: 13px;
|
|
1993
|
+
font-weight: 700;
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
#dc-preview .dc-pv-blocked {
|
|
1997
|
+
margin: 6px 0;
|
|
1998
|
+
padding: 14px;
|
|
1999
|
+
border: 1px dashed var(--dc-border);
|
|
2000
|
+
border-radius: 8px;
|
|
2001
|
+
color: var(--dc-text-dim);
|
|
2002
|
+
font-size: 12px;
|
|
2003
|
+
text-align: center;
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
#dc-preview .dc-pv-embed { display: inline-block; margin: 6px 0; font-weight: 700; }
|
|
2007
|
+
|
|
2008
|
+
.dc-pv-anchor { text-decoration: underline !important; text-decoration-color: var(--dc-accent-ink) !important; }
|
|
2009
|
+
|
|
1854
2010
|
.dc-key-cursor { outline: 2px solid var(--dc-accent-ink) !important; outline-offset: -2px; background: var(--dc-accent-soft) !important; }
|
|
1855
2011
|
|
|
1856
2012
|
#dc-custom-modal .dc-about {
|
|
@@ -6462,7 +6618,97 @@
|
|
|
6462
6618
|
|
|
6463
6619
|
const currentPostKey = () => extractPostPath(location.href) || location.pathname;
|
|
6464
6620
|
|
|
6465
|
-
const
|
|
6621
|
+
const HIT_DAY_MS = 86400000;
|
|
6622
|
+
const hitToday = () => Math.floor(Date.now() / HIT_DAY_MS);
|
|
6623
|
+
|
|
6624
|
+
const readBlockHits = () => {
|
|
6625
|
+
const stored = readObject(STORAGE.blockHits);
|
|
6626
|
+
|
|
6627
|
+
return {
|
|
6628
|
+
since: Number(stored.since) || hitToday(),
|
|
6629
|
+
k: stored.k && typeof stored.k === 'object' && !Array.isArray(stored.k) ? { ...stored.k } : {}
|
|
6630
|
+
};
|
|
6631
|
+
};
|
|
6632
|
+
|
|
6633
|
+
let blockHits = readBlockHits();
|
|
6634
|
+
let blockHitsDirty = !readObject(STORAGE.blockHits).since;
|
|
6635
|
+
let blockHitsTimer = null;
|
|
6636
|
+
|
|
6637
|
+
const blockHitKeys = () => [
|
|
6638
|
+
...blockedUsers,
|
|
6639
|
+
...blockedTitles.map(word => `t:${word}`),
|
|
6640
|
+
...blockedKeywords.map(word => `w:${word}`)
|
|
6641
|
+
];
|
|
6642
|
+
|
|
6643
|
+
const flushBlockHits = () => {
|
|
6644
|
+
clearTimeout(blockHitsTimer);
|
|
6645
|
+
blockHitsTimer = null;
|
|
6646
|
+
|
|
6647
|
+
if (!blockHitsDirty) {
|
|
6648
|
+
return;
|
|
6649
|
+
}
|
|
6650
|
+
|
|
6651
|
+
blockHitsDirty = false;
|
|
6652
|
+
|
|
6653
|
+
const today = hitToday();
|
|
6654
|
+
const next = {};
|
|
6655
|
+
|
|
6656
|
+
blockHitKeys().forEach(key => {
|
|
6657
|
+
next[key] = Number(blockHits.k[key]) || today;
|
|
6658
|
+
});
|
|
6659
|
+
|
|
6660
|
+
blockHits = { since: blockHits.since, k: next };
|
|
6661
|
+
writeJson(STORAGE.blockHits, blockHits);
|
|
6662
|
+
};
|
|
6663
|
+
|
|
6664
|
+
const scheduleBlockHitsFlush = () => {
|
|
6665
|
+
blockHitsDirty = true;
|
|
6666
|
+
|
|
6667
|
+
if (!blockHitsTimer) {
|
|
6668
|
+
blockHitsTimer = setTimeout(flushBlockHits, 20000);
|
|
6669
|
+
}
|
|
6670
|
+
};
|
|
6671
|
+
|
|
6672
|
+
const noteBlockHit = reason => {
|
|
6673
|
+
if (!reason) {
|
|
6674
|
+
return reason;
|
|
6675
|
+
}
|
|
6676
|
+
|
|
6677
|
+
const keys = reason.type === 'user'
|
|
6678
|
+
? reason.userKeys || []
|
|
6679
|
+
: reason.type === 'title'
|
|
6680
|
+
? [`t:${reason.word}`]
|
|
6681
|
+
: reason.type === 'keyword'
|
|
6682
|
+
? [blockedTitles.includes(reason.word) && !blockedKeywords.includes(reason.word) ? `t:${reason.word}` : `w:${reason.word}`]
|
|
6683
|
+
: [];
|
|
6684
|
+
const today = hitToday();
|
|
6685
|
+
|
|
6686
|
+
keys.forEach(key => {
|
|
6687
|
+
if (blockHits.k[key] !== today) {
|
|
6688
|
+
blockHits.k[key] = today;
|
|
6689
|
+
scheduleBlockHitsFlush();
|
|
6690
|
+
}
|
|
6691
|
+
});
|
|
6692
|
+
|
|
6693
|
+
return reason;
|
|
6694
|
+
};
|
|
6695
|
+
|
|
6696
|
+
window.addEventListener('pagehide', flushBlockHits);
|
|
6697
|
+
document.addEventListener('visibilitychange', () => {
|
|
6698
|
+
if (document.visibilityState === 'hidden') {
|
|
6699
|
+
flushBlockHits();
|
|
6700
|
+
}
|
|
6701
|
+
});
|
|
6702
|
+
|
|
6703
|
+
storageWriteListeners.push(key => {
|
|
6704
|
+
if (key === STORAGE.users || key === STORAGE.keywords || key === STORAGE.titles) {
|
|
6705
|
+
scheduleBlockHitsFlush();
|
|
6706
|
+
}
|
|
6707
|
+
});
|
|
6708
|
+
|
|
6709
|
+
const computeBlockReason = el => noteBlockHit(computeBlockReasonRaw(el));
|
|
6710
|
+
|
|
6711
|
+
const computeBlockReasonRaw = el => {
|
|
6466
6712
|
const hits = buildBlockKeys({
|
|
6467
6713
|
nickname: el.dataset.dcNick || '',
|
|
6468
6714
|
ip: el.dataset.dcIp || '',
|
|
@@ -9987,6 +10233,7 @@
|
|
|
9987
10233
|
});
|
|
9988
10234
|
|
|
9989
10235
|
area.appendChild(seg);
|
|
10236
|
+
renderCleanupHelper(area);
|
|
9990
10237
|
(renderBlockSections[blockSection] || renderBlockSections.keywords)(area);
|
|
9991
10238
|
};
|
|
9992
10239
|
|
|
@@ -10173,6 +10420,15 @@
|
|
|
10173
10420
|
off: '์ฌ์ดํธ ๊ธฐ๋ณธ ํ ์ค ์๋ฆผ์ ๊ทธ๋๋ก ์๋๋ค.',
|
|
10174
10421
|
refresh: 'root'
|
|
10175
10422
|
},
|
|
10423
|
+
{
|
|
10424
|
+
group: 'alarm',
|
|
10425
|
+
key: 'alarmSystemNotify',
|
|
10426
|
+
parent: 'alarmBubble',
|
|
10427
|
+
name: '๋ค๋ฅธ ํญ์ ๋ณผ ๋ ๊ธฐ๊ธฐ ์๋ฆผ์ผ๋ก๋ (PC)',
|
|
10428
|
+
on: '์ด ํญ์ ๋ณด๊ณ ์์ง ์์ ๋ ๋์ ์๋ฆผ์ด ์ค๋ฉด ์๋์ฐยท๋งฅ ์๋ฆผ์ผ๋ก ๋์๋๋ค. ๋๋ฅด๋ฉด ์ด ํญ์ผ๋ก ๋์์ ํด๋น ๊ธ๋ก ๊ฐ๋๋ค. ์ฒ์ ์ผค ๋ ๋ธ๋ผ์ฐ์ ๊ฐ ๊ถํ์ ๋ฌป์ต๋๋ค.',
|
|
10429
|
+
off: '์ด ํญ์ ๋ณผ ๋ ๋งํ์ ์ผ๋ก๋ง ์๋ฆฝ๋๋ค.',
|
|
10430
|
+
refresh: 'root'
|
|
10431
|
+
},
|
|
10176
10432
|
{
|
|
10177
10433
|
group: 'alarm',
|
|
10178
10434
|
key: 'alarmKeepPolling',
|
|
@@ -10206,6 +10462,14 @@
|
|
|
10206
10462
|
off: '๋จ์ถํค๋ฅผ ์ฐ์ง ์์ต๋๋ค.',
|
|
10207
10463
|
refresh: 'none'
|
|
10208
10464
|
},
|
|
10465
|
+
{
|
|
10466
|
+
group: 'list',
|
|
10467
|
+
key: 'hoverPreview',
|
|
10468
|
+
name: '์ ๋ชฉ์ ๋ง์ฐ์ค๋ฅผ ์ฌ๋ฆฌ๋ฉด ๊ธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ (PC)',
|
|
10469
|
+
on: '๋ชฉ๋ก ์ ๋ชฉ ์์ ์ ๊น ๋จธ๋ฌด๋ฅด๋ฉด ๊ธ ์ ์ฒด๋ฅผ ์ ์ฐฝ์ ๋ณด์ฌ ์ค๋๋ค. ์ฐฝ ์์์ ์คํฌ๋กคํด ์ฝ๊ณ , ์คํฌ๋ฉยท์์ฑ์ ์ฐจ๋จ๋ ๋ฐ๋ก ํ ์ ์์ต๋๋ค. ์ฐจ๋จํ ์ด๋ฏธ์งยท๋จ์ด๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ์์๋ ๊ฐ๋ฆฝ๋๋ค. ํค๋ณด๋๋ก ๊ณ ๋ฅธ ๊ธ์ P ๋ก ์ฝ๋๋ค.',
|
|
10470
|
+
off: '์ ๋ชฉ์ ๋๋ฌ์ผ ๊ธ์ ๋ด
๋๋ค.',
|
|
10471
|
+
refresh: 'root'
|
|
10472
|
+
},
|
|
10209
10473
|
{
|
|
10210
10474
|
group: 'list',
|
|
10211
10475
|
key: 'autoFillList',
|
|
@@ -10403,6 +10667,20 @@
|
|
|
10403
10667
|
paintAlarmBadge();
|
|
10404
10668
|
}
|
|
10405
10669
|
|
|
10670
|
+
if (item.key === 'hoverPreview' && settings.hoverPreview === false) {
|
|
10671
|
+
closePreview();
|
|
10672
|
+
}
|
|
10673
|
+
|
|
10674
|
+
if (item.key === 'alarmSystemNotify' && settings.alarmSystemNotify === true) {
|
|
10675
|
+
requestSystemNotify().then(granted => {
|
|
10676
|
+
if (!granted) {
|
|
10677
|
+
settings.alarmSystemNotify = false;
|
|
10678
|
+
saveSettings();
|
|
10679
|
+
rerenderModal();
|
|
10680
|
+
}
|
|
10681
|
+
});
|
|
10682
|
+
}
|
|
10683
|
+
|
|
10406
10684
|
break;
|
|
10407
10685
|
|
|
10408
10686
|
case 'log':
|
|
@@ -11626,7 +11904,8 @@
|
|
|
11626
11904
|
scraps: scraps.map(item => ({ ...item })),
|
|
11627
11905
|
settings: syncedSettings(),
|
|
11628
11906
|
recent: collectRecentForSync(),
|
|
11629
|
-
search: collectSearchForSync()
|
|
11907
|
+
search: collectSearchForSync(),
|
|
11908
|
+
hits: collectHitsForSync()
|
|
11630
11909
|
});
|
|
11631
11910
|
|
|
11632
11911
|
const skippedFields = skip => SYNC_PARTS.filter(part => skip.includes(part.key)).flatMap(part => part.fields);
|
|
@@ -11734,7 +12013,8 @@
|
|
|
11734
12013
|
scraps: mergeScraps(local.scraps, base && base.scraps, remote && remote.scraps),
|
|
11735
12014
|
settings: mergeSettings(local.settings, base && base.settings, remote && remote.settings),
|
|
11736
12015
|
recent: mergeRecent(local.recent, base && base.recent, remote && remote.recent),
|
|
11737
|
-
search: mergeSearchHistory(local.search, base && base.search, remote && remote.search)
|
|
12016
|
+
search: mergeSearchHistory(local.search, base && base.search, remote && remote.search),
|
|
12017
|
+
hits: mergeBlockHits(local.hits, remote && remote.hits)
|
|
11738
12018
|
};
|
|
11739
12019
|
|
|
11740
12020
|
skippedFields(skip).forEach(field => {
|
|
@@ -11789,6 +12069,7 @@
|
|
|
11789
12069
|
|
|
11790
12070
|
delete data.recent;
|
|
11791
12071
|
delete data.search;
|
|
12072
|
+
delete data.hits;
|
|
11792
12073
|
|
|
11793
12074
|
return JSON.stringify(data);
|
|
11794
12075
|
};
|
|
@@ -11796,6 +12077,7 @@
|
|
|
11796
12077
|
const applySyncData = data => {
|
|
11797
12078
|
const recentChanged = data && 'recent' in data ? applyRecentFromSync(data.recent) : false;
|
|
11798
12079
|
const searchChanged = data && 'search' in data ? applySearchFromSync(data.search) : false;
|
|
12080
|
+
const hitsChanged = data && 'hits' in data ? applyHitsFromSync(data.hits) : false;
|
|
11799
12081
|
const clean = sanitizeBackup({ app: BACKUP_APP, ...data });
|
|
11800
12082
|
const before = blockSyncData();
|
|
11801
12083
|
|
|
@@ -11850,7 +12132,7 @@
|
|
|
11850
12132
|
refreshAfterBlockChange();
|
|
11851
12133
|
}
|
|
11852
12134
|
|
|
11853
|
-
return changed || recentChanged || searchChanged;
|
|
12135
|
+
return changed || recentChanged || searchChanged || hitsChanged;
|
|
11854
12136
|
};
|
|
11855
12137
|
|
|
11856
12138
|
const saveSyncUndo = (before, incoming, summary, from) => {
|
|
@@ -13751,7 +14033,9 @@
|
|
|
13751
14033
|
let alarmWatchTimer = null;
|
|
13752
14034
|
|
|
13753
14035
|
const checkSiteAlarms = () => {
|
|
13754
|
-
|
|
14036
|
+
const away = document.visibilityState === 'hidden' || (typeof document.hasFocus === 'function' && !document.hasFocus());
|
|
14037
|
+
|
|
14038
|
+
if (settings.alarmBubble === false || (document.visibilityState === 'hidden' && !canSystemNotify())) {
|
|
13755
14039
|
return;
|
|
13756
14040
|
}
|
|
13757
14041
|
|
|
@@ -13779,7 +14063,11 @@
|
|
|
13779
14063
|
writeAlarmMarks({ shown: latest });
|
|
13780
14064
|
}
|
|
13781
14065
|
|
|
13782
|
-
if (fresh.length) {
|
|
14066
|
+
if (fresh.length && away && canSystemNotify()) {
|
|
14067
|
+
showSystemAlarm(fresh[0], fresh.length - 1);
|
|
14068
|
+
}
|
|
14069
|
+
|
|
14070
|
+
if (fresh.length && document.visibilityState !== 'hidden') {
|
|
13783
14071
|
showAlarmBubble(fresh[0], fresh.length > ALARM_BUBBLE_MAX ? fresh.length - 1 : 0);
|
|
13784
14072
|
|
|
13785
14073
|
if (fresh.length > 1 && fresh.length <= ALARM_BUBBLE_MAX) {
|
|
@@ -13990,7 +14278,7 @@
|
|
|
13990
14278
|
|
|
13991
14279
|
// =========================================================
|
|
13992
14280
|
|
|
13993
|
-
const KEY_HELP = 'J/K ๋ค์ยท์ด์ ๊ธ ยท Enter ์ด๊ธฐ ยท S ์คํฌ๋ฉ ยท / ๊ฒ์ ยท B ์ฐจ๋จ ๊ด๋ฆฌ';
|
|
14281
|
+
const KEY_HELP = 'J/K ๋ค์ยท์ด์ ๊ธ ยท Enter ์ด๊ธฐ ยท P ๋ฏธ๋ฆฌ๋ณด๊ธฐ ยท S ์คํฌ๋ฉ ยท / ๊ฒ์ ยท B ์ฐจ๋จ ๊ด๋ฆฌ';
|
|
13994
14282
|
|
|
13995
14283
|
const typingTarget = el =>
|
|
13996
14284
|
!!el && (el.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName) || !!el.closest?.('[contenteditable="true"]'));
|
|
@@ -14091,6 +14379,8 @@
|
|
|
14091
14379
|
} else if (key === 'b' || key === 'B') {
|
|
14092
14380
|
openBlockModal(document.getElementById('dc-custom-fab')?.dataset.dcAlarm ? 'recent' : 'overview');
|
|
14093
14381
|
handled = true;
|
|
14382
|
+
} else if ((key === 'p' || key === 'P') && togglePreviewForCursor()) {
|
|
14383
|
+
handled = true;
|
|
14094
14384
|
} else if (key === '?') {
|
|
14095
14385
|
showToast(`โจ๏ธ ${KEY_HELP}`, { duration: 6000 });
|
|
14096
14386
|
handled = true;
|
|
@@ -14159,6 +14449,713 @@
|
|
|
14159
14449
|
|
|
14160
14450
|
return true;
|
|
14161
14451
|
};
|
|
14452
|
+
|
|
14453
|
+
// =========================================================
|
|
14454
|
+
// 13-4. ์ฐจ๋จ ๋ชฉ๋ก ์ ๋ฆฌ ๋์ฐ๋ฏธ ยท ๊ธฐ๊ธฐ ์๋ฆผ ยท PC ๊ธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
|
|
14455
|
+
// =========================================================
|
|
14456
|
+
|
|
14457
|
+
const collectHitsForSync = () => {
|
|
14458
|
+
flushBlockHits();
|
|
14459
|
+
|
|
14460
|
+
return { since: blockHits.since, k: { ...blockHits.k } };
|
|
14461
|
+
};
|
|
14462
|
+
|
|
14463
|
+
const mergeBlockHits = (local, remote) => {
|
|
14464
|
+
if (!remote || typeof remote !== 'object' || !remote.k) {
|
|
14465
|
+
return local;
|
|
14466
|
+
}
|
|
14467
|
+
|
|
14468
|
+
const k = { ...(remote.k || {}) };
|
|
14469
|
+
|
|
14470
|
+
Object.entries((local && local.k) || {}).forEach(([key, day]) => {
|
|
14471
|
+
k[key] = Math.max(Number(k[key]) || 0, Number(day) || 0);
|
|
14472
|
+
});
|
|
14473
|
+
|
|
14474
|
+
return { since: Math.min(Number(local && local.since) || hitToday(), Number(remote.since) || hitToday()), k };
|
|
14475
|
+
};
|
|
14476
|
+
|
|
14477
|
+
const applyHitsFromSync = data => {
|
|
14478
|
+
if (!data || typeof data !== 'object' || !data.k) {
|
|
14479
|
+
return false;
|
|
14480
|
+
}
|
|
14481
|
+
|
|
14482
|
+
const merged = mergeBlockHits(blockHits, data);
|
|
14483
|
+
|
|
14484
|
+
if (JSON.stringify(merged) === JSON.stringify(blockHits)) {
|
|
14485
|
+
return false;
|
|
14486
|
+
}
|
|
14487
|
+
|
|
14488
|
+
blockHits = merged;
|
|
14489
|
+
blockHitsDirty = true;
|
|
14490
|
+
flushBlockHits();
|
|
14491
|
+
|
|
14492
|
+
return true;
|
|
14493
|
+
};
|
|
14494
|
+
|
|
14495
|
+
// =========================================================
|
|
14496
|
+
|
|
14497
|
+
// =========================================================
|
|
14498
|
+
|
|
14499
|
+
const CLEANUP_IDLE_DAYS = 60;
|
|
14500
|
+
|
|
14501
|
+
const cleanupSuggestions = () => {
|
|
14502
|
+
flushBlockHits();
|
|
14503
|
+
|
|
14504
|
+
const today = hitToday();
|
|
14505
|
+
const tracked = today - blockHits.since;
|
|
14506
|
+
const idle = [];
|
|
14507
|
+
|
|
14508
|
+
if (tracked >= CLEANUP_IDLE_DAYS) {
|
|
14509
|
+
blockHitKeys().forEach(key => {
|
|
14510
|
+
const day = Number(blockHits.k[key]) || today;
|
|
14511
|
+
|
|
14512
|
+
if (today - day >= CLEANUP_IDLE_DAYS) {
|
|
14513
|
+
idle.push({ key, days: today - day });
|
|
14514
|
+
}
|
|
14515
|
+
});
|
|
14516
|
+
}
|
|
14517
|
+
|
|
14518
|
+
const redundant = [];
|
|
14519
|
+
|
|
14520
|
+
blockedKeywords.forEach(word => {
|
|
14521
|
+
const cover = blockedKeywords.find(other => other !== word && other.length < word.length && word.includes(other));
|
|
14522
|
+
|
|
14523
|
+
if (cover) {
|
|
14524
|
+
redundant.push({ key: `w:${word}`, cover });
|
|
14525
|
+
}
|
|
14526
|
+
});
|
|
14527
|
+
|
|
14528
|
+
blockedTitles.forEach(word => {
|
|
14529
|
+
const cover = [...blockedKeywords, ...blockedTitles].find(other => other !== word && other.length < word.length && word.includes(other));
|
|
14530
|
+
|
|
14531
|
+
if (cover) {
|
|
14532
|
+
redundant.push({ key: `t:${word}`, cover });
|
|
14533
|
+
}
|
|
14534
|
+
});
|
|
14535
|
+
|
|
14536
|
+
return { idle: idle.sort((a, b) => b.days - a.days), redundant, tracked };
|
|
14537
|
+
};
|
|
14538
|
+
|
|
14539
|
+
const describeHitKey = key => {
|
|
14540
|
+
if (key.startsWith('w:')) {
|
|
14541
|
+
return { label: key.slice(2), kind: '๋จ์ด' };
|
|
14542
|
+
}
|
|
14543
|
+
|
|
14544
|
+
if (key.startsWith('t:')) {
|
|
14545
|
+
return { label: key.slice(2), kind: '์ ๋ชฉ ๋จ์ด' };
|
|
14546
|
+
}
|
|
14547
|
+
|
|
14548
|
+
const parsed = parseBlockKey(key);
|
|
14549
|
+
|
|
14550
|
+
return { label: parsed.value, kind: BLOCK_TYPE_LABELS[parsed.type] || '์ ์ ' };
|
|
14551
|
+
};
|
|
14552
|
+
|
|
14553
|
+
const removeBlockKeys = keys => {
|
|
14554
|
+
const before = { users: [...blockedUsers], keywords: [...blockedKeywords], titles: [...blockedTitles] };
|
|
14555
|
+
const drop = new Set(keys);
|
|
14556
|
+
|
|
14557
|
+
blockedUsers = blockedUsers.filter(key => !drop.has(key));
|
|
14558
|
+
blockedKeywords = blockedKeywords.filter(word => !drop.has(`w:${word}`));
|
|
14559
|
+
blockedTitles = blockedTitles.filter(word => !drop.has(`t:${word}`));
|
|
14560
|
+
saveUsers();
|
|
14561
|
+
saveKeywords();
|
|
14562
|
+
saveTitles();
|
|
14563
|
+
refreshAfterBlockChange();
|
|
14564
|
+
|
|
14565
|
+
showToast(`๐งน ${keys.length}๊ฐ ์ ๋ฆฌํจ`, {
|
|
14566
|
+
actionLabel: '๋๋๋ฆฌ๊ธฐ',
|
|
14567
|
+
duration: 6000,
|
|
14568
|
+
onAction: () => {
|
|
14569
|
+
blockedUsers = before.users;
|
|
14570
|
+
blockedKeywords = before.keywords;
|
|
14571
|
+
blockedTitles = before.titles;
|
|
14572
|
+
saveUsers();
|
|
14573
|
+
saveKeywords();
|
|
14574
|
+
saveTitles();
|
|
14575
|
+
refreshAfterBlockChange();
|
|
14576
|
+
rerenderModal();
|
|
14577
|
+
}
|
|
14578
|
+
});
|
|
14579
|
+
};
|
|
14580
|
+
|
|
14581
|
+
const renderCleanupHelper = area => {
|
|
14582
|
+
const { idle, redundant, tracked } = cleanupSuggestions();
|
|
14583
|
+
const count = idle.length + redundant.length;
|
|
14584
|
+
const waitDays = Math.max(0, CLEANUP_IDLE_DAYS - tracked);
|
|
14585
|
+
|
|
14586
|
+
if (!count && !waitDays) {
|
|
14587
|
+
return;
|
|
14588
|
+
}
|
|
14589
|
+
|
|
14590
|
+
area.appendChild(makeFoldSection({
|
|
14591
|
+
id: 'cleanup',
|
|
14592
|
+
title: `๐งน ์ ๋ฆฌ ๋์ฐ๋ฏธ${count ? '' : ' ยท ์ค๋น ์ค'}`,
|
|
14593
|
+
count,
|
|
14594
|
+
defaultOpen: false,
|
|
14595
|
+
render: body => {
|
|
14596
|
+
if (waitDays) {
|
|
14597
|
+
body.appendChild(makeNote(`์ด๋ค ์ฐจ๋จ์ด ์ค์ ๋ก ์ฐ์ด๋์ง ๊ธฐ๋ก์ ๋ชจ์ผ๋ ์ค์
๋๋ค. ${waitDays}์ผ ๋ค๋ถํฐ ์ค๋ ์ ๊ฑธ๋ฆฐ ํญ๋ชฉ์ ์ถ์ฒํฉ๋๋ค.`));
|
|
14598
|
+
}
|
|
14599
|
+
|
|
14600
|
+
const group = (title, items, meta) => {
|
|
14601
|
+
if (!items.length) {
|
|
14602
|
+
return;
|
|
14603
|
+
}
|
|
14604
|
+
|
|
14605
|
+
body.appendChild(makeSectionTitle(`${title} ยท ${items.length}๊ฐ`));
|
|
14606
|
+
renderPaged(body, items, item => {
|
|
14607
|
+
const info = describeHitKey(item.key);
|
|
14608
|
+
|
|
14609
|
+
return makeRow({
|
|
14610
|
+
title: info.label,
|
|
14611
|
+
chip: info.kind,
|
|
14612
|
+
chipClass: 'scope',
|
|
14613
|
+
meta: meta(item),
|
|
14614
|
+
actions: [{ label: 'ํด์ ', className: 'on', onClick: () => {
|
|
14615
|
+
removeBlockKeys([item.key]);
|
|
14616
|
+
rerenderModal();
|
|
14617
|
+
} }]
|
|
14618
|
+
});
|
|
14619
|
+
});
|
|
14620
|
+
body.appendChild(makeButton(`${title} ๋ชจ๋ ํด์ `, 'wide', () => {
|
|
14621
|
+
if (confirm(`${title} ${items.length}๊ฐ๋ฅผ ์ฐจ๋จ ๋ชฉ๋ก์์ ๋บ๊น์? (๋ฐ๋ก ๋๋๋ฆด ์ ์์ต๋๋ค)`)) {
|
|
14622
|
+
removeBlockKeys(items.map(item => item.key));
|
|
14623
|
+
rerenderModal();
|
|
14624
|
+
}
|
|
14625
|
+
}));
|
|
14626
|
+
};
|
|
14627
|
+
|
|
14628
|
+
group('ํ์ ์๋ ๋จ์ด', redundant, item => `"${item.cover}" ๊ฐ ์ด๋ฏธ ๊ฑธ๋ฌ ์ค`);
|
|
14629
|
+
group(`${CLEANUP_IDLE_DAYS}์ผ ๋๊ฒ ์ ๊ฑธ๋ฆฐ ํญ๋ชฉ`, idle, item => `${item.days}์ผ ๋์ ๊ฑธ๋ฆฐ ๊ธยท๋๊ธ ์์ (๋ชจ๋ ๊ธฐ๊ธฐ)`);
|
|
14630
|
+
}
|
|
14631
|
+
}));
|
|
14632
|
+
};
|
|
14633
|
+
|
|
14634
|
+
// =========================================================
|
|
14635
|
+
|
|
14636
|
+
// =========================================================
|
|
14637
|
+
|
|
14638
|
+
const systemNotifySupported = () => typeof window.Notification === 'function';
|
|
14639
|
+
|
|
14640
|
+
const canSystemNotify = () =>
|
|
14641
|
+
settings.alarmSystemNotify === true && systemNotifySupported() && window.Notification.permission === 'granted';
|
|
14642
|
+
|
|
14643
|
+
const showSystemAlarm = (item, extra = 0) => {
|
|
14644
|
+
try {
|
|
14645
|
+
const note = new window.Notification(`๋์ ์๋ฆผ ยท ${item.tag}`, {
|
|
14646
|
+
body: extra ? `${item.text}\n์ธ ${extra}๊ฐ` : item.text,
|
|
14647
|
+
tag: `dcx-${item.key}`,
|
|
14648
|
+
silent: false
|
|
14649
|
+
});
|
|
14650
|
+
|
|
14651
|
+
note.onclick = () => {
|
|
14652
|
+
try {
|
|
14653
|
+
window.focus();
|
|
14654
|
+
} catch {
|
|
14655
|
+
}
|
|
14656
|
+
|
|
14657
|
+
note.close();
|
|
14658
|
+
|
|
14659
|
+
if (extra) {
|
|
14660
|
+
openBlockModal('recent');
|
|
14661
|
+
} else {
|
|
14662
|
+
openAlarm(item);
|
|
14663
|
+
}
|
|
14664
|
+
};
|
|
14665
|
+
} catch {
|
|
14666
|
+
}
|
|
14667
|
+
};
|
|
14668
|
+
|
|
14669
|
+
const requestSystemNotify = async () => {
|
|
14670
|
+
if (!systemNotifySupported()) {
|
|
14671
|
+
showToast('์ด ๋ธ๋ผ์ฐ์ ๋ ๊ธฐ๊ธฐ ์๋ฆผ์ ์ง์ํ์ง ์์ต๋๋ค');
|
|
14672
|
+
return false;
|
|
14673
|
+
}
|
|
14674
|
+
|
|
14675
|
+
let permission = window.Notification.permission;
|
|
14676
|
+
|
|
14677
|
+
if (permission === 'default') {
|
|
14678
|
+
try {
|
|
14679
|
+
permission = await window.Notification.requestPermission();
|
|
14680
|
+
} catch {
|
|
14681
|
+
permission = 'denied';
|
|
14682
|
+
}
|
|
14683
|
+
}
|
|
14684
|
+
|
|
14685
|
+
if (permission !== 'granted') {
|
|
14686
|
+
showToast('๐ ๋ธ๋ผ์ฐ์ ์์ ์ด ์ฌ์ดํธ์ ์๋ฆผ์ ํ์ฉํด์ผ ๊ธฐ๊ธฐ ์๋ฆผ์ ๋์ธ ์ ์์ต๋๋ค', { duration: 6000 });
|
|
14687
|
+
return false;
|
|
14688
|
+
}
|
|
14689
|
+
|
|
14690
|
+
showToast('๐ ๋ค๋ฅธ ํญ์ ๋ณด๊ณ ์์ด๋ ๋์ ์๋ฆผ์ ๊ธฐ๊ธฐ ์๋ฆผ์ผ๋ก ๋์๋๋ค');
|
|
14691
|
+
return true;
|
|
14692
|
+
};
|
|
14693
|
+
|
|
14694
|
+
// =========================================================
|
|
14695
|
+
|
|
14696
|
+
// =========================================================
|
|
14697
|
+
|
|
14698
|
+
const PREVIEW_DELAY = 450;
|
|
14699
|
+
const PREVIEW_CACHE_MS = 5 * 60 * 1000;
|
|
14700
|
+
const PREVIEW_CACHE_MAX = 30;
|
|
14701
|
+
const PREVIEW_TITLE_SELECTOR = 'table.gall_list td.gall_tit > a:not(.reply_numbox)';
|
|
14702
|
+
|
|
14703
|
+
const previewCache = new Map();
|
|
14704
|
+
let previewEl = null;
|
|
14705
|
+
let previewKey = '';
|
|
14706
|
+
let previewAnchor = null;
|
|
14707
|
+
let previewHoverTimer = null;
|
|
14708
|
+
let previewCloseTimer = null;
|
|
14709
|
+
|
|
14710
|
+
const previewEnabled = () => IS_PC_SITE && settings.hoverPreview !== false;
|
|
14711
|
+
|
|
14712
|
+
const ensurePreviewEl = () => {
|
|
14713
|
+
if (previewEl && previewEl.isConnected) {
|
|
14714
|
+
return previewEl;
|
|
14715
|
+
}
|
|
14716
|
+
|
|
14717
|
+
previewEl = h('div', 'dc-ui');
|
|
14718
|
+
previewEl.id = 'dc-preview';
|
|
14719
|
+
previewEl.setAttribute('role', 'dialog');
|
|
14720
|
+
previewEl.setAttribute('aria-label', '๊ธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ');
|
|
14721
|
+
previewEl.innerHTML =
|
|
14722
|
+
'<div class="dc-pv-head">' +
|
|
14723
|
+
'<div class="dc-pv-title"></div>' +
|
|
14724
|
+
'<div class="dc-pv-meta"></div>' +
|
|
14725
|
+
'<div class="dc-pv-actions"></div>' +
|
|
14726
|
+
'</div>' +
|
|
14727
|
+
'<div class="dc-pv-body"></div>';
|
|
14728
|
+
previewEl.addEventListener('mouseenter', () => clearTimeout(previewCloseTimer));
|
|
14729
|
+
previewEl.addEventListener('mouseleave', () => schedulePreviewClose());
|
|
14730
|
+
document.body.appendChild(previewEl);
|
|
14731
|
+
|
|
14732
|
+
return previewEl;
|
|
14733
|
+
};
|
|
14734
|
+
|
|
14735
|
+
const placePreview = anchor => {
|
|
14736
|
+
const el = ensurePreviewEl();
|
|
14737
|
+
const rect = anchor.getBoundingClientRect();
|
|
14738
|
+
const vw = window.innerWidth;
|
|
14739
|
+
const vh = window.innerHeight;
|
|
14740
|
+
const width = Math.min(640, Math.max(360, Math.round(vw * 0.42)));
|
|
14741
|
+
const height = Math.min(Math.round(vh * 0.78), 860);
|
|
14742
|
+
|
|
14743
|
+
el.style.width = `${width}px`;
|
|
14744
|
+
el.style.maxHeight = `${height}px`;
|
|
14745
|
+
|
|
14746
|
+
let left = rect.right + 16;
|
|
14747
|
+
|
|
14748
|
+
if (left + width > vw - 12) {
|
|
14749
|
+
left = Math.max(12, rect.left - width - 16);
|
|
14750
|
+
}
|
|
14751
|
+
|
|
14752
|
+
if (left + width > vw - 12) {
|
|
14753
|
+
left = Math.max(12, vw - width - 12);
|
|
14754
|
+
}
|
|
14755
|
+
|
|
14756
|
+
const top = Math.min(Math.max(12, rect.top - 60), Math.max(12, vh - height - 12));
|
|
14757
|
+
|
|
14758
|
+
el.style.left = `${Math.round(left)}px`;
|
|
14759
|
+
el.style.top = `${Math.round(top)}px`;
|
|
14760
|
+
};
|
|
14761
|
+
|
|
14762
|
+
const closePreview = () => {
|
|
14763
|
+
clearTimeout(previewHoverTimer);
|
|
14764
|
+
clearTimeout(previewCloseTimer);
|
|
14765
|
+
|
|
14766
|
+
if (previewEl) {
|
|
14767
|
+
previewEl.classList.remove('show');
|
|
14768
|
+
previewEl.querySelector('.dc-pv-body').textContent = '';
|
|
14769
|
+
}
|
|
14770
|
+
|
|
14771
|
+
previewAnchor?.classList.remove('dc-pv-anchor');
|
|
14772
|
+
previewAnchor = null;
|
|
14773
|
+
previewKey = '';
|
|
14774
|
+
};
|
|
14775
|
+
|
|
14776
|
+
const schedulePreviewClose = () => {
|
|
14777
|
+
clearTimeout(previewCloseTimer);
|
|
14778
|
+
previewCloseTimer = setTimeout(closePreview, 260);
|
|
14779
|
+
};
|
|
14780
|
+
|
|
14781
|
+
let previewHref = '';
|
|
14782
|
+
|
|
14783
|
+
const withPostReferrer = (href, fn) => {
|
|
14784
|
+
const back = location.href;
|
|
14785
|
+
let swapped = false;
|
|
14786
|
+
|
|
14787
|
+
try {
|
|
14788
|
+
const target = new URL(href, location.href);
|
|
14789
|
+
|
|
14790
|
+
if (target.origin === location.origin && target.href !== back) {
|
|
14791
|
+
history.replaceState(history.state, '', target.pathname + target.search);
|
|
14792
|
+
swapped = true;
|
|
14793
|
+
}
|
|
14794
|
+
} catch {
|
|
14795
|
+
}
|
|
14796
|
+
|
|
14797
|
+
try {
|
|
14798
|
+
return fn();
|
|
14799
|
+
} finally {
|
|
14800
|
+
if (swapped) {
|
|
14801
|
+
setTimeout(() => {
|
|
14802
|
+
try {
|
|
14803
|
+
history.replaceState(history.state, '', back);
|
|
14804
|
+
} catch {
|
|
14805
|
+
}
|
|
14806
|
+
}, 60);
|
|
14807
|
+
}
|
|
14808
|
+
}
|
|
14809
|
+
};
|
|
14810
|
+
|
|
14811
|
+
const cleanPreviewBody = source => withPostReferrer(previewHref, () => cleanPreviewBodyRaw(source));
|
|
14812
|
+
|
|
14813
|
+
const cleanPreviewBodyRaw = source => {
|
|
14814
|
+
const body = document.importNode(source, true);
|
|
14815
|
+
let hiddenMedia = 0;
|
|
14816
|
+
|
|
14817
|
+
body.querySelectorAll('script, style, link, iframe, object, embed, form, noscript, .dc-ui').forEach(node => {
|
|
14818
|
+
if (node.tagName === 'IFRAME') {
|
|
14819
|
+
const src = node.getAttribute('src') || '';
|
|
14820
|
+
const link = document.createElement('a');
|
|
14821
|
+
|
|
14822
|
+
link.href = src;
|
|
14823
|
+
link.textContent = '๐ฌ ์ฝ์
๋ ๋์์ ์ด๊ธฐ';
|
|
14824
|
+
link.className = 'dc-pv-embed';
|
|
14825
|
+
node.replaceWith(link);
|
|
14826
|
+
} else {
|
|
14827
|
+
node.remove();
|
|
14828
|
+
}
|
|
14829
|
+
});
|
|
14830
|
+
|
|
14831
|
+
body.querySelectorAll('*').forEach(node => {
|
|
14832
|
+
[...node.attributes].forEach(attr => {
|
|
14833
|
+
if (/^on/i.test(attr.name) || (/^(href|src)$/i.test(attr.name) && /^\s*javascript:/i.test(attr.value))) {
|
|
14834
|
+
node.removeAttribute(attr.name);
|
|
14835
|
+
}
|
|
14836
|
+
});
|
|
14837
|
+
});
|
|
14838
|
+
|
|
14839
|
+
body.querySelectorAll('img, video').forEach(media => {
|
|
14840
|
+
const lazy = media.getAttribute('data-original') || media.getAttribute('data-src');
|
|
14841
|
+
|
|
14842
|
+
if (lazy && !media.getAttribute('src')) {
|
|
14843
|
+
media.setAttribute('src', lazy);
|
|
14844
|
+
}
|
|
14845
|
+
|
|
14846
|
+
const candidates = collectMediaCandidates(media);
|
|
14847
|
+
|
|
14848
|
+
if (isDcconElement(media, candidates)) {
|
|
14849
|
+
if (settings.blockDccon !== false) {
|
|
14850
|
+
media.remove();
|
|
14851
|
+
}
|
|
14852
|
+
|
|
14853
|
+
return;
|
|
14854
|
+
}
|
|
14855
|
+
|
|
14856
|
+
const blocked = findBlockedMediaKey(resolveMediaIds(media, candidates));
|
|
14857
|
+
|
|
14858
|
+
if (blocked) {
|
|
14859
|
+
const stub = document.createElement('div');
|
|
14860
|
+
|
|
14861
|
+
stub.className = 'dc-pv-blocked';
|
|
14862
|
+
stub.textContent = '๐ซ ์ฐจ๋จํ ์ด๋ฏธ์ง';
|
|
14863
|
+
(media.closest('a') || media).replaceWith(stub);
|
|
14864
|
+
hiddenMedia += 1;
|
|
14865
|
+
return;
|
|
14866
|
+
}
|
|
14867
|
+
|
|
14868
|
+
media.removeAttribute('loading');
|
|
14869
|
+
media.removeAttribute('width');
|
|
14870
|
+
media.removeAttribute('height');
|
|
14871
|
+
|
|
14872
|
+
if (media.tagName === 'VIDEO') {
|
|
14873
|
+
media.setAttribute('controls', '');
|
|
14874
|
+
media.setAttribute('preload', 'metadata');
|
|
14875
|
+
media.removeAttribute('autoplay');
|
|
14876
|
+
}
|
|
14877
|
+
});
|
|
14878
|
+
|
|
14879
|
+
body.querySelectorAll('a[href]').forEach(link => {
|
|
14880
|
+
link.target = '_blank';
|
|
14881
|
+
link.rel = 'noopener noreferrer';
|
|
14882
|
+
});
|
|
14883
|
+
|
|
14884
|
+
return { body, hiddenMedia };
|
|
14885
|
+
};
|
|
14886
|
+
|
|
14887
|
+
const readPreviewDoc = (html, key) => {
|
|
14888
|
+
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
14889
|
+
const source = doc.querySelector('.write_div') || doc.querySelector(POST_BODY_SELECTOR);
|
|
14890
|
+
const head = doc.querySelector('.gallview_head');
|
|
14891
|
+
|
|
14892
|
+
if (!source) {
|
|
14893
|
+
return { missing: true };
|
|
14894
|
+
}
|
|
14895
|
+
|
|
14896
|
+
const writer = head?.querySelector('.gall_writer');
|
|
14897
|
+
const text = normalizeWord(`${head?.querySelector('.title_subject')?.textContent || ''} ${source.textContent}`).slice(0, BODY_TEXT_LIMIT);
|
|
14898
|
+
const word = findWord(blockedKeywords, text);
|
|
14899
|
+
|
|
14900
|
+
if (key) {
|
|
14901
|
+
bodyScanCache[key] = { s: bodyScanSignature(), w: word, m: '', t: Date.now() };
|
|
14902
|
+
saveBodyScanSoon();
|
|
14903
|
+
}
|
|
14904
|
+
|
|
14905
|
+
return {
|
|
14906
|
+
title: cleanText(head?.querySelector('.title_subject')?.textContent || ''),
|
|
14907
|
+
head: cleanText(head?.querySelector('.title_headtext')?.textContent || '').replace(/^\[|\]$/g, ''),
|
|
14908
|
+
nick: writer?.getAttribute('data-nick') || cleanText(writer?.querySelector('.nickname')?.textContent || ''),
|
|
14909
|
+
ip: writer?.getAttribute('data-ip') || '',
|
|
14910
|
+
code: writer?.getAttribute('data-uid') || '',
|
|
14911
|
+
date: head?.querySelector('.gall_date')?.getAttribute('title') || cleanText(head?.querySelector('.gall_date')?.textContent || ''),
|
|
14912
|
+
stats: (cleanText(head?.querySelector('.fr')?.textContent || '').match(/(์กฐํ|์ถ์ฒ|๋๊ธ)\s*[\d,]+/g) || []).join(' ยท '),
|
|
14913
|
+
source,
|
|
14914
|
+
word
|
|
14915
|
+
};
|
|
14916
|
+
};
|
|
14917
|
+
|
|
14918
|
+
const renderPreview = (data, href, key) => {
|
|
14919
|
+
const el = ensurePreviewEl();
|
|
14920
|
+
|
|
14921
|
+
previewHref = href;
|
|
14922
|
+
const titleEl = el.querySelector('.dc-pv-title');
|
|
14923
|
+
const metaEl = el.querySelector('.dc-pv-meta');
|
|
14924
|
+
const actions = el.querySelector('.dc-pv-actions');
|
|
14925
|
+
const bodyEl = el.querySelector('.dc-pv-body');
|
|
14926
|
+
|
|
14927
|
+
actions.textContent = '';
|
|
14928
|
+
bodyEl.textContent = '';
|
|
14929
|
+
bodyEl.scrollTop = 0;
|
|
14930
|
+
el.scrollTop = 0;
|
|
14931
|
+
|
|
14932
|
+
if (data.missing) {
|
|
14933
|
+
titleEl.textContent = '๋ณธ๋ฌธ์ ๋ถ๋ฌ์ฌ ์ ์์ต๋๋ค';
|
|
14934
|
+
metaEl.textContent = '์ญ์ ๋๊ฑฐ๋ ์ฑ์ธ ์ธ์ฆ์ด ํ์ํ ๊ธ์
๋๋ค.';
|
|
14935
|
+
} else {
|
|
14936
|
+
titleEl.textContent = `${data.head ? `[${data.head}] ` : ''}${data.title || '(์ ๋ชฉ ์์)'}`;
|
|
14937
|
+
metaEl.textContent = [data.nick && `${data.nick}${data.ip ? `(${data.ip})` : ''}`, data.date, data.stats].filter(Boolean).join(' ยท ');
|
|
14938
|
+
|
|
14939
|
+
if (data.word) {
|
|
14940
|
+
const note = h('div', 'dc-pv-warn', `๐ซ ๋ณธ๋ฌธ์ ์ฐจ๋จ ๋จ์ด "${data.word}" ๊ฐ ์์ด ๊ฐ๋ ธ์ต๋๋ค${settings.prefetchBodies !== false ? ' ยท ๋ชฉ๋ก์์๋ ๊ฐ๋ ค์ง๋๋ค' : ''}`);
|
|
14941
|
+
const reveal = makeButton('๊ทธ๋๋ ๋ณด๊ธฐ', 'mini', () => {
|
|
14942
|
+
note.remove();
|
|
14943
|
+
bodyEl.appendChild(cleanPreviewBody(data.source).body);
|
|
14944
|
+
});
|
|
14945
|
+
|
|
14946
|
+
note.appendChild(reveal);
|
|
14947
|
+
bodyEl.appendChild(note);
|
|
14948
|
+
} else {
|
|
14949
|
+
const { body, hiddenMedia } = cleanPreviewBody(data.source);
|
|
14950
|
+
|
|
14951
|
+
if (hiddenMedia) {
|
|
14952
|
+
bodyEl.appendChild(h('div', 'dc-pv-note', `์ฐจ๋จํ ์ด๋ฏธ์ง ${hiddenMedia}๊ฐ๋ฅผ ๋บ์ต๋๋ค`));
|
|
14953
|
+
}
|
|
14954
|
+
|
|
14955
|
+
bodyEl.appendChild(body);
|
|
14956
|
+
}
|
|
14957
|
+
}
|
|
14958
|
+
|
|
14959
|
+
const open = h('a', 'dc-btn mini', '๊ธ ์ด๊ธฐ');
|
|
14960
|
+
|
|
14961
|
+
open.href = href;
|
|
14962
|
+
actions.appendChild(open);
|
|
14963
|
+
|
|
14964
|
+
if (!data.missing && key) {
|
|
14965
|
+
const match = /[?&]id=([^&]+)&no=(\d+)/.exec(href) || [];
|
|
14966
|
+
const kind = /\/mgallery\//.test(href) ? 'M' : /\/mini\//.test(href) ? 'N' : /\/person\//.test(href) ? 'P' : 'G';
|
|
14967
|
+
const info = match[1] ? normalizeScrap({ k: kind, id: decodeURIComponent(match[1]), no: match[2], t: data.title, g: '', d: Date.now() }) : null;
|
|
14968
|
+
|
|
14969
|
+
if (info && isValidScrap(info)) {
|
|
14970
|
+
const scrapBtn = makeButton(isScrapped(info) ? '๐ ์คํฌ๋ฉ๋จ' : '๐ ์คํฌ๋ฉ', 'mini', () => {
|
|
14971
|
+
toggleScrap(info);
|
|
14972
|
+
scrapBtn.textContent = isScrapped(info) ? '๐ ์คํฌ๋ฉ๋จ' : '๐ ์คํฌ๋ฉ';
|
|
14973
|
+
});
|
|
14974
|
+
|
|
14975
|
+
actions.appendChild(scrapBtn);
|
|
14976
|
+
}
|
|
14977
|
+
|
|
14978
|
+
const userKey = data.code ? `id::${data.code}` : data.ip ? `ip::${data.ip}` : data.nick ? `nick::${data.nick}` : '';
|
|
14979
|
+
|
|
14980
|
+
if (userKey && !blockedUsers.includes(userKey)) {
|
|
14981
|
+
actions.appendChild(makeButton('๐ซ ์์ฑ์ ์ฐจ๋จ', 'mini danger-ghost', () => {
|
|
14982
|
+
blockedUsers = sortUserKeys([...blockedUsers, userKey]);
|
|
14983
|
+
saveUsers();
|
|
14984
|
+
refreshAfterBlockChange();
|
|
14985
|
+
closePreview();
|
|
14986
|
+
offerUndo(`โ ${describeHitKey(userKey).kind} ${describeHitKey(userKey).label} ์ฐจ๋จ`, () => {
|
|
14987
|
+
blockedUsers = blockedUsers.filter(item => item !== userKey);
|
|
14988
|
+
saveUsers();
|
|
14989
|
+
refreshAfterBlockChange();
|
|
14990
|
+
});
|
|
14991
|
+
}));
|
|
14992
|
+
}
|
|
14993
|
+
}
|
|
14994
|
+
|
|
14995
|
+
const close = makeButton('โ', 'mini dc-pv-close', closePreview);
|
|
14996
|
+
|
|
14997
|
+
close.setAttribute('aria-label', '๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ซ๊ธฐ');
|
|
14998
|
+
actions.appendChild(close);
|
|
14999
|
+
};
|
|
15000
|
+
|
|
15001
|
+
const showPreviewFor = async anchor => {
|
|
15002
|
+
if (!previewEnabled() || !anchor || !anchor.isConnected) {
|
|
15003
|
+
return;
|
|
15004
|
+
}
|
|
15005
|
+
|
|
15006
|
+
const row = anchor.closest('tr');
|
|
15007
|
+
|
|
15008
|
+
if (row && (row.classList.contains('dc-user-blocked') && !row.classList.contains('dc-user-revealed') || row.classList.contains('dc-head-hidden'))) {
|
|
15009
|
+
return;
|
|
15010
|
+
}
|
|
15011
|
+
|
|
15012
|
+
const href = anchor.href;
|
|
15013
|
+
const key = extractPostPath(href);
|
|
15014
|
+
|
|
15015
|
+
if (!key) {
|
|
15016
|
+
return;
|
|
15017
|
+
}
|
|
15018
|
+
|
|
15019
|
+
previewAnchor?.classList.remove('dc-pv-anchor');
|
|
15020
|
+
previewAnchor = anchor;
|
|
15021
|
+
previewKey = key;
|
|
15022
|
+
anchor.classList.add('dc-pv-anchor');
|
|
15023
|
+
|
|
15024
|
+
const el = ensurePreviewEl();
|
|
15025
|
+
|
|
15026
|
+
placePreview(anchor);
|
|
15027
|
+
el.classList.add('show');
|
|
15028
|
+
|
|
15029
|
+
const cached = previewCache.get(key);
|
|
15030
|
+
|
|
15031
|
+
if (cached && Date.now() - cached.at < PREVIEW_CACHE_MS) {
|
|
15032
|
+
renderPreview(cached.data, href, key);
|
|
15033
|
+
return;
|
|
15034
|
+
}
|
|
15035
|
+
|
|
15036
|
+
const paused = netPausedUntil();
|
|
15037
|
+
|
|
15038
|
+
el.querySelector('.dc-pv-title').textContent = cleanText(anchor.textContent);
|
|
15039
|
+
el.querySelector('.dc-pv-meta').textContent = '';
|
|
15040
|
+
el.querySelector('.dc-pv-actions').textContent = '';
|
|
15041
|
+
el.querySelector('.dc-pv-body').textContent = '';
|
|
15042
|
+
|
|
15043
|
+
if (paused) {
|
|
15044
|
+
el.querySelector('.dc-pv-body').appendChild(h('div', 'dc-pv-note', `โธ ๋์ ์์ฒญ ์ ํ ์ค์ด๋ผ ${Math.max(1, Math.ceil((paused - Date.now()) / 60000))}๋ถ ๋ค์ ๋ฏธ๋ฆฌ๋ณผ ์ ์์ต๋๋ค`));
|
|
15045
|
+
return;
|
|
15046
|
+
}
|
|
15047
|
+
|
|
15048
|
+
el.querySelector('.dc-pv-body').appendChild(h('div', 'dc-pv-loading', '๋ถ๋ฌ์ค๋ ์คโฆ'));
|
|
15049
|
+
|
|
15050
|
+
try {
|
|
15051
|
+
const html = await siteFetchText(href, { credentials: 'same-origin', cache: 'no-cache' });
|
|
15052
|
+
const data = readPreviewDoc(html, key);
|
|
15053
|
+
|
|
15054
|
+
previewCache.set(key, { at: Date.now(), data });
|
|
15055
|
+
|
|
15056
|
+
while (previewCache.size > PREVIEW_CACHE_MAX) {
|
|
15057
|
+
previewCache.delete(previewCache.keys().next().value);
|
|
15058
|
+
}
|
|
15059
|
+
|
|
15060
|
+
if (previewKey === key) {
|
|
15061
|
+
renderPreview(data, href, key);
|
|
15062
|
+
|
|
15063
|
+
if (data.word && settings.prefetchBodies !== false) {
|
|
15064
|
+
refreshAfterBlockChange();
|
|
15065
|
+
}
|
|
15066
|
+
}
|
|
15067
|
+
} catch (error) {
|
|
15068
|
+
if (previewKey !== key) {
|
|
15069
|
+
return;
|
|
15070
|
+
}
|
|
15071
|
+
|
|
15072
|
+
const body = el.querySelector('.dc-pv-body');
|
|
15073
|
+
|
|
15074
|
+
body.textContent = '';
|
|
15075
|
+
body.appendChild(h('div', 'dc-pv-note', error instanceof NetPausedError
|
|
15076
|
+
? 'โธ ๋์ ์์ฒญ ์ ํ ์ค์ด๋ผ ์ ์ ๋ค์ ๋ฏธ๋ฆฌ๋ณผ ์ ์์ต๋๋ค'
|
|
15077
|
+
: '๋ถ๋ฌ์ค์ง ๋ชปํ์ต๋๋ค. ์ ์ ๋ค ๋ค์ ์ฌ๋ ค ๋ณด์ธ์.'));
|
|
15078
|
+
}
|
|
15079
|
+
};
|
|
15080
|
+
|
|
15081
|
+
const initHoverPreview = () => {
|
|
15082
|
+
if (!IS_PC_SITE) {
|
|
15083
|
+
return;
|
|
15084
|
+
}
|
|
15085
|
+
|
|
15086
|
+
document.addEventListener('mouseover', event => {
|
|
15087
|
+
if (!previewEnabled() || (event.pointerType && event.pointerType !== 'mouse')) {
|
|
15088
|
+
return;
|
|
15089
|
+
}
|
|
15090
|
+
|
|
15091
|
+
const anchor = event.target instanceof Element ? event.target.closest(PREVIEW_TITLE_SELECTOR) : null;
|
|
15092
|
+
|
|
15093
|
+
if (!anchor || anchor.closest('.dc-ui')) {
|
|
15094
|
+
return;
|
|
15095
|
+
}
|
|
15096
|
+
|
|
15097
|
+
clearTimeout(previewCloseTimer);
|
|
15098
|
+
|
|
15099
|
+
if (anchor === previewAnchor) {
|
|
15100
|
+
return;
|
|
15101
|
+
}
|
|
15102
|
+
|
|
15103
|
+
clearTimeout(previewHoverTimer);
|
|
15104
|
+
previewHoverTimer = setTimeout(() => showPreviewFor(anchor), PREVIEW_DELAY);
|
|
15105
|
+
});
|
|
15106
|
+
|
|
15107
|
+
document.addEventListener('mouseout', event => {
|
|
15108
|
+
const anchor = event.target instanceof Element ? event.target.closest(PREVIEW_TITLE_SELECTOR) : null;
|
|
15109
|
+
|
|
15110
|
+
if (!anchor || (event.relatedTarget instanceof Node && anchor.contains(event.relatedTarget))) {
|
|
15111
|
+
return;
|
|
15112
|
+
}
|
|
15113
|
+
|
|
15114
|
+
clearTimeout(previewHoverTimer);
|
|
15115
|
+
|
|
15116
|
+
if (previewEl && previewEl.classList.contains('show')) {
|
|
15117
|
+
schedulePreviewClose();
|
|
15118
|
+
}
|
|
15119
|
+
});
|
|
15120
|
+
|
|
15121
|
+
document.addEventListener('mousedown', event => {
|
|
15122
|
+
if (previewEl && previewEl.classList.contains('show') && !(event.target instanceof Node && previewEl.contains(event.target))) {
|
|
15123
|
+
closePreview();
|
|
15124
|
+
}
|
|
15125
|
+
}, true);
|
|
15126
|
+
|
|
15127
|
+
window.addEventListener('scroll', () => {
|
|
15128
|
+
if (previewEl && previewEl.classList.contains('show') && previewAnchor && !previewEl.matches(':hover')) {
|
|
15129
|
+
closePreview();
|
|
15130
|
+
}
|
|
15131
|
+
}, { passive: true });
|
|
15132
|
+
|
|
15133
|
+
document.addEventListener('keydown', event => {
|
|
15134
|
+
if (event.key === 'Escape' && previewEl && previewEl.classList.contains('show')) {
|
|
15135
|
+
closePreview();
|
|
15136
|
+
}
|
|
15137
|
+
});
|
|
15138
|
+
};
|
|
15139
|
+
|
|
15140
|
+
const togglePreviewForCursor = () => {
|
|
15141
|
+
if (!previewEnabled()) {
|
|
15142
|
+
return false;
|
|
15143
|
+
}
|
|
15144
|
+
|
|
15145
|
+
if (previewEl && previewEl.classList.contains('show')) {
|
|
15146
|
+
closePreview();
|
|
15147
|
+
return true;
|
|
15148
|
+
}
|
|
15149
|
+
|
|
15150
|
+
const anchor = keyCursor && keyCursor.isConnected ? keyCursor.querySelector(PREVIEW_TITLE_SELECTOR.replace('table.gall_list ', '')) : null;
|
|
15151
|
+
|
|
15152
|
+
if (!anchor) {
|
|
15153
|
+
return false;
|
|
15154
|
+
}
|
|
15155
|
+
|
|
15156
|
+
showPreviewFor(anchor);
|
|
15157
|
+
return true;
|
|
15158
|
+
};
|
|
14162
15159
|
// =========================================================
|
|
14163
15160
|
// 14. ํ๋กํ
๋ฒํผ
|
|
14164
15161
|
// =========================================================
|
|
@@ -15147,6 +16144,7 @@
|
|
|
15147
16144
|
initRecent();
|
|
15148
16145
|
initSiteAlarms();
|
|
15149
16146
|
initKeyboardShortcuts();
|
|
16147
|
+
initHoverPreview();
|
|
15150
16148
|
restoreListSnapshot();
|
|
15151
16149
|
processElements();
|
|
15152
16150
|
|
package/package.json
CHANGED