deepseek-harness-background 0.4.0 → 0.4.1
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/lib/client.js +175 -56
- package/lib/client.js.map +1 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -75,7 +75,13 @@ window.__ModuleLoader__.load({
|
|
|
75
75
|
*
|
|
76
76
|
* Selectors target authored attributes (`data-dsh-bg`, `data-composer-card`,
|
|
77
77
|
* `data-terminal`…), the `:global` `.md-code-block` anchor, and CSS-module
|
|
78
|
-
* SUFFIX conventions (`_bubble`, `_newSession`…) audited for collisions
|
|
78
|
+
* SUFFIX conventions (`_bubble`, `_newSession`…) audited for collisions.
|
|
79
|
+
*
|
|
80
|
+
* MAINTENANCE NOTE: the suffix anchors are the host's only stable-enough
|
|
81
|
+
* integration surface today, but a host restyle that renames them silently
|
|
82
|
+
* drops the glass. Upgrade path: once the host ships stable data-* anchors
|
|
83
|
+
* for these surfaces, swap the selector lists below to them and delete the
|
|
84
|
+
* suffix entries.
|
|
79
85
|
* `_bubble` excludes `role="tooltip"` (Tooltip.module.css shares the suffix),
|
|
80
86
|
* `_add` is scoped under `[data-composer-card]` (DiffBlock line markers share
|
|
81
87
|
* it), `_newSession` excludes `Label` (the button's inner label span) and
|
|
@@ -440,6 +446,8 @@ window.__ModuleLoader__.load({
|
|
|
440
446
|
observer;
|
|
441
447
|
active = false;
|
|
442
448
|
settings;
|
|
449
|
+
/** Whether the current section resolves to an actual image source. */
|
|
450
|
+
hasSource = false;
|
|
443
451
|
savedTokens = /* @__PURE__ */ new Map();
|
|
444
452
|
savedVars = /* @__PURE__ */ new Map();
|
|
445
453
|
/** Remember + hijack a property only once so dispose restores the original. */
|
|
@@ -468,6 +476,7 @@ window.__ModuleLoader__.load({
|
|
|
468
476
|
this.restoreFrameTokens();
|
|
469
477
|
this.applySurfaceGlass(settings, true);
|
|
470
478
|
this.active = false;
|
|
479
|
+
this.hasSource = false;
|
|
471
480
|
this.removeLayers();
|
|
472
481
|
document.body.removeAttribute(ACTIVE_ATTR);
|
|
473
482
|
return;
|
|
@@ -483,10 +492,20 @@ window.__ModuleLoader__.load({
|
|
|
483
492
|
this.img.className = IMAGE_CLASS;
|
|
484
493
|
this.img.alt = "";
|
|
485
494
|
this.img.referrerPolicy = "no-referrer";
|
|
495
|
+
this.img.onerror = () => {
|
|
496
|
+
if (this.img === null || this.img.dataset.failed === "1") return;
|
|
497
|
+
this.img.dataset.failed = "1";
|
|
498
|
+
this.img.style.visibility = "hidden";
|
|
499
|
+
console.warn("[deepseek-harness-background] wallpaper image failed to load:", this.img.getAttribute("src"));
|
|
500
|
+
};
|
|
486
501
|
this.layer.appendChild(this.img);
|
|
487
502
|
document.body.appendChild(this.layer);
|
|
488
503
|
}
|
|
489
|
-
if (this.img && this.img.getAttribute("src") !== url)
|
|
504
|
+
if (this.img && this.img.getAttribute("src") !== url) {
|
|
505
|
+
delete this.img.dataset.failed;
|
|
506
|
+
this.img.style.visibility = "";
|
|
507
|
+
this.img.src = url;
|
|
508
|
+
}
|
|
490
509
|
if (!this.scrim) {
|
|
491
510
|
this.scrim = document.createElement("div");
|
|
492
511
|
this.scrim.className = SCRIM_CLASS;
|
|
@@ -494,6 +513,7 @@ window.__ModuleLoader__.load({
|
|
|
494
513
|
}
|
|
495
514
|
document.body.setAttribute(ACTIVE_ATTR, "on");
|
|
496
515
|
this.active = true;
|
|
516
|
+
this.hasSource = true;
|
|
497
517
|
document.body.style;
|
|
498
518
|
this.setVar("--bg-object-fit", settings.fit);
|
|
499
519
|
this.setVar("--bg-opacity", String(settings.opacity));
|
|
@@ -546,6 +566,15 @@ window.__ModuleLoader__.load({
|
|
|
546
566
|
case "scrim":
|
|
547
567
|
this.setVar("--bg-scrim", String(value));
|
|
548
568
|
break;
|
|
569
|
+
case "panelOpacity": {
|
|
570
|
+
const next = {
|
|
571
|
+
...this.settings,
|
|
572
|
+
panelOpacity: Number(value)
|
|
573
|
+
};
|
|
574
|
+
this.settings = next;
|
|
575
|
+
this.applySurfaceGlass(next, !this.hasSource);
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
549
578
|
case "blur":
|
|
550
579
|
this.setVar("--bg-glass-blur", `${value}px`);
|
|
551
580
|
this.setVar("--bg-glass-saturate", String(glassSaturate(Number(value))));
|
|
@@ -696,14 +725,22 @@ window.__ModuleLoader__.load({
|
|
|
696
725
|
const REGISTRY_CSS_TAG = "deepseek-harness-background/glass-registry";
|
|
697
726
|
/** Plugin identity stamped onto the registry <style> element. */
|
|
698
727
|
const PLUGIN_ID = "deepseek-harness-background";
|
|
699
|
-
/**
|
|
728
|
+
/**
|
|
729
|
+
* Characters whose presence would let a selector escape its rule context.
|
|
730
|
+
* ',' is refused too: inside the generated rule body
|
|
731
|
+
* (`body[gate] <selector> { … }`) a comma lets one registration broaden the
|
|
732
|
+
* rule to ARBITRARY extra subjects (`.x, html body`) — an unintended
|
|
733
|
+
* widening of the glass sheet beyond the registered surface. Multiple
|
|
734
|
+
* surfaces stay supported through the selectors ARRAY.
|
|
735
|
+
*/
|
|
700
736
|
const FORBIDDEN_SELECTOR_CHARS = [
|
|
701
737
|
"{",
|
|
702
738
|
"}",
|
|
703
739
|
";",
|
|
704
740
|
"@",
|
|
705
741
|
"<",
|
|
706
|
-
">"
|
|
742
|
+
">",
|
|
743
|
+
","
|
|
707
744
|
];
|
|
708
745
|
/** Hard cap on one selector's length (diagnostics-friendly, abuse-proof). */
|
|
709
746
|
const MAX_SELECTOR_LENGTH = 500;
|
|
@@ -916,7 +953,8 @@ window.__ModuleLoader__.load({
|
|
|
916
953
|
"timeline.marksOnly": "★ 只看标记",
|
|
917
954
|
"timeline.mark": "标记为重点",
|
|
918
955
|
"timeline.unmark": "取消重点标记",
|
|
919
|
-
"timeline.noMarks": "还没有标记的重点"
|
|
956
|
+
"timeline.noMarks": "还没有标记的重点",
|
|
957
|
+
"timeline.cannotJump": "无法跳转:这条历史消息缺少定位信息"
|
|
920
958
|
};
|
|
921
959
|
/** English copy. */
|
|
922
960
|
const en = {
|
|
@@ -952,7 +990,8 @@ window.__ModuleLoader__.load({
|
|
|
952
990
|
"timeline.marksOnly": "★ Marked only",
|
|
953
991
|
"timeline.mark": "Mark as key point",
|
|
954
992
|
"timeline.unmark": "Unmark key point",
|
|
955
|
-
"timeline.noMarks": "No marked key points"
|
|
993
|
+
"timeline.noMarks": "No marked key points",
|
|
994
|
+
"timeline.cannotJump": "Cannot jump: this history message lacks position info"
|
|
956
995
|
};
|
|
957
996
|
//#endregion
|
|
958
997
|
//#region node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
@@ -1087,41 +1126,41 @@ window.__ModuleLoader__.load({
|
|
|
1087
1126
|
document.head.appendChild(tag);
|
|
1088
1127
|
}
|
|
1089
1128
|
var SettingsRow_module_css_default = {
|
|
1090
|
-
"
|
|
1129
|
+
"row": "-ozqdq_row",
|
|
1130
|
+
"segBtn": "-ozqdq_segBtn",
|
|
1091
1131
|
"preview": "-ozqdq_preview",
|
|
1092
|
-
"sliderLabel": "-ozqdq_sliderLabel",
|
|
1093
|
-
"segRow": "-ozqdq_segRow",
|
|
1094
1132
|
"urlRow": "-ozqdq_urlRow",
|
|
1133
|
+
"sliderValue": "-ozqdq_sliderValue",
|
|
1134
|
+
"titleRow": "-ozqdq_titleRow",
|
|
1135
|
+
"clearBtn": "-ozqdq_clearBtn",
|
|
1136
|
+
"segRow": "-ozqdq_segRow",
|
|
1137
|
+
"enabledBadge": "-ozqdq_enabledBadge",
|
|
1138
|
+
"title": "-ozqdq_title",
|
|
1095
1139
|
"previewImg": "-ozqdq_previewImg",
|
|
1096
|
-
"previewGlass": "-ozqdq_previewGlass",
|
|
1097
|
-
"hint": "-ozqdq_hint",
|
|
1098
1140
|
"header": "-ozqdq_header",
|
|
1141
|
+
"previewGlass": "-ozqdq_previewGlass",
|
|
1142
|
+
"sliderRow": "-ozqdq_sliderRow",
|
|
1143
|
+
"previewGlassText": "-ozqdq_previewGlassText",
|
|
1099
1144
|
"slider": "-ozqdq_slider",
|
|
1100
|
-
"
|
|
1101
|
-
"
|
|
1102
|
-
"
|
|
1145
|
+
"switch": "-ozqdq_switch",
|
|
1146
|
+
"sourceRow": "-ozqdq_sourceRow",
|
|
1147
|
+
"clearRow": "-ozqdq_clearRow",
|
|
1103
1148
|
"error": "-ozqdq_error",
|
|
1104
|
-
"
|
|
1105
|
-
"btnPrimary": "-ozqdq_btnPrimary",
|
|
1106
|
-
"clearBtn": "-ozqdq_clearBtn",
|
|
1107
|
-
"sectionLabel": "-ozqdq_sectionLabel",
|
|
1108
|
-
"switchKnob": "-ozqdq_switchKnob",
|
|
1109
|
-
"section": "-ozqdq_section",
|
|
1110
|
-
"sliderValue": "-ozqdq_sliderValue",
|
|
1111
|
-
"row": "-ozqdq_row",
|
|
1149
|
+
"sliderLabel": "-ozqdq_sliderLabel",
|
|
1112
1150
|
"previewScrim": "-ozqdq_previewScrim",
|
|
1151
|
+
"urlInput": "-ozqdq_urlInput",
|
|
1113
1152
|
"desc": "-ozqdq_desc",
|
|
1153
|
+
"previewEmpty": "-ozqdq_previewEmpty",
|
|
1154
|
+
"section": "-ozqdq_section",
|
|
1155
|
+
"hint": "-ozqdq_hint",
|
|
1156
|
+
"btn": "-ozqdq_btn",
|
|
1114
1157
|
"segGroup": "-ozqdq_segGroup",
|
|
1115
|
-
"
|
|
1158
|
+
"segLabel": "-ozqdq_segLabel",
|
|
1159
|
+
"sectionLabel": "-ozqdq_sectionLabel",
|
|
1160
|
+
"btnPrimary": "-ozqdq_btnPrimary",
|
|
1116
1161
|
"segActive": "-ozqdq_segActive",
|
|
1117
|
-
"
|
|
1118
|
-
"
|
|
1119
|
-
"titleRow": "-ozqdq_titleRow",
|
|
1120
|
-
"btnDanger": "-ozqdq_btnDanger",
|
|
1121
|
-
"previewGlassText": "-ozqdq_previewGlassText",
|
|
1122
|
-
"sourceRow": "-ozqdq_sourceRow",
|
|
1123
|
-
"segBtn": "-ozqdq_segBtn",
|
|
1124
|
-
"previewEmpty": "-ozqdq_previewEmpty"
|
|
1162
|
+
"switchKnob": "-ozqdq_switchKnob",
|
|
1163
|
+
"btnDanger": "-ozqdq_btnDanger"
|
|
1125
1164
|
};
|
|
1126
1165
|
//#endregion
|
|
1127
1166
|
//#region src/client/SettingsRow.tsx
|
|
@@ -1320,8 +1359,7 @@ window.__ModuleLoader__.load({
|
|
|
1320
1359
|
};
|
|
1321
1360
|
draftRef.current = next;
|
|
1322
1361
|
markEditing();
|
|
1323
|
-
|
|
1324
|
-
else paintBackgroundKnob(key, value);
|
|
1362
|
+
paintBackgroundKnob(key, value);
|
|
1325
1363
|
if (previewRef.current) paintPreviewSurface(previewRef.current, next);
|
|
1326
1364
|
}, [markEditing]);
|
|
1327
1365
|
/** Persist one section through the host route and adopt it on success. */
|
|
@@ -1329,6 +1367,7 @@ window.__ModuleLoader__.load({
|
|
|
1329
1367
|
dirtyRef.current = true;
|
|
1330
1368
|
const result = await settingsClient.save(next);
|
|
1331
1369
|
if (result === "failed") {
|
|
1370
|
+
dirtyRef.current = false;
|
|
1332
1371
|
setError(t("background.saveFailed"));
|
|
1333
1372
|
return;
|
|
1334
1373
|
}
|
|
@@ -1877,6 +1916,8 @@ window.__ModuleLoader__.load({
|
|
|
1877
1916
|
display: flex; align-items: center; justify-content: flex-end;
|
|
1878
1917
|
}
|
|
1879
1918
|
.dsbt-jump:focus-visible { outline: 1px solid currentColor; outline-offset: -1px; border-radius: 6px; }
|
|
1919
|
+
.dsbt-jump:disabled { cursor: default; opacity: .55; }
|
|
1920
|
+
.dsbt-jump:disabled .dsbt-title { text-decoration: line-through; text-decoration-color: currentColor; }
|
|
1880
1921
|
.dsbt-item:hover { color: var(--dsw-alias-label-primary, rgba(0, 0, 0, .95)); }
|
|
1881
1922
|
body[data-ds-dark-theme] .dsbt-item { color: rgba(255, 255, 255, .65); }
|
|
1882
1923
|
body[data-ds-dark-theme] .dsbt-item:hover { color: rgba(255, 255, 255, .95); }
|
|
@@ -2175,6 +2216,19 @@ window.__ModuleLoader__.load({
|
|
|
2175
2216
|
out.sort((a, b) => a.seq - b.seq);
|
|
2176
2217
|
return out;
|
|
2177
2218
|
}
|
|
2219
|
+
/**
|
|
2220
|
+
* Count the user messages the loaded window holds WITHOUT collecting or
|
|
2221
|
+
* sorting them — the fast gate railMessages uses to skip the merge path on
|
|
2222
|
+
* the streaming hot path (see there).
|
|
2223
|
+
* @param chat - the loaded chat snapshot.
|
|
2224
|
+
*/
|
|
2225
|
+
function countWindowUserMessages(chat) {
|
|
2226
|
+
const nodes = chat?.nodes;
|
|
2227
|
+
if (nodes === void 0 || typeof nodes.values !== "function") return 0;
|
|
2228
|
+
let count = 0;
|
|
2229
|
+
for (const node of nodes.values()) if (node !== null && typeof node === "object" && node.kind === "user") count += 1;
|
|
2230
|
+
return count;
|
|
2231
|
+
}
|
|
2178
2232
|
/** Resolve the DOM anchor key of one entry (direct key form only). */
|
|
2179
2233
|
function resolveAnchorKey(m) {
|
|
2180
2234
|
return typeof m.key === "string" && m.key !== "" ? m.key : void 0;
|
|
@@ -2219,24 +2273,44 @@ window.__ModuleLoader__.load({
|
|
|
2219
2273
|
return out;
|
|
2220
2274
|
}
|
|
2221
2275
|
/**
|
|
2222
|
-
* Rail messages
|
|
2223
|
-
*
|
|
2224
|
-
*
|
|
2225
|
-
*
|
|
2226
|
-
*
|
|
2227
|
-
*
|
|
2276
|
+
* Rail messages: the host projection (whole-session index) MERGED with the
|
|
2277
|
+
* loaded chat-node window. The projection normally wins outright, but a
|
|
2278
|
+
* projection that lost its baseline (e.g. the plugin was hot-reloaded after
|
|
2279
|
+
* the session's tail page seeded the client store) can miss early entries —
|
|
2280
|
+
* the window fills those gaps whenever it holds them, and window entries
|
|
2281
|
+
* lend their real anchor key to projected entries whose durable id was
|
|
2282
|
+
* absent (early events without one). Locally-known rewind hiding applies to
|
|
2283
|
+
* the merged list so a cut lands instantly, before the next projection push.
|
|
2284
|
+
* @param snapshot - the session conversation snapshot (node window).
|
|
2228
2285
|
* @param projected - the raw bgTimeline projection value.
|
|
2229
2286
|
*/
|
|
2230
2287
|
function railMessages(snapshot, projected) {
|
|
2231
2288
|
const projectedMessages = normalizeProjectedTimeline(projected);
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2289
|
+
const chat = snapshot?.chat;
|
|
2290
|
+
const hidden = rewindHiddenSeqsOfChat(chat);
|
|
2291
|
+
const spans = rewindSpansOfChat(chat);
|
|
2292
|
+
const isHidden = (seq) => hidden.has(seq) || spans.some((span) => seq >= span.start && seq <= span.end);
|
|
2293
|
+
if (projectedMessages.length === 0) return collectMessages(snapshot);
|
|
2294
|
+
const windowUserCount = countWindowUserMessages(chat);
|
|
2295
|
+
const projectionLacksKeys = projectedMessages.some((m) => m.key === void 0);
|
|
2296
|
+
if (windowUserCount <= projectedMessages.length && !projectionLacksKeys) return hidden.size === 0 && spans.length === 0 ? projectedMessages : projectedMessages.filter((m) => !isHidden(m.seq));
|
|
2297
|
+
const windowMessages = collectMessages(snapshot);
|
|
2298
|
+
const bySeq = /* @__PURE__ */ new Map();
|
|
2299
|
+
for (const m of projectedMessages) if (!isHidden(m.seq)) bySeq.set(m.seq, m);
|
|
2300
|
+
for (const m of windowMessages) {
|
|
2301
|
+
if (isHidden(m.seq)) continue;
|
|
2302
|
+
const existing = bySeq.get(m.seq);
|
|
2303
|
+
if (existing === void 0) {
|
|
2304
|
+
bySeq.set(m.seq, m);
|
|
2305
|
+
continue;
|
|
2306
|
+
}
|
|
2307
|
+
if (existing.key === void 0 && m.key !== void 0) bySeq.set(m.seq, {
|
|
2308
|
+
...existing,
|
|
2309
|
+
key: m.key,
|
|
2310
|
+
...existing.text === "" && m.text !== "" ? { text: m.text } : {}
|
|
2311
|
+
});
|
|
2238
2312
|
}
|
|
2239
|
-
return
|
|
2313
|
+
return [...bySeq.values()].sort((a, b) => a.seq - b.seq);
|
|
2240
2314
|
}
|
|
2241
2315
|
/**
|
|
2242
2316
|
* Outer rail height for a message count: rows + breathing room, clamped so
|
|
@@ -2270,26 +2344,70 @@ window.__ModuleLoader__.load({
|
|
|
2270
2344
|
}
|
|
2271
2345
|
return Math.round(Math.max(RAIL_MIN_WIDTH, Math.min(RAIL_MAX_WIDTH, widest + 6 + 24 + 16 + 12)));
|
|
2272
2346
|
}
|
|
2273
|
-
/**
|
|
2274
|
-
|
|
2347
|
+
/** How long one jump may keep paging older history before giving up. */
|
|
2348
|
+
const JUMP_PAGE_DEADLINE_MS = 3e4;
|
|
2349
|
+
/** How long to wait for the chat view to commit the target row. */
|
|
2350
|
+
const JUMP_ROW_WAIT_MS = 3e3;
|
|
2351
|
+
/**
|
|
2352
|
+
* Poll the conversation DOM until the target row is committed. The session
|
|
2353
|
+
* store updates BEFORE React renders the prepended page, so the old one-shot
|
|
2354
|
+
* query right after loadOlder() resolved could miss the row and silently
|
|
2355
|
+
* give up — the reported "click does nothing until the conversation is
|
|
2356
|
+
* nudged (scroll/click)" behavior.
|
|
2357
|
+
* @param key - chat anchor key to look for.
|
|
2358
|
+
* @param timeoutMs - polling budget.
|
|
2359
|
+
*/
|
|
2360
|
+
async function waitForChatRow(key, timeoutMs) {
|
|
2361
|
+
const scrollports = Array.from(document.querySelectorAll("[data-conversation-scroll]"));
|
|
2362
|
+
if (scrollports.length === 0) return null;
|
|
2363
|
+
const selector = `[data-chat-anchor-key="${CSS.escape(key)}"]`;
|
|
2364
|
+
const deadline = Date.now() + timeoutMs;
|
|
2365
|
+
for (;;) {
|
|
2366
|
+
for (const scrollport of scrollports) {
|
|
2367
|
+
const row = scrollport.querySelector(selector);
|
|
2368
|
+
if (row !== null) return row;
|
|
2369
|
+
}
|
|
2370
|
+
if (Date.now() >= deadline) return null;
|
|
2371
|
+
await delay(40);
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
/**
|
|
2375
|
+
* Ensure the target node is loaded, wait for the chat view to commit its row
|
|
2376
|
+
* into the DOM, then scroll it into view. Paging uses a time budget instead
|
|
2377
|
+
* of the old fixed 120-iteration guard (each in-flight page burned 50ms of
|
|
2378
|
+
* that guard, so slow history could exhaust it and silently fail).
|
|
2379
|
+
*/
|
|
2380
|
+
async function jumpToMessage(sessionsService, sessionId, key, rowWaitMs = JUMP_ROW_WAIT_MS) {
|
|
2275
2381
|
const session = sessionsService.binding(sessionId)?.session;
|
|
2276
2382
|
if (session === void 0) return false;
|
|
2277
|
-
|
|
2278
|
-
|
|
2383
|
+
const deadline = Date.now() + JUMP_PAGE_DEADLINE_MS;
|
|
2384
|
+
for (;;) {
|
|
2279
2385
|
const snapshot = session.getSnapshot();
|
|
2280
2386
|
if (snapshot?.chat?.nodes?.get(key) !== void 0) break;
|
|
2281
|
-
if (snapshot?.hasMore !== true)
|
|
2387
|
+
if (snapshot?.hasMore !== true) break;
|
|
2388
|
+
if (Date.now() >= deadline) break;
|
|
2282
2389
|
if (snapshot.loadingOlder === true) {
|
|
2283
2390
|
await delay(50);
|
|
2284
2391
|
continue;
|
|
2285
2392
|
}
|
|
2393
|
+
if (snapshot.openState !== void 0 && snapshot.openState !== "open") {
|
|
2394
|
+
await delay(100);
|
|
2395
|
+
continue;
|
|
2396
|
+
}
|
|
2286
2397
|
await session.loadOlder();
|
|
2287
2398
|
}
|
|
2288
|
-
const row =
|
|
2289
|
-
if (row === null)
|
|
2399
|
+
const row = await waitForChatRow(key, rowWaitMs);
|
|
2400
|
+
if (row === null) {
|
|
2401
|
+
console.warn(`[deepseek-harness-background] timeline jump target never rendered: ${key}`);
|
|
2402
|
+
return false;
|
|
2403
|
+
}
|
|
2290
2404
|
const reducedMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
2291
2405
|
row.scrollIntoView({
|
|
2292
|
-
behavior:
|
|
2406
|
+
behavior: "auto",
|
|
2407
|
+
block: "center"
|
|
2408
|
+
});
|
|
2409
|
+
if (!reducedMotion) row.scrollIntoView({
|
|
2410
|
+
behavior: "smooth",
|
|
2293
2411
|
block: "center"
|
|
2294
2412
|
});
|
|
2295
2413
|
return true;
|
|
@@ -2578,8 +2696,9 @@ window.__ModuleLoader__.load({
|
|
|
2578
2696
|
type: "button",
|
|
2579
2697
|
className: "dsbt-jump",
|
|
2580
2698
|
ref: isActive ? activeItemRef : void 0,
|
|
2581
|
-
|
|
2582
|
-
"
|
|
2699
|
+
disabled: key === void 0,
|
|
2700
|
+
title: key === void 0 ? t("timeline.cannotJump") : `${marked ? "★ " : ""}${m.text === "" ? t("timeline.noText") : m.text}`,
|
|
2701
|
+
"aria-label": key === void 0 ? `${marked ? "★ " : ""}${t("timeline.roleUser")}: ${t("timeline.cannotJump")}` : `${marked ? "★ " : ""}${t("timeline.roleUser")}: ${m.text.slice(0, 60) || t("timeline.noText")}`,
|
|
2583
2702
|
"aria-current": isActive ? "location" : void 0,
|
|
2584
2703
|
onClick: () => {
|
|
2585
2704
|
if (key === void 0) return;
|