Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .storybook/mockDashboardBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export const mockDashboardBridge: DashboardBridge = {
saveDashboard: () => {
// noop
},
resetDashboard: async () => {
// For mock, just return the default dashboard
return defaultDashboard;
},
dashboardUpdated: (callback) => {
callback(defaultDashboard);
return () => {
Expand Down
6 changes: 5 additions & 1 deletion src/app/bridge/dashboard/dashboardBridge.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ipcMain } from 'electron';
import { onDashboardUpdated } from '../../storage/dashboardEvents';
import { getDashboard, saveDashboard } from '../../storage/dashboards';
import { getDashboard, saveDashboard, resetDashboard } from '../../storage/dashboards';
import { OverlayManager } from 'src/app/overlayManager';

export async function publishDashboardUpdates(overlayManager: OverlayManager) {
Expand All @@ -18,6 +18,10 @@ export async function publishDashboardUpdates(overlayManager: OverlayManager) {
overlayManager.publishMessage('dashboardUpdated', dashboard);
});

ipcMain.handle('resetDashboard', (_, resetEverything: boolean) => {
return resetDashboard(resetEverything, 'default');
});

ipcMain.handle('toggleLockOverlays', () => {
return overlayManager.toggleLockOverlays();
});
Expand Down
3 changes: 3 additions & 0 deletions src/app/bridge/rendererExposeBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export function exposeBridge() {
saveDashboard: (value: DashboardLayout) => {
ipcRenderer.send('saveDashboard', value);
},
resetDashboard: (resetEverything: boolean) => {
return ipcRenderer.invoke('resetDashboard', resetEverything);
},
toggleLockOverlays: () => {
return ipcRenderer.invoke('toggleLockOverlays');
},
Expand Down
31 changes: 31 additions & 0 deletions src/app/storage/dashboards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,34 @@ export const saveDashboard = (
emitDashboardUpdated(mergedDashboard);
}
};

export const resetDashboard = (resetEverything = false, dashboardId = 'default') => {
const dashboard = getDashboard(dashboardId);
if (!dashboard) {
throw new Error('Dashboard not found');
}

if (resetEverything) {
// Completely reset to default dashboard
saveDashboard(dashboardId, defaultDashboard);
return defaultDashboard;
} else {
// Reset only widget configurations while preserving positions and enabled states
const resetDashboard: DashboardLayout = {
...dashboard,
widgets: dashboard.widgets.map((widget) => {
const defaultWidget = defaultDashboard.widgets.find((w) => w.id === widget.id);
return {
...widget,
config: defaultWidget?.config || widget.config,
};
}),
generalSettings: {
...defaultDashboard.generalSettings,
},
};

saveDashboard(dashboardId, resetDashboard);
return resetDashboard;
}
};
7 changes: 7 additions & 0 deletions src/app/storage/defaultDashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ export const defaultDashboard: DashboardLayout = {
width: 400,
height: 600,
},
config: {
iRatingChange: { enabled: true },
badge: { enabled: true },
delta: { enabled: true },
lastTime: { enabled: true },
fastestTime: { enabled: true },
},
},
{
id: 'input',
Expand Down
47 changes: 46 additions & 1 deletion src/frontend/components/Settings/sections/AdvancedSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState } from 'react';
import { useDashboard } from '@irdashies/context';

export const AdvancedSettings = () => {
const { currentDashboard, onDashboardUpdated } = useDashboard();
const { currentDashboard, onDashboardUpdated, resetDashboard } = useDashboard();
const [dashboardInput, setDashboardInput] = useState<string | undefined>(
JSON.stringify(currentDashboard, undefined, 2)
);
Expand All @@ -29,13 +29,58 @@ export const AdvancedSettings = () => {
}
};

const handleResetConfigs = async () => {
if (!confirm('Reset all widget configurations to defaults? This will preserve widget positions and enabled states.')) {
return;
}

try {
const result = await resetDashboard(false);
setDashboardInput(JSON.stringify(result, undefined, 2));
} catch (e) {
console.error('Failed to reset configurations:', e);
alert('Failed to reset configurations');
}
};

const handleResetCompletely = async () => {
if (!confirm('Reset everything to defaults? This will reset all widget positions, enabled states, and configurations.')) {
return;
}

try {
const result = await resetDashboard(true);
setDashboardInput(JSON.stringify(result, undefined, 2));
} catch (e) {
console.error('Failed to reset dashboard:', e);
alert('Failed to reset dashboard');
}
};

return (
<div className="flex flex-col h-full space-y-4">
<div>
<h2 className="text-xl mb-4">Advanced Settings</h2>
<p className="text-slate-400 mb-4">Configure advanced system settings and preferences.</p>
</div>

<div className="flex space-x-2">
<button
type="button"
onClick={handleResetConfigs}
className="flex-1 bg-amber-700 hover:bg-amber-600 rounded px-4 py-2 transition-colors cursor-pointer"
>
Reset Configurations
</button>
<button
type="button"
onClick={handleResetCompletely}
className="flex-1 bg-red-700 hover:bg-red-600 rounded px-4 py-2 transition-colors cursor-pointer"
>
Reset Everything
</button>
</div>

<textarea
className="flex-1 w-full bg-slate-800 p-4 font-mono text-sm rounded border border-slate-600 focus:border-slate-500 focus:outline-none"
value={dashboardInput}
Expand Down
95 changes: 88 additions & 7 deletions src/frontend/components/Settings/sections/StandingsSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,40 @@ import { useState } from 'react';
import { BaseSettingsSection } from '../components/BaseSettingsSection';
import { StandingsWidgetSettings } from '../types';
import { useDashboard } from '@irdashies/context';
import { ToggleSwitch } from '../components/ToggleSwitch';

const SETTING_ID = 'standings';

const defaultConfig: StandingsWidgetSettings['config'] = {
iRatingChange: { enabled: true },
badge: { enabled: true },
delta: { enabled: true },
lastTime: { enabled: true },
fastestTime: { enabled: true },
};

// Migration function to handle missing properties in the new config format
const migrateConfig = (savedConfig: unknown): StandingsWidgetSettings['config'] => {
if (!savedConfig || typeof savedConfig !== 'object') return defaultConfig;

const config = savedConfig as Record<string, unknown>;

// Handle new format with missing properties
return {
iRatingChange: { enabled: (config.iRatingChange as { enabled?: boolean })?.enabled ?? true },
badge: { enabled: (config.badge as { enabled?: boolean })?.enabled ?? true },
delta: { enabled: (config.delta as { enabled?: boolean })?.enabled ?? true },
lastTime: { enabled: (config.lastTime as { enabled?: boolean })?.enabled ?? true },
fastestTime: { enabled: (config.fastestTime as { enabled?: boolean })?.enabled ?? true },
};
};

export const StandingsSettings = () => {
const { currentDashboard } = useDashboard();
const savedSettings = currentDashboard?.widgets.find(w => w.id === SETTING_ID) as StandingsWidgetSettings | undefined;
const [settings, setSettings] = useState<StandingsWidgetSettings>({
enabled: currentDashboard?.widgets.find(w => w.id === 'standings')?.enabled ?? false,
config: currentDashboard?.widgets.find(w => w.id === 'standings')?.config ?? {},
enabled: savedSettings?.enabled ?? false,
config: migrateConfig(savedSettings?.config),
});

if (!currentDashboard) {
Expand All @@ -20,12 +48,65 @@ export const StandingsSettings = () => {
description="Configure how the standings widget appears and behaves."
settings={settings}
onSettingsChange={setSettings}
widgetId="standings"
widgetId={SETTING_ID}
>
{/* Add specific settings controls here */}
<div className="text-slate-300">
Additional settings will appear here
</div>
{(handleConfigChange) => (
<div className="space-y-8">
{/* Display Settings */}
<div className="space-y-4">
<div className="flex items-center justify-between">
<h3 className="text-lg font-medium text-slate-200">Display Settings</h3>
</div>
<div className="space-y-3 pl-4">
<div className="flex items-center justify-between">
<span className="text-sm text-slate-300">Show iRating Changes</span>
<ToggleSwitch
enabled={settings.config.iRatingChange.enabled}
onToggle={(enabled) =>
handleConfigChange({ iRatingChange: { enabled } })
}
/>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-slate-300">Show Driver Badge</span>
<ToggleSwitch
enabled={settings.config.badge.enabled}
onToggle={(enabled) =>
handleConfigChange({ badge: { enabled } })
}
/>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-slate-300">Show Delta</span>
<ToggleSwitch
enabled={settings.config.delta.enabled}
onToggle={(enabled) =>
handleConfigChange({ delta: { enabled } })
}
/>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-slate-300">Show Last Time</span>
<ToggleSwitch
enabled={settings.config.lastTime.enabled}
onToggle={(enabled) =>
handleConfigChange({ lastTime: { enabled } })
}
/>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-slate-300">Show Fastest Time</span>
<ToggleSwitch
enabled={settings.config.fastestTime.enabled}
onToggle={(enabled) =>
handleConfigChange({ fastestTime: { enabled } })
}
/>
</div>
</div>
</div>
</div>
)}
</BaseSettingsSection>
);
};
8 changes: 7 additions & 1 deletion src/frontend/components/Settings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ export interface BaseWidgetSettings<T = Record<string, unknown>> {
}

export interface StandingsWidgetSettings extends BaseWidgetSettings {
// Add specific standings settings here
config: {
iRatingChange: { enabled: boolean };
badge: { enabled: boolean };
delta: { enabled: boolean };
lastTime: { enabled: boolean };
fastestTime: { enabled: boolean };
};
}

export interface RelativeWidgetSettings extends BaseWidgetSettings {
Expand Down
15 changes: 8 additions & 7 deletions src/frontend/components/Standings/Standings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { DriverRatingBadge } from './components/DriverRatingBadge/DriverRatingBa
import { RatingChange } from './components/RatingChange/RatingChange';
import { SessionBar } from './components/SessionBar/SessionBar';
import { SessionFooter } from './components/SessionFooter/SessionFooter';
import { useCarClassStats, useDriverStandings } from './hooks';
import { useCarClassStats, useDriverStandings, useStandingsSettings } from './hooks';

export const Standings = () => {
const [parent] = useAutoAnimate();
const standings = useDriverStandings({ buffer: 3 });
const classStats = useCarClassStats();
const settings = useStandingsSettings();

return (
<div className="w-full h-full">
Expand All @@ -36,20 +37,20 @@ export const Standings = () => {
name={result.driver?.name || ''}
isPlayer={result.isPlayer}
hasFastestTime={result.hasFastestTime}
delta={result.delta}
delta={settings?.delta?.enabled ? result.delta : undefined}
position={result.classPosition}
iratingChange={<RatingChange value={result.iratingChange} />}
lastTime={result.lastTime}
fastestTime={result.fastestTime}
iratingChange={settings?.iRatingChange?.enabled ? <RatingChange value={result.iratingChange} /> : undefined}
lastTime={settings?.lastTime?.enabled ? result.lastTime : undefined}
fastestTime={settings?.fastestTime?.enabled ? result.fastestTime : undefined}
onPitRoad={result.onPitRoad}
onTrack={result.onTrack}
radioActive={result.radioActive}
badge={
badge={settings?.badge?.enabled ? (
<DriverRatingBadge
license={result.driver?.license}
rating={result.driver?.rating}
/>
}
) : undefined}
/>
))}
</Fragment>
Expand Down
Loading