import React from 'react' import {StyleSheet, TouchableOpacity, View} from 'react-native' import {Image as RNImage} from 'react-native-image-crop-picker' import {Image} from 'expo-image' import {ModerationUI} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {logger} from '#/logger' import {usePalette} from 'lib/hooks/usePalette' import { useCameraPermission, usePhotoLibraryPermission, } from 'lib/hooks/usePermissions' import {colors} from 'lib/styles' import {useTheme} from 'lib/ThemeContext' import {isAndroid, isNative} from 'platform/detection' import {EventStopper} from 'view/com/util/EventStopper' import {tokens, useTheme as useAlfTheme} from '#/alf' 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' import * as Menu from '#/components/Menu' import {openCamera, openCropper, openPicker} from '../../../lib/media/picker' export function UserBanner({ type, banner, moderation, onSelectNewBanner, }: { type?: 'labeler' | 'default' banner?: string | null moderation?: ModerationUI onSelectNewBanner?: (img: RNImage | null) => void }) { const pal = usePalette('default') const theme = useTheme() const t = useAlfTheme() const {_} = useLingui() const {requestCameraAccessIfNeeded} = useCameraPermission() const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission() const onOpenCamera = React.useCallback(async () => { if (!(await requestCameraAccessIfNeeded())) { return } onSelectNewBanner?.( await openCamera({ width: 3000, height: 1000, }), ) }, [onSelectNewBanner, requestCameraAccessIfNeeded]) const onOpenLibrary = React.useCallback(async () => { if (!(await requestPhotoAccessIfNeeded())) { return } const items = await openPicker() if (!items[0]) { return } try { onSelectNewBanner?.( await openCropper({ mediaType: 'photo', path: items[0].path, width: 3000, height: 1000, }), ) } catch (e: any) { if (!String(e).includes('Canceled')) { logger.error('Failed to crop banner', {error: e}) } } }, [onSelectNewBanner, requestPhotoAccessIfNeeded]) const onRemoveBanner = React.useCallback(() => { onSelectNewBanner?.(null) }, [onSelectNewBanner]) // setUserBanner is only passed as prop on the EditProfile component return onSelectNewBanner ? ( {({props}) => ( {banner ? ( ) : ( )} )} {isNative && ( Upload from Camera )} {isNative ? ( Upload from Library ) : ( Upload from Files )} {!!banner && ( <> Remove Banner )} ) : banner && !((moderation?.blur && isAndroid) /* android crashes with blur */) ? ( ) : ( ) } const styles = StyleSheet.create({ editButtonContainer: { position: 'absolute', width: 24, height: 24, bottom: 8, right: 24, borderRadius: 12, alignItems: 'center', justifyContent: 'center', backgroundColor: colors.gray5, }, bannerImage: { width: '100%', height: 150, }, defaultBanner: { backgroundColor: '#0070ff', }, labelerBanner: { backgroundColor: tokens.color.temp_purple, }, })