-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* quick switch menu * Some small tweaks and fixes to the account switch modal * Factor out the account switcher logic to a hook * Add haptic feedback on account switcher open * Fix bad merge --------- Co-authored-by: Samuel Newman <[email protected]>
- Loading branch information
Showing
9 changed files
with
243 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -246,6 +246,7 @@ function TabsNavigator() { | |
), | ||
[], | ||
) | ||
|
||
return ( | ||
<Tab.Navigator | ||
initialRouteName="HomeTab" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import {useCallback, useState} from 'react' | ||
import {useStores} from 'state/index' | ||
import {useAnalytics} from 'lib/analytics/analytics' | ||
import {StackActions, useNavigation} from '@react-navigation/native' | ||
import {NavigationProp} from 'lib/routes/types' | ||
import {AccountData} from 'state/models/session' | ||
import {reset as resetNavigation} from '../../Navigation' | ||
import * as Toast from 'view/com/util/Toast' | ||
|
||
export function useAccountSwitcher(): [ | ||
boolean, | ||
(v: boolean) => void, | ||
(acct: AccountData) => Promise<void>, | ||
] { | ||
const {track} = useAnalytics() | ||
|
||
const store = useStores() | ||
const [isSwitching, setIsSwitching] = useState(false) | ||
const navigation = useNavigation<NavigationProp>() | ||
|
||
const onPressSwitchAccount = useCallback( | ||
async (acct: AccountData) => { | ||
track('Settings:SwitchAccountButtonClicked') | ||
setIsSwitching(true) | ||
const success = await store.session.resumeSession(acct) | ||
store.shell.closeAllActiveElements() | ||
if (success) { | ||
resetNavigation() | ||
Toast.show(`Signed in as ${acct.displayName || acct.handle}`) | ||
} else { | ||
Toast.show('Sorry! We need you to enter your password.') | ||
navigation.navigate('HomeTab') | ||
navigation.dispatch(StackActions.popToTop()) | ||
store.session.clear() | ||
} | ||
}, | ||
[track, setIsSwitching, navigation, store], | ||
) | ||
|
||
return [isSwitching, setIsSwitching, onPressSwitchAccount] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import React from 'react' | ||
import { | ||
ActivityIndicator, | ||
StyleSheet, | ||
TouchableOpacity, | ||
View, | ||
} from 'react-native' | ||
import {Text} from '../util/text/Text' | ||
import {useStores} from 'state/index' | ||
import {s} from 'lib/styles' | ||
import {usePalette} from 'lib/hooks/usePalette' | ||
import {useAnalytics} from 'lib/analytics/analytics' | ||
import {useAccountSwitcher} from 'lib/hooks/useAccountSwitcher' | ||
import {UserAvatar} from '../util/UserAvatar' | ||
import {AccountDropdownBtn} from '../util/AccountDropdownBtn' | ||
import {Link} from '../util/Link' | ||
import {makeProfileLink} from 'lib/routes/links' | ||
import {BottomSheetScrollView} from '@gorhom/bottom-sheet' | ||
import {Haptics} from 'lib/haptics' | ||
|
||
export const snapPoints = ['40%', '90%'] | ||
|
||
export function Component({}: {}) { | ||
const pal = usePalette('default') | ||
const {track} = useAnalytics() | ||
|
||
const store = useStores() | ||
const [isSwitching, _, onPressSwitchAccount] = useAccountSwitcher() | ||
|
||
React.useEffect(() => { | ||
Haptics.default() | ||
}) | ||
|
||
const onPressSignout = React.useCallback(() => { | ||
track('Settings:SignOutButtonClicked') | ||
store.session.logout() | ||
}, [track, store]) | ||
|
||
return ( | ||
<View style={[styles.container, pal.view]}> | ||
<Text type="title-xl" style={[styles.title, pal.text]}> | ||
Switch Account | ||
</Text> | ||
<BottomSheetScrollView | ||
style={styles.container} | ||
contentContainerStyle={[styles.innerContainer, pal.view]}> | ||
{isSwitching ? ( | ||
<View style={[pal.view, styles.linkCard]}> | ||
<ActivityIndicator /> | ||
</View> | ||
) : ( | ||
<Link | ||
href={makeProfileLink(store.me)} | ||
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} | ||
accessibilityRole="button" | ||
accessibilityLabel="Sign out" | ||
accessibilityHint={`Signs ${store.me.displayName} out of Bluesky`}> | ||
<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) | ||
} | ||
accessibilityRole="button" | ||
accessibilityLabel={`Switch to ${account.handle}`} | ||
accessibilityHint="Switches the account you are logged in to"> | ||
<View style={styles.avi}> | ||
<UserAvatar size={40} avatar={account.aviUrl} /> | ||
</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} /> | ||
</TouchableOpacity> | ||
))} | ||
</BottomSheetScrollView> | ||
</View> | ||
) | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
container: { | ||
flex: 1, | ||
}, | ||
innerContainer: { | ||
paddingBottom: 20, | ||
}, | ||
title: { | ||
textAlign: 'center', | ||
marginTop: 12, | ||
marginBottom: 12, | ||
}, | ||
linkCard: { | ||
flexDirection: 'row', | ||
alignItems: 'center', | ||
paddingVertical: 12, | ||
paddingHorizontal: 18, | ||
marginBottom: 1, | ||
}, | ||
avi: { | ||
marginRight: 12, | ||
}, | ||
dimmed: { | ||
opacity: 0.5, | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import React from 'react' | ||
import {Pressable} from 'react-native' | ||
import { | ||
FontAwesomeIcon, | ||
FontAwesomeIconStyle, | ||
} from '@fortawesome/react-native-fontawesome' | ||
import {s} from 'lib/styles' | ||
import {useStores} from 'state/index' | ||
import {usePalette} from 'lib/hooks/usePalette' | ||
import {DropdownItem, NativeDropdown} from './forms/NativeDropdown' | ||
import * as Toast from '../../com/util/Toast' | ||
|
||
export function AccountDropdownBtn({handle}: {handle: string}) { | ||
const store = useStores() | ||
const pal = usePalette('default') | ||
const items: DropdownItem[] = [ | ||
{ | ||
label: 'Remove account', | ||
onPress: () => { | ||
store.session.removeAccount(handle) | ||
Toast.show('Account removed from quick access') | ||
}, | ||
icon: { | ||
ios: { | ||
name: 'trash', | ||
}, | ||
android: 'ic_delete', | ||
web: 'trash', | ||
}, | ||
}, | ||
] | ||
return ( | ||
<Pressable accessibilityRole="button" style={s.pl10}> | ||
<NativeDropdown | ||
testID="accountSettingsDropdownBtn" | ||
items={items} | ||
accessibilityLabel="Account options" | ||
accessibilityHint=""> | ||
<FontAwesomeIcon | ||
icon="ellipsis-h" | ||
style={pal.textLight as FontAwesomeIconStyle} | ||
/> | ||
</NativeDropdown> | ||
</Pressable> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.