@kud/gh-ink 0.73.0 → 0.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +49 -0
- package/dist/index.js +153 -118
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -526,6 +526,27 @@ declare const writeCache: (key: string, data: {
|
|
|
526
526
|
sidebar?: Rails;
|
|
527
527
|
}) => void;
|
|
528
528
|
|
|
529
|
+
/**
|
|
530
|
+
* What an action did to a row, said before the server has agreed to it.
|
|
531
|
+
*
|
|
532
|
+
* Three shapes cover every action the inbox takes on a row: it leaves the list
|
|
533
|
+
* (close, done), it changes tab (a Jira move), or it changes in place (labels,
|
|
534
|
+
* assignee, read). A patch names the END STATE rather than the step that gets
|
|
535
|
+
* there, which is what lets it be reapplied on top of every fetch: "SHOP-1234
|
|
536
|
+
* belongs in review, wearing In Review" is as true on the third fetch as on the
|
|
537
|
+
* first, where "move it one tab right" would walk it off the board.
|
|
538
|
+
*/
|
|
539
|
+
type Patch = {
|
|
540
|
+
kind: "remove";
|
|
541
|
+
} | {
|
|
542
|
+
kind: "move";
|
|
543
|
+
toSection: string;
|
|
544
|
+
fields?: Record<string, unknown>;
|
|
545
|
+
} | {
|
|
546
|
+
kind: "mutate";
|
|
547
|
+
fields: Record<string, unknown>;
|
|
548
|
+
};
|
|
549
|
+
|
|
529
550
|
type DetailContext = {
|
|
530
551
|
item: GHItem;
|
|
531
552
|
kind: "pr" | "issue";
|
|
@@ -629,6 +650,25 @@ type TabForStatus = (to: {
|
|
|
629
650
|
name: string;
|
|
630
651
|
category?: string;
|
|
631
652
|
}) => string | null;
|
|
653
|
+
/**
|
|
654
|
+
* What a move hands back when the screen took it optimistically: the request's
|
|
655
|
+
* two possible answers, reported so the pending patch can stop showing `◌` or
|
|
656
|
+
* be marked failed. Absent when the move was not taken optimistically, and the
|
|
657
|
+
* caller falls back to its own flashes.
|
|
658
|
+
*/
|
|
659
|
+
type OptimisticHandle = {
|
|
660
|
+
settled: () => void;
|
|
661
|
+
failed: (err: unknown) => void;
|
|
662
|
+
};
|
|
663
|
+
/**
|
|
664
|
+
* A row action said ahead of the server: the end state it leaves the row in,
|
|
665
|
+
* and the verb the failure line names it by — `close` reads back as
|
|
666
|
+
* "Couldn't close #412".
|
|
667
|
+
*/
|
|
668
|
+
type OptimisticChange = {
|
|
669
|
+
patch: Patch;
|
|
670
|
+
action: string;
|
|
671
|
+
};
|
|
632
672
|
/**
|
|
633
673
|
* Resolve the live transitions for a ticket, called lazily when its move
|
|
634
674
|
* submenu opens — never at board fetch, where one call per visible ticket
|
|
@@ -766,6 +806,15 @@ declare const buildActions: (item: AnyItem, login: string, showFlash: (msg: stri
|
|
|
766
806
|
* the settlement signal.
|
|
767
807
|
*/
|
|
768
808
|
onSettled?: (item: GHItem, result: SettledResult) => void;
|
|
809
|
+
/**
|
|
810
|
+
* Take the row's action ahead of the server — see `OptimisticChange`. A
|
|
811
|
+
* handle back means the row is already where the action puts it, so the
|
|
812
|
+
* request's answer goes to the handle and a failure goes ONLY there: the
|
|
813
|
+
* failed patch has its own sticky line with `w` beside it, and a flash
|
|
814
|
+
* naming the same failure would be a second voice saying it less well.
|
|
815
|
+
* Absent, every action keeps the pessimistic shape it had.
|
|
816
|
+
*/
|
|
817
|
+
optimistic?: (item: AnyItem, change: OptimisticChange) => OptimisticHandle | undefined;
|
|
769
818
|
/**
|
|
770
819
|
* Open the ticket's move submenu through the live-transitions hook. Passed
|
|
771
820
|
* by the browse screen (which owns the menu the rows open into) only when
|
package/dist/index.js
CHANGED
|
@@ -1054,9 +1054,9 @@ var PrRow = ({
|
|
|
1054
1054
|
justifyContent: "flex-end",
|
|
1055
1055
|
flexShrink: 0,
|
|
1056
1056
|
children: sizeParts ? /* @__PURE__ */ jsxs(Text3, { children: [
|
|
1057
|
-
/* @__PURE__ */ jsx(Text3, { color: colors.
|
|
1057
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.added, children: sizeParts.added }),
|
|
1058
1058
|
" ",
|
|
1059
|
-
/* @__PURE__ */ jsx(Text3, { color: colors.
|
|
1059
|
+
/* @__PURE__ */ jsx(Text3, { color: colors.removed, children: sizeParts.removed })
|
|
1060
1060
|
] }) : null
|
|
1061
1061
|
}
|
|
1062
1062
|
) : null,
|
|
@@ -1335,20 +1335,12 @@ var lookupRows = (claim, lookup, query, start, openUrl) => {
|
|
|
1335
1335
|
if (lookup?.phase === "failed")
|
|
1336
1336
|
return {
|
|
1337
1337
|
exclusive: true,
|
|
1338
|
-
rows: [
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
claim.label,
|
|
1345
|
-
" \xB7 ",
|
|
1346
|
-
lookup.message
|
|
1347
|
-
] }),
|
|
1348
|
-
run: () => start(query, claim),
|
|
1349
|
-
keepOpen: true
|
|
1350
|
-
}
|
|
1351
|
-
]
|
|
1338
|
+
rows: [],
|
|
1339
|
+
message: {
|
|
1340
|
+
text: `couldn't look up ${claim.label} \xB7 ${lookup.message} \xB7 \u21B5 retry`,
|
|
1341
|
+
tone: "error",
|
|
1342
|
+
onSubmit: () => start(query, claim)
|
|
1343
|
+
}
|
|
1352
1344
|
};
|
|
1353
1345
|
const rows = [
|
|
1354
1346
|
{
|
|
@@ -1696,6 +1688,7 @@ var failureNotice = (failed) => {
|
|
|
1696
1688
|
};
|
|
1697
1689
|
var quietly = $({ quiet: true });
|
|
1698
1690
|
var isMenuGap = (row) => "gap" in row;
|
|
1691
|
+
var rowLabelOf = (item) => item.kind === "task" ? item.ticket ?? item.key : item.kind === "pr" || item.kind === "issue" ? `#${item.number}` : "";
|
|
1699
1692
|
var jiraMovesCache = /* @__PURE__ */ new Map();
|
|
1700
1693
|
var cachedJiraMoves = (ticket, status) => {
|
|
1701
1694
|
const entry = jiraMovesCache.get(ticket);
|
|
@@ -2297,6 +2290,19 @@ var workCount = (s) => {
|
|
|
2297
2290
|
}
|
|
2298
2291
|
return n;
|
|
2299
2292
|
};
|
|
2293
|
+
var countedSections = (sections, departing) => {
|
|
2294
|
+
if (!departing?.size) return sections;
|
|
2295
|
+
const sent = new Set(sections.map((s) => s.id));
|
|
2296
|
+
return sections.map((s) => {
|
|
2297
|
+
const items = s.items.filter((item) => {
|
|
2298
|
+
const key = keyOf(item);
|
|
2299
|
+
if (!key || !departing.has(key)) return true;
|
|
2300
|
+
const to = departing.get(key);
|
|
2301
|
+
return to != null && (to === s.id || !sent.has(to));
|
|
2302
|
+
});
|
|
2303
|
+
return items.length === s.items.length ? s : { ...s, items };
|
|
2304
|
+
});
|
|
2305
|
+
};
|
|
2300
2306
|
var drillCmd = (item) => {
|
|
2301
2307
|
if (item.kind === "task")
|
|
2302
2308
|
return item.ticket ? `jira issue view ${item.ticket}` : null;
|
|
@@ -2360,6 +2366,7 @@ var openInJira = (jiraBase, key, showFlash) => {
|
|
|
2360
2366
|
});
|
|
2361
2367
|
showFlash(`\u2197 Opened ${key} in Jira`);
|
|
2362
2368
|
};
|
|
2369
|
+
var REMOVE_ME_AS_REVIEWER = "Remove me as reviewer";
|
|
2363
2370
|
var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions, onRefresh, onRemove, onOpenView, ext) => {
|
|
2364
2371
|
if (item.kind === "repo-header" || item.kind === "subgroup-header" || item.kind === "show-more" || item.kind === "show-less")
|
|
2365
2372
|
return [];
|
|
@@ -2464,6 +2471,32 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
2464
2471
|
}
|
|
2465
2472
|
const actions = drillAction ? [drillAction, open, copyUrl] : [open, copyUrl];
|
|
2466
2473
|
const closing = [];
|
|
2474
|
+
const removeAhead = (opts) => {
|
|
2475
|
+
const row = item;
|
|
2476
|
+
const held = ext?.optimistic?.(row, {
|
|
2477
|
+
patch: { kind: "remove" },
|
|
2478
|
+
action: opts.action
|
|
2479
|
+
});
|
|
2480
|
+
onRemove?.(row);
|
|
2481
|
+
showFlash(opts.taking);
|
|
2482
|
+
void opts.request().then(
|
|
2483
|
+
() => {
|
|
2484
|
+
held?.settled();
|
|
2485
|
+
if (opts.done) showFlash(opts.done);
|
|
2486
|
+
if (held || opts.refreshes) ext?.onActed?.();
|
|
2487
|
+
if (opts.settles) ext?.onSettled?.(row, { ok: true });
|
|
2488
|
+
},
|
|
2489
|
+
(e) => {
|
|
2490
|
+
if (held) held.failed(e);
|
|
2491
|
+
else {
|
|
2492
|
+
showFlash(opts.refused(e));
|
|
2493
|
+
onRefresh?.();
|
|
2494
|
+
}
|
|
2495
|
+
if (opts.settles)
|
|
2496
|
+
ext?.onSettled?.(row, { ok: false, reason: firstLine(e) });
|
|
2497
|
+
}
|
|
2498
|
+
);
|
|
2499
|
+
};
|
|
2467
2500
|
actions.push({
|
|
2468
2501
|
label: "Copy repo name",
|
|
2469
2502
|
hint: "r",
|
|
@@ -2486,7 +2519,7 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
2486
2519
|
});
|
|
2487
2520
|
if (item.kind === "pr" && item.standing === "queued" && login) {
|
|
2488
2521
|
actions.push({
|
|
2489
|
-
label:
|
|
2522
|
+
label: REMOVE_ME_AS_REVIEWER,
|
|
2490
2523
|
hint: "x",
|
|
2491
2524
|
// Quiet, beside Unsubscribe: both are "less of this PR for me" — no more
|
|
2492
2525
|
// review requests, no more notifications. Guarded by the caller's own
|
|
@@ -2494,25 +2527,17 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
2494
2527
|
// review request there is no such row, and none is invented here.
|
|
2495
2528
|
group: "quiet",
|
|
2496
2529
|
icon: "\uF468",
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
onRefresh?.();
|
|
2509
|
-
ext?.onSettled?.(item, {
|
|
2510
|
-
ok: false,
|
|
2511
|
-
reason: firstLine(e)
|
|
2512
|
-
});
|
|
2513
|
-
}
|
|
2514
|
-
);
|
|
2515
|
-
}
|
|
2530
|
+
// Optimistic, the same shape Close uses. A row that lingers for a round
|
|
2531
|
+
// trip reads as a broken keypress.
|
|
2532
|
+
run: () => removeAhead({
|
|
2533
|
+
action: "remove you from",
|
|
2534
|
+
request: () => quietly`gh pr edit ${item.number} --repo ${item.repo} --remove-reviewer ${login}`,
|
|
2535
|
+
taking: `\u22EF Removing you from #${item.number}\u2026`,
|
|
2536
|
+
done: `\u2713 Removed you as reviewer on #${item.number}`,
|
|
2537
|
+
refused: (e) => `\u2717 #${item.number}: ${explainGhAction(e)}`,
|
|
2538
|
+
settles: true,
|
|
2539
|
+
refreshes: true
|
|
2540
|
+
})
|
|
2516
2541
|
});
|
|
2517
2542
|
}
|
|
2518
2543
|
if (item.kind === "pr" && item.branch) {
|
|
@@ -2584,23 +2609,13 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
2584
2609
|
label: `Close #${item.number}`,
|
|
2585
2610
|
hint: "",
|
|
2586
2611
|
group: "confirm",
|
|
2587
|
-
run: () => {
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
(e) => {
|
|
2595
|
-
showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
|
|
2596
|
-
onRefresh?.();
|
|
2597
|
-
ext?.onSettled?.(item, {
|
|
2598
|
-
ok: false,
|
|
2599
|
-
reason: firstLine(e)
|
|
2600
|
-
});
|
|
2601
|
-
}
|
|
2602
|
-
);
|
|
2603
|
-
}
|
|
2612
|
+
run: () => removeAhead({
|
|
2613
|
+
action: "close",
|
|
2614
|
+
request: () => quietly`gh issue close ${item.number} --repo ${item.repo}`,
|
|
2615
|
+
taking: `\u2713 Closed #${item.number}`,
|
|
2616
|
+
refused: () => `\u2717 Close failed \u2014 restoring #${item.number}`,
|
|
2617
|
+
settles: true
|
|
2618
|
+
})
|
|
2604
2619
|
},
|
|
2605
2620
|
{ label: "Cancel", hint: "", group: "confirm", run: () => {
|
|
2606
2621
|
} }
|
|
@@ -2651,23 +2666,13 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
2651
2666
|
label: `Close #${item.number}`,
|
|
2652
2667
|
hint: "",
|
|
2653
2668
|
group: "confirm",
|
|
2654
|
-
run: () => {
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
(e) => {
|
|
2662
|
-
showFlash(`\u2717 Close failed \u2014 restoring #${item.number}`);
|
|
2663
|
-
onRefresh?.();
|
|
2664
|
-
ext?.onSettled?.(item, {
|
|
2665
|
-
ok: false,
|
|
2666
|
-
reason: firstLine(e)
|
|
2667
|
-
});
|
|
2668
|
-
}
|
|
2669
|
-
);
|
|
2670
|
-
}
|
|
2669
|
+
run: () => removeAhead({
|
|
2670
|
+
action: "close",
|
|
2671
|
+
request: () => quietly`gh pr close ${item.number} --repo ${item.repo}`,
|
|
2672
|
+
taking: `\u2713 Closed #${item.number}`,
|
|
2673
|
+
refused: () => `\u2717 Close failed \u2014 restoring #${item.number}`,
|
|
2674
|
+
settles: true
|
|
2675
|
+
})
|
|
2671
2676
|
},
|
|
2672
2677
|
{ label: "Cancel", hint: "", group: "confirm", run: () => {
|
|
2673
2678
|
} }
|
|
@@ -2688,16 +2693,23 @@ var buildActions = (item, login, showFlash, jiraBase, jiraKeyRe, jiraTransitions
|
|
|
2688
2693
|
label: `Close #${item.number} and delete ${item.branch}`,
|
|
2689
2694
|
hint: "",
|
|
2690
2695
|
group: "confirm",
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2696
|
+
// The patch covers the close and nothing else. A branch that will
|
|
2697
|
+
// not delete leaves a PR that IS closed, so reporting "Couldn't
|
|
2698
|
+
// close #412" and offering `w` would restore a row the server no
|
|
2699
|
+
// longer has; the branch gets its own flash instead.
|
|
2700
|
+
run: () => removeAhead({
|
|
2701
|
+
action: "close",
|
|
2702
|
+
request: async () => {
|
|
2703
|
+
await quietly`gh pr close ${item.number} --repo ${item.repo}`;
|
|
2704
|
+
void quietly`gh api -X DELETE ${`repos/${item.repo}/git/refs/heads/${item.branch}`}`.catch(
|
|
2705
|
+
() => showFlash(
|
|
2706
|
+
`\u2717 Closed #${item.number}, but couldn't delete ${item.branch}`
|
|
2707
|
+
)
|
|
2708
|
+
);
|
|
2709
|
+
},
|
|
2710
|
+
taking: `\u2713 Closed #${item.number} and deleted ${item.branch}`,
|
|
2711
|
+
refused: () => `\u2717 Close + delete failed \u2014 restoring`
|
|
2712
|
+
})
|
|
2701
2713
|
},
|
|
2702
2714
|
{ label: "Cancel", hint: "", group: "confirm", run: () => {
|
|
2703
2715
|
} }
|
|
@@ -2983,7 +2995,7 @@ var ItemRow = ({
|
|
|
2983
2995
|
const icon = merged ? {
|
|
2984
2996
|
glyph: MERGED_FRAMES[sparkFrame % MERGED_FRAMES.length],
|
|
2985
2997
|
color: MERGED_COLOUR
|
|
2986
|
-
} : transient ? {
|
|
2998
|
+
} : pending ? { glyph: PENDING_GLYPH, color: colors.muted } : transient ? {
|
|
2987
2999
|
glyph: isDeparture(transient) ? TRANSIT_OUT_FRAMES[rampAt(TRANSIT_OUT_FRAMES.length)] : isArrival(transient) ? TRANSIT_IN_FRAMES[rampAt(TRANSIT_IN_FRAMES.length)] : displayFor(item.health).glyph,
|
|
2988
3000
|
color: TRANSIT_COLOUR[transient]
|
|
2989
3001
|
} : void 0;
|
|
@@ -3043,17 +3055,18 @@ var useActionMenu = () => {
|
|
|
3043
3055
|
};
|
|
3044
3056
|
const handleKey = (key) => {
|
|
3045
3057
|
if (!actions) return false;
|
|
3058
|
+
const live = (n) => n >= 0 && n < actions.length && !isMenuGap(actions[n]);
|
|
3046
3059
|
if (key.upArrow)
|
|
3047
3060
|
setCursor((c) => {
|
|
3048
3061
|
let n = c - 1;
|
|
3049
3062
|
while (n > 0 && isMenuGap(actions[n])) n -= 1;
|
|
3050
|
-
return
|
|
3063
|
+
return live(n) ? n : c;
|
|
3051
3064
|
});
|
|
3052
3065
|
if (key.downArrow)
|
|
3053
3066
|
setCursor((c) => {
|
|
3054
3067
|
let n = c + 1;
|
|
3055
3068
|
while (n < actions.length - 1 && isMenuGap(actions[n])) n += 1;
|
|
3056
|
-
return
|
|
3069
|
+
return live(n) ? n : c;
|
|
3057
3070
|
});
|
|
3058
3071
|
if (key.return) {
|
|
3059
3072
|
const row = actions[cursor];
|
|
@@ -3453,6 +3466,8 @@ var BrowseScreen = ({
|
|
|
3453
3466
|
sidebar,
|
|
3454
3467
|
liveLabel,
|
|
3455
3468
|
optimisticMove,
|
|
3469
|
+
optimistic,
|
|
3470
|
+
departing,
|
|
3456
3471
|
pendingKeys,
|
|
3457
3472
|
failure,
|
|
3458
3473
|
onRestore
|
|
@@ -3578,6 +3593,14 @@ var BrowseScreen = ({
|
|
|
3578
3593
|
const timer = setTimeout(() => setDismissedSeq(seq), FAILURE_NOTICE_MS);
|
|
3579
3594
|
return () => clearTimeout(timer);
|
|
3580
3595
|
}, [failure?.seq]);
|
|
3596
|
+
const counted = useMemo(
|
|
3597
|
+
() => countedSections(localSections, departing),
|
|
3598
|
+
[localSections, departing]
|
|
3599
|
+
);
|
|
3600
|
+
const countOf = (id) => {
|
|
3601
|
+
const s = counted.find((c) => c.id === id);
|
|
3602
|
+
return s ? workCount(s) : 0;
|
|
3603
|
+
};
|
|
3581
3604
|
const markedTabs = useMemo(() => {
|
|
3582
3605
|
const out = /* @__PURE__ */ new Set();
|
|
3583
3606
|
if (!transients?.size) return out;
|
|
@@ -3713,31 +3736,34 @@ var BrowseScreen = ({
|
|
|
3713
3736
|
optimistic: optimisticMove ? (to) => optimisticMove(task, to) : void 0
|
|
3714
3737
|
});
|
|
3715
3738
|
};
|
|
3739
|
+
const actionsFor = (item, flash2) => buildActions(
|
|
3740
|
+
item,
|
|
3741
|
+
login,
|
|
3742
|
+
flash2,
|
|
3743
|
+
jiraBase,
|
|
3744
|
+
jiraKeyRe,
|
|
3745
|
+
jiraTransitions,
|
|
3746
|
+
onRefresh,
|
|
3747
|
+
dismissItem,
|
|
3748
|
+
openDrillView,
|
|
3749
|
+
{
|
|
3750
|
+
extensions,
|
|
3751
|
+
onOpenExt,
|
|
3752
|
+
onActed,
|
|
3753
|
+
onSettled,
|
|
3754
|
+
optimistic,
|
|
3755
|
+
onOpenMove: jiraTransitionsFor ? openMoveFor : void 0
|
|
3756
|
+
}
|
|
3757
|
+
);
|
|
3716
3758
|
const openMenu = () => {
|
|
3717
3759
|
if (!activeItem || activeItem.kind === "repo-header" || activeItem.kind === "subgroup-header")
|
|
3718
3760
|
return;
|
|
3719
|
-
|
|
3720
|
-
activeItem,
|
|
3721
|
-
login,
|
|
3722
|
-
(msg) => {
|
|
3761
|
+
menu.open(
|
|
3762
|
+
actionsFor(activeItem, (msg) => {
|
|
3723
3763
|
menu.close();
|
|
3724
3764
|
showFlash(msg);
|
|
3725
|
-
}
|
|
3726
|
-
jiraBase,
|
|
3727
|
-
jiraKeyRe,
|
|
3728
|
-
jiraTransitions,
|
|
3729
|
-
onRefresh,
|
|
3730
|
-
dismissItem,
|
|
3731
|
-
openDrillView,
|
|
3732
|
-
{
|
|
3733
|
-
extensions,
|
|
3734
|
-
onOpenExt,
|
|
3735
|
-
onActed,
|
|
3736
|
-
onSettled,
|
|
3737
|
-
onOpenMove: jiraTransitionsFor ? openMoveFor : void 0
|
|
3738
|
-
}
|
|
3765
|
+
})
|
|
3739
3766
|
);
|
|
3740
|
-
menu.open(actions);
|
|
3741
3767
|
};
|
|
3742
3768
|
useInput((input, key) => {
|
|
3743
3769
|
const idleFor = Date.now() - lastKeyAt.current;
|
|
@@ -4029,20 +4055,7 @@ var BrowseScreen = ({
|
|
|
4029
4055
|
return;
|
|
4030
4056
|
}
|
|
4031
4057
|
if (input === "x" && activeItem.kind === "pr" && activeItem.standing === "queued" && login) {
|
|
4032
|
-
|
|
4033
|
-
showFlash(`\u22EF Removing you from #${activeItem.number}\u2026`);
|
|
4034
|
-
void quietly`gh pr edit ${activeItem.number} --repo ${activeItem.repo} --remove-reviewer ${login}`.then(
|
|
4035
|
-
() => {
|
|
4036
|
-
showFlash(`\u2713 Removed you as reviewer on #${activeItem.number}`);
|
|
4037
|
-
onActed?.();
|
|
4038
|
-
onSettled?.(activeItem, { ok: true });
|
|
4039
|
-
},
|
|
4040
|
-
(e) => {
|
|
4041
|
-
showFlash(`\u2717 #${activeItem.number}: ${explainGhAction(e)}`);
|
|
4042
|
-
onRefresh?.();
|
|
4043
|
-
onSettled?.(activeItem, { ok: false, reason: firstLine(e) });
|
|
4044
|
-
}
|
|
4045
|
-
);
|
|
4058
|
+
actionsFor(activeItem, showFlash).find((a) => a.label === REMOVE_ME_AS_REVIEWER)?.run();
|
|
4046
4059
|
return;
|
|
4047
4060
|
}
|
|
4048
4061
|
if (input === "b" && activeItem.kind === "pr" && activeItem.branch) {
|
|
@@ -4331,7 +4344,7 @@ var BrowseScreen = ({
|
|
|
4331
4344
|
InboxHeader,
|
|
4332
4345
|
{
|
|
4333
4346
|
brand,
|
|
4334
|
-
sections:
|
|
4347
|
+
sections: counted,
|
|
4335
4348
|
login,
|
|
4336
4349
|
scopeLabel: overlayOpen ? chrome?.scope ?? origin?.label : origin?.label,
|
|
4337
4350
|
budgetLabel: budgetNotice(budget)?.label,
|
|
@@ -4363,7 +4376,7 @@ var BrowseScreen = ({
|
|
|
4363
4376
|
items: localSections.map((s) => ({
|
|
4364
4377
|
value: s.id,
|
|
4365
4378
|
label: s.label,
|
|
4366
|
-
count:
|
|
4379
|
+
count: countOf(s.id),
|
|
4367
4380
|
/*
|
|
4368
4381
|
* The denominator, and only where it can still be true.
|
|
4369
4382
|
*
|
|
@@ -4835,6 +4848,26 @@ var App = ({
|
|
|
4835
4848
|
phase: "inflight"
|
|
4836
4849
|
});
|
|
4837
4850
|
} : void 0;
|
|
4851
|
+
const optimistic = (item, change) => {
|
|
4852
|
+
const key = keyOf(item);
|
|
4853
|
+
if (!key) return void 0;
|
|
4854
|
+
return hold(key, {
|
|
4855
|
+
patch: change.patch,
|
|
4856
|
+
action: change.action,
|
|
4857
|
+
label: rowLabelOf(item),
|
|
4858
|
+
since: Date.now(),
|
|
4859
|
+
phase: "inflight"
|
|
4860
|
+
});
|
|
4861
|
+
};
|
|
4862
|
+
const departing = useMemo(
|
|
4863
|
+
() => new Map(
|
|
4864
|
+
[...overrides.current].flatMap(
|
|
4865
|
+
([key, { patch }]) => patch.kind === "remove" ? [[key, null]] : patch.kind === "move" ? [[key, patch.toSection]] : []
|
|
4866
|
+
)
|
|
4867
|
+
),
|
|
4868
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4869
|
+
[overrideRev]
|
|
4870
|
+
);
|
|
4838
4871
|
const restore = () => {
|
|
4839
4872
|
const newest = failedOverrides(overrides.current)[0];
|
|
4840
4873
|
if (!newest) return;
|
|
@@ -5070,6 +5103,8 @@ var App = ({
|
|
|
5070
5103
|
jiraTransitions,
|
|
5071
5104
|
jiraTransitionsFor,
|
|
5072
5105
|
optimisticMove,
|
|
5106
|
+
optimistic,
|
|
5107
|
+
departing,
|
|
5073
5108
|
pendingKeys,
|
|
5074
5109
|
failure,
|
|
5075
5110
|
onRestore: restore,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kud/gh-ink",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.74.0",
|
|
4
4
|
"description": "Ink components for rendering GitHub PR review comments and health — controlled, presentation-only, built on @kud/ink-ui and fed by @kud/gh.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"access": "public"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@kud/ink-ui": ">=0.
|
|
47
|
+
"@kud/ink-ui": ">=0.38.0 <1",
|
|
48
48
|
"ink": ">=7",
|
|
49
49
|
"react": ">=19"
|
|
50
50
|
},
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"zx": "8.8.5"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@kud/ink-ui": "0.
|
|
57
|
+
"@kud/ink-ui": "0.38.0",
|
|
58
58
|
"@types/node": "22.20.1",
|
|
59
59
|
"@types/react": "19.2.17",
|
|
60
60
|
"ink": "7.1.0",
|