1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

Merge pull request #342 from tooot-app/main

Release v4.1.3
This commit is contained in:
xmflsct
2022-06-17 00:15:08 +02:00
committed by GitHub
10 changed files with 325 additions and 15 deletions

View File

@ -4,7 +4,7 @@
"native": "220603",
"major": 4,
"minor": 1,
"patch": 2,
"patch": 3,
"expo": "45.0.0"
},
"description": "tooot app for Mastodon",

View File

@ -5,12 +5,14 @@ import {
AccessibilityProps,
Image,
ImageStyle,
Platform,
Pressable,
StyleProp,
StyleSheet,
View,
ViewStyle
} from 'react-native'
import FastImage from 'react-native-fast-image'
import { Blurhash } from 'react-native-blurhash'
// blurhas -> if blurhash, show before any loading succeed
@ -125,13 +127,24 @@ const GracefullyImage = ({
]}
/>
) : null}
<Image
fadeDuration={0}
source={source}
style={[{ flex: 1 }, imageStyle]}
onLoad={onLoad}
onError={onError}
/>
{Platform.OS === 'ios' ? (
<Image
fadeDuration={0}
source={source}
style={[{ flex: 1 }, imageStyle]}
onLoad={onLoad}
onError={onError}
/>
) : (
<FastImage
fadeDuration={0}
source={source}
// @ts-ignore
style={[{ flex: 1 }, imageStyle]}
onLoad={onLoad}
onError={onError}
/>
)}
{blurhashView}
</Pressable>
)

View File

@ -78,6 +78,7 @@ const TimelineDefault: React.FC<Props> = ({
status={actualStatus}
queryKey={queryKey}
rootQueryKey={rootQueryKey}
disabled={highlighted}
>
<Pressable
accessible={highlighted ? false : true}

View File

@ -59,7 +59,11 @@ const TimelineNotifications = React.memo(
}, [])
return (
<TimelineContextMenu status={notification.status} queryKey={queryKey}>
<TimelineContextMenu
status={notification.status}
queryKey={queryKey}
disabled={highlighted}
>
<Pressable
style={{
padding: StyleConstants.Spacing.Global.PagePadding,
@ -96,7 +100,10 @@ const TimelineNotifications = React.memo(
account={actualAccount}
highlighted={highlighted}
/>
<TimelineHeaderNotification notification={notification} />
<TimelineHeaderNotification
queryKey={queryKey}
notification={notification}
/>
</View>
{notification.status ? (

View File

@ -5,6 +5,7 @@ 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
@ -14,6 +15,7 @@ export interface Props {
status?: Mastodon.Status
queryKey?: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline
disabled?: boolean // Allowing toot to be copied when highlighted
}
export const ContextMenuContext = createContext<ContextMenuAction[]>([])
@ -23,9 +25,10 @@ const TimelineContextMenu: React.FC<Props & ContextMenuProps> = ({
status,
queryKey,
rootQueryKey,
disabled,
...props
}) => {
if (!status || !queryKey) {
if (!status || !queryKey || disabled || Platform.OS === 'android') {
return <>{children}</>
}

View File

@ -0,0 +1,120 @@
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 { 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 { Platform, Pressable, View } from 'react-native'
import ContextMenu, { ContextMenuAction } 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) => {
if (!queryKey) return
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
})
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,
flexDirection: 'row',
justifyContent: 'center',
marginBottom: StyleConstants.Spacing.L
}}
>
<ContextMenu
dropdownMenuMode
actions={actions}
onPress={({ nativeEvent: { index } }) => {
console.log('index', index)
for (const on of [
shareOnPress,
statusOnPress,
accountOnPress,
instanceOnPress
]) {
on && on(index)
}
}}
children={
<Icon
name='MoreHorizontal'
color={colors.secondary}
size={StyleConstants.Font.Size.L}
/>
}
/>
</Pressable>
) : null}
</View>
)
}
export default TimelineHeaderDefault

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 { Pressable, View } from 'react-native'
import { Platform, 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 ? (
{queryKey && !highlighted ? (
<Pressable
accessibilityHint={t('accessibilityHint')}
style={{

View File

@ -0,0 +1,163 @@
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 { 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 ContextMenu, { 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 = contextMenuStatus({
actions: contextMenuActions,
status,
queryKey
})
const accountOnPress = contextMenuAccount({
actions: contextMenuActions,
type: 'status',
queryKey,
id: status?.account.id
})
const instanceOnPress = contextMenuInstance({
actions: contextMenuActions,
status,
queryKey
})
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,
flexDirection: 'row',
justifyContent: 'center',
paddingBottom: StyleConstants.Spacing.S
}}
children={
<ContextMenu
dropdownMenuMode
actions={contextMenuActions}
onPress={({ nativeEvent: { index } }) => {
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

View File

@ -3,6 +3,7 @@ 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'
@ -16,6 +17,7 @@ import HeaderSharedMuted from './HeaderShared/Muted'
import HeaderSharedVisibility from './HeaderShared/Visibility'
export interface Props {
queryKey: QueryKeyTimeline
notification: Mastodon.Notification
}

View File

@ -2,7 +2,8 @@ import Button from '@components/Button'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { Dimensions, Image, View } from 'react-native'
import { Dimensions, View } from 'react-native'
import FastImage from 'react-native-fast-image'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
export interface Props {
@ -18,7 +19,7 @@ const AccountHeader = React.memo(
return (
<View>
<Image
<FastImage
source={{
uri: reduceMotionEnabled ? account?.header_static : account?.header
}}