feat(night-light): optional auto-on schedule (time window)
Night Light was all-or-nothing. Add an optional schedule with From/To time inputs so the warm overlay only shows during set hours and toggles itself on/off automatically (the overlay re-checks every minute; no reload). Overnight windows that wrap midnight (e.g. 21:00 -> 07:00) are handled. Window logic is the pure, unit-tested isWithinTimeWindow/parseHHMM in utils/timeWindow.ts. New settings: nightLightSchedule/Start/End (default 21:00-07:00). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -96,6 +96,7 @@ import {
|
||||
useThemes,
|
||||
} from '../../../hooks/useTheme';
|
||||
import { stopPropagation } from '../../../utils/keyboard';
|
||||
import { pickerInputStyle } from '../../../utils/datetimeInput';
|
||||
import { BG_OPTIONS, getChatBg } from '../../lotus/chatBackground';
|
||||
import { resetBootSequence, runLotusBootSequence } from '../../../../lotus-boot';
|
||||
import { useMessageLayoutItems } from '../../../hooks/useMessageLayout';
|
||||
@@ -435,6 +436,12 @@ function Appearance() {
|
||||
const [lotusTerminal, setLotusTerminal] = useSetting(settingsAtom, 'lotusTerminal');
|
||||
const [nightLightEnabled, setNightLightEnabled] = useSetting(settingsAtom, 'nightLightEnabled');
|
||||
const [nightLightOpacity, setNightLightOpacity] = useSetting(settingsAtom, 'nightLightOpacity');
|
||||
const [nightLightSchedule, setNightLightSchedule] = useSetting(
|
||||
settingsAtom,
|
||||
'nightLightSchedule',
|
||||
);
|
||||
const [nightLightStart, setNightLightStart] = useSetting(settingsAtom, 'nightLightStart');
|
||||
const [nightLightEnd, setNightLightEnd] = useSetting(settingsAtom, 'nightLightEnd');
|
||||
const [glassmorphismSidebar, setGlassmorphismSidebar] = useSetting(
|
||||
settingsAtom,
|
||||
'glassmorphismSidebar',
|
||||
@@ -567,23 +574,66 @@ function Appearance() {
|
||||
{nightLightEnabled && (
|
||||
<Box
|
||||
direction="Column"
|
||||
gap="100"
|
||||
gap="300"
|
||||
style={{ padding: `0 ${config.space.S400} ${config.space.S300}` }}
|
||||
>
|
||||
<Text size="T200" priority="300">
|
||||
Intensity: {nightLightOpacity}%
|
||||
</Text>
|
||||
<input
|
||||
aria-label="Night light intensity"
|
||||
type="range"
|
||||
min={5}
|
||||
max={80}
|
||||
value={nightLightOpacity}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setNightLightOpacity(parseInt(e.target.value, 10))
|
||||
}
|
||||
style={{ width: '100%', accentColor: color.Primary.Main }}
|
||||
/>
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="T200" priority="300">
|
||||
Intensity: {nightLightOpacity}%
|
||||
</Text>
|
||||
<input
|
||||
aria-label="Night light intensity"
|
||||
type="range"
|
||||
min={5}
|
||||
max={80}
|
||||
value={nightLightOpacity}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
setNightLightOpacity(parseInt(e.target.value, 10))
|
||||
}
|
||||
style={{ width: '100%', accentColor: color.Primary.Main }}
|
||||
/>
|
||||
</Box>
|
||||
<Box alignItems="Center" justifyContent="SpaceBetween" gap="200">
|
||||
<Box direction="Column">
|
||||
<Text size="T300">Schedule</Text>
|
||||
<Text size="T200" priority="300">
|
||||
Only tint during the hours below
|
||||
</Text>
|
||||
</Box>
|
||||
<Switch
|
||||
variant="Primary"
|
||||
value={nightLightSchedule}
|
||||
onChange={setNightLightSchedule}
|
||||
/>
|
||||
</Box>
|
||||
{nightLightSchedule && (
|
||||
<Box gap="200">
|
||||
<Box direction="Column" gap="100" style={{ flex: 1 }}>
|
||||
<Text as="label" htmlFor="night-light-start" size="T200" priority="400">
|
||||
From
|
||||
</Text>
|
||||
<input
|
||||
id="night-light-start"
|
||||
type="time"
|
||||
value={nightLightStart}
|
||||
onChange={(e) => setNightLightStart(e.target.value)}
|
||||
style={pickerInputStyle(color, config)}
|
||||
/>
|
||||
</Box>
|
||||
<Box direction="Column" gap="100" style={{ flex: 1 }}>
|
||||
<Text as="label" htmlFor="night-light-end" size="T200" priority="400">
|
||||
To
|
||||
</Text>
|
||||
<input
|
||||
id="night-light-end"
|
||||
type="time"
|
||||
value={nightLightEnd}
|
||||
onChange={(e) => setNightLightEnd(e.target.value)}
|
||||
style={pickerInputStyle(color, config)}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</SequenceCard>
|
||||
|
||||
Reference in New Issue
Block a user