import {useCallback} from 'react' import {Pressable, View} from 'react-native' import Animated, { FadeInUp, FadeOutUp, LayoutAnimationConfig, LinearTransition, } from 'react-native-reanimated' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' import { type CommonNavigatorParams, type NativeStackScreenProps, } from '#/lib/routes/types' import { useEnableSquareAvatars, useSetEnableSquareAvatars, } from '#/state/preferences/enable-square-avatars' import { useEnableSquareButtons, useSetEnableSquareButtons, } from '#/state/preferences/enable-square-buttons' import {useKawaiiMode, useSetKawaiiMode} from '#/state/preferences/kawaii' import {useSetThemePrefs, useThemePrefs} from '#/state/shell' import {SettingsListItem as AppIconSettingsListItem} from '#/screens/Settings/AppIconSettings/SettingsListItem' import {type Alf, atoms as a, native, useAlf, useTheme} from '#/alf' import { BLACKSKY_PALETTE, BLUESKY_PALETTE, CATPPUCIN_PALETTE, DEER_PALETTE, DEFAULT_PALETTE, EVERGARDEN_PALETTE, KITTY_PALETTE, REDDWARF_PALETTE, ZEPPELIN_PALETTE, } from '#/alf/themes' import * as SegmentedControl from '#/components/forms/SegmentedControl' import {Slider} from '#/components/forms/Slider' import * as Toggle from '#/components/forms/Toggle' import {Circle_And_Square_Stroke1_Corner0_Rounded_Filled as SquareIcon} from '#/components/icons/CircleAndSquare' import {ColorPalette_Stroke2_Corner0_Rounded as ColorPaletteIcon} from '#/components/icons/ColorPalette' import {type Props as SVGIconProps} from '#/components/icons/common' import { Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled, Heart2_Stroke2_Corner0_Rounded as HeartIconOutline, } from '#/components/icons/Heart2' import {Moon_Stroke2_Corner0_Rounded as MoonIcon} from '#/components/icons/Moon' import {Phone_Stroke2_Corner0_Rounded as PhoneIcon} from '#/components/icons/Phone' import {Sparkle_Stroke2_Corner0_Rounded as SparkleIcon} from '#/components/icons/Sparkle' import {TextSize_Stroke2_Corner0_Rounded as TextSize} from '#/components/icons/TextSize' import {TitleCase_Stroke2_Corner0_Rounded as Aa} from '#/components/icons/TitleCase' import * as Layout from '#/components/Layout' import {Text} from '#/components/Typography' import {IS_INTERNAL, IS_NATIVE} from '#/env' import * as SettingsList from './components/SettingsList' type Props = NativeStackScreenProps type ColorSchemeName = | 'witchsky' | 'bluesky' | 'blacksky' | 'deer' | 'zeppelin' | 'kitty' | 'reddwarf' | 'catppuccin' | 'evergarden' type ColorSchemeOption = { name: ColorSchemeName label: string primary: string } export function AppearanceSettingsScreen({}: Props) { const {_} = useLingui() const {fonts} = useAlf() const t = useTheme() const {colorMode, colorScheme, darkTheme, hue} = useThemePrefs() const {setColorMode, setColorScheme, setDarkTheme, setHue} = useSetThemePrefs() const kawaiiMode = useKawaiiMode() const setKawaiiMode = useSetKawaiiMode() const enableSquareAvatars = useEnableSquareAvatars() const setEnableSquareAvatars = useSetEnableSquareAvatars() const enableSquareButtons = useEnableSquareButtons() const setEnableSquareButtons = useSetEnableSquareButtons() const onChangeAppearance = useCallback( (value: 'light' | 'system' | 'dark') => { setColorMode(value) }, [setColorMode], ) const onChangeScheme = useCallback( (value: ColorSchemeName) => { setColorScheme(value) }, [setColorScheme], ) const onChangeDarkTheme = useCallback( (value: 'dim' | 'dark') => { setDarkTheme(value) }, [setDarkTheme], ) const onChangeFontFamily = useCallback( (value: 'system' | 'theme') => { fonts.setFontFamily(value) }, [fonts], ) const onChangeFontScale = useCallback( (value: Alf['fonts']['scale']) => { fonts.setFontScale(value) }, [fonts], ) const colorSchemes: ColorSchemeOption[] = [ { name: 'witchsky', label: _(msg`Witchsky`), primary: DEFAULT_PALETTE.primary_500, }, { name: 'bluesky', label: _(msg`Bluesky`), primary: BLUESKY_PALETTE.primary_500, }, { name: 'blacksky', label: _(msg`Blacksky`), primary: BLACKSKY_PALETTE.primary_500, }, { name: 'deer', label: _(msg`Deer`), primary: DEER_PALETTE.primary_500, }, { name: 'zeppelin', label: _(msg`Zeppelin`), primary: ZEPPELIN_PALETTE.primary_500, }, { name: 'kitty', label: _(msg`Kitty`), primary: KITTY_PALETTE.primary_500, }, { name: 'reddwarf', label: _(msg`Red Dwarf`), primary: REDDWARF_PALETTE.primary_500, }, { name: 'catppuccin', label: _(msg`Catppuccin`), primary: CATPPUCIN_PALETTE.primary_500, }, { name: 'evergarden', label: _(msg`Evergarden`), primary: EVERGARDEN_PALETTE.primary_500, }, ] return ( Appearance {colorMode !== 'light' && ( )} Color Theme Choose which color scheme to use: Hue shift the colors: Logo setKawaiiMode(value)} style={[a.w_full]}> Enable kawaii logo Shapes setEnableSquareAvatars(value)} style={[a.w_full]}> Enable square avatars setEnableSquareButtons(value)} style={[a.w_full]}> Enable square buttons {IS_NATIVE && IS_INTERNAL && ( <> )} ) } function ColorSchemeGrid({ schemes, selectedScheme, onSchemeChange, }: { schemes: ColorSchemeOption[] selectedScheme: ColorSchemeName onSchemeChange: (scheme: ColorSchemeName) => void }) { const t = useTheme() return ( {schemes.map(({name, label, primary}) => { const isSelected = selectedScheme === name const HeartIcon = isSelected ? HeartIconFilled : HeartIconOutline return ( onSchemeChange(name)} style={[ a.flex_1, a.rounded_md, a.overflow_hidden, {minWidth: '30%'}, a.border, { borderColor: isSelected ? primary : t.atoms.border_contrast_low.borderColor, borderWidth: isSelected ? 2 : 1, }, ]}> {label} ) })} ) } export function AppearanceToggleButtonGroup({ title, description, icon: Icon, items, value, onChange, }: { title: string description?: string icon: React.ComponentType items: { label: string name: T }[] value: T onChange: (value: T) => void }) { const t = useTheme() return ( <> {title} {description && ( {description} )} {items.map(item => ( {item.label} ))} ) }