@co0ontty/wand 1.31.1 → 1.31.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.
|
@@ -106,6 +106,13 @@
|
|
|
106
106
|
terminalHealthTimer: null,
|
|
107
107
|
lastTerminalResyncAt: 0,
|
|
108
108
|
terminalAutoFollow: true,
|
|
109
|
+
// 程序触发的滚动(wand 主动 scrollTo / wterm 内部因 _shouldScrollToBottom=true
|
|
110
|
+
// 拽 scrollTop=scrollHeight)落到 scroll handler 时会被误判为"用户滚回严格
|
|
111
|
+
// 底部",把 autoFollow 反转回 true,把用户刚 wheel 上滚的意图吞掉。
|
|
112
|
+
// 存"窗口截止时间戳"而非"开始时间戳":不同调用方按各自动画长度延长窗口
|
|
113
|
+
// (瞬时 120ms 覆盖一次 rAF + 事件分发;smooth 500ms 覆盖 Chromium smooth
|
|
114
|
+
// scroll 动画),多次调用用 Math.max 合并、不会被短窗口缩短。
|
|
115
|
+
terminalProgrammaticScrollUntil: 0,
|
|
109
116
|
terminalScrollIdleTimer: null,
|
|
110
117
|
terminalScrollIdleMs: 1800,
|
|
111
118
|
terminalScrollThreshold: 12,
|
|
@@ -7081,6 +7088,16 @@
|
|
|
7081
7088
|
if (!state.terminal) return;
|
|
7082
7089
|
var viewport = getTerminalViewport();
|
|
7083
7090
|
if (!viewport) return;
|
|
7091
|
+
// 打"程序触发滚动"窗口:紧跟着的 scroll 事件是 wand 自己拽出来的,
|
|
7092
|
+
// scroll handler 在窗口内跳过 autoFollow 修改,避免"程序拽底 →
|
|
7093
|
+
// scroll 事件 → handler 看到在底 → autoFollow=true"的反馈环把
|
|
7094
|
+
// 用户刚 wheel 上滚的意图覆盖掉。smooth 模式 Chromium 滚动动画约
|
|
7095
|
+
// 300-500ms,瞬时滚动只需覆盖一次 rAF + 事件分发延迟。
|
|
7096
|
+
var windowMs = smooth ? 500 : 120;
|
|
7097
|
+
state.terminalProgrammaticScrollUntil = Math.max(
|
|
7098
|
+
state.terminalProgrammaticScrollUntil,
|
|
7099
|
+
Date.now() + windowMs
|
|
7100
|
+
);
|
|
7084
7101
|
if (smooth) {
|
|
7085
7102
|
viewport.scrollTo({ top: viewport.scrollHeight, behavior: "smooth" });
|
|
7086
7103
|
} else {
|
|
@@ -7487,7 +7504,36 @@
|
|
|
7487
7504
|
if (!state.wideParserState) state.wideParserState = createWideParserState();
|
|
7488
7505
|
var padded = widePadAnsi(data, state.wideParserState);
|
|
7489
7506
|
var framed = processSyncOutputFraming(padded);
|
|
7507
|
+
// wterm.write 内部用 5px 阈值判定"在底部",下一帧 _doRender 据此强制
|
|
7508
|
+
// scrollTop = scrollHeight。这与 wand 的 autoFollow("真正到底"才为
|
|
7509
|
+
// true,2px 阈值)独立,会把用户主动向上滚的几像素吞掉。覆写为 wand
|
|
7510
|
+
// 的 autoFollow 状态,让 autoFollow 成为唯一真相。
|
|
7511
|
+
//
|
|
7512
|
+
// 时序关键:必须在 terminal.write() 之前先覆写一次,否则 wterm 在 write
|
|
7513
|
+
// 内部解析 chunk 时可能同步触发 _doRender → 提前完成 scrollTop=scrollHeight,
|
|
7514
|
+
// write 之后再覆写就晚了一帧,用户上滚位置已被吞。write 之后再覆写一次
|
|
7515
|
+
// 兜底:wterm 在解析 newline / cursor move / scroll region 时可能把
|
|
7516
|
+
// _shouldScrollToBottom 改回 true。
|
|
7517
|
+
var follow = state.terminalAutoFollow !== false;
|
|
7518
|
+
if ("_shouldScrollToBottom" in terminal) {
|
|
7519
|
+
terminal._shouldScrollToBottom = follow;
|
|
7520
|
+
}
|
|
7490
7521
|
if (framed) terminal.write(framed);
|
|
7522
|
+
if ("_shouldScrollToBottom" in terminal) {
|
|
7523
|
+
terminal._shouldScrollToBottom = follow;
|
|
7524
|
+
}
|
|
7525
|
+
// wterm 按 follow=true 真的 scrollTop=scrollHeight 时会触发一次程序性的
|
|
7526
|
+
// scroll 事件 — 打窗口,让 scroll handler 不要误判为"用户滚回底部"。
|
|
7527
|
+
// **只在 follow=true 时打**:follow=false 时 wterm 不会拽底,没有程序事件
|
|
7528
|
+
// 要过滤;如果这里也打标,Claude 流式输出 chunk <120ms 一个会让窗口永
|
|
7529
|
+
// 不过期,scroll handler 永远 early return,用户哪怕滚回严格底部 autoFollow
|
|
7530
|
+
// 也回不到 true,再也走不出"上滚阅读"模式。
|
|
7531
|
+
if (follow) {
|
|
7532
|
+
state.terminalProgrammaticScrollUntil = Math.max(
|
|
7533
|
+
state.terminalProgrammaticScrollUntil,
|
|
7534
|
+
Date.now() + 120
|
|
7535
|
+
);
|
|
7536
|
+
}
|
|
7491
7537
|
// R6: 在 chunk 热路径上识别原地重绘序列(CSI nA/B/C/D/f/H/J/K),
|
|
7492
7538
|
// 节流安排一次 softResync 兜底。Claude 用相对光标位移重画菜单时,
|
|
7493
7539
|
// 如果 NEW-A 的 sync output buffer 因某种原因没拦截到完整帧(比如
|
|
@@ -7495,13 +7541,6 @@
|
|
|
7495
7541
|
// 错位。此 fallback 仅在真出现错位序列时触发,正常输出零开销。
|
|
7496
7542
|
// 与 R2 策略 A 配合:移除被动 5 处触发后,这是唯一的主动救场路径。
|
|
7497
7543
|
maybeScheduleResyncForChunk(data);
|
|
7498
|
-
// wterm.write 内部用 5px 阈值判定"在底部",下一帧 _doRender 据此强制
|
|
7499
|
-
// scrollTop = scrollHeight。这与 wand 的 autoFollow("真正到底"才为
|
|
7500
|
-
// true,2px 阈值)独立,会把用户主动向上滚的几像素吞掉。覆写为 wand
|
|
7501
|
-
// 的 autoFollow 状态,让 autoFollow 成为唯一真相。
|
|
7502
|
-
if ("_shouldScrollToBottom" in terminal) {
|
|
7503
|
-
terminal._shouldScrollToBottom = state.terminalAutoFollow !== false;
|
|
7504
|
-
}
|
|
7505
7544
|
}
|
|
7506
7545
|
|
|
7507
7546
|
function resetWideParserState() {
|
|
@@ -7919,6 +7958,16 @@
|
|
|
7919
7958
|
var viewport = getTerminalViewport();
|
|
7920
7959
|
if (viewport) {
|
|
7921
7960
|
state.terminalViewportScrollHandler = function() {
|
|
7961
|
+
// 程序触发的 scroll(wand 主动 scrollTo / wterm 内部
|
|
7962
|
+
// _doRender 因 _shouldScrollToBottom=true 拽 scrollTop=scrollHeight)
|
|
7963
|
+
// 也会进这里。如果不过滤,handler 会看到 isTerminalAtBottom()=true
|
|
7964
|
+
// 把 autoFollow 反转回 true,把用户刚上滚的意图吞掉,下一帧 chunk
|
|
7965
|
+
// 到达又被拽底,形成"上滚→拽底"反馈环。窗口长度由调用方按
|
|
7966
|
+
// 各自动画长度决定(瞬时 120ms / smooth 500ms)。
|
|
7967
|
+
if (Date.now() < state.terminalProgrammaticScrollUntil) {
|
|
7968
|
+
updateTerminalJumpToBottomButton();
|
|
7969
|
+
return;
|
|
7970
|
+
}
|
|
7922
7971
|
// 严格"真正到底"才恢复 autoFollow:避免 wheel 设 false 后被
|
|
7923
7972
|
// 紧接着的 scroll 事件因"接近底部 12px"而反转回 true。
|
|
7924
7973
|
if (isTerminalAtBottom()) {
|