diff --git a/frontend/app/block/block.tsx b/frontend/app/block/block.tsx index 68713bc58..8ddabc7d0 100644 --- a/frontend/app/block/block.tsx +++ b/frontend/app/block/block.tsx @@ -602,6 +602,11 @@ const BlockFull = React.memo(({ blockId, layoutModel }: BlockProps) => { setBlockClicked(true); }, []); + let { viewElem, viewModel } = React.useMemo( + () => getViewElemAndModel(blockId, blockData?.view, blockRef), + [blockId, blockData?.view, blockRef] + ); + const determineFocusedChild = React.useCallback( (event: React.FocusEvent) => { setFocusedChild(event.target); @@ -609,33 +614,13 @@ const BlockFull = React.memo(({ blockId, layoutModel }: BlockProps) => { [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 focusableChildren = getFocusableChildren(); - if (focusableChildren.length == 0) { - focusElemRef.current.focus({ preventScroll: true }); - } else { - const firstFocusableChild = focusableChildren[0] as HTMLElement; - if (!firstFocusableChild.classList.contains("url-input")) { - firstFocusableChild.focus({ preventScroll: true }); - } + const ok = viewModel?.giveFocus?.(); + if (ok) { + return; } - }, [getFocusableChildren]); - - let { viewElem, viewModel } = React.useMemo( - () => getViewElemAndModel(blockId, blockData?.view, blockRef), - [blockId, blockData?.view, blockRef] - ); + focusElemRef.current.focus({ preventScroll: true }); + }, []); if (!blockId || !blockData) return null; @@ -658,14 +643,7 @@ const BlockFull = React.memo(({ blockId, layoutModel }: BlockProps) => { viewModel={viewModel} >
- {}} - disabled={getFocusableChildren().length > 0} - /> + {}} />
diff --git a/frontend/app/view/directorypreview.tsx b/frontend/app/view/directorypreview.tsx index 46478c912..9a4f39a5f 100644 --- a/frontend/app/view/directorypreview.tsx +++ b/frontend/app/view/directorypreview.tsx @@ -560,6 +560,14 @@ function DirectoryPreview({ fileNameAtom, model }: DirectoryPreviewProps) { } }, [filteredData]); + const inputRef = React.useRef(null); + React.useEffect(() => { + model.directoryInputElem = inputRef.current; + return () => { + model.directoryInputElem = null; + }; + }, []); + return (
{}} //for nuisance warnings maxLength={400} - autoFocus={true} value={searchText} />
diff --git a/frontend/app/view/preview.tsx b/frontend/app/view/preview.tsx index 71bad903e..c854c72c5 100644 --- a/frontend/app/view/preview.tsx +++ b/frontend/app/view/preview.tsx @@ -54,6 +54,7 @@ export class PreviewModel implements ViewModel { showHiddenFiles: jotai.PrimitiveAtom; refreshVersion: jotai.PrimitiveAtom; refreshCallback: () => void; + directoryInputElem: HTMLInputElement; setPreviewFileName(fileName: string) { services.ObjectService.UpdateObjectMeta(`block:${this.blockId}`, { file: fileName }); @@ -101,14 +102,14 @@ export class PreviewModel implements ViewModel { }); this.viewName = jotai.atom("Preview"); this.viewText = jotai.atom((get) => { - const viewTextChildren: HeaderElem[] = [ - { - elemtype: "input", - value: get(this.fileName), - isDisabled: true, - }, - ]; if (get(this.isCeView)) { + const viewTextChildren: HeaderElem[] = [ + { + elemtype: "input", + value: get(this.fileName), + isDisabled: true, + }, + ]; if (get(this.ceReadOnly) == false) { viewTextChildren.push( { @@ -138,6 +139,13 @@ export class PreviewModel implements ViewModel { children: viewTextChildren, }, ] as HeaderElem[]; + } else { + return [ + { + elemtype: "text", + text: get(this.fileName), + }, + ]; } }); @@ -272,6 +280,14 @@ export class PreviewModel implements ViewModel { }); return menuItems; } + + giveFocus(): boolean { + if (this.directoryInputElem) { + this.directoryInputElem.focus({ preventScroll: true }); + return true; + } + return false; + } } function makePreviewModel(blockId: string): PreviewModel { diff --git a/frontend/app/view/webview.tsx b/frontend/app/view/webview.tsx index 529756d11..9f5a4a14b 100644 --- a/frontend/app/view/webview.tsx +++ b/frontend/app/view/webview.tsx @@ -280,6 +280,13 @@ export class WebViewModel implements ViewModel { getUrl() { return this.historyStack[this.historyIndex]; } + + giveFocus(): boolean { + if (this.urlInputRef.current) { + this.urlInputRef.current.focus({ preventScroll: true }); + return true; + } + } } function makeWebViewModel(blockId: string): WebViewModel { diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index 4c518d9b3..7be0890af 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -173,6 +173,7 @@ declare global { onSearchChange?: (text: string) => void; onSearch?: (text: string) => void; getSettingsMenuItems?: () => ContextMenuItem[]; + giveFocus?: () => boolean; } // jotai doesn't export this type :/