Repository navigation
feat(web): add a setting to share the right panel width across threads #35200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,12 @@ | ||
| import * as Schema from "effect/Schema"; | ||
| import { type PointerEvent as ReactPointerEvent, useLayoutEffect, useState } from "react"; | ||
|
|
||
| import { getLocalStorageItem, setLocalStorageItem } from "./useLocalStorage"; | ||
| import { useLocalStorage, writeLocalStorageValue } from "./useLocalStorage"; | ||
| import { useResizeDrag } from "./useResizeDrag"; | ||
| import { useStableCallback } from "./useStableCallback"; | ||
|
|
||
| const WidthSchema = Schema.Finite; | ||
| // Null while no width is saved, so an unsaved width survives a responsive default changing. | ||
| const StoredWidthSchema = Schema.NullOr(Schema.Finite); | ||
|
|
||
| /** The host must size itself from this custom property. */ | ||
| export const RESIZABLE_WIDTH_PROPERTY = "--resizable-width"; | ||
|
|
@@ -40,34 +41,26 @@ export function useResizableWidth(options: UseResizableWidthOptions): { | |
| return Math.max(minWidth, Math.min(maxWidth, value)); | ||
| }; | ||
|
|
||
| const readWidth = (): number | null => { | ||
| if (typeof window === "undefined") return null; | ||
| try { | ||
| const stored = getLocalStorageItem(storageKey, WidthSchema); | ||
| return stored === null ? null : clamp(stored); | ||
| } catch (error) { | ||
| console.error("Could not read persisted panel width.", error); | ||
| return null; | ||
| } | ||
| }; | ||
| const [widthState, setWidthState] = useState(() => ({ storageKey, width: readWidth() })); | ||
| if (widthState.storageKey !== storageKey) { | ||
| setWidthState({ storageKey, width: readWidth() }); | ||
| } | ||
|
|
||
| const clampedWidth = clamp(widthState.width ?? defaultWidth); | ||
| // Panels that share a key follow each other's drags, in this tab and in others. | ||
| const [storedWidth] = useLocalStorage(storageKey, null, StoredWidthSchema); | ||
| // Resizing remains usable for this session when browser storage is unavailable. | ||
| const [unsaved, setUnsaved] = useState<{ | ||
| readonly storageKey: string; | ||
| readonly storedWidth: number | null; | ||
| readonly width: number; | ||
| } | null>(null); | ||
| const clampedWidth = clamp( | ||
| unsaved?.storageKey === storageKey && unsaved.storedWidth === storedWidth | ||
| ? unsaved.width | ||
| : (storedWidth ?? defaultWidth), | ||
| ); | ||
| const restoreWidth = useStableCallback((host: HTMLElement | null) => { | ||
| host?.style.setProperty(RESIZABLE_WIDTH_PROPERTY, `${clampedWidth}px`); | ||
| }); | ||
|
|
||
| const commitWidth = (nextStorageKey: string, nextWidth: number) => { | ||
| // Resizing remains usable for this session when browser storage is unavailable. | ||
| setWidthState({ storageKey: nextStorageKey, width: nextWidth }); | ||
| try { | ||
| setLocalStorageItem(nextStorageKey, nextWidth, WidthSchema); | ||
| } catch (error) { | ||
| console.error("Could not persist panel width.", error); | ||
| } | ||
| const saved = writeLocalStorageValue(nextStorageKey, nextWidth, null, StoredWidthSchema); | ||
| setUnsaved(saved ? null : { storageKey: nextStorageKey, storedWidth, width: nextWidth }); | ||
|
Comment on lines
+62
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Restore the current key's width when a drag commits to a different key. A drag that starts on key A and survives a switch to key B still writes its width to the host on every move. When the drag ends, Suggested fix
|
||
| }; | ||
|
|
||
| const drag = useResizeDrag<HTMLElement>((event) => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalidate the failed-write fallback after a storage update.
Suppose the saved width is
400and a rejected resize records500. An external update to550correctly displays550. If another external update stores400, this comparison becomes true again and displays the stale500instead of the saved400.Discard the fallback when an external update supersedes it. Comparing only the current value with the original baseline lets an old failed resize override a newer saved width.