@co0ontty/wand 1.43.1 → 1.43.3
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/dist/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commit": "
|
|
3
|
-
"builtAt": "2026-05-
|
|
4
|
-
"version": "1.43.
|
|
2
|
+
"commit": "928999824e2776170b08b37eac1884673b0c8b2d",
|
|
3
|
+
"builtAt": "2026-05-31T06:10:02.658Z",
|
|
4
|
+
"version": "1.43.3",
|
|
5
5
|
"channel": "stable"
|
|
6
6
|
}
|
|
@@ -1563,7 +1563,7 @@
|
|
|
1563
1563
|
|
|
1564
1564
|
// ===== 桌面:点 sidebar 外的空白处自动收起 =====
|
|
1565
1565
|
// 只对「临时打开但未锁定」的全尺寸侧栏生效;已锁定的 pinned 侧栏
|
|
1566
|
-
// 必须保持常驻,除非用户明确点 X
|
|
1566
|
+
// 必须保持常驻,除非用户明确点 X 关闭。
|
|
1567
1567
|
// - 仅 desktop + 未锁定 + 全尺寸(非窄条)+ 已打开 时生效
|
|
1568
1568
|
// - 窄条态不触发(窄条本来就是稳定常驻形态)
|
|
1569
1569
|
// - 手机端由 .drawer-backdrop 元素自己接住点击,不在这里重复处理
|
|
@@ -1588,7 +1588,7 @@
|
|
|
1588
1588
|
".folder-picker-dropdown, .path-suggestions, " +
|
|
1589
1589
|
".permission-prompt-overlay, .restart-overlay"
|
|
1590
1590
|
)) return;
|
|
1591
|
-
|
|
1591
|
+
closeTransientSessionsDrawer();
|
|
1592
1592
|
}, true);
|
|
1593
1593
|
|
|
1594
1594
|
renderBootLoading();
|
|
@@ -1783,6 +1783,7 @@
|
|
|
1783
1783
|
var terminalInfo = selectedSession ? (selectedSession.mode + " | " + selectedSession.status) : "点击上方「新对话」开始";
|
|
1784
1784
|
var currentDraft = state.selectedId ? (state.drafts[state.selectedId] || "") : "";
|
|
1785
1785
|
var drawerClass = state.sessionsDrawerOpen ? " open" : "";
|
|
1786
|
+
var backdropClass = shouldShowSessionsBackdrop() ? " open" : "";
|
|
1786
1787
|
var preferredTool = getComposerTool();
|
|
1787
1788
|
var composerMode = getSafeModeForTool(preferredTool, state.chatMode);
|
|
1788
1789
|
|
|
@@ -1796,7 +1797,7 @@
|
|
|
1796
1797
|
var collapsedCls = isCollapsed ? ' sidebar-collapsed' : '';
|
|
1797
1798
|
var sidebarCollapsedCls = isCollapsed ? ' collapsed' : '';
|
|
1798
1799
|
return '<div class="app-container">' +
|
|
1799
|
-
'<div id="sessions-drawer-backdrop" class="drawer-backdrop' +
|
|
1800
|
+
'<div id="sessions-drawer-backdrop" class="drawer-backdrop' + backdropClass + '"></div>' +
|
|
1800
1801
|
'<div class="main-layout' + (state.sessionsDrawerOpen ? ' sidebar-open' : '') + (isAnchored ? ' sidebar-pinned' : '') + collapsedCls + '">' +
|
|
1801
1802
|
'<aside id="sessions-drawer" class="sidebar' + drawerClass + (isAnchored ? ' pinned' : '') + sidebarCollapsedCls + '">' +
|
|
1802
1803
|
'<div class="sidebar-header">' +
|
|
@@ -2295,29 +2296,6 @@
|
|
|
2295
2296
|
};
|
|
2296
2297
|
}
|
|
2297
2298
|
|
|
2298
|
-
// Knob starts at LEFT (Commit). Three zones, left → right:
|
|
2299
|
-
// commit (0.00..0.32) — starting position
|
|
2300
|
-
// tag (0.32..0.68) — dwell here ~600ms to "arm" the Tag latch
|
|
2301
|
-
// push (0.68..1.00) — release here to push
|
|
2302
|
-
function getQuickCommitZoneFromRatio(ratio) {
|
|
2303
|
-
if (ratio <= 0.32) return "commit";
|
|
2304
|
-
if (ratio >= 0.68) return "push";
|
|
2305
|
-
return "tag";
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
|
-
// tagArmed is only true if the user dwelled long enough in the Tag zone.
|
|
2309
|
-
// Sliding straight through Tag → Push without dwelling = commit-push (skip Tag).
|
|
2310
|
-
function composeQuickCommitAction(zone, tagArmed) {
|
|
2311
|
-
if (zone === "push") return tagArmed ? "commit-tag-push" : "commit-push";
|
|
2312
|
-
if (zone === "tag") return "commit-tag";
|
|
2313
|
-
return "commit";
|
|
2314
|
-
}
|
|
2315
|
-
|
|
2316
|
-
// How long the user must hold the knob inside the Tag zone before the Tag latch arms.
|
|
2317
|
-
// Keep in sync with `--qc-dwell-ms` in styles.css.
|
|
2318
|
-
var QUICK_COMMIT_TAG_DWELL_MS = 1100;
|
|
2319
|
-
var QUICK_COMMIT_ZONE_RANK = { commit: 0, tag: 1, push: 2 };
|
|
2320
|
-
|
|
2321
2299
|
function openQuickCommitModal() {
|
|
2322
2300
|
if (!state.selectedId) return;
|
|
2323
2301
|
state.quickCommitOpen = true;
|
|
@@ -2448,236 +2426,194 @@
|
|
|
2448
2426
|
attachQuickCommitDrag();
|
|
2449
2427
|
}
|
|
2450
2428
|
|
|
2451
|
-
//
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
var
|
|
2456
|
-
if (
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
if (action === "commit-tag") defaultRatio = 0.5;
|
|
2461
|
-
else if (action === "commit-push" || action === "commit-tag-push") defaultRatio = 1;
|
|
2462
|
-
var progress = typeof ratio === "number"
|
|
2463
|
-
? Math.max(0, Math.min(1, ratio))
|
|
2464
|
-
: defaultRatio;
|
|
2465
|
-
var zone = getQuickCommitZoneFromRatio(progress);
|
|
2466
|
-
track.setAttribute("data-action", action);
|
|
2467
|
-
track.setAttribute("data-zone", zone);
|
|
2468
|
-
track.setAttribute("data-tag-armed", (action === "commit-tag" || action === "commit-tag-push") ? "1" : "0");
|
|
2469
|
-
track.style.setProperty("--qc-progress", (progress * 100).toFixed(1) + "%");
|
|
2470
|
-
var knob = document.getElementById("quick-commit-drag-action");
|
|
2471
|
-
if (knob) {
|
|
2472
|
-
var trackWidth = track.clientWidth;
|
|
2473
|
-
var knobWidth = knob.offsetWidth;
|
|
2474
|
-
var pad = 6;
|
|
2475
|
-
// Knob CENTER tracks ratio * trackWidth, clamped so the knob stays fully inside.
|
|
2476
|
-
var center = progress * trackWidth;
|
|
2477
|
-
var minLeft = pad;
|
|
2478
|
-
var maxLeft = Math.max(pad, trackWidth - knobWidth - pad);
|
|
2479
|
-
var left = Math.max(minLeft, Math.min(maxLeft, center - knobWidth / 2));
|
|
2480
|
-
track.style.setProperty("--qc-knob-x", left.toFixed(1) + "px");
|
|
2481
|
-
}
|
|
2482
|
-
var label = document.getElementById("quick-commit-drag-label");
|
|
2483
|
-
if (label) {
|
|
2484
|
-
var dwell = track.getAttribute("data-tag-dwell") || "idle";
|
|
2485
|
-
var cancelMode = track.getAttribute("data-cancel-mode") === "1";
|
|
2486
|
-
var txt;
|
|
2487
|
-
if (state.quickCommitSubmitting) {
|
|
2488
|
-
txt = state.quickCommitAutoGenerating ? "AI 生成 + 提交中…" : "执行中…";
|
|
2489
|
-
} else if (cancelMode) {
|
|
2490
|
-
txt = "松手取消 ✕";
|
|
2491
|
-
} else if (dwell === "active") {
|
|
2492
|
-
txt = "锁定 Tag 中…";
|
|
2493
|
-
} else if (dwell === "armed" && zone === "tag") {
|
|
2494
|
-
txt = "Tag 已就绪 · 继续推送 →";
|
|
2495
|
-
} else {
|
|
2496
|
-
txt = meta.label;
|
|
2497
|
-
}
|
|
2498
|
-
label.textContent = txt;
|
|
2499
|
-
}
|
|
2500
|
-
// Stage class refresh.
|
|
2501
|
-
var stages = track.querySelectorAll("[data-qc-stage]");
|
|
2502
|
-
for (var i = 0; i < stages.length; i++) {
|
|
2503
|
-
var st = stages[i].getAttribute("data-qc-stage");
|
|
2504
|
-
var active = false, passed = false;
|
|
2505
|
-
if (st === "commit") {
|
|
2506
|
-
active = action === "commit";
|
|
2507
|
-
passed = true;
|
|
2508
|
-
} else if (st === "tag") {
|
|
2509
|
-
active = action === "commit-tag";
|
|
2510
|
-
passed = action === "commit-tag" || action === "commit-tag-push";
|
|
2511
|
-
} else if (st === "push") {
|
|
2512
|
-
active = action === "commit-push" || action === "commit-tag-push";
|
|
2513
|
-
passed = active;
|
|
2514
|
-
}
|
|
2515
|
-
stages[i].classList.toggle("is-active", active);
|
|
2516
|
-
stages[i].classList.toggle("is-passed", passed);
|
|
2517
|
-
}
|
|
2429
|
+
// Compose the final action from which stations the orb attached during the drag.
|
|
2430
|
+
// Commit is implicit — every action starts with a commit.
|
|
2431
|
+
function composeOrbAction(attached) {
|
|
2432
|
+
var hasTag = !!(attached && attached.tag);
|
|
2433
|
+
var hasPush = !!(attached && attached.push);
|
|
2434
|
+
if (hasTag && hasPush) return "commit-tag-push";
|
|
2435
|
+
if (hasTag) return "commit-tag";
|
|
2436
|
+
if (hasPush) return "commit-push";
|
|
2437
|
+
return "commit";
|
|
2518
2438
|
}
|
|
2519
2439
|
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
if (!track || !knob) return;
|
|
2524
|
-
updateQuickCommitDragVisual(state.quickCommitDragAction || "commit");
|
|
2440
|
+
// How close (px) the pointer must come to a loose chip's home before that chip is
|
|
2441
|
+
// magnetically picked up into the chip currently being dragged.
|
|
2442
|
+
var QC_DOCK_PICKUP_R = 58;
|
|
2525
2443
|
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
}
|
|
2444
|
+
// A plain tap on a chip fires its own action directly (tag/push imply a commit too).
|
|
2445
|
+
function qcChipTapAction(id) {
|
|
2446
|
+
if (id === "tag") return "commit-tag";
|
|
2447
|
+
if (id === "push") return "commit-push";
|
|
2448
|
+
return "commit";
|
|
2449
|
+
}
|
|
2533
2450
|
|
|
2534
|
-
|
|
2451
|
+
// Magnetic dock: three loose chips (Commit / Tag / Push) rest in a field. Grab ANY chip and
|
|
2452
|
+
// drag it; whenever the pointer brushes another chip it sticks to the travelling cluster and
|
|
2453
|
+
// moves along (ordered Commit → Tag → Push). Fling the cluster into the right-side ▶ pad to
|
|
2454
|
+
// fire compose(members) — a commit is always implied. Release anywhere else and every chip
|
|
2455
|
+
// springs back home. A plain tap (no drag) on a chip fires that chip's own action.
|
|
2456
|
+
function attachQuickCommitDrag() {
|
|
2457
|
+
var field = document.getElementById("qc-dock-field");
|
|
2458
|
+
var stage = document.getElementById("qc-dock-stage");
|
|
2459
|
+
var launch = document.getElementById("qc-dock-launch");
|
|
2460
|
+
var cluster = document.getElementById("qc-dock-cluster");
|
|
2461
|
+
if (!field || !stage || !launch || !cluster) return;
|
|
2462
|
+
|
|
2463
|
+
var ORDER = ["commit", "tag", "push"];
|
|
2464
|
+
var chips = {};
|
|
2465
|
+
ORDER.forEach(function(id) { chips[id] = field.querySelector('[data-chip="' + id + '"]'); });
|
|
2466
|
+
if (!chips.commit || !chips.tag || !chips.push) return;
|
|
2467
|
+
|
|
2468
|
+
function cw(id) { return chips[id] ? chips[id].offsetWidth : 90; }
|
|
2469
|
+
function chH() { return chips.commit ? chips.commit.offsetHeight : 38; }
|
|
2470
|
+
|
|
2471
|
+
// Resting (home) positions — the three chips in one centered row.
|
|
2472
|
+
function homePositions() {
|
|
2473
|
+
var fw = field.clientWidth, fh = field.clientHeight, H = chH();
|
|
2474
|
+
var gap = 14;
|
|
2475
|
+
var total = ORDER.reduce(function(s, id) { return s + cw(id); }, 0) + (ORDER.length - 1) * gap;
|
|
2476
|
+
var x = Math.max(8, (fw - total) / 2);
|
|
2477
|
+
var y = (fh - H) / 2;
|
|
2478
|
+
var pos = {};
|
|
2479
|
+
ORDER.forEach(function(id) { pos[id] = { x: x, y: y }; x += cw(id) + gap; });
|
|
2480
|
+
return pos;
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
var home = {};
|
|
2484
|
+
function placeChip(id, x, y) {
|
|
2485
|
+
if (chips[id]) chips[id].style.transform = "translate(" + x.toFixed(1) + "px," + y.toFixed(1) + "px)";
|
|
2486
|
+
}
|
|
2487
|
+
function layoutHome(animated) {
|
|
2488
|
+
home = homePositions();
|
|
2489
|
+
ORDER.forEach(function(id) {
|
|
2490
|
+
chips[id].classList.toggle("qc-chip--anim", !!animated);
|
|
2491
|
+
placeChip(id, home[id].x, home[id].y);
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
layoutHome(false);
|
|
2495
|
+
|
|
2496
|
+
var drag = null;
|
|
2497
|
+
|
|
2498
|
+
// Lay the current cluster members in a tight row centered on (cx, cy) within the field.
|
|
2499
|
+
function layoutCluster(members, cx, cy) {
|
|
2500
|
+
var H = chH(), gapIn = 5;
|
|
2501
|
+
var ids = ORDER.filter(function(id) { return members.indexOf(id) >= 0; });
|
|
2502
|
+
var total = ids.reduce(function(s, id) { return s + cw(id); }, 0) + Math.max(0, ids.length - 1) * gapIn;
|
|
2503
|
+
var fh = field.clientHeight;
|
|
2504
|
+
var x = cx - total / 2;
|
|
2505
|
+
var y = Math.max(2, Math.min(fh - H - 2, cy - H / 2));
|
|
2506
|
+
ids.forEach(function(id) { placeChip(id, x, y); x += cw(id) + gapIn; });
|
|
2507
|
+
return { x: cx - total / 2 - 7, y: y - 7, w: total + 14, h: H + 14 };
|
|
2508
|
+
}
|
|
2509
|
+
function showCluster(box) {
|
|
2510
|
+
cluster.classList.add("is-active");
|
|
2511
|
+
cluster.style.transform = "translate(" + box.x.toFixed(1) + "px," + box.y.toFixed(1) + "px)";
|
|
2512
|
+
cluster.style.width = box.w.toFixed(1) + "px";
|
|
2513
|
+
cluster.style.height = box.h.toFixed(1) + "px";
|
|
2514
|
+
}
|
|
2515
|
+
function hideCluster() { cluster.classList.remove("is-active"); }
|
|
2516
|
+
|
|
2517
|
+
function clusterAction(members) {
|
|
2518
|
+
return composeOrbAction({
|
|
2519
|
+
commit: true,
|
|
2520
|
+
tag: members.indexOf("tag") >= 0,
|
|
2521
|
+
push: members.indexOf("push") >= 0,
|
|
2522
|
+
});
|
|
2523
|
+
}
|
|
2524
|
+
function setLaunchLabel(t) {
|
|
2525
|
+
var l = document.getElementById("qc-dock-launch-label");
|
|
2526
|
+
if (l) l.textContent = t;
|
|
2527
|
+
}
|
|
2528
|
+
function pointInLaunch(x, y) {
|
|
2529
|
+
var r = launch.getBoundingClientRect();
|
|
2530
|
+
return x >= r.left && x <= r.right && y >= r.top && y <= r.bottom;
|
|
2531
|
+
}
|
|
2535
2532
|
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
maxZone: "commit", // furthest zone the knob ever reached this drag
|
|
2546
|
-
tagArmed: false,
|
|
2547
|
-
tagArmTimer: null,
|
|
2548
|
-
action: "commit",
|
|
2533
|
+
function onDown(id) {
|
|
2534
|
+
return function(e) {
|
|
2535
|
+
if (chips[id].disabled || isQuickCommitOpInFlight()) return;
|
|
2536
|
+
drag = { anchor: id, pointerId: e.pointerId, startX: e.clientX, startY: e.clientY, moved: false, members: [id] };
|
|
2537
|
+
ORDER.forEach(function(m) { chips[m].classList.remove("qc-chip--anim"); });
|
|
2538
|
+
chips[id].classList.add("is-grabbing");
|
|
2539
|
+
try { chips[id].setPointerCapture(e.pointerId); } catch (err) { /* ignored */ }
|
|
2540
|
+
stage.classList.add("is-dragging");
|
|
2541
|
+
e.preventDefault();
|
|
2549
2542
|
};
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
e.
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
if (QUICK_COMMIT_ZONE_RANK[zone] > QUICK_COMMIT_ZONE_RANK[quickCommitDragState.maxZone]) {
|
|
2566
|
-
quickCommitDragState.maxZone = zone;
|
|
2567
|
-
}
|
|
2568
|
-
// Zone transitions drive the dwell state machine.
|
|
2569
|
-
if (zone !== quickCommitDragState.zone) {
|
|
2570
|
-
if (zone === "tag" && !quickCommitDragState.tagArmed) {
|
|
2571
|
-
// Entered Tag zone unarmed → kick off the dwell timer + CSS fill animation.
|
|
2572
|
-
clearArmTimer();
|
|
2573
|
-
setDwell("active");
|
|
2574
|
-
quickCommitDragState.tagArmTimer = setTimeout(function() {
|
|
2575
|
-
if (!quickCommitDragState) return;
|
|
2576
|
-
quickCommitDragState.tagArmed = true;
|
|
2577
|
-
quickCommitDragState.tagArmTimer = null;
|
|
2578
|
-
setDwell("armed");
|
|
2579
|
-
var newAction = composeQuickCommitAction(quickCommitDragState.zone, true);
|
|
2580
|
-
quickCommitDragState.action = newAction;
|
|
2581
|
-
updateQuickCommitDragVisual(newAction);
|
|
2582
|
-
}, QUICK_COMMIT_TAG_DWELL_MS);
|
|
2583
|
-
} else if (zone !== "tag" && !quickCommitDragState.tagArmed) {
|
|
2584
|
-
// Left Tag zone before arming → cancel the dwell.
|
|
2585
|
-
clearArmTimer();
|
|
2586
|
-
setDwell("idle");
|
|
2587
|
-
} else if (zone === "tag" && quickCommitDragState.tagArmed) {
|
|
2588
|
-
setDwell("armed");
|
|
2543
|
+
}
|
|
2544
|
+
function onMove(e) {
|
|
2545
|
+
if (!drag || drag.pointerId !== e.pointerId) return;
|
|
2546
|
+
if (Math.abs(e.clientX - drag.startX) > 3 || Math.abs(e.clientY - drag.startY) > 3) drag.moved = true;
|
|
2547
|
+
var fr = field.getBoundingClientRect();
|
|
2548
|
+
var fx = e.clientX - fr.left, fy = e.clientY - fr.top;
|
|
2549
|
+
// magnetic pickup: any loose chip whose home center is near the pointer joins the cluster.
|
|
2550
|
+
ORDER.forEach(function(id) {
|
|
2551
|
+
if (drag.members.indexOf(id) >= 0) return;
|
|
2552
|
+
var hx = home[id].x + cw(id) / 2, hy = home[id].y + chH() / 2;
|
|
2553
|
+
var dx = fx - hx, dy = fy - hy;
|
|
2554
|
+
if (Math.sqrt(dx * dx + dy * dy) < QC_DOCK_PICKUP_R) {
|
|
2555
|
+
drag.members.push(id);
|
|
2556
|
+
chips[id].classList.remove("qc-chip--anim");
|
|
2557
|
+
chips[id].classList.add("is-attached");
|
|
2589
2558
|
}
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
// Backtrack: user ventured out past Commit, then dragged back and released at Commit → cancel.
|
|
2612
|
-
var isBacktrack = current.moved
|
|
2613
|
-
&& current.zone === "commit"
|
|
2614
|
-
&& current.maxZone !== "commit";
|
|
2615
|
-
if (cancelled || isBacktrack) {
|
|
2616
|
-
updateQuickCommitDragVisual("commit");
|
|
2559
|
+
});
|
|
2560
|
+
var box = layoutCluster(drag.members, fx, fy);
|
|
2561
|
+
var hot = pointInLaunch(e.clientX, e.clientY);
|
|
2562
|
+
stage.setAttribute("data-hot", hot ? "1" : "0");
|
|
2563
|
+
stage.setAttribute("data-action", clusterAction(drag.members));
|
|
2564
|
+
if (drag.members.length > 1) showCluster(box); else hideCluster();
|
|
2565
|
+
setLaunchLabel(hot ? "松手执行" : "提交");
|
|
2566
|
+
}
|
|
2567
|
+
function endDrag(e, cancelled) {
|
|
2568
|
+
if (!drag || drag.pointerId !== e.pointerId) return;
|
|
2569
|
+
var cur = drag; drag = null;
|
|
2570
|
+
stage.classList.remove("is-dragging");
|
|
2571
|
+
stage.setAttribute("data-hot", "0");
|
|
2572
|
+
setLaunchLabel("提交");
|
|
2573
|
+
hideCluster();
|
|
2574
|
+
ORDER.forEach(function(m) { chips[m].classList.remove("is-grabbing", "is-attached"); });
|
|
2575
|
+
try { chips[cur.anchor].releasePointerCapture(cur.pointerId); } catch (err) { /* ignored */ }
|
|
2576
|
+
|
|
2577
|
+
if (!cancelled && !cur.moved) {
|
|
2578
|
+
// plain tap → fire this chip's own action
|
|
2579
|
+
submitQuickCommit(qcChipTapAction(cur.anchor));
|
|
2617
2580
|
return;
|
|
2618
2581
|
}
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
: "commit";
|
|
2623
|
-
updateQuickCommitDragVisual(action);
|
|
2624
|
-
submitQuickCommit(action);
|
|
2625
|
-
if (e && typeof e.preventDefault === "function") e.preventDefault();
|
|
2626
|
-
};
|
|
2627
|
-
var onPointerUp = function(e) {
|
|
2628
|
-
if (!quickCommitDragState || quickCommitDragState.pointerId !== e.pointerId) return;
|
|
2629
|
-
finish(e, false);
|
|
2630
|
-
};
|
|
2631
|
-
var onPointerCancel = function(e) {
|
|
2632
|
-
if (!quickCommitDragState || quickCommitDragState.pointerId !== e.pointerId) return;
|
|
2633
|
-
finish(e, true);
|
|
2634
|
-
};
|
|
2635
|
-
// Keyboard parity:
|
|
2636
|
-
// → step zone right (commit → commit-tag → commit-tag-push). The first → into Tag arms it instantly.
|
|
2637
|
-
// ← step zone left
|
|
2638
|
-
// Home → reset to commit
|
|
2639
|
-
// Enter / Space → submit current action
|
|
2640
|
-
var onKeyDown = function(e) {
|
|
2641
|
-
if (knob.disabled || isQuickCommitOpInFlight()) return;
|
|
2642
|
-
var cur = state.quickCommitDragAction || "commit";
|
|
2643
|
-
if (e.key === "ArrowRight") {
|
|
2644
|
-
e.preventDefault();
|
|
2645
|
-
var next = cur;
|
|
2646
|
-
if (cur === "commit") next = "commit-tag"; // arm Tag
|
|
2647
|
-
else if (cur === "commit-tag") next = "commit-tag-push";
|
|
2648
|
-
else if (cur === "commit-push") next = "commit-push";
|
|
2649
|
-
updateQuickCommitDragVisual(next);
|
|
2650
|
-
} else if (e.key === "ArrowLeft") {
|
|
2651
|
-
e.preventDefault();
|
|
2652
|
-
var prev = cur;
|
|
2653
|
-
if (cur === "commit-tag-push") prev = "commit-tag";
|
|
2654
|
-
else if (cur === "commit-tag") prev = "commit";
|
|
2655
|
-
else if (cur === "commit-push") prev = "commit";
|
|
2656
|
-
updateQuickCommitDragVisual(prev);
|
|
2657
|
-
} else if (e.key === "Home") {
|
|
2658
|
-
e.preventDefault();
|
|
2659
|
-
updateQuickCommitDragVisual("commit");
|
|
2660
|
-
} else if (e.key === "Enter" || e.key === " ") {
|
|
2661
|
-
e.preventDefault();
|
|
2662
|
-
submitQuickCommit(state.quickCommitDragAction || "commit");
|
|
2582
|
+
if (!cancelled && pointInLaunch(e.clientX, e.clientY)) {
|
|
2583
|
+
submitQuickCommit(clusterAction(cur.members));
|
|
2584
|
+
return;
|
|
2663
2585
|
}
|
|
2664
|
-
|
|
2586
|
+
// released loose → everyone springs back home
|
|
2587
|
+
stage.setAttribute("data-action", "commit");
|
|
2588
|
+
layoutHome(true);
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
var onResize = function() { if (state.quickCommitOpen && !drag) layoutHome(false); };
|
|
2592
|
+
window.addEventListener("resize", onResize);
|
|
2593
|
+
|
|
2594
|
+
ORDER.forEach(function(id) {
|
|
2595
|
+
var c = chips[id];
|
|
2596
|
+
c.addEventListener("pointerdown", onDown(id));
|
|
2597
|
+
c.addEventListener("pointermove", onMove);
|
|
2598
|
+
c.addEventListener("pointerup", function(e) { endDrag(e, false); });
|
|
2599
|
+
c.addEventListener("pointercancel", function(e) { endDrag(e, true); });
|
|
2600
|
+
c.addEventListener("keydown", function(e) {
|
|
2601
|
+
if (c.disabled || isQuickCommitOpInFlight()) return;
|
|
2602
|
+
if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
|
|
2603
|
+
e.preventDefault();
|
|
2604
|
+
submitQuickCommit(qcChipTapAction(id));
|
|
2605
|
+
}
|
|
2606
|
+
});
|
|
2607
|
+
});
|
|
2608
|
+
|
|
2609
|
+
launch.addEventListener("click", function() {
|
|
2610
|
+
if (launch.disabled || isQuickCommitOpInFlight() || drag) return;
|
|
2611
|
+
submitQuickCommit("commit");
|
|
2612
|
+
});
|
|
2665
2613
|
|
|
2666
|
-
knob.addEventListener("pointerdown", onPointerDown);
|
|
2667
|
-
knob.addEventListener("pointermove", onPointerMove);
|
|
2668
|
-
knob.addEventListener("pointerup", onPointerUp);
|
|
2669
|
-
knob.addEventListener("pointercancel", onPointerCancel);
|
|
2670
|
-
knob.addEventListener("keydown", onKeyDown);
|
|
2671
2614
|
quickCommitDragCleanup = function() {
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
knob.removeEventListener("pointerup", onPointerUp);
|
|
2675
|
-
knob.removeEventListener("pointercancel", onPointerCancel);
|
|
2676
|
-
knob.removeEventListener("keydown", onKeyDown);
|
|
2677
|
-
if (quickCommitDragState && quickCommitDragState.tagArmTimer) {
|
|
2678
|
-
clearTimeout(quickCommitDragState.tagArmTimer);
|
|
2679
|
-
}
|
|
2680
|
-
quickCommitDragState = null;
|
|
2615
|
+
window.removeEventListener("resize", onResize);
|
|
2616
|
+
drag = null;
|
|
2681
2617
|
};
|
|
2682
2618
|
}
|
|
2683
2619
|
|
|
@@ -2937,45 +2873,40 @@
|
|
|
2937
2873
|
}
|
|
2938
2874
|
|
|
2939
2875
|
function renderQuickCommitDragControl(hasChanges) {
|
|
2940
|
-
var action = normalizeQuickCommitAction(state.quickCommitDragAction || "commit");
|
|
2941
|
-
var meta = getQuickCommitActionMeta(action);
|
|
2942
2876
|
var disabled = !hasChanges || isQuickCommitOpInFlight();
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
'<
|
|
2952
|
-
|
|
2953
|
-
'<
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
'<span class="qc-drag-stage qc-stage-tag' + (tagActive ? ' is-active' : '') + (tagPassed ? ' is-passed' : '') + '" data-qc-stage="tag">Tag</span>' +
|
|
2968
|
-
'<span class="qc-drag-stage qc-stage-push' + (pushActive ? ' is-active is-passed' : '') + '" data-qc-stage="push">Push</span>' +
|
|
2877
|
+
// Busy panel — replaces the dock entirely while the request is in flight.
|
|
2878
|
+
if (state.quickCommitSubmitting) {
|
|
2879
|
+
var busyLabel = state.quickCommitAutoGenerating ? "AI 生成 + 提交中…" : "执行中…";
|
|
2880
|
+
return '<div class="qc-dock-wrap">' +
|
|
2881
|
+
'<div class="qc-dock-busy" role="status"><span class="qc-dock-busy-dot"></span>' + escapeHtml(busyLabel) + '</div>' +
|
|
2882
|
+
'</div>';
|
|
2883
|
+
}
|
|
2884
|
+
function chip(id, label) {
|
|
2885
|
+
return '<button type="button" class="qc-chip qc-chip--' + id + '"' +
|
|
2886
|
+
' data-chip="' + id + '"' + (disabled ? ' disabled' : '') + '>' +
|
|
2887
|
+
'<span class="qc-chip-dot" aria-hidden="true"></span>' +
|
|
2888
|
+
'<span class="qc-chip-label">' + label + '</span>' +
|
|
2889
|
+
'</button>';
|
|
2890
|
+
}
|
|
2891
|
+
var hint = disabled
|
|
2892
|
+
? (!hasChanges ? "工作区干净,无可提交" : "")
|
|
2893
|
+
: "拖一个去碰另一个会黏在一起 · 整串丢进 ▶ 执行组合 · 单击直接执行该项";
|
|
2894
|
+
return '<div class="qc-dock-wrap"' + (disabled ? ' data-disabled="1"' : '') + '>' +
|
|
2895
|
+
'<div id="qc-dock-stage" class="qc-dock-stage" data-action="commit" data-hot="0">' +
|
|
2896
|
+
'<div id="qc-dock-field" class="qc-dock-field">' +
|
|
2897
|
+
'<div id="qc-dock-cluster" class="qc-dock-cluster" aria-hidden="true"></div>' +
|
|
2898
|
+
chip("commit", "Commit") +
|
|
2899
|
+
chip("tag", "Tag") +
|
|
2900
|
+
chip("push", "Push") +
|
|
2969
2901
|
'</div>' +
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
'
|
|
2974
|
-
|
|
2975
|
-
'<span class="qc-drag-dwell-bar" aria-hidden="true"></span>' +
|
|
2902
|
+
'<button type="button" id="qc-dock-launch" class="qc-dock-launch"' + (disabled ? ' disabled' : '') + ' aria-label="执行提交">' +
|
|
2903
|
+
'<span class="qc-dock-launch-arrow" aria-hidden="true">' +
|
|
2904
|
+
'<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h12M13 6l6 6-6 6"/></svg>' +
|
|
2905
|
+
'</span>' +
|
|
2906
|
+
'<span id="qc-dock-launch-label" class="qc-dock-launch-label">提交</span>' +
|
|
2976
2907
|
'</button>' +
|
|
2977
2908
|
'</div>' +
|
|
2978
|
-
'<div class="qc-
|
|
2909
|
+
'<div class="qc-dock-hint">' + escapeHtml(hint) + '</div>' +
|
|
2979
2910
|
'</div>';
|
|
2980
2911
|
}
|
|
2981
2912
|
|
|
@@ -4209,6 +4140,10 @@
|
|
|
4209
4140
|
return window.innerWidth <= 768;
|
|
4210
4141
|
}
|
|
4211
4142
|
|
|
4143
|
+
function shouldShowSessionsBackdrop() {
|
|
4144
|
+
return !!state.sessionsDrawerOpen && (isMobileLayout() || !state.sidebarPinned);
|
|
4145
|
+
}
|
|
4146
|
+
|
|
4212
4147
|
function setFilePanelOpen(nextOpen) {
|
|
4213
4148
|
state.filePanelOpen = nextOpen;
|
|
4214
4149
|
try {
|
|
@@ -9891,7 +9826,7 @@
|
|
|
9891
9826
|
drawer.classList.toggle("open", state.sessionsDrawerOpen);
|
|
9892
9827
|
}
|
|
9893
9828
|
if (backdrop) {
|
|
9894
|
-
backdrop.classList.toggle("open",
|
|
9829
|
+
backdrop.classList.toggle("open", shouldShowSessionsBackdrop());
|
|
9895
9830
|
}
|
|
9896
9831
|
if (mainLayout) {
|
|
9897
9832
|
mainLayout.classList.toggle("sidebar-open", state.sessionsDrawerOpen);
|
|
@@ -9906,17 +9841,14 @@
|
|
|
9906
9841
|
function toggleSessionsDrawer() {
|
|
9907
9842
|
var isMobile = isMobileLayout();
|
|
9908
9843
|
if (!isMobile) {
|
|
9909
|
-
//
|
|
9910
|
-
|
|
9911
|
-
var willOpen = !state.sidebarPinned;
|
|
9912
|
-
state.sidebarPinned = willOpen;
|
|
9844
|
+
// 桌面:hamburger 只负责临时打开/关闭;锁定常驻由图钉按钮控制。
|
|
9845
|
+
var willOpen = state.sidebarPinned ? false : !state.sessionsDrawerOpen;
|
|
9913
9846
|
state.sessionsDrawerOpen = willOpen;
|
|
9914
9847
|
if (willOpen) {
|
|
9915
9848
|
// 桌面重新呼出默认回到全尺寸;窄条形态需用户主动点 collapse 按钮切换。
|
|
9916
9849
|
state.sidebarCollapsed = false;
|
|
9917
9850
|
writeStoredBoolean("wand-sidebar-collapsed", false);
|
|
9918
9851
|
}
|
|
9919
|
-
writeStoredBoolean("wand-sidebar-pinned", willOpen);
|
|
9920
9852
|
writeStoredBoolean("wand-sidebar-open", state.sessionsDrawerOpen);
|
|
9921
9853
|
updateLayoutState();
|
|
9922
9854
|
scheduleTerminalRefitAfterPaddingTransition();
|
|
@@ -9957,6 +9889,19 @@
|
|
|
9957
9889
|
updateLayoutState();
|
|
9958
9890
|
}
|
|
9959
9891
|
|
|
9892
|
+
function closeTransientSessionsDrawer() {
|
|
9893
|
+
if (isMobileLayout()) {
|
|
9894
|
+
closeSessionsDrawer();
|
|
9895
|
+
return;
|
|
9896
|
+
}
|
|
9897
|
+
if (state.sidebarPinned || state.sidebarCollapsed || !state.sessionsDrawerOpen) return;
|
|
9898
|
+
closeSwipedItem();
|
|
9899
|
+
state.sessionsDrawerOpen = false;
|
|
9900
|
+
writeStoredBoolean("wand-sidebar-open", false);
|
|
9901
|
+
updateLayoutState();
|
|
9902
|
+
scheduleTerminalRefitAfterPaddingTransition();
|
|
9903
|
+
}
|
|
9904
|
+
|
|
9960
9905
|
// 把"浮在内容上的 drawer/backdrop"关掉,但保留桌面常驻栏与窄条形态。
|
|
9961
9906
|
// 用法:从 input focus / send 按钮 / 选中会话 / 新建会话回调里调,这些场
|
|
9962
9907
|
// 景只想避免遮罩挡住内容,并不想撤掉用户主动开启的常驻侧栏。
|