fix(P6): hoist savedPositionRef above initialTopMostIndex (TDZ) + auto-open DevTools in dev
This commit is contained in:
@@ -147,6 +147,17 @@ async function createWindow(): Promise<BrowserWindow> {
|
||||
attachWindowState(win, WINDOW_STATE_FILE);
|
||||
|
||||
if (!app.isPackaged) {
|
||||
// Auto-open DevTools in dev — the menu bar is stripped (Discord-style)
|
||||
// so F12 / Ctrl+Shift+I have no chord; opening detached gives a
|
||||
// separate inspector window for easy debugging.
|
||||
win.webContents.openDevTools({ mode: 'detach' });
|
||||
// Forward renderer console messages to the main-process stdout so
|
||||
// errors during local dev are visible in the terminal too (helps when
|
||||
// the inspector isn't focused).
|
||||
win.webContents.on('console-message', (_event, level, message, line, sourceId) => {
|
||||
const tag = level === 3 ? 'error' : level === 2 ? 'warn' : level === 1 ? 'log' : 'info';
|
||||
console.log('[renderer ' + tag + ']', message, '(' + sourceId + ':' + line + ')');
|
||||
});
|
||||
await win.loadURL(DEV_URL);
|
||||
} else {
|
||||
await win.loadFile(resolveRendererIndex());
|
||||
|
||||
@@ -434,6 +434,22 @@ export function ConversationPage() {
|
||||
return out;
|
||||
}, [messages, pending, displayCount]);
|
||||
|
||||
// Snapshot of the saved position for this conversation, captured once on
|
||||
// mount. Used to derive the `initialTopMostItemIndex` we hand to the
|
||||
// Virtuoso instance below — Virtuoso applies that index synchronously
|
||||
// before its first paint, so re-entering a chat shows the saved row in
|
||||
// one frame rather than a "starts at top, jumps" flicker.
|
||||
//
|
||||
// Declared HERE (above `initialTopMostIndex`) rather than further down
|
||||
// because the useMemo that consumes it would otherwise hit a TDZ on
|
||||
// first render — `const` refs aren't hoisted.
|
||||
const savedPositionRef = useRef<{ topmostIndex: number; stickToBottom: boolean } | null>(
|
||||
null,
|
||||
);
|
||||
if (savedPositionRef.current === null && id) {
|
||||
savedPositionRef.current = scrollPositions.get(id) ?? null;
|
||||
}
|
||||
|
||||
// Initial scroll position for the freshly-mounted Virtuoso instance.
|
||||
// Default = bottom (newest message). If we have a saved position from a
|
||||
// previous visit to this chat AND the user wasn't sticking to the
|
||||
@@ -648,17 +664,8 @@ export function ConversationPage() {
|
||||
// The old useLayoutEffect that wrote `scrollTop = scrollHeight` is no
|
||||
// longer needed: Virtuoso owns scroll positioning now.
|
||||
|
||||
// Snapshot of the saved position for this conversation, captured once on
|
||||
// mount. Used to derive the `initialTopMostItemIndex` we hand to the
|
||||
// Virtuoso instance below — Virtuoso applies that index synchronously
|
||||
// before its first paint, so re-entering a chat shows the saved row in
|
||||
// one frame rather than a "starts at top, jumps" flicker.
|
||||
const savedPositionRef = useRef<{ topmostIndex: number; stickToBottom: boolean } | null>(
|
||||
null,
|
||||
);
|
||||
if (savedPositionRef.current === null && id) {
|
||||
savedPositionRef.current = scrollPositions.get(id) ?? null;
|
||||
}
|
||||
// (savedPositionRef declared earlier — see TDZ note above the
|
||||
// initialTopMostIndex useMemo.)
|
||||
|
||||
// Track whether the user is currently scrolled to the bottom. Virtuoso
|
||||
// calls this whenever the bottom-state changes; we feed it into
|
||||
|
||||
Reference in New Issue
Block a user