@pi-unipi/info-screen 2.0.13 → 2.1.1
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/index.ts +3 -1
- package/package.json +5 -5
- package/settings/settings-tui.ts +51 -12
- package/tui/info-overlay.ts +16 -7
package/index.ts
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* /unipi:info-settings - Configure info display
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { dirname } from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
12
14
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
13
15
|
import { UNIPI_EVENTS, MODULES, UNIPI_PREFIX, emitEvent, getPackageVersion, type UnipiModuleEvent, type UnipiInfoGroupEvent } from "@pi-unipi/core";
|
|
14
16
|
import { infoRegistry } from "./registry.js";
|
|
@@ -21,7 +23,7 @@ import { InfoOverlay } from "./tui/info-overlay.js";
|
|
|
21
23
|
import { SettingsOverlay } from "./settings/settings-tui.js";
|
|
22
24
|
|
|
23
25
|
/** Package version */
|
|
24
|
-
const VERSION = getPackageVersion(
|
|
26
|
+
const VERSION = getPackageVersion(dirname(fileURLToPath(import.meta.url)));
|
|
25
27
|
|
|
26
28
|
export default function (pi: ExtensionAPI) {
|
|
27
29
|
setPiApi(pi);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/info-screen",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Dashboard and module registry for Unipi
|
|
3
|
+
"version": "2.1.1",
|
|
4
|
+
"description": "Dashboard and module registry for Unipi — configurable info overlay with tabbed groups",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
7
7
|
"license": "MIT",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "2.
|
|
36
|
+
"@pi-unipi/core": "2.1.1"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
40
|
-
"@earendil-works/pi-tui": "^0.
|
|
39
|
+
"@earendil-works/pi-coding-agent": "^0.80.0",
|
|
40
|
+
"@earendil-works/pi-tui": "^0.80.0",
|
|
41
41
|
"typebox": "^1.1.38"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
package/settings/settings-tui.ts
CHANGED
|
@@ -35,6 +35,8 @@ export class SettingsOverlay implements Component {
|
|
|
35
35
|
private settings: InfoScreenSettings;
|
|
36
36
|
private groups: Array<{ id: string; name: string; icon: string }>;
|
|
37
37
|
private selectedIndex = 0;
|
|
38
|
+
/** Index of the "Show on boot" toggle row (above the group list). */
|
|
39
|
+
private static readonly BOOT_TOGGLE_INDEX = 0;
|
|
38
40
|
private savedGroupIndex = 0; // Saved position before entering stats mode
|
|
39
41
|
private mode: "groups" | "stats" = "groups";
|
|
40
42
|
private selectedGroupId: string | null = null;
|
|
@@ -81,28 +83,41 @@ export class SettingsOverlay implements Component {
|
|
|
81
83
|
* Handle input in groups mode.
|
|
82
84
|
*/
|
|
83
85
|
private handleGroupsInput(data: string): void {
|
|
86
|
+
const lastIndex = this.groups.length; // boot toggle is index 0, groups occupy 1..length
|
|
84
87
|
switch (data) {
|
|
85
88
|
case "\x1b[A": // Up
|
|
86
89
|
case "k":
|
|
87
|
-
this.selectedIndex = (this.selectedIndex - 1 +
|
|
90
|
+
this.selectedIndex = (this.selectedIndex - 1 + (lastIndex + 1)) % (lastIndex + 1);
|
|
88
91
|
break;
|
|
89
92
|
case "\x1b[B": // Down
|
|
90
93
|
case "j":
|
|
91
|
-
this.selectedIndex = (this.selectedIndex + 1) %
|
|
94
|
+
this.selectedIndex = (this.selectedIndex + 1) % (lastIndex + 1);
|
|
92
95
|
break;
|
|
93
|
-
case " ": // Space - toggle
|
|
94
|
-
|
|
96
|
+
case " ": // Space - toggle
|
|
97
|
+
if (this.selectedIndex === SettingsOverlay.BOOT_TOGGLE_INDEX) {
|
|
98
|
+
this.toggleShowOnBoot();
|
|
99
|
+
} else {
|
|
100
|
+
this.toggleGroupVisibility(this.groups[this.selectedIndex - 1].id);
|
|
101
|
+
}
|
|
95
102
|
break;
|
|
96
103
|
case "\r": // Enter - enter stats mode
|
|
97
104
|
case "\x1b[C": // Right - enter stats mode
|
|
98
105
|
case "l":
|
|
99
|
-
|
|
106
|
+
if (this.selectedIndex === SettingsOverlay.BOOT_TOGGLE_INDEX) {
|
|
107
|
+
this.toggleShowOnBoot();
|
|
108
|
+
} else {
|
|
109
|
+
this.enterStatsMode(this.groups[this.selectedIndex - 1].id);
|
|
110
|
+
}
|
|
100
111
|
break;
|
|
101
112
|
case "J": // Shift+J - move group down
|
|
102
|
-
this.
|
|
113
|
+
if (this.selectedIndex > SettingsOverlay.BOOT_TOGGLE_INDEX) {
|
|
114
|
+
this.moveGroupDown();
|
|
115
|
+
}
|
|
103
116
|
break;
|
|
104
117
|
case "K": // Shift+K - move group up
|
|
105
|
-
this.
|
|
118
|
+
if (this.selectedIndex > SettingsOverlay.BOOT_TOGGLE_INDEX) {
|
|
119
|
+
this.moveGroupUp();
|
|
120
|
+
}
|
|
106
121
|
break;
|
|
107
122
|
case "q": // Quit
|
|
108
123
|
case "\x1b": // Escape
|
|
@@ -180,6 +195,14 @@ export class SettingsOverlay implements Component {
|
|
|
180
195
|
this.settings.groups[groupId] = groupSettings;
|
|
181
196
|
}
|
|
182
197
|
|
|
198
|
+
/**
|
|
199
|
+
* Toggle the "show on boot" setting.
|
|
200
|
+
*/
|
|
201
|
+
private toggleShowOnBoot(): void {
|
|
202
|
+
this.settings.showOnBoot = !this.settings.showOnBoot;
|
|
203
|
+
saveInfoSettings(this.settings);
|
|
204
|
+
}
|
|
205
|
+
|
|
183
206
|
/**
|
|
184
207
|
* Enter stats editing mode for a group.
|
|
185
208
|
*/
|
|
@@ -194,8 +217,8 @@ export class SettingsOverlay implements Component {
|
|
|
194
217
|
* Move selected group up in order.
|
|
195
218
|
*/
|
|
196
219
|
private moveGroupUp(): void {
|
|
197
|
-
if (this.selectedIndex <=
|
|
198
|
-
const i = this.selectedIndex;
|
|
220
|
+
if (this.selectedIndex <= SettingsOverlay.BOOT_TOGGLE_INDEX + 1) return;
|
|
221
|
+
const i = this.selectedIndex - 1; // map back to groups array index
|
|
199
222
|
// Swap with previous
|
|
200
223
|
const temp = this.groups[i]!;
|
|
201
224
|
this.groups[i] = this.groups[i - 1]!;
|
|
@@ -208,8 +231,8 @@ export class SettingsOverlay implements Component {
|
|
|
208
231
|
* Move selected group down in order.
|
|
209
232
|
*/
|
|
210
233
|
private moveGroupDown(): void {
|
|
211
|
-
if (this.selectedIndex >= this.groups.length
|
|
212
|
-
const i = this.selectedIndex;
|
|
234
|
+
if (this.selectedIndex >= this.groups.length) return; // boot toggle occupies 0, groups 1..length
|
|
235
|
+
const i = this.selectedIndex - 1; // map back to groups array index
|
|
213
236
|
// Swap with next
|
|
214
237
|
const temp = this.groups[i]!;
|
|
215
238
|
this.groups[i] = this.groups[i + 1]!;
|
|
@@ -261,9 +284,25 @@ export class SettingsOverlay implements Component {
|
|
|
261
284
|
lines.push(`${ansi.dim}├${"─".repeat(innerWidth)}┤${ansi.reset}`);
|
|
262
285
|
|
|
263
286
|
// Group list
|
|
287
|
+
// Boot toggle row (index 0)
|
|
288
|
+
{
|
|
289
|
+
const isSelected = SettingsOverlay.BOOT_TOGGLE_INDEX === this.selectedIndex;
|
|
290
|
+
const isEnabled = this.settings.showOnBoot;
|
|
291
|
+
const toggle = isEnabled ? TOGGLE_ON : TOGGLE_OFF;
|
|
292
|
+
const indicator = isSelected ? `${ansi.cyan}▸${ansi.reset}` : " ";
|
|
293
|
+
let line = ` ${indicator} ${toggle} 🚀 Show on boot`;
|
|
294
|
+
if (isSelected) {
|
|
295
|
+
line += ` ${ansi.dim}→ toggle${ansi.reset}`;
|
|
296
|
+
}
|
|
297
|
+
lines.push(`${ansi.dim}│${ansi.reset}${this.padToWidth(line, innerWidth)}${ansi.dim}│${ansi.reset}`);
|
|
298
|
+
}
|
|
299
|
+
lines.push(`${ansi.dim}├${"─".repeat(innerWidth)}┤${ansi.reset}`);
|
|
300
|
+
|
|
264
301
|
for (let i = 0; i < this.groups.length; i++) {
|
|
265
302
|
const group = this.groups[i];
|
|
266
|
-
|
|
303
|
+
// index 0 is the boot toggle; groups start at row index 1
|
|
304
|
+
const rowIndex = i + 1;
|
|
305
|
+
const isSelected = rowIndex === this.selectedIndex;
|
|
267
306
|
const groupSettings = getGroupSettings(group.id);
|
|
268
307
|
const isEnabled = groupSettings.show;
|
|
269
308
|
|
package/tui/info-overlay.ts
CHANGED
|
@@ -94,15 +94,24 @@ export class InfoOverlay implements Component {
|
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
96
|
* Fetch all groups in background. Each resolves independently.
|
|
97
|
+
*
|
|
98
|
+
* Each fetch is deferred to a macrotask (setTimeout 0) so the constructor
|
|
99
|
+
* returns immediately. Without this, getGroupData() runs each group's
|
|
100
|
+
* dataProvider synchronously up to its first `await` before yielding —
|
|
101
|
+
* heavy providers (usage stats parse 1GB+ of session files, memory scans)
|
|
102
|
+
* blocked the session_start handler for seconds.
|
|
97
103
|
*/
|
|
98
|
-
private
|
|
104
|
+
private fetchAllBackground(): void {
|
|
99
105
|
for (const group of this.groups) {
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
this.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
// Defer each fetch to a macrotask so the overlay constructs instantly.
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
if (this._destroyed) return;
|
|
109
|
+
infoRegistry.getGroupData(group.id).then(() => {
|
|
110
|
+
this.groupLoading.set(group.id, false);
|
|
111
|
+
}).catch(() => {
|
|
112
|
+
this.groupLoading.set(group.id, false);
|
|
113
|
+
});
|
|
114
|
+
}, 0);
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
117
|
|