diff --git a/package.json b/package.json index f63aecf..c7ba199 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@fontsource-variable/fira-code": "^5.1.0", + "@fontsource/space-mono": "^5.1.1", "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-label": "^2.1.0", @@ -81,4 +82,4 @@ "vite-bundle-visualizer": "^1.2.1", "vite-plugin-static-copy": "^2.1.0" } -} \ No newline at end of file +} diff --git a/src/components/Editor.tsx b/src/components/Editor.tsx index 53e6df2..3983dba 100644 --- a/src/components/Editor.tsx +++ b/src/components/Editor.tsx @@ -5,6 +5,7 @@ import { LoaderCircle } from "lucide-react"; import { dbExistsResource, useDoc } from "@/hooks/use-doc"; import * as Y from "yjs"; import { toast } from "sonner"; +import { usePosition } from "@/hooks/use-position"; const EditorMenu = lazy(() => import("./EditorMenu")); @@ -20,12 +21,11 @@ const Loading = () => { const EditorView = ({ doc, firstLoad }: { doc: Y.Doc; firstLoad: boolean }) => { const editor = useMemo(() => { const editor = new TiptapEditor({ - autofocus: true, extensions: [...loadExtensions(doc)], editorProps: { attributes: { class: - "!w-full prose !max-w-none dark:prose-invert prose-md leading-tight focus:outline-none min-h-[90vh]", + "!w-full prose !max-w-none dark:prose-invert prose-md leading-tight focus:outline-none min-h-[60vh]", }, }, }); @@ -35,17 +35,22 @@ const EditorView = ({ doc, firstLoad }: { doc: Y.Doc; firstLoad: boolean }) => { return editor; }, [doc, firstLoad]); - useEffect(() => { - if (!editor.isFocused) { - editor.commands.focus("end"); - } - }, [editor]); + usePosition(doc); return ( -
- + <> +
+ +
{ + // Focus the editor at the end when clicking on the empty space + editor.commands.focus("end"); + }}>
+
-
+ ); }; @@ -57,7 +62,9 @@ export const Editor = () => { if (!dbExists) { // Display welcome toast const timer = setTimeout(() => { - toast(✨ Welcome to Strophe. Add some sparkle to your notes.); + toast( + ✨ Welcome to Strophe. Add some sparkle to your notes. + ); }, 100); return () => clearTimeout(timer); diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..01a64c1 --- /dev/null +++ b/src/constants.ts @@ -0,0 +1 @@ +export const dbName = "st-content"; \ No newline at end of file diff --git a/src/hooks/use-doc.ts b/src/hooks/use-doc.ts index ab00eaf..49de1b8 100644 --- a/src/hooks/use-doc.ts +++ b/src/hooks/use-doc.ts @@ -1,8 +1,9 @@ import * as Y from "yjs"; import { IndexeddbPersistence } from "y-indexeddb"; import { useEffect } from "react"; +import { dbName } from "@/constants"; + -const dbName = "st-content"; export const getDbExists = () => { let status = "pending"; diff --git a/src/hooks/use-position.ts b/src/hooks/use-position.ts new file mode 100644 index 0000000..15a090d --- /dev/null +++ b/src/hooks/use-position.ts @@ -0,0 +1,31 @@ +import { useEffect, useMemo } from "react"; +import * as Y from "yjs"; + +export const usePosition = (doc: Y.Doc) => { + const position = useMemo(() => { + const position: Y.Map = doc.getMap("position"); + return position; + }, [doc]); + + useEffect(() => { + // scroll to the last known scroll position softly + const scroll = position.get("scroll"); + if (scroll) { + window.scrollTo({ top: scroll, behavior: "smooth" }); + } else { + window.scrollTo({ top: 0, behavior: "smooth" }); + } + }, [position]); + + useEffect(() => { + const handleScroll = () => { + position.set("scroll", window.scrollY); + }; + + window.addEventListener("scroll", handleScroll); + + return () => { + window.removeEventListener("scroll", handleScroll); + }; + }, [position]); +}; diff --git a/src/lib/extensions/ClearMarksOnEnter.ts b/src/lib/extensions/ClearMarksOnEnter.ts index 0709cb0..968f98f 100644 --- a/src/lib/extensions/ClearMarksOnEnter.ts +++ b/src/lib/extensions/ClearMarksOnEnter.ts @@ -6,7 +6,6 @@ const ClearMarksOnEnter = Extension.create({ addKeyboardShortcuts() { return { Enter: ({ editor }) => { - console.log("Enter key pressed"); editor .chain() .unsetBold() diff --git a/src/lib/extensions/index.ts b/src/lib/extensions/index.ts index 4f73081..c3d95cb 100644 --- a/src/lib/extensions/index.ts +++ b/src/lib/extensions/index.ts @@ -63,7 +63,7 @@ export const loadExtensions = (doc: Y.Doc) => { types: ["heading", "paragraph"], }), CommitUndo, - ClearMarksOnEnter + ClearMarksOnEnter, ]; return extensions; diff --git a/yarn.lock b/yarn.lock index 5559d8b..8489c53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -373,6 +373,11 @@ resolved "https://registry.npmjs.org/@fontsource-variable/fira-code/-/fira-code-5.1.0.tgz" integrity sha512-fwJbJLvyZ2BhgBSPYCNsrQ6IFQTpRu9GWXY8N20wHTpbhV0Ro5QJihiZV060Ay3kVR6IVH/oSVe/cr7Ube28gg== +"@fontsource/space-mono@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@fontsource/space-mono/-/space-mono-5.1.1.tgz#578ca4313f669eac19a98ea0c64b926005a980fe" + integrity sha512-v72P4frEQhldHTKQv0GqOF2JRRGhMrPAIj50v88qmW1aJW1SJAvjMtFOk/3D+L+dQM0fP2A1ZVzVkDbv8JGf7A== + "@humanfs/core@^0.19.1": version "0.19.1" resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz"