Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions website/src/lib/changelog-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ export class ChangelogRunner implements InteractiveProgram {
private selectedIndex = 0;
private listOffset = 0;
private detailOffset = 0;
private hoverIndex: number | null = null;
private lastMousePos: { col: number; row: number } | null = null;
private resizeUnsub: (() => void) | null = null;
private disposed = false;
private detailCache: { index: number; width: number; lines: string[] } | null = null;
Expand Down Expand Up @@ -161,6 +163,7 @@ export class ChangelogRunner implements InteractiveProgram {
}

private handleMouse(button: number, col: number, row: number, finalByte: string): void {
this.lastMousePos = { col, row };
// Wheel scroll routes to whichever column the cursor is over so each
// side scrolls independently.
if (button === WHEEL_UP) {
Expand All @@ -173,11 +176,17 @@ export class ChangelogRunner implements InteractiveProgram {
else this.scrollDetail(1);
return;
}
// Motion (no button held). 1003h reports these as button code 35:
// bit 5 (motion) | code 3 (no button). Highlight the list row under
// the cursor so the user can see where a click would land.
if (button === 35 && finalByte === "M") {
if (this.listIndexAt(col, row) !== this.hoverIndex) this.render();
return;
}
// Left-button press on the version list selects that release.
if (button === 0 && finalByte === "M" && col < LIST_WIDTH) {
const bodyTop = HEADER_ROWS;
const idx = this.listOffset + (row - bodyTop);
if (idx >= 0 && idx < RELEASES.length) {
if (button === 0 && finalByte === "M") {
const idx = this.listIndexAt(col, row);
if (idx !== null) {
this.selectedIndex = idx;
this.detailOffset = 0;
this.ensureSelectionVisible();
Expand All @@ -186,6 +195,14 @@ export class ChangelogRunner implements InteractiveProgram {
}
}

private listIndexAt(col: number, row: number): number | null {
if (col >= LIST_WIDTH) return null;
const r = row - HEADER_ROWS;
if (r < 0 || r >= this.bodyHeight()) return null;
const idx = this.listOffset + r;
return idx >= 0 && idx < RELEASES.length ? idx : null;
}

private moveSelection(delta: number): void {
const next = Math.max(0, Math.min(RELEASES.length - 1, this.selectedIndex + delta));
if (next === this.selectedIndex) return;
Expand Down Expand Up @@ -280,6 +297,12 @@ export class ChangelogRunner implements InteractiveProgram {
private render(): void {
if (this.disposed) return;
this.lastSize = { ...this.size };
// Re-sync hover from the cursor's last position so wheel-scrolls and
// keyboard jumps move the highlight to whatever release is now under
// the mouse.
this.hoverIndex = this.lastMousePos
? this.listIndexAt(this.lastMousePos.col, this.lastMousePos.row)
: null;
const bodyH = this.bodyHeight();
const detailLines = this.getDetailLines();

Expand All @@ -296,6 +319,8 @@ export class ChangelogRunner implements InteractiveProgram {
const padded = label.length > LIST_WIDTH - 2 ? label.slice(0, LIST_WIDTH - 2) : label.padEnd(LIST_WIDTH - 2);
if (idx === this.selectedIndex) {
leftCell = `${fg(36)}❯${RESET} ${BOLD}${padded}${RESET}`;
} else if (idx === this.hoverIndex) {
leftCell = `${fg(36)}›${RESET} ${padded}`;
} else {
leftCell = ` ${padded}`;
}
Expand Down
Loading