From 0991d502403ed4cb0c51cd9afd98cdbc4a454280 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Tue, 7 Jun 2022 20:07:14 +0200 Subject: [PATCH] Fixed #158 --- .../Shared => }/ContextMenu/account.ts | 25 ++- .../Shared => }/ContextMenu/instance.ts | 8 +- .../Shared => }/ContextMenu/share.ts | 20 +- .../Shared => }/ContextMenu/status.ts | 8 +- src/components/Timeline/Notifications.tsx | 181 +++++++++--------- .../Timeline/Shared/ContextMenu.tsx | 61 +++--- .../Timeline/Shared/HeaderDefault.tsx | 18 +- .../Timeline/Shared/HeaderNotification.tsx | 36 ++-- src/screens/Actions.tsx | 74 ------- src/screens/Compose/EditAttachment/Image.tsx | 4 +- src/screens/Compose/EditAttachment/Root.tsx | 2 +- src/screens/Compose/utils/reducer.ts | 2 +- src/screens/Compose/utils/types.d.ts | 7 +- src/screens/Tabs/Shared/Account.tsx | 32 +--- src/screens/Tabs/Shared/Root.tsx | 49 ++++- src/utils/navigation/navigators.ts | 10 - 16 files changed, 239 insertions(+), 298 deletions(-) rename src/components/{Timeline/Shared => }/ContextMenu/account.ts (91%) rename src/components/{Timeline/Shared => }/ContextMenu/instance.ts (96%) rename src/components/{Timeline/Shared => }/ContextMenu/share.ts (67%) rename src/components/{Timeline/Shared => }/ContextMenu/status.ts (98%) diff --git a/src/components/Timeline/Shared/ContextMenu/account.ts b/src/components/ContextMenu/account.ts similarity index 91% rename from src/components/Timeline/Shared/ContextMenu/account.ts rename to src/components/ContextMenu/account.ts index 76e6436b..d1289679 100644 --- a/src/components/Timeline/Shared/ContextMenu/account.ts +++ b/src/components/ContextMenu/account.ts @@ -14,17 +14,17 @@ import { useQueryClient } from 'react-query' import { useSelector } from 'react-redux' export interface Props { - menuItems: ContextMenuAction[] - status: Mastodon.Status - queryKey: QueryKeyTimeline + actions: ContextMenuAction[] + queryKey?: QueryKeyTimeline rootQueryKey?: QueryKeyTimeline + id: Mastodon.Account['id'] } const contextMenuAccount = ({ - menuItems, - status, + actions, queryKey, - rootQueryKey + rootQueryKey, + id: accountId }: Props) => { const { theme } = useTheme() const { t } = useTranslation('componentContextMenu') @@ -68,12 +68,12 @@ const contextMenuAccount = ({ getInstanceAccount, (prev, next) => prev.id === next.id ) - const ownAccount = instanceAccount?.id === status.account.id + const ownAccount = instanceAccount?.id === accountId if (!ownAccount) { switch (Platform.OS) { case 'ios': - menuItems.push({ + actions.push({ id: 'account', title: t('account.title'), inlineChildren: true, @@ -99,7 +99,7 @@ const contextMenuAccount = ({ }) break default: - menuItems.push( + actions.push( { id: 'account-mute', title: t('account.mute.action'), @@ -123,7 +123,6 @@ const contextMenuAccount = ({ } return (id: string) => { - const url = status.url || status.uri switch (id) { case 'account-mute': analytics('timeline_shared_headeractions_account_mute_press', { @@ -132,7 +131,7 @@ const contextMenuAccount = ({ mutateion.mutate({ type: 'updateAccountProperty', queryKey, - id: status.account.id, + id: accountId, payload: { property: 'mute' } }) break @@ -143,7 +142,7 @@ const contextMenuAccount = ({ mutateion.mutate({ type: 'updateAccountProperty', queryKey, - id: status.account.id, + id: accountId, payload: { property: 'block' } }) break @@ -154,7 +153,7 @@ const contextMenuAccount = ({ mutateion.mutate({ type: 'updateAccountProperty', queryKey, - id: status.account.id, + id: accountId, payload: { property: 'reports' } }) break diff --git a/src/components/Timeline/Shared/ContextMenu/instance.ts b/src/components/ContextMenu/instance.ts similarity index 96% rename from src/components/Timeline/Shared/ContextMenu/instance.ts rename to src/components/ContextMenu/instance.ts index 008b1b80..676bc8ad 100644 --- a/src/components/Timeline/Shared/ContextMenu/instance.ts +++ b/src/components/ContextMenu/instance.ts @@ -13,14 +13,14 @@ import { useQueryClient } from 'react-query' import { useSelector } from 'react-redux' export interface Props { - menuItems: ContextMenuAction[] + actions: ContextMenuAction[] status: Mastodon.Status queryKey: QueryKeyTimeline rootQueryKey?: QueryKeyTimeline } const contextMenuInstance = ({ - menuItems, + actions, status, queryKey, rootQueryKey @@ -49,7 +49,7 @@ const contextMenuInstance = ({ if (currentInstance !== instance && instance) { switch (Platform.OS) { case 'ios': - menuItems.push({ + actions.push({ id: 'instance', title: t('instance.title'), actions: [ @@ -62,7 +62,7 @@ const contextMenuInstance = ({ }) break default: - menuItems.push({ + actions.push({ id: 'instance-block', title: t('instance.block.action', { instance }), destructive: true diff --git a/src/components/Timeline/Shared/ContextMenu/share.ts b/src/components/ContextMenu/share.ts similarity index 67% rename from src/components/Timeline/Shared/ContextMenu/share.ts rename to src/components/ContextMenu/share.ts index 68e4213f..4f7b25ec 100644 --- a/src/components/Timeline/Shared/ContextMenu/share.ts +++ b/src/components/ContextMenu/share.ts @@ -4,23 +4,21 @@ import { Platform, Share } from 'react-native' import { ContextMenuAction } from 'react-native-context-menu-view' export interface Props { - menuItems: ContextMenuAction[] - status: Mastodon.Status + actions: ContextMenuAction[] + type: 'status' | 'account' + url: string } -const contextMenuShare = ({ menuItems, status }: Props) => { +const contextMenuShare = ({ actions, type, url }: Props) => { const { t } = useTranslation('componentContextMenu') - if (status.visibility !== 'direct') { - menuItems.push({ - id: 'share', - title: t(`share.status.action`), - systemIcon: 'square.and.arrow.up' - }) - } + actions.push({ + id: 'share', + title: t(`share.${type}.action`), + systemIcon: 'square.and.arrow.up' + }) return (id: string) => { - const url = status.url || status.uri switch (id) { case 'share': analytics('timeline_shared_headeractions_share_press') diff --git a/src/components/Timeline/Shared/ContextMenu/status.ts b/src/components/ContextMenu/status.ts similarity index 98% rename from src/components/Timeline/Shared/ContextMenu/status.ts rename to src/components/ContextMenu/status.ts index 858c3522..8867b01a 100644 --- a/src/components/Timeline/Shared/ContextMenu/status.ts +++ b/src/components/ContextMenu/status.ts @@ -21,14 +21,14 @@ import { useQueryClient } from 'react-query' import { useSelector } from 'react-redux' export interface Props { - menuItems: ContextMenuAction[] + actions: ContextMenuAction[] status: Mastodon.Status queryKey: QueryKeyTimeline rootQueryKey?: QueryKeyTimeline } const contextMenuStatus = ({ - menuItems, + actions, status, queryKey, rootQueryKey @@ -116,7 +116,7 @@ const contextMenuStatus = ({ switch (Platform.OS) { case 'ios': - menuItems.push({ + actions.push({ id: 'status', title: t('status.title'), inlineChildren: true, @@ -124,7 +124,7 @@ const contextMenuStatus = ({ }) break default: - menuItems.push(...accountMenuItems) + actions.push(...accountMenuItems) break } } diff --git a/src/components/Timeline/Notifications.tsx b/src/components/Timeline/Notifications.tsx index c4df686f..80be1816 100644 --- a/src/components/Timeline/Notifications.tsx +++ b/src/components/Timeline/Notifications.tsx @@ -18,6 +18,7 @@ import { isEqual, uniqBy } from 'lodash' import React, { useCallback } from 'react' import { Pressable, View } from 'react-native' import { useSelector } from 'react-redux' +import TimelineContextMenu from './Shared/ContextMenu' import TimelineFiltered, { shouldFilter } from './Shared/Filtered' import TimelineFullConversation from './Shared/FullConversation' @@ -58,103 +59,105 @@ const TimelineNotifications = React.memo( }, []) return ( - - {notification.type !== 'mention' ? ( - - ) : null} - - + {}} > - - - + ) : null} + + + + + + + + {notification.status ? ( + + {notification.status.content.length > 0 ? ( + + ) : null} + {notification.status.poll ? ( + + ) : null} + {notification.status.media_attachments.length > 0 ? ( + + ) : null} + {notification.status.card ? ( + + ) : null} + + + ) : null} {notification.status ? ( - - {notification.status.content.length > 0 ? ( - - ) : null} - {notification.status.poll ? ( - - ) : null} - {notification.status.media_attachments.length > 0 ? ( - - ) : null} - {notification.status.card ? ( - - ) : null} - - + d?.id !== instanceAccount?.id), + d => d?.id + ).map(d => d?.acct)} + reblog={false} + /> ) : null} - - - {notification.status ? ( - d?.id !== instanceAccount?.id), - d => d?.id - ).map(d => d?.acct)} - reblog={false} - /> - ) : null} - + + ) }, (prev, next) => isEqual(prev.notification, next.notification) diff --git a/src/components/Timeline/Shared/ContextMenu.tsx b/src/components/Timeline/Shared/ContextMenu.tsx index d3769c84..f11af4b4 100644 --- a/src/components/Timeline/Shared/ContextMenu.tsx +++ b/src/components/Timeline/Shared/ContextMenu.tsx @@ -1,62 +1,79 @@ +import contextMenuAccount from '@components/ContextMenu/account' +import contextMenuInstance from '@components/ContextMenu/instance' +import contextMenuShare from '@components/ContextMenu/share' +import contextMenuStatus from '@components/ContextMenu/status' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' +import React from 'react' import { createContext } from 'react' -import ContextMenu, { ContextMenuAction } from 'react-native-context-menu-view' -import contextMenuAccount from './ContextMenu/account' -import contextMenuInstance from './ContextMenu/instance' -import contextMenuShare from './ContextMenu/share' -import contextMenuStatus from './ContextMenu/status' +import ContextMenu, { + ContextMenuAction, + ContextMenuProps +} from 'react-native-context-menu-view' export interface Props { - status: Mastodon.Status + status?: Mastodon.Status queryKey?: QueryKeyTimeline rootQueryKey?: QueryKeyTimeline } export const ContextMenuContext = createContext([]) -const TimelineContextMenu: React.FC = ({ +const TimelineContextMenu: React.FC = ({ children, status, queryKey, - rootQueryKey + rootQueryKey, + ...props }) => { - if (!queryKey) { + if (!status || !queryKey) { return <>{children} } - const menuItems: ContextMenuAction[] = [] + const actions: ContextMenuAction[] = [] - const shareOnPress = contextMenuShare({ menuItems, status }) + const shareOnPress = + status.visibility !== 'direct' + ? contextMenuShare({ + actions, + type: 'status', + url: status.url || status.uri + }) + : null const statusOnPress = contextMenuStatus({ - menuItems, + actions, status, queryKey, rootQueryKey }) const accountOnPress = contextMenuAccount({ - menuItems, - status, + actions, queryKey, - rootQueryKey + rootQueryKey, + id: status.account.id }) const instanceOnPress = contextMenuInstance({ - menuItems, + actions, status, queryKey, rootQueryKey }) return ( - + { - shareOnPress(id) - statusOnPress(id) - accountOnPress(id) - instanceOnPress(id) + for (const on of [ + shareOnPress, + statusOnPress, + accountOnPress, + instanceOnPress + ]) { + on && on(id) + } }} children={children} + {...props} /> ) diff --git a/src/components/Timeline/Shared/HeaderDefault.tsx b/src/components/Timeline/Shared/HeaderDefault.tsx index ebfc2135..80a1c1bb 100644 --- a/src/components/Timeline/Shared/HeaderDefault.tsx +++ b/src/components/Timeline/Shared/HeaderDefault.tsx @@ -2,11 +2,10 @@ import Icon from '@components/Icon' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' -import React, { useContext, useRef } from 'react' +import React, { useContext } from 'react' import { useTranslation } from 'react-i18next' import { Pressable, View } from 'react-native' import ContextMenu from 'react-native-context-menu-view' -import { TouchableWithoutFeedback } from 'react-native-gesture-handler' import { ContextMenuContext } from './ContextMenu' import HeaderSharedAccount from './HeaderShared/Account' import HeaderSharedApplication from './HeaderShared/Application' @@ -24,7 +23,7 @@ const TimelineHeaderDefault = ({ queryKey, status, highlighted }: Props) => { const { t } = useTranslation('componentContextMenu') const { colors } = useTheme() - const contextMenuItems = useContext(ContextMenuContext) + const contextMenuContext = useContext(ContextMenuContext) return ( @@ -60,16 +59,9 @@ const TimelineHeaderDefault = ({ queryKey, status, highlighted }: Props) => { }} > { - // console.log('index', index) - // console.log('name', name) - // // shareOnPress(name) - // // statusOnPress(name) - // accountOnPress(name) - // // instanceOnPress(name) - // }} + dropdownMenuMode + actions={contextMenuContext} + onPress={() => {}} children={ { - const navigation = useNavigation>() +const TimelineHeaderNotification = ({ notification }: Props) => { const { colors } = useTheme() + const contextMenuContext = useContext(ContextMenuContext) + const actions = useMemo(() => { switch (notification.type) { case 'follow': @@ -42,18 +40,18 @@ const TimelineHeaderNotification = ({ queryKey, notification }: Props) => { justifyContent: 'center', paddingBottom: StyleConstants.Spacing.S }} - onPress={() => - navigation.navigate('Screen-Actions', { - queryKey, - status: notification.status!, - type: 'status' - }) - } children={ - {}} + children={ + + } /> } /> diff --git a/src/screens/Actions.tsx b/src/screens/Actions.tsx index c1cf3d7e..c6db5ffa 100644 --- a/src/screens/Actions.tsx +++ b/src/screens/Actions.tsx @@ -1,14 +1,7 @@ -import analytics from '@components/analytics' -import Button from '@components/Button' import { RootStackScreenProps } from '@utils/navigation/navigators' -import { - getInstanceAccount, - getInstanceUrl -} from '@utils/slices/instancesSlice' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { useCallback, useEffect } from 'react' -import { useTranslation } from 'react-i18next' import { Dimensions, StyleSheet, View } from 'react-native' import { PanGestureHandler, @@ -28,46 +21,13 @@ import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context' -import { useSelector } from 'react-redux' -import ActionsAccount from './Actions/Account' import ActionsAltText from './Actions/AltText' -import ActionsDomain from './Actions/Domain' import ActionsNotificationsFilter from './Actions/NotificationsFilter' -import ActionsShare from './Actions/Share' -import ActionsStatus from './Actions/Status' const ScreenActions = ({ route: { params }, navigation }: RootStackScreenProps<'Screen-Actions'>) => { - const { t } = useTranslation() - - const instanceAccount = useSelector( - getInstanceAccount, - (prev, next) => prev?.id === next?.id - ) - let sameAccount = false - switch (params.type) { - case 'status': - sameAccount = instanceAccount?.id === params.status.account.id - break - case 'account': - sameAccount = instanceAccount?.id === params.account.id - break - } - - const instanceDomain = useSelector(getInstanceUrl) - let sameDomain = true - let statusDomain: string - switch (params.type) { - case 'status': - statusDomain = params.status.uri - ? params.status.uri.split(new RegExp(/\/\/(.*?)\//))[1] - : '' - sameDomain = instanceDomain === statusDomain - break - } - const { colors } = useTheme() const insets = useSafeAreaInsets() @@ -105,40 +65,6 @@ const ScreenActions = ({ const actions = () => { switch (params.type) { - case 'status': - return ( - <> - {!sameAccount ? ( - - ) : null} - - ) - case 'account': - return ( - <> - {!sameAccount ? ( - - ) : null} - -