fix: improve OpenCode settings handling
Improves OpenCode CLI and shortcut settings flows Updates runtime API and persistence handling Adds coverage for settings helper behavior
This commit is contained in:
@@ -648,6 +648,8 @@ export interface SettingsPayload {
|
||||
queueModeEnabled?: boolean;
|
||||
gitmojiEnabled?: boolean;
|
||||
inputSpellcheckEnabled?: boolean;
|
||||
showOpenCodeUpdateNotifications?: boolean;
|
||||
openCodeUpdateToastDismissedVersion?: string;
|
||||
showToolFileIcons?: boolean;
|
||||
showExpandedBashTools?: boolean;
|
||||
showExpandedEditTools?: boolean;
|
||||
@@ -663,6 +665,7 @@ export interface SettingsPayload {
|
||||
padding?: number;
|
||||
cornerRadius?: number;
|
||||
inputBarOffset?: number;
|
||||
shortcutOverrides?: Record<string, string>;
|
||||
diffLayoutPreference?: 'dynamic' | 'inline' | 'side-by-side';
|
||||
diffViewMode?: 'single' | 'stacked';
|
||||
gitChangesViewMode?: 'flat' | 'tree';
|
||||
|
||||
@@ -131,6 +131,8 @@ export type DesktopSettings = {
|
||||
pwaOrientation?: 'system' | 'portrait' | 'landscape';
|
||||
mobileKeyboardMode?: MobileKeyboardMode;
|
||||
inputSpellcheckEnabled?: boolean;
|
||||
showOpenCodeUpdateNotifications?: boolean;
|
||||
openCodeUpdateToastDismissedVersion?: string;
|
||||
showToolFileIcons?: boolean;
|
||||
showExpandedBashTools?: boolean;
|
||||
showExpandedEditTools?: boolean;
|
||||
@@ -151,6 +153,7 @@ export type DesktopSettings = {
|
||||
padding?: number;
|
||||
cornerRadius?: number;
|
||||
inputBarOffset?: number;
|
||||
shortcutOverrides?: Record<string, string>;
|
||||
|
||||
favoriteModels?: Array<{ providerID: string; modelID: string }>;
|
||||
recentModels?: Array<{ providerID: string; modelID: string }>;
|
||||
|
||||
@@ -98,6 +98,14 @@ const persistToLocalStorage = (settings: DesktopSettings) => {
|
||||
if (typeof settings.mobileKeyboardMode === 'string') {
|
||||
setStoredMobileKeyboardMode(settings.mobileKeyboardMode);
|
||||
}
|
||||
if (typeof settings.openCodeUpdateToastDismissedVersion === 'string') {
|
||||
const version = settings.openCodeUpdateToastDismissedVersion.trim();
|
||||
if (version) {
|
||||
localStorage.setItem('opencode-update-toast-dismissed-version', version);
|
||||
} else {
|
||||
localStorage.removeItem('opencode-update-toast-dismissed-version');
|
||||
}
|
||||
}
|
||||
if (settings.sttProvider === 'browser' || settings.sttProvider === 'server') {
|
||||
localStorage.setItem('sttProvider', settings.sttProvider);
|
||||
}
|
||||
@@ -167,6 +175,27 @@ const sanitizeSkillCatalogs = (value: unknown): DesktopSettings['skillCatalogs']
|
||||
return result;
|
||||
};
|
||||
|
||||
const sanitizeShortcutOverrides = (value: unknown): Record<string, string> | undefined => {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
return undefined;
|
||||
}
|
||||
const result: Record<string, string> = {};
|
||||
for (const [key, combo] of Object.entries(value)) {
|
||||
const normalizedKey = typeof key === 'string' ? key.trim() : '';
|
||||
const normalizedCombo = typeof combo === 'string' ? combo.trim() : '';
|
||||
if (!normalizedKey || !normalizedCombo) continue;
|
||||
result[normalizedKey] = normalizedCombo;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const areStringRecordsEqual = (left: Record<string, string>, right: Record<string, string>): boolean => {
|
||||
const leftEntries = Object.entries(left);
|
||||
const rightEntries = Object.entries(right);
|
||||
if (leftEntries.length !== rightEntries.length) return false;
|
||||
return leftEntries.every(([key, value]) => right[key] === value);
|
||||
};
|
||||
|
||||
const HEX_COLOR_PATTERN = /^#(?:[\da-fA-F]{3}|[\da-fA-F]{6})$/;
|
||||
|
||||
const normalizeIconBackground = (value: unknown): string | null => {
|
||||
@@ -417,6 +446,12 @@ const applyDesktopUiPreferences = (settings: DesktopSettings) => {
|
||||
if (typeof settings.inputSpellcheckEnabled === 'boolean' && settings.inputSpellcheckEnabled !== store.inputSpellcheckEnabled) {
|
||||
store.setInputSpellcheckEnabled(settings.inputSpellcheckEnabled);
|
||||
}
|
||||
if (
|
||||
typeof settings.showOpenCodeUpdateNotifications === 'boolean'
|
||||
&& settings.showOpenCodeUpdateNotifications !== store.showOpenCodeUpdateNotifications
|
||||
) {
|
||||
store.setShowOpenCodeUpdateNotifications(settings.showOpenCodeUpdateNotifications);
|
||||
}
|
||||
if (typeof settings.showToolFileIcons === 'boolean' && settings.showToolFileIcons !== store.showToolFileIcons) {
|
||||
store.setShowToolFileIcons(settings.showToolFileIcons);
|
||||
}
|
||||
@@ -510,6 +545,9 @@ const applyDesktopUiPreferences = (settings: DesktopSettings) => {
|
||||
if (typeof settings.inputBarOffset === 'number' && Number.isFinite(settings.inputBarOffset) && settings.inputBarOffset !== store.inputBarOffset) {
|
||||
store.setInputBarOffset(settings.inputBarOffset);
|
||||
}
|
||||
if (settings.shortcutOverrides && !areStringRecordsEqual(settings.shortcutOverrides, store.shortcutOverrides)) {
|
||||
useUIStore.setState({ shortcutOverrides: settings.shortcutOverrides });
|
||||
}
|
||||
if (typeof settings.mobileKeyboardMode === 'string') {
|
||||
const mode = normalizeMobileKeyboardMode(settings.mobileKeyboardMode, store.mobileKeyboardMode);
|
||||
if (mode !== store.mobileKeyboardMode) {
|
||||
@@ -910,6 +948,12 @@ const sanitizeWebSettings = (payload: unknown): DesktopSettings | null => {
|
||||
if (typeof candidate.inputSpellcheckEnabled === 'boolean') {
|
||||
result.inputSpellcheckEnabled = candidate.inputSpellcheckEnabled;
|
||||
}
|
||||
if (typeof candidate.showOpenCodeUpdateNotifications === 'boolean') {
|
||||
result.showOpenCodeUpdateNotifications = candidate.showOpenCodeUpdateNotifications;
|
||||
}
|
||||
if (typeof candidate.openCodeUpdateToastDismissedVersion === 'string') {
|
||||
result.openCodeUpdateToastDismissedVersion = candidate.openCodeUpdateToastDismissedVersion.trim().slice(0, 128);
|
||||
}
|
||||
if (typeof candidate.showToolFileIcons === 'boolean') {
|
||||
result.showToolFileIcons = candidate.showToolFileIcons;
|
||||
}
|
||||
@@ -977,10 +1021,13 @@ const sanitizeWebSettings = (payload: unknown): DesktopSettings | null => {
|
||||
if (typeof candidate.inputBarOffset === 'number' && Number.isFinite(candidate.inputBarOffset)) {
|
||||
result.inputBarOffset = candidate.inputBarOffset;
|
||||
}
|
||||
const shortcutOverrides = sanitizeShortcutOverrides(candidate.shortcutOverrides);
|
||||
if (shortcutOverrides) {
|
||||
result.shortcutOverrides = shortcutOverrides;
|
||||
}
|
||||
if (typeof candidate.mobileKeyboardMode === 'string') {
|
||||
const mode = normalizeMobileKeyboardMode(candidate.mobileKeyboardMode, undefined);
|
||||
if (mode) {
|
||||
result.mobileKeyboardMode = mode;
|
||||
if (candidate.mobileKeyboardMode === 'native' || candidate.mobileKeyboardMode === 'resize-content') {
|
||||
result.mobileKeyboardMode = candidate.mobileKeyboardMode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user