diff --git a/ui/desktop/src/components/settings/chat/ChatSettingsSection.tsx b/ui/desktop/src/components/settings/chat/ChatSettingsSection.tsx index 4df9683dfbe1..fc7ae5acd61e 100644 --- a/ui/desktop/src/components/settings/chat/ChatSettingsSection.tsx +++ b/ui/desktop/src/components/settings/chat/ChatSettingsSection.tsx @@ -3,6 +3,7 @@ import DictationSection from '../dictation/DictationSection'; import { SecurityToggle } from '../security/SecurityToggle'; import { ResponseStylesSection } from '../response_styles/ResponseStylesSection'; import { GoosehintsSection } from './GoosehintsSection'; +import { SpellcheckToggle } from './SpellcheckToggle'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../ui/card'; export default function ChatSettingsSection() { @@ -37,6 +38,7 @@ export default function ChatSettingsSection() { + diff --git a/ui/desktop/src/components/settings/chat/SpellcheckToggle.tsx b/ui/desktop/src/components/settings/chat/SpellcheckToggle.tsx new file mode 100644 index 000000000000..95275746fe8b --- /dev/null +++ b/ui/desktop/src/components/settings/chat/SpellcheckToggle.tsx @@ -0,0 +1,33 @@ +import { useState, useEffect } from 'react'; +import { Switch } from '../../ui/switch'; + +export const SpellcheckToggle = () => { + const [enabled, setEnabled] = useState(true); + + useEffect(() => { + const loadState = async () => { + const state = await window.electron.getSpellcheckState(); + setEnabled(state); + }; + loadState(); + }, []); + + const handleToggle = async (checked: boolean) => { + setEnabled(checked); + await window.electron.setSpellcheck(checked); + }; + + return ( +
+
+

Enable Spellcheck

+

+ Check spelling in the chat input. Requires restart to take effect. +

+
+
+ +
+
+ ); +}; diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index 2bf4fce7a3ad..1699310ba86c 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -559,7 +559,7 @@ const createChat = async ( useContentSize: true, icon: path.join(__dirname, '../images/icon.icns'), webPreferences: { - spellcheck: true, + spellcheck: settings.spellcheckEnabled ?? true, preload: path.join(__dirname, 'preload.js'), webSecurity: true, nodeIntegration: false, @@ -1421,6 +1421,28 @@ ipcMain.handle('get-wakelock-state', () => { } }); +ipcMain.handle('set-spellcheck', async (_event, enable: boolean) => { + try { + const settings = loadSettings(); + settings.spellcheckEnabled = enable; + saveSettings(settings); + return true; + } catch (error) { + console.error('Error setting spellcheck:', error); + return false; + } +}); + +ipcMain.handle('get-spellcheck-state', () => { + try { + const settings = loadSettings(); + return settings.spellcheckEnabled ?? true; + } catch (error) { + console.error('Error getting spellcheck state:', error); + return true; + } +}); + // Add file/directory selection handler ipcMain.handle('select-file-or-directory', async (_event, defaultPath?: string) => { const dialogOptions: OpenDialogOptions = { diff --git a/ui/desktop/src/preload.ts b/ui/desktop/src/preload.ts index 043508a293be..85865de47663 100644 --- a/ui/desktop/src/preload.ts +++ b/ui/desktop/src/preload.ts @@ -96,6 +96,8 @@ type ElectronAPI = { getGoosedHostPort: () => Promise; setWakelock: (enable: boolean) => Promise; getWakelockState: () => Promise; + setSpellcheck: (enable: boolean) => Promise; + getSpellcheckState: () => Promise; openNotificationsSettings: () => Promise; onMouseBackButtonClicked: (callback: () => void) => void; offMouseBackButtonClicked: (callback: () => void) => void; @@ -201,6 +203,8 @@ const electronAPI: ElectronAPI = { getGoosedHostPort: () => ipcRenderer.invoke('get-goosed-host-port'), setWakelock: (enable: boolean) => ipcRenderer.invoke('set-wakelock', enable), getWakelockState: () => ipcRenderer.invoke('get-wakelock-state'), + setSpellcheck: (enable: boolean) => ipcRenderer.invoke('set-spellcheck', enable), + getSpellcheckState: () => ipcRenderer.invoke('get-spellcheck-state'), openNotificationsSettings: () => ipcRenderer.invoke('open-notifications-settings'), onMouseBackButtonClicked: (callback: () => void) => { // Wrapper that ignores the event parameter. diff --git a/ui/desktop/src/utils/settings.ts b/ui/desktop/src/utils/settings.ts index edc3115b1aa1..3eaf5e97d8f4 100644 --- a/ui/desktop/src/utils/settings.ts +++ b/ui/desktop/src/utils/settings.ts @@ -18,6 +18,7 @@ export interface Settings { showMenuBarIcon: boolean; showDockIcon: boolean; enableWakelock: boolean; + spellcheckEnabled: boolean; externalGoosed?: ExternalGoosedConfig; } @@ -31,6 +32,7 @@ const defaultSettings: Settings = { showMenuBarIcon: true, showDockIcon: true, enableWakelock: false, + spellcheckEnabled: true, }; // Settings management