Spell check setting (#6446)
Co-authored-by: Douwe Osinga <douwe@squareup.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import DictationSection from '../dictation/DictationSection';
|
|||||||
import { SecurityToggle } from '../security/SecurityToggle';
|
import { SecurityToggle } from '../security/SecurityToggle';
|
||||||
import { ResponseStylesSection } from '../response_styles/ResponseStylesSection';
|
import { ResponseStylesSection } from '../response_styles/ResponseStylesSection';
|
||||||
import { GoosehintsSection } from './GoosehintsSection';
|
import { GoosehintsSection } from './GoosehintsSection';
|
||||||
|
import { SpellcheckToggle } from './SpellcheckToggle';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../ui/card';
|
||||||
|
|
||||||
export default function ChatSettingsSection() {
|
export default function ChatSettingsSection() {
|
||||||
@@ -37,6 +38,7 @@ export default function ChatSettingsSection() {
|
|||||||
<Card className="pb-2 rounded-lg">
|
<Card className="pb-2 rounded-lg">
|
||||||
<CardContent className="px-2">
|
<CardContent className="px-2">
|
||||||
<DictationSection />
|
<DictationSection />
|
||||||
|
<SpellcheckToggle />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
|||||||
@@ -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 (
|
||||||
|
<div className="flex items-center justify-between py-2 px-2 hover:bg-background-muted rounded-lg transition-all">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-text-default">Enable Spellcheck</h3>
|
||||||
|
<p className="text-xs text-text-muted max-w-md mt-[2px]">
|
||||||
|
Check spelling in the chat input. Requires restart to take effect.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Switch checked={enabled} onCheckedChange={handleToggle} variant="mono" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
+23
-1
@@ -559,7 +559,7 @@ const createChat = async (
|
|||||||
useContentSize: true,
|
useContentSize: true,
|
||||||
icon: path.join(__dirname, '../images/icon.icns'),
|
icon: path.join(__dirname, '../images/icon.icns'),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
spellcheck: true,
|
spellcheck: settings.spellcheckEnabled ?? true,
|
||||||
preload: path.join(__dirname, 'preload.js'),
|
preload: path.join(__dirname, 'preload.js'),
|
||||||
webSecurity: true,
|
webSecurity: true,
|
||||||
nodeIntegration: false,
|
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
|
// Add file/directory selection handler
|
||||||
ipcMain.handle('select-file-or-directory', async (_event, defaultPath?: string) => {
|
ipcMain.handle('select-file-or-directory', async (_event, defaultPath?: string) => {
|
||||||
const dialogOptions: OpenDialogOptions = {
|
const dialogOptions: OpenDialogOptions = {
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ type ElectronAPI = {
|
|||||||
getGoosedHostPort: () => Promise<string | null>;
|
getGoosedHostPort: () => Promise<string | null>;
|
||||||
setWakelock: (enable: boolean) => Promise<boolean>;
|
setWakelock: (enable: boolean) => Promise<boolean>;
|
||||||
getWakelockState: () => Promise<boolean>;
|
getWakelockState: () => Promise<boolean>;
|
||||||
|
setSpellcheck: (enable: boolean) => Promise<boolean>;
|
||||||
|
getSpellcheckState: () => Promise<boolean>;
|
||||||
openNotificationsSettings: () => Promise<boolean>;
|
openNotificationsSettings: () => Promise<boolean>;
|
||||||
onMouseBackButtonClicked: (callback: () => void) => void;
|
onMouseBackButtonClicked: (callback: () => void) => void;
|
||||||
offMouseBackButtonClicked: (callback: () => void) => void;
|
offMouseBackButtonClicked: (callback: () => void) => void;
|
||||||
@@ -201,6 +203,8 @@ const electronAPI: ElectronAPI = {
|
|||||||
getGoosedHostPort: () => ipcRenderer.invoke('get-goosed-host-port'),
|
getGoosedHostPort: () => ipcRenderer.invoke('get-goosed-host-port'),
|
||||||
setWakelock: (enable: boolean) => ipcRenderer.invoke('set-wakelock', enable),
|
setWakelock: (enable: boolean) => ipcRenderer.invoke('set-wakelock', enable),
|
||||||
getWakelockState: () => ipcRenderer.invoke('get-wakelock-state'),
|
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'),
|
openNotificationsSettings: () => ipcRenderer.invoke('open-notifications-settings'),
|
||||||
onMouseBackButtonClicked: (callback: () => void) => {
|
onMouseBackButtonClicked: (callback: () => void) => {
|
||||||
// Wrapper that ignores the event parameter.
|
// Wrapper that ignores the event parameter.
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export interface Settings {
|
|||||||
showMenuBarIcon: boolean;
|
showMenuBarIcon: boolean;
|
||||||
showDockIcon: boolean;
|
showDockIcon: boolean;
|
||||||
enableWakelock: boolean;
|
enableWakelock: boolean;
|
||||||
|
spellcheckEnabled: boolean;
|
||||||
externalGoosed?: ExternalGoosedConfig;
|
externalGoosed?: ExternalGoosedConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ const defaultSettings: Settings = {
|
|||||||
showMenuBarIcon: true,
|
showMenuBarIcon: true,
|
||||||
showDockIcon: true,
|
showDockIcon: true,
|
||||||
enableWakelock: false,
|
enableWakelock: false,
|
||||||
|
spellcheckEnabled: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Settings management
|
// Settings management
|
||||||
|
|||||||
Reference in New Issue
Block a user