mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Moving to using zeego
This commit is contained in:
@ -1,84 +0,0 @@
|
||||
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 { Platform } from 'react-native'
|
||||
import ContextMenu, { ContextMenuAction, ContextMenuProps } from 'react-native-context-menu-view'
|
||||
|
||||
export interface Props {
|
||||
copiableContent: React.MutableRefObject<{
|
||||
content: string
|
||||
complete: boolean
|
||||
}>
|
||||
status?: Mastodon.Status
|
||||
queryKey?: QueryKeyTimeline
|
||||
rootQueryKey?: QueryKeyTimeline
|
||||
}
|
||||
|
||||
export const ContextMenuContext = createContext<ContextMenuAction[]>([])
|
||||
|
||||
const TimelineContextMenu: React.FC<Props & ContextMenuProps> = ({
|
||||
children,
|
||||
copiableContent,
|
||||
status,
|
||||
queryKey,
|
||||
rootQueryKey,
|
||||
...props
|
||||
}) => {
|
||||
if (!status || !queryKey || Platform.OS === 'android') {
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
const actions: ContextMenuAction[] = []
|
||||
|
||||
const shareOnPress =
|
||||
status.visibility !== 'direct'
|
||||
? contextMenuShare({
|
||||
copiableContent,
|
||||
actions,
|
||||
type: 'status',
|
||||
url: status.url || status.uri
|
||||
})
|
||||
: null
|
||||
const statusOnPress = contextMenuStatus({
|
||||
actions,
|
||||
status,
|
||||
queryKey,
|
||||
rootQueryKey
|
||||
})
|
||||
const accountOnPress = status?.account?.id
|
||||
? contextMenuAccount({
|
||||
actions,
|
||||
type: 'status',
|
||||
queryKey,
|
||||
rootQueryKey,
|
||||
id: status.account.id
|
||||
})
|
||||
: null
|
||||
const instanceOnPress = contextMenuInstance({
|
||||
actions,
|
||||
status,
|
||||
queryKey,
|
||||
rootQueryKey
|
||||
})
|
||||
|
||||
return (
|
||||
<ContextMenuContext.Provider value={actions}>
|
||||
<ContextMenu
|
||||
actions={actions}
|
||||
onPress={({ nativeEvent: { index } }) => {
|
||||
for (const on of [shareOnPress, statusOnPress, accountOnPress, instanceOnPress]) {
|
||||
on && on(index)
|
||||
}
|
||||
}}
|
||||
children={children}
|
||||
{...props}
|
||||
/>
|
||||
</ContextMenuContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimelineContextMenu
|
103
src/components/Timeline/Shared/HeaderAndroid.tsx
Normal file
103
src/components/Timeline/Shared/HeaderAndroid.tsx
Normal file
@ -0,0 +1,103 @@
|
||||
import menuAccount from '@components/contextMenu/account'
|
||||
import menuInstance from '@components/contextMenu/instance'
|
||||
import menuShare from '@components/contextMenu/share'
|
||||
import menuStatus from '@components/contextMenu/status'
|
||||
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, { useState } from 'react'
|
||||
import { Platform, View } from 'react-native'
|
||||
import * as DropdownMenu from 'zeego/dropdown-menu'
|
||||
|
||||
export interface Props {
|
||||
queryKey?: QueryKeyTimeline
|
||||
rootQueryKey?: QueryKeyTimeline
|
||||
status?: Mastodon.Status
|
||||
}
|
||||
|
||||
const TimelineHeaderAndroid: React.FC<Props> = ({ queryKey, rootQueryKey, status }) => {
|
||||
if (Platform.OS !== 'android' || !status) return null
|
||||
|
||||
const { colors } = useTheme()
|
||||
|
||||
const [openChange, setOpenChange] = useState(false)
|
||||
const mShare = menuShare({
|
||||
visibility: status.visibility,
|
||||
type: 'status',
|
||||
url: status.url || status.uri
|
||||
})
|
||||
const mAccount = menuAccount({
|
||||
openChange,
|
||||
id: status.account.id,
|
||||
queryKey
|
||||
})
|
||||
const mStatus = menuStatus({ status, queryKey, rootQueryKey })
|
||||
const mInstance = menuInstance({ status, queryKey, rootQueryKey })
|
||||
|
||||
return (
|
||||
<View style={{ position: 'absolute', top: 0, right: 0 }}>
|
||||
{queryKey ? (
|
||||
<DropdownMenu.Root onOpenChange={setOpenChange}>
|
||||
<DropdownMenu.Trigger>
|
||||
<View style={{ padding: StyleConstants.Spacing.L }}>
|
||||
<Icon
|
||||
name='MoreHorizontal'
|
||||
color={colors.secondary}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
/>
|
||||
</View>
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
<DropdownMenu.Content>
|
||||
{mShare.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mAccount.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mStatus.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mInstance.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
) : null}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimelineHeaderAndroid
|
@ -1,114 +0,0 @@
|
||||
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 Icon from '@components/Icon'
|
||||
import { useActionSheet } from '@expo/react-native-action-sheet'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Pressable, View } from 'react-native'
|
||||
import { ContextMenuAction } from 'react-native-context-menu-view'
|
||||
import HeaderSharedAccount from './HeaderShared/Account'
|
||||
import HeaderSharedApplication from './HeaderShared/Application'
|
||||
import HeaderSharedCreated from './HeaderShared/Created'
|
||||
import HeaderSharedMuted from './HeaderShared/Muted'
|
||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||
|
||||
export interface Props {
|
||||
queryKey?: QueryKeyTimeline
|
||||
status: Mastodon.Status
|
||||
highlighted: boolean
|
||||
}
|
||||
|
||||
const TimelineHeaderDefault = ({ queryKey, status, highlighted }: Props) => {
|
||||
if (!queryKey) return null
|
||||
|
||||
const { t } = useTranslation('componentContextMenu')
|
||||
const { colors } = useTheme()
|
||||
|
||||
const actions: ContextMenuAction[] = []
|
||||
|
||||
const shareOnPress =
|
||||
status.visibility !== 'direct'
|
||||
? contextMenuShare({
|
||||
actions,
|
||||
type: 'status',
|
||||
url: status.url || status.uri
|
||||
})
|
||||
: null
|
||||
const statusOnPress = contextMenuStatus({
|
||||
actions,
|
||||
status,
|
||||
queryKey
|
||||
})
|
||||
const accountOnPress = contextMenuAccount({
|
||||
actions,
|
||||
type: 'status',
|
||||
queryKey,
|
||||
id: status.account.id
|
||||
})
|
||||
const instanceOnPress = contextMenuInstance({
|
||||
actions,
|
||||
status,
|
||||
queryKey
|
||||
})
|
||||
|
||||
const { showActionSheetWithOptions } = useActionSheet()
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, flexDirection: 'row' }}>
|
||||
<View style={{ flex: 7 }}>
|
||||
<HeaderSharedAccount account={status.account} />
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: StyleConstants.Spacing.XS,
|
||||
marginBottom: StyleConstants.Spacing.S
|
||||
}}
|
||||
>
|
||||
<HeaderSharedCreated
|
||||
created_at={status.created_at}
|
||||
edited_at={status.edited_at}
|
||||
highlighted={highlighted}
|
||||
/>
|
||||
<HeaderSharedVisibility visibility={status.visibility} />
|
||||
<HeaderSharedMuted muted={status.muted} />
|
||||
<HeaderSharedApplication application={status.application} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{queryKey ? (
|
||||
<Pressable
|
||||
accessibilityHint={t('accessibilityHint')}
|
||||
style={{ flex: 1, flexBasis: StyleConstants.Font.Size.L }}
|
||||
onPress={() =>
|
||||
showActionSheetWithOptions(
|
||||
{
|
||||
options: actions.map(action => action.title),
|
||||
cancelButtonIndex: 999,
|
||||
destructiveButtonIndex: actions
|
||||
.map((action, index) => (action.destructive ? index : 999))
|
||||
.filter(num => num !== 999)
|
||||
},
|
||||
index => {
|
||||
if (index !== undefined) {
|
||||
for (const on of [shareOnPress, statusOnPress, accountOnPress, instanceOnPress]) {
|
||||
on && on(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
>
|
||||
<Icon name='MoreHorizontal' color={colors.secondary} size={StyleConstants.Font.Size.L} />
|
||||
</Pressable>
|
||||
) : null}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimelineHeaderDefault
|
@ -1,75 +0,0 @@
|
||||
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 } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Pressable, View } from 'react-native'
|
||||
import ContextMenu from 'react-native-context-menu-view'
|
||||
import { ContextMenuContext } from './ContextMenu'
|
||||
import HeaderSharedAccount from './HeaderShared/Account'
|
||||
import HeaderSharedApplication from './HeaderShared/Application'
|
||||
import HeaderSharedCreated from './HeaderShared/Created'
|
||||
import HeaderSharedMuted from './HeaderShared/Muted'
|
||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||
|
||||
export interface Props {
|
||||
queryKey?: QueryKeyTimeline
|
||||
status: Mastodon.Status
|
||||
highlighted: boolean
|
||||
}
|
||||
|
||||
const TimelineHeaderDefault = ({ queryKey, status, highlighted }: Props) => {
|
||||
const { t } = useTranslation('componentContextMenu')
|
||||
const { colors } = useTheme()
|
||||
|
||||
const contextMenuContext = useContext(ContextMenuContext)
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, flexDirection: 'row' }}>
|
||||
<View style={{ flex: 7 }}>
|
||||
<HeaderSharedAccount account={status.account} />
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: StyleConstants.Spacing.XS,
|
||||
marginBottom: StyleConstants.Spacing.S
|
||||
}}
|
||||
>
|
||||
<HeaderSharedCreated
|
||||
created_at={status.created_at}
|
||||
edited_at={status.edited_at}
|
||||
highlighted={highlighted}
|
||||
/>
|
||||
<HeaderSharedVisibility visibility={status.visibility} />
|
||||
<HeaderSharedMuted muted={status.muted} />
|
||||
<HeaderSharedApplication application={status.application} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{queryKey ? (
|
||||
<Pressable
|
||||
accessibilityHint={t('accessibilityHint')}
|
||||
style={{ flex: 1, flexBasis: StyleConstants.Font.Size.L }}
|
||||
>
|
||||
<ContextMenu
|
||||
style={{ flex: 1, alignItems: 'center' }}
|
||||
dropdownMenuMode
|
||||
actions={contextMenuContext}
|
||||
onPress={() => {}}
|
||||
children={
|
||||
<Icon
|
||||
name='MoreHorizontal'
|
||||
color={colors.secondary}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Pressable>
|
||||
) : null}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimelineHeaderDefault
|
144
src/components/Timeline/Shared/HeaderDefault.tsx
Normal file
144
src/components/Timeline/Shared/HeaderDefault.tsx
Normal file
@ -0,0 +1,144 @@
|
||||
import menuAccount from '@components/contextMenu/account'
|
||||
import menuInstance from '@components/contextMenu/instance'
|
||||
import menuShare from '@components/contextMenu/share'
|
||||
import menuStatus from '@components/contextMenu/status'
|
||||
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, { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Platform, Pressable, View } from 'react-native'
|
||||
import * as DropdownMenu from 'zeego/dropdown-menu'
|
||||
import HeaderSharedAccount from './HeaderShared/Account'
|
||||
import HeaderSharedApplication from './HeaderShared/Application'
|
||||
import HeaderSharedCreated from './HeaderShared/Created'
|
||||
import HeaderSharedMuted from './HeaderShared/Muted'
|
||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||
|
||||
export interface Props {
|
||||
queryKey?: QueryKeyTimeline
|
||||
rootQueryKey?: QueryKeyTimeline
|
||||
status: Mastodon.Status
|
||||
highlighted: boolean
|
||||
copiableContent: React.MutableRefObject<{
|
||||
content: string
|
||||
complete: boolean
|
||||
}>
|
||||
}
|
||||
|
||||
const TimelineHeaderDefault: React.FC<Props> = ({
|
||||
queryKey,
|
||||
rootQueryKey,
|
||||
status,
|
||||
highlighted,
|
||||
copiableContent
|
||||
}) => {
|
||||
const { colors } = useTheme()
|
||||
const { t } = useTranslation('componentContextMenu')
|
||||
|
||||
const [openChange, setOpenChange] = useState(false)
|
||||
const mShare = menuShare({
|
||||
visibility: status.visibility,
|
||||
type: 'status',
|
||||
url: status.url || status.uri,
|
||||
copiableContent
|
||||
})
|
||||
const mAccount = menuAccount({
|
||||
openChange,
|
||||
id: status.account.id,
|
||||
queryKey
|
||||
})
|
||||
const mStatus = menuStatus({ status, queryKey, rootQueryKey })
|
||||
const mInstance = menuInstance({ status, queryKey, rootQueryKey })
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, flexDirection: 'row' }}>
|
||||
<View style={{ flex: 7 }}>
|
||||
<HeaderSharedAccount account={status.account} />
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: StyleConstants.Spacing.XS,
|
||||
marginBottom: StyleConstants.Spacing.S
|
||||
}}
|
||||
>
|
||||
<HeaderSharedCreated
|
||||
created_at={status.created_at}
|
||||
edited_at={status.edited_at}
|
||||
highlighted={highlighted}
|
||||
/>
|
||||
<HeaderSharedVisibility visibility={status.visibility} />
|
||||
<HeaderSharedMuted muted={status.muted} />
|
||||
<HeaderSharedApplication application={status.application} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{Platform.OS !== 'android' && queryKey ? (
|
||||
<Pressable
|
||||
accessibilityHint={t('accessibilityHint')}
|
||||
style={{ flex: 1, alignItems: 'center' }}
|
||||
>
|
||||
<DropdownMenu.Root onOpenChange={setOpenChange}>
|
||||
<DropdownMenu.Trigger>
|
||||
<Icon
|
||||
name='MoreHorizontal'
|
||||
color={colors.secondary}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
/>
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
<DropdownMenu.Content>
|
||||
{mShare.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mAccount.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mStatus.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mInstance.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
</Pressable>
|
||||
) : null}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimelineHeaderDefault
|
@ -1,157 +0,0 @@
|
||||
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 Icon from '@components/Icon'
|
||||
import { RelationshipIncoming, RelationshipOutgoing } from '@components/Relationship'
|
||||
import { useActionSheet } from '@expo/react-native-action-sheet'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useMemo } from 'react'
|
||||
import { Pressable, View } from 'react-native'
|
||||
import { ContextMenuAction } from 'react-native-context-menu-view'
|
||||
import HeaderSharedAccount from './HeaderShared/Account'
|
||||
import HeaderSharedApplication from './HeaderShared/Application'
|
||||
import HeaderSharedCreated from './HeaderShared/Created'
|
||||
import HeaderSharedMuted from './HeaderShared/Muted'
|
||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||
|
||||
export interface Props {
|
||||
queryKey: QueryKeyTimeline
|
||||
notification: Mastodon.Notification
|
||||
}
|
||||
|
||||
const TimelineHeaderNotification = ({ queryKey, notification }: Props) => {
|
||||
const { colors } = useTheme()
|
||||
|
||||
const contextMenuActions: ContextMenuAction[] = []
|
||||
const status = notification.status
|
||||
const shareOnPress =
|
||||
status && status?.visibility !== 'direct'
|
||||
? contextMenuShare({
|
||||
actions: contextMenuActions,
|
||||
type: 'status',
|
||||
url: status.url || status.uri
|
||||
})
|
||||
: null
|
||||
const statusOnPress =
|
||||
status &&
|
||||
contextMenuStatus({
|
||||
actions: contextMenuActions,
|
||||
status: status,
|
||||
queryKey
|
||||
})
|
||||
const accountOnPress =
|
||||
status &&
|
||||
contextMenuAccount({
|
||||
actions: contextMenuActions,
|
||||
type: 'status',
|
||||
queryKey,
|
||||
id: status.account.id
|
||||
})
|
||||
const instanceOnPress =
|
||||
status &&
|
||||
contextMenuInstance({
|
||||
actions: contextMenuActions,
|
||||
status: status,
|
||||
queryKey
|
||||
})
|
||||
|
||||
const { showActionSheetWithOptions } = useActionSheet()
|
||||
|
||||
const actions = useMemo(() => {
|
||||
switch (notification.type) {
|
||||
case 'follow':
|
||||
return <RelationshipOutgoing id={notification.account.id} />
|
||||
case 'follow_request':
|
||||
return <RelationshipIncoming id={notification.account.id} />
|
||||
default:
|
||||
if (notification.status) {
|
||||
return (
|
||||
<Pressable
|
||||
style={{ flex: 1, flexBasis: StyleConstants.Font.Size.L }}
|
||||
onPress={() =>
|
||||
showActionSheetWithOptions(
|
||||
{
|
||||
options: contextMenuActions.map(action => action.title),
|
||||
cancelButtonIndex: 999,
|
||||
destructiveButtonIndex: contextMenuActions
|
||||
.map((action, index) => (action.destructive ? index : 999))
|
||||
.filter(num => num !== 999)
|
||||
},
|
||||
index => {
|
||||
if (index !== undefined) {
|
||||
for (const on of [
|
||||
shareOnPress,
|
||||
statusOnPress,
|
||||
accountOnPress,
|
||||
instanceOnPress
|
||||
]) {
|
||||
on && on(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
children={
|
||||
<Icon
|
||||
name='MoreHorizontal'
|
||||
color={colors.secondary}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [notification.type])
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, flexDirection: 'row' }}>
|
||||
<View
|
||||
style={{
|
||||
flex: notification.type === 'follow' || notification.type === 'follow_request' ? 1 : 4
|
||||
}}
|
||||
>
|
||||
<HeaderSharedAccount
|
||||
account={notification.status ? notification.status.account : notification.account}
|
||||
{...((notification.type === 'follow' || notification.type === 'follow_request') && {
|
||||
withoutName: true
|
||||
})}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: StyleConstants.Spacing.XS,
|
||||
marginBottom: StyleConstants.Spacing.S
|
||||
}}
|
||||
>
|
||||
<HeaderSharedCreated
|
||||
created_at={notification.status?.created_at || notification.created_at}
|
||||
edited_at={notification.status?.edited_at}
|
||||
/>
|
||||
{notification.status?.visibility ? (
|
||||
<HeaderSharedVisibility visibility={notification.status.visibility} />
|
||||
) : null}
|
||||
<HeaderSharedMuted muted={notification.status?.muted} />
|
||||
<HeaderSharedApplication application={notification.status?.application} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={[
|
||||
{ marginLeft: StyleConstants.Spacing.M },
|
||||
notification.type === 'follow' || notification.type === 'follow_request'
|
||||
? { flexShrink: 1 }
|
||||
: { flex: 1 }
|
||||
]}
|
||||
>
|
||||
{actions}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimelineHeaderNotification
|
@ -1,105 +0,0 @@
|
||||
import Icon from '@components/Icon'
|
||||
import { RelationshipIncoming, RelationshipOutgoing } from '@components/Relationship'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useContext, useMemo } from 'react'
|
||||
import { Pressable, View } from 'react-native'
|
||||
import ContextMenu from 'react-native-context-menu-view'
|
||||
import { ContextMenuContext } from './ContextMenu'
|
||||
import HeaderSharedAccount from './HeaderShared/Account'
|
||||
import HeaderSharedApplication from './HeaderShared/Application'
|
||||
import HeaderSharedCreated from './HeaderShared/Created'
|
||||
import HeaderSharedMuted from './HeaderShared/Muted'
|
||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||
|
||||
export interface Props {
|
||||
queryKey: QueryKeyTimeline
|
||||
notification: Mastodon.Notification
|
||||
}
|
||||
|
||||
const TimelineHeaderNotification = ({ notification }: Props) => {
|
||||
const { colors } = useTheme()
|
||||
|
||||
const contextMenuContext = useContext(ContextMenuContext)
|
||||
|
||||
const actions = useMemo(() => {
|
||||
switch (notification.type) {
|
||||
case 'follow':
|
||||
return <RelationshipOutgoing id={notification.account.id} />
|
||||
case 'follow_request':
|
||||
return <RelationshipIncoming id={notification.account.id} />
|
||||
default:
|
||||
if (notification.status) {
|
||||
return (
|
||||
<Pressable
|
||||
style={{ flex: 1, flexBasis: StyleConstants.Font.Size.L }}
|
||||
children={
|
||||
<ContextMenu
|
||||
style={{ flex: 1, alignItems: 'center' }}
|
||||
dropdownMenuMode
|
||||
actions={contextMenuContext}
|
||||
onPress={() => {}}
|
||||
children={
|
||||
<Icon
|
||||
name='MoreHorizontal'
|
||||
color={colors.secondary}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [notification.type])
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, flexDirection: 'row' }}>
|
||||
<View
|
||||
style={{
|
||||
flex: notification.type === 'follow' || notification.type === 'follow_request' ? 1 : 4
|
||||
}}
|
||||
>
|
||||
<HeaderSharedAccount
|
||||
account={notification.status ? notification.status.account : notification.account}
|
||||
{...((notification.type === 'follow' || notification.type === 'follow_request') && {
|
||||
withoutName: true
|
||||
})}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: StyleConstants.Spacing.XS,
|
||||
marginBottom: StyleConstants.Spacing.S
|
||||
}}
|
||||
>
|
||||
<HeaderSharedCreated
|
||||
created_at={notification.status?.created_at || notification.created_at}
|
||||
edited_at={notification.status?.edited_at}
|
||||
/>
|
||||
{notification.status?.visibility ? (
|
||||
<HeaderSharedVisibility visibility={notification.status.visibility} />
|
||||
) : null}
|
||||
<HeaderSharedMuted muted={notification.status?.muted} />
|
||||
<HeaderSharedApplication application={notification.status?.application} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={[
|
||||
{ marginLeft: StyleConstants.Spacing.M },
|
||||
notification.type === 'follow' || notification.type === 'follow_request'
|
||||
? { flexShrink: 1 }
|
||||
: { flex: 1 }
|
||||
]}
|
||||
>
|
||||
{actions}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimelineHeaderNotification
|
163
src/components/Timeline/Shared/HeaderNotification.tsx
Normal file
163
src/components/Timeline/Shared/HeaderNotification.tsx
Normal file
@ -0,0 +1,163 @@
|
||||
import menuAccount from '@components/contextMenu/account'
|
||||
import menuInstance from '@components/contextMenu/instance'
|
||||
import menuShare from '@components/contextMenu/share'
|
||||
import menuStatus from '@components/contextMenu/status'
|
||||
import Icon from '@components/Icon'
|
||||
import { RelationshipIncoming, RelationshipOutgoing } from '@components/Relationship'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useState } from 'react'
|
||||
import { Platform, Pressable, View } from 'react-native'
|
||||
import * as DropdownMenu from 'zeego/dropdown-menu'
|
||||
import HeaderSharedAccount from './HeaderShared/Account'
|
||||
import HeaderSharedApplication from './HeaderShared/Application'
|
||||
import HeaderSharedCreated from './HeaderShared/Created'
|
||||
import HeaderSharedMuted from './HeaderShared/Muted'
|
||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||
|
||||
export interface Props {
|
||||
queryKey: QueryKeyTimeline
|
||||
notification: Mastodon.Notification
|
||||
}
|
||||
|
||||
const TimelineHeaderNotification = ({ queryKey, notification }: Props) => {
|
||||
const { colors } = useTheme()
|
||||
|
||||
const [openChange, setOpenChange] = useState(false)
|
||||
const mShare = menuShare({
|
||||
visibility: notification.status?.visibility,
|
||||
type: 'status',
|
||||
url: notification.status?.url || notification.status?.uri
|
||||
})
|
||||
const mAccount = menuAccount({
|
||||
openChange,
|
||||
id: notification.status?.account.id,
|
||||
queryKey
|
||||
})
|
||||
const mStatus = menuStatus({ status: notification.status, queryKey })
|
||||
const mInstance = menuInstance({ status: notification.status, queryKey })
|
||||
|
||||
const actions = () => {
|
||||
switch (notification.type) {
|
||||
case 'follow':
|
||||
return <RelationshipOutgoing id={notification.account.id} />
|
||||
case 'follow_request':
|
||||
return <RelationshipIncoming id={notification.account.id} />
|
||||
default:
|
||||
if (notification.status) {
|
||||
return (
|
||||
<Pressable
|
||||
style={{ flex: 1, alignItems: 'center' }}
|
||||
children={
|
||||
<DropdownMenu.Root onOpenChange={setOpenChange}>
|
||||
<DropdownMenu.Trigger>
|
||||
<Icon
|
||||
name='MoreHorizontal'
|
||||
color={colors.secondary}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
/>
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
<DropdownMenu.Content>
|
||||
{mShare.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mAccount.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mStatus.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
|
||||
{mInstance.map((mGroup, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
{mGroup.map(menu => (
|
||||
<DropdownMenu.Item key={menu.key} {...menu.item}>
|
||||
<DropdownMenu.ItemTitle children={menu.title} />
|
||||
<DropdownMenu.ItemIcon iosIconName={menu.icon} />
|
||||
</DropdownMenu.Item>
|
||||
))}
|
||||
</DropdownMenu.Group>
|
||||
))}
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, flexDirection: 'row' }}>
|
||||
<View
|
||||
style={{
|
||||
flex: notification.type === 'follow' || notification.type === 'follow_request' ? 1 : 4
|
||||
}}
|
||||
>
|
||||
<HeaderSharedAccount
|
||||
account={notification.status ? notification.status.account : notification.account}
|
||||
{...((notification.type === 'follow' || notification.type === 'follow_request') && {
|
||||
withoutName: true
|
||||
})}
|
||||
/>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginTop: StyleConstants.Spacing.XS,
|
||||
marginBottom: StyleConstants.Spacing.S
|
||||
}}
|
||||
>
|
||||
<HeaderSharedCreated
|
||||
created_at={notification.status?.created_at || notification.created_at}
|
||||
edited_at={notification.status?.edited_at}
|
||||
/>
|
||||
{notification.status?.visibility ? (
|
||||
<HeaderSharedVisibility visibility={notification.status.visibility} />
|
||||
) : null}
|
||||
<HeaderSharedMuted muted={notification.status?.muted} />
|
||||
<HeaderSharedApplication application={notification.status?.application} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{Platform.OS !== 'android' ? (
|
||||
<View
|
||||
style={[
|
||||
{ marginLeft: StyleConstants.Spacing.M },
|
||||
notification.type === 'follow' || notification.type === 'follow_request'
|
||||
? { flexShrink: 1 }
|
||||
: { flex: 1 }
|
||||
]}
|
||||
children={actions()}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default TimelineHeaderNotification
|
Reference in New Issue
Block a user