feat: you can now focus onto pages by pressing '/' from anywhere!

This commit is contained in:
Palanikannan M 2024-06-12 20:35:05 +05:30
parent 34e1be7ba0
commit 123f1f99c1
5 changed files with 49 additions and 0 deletions

View File

@ -187,6 +187,24 @@ export const useEditor = ({
scrollSummary(editorRef.current, marking); scrollSummary(editorRef.current, marking);
}, },
isEditorReadyToDiscard: () => editorRef.current?.storage.image.uploadInProgress === false, isEditorReadyToDiscard: () => editorRef.current?.storage.image.uploadInProgress === false,
isEditorFocused: () => editorRef.current?.isFocused,
setFocusAtSavedSelection: () => {
if (!editorRef.current || editorRef.current.isDestroyed) {
console.error("Editor reference is not available or has been destroyed.");
return;
}
try {
let focusPosition = 0;
if (savedSelection) {
focusPosition = savedSelection.from;
}
const docSize = editorRef.current.state.doc.content.size;
const safePosition = Math.max(0, Math.min(focusPosition, docSize));
editorRef.current.chain().focus().setTextSelection(safePosition).run();
} catch (error) {
console.error("An error occurred while setting focus at position:", error);
}
},
setFocusAtPosition: (position: number) => { setFocusAtPosition: (position: number) => {
if (!editorRef.current || editorRef.current.isDestroyed) { if (!editorRef.current || editorRef.current.isDestroyed) {
console.error("Editor reference is not available or has been destroyed."); console.error("Editor reference is not available or has been destroyed.");

View File

@ -16,4 +16,6 @@ export interface EditorRefApi extends EditorReadOnlyRefApi {
onStateChange: (callback: () => void) => () => void; onStateChange: (callback: () => void) => () => void;
setFocusAtPosition: (position: number) => void; setFocusAtPosition: (position: number) => void;
isEditorReadyToDiscard: () => boolean; isEditorReadyToDiscard: () => boolean;
isEditorFocused: () => boolean;
setFocusAtSavedSelection: () => void;
} }

View File

@ -139,6 +139,9 @@ export const CoreEditorExtensions = ({
}), }),
Placeholder.configure({ Placeholder.configure({
placeholder: ({ editor, node }) => { placeholder: ({ editor, node }) => {
if (!editor.isFocused && editor.state.doc.content.size === 2) {
return "Focus by pressing /";
}
if (node.type.name === "heading") return `Heading ${node.attrs.level}`; if (node.type.name === "heading") return `Heading ${node.attrs.level}`;
if (editor.storage.image.uploadInProgress) return ""; if (editor.storage.image.uploadInProgress) return "";

View File

@ -20,6 +20,7 @@ import { PageEditorBody, PageEditorHeaderRoot } from "@/components/pages";
import { cn } from "@/helpers/common.helper"; import { cn } from "@/helpers/common.helper";
// hooks // hooks
import { usePage, useProjectPages } from "@/hooks/store"; import { usePage, useProjectPages } from "@/hooks/store";
import useFocusOnSlash from "@/hooks/use-focus-on-slash";
const PageDetailsPage = observer(() => { const PageDetailsPage = observer(() => {
// states // states
@ -29,6 +30,8 @@ const PageDetailsPage = observer(() => {
// refs // refs
const editorRef = useRef<EditorRefApi>(null); const editorRef = useRef<EditorRefApi>(null);
const readOnlyEditorRef = useRef<EditorRefApi>(null); const readOnlyEditorRef = useRef<EditorRefApi>(null);
// Use the custom hook to focus on the editor when "/" is pressed
useFocusOnSlash(editorRef);
// router // router
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, pageId } = useParams(); const { workspaceSlug, projectId, pageId } = useParams();

View File

@ -0,0 +1,23 @@
import { useEffect } from "react";
import { EditorRefApi } from "@plane/document-editor";
const useFocusOnSlash = (editorRef: React.RefObject<EditorRefApi>) => {
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (!editorRef.current?.isEditorFocused()) {
if (e.key === "/") {
e.preventDefault();
editorRef.current?.setFocusAtSavedSelection();
}
}
};
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [editorRef]);
};
export default useFocusOnSlash;