From ee5ebfe7eb9123492af96899c4608658db6445b4 Mon Sep 17 00:00:00 2001 From: Ammar Ahmed Date: Thu, 15 Feb 2024 16:04:03 +0500 Subject: [PATCH] editor: fix keyboard focus issues on mobile --- packages/editor/src/components/button.tsx | 4 +++- .../src/components/popup-presenter/index.tsx | 1 + .../extensions/keep-in-view/keep-in-view.ts | 11 +++++++-- .../src/extensions/task-item/component.tsx | 2 +- .../editor/src/toolbar/components/popup.tsx | 6 ++--- .../src/toolbar/components/tool-button.tsx | 6 ++++- .../src/toolbar/popups/color-picker.tsx | 23 +++++++++++++++++-- packages/editor/src/toolbar/tools/block.tsx | 6 ++++- packages/editor/src/toolbar/tools/colors.tsx | 13 +++++++---- packages/editor/src/toolbar/tools/lists.tsx | 6 ++++- 10 files changed, 61 insertions(+), 17 deletions(-) diff --git a/packages/editor/src/components/button.tsx b/packages/editor/src/components/button.tsx index 8fa74df76..7f3189b6e 100644 --- a/packages/editor/src/components/button.tsx +++ b/packages/editor/src/components/button.tsx @@ -33,7 +33,9 @@ const _Button = ( if (!buttonRef.current) return; function onMouseDown(e: MouseEvent) { - e.preventDefault(); + if (globalThis.keyboardShown) { + e.preventDefault(); + } } buttonRef.current.addEventListener("mousedown", onMouseDown, { diff --git a/packages/editor/src/components/popup-presenter/index.tsx b/packages/editor/src/components/popup-presenter/index.tsx index 4e6008a8a..9bd2de96f 100644 --- a/packages/editor/src/components/popup-presenter/index.tsx +++ b/packages/editor/src/components/popup-presenter/index.tsx @@ -56,6 +56,7 @@ export function PopupWrapper(props: PropsWithChildren) { position={position} blocking focusOnRender + className={isMobile ? "editor-mobile-toolbar-popup" : undefined} isMobile={isMobile} {...presenterProps} isOpen={isPopupOpen} diff --git a/packages/editor/src/extensions/keep-in-view/keep-in-view.ts b/packages/editor/src/extensions/keep-in-view/keep-in-view.ts index cc8320d15..7cff15375 100644 --- a/packages/editor/src/extensions/keep-in-view/keep-in-view.ts +++ b/packages/editor/src/extensions/keep-in-view/keep-in-view.ts @@ -64,9 +64,14 @@ export function keepLastLineInView( ) { if (!editor.state.selection.empty) return; + const isPopupVisible = document.getElementsByClassName( + "editor-mobile-toolbar-popup" + ); + const node = editor.state.selection.$from; const { top } = posToDOMRect(editor.view, node.pos, node.pos + 1); - const isBelowThreshold = window.innerHeight - top < THRESHOLD; + const isBelowThreshold = + window.innerHeight - top < (isPopupVisible ? THRESHOLD + 60 : THRESHOLD); const isAboveThreshold = top < THRESHOLD; const DIFF_BOTTOM = THRESHOLD - (window.innerHeight - top); @@ -83,7 +88,9 @@ export function keepLastLineInView( const container = findScrollContainer(domNode); if (container) { container.scrollBy({ - top: isAboveThreshold ? DIFF_TOP + 10 : DIFF_BOTTOM, + top: isAboveThreshold + ? DIFF_TOP + 10 + : DIFF_BOTTOM + (isPopupVisible ? 60 : 0), behavior: "smooth" }); } else domNode.scrollIntoView({ behavior: "smooth", block: "center" }); diff --git a/packages/editor/src/extensions/task-item/component.tsx b/packages/editor/src/extensions/task-item/component.tsx index 138b47d01..0581e3fc9 100644 --- a/packages/editor/src/extensions/task-item/component.tsx +++ b/packages/editor/src/extensions/task-item/component.tsx @@ -103,7 +103,7 @@ export function TaskItemComponent( fontFamily: "inherit" }} onMouseDown={(e) => { - if (globalThis["keyboardShown"]) { + if (globalThis.keyboardShown) { e.preventDefault(); } toggle(); diff --git a/packages/editor/src/toolbar/components/popup.tsx b/packages/editor/src/toolbar/components/popup.tsx index 058f8e1e3..c7491d263 100644 --- a/packages/editor/src/toolbar/components/popup.tsx +++ b/packages/editor/src/toolbar/components/popup.tsx @@ -17,12 +17,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { Button, Flex, Text } from "@theme-ui/components"; +import { EmotionThemeProvider } from "@notesnook/theme"; import { Icon } from "@notesnook/ui"; -import { Icons } from "../icons"; +import { Button, Flex, Text } from "@theme-ui/components"; import { PropsWithChildren } from "react"; import { DesktopOnly, MobileOnly } from "../../components/responsive"; -import { EmotionThemeProvider } from "@notesnook/theme"; +import { Icons } from "../icons"; type Action = { title: string; diff --git a/packages/editor/src/toolbar/components/tool-button.tsx b/packages/editor/src/toolbar/components/tool-button.tsx index d84e0e377..927fe6b71 100644 --- a/packages/editor/src/toolbar/components/tool-button.tsx +++ b/packages/editor/src/toolbar/components/tool-button.tsx @@ -74,7 +74,11 @@ export const ToolButton = React.memo( }, ...sx }} - onMouseDown={(e) => e.preventDefault()} + onMouseDown={(e) => { + if (globalThis.keyboardShown) { + e.preventDefault(); + } + }} {...buttonProps} > void; @@ -69,7 +71,8 @@ export function ColorPicker(props: ColorPickerProps) { expanded, onSave, colors = [], - onDelete + onDelete, + editor } = props; const ref = useRef(null); const [isPickerOpen, setIsPickerOpen] = useState(expanded || false); @@ -205,7 +208,23 @@ export function ColorPicker(props: ColorPickerProps) { setIsPickerOpen((s) => !s)} + onClick={() => { + setIsPickerOpen((s) => { + if (s) { + editor.current?.commands.focus(); + } else { + const onSelectionChange = () => { + setIsPickerOpen(false); + editor.current?.off( + "selectionUpdate", + onSelectionChange + ); + }; + editor.current?.on("selectionUpdate", onSelectionChange); + } + return !s; + }); + }} title="Choose custom color" iconSize={18} bg={currentColor} diff --git a/packages/editor/src/toolbar/tools/block.tsx b/packages/editor/src/toolbar/tools/block.tsx index 3b0aae9ac..fc73933cd 100644 --- a/packages/editor/src/toolbar/tools/block.tsx +++ b/packages/editor/src/toolbar/tools/block.tsx @@ -72,7 +72,11 @@ export function InsertBlock(props: ToolProps) { mr: 0 } }} - onMouseDown={(e) => e.preventDefault()} + onMouseDown={(e) => { + if (globalThis.keyboardShown) { + e.preventDefault(); + } + }} onClick={() => setIsOpen((s) => !s)} > diff --git a/packages/editor/src/toolbar/tools/colors.tsx b/packages/editor/src/toolbar/tools/colors.tsx index ef8e9b9a7..bc04cd815 100644 --- a/packages/editor/src/toolbar/tools/colors.tsx +++ b/packages/editor/src/toolbar/tools/colors.tsx @@ -89,6 +89,7 @@ export function ColorTool(props: ColorToolProps) { > { if (DEFAULT_COLORS.includes(color)) return; @@ -108,7 +109,9 @@ export function ColorTool(props: ColorToolProps) { onColorChange(color); config.set(cacheKey, color); }} - onClose={() => setIsOpen(false)} + onClose={() => { + setIsOpen(false); + }} title={title} /> @@ -126,8 +129,8 @@ export function Highlight(props: ToolProps) { title={"Background color"} onColorChange={(color) => color - ? editor.current?.chain().focus().setHighlight(color).run() - : editor.current?.chain().focus().unsetHighlight().run() + ? editor.current?.chain().setHighlight(color).run() + : editor.current?.chain().unsetHighlight().run() } /> ); @@ -143,8 +146,8 @@ export function TextColor(props: ToolProps) { title="Text color" onColorChange={(color) => color - ? editor.current?.chain().focus().setColor(color).run() - : editor.current?.chain().focus().unsetColor().run() + ? editor.current?.chain().setColor(color).run() + : editor.current?.chain().unsetColor().run() } /> ); diff --git a/packages/editor/src/toolbar/tools/lists.tsx b/packages/editor/src/toolbar/tools/lists.tsx index 090031cdf..c5da7a9d3 100644 --- a/packages/editor/src/toolbar/tools/lists.tsx +++ b/packages/editor/src/toolbar/tools/lists.tsx @@ -223,7 +223,11 @@ function ListThumbnail(props: ListThumbnailProps) { listStyleType, gap: 1 }} - onMouseDown={(e) => e.preventDefault()} + onMouseDown={(e) => { + if (globalThis.keyboardShown) { + e.preventDefault(); + } + }} > {[0, 1, 2].map((i) => (