dsh-git-branch-manage 1.0.3 → 1.0.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.
- package/lib/client.js +810 -187
- package/lib/git.d.ts +30 -6
- package/lib/git.js +41 -13
- package/lib/index.d.ts +16 -0
- package/lib/index.js +28 -1
- package/lib/normalize.d.ts +28 -3
- package/lib/normalize.js +38 -3
- package/lib/routes.d.ts +10 -1
- package/lib/routes.js +23 -6
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -44,6 +44,36 @@ window.__ModuleLoader__.load({
|
|
|
44
44
|
if (/(^|\/)[^/]+\.lock($|\/)/.test(name)) return "illegal";
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Shipped default for the cn-accelerate mirror prefix (the design doc's
|
|
49
|
+
* `cnAccelerateUrl` default and the popover's「恢复默认」target).
|
|
50
|
+
*/
|
|
51
|
+
const ACCEL_DEFAULT_URL = "https://gh-proxy.com/";
|
|
52
|
+
/**
|
|
53
|
+
* Pre-flight check of the cn-accelerate prefix against what the rewrite can
|
|
54
|
+
* actually use: non-empty after trim, `http://` or `https://` scheme, and no
|
|
55
|
+
* whitespace anywhere (a space would break the `url.<base>.insteadOf=<target>`
|
|
56
|
+
* git config value and smuggle a second argument).
|
|
57
|
+
* @param value - raw draft text.
|
|
58
|
+
* @returns the issue kind, or undefined when the value is acceptable.
|
|
59
|
+
*/
|
|
60
|
+
function accelerateUrlError(value) {
|
|
61
|
+
const trimmed = value.trim();
|
|
62
|
+
if (trimmed === "") return "empty";
|
|
63
|
+
if (/\s/.test(trimmed)) return "invalid";
|
|
64
|
+
if (!trimmed.startsWith("http://") && !trimmed.startsWith("https://")) return "invalid";
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Normalize an accepted accelerate URL: trim, and append the trailing `/`
|
|
68
|
+
* the prefix concatenation requires (`https://gh-proxy.com/` + `o/r.git`
|
|
69
|
+
* must stay one valid URL). Callers pass the result to `url.<base>.insteadOf`.
|
|
70
|
+
* @param value - an accepted (non-empty, http(s), whitespace-free) URL.
|
|
71
|
+
* @returns the prefix ending in `/`.
|
|
72
|
+
*/
|
|
73
|
+
function normalizeAccelerateUrl(value) {
|
|
74
|
+
const trimmed = value.trim();
|
|
75
|
+
return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
|
|
76
|
+
}
|
|
47
77
|
//#endregion
|
|
48
78
|
//#region src/wire.ts
|
|
49
79
|
/**
|
|
@@ -391,6 +421,21 @@ window.__ModuleLoader__.load({
|
|
|
391
421
|
return post(ROUTE_AI_COMMIT_MESSAGE, body);
|
|
392
422
|
}
|
|
393
423
|
//#endregion
|
|
424
|
+
//#region src/client/git-events.ts
|
|
425
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
426
|
+
/** Announce that a surface changed repository state (checkout, rename,
|
|
427
|
+
* delete, create, commit, fetch, update, push). */
|
|
428
|
+
function emitGitMutated() {
|
|
429
|
+
for (const listener of [...listeners]) listener();
|
|
430
|
+
}
|
|
431
|
+
/** Subscribe; returns the unsubscribe function. */
|
|
432
|
+
function onGitMutated(listener) {
|
|
433
|
+
listeners.add(listener);
|
|
434
|
+
return () => {
|
|
435
|
+
listeners.delete(listener);
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
//#endregion
|
|
394
439
|
//#region src/client/branch-tree.ts
|
|
395
440
|
/** Whether a bare `git push` has a known upstream and local commits ahead. */
|
|
396
441
|
function hasPushableCommits(rows, currentBranch) {
|
|
@@ -2735,6 +2780,12 @@ window.__ModuleLoader__.load({
|
|
|
2735
2780
|
document.removeEventListener("visibilitychange", onVisibility);
|
|
2736
2781
|
};
|
|
2737
2782
|
}, [refresh]);
|
|
2783
|
+
(0, react.useEffect)(() => {
|
|
2784
|
+
return onGitMutated(() => {
|
|
2785
|
+
if (busyRef.current) return;
|
|
2786
|
+
refresh();
|
|
2787
|
+
});
|
|
2788
|
+
}, [refresh]);
|
|
2738
2789
|
const showError = (0, react.useCallback)((message) => {
|
|
2739
2790
|
pushToast(t("errorGeneric", { message }));
|
|
2740
2791
|
}, [pushToast, t]);
|
|
@@ -2756,6 +2807,7 @@ window.__ModuleLoader__.load({
|
|
|
2756
2807
|
setConfirm(null);
|
|
2757
2808
|
if (!keepOpen) setMenuOpen(false);
|
|
2758
2809
|
onSettled?.();
|
|
2810
|
+
emitGitMutated();
|
|
2759
2811
|
}, [showError]);
|
|
2760
2812
|
/** In-place switch flow: POST /switch, then refetch the status. */
|
|
2761
2813
|
const doSwitch = (0, react.useCallback)((branch, keepOpen = false) => runGuarded(async () => {
|
|
@@ -3379,6 +3431,151 @@ window.__ModuleLoader__.load({
|
|
|
3379
3431
|
}
|
|
3380
3432
|
};
|
|
3381
3433
|
//#endregion
|
|
3434
|
+
//#region src/client/accel-form.ts
|
|
3435
|
+
/** The fields this form edits. */
|
|
3436
|
+
const ACCEL_ENABLED_FIELD = "cnAccelerate";
|
|
3437
|
+
const ACCEL_URL_FIELD = "cnAccelerateUrl";
|
|
3438
|
+
/**
|
|
3439
|
+
* Stages the cn-accelerate edits over the `dsh-git-branch` Host entry.
|
|
3440
|
+
*
|
|
3441
|
+
* Publishes through a snapshot store like {@link CardForm}: the consumer
|
|
3442
|
+
* reads through a snapshot selector while the scope and the local drafts
|
|
3443
|
+
* change underneath; every projection is rebuilt from the two together.
|
|
3444
|
+
*/
|
|
3445
|
+
var AccelForm = class {
|
|
3446
|
+
scope;
|
|
3447
|
+
snapshotValue;
|
|
3448
|
+
listeners = /* @__PURE__ */ new Set();
|
|
3449
|
+
enabledDraft;
|
|
3450
|
+
urlDraft;
|
|
3451
|
+
saving = false;
|
|
3452
|
+
failed = false;
|
|
3453
|
+
/**
|
|
3454
|
+
* @param scope - the bound configuration form for the `dsh-git-branch` Host entry.
|
|
3455
|
+
*/
|
|
3456
|
+
constructor(scope) {
|
|
3457
|
+
this.scope = scope;
|
|
3458
|
+
this.snapshotValue = this.project();
|
|
3459
|
+
scope.subscribe(() => {
|
|
3460
|
+
this.publish();
|
|
3461
|
+
});
|
|
3462
|
+
}
|
|
3463
|
+
/** @returns the store a consumer reads through its bound selector. */
|
|
3464
|
+
bind() {
|
|
3465
|
+
return {
|
|
3466
|
+
getSnapshot: () => this.snapshotValue,
|
|
3467
|
+
subscribe: (listener) => {
|
|
3468
|
+
this.listeners.add(listener);
|
|
3469
|
+
return () => {
|
|
3470
|
+
this.listeners.delete(listener);
|
|
3471
|
+
};
|
|
3472
|
+
},
|
|
3473
|
+
set: (next) => {
|
|
3474
|
+
this.store(next);
|
|
3475
|
+
}
|
|
3476
|
+
};
|
|
3477
|
+
}
|
|
3478
|
+
/** @returns the stage, restore, save, and discard actions bound to this form. */
|
|
3479
|
+
actions() {
|
|
3480
|
+
return {
|
|
3481
|
+
setAccelEnabled: (value) => {
|
|
3482
|
+
this.enabledDraft = value;
|
|
3483
|
+
this.failed = false;
|
|
3484
|
+
this.publish();
|
|
3485
|
+
},
|
|
3486
|
+
editAccelUrl: (text) => {
|
|
3487
|
+
this.urlDraft = text;
|
|
3488
|
+
this.failed = false;
|
|
3489
|
+
this.publish();
|
|
3490
|
+
},
|
|
3491
|
+
restoreAccelDefault: () => {
|
|
3492
|
+
this.urlDraft = ACCEL_DEFAULT_URL;
|
|
3493
|
+
this.failed = false;
|
|
3494
|
+
this.publish();
|
|
3495
|
+
},
|
|
3496
|
+
saveAccel: () => this.save(),
|
|
3497
|
+
discardAccel: () => {
|
|
3498
|
+
if (this.enabledDraft === void 0 && this.urlDraft === void 0 && !this.failed) return;
|
|
3499
|
+
this.enabledDraft = void 0;
|
|
3500
|
+
this.urlDraft = void 0;
|
|
3501
|
+
this.failed = false;
|
|
3502
|
+
this.publish();
|
|
3503
|
+
}
|
|
3504
|
+
};
|
|
3505
|
+
}
|
|
3506
|
+
/** The URL as the user sees it: the live draft, else the stored value over
|
|
3507
|
+
* the shipped default. */
|
|
3508
|
+
effectiveUrlText() {
|
|
3509
|
+
const value = this.scope.getSnapshot().value?.[ACCEL_URL_FIELD];
|
|
3510
|
+
return this.urlDraft ?? value ?? "https://gh-proxy.com/";
|
|
3511
|
+
}
|
|
3512
|
+
/**
|
|
3513
|
+
* Write the switch and the normalized URL TOGETHER, then re-seed from what
|
|
3514
|
+
* the Host accepted. The URL is validated first — an unusable draft blocks
|
|
3515
|
+
* the save (and the surfaces disable the button on the same error), so the
|
|
3516
|
+
* switch can never land alone against a mirror the user has not confirmed.
|
|
3517
|
+
* A save that did not land keeps its drafts so the user can correct them.
|
|
3518
|
+
*/
|
|
3519
|
+
async save() {
|
|
3520
|
+
if (this.enabledDraft === void 0 && this.urlDraft === void 0 || this.saving) return;
|
|
3521
|
+
const urlText = this.effectiveUrlText();
|
|
3522
|
+
if (accelerateUrlError(urlText) !== void 0) return;
|
|
3523
|
+
const intendedEnabled = this.enabledDraft ?? this.scope.getSnapshot().value?.["cnAccelerate"] ?? false;
|
|
3524
|
+
const intendedUrl = normalizeAccelerateUrl(urlText);
|
|
3525
|
+
this.saving = true;
|
|
3526
|
+
this.failed = false;
|
|
3527
|
+
this.publish();
|
|
3528
|
+
let landed = true;
|
|
3529
|
+
try {
|
|
3530
|
+
await this.scope.set(ACCEL_ENABLED_FIELD, intendedEnabled);
|
|
3531
|
+
await this.scope.set(ACCEL_URL_FIELD, intendedUrl);
|
|
3532
|
+
const user = this.userLayer();
|
|
3533
|
+
if (user?.["cnAccelerate"] !== intendedEnabled || user?.["cnAccelerateUrl"] !== intendedUrl) landed = false;
|
|
3534
|
+
} catch (_settingsWriteFailure) {
|
|
3535
|
+
landed = false;
|
|
3536
|
+
}
|
|
3537
|
+
if (landed) {
|
|
3538
|
+
this.enabledDraft = void 0;
|
|
3539
|
+
this.urlDraft = void 0;
|
|
3540
|
+
}
|
|
3541
|
+
this.saving = false;
|
|
3542
|
+
this.failed = !landed;
|
|
3543
|
+
this.publish();
|
|
3544
|
+
}
|
|
3545
|
+
/** The raw user layer narrowed to a record; the wire answer is `unknown`. */
|
|
3546
|
+
userLayer() {
|
|
3547
|
+
const user = this.scope.getSnapshot().user;
|
|
3548
|
+
return typeof user === "object" && user !== null ? user : void 0;
|
|
3549
|
+
}
|
|
3550
|
+
project() {
|
|
3551
|
+
const snapshot = this.scope.getSnapshot();
|
|
3552
|
+
const storedEnabled = snapshot.value?.["cnAccelerate"] ?? false;
|
|
3553
|
+
const storedUrl = snapshot.value?.["cnAccelerateUrl"] ?? "https://gh-proxy.com/";
|
|
3554
|
+
const urlText = this.effectiveUrlText();
|
|
3555
|
+
const enabledDirty = this.enabledDraft !== void 0 && this.enabledDraft !== storedEnabled;
|
|
3556
|
+
const urlDirty = this.urlDraft !== void 0 && this.urlDraft !== storedUrl;
|
|
3557
|
+
return {
|
|
3558
|
+
available: snapshot.status === "ready",
|
|
3559
|
+
writable: snapshot.writable,
|
|
3560
|
+
enabled: this.enabledDraft ?? storedEnabled,
|
|
3561
|
+
urlText,
|
|
3562
|
+
dirty: enabledDirty || urlDirty,
|
|
3563
|
+
saving: this.saving,
|
|
3564
|
+
failed: this.failed,
|
|
3565
|
+
urlError: accelerateUrlError(urlText) ?? null
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
/** Replace the snapshot reference and notify, only when the fact moved. */
|
|
3569
|
+
store(next) {
|
|
3570
|
+
if (next === this.snapshotValue) return;
|
|
3571
|
+
this.snapshotValue = next;
|
|
3572
|
+
for (const listener of this.listeners) listener();
|
|
3573
|
+
}
|
|
3574
|
+
publish() {
|
|
3575
|
+
this.store(this.project());
|
|
3576
|
+
}
|
|
3577
|
+
};
|
|
3578
|
+
//#endregion
|
|
3382
3579
|
//#region src/client/git-panel-data.ts
|
|
3383
3580
|
/**
|
|
3384
3581
|
* Classify raw %D decoration segments: `HEAD -> main` (and bare `HEAD`) is
|
|
@@ -3459,6 +3656,17 @@ window.__ModuleLoader__.load({
|
|
|
3459
3656
|
if (needle === "") return [...commits];
|
|
3460
3657
|
return commits.filter((commit) => commit.subject.toLowerCase().includes(needle) || commit.authorName.toLowerCase().includes(needle));
|
|
3461
3658
|
}
|
|
3659
|
+
/**
|
|
3660
|
+
* Case-insensitive substring filter over the branch name — the branch card's
|
|
3661
|
+
* head search box. A remote row matches on its full `remote/name`, which
|
|
3662
|
+
* contains the prefix-stripped short name the tree renders, so searching what
|
|
3663
|
+
* the user sees and searching the remote prefix both hit.
|
|
3664
|
+
*/
|
|
3665
|
+
function filterBranches(rows, query) {
|
|
3666
|
+
const needle = query.trim().toLowerCase();
|
|
3667
|
+
if (needle === "") return [...rows];
|
|
3668
|
+
return rows.filter((row) => row.name.toLowerCase().includes(needle));
|
|
3669
|
+
}
|
|
3462
3670
|
/** Merge the next page into the accumulated list, dropping hash duplicates
|
|
3463
3671
|
* (a ref moved between fetches must not duplicate rows). */
|
|
3464
3672
|
function appendPage(current, page) {
|
|
@@ -3520,9 +3728,19 @@ window.__ModuleLoader__.load({
|
|
|
3520
3728
|
branches
|
|
3521
3729
|
})).sort((left, right) => left.remote.localeCompare(right.remote));
|
|
3522
3730
|
}
|
|
3731
|
+
/** Every group key the branch tree renders — the collapse-all target set.
|
|
3732
|
+
* The bare `remote` key folds the whole remote tree; the nested
|
|
3733
|
+
* `remote:<name>` keys matter only for the groups it re-opens. */
|
|
3734
|
+
function branchGroupKeys(remotes) {
|
|
3735
|
+
return [
|
|
3736
|
+
"local",
|
|
3737
|
+
"remote",
|
|
3738
|
+
...groupRemotes(remotes).map((group) => `remote:${group.remote}`)
|
|
3739
|
+
];
|
|
3740
|
+
}
|
|
3523
3741
|
//#endregion
|
|
3524
3742
|
//#region \0git-worktree-css:/home/runner/work/dsh-git-branch/dsh-git-branch/src/client/GitHistoryPanel.module.css?inline
|
|
3525
|
-
const css$2 = "/* Git panel (sidebar global panel). Three stacked sections over the main\n * column: uncommitted changes + commit box, branches, commit history. Host\n * tokens only; the few status colors fall back to the same literals the\n * settings card uses. */\n\n.page_427795137 {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n}\n\n.topbar_427795137 {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 16px 8px;\n}\n\n.back_427795137 {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: 0;\n background: none;\n cursor: pointer;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n padding: 4px 8px;\n border-radius: 8px;\n}\n\n.back_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.title_427795137 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.repoPill_427795137 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n font-size: 12px;\n line-height: 1.4;\n color: var(--dsw-alias-label-secondary);\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 999px;\n padding: 3px 10px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.repoName_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.branchName_427795137 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.track_427795137 {\n font-variant-numeric: tabular-nums;\n}\n\n.topbarActions_427795137 {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n flex: none;\n}\n\n.refreshBtn_427795137 {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n border-radius: 8px;\n background: none;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n.refreshBtn_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.refreshBtn_427795137[disabled] {\n opacity: 0.5;\n cursor: default;\n}\n\n.scroll_427795137 {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 0 16px 16px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n/* Sections NEVER flex-shrink: the scroll container is a definite-height\n * flex column, and a shrinkable child collapses to a fraction of its\n * content while the overflow paints over the following sections (the\n * branch section went empty and the commit box drifted into the history).\n * Natural heights; the container scrolls as a whole. */\n.section_427795137 {\n flex: none;\n border: 0.5px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-2);\n display: flex;\n flex-direction: column;\n}\n\n.sectionHead_427795137 {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.sectionTitle_427795137 {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.countBadge_427795137 {\n font-size: 10px;\n line-height: 1;\n border-radius: 999px;\n padding: 3px 7px;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.sectionTools_427795137 {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.sectionBody_427795137 {\n padding: 10px 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* Small action chip used across the section heads and the commit row. */\n.act_427795137 {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font: inherit;\n font-size: 12px;\n line-height: 1.4;\n cursor: pointer;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 7px;\n padding: 4px 10px;\n white-space: nowrap;\n}\n\n.act_427795137:hover:not([disabled]) {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.act_427795137[disabled] {\n opacity: 0.45;\n cursor: default;\n}\n\n.actPrimary_427795137 {\n /* Hardcoded blue by request — the brand token does not resolve reliably\n * inside the better-sidebar panel. */\n background: #4c6bf5;\n border-color: transparent;\n color: #fff;\n}\n\n.actPrimary_427795137:hover:not([disabled]) {\n border-color: transparent;\n filter: brightness(1.06);\n}\n\n/* Uncommitted changes */\n\n.groupTitleRow_427795137 {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.linkBtn_427795137 {\n margin-left: auto;\n background: none;\n border: 0;\n padding: 2px 4px;\n font: inherit;\n font-size: 12px;\n color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n border-radius: 5px;\n}\n\n.linkBtn_427795137:hover:not([disabled]) {\n text-decoration: underline;\n}\n\n.linkBtn_427795137[disabled] {\n opacity: 0.5;\n cursor: default;\n}\n\n.changeRow_427795137 {\n display: grid;\n grid-template-columns: 16px 18px minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n padding: 3px 6px;\n border-radius: 6px;\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n}\n\n.changeRow_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.changeCheck_427795137 {\n width: 14px;\n height: 14px;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n margin: 0;\n}\n\n.statusBadge_427795137 {\n width: 16px;\n height: 16px;\n border-radius: 4px;\n font-size: 10px;\n line-height: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n color: #fff;\n box-sizing: border-box;\n}\n\n.statusA_427795137 { background: var(--dsw-alias-status-success, #218358); }\n.statusM_427795137 { background: var(--dsw-alias-label-warning, #b07000); }\n.statusD_427795137 { background: var(--dsw-alias-status-danger, #d5304f); }\n.statusR_427795137 { background: #8350d8; }\n.statusC_427795137 { background: #8350d8; }\n.statusT_427795137 { background: #5b7a9d; }\n.statusQ_427795137 { background: var(--dsw-alias-label-dimmed, #9aa0aa); }\n.statusU_427795137 { background: #d5502e; }\n\n.changePath_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: ui-monospace, Consolas, monospace;\n font-size: 11.5px;\n direction: rtl;\n text-align: left;\n}\n\n.stageHint_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n flex: none;\n}\n\n.commitBox_427795137 {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n.commitInput_427795137 {\n width: 100%;\n box-sizing: border-box;\n resize: vertical;\n min-height: 52px;\n font: inherit;\n font-size: 12.5px;\n line-height: 1.5;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n padding: 7px 10px;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n outline: none;\n}\n\n.commitInput_427795137:focus {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.commitActions_427795137 {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.commitHint_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n min-height: 16px;\n}\n\n.split_427795137 {\n margin-left: auto;\n display: flex;\n position: relative;\n}\n\n.splitMain_427795137 {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n padding: 6px 16px;\n font-size: 13px;\n}\n\n.splitCaret_427795137 {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n margin-left: 1px;\n padding: 6px 6px;\n}\n\n.menu_427795137 {\n position: absolute;\n right: 0;\n top: calc(100% + 4px);\n z-index: 40;\n width: max-content;\n min-width: 0;\n background: var(--dsw-alias-surface-raised, var(--dsw-alias-bg-layer-3));\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n box-shadow: var(--dsw-shadow-lv3);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n padding: 3px;\n display: flex;\n flex-direction: column;\n}\n\n.menuItem_427795137 {\n display: block;\n width: 100%;\n text-align: left;\n background: none;\n border: 0;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 1.4;\n padding: 5px 10px;\n border-radius: 5px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.menuItem_427795137:hover:not([disabled]) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.menuItem_427795137[disabled] {\n opacity: 0.5;\n cursor: default;\n}\n\n.menuSub_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n margin-top: 1px;\n}\n\n/* Branch section — two IDEA-style trees: 本地 → branches, 远程 → per-remote → branches */\n\n.treeHead_427795137 {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-label-secondary);\n user-select: none;\n}\n\n.treeHead_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.treeChevron_427795137 {\n display: inline-flex;\n align-items: center;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.treeChildren_427795137 {\n display: flex;\n flex-direction: column;\n margin-left: 12px;\n}\n\n.treeHeadNest_427795137 {\n font-weight: 400;\n}\n\n.treeNest_427795137 {\n margin-left: 12px;\n}\n\n.branchRow_427795137 {\n display: grid;\n grid-template-columns: 20px minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n padding: 5px 8px;\n border-radius: 7px;\n cursor: pointer;\n font-size: 12.5px;\n color: var(--dsw-alias-label-primary);\n}\n\n.branchRow_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.branchRowCurrent_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n cursor: default;\n}\n\n.branchRowCurrent_427795137:hover {\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.branchMark_427795137 {\n color: var(--dsw-alias-brand-primary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.branchName_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n}\n\n.branchKind_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n margin-left: 6px;\n}\n\n.branchTrack_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n flex: none;\n}\n\n/* The branch action menu is portaled; fixed positioning by row rect. */\n.floatMenu_427795137 {\n position: fixed;\n z-index: 60;\n min-width: 190px;\n}\n\n.menuHead_427795137 {\n padding: 6px 10px 5px;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n margin-bottom: 3px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.menuHeadStrong_427795137 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.menuDanger_427795137 {\n color: var(--dsw-alias-status-danger, #d5304f);\n}\n\n.formField_427795137 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.formLabel_427795137 {\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.formInput_427795137 {\n font: inherit;\n font-size: 13px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n padding: 7px 10px;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n outline: none;\n}\n\n.formInput_427795137:focus {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.formError_427795137 {\n font-size: 12px;\n color: var(--dsw-alias-status-danger, #d5304f);\n min-height: 16px;\n}\n\n/* Commit history */\n\n.historyHead_427795137 {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.searchBox_427795137 {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n flex: 1;\n max-width: 300px;\n min-width: 140px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 7px;\n padding: 0 9px;\n height: 28px;\n color: var(--dsw-alias-label-tertiary);\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.searchInput_427795137 {\n flex: 1;\n min-width: 0;\n border: 0;\n background: none;\n outline: none;\n font: inherit;\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n}\n\n.searchInput_427795137::placeholder {\n color: var(--dsw-alias-label-tertiary);\n}\n\n.commitRow_427795137 {\n position: relative;\n display: grid;\n grid-template-columns: 22px minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n padding: 6px 8px 6px 2px;\n cursor: pointer;\n border-radius: 7px;\n}\n\n.commitRow_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.commitRowOpen_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.commitRowOpen_427795137:hover {\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.commitGraph_427795137 {\n position: relative;\n align-self: stretch;\n min-height: 34px;\n}\n\n.commitGraph_427795137::before {\n content: \"\";\n position: absolute;\n left: 10px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--dsw-alias-border-l2);\n}\n\n.commitRowFirst_427795137 .commitGraph_427795137::before {\n top: 50%;\n}\n\n.commitRowLast_427795137 .commitGraph_427795137::before {\n bottom: 50%;\n}\n\n.commitDot_427795137 {\n position: absolute;\n left: 5px;\n top: 50%;\n transform: translateY(-50%);\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: var(--dsw-alias-brand-primary);\n border: 3px solid var(--dsw-alias-bg-layer-2);\n box-sizing: content-box;\n margin-left: -3px;\n}\n\n.commitDotMerge_427795137 {\n background: #8350d8;\n}\n\n.commitMain_427795137 {\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n.commitSubject_427795137 {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n font-size: 12.5px;\n color: var(--dsw-alias-label-primary);\n}\n\n.commitSubjectText_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.commitRowOpen_427795137 .commitSubjectText_427795137 {\n font-weight: 600;\n}\n\n.refBadges_427795137 {\n display: inline-flex;\n gap: 4px;\n flex: none;\n}\n\n.refBadge_427795137 {\n font-size: 10px;\n line-height: 1;\n border-radius: 4px;\n padding: 3px 5px;\n font-weight: 500;\n white-space: nowrap;\n max-width: 140px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.refHead_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary-bluish);\n border: 0.5px solid var(--dsw-alias-border-l4);\n}\n\n.refTag_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-warning, #b07000);\n border: 0.5px solid var(--dsw-alias-border-l4);\n}\n\n.refRemote_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n color: #8350d8;\n border: 0.5px solid var(--dsw-alias-border-l4);\n}\n\n.refLocal_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-status-success, #218358);\n border: 0.5px solid var(--dsw-alias-border-l4);\n}\n\n.commitMeta_427795137 {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11.5px;\n}\n\n.authorDot_427795137 {\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: var(--dsw-alias-brand-primary);\n color: #fff;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 9px;\n flex: none;\n}\n\n.commitSide_427795137 {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11.5px;\n flex: none;\n}\n\n.commitHash_427795137 {\n font-family: ui-monospace, Consolas, monospace;\n}\n\n.commitExpand_427795137 {\n grid-column: 1 / -1;\n padding: 2px 4px 8px 28px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.commitExpandTitle_427795137 {\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\n margin-bottom: 3px;\n}\n\n.fileRow_427795137 {\n display: grid;\n grid-template-columns: 18px minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n padding: 3px 6px;\n border-radius: 6px;\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n}\n\n.fileRow_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.filePath_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: ui-monospace, Consolas, monospace;\n font-size: 11.5px;\n direction: rtl;\n text-align: left;\n}\n\n.fileNums_427795137 {\n font-variant-numeric: tabular-nums;\n color: var(--dsw-alias-label-tertiary);\n flex: none;\n}\n\n.fileAdd_427795137 { color: var(--dsw-alias-status-success, #218358); }\n.fileDel_427795137 { color: var(--dsw-alias-status-danger, #d5304f); }\n\n.empty_427795137 {\n padding: 28px 16px;\n text-align: center;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12.5px;\n}\n\n.errorText_427795137 {\n padding: 20px 16px;\n text-align: center;\n color: var(--dsw-alias-status-danger, #d5304f);\n font-size: 12.5px;\n}\n\n.moreRow_427795137 {\n display: flex;\n justify-content: center;\n padding: 8px 0 2px;\n}\n";
|
|
3743
|
+
const css$2 = "/* Git panel (sidebar global panel). Three stacked sections over the main\n * column: uncommitted changes + commit box, branches, commit history. Host\n * tokens only; the few status colors fall back to the same literals the\n * settings card uses. */\n\n.page_427795137 {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n}\n\n.topbar_427795137 {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 16px 8px;\n}\n\n.back_427795137 {\n flex: none;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: 0;\n background: none;\n cursor: pointer;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n padding: 4px 8px;\n border-radius: 8px;\n}\n\n.back_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.title_427795137 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.repoPill_427795137 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n font-size: 12px;\n line-height: 1.4;\n color: var(--dsw-alias-label-secondary);\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 999px;\n padding: 3px 10px;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.repoName_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.branchName_427795137 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.track_427795137 {\n font-variant-numeric: tabular-nums;\n}\n\n.topbarActions_427795137 {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n flex: none;\n}\n\n.refreshBtn_427795137 {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n border-radius: 8px;\n background: none;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n.refreshBtn_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.refreshBtn_427795137[disabled] {\n opacity: 0.5;\n cursor: default;\n}\n\n/* Cn-accelerate: the topbar 国内加速 button and its anchored popover. The\n * button's on-state is brand tint + brand text + green dot; the popover\n * mirrors the settings card's switch/input affordances over this panel's\n * tokens (popup chrome follows .menu_427795137 above). */\n\n.cnWrap_427795137 {\n position: relative;\n display: inline-flex;\n}\n\n.cnBtn_427795137,\n.cnBtnOn_427795137 {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n height: 28px;\n padding: 0 10px;\n border: 0;\n border-radius: 8px;\n background: none;\n color: var(--dsw-alias-label-secondary);\n font: inherit;\n font-size: 12px;\n line-height: 1;\n cursor: pointer;\n}\n\n.cnBtn_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.cnBtnOn_427795137 {\n background: rgba(76, 107, 245, 0.16);\n color: var(--dsw-alias-brand-primary);\n}\n\n.cnBtnOn_427795137:hover {\n background: rgba(76, 107, 245, 0.22);\n color: var(--dsw-alias-brand-primary);\n}\n\n.cnDot_427795137 {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--dsw-alias-status-success, #218358);\n}\n\n.cnPop_427795137 {\n position: absolute;\n right: 0;\n top: calc(100% + 6px);\n z-index: 40;\n width: 320px;\n background: var(--dsw-alias-surface-raised, var(--dsw-alias-bg-layer-3));\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n box-shadow: var(--dsw-shadow-lv3);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.cnPopHead_427795137 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n\n.cnPopTitle_427795137 {\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.cnSwitchRow_427795137 {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n.cnSwitch_427795137 {\n width: 16px;\n height: 16px;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n.cnSwitch_427795137:disabled {\n cursor: default;\n}\n\n.cnHint_427795137 {\n margin: 0;\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.cnFieldHead_427795137 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n font-size: 12px;\n}\n\n.cnFieldLabel_427795137 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.cnLink_427795137 {\n border: 0;\n background: none;\n padding: 0;\n font: inherit;\n font-size: 12px;\n color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n.cnLink_427795137:hover {\n text-decoration: underline;\n}\n\n.cnLink_427795137:disabled {\n opacity: 0.5;\n cursor: default;\n text-decoration: none;\n}\n\n.cnInput_427795137,\n.cnInputBad_427795137 {\n box-sizing: border-box;\n width: 100%;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n padding: 6px 8px;\n outline: none;\n}\n\n.cnInput_427795137:focus {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.cnInputBad_427795137,\n.cnInputBad_427795137:focus {\n border-color: var(--dsw-alias-status-danger, #d5304f);\n}\n\n.cnError_427795137 {\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-status-danger, #d5304f);\n}\n\n.cnFooter_427795137 {\n display: flex;\n justify-content: flex-end;\n gap: 6px;\n margin-top: 2px;\n}\n\n.cnGhost_427795137,\n.cnSave_427795137 {\n border: 0;\n border-radius: 6px;\n font: inherit;\n font-size: 12px;\n padding: 5px 12px;\n cursor: pointer;\n}\n\n.cnGhost_427795137 {\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n\n.cnGhost_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.cnSave_427795137 {\n background: var(--dsw-alias-brand-primary);\n color: #fff;\n}\n\n.cnSave_427795137:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.scroll_427795137 {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n padding: 0 16px 16px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n/* The page column below the topbar is a definite-height flex column and the\n * three cards split it 2:1:2 (uncommitted : branches : history) — five\n * shares, the topbar and gaps taking their natural height first. Each body\n * scrolls INSIDE its share — min-height: 0 is what lets a flex child shrink\n * below its content (the old natural-height model painted overflowing rows\n * over the sections below). A floor keeps a very short panel from\n * collapsing a card to its bare head; past the floor the column itself\n * scrolls. */\n.section_427795137 {\n border: 0.5px solid var(--dsw-alias-border-l2);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-2);\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\n\n.sectionFill_427795137 {\n flex: 1 1 0;\n min-height: 84px;\n}\n\n/* The three flex-grow overrides of the 2:1:2 split. */\n.sectionChanges_427795137 {\n flex-grow: 2;\n}\n\n.sectionBranches_427795137 {\n flex-grow: 1;\n}\n\n.sectionHistory_427795137 {\n flex-grow: 2;\n}\n\n.sectionHead_427795137 {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.sectionTitle_427795137 {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.countBadge_427795137 {\n font-size: 10px;\n line-height: 1;\n border-radius: 999px;\n padding: 3px 7px;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-secondary);\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.sectionTools_427795137 {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.sectionBody_427795137 {\n padding: 10px 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex: 1 1 auto;\n min-height: 0;\n}\n\n/* The branch and history bodies scroll as a whole inside their share. */\n.sectionBodyScroll_427795137 {\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n/* Inside the uncommitted card only the file lists scroll; the commit box\n * below stays pinned however long the change tree is. */\n.changeList_427795137 {\n display: flex;\n flex-direction: column;\n gap: 8px;\n flex: 1 1 auto;\n min-height: 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n}\n\n/* The 全部展开/全部折叠 text chips in the branch card head. */\n.treeToggle_427795137 {\n background: none;\n border: 0;\n padding: 2px 5px;\n font: inherit;\n font-size: 11.5px;\n line-height: 1.4;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n border-radius: 5px;\n white-space: nowrap;\n}\n\n.treeToggle_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-brand-primary);\n}\n\n/* Small action chip used across the section heads and the commit row. */\n.act_427795137 {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font: inherit;\n font-size: 12px;\n line-height: 1.4;\n cursor: pointer;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 7px;\n padding: 4px 10px;\n white-space: nowrap;\n}\n\n.act_427795137:hover:not([disabled]) {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.act_427795137[disabled] {\n opacity: 0.45;\n cursor: default;\n}\n\n.actPrimary_427795137 {\n /* Hardcoded blue by request — the brand token does not resolve reliably\n * inside the better-sidebar panel. */\n background: #4c6bf5;\n border-color: transparent;\n color: #fff;\n}\n\n.actPrimary_427795137:hover:not([disabled]) {\n border-color: transparent;\n filter: brightness(1.06);\n}\n\n/* Uncommitted changes */\n\n.groupTitleRow_427795137 {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.linkBtn_427795137 {\n margin-left: auto;\n background: none;\n border: 0;\n padding: 2px 4px;\n font: inherit;\n font-size: 12px;\n color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n border-radius: 5px;\n}\n\n.linkBtn_427795137:hover:not([disabled]) {\n text-decoration: underline;\n}\n\n.linkBtn_427795137[disabled] {\n opacity: 0.5;\n cursor: default;\n}\n\n.changeRow_427795137 {\n display: grid;\n grid-template-columns: 16px 18px minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n padding: 3px 6px;\n border-radius: 6px;\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n}\n\n.changeRow_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.changeCheck_427795137 {\n width: 14px;\n height: 14px;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n margin: 0;\n}\n\n.statusBadge_427795137 {\n width: 16px;\n height: 16px;\n border-radius: 4px;\n font-size: 10px;\n line-height: 1;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n color: #fff;\n box-sizing: border-box;\n}\n\n.statusA_427795137 { background: var(--dsw-alias-status-success, #218358); }\n.statusM_427795137 { background: var(--dsw-alias-label-warning, #b07000); }\n.statusD_427795137 { background: var(--dsw-alias-status-danger, #d5304f); }\n.statusR_427795137 { background: #8350d8; }\n.statusC_427795137 { background: #8350d8; }\n.statusT_427795137 { background: #5b7a9d; }\n.statusQ_427795137 { background: var(--dsw-alias-label-dimmed, #9aa0aa); }\n.statusU_427795137 { background: #d5502e; }\n\n.changePath_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: ui-monospace, Consolas, monospace;\n font-size: 11.5px;\n direction: rtl;\n text-align: left;\n}\n\n.stageHint_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n flex: none;\n}\n\n.commitBox_427795137 {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n flex: none;\n}\n\n.commitInput_427795137 {\n width: 100%;\n box-sizing: border-box;\n resize: vertical;\n min-height: 52px;\n font: inherit;\n font-size: 12.5px;\n line-height: 1.5;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n padding: 7px 10px;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n outline: none;\n}\n\n.commitInput_427795137:focus {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.commitActions_427795137 {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.commitHint_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n min-height: 16px;\n}\n\n.split_427795137 {\n margin-left: auto;\n display: flex;\n position: relative;\n}\n\n.splitMain_427795137 {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n padding: 6px 16px;\n font-size: 13px;\n}\n\n.splitCaret_427795137 {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n margin-left: 1px;\n padding: 6px 6px;\n}\n\n.menu_427795137 {\n position: absolute;\n right: 0;\n top: calc(100% + 4px);\n z-index: 40;\n width: max-content;\n min-width: 0;\n background: var(--dsw-alias-surface-raised, var(--dsw-alias-bg-layer-3));\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n box-shadow: var(--dsw-shadow-lv3);\n backdrop-filter: var(--dsw-menu-backdrop-filter);\n padding: 3px;\n display: flex;\n flex-direction: column;\n}\n\n.menuItem_427795137 {\n display: block;\n width: 100%;\n text-align: left;\n background: none;\n border: 0;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n line-height: 1.4;\n padding: 5px 10px;\n border-radius: 5px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.menuItem_427795137:hover:not([disabled]) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.menuItem_427795137[disabled] {\n opacity: 0.5;\n cursor: default;\n}\n\n.menuSub_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n margin-top: 1px;\n}\n\n/* Branch section — two IDEA-style trees: 本地 → branches, 远程 → per-remote → branches */\n\n.treeHead_427795137 {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 6px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-label-secondary);\n user-select: none;\n}\n\n.treeHead_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.treeChevron_427795137 {\n display: inline-flex;\n align-items: center;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.treeChildren_427795137 {\n display: flex;\n flex-direction: column;\n margin-left: 12px;\n}\n\n.treeHeadNest_427795137 {\n font-weight: 400;\n}\n\n.treeNest_427795137 {\n margin-left: 12px;\n}\n\n.branchRow_427795137 {\n display: grid;\n grid-template-columns: 20px minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n padding: 5px 8px;\n border-radius: 7px;\n /* The action menu opens on RIGHT-CLICK (Enter/Space for keyboard) — an\n * arrow, not the pointing hand a left-click affordance would promise. */\n cursor: default;\n font-size: 12.5px;\n color: var(--dsw-alias-label-primary);\n}\n\n.branchRow_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n/* Whole-row highlight for the current branch: the ✓ alone read as too\n * quiet inside the tree. A translucent brand-blue wash plus the inset left\n * accent and a colored name survives both themes; #4c6bf5 is the same\n * hardcoded blue actPrimary uses (the brand token does not resolve\n * reliably inside the better-sidebar panel). */\n.branchRowCurrent_427795137 {\n background: rgba(76, 107, 245, 0.16);\n box-shadow: inset 2px 0 0 #4c6bf5;\n cursor: default;\n}\n\n.branchRowCurrent_427795137:hover {\n background: rgba(76, 107, 245, 0.16);\n}\n\n.branchRowCurrent_427795137 .branchName_427795137 {\n color: #4c6bf5;\n font-weight: 600;\n}\n\n.branchMark_427795137 {\n color: var(--dsw-alias-brand-primary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.branchName_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n}\n\n.branchKind_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n margin-left: 6px;\n}\n\n.branchTrack_427795137 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n flex: none;\n}\n\n/* The branch action menu is portaled; fixed positioning by row rect. */\n.floatMenu_427795137 {\n position: fixed;\n z-index: 60;\n min-width: 190px;\n}\n\n.menuHead_427795137 {\n padding: 6px 10px 5px;\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n margin-bottom: 3px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.menuHeadStrong_427795137 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.menuDanger_427795137 {\n color: var(--dsw-alias-status-danger, #d5304f);\n}\n\n.formField_427795137 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.formLabel_427795137 {\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.formInput_427795137 {\n font: inherit;\n font-size: 13px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n padding: 7px 10px;\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary);\n outline: none;\n}\n\n.formInput_427795137:focus {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.formError_427795137 {\n font-size: 12px;\n color: var(--dsw-alias-status-danger, #d5304f);\n min-height: 16px;\n}\n\n/* Commit history */\n\n.historyHead_427795137 {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.searchBox_427795137 {\n margin-left: auto;\n display: flex;\n align-items: center;\n gap: 6px;\n flex: 1;\n max-width: 300px;\n min-width: 140px;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 7px;\n padding: 0 9px;\n height: 28px;\n color: var(--dsw-alias-label-tertiary);\n background: var(--dsw-alias-bg-layer-3);\n}\n\n/* The branch card's head variant: sits right of the title and grows toward\n * the tools instead of being right-aligned by `margin-left: auto`. The\n * overrides win because both selectors are single classes and this one is\n * declared later. */\n.searchBoxHead_427795137 {\n margin-left: 0;\n flex: 1 1 auto;\n max-width: 320px;\n min-width: 90px;\n}\n\n.searchInput_427795137 {\n flex: 1;\n min-width: 0;\n border: 0;\n background: none;\n outline: none;\n font: inherit;\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n}\n\n.searchInput_427795137::placeholder {\n color: var(--dsw-alias-label-tertiary);\n}\n\n.commitRow_427795137 {\n position: relative;\n display: grid;\n grid-template-columns: 22px minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n padding: 6px 8px 6px 2px;\n cursor: pointer;\n border-radius: 7px;\n}\n\n.commitRow_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.commitRowOpen_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.commitRowOpen_427795137:hover {\n background: var(--dsw-alias-bg-layer-3);\n}\n\n.commitGraph_427795137 {\n position: relative;\n align-self: stretch;\n min-height: 34px;\n}\n\n.commitGraph_427795137::before {\n content: \"\";\n position: absolute;\n left: 10px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--dsw-alias-border-l2);\n}\n\n.commitRowFirst_427795137 .commitGraph_427795137::before {\n top: 50%;\n}\n\n.commitRowLast_427795137 .commitGraph_427795137::before {\n bottom: 50%;\n}\n\n/* A small plain dot on the rail — the old 10px dot with a fat card-colored\n * ring read as a heavy black blob. #4c6bf5 for the same reason actPrimary\n * hardcodes it (the brand token does not resolve reliably in this panel). */\n.commitDot_427795137 {\n position: absolute;\n left: 8px;\n top: 50%;\n transform: translateY(-50%);\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: #4c6bf5;\n}\n\n.commitDotMerge_427795137 {\n background: #8350d8;\n}\n\n.commitMain_427795137 {\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n.commitSubject_427795137 {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n font-size: 12.5px;\n color: var(--dsw-alias-label-primary);\n}\n\n.commitSubjectText_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.commitRowOpen_427795137 .commitSubjectText_427795137 {\n font-weight: 600;\n}\n\n.refBadges_427795137 {\n display: inline-flex;\n gap: 4px;\n flex: none;\n}\n\n.refBadge_427795137 {\n font-size: 10px;\n line-height: 1;\n border-radius: 4px;\n padding: 3px 5px;\n font-weight: 500;\n white-space: nowrap;\n max-width: 140px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.refHead_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-primary-bluish);\n border: 0.5px solid var(--dsw-alias-border-l4);\n}\n\n.refTag_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-label-warning, #b07000);\n border: 0.5px solid var(--dsw-alias-border-l4);\n}\n\n.refRemote_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n color: #8350d8;\n border: 0.5px solid var(--dsw-alias-border-l4);\n}\n\n.refLocal_427795137 {\n background: var(--dsw-alias-bg-layer-3);\n color: var(--dsw-alias-status-success, #218358);\n border: 0.5px solid var(--dsw-alias-border-l4);\n}\n\n.commitMeta_427795137 {\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11.5px;\n}\n\n.commitSide_427795137 {\n display: flex;\n align-items: center;\n gap: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11.5px;\n flex: none;\n}\n\n.commitHash_427795137 {\n font-family: ui-monospace, Consolas, monospace;\n}\n\n.commitExpand_427795137 {\n grid-column: 1 / -1;\n padding: 2px 4px 8px 28px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.commitExpandTitle_427795137 {\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\n margin-bottom: 3px;\n}\n\n.fileRow_427795137 {\n display: grid;\n grid-template-columns: 18px minmax(0, 1fr) auto;\n gap: 8px;\n align-items: center;\n padding: 3px 6px;\n border-radius: 6px;\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n}\n\n.fileRow_427795137:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.filePath_427795137 {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-family: ui-monospace, Consolas, monospace;\n font-size: 11.5px;\n direction: rtl;\n text-align: left;\n}\n\n.fileNums_427795137 {\n font-variant-numeric: tabular-nums;\n color: var(--dsw-alias-label-tertiary);\n flex: none;\n}\n\n.fileAdd_427795137 { color: var(--dsw-alias-status-success, #218358); }\n.fileDel_427795137 { color: var(--dsw-alias-status-danger, #d5304f); }\n\n.empty_427795137 {\n padding: 28px 16px;\n text-align: center;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12.5px;\n}\n\n.errorText_427795137 {\n padding: 20px 16px;\n text-align: center;\n color: var(--dsw-alias-status-danger, #d5304f);\n font-size: 12.5px;\n}\n\n.moreRow_427795137 {\n display: flex;\n justify-content: center;\n padding: 8px 0 2px;\n}\n";
|
|
3526
3744
|
const tagId$2 = "dsh-git-branch-manage/GitHistoryPanel.module.css";
|
|
3527
3745
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId$2 + "\"]") === null) {
|
|
3528
3746
|
const tag = document.createElement("style");
|
|
@@ -3542,13 +3760,40 @@ window.__ModuleLoader__.load({
|
|
|
3542
3760
|
"track": "track_427795137",
|
|
3543
3761
|
"topbarActions": "topbarActions_427795137",
|
|
3544
3762
|
"refreshBtn": "refreshBtn_427795137",
|
|
3763
|
+
"menu": "menu_427795137",
|
|
3764
|
+
"cnWrap": "cnWrap_427795137",
|
|
3765
|
+
"cnBtn": "cnBtn_427795137",
|
|
3766
|
+
"cnBtnOn": "cnBtnOn_427795137",
|
|
3767
|
+
"cnDot": "cnDot_427795137",
|
|
3768
|
+
"cnPop": "cnPop_427795137",
|
|
3769
|
+
"cnPopHead": "cnPopHead_427795137",
|
|
3770
|
+
"cnPopTitle": "cnPopTitle_427795137",
|
|
3771
|
+
"cnSwitchRow": "cnSwitchRow_427795137",
|
|
3772
|
+
"cnSwitch": "cnSwitch_427795137",
|
|
3773
|
+
"cnHint": "cnHint_427795137",
|
|
3774
|
+
"cnFieldHead": "cnFieldHead_427795137",
|
|
3775
|
+
"cnFieldLabel": "cnFieldLabel_427795137",
|
|
3776
|
+
"cnLink": "cnLink_427795137",
|
|
3777
|
+
"cnInput": "cnInput_427795137",
|
|
3778
|
+
"cnInputBad": "cnInputBad_427795137",
|
|
3779
|
+
"cnError": "cnError_427795137",
|
|
3780
|
+
"cnFooter": "cnFooter_427795137",
|
|
3781
|
+
"cnGhost": "cnGhost_427795137",
|
|
3782
|
+
"cnSave": "cnSave_427795137",
|
|
3545
3783
|
"scroll": "scroll_427795137",
|
|
3546
3784
|
"section": "section_427795137",
|
|
3785
|
+
"sectionFill": "sectionFill_427795137",
|
|
3786
|
+
"sectionChanges": "sectionChanges_427795137",
|
|
3787
|
+
"sectionBranches": "sectionBranches_427795137",
|
|
3788
|
+
"sectionHistory": "sectionHistory_427795137",
|
|
3547
3789
|
"sectionHead": "sectionHead_427795137",
|
|
3548
3790
|
"sectionTitle": "sectionTitle_427795137",
|
|
3549
3791
|
"countBadge": "countBadge_427795137",
|
|
3550
3792
|
"sectionTools": "sectionTools_427795137",
|
|
3551
3793
|
"sectionBody": "sectionBody_427795137",
|
|
3794
|
+
"sectionBodyScroll": "sectionBodyScroll_427795137",
|
|
3795
|
+
"changeList": "changeList_427795137",
|
|
3796
|
+
"treeToggle": "treeToggle_427795137",
|
|
3552
3797
|
"act": "act_427795137",
|
|
3553
3798
|
"actPrimary": "actPrimary_427795137",
|
|
3554
3799
|
"groupTitleRow": "groupTitleRow_427795137",
|
|
@@ -3573,7 +3818,6 @@ window.__ModuleLoader__.load({
|
|
|
3573
3818
|
"split": "split_427795137",
|
|
3574
3819
|
"splitMain": "splitMain_427795137",
|
|
3575
3820
|
"splitCaret": "splitCaret_427795137",
|
|
3576
|
-
"menu": "menu_427795137",
|
|
3577
3821
|
"menuItem": "menuItem_427795137",
|
|
3578
3822
|
"menuSub": "menuSub_427795137",
|
|
3579
3823
|
"treeHead": "treeHead_427795137",
|
|
@@ -3596,6 +3840,7 @@ window.__ModuleLoader__.load({
|
|
|
3596
3840
|
"formError": "formError_427795137",
|
|
3597
3841
|
"historyHead": "historyHead_427795137",
|
|
3598
3842
|
"searchBox": "searchBox_427795137",
|
|
3843
|
+
"searchBoxHead": "searchBoxHead_427795137",
|
|
3599
3844
|
"searchInput": "searchInput_427795137",
|
|
3600
3845
|
"commitRow": "commitRow_427795137",
|
|
3601
3846
|
"commitRowOpen": "commitRowOpen_427795137",
|
|
@@ -3614,7 +3859,6 @@ window.__ModuleLoader__.load({
|
|
|
3614
3859
|
"refRemote": "refRemote_427795137",
|
|
3615
3860
|
"refLocal": "refLocal_427795137",
|
|
3616
3861
|
"commitMeta": "commitMeta_427795137",
|
|
3617
|
-
"authorDot": "authorDot_427795137",
|
|
3618
3862
|
"commitSide": "commitSide_427795137",
|
|
3619
3863
|
"commitHash": "commitHash_427795137",
|
|
3620
3864
|
"commitExpand": "commitExpand_427795137",
|
|
@@ -3632,18 +3876,36 @@ window.__ModuleLoader__.load({
|
|
|
3632
3876
|
//#region src/client/panel/BranchSection.tsx
|
|
3633
3877
|
/**
|
|
3634
3878
|
* BranchSection: the panel's middle block — the branch list with an IDEA-style
|
|
3635
|
-
* action menu.
|
|
3636
|
-
* new branch from here, rename, delete, copy name — remote rows
|
|
3637
|
-
* the actions a remote branch can take); the CURRENT branch's
|
|
3638
|
-
* checkout and delete, so rename/new-from/copy stay
|
|
3639
|
-
*
|
|
3640
|
-
*
|
|
3641
|
-
*
|
|
3642
|
-
*
|
|
3643
|
-
*
|
|
3879
|
+
* action menu. RIGHT-CLICKING any row opens a small menu anchored to it
|
|
3880
|
+
* (checkout, new branch from here, rename, delete, copy name — remote rows
|
|
3881
|
+
* narrow it to the actions a remote branch can take); the CURRENT branch's
|
|
3882
|
+
* menu hides only checkout and delete, so rename/new-from/copy stay
|
|
3883
|
+
* reachable. Keyboard rows keep Enter/Space as the menu opener — a context
|
|
3884
|
+
* menu has no keyboard twin. Rename and create run through the Modal
|
|
3885
|
+
* primitive with the same client-side name validation the composer chip
|
|
3886
|
+
* applies; delete confirms first and always uses the safe `-d` form (git
|
|
3887
|
+
* refuses unmerged). Presentational: every action arrives as a callback; the
|
|
3888
|
+
* menu/dialog state is local and resets when the branch list identity
|
|
3889
|
+
* changes.
|
|
3890
|
+
*
|
|
3891
|
+
* The tree opens on 本地 only (the current branch lives there) and the card
|
|
3892
|
+
* takes one share of the panel's fixed 2:1:2 split (its body scrolls inside
|
|
3893
|
+
* it), so a branch-heavy repository can no longer push the other cards off
|
|
3894
|
+
* screen. 全部展开/全部折叠 drive every group at once, and after a checkout
|
|
3895
|
+
* (or expand-all) the card re-centers on the current branch row.
|
|
3896
|
+
*
|
|
3897
|
+
* The head carries a search box: it filters both trees by branch name
|
|
3898
|
+
* (case-insensitive substring), and while a query is active every matching
|
|
3899
|
+
* group renders expanded with its count following the filter — the folded
|
|
3900
|
+
* state the user set is untouched and comes back when the query clears.
|
|
3644
3901
|
*
|
|
3645
3902
|
* @module git-worktree/client/panel/BranchSection
|
|
3646
3903
|
*/
|
|
3904
|
+
/** Groups folded when the card mounts: the remote tree only. The current
|
|
3905
|
+
* branch lives at the TOP of the local group (buildBranchRows sorts it
|
|
3906
|
+
* first), so 本地 stays open — the card opens showing what the panel is
|
|
3907
|
+
* about, without the wall of remote branches. */
|
|
3908
|
+
const COLLAPSED_ON_MOUNT = /* @__PURE__ */ new Set(["remote"]);
|
|
3647
3909
|
/** The action menu as a body portal, fixed-positioned next to the row. */
|
|
3648
3910
|
function BranchFloatMenu(props) {
|
|
3649
3911
|
const { state, t, busy, onAction, onClose } = props;
|
|
@@ -3739,7 +4001,16 @@ window.__ModuleLoader__.load({
|
|
|
3739
4001
|
const [menu, setMenu] = (0, react.useState)(null);
|
|
3740
4002
|
const [dialog, setDialog] = (0, react.useState)(null);
|
|
3741
4003
|
const [draft, setDraft] = (0, react.useState)("");
|
|
3742
|
-
const [
|
|
4004
|
+
const [query, setQuery] = (0, react.useState)("");
|
|
4005
|
+
const [collapsedGroups, setCollapsedGroups] = (0, react.useState)(COLLAPSED_ON_MOUNT);
|
|
4006
|
+
/** The card's scroll body — the locate math centers rows inside it. */
|
|
4007
|
+
const bodyRef = (0, react.useRef)(null);
|
|
4008
|
+
/** The current branch this mount last centered on. A refresh re-centers
|
|
4009
|
+
* only when the checkout moved; a same-branch refresh (stage, commit…)
|
|
4010
|
+
* keeps the scroll where the user left it. */
|
|
4011
|
+
const locatedRef = (0, react.useRef)(null);
|
|
4012
|
+
/** Expand-all asks for one more locate — its rows mount on the next commit. */
|
|
4013
|
+
const pendingLocateRef = (0, react.useRef)(false);
|
|
3743
4014
|
const toggleGroup = (key) => {
|
|
3744
4015
|
setCollapsedGroups((prev) => {
|
|
3745
4016
|
const next = new Set(prev);
|
|
@@ -3748,7 +4019,41 @@ window.__ModuleLoader__.load({
|
|
|
3748
4019
|
return next;
|
|
3749
4020
|
});
|
|
3750
4021
|
};
|
|
4022
|
+
const expandAll = () => {
|
|
4023
|
+
pendingLocateRef.current = true;
|
|
4024
|
+
setCollapsedGroups(/* @__PURE__ */ new Set());
|
|
4025
|
+
};
|
|
4026
|
+
const collapseAll = () => {
|
|
4027
|
+
setCollapsedGroups(new Set(branchGroupKeys(remotes)));
|
|
4028
|
+
};
|
|
4029
|
+
/** Center the current branch row in the card body (no scroll when the
|
|
4030
|
+
* body is shorter than its cap). Rect arithmetic, not offsetTop: no
|
|
4031
|
+
* positioned ancestor is guaranteed between the row and the body. */
|
|
4032
|
+
const locateCurrent = () => {
|
|
4033
|
+
const body = bodyRef.current;
|
|
4034
|
+
if (body === null) return;
|
|
4035
|
+
const row = body.querySelector("[data-current=\"true\"]");
|
|
4036
|
+
if (!(row instanceof HTMLElement)) return;
|
|
4037
|
+
const top = row.getBoundingClientRect().top - body.getBoundingClientRect().top + body.scrollTop;
|
|
4038
|
+
body.scrollTop = Math.max(0, top - (body.clientHeight - row.offsetHeight) / 2);
|
|
4039
|
+
};
|
|
4040
|
+
(0, react.useLayoutEffect)(() => {
|
|
4041
|
+
const current = locals.find((row) => row.current)?.name;
|
|
4042
|
+
if (current === void 0) return;
|
|
4043
|
+
if (!pendingLocateRef.current && current === locatedRef.current) return;
|
|
4044
|
+
pendingLocateRef.current = false;
|
|
4045
|
+
locatedRef.current = current;
|
|
4046
|
+
locateCurrent();
|
|
4047
|
+
});
|
|
3751
4048
|
const total = locals.length + remotes.length;
|
|
4049
|
+
/** The head search: name-substring rows only. A live query opens every
|
|
4050
|
+
* group whatever the folded state is (a hidden match reads as a bug),
|
|
4051
|
+
* without touching that state — clearing the query restores it. */
|
|
4052
|
+
const searching = query.trim() !== "";
|
|
4053
|
+
const visibleLocals = filterBranches(locals, query);
|
|
4054
|
+
const visibleRemotes = filterBranches(remotes, query);
|
|
4055
|
+
const openGroup = (key) => searching || !collapsedGroups.has(key);
|
|
4056
|
+
const matched = visibleLocals.length + visibleRemotes.length;
|
|
3752
4057
|
const openMenu = (branch, event) => {
|
|
3753
4058
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
3754
4059
|
setMenu({
|
|
@@ -3803,7 +4108,7 @@ window.__ModuleLoader__.load({
|
|
|
3803
4108
|
className: `${GitHistoryPanel_module_default.treeHead} ${nested ? GitHistoryPanel_module_default.treeHeadNest : ""}`,
|
|
3804
4109
|
role: "button",
|
|
3805
4110
|
tabIndex: 0,
|
|
3806
|
-
"aria-expanded":
|
|
4111
|
+
"aria-expanded": openGroup(key),
|
|
3807
4112
|
onClick: () => toggleGroup(key),
|
|
3808
4113
|
onKeyDown: (event) => {
|
|
3809
4114
|
if (event.key === "Enter" || event.key === " ") {
|
|
@@ -3814,7 +4119,7 @@ window.__ModuleLoader__.load({
|
|
|
3814
4119
|
children: [
|
|
3815
4120
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3816
4121
|
className: GitHistoryPanel_module_default.treeChevron,
|
|
3817
|
-
children:
|
|
4122
|
+
children: openGroup(key) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { size: 12 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronRightOutlineRegular, { size: 12 })
|
|
3818
4123
|
}),
|
|
3819
4124
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label }),
|
|
3820
4125
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -3825,9 +4130,13 @@ window.__ModuleLoader__.load({
|
|
|
3825
4130
|
});
|
|
3826
4131
|
const renderBranchRow = (row, displayName) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3827
4132
|
className: `${GitHistoryPanel_module_default.branchRow} ${row.current ? GitHistoryPanel_module_default.branchRowCurrent : ""}`,
|
|
4133
|
+
"data-current": row.current ? "true" : void 0,
|
|
3828
4134
|
role: "button",
|
|
3829
4135
|
tabIndex: 0,
|
|
3830
|
-
|
|
4136
|
+
onContextMenu: (event) => {
|
|
4137
|
+
event.preventDefault();
|
|
4138
|
+
openMenu(row, event);
|
|
4139
|
+
},
|
|
3831
4140
|
onKeyDown: (event) => {
|
|
3832
4141
|
if (event.key === "Enter" || event.key === " ") {
|
|
3833
4142
|
event.preventDefault();
|
|
@@ -3851,39 +4160,75 @@ window.__ModuleLoader__.load({
|
|
|
3851
4160
|
]
|
|
3852
4161
|
}, row.name);
|
|
3853
4162
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
3854
|
-
className: GitHistoryPanel_module_default.section
|
|
4163
|
+
className: `${GitHistoryPanel_module_default.section} ${GitHistoryPanel_module_default.sectionFill} ${GitHistoryPanel_module_default.sectionBranches}`,
|
|
3855
4164
|
"aria-label": t("panel.branches"),
|
|
3856
4165
|
children: [
|
|
3857
4166
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3858
4167
|
className: GitHistoryPanel_module_default.sectionHead,
|
|
3859
|
-
children: [
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
4168
|
+
children: [
|
|
4169
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
4170
|
+
className: GitHistoryPanel_module_default.sectionTitle,
|
|
4171
|
+
children: t("panel.branches")
|
|
4172
|
+
}),
|
|
4173
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4174
|
+
className: `${GitHistoryPanel_module_default.searchBox} ${GitHistoryPanel_module_default.searchBoxHead}`,
|
|
4175
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4176
|
+
"aria-hidden": "true",
|
|
4177
|
+
children: "⌕"
|
|
4178
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4179
|
+
type: "text",
|
|
4180
|
+
className: GitHistoryPanel_module_default.searchInput,
|
|
4181
|
+
value: query,
|
|
4182
|
+
placeholder: t("menuSearchPlaceholder"),
|
|
4183
|
+
"aria-label": t("menuSearchPlaceholder"),
|
|
4184
|
+
onChange: (event) => setQuery(event.target.value)
|
|
4185
|
+
})]
|
|
4186
|
+
}),
|
|
4187
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4188
|
+
className: GitHistoryPanel_module_default.sectionTools,
|
|
4189
|
+
children: [
|
|
4190
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4191
|
+
type: "button",
|
|
4192
|
+
className: GitHistoryPanel_module_default.treeToggle,
|
|
4193
|
+
onClick: expandAll,
|
|
4194
|
+
children: t("menuExpandAll")
|
|
4195
|
+
}),
|
|
4196
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4197
|
+
type: "button",
|
|
4198
|
+
className: GitHistoryPanel_module_default.treeToggle,
|
|
4199
|
+
onClick: collapseAll,
|
|
4200
|
+
children: t("menuCollapseAll")
|
|
4201
|
+
}),
|
|
4202
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4203
|
+
type: "button",
|
|
4204
|
+
className: GitHistoryPanel_module_default.act,
|
|
4205
|
+
disabled: busy,
|
|
4206
|
+
onClick: () => openDialog("new"),
|
|
4207
|
+
children: ["+ ", t("panel.branchNew")]
|
|
4208
|
+
})
|
|
4209
|
+
]
|
|
3870
4210
|
})
|
|
3871
|
-
|
|
4211
|
+
]
|
|
3872
4212
|
}),
|
|
3873
4213
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3874
|
-
className: GitHistoryPanel_module_default.sectionBody
|
|
4214
|
+
className: `${GitHistoryPanel_module_default.sectionBody} ${GitHistoryPanel_module_default.sectionBodyScroll}`,
|
|
4215
|
+
ref: bodyRef,
|
|
3875
4216
|
children: [
|
|
3876
4217
|
total === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3877
4218
|
className: GitHistoryPanel_module_default.empty,
|
|
3878
4219
|
children: t("menuNoBranches")
|
|
3879
4220
|
}) : null,
|
|
3880
|
-
|
|
4221
|
+
total > 0 && matched === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4222
|
+
className: GitHistoryPanel_module_default.empty,
|
|
4223
|
+
children: t("menuNoMatches")
|
|
4224
|
+
}) : null,
|
|
4225
|
+
visibleLocals.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [groupHead("local", t("panel.branchLocals"), visibleLocals.length, false), openGroup("local") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3881
4226
|
className: GitHistoryPanel_module_default.treeChildren,
|
|
3882
|
-
children:
|
|
4227
|
+
children: visibleLocals.map((row) => renderBranchRow(row))
|
|
3883
4228
|
}) : null] }) : null,
|
|
3884
|
-
|
|
4229
|
+
visibleRemotes.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [groupHead("remote", t("panel.branchRemotes"), visibleRemotes.length, false), openGroup("remote") ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3885
4230
|
className: GitHistoryPanel_module_default.treeNest,
|
|
3886
|
-
children: groupRemotes(
|
|
4231
|
+
children: groupRemotes(visibleRemotes).map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [groupHead(`remote:${group.remote}`, group.remote, group.branches.length, true), openGroup(`remote:${group.remote}`) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3887
4232
|
className: GitHistoryPanel_module_default.treeChildren,
|
|
3888
4233
|
children: group.branches.map((row) => renderBranchRow(row, row.short))
|
|
3889
4234
|
}) : null] }, group.remote))
|
|
@@ -3965,6 +4310,135 @@ window.__ModuleLoader__.load({
|
|
|
3965
4310
|
});
|
|
3966
4311
|
}
|
|
3967
4312
|
//#endregion
|
|
4313
|
+
//#region src/client/panel/CnAcceleratePopover.tsx
|
|
4314
|
+
/**
|
|
4315
|
+
* CnAcceleratePopover: the 国内加速 popover under the topbar button.
|
|
4316
|
+
*
|
|
4317
|
+
* This is the SHORTCUT surface of the same staged form the settings card row
|
|
4318
|
+
* edits ({@link ../accel-form}): enable switch + mirror URL stage together
|
|
4319
|
+
* and commit together on 保存. Closing the popover — Esc, outside click, 取消
|
|
4320
|
+
* — discards the staged edits through the owner's close handler, so an
|
|
4321
|
+
* abandoned draft can never land half-written.
|
|
4322
|
+
*
|
|
4323
|
+
* Layout follows docs/design/cn-accelerate.md §2.2: title + switch → security
|
|
4324
|
+
* hint → URL field with 恢复默认 → error line → footer.
|
|
4325
|
+
*
|
|
4326
|
+
* @module git-worktree/client/panel/CnAcceleratePopover
|
|
4327
|
+
*/
|
|
4328
|
+
function CnAcceleratePopover(props) {
|
|
4329
|
+
const { accel, t, pushToast, onClose } = props;
|
|
4330
|
+
const rootRef = (0, react.useRef)(null);
|
|
4331
|
+
const state = (0, react.useSyncExternalStore)(accel.store.subscribe, accel.store.getSnapshot);
|
|
4332
|
+
(0, react.useEffect)(() => {
|
|
4333
|
+
const onKeyDown = (event) => {
|
|
4334
|
+
if (event.key === "Escape") onClose();
|
|
4335
|
+
};
|
|
4336
|
+
const onPointerDown = (event) => {
|
|
4337
|
+
if (rootRef.current !== null && !rootRef.current.contains(event.target)) onClose();
|
|
4338
|
+
};
|
|
4339
|
+
document.addEventListener("keydown", onKeyDown);
|
|
4340
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
4341
|
+
return () => {
|
|
4342
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
4343
|
+
document.removeEventListener("pointerdown", onPointerDown);
|
|
4344
|
+
};
|
|
4345
|
+
}, [onClose]);
|
|
4346
|
+
const locked = state.saving || !state.writable;
|
|
4347
|
+
const onSave = (0, react.useCallback)(() => {
|
|
4348
|
+
if (state.saving || state.urlError !== null || !state.writable) return;
|
|
4349
|
+
(async () => {
|
|
4350
|
+
await accel.saveAccel();
|
|
4351
|
+
const after = accel.store.getSnapshot();
|
|
4352
|
+
if (after.failed) {
|
|
4353
|
+
pushToast(t("accel.saveFailed"), "error");
|
|
4354
|
+
return;
|
|
4355
|
+
}
|
|
4356
|
+
pushToast(after.enabled ? t("accel.savedOn", { url: after.urlText }) : t("accel.savedOff"), "success");
|
|
4357
|
+
onClose();
|
|
4358
|
+
})();
|
|
4359
|
+
}, [
|
|
4360
|
+
accel,
|
|
4361
|
+
onClose,
|
|
4362
|
+
pushToast,
|
|
4363
|
+
state.saving,
|
|
4364
|
+
state.urlError,
|
|
4365
|
+
state.writable,
|
|
4366
|
+
t
|
|
4367
|
+
]);
|
|
4368
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4369
|
+
className: GitHistoryPanel_module_default.cnPop,
|
|
4370
|
+
ref: rootRef,
|
|
4371
|
+
role: "dialog",
|
|
4372
|
+
"aria-label": t("panel.cnAccelerate"),
|
|
4373
|
+
children: [
|
|
4374
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4375
|
+
className: GitHistoryPanel_module_default.cnPopHead,
|
|
4376
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4377
|
+
className: GitHistoryPanel_module_default.cnPopTitle,
|
|
4378
|
+
children: t("panel.cnAccelerate")
|
|
4379
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
4380
|
+
className: GitHistoryPanel_module_default.cnSwitchRow,
|
|
4381
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("accel.enable") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4382
|
+
type: "checkbox",
|
|
4383
|
+
className: GitHistoryPanel_module_default.cnSwitch,
|
|
4384
|
+
checked: state.enabled,
|
|
4385
|
+
disabled: locked,
|
|
4386
|
+
onChange: (event) => accel.setAccelEnabled(event.target.checked)
|
|
4387
|
+
})]
|
|
4388
|
+
})]
|
|
4389
|
+
}),
|
|
4390
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4391
|
+
className: GitHistoryPanel_module_default.cnHint,
|
|
4392
|
+
children: t("accel.hint")
|
|
4393
|
+
}),
|
|
4394
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4395
|
+
className: GitHistoryPanel_module_default.cnFieldHead,
|
|
4396
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4397
|
+
className: GitHistoryPanel_module_default.cnFieldLabel,
|
|
4398
|
+
children: t("accel.urlLabel")
|
|
4399
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4400
|
+
type: "button",
|
|
4401
|
+
className: GitHistoryPanel_module_default.cnLink,
|
|
4402
|
+
disabled: locked,
|
|
4403
|
+
onClick: () => accel.restoreAccelDefault(),
|
|
4404
|
+
children: t("accel.restoreDefault")
|
|
4405
|
+
})]
|
|
4406
|
+
}),
|
|
4407
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
4408
|
+
type: "text",
|
|
4409
|
+
className: state.urlError !== null ? GitHistoryPanel_module_default.cnInputBad : GitHistoryPanel_module_default.cnInput,
|
|
4410
|
+
value: state.urlText,
|
|
4411
|
+
spellCheck: false,
|
|
4412
|
+
disabled: locked,
|
|
4413
|
+
"aria-invalid": state.urlError !== null,
|
|
4414
|
+
onChange: (event) => accel.editAccelUrl(event.target.value),
|
|
4415
|
+
onKeyDown: (event) => {
|
|
4416
|
+
if (event.key === "Enter") onSave();
|
|
4417
|
+
}
|
|
4418
|
+
}),
|
|
4419
|
+
state.urlError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4420
|
+
className: GitHistoryPanel_module_default.cnError,
|
|
4421
|
+
children: state.urlError === "empty" ? t("accel.urlEmpty") : t("accel.urlInvalid")
|
|
4422
|
+
}) : null,
|
|
4423
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4424
|
+
className: GitHistoryPanel_module_default.cnFooter,
|
|
4425
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4426
|
+
type: "button",
|
|
4427
|
+
className: GitHistoryPanel_module_default.cnGhost,
|
|
4428
|
+
onClick: onClose,
|
|
4429
|
+
children: t("cancel")
|
|
4430
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4431
|
+
type: "button",
|
|
4432
|
+
className: GitHistoryPanel_module_default.cnSave,
|
|
4433
|
+
disabled: state.saving || state.urlError !== null || !state.writable,
|
|
4434
|
+
onClick: onSave,
|
|
4435
|
+
children: t("cardSave")
|
|
4436
|
+
})]
|
|
4437
|
+
})
|
|
4438
|
+
]
|
|
4439
|
+
});
|
|
4440
|
+
}
|
|
4441
|
+
//#endregion
|
|
3968
4442
|
//#region src/client/panel/HistorySection.tsx
|
|
3969
4443
|
/**
|
|
3970
4444
|
* HistorySection: the panel's third block — the commit list. One row shows
|
|
@@ -4024,7 +4498,6 @@ window.__ModuleLoader__.load({
|
|
|
4024
4498
|
const badges = classifyRefs(commit.refs);
|
|
4025
4499
|
const when = new Date(commit.date);
|
|
4026
4500
|
const absolute = Number.isFinite(commit.date) && commit.date > 0 ? `${when.toLocaleDateString()} ${when.toLocaleTimeString()}` : "";
|
|
4027
|
-
const authorInitial = commit.authorName.slice(0, 1);
|
|
4028
4501
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4029
4502
|
ref,
|
|
4030
4503
|
className: [
|
|
@@ -4069,15 +4542,7 @@ window.__ModuleLoader__.load({
|
|
|
4069
4542
|
})]
|
|
4070
4543
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4071
4544
|
className: GitHistoryPanel_module_default.commitMeta,
|
|
4072
|
-
children: [
|
|
4073
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4074
|
-
className: GitHistoryPanel_module_default.authorDot,
|
|
4075
|
-
"aria-hidden": "true",
|
|
4076
|
-
children: authorInitial
|
|
4077
|
-
}),
|
|
4078
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: commit.authorName }),
|
|
4079
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: timeLabelFor(commit.date) })
|
|
4080
|
-
]
|
|
4545
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: commit.authorName }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: timeLabelFor(commit.date) })]
|
|
4081
4546
|
})]
|
|
4082
4547
|
}),
|
|
4083
4548
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -4122,7 +4587,7 @@ window.__ModuleLoader__.load({
|
|
|
4122
4587
|
const needle = query.trim().toLowerCase();
|
|
4123
4588
|
const visible = filterCommits(commits, query);
|
|
4124
4589
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4125
|
-
className: GitHistoryPanel_module_default.section
|
|
4590
|
+
className: `${GitHistoryPanel_module_default.section} ${GitHistoryPanel_module_default.sectionFill} ${GitHistoryPanel_module_default.sectionHistory}`,
|
|
4126
4591
|
"aria-label": t("panel.history"),
|
|
4127
4592
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4128
4593
|
className: GitHistoryPanel_module_default.historyHead,
|
|
@@ -4144,7 +4609,7 @@ window.__ModuleLoader__.load({
|
|
|
4144
4609
|
})]
|
|
4145
4610
|
})]
|
|
4146
4611
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4147
|
-
className: GitHistoryPanel_module_default.sectionBody
|
|
4612
|
+
className: `${GitHistoryPanel_module_default.sectionBody} ${GitHistoryPanel_module_default.sectionBodyScroll}`,
|
|
4148
4613
|
children: [loadError !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4149
4614
|
className: GitHistoryPanel_module_default.errorText,
|
|
4150
4615
|
children: loadError
|
|
@@ -4191,6 +4656,11 @@ window.__ModuleLoader__.load({
|
|
|
4191
4656
|
* the draft, and every action arrive as props from the panel state owner, so
|
|
4192
4657
|
* this file renders and never talks to git itself.
|
|
4193
4658
|
*
|
|
4659
|
+
* The card takes two shares of the panel's fixed 2:1:2 split: the file
|
|
4660
|
+
* lists scroll inside their own region while the commit box stays pinned
|
|
4661
|
+
* below — a 500-change tree must not bury the commit affordance, and a
|
|
4662
|
+
* clean tree must not float it up either.
|
|
4663
|
+
*
|
|
4194
4664
|
* The commit affordance is a split button: the main face commits, the caret
|
|
4195
4665
|
* opens the two op variants (commit; commit and push). The AI button fills
|
|
4196
4666
|
* the draft from the host's one-shot llm route — it renders only when the
|
|
@@ -4263,7 +4733,7 @@ window.__ModuleLoader__.load({
|
|
|
4263
4733
|
const hint = staged.length === 0 ? t("panel.commitNeedsStaged") : commitDraft.trim() === "" ? t("panel.commitNeedsMessage") : "";
|
|
4264
4734
|
const aiReady = aiAvailable && total > 0;
|
|
4265
4735
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4266
|
-
className: GitHistoryPanel_module_default.section
|
|
4736
|
+
className: `${GitHistoryPanel_module_default.section} ${GitHistoryPanel_module_default.sectionFill} ${GitHistoryPanel_module_default.sectionChanges}`,
|
|
4267
4737
|
"aria-label": t("panel.uncommitted"),
|
|
4268
4738
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4269
4739
|
className: GitHistoryPanel_module_default.sectionHead,
|
|
@@ -4308,129 +4778,131 @@ window.__ModuleLoader__.load({
|
|
|
4308
4778
|
]
|
|
4309
4779
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4310
4780
|
className: GitHistoryPanel_module_default.sectionBody,
|
|
4311
|
-
children: [
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
children: [
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4331
|
-
disabled: busy,
|
|
4332
|
-
onClick: onUnstageAll,
|
|
4333
|
-
children: t("panel.unstageAll")
|
|
4334
|
-
})
|
|
4335
|
-
]
|
|
4336
|
-
}), staged.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChangeRowView, {
|
|
4337
|
-
row,
|
|
4338
|
-
disabled: busy,
|
|
4339
|
-
onToggle: onToggleRow,
|
|
4340
|
-
t
|
|
4341
|
-
}, `${row.staged}:${row.path}:${row.oldPath ?? ""}`))] }) : null,
|
|
4342
|
-
unstaged.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4343
|
-
className: GitHistoryPanel_module_default.groupTitleRow,
|
|
4344
|
-
children: [
|
|
4345
|
-
t("panel.unstaged"),
|
|
4346
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4347
|
-
className: GitHistoryPanel_module_default.countBadge,
|
|
4348
|
-
children: String(unstaged.length)
|
|
4349
|
-
}),
|
|
4350
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4351
|
-
type: "button",
|
|
4352
|
-
className: GitHistoryPanel_module_default.linkBtn,
|
|
4353
|
-
disabled: busy,
|
|
4354
|
-
onClick: onStageAll,
|
|
4355
|
-
children: t("panel.stageAll")
|
|
4356
|
-
})
|
|
4357
|
-
]
|
|
4358
|
-
}), unstaged.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChangeRowView, {
|
|
4359
|
-
row,
|
|
4360
|
-
disabled: busy,
|
|
4361
|
-
onToggle: onToggleRow,
|
|
4362
|
-
t
|
|
4363
|
-
}, `u:${row.path}:${row.oldPath ?? ""}`))] }) : null,
|
|
4364
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4365
|
-
className: GitHistoryPanel_module_default.commitBox,
|
|
4366
|
-
children: [
|
|
4367
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
4368
|
-
className: GitHistoryPanel_module_default.commitInput,
|
|
4369
|
-
value: commitDraft,
|
|
4370
|
-
placeholder: t("panel.commitPlaceholder"),
|
|
4371
|
-
"aria-label": t("panel.commitPlaceholder"),
|
|
4372
|
-
rows: 2,
|
|
4373
|
-
maxLength: COMMIT_MESSAGE_LIMIT,
|
|
4374
|
-
onChange: (event) => onCommitDraft(event.target.value)
|
|
4375
|
-
}),
|
|
4376
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4377
|
-
className: GitHistoryPanel_module_default.commitActions,
|
|
4378
|
-
children: [aiAvailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4781
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4782
|
+
className: GitHistoryPanel_module_default.changeList,
|
|
4783
|
+
children: [
|
|
4784
|
+
total === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4785
|
+
className: GitHistoryPanel_module_default.empty,
|
|
4786
|
+
children: t("panel.clean")
|
|
4787
|
+
}) : null,
|
|
4788
|
+
truncated ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4789
|
+
className: GitHistoryPanel_module_default.empty,
|
|
4790
|
+
children: t("panel.changesTruncated")
|
|
4791
|
+
}) : null,
|
|
4792
|
+
staged.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4793
|
+
className: GitHistoryPanel_module_default.groupTitleRow,
|
|
4794
|
+
children: [
|
|
4795
|
+
t("panel.staged"),
|
|
4796
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4797
|
+
className: GitHistoryPanel_module_default.countBadge,
|
|
4798
|
+
children: String(staged.length)
|
|
4799
|
+
}),
|
|
4800
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4379
4801
|
type: "button",
|
|
4380
|
-
className: GitHistoryPanel_module_default.
|
|
4381
|
-
disabled: busy
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4802
|
+
className: GitHistoryPanel_module_default.linkBtn,
|
|
4803
|
+
disabled: busy,
|
|
4804
|
+
onClick: onUnstageAll,
|
|
4805
|
+
children: t("panel.unstageAll")
|
|
4806
|
+
})
|
|
4807
|
+
]
|
|
4808
|
+
}), staged.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChangeRowView, {
|
|
4809
|
+
row,
|
|
4810
|
+
disabled: busy,
|
|
4811
|
+
onToggle: onToggleRow,
|
|
4812
|
+
t
|
|
4813
|
+
}, `${row.staged}:${row.path}:${row.oldPath ?? ""}`))] }) : null,
|
|
4814
|
+
unstaged.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4815
|
+
className: GitHistoryPanel_module_default.groupTitleRow,
|
|
4816
|
+
children: [
|
|
4817
|
+
t("panel.unstaged"),
|
|
4818
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4819
|
+
className: GitHistoryPanel_module_default.countBadge,
|
|
4820
|
+
children: String(unstaged.length)
|
|
4821
|
+
}),
|
|
4822
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4823
|
+
type: "button",
|
|
4824
|
+
className: GitHistoryPanel_module_default.linkBtn,
|
|
4825
|
+
disabled: busy,
|
|
4826
|
+
onClick: onStageAll,
|
|
4827
|
+
children: t("panel.stageAll")
|
|
4828
|
+
})
|
|
4829
|
+
]
|
|
4830
|
+
}), unstaged.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChangeRowView, {
|
|
4831
|
+
row,
|
|
4832
|
+
disabled: busy,
|
|
4833
|
+
onToggle: onToggleRow,
|
|
4834
|
+
t
|
|
4835
|
+
}, `u:${row.path}:${row.oldPath ?? ""}`))] }) : null
|
|
4836
|
+
]
|
|
4837
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4838
|
+
className: GitHistoryPanel_module_default.commitBox,
|
|
4839
|
+
children: [
|
|
4840
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
4841
|
+
className: GitHistoryPanel_module_default.commitInput,
|
|
4842
|
+
value: commitDraft,
|
|
4843
|
+
placeholder: t("panel.commitPlaceholder"),
|
|
4844
|
+
"aria-label": t("panel.commitPlaceholder"),
|
|
4845
|
+
rows: 2,
|
|
4846
|
+
maxLength: COMMIT_MESSAGE_LIMIT,
|
|
4847
|
+
onChange: (event) => onCommitDraft(event.target.value)
|
|
4848
|
+
}),
|
|
4849
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4850
|
+
className: GitHistoryPanel_module_default.commitActions,
|
|
4851
|
+
children: [aiAvailable ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4852
|
+
type: "button",
|
|
4853
|
+
className: GitHistoryPanel_module_default.act,
|
|
4854
|
+
disabled: busy || aiBusy || !aiReady,
|
|
4855
|
+
title: !aiReady ? t("panel.aiNeedsChanges") : void 0,
|
|
4856
|
+
onClick: onAiGenerate,
|
|
4857
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSparkleRegular, { size: 13 }), aiBusy ? t("panel.aiBusy") : t("panel.aiGenerate")]
|
|
4858
|
+
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4859
|
+
className: GitHistoryPanel_module_default.split,
|
|
4860
|
+
ref: menuRef,
|
|
4861
|
+
children: [
|
|
4862
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4863
|
+
type: "button",
|
|
4864
|
+
className: `${GitHistoryPanel_module_default.act} ${GitHistoryPanel_module_default.actPrimary} ${GitHistoryPanel_module_default.splitMain}`,
|
|
4865
|
+
disabled: !canCommit || busy,
|
|
4866
|
+
onClick: () => onCommit(false),
|
|
4867
|
+
children: busy ? t("panel.commitBusy") : t("panel.commit")
|
|
4868
|
+
}),
|
|
4869
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4870
|
+
type: "button",
|
|
4871
|
+
className: `${GitHistoryPanel_module_default.act} ${GitHistoryPanel_module_default.actPrimary} ${GitHistoryPanel_module_default.splitCaret}`,
|
|
4872
|
+
"aria-label": t("panel.commitMoreAria"),
|
|
4873
|
+
"aria-expanded": commitMenuOpen,
|
|
4874
|
+
disabled: !canCommit || busy,
|
|
4875
|
+
onClick: onToggleCommitMenu,
|
|
4876
|
+
children: "▾"
|
|
4877
|
+
}),
|
|
4878
|
+
commitMenuOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4879
|
+
className: GitHistoryPanel_module_default.menu,
|
|
4880
|
+
role: "menu",
|
|
4881
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4390
4882
|
type: "button",
|
|
4391
|
-
|
|
4392
|
-
|
|
4883
|
+
role: "menuitem",
|
|
4884
|
+
className: GitHistoryPanel_module_default.menuItem,
|
|
4885
|
+
disabled: !canCommit,
|
|
4393
4886
|
onClick: () => onCommit(false),
|
|
4394
|
-
children:
|
|
4395
|
-
}),
|
|
4396
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4887
|
+
children: t("panel.commit")
|
|
4888
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4397
4889
|
type: "button",
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
children: t("panel.commit")
|
|
4415
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4416
|
-
type: "button",
|
|
4417
|
-
role: "menuitem",
|
|
4418
|
-
className: GitHistoryPanel_module_default.menuItem,
|
|
4419
|
-
disabled: !canCommit,
|
|
4420
|
-
onClick: () => onCommit(true),
|
|
4421
|
-
children: t("panel.commitPush")
|
|
4422
|
-
})]
|
|
4423
|
-
}) : null
|
|
4424
|
-
]
|
|
4425
|
-
})]
|
|
4426
|
-
}),
|
|
4427
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4428
|
-
className: GitHistoryPanel_module_default.commitHint,
|
|
4429
|
-
children: hint
|
|
4430
|
-
})
|
|
4431
|
-
]
|
|
4432
|
-
})
|
|
4433
|
-
]
|
|
4890
|
+
role: "menuitem",
|
|
4891
|
+
className: GitHistoryPanel_module_default.menuItem,
|
|
4892
|
+
disabled: !canCommit,
|
|
4893
|
+
onClick: () => onCommit(true),
|
|
4894
|
+
children: t("panel.commitPush")
|
|
4895
|
+
})]
|
|
4896
|
+
}) : null
|
|
4897
|
+
]
|
|
4898
|
+
})]
|
|
4899
|
+
}),
|
|
4900
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4901
|
+
className: GitHistoryPanel_module_default.commitHint,
|
|
4902
|
+
children: hint
|
|
4903
|
+
})
|
|
4904
|
+
]
|
|
4905
|
+
})]
|
|
4434
4906
|
})]
|
|
4435
4907
|
});
|
|
4436
4908
|
}
|
|
@@ -4507,7 +4979,7 @@ window.__ModuleLoader__.load({
|
|
|
4507
4979
|
/** Data owner for the three sections. Remounts when `cwd` changes (the page
|
|
4508
4980
|
* keys the mount by cwd), so no state crosses a repository boundary. */
|
|
4509
4981
|
const GitHistoryPanelData = (0, react.forwardRef)(function GitHistoryPanelData(props, ref) {
|
|
4510
|
-
const { cwd, model, t, pushToast } = props;
|
|
4982
|
+
const { cwd, model, t, pushToast, accelOn } = props;
|
|
4511
4983
|
const [status, setStatus] = (0, react.useState)(null);
|
|
4512
4984
|
const [statusError, setStatusError] = (0, react.useState)();
|
|
4513
4985
|
const [changes, setChanges] = (0, react.useState)([]);
|
|
@@ -4572,16 +5044,20 @@ window.__ModuleLoader__.load({
|
|
|
4572
5044
|
const refresh = (0, react.useCallback)(() => {
|
|
4573
5045
|
loadAll();
|
|
4574
5046
|
}, [loadAll]);
|
|
5047
|
+
(0, react.useEffect)(() => onGitMutated(refresh), [refresh]);
|
|
4575
5048
|
(0, react.useImperativeHandle)(ref, () => ({ refresh }), [refresh]);
|
|
4576
5049
|
const repo = status !== null && status.repo ? status : null;
|
|
4577
5050
|
/** Run one mutating verb with the section-busy guard and error toast.
|
|
4578
5051
|
* Mutations refresh through `loadAll` so their re-read bumps the request
|
|
4579
5052
|
* sequence — an older in-flight snapshot can never land over the fresh
|
|
4580
|
-
* post-mutation state.
|
|
5053
|
+
* post-mutation state. A SUCCESS also emits the cross-surface notice so
|
|
5054
|
+
* the composer chip drops the branch git just left (stage toggles ride
|
|
5055
|
+
* along — one extra idempotent /status beats per-verb wiring). */
|
|
4581
5056
|
const runGuarded = (0, react.useCallback)(async (verb) => {
|
|
4582
5057
|
setSectionBusy(true);
|
|
4583
5058
|
try {
|
|
4584
5059
|
await verb();
|
|
5060
|
+
emitGitMutated();
|
|
4585
5061
|
} catch (error) {
|
|
4586
5062
|
pushToast(t("errorGeneric", { message: failureText(error) }), "error");
|
|
4587
5063
|
} finally {
|
|
@@ -4697,13 +5173,23 @@ window.__ModuleLoader__.load({
|
|
|
4697
5173
|
pushToast,
|
|
4698
5174
|
t
|
|
4699
5175
|
]);
|
|
5176
|
+
/** Fetch/update failure toast text: the git failure line, plus the
|
|
5177
|
+
* mirror-unavailable hint while cn-accelerate is on (push is never
|
|
5178
|
+
* accelerated, so its failures stay hint-free). */
|
|
5179
|
+
const syncFailureText = (0, react.useCallback)((message) => {
|
|
5180
|
+
const generic = t("errorGeneric", { message });
|
|
5181
|
+
return accelOn() ? `${generic} ${t("accel.mirrorDownHint")}` : generic;
|
|
5182
|
+
}, [accelOn, t]);
|
|
4700
5183
|
const onFetch = (0, react.useCallback)(() => {
|
|
4701
5184
|
setSyncBusy(true);
|
|
4702
5185
|
(async () => {
|
|
4703
5186
|
try {
|
|
4704
5187
|
const result = await requestFetch(cwd);
|
|
4705
|
-
if (!result.ok) pushToast(
|
|
4706
|
-
else
|
|
5188
|
+
if (!result.ok) pushToast(syncFailureText(result.error), "error");
|
|
5189
|
+
else {
|
|
5190
|
+
pushToast(t("fetchDone"), "success");
|
|
5191
|
+
emitGitMutated();
|
|
5192
|
+
}
|
|
4707
5193
|
await loadAll();
|
|
4708
5194
|
} finally {
|
|
4709
5195
|
setSyncBusy(false);
|
|
@@ -4713,6 +5199,7 @@ window.__ModuleLoader__.load({
|
|
|
4713
5199
|
cwd,
|
|
4714
5200
|
loadAll,
|
|
4715
5201
|
pushToast,
|
|
5202
|
+
syncFailureText,
|
|
4716
5203
|
t
|
|
4717
5204
|
]);
|
|
4718
5205
|
const onUpdate = (0, react.useCallback)(() => {
|
|
@@ -4720,8 +5207,11 @@ window.__ModuleLoader__.load({
|
|
|
4720
5207
|
(async () => {
|
|
4721
5208
|
try {
|
|
4722
5209
|
const result = await requestUpdate(cwd);
|
|
4723
|
-
if (!result.ok) pushToast(
|
|
4724
|
-
else
|
|
5210
|
+
if (!result.ok) pushToast(syncFailureText(result.error), "error");
|
|
5211
|
+
else {
|
|
5212
|
+
pushToast(result.updated ? t("updateDone", { branch: result.branch }) : t("updateUpToDate"), "success");
|
|
5213
|
+
emitGitMutated();
|
|
5214
|
+
}
|
|
4725
5215
|
await loadAll();
|
|
4726
5216
|
} finally {
|
|
4727
5217
|
setSyncBusy(false);
|
|
@@ -4731,6 +5221,7 @@ window.__ModuleLoader__.load({
|
|
|
4731
5221
|
cwd,
|
|
4732
5222
|
loadAll,
|
|
4733
5223
|
pushToast,
|
|
5224
|
+
syncFailureText,
|
|
4734
5225
|
t
|
|
4735
5226
|
]);
|
|
4736
5227
|
const onPush = (0, react.useCallback)(() => {
|
|
@@ -4739,7 +5230,10 @@ window.__ModuleLoader__.load({
|
|
|
4739
5230
|
try {
|
|
4740
5231
|
const result = await requestPush(cwd);
|
|
4741
5232
|
if (!result.ok) pushToast(t("errorGeneric", { message: result.error }), "error");
|
|
4742
|
-
else
|
|
5233
|
+
else {
|
|
5234
|
+
pushToast(result.pushed ? t("pushDone", { branch: result.branch }) : t("pushUpToDate"), "success");
|
|
5235
|
+
emitGitMutated();
|
|
5236
|
+
}
|
|
4743
5237
|
await loadAll();
|
|
4744
5238
|
} finally {
|
|
4745
5239
|
setSyncBusy(false);
|
|
@@ -4936,7 +5430,7 @@ window.__ModuleLoader__.load({
|
|
|
4936
5430
|
/** The registered better-sidebar tab's content: chrome + data owner, keyed
|
|
4937
5431
|
* by cwd so a session switch starts every section from scratch. */
|
|
4938
5432
|
function GitPanelTab(props) {
|
|
4939
|
-
const { ctx, scope, t } = props;
|
|
5433
|
+
const { ctx, scope, t, accel } = props;
|
|
4940
5434
|
const subscribe = (0, react.useCallback)((listener) => ctx.sessions.list.subscribe(listener), [ctx]);
|
|
4941
5435
|
const cwd = (0, react.useSyncExternalStore)(subscribe, () => scope.cwd ?? ctx.sessions.list.getSnapshot().byId[scope.sessionId]?.cwd);
|
|
4942
5436
|
const model = (0, react.useSyncExternalStore)(subscribe, () => {
|
|
@@ -4955,6 +5449,13 @@ window.__ModuleLoader__.load({
|
|
|
4955
5449
|
tone
|
|
4956
5450
|
}]);
|
|
4957
5451
|
}, []);
|
|
5452
|
+
const accelState = (0, react.useSyncExternalStore)(accel.store.subscribe, accel.store.getSnapshot);
|
|
5453
|
+
const [accelOpen, setAccelOpen] = (0, react.useState)(false);
|
|
5454
|
+
const accelOn = (0, react.useCallback)(() => accel.store.getSnapshot().enabled, [accel]);
|
|
5455
|
+
const closeAccel = (0, react.useCallback)(() => {
|
|
5456
|
+
accel.discardAccel();
|
|
5457
|
+
setAccelOpen(false);
|
|
5458
|
+
}, [accel]);
|
|
4958
5459
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4959
5460
|
className: GitHistoryPanel_module_default.page,
|
|
4960
5461
|
children: [
|
|
@@ -4966,9 +5467,35 @@ window.__ModuleLoader__.load({
|
|
|
4966
5467
|
className: GitHistoryPanel_module_default.repoName,
|
|
4967
5468
|
children: cwd
|
|
4968
5469
|
})
|
|
4969
|
-
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.
|
|
5470
|
+
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4970
5471
|
className: GitHistoryPanel_module_default.topbarActions,
|
|
4971
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
5472
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5473
|
+
className: GitHistoryPanel_module_default.cnWrap,
|
|
5474
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5475
|
+
type: "button",
|
|
5476
|
+
className: accelState.enabled ? GitHistoryPanel_module_default.cnBtnOn : GitHistoryPanel_module_default.cnBtn,
|
|
5477
|
+
title: t("panel.cnAccelerate"),
|
|
5478
|
+
"aria-label": t("panel.cnAccelerate"),
|
|
5479
|
+
"aria-expanded": accelOpen,
|
|
5480
|
+
onClick: () => accelOpen ? closeAccel() : setAccelOpen(true),
|
|
5481
|
+
children: [
|
|
5482
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5483
|
+
"aria-hidden": "true",
|
|
5484
|
+
children: "⚡"
|
|
5485
|
+
}),
|
|
5486
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("panel.cnAccelerate") }),
|
|
5487
|
+
accelState.enabled ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5488
|
+
className: GitHistoryPanel_module_default.cnDot,
|
|
5489
|
+
"aria-hidden": "true"
|
|
5490
|
+
}) : null
|
|
5491
|
+
]
|
|
5492
|
+
}), accelOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CnAcceleratePopover, {
|
|
5493
|
+
accel,
|
|
5494
|
+
t,
|
|
5495
|
+
pushToast,
|
|
5496
|
+
onClose: closeAccel
|
|
5497
|
+
}) : null]
|
|
5498
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4972
5499
|
type: "button",
|
|
4973
5500
|
className: GitHistoryPanel_module_default.refreshBtn,
|
|
4974
5501
|
disabled: cwd === void 0,
|
|
@@ -4979,7 +5506,7 @@ window.__ModuleLoader__.load({
|
|
|
4979
5506
|
size: 14,
|
|
4980
5507
|
"aria-hidden": "true"
|
|
4981
5508
|
})
|
|
4982
|
-
})
|
|
5509
|
+
})]
|
|
4983
5510
|
})]
|
|
4984
5511
|
}),
|
|
4985
5512
|
cwd === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -4990,7 +5517,8 @@ window.__ModuleLoader__.load({
|
|
|
4990
5517
|
cwd,
|
|
4991
5518
|
model,
|
|
4992
5519
|
t,
|
|
4993
|
-
pushToast
|
|
5520
|
+
pushToast,
|
|
5521
|
+
accelOn
|
|
4994
5522
|
}, cwd),
|
|
4995
5523
|
toasts.map((toast) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
|
|
4996
5524
|
text: toast.text,
|
|
@@ -5598,7 +6126,7 @@ window.__ModuleLoader__.load({
|
|
|
5598
6126
|
}
|
|
5599
6127
|
//#endregion
|
|
5600
6128
|
//#region \0git-worktree-css:/home/runner/work/dsh-git-branch/dsh-git-branch/src/client/GitWorktreeCard.module.css?inline
|
|
5601
|
-
const css = "/* git-worktree bundle configuration on the Plugins page. The page owns the\n * chrome (title, icon, breadcrumb); this component renders either the\n * bundle-row summary line or the configuration form inside the page. Visual\n * language mirrors the settings section's own card chrome (layer fills,\n * footer buttons); tokens only, no literal colors. */\n\n/* The one-line preview on the bundle's row. */\n.summary_1281848784 {\n margin: 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* The configuration form inside the bundle's page. */\n.page_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.note_1281848784 {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.field_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.fieldLabel_1281848784 {\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* The read-only legacy storage root: text (not an input — the location is\n * historical and cannot be edited) plus its \"unused\" state on one row. */\n.rootRow_1281848784 {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n}\n\n.rootValue_1281848784 {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n overflow-wrap: anywhere;\n}\n\n.rootUnused_1281848784 {\n flex: none;\n font-size: 11px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 4px;\n padding: 0 5px;\n}\n\n.hint_1281848784 {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.footer_1281848784 {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 0 4px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.failed_1281848784 {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n\n.discard_1281848784,\n.save_1281848784 {\n appearance: none;\n border: 0.5px solid transparent;\n border-radius: 8px;\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n}\n\n.discard_1281848784 {\n border-color: var(--dsw-alias-border-l2);\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n\n.discard_1281848784:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n.save_1281848784 {\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n\n.discard_1281848784:disabled,\n.save_1281848784:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.discard_1281848784:focus-visible,\n.save_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* Sidebar-grouping switch: title + hint + caution beside a checkbox. */\n.toggleRow_1281848784 {\n margin-top: 10px;\n flex-direction: row;\n align-items: flex-start;\n gap: 10px;\n}\n\n.toggleText_1281848784 {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.toggleLabel_1281848784 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.toggleMark_1281848784 {\n margin-left: 4px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.toggleHint_1281848784 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.toggleControl_1281848784 {\n display: flex;\n align-items: center;\n gap: 6px;\n flex: none;\n margin-top: 2px;\n}\n\n.spinner_1281848784 {\n display: flex;\n color: var(--dsw-alias-label-tertiary);\n animation: spin 0.7s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n.toggle_1281848784 {\n width: 16px;\n height: 16px;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n.toggle_1281848784:disabled {\n cursor: progress;\n}\n\n/* Manager entry row: title + hint on the left (the toggle rows' text\n * column), the launcher button on the right — the same posture as the\n * grouping switch, minus the checkbox. (.field_1281848784 is columnar; the row\n * direction is restated here.) */\n.manageRow_1281848784 {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.manage_1281848784 {\n appearance: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: none;\n font: inherit;\n font-size: 13px;\n color: var(--dsw-alias-label-primary);\n padding: 6px 12px;\n cursor: pointer;\n}\n\n.manage_1281848784:hover {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.manage_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n/* Keep-cap row: the number input rides the toggle row's title column, and\n * stays disabled while the auto-prune switch is off (the cap means nothing\n * without the prune that enforces it). */\n.keepRow_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.keepControl_1281848784 {\n display: flex;\n justify-content: flex-start;\n}\n\n.keepInput_1281848784 {\n width: 96px;\n appearance: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-2);\n font: inherit;\n font-size: 13px;\n color: var(--dsw-alias-label-primary);\n padding: 6px 10px;\n}\n\n.keepInput_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.keepInput_1281848784:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n.keepBad_1281848784 {\n font-size: 12px;\n color: var(--dsw-alias-label-danger, #d64545);\n}\n\n.copyFilesRow_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.copyFilesInput_1281848784 {\n width: 100%;\n box-sizing: border-box;\n appearance: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-2);\n font: inherit;\n font-family: monospace;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n padding: 6px 10px;\n resize: vertical;\n min-height: 64px;\n}\n\n.copyFilesInput_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.copyFilesInput_1281848784:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n/* Write-through switches flip optimistically, so a rejected write shows up\n * as the control snapping back. This note sits in the switch's own text\n * column and says which one did not take. */\n.switchBad_1281848784 {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-danger, #d64545);\n}\n\n/* The auto-prune audit trail (清理记录): newest first, one run per line —\n * relative time, the removed directories with their belonging, then the\n * run's exceptions in the secondary tone. */\n.historyRow_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.history_1281848784 {\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.historyRun_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 4px 8px;\n border: 0.5px solid color-mix(in srgb, currentColor 12%, transparent);\n border-radius: 6px;\n}\n\n.historyTime_1281848784 {\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.historyLine_1281848784 {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n overflow-wrap: anywhere;\n}\n\n/* The fold toggle. A link, not a button chrome: it reveals rows in place,\n * it does not act on anything. */\n.historyMore_1281848784 {\n align-self: flex-start;\n padding: 0;\n border: none;\n background: none;\n font: inherit;\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-link, var(--dsw-alias-label-secondary));\n cursor: pointer;\n}\n\n.historyMore_1281848784:hover {\n text-decoration: underline;\n}\n";
|
|
6129
|
+
const css = "/* git-worktree bundle configuration on the Plugins page. The page owns the\n * chrome (title, icon, breadcrumb); this component renders either the\n * bundle-row summary line or the configuration form inside the page. Visual\n * language mirrors the settings section's own card chrome (layer fills,\n * footer buttons); tokens only, no literal colors. */\n\n/* The one-line preview on the bundle's row. */\n.summary_1281848784 {\n margin: 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n/* The configuration form inside the bundle's page. */\n.page_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.note_1281848784 {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.field_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.fieldLabel_1281848784 {\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* The read-only legacy storage root: text (not an input — the location is\n * historical and cannot be edited) plus its \"unused\" state on one row. */\n.rootRow_1281848784 {\n display: flex;\n align-items: baseline;\n gap: 8px;\n min-width: 0;\n}\n\n.rootValue_1281848784 {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n overflow-wrap: anywhere;\n}\n\n.rootUnused_1281848784 {\n flex: none;\n font-size: 11px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 4px;\n padding: 0 5px;\n}\n\n.hint_1281848784 {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.footer_1281848784 {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 8px;\n padding: 8px 0 4px;\n border-top: 0.5px solid var(--dsw-alias-border-l2);\n}\n\n.failed_1281848784 {\n flex: 1;\n min-width: 0;\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-error);\n}\n\n.discard_1281848784,\n.save_1281848784 {\n appearance: none;\n border: 0.5px solid transparent;\n border-radius: 8px;\n padding: 5px 14px;\n font: inherit;\n font-size: 13px;\n line-height: 1.5;\n cursor: pointer;\n}\n\n.discard_1281848784 {\n border-color: var(--dsw-alias-border-l2);\n background: none;\n color: var(--dsw-alias-label-secondary);\n}\n\n.discard_1281848784:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n.save_1281848784 {\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n}\n\n.discard_1281848784:disabled,\n.save_1281848784:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.discard_1281848784:focus-visible,\n.save_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* Sidebar-grouping switch: title + hint + caution beside a checkbox. */\n.toggleRow_1281848784 {\n margin-top: 10px;\n flex-direction: row;\n align-items: flex-start;\n gap: 10px;\n}\n\n.toggleText_1281848784 {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n\n.toggleLabel_1281848784 {\n color: var(--dsw-alias-label-primary);\n font-weight: 500;\n}\n\n.toggleMark_1281848784 {\n margin-left: 4px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n.toggleHint_1281848784 {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.toggleControl_1281848784 {\n display: flex;\n align-items: center;\n gap: 6px;\n flex: none;\n margin-top: 2px;\n}\n\n.spinner_1281848784 {\n display: flex;\n color: var(--dsw-alias-label-tertiary);\n animation: spin 0.7s linear infinite;\n}\n\n@keyframes spin {\n to { transform: rotate(360deg); }\n}\n\n.toggle_1281848784 {\n width: 16px;\n height: 16px;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n.toggle_1281848784:disabled {\n cursor: progress;\n}\n\n/* Manager entry row: title + hint on the left (the toggle rows' text\n * column), the launcher button on the right — the same posture as the\n * grouping switch, minus the checkbox. (.field_1281848784 is columnar; the row\n * direction is restated here.) */\n.manageRow_1281848784 {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n\n.manage_1281848784 {\n appearance: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: none;\n font: inherit;\n font-size: 13px;\n color: var(--dsw-alias-label-primary);\n padding: 6px 12px;\n cursor: pointer;\n}\n\n.manage_1281848784:hover {\n border-color: var(--dsw-alias-brand-primary);\n}\n\n.manage_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n/* Keep-cap row: the number input rides the toggle row's title column, and\n * stays disabled while the auto-prune switch is off (the cap means nothing\n * without the prune that enforces it). */\n.keepRow_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.keepControl_1281848784 {\n display: flex;\n justify-content: flex-start;\n}\n\n.keepInput_1281848784 {\n width: 96px;\n appearance: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-2);\n font: inherit;\n font-size: 13px;\n color: var(--dsw-alias-label-primary);\n padding: 6px 10px;\n}\n\n.keepInput_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.keepInput_1281848784:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n.keepBad_1281848784 {\n font-size: 12px;\n color: var(--dsw-alias-label-danger, #d64545);\n}\n\n.copyFilesRow_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.copyFilesInput_1281848784 {\n width: 100%;\n box-sizing: border-box;\n appearance: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-2);\n font: inherit;\n font-family: monospace;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n padding: 6px 10px;\n resize: vertical;\n min-height: 64px;\n}\n\n.copyFilesInput_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.copyFilesInput_1281848784:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n/* Cn-accelerate URL row: a single-line URL text field (the keep row's input\n * posture at full width). The invalid-draft line reuses .keepBad_1281848784. */\n.accelInput_1281848784 {\n width: 100%;\n box-sizing: border-box;\n appearance: none;\n border: 0.5px solid var(--dsw-alias-border-l4);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-2);\n font: inherit;\n font-family: monospace;\n font-size: 12px;\n color: var(--dsw-alias-label-primary);\n padding: 6px 10px;\n}\n\n.accelInput_1281848784:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n.accelInput_1281848784:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n\n/* Write-through switches flip optimistically, so a rejected write shows up\n * as the control snapping back. This note sits in the switch's own text\n * column and says which one did not take. */\n.switchBad_1281848784 {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-danger, #d64545);\n}\n\n/* The auto-prune audit trail (清理记录): newest first, one run per line —\n * relative time, the removed directories with their belonging, then the\n * run's exceptions in the secondary tone. */\n.historyRow_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.history_1281848784 {\n margin: 0;\n padding: 0;\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.historyRun_1281848784 {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 4px 8px;\n border: 0.5px solid color-mix(in srgb, currentColor 12%, transparent);\n border-radius: 6px;\n}\n\n.historyTime_1281848784 {\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n.historyLine_1281848784 {\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-secondary);\n overflow-wrap: anywhere;\n}\n\n/* The fold toggle. A link, not a button chrome: it reveals rows in place,\n * it does not act on anything. */\n.historyMore_1281848784 {\n align-self: flex-start;\n padding: 0;\n border: none;\n background: none;\n font: inherit;\n font-size: 12px;\n line-height: 16px;\n color: var(--dsw-alias-label-link, var(--dsw-alias-label-secondary));\n cursor: pointer;\n}\n\n.historyMore_1281848784:hover {\n text-decoration: underline;\n}\n";
|
|
5602
6130
|
const tagId = "dsh-git-branch-manage/GitWorktreeCard.module.css";
|
|
5603
6131
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + tagId + "\"]") === null) {
|
|
5604
6132
|
const tag = document.createElement("style");
|
|
@@ -5637,6 +6165,7 @@ window.__ModuleLoader__.load({
|
|
|
5637
6165
|
"keepBad": "keepBad_1281848784",
|
|
5638
6166
|
"copyFilesRow": "copyFilesRow_1281848784",
|
|
5639
6167
|
"copyFilesInput": "copyFilesInput_1281848784",
|
|
6168
|
+
"accelInput": "accelInput_1281848784",
|
|
5640
6169
|
"switchBad": "switchBad_1281848784",
|
|
5641
6170
|
"historyRow": "historyRow_1281848784",
|
|
5642
6171
|
"history": "history_1281848784",
|
|
@@ -5713,13 +6242,14 @@ window.__ModuleLoader__.load({
|
|
|
5713
6242
|
const shownHistory = historyAll ? history : history.slice(0, HISTORY_PREVIEW);
|
|
5714
6243
|
const { t } = props;
|
|
5715
6244
|
const state = props.useGitWorktreeCard((snapshot) => snapshot);
|
|
6245
|
+
const accelState = props.useGitWorktreeAccel((snapshot) => snapshot);
|
|
5716
6246
|
if (!state.available) return null;
|
|
5717
6247
|
if (!onPage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5718
6248
|
className: GitWorktreeCard_module_default.summary,
|
|
5719
6249
|
children: t("cardDescription")
|
|
5720
6250
|
});
|
|
5721
6251
|
const lockInput = !state.writable;
|
|
5722
|
-
const lockActions = !state.dirty || state.saving || !state.keepWorktreesValid;
|
|
6252
|
+
const lockActions = !state.dirty && !accelState.dirty || state.saving || accelState.saving || !state.keepWorktreesValid || accelState.urlError !== null;
|
|
5723
6253
|
const legacyRootText = storage?.legacyRoot ?? (state.rootDir === "" ? "—" : state.rootDir);
|
|
5724
6254
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5725
6255
|
className: GitWorktreeCard_module_default.page,
|
|
@@ -5893,6 +6423,56 @@ window.__ModuleLoader__.load({
|
|
|
5893
6423
|
})
|
|
5894
6424
|
]
|
|
5895
6425
|
}),
|
|
6426
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
6427
|
+
className: `${GitWorktreeCard_module_default.field} ${GitWorktreeCard_module_default.toggleRow}`,
|
|
6428
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6429
|
+
className: GitWorktreeCard_module_default.toggleText,
|
|
6430
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6431
|
+
className: GitWorktreeCard_module_default.toggleLabel,
|
|
6432
|
+
children: t("panel.cnAccelerate")
|
|
6433
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6434
|
+
className: GitWorktreeCard_module_default.toggleHint,
|
|
6435
|
+
children: t("accel.hint")
|
|
6436
|
+
})]
|
|
6437
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6438
|
+
className: GitWorktreeCard_module_default.toggleControl,
|
|
6439
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6440
|
+
className: GitWorktreeCard_module_default.toggle,
|
|
6441
|
+
type: "checkbox",
|
|
6442
|
+
disabled: lockInput || accelState.saving,
|
|
6443
|
+
checked: accelState.enabled,
|
|
6444
|
+
onChange: (event) => {
|
|
6445
|
+
props.setAccelEnabled(event.target.checked);
|
|
6446
|
+
}
|
|
6447
|
+
})
|
|
6448
|
+
})]
|
|
6449
|
+
}),
|
|
6450
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
6451
|
+
className: `${GitWorktreeCard_module_default.field} ${GitWorktreeCard_module_default.copyFilesRow}`,
|
|
6452
|
+
htmlFor: "git-worktree-card-accel-url",
|
|
6453
|
+
children: [
|
|
6454
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6455
|
+
className: GitWorktreeCard_module_default.fieldLabel,
|
|
6456
|
+
children: t("accel.urlLabel")
|
|
6457
|
+
}),
|
|
6458
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6459
|
+
id: "git-worktree-card-accel-url",
|
|
6460
|
+
className: GitWorktreeCard_module_default.accelInput,
|
|
6461
|
+
type: "text",
|
|
6462
|
+
spellCheck: false,
|
|
6463
|
+
disabled: lockInput || accelState.saving,
|
|
6464
|
+
value: accelState.urlText,
|
|
6465
|
+
onChange: (event) => {
|
|
6466
|
+
props.editAccelUrl(event.target.value);
|
|
6467
|
+
}
|
|
6468
|
+
}),
|
|
6469
|
+
accelState.urlError !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6470
|
+
className: GitWorktreeCard_module_default.keepBad,
|
|
6471
|
+
role: "alert",
|
|
6472
|
+
children: accelState.urlError === "empty" ? t("accel.urlEmpty") : t("accel.urlInvalid")
|
|
6473
|
+
}) : null
|
|
6474
|
+
]
|
|
6475
|
+
}),
|
|
5896
6476
|
history.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5897
6477
|
className: `${GitWorktreeCard_module_default.field} ${GitWorktreeCard_module_default.historyRow}`,
|
|
5898
6478
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -5959,19 +6539,30 @@ window.__ModuleLoader__.load({
|
|
|
5959
6539
|
role: "status",
|
|
5960
6540
|
children: t("cardSaveFailed")
|
|
5961
6541
|
}) : null,
|
|
6542
|
+
accelState.failed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6543
|
+
className: GitWorktreeCard_module_default.failed,
|
|
6544
|
+
role: "status",
|
|
6545
|
+
children: t("accel.saveFailed")
|
|
6546
|
+
}) : null,
|
|
5962
6547
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5963
6548
|
type: "button",
|
|
5964
6549
|
className: GitWorktreeCard_module_default.discard,
|
|
5965
6550
|
disabled: lockActions,
|
|
5966
|
-
onClick:
|
|
6551
|
+
onClick: () => {
|
|
6552
|
+
props.discard();
|
|
6553
|
+
props.discardAccel();
|
|
6554
|
+
},
|
|
5967
6555
|
children: t("cardDiscard")
|
|
5968
6556
|
}),
|
|
5969
6557
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5970
6558
|
type: "button",
|
|
5971
6559
|
className: GitWorktreeCard_module_default.save,
|
|
5972
6560
|
disabled: lockActions,
|
|
5973
|
-
onClick:
|
|
5974
|
-
|
|
6561
|
+
onClick: () => {
|
|
6562
|
+
props.save();
|
|
6563
|
+
props.saveAccel();
|
|
6564
|
+
},
|
|
6565
|
+
children: t(state.saving || accelState.saving ? "cardSaving" : "cardSave")
|
|
5975
6566
|
})
|
|
5976
6567
|
]
|
|
5977
6568
|
})
|
|
@@ -6168,7 +6759,18 @@ window.__ModuleLoader__.load({
|
|
|
6168
6759
|
"panel.stCopy": "copied",
|
|
6169
6760
|
"panel.stType": "type changed",
|
|
6170
6761
|
"panel.stUntrack": "untracked",
|
|
6171
|
-
"panel.stUnmerged": "conflict"
|
|
6762
|
+
"panel.stUnmerged": "conflict",
|
|
6763
|
+
"panel.cnAccelerate": "China acceleration",
|
|
6764
|
+
"accel.enable": "Enable acceleration",
|
|
6765
|
+
"accel.hint": "Accelerates https github.com remotes for fetch/update only; push is never proxied. The mirror sees repository content — do not use it for private or sensitive repositories.",
|
|
6766
|
+
"accel.urlLabel": "Acceleration URL",
|
|
6767
|
+
"accel.restoreDefault": "Restore default",
|
|
6768
|
+
"accel.urlInvalid": "Enter an http(s):// URL",
|
|
6769
|
+
"accel.urlEmpty": "Enter an acceleration URL",
|
|
6770
|
+
"accel.saveFailed": "The change did not save. Try again.",
|
|
6771
|
+
"accel.savedOn": "China acceleration enabled: {url}",
|
|
6772
|
+
"accel.savedOff": "China acceleration disabled",
|
|
6773
|
+
"accel.mirrorDownHint": "If the mirror is down, disable acceleration or change the URL"
|
|
6172
6774
|
};
|
|
6173
6775
|
/** 中文词典。 */
|
|
6174
6776
|
const zh = {
|
|
@@ -6358,7 +6960,18 @@ window.__ModuleLoader__.load({
|
|
|
6358
6960
|
"panel.stCopy": "复制",
|
|
6359
6961
|
"panel.stType": "类型变更",
|
|
6360
6962
|
"panel.stUntrack": "未跟踪",
|
|
6361
|
-
"panel.stUnmerged": "冲突"
|
|
6963
|
+
"panel.stUnmerged": "冲突",
|
|
6964
|
+
"panel.cnAccelerate": "国内加速",
|
|
6965
|
+
"accel.enable": "启用加速",
|
|
6966
|
+
"accel.hint": "仅加速 https 的 github.com 仓库地址,作用于提取/更新;推送不走加速。第三方加速站可看到仓库内容,请勿用于私有/敏感仓库。",
|
|
6967
|
+
"accel.urlLabel": "加速地址",
|
|
6968
|
+
"accel.restoreDefault": "恢复默认",
|
|
6969
|
+
"accel.urlInvalid": "请输入以 http(s):// 开头的地址",
|
|
6970
|
+
"accel.urlEmpty": "请输入加速地址",
|
|
6971
|
+
"accel.saveFailed": "保存未生效,请重试。",
|
|
6972
|
+
"accel.savedOn": "已启用国内加速:{url}",
|
|
6973
|
+
"accel.savedOff": "已关闭国内加速",
|
|
6974
|
+
"accel.mirrorDownHint": "若加速地址不可用,可停用国内加速或更换地址"
|
|
6362
6975
|
};
|
|
6363
6976
|
//#endregion
|
|
6364
6977
|
//#region src/client/index.ts
|
|
@@ -6609,6 +7222,11 @@ window.__ModuleLoader__.load({
|
|
|
6609
7222
|
});
|
|
6610
7223
|
const form = new CardForm(settingsForm);
|
|
6611
7224
|
const store = form.bind();
|
|
7225
|
+
const accelForm = new AccelForm(settingsForm);
|
|
7226
|
+
const accelFace = {
|
|
7227
|
+
store: accelForm.bind(),
|
|
7228
|
+
...accelForm.actions()
|
|
7229
|
+
};
|
|
6612
7230
|
const describeFace = ctx.configForms.describe();
|
|
6613
7231
|
let configDisposer;
|
|
6614
7232
|
const syncCardSeat = () => {
|
|
@@ -6619,8 +7237,12 @@ window.__ModuleLoader__.load({
|
|
|
6619
7237
|
key: PLUGIN_PACKAGE,
|
|
6620
7238
|
locale: NS,
|
|
6621
7239
|
inject: () => ({
|
|
6622
|
-
hooks: {
|
|
7240
|
+
hooks: {
|
|
7241
|
+
gitWorktreeCard: store,
|
|
7242
|
+
gitWorktreeAccel: accelFace.store
|
|
7243
|
+
},
|
|
6623
7244
|
...form.actions(),
|
|
7245
|
+
...accelForm.actions(),
|
|
6624
7246
|
manager: managerFace()
|
|
6625
7247
|
})
|
|
6626
7248
|
}, GitWorktreeCard));
|
|
@@ -6652,7 +7274,8 @@ window.__ModuleLoader__.load({
|
|
|
6652
7274
|
component: (tabProps) => (0, react.createElement)(GitPanelTab, {
|
|
6653
7275
|
ctx: betterCtx,
|
|
6654
7276
|
scope: tabProps.scope,
|
|
6655
|
-
t: panelT
|
|
7277
|
+
t: panelT,
|
|
7278
|
+
accel: accelFace
|
|
6656
7279
|
})
|
|
6657
7280
|
}), "git-worktree: better-sidebar tab");
|
|
6658
7281
|
});
|