dsh-milestone 0.7.1 → 0.7.2

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.md CHANGED
@@ -140,7 +140,14 @@ shell.overlay (root scope)
140
140
  ## 更新日志
141
141
 
142
142
  <details>
143
- <summary>v0.7.1 / v0.7.0 / v0.6.6 / v0.6.5 / v0.6.4(点击展开)</summary>
143
+ <summary>v0.7.2 / v0.7.1 / v0.7.0 / v0.6.6 / v0.6.5 / v0.6.4(点击展开)</summary>
144
+
145
+ **v0.7.2** · 点击旧圆点自动翻页定位(深跳鲁棒性)· 459 项测试
146
+
147
+ - **点旧圆点不再"没反应"**:里程碑条覆盖整个会话,但 DOM 只渲染已加载窗口——此前点一个很早的圆点会静默无反应。现在会自动按页载入更早历史直到定位(有界 20 页),定位期间该圆点脉冲提示,失败则安静结束。
148
+ - 站内搜索的"下一个匹配"跳转同样受益。
149
+
150
+ > [GitHub Release v0.7.2](https://github.com/SnowCrescenter-tech/dsh-milestone/releases/tag/v0.7.2)
144
151
 
145
152
  **v0.7.1** · 升级不再被卡(可选 peer + 兼容边界)· 恢复模型与错误徽标 · 跟随官方 0.1.5-rc.2 · 457 项测试
146
153
 
package/lib/client.js CHANGED
@@ -2865,7 +2865,7 @@ window.__ModuleLoader__.load({
2865
2865
  * Installed plugin version. Injected at build time as
2866
2866
  * `__DSH_MILESTONE_VERSION__`; falls back to `0.0.0-dev` when unbuilt.
2867
2867
  */
2868
- const PLUGIN_VERSION = "0.7.1";
2868
+ const PLUGIN_VERSION = "0.7.2";
2869
2869
  //#endregion
2870
2870
  //#region src/client/MilestoneRail.tsx
2871
2871
  /**
@@ -3137,6 +3137,18 @@ window.__ModuleLoader__.load({
3137
3137
  const DEEP_LINK_MAX_POLLS = 5;
3138
3138
  /** P3: bounded polls after `loadOlder`, then the deep link gives up silently. */
3139
3139
  const DEEP_LINK_MAX_RETRY_POLLS = 5;
3140
+ /**
3141
+ * Jump paging: the rail's dots cover the WHOLE log while the DOM renders only
3142
+ * the loaded window, so activating an older dot must page history in first.
3143
+ * Bounded so an unreachable target gives up instead of paging forever.
3144
+ */
3145
+ const LOCATE_MAX_PAGES = 20;
3146
+ /** Delay between a page fetch and the DOM-row recheck (lets React commit). */
3147
+ const LOCATE_POLL_DELAY = 150;
3148
+ /** Pulse applied to the dot whose jump is still paging history in. */
3149
+ const LOCATING_CSS = `@keyframes ms-locating { 0%, 100% { opacity: 1 } 50% { opacity: 0.35 } }
3150
+ [data-locating="true"] { animation: ms-locating 800ms ease-in-out infinite; }
3151
+ @media (prefers-reduced-motion: reduce) { [data-locating="true"] { animation: none } }`;
3140
3152
  /** B4 update-check: mount-time silent check delay (ms) — give the harness
3141
3153
  * time to settle before hitting the registry. */
3142
3154
  const UPDATE_CHECK_MOUNT_DELAY = 1500;
@@ -3238,6 +3250,13 @@ window.__ModuleLoader__.load({
3238
3250
  const listRef = (0, react.useRef)(null);
3239
3251
  const currentKey = useCurrentAnchor(marks.map((m) => m.key));
3240
3252
  /**
3253
+ * Mark key whose jump is still paging older history in; its dot pulses so a
3254
+ * slow locate never looks like a dead click.
3255
+ */
3256
+ const [locatingKey, setLocatingKey] = (0, react.useState)(null);
3257
+ /** Guards against overlapping locate loops (a second activation is ignored). */
3258
+ const locatingRef = (0, react.useRef)(false);
3259
+ /**
3241
3260
  * P3: jump to the chat row with the given node key — smooth-scroll it into
3242
3261
  * view and write the position back into the URL hash (`#msg=<key>`) so
3243
3262
  * refresh and share preserve it. `history.replaceState` (not a
@@ -3255,6 +3274,45 @@ window.__ModuleLoader__.load({
3255
3274
  });
3256
3275
  history.replaceState(null, "", buildMessageHash(key));
3257
3276
  };
3277
+ /**
3278
+ * Jump to a mark, paging older history in first when its row is not rendered
3279
+ * yet. The dots cover the whole log but the DOM holds only the loaded window,
3280
+ * so without this an older dot is a silent no-op (the official rail pages
3281
+ * unloaded turns in the same way). Bounded to LOCATE_MAX_PAGES fetches; the
3282
+ * dot pulses meanwhile.
3283
+ * @param key - the mark key (deep-link payload + exact-match anchor).
3284
+ * @param messageId - the user/message id (real-harness anchor suffix).
3285
+ */
3286
+ const locateAndJump = (key, messageId) => {
3287
+ if (findRow(key, messageId) !== null) {
3288
+ jump(key, messageId);
3289
+ return;
3290
+ }
3291
+ if (!hasMore || locatingRef.current) return;
3292
+ locatingRef.current = true;
3293
+ setLocatingKey(key);
3294
+ (async () => {
3295
+ try {
3296
+ for (let page = 0; page < LOCATE_MAX_PAGES; page += 1) {
3297
+ try {
3298
+ await loadOlder();
3299
+ } catch {
3300
+ return;
3301
+ }
3302
+ await new Promise((resolve) => {
3303
+ window.setTimeout(resolve, LOCATE_POLL_DELAY);
3304
+ });
3305
+ if (findRow(key, messageId) !== null) {
3306
+ jump(key, messageId);
3307
+ return;
3308
+ }
3309
+ }
3310
+ } finally {
3311
+ locatingRef.current = false;
3312
+ setLocatingKey(null);
3313
+ }
3314
+ })();
3315
+ };
3258
3316
  const displayMarks = (0, react.useMemo)(() => {
3259
3317
  if (!bookmarksOnly) return marks;
3260
3318
  return filterByBookmarks(marks, bookmarkedKeys).visible.map((i) => marks[i]);
@@ -3624,7 +3682,7 @@ window.__ModuleLoader__.load({
3624
3682
  activePos: next
3625
3683
  }));
3626
3684
  const mark = displayMarks[matches[next]];
3627
- jump(mark.key, mark.messageId);
3685
+ locateAndJump(mark.key, mark.messageId);
3628
3686
  };
3629
3687
  const onSearchKeyDown = (e) => {
3630
3688
  if (e.key === "Enter") advanceMatch();
@@ -4211,6 +4269,7 @@ window.__ModuleLoader__.load({
4211
4269
  "data-inset": String(inset),
4212
4270
  children: [
4213
4271
  pulseCss !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: pulseCss }),
4272
+ locatingKey !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: LOCATING_CSS }),
4214
4273
  focusActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: buildFocusCss(prefs.focus) }),
4215
4274
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: MODAL_CSS }),
4216
4275
  showLoadOlder && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -5315,7 +5374,7 @@ window.__ModuleLoader__.load({
5315
5374
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5316
5375
  style: { color: "#8b96ab" },
5317
5376
  children: [t("update.current"), ": "]
5318
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "0.7.1" })] }),
5377
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "0.7.2" })] }),
5319
5378
  updateCheck.phase === "ok" && updateCheck.latest !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5320
5379
  "data-update-latest": true,
5321
5380
  children: [
@@ -5493,8 +5552,9 @@ window.__ModuleLoader__.load({
5493
5552
  top: rect.top + rect.height / 2
5494
5553
  });
5495
5554
  },
5496
- onClick: () => jump(mark.key, mark.messageId),
5555
+ onClick: () => locateAndJump(mark.key, mark.messageId),
5497
5556
  "data-rail-dot": true,
5557
+ "data-locating": locatingKey === mark.key ? "true" : void 0,
5498
5558
  "data-turn-gap": showGroupGap ? "true" : void 0,
5499
5559
  "data-turn": showGroupGap && mark.turn !== void 0 ? mark.turn : void 0,
5500
5560
  "data-collapsed-summary": summaryCount !== void 0 ? "true" : void 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-milestone",
3
- "version": "0.7.1",
3
+ "version": "0.7.2",
4
4
  "description": "Git-style milestone timeline for DeepSeek Harness: hover for metadata, click to jump to any message. 会话里程碑导航条:圆点时间线,定位并跳转到每条提问。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",