diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 72b6d15d..cbc102b5 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -114,6 +114,10 @@ pub struct Settings { pub pinned_note_ids: Option>, #[serde(rename = "textDirection")] pub text_direction: Option, + #[serde(rename = "spellCheckEnabled")] + pub spell_check_enabled: Option, + #[serde(rename = "autoCorrectEnabled")] + pub auto_correct_enabled: Option, #[serde(rename = "editorWidth")] pub editor_width: Option, #[serde(rename = "defaultNoteName")] diff --git a/src/components/editor/Editor.tsx b/src/components/editor/Editor.tsx index 32a8159c..2bdd3932 100644 --- a/src/components/editor/Editor.tsx +++ b/src/components/editor/Editor.tsx @@ -546,7 +546,7 @@ export function Editor({ const pinNote = notesCtx?.pinNote; const unpinNote = notesCtx?.unpinNote; const notes = notesCtx?.notes; - const { textDirection } = useTheme(); + const { textDirection, spellCheckEnabled, autoCorrectEnabled } = useTheme(); const [isSaving, setIsSaving] = useState(false); // Force re-render when selection changes to update toolbar active states const [, setSelectionKey] = useState(0); @@ -1134,8 +1134,8 @@ export function Editor({ attributes: { class: "prose prose-lg dark:prose-invert max-w-3xl mx-auto focus:outline-none min-h-full px-6 pt-8 pb-24", - spellcheck: "true", - autocorrect: "on", + spellcheck: spellCheckEnabled ? "true" : "false", + autocorrect: autoCorrectEnabled ? "on" : "off", autocapitalize: "sentences", }, // Serialize copied text as markdown instead of plain text diff --git a/src/components/settings/EditorSettingsSection.tsx b/src/components/settings/EditorSettingsSection.tsx index 997e9180..8413999d 100644 --- a/src/components/settings/EditorSettingsSection.tsx +++ b/src/components/settings/EditorSettingsSection.tsx @@ -66,6 +66,10 @@ export function AppearanceSettingsSection() { resetEditorFontSettings, textDirection, setTextDirection, + spellCheckEnabled, + setSpellCheckEnabled, + autoCorrectEnabled, + setAutoCorrectEnabled, editorWidth, setEditorWidth, interfaceZoom, @@ -179,6 +183,64 @@ export function AppearanceSettingsSection() { {/* Divider */}
+ {/* Writing Section */} +
+

Writing

+
+
+ +
+ + +
+
+ +
+ +
+ + +
+
+
+

+ Auto Correct requires Spell Check. Enabling it also enables Spell + Check. Spell checking may reduce performance when inserting large + amounts of text. +

+
+ + {/* Divider */} +
+ {/* Typography Section */}
diff --git a/src/context/ThemeContext.tsx b/src/context/ThemeContext.tsx index fd33071d..d7f97698 100644 --- a/src/context/ThemeContext.tsx +++ b/src/context/ThemeContext.tsx @@ -106,6 +106,10 @@ interface ThemeContextType { reloadSettings: () => Promise; textDirection: TextDirection; setTextDirection: (dir: TextDirection) => void; + spellCheckEnabled: boolean; + setSpellCheckEnabled: (enabled: boolean) => void; + autoCorrectEnabled: boolean; + setAutoCorrectEnabled: (enabled: boolean) => void; editorWidth: EditorWidth; setEditorWidth: (width: EditorWidth) => void; interfaceZoom: number; @@ -186,6 +190,8 @@ export function ThemeProvider({ children }: ThemeProviderProps) { Required >(defaultEditorFontSettings); const [textDirection, setTextDirectionState] = useState("auto"); + const [spellCheckEnabled, setSpellCheckEnabledState] = useState(false); + const [autoCorrectEnabled, setAutoCorrectEnabledState] = useState(false); const [editorWidth, setEditorWidthState] = useState("normal"); const [interfaceZoom, setInterfaceZoomState] = useState(1.0); const [customEditorWidthPx, setCustomEditorWidthPxState] = useState( @@ -225,6 +231,11 @@ export function ThemeProvider({ children }: ThemeProviderProps) { if (isTextDirection(settings.textDirection)) { setTextDirectionState(settings.textDirection); } + const isSpellCheckEnabled = settings.spellCheckEnabled === true; + setSpellCheckEnabledState(isSpellCheckEnabled); + setAutoCorrectEnabledState( + isSpellCheckEnabled && settings.autoCorrectEnabled === true, + ); if ( settings.editorWidth === "narrow" || settings.editorWidth === "normal" || @@ -431,6 +442,40 @@ export function ThemeProvider({ children }: ThemeProviderProps) { } }, []); + const setSpellCheckEnabled = useCallback(async (enabled: boolean) => { + setSpellCheckEnabledState(enabled); + if (!enabled) { + setAutoCorrectEnabledState(false); + } + try { + const settings = await getSettings(); + await updateSettings({ + ...settings, + spellCheckEnabled: enabled, + autoCorrectEnabled: enabled && autoCorrectEnabled, + }); + } catch (error) { + console.error("Failed to save spell check setting:", error); + } + }, [autoCorrectEnabled]); + + const setAutoCorrectEnabled = useCallback(async (enabled: boolean) => { + setAutoCorrectEnabledState(enabled); + if (enabled) { + setSpellCheckEnabledState(true); + } + try { + const settings = await getSettings(); + await updateSettings({ + ...settings, + spellCheckEnabled: enabled || spellCheckEnabled, + autoCorrectEnabled: enabled, + }); + } catch (error) { + console.error("Failed to save auto correct setting:", error); + } + }, [spellCheckEnabled]); + // Save and set editor width const setEditorWidth = useCallback(async (width: EditorWidth) => { setEditorWidthState(width); @@ -620,6 +665,10 @@ export function ThemeProvider({ children }: ThemeProviderProps) { reloadSettings, textDirection, setTextDirection, + spellCheckEnabled, + setSpellCheckEnabled, + autoCorrectEnabled, + setAutoCorrectEnabled, editorWidth, setEditorWidth, interfaceZoom, diff --git a/src/types/note.ts b/src/types/note.ts index 387a9b61..a2706c8d 100644 --- a/src/types/note.ts +++ b/src/types/note.ts @@ -51,6 +51,8 @@ export interface Settings { foldersEnabled?: boolean; pinnedNoteIds?: string[]; textDirection?: TextDirection; + spellCheckEnabled?: boolean; + autoCorrectEnabled?: boolean; editorWidth?: EditorWidth; customEditorWidthPx?: number; sidebarWidthPx?: number;