about summary refs log tree commit diff
path: root/src/components/AccountList.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/AccountList.tsx')
-rw-r--r--src/components/AccountList.tsx141
1 files changed, 141 insertions, 0 deletions
diff --git a/src/components/AccountList.tsx b/src/components/AccountList.tsx
new file mode 100644
index 000000000..169e7b84f
--- /dev/null
+++ b/src/components/AccountList.tsx
@@ -0,0 +1,141 @@
+import React, {useCallback} from 'react'
+import {View} from 'react-native'
+import {msg, Trans} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+import {useProfileQuery} from '#/state/queries/profile'
+import {type SessionAccount, useSession} from '#/state/session'
+import {UserAvatar} from '#/view/com/util/UserAvatar'
+import {atoms as a, useTheme} from '#/alf'
+import {Check_Stroke2_Corner0_Rounded as Check} from '#/components/icons/Check'
+import {ChevronRight_Stroke2_Corner0_Rounded as Chevron} from '#/components/icons/Chevron'
+import {Button} from './Button'
+import {Text} from './Typography'
+
+export function AccountList({
+  onSelectAccount,
+  onSelectOther,
+  otherLabel,
+}: {
+  onSelectAccount: (account: SessionAccount) => void
+  onSelectOther: () => void
+  otherLabel?: string
+}) {
+  const {isSwitchingAccounts, currentAccount, accounts} = useSession()
+  const t = useTheme()
+  const {_} = useLingui()
+
+  const onPressAddAccount = useCallback(() => {
+    onSelectOther()
+  }, [onSelectOther])
+
+  return (
+    <View
+      style={[
+        a.rounded_md,
+        a.overflow_hidden,
+        a.border,
+        t.atoms.border_contrast_low,
+      ]}>
+      {accounts.map(account => (
+        <React.Fragment key={account.did}>
+          <AccountItem
+            account={account}
+            onSelect={onSelectAccount}
+            isCurrentAccount={account.did === currentAccount?.did}
+          />
+          <View style={[a.border_b, t.atoms.border_contrast_low]} />
+        </React.Fragment>
+      ))}
+      <Button
+        testID="chooseAddAccountBtn"
+        style={[a.flex_1]}
+        onPress={isSwitchingAccounts ? undefined : onPressAddAccount}
+        label={_(msg`Login to account that is not listed`)}>
+        {({hovered, pressed}) => (
+          <View
+            style={[
+              a.flex_1,
+              a.flex_row,
+              a.align_center,
+              {height: 48},
+              (hovered || pressed || isSwitchingAccounts) &&
+                t.atoms.bg_contrast_25,
+            ]}>
+            <Text
+              style={[
+                a.align_baseline,
+                a.flex_1,
+                a.flex_row,
+                a.py_sm,
+                {paddingLeft: 48},
+              ]}>
+              {otherLabel ?? <Trans>Other account</Trans>}
+            </Text>
+            <Chevron size="sm" style={[t.atoms.text, a.mr_md]} />
+          </View>
+        )}
+      </Button>
+    </View>
+  )
+}
+
+function AccountItem({
+  account,
+  onSelect,
+  isCurrentAccount,
+}: {
+  account: SessionAccount
+  onSelect: (account: SessionAccount) => void
+  isCurrentAccount: boolean
+}) {
+  const t = useTheme()
+  const {_} = useLingui()
+  const {data: profile} = useProfileQuery({did: account.did})
+
+  const onPress = React.useCallback(() => {
+    onSelect(account)
+  }, [account, onSelect])
+
+  return (
+    <Button
+      testID={`chooseAccountBtn-${account.handle}`}
+      key={account.did}
+      style={[a.flex_1]}
+      onPress={onPress}
+      label={
+        isCurrentAccount
+          ? _(msg`Continue as ${account.handle} (currently signed in)`)
+          : _(msg`Sign in as ${account.handle}`)
+      }>
+      {({hovered, pressed}) => (
+        <View
+          style={[
+            a.flex_1,
+            a.flex_row,
+            a.align_center,
+            {height: 48},
+            (hovered || pressed) && t.atoms.bg_contrast_25,
+          ]}>
+          <View style={a.p_md}>
+            <UserAvatar avatar={profile?.avatar} size={24} />
+          </View>
+          <Text style={[a.align_baseline, a.flex_1, a.flex_row, a.py_sm]}>
+            <Text style={[a.font_bold]}>
+              {profile?.displayName || account.handle}{' '}
+            </Text>
+            <Text style={[t.atoms.text_contrast_medium]}>{account.handle}</Text>
+          </Text>
+          {isCurrentAccount ? (
+            <Check
+              size="sm"
+              style={[{color: t.palette.positive_600}, a.mr_md]}
+            />
+          ) : (
+            <Chevron size="sm" style={[t.atoms.text, a.mr_md]} />
+          )}
+        </View>
+      )}
+    </Button>
+  )
+}