1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00
This commit is contained in:
xmflsct
2022-08-09 00:44:56 +02:00
parent a68ed6ea1b
commit 9f17f95a98
12 changed files with 333 additions and 277 deletions

View File

@ -1,15 +1,23 @@
import analytics from '@components/analytics'
import { displayMessage } from '@components/Message'
import Clipboard from '@react-native-clipboard/clipboard'
import { useTheme } from '@utils/styles/ThemeManager'
import { useTranslation } from 'react-i18next'
import { Platform, Share } from 'react-native'
import { ContextMenuAction } from 'react-native-context-menu-view'
export interface Props {
copiableContent?: React.MutableRefObject<{
content?: string | undefined
complete: boolean
}>
actions: ContextMenuAction[]
type: 'status' | 'account'
url: string
}
const contextMenuShare = ({ actions, type, url }: Props) => {
const contextMenuShare = ({ copiableContent, actions, type, url }: Props) => {
const { theme } = useTheme()
const { t } = useTranslation('componentContextMenu')
actions.push({
@ -17,8 +25,24 @@ const contextMenuShare = ({ actions, type, url }: Props) => {
title: t(`share.${type}.action`),
systemIcon: 'square.and.arrow.up'
})
Platform.OS !== 'android' &&
actions.push({
id: 'copy',
title: t(`copy.action`),
systemIcon: 'doc.on.doc',
disabled: !copiableContent?.current.content?.length
})
return (index: number) => {
if (actions[index].id === 'copy') {
analytics('timeline_shared_headeractions_copy_press')
Clipboard.setString(copiableContent?.current.content || '')
displayMessage({
theme,
type: 'success',
message: t(`copy.succeed`)
})
}
if (actions[index].id === 'share') {
analytics('timeline_shared_headeractions_share_press')
switch (Platform.OS) {

View File

@ -15,7 +15,7 @@ import { getInstanceAccount } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { uniqBy } from 'lodash'
import React, { useCallback } from 'react'
import React, { useCallback, useEffect, useRef } from 'react'
import { Pressable, View } from 'react-native'
import { useSelector } from 'react-redux'
import TimelineContextMenu from './Shared/ContextMenu'
@ -53,10 +53,15 @@ const TimelineDefault: React.FC<Props> = ({
const ownAccount = actualStatus.account?.id === instanceAccount?.id
const copiableContent = useRef<{ content: string; complete: boolean }>({
content: '',
complete: false
})
if (
!highlighted &&
queryKey &&
shouldFilter({ status: actualStatus, queryKey })
shouldFilter({ copiableContent, status: actualStatus, queryKey })
) {
return <TimelineFiltered />
}
@ -75,10 +80,10 @@ const TimelineDefault: React.FC<Props> = ({
return (
<TimelineContextMenu
copiableContent={copiableContent}
status={actualStatus}
queryKey={queryKey}
rootQueryKey={rootQueryKey}
disabled={highlighted}
>
<Pressable
accessible={highlighted ? false : true}

View File

@ -15,7 +15,7 @@ import { getInstanceAccount } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { isEqual, uniqBy } from 'lodash'
import React, { useCallback } from 'react'
import React, { useCallback, useRef } from 'react'
import { Pressable, View } from 'react-native'
import { useSelector } from 'react-redux'
import TimelineContextMenu from './Shared/ContextMenu'
@ -30,9 +30,14 @@ export interface Props {
const TimelineNotifications = React.memo(
({ notification, queryKey, highlighted = false }: Props) => {
const copiableContent = useRef<{ content: string; complete: boolean }>({
content: '',
complete: false
})
if (
notification.status &&
shouldFilter({ status: notification.status, queryKey })
shouldFilter({ copiableContent, status: notification.status, queryKey })
) {
return <TimelineFiltered />
}
@ -60,9 +65,9 @@ const TimelineNotifications = React.memo(
return (
<TimelineContextMenu
copiableContent={copiableContent}
status={notification.status}
queryKey={queryKey}
disabled={highlighted}
>
<Pressable
style={{

View File

@ -38,7 +38,6 @@ const TimelineContent = React.memo(
numberOfLines={999}
highlighted={highlighted}
disableDetails={disableDetails}
selectable={highlighted}
/>
<ParseHTML
content={status.content}
@ -53,7 +52,6 @@ const TimelineContent = React.memo(
expandHint={t('shared.content.expandHint')}
highlighted={highlighted}
disableDetails={disableDetails}
selectable={highlighted}
/>
</>
) : (
@ -66,7 +64,6 @@ const TimelineContent = React.memo(
tags={status.tags}
numberOfLines={highlighted ? 999 : numberOfLines}
disableDetails={disableDetails}
selectable={highlighted}
/>
)}
</>

View File

@ -12,23 +12,26 @@ import ContextMenu, {
} from 'react-native-context-menu-view'
export interface Props {
copiableContent: React.MutableRefObject<{
content: string
complete: boolean
}>
status?: Mastodon.Status
queryKey?: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline
disabled?: boolean // Allowing toot to be copied when highlighted
}
export const ContextMenuContext = createContext<ContextMenuAction[]>([])
const TimelineContextMenu: React.FC<Props & ContextMenuProps> = ({
children,
copiableContent,
status,
queryKey,
rootQueryKey,
disabled,
...props
}) => {
if (!status || !queryKey || disabled || Platform.OS === 'android') {
if (!status || !queryKey || Platform.OS === 'android') {
return <>{children}</>
}
@ -37,6 +40,7 @@ const TimelineContextMenu: React.FC<Props & ContextMenuProps> = ({
const shareOnPress =
status.visibility !== 'direct'
? contextMenuShare({
copiableContent,
actions,
type: 'status',
url: status.url || status.uri

View File

@ -34,9 +34,14 @@ const TimelineFiltered = React.memo(
)
export const shouldFilter = ({
copiableContent,
status,
queryKey
}: {
copiableContent: React.MutableRefObject<{
content: string
complete: boolean
}>
status: Mastodon.Status
queryKey: QueryKeyTimeline
}) => {
@ -48,6 +53,11 @@ export const shouldFilter = ({
if (!ownAccount) {
const parser = new htmlparser2.Parser({
ontext: (text: string) => {
if (!copiableContent.current.complete) {
copiableContent.current.content =
copiableContent.current.content + text
}
const checkFilter = (filter: Mastodon.Filter) => {
const escapedPhrase = filter.phrase.replace(
/[.*+?^${}()|[\]\\]/g,
@ -103,6 +113,7 @@ export const shouldFilter = ({
status.spoiler_text && parser.write(status.spoiler_text)
parser.write(status.content)
parser.end()
copiableContent.current.complete = true
}
return shouldFilter

View File

@ -4,7 +4,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { Platform, Pressable, View } from 'react-native'
import { Pressable, View } from 'react-native'
import ContextMenu from 'react-native-context-menu-view'
import { ContextMenuContext } from './ContextMenu'
import HeaderSharedAccount from './HeaderShared/Account'
@ -48,7 +48,7 @@ const TimelineHeaderDefault = ({ queryKey, status, highlighted }: Props) => {
</View>
</View>
{queryKey && !highlighted ? (
{queryKey ? (
<Pressable
accessibilityHint={t('accessibilityHint')}
style={{

View File

@ -141,13 +141,7 @@ const TimelineTranslate = React.memo(
</Pressable>
{data && data.error === undefined
? data.text.map((d, i) => (
<ParseHTML
key={i}
content={d}
size={'M'}
numberOfLines={999}
selectable
/>
<ParseHTML key={i} content={d} size={'M'} numberOfLines={999} />
))
: null}
</>