@wichayutdew/pi-workflows 2.0.1 → 2.1.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.
@@ -135,6 +135,7 @@ function nextScrollOffset(state: ViewportState, value: number): number {
135
135
  export class WorkflowStatusView implements Component {
136
136
  private timer: RefreshTimer | undefined;
137
137
  private state = initialViewportState();
138
+ private pendingDetailTopKey = false;
138
139
  private readonly statusShortcutLabel: string;
139
140
  private readonly dependencies: WorkflowStatusViewDependencies;
140
141
  private readonly transcriptCache = new Map<string, StepTranscriptViewState>();
@@ -180,11 +181,15 @@ export class WorkflowStatusView implements Component {
180
181
 
181
182
  /** Handle close and scrolling key input. */
182
183
  handleInput(data: string): void {
184
+ const isDetailHalfPageDown =
185
+ this.state.mode === 'detail' && matchesKey(data, Key.ctrl('d'));
186
+ const isDetailHalfPageUp =
187
+ this.state.mode === 'detail' && matchesKey(data, Key.ctrl('u'));
183
188
  if (
184
189
  data === 'q' ||
185
190
  data === 'Q' ||
186
191
  matchesKey(data, 'ctrl+c') ||
187
- matchesKey(data, 'ctrl+d') ||
192
+ (this.state.mode !== 'detail' && matchesKey(data, 'ctrl+d')) ||
188
193
  matchesKey(data, this.statusShortcut)
189
194
  ) {
190
195
  this.close();
@@ -199,13 +204,31 @@ export class WorkflowStatusView implements Component {
199
204
  return;
200
205
  }
201
206
  const pageSize = Math.max(1, this.state.viewportRows - 2);
207
+ const contentHeight = Math.max(1, this.state.viewportRows - 1);
208
+ const halfPageSize = Math.max(1, Math.floor(contentHeight / 2));
202
209
  if (this.state.mode === 'detail') {
203
- if (matchesKey(data, Key.left) || data === 'h') {
210
+ if (data === 'gg' || (data === 'g' && this.pendingDetailTopKey)) {
211
+ this.pendingDetailTopKey = false;
212
+ this.setScrollOffset(0);
213
+ return;
214
+ }
215
+ if (data === 'g') {
216
+ this.pendingDetailTopKey = true;
217
+ return;
218
+ }
219
+ this.pendingDetailTopKey = false;
220
+ if (data === 'G') {
221
+ this.setScrollOffset(Number.MAX_SAFE_INTEGER);
222
+ } else if (matchesKey(data, Key.left) || data === 'h') {
204
223
  this.showBoard();
205
224
  } else if (matchesKey(data, Key.down) || data === 'j') {
206
225
  this.setScrollOffset(this.state.scrollOffset + 1);
207
226
  } else if (matchesKey(data, Key.up) || data === 'k') {
208
227
  this.setScrollOffset(this.state.scrollOffset - 1);
228
+ } else if (isDetailHalfPageDown) {
229
+ this.setScrollOffset(this.state.scrollOffset + halfPageSize);
230
+ } else if (isDetailHalfPageUp) {
231
+ this.setScrollOffset(this.state.scrollOffset - halfPageSize);
209
232
  } else if (matchesKey(data, Key.pageDown)) {
210
233
  this.setScrollOffset(this.state.scrollOffset + pageSize);
211
234
  } else if (matchesKey(data, Key.pageUp)) {
@@ -217,6 +240,7 @@ export class WorkflowStatusView implements Component {
217
240
  }
218
241
  return;
219
242
  }
243
+ this.pendingDetailTopKey = false;
220
244
  if (matchesKey(data, Key.down) || data === 'j') {
221
245
  this.moveSelection(1);
222
246
  } else if (matchesKey(data, Key.up) || data === 'k') {
@@ -287,7 +311,7 @@ export class WorkflowStatusView implements Component {
287
311
  this.statusShortcutLabel,
288
312
  this.theme,
289
313
  this.state.mode === 'detail'
290
- ? '↑/↓ or j/k scroll · PgUp/PgDn · ←/h/Esc back'
314
+ ? '↑↓/jk · Ctrl+D/U half-page · gg/G top/bottom · PgUp/PgDn · ←/h/Esc'
291
315
  : '↑/↓ or j/k select · Enter/→/l inspect · PgUp/PgDn',
292
316
  );
293
317
  this.state = page.state;
@@ -339,6 +363,7 @@ export class WorkflowStatusView implements Component {
339
363
  if (!snapshot) return;
340
364
  this.normalizeSelection(snapshot);
341
365
  if (!selectedStepDetail(snapshot, this.state.selectedIndex)) return;
366
+ this.pendingDetailTopKey = false;
342
367
  this.state = { ...this.state, mode: 'detail', scrollOffset: 0 };
343
368
  this.ensureSelectedTranscripts(snapshot);
344
369
  this.tui.requestRender(true);
@@ -346,6 +371,7 @@ export class WorkflowStatusView implements Component {
346
371
 
347
372
  private showBoard(): void {
348
373
  if (this.state.mode === 'board') return;
374
+ this.pendingDetailTopKey = false;
349
375
  this.state = { ...this.state, mode: 'board', scrollOffset: 0 };
350
376
  this.tui.requestRender(true);
351
377
  }