Skip to content

Commit

Permalink
fix: retain selection state when restoring webview (#544)
Browse files Browse the repository at this point in the history
Fixes #529
  • Loading branch information
connor4312 authored Nov 1, 2024
1 parent 2c74447 commit e39b16d
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 6 deletions.
21 changes: 18 additions & 3 deletions media/editor/dataDisplayContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { createContext, useContext, useEffect, useState } from "react";
import { SetterOrUpdater } from "recoil";
import { HexDocumentEdit } from "../../shared/hexDocumentModel";
import { MessageType } from "../../shared/protocol";
import { Range, getRangeSelectionsFromStack } from "../../shared/util/range";
import { Range, RangeDirection, getRangeSelectionsFromStack } from "../../shared/util/range";
import _style from "./dataDisplayContext.css";
import { messageHandler, registerHandler } from "./state";
import { getWebviewState, messageHandler, registerHandler, setWebviewState } from "./state";
import { throwOnUndefinedAccessInDev } from "./util";

const style = throwOnUndefinedAccessInDev(_style);
Expand Down Expand Up @@ -34,12 +34,18 @@ export class FocusedElement {
}
}

const selectionStateKey = "DisplayContextSelection";

type SelectionState = { start: number; end: number; dir: RangeDirection }[];

/**
* Data management context component. Initially we used Recoil for this, but
* this ended up introducing performance issues with very many components.
*/
export class DisplayContext {
private _selection: Range[] = [];
private _selection: Range[] = getWebviewState<SelectionState>(selectionStateKey, []).map(
r => new Range(r.start, r.end, r.dir),
);
private _hoveredByte?: FocusedElement;
private _focusedByte?: FocusedElement;
private _unsavedRanges: readonly Range[] = [];
Expand Down Expand Up @@ -288,6 +294,15 @@ export class DisplayContext {
selected += range.size;
}

setWebviewState(
selectionStateKey,
this._selection.map(r => ({
start: r.start,
end: r.end,
dir: r.direction,
})) satisfies SelectionState,
);

messageHandler.sendEvent({
type: MessageType.SetSelectedCount,
selected: selected,
Expand Down
4 changes: 2 additions & 2 deletions media/editor/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ export const usePersistedState = <T>(
key: string,
defaultValue: T,
): [T, React.Dispatch<React.SetStateAction<T>>] => {
const [value, setValue] = useState<T>(select.vscode.getState()?.[key] ?? defaultValue);
const [value, setValue] = useState<T>(select.getWebviewState(key, defaultValue));

useLazyEffect(() => {
select.vscode.setState({ ...select.vscode.getState(), [key]: value });
select.setWebviewState(key, value);
}, [value]);

return [value, setValue];
Expand Down
10 changes: 9 additions & 1 deletion media/editor/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,14 @@ const acquireVsCodeApi: () => {

export const vscode = acquireVsCodeApi?.();

export const setWebviewState = (key: string, value: unknown) => {
vscode.setState?.({ ...vscode.getState(), [key]: value });
};

export const getWebviewState = <T>(key: string, defaultValue: T): T => {
return vscode.getState?.()[key] ?? defaultValue;
};

type HandlerFn = (message: ToWebviewMessage) => Promise<FromWebviewMessage> | undefined;

const handles: { [T in ToWebviewMessage["type"]]?: HandlerFn | HandlerFn[] } = {};
Expand Down Expand Up @@ -469,7 +477,7 @@ export const decoratorsPage = selectorFamily({
const searcherByEnd = binarySearch<HexDecorator>(decorator => decorator.range.end);
const startIndex = searcherByEnd(pageSize * pageNumber, allDecorators);
const searcherByStart = binarySearch<HexDecorator>(d => d.range.start);
const endIndex = searcherByStart(pageSize * pageNumber + pageSize+1, allDecorators);
const endIndex = searcherByStart(pageSize * pageNumber + pageSize + 1, allDecorators);
return allDecorators.slice(startIndex, endIndex);
},
});
Expand Down

0 comments on commit e39b16d

Please sign in to comment.