Rework logged out state to preserve routing and work for web
This commit is contained in:
parent
b5c64a03b6
commit
774fb83719
26 changed files with 1063 additions and 1078 deletions
|
@ -16,6 +16,7 @@ import {
|
|||
} from '@fortawesome/react-native-fontawesome'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
|
||||
import {withAuthRequired} from 'view/com/auth/withAuthRequired'
|
||||
import * as AppInfo from 'lib/app-info'
|
||||
import {useStores} from 'state/index'
|
||||
import {s, colors} from 'lib/styles'
|
||||
|
@ -33,235 +34,237 @@ import {useAnalytics} from 'lib/analytics'
|
|||
import {NavigationProp} from 'lib/routes/types'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'>
|
||||
export const SettingsScreen = observer(function Settings({}: Props) {
|
||||
const theme = useTheme()
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {screen, track} = useAnalytics()
|
||||
const [isSwitching, setIsSwitching] = React.useState(false)
|
||||
export const SettingsScreen = withAuthRequired(
|
||||
observer(function Settings({}: Props) {
|
||||
const theme = useTheme()
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {screen, track} = useAnalytics()
|
||||
const [isSwitching, setIsSwitching] = React.useState(false)
|
||||
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
screen('Settings')
|
||||
store.shell.setMinimalShellMode(false)
|
||||
}, [screen, store]),
|
||||
)
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
screen('Settings')
|
||||
store.shell.setMinimalShellMode(false)
|
||||
}, [screen, store]),
|
||||
)
|
||||
|
||||
const onPressSwitchAccount = async (acct: AccountData) => {
|
||||
track('Settings:SwitchAccountButtonClicked')
|
||||
setIsSwitching(true)
|
||||
if (await store.session.resumeSession(acct)) {
|
||||
const onPressSwitchAccount = async (acct: AccountData) => {
|
||||
track('Settings:SwitchAccountButtonClicked')
|
||||
setIsSwitching(true)
|
||||
if (await store.session.resumeSession(acct)) {
|
||||
setIsSwitching(false)
|
||||
navigation.navigate('HomeTab')
|
||||
navigation.dispatch(StackActions.popToTop())
|
||||
Toast.show(`Signed in as ${acct.displayName || acct.handle}`)
|
||||
return
|
||||
}
|
||||
setIsSwitching(false)
|
||||
Toast.show('Sorry! We need you to enter your password.')
|
||||
navigation.navigate('HomeTab')
|
||||
navigation.dispatch(StackActions.popToTop())
|
||||
Toast.show(`Signed in as ${acct.displayName || acct.handle}`)
|
||||
return
|
||||
store.session.clear()
|
||||
}
|
||||
const onPressAddAccount = () => {
|
||||
track('Settings:AddAccountButtonClicked')
|
||||
store.session.clear()
|
||||
}
|
||||
const onPressChangeHandle = () => {
|
||||
track('Settings:ChangeHandleButtonClicked')
|
||||
store.shell.openModal({
|
||||
name: 'change-handle',
|
||||
onChanged() {
|
||||
setIsSwitching(true)
|
||||
store.session.reloadFromServer().then(
|
||||
() => {
|
||||
setIsSwitching(false)
|
||||
Toast.show('Your handle has been updated')
|
||||
},
|
||||
err => {
|
||||
store.log.error(
|
||||
'Failed to reload from server after handle update',
|
||||
{err},
|
||||
)
|
||||
setIsSwitching(false)
|
||||
},
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
const onPressSignout = () => {
|
||||
track('Settings:SignOutButtonClicked')
|
||||
store.session.logout()
|
||||
}
|
||||
const onPressDeleteAccount = () => {
|
||||
store.shell.openModal({name: 'delete-account'})
|
||||
}
|
||||
setIsSwitching(false)
|
||||
Toast.show('Sorry! We need you to enter your password.')
|
||||
navigation.navigate('HomeTab')
|
||||
navigation.dispatch(StackActions.popToTop())
|
||||
store.session.clear()
|
||||
}
|
||||
const onPressAddAccount = () => {
|
||||
track('Settings:AddAccountButtonClicked')
|
||||
store.session.clear()
|
||||
}
|
||||
const onPressChangeHandle = () => {
|
||||
track('Settings:ChangeHandleButtonClicked')
|
||||
store.shell.openModal({
|
||||
name: 'change-handle',
|
||||
onChanged() {
|
||||
setIsSwitching(true)
|
||||
store.session.reloadFromServer().then(
|
||||
() => {
|
||||
setIsSwitching(false)
|
||||
Toast.show('Your handle has been updated')
|
||||
},
|
||||
err => {
|
||||
store.log.error(
|
||||
'Failed to reload from server after handle update',
|
||||
{err},
|
||||
)
|
||||
setIsSwitching(false)
|
||||
},
|
||||
)
|
||||
},
|
||||
})
|
||||
}
|
||||
const onPressSignout = () => {
|
||||
track('Settings:SignOutButtonClicked')
|
||||
store.session.logout()
|
||||
}
|
||||
const onPressDeleteAccount = () => {
|
||||
store.shell.openModal({name: 'delete-account'})
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[s.hContentRegion]} testID="settingsScreen">
|
||||
<ViewHeader title="Settings" />
|
||||
<ScrollView style={s.hContentRegion}>
|
||||
<View style={styles.spacer20} />
|
||||
<View style={[s.flexRow, styles.heading]}>
|
||||
<Text type="xl-bold" style={pal.text}>
|
||||
Signed in as
|
||||
</Text>
|
||||
<View style={s.flex1} />
|
||||
</View>
|
||||
{isSwitching ? (
|
||||
<View style={[pal.view, styles.linkCard]}>
|
||||
<ActivityIndicator />
|
||||
return (
|
||||
<View style={[s.hContentRegion]} testID="settingsScreen">
|
||||
<ViewHeader title="Settings" />
|
||||
<ScrollView style={s.hContentRegion}>
|
||||
<View style={styles.spacer20} />
|
||||
<View style={[s.flexRow, styles.heading]}>
|
||||
<Text type="xl-bold" style={pal.text}>
|
||||
Signed in as
|
||||
</Text>
|
||||
<View style={s.flex1} />
|
||||
</View>
|
||||
) : (
|
||||
<Link
|
||||
href={`/profile/${store.me.handle}`}
|
||||
title="Your profile"
|
||||
noFeedback>
|
||||
{isSwitching ? (
|
||||
<View style={[pal.view, styles.linkCard]}>
|
||||
<ActivityIndicator />
|
||||
</View>
|
||||
) : (
|
||||
<Link
|
||||
href={`/profile/${store.me.handle}`}
|
||||
title="Your profile"
|
||||
noFeedback>
|
||||
<View style={[pal.view, styles.linkCard]}>
|
||||
<View style={styles.avi}>
|
||||
<UserAvatar size={40} avatar={store.me.avatar} />
|
||||
</View>
|
||||
<View style={[s.flex1]}>
|
||||
<Text type="md-bold" style={pal.text} numberOfLines={1}>
|
||||
{store.me.displayName || store.me.handle}
|
||||
</Text>
|
||||
<Text type="sm" style={pal.textLight} numberOfLines={1}>
|
||||
{store.me.handle}
|
||||
</Text>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
testID="signOutBtn"
|
||||
onPress={isSwitching ? undefined : onPressSignout}>
|
||||
<Text type="lg" style={pal.link}>
|
||||
Sign out
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Link>
|
||||
)}
|
||||
{store.session.switchableAccounts.map(account => (
|
||||
<TouchableOpacity
|
||||
testID={`switchToAccountBtn-${account.handle}`}
|
||||
key={account.did}
|
||||
style={[pal.view, styles.linkCard, isSwitching && styles.dimmed]}
|
||||
onPress={
|
||||
isSwitching ? undefined : () => onPressSwitchAccount(account)
|
||||
}>
|
||||
<View style={styles.avi}>
|
||||
<UserAvatar size={40} avatar={store.me.avatar} />
|
||||
<UserAvatar size={40} avatar={account.aviUrl} />
|
||||
</View>
|
||||
<View style={[s.flex1]}>
|
||||
<Text type="md-bold" style={pal.text} numberOfLines={1}>
|
||||
{store.me.displayName || store.me.handle}
|
||||
<Text type="md-bold" style={pal.text}>
|
||||
{account.displayName || account.handle}
|
||||
</Text>
|
||||
<Text type="sm" style={pal.textLight} numberOfLines={1}>
|
||||
{store.me.handle}
|
||||
<Text type="sm" style={pal.textLight}>
|
||||
{account.handle}
|
||||
</Text>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
testID="signOutBtn"
|
||||
onPress={isSwitching ? undefined : onPressSignout}>
|
||||
<Text type="lg" style={pal.link}>
|
||||
Sign out
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Link>
|
||||
)}
|
||||
{store.session.switchableAccounts.map(account => (
|
||||
<AccountDropdownBtn handle={account.handle} />
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
<TouchableOpacity
|
||||
testID={`switchToAccountBtn-${account.handle}`}
|
||||
key={account.did}
|
||||
style={[pal.view, styles.linkCard, isSwitching && styles.dimmed]}
|
||||
onPress={
|
||||
isSwitching ? undefined : () => onPressSwitchAccount(account)
|
||||
}>
|
||||
<View style={styles.avi}>
|
||||
<UserAvatar size={40} avatar={account.aviUrl} />
|
||||
testID="switchToNewAccountBtn"
|
||||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
||||
onPress={isSwitching ? undefined : onPressAddAccount}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="plus"
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
</View>
|
||||
<View style={[s.flex1]}>
|
||||
<Text type="md-bold" style={pal.text}>
|
||||
{account.displayName || account.handle}
|
||||
</Text>
|
||||
<Text type="sm" style={pal.textLight}>
|
||||
{account.handle}
|
||||
</Text>
|
||||
</View>
|
||||
<AccountDropdownBtn handle={account.handle} />
|
||||
<Text type="lg" style={pal.text}>
|
||||
Add account
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
<TouchableOpacity
|
||||
testID="switchToNewAccountBtn"
|
||||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
||||
onPress={isSwitching ? undefined : onPressAddAccount}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="plus"
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Add account
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Advanced
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
testID="changeHandleBtn"
|
||||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
||||
onPress={isSwitching ? undefined : onPressChangeHandle}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="at"
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Change my handle
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Advanced
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
testID="changeHandleBtn"
|
||||
style={[styles.linkCard, pal.view, isSwitching && styles.dimmed]}
|
||||
onPress={isSwitching ? undefined : onPressChangeHandle}>
|
||||
<View style={[styles.iconContainer, pal.btn]}>
|
||||
<FontAwesomeIcon
|
||||
icon="at"
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
/>
|
||||
</View>
|
||||
<Text type="lg" style={pal.text}>
|
||||
Change my handle
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Danger zone
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Danger zone
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={[pal.view, styles.linkCard]}
|
||||
onPress={onPressDeleteAccount}>
|
||||
<View
|
||||
style={[
|
||||
styles.iconContainer,
|
||||
theme.colorScheme === 'dark'
|
||||
? styles.trashIconContainerDark
|
||||
: styles.trashIconContainerLight,
|
||||
]}>
|
||||
<FontAwesomeIcon
|
||||
icon={['far', 'trash-can']}
|
||||
<TouchableOpacity
|
||||
style={[pal.view, styles.linkCard]}
|
||||
onPress={onPressDeleteAccount}>
|
||||
<View
|
||||
style={[
|
||||
styles.iconContainer,
|
||||
theme.colorScheme === 'dark'
|
||||
? styles.trashIconContainerDark
|
||||
: styles.trashIconContainerLight,
|
||||
]}>
|
||||
<FontAwesomeIcon
|
||||
icon={['far', 'trash-can']}
|
||||
style={
|
||||
theme.colorScheme === 'dark'
|
||||
? styles.dangerDark
|
||||
: styles.dangerLight
|
||||
}
|
||||
size={21}
|
||||
/>
|
||||
</View>
|
||||
<Text
|
||||
type="lg"
|
||||
style={
|
||||
theme.colorScheme === 'dark'
|
||||
? styles.dangerDark
|
||||
: styles.dangerLight
|
||||
}
|
||||
size={21}
|
||||
/>
|
||||
</View>
|
||||
<Text
|
||||
type="lg"
|
||||
style={
|
||||
theme.colorScheme === 'dark'
|
||||
? styles.dangerDark
|
||||
: styles.dangerLight
|
||||
}>
|
||||
Delete my account
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
}>
|
||||
Delete my account
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.spacer20} />
|
||||
<View style={styles.spacer20} />
|
||||
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Developer tools
|
||||
</Text>
|
||||
<Link
|
||||
style={[pal.view, styles.linkCardNoIcon]}
|
||||
href="/sys/log"
|
||||
title="System log">
|
||||
<Text type="lg" style={pal.text}>
|
||||
System log
|
||||
<Text type="xl-bold" style={[pal.text, styles.heading]}>
|
||||
Developer tools
|
||||
</Text>
|
||||
</Link>
|
||||
<Link
|
||||
style={[pal.view, styles.linkCardNoIcon]}
|
||||
href="/sys/debug"
|
||||
title="Debug tools">
|
||||
<Text type="lg" style={pal.text}>
|
||||
Storybook
|
||||
<Link
|
||||
style={[pal.view, styles.linkCardNoIcon]}
|
||||
href="/sys/log"
|
||||
title="System log">
|
||||
<Text type="lg" style={pal.text}>
|
||||
System log
|
||||
</Text>
|
||||
</Link>
|
||||
<Link
|
||||
style={[pal.view, styles.linkCardNoIcon]}
|
||||
href="/sys/debug"
|
||||
title="Debug tools">
|
||||
<Text type="lg" style={pal.text}>
|
||||
Storybook
|
||||
</Text>
|
||||
</Link>
|
||||
<Text type="sm" style={[styles.buildInfo, pal.textLight]}>
|
||||
Build version {AppInfo.appVersion} ({AppInfo.buildVersion})
|
||||
</Text>
|
||||
</Link>
|
||||
<Text type="sm" style={[styles.buildInfo, pal.textLight]}>
|
||||
Build version {AppInfo.appVersion} ({AppInfo.buildVersion})
|
||||
</Text>
|
||||
<View style={s.footerSpacer} />
|
||||
</ScrollView>
|
||||
</View>
|
||||
)
|
||||
})
|
||||
<View style={s.footerSpacer} />
|
||||
</ScrollView>
|
||||
</View>
|
||||
)
|
||||
}),
|
||||
)
|
||||
|
||||
function AccountDropdownBtn({handle}: {handle: string}) {
|
||||
const store = useStores()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue