From c8f264b78b1dfb95f68bfb820bd012828cd5fddc Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 29 Oct 2024 21:14:54 +0000 Subject: Settings revamp (#5745) * start building storybook * add title * add some styles * try out new icons * more settings list component parts * make text do the spacing * clean up storybook * gated new settings screen * switch account * add current profile * use Layout.Screen * Layout.Header and Layout.Content * translate helpdesk text thanks @surfdude29! Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * add account settings * undo changes to export car dialog * privacy and security screen * Translate protect account stuff Thanks @surfdude29! Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * content and media settings * about settings * 2fa copy Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * a11y and appearance * use new components for appearance settings * redesign accessibility settings * Update ContentAndMediaSettings.tsx Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * add divider * remove a11y and appearance middleman screen * fix web settingslist styles * new SettingsList.Group component * explain how portal magic works * hide pwioptout in old location * Update Settings.tsx Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> * replace gate with `IS_INTERNAL` * add IS_INTERNAL to app-info.web * fix profile area growing * add close button to switch account --------- Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> --- src/screens/Settings/Settings.tsx | 282 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 src/screens/Settings/Settings.tsx (limited to 'src/screens/Settings/Settings.tsx') diff --git a/src/screens/Settings/Settings.tsx b/src/screens/Settings/Settings.tsx new file mode 100644 index 000000000..789ffb56f --- /dev/null +++ b/src/screens/Settings/Settings.tsx @@ -0,0 +1,282 @@ +import React from 'react' +import {View} from 'react-native' +import {Linking} from 'react-native' +import {AppBskyActorDefs, moderateProfile} from '@atproto/api' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {NativeStackScreenProps} from '@react-navigation/native-stack' + +import {HELP_DESK_URL} from '#/lib/constants' +import {CommonNavigatorParams} from '#/lib/routes/types' +import {useProfileShadow} from '#/state/cache/profile-shadow' +import {useModerationOpts} from '#/state/preferences/moderation-opts' +import {useProfileQuery, useProfilesQuery} from '#/state/queries/profile' +import {useSession, useSessionApi} from '#/state/session' +import {useLoggedOutViewControls} from '#/state/shell/logged-out' +import {useCloseAllActiveElements} from '#/state/util' +import {UserAvatar} from '#/view/com/util/UserAvatar' +import {ProfileHeaderDisplayName} from '#/screens/Profile/Header/DisplayName' +import {ProfileHeaderHandle} from '#/screens/Profile/Header/Handle' +import * as SettingsList from '#/screens/Settings/components/SettingsList' +import {atoms as a, useTheme} from '#/alf' +import {useDialogControl} from '#/components/Dialog' +import {SwitchAccountDialog} from '#/components/dialogs/SwitchAccount' +import {Accessibility_Stroke2_Corner2_Rounded as AccessibilityIcon} from '#/components/icons/Accessibility' +import {BubbleInfo_Stroke2_Corner2_Rounded as BubbleInfoIcon} from '#/components/icons/BubbleInfo' +import {CircleQuestion_Stroke2_Corner2_Rounded as CircleQuestionIcon} from '#/components/icons/CircleQuestion' +import {Earth_Stroke2_Corner2_Rounded as EarthIcon} from '#/components/icons/Globe' +import {Lock_Stroke2_Corner2_Rounded as LockIcon} from '#/components/icons/Lock' +import {PaintRoller_Stroke2_Corner2_Rounded as PaintRollerIcon} from '#/components/icons/PaintRoller' +import { + Person_Stroke2_Corner2_Rounded as PersonIcon, + PersonGroup_Stroke2_Corner2_Rounded as PersonGroupIcon, +} from '#/components/icons/Person' +import {RaisingHand4Finger_Stroke2_Corner2_Rounded as HandIcon} from '#/components/icons/RaisingHand' +import {Window_Stroke2_Corner2_Rounded as WindowIcon} from '#/components/icons/Window' +import * as Layout from '#/components/Layout' +import * as Prompt from '#/components/Prompt' + +type Props = NativeStackScreenProps +export function SettingsScreen({}: Props) { + const {_} = useLingui() + const {logoutEveryAccount} = useSessionApi() + const {accounts, currentAccount} = useSession() + const switchAccountControl = useDialogControl() + const signOutPromptControl = Prompt.usePromptControl() + const {data: profile} = useProfileQuery({did: currentAccount?.did}) + const {setShowLoggedOut} = useLoggedOutViewControls() + const closeEverything = useCloseAllActiveElements() + + const onAddAnotherAccount = () => { + setShowLoggedOut(true) + closeEverything() + } + + return ( + + + + + + {profile && } + + 1 + ? _(msg`Switch account`) + : _(msg`Add another account`) + } + onPress={() => + accounts.length > 1 + ? switchAccountControl.open() + : onAddAnotherAccount() + }> + + + {accounts.length > 1 ? ( + Switch account + ) : ( + Add another account + )} + + {accounts.length > 1 && ( + acc.did) + .filter(did => did !== currentAccount?.did) + .slice(0, 5)} + /> + )} + + + + + + Account + + + + + + Privacy and security + + + + + + Moderation + + + + + + Content and media + + + + + + Appearance + + + + + + Accessibility + + + + + + Languages + + + Linking.openURL(HELP_DESK_URL)} + label={_(msg`Help`)} + accessibilityHint={_(msg`Open helpdesk in browser`)}> + + + Help + + + + + + + About + + + + signOutPromptControl.open()} + label={_(msg`Sign out`)}> + + Sign out + + + + + + logoutEveryAccount('Settings')} + confirmButtonCta={_(msg`Sign out`)} + cancelButtonCta={_(msg`Cancel`)} + confirmButtonColor="negative" + /> + + + + ) +} + +function ProfilePreview({ + profile, +}: { + profile: AppBskyActorDefs.ProfileViewDetailed +}) { + const shadow = useProfileShadow(profile) + const moderationOpts = useModerationOpts() + + if (!moderationOpts) return null + + const moderation = moderateProfile(profile, moderationOpts) + + return ( + <> + + + + + ) +} + +const AVI_SIZE = 26 +const HALF_AVI_SIZE = AVI_SIZE / 2 + +function AvatarStack({profiles}: {profiles: string[]}) { + const {data, error} = useProfilesQuery({handles: profiles}) + const t = useTheme() + const moderationOpts = useModerationOpts() + + if (error) { + console.error(error) + return null + } + + const isPending = !data || !moderationOpts + + const items = isPending + ? Array.from({length: profiles.length}).map((_, i) => ({ + key: i, + profile: null, + moderation: null, + })) + : data.profiles.map(item => ({ + key: item.did, + profile: item, + moderation: moderateProfile(item, moderationOpts), + })) + + return ( + + {items.map((item, i) => ( + + {item.profile && ( + + )} + + ))} + + ) +} -- cgit 1.4.1