about summary refs log tree commit diff
path: root/src/view/com/util/UserBanner.tsx
diff options
context:
space:
mode:
authorHailey <me@haileyok.com>2024-03-12 10:17:27 -0700
committerGitHub <noreply@github.com>2024-03-12 10:17:27 -0700
commit812329919266924c1ea488669dc38aa106b79d71 (patch)
tree86cdd30eb901fb87e4d9879d1384845ff55ba8bd /src/view/com/util/UserBanner.tsx
parent80cc1f18a215182cae60c902744319ef4e842d9c (diff)
downloadvoidsky-812329919266924c1ea488669dc38aa106b79d71.tar.zst
Convert profile edit avatar/banner dropdown menus to new menu (#3177)
* convert profile edit dropdown menu to new menu

fix banner text

add `showCancel` prop to menu outer

banner dropdown to menu

add Cancel button to menu

replace user avatar dropdown with menu

add StreamingLive icon

add camera icon

* remove export

* use new camera icon

* adjust icon color
Diffstat (limited to 'src/view/com/util/UserBanner.tsx')
-rw-r--r--src/view/com/util/UserBanner.tsx230
1 files changed, 120 insertions, 110 deletions
diff --git a/src/view/com/util/UserBanner.tsx b/src/view/com/util/UserBanner.tsx
index cb47b6659..a5ddfee8a 100644
--- a/src/view/com/util/UserBanner.tsx
+++ b/src/view/com/util/UserBanner.tsx
@@ -1,21 +1,29 @@
-import React, {useMemo} from 'react'
-import {StyleSheet, View} from 'react-native'
-import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import React from 'react'
+import {StyleSheet, TouchableOpacity, View} from 'react-native'
 import {ModerationUI} from '@atproto/api'
 import {Image} from 'expo-image'
 import {useLingui} from '@lingui/react'
-import {msg} from '@lingui/macro'
+import {msg, Trans} from '@lingui/macro'
+
 import {colors} from 'lib/styles'
 import {useTheme} from 'lib/ThemeContext'
+import {useTheme as useAlfTheme} from '#/alf'
 import {openCamera, openCropper, openPicker} from '../../../lib/media/picker'
 import {
   usePhotoLibraryPermission,
   useCameraPermission,
 } from 'lib/hooks/usePermissions'
 import {usePalette} from 'lib/hooks/usePalette'
-import {isWeb, isAndroid} from 'platform/detection'
+import {isAndroid, isNative} from 'platform/detection'
 import {Image as RNImage} from 'react-native-image-crop-picker'
-import {NativeDropdown, DropdownItem} from './forms/NativeDropdown'
+import {EventStopper} from 'view/com/util/EventStopper'
+import * as Menu from '#/components/Menu'
+import {
+  Camera_Filled_Stroke2_Corner0_Rounded as CameraFilled,
+  Camera_Stroke2_Corner0_Rounded as Camera,
+} from '#/components/icons/Camera'
+import {StreamingLive_Stroke2_Corner0_Rounded as Library} from '#/components/icons/StreamingLive'
+import {Trash_Stroke2_Corner0_Rounded as Trash} from '#/components/icons/Trash'
 
 export function UserBanner({
   banner,
@@ -28,118 +36,120 @@ export function UserBanner({
 }) {
   const pal = usePalette('default')
   const theme = useTheme()
+  const t = useAlfTheme()
   const {_} = useLingui()
   const {requestCameraAccessIfNeeded} = useCameraPermission()
   const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
 
-  const dropdownItems: DropdownItem[] = useMemo(
-    () =>
-      [
-        !isWeb && {
-          testID: 'changeBannerCameraBtn',
-          label: _(msg`Camera`),
-          icon: {
-            ios: {
-              name: 'camera',
-            },
-            android: 'ic_menu_camera',
-            web: 'camera',
-          },
-          onPress: async () => {
-            if (!(await requestCameraAccessIfNeeded())) {
-              return
-            }
-            onSelectNewBanner?.(
-              await openCamera({
-                width: 3000,
-                height: 1000,
-              }),
-            )
-          },
-        },
-        {
-          testID: 'changeBannerLibraryBtn',
-          label: _(msg`Library`),
-          icon: {
-            ios: {
-              name: 'photo.on.rectangle.angled',
-            },
-            android: 'ic_menu_gallery',
-            web: 'gallery',
-          },
-          onPress: async () => {
-            if (!(await requestPhotoAccessIfNeeded())) {
-              return
-            }
-            const items = await openPicker()
-            if (!items[0]) {
-              return
-            }
+  const onOpenCamera = React.useCallback(async () => {
+    if (!(await requestCameraAccessIfNeeded())) {
+      return
+    }
+    onSelectNewBanner?.(
+      await openCamera({
+        width: 3000,
+        height: 1000,
+      }),
+    )
+  }, [onSelectNewBanner, requestCameraAccessIfNeeded])
 
-            onSelectNewBanner?.(
-              await openCropper({
-                mediaType: 'photo',
-                path: items[0].path,
-                width: 3000,
-                height: 1000,
-              }),
-            )
-          },
-        },
-        !!banner && {
-          testID: 'changeBannerRemoveBtn',
-          label: _(msg`Remove`),
-          icon: {
-            ios: {
-              name: 'trash',
-            },
-            android: 'ic_delete',
-            web: ['far', 'trash-can'],
-          },
-          onPress: () => {
-            onSelectNewBanner?.(null)
-          },
-        },
-      ].filter(Boolean) as DropdownItem[],
-    [
-      banner,
-      onSelectNewBanner,
-      requestCameraAccessIfNeeded,
-      requestPhotoAccessIfNeeded,
-      _,
-    ],
-  )
+  const onOpenLibrary = React.useCallback(async () => {
+    if (!(await requestPhotoAccessIfNeeded())) {
+      return
+    }
+    const items = await openPicker()
+    if (!items[0]) {
+      return
+    }
+
+    onSelectNewBanner?.(
+      await openCropper({
+        mediaType: 'photo',
+        path: items[0].path,
+        width: 3000,
+        height: 1000,
+      }),
+    )
+  }, [onSelectNewBanner, requestPhotoAccessIfNeeded])
+
+  const onRemoveBanner = React.useCallback(() => {
+    onSelectNewBanner?.(null)
+  }, [onSelectNewBanner])
 
   // setUserBanner is only passed as prop on the EditProfile component
   return onSelectNewBanner ? (
-    <NativeDropdown
-      testID="changeBannerBtn"
-      items={dropdownItems}
-      accessibilityLabel={_(msg`Image options`)}
-      accessibilityHint="">
-      {banner ? (
-        <Image
-          testID="userBannerImage"
-          style={styles.bannerImage}
-          source={{uri: banner}}
-          accessible={true}
-          accessibilityIgnoresInvertColors
-        />
-      ) : (
-        <View
-          testID="userBannerFallback"
-          style={[styles.bannerImage, styles.defaultBanner]}
-        />
-      )}
-      <View style={[styles.editButtonContainer, pal.btn]}>
-        <FontAwesomeIcon
-          icon="camera"
-          size={12}
-          style={{color: colors.white}}
-          color={pal.text.color as string}
-        />
-      </View>
-    </NativeDropdown>
+    <EventStopper onKeyDown={false}>
+      <Menu.Root>
+        <Menu.Trigger label={_(msg`Edit avatar`)}>
+          {({props}) => (
+            <TouchableOpacity {...props} activeOpacity={0.8}>
+              {banner ? (
+                <Image
+                  testID="userBannerImage"
+                  style={styles.bannerImage}
+                  source={{uri: banner}}
+                  accessible={true}
+                  accessibilityIgnoresInvertColors
+                />
+              ) : (
+                <View
+                  testID="userBannerFallback"
+                  style={[styles.bannerImage, styles.defaultBanner]}
+                />
+              )}
+              <View style={[styles.editButtonContainer, pal.btn]}>
+                <CameraFilled height={14} width={14} style={t.atoms.text} />
+              </View>
+            </TouchableOpacity>
+          )}
+        </Menu.Trigger>
+        <Menu.Outer showCancel>
+          <Menu.Group>
+            {isNative && (
+              <Menu.Item
+                testID="changeBannerCameraBtn"
+                label={_(msg`Upload from Camera`)}
+                onPress={onOpenCamera}>
+                <Menu.ItemText>
+                  <Trans>Upload from Camera</Trans>
+                </Menu.ItemText>
+                <Menu.ItemIcon icon={Camera} />
+              </Menu.Item>
+            )}
+
+            <Menu.Item
+              testID="changeBannerLibraryBtn"
+              label={_(msg`Upload from Library`)}
+              onPress={onOpenLibrary}>
+              <Menu.ItemText>
+                {isNative ? (
+                  <Trans>Upload from Library</Trans>
+                ) : (
+                  <Trans>Upload from Files</Trans>
+                )}
+              </Menu.ItemText>
+              <Menu.ItemIcon icon={Library} />
+            </Menu.Item>
+          </Menu.Group>
+          {!!banner && (
+            <>
+              <Menu.Divider />
+              <Menu.Group>
+                <Menu.Item
+                  testID="changeBannerRemoveBtn"
+                  label={_(`Remove Banner`)}
+                  onPress={onRemoveBanner}>
+                  <Menu.ItemText>
+                    <Trans>Remove Banner</Trans>
+                  </Menu.ItemText>
+                  <Menu.ItemIcon icon={Trash} />
+                </Menu.Item>
+              </Menu.Group>
+            </>
+          )}
+        </Menu.Outer>
+      </Menu.Root>
+    </EventStopper>
   ) : banner &&
     !((moderation?.blur && isAndroid) /* android crashes with blur */) ? (
     <Image