@underactive/pi-topping-statusline 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -9
- package/index.ts +146 -39
- package/package.json +4 -4
- package/src/compaction-embed.ts +62 -0
- package/src/context-graph.ts +5 -5
- package/src/context-thresholds.ts +7 -3
- package/src/context.ts +72 -13
- package/src/layout.ts +76 -27
- package/src/menu.ts +25 -36
- package/src/segments.ts +54 -0
- package/src/settings-menu.ts +66 -36
- package/src/settings.ts +25 -3
- package/src/tests/compaction-embed.test.ts +184 -0
- package/src/tests/context-estimate.test.ts +207 -0
- package/src/tests/context-thresholds.test.ts +6 -0
- package/src/tests/feeds.test.ts +2 -8
- package/src/tests/menu.test.ts +31 -2
- package/src/tests/token-rate.test.ts +2 -1
- package/src/tests/working-status-embed.test.ts +12 -0
- package/src/tests/working-status.test.ts +60 -9
- package/src/tests/working.test.ts +220 -25
- package/src/token-rate.ts +1 -1
- package/src/types.ts +28 -2
- package/src/working-status-embed.ts +15 -0
- package/src/working-status.ts +42 -15
package/src/working-status.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { easeFade } from "./theme.js";
|
|
|
3
3
|
|
|
4
4
|
export type StatusIndicatorKind = NonNullable<Parameters<CustomEditor["setWorkingStatusIndicator"]>[0]>["kind"];
|
|
5
5
|
|
|
6
|
+
/** Slide-out time for a status that appears while the top-left group shows none. */
|
|
7
|
+
export const STATUS_SLIDE_MS = 300;
|
|
6
8
|
/** Briefly retain a cleared status so handoffs between host indicators do not flash. */
|
|
7
9
|
export const STATUS_HOLD_MS = 150;
|
|
8
10
|
/** Cross-fade budget when the embedded working status disappears: half out, half in. */
|
|
@@ -13,13 +15,15 @@ export function isMessageKind(kind: StatusIndicatorKind | undefined): boolean {
|
|
|
13
15
|
return kind !== undefined && kind !== "working";
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
/** Which status the top-left group shows this frame and how far it has faded. */
|
|
18
|
+
/** Which status the top-left group shows this frame and how far it has slid out or faded. */
|
|
17
19
|
export interface StatusFrame {
|
|
18
20
|
status: string | undefined;
|
|
19
21
|
leftFade?: number;
|
|
22
|
+
/** How far the status has slid out (0..1); absent once it is fully out. */
|
|
23
|
+
reveal?: number;
|
|
20
24
|
/** Kind of the status this frame shows, for truncation styling. */
|
|
21
25
|
kind: StatusIndicatorKind | undefined;
|
|
22
|
-
/** True while a hold or fade still needs repaints. */
|
|
26
|
+
/** True while a slide, hold, or fade still needs repaints. */
|
|
23
27
|
pending: boolean;
|
|
24
28
|
}
|
|
25
29
|
|
|
@@ -31,24 +35,29 @@ interface StatusExit {
|
|
|
31
35
|
/**
|
|
32
36
|
* Resolve host status-indicator handoffs into stable top-bar frames.
|
|
33
37
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
+
* A status that appears while the top-left group shows none slides out over
|
|
39
|
+
* STATUS_SLIDE_MS. pi 0.86 routes working, retry, compaction, and
|
|
40
|
+
* branch-summary indicators through the editor border and may clear the slot
|
|
41
|
+
* between them. A cleared status is held briefly to bridge that gap, and a
|
|
42
|
+
* status arriving while the previous one is still drawn takes its place
|
|
43
|
+
* without sliding again. Only the working indicator — the one that genuinely
|
|
44
|
+
* ends a stream — then cross-fades back to user segments.
|
|
38
45
|
*/
|
|
39
46
|
export class StatusTransition {
|
|
40
47
|
#liveShown = false;
|
|
41
48
|
#lastStatus: string | undefined;
|
|
42
49
|
#lastKind: StatusIndicatorKind | undefined;
|
|
43
50
|
#exit: StatusExit | undefined;
|
|
51
|
+
#slideFrom: number | undefined;
|
|
44
52
|
|
|
45
53
|
resolve(live: string | undefined, kind: StatusIndicatorKind | undefined, now: number): StatusFrame {
|
|
46
54
|
if (live !== undefined) {
|
|
55
|
+
if (!this.#liveShown && !this.#exitDrawsStatus(now)) this.#slideFrom = now;
|
|
47
56
|
this.#liveShown = true;
|
|
48
57
|
this.#lastStatus = live;
|
|
49
58
|
this.#lastKind = kind;
|
|
50
59
|
this.#exit = undefined;
|
|
51
|
-
return { status: live, kind, pending: false };
|
|
60
|
+
return this.#withSlide({ status: live, kind, pending: false }, now);
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
if (this.#liveShown) {
|
|
@@ -62,7 +71,7 @@ export class StatusTransition {
|
|
|
62
71
|
const exit = this.#exit;
|
|
63
72
|
if (!exit) return { status: undefined, kind: undefined, pending: false };
|
|
64
73
|
if (now < exit.holdUntil) {
|
|
65
|
-
return { status: this.#lastStatus, kind: this.#lastKind, pending: true };
|
|
74
|
+
return this.#withSlide({ status: this.#lastStatus, kind: this.#lastKind, pending: true }, now);
|
|
66
75
|
}
|
|
67
76
|
const elapsed = now - exit.holdUntil;
|
|
68
77
|
if (elapsed >= exit.fadeMs) {
|
|
@@ -72,17 +81,14 @@ export class StatusTransition {
|
|
|
72
81
|
const half = exit.fadeMs / 2;
|
|
73
82
|
const outgoing = elapsed < half;
|
|
74
83
|
const leftFade = easeFade(outgoing ? 1 - elapsed / half : (elapsed - half) / half);
|
|
75
|
-
return {
|
|
76
|
-
|
|
77
|
-
kind: outgoing ? this.#lastKind : undefined,
|
|
78
|
-
leftFade,
|
|
79
|
-
pending: true,
|
|
80
|
-
};
|
|
84
|
+
if (!outgoing) return { status: undefined, kind: undefined, leftFade, pending: true };
|
|
85
|
+
return this.#withSlide({ status: this.#lastStatus, kind: this.#lastKind, leftFade, pending: true }, now);
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
pending(now: number): boolean {
|
|
84
89
|
const exit = this.#exit;
|
|
85
|
-
|
|
90
|
+
if (exit) return now < exit.holdUntil + exit.fadeMs;
|
|
91
|
+
return this.#slideFrom !== undefined && now < this.#slideFrom + STATUS_SLIDE_MS;
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
reset(): void {
|
|
@@ -90,9 +96,30 @@ export class StatusTransition {
|
|
|
90
96
|
this.#clearExit();
|
|
91
97
|
}
|
|
92
98
|
|
|
99
|
+
/** A cleared status is still drawn through its hold and the fade's outgoing half. */
|
|
100
|
+
#exitDrawsStatus(now: number): boolean {
|
|
101
|
+
const exit = this.#exit;
|
|
102
|
+
return exit !== undefined && now < exit.holdUntil + exit.fadeMs / 2;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Add slide-out progress to a frame that draws a status. A status cleared
|
|
107
|
+
* mid-slide keeps sliding through its exit rather than snapping to full width.
|
|
108
|
+
*/
|
|
109
|
+
#withSlide(frame: StatusFrame, now: number): StatusFrame {
|
|
110
|
+
if (this.#slideFrom === undefined) return frame;
|
|
111
|
+
const progress = (now - this.#slideFrom) / STATUS_SLIDE_MS;
|
|
112
|
+
if (progress >= 1) {
|
|
113
|
+
this.#slideFrom = undefined;
|
|
114
|
+
return frame;
|
|
115
|
+
}
|
|
116
|
+
return { ...frame, reveal: easeFade(progress), pending: true };
|
|
117
|
+
}
|
|
118
|
+
|
|
93
119
|
#clearExit(): void {
|
|
94
120
|
this.#lastStatus = undefined;
|
|
95
121
|
this.#lastKind = undefined;
|
|
96
122
|
this.#exit = undefined;
|
|
123
|
+
this.#slideFrom = undefined;
|
|
97
124
|
}
|
|
98
125
|
}
|