create an explicit giveFocus() method on the viewmodel. fix preview header text

This commit is contained in:
sawka 2024-07-22 16:41:18 -07:00
parent b2ee164b85
commit 198ec60e69
5 changed files with 51 additions and 41 deletions

View File

@ -602,6 +602,11 @@ const BlockFull = React.memo(({ blockId, layoutModel }: BlockProps) => {
setBlockClicked(true); setBlockClicked(true);
}, []); }, []);
let { viewElem, viewModel } = React.useMemo(
() => getViewElemAndModel(blockId, blockData?.view, blockRef),
[blockId, blockData?.view, blockRef]
);
const determineFocusedChild = React.useCallback( const determineFocusedChild = React.useCallback(
(event: React.FocusEvent<HTMLDivElement, Element>) => { (event: React.FocusEvent<HTMLDivElement, Element>) => {
setFocusedChild(event.target); setFocusedChild(event.target);
@ -609,33 +614,13 @@ const BlockFull = React.memo(({ blockId, layoutModel }: BlockProps) => {
[setFocusedChild] [setFocusedChild]
); );
const getFocusableChildren = React.useCallback(() => {
if (blockRef.current == null) {
return [];
}
return Array.from(
blockRef.current.querySelectorAll(
'a[href], area[href], input:not([disabled]), select:not([disabled]), button:not([disabled]), [tabindex="0"]'
)
).filter((elem) => elem.id != `${blockId}-dummy-focus`);
}, [blockRef.current]);
const setFocusTarget = React.useCallback(() => { const setFocusTarget = React.useCallback(() => {
const focusableChildren = getFocusableChildren(); const ok = viewModel?.giveFocus?.();
if (focusableChildren.length == 0) { if (ok) {
focusElemRef.current.focus({ preventScroll: true }); return;
} else {
const firstFocusableChild = focusableChildren[0] as HTMLElement;
if (!firstFocusableChild.classList.contains("url-input")) {
firstFocusableChild.focus({ preventScroll: true });
}
} }
}, [getFocusableChildren]); focusElemRef.current.focus({ preventScroll: true });
}, []);
let { viewElem, viewModel } = React.useMemo(
() => getViewElemAndModel(blockId, blockData?.view, blockRef),
[blockId, blockData?.view, blockRef]
);
if (!blockId || !blockData) return null; if (!blockId || !blockData) return null;
@ -658,14 +643,7 @@ const BlockFull = React.memo(({ blockId, layoutModel }: BlockProps) => {
viewModel={viewModel} viewModel={viewModel}
> >
<div key="focuselem" className="block-focuselem"> <div key="focuselem" className="block-focuselem">
<input <input type="text" value="" ref={focusElemRef} id={`${blockId}-dummy-focus`} onChange={() => {}} />
type="text"
value=""
ref={focusElemRef}
id={`${blockId}-dummy-focus`}
onChange={() => {}}
disabled={getFocusableChildren().length > 0}
/>
</div> </div>
<div key="content" className="block-content"> <div key="content" className="block-content">
<ErrorBoundary> <ErrorBoundary>

View File

@ -560,6 +560,14 @@ function DirectoryPreview({ fileNameAtom, model }: DirectoryPreviewProps) {
} }
}, [filteredData]); }, [filteredData]);
const inputRef = React.useRef<HTMLInputElement>(null);
React.useEffect(() => {
model.directoryInputElem = inputRef.current;
return () => {
model.directoryInputElem = null;
};
}, []);
return ( return (
<div <div
className="dir-table-container" className="dir-table-container"
@ -574,9 +582,9 @@ function DirectoryPreview({ fileNameAtom, model }: DirectoryPreviewProps) {
<input <input
type="text" type="text"
className="dir-table-search-box" className="dir-table-search-box"
ref={inputRef}
onChange={() => {}} //for nuisance warnings onChange={() => {}} //for nuisance warnings
maxLength={400} maxLength={400}
autoFocus={true}
value={searchText} value={searchText}
/> />
</div> </div>

View File

@ -54,6 +54,7 @@ export class PreviewModel implements ViewModel {
showHiddenFiles: jotai.PrimitiveAtom<boolean>; showHiddenFiles: jotai.PrimitiveAtom<boolean>;
refreshVersion: jotai.PrimitiveAtom<number>; refreshVersion: jotai.PrimitiveAtom<number>;
refreshCallback: () => void; refreshCallback: () => void;
directoryInputElem: HTMLInputElement;
setPreviewFileName(fileName: string) { setPreviewFileName(fileName: string) {
services.ObjectService.UpdateObjectMeta(`block:${this.blockId}`, { file: fileName }); services.ObjectService.UpdateObjectMeta(`block:${this.blockId}`, { file: fileName });
@ -101,14 +102,14 @@ export class PreviewModel implements ViewModel {
}); });
this.viewName = jotai.atom("Preview"); this.viewName = jotai.atom("Preview");
this.viewText = jotai.atom((get) => { this.viewText = jotai.atom((get) => {
const viewTextChildren: HeaderElem[] = [
{
elemtype: "input",
value: get(this.fileName),
isDisabled: true,
},
];
if (get(this.isCeView)) { if (get(this.isCeView)) {
const viewTextChildren: HeaderElem[] = [
{
elemtype: "input",
value: get(this.fileName),
isDisabled: true,
},
];
if (get(this.ceReadOnly) == false) { if (get(this.ceReadOnly) == false) {
viewTextChildren.push( viewTextChildren.push(
{ {
@ -138,6 +139,13 @@ export class PreviewModel implements ViewModel {
children: viewTextChildren, children: viewTextChildren,
}, },
] as HeaderElem[]; ] as HeaderElem[];
} else {
return [
{
elemtype: "text",
text: get(this.fileName),
},
];
} }
}); });
@ -272,6 +280,14 @@ export class PreviewModel implements ViewModel {
}); });
return menuItems; return menuItems;
} }
giveFocus(): boolean {
if (this.directoryInputElem) {
this.directoryInputElem.focus({ preventScroll: true });
return true;
}
return false;
}
} }
function makePreviewModel(blockId: string): PreviewModel { function makePreviewModel(blockId: string): PreviewModel {

View File

@ -280,6 +280,13 @@ export class WebViewModel implements ViewModel {
getUrl() { getUrl() {
return this.historyStack[this.historyIndex]; return this.historyStack[this.historyIndex];
} }
giveFocus(): boolean {
if (this.urlInputRef.current) {
this.urlInputRef.current.focus({ preventScroll: true });
return true;
}
}
} }
function makeWebViewModel(blockId: string): WebViewModel { function makeWebViewModel(blockId: string): WebViewModel {

View File

@ -173,6 +173,7 @@ declare global {
onSearchChange?: (text: string) => void; onSearchChange?: (text: string) => void;
onSearch?: (text: string) => void; onSearch?: (text: string) => void;
getSettingsMenuItems?: () => ContextMenuItem[]; getSettingsMenuItems?: () => ContextMenuItem[];
giveFocus?: () => boolean;
} }
// jotai doesn't export this type :/ // jotai doesn't export this type :/