splash screen configurable in global settings

This commit is contained in:
webdevcody
2026-01-23 12:55:01 -05:00
parent 0b92349890
commit bc3e3dad1c
7 changed files with 211 additions and 94 deletions

View File

@@ -6,14 +6,25 @@ import { SplashScreen } from './components/splash-screen';
import { useSettingsSync } from './hooks/use-settings-sync';
import { useCursorStatusInit } from './hooks/use-cursor-status-init';
import { useProviderAuthInit } from './hooks/use-provider-auth-init';
import { useAppStore } from './store/app-store';
import './styles/global.css';
import './styles/theme-imports';
import './styles/font-imports';
const logger = createLogger('App');
// Key for localStorage to persist splash screen preference
const DISABLE_SPLASH_KEY = 'automaker-disable-splash';
export default function App() {
const disableSplashScreen = useAppStore((state) => state.disableSplashScreen);
const [showSplash, setShowSplash] = useState(() => {
// Check localStorage for user preference (available synchronously)
const savedPreference = localStorage.getItem(DISABLE_SPLASH_KEY);
if (savedPreference === 'true') {
return false;
}
// Only show splash once per session
if (sessionStorage.getItem('automaker-splash-shown')) {
return false;
@@ -21,6 +32,11 @@ export default function App() {
return true;
});
// Sync the disableSplashScreen setting to localStorage for fast access on next startup
useEffect(() => {
localStorage.setItem(DISABLE_SPLASH_KEY, String(disableSplashScreen));
}, [disableSplashScreen]);
// Clear accumulated PerformanceMeasure entries to prevent memory leak in dev mode
// React's internal scheduler creates performance marks/measures that accumulate without cleanup
useEffect(() => {
@@ -61,7 +77,7 @@ export default function App() {
return (
<>
<RouterProvider router={router} />
{showSplash && <SplashScreen onComplete={handleSplashComplete} />}
{showSplash && !disableSplashScreen && <SplashScreen onComplete={handleSplashComplete} />}
</>
);
}

View File

@@ -1,6 +1,7 @@
import { useState, useEffect } from 'react';
import { Label } from '@/components/ui/label';
import { Palette, Moon, Sun, Type } from 'lucide-react';
import { Switch } from '@/components/ui/switch';
import { Palette, Moon, Sun, Type, Sparkles } from 'lucide-react';
import { darkThemes, lightThemes } from '@/config/theme-options';
import {
UI_SANS_FONT_OPTIONS,
@@ -18,7 +19,14 @@ interface AppearanceSectionProps {
}
export function AppearanceSection({ effectiveTheme, onThemeChange }: AppearanceSectionProps) {
const { fontFamilySans, fontFamilyMono, setFontSans, setFontMono } = useAppStore();
const {
fontFamilySans,
fontFamilyMono,
setFontSans,
setFontMono,
disableSplashScreen,
setDisableSplashScreen,
} = useAppStore();
// Determine if current theme is light or dark
const isLightTheme = lightThemes.some((t) => t.value === effectiveTheme);
@@ -189,6 +197,30 @@ export function AppearanceSection({ effectiveTheme, onThemeChange }: AppearanceS
</div>
</div>
</div>
{/* Splash Screen Section */}
<div className="space-y-4 pt-6 border-t border-border/50">
<div className="flex items-center gap-2 mb-4">
<Sparkles className="w-4 h-4 text-muted-foreground" />
<Label className="text-foreground font-medium">Startup</Label>
</div>
<div className="flex items-center justify-between">
<div className="space-y-1">
<Label htmlFor="disable-splash-screen" className="text-sm">
Disable Splash Screen
</Label>
<p className="text-xs text-muted-foreground">
Skip the animated splash screen when the app starts
</p>
</div>
<Switch
id="disable-splash-screen"
checked={disableSplashScreen}
onCheckedChange={setDisableSplashScreen}
/>
</div>
</div>
</div>
</div>
);

View File

@@ -181,6 +181,7 @@ export function parseLocalStorageSettings(): Partial<GlobalSettings> | null {
defaultPlanningMode: state.defaultPlanningMode as GlobalSettings['defaultPlanningMode'],
defaultRequirePlanApproval: state.defaultRequirePlanApproval as boolean,
muteDoneSound: state.muteDoneSound as boolean,
disableSplashScreen: state.disableSplashScreen as boolean,
enhancementModel: state.enhancementModel as GlobalSettings['enhancementModel'],
validationModel: state.validationModel as GlobalSettings['validationModel'],
phaseModels: state.phaseModels as GlobalSettings['phaseModels'],
@@ -711,6 +712,7 @@ export function hydrateStoreFromSettings(settings: GlobalSettings): void {
model: 'claude-opus',
},
muteDoneSound: settings.muteDoneSound ?? false,
disableSplashScreen: settings.disableSplashScreen ?? false,
serverLogLevel: settings.serverLogLevel ?? 'info',
enableRequestLogging: settings.enableRequestLogging ?? true,
showQueryDevtools: settings.showQueryDevtools ?? true,
@@ -798,6 +800,7 @@ function buildSettingsUpdateFromStore(): Record<string, unknown> {
defaultPlanningMode: state.defaultPlanningMode,
defaultRequirePlanApproval: state.defaultRequirePlanApproval,
muteDoneSound: state.muteDoneSound,
disableSplashScreen: state.disableSplashScreen,
serverLogLevel: state.serverLogLevel,
enableRequestLogging: state.enableRequestLogging,
enhancementModel: state.enhancementModel,

View File

@@ -64,6 +64,7 @@ const SETTINGS_FIELDS_TO_SYNC = [
'defaultRequirePlanApproval',
'defaultFeatureModel',
'muteDoneSound',
'disableSplashScreen',
'serverLogLevel',
'enableRequestLogging',
'showQueryDevtools',
@@ -710,6 +711,7 @@ export async function refreshSettingsFromServer(): Promise<boolean> {
? migratePhaseModelEntry(serverSettings.defaultFeatureModel)
: { model: 'claude-opus' },
muteDoneSound: serverSettings.muteDoneSound,
disableSplashScreen: serverSettings.disableSplashScreen ?? false,
serverLogLevel: serverSettings.serverLogLevel ?? 'info',
enableRequestLogging: serverSettings.enableRequestLogging ?? true,
enhancementModel: serverSettings.enhancementModel,

View File

@@ -686,6 +686,9 @@ export interface AppState {
// Audio Settings
muteDoneSound: boolean; // When true, mute the notification sound when agents complete (default: false)
// Splash Screen Settings
disableSplashScreen: boolean; // When true, skip showing the splash screen overlay on startup
// Server Log Level Settings
serverLogLevel: ServerLogLevel; // Log level for the API server (error, warn, info, debug)
enableRequestLogging: boolean; // Enable HTTP request logging (Morgan)
@@ -1183,6 +1186,9 @@ export interface AppActions {
// Audio Settings actions
setMuteDoneSound: (muted: boolean) => void;
// Splash Screen actions
setDisableSplashScreen: (disabled: boolean) => void;
// Server Log Level actions
setServerLogLevel: (level: ServerLogLevel) => void;
setEnableRequestLogging: (enabled: boolean) => void;
@@ -1502,6 +1508,7 @@ const initialState: AppState = {
worktreesByProject: {},
keyboardShortcuts: DEFAULT_KEYBOARD_SHORTCUTS, // Default keyboard shortcuts
muteDoneSound: false, // Default to sound enabled (not muted)
disableSplashScreen: false, // Default to showing splash screen
serverLogLevel: 'info', // Default to info level for server logs
enableRequestLogging: true, // Default to enabled for HTTP request logging
showQueryDevtools: true, // Default to enabled (only shown in dev mode anyway)
@@ -2626,6 +2633,9 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
// Audio Settings actions
setMuteDoneSound: (muted) => set({ muteDoneSound: muted }),
// Splash Screen actions
setDisableSplashScreen: (disabled) => set({ disableSplashScreen: disabled }),
// Server Log Level actions
setServerLogLevel: (level) => set({ serverLogLevel: level }),
setEnableRequestLogging: (enabled) => set({ enableRequestLogging: enabled }),