Skip to content

Commit 2660e17

Browse files
authored
feat: add background opacity (#38)
1 parent a1ea184 commit 2660e17

File tree

9 files changed

+166
-26
lines changed

9 files changed

+166
-26
lines changed

src/app/storage/defaultDashboard.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const defaultDashboard: DashboardLayout = {
1717
delta: { enabled: true },
1818
lastTime: { enabled: true },
1919
fastestTime: { enabled: true },
20+
backgroundOpacity: { value: 0 },
2021
},
2122
},
2223
{
@@ -57,6 +58,7 @@ export const defaultDashboard: DashboardLayout = {
5758
},
5859
config: {
5960
buffer: 3,
61+
backgroundOpacity: { value: 0 },
6062
},
6163
},
6264
{
@@ -78,6 +80,9 @@ export const defaultDashboard: DashboardLayout = {
7880
width: 160,
7981
height: 380,
8082
},
83+
config: {
84+
backgroundOpacity: { value: 25 },
85+
},
8186
},
8287
{
8388
id: 'fastercarsfrombehind',

src/frontend/components/Settings/sections/RelativeSettings.tsx

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,26 @@ const SETTING_ID = 'relative';
77

88
const defaultConfig: RelativeWidgetSettings['config'] = {
99
buffer: 3,
10+
background: { opacity: 0 },
11+
};
12+
13+
const migrateConfig = (savedConfig: unknown): RelativeWidgetSettings['config'] => {
14+
if (!savedConfig || typeof savedConfig !== 'object') return defaultConfig;
15+
const config = savedConfig as Record<string, unknown>;
16+
return {
17+
buffer: (config.buffer as { value?: number })?.value ?? 3,
18+
background: { opacity: (config.background as { opacity?: number })?.opacity ?? 0 },
19+
};
1020
};
1121

1222
export const RelativeSettings = () => {
1323
const { currentDashboard } = useDashboard();
14-
const savedSettings = currentDashboard?.widgets.find(w => w.id === SETTING_ID) as RelativeWidgetSettings | undefined;
24+
const savedSettings = currentDashboard?.widgets.find(
25+
(w) => w.id === SETTING_ID
26+
) as RelativeWidgetSettings | undefined;
1527
const [settings, setSettings] = useState<RelativeWidgetSettings>({
1628
enabled: savedSettings?.enabled ?? true,
17-
config: savedSettings?.config ?? defaultConfig,
29+
config: migrateConfig(savedSettings?.config),
1830
});
1931

2032
if (!currentDashboard) {
@@ -40,7 +52,9 @@ export const RelativeSettings = () => {
4052
</div>
4153
<select
4254
value={settings.config.buffer}
43-
onChange={(e) => handleConfigChange({ buffer: parseInt(e.target.value) })}
55+
onChange={(e) =>
56+
handleConfigChange({ buffer: parseInt(e.target.value) })
57+
}
4458
className="bg-slate-700 text-slate-200 px-3 py-1 rounded border border-slate-600 focus:border-blue-500 focus:outline-none"
4559
>
4660
{Array.from({ length: 10 }, (_, i) => (
@@ -50,8 +64,28 @@ export const RelativeSettings = () => {
5064
))}
5165
</select>
5266
</div>
67+
<div className="flex items-center justify-between">
68+
<span className="text-sm text-slate-300">Background Opacity</span>
69+
<div className="flex items-center gap-2">
70+
<input
71+
type="range"
72+
min="0"
73+
max="100"
74+
value={settings.config.background.opacity}
75+
onChange={(e) =>
76+
handleConfigChange({
77+
background: { opacity: parseInt(e.target.value) },
78+
})
79+
}
80+
className="w-20 h-2 bg-slate-600 rounded-lg appearance-none cursor-pointer"
81+
/>
82+
<span className="text-xs text-slate-400 w-8">
83+
{settings.config.background.opacity}%
84+
</span>
85+
</div>
86+
</div>
5387
</div>
5488
)}
5589
</BaseSettingsSection>
5690
);
57-
};
91+
};

src/frontend/components/Settings/sections/StandingsSettings.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const defaultConfig: StandingsWidgetSettings['config'] = {
1212
delta: { enabled: true },
1313
lastTime: { enabled: true },
1414
fastestTime: { enabled: true },
15+
background: { opacity: 0 },
1516
};
1617

1718
// Migration function to handle missing properties in the new config format
@@ -27,6 +28,7 @@ const migrateConfig = (savedConfig: unknown): StandingsWidgetSettings['config']
2728
delta: { enabled: (config.delta as { enabled?: boolean })?.enabled ?? true },
2829
lastTime: { enabled: (config.lastTime as { enabled?: boolean })?.enabled ?? true },
2930
fastestTime: { enabled: (config.fastestTime as { enabled?: boolean })?.enabled ?? true },
31+
background: { opacity: (config.background as { opacity?: number })?.opacity ?? 0 },
3032
};
3133
};
3234

@@ -103,6 +105,24 @@ export const StandingsSettings = () => {
103105
}
104106
/>
105107
</div>
108+
<div className="flex items-center justify-between">
109+
<span className="text-sm text-slate-300">Background Opacity</span>
110+
<div className="flex items-center gap-2">
111+
<input
112+
type="range"
113+
min="0"
114+
max="100"
115+
value={settings.config.background.opacity}
116+
onChange={(e) =>
117+
handleConfigChange({ background: { opacity: parseInt(e.target.value) } })
118+
}
119+
className="w-20 h-2 bg-slate-600 rounded-lg appearance-none cursor-pointer"
120+
/>
121+
<span className="text-xs text-slate-400 w-8">
122+
{settings.config.background.opacity}%
123+
</span>
124+
</div>
125+
</div>
106126
</div>
107127
</div>
108128
</div>

src/frontend/components/Settings/sections/WeatherSettings.tsx

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,28 @@ import { BaseSettingsSection } from '../components/BaseSettingsSection';
33
import { WeatherWidgetSettings } from '../types';
44
import { useDashboard } from '@irdashies/context';
55

6+
const SETTING_ID = 'weather';
7+
8+
const defaultConfig: WeatherWidgetSettings['config'] = {
9+
background: { opacity: 0 },
10+
};
11+
12+
const migrateConfig = (savedConfig: unknown): WeatherWidgetSettings['config'] => {
13+
if (!savedConfig || typeof savedConfig !== 'object') return defaultConfig;
14+
const config = savedConfig as Record<string, unknown>;
15+
return {
16+
background: { opacity: (config.background as { opacity?: number })?.opacity ?? 0 },
17+
};
18+
};
19+
620
export const WeatherSettings = () => {
721
const { currentDashboard } = useDashboard();
22+
const savedSettings = currentDashboard?.widgets.find(
23+
(w) => w.id === SETTING_ID
24+
) as WeatherWidgetSettings | undefined;
825
const [settings, setSettings] = useState<WeatherWidgetSettings>({
9-
enabled: currentDashboard?.widgets.find(w => w.id === 'weather')?.enabled ?? false,
10-
config: currentDashboard?.widgets.find(w => w.id === 'weather')?.config ?? {},
26+
enabled: savedSettings?.enabled ?? false,
27+
config: migrateConfig(savedSettings?.config),
1128
});
1229

1330
if (!currentDashboard) {
@@ -20,12 +37,30 @@ export const WeatherSettings = () => {
2037
description="Configure weather widget display options."
2138
settings={settings}
2239
onSettingsChange={setSettings}
23-
widgetId="weather"
40+
widgetId={SETTING_ID}
2441
>
25-
{/* Add specific settings controls here */}
26-
<div className="text-slate-300">
27-
Additional settings will appear here
28-
</div>
42+
{(handleConfigChange) => (
43+
<div className="space-y-4">
44+
<div className="flex items-center justify-between">
45+
<span className="text-sm text-slate-300">Background Opacity</span>
46+
<div className="flex items-center gap-2">
47+
<input
48+
type="range"
49+
min="0"
50+
max="100"
51+
value={settings.config.background.opacity}
52+
onChange={(e) =>
53+
handleConfigChange({ background: { opacity: parseInt(e.target.value) } })
54+
}
55+
className="w-20 h-2 bg-slate-600 rounded-lg appearance-none cursor-pointer"
56+
/>
57+
<span className="text-xs text-slate-400 w-8">
58+
{settings.config.background.opacity}%
59+
</span>
60+
</div>
61+
</div>
62+
</div>
63+
)}
2964
</BaseSettingsSection>
3065
);
3166
};

src/frontend/components/Settings/types.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,21 @@ export interface StandingsWidgetSettings extends BaseWidgetSettings {
1313
delta: { enabled: boolean };
1414
lastTime: { enabled: boolean };
1515
fastestTime: { enabled: boolean };
16+
background: { opacity: number };
1617
};
1718
}
1819

1920
export interface RelativeWidgetSettings extends BaseWidgetSettings {
2021
config: {
2122
buffer: number;
23+
background: { opacity: number };
2224
};
2325
}
2426

2527
export interface WeatherWidgetSettings extends BaseWidgetSettings {
26-
// Add specific weather settings here
28+
config: {
29+
background: { opacity: number };
30+
};
2731
}
2832

2933
export interface TrackMapWidgetSettings extends BaseWidgetSettings {

src/frontend/components/Standings/Relative.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ export const Relative = () => {
7272
});
7373

7474
return (
75-
<div className="w-full h-full">
75+
<div
76+
className="w-full h-full bg-slate-800/[var(--bg-opacity)] rounded-sm p-2"
77+
style={{
78+
['--bg-opacity' as string]: `${config?.background?.opacity ?? 0}%`,
79+
}}
80+
>
7681
<SessionBar />
7782
<table className="w-full table-auto text-sm border-separate border-spacing-y-0.5 mb-3 mt-3">
7883
<tbody ref={parent}>{rows}</tbody>

src/frontend/components/Standings/Standings.tsx

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,24 @@ import { DriverRatingBadge } from './components/DriverRatingBadge/DriverRatingBa
66
import { RatingChange } from './components/RatingChange/RatingChange';
77
import { SessionBar } from './components/SessionBar/SessionBar';
88
import { SessionFooter } from './components/SessionFooter/SessionFooter';
9-
import { useCarClassStats, useDriverStandings, useStandingsSettings } from './hooks';
9+
import {
10+
useCarClassStats,
11+
useDriverStandings,
12+
useStandingsSettings,
13+
} from './hooks';
1014

1115
export const Standings = () => {
1216
const [parent] = useAutoAnimate();
1317
const standings = useDriverStandings({ buffer: 3 });
1418
const classStats = useCarClassStats();
1519
const settings = useStandingsSettings();
16-
1720
return (
18-
<div className="w-full h-full">
21+
<div
22+
className={`w-full h-full bg-slate-800/[var(--bg-opacity)] rounded-sm p-2 text-white overflow-hidden`}
23+
style={{
24+
['--bg-opacity' as string]: `${settings?.background?.opacity ?? 0}%`,
25+
}}
26+
>
1927
<SessionBar />
2028
<table className="w-full table-auto text-sm border-separate border-spacing-y-0.5 mb-3">
2129
<tbody ref={parent}>
@@ -39,18 +47,30 @@ export const Standings = () => {
3947
hasFastestTime={result.hasFastestTime}
4048
delta={settings?.delta?.enabled ? result.delta : undefined}
4149
position={result.classPosition}
42-
iratingChange={settings?.iRatingChange?.enabled ? <RatingChange value={result.iratingChange} /> : undefined}
43-
lastTime={settings?.lastTime?.enabled ? result.lastTime : undefined}
44-
fastestTime={settings?.fastestTime?.enabled ? result.fastestTime : undefined}
50+
iratingChange={
51+
settings?.iRatingChange?.enabled ? (
52+
<RatingChange value={result.iratingChange} />
53+
) : undefined
54+
}
55+
lastTime={
56+
settings?.lastTime?.enabled ? result.lastTime : undefined
57+
}
58+
fastestTime={
59+
settings?.fastestTime?.enabled
60+
? result.fastestTime
61+
: undefined
62+
}
4563
onPitRoad={result.onPitRoad}
4664
onTrack={result.onTrack}
4765
radioActive={result.radioActive}
48-
badge={settings?.badge?.enabled ? (
49-
<DriverRatingBadge
50-
license={result.driver?.license}
51-
rating={result.driver?.rating}
52-
/>
53-
) : undefined}
66+
badge={
67+
settings?.badge?.enabled ? (
68+
<DriverRatingBadge
69+
license={result.driver?.license}
70+
rating={result.driver?.rating}
71+
/>
72+
) : undefined
73+
}
5474
/>
5575
))}
5676
</Fragment>

src/frontend/components/Weather/Weather.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { WeatherTrackWetness } from './WeatherTrackWetness/WeatherTrackWetness';
66
import { WeatherTrackRubbered } from './WeatherTrackRubbered/WeatherTrackRubbered';
77
import { WindDirection } from './WindDirection/WindDirection';
88
import { useTrackRubberedState } from './hooks/useTrackRubberedState';
9+
import { useWeatherSettings } from './hooks/useWeatherSettings';
910

1011
export const Weather = () => {
1112
const [parent] = useAutoAnimate();
@@ -14,10 +15,14 @@ export const Weather = () => {
1415
const windSpeed = weather.windVelocity;
1516
const relativeWindDirection = (weather.windDirection ?? 0) - (weather.windYaw ?? 0);
1617
const trackRubbered = useTrackRubberedState();
18+
const settings = useWeatherSettings();
1719

1820
return (
1921
<div
20-
className="w-full inline-flex flex-row bg-slate-800/25 rounded-sm"
22+
className="w-full inline-flex flex-row bg-slate-800/[var(--bg-opacity)] rounded-sm"
23+
style={{
24+
['--bg-opacity' as string]: `${settings?.background?.opacity ?? 25}%`,
25+
}}
2126
ref={parent}
2227
>
2328
<div className="flex flex-col p-2 w-full rounded-sm gap-2">
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { useDashboard } from '@irdashies/context';
2+
import { WeatherWidgetSettings } from '../../Settings/types';
3+
4+
export const useWeatherSettings = () => {
5+
const { currentDashboard } = useDashboard();
6+
7+
const weatherSettings = currentDashboard?.widgets.find(
8+
(widget) => widget.id === 'weather',
9+
)?.config;
10+
11+
return weatherSettings as WeatherWidgetSettings['config'];
12+
};

0 commit comments

Comments
 (0)