Files
cinny/src/app/features/settings/notifications/Notifications.tsx
T
jared 5469740f4c
CI / Build & Quality Checks (push) Successful in 10m27s
Trigger Desktop Build / trigger (push) Successful in 7s
feat: P5-21 mention color, P5-22 font selector, P5-27 notification presets; update docs
- P5-21: Custom @mention highlight color picker in Settings → Appearance.
  CSS vars with luminance-computed text color; resets cleanly to theme default.
- P5-22: Font selector (System, Inter, JetBrains Mono, Fira Code) in
  Settings → Appearance. Fira Code added to Google Fonts preload.
- P5-27: Gaming/Work/Sleep preset buttons at top of Settings → Notifications.
  Each atomically applies a group of notification settings.
- AppearanceEffects component in App.tsx applies CSS vars on settings change.
- LOTUS_BUGS.md: mark presence + manifest icon bugs as resolved.
- LOTUS_TODO.md: mark P3-6, P5-21, P5-22, P5-27 as [x].
- LOTUS_FEATURES.md: document all four completed features.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 15:39:35 -04:00

151 lines
4.8 KiB
TypeScript

import React from 'react';
import { useAtomValue, useSetAtom } from 'jotai';
import { Box, Text, IconButton, Icon, Icons, Scroll, config, toRem } from 'folds';
import { Page, PageContent, PageHeader } from '../../../components/page';
import { SystemNotification } from './SystemNotification';
import { AllMessagesNotifications } from './AllMessages';
import { SpecialMessagesNotifications } from './SpecialMessages';
import { KeywordMessagesNotifications } from './KeywordMessages';
import { PushRuleEditor } from './PushRuleEditor';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
import { SettingTile } from '../../../components/setting-tile';
import { settingsAtom, Settings } from '../../../state/settings';
const PRESETS: Array<{
label: string;
emoji: string;
description: string;
patch: Partial<Settings>;
}> = [
{
label: 'Gaming',
emoji: '🎮',
description: 'Notifications on, sounds off',
patch: {
showNotifications: true,
isNotificationSounds: false,
messageSoundId: 'none',
inviteSoundId: 'none',
quietHoursEnabled: false,
},
},
{
label: 'Work',
emoji: '💼',
description: 'All notifications and sounds on',
patch: {
showNotifications: true,
isNotificationSounds: true,
messageSoundId: 'notification',
inviteSoundId: 'invite',
quietHoursEnabled: false,
},
},
{
label: 'Sleep',
emoji: '🌙',
description: 'All notifications off',
patch: {
showNotifications: false,
isNotificationSounds: false,
quietHoursEnabled: false,
},
},
];
function NotificationPresets() {
const settings = useAtomValue(settingsAtom);
const setSettings = useSetAtom(settingsAtom);
const applyPreset = (patch: Partial<Settings>) => {
setSettings({ ...settings, ...patch });
};
return (
<Box direction="Column" gap="100">
<Text size="L400">Quick Presets</Text>
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
<Box gap="300" style={{ padding: config.space.S300, flexWrap: 'wrap' }}>
{PRESETS.map((preset) => (
<button
key={preset.label}
type="button"
onClick={() => applyPreset(preset.patch)}
title={preset.description}
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: toRem(4),
padding: `${toRem(8)} ${toRem(16)}`,
borderRadius: config.radii.R300,
border: '1px solid var(--border-interactive-normal)',
background: 'var(--bg-surface-low)',
color: 'inherit',
cursor: 'pointer',
minWidth: toRem(80),
}}
>
<span style={{ fontSize: toRem(24) }}>{preset.emoji}</span>
<Text size="T300" style={{ fontWeight: 600 }}>{preset.label}</Text>
<Text size="T200" priority="300" style={{ textAlign: 'center', maxWidth: toRem(120) }}>
{preset.description}
</Text>
</button>
))}
</Box>
</SequenceCard>
</Box>
);
}
type NotificationsProps = {
requestClose: () => void;
};
export function Notifications({ requestClose }: NotificationsProps) {
return (
<Page>
<PageHeader outlined={false}>
<Box grow="Yes" gap="200">
<Box grow="Yes" alignItems="Center" gap="200">
<Text size="H3" truncate>
Notifications
</Text>
</Box>
<Box shrink="No">
<IconButton onClick={requestClose} variant="Surface" aria-label="Close">
<Icon src={Icons.Cross} />
</IconButton>
</Box>
</Box>
</PageHeader>
<Box grow="Yes">
<Scroll hideTrack visibility="Hover">
<PageContent>
<Box direction="Column" gap="700">
<NotificationPresets />
<SystemNotification />
<AllMessagesNotifications />
<SpecialMessagesNotifications />
<KeywordMessagesNotifications />
<PushRuleEditor />
<Box direction="Column" gap="100">
<Text size="L400">Block Messages</Text>
<SequenceCard
className={SequenceCardStyle}
variant="SurfaceVariant"
direction="Column"
gap="400"
>
<SettingTile description='This option has been moved to "Account > Block Users" section.' />
</SequenceCard>
</Box>
</Box>
</PageContent>
</Scroll>
</Box>
</Page>
);
}