Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: density settings (compact account switcher)

+436 -170
+7 -1
src/Navigation.tsx
··· 131 131 import {RunesSettingsScreen} from '#/screens/Settings/RunesSettings' 132 132 import {RunesDisplayAlsoLikedSettingsScreen} from '#/screens/Settings/RunesSettings/AlsoLikedSettings' 133 133 import {RunesBadgesSettingsScreen} from '#/screens/Settings/RunesSettings/BadgesSettings' 134 + import {RunesDisplayDensitySettingsScreen} from '#/screens/Settings/RunesSettings/DensitySettings' 134 135 import {RunesDisplaySettingsScreen} from '#/screens/Settings/RunesSettings/DisplaySettings' 135 - import {RunesSettingsSyncSettingsScreen} from '#/screens/Settings/RunesSettings/SettingsSyncSettings' 136 136 import {RunesExtraSettingsScreen} from '#/screens/Settings/RunesSettings/ExtraSettings' 137 137 import {RunesUsabilityFeedSettingsScreen} from '#/screens/Settings/RunesSettings/FeedSettings' 138 138 import {RunesImpressionsSettingsScreen} from '#/screens/Settings/RunesSettings/ImpressionsSettings' 139 139 import {RunesInfrastructureSettingsScreen} from '#/screens/Settings/RunesSettings/InfrastructureSettings' 140 140 import {RunesMenusSettingsScreen} from '#/screens/Settings/RunesSettings/MenusSettings' 141 + import {RunesSettingsSyncSettingsScreen} from '#/screens/Settings/RunesSettings/SettingsSyncSettings' 141 142 import {RunesUsabilitySettingsScreen} from '#/screens/Settings/RunesSettings/UsabilitySettings' 142 143 import {SettingsScreen} from '#/screens/Settings/Settings' 143 144 import {ThreadPreferencesScreen} from '#/screens/Settings/ThreadPreferences' ··· 469 470 name="RunesDisplayAlsoLikedSettings" 470 471 getComponent={() => RunesDisplayAlsoLikedSettingsScreen} 471 472 options={{title: title(msg`Also liked`), requireAuth: true}} 473 + /> 474 + <Stack.Screen 475 + name="RunesDisplayDensitySettings" 476 + getComponent={() => RunesDisplayDensitySettingsScreen} 477 + options={{title: title(msg`Density`), requireAuth: true}} 472 478 /> 473 479 <Stack.Screen 474 480 name="RunesInfrastructureSettings"
+86 -37
src/components/AccountList.tsx
··· 8 8 import {isJwtExpired} from '#/lib/jwt' 9 9 import {sanitizeDisplayName} from '#/lib/strings/display-names' 10 10 import {sanitizeHandle} from '#/lib/strings/handles' 11 + import {useAutoCompactAccountSwitcher} from '#/state/preferences/auto-compact-account-switcher' 12 + import {useCompactAccountSwitcher} from '#/state/preferences/compact-account-switcher' 11 13 import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 12 14 import {useProfilesQuery} from '#/state/queries/profile' 13 15 import {type SessionAccount, useSession} from '#/state/session' ··· 44 46 const t = useTheme() 45 47 const {_} = useLingui() 46 48 const enableSquareButtons = useEnableSquareButtons() 49 + const useCompactSwitcher = useCompactAccountSwitcher() 50 + const autoCompactSwitcher = useAutoCompactAccountSwitcher() 47 51 const accounts = accountsProp ?? sessionAccounts 48 52 const [, , hiddenDidsSet] = useHiddenAccountsElsewhere() 49 53 const {data: profiles} = useProfilesQuery({ ··· 52 56 const sortedAccounts = useSortedAccountItems(accounts).filter( 53 57 account => !hiddenDidsSet.has(account.did), 54 58 ) 59 + const shouldUseCompactSwitcher = 60 + Boolean(useCompactSwitcher) || 61 + (Boolean(autoCompactSwitcher) && sortedAccounts.length > 6) 55 62 56 63 const onPressAddAccount = useCallback(() => { 57 64 onSelectOther() ··· 61 68 <View 62 69 pointerEvents={pendingDid ? 'none' : 'auto'} 63 70 style={[ 64 - a.rounded_lg, 71 + shouldUseCompactSwitcher ? a.rounded_md : a.rounded_lg, 65 72 a.overflow_hidden, 66 73 a.border, 67 74 t.atoms.border_contrast_low, ··· 72 79 profile={profiles?.profiles.find(p => p.did === account.did)} 73 80 account={account} 74 81 onSelect={onSelectAccount} 82 + useCompactSwitcher={shouldUseCompactSwitcher} 75 83 isCurrentAccount={ 76 84 account.did === (selectedDid ?? currentAccount?.did) 77 85 } ··· 92 100 a.flex_1, 93 101 a.flex_row, 94 102 a.align_center, 95 - a.p_lg, 96 - a.gap_sm, 103 + shouldUseCompactSwitcher ? {height: 48} : a.p_lg, 104 + shouldUseCompactSwitcher ? null : a.gap_sm, 97 105 (hovered || pressed) && t.atoms.bg_contrast_25, 98 106 ]}> 99 - <View 100 - style={[ 101 - t.atoms.bg_contrast_25, 102 - enableSquareButtons ? a.rounded_sm : a.rounded_full, 103 - {width: 48, height: 48}, 104 - a.justify_center, 105 - a.align_center, 106 - (hovered || pressed) && t.atoms.bg_contrast_50, 107 - ]}> 108 - <PlusIcon style={[t.atoms.text_contrast_low]} size="md" /> 109 - </View> 110 - <Text 111 - style={[a.flex_1, a.leading_tight, a.text_md, a.font_medium]}> 112 - {otherLabel ?? <Trans>Other account</Trans>} 113 - </Text> 114 - <ChevronIcon size="md" style={[t.atoms.text_contrast_low]} /> 107 + {shouldUseCompactSwitcher ? ( 108 + <> 109 + <Text 110 + style={[ 111 + a.font_semi_bold, 112 + a.flex_1, 113 + a.flex_row, 114 + a.py_sm, 115 + a.leading_tight, 116 + t.atoms.text_contrast_medium, 117 + {paddingLeft: 56}, 118 + ]}> 119 + {otherLabel ?? <Trans>Other account</Trans>} 120 + </Text> 121 + <ChevronIcon size="sm" style={[t.atoms.text, a.mr_md]} /> 122 + </> 123 + ) : ( 124 + <> 125 + <View 126 + style={[ 127 + t.atoms.bg_contrast_25, 128 + enableSquareButtons ? a.rounded_sm : a.rounded_full, 129 + {width: 48, height: 48}, 130 + a.justify_center, 131 + a.align_center, 132 + (hovered || pressed) && t.atoms.bg_contrast_50, 133 + ]}> 134 + <PlusIcon style={[t.atoms.text_contrast_low]} size="md" /> 135 + </View> 136 + <Text 137 + style={[ 138 + a.flex_1, 139 + a.leading_tight, 140 + a.text_md, 141 + a.font_medium, 142 + ]}> 143 + {otherLabel ?? <Trans>Other account</Trans>} 144 + </Text> 145 + <ChevronIcon size="md" style={[t.atoms.text_contrast_low]} /> 146 + </> 147 + )} 115 148 </View> 116 149 )} 117 150 </Button> ··· 124 157 profile, 125 158 account, 126 159 onSelect, 160 + useCompactSwitcher, 127 161 isCurrentAccount, 128 162 isPendingAccount, 129 163 }: { 130 164 profile?: AppBskyActorDefs.ProfileViewDetailed 131 165 account: SessionAccount 132 166 onSelect: (account: SessionAccount) => void 167 + useCompactSwitcher: boolean 133 168 isCurrentAccount: boolean 134 169 isPendingAccount: boolean 135 170 }) { ··· 163 198 a.flex_1, 164 199 a.flex_row, 165 200 a.align_center, 166 - a.p_lg, 201 + useCompactSwitcher ? a.px_md : a.p_lg, 167 202 a.gap_sm, 203 + useCompactSwitcher ? {height: 56} : null, 168 204 (hovered || pressed || isPendingAccount) && t.atoms.bg_contrast_25, 169 205 ]}> 170 206 <UserAvatar 171 207 avatar={profile?.avatar} 172 - size={48} 208 + size={useCompactSwitcher ? 36 : 48} 173 209 type={profile?.associated?.labeler ? 'labeler' : 'user'} 174 210 live={live} 175 211 hideLiveBadge ··· 179 215 <View style={[a.flex_row, a.align_center, a.gap_xs]}> 180 216 <Text 181 217 emoji 182 - style={[a.font_medium, a.leading_tight, a.text_md]} 218 + style={[ 219 + useCompactSwitcher ? a.font_semi_bold : a.font_medium, 220 + a.leading_tight, 221 + useCompactSwitcher ? null : a.text_md, 222 + ]} 183 223 numberOfLines={1}> 184 224 {sanitizeDisplayName( 185 225 profile?.displayName || profile?.handle || account.handle, ··· 197 237 style={[ 198 238 a.leading_tight, 199 239 t.atoms.text_contrast_medium, 200 - a.text_sm, 240 + useCompactSwitcher ? null : a.text_sm, 201 241 ]}> 202 242 {sanitizeHandle(account.handle, '@')} 203 243 </Text> ··· 215 255 </View> 216 256 217 257 {isCurrentAccount ? ( 218 - <View 219 - style={[ 220 - { 221 - width: 20, 222 - height: 20, 223 - backgroundColor: t.palette.positive_500, 224 - }, 225 - enableSquareButtons ? a.rounded_sm : a.rounded_full, 226 - a.justify_center, 227 - a.align_center, 228 - ]}> 229 - <CheckIcon size="xs" style={[{color: t.palette.white}]} /> 230 - </View> 258 + useCompactSwitcher ? ( 259 + <CheckIcon size="sm" style={[{color: t.palette.positive_500}]} /> 260 + ) : ( 261 + <View 262 + style={[ 263 + { 264 + width: 20, 265 + height: 20, 266 + backgroundColor: t.palette.positive_500, 267 + }, 268 + enableSquareButtons ? a.rounded_sm : a.rounded_full, 269 + a.justify_center, 270 + a.align_center, 271 + ]}> 272 + <CheckIcon size="xs" style={[{color: t.palette.white}]} /> 273 + </View> 274 + ) 231 275 ) : ( 232 - <ChevronIcon size="md" style={[t.atoms.text_contrast_low]} /> 276 + <ChevronIcon 277 + size={useCompactSwitcher ? 'sm' : 'md'} 278 + style={[ 279 + useCompactSwitcher ? t.atoms.text : t.atoms.text_contrast_low, 280 + ]} 281 + /> 233 282 )} 234 283 </View> 235 284 )}
+1
src/lib/routes/types.ts
··· 59 59 RunesUsabilityFeedSettings: undefined 60 60 RunesDisplaySettings: undefined 61 61 RunesDisplayAlsoLikedSettings: undefined 62 + RunesDisplayDensitySettings: undefined 62 63 RunesInfrastructureSettings: undefined 63 64 RunesExtraSettings: undefined 64 65 RunesSettingsSyncSettings: undefined
+1
src/routes.ts
··· 56 56 RunesUsabilityFeedSettings: '/settings/runes/usability/feeds', 57 57 RunesDisplaySettings: '/settings/runes/display', 58 58 RunesDisplayAlsoLikedSettings: '/settings/runes/display/also-liked', 59 + RunesDisplayDensitySettings: '/settings/runes/display/density', 59 60 RunesInfrastructureSettings: '/settings/runes/infrastructure', 60 61 RunesExtraSettings: '/settings/runes/extra', 61 62 RunesSettingsSyncSettings: '/settings/runes/settings-sync',
-2
src/screens/Settings/AppearanceSettings.tsx
··· 60 60 61 61 const enableSquareButtons = useEnableSquareButtons() 62 62 const setEnableSquareButtons = useSetEnableSquareButtons() 63 - 64 63 const colorSchemes = useColorSchemes() 65 64 const colorSchemeLabel = getColorSchemeLabel(colorSchemes, colorScheme) 66 65 ··· 254 253 <Toggle.Platform /> 255 254 </SettingsList.Item> 256 255 </Toggle.Item> 257 - 258 256 {IS_NATIVE && IS_INTERNAL && ( 259 257 <> 260 258 <SettingsList.Divider />
+61
src/screens/Settings/RunesSettings/DensitySettings.tsx
··· 1 + import {Trans, useLingui} from '@lingui/react/macro' 2 + 3 + import { 4 + useAutoCompactAccountSwitcher, 5 + useSetAutoCompactAccountSwitcher, 6 + } from '#/state/preferences/auto-compact-account-switcher' 7 + import { 8 + useCompactAccountSwitcher, 9 + useSetCompactAccountSwitcher, 10 + } from '#/state/preferences/compact-account-switcher' 11 + import * as SettingsList from '#/screens/Settings/components/SettingsList' 12 + import {atoms as a} from '#/alf' 13 + import * as Toggle from '#/components/forms/Toggle' 14 + import {PersonGroup_Stroke2_Corner2_Rounded as PersonGroupIcon} from '#/components/icons/Person' 15 + import {RunesScreenLayout} from './components/RunesScreenLayout' 16 + 17 + export function RunesDisplayDensitySettingsScreen() { 18 + const {t: l} = useLingui() 19 + 20 + const compactAccountSwitcher = useCompactAccountSwitcher() 21 + const setCompactAccountSwitcher = useSetCompactAccountSwitcher() 22 + 23 + const autoCompactAccountSwitcher = useAutoCompactAccountSwitcher() 24 + const setAutoCompactAccountSwitcher = useSetAutoCompactAccountSwitcher() 25 + 26 + return ( 27 + <RunesScreenLayout titleText={l`Density`}> 28 + <SettingsList.Group contentContainerStyle={[a.gap_sm]}> 29 + <SettingsList.ItemIcon icon={PersonGroupIcon} /> 30 + <SettingsList.ItemText> 31 + <Trans>Account switcher</Trans> 32 + </SettingsList.ItemText> 33 + <Toggle.Item 34 + name="compact_account_switcher" 35 + label={l`Use compact account switcher`} 36 + value={compactAccountSwitcher} 37 + onChange={value => setCompactAccountSwitcher(value)} 38 + style={[a.w_full]}> 39 + <Toggle.LabelText style={[a.flex_1]}> 40 + <Trans>Use compact account switcher</Trans> 41 + </Toggle.LabelText> 42 + <Toggle.Platform /> 43 + </Toggle.Item> 44 + <Toggle.Item 45 + name="auto_compact_account_switcher" 46 + label={l`Automatically use compact account switcher with more than 6 accounts`} 47 + value={autoCompactAccountSwitcher} 48 + onChange={value => setAutoCompactAccountSwitcher(value)} 49 + style={[a.w_full]}> 50 + <Toggle.LabelText style={[a.flex_1]}> 51 + <Trans> 52 + Automatically use compact account switcher with more than 6 53 + accounts 54 + </Trans> 55 + </Toggle.LabelText> 56 + <Toggle.Platform /> 57 + </Toggle.Item> 58 + </SettingsList.Group> 59 + </RunesScreenLayout> 60 + ) 61 + }
+28
src/screens/Settings/RunesSettings/DisplaySettings.tsx
··· 10 10 useAlsoLikedCollapseByDefault, 11 11 useAlsoLikedFeedEnabled, 12 12 } from '#/state/preferences' 13 + import {useAutoCompactAccountSwitcher} from '#/state/preferences/auto-compact-account-switcher' 14 + import {useCompactAccountSwitcher} from '#/state/preferences/compact-account-switcher' 13 15 import { 14 16 useHighQualityImages, 15 17 useSetHighQualityImages, ··· 35 37 import {Heart2_Stroke2_Corner0_Rounded as HeartIcon} from '#/components/icons/Heart2' 36 38 import {Image_Stroke2_Corner0_Rounded as ImageIcon} from '#/components/icons/Image' 37 39 import {Pencil_Stroke2_Corner0_Rounded as PencilIcon} from '#/components/icons/Pencil' 40 + import {PersonGroup_Stroke2_Corner2_Rounded as PersonGroupIcon} from '#/components/icons/Person' 38 41 import {Repost_Stroke2_Corner3_Rounded as RepostIcon} from '#/components/icons/Repost' 39 42 import {Window_Stroke2_Corner2_Rounded as WindowIcon} from '#/components/icons/Window' 40 43 import {Text} from '#/components/Typography' ··· 74 77 collapseByDefault={alsoLikedCollapseByDefault} 75 78 /> 76 79 } 80 + /> 81 + </SettingsList.LinkItem> 82 + <SettingsList.LinkItem 83 + to="/settings/runes/display/density" 84 + label={l`Density`} 85 + contentContainerStyle={[a.align_start]}> 86 + <SettingsList.ItemIcon icon={PersonGroupIcon} /> 87 + <ItemTextWithSubtitle 88 + titleText={<Trans>Density</Trans>} 89 + subtitleText={<AccountSwitcherDeclaration />} 77 90 /> 78 91 </SettingsList.LinkItem> 79 92 <Toggle.Item ··· 154 167 } 155 168 156 169 return <Trans>Shown in thread views, expanded by default</Trans> 170 + } 171 + 172 + function AccountSwitcherDeclaration() { 173 + const compactAccountSwitcher = useCompactAccountSwitcher() 174 + const autoCompactAccountSwitcher = useAutoCompactAccountSwitcher() 175 + 176 + if (compactAccountSwitcher) { 177 + return <Trans>Compact always on</Trans> 178 + } 179 + 180 + if (autoCompactAccountSwitcher) { 181 + return <Trans>Auto-compact with 7+ accounts</Trans> 182 + } 183 + 184 + return <Trans>Default layout only</Trans> 157 185 } 158 186 159 187 function PostReplacementDialog({
+4
src/state/persisted/schema.ts
··· 196 196 discoverContextEnabled: z.boolean().optional(), 197 197 enableSquareAvatars: z.boolean().optional(), 198 198 enableSquareButtons: z.boolean().optional(), 199 + useCompactAccountSwitcher: z.boolean().optional(), 200 + autoCompactAccountSwitcher: z.boolean().optional(), 199 201 disableVerifyEmailReminder: z.boolean().optional(), 200 202 showViaClient: z.boolean().optional(), 201 203 deerVerification: z ··· 335 337 discoverContextEnabled: false, 336 338 enableSquareAvatars: true, 337 339 enableSquareButtons: true, 340 + useCompactAccountSwitcher: false, 341 + autoCompactAccountSwitcher: true, 338 342 disableVerifyEmailReminder: false, 339 343 showViaClient: true, 340 344 deerVerification: {
+56
src/state/preferences/auto-compact-account-switcher.tsx
··· 1 + import { 2 + createContext, 3 + type PropsWithChildren, 4 + useCallback, 5 + useContext, 6 + useEffect, 7 + useState, 8 + } from 'react' 9 + 10 + import * as persisted from '#/state/persisted' 11 + 12 + type StateContext = persisted.Schema['autoCompactAccountSwitcher'] 13 + type SetContext = (v: persisted.Schema['autoCompactAccountSwitcher']) => void 14 + 15 + const stateContext = createContext<StateContext>( 16 + persisted.defaults.autoCompactAccountSwitcher, 17 + ) 18 + const setContext = createContext<SetContext>( 19 + (_: persisted.Schema['autoCompactAccountSwitcher']) => {}, 20 + ) 21 + 22 + export function Provider({children}: PropsWithChildren<{}>) { 23 + const [state, setState] = useState( 24 + persisted.get('autoCompactAccountSwitcher'), 25 + ) 26 + 27 + const setStateWrapped = useCallback( 28 + (value: persisted.Schema['autoCompactAccountSwitcher']) => { 29 + setState(value) 30 + persisted.write('autoCompactAccountSwitcher', value) 31 + }, 32 + [], 33 + ) 34 + 35 + useEffect(() => { 36 + return persisted.onUpdate('autoCompactAccountSwitcher', next => { 37 + setState(next) 38 + }) 39 + }, []) 40 + 41 + return ( 42 + <stateContext.Provider value={state}> 43 + <setContext.Provider value={setStateWrapped}> 44 + {children} 45 + </setContext.Provider> 46 + </stateContext.Provider> 47 + ) 48 + } 49 + 50 + export function useAutoCompactAccountSwitcher() { 51 + return useContext(stateContext) 52 + } 53 + 54 + export function useSetAutoCompactAccountSwitcher() { 55 + return useContext(setContext) 56 + }
+54
src/state/preferences/compact-account-switcher.tsx
··· 1 + import { 2 + createContext, 3 + type PropsWithChildren, 4 + useCallback, 5 + useContext, 6 + useEffect, 7 + useState, 8 + } from 'react' 9 + 10 + import * as persisted from '#/state/persisted' 11 + 12 + type StateContext = persisted.Schema['useCompactAccountSwitcher'] 13 + type SetContext = (v: persisted.Schema['useCompactAccountSwitcher']) => void 14 + 15 + const stateContext = createContext<StateContext>( 16 + persisted.defaults.useCompactAccountSwitcher, 17 + ) 18 + const setContext = createContext<SetContext>( 19 + (_: persisted.Schema['useCompactAccountSwitcher']) => {}, 20 + ) 21 + 22 + export function Provider({children}: PropsWithChildren<{}>) { 23 + const [state, setState] = useState(persisted.get('useCompactAccountSwitcher')) 24 + 25 + const setStateWrapped = useCallback( 26 + (value: persisted.Schema['useCompactAccountSwitcher']) => { 27 + setState(value) 28 + persisted.write('useCompactAccountSwitcher', value) 29 + }, 30 + [], 31 + ) 32 + 33 + useEffect(() => { 34 + return persisted.onUpdate('useCompactAccountSwitcher', next => { 35 + setState(next) 36 + }) 37 + }, []) 38 + 39 + return ( 40 + <stateContext.Provider value={state}> 41 + <setContext.Provider value={setStateWrapped}> 42 + {children} 43 + </setContext.Provider> 44 + </stateContext.Provider> 45 + ) 46 + } 47 + 48 + export function useCompactAccountSwitcher() { 49 + return useContext(stateContext) 50 + } 51 + 52 + export function useSetCompactAccountSwitcher() { 53 + return useContext(setContext) 54 + }
+130 -121
src/state/preferences/index.tsx
··· 3 3 import {Provider as AlsoLikedCollapseByDefaultProvider} from './also-liked-collapse-by-default' 4 4 import {Provider as AlsoLikedFeedProvider} from './also-liked-feed-enabled' 5 5 import {Provider as AltTextRequiredProvider} from './alt-text-required' 6 + import {Provider as AutoCompactAccountSwitcherProvider} from './auto-compact-account-switcher' 6 7 import {Provider as AutoLikeOnRepostProvider} from './auto-like-on-repost' 7 - import {Provider as SettingsSyncProvider} from './settings-sync' 8 8 import {Provider as AutoplayProvider} from './autoplay' 9 + import {Provider as CompactAccountSwitcherProvider} from './compact-account-switcher' 9 10 import {Provider as ConstellationProvider} from './constellation-enabled' 10 11 import {Provider as ConstellationInstanceProvider} from './constellation-instance' 11 12 import {Provider as DeerVerificationProvider} from './deer-verification' ··· 50 51 import {Provider as PlcDirectoryProvider} from './plc-directory' 51 52 import {Provider as PostNameReplacementProvider} from './post-name-replacement.tsx' 52 53 import {Provider as RepostCarouselProvider} from './repost-carousel-enabled' 54 + import {Provider as SettingsSyncProvider} from './settings-sync' 53 55 import {Provider as ShowFollowsYouBadgeProvider} from './show-follows-you-badge' 54 56 import {Provider as ShowLinkInHandleProvider} from './show-link-in-handle' 55 57 import {Provider as ShowLinkInHandleOnlyOnWorkingLinksProvider} from './show-link-in-handle-only-on-working-links' ··· 72 74 useRequireAltTextEnabled, 73 75 useSetRequireAltTextEnabled, 74 76 } from './alt-text-required' 75 - export {useSettingsSyncEnabled, useSetSettingsSyncEnabled} from './settings-sync' 76 77 export {useAutoplayDisabled, useSetAutoplayDisabled} from './autoplay' 77 78 export { 78 79 useDisableComposerPrompt, ··· 118 119 usePlcDirectory, 119 120 useSetPlcDirectory, 120 121 } from './plc-directory' 122 + export { 123 + useSetSettingsSyncEnabled, 124 + useSettingsSyncEnabled, 125 + } from './settings-sync' 121 126 export {useSetSubtitlesEnabled, useSubtitlesEnabled} from './subtitles' 122 127 export { 123 128 useSetTranslationServicePreference, ··· 127 132 export function Provider({children}: PropsWithChildren<{}>) { 128 133 return ( 129 134 <SettingsSyncProvider> 130 - <LanguagesProvider> 131 - <AltTextRequiredProvider> 132 - <AutoLikeOnRepostProvider> 133 - <ExternalShareButtonsProvider> 134 - <GoLinksProvider> 135 - <NoAppLabelersProvider> 136 - <DirectFetchRecordsProvider> 137 - <ConstellationProvider> 138 - <ConstellationInstanceProvider> 139 - <DeerVerificationProvider> 140 - <FaviconServiceProvider> 141 - <PdsLabelProvider> 142 - <NoDiscoverProvider> 143 - <ShowLinkInHandleProvider> 144 - <ShowLinkInHandleOnlyOnWorkingLinksProvider> 145 - <UseHandleInLinksProvider> 146 - <LargeAltBadgeProvider> 147 - <ExternalEmbedsProvider> 148 - <HiddenPostsProvider> 149 - <HighQualityImagesProvider> 150 - <ImageCdnHostProvider> 151 - <PlcDirectoryProvider> 152 - <InAppBrowserProvider> 153 - <DisableHapticsProvider> 154 - <AutoplayProvider> 155 - <UsedStarterPacksProvider> 156 - <SubtitlesProvider> 157 - <TrendingSettingsProvider> 158 - <RepostCarouselProvider> 159 - <AlsoLikedFeedProvider> 160 - <AlsoLikedCollapseByDefaultProvider> 161 - <KawaiiProvider> 162 - <HideFeedsPromoTabProvider> 163 - <DisableViaRepostNotificationProvider> 164 - <DisableLikesMetricsProvider> 165 - <DisableRepostsMetricsProvider> 166 - <DisableQuotesMetricsProvider> 167 - <DisableSavesMetricsProvider> 168 - <DisableReplyMetricsProvider> 169 - <DisableFollowersMetricsProvider> 170 - <DisableFollowingMetricsProvider> 171 - <DisableFollowedByMetricsProvider> 172 - <DisablePostsMetricsProvider> 173 - <ShowFollowsYouBadgeProvider> 174 - <HideSimilarAccountsRecommProvider> 175 - <HideScaryFollowButtonsProvider> 176 - <HideUnreplyablePostsProvider> 177 - <EnableSquareAvatarsProvider> 178 - <EnableSquareButtonsProvider> 179 - <ShowViaClientProvider> 180 - <PostNameReplacementProvider> 181 - <DisableVerifyEmailReminderProvider> 182 - <TranslationServicePreferenceProvider> 183 - <OpenRouterProvider> 184 - <DisableComposerPromptProvider> 185 - <DisableTopOfFeedButtonProvider> 186 - <DiscoverContextEnabledProvider> 187 - <OmitViaFieldProvider> 188 - { 189 - children 190 - } 191 - </OmitViaFieldProvider> 192 - </DiscoverContextEnabledProvider> 193 - </DisableTopOfFeedButtonProvider> 194 - </DisableComposerPromptProvider> 195 - </OpenRouterProvider> 196 - </TranslationServicePreferenceProvider> 197 - </DisableVerifyEmailReminderProvider> 198 - </PostNameReplacementProvider> 199 - </ShowViaClientProvider> 200 - </EnableSquareButtonsProvider> 201 - </EnableSquareAvatarsProvider> 202 - </HideUnreplyablePostsProvider> 203 - </HideScaryFollowButtonsProvider> 204 - </HideSimilarAccountsRecommProvider> 205 - </ShowFollowsYouBadgeProvider> 206 - </DisablePostsMetricsProvider> 207 - </DisableFollowedByMetricsProvider> 208 - </DisableFollowingMetricsProvider> 209 - </DisableFollowersMetricsProvider> 210 - </DisableReplyMetricsProvider> 211 - </DisableSavesMetricsProvider> 212 - </DisableQuotesMetricsProvider> 213 - </DisableRepostsMetricsProvider> 214 - </DisableLikesMetricsProvider> 215 - </DisableViaRepostNotificationProvider> 216 - </HideFeedsPromoTabProvider> 217 - </KawaiiProvider> 218 - </AlsoLikedCollapseByDefaultProvider> 219 - </AlsoLikedFeedProvider> 220 - </RepostCarouselProvider> 221 - </TrendingSettingsProvider> 222 - </SubtitlesProvider> 223 - </UsedStarterPacksProvider> 224 - </AutoplayProvider> 225 - </DisableHapticsProvider> 226 - </InAppBrowserProvider> 227 - </PlcDirectoryProvider> 228 - </ImageCdnHostProvider> 229 - </HighQualityImagesProvider> 230 - </HiddenPostsProvider> 231 - </ExternalEmbedsProvider> 232 - </LargeAltBadgeProvider> 233 - </UseHandleInLinksProvider> 234 - </ShowLinkInHandleOnlyOnWorkingLinksProvider> 235 - </ShowLinkInHandleProvider> 236 - </NoDiscoverProvider> 237 - </PdsLabelProvider> 238 - </FaviconServiceProvider> 239 - </DeerVerificationProvider> 240 - </ConstellationInstanceProvider> 241 - </ConstellationProvider> 242 - </DirectFetchRecordsProvider> 243 - </NoAppLabelersProvider> 244 - </GoLinksProvider> 245 - </ExternalShareButtonsProvider> 246 - </AutoLikeOnRepostProvider> 247 - </AltTextRequiredProvider> 248 - </LanguagesProvider> 135 + <LanguagesProvider> 136 + <AltTextRequiredProvider> 137 + <AutoLikeOnRepostProvider> 138 + <ExternalShareButtonsProvider> 139 + <GoLinksProvider> 140 + <NoAppLabelersProvider> 141 + <DirectFetchRecordsProvider> 142 + <ConstellationProvider> 143 + <ConstellationInstanceProvider> 144 + <DeerVerificationProvider> 145 + <FaviconServiceProvider> 146 + <PdsLabelProvider> 147 + <NoDiscoverProvider> 148 + <ShowLinkInHandleProvider> 149 + <ShowLinkInHandleOnlyOnWorkingLinksProvider> 150 + <UseHandleInLinksProvider> 151 + <LargeAltBadgeProvider> 152 + <ExternalEmbedsProvider> 153 + <HiddenPostsProvider> 154 + <HighQualityImagesProvider> 155 + <ImageCdnHostProvider> 156 + <PlcDirectoryProvider> 157 + <InAppBrowserProvider> 158 + <DisableHapticsProvider> 159 + <AutoplayProvider> 160 + <UsedStarterPacksProvider> 161 + <SubtitlesProvider> 162 + <TrendingSettingsProvider> 163 + <RepostCarouselProvider> 164 + <AlsoLikedFeedProvider> 165 + <AlsoLikedCollapseByDefaultProvider> 166 + <KawaiiProvider> 167 + <HideFeedsPromoTabProvider> 168 + <DisableViaRepostNotificationProvider> 169 + <DisableLikesMetricsProvider> 170 + <DisableRepostsMetricsProvider> 171 + <DisableQuotesMetricsProvider> 172 + <DisableSavesMetricsProvider> 173 + <DisableReplyMetricsProvider> 174 + <DisableFollowersMetricsProvider> 175 + <DisableFollowingMetricsProvider> 176 + <DisableFollowedByMetricsProvider> 177 + <DisablePostsMetricsProvider> 178 + <ShowFollowsYouBadgeProvider> 179 + <HideSimilarAccountsRecommProvider> 180 + <HideScaryFollowButtonsProvider> 181 + <HideUnreplyablePostsProvider> 182 + <EnableSquareAvatarsProvider> 183 + <EnableSquareButtonsProvider> 184 + <AutoCompactAccountSwitcherProvider> 185 + <CompactAccountSwitcherProvider> 186 + <ShowViaClientProvider> 187 + <PostNameReplacementProvider> 188 + <DisableVerifyEmailReminderProvider> 189 + <TranslationServicePreferenceProvider> 190 + <OpenRouterProvider> 191 + <DisableComposerPromptProvider> 192 + <DisableTopOfFeedButtonProvider> 193 + <DiscoverContextEnabledProvider> 194 + <OmitViaFieldProvider> 195 + { 196 + children 197 + } 198 + </OmitViaFieldProvider> 199 + </DiscoverContextEnabledProvider> 200 + </DisableTopOfFeedButtonProvider> 201 + </DisableComposerPromptProvider> 202 + </OpenRouterProvider> 203 + </TranslationServicePreferenceProvider> 204 + </DisableVerifyEmailReminderProvider> 205 + </PostNameReplacementProvider> 206 + </ShowViaClientProvider> 207 + </CompactAccountSwitcherProvider> 208 + </AutoCompactAccountSwitcherProvider> 209 + </EnableSquareButtonsProvider> 210 + </EnableSquareAvatarsProvider> 211 + </HideUnreplyablePostsProvider> 212 + </HideScaryFollowButtonsProvider> 213 + </HideSimilarAccountsRecommProvider> 214 + </ShowFollowsYouBadgeProvider> 215 + </DisablePostsMetricsProvider> 216 + </DisableFollowedByMetricsProvider> 217 + </DisableFollowingMetricsProvider> 218 + </DisableFollowersMetricsProvider> 219 + </DisableReplyMetricsProvider> 220 + </DisableSavesMetricsProvider> 221 + </DisableQuotesMetricsProvider> 222 + </DisableRepostsMetricsProvider> 223 + </DisableLikesMetricsProvider> 224 + </DisableViaRepostNotificationProvider> 225 + </HideFeedsPromoTabProvider> 226 + </KawaiiProvider> 227 + </AlsoLikedCollapseByDefaultProvider> 228 + </AlsoLikedFeedProvider> 229 + </RepostCarouselProvider> 230 + </TrendingSettingsProvider> 231 + </SubtitlesProvider> 232 + </UsedStarterPacksProvider> 233 + </AutoplayProvider> 234 + </DisableHapticsProvider> 235 + </InAppBrowserProvider> 236 + </PlcDirectoryProvider> 237 + </ImageCdnHostProvider> 238 + </HighQualityImagesProvider> 239 + </HiddenPostsProvider> 240 + </ExternalEmbedsProvider> 241 + </LargeAltBadgeProvider> 242 + </UseHandleInLinksProvider> 243 + </ShowLinkInHandleOnlyOnWorkingLinksProvider> 244 + </ShowLinkInHandleProvider> 245 + </NoDiscoverProvider> 246 + </PdsLabelProvider> 247 + </FaviconServiceProvider> 248 + </DeerVerificationProvider> 249 + </ConstellationInstanceProvider> 250 + </ConstellationProvider> 251 + </DirectFetchRecordsProvider> 252 + </NoAppLabelersProvider> 253 + </GoLinksProvider> 254 + </ExternalShareButtonsProvider> 255 + </AutoLikeOnRepostProvider> 256 + </AltTextRequiredProvider> 257 + </LanguagesProvider> 249 258 </SettingsSyncProvider> 250 259 ) 251 260 }
+8 -9
src/state/preferences/settings-sync.tsx
··· 5 5 useEffect, 6 6 useState, 7 7 } from 'react' 8 - import type {PropsWithChildren} from 'react' 8 + import {type PropsWithChildren} from 'react' 9 9 10 10 import * as persisted from '#/state/persisted' 11 - import type {Schema} from '#/state/persisted/schema' 11 + import {type Schema} from '#/state/persisted/schema' 12 12 13 13 // --------------------------------------------------------------------------- 14 14 // Synced keys allowlist ··· 65 65 'discoverContextEnabled', 66 66 'enableSquareAvatars', 67 67 'enableSquareButtons', 68 + 'useCompactAccountSwitcher', 69 + 'autoCompactAccountSwitcher', 68 70 'disableVerifyEmailReminder', 69 71 'showViaClient', 70 72 'deerVerification', ··· 115 117 Boolean(persisted.get('settingsSyncEnabled')), 116 118 ) 117 119 118 - const setStateWrapped = useCallback( 119 - (value: boolean) => { 120 - setState(value) 121 - persisted.write('settingsSyncEnabled', value) 122 - }, 123 - [], 124 - ) 120 + const setStateWrapped = useCallback((value: boolean) => { 121 + setState(value) 122 + persisted.write('settingsSyncEnabled', value) 123 + }, []) 125 124 126 125 useEffect(() => { 127 126 return persisted.onUpdate('settingsSyncEnabled', next => {