f57c28e5d8
Add migration logic in settings-store.ts to automatically set onboardingCompleted=true for existing users. The migration checks if: - globalClaudeOAuthToken is configured - autoBuildPath is configured If either condition is true, the user is considered an existing user and will skip the onboarding wizard. New users (no tokens or paths configured) will have onboardingCompleted set to false. The migration runs during loadSettings() and persists the change if the onboardingCompleted value was previously undefined. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
107 lines
3.1 KiB
TypeScript
107 lines
3.1 KiB
TypeScript
import { create } from 'zustand';
|
|
import type { AppSettings } from '../../shared/types';
|
|
import { DEFAULT_APP_SETTINGS } from '../../shared/constants';
|
|
|
|
interface SettingsState {
|
|
settings: AppSettings;
|
|
isLoading: boolean;
|
|
error: string | null;
|
|
|
|
// Actions
|
|
setSettings: (settings: AppSettings) => void;
|
|
updateSettings: (updates: Partial<AppSettings>) => void;
|
|
setLoading: (loading: boolean) => void;
|
|
setError: (error: string | null) => void;
|
|
}
|
|
|
|
export const useSettingsStore = create<SettingsState>((set) => ({
|
|
settings: DEFAULT_APP_SETTINGS as AppSettings,
|
|
isLoading: false,
|
|
error: null,
|
|
|
|
setSettings: (settings) => set({ settings }),
|
|
|
|
updateSettings: (updates) =>
|
|
set((state) => ({
|
|
settings: { ...state.settings, ...updates }
|
|
})),
|
|
|
|
setLoading: (isLoading) => set({ isLoading }),
|
|
|
|
setError: (error) => set({ error })
|
|
}));
|
|
|
|
/**
|
|
* Check if settings need migration for onboardingCompleted flag.
|
|
* Existing users (with tokens or projects configured) should have
|
|
* onboardingCompleted set to true to skip the onboarding wizard.
|
|
*/
|
|
function migrateOnboardingCompleted(settings: AppSettings): AppSettings {
|
|
// Only migrate if onboardingCompleted is undefined (not explicitly set)
|
|
if (settings.onboardingCompleted !== undefined) {
|
|
return settings;
|
|
}
|
|
|
|
// Check for signs of an existing user:
|
|
// - Has a Claude OAuth token configured
|
|
// - Has the auto-build source path configured
|
|
const hasOAuthToken = Boolean(settings.globalClaudeOAuthToken);
|
|
const hasAutoBuildPath = Boolean(settings.autoBuildPath);
|
|
|
|
const isExistingUser = hasOAuthToken || hasAutoBuildPath;
|
|
|
|
if (isExistingUser) {
|
|
// Mark onboarding as completed for existing users
|
|
return { ...settings, onboardingCompleted: true };
|
|
}
|
|
|
|
// New user - set to false to trigger onboarding wizard
|
|
return { ...settings, onboardingCompleted: false };
|
|
}
|
|
|
|
/**
|
|
* Load settings from main process
|
|
*/
|
|
export async function loadSettings(): Promise<void> {
|
|
const store = useSettingsStore.getState();
|
|
store.setLoading(true);
|
|
|
|
try {
|
|
const result = await window.electronAPI.getSettings();
|
|
if (result.success && result.data) {
|
|
// Apply migration for onboardingCompleted flag
|
|
const migratedSettings = migrateOnboardingCompleted(result.data);
|
|
store.setSettings(migratedSettings);
|
|
|
|
// If migration changed the settings, persist them
|
|
if (migratedSettings.onboardingCompleted !== result.data.onboardingCompleted) {
|
|
await window.electronAPI.saveSettings({
|
|
onboardingCompleted: migratedSettings.onboardingCompleted
|
|
});
|
|
}
|
|
}
|
|
} catch (error) {
|
|
store.setError(error instanceof Error ? error.message : 'Failed to load settings');
|
|
} finally {
|
|
store.setLoading(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save settings to main process
|
|
*/
|
|
export async function saveSettings(updates: Partial<AppSettings>): Promise<boolean> {
|
|
const store = useSettingsStore.getState();
|
|
|
|
try {
|
|
const result = await window.electronAPI.saveSettings(updates);
|
|
if (result.success) {
|
|
store.updateSettings(updates);
|
|
return true;
|
|
}
|
|
return false;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|