@pi-unipi/info-screen 2.1.0 → 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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pi-unipi/info-screen",
3
- "version": "2.1.0",
4
- "description": "Dashboard and module registry for Unipi \u2014 configurable info overlay with tabbed groups",
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,7 +33,7 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@pi-unipi/core": "2.1.0"
36
+ "@pi-unipi/core": "2.1.1"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@earendil-works/pi-coding-agent": "^0.80.0",
@@ -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 + this.groups.length) % this.groups.length;
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) % this.groups.length;
94
+ this.selectedIndex = (this.selectedIndex + 1) % (lastIndex + 1);
92
95
  break;
93
- case " ": // Space - toggle visibility
94
- this.toggleGroupVisibility(this.groups[this.selectedIndex].id);
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
- this.enterStatsMode(this.groups[this.selectedIndex].id);
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.moveGroupDown();
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.moveGroupUp();
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 <= 0) return;
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 - 1) return;
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
- const isSelected = i === this.selectedIndex;
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
 
@@ -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 async fetchAllBackground(): Promise<void> {
104
+ private fetchAllBackground(): void {
99
105
  for (const group of this.groups) {
100
- // Fire each fetch independently don't await sequentially
101
- infoRegistry.getGroupData(group.id).then(() => {
102
- this.groupLoading.set(group.id, false);
103
- }).catch(() => {
104
- this.groupLoading.set(group.id, false);
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