@kangsicj/dcinsideenhancer 1.3.3 → 1.3.5

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.
@@ -2,7 +2,7 @@
2
2
  // @name DCInside Enhancer
3
3
  // @name:ko 디시 인핸서
4
4
  // @namespace https://github.com/kangsicj/DCInsideEnhancer
5
- // @version 1.3.3
5
+ // @version 1.3.5
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 (no account, no tracking).
7
7
  // @description:ko 디시인사이드 차단·편의 기능 (모바일·PC) - 유저·단어(제목/본문)·말머리·공지 차단, 같은/비슷한 이미지·움짤 모든 글 차단, 디시콘 제거, 차단 미디어 데이터 절약, 목록 자동 보충·무한 스크롤·뒤로 가기 위치 복원, 스크랩, 이미지 확대뷰 개선, 야간모드 자동 연동, 암호화 기기 간 동기화 (계정 없음·추적 없음)
8
8
  // @author kangsicj
@@ -37,7 +37,7 @@
37
37
  window.__dcInsideEnhancer = true;
38
38
  window.__dcRefinery = true;
39
39
 
40
- const SCRIPT_VERSION = '1.3.3';
40
+ const SCRIPT_VERSION = '1.3.5';
41
41
  const PROJECT_URL = 'https://github.com/kangsicj/DCInsideEnhancer';
42
42
  const DONATE_URL = 'https://fairy.hada.io/@kangsicj';
43
43
  const DONATE_URL_BMC = 'https://buymeacoffee.com/kangsicj';
@@ -187,7 +187,6 @@
187
187
  hideCommentAds: true,
188
188
  hideCommentFab: true,
189
189
  mobileRecentBar: true,
190
- mobileRecentStrip: true,
191
190
  hideSilbeAlarm: true,
192
191
  alarmBubble: true,
193
192
  alarmKeepPolling: true,
@@ -2032,17 +2031,16 @@
2032
2031
  #dc-recent-bar {
2033
2032
  display: flex;
2034
2033
  align-items: center;
2035
- gap: 0;
2036
- height: 34px;
2034
+ gap: var(--dc-rb-gap, 30px);
2035
+ height: 40px;
2037
2036
  margin: 0;
2038
- padding: 0 6px;
2037
+ padding: 0 var(--dc-rb-pad, 14px);
2039
2038
  overflow-x: auto;
2040
2039
  overflow-y: hidden;
2041
2040
  -webkit-overflow-scrolling: touch;
2042
2041
  scrollbar-width: none;
2043
2042
  overscroll-behavior-x: contain;
2044
2043
  background: var(--dc-rb-bg, #3b4890);
2045
- border-bottom: 1px solid rgba(255,255,255,.12);
2046
2044
  box-sizing: border-box;
2047
2045
  }
2048
2046
  #dc-recent-bar::-webkit-scrollbar { display: none; }
@@ -2050,74 +2048,23 @@
2050
2048
  flex: 0 0 auto;
2051
2049
  display: inline-flex;
2052
2050
  align-items: center;
2053
- gap: 2px;
2054
- max-width: 46vw;
2055
- height: 34px;
2056
- padding: 0 10px;
2051
+ gap: 3px;
2052
+ max-width: 60vw;
2053
+ height: 40px;
2054
+ padding: 0;
2057
2055
  overflow: hidden;
2058
- color: rgba(255,255,255,.82);
2059
- font-size: 13px;
2060
- font-weight: 500;
2061
- letter-spacing: -.3px;
2056
+ color: var(--dc-rb-color, #fff);
2057
+ font-family: var(--dc-rb-family, inherit);
2058
+ font-size: var(--dc-rb-size, 16px);
2059
+ font-weight: var(--dc-rb-weight, 700);
2060
+ letter-spacing: var(--dc-rb-spacing, normal);
2062
2061
  text-decoration: none;
2063
2062
  text-overflow: ellipsis;
2064
2063
  white-space: nowrap;
2064
+ opacity: .9;
2065
2065
  }
2066
- #dc-recent-bar .dc-rb-item + .dc-rb-item { border-left: 1px solid rgba(255,255,255,.18); }
2067
- #dc-recent-bar .dc-rb-item.on { color: var(--dc-rb-on, #ffe10a); font-weight: 700; }
2068
- #dc-recent-bar .dc-rb-kind { font-size: 11px; opacity: .8; }
2069
-
2070
- html.dc-recent-strip-on #lately_pop.dc-strip-lately #swiper-lately,
2071
- html.dc-recent-strip-on #lately_pop.dc-strip-lately #lately_paging1 { display: none !important; }
2072
- .dc-recent-strip {
2073
- display: flex;
2074
- gap: 8px;
2075
- padding: 12px 12px 14px;
2076
- overflow-x: auto;
2077
- overflow-y: hidden;
2078
- -webkit-overflow-scrolling: touch;
2079
- scroll-snap-type: x proximity;
2080
- scrollbar-width: none;
2081
- overscroll-behavior-x: contain;
2082
- }
2083
- .dc-recent-strip::-webkit-scrollbar { display: none; }
2084
- .dc-recent-strip[hidden] { display: none !important; }
2085
- .dc-recent-strip .dc-rs-chip {
2086
- flex: 0 0 auto;
2087
- display: inline-flex;
2088
- align-items: center;
2089
- gap: 4px;
2090
- max-width: 60vw;
2091
- height: 36px;
2092
- padding: 0 4px 0 14px;
2093
- border: 1px solid var(--dc-border);
2094
- border-radius: 999px;
2095
- background: var(--dc-surface-2);
2096
- color: var(--dc-text);
2097
- font-size: 14px;
2098
- font-weight: 600;
2099
- text-decoration: none;
2100
- white-space: nowrap;
2101
- scroll-snap-align: start;
2102
- }
2103
- .dc-recent-strip .dc-rs-chip.here { border-color: var(--dc-accent-ink); color: var(--dc-accent-ink); background: var(--dc-accent-soft); }
2104
- .dc-recent-strip .dc-rs-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
2105
- .dc-recent-strip .dc-rs-kind { color: var(--dc-text-dim); font-size: 13px; }
2106
- .dc-recent-strip .dc-rs-del {
2107
- flex: 0 0 auto;
2108
- width: 28px;
2109
- height: 28px;
2110
- margin: 0;
2111
- padding: 0;
2112
- border: none;
2113
- border-radius: 50%;
2114
- background: transparent;
2115
- color: var(--dc-text-dim);
2116
- font-size: 18px;
2117
- line-height: 28px;
2118
- }
2119
- .dc-recent-strip .dc-rs-pin,
2120
- .dc-recent-strip .dc-rs-empty { flex: 0 0 auto; align-self: center; padding: 0 6px; color: var(--dc-text-dim); font-size: 12px; white-space: nowrap; }
2066
+ #dc-recent-bar .dc-rb-item.on { color: var(--dc-rb-on, #ffe10a); opacity: 1; }
2067
+ #dc-recent-bar .dc-rb-kind { font-size: .75em; font-weight: 400; opacity: .85; }
2121
2068
 
2122
2069
  .dc-key-cursor { outline: 2px solid var(--dc-accent-ink) !important; outline-offset: -2px; background: var(--dc-accent-soft) !important; }
2123
2070
 
@@ -3362,6 +3309,13 @@
3362
3309
  saveSettings();
3363
3310
  }
3364
3311
 
3312
+ const staleSettings = Object.keys(settings).filter(key => !(key in DEFAULT_SETTINGS) && key !== 'settingsRev');
3313
+
3314
+ if (staleSettings.length) {
3315
+ staleSettings.forEach(key => delete settings[key]);
3316
+ saveSettings();
3317
+ }
3318
+
3365
3319
  OBSOLETE_STORAGE.forEach(key => {
3366
3320
  try {
3367
3321
  localStorage.removeItem(key);
@@ -9961,6 +9915,17 @@
9961
9915
  area.querySelectorAll('.dc-row').forEach(row => {
9962
9916
  row.hidden = !matchesFilter(row.textContent);
9963
9917
  });
9918
+
9919
+ area.querySelectorAll('.dc-setting-row').forEach(row => {
9920
+ row.hidden = !matchesFilter(row.textContent);
9921
+ });
9922
+ area.querySelectorAll('.dc-settings-group[data-dc-group]').forEach(box => {
9923
+ const empty = !!blockFilter.trim() && ![...box.querySelectorAll('.dc-setting-row')].some(row => !row.hidden);
9924
+
9925
+ area.querySelectorAll(`[data-dc-group="${box.dataset.dcGroup}"]`).forEach(el => {
9926
+ el.hidden = empty;
9927
+ });
9928
+ });
9964
9929
  };
9965
9930
 
9966
9931
  const matchesFilter = text => !blockFilter || String(text).toLowerCase().includes(blockFilter.trim().toLowerCase());
@@ -10309,6 +10274,7 @@
10309
10274
  { key: 'alarm', title: '🔔 알림', intro: '디시 알림(댓글·답글·힛갤 등)을 보기 쉽게 바꿉니다. 알림 내용은 사이트가 받은 것을 그대로 씁니다.' },
10310
10275
  { key: 'dccon', title: '😶 디시콘', intro: '디시 자체 이모티콘을 다룹니다.' },
10311
10276
  { key: 'list', title: '📜 목록 보기', intro: '게시판 목록을 넘겨 보는 방식을 정합니다.' },
10277
+ { key: 'handy', title: '✨ 편의 기능', intro: '최근 방문 · 글 미리보기 · 단축키 · 스크랩처럼 사이트를 더 편하게 쓰는 기능입니다.' },
10312
10278
  { key: 'media', title: '🖼 이미지·영상', intro: '본문 이미지 차단과 확대 보기를 다룹니다.' },
10313
10279
  { key: 'data', title: '📶 데이터 절약', intro: '모바일 데이터를 아끼는 기능입니다.' },
10314
10280
  { key: 'theme', title: '🌓 화면 테마', intro: '주간/야간 모드를 기기 설정에 맞춥니다.' },
@@ -10455,21 +10421,13 @@
10455
10421
  refresh: 'root'
10456
10422
  },
10457
10423
  {
10458
- group: 'clean',
10424
+ group: 'handy',
10459
10425
  key: 'mobileRecentBar',
10460
10426
  name: '메뉴 위에 최근 방문 갤러리 늘 보이기 (모바일)',
10461
10427
  on: '검색창과 [갤러리 · 마이너갤 · …] 메뉴 사이에 최근 방문 갤러리를 한 줄로 보여 줍니다. 옆으로 밀어 보고, 누르면 바로 이동합니다. 지금 갤러리는 노란색입니다.',
10462
10428
  off: '[최근 방문]을 눌러야 보입니다.',
10463
10429
  refresh: 'root'
10464
10430
  },
10465
- {
10466
- group: 'clean',
10467
- key: 'mobileRecentStrip',
10468
- name: "'최근 방문'을 한 줄로 밀어 보기 (모바일)",
10469
- on: '위쪽 [최근 방문]을 누르면 넓은 표 대신 갤러리가 순서대로 한 줄에 나오고, 옆으로 밀어 봅니다. 고정한 순서를 그대로 따릅니다.',
10470
- off: '사이트 기본 표(2줄 × 4칸, 넘겨 보기)로 보여 줍니다.',
10471
- refresh: 'root'
10472
- },
10473
10431
  {
10474
10432
  group: 'clean',
10475
10433
  key: 'hideAdSlots',
@@ -10545,7 +10503,7 @@
10545
10503
  refresh: 'all'
10546
10504
  },
10547
10505
  {
10548
- group: 'list',
10506
+ group: 'handy',
10549
10507
  key: 'keyboardShortcuts',
10550
10508
  name: '키보드 단축키 (PC)',
10551
10509
  on: '목록에서 J/K 로 글을 고르고 Enter 로 엽니다. 글에서는 J/K 로 다음·이전 글, S 스크랩, / 검색창, B 차단 관리, ? 안내.',
@@ -10553,7 +10511,7 @@
10553
10511
  refresh: 'none'
10554
10512
  },
10555
10513
  {
10556
- group: 'list',
10514
+ group: 'handy',
10557
10515
  key: 'hoverPreview',
10558
10516
  name: '제목을 길게 누르면 글 미리보기 (PC)',
10559
10517
  on: '아이폰처럼 목록 제목을 길게 누르면 화면이 흐려지며 글 전체가 가운데에 떠오릅니다. 짧게 누르면 평소처럼 글로 갑니다. 창에서 본문을 누르면 글로 이동, 바깥을 누르거나 Esc 로 닫습니다. 스크랩·작성자 차단도 바로 할 수 있고, 차단한 이미지·단어는 미리보기에서도 가립니다. 키보드로 고른 글은 P 로 엽니다.',
@@ -10561,7 +10519,7 @@
10561
10519
  refresh: 'root'
10562
10520
  },
10563
10521
  {
10564
- group: 'list',
10522
+ group: 'handy',
10565
10523
  key: 'previewHover',
10566
10524
  parent: 'hoverPreview',
10567
10525
  name: '마우스를 올려 멈춰도 미리보기 (PC)',
@@ -10606,7 +10564,7 @@
10606
10564
  refresh: 'root'
10607
10565
  },
10608
10566
  {
10609
- group: 'list',
10567
+ group: 'handy',
10610
10568
  key: 'autoHideScrollbar',
10611
10569
  name: '스크롤바 자동 숨기기',
10612
10570
  on: '화면 스크롤바를 숨기고, 스크롤하는 동안만 얇은 표시가 잠깐 나타납니다 (스크롤바가 자리를 차지하는 PC).',
@@ -10614,7 +10572,7 @@
10614
10572
  refresh: 'root'
10615
10573
  },
10616
10574
  {
10617
- group: 'list',
10575
+ group: 'handy',
10618
10576
  key: 'scrapIntercept',
10619
10577
  name: '무제한 스크랩',
10620
10578
  on: '글의 스크랩 버튼을 누르면 개수 제한 없이 이 기기에 저장합니다. 플로팅 메뉴의 📌 스크랩 탭에서 봅니다.',
@@ -10622,7 +10580,7 @@
10622
10580
  refresh: 'none'
10623
10581
  },
10624
10582
  {
10625
- group: 'list',
10583
+ group: 'handy',
10626
10584
  key: 'showScrollTop',
10627
10585
  name: '맨 위로 버튼',
10628
10586
  on: '목록을 많이 내려가면 플로팅 버튼 위에 ↑ 버튼이 나타납니다.',
@@ -10766,10 +10724,6 @@
10766
10724
  renderRecentBar();
10767
10725
  }
10768
10726
 
10769
- if (item.key === 'mobileRecentStrip') {
10770
- renderRecentStrip();
10771
- }
10772
-
10773
10727
  if (item.key === 'alarmBubble') {
10774
10728
  paintAlarmBadge();
10775
10729
  }
@@ -11150,7 +11104,7 @@
11150
11104
  const seg = h('div', 'dc-choice-seg');
11151
11105
 
11152
11106
  head.append(
11153
- h('span', 'dc-setting-name', item.name),
11107
+ h('span', 'dc-setting-name', settingLabel(item)),
11154
11108
  h('span', 'dc-state-badge on', chosen ? chosen.label : String(current))
11155
11109
  );
11156
11110
  text.append(head, h('span', 'dc-setting-desc', item.on));
@@ -11186,17 +11140,43 @@
11186
11140
  return row;
11187
11141
  };
11188
11142
 
11143
+ const settingPlatform = item => (/\(PC\)$/.test(item.name) ? 'pc' : /\(모바일\)$/.test(item.name) ? 'mobile' : 'all');
11144
+ const settingShownHere = item => {
11145
+ const platform = settingPlatform(item);
11146
+
11147
+ return platform === 'all' || (platform === 'pc') === IS_PC_SITE;
11148
+ };
11149
+ const settingLabel = item => item.name.replace(/\s*\((PC|모바일)\)$/, '');
11150
+
11189
11151
  const renderSettings = area => {
11190
11152
  area.appendChild(
11191
- makeNote('스위치가 초록색이면 켜짐입니다. 바꾸면 바로 적용되고 자동으로 저장됩니다.')
11153
+ makeNote(`스위치가 초록색이면 켜짐입니다. 바꾸면 바로 적용되고 자동으로 저장됩니다. ${IS_PC_SITE ? 'PC' : '모바일'}에서 쓰는 설정만 보입니다.`)
11192
11154
  );
11193
11155
 
11156
+ const search = makeFilterRow(99);
11157
+
11158
+ if (search) {
11159
+ search.querySelector('input').placeholder = '🔍 설정에서 찾기';
11160
+ area.appendChild(search);
11161
+ }
11162
+
11194
11163
  SETTING_GROUPS.forEach(group => {
11164
+ const items = SETTING_ITEMS.filter(item => item.group === group.key && settingShownHere(item));
11165
+
11166
+ if (!items.length) {
11167
+ return;
11168
+ }
11169
+
11195
11170
  const box = h('div', 'dc-settings-group');
11171
+ const title = h('div', 'dc-group-title', group.title);
11172
+ const intro = h('div', 'dc-group-intro', group.intro);
11196
11173
 
11197
- area.append(h('div', 'dc-group-title', group.title), h('div', 'dc-group-intro', group.intro), box);
11174
+ title.dataset.dcGroup = group.key;
11175
+ intro.dataset.dcGroup = group.key;
11176
+ box.dataset.dcGroup = group.key;
11177
+ area.append(title, intro, box);
11198
11178
 
11199
- SETTING_ITEMS.filter(item => item.group === group.key).forEach(item => {
11179
+ items.forEach(item => {
11200
11180
  if (item.choices) {
11201
11181
  box.appendChild(renderChoiceSetting(item));
11202
11182
  return;
@@ -11211,7 +11191,7 @@
11211
11191
  const toggle = h('button', `dc-switch${on ? ' on' : ''}`);
11212
11192
 
11213
11193
  head.append(
11214
- h('span', 'dc-setting-name', item.name),
11194
+ h('span', 'dc-setting-name', settingLabel(item)),
11215
11195
  h('span', `dc-state-badge${on ? ' on' : ''}`, on ? '켜짐' : '꺼짐')
11216
11196
  );
11217
11197
  text.append(head, h('span', 'dc-setting-desc', on || !item.off ? item.on : item.off));
@@ -11221,7 +11201,7 @@
11221
11201
  }
11222
11202
 
11223
11203
  const status = !effective
11224
- ? `위의 '${parent.name}' 설정을 먼저 켜 주세요.`
11204
+ ? `위의 '${settingLabel(parent)}' 설정을 먼저 켜 주세요.`
11225
11205
  : item.status
11226
11206
  ? item.status(on)
11227
11207
  : null;
@@ -11233,7 +11213,7 @@
11233
11213
  toggle.type = 'button';
11234
11214
  toggle.disabled = !effective;
11235
11215
  toggle.setAttribute('role', 'switch');
11236
- toggle.setAttribute('aria-label', item.name);
11216
+ toggle.setAttribute('aria-label', settingLabel(item));
11237
11217
  toggle.setAttribute('aria-checked', String(on));
11238
11218
 
11239
11219
  toggle.addEventListener('click', () => {
@@ -11685,7 +11665,13 @@
11685
11665
  };
11686
11666
 
11687
11667
  const setModalView = view => {
11688
- currentView = MODAL_VIEWS[view] ? view : 'overview';
11668
+ const next = MODAL_VIEWS[view] ? view : 'overview';
11669
+
11670
+ if (next !== currentView) {
11671
+ blockFilter = '';
11672
+ }
11673
+
11674
+ currentView = next;
11689
11675
 
11690
11676
  document.getElementById('dc-modal-title').textContent = MODAL_VIEWS[currentView].title;
11691
11677
  document.querySelectorAll('[data-dc-view]').forEach(btn => {
@@ -11994,6 +11980,18 @@
11994
11980
  return out;
11995
11981
  };
11996
11982
 
11983
+ const pickKnownSettings = (source = {}) => {
11984
+ const out = {};
11985
+
11986
+ Object.keys(source || {}).forEach(key => {
11987
+ if (key in DEFAULT_SETTINGS && !SYNC_SETTINGS_SKIP.includes(key)) {
11988
+ out[key] = source[key];
11989
+ }
11990
+ });
11991
+
11992
+ return out;
11993
+ };
11994
+
11997
11995
  const collectSyncData = () => ({
11998
11996
  users: [...blockedUsers],
11999
11997
  images: [...blockedMedia],
@@ -12153,7 +12151,7 @@
12153
12151
  if (after.scraps) diff('스크랩', (before.scraps || []).map(scrapKeyOf), after.scraps.map(scrapKeyOf));
12154
12152
 
12155
12153
  if (after.settings) {
12156
- const changed = Object.keys(after.settings).filter(key => JSON.stringify(after.settings[key]) !== JSON.stringify((before.settings || {})[key])).length;
12154
+ const changed = Object.keys(pickKnownSettings(after.settings)).filter(key => JSON.stringify(after.settings[key]) !== JSON.stringify((before.settings || {})[key])).length;
12157
12155
 
12158
12156
  if (changed) {
12159
12157
  parts.push(`설정 ${changed}개`);
@@ -12575,6 +12573,10 @@
12575
12573
  delete incoming.devices;
12576
12574
  skippedFields(conf.skip).forEach(field => delete incoming[field]);
12577
12575
 
12576
+ if (incoming.settings) {
12577
+ incoming.settings = pickKnownSettings(incoming.settings);
12578
+ }
12579
+
12578
12580
  const mine = {};
12579
12581
 
12580
12582
  Object.keys(incoming).forEach(field => {
@@ -13887,82 +13889,6 @@
13887
13889
  }
13888
13890
  }
13889
13891
 
13890
- const renderRecentStrip = () => {
13891
- const pop = document.getElementById('lately_pop');
13892
-
13893
- if (!IS_MOBILE_SITE || !pop || settings.mobileRecentStrip === false) {
13894
- document.documentElement.classList.remove('dc-recent-strip-on');
13895
- pop?.querySelector('.dc-recent-strip')?.remove();
13896
- return;
13897
- }
13898
-
13899
- const latelyTab = document.getElementById('lately_gall');
13900
- const showing = !latelyTab || latelyTab.classList.contains('on');
13901
- let strip = pop.querySelector('.dc-recent-strip');
13902
-
13903
- if (!strip) {
13904
- strip = h('div', 'dc-ui dc-recent-strip');
13905
- strip.setAttribute('role', 'list');
13906
- const slider = pop.querySelector('#swiper-lately') || pop.querySelector('.vst-slider');
13907
-
13908
- (slider ? slider.parentNode : pop).insertBefore(strip, slider || null);
13909
- }
13910
-
13911
- document.documentElement.classList.add('dc-recent-strip-on');
13912
- strip.hidden = !showing;
13913
- pop.classList.toggle('dc-strip-lately', showing);
13914
-
13915
- if (!showing) {
13916
- return;
13917
- }
13918
-
13919
- const keepScroll = strip.scrollLeft;
13920
-
13921
- strip.textContent = '';
13922
-
13923
- if (!recentGalls.length) {
13924
- strip.appendChild(h('span', 'dc-rs-empty', '최근 방문한 갤러리가 없습니다'));
13925
- return;
13926
- }
13927
-
13928
- const here = (currentGalleryVisit() || {}).id;
13929
-
13930
- recentGalls.forEach(item => {
13931
- const chip = h('a', `dc-rs-chip${item.id === here ? ' here' : ''}`);
13932
-
13933
- chip.href = recentUrl(item);
13934
- chip.setAttribute('role', 'listitem');
13935
- chip.appendChild(h('span', 'dc-rs-name', item.n || item.id));
13936
-
13937
- if (RECENT_KIND_LABEL[item.k]) {
13938
- chip.appendChild(h('span', 'dc-rs-kind', item.k === 'M' ? 'ⓜ' : item.k === 'N' ? 'ⓝ' : 'ⓟ'));
13939
- }
13940
-
13941
- const del = h('button', 'dc-rs-del', '×');
13942
-
13943
- del.type = 'button';
13944
- del.setAttribute('aria-label', `${item.n || item.id} 지우기`);
13945
- del.addEventListener('click', event => {
13946
- event.preventDefault();
13947
- event.stopPropagation();
13948
- recentGalls = recentGalls.filter(other => other !== item);
13949
- saveRecent();
13950
- exportNativeRecent();
13951
- renderRecentStrip();
13952
- });
13953
- chip.appendChild(del);
13954
- strip.appendChild(chip);
13955
- });
13956
-
13957
- if (recentOrder.fixed) {
13958
- strip.appendChild(h('span', 'dc-rs-pin', '📌 순서 고정'));
13959
- }
13960
-
13961
- strip.scrollLeft = keepScroll;
13962
-
13963
- strip.querySelector('.dc-rs-chip.here')?.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });
13964
- };
13965
-
13966
13892
  const renderRecentBar = () => {
13967
13893
  const nav = IS_MOBILE_SITE ? document.querySelector('nav.nav') : null;
13968
13894
  let bar = document.getElementById('dc-recent-bar');
@@ -13982,9 +13908,21 @@
13982
13908
  try {
13983
13909
  const cs = getComputedStyle(nav);
13984
13910
  const active = nav.querySelector('li.on a') || nav.querySelector('a');
13985
-
13986
- bar.style.setProperty('--dc-rb-bg', cs.backgroundColor);
13987
- bar.style.setProperty('--dc-rb-on', active ? getComputedStyle(active).color : '#ffe10a');
13911
+ const plain = nav.querySelector('li:not(.on) a') || active;
13912
+ const items = [...nav.querySelectorAll('li')].filter(li => li.getBoundingClientRect().width);
13913
+ const gap = items.length > 1 ? Math.round(items[1].getBoundingClientRect().left - items[0].getBoundingClientRect().right) : 30;
13914
+ const ps = plain ? getComputedStyle(plain) : null;
13915
+ const set = (name, value) => value && bar.style.setProperty(name, value);
13916
+
13917
+ set('--dc-rb-bg', cs.backgroundColor);
13918
+ set('--dc-rb-on', active ? getComputedStyle(active).color : '');
13919
+ set('--dc-rb-color', ps ? ps.color : '');
13920
+ set('--dc-rb-size', ps ? ps.fontSize : '');
13921
+ set('--dc-rb-weight', ps ? ps.fontWeight : '');
13922
+ set('--dc-rb-family', ps ? ps.fontFamily : '');
13923
+ set('--dc-rb-spacing', ps ? ps.letterSpacing : '');
13924
+ set('--dc-rb-gap', `${Math.max(16, Math.min(40, gap))}px`);
13925
+ set('--dc-rb-pad', items[0] ? `${Math.round(items[0].getBoundingClientRect().left - nav.getBoundingClientRect().left)}px` : '');
13988
13926
  } catch {
13989
13927
  }
13990
13928
 
@@ -14019,41 +13957,11 @@
14019
13957
  }
14020
13958
  };
14021
13959
 
14022
- const watchRecentStrip = () => {
14023
- const pop = document.getElementById('lately_pop');
14024
-
14025
- if (!IS_MOBILE_SITE || !pop) {
14026
- return;
14027
- }
14028
-
14029
- let timer = null;
14030
- const refresh = () => {
14031
- clearTimeout(timer);
14032
- timer = setTimeout(() => {
14033
- if (pop.style.display !== 'none') {
14034
- importNativeRecent();
14035
- renderRecentStrip();
14036
- }
14037
- }, 30);
14038
- };
14039
-
14040
- new MutationObserver(refresh).observe(pop, { attributes: true, attributeFilter: ['style'] });
14041
-
14042
- const tabs = pop.querySelector('.tab-lst');
14043
-
14044
- if (tabs) {
14045
- new MutationObserver(refresh).observe(tabs, { attributes: true, subtree: true, attributeFilter: ['class'] });
14046
- }
14047
-
14048
- renderRecentStrip();
14049
- };
14050
-
14051
13960
  const initRecent = () => {
14052
13961
  importNativeRecent();
14053
13962
  recordGalleryVisit();
14054
13963
  exportNativeRecent();
14055
13964
  watchNativeRecentDom();
14056
- watchRecentStrip();
14057
13965
  renderRecentBar();
14058
13966
 
14059
13967
  const follow = () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kangsicj/dcinsideenhancer",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "description": "DCInside filter & enhancer userscript for mobile and PC (디시인사이드 차단·편의 유저스크립트)",
5
5
  "license": "GPL-3.0-only",
6
6
  "author": "kangsicj",
@@ -12,10 +12,10 @@
12
12
  "bugs": {
13
13
  "url": "https://github.com/kangsicj/DCInsideEnhancer/issues"
14
14
  },
15
- "funding": {
16
- "type": "individual",
17
- "url": "https://fairy.hada.io/@jinny"
18
- },
15
+ "funding": [
16
+ { "type": "individual", "url": "https://fairy.hada.io/@kangsicj" },
17
+ { "type": "individual", "url": "https://buymeacoffee.com/kangsicj" }
18
+ ],
19
19
  "keywords": [
20
20
  "userscript",
21
21
  "tampermonkey",