From 6432667f608fae447b59e41b9f8bb64b564205a1 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 9 Sep 2025 20:20:33 +0300 Subject: ALF lists screen (#8941) * alf list screens * relocate to `#/screens`, balkanize * use useBreakpoints * showCancel on subscribe menu * fix typo --- .../ProfileList/components/MoreOptionsMenu.tsx | 298 +++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 src/screens/ProfileList/components/MoreOptionsMenu.tsx (limited to 'src/screens/ProfileList/components/MoreOptionsMenu.tsx') diff --git a/src/screens/ProfileList/components/MoreOptionsMenu.tsx b/src/screens/ProfileList/components/MoreOptionsMenu.tsx new file mode 100644 index 000000000..17ca43a82 --- /dev/null +++ b/src/screens/ProfileList/components/MoreOptionsMenu.tsx @@ -0,0 +1,298 @@ +import {type AppBskyActorDefs, AppBskyGraphDefs, AtUri} from '@atproto/api' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useNavigation} from '@react-navigation/native' + +import {type NavigationProp} from '#/lib/routes/types' +import {shareUrl} from '#/lib/sharing' +import {toShareUrl} from '#/lib/strings/url-helpers' +import {logger} from '#/logger' +import {isWeb} from '#/platform/detection' +import {useModalControls} from '#/state/modals' +import { + useListBlockMutation, + useListDeleteMutation, + useListMuteMutation, +} from '#/state/queries/list' +import {useRemoveFeedMutation} from '#/state/queries/preferences' +import {useSession} from '#/state/session' +import {Button, ButtonIcon} from '#/components/Button' +import {useDialogControl} from '#/components/Dialog' +import {ArrowOutOfBoxModified_Stroke2_Corner2_Rounded as ShareIcon} from '#/components/icons/ArrowOutOfBox' +import {ChainLink_Stroke2_Corner0_Rounded as ChainLink} from '#/components/icons/ChainLink' +import {DotGrid_Stroke2_Corner0_Rounded as DotGridIcon} from '#/components/icons/DotGrid' +import {PencilLine_Stroke2_Corner0_Rounded as PencilLineIcon} from '#/components/icons/Pencil' +import {PersonCheck_Stroke2_Corner0_Rounded as PersonCheckIcon} from '#/components/icons/Person' +import {Pin_Stroke2_Corner0_Rounded as PinIcon} from '#/components/icons/Pin' +import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as UnmuteIcon} from '#/components/icons/Speaker' +import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash' +import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning' +import * as Menu from '#/components/Menu' +import { + ReportDialog, + useReportDialogControl, +} from '#/components/moderation/ReportDialog' +import * as Prompt from '#/components/Prompt' +import * as Toast from '#/components/Toast' + +export function MoreOptionsMenu({ + list, + savedFeedConfig, +}: { + list: AppBskyGraphDefs.ListView + savedFeedConfig?: AppBskyActorDefs.SavedFeed +}) { + const {_} = useLingui() + const {currentAccount} = useSession() + const {openModal} = useModalControls() + const deleteListPromptControl = useDialogControl() + const reportDialogControl = useReportDialogControl() + const navigation = useNavigation() + + const {mutateAsync: removeSavedFeed} = useRemoveFeedMutation() + const {mutateAsync: deleteList} = useListDeleteMutation() + const {mutateAsync: muteList} = useListMuteMutation() + const {mutateAsync: blockList} = useListBlockMutation() + + const isCurateList = list.purpose === AppBskyGraphDefs.CURATELIST + const isModList = list.purpose === AppBskyGraphDefs.MODLIST + const isBlocking = !!list.viewer?.blocked + const isMuting = !!list.viewer?.muted + const isPinned = Boolean(savedFeedConfig?.pinned) + const isOwner = currentAccount?.did === list.creator.did + + const onPressShare = () => { + const {rkey} = new AtUri(list.uri) + const url = toShareUrl(`/profile/${list.creator.did}/lists/${rkey}`) + shareUrl(url) + } + + const onRemoveFromSavedFeeds = async () => { + if (!savedFeedConfig) return + try { + await removeSavedFeed(savedFeedConfig) + Toast.show(_(msg`Removed from your feeds`)) + } catch (e) { + Toast.show(_(msg`There was an issue contacting the server`), { + type: 'error', + }) + logger.error('Failed to remove pinned list', {message: e}) + } + } + + const onPressEdit = () => { + openModal({ + name: 'create-or-edit-list', + list, + }) + } + + const onPressDelete = async () => { + await deleteList({uri: list.uri}) + + if (savedFeedConfig) { + await removeSavedFeed(savedFeedConfig) + } + + Toast.show(_(msg({message: 'List deleted', context: 'toast'}))) + if (navigation.canGoBack()) { + navigation.goBack() + } else { + navigation.navigate('Home') + } + } + + const onUnpinModList = async () => { + try { + if (!savedFeedConfig) return + await removeSavedFeed(savedFeedConfig) + Toast.show(_(msg`Unpinned list`)) + } catch { + Toast.show(_(msg`Failed to unpin list`), { + type: 'error', + }) + } + } + + const onUnsubscribeMute = async () => { + try { + await muteList({uri: list.uri, mute: false}) + Toast.show(_(msg({message: 'List unmuted', context: 'toast'}))) + logger.metric( + 'moderation:unsubscribedFromList', + {listType: 'mute'}, + {statsig: true}, + ) + } catch { + Toast.show( + _( + msg`There was an issue. Please check your internet connection and try again.`, + ), + ) + } + } + + const onUnsubscribeBlock = async () => { + try { + await blockList({uri: list.uri, block: false}) + Toast.show(_(msg({message: 'List unblocked', context: 'toast'}))) + logger.metric( + 'moderation:unsubscribedFromList', + {listType: 'block'}, + {statsig: true}, + ) + } catch { + Toast.show( + _( + msg`There was an issue. Please check your internet connection and try again.`, + ), + ) + } + } + + return ( + <> + + + {({props}) => ( + + )} + + + + + + {isWeb ? ( + Copy link to list + ) : ( + Share via... + )} + + + + {savedFeedConfig && ( + + + Remove from my feeds + + + + )} + + + + + {isOwner ? ( + + + + Edit list details + + + + + + Delete list + + + + + ) : ( + + + + Report list + + + + + )} + + {isModList && isPinned && ( + <> + + + + + Unpin moderation list + + + + + + )} + + {isCurateList && (isBlocking || isMuting) && ( + <> + + + {isBlocking && ( + + + Unblock list + + + + )} + {isMuting && ( + + + Unmute list + + + + )} + + + )} + + + + + + + + ) +} -- cgit 1.4.1