mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Merge branch 'main' into release
This commit is contained in:
@ -0,0 +1,38 @@
|
||||
diff --git a/src/zoom.tsx b/src/zoom.tsx
|
||||
index 70ce1c8d6a43e711f06b93d1eda3b44a3ad9a659..cdc2713470f2d332b8bf3e9c97e38fd9b78281df 100644
|
||||
--- a/src/zoom.tsx
|
||||
+++ b/src/zoom.tsx
|
||||
@@ -4,6 +4,7 @@ import Animated, {
|
||||
useSharedValue,
|
||||
useAnimatedStyle,
|
||||
useDerivedValue,
|
||||
+ withDecay,
|
||||
withTiming,
|
||||
cancelAnimation,
|
||||
runOnJS,
|
||||
@@ -120,11 +121,22 @@ export function Zoom(props: Props) {
|
||||
}
|
||||
}
|
||||
})
|
||||
- .onEnd(() => {
|
||||
+ .onEnd((event) => {
|
||||
if (isPinching.value || !isZoomed.value) return;
|
||||
|
||||
- panTranslateX.value = 0;
|
||||
- panTranslateY.value = 0;
|
||||
+ const maxTranslateX = (viewWidth.value / 2) * scale.value - viewWidth.value / 2;
|
||||
+ const minTranslateX = -maxTranslateX;
|
||||
+ translationX.value = withDecay({
|
||||
+ velocity: event.velocityX,
|
||||
+ clamp: [minTranslateX, maxTranslateX]
|
||||
+ });
|
||||
+
|
||||
+ const maxTranslateY = (viewHeight.value / 2) * scale.value - viewHeight.value / 2;
|
||||
+ const minTranslateY = -maxTranslateY;
|
||||
+ translationY.value = withDecay({
|
||||
+ velocity: event.velocityY,
|
||||
+ clamp: [minTranslateY, maxTranslateY]
|
||||
+ });
|
||||
});
|
||||
|
||||
const pinch = Gesture.Pinch()
|
@ -35,6 +35,7 @@
|
||||
<array>
|
||||
<string>tooot-share</string>
|
||||
<string>tooot</string>
|
||||
<string>https</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tooot",
|
||||
"version": "4.9.2",
|
||||
"version": "4.9.3",
|
||||
"description": "tooot for Mastodon",
|
||||
"author": "xmflsct <me@xmflsct.com>",
|
||||
"license": "GPL-3.0-or-later",
|
||||
@ -114,6 +114,7 @@
|
||||
"expo-av@^13.0.2": "patch:expo-av@npm%3A13.0.2#./.yarn/patches/expo-av-npm-13.0.2-7a651776f1.patch",
|
||||
"react-native-share-menu@^6.0.0": "patch:react-native-share-menu@npm%3A6.0.0#./.yarn/patches/react-native-share-menu-npm-6.0.0-f1094c3204.patch",
|
||||
"@types/react-native-share-menu@^5.0.2": "patch:@types/react-native-share-menu@npm%3A5.0.2#./.yarn/patches/@types-react-native-share-menu-npm-5.0.2-373df17ecc.patch",
|
||||
"react-native-ios-context-menu@^1.15.1": "patch:react-native-ios-context-menu@npm%3A1.15.1#./.yarn/patches/react-native-ios-context-menu-npm-1.15.1-0034bfa5ba.patch"
|
||||
"react-native-ios-context-menu@^1.15.1": "patch:react-native-ios-context-menu@npm%3A1.15.1#./.yarn/patches/react-native-ios-context-menu-npm-1.15.1-0034bfa5ba.patch",
|
||||
"react-native-reanimated-zoom@^0.3.3": "patch:react-native-reanimated-zoom@npm%3A0.3.3#./.yarn/patches/react-native-reanimated-zoom-npm-0.3.3-bbb8d84109.patch"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
import menuInstance from '@components/contextMenu/instance'
|
||||
import menuShare from '@components/contextMenu/share'
|
||||
import menuStatus from '@components/contextMenu/status'
|
||||
import TimelineActioned from '@components/Timeline/Shared/Actioned'
|
||||
import TimelineActions from '@components/Timeline/Shared/Actions'
|
||||
import TimelineAttachment from '@components/Timeline/Shared/Attachment'
|
||||
@ -19,9 +16,8 @@ import { usePreferencesQuery } from '@utils/queryHooks/preferences'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { Fragment, useRef, useState } from 'react'
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { Pressable, StyleProp, View, ViewStyle } from 'react-native'
|
||||
import * as ContextMenu from 'zeego/context-menu'
|
||||
import StatusContext from './Shared/Context'
|
||||
import TimelineFeedback from './Shared/Feedback'
|
||||
import TimelineFiltered, { FilteredProps, shouldFilter } from './Shared/Filtered'
|
||||
@ -126,15 +122,6 @@ const TimelineDefault: React.FC<Props> = ({
|
||||
</>
|
||||
)
|
||||
|
||||
const mShare = menuShare({
|
||||
visibility: status.visibility,
|
||||
type: 'status',
|
||||
url: status.url || status.uri,
|
||||
rawContent
|
||||
})
|
||||
const mStatus = menuStatus({ status, queryKey })
|
||||
const mInstance = menuInstance({ status, queryKey })
|
||||
|
||||
if (!isMyAccount) {
|
||||
let filterResults: FilteredProps['filterResults'] = []
|
||||
const [filterRevealed, setFilterRevealed] = useState(false)
|
||||
@ -183,67 +170,14 @@ const TimelineDefault: React.FC<Props> = ({
|
||||
<View style={mainStyle}>{main()}</View>
|
||||
) : (
|
||||
<>
|
||||
<ContextMenu.Root>
|
||||
<ContextMenu.Trigger>
|
||||
<Pressable
|
||||
accessible={highlighted ? false : true}
|
||||
style={mainStyle}
|
||||
disabled={highlighted}
|
||||
onPress={() => navigation.push('Tab-Shared-Toot', { toot: status })}
|
||||
onLongPress={() => {}}
|
||||
children={main()}
|
||||
/>
|
||||
</ContextMenu.Trigger>
|
||||
|
||||
<ContextMenu.Content>
|
||||
{[mShare, mStatus, mInstance].map((menu, i) => (
|
||||
<Fragment key={i}>
|
||||
{menu.map((group, index) => (
|
||||
<ContextMenu.Group key={index}>
|
||||
{group.map(item => {
|
||||
switch (item.type) {
|
||||
case 'item':
|
||||
return (
|
||||
<ContextMenu.Item key={item.key} {...item.props}>
|
||||
<ContextMenu.ItemTitle children={item.title} />
|
||||
{item.icon ? (
|
||||
<ContextMenu.ItemIcon ios={{ name: item.icon }} />
|
||||
) : null}
|
||||
</ContextMenu.Item>
|
||||
)
|
||||
case 'sub':
|
||||
return (
|
||||
// @ts-ignore
|
||||
<ContextMenu.Sub key={item.key}>
|
||||
<ContextMenu.SubTrigger
|
||||
key={item.trigger.key}
|
||||
{...item.trigger.props}
|
||||
>
|
||||
<ContextMenu.ItemTitle children={item.trigger.title} />
|
||||
{item.trigger.icon ? (
|
||||
<ContextMenu.ItemIcon ios={{ name: item.trigger.icon }} />
|
||||
) : null}
|
||||
</ContextMenu.SubTrigger>
|
||||
<ContextMenu.SubContent>
|
||||
{item.items.map(sub => (
|
||||
<ContextMenu.Item key={sub.key} {...sub.props}>
|
||||
<ContextMenu.ItemTitle children={sub.title} />
|
||||
{sub.icon ? (
|
||||
<ContextMenu.ItemIcon ios={{ name: sub.icon }} />
|
||||
) : null}
|
||||
</ContextMenu.Item>
|
||||
))}
|
||||
</ContextMenu.SubContent>
|
||||
</ContextMenu.Sub>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</ContextMenu.Group>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
</ContextMenu.Content>
|
||||
</ContextMenu.Root>
|
||||
<Pressable
|
||||
accessible={highlighted ? false : true}
|
||||
style={mainStyle}
|
||||
disabled={highlighted}
|
||||
onPress={() => navigation.push('Tab-Shared-Toot', { toot: status })}
|
||||
onLongPress={() => {}}
|
||||
children={main()}
|
||||
/>
|
||||
<TimelineHeaderAndroid />
|
||||
</>
|
||||
)}
|
||||
|
@ -1,6 +1,3 @@
|
||||
import menuInstance from '@components/contextMenu/instance'
|
||||
import menuShare from '@components/contextMenu/share'
|
||||
import menuStatus from '@components/contextMenu/status'
|
||||
import TimelineActioned from '@components/Timeline/Shared/Actioned'
|
||||
import TimelineActions from '@components/Timeline/Shared/Actions'
|
||||
import TimelineAttachment from '@components/Timeline/Shared/Attachment'
|
||||
@ -18,9 +15,8 @@ import { usePreferencesQuery } from '@utils/queryHooks/preferences'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { Fragment, useState } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { Pressable, View } from 'react-native'
|
||||
import * as ContextMenu from 'zeego/context-menu'
|
||||
import StatusContext from './Shared/Context'
|
||||
import TimelineFiltered, { FilteredProps, shouldFilter } from './Shared/Filtered'
|
||||
import TimelineFullConversation from './Shared/FullConversation'
|
||||
@ -100,14 +96,6 @@ const TimelineNotifications: React.FC<Props> = ({ notification, queryKey }) => {
|
||||
)
|
||||
}
|
||||
|
||||
const mShare = menuShare({
|
||||
visibility: notification.status?.visibility,
|
||||
type: 'status',
|
||||
url: notification.status?.url || notification.status?.uri
|
||||
})
|
||||
const mStatus = menuStatus({ status: notification.status, queryKey })
|
||||
const mInstance = menuInstance({ status: notification.status, queryKey })
|
||||
|
||||
if (!isMyAccount) {
|
||||
let filterResults: FilteredProps['filterResults'] = []
|
||||
const [filterRevealed, setFilterRevealed] = useState(false)
|
||||
@ -143,67 +131,18 @@ const TimelineNotifications: React.FC<Props> = ({ notification, queryKey }) => {
|
||||
spoilerHidden
|
||||
}}
|
||||
>
|
||||
<ContextMenu.Root>
|
||||
<ContextMenu.Trigger>
|
||||
<Pressable
|
||||
style={{
|
||||
padding: StyleConstants.Spacing.Global.PagePadding,
|
||||
backgroundColor: colors.backgroundDefault,
|
||||
paddingBottom: notification.status ? 0 : StyleConstants.Spacing.Global.PagePadding
|
||||
}}
|
||||
onPress={() =>
|
||||
notification.status &&
|
||||
navigation.push('Tab-Shared-Toot', { toot: notification.status })
|
||||
}
|
||||
onLongPress={() => {}}
|
||||
children={main()}
|
||||
/>
|
||||
</ContextMenu.Trigger>
|
||||
|
||||
<ContextMenu.Content>
|
||||
{[mShare, mStatus, mInstance].map((menu, i) => (
|
||||
<Fragment key={i}>
|
||||
{menu.map((group, index) => (
|
||||
<ContextMenu.Group key={index}>
|
||||
{group.map(item => {
|
||||
switch (item.type) {
|
||||
case 'item':
|
||||
return (
|
||||
<ContextMenu.Item key={item.key} {...item.props}>
|
||||
<ContextMenu.ItemTitle children={item.title} />
|
||||
{item.icon ? <ContextMenu.ItemIcon ios={{ name: item.icon }} /> : null}
|
||||
</ContextMenu.Item>
|
||||
)
|
||||
case 'sub':
|
||||
return (
|
||||
// @ts-ignore
|
||||
<ContextMenu.Sub key={item.key}>
|
||||
<ContextMenu.SubTrigger key={item.trigger.key} {...item.trigger.props}>
|
||||
<ContextMenu.ItemTitle children={item.trigger.title} />
|
||||
{item.trigger.icon ? (
|
||||
<ContextMenu.ItemIcon ios={{ name: item.trigger.icon }} />
|
||||
) : null}
|
||||
</ContextMenu.SubTrigger>
|
||||
<ContextMenu.SubContent>
|
||||
{item.items.map(sub => (
|
||||
<ContextMenu.Item key={sub.key} {...sub.props}>
|
||||
<ContextMenu.ItemTitle children={sub.title} />
|
||||
{sub.icon ? (
|
||||
<ContextMenu.ItemIcon ios={{ name: sub.icon }} />
|
||||
) : null}
|
||||
</ContextMenu.Item>
|
||||
))}
|
||||
</ContextMenu.SubContent>
|
||||
</ContextMenu.Sub>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</ContextMenu.Group>
|
||||
))}
|
||||
</Fragment>
|
||||
))}
|
||||
</ContextMenu.Content>
|
||||
</ContextMenu.Root>
|
||||
<Pressable
|
||||
style={{
|
||||
padding: StyleConstants.Spacing.Global.PagePadding,
|
||||
backgroundColor: colors.backgroundDefault,
|
||||
paddingBottom: notification.status ? 0 : StyleConstants.Spacing.Global.PagePadding
|
||||
}}
|
||||
onPress={() =>
|
||||
notification.status && navigation.push('Tab-Shared-Toot', { toot: notification.status })
|
||||
}
|
||||
onLongPress={() => {}}
|
||||
children={main()}
|
||||
/>
|
||||
<TimelineHeaderAndroid />
|
||||
</StatusContext.Provider>
|
||||
)
|
||||
|
@ -17,7 +17,15 @@ export const CardNeodb: React.FC<Props> = ({ card }) => {
|
||||
const { colors } = useTheme()
|
||||
|
||||
const segments = Linking.parse(card.url).path?.split('/')
|
||||
if (!segments || !(segments[0] === 'movie' || segments[0] === 'book' || segments[0] === 'tv'))
|
||||
if (
|
||||
!segments ||
|
||||
!(
|
||||
segments[0] === 'movie' ||
|
||||
segments[0] === 'book' ||
|
||||
(segments[0] === 'tv' && segments[1] !== 'season') ||
|
||||
segments[0] === 'game'
|
||||
)
|
||||
)
|
||||
return null
|
||||
|
||||
const [headingLines, setHeadingLines] = useState(3)
|
||||
@ -26,121 +34,104 @@ export const CardNeodb: React.FC<Props> = ({ card }) => {
|
||||
|
||||
if (!data) return null
|
||||
|
||||
const pressableProps = {
|
||||
style: {
|
||||
marginTop: StyleConstants.Spacing.M,
|
||||
backgroundColor: colors.shimmerDefault,
|
||||
borderRadius: StyleConstants.BorderRadius,
|
||||
padding: StyleConstants.Spacing.S,
|
||||
flexDirection: 'row' as 'row'
|
||||
},
|
||||
onPress: () => openLink(card.url)
|
||||
}
|
||||
const contentProps = { style: { flex: 1, gap: StyleConstants.Spacing.S } }
|
||||
|
||||
const itemImage = data.cover_image_url ? (
|
||||
<GracefullyImage
|
||||
sources={{ default: { uri: data.cover_image_url } }}
|
||||
dimension={{
|
||||
width: StyleConstants.Font.LineHeight.M * 4,
|
||||
height: StyleConstants.Font.LineHeight.M * 5
|
||||
const Content = ({ heading, details }: { heading: string[]; details: string[] }) => (
|
||||
<Pressable
|
||||
style={{
|
||||
marginTop: StyleConstants.Spacing.M,
|
||||
backgroundColor: colors.shimmerDefault,
|
||||
borderRadius: StyleConstants.BorderRadius,
|
||||
padding: StyleConstants.Spacing.S,
|
||||
flexDirection: 'row'
|
||||
}}
|
||||
style={{ marginRight: StyleConstants.Spacing.S }}
|
||||
imageStyle={{ borderRadius: StyleConstants.BorderRadius / 2 }}
|
||||
dim
|
||||
/>
|
||||
) : null
|
||||
const itemHeading = (value: string) => (
|
||||
<CustomText
|
||||
fontStyle='S'
|
||||
fontWeight='Bold'
|
||||
style={{ color: colors.primaryDefault }}
|
||||
numberOfLines={3}
|
||||
children={value}
|
||||
onTextLayout={({ nativeEvent }) => setHeadingLines(nativeEvent.lines.length)}
|
||||
/>
|
||||
)
|
||||
const itemDetails = (value: string) => (
|
||||
<CustomText
|
||||
fontStyle='S'
|
||||
style={{ color: colors.secondary }}
|
||||
numberOfLines={4 - headingLines}
|
||||
children={value}
|
||||
/>
|
||||
onPress={() => openLink(card.url)}
|
||||
>
|
||||
{data.cover_image_url ? (
|
||||
<GracefullyImage
|
||||
sources={{ default: { uri: data.cover_image_url } }}
|
||||
dimension={{
|
||||
width: StyleConstants.Font.LineHeight.M * 4,
|
||||
height: StyleConstants.Font.LineHeight.M * 5
|
||||
}}
|
||||
style={{ marginRight: StyleConstants.Spacing.S }}
|
||||
imageStyle={{ borderRadius: StyleConstants.BorderRadius / 2 }}
|
||||
dim
|
||||
/>
|
||||
) : null}
|
||||
<View style={{ flex: 1, gap: StyleConstants.Spacing.S, justifyContent: 'space-between' }}>
|
||||
<View style={{ gap: StyleConstants.Spacing.S }}>
|
||||
<CustomText
|
||||
fontStyle='S'
|
||||
fontWeight='Bold'
|
||||
style={{ color: colors.primaryDefault }}
|
||||
numberOfLines={3}
|
||||
onTextLayout={({ nativeEvent }) => setHeadingLines(nativeEvent.lines.length)}
|
||||
children={heading.filter(d => d).join(' ')}
|
||||
/>
|
||||
<Rating rating={data.rating / 2} />
|
||||
</View>
|
||||
|
||||
<CustomText
|
||||
fontStyle='S'
|
||||
style={{ color: colors.secondary }}
|
||||
numberOfLines={4 - headingLines}
|
||||
children={details.filter(d => d).join(' / ')}
|
||||
/>
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
|
||||
switch (segments[0]) {
|
||||
case 'movie':
|
||||
return (
|
||||
<Pressable {...pressableProps}>
|
||||
{itemImage}
|
||||
<View {...contentProps}>
|
||||
{itemHeading(
|
||||
[data.title, data.orig_title, data.year ? `(${data.year})` : null]
|
||||
.filter(d => d)
|
||||
.join(' ')
|
||||
)}
|
||||
<Rating rating={data.rating / 2} />
|
||||
{itemDetails(
|
||||
[
|
||||
data.duration
|
||||
? parseInt(data.duration).toString() === data.duration
|
||||
? `${data.duration}分钟`
|
||||
: data.duration
|
||||
: null,
|
||||
data.area?.join(' '),
|
||||
data.genre?.join(' '),
|
||||
data.director?.join(' ')
|
||||
]
|
||||
.filter(d => d)
|
||||
.join(' / ')
|
||||
)}
|
||||
</View>
|
||||
</Pressable>
|
||||
<Content
|
||||
heading={[data.title, data.orig_title, data.year ? `(${data.year})` : null]}
|
||||
details={[
|
||||
data.duration
|
||||
? parseInt(data.duration).toString() === data.duration
|
||||
? `${data.duration}分钟`
|
||||
: data.duration
|
||||
: null,
|
||||
data.area?.join(' '),
|
||||
data.genre?.join(' '),
|
||||
data.director?.join(' ')
|
||||
]}
|
||||
/>
|
||||
)
|
||||
case 'book':
|
||||
return (
|
||||
<Pressable {...pressableProps}>
|
||||
{itemImage}
|
||||
<View {...contentProps}>
|
||||
{itemHeading(data.title)}
|
||||
<Rating rating={data.rating / 2} />
|
||||
{itemDetails(
|
||||
[
|
||||
data.author?.join(' '),
|
||||
data.pages ? `${data.pages}页` : null,
|
||||
data.language,
|
||||
data.pub_house
|
||||
]
|
||||
.filter(d => d)
|
||||
.join(' / ')
|
||||
)}
|
||||
</View>
|
||||
</Pressable>
|
||||
<Content
|
||||
heading={[data.title]}
|
||||
details={[
|
||||
data.author?.join(' '),
|
||||
data.pages ? `${data.pages}页` : null,
|
||||
data.language,
|
||||
data.pub_house
|
||||
]}
|
||||
/>
|
||||
)
|
||||
case 'tv':
|
||||
return (
|
||||
<Pressable {...pressableProps}>
|
||||
{itemImage}
|
||||
<View {...contentProps}>
|
||||
{itemHeading(
|
||||
[data.title, data.orig_title, data.year ? `(${data.year})` : null]
|
||||
.filter(d => d)
|
||||
.join(' ')
|
||||
)}
|
||||
<Rating rating={data.rating / 2} />
|
||||
{itemDetails(
|
||||
[
|
||||
data.season_count ? `共${data.season_count}季` : null,
|
||||
data.area?.join(' '),
|
||||
data.genre?.join(' '),
|
||||
data.director?.join(' ')
|
||||
]
|
||||
.filter(d => d)
|
||||
.join(' / ')
|
||||
)}
|
||||
</View>
|
||||
</Pressable>
|
||||
<Content
|
||||
heading={[data.title, data.orig_title, data.year ? `(${data.year})` : null]}
|
||||
details={[
|
||||
data.season_count ? `共${data.season_count}季` : null,
|
||||
data.area?.join(' '),
|
||||
data.genre?.join(' '),
|
||||
data.director?.join(' ')
|
||||
]}
|
||||
/>
|
||||
)
|
||||
case 'game':
|
||||
return (
|
||||
<Content
|
||||
heading={[data.title]}
|
||||
details={[
|
||||
data.genre?.join(' '),
|
||||
data.developer?.join(' '),
|
||||
data.platform?.join(' '),
|
||||
data.release_date
|
||||
]}
|
||||
/>
|
||||
)
|
||||
default:
|
||||
return null
|
||||
|
@ -4,6 +4,7 @@ import openLink from '@components/openLink'
|
||||
import CustomText from '@components/Text'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { isDevelopment } from '@utils/helpers/checkEnvironment'
|
||||
import { urlMatcher } from '@utils/helpers/urlMatcher'
|
||||
import { TabLocalStackParamList } from '@utils/navigation/navigators'
|
||||
import { useAccountQuery } from '@utils/queryHooks/account'
|
||||
@ -17,14 +18,19 @@ import TimelineDefault from '../../Default'
|
||||
import StatusContext from '../Context'
|
||||
import { CardNeodb } from './Neodb'
|
||||
|
||||
const CARD_URL_BLACKLISTS = ['weibo.com', 'weibo.cn']
|
||||
|
||||
const TimelineCard: React.FC = () => {
|
||||
const { status, spoilerHidden, disableDetails, inThread } = useContext(StatusContext)
|
||||
if (!status || !status.card) return null
|
||||
|
||||
if (CARD_URL_BLACKLISTS.find(domain => status.card?.url.includes(`${domain}/`))) return null
|
||||
|
||||
const { i18n } = useTranslation()
|
||||
if (
|
||||
status.card.url.includes('://neodb.social/') &&
|
||||
i18n.language.toLowerCase().startsWith('zh-hans')
|
||||
(status.card.url.includes('://neodb.social/') &&
|
||||
i18n.language.toLowerCase().startsWith('zh-hans')) ||
|
||||
isDevelopment
|
||||
) {
|
||||
return <CardNeodb card={status.card} />
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
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'
|
||||
@ -17,7 +18,8 @@ import HeaderSharedReplies from './HeaderShared/Replies'
|
||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||
|
||||
const TimelineHeaderDefault: React.FC = () => {
|
||||
const { queryKey, status, disableDetails, rawContent, isRemote } = useContext(StatusContext)
|
||||
const { queryKey, status, disableDetails, rawContent, isRemote, highlighted } =
|
||||
useContext(StatusContext)
|
||||
if (!status) return null
|
||||
|
||||
const { colors } = useTheme()
|
||||
@ -37,6 +39,7 @@ const TimelineHeaderDefault: React.FC = () => {
|
||||
...(status && { status })
|
||||
})
|
||||
const mStatus = menuStatus({ status, queryKey })
|
||||
const mInstance = highlighted ? menuInstance({ status, queryKey }) : []
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, flexDirection: 'row' }}>
|
||||
@ -87,7 +90,7 @@ const TimelineHeaderDefault: React.FC = () => {
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
<DropdownMenu.Content>
|
||||
{[mShare, mAccount, mStatus].map((menu, i) => (
|
||||
{[mShare, mAccount, mStatus, mInstance].map((menu, i) => (
|
||||
<Fragment key={i}>
|
||||
{menu.map((group, index) => (
|
||||
<DropdownMenu.Group key={index}>
|
||||
|
@ -387,12 +387,12 @@
|
||||
"account": {
|
||||
"actions": {
|
||||
"accessibilityLabel": "Дзеянні для карыстальніка {{user}}",
|
||||
"accessibilityHint": ""
|
||||
"accessibilityHint": "Вы можаце ігнараваць, блакіраваць або абагуліць гэтага карыстальніка"
|
||||
},
|
||||
"followed_by": " падпісаны на вас",
|
||||
"privateNote": "",
|
||||
"moved": "",
|
||||
"created_at": "",
|
||||
"created_at": "Далучыўся: {{date}}",
|
||||
"summary": {
|
||||
"statuses_count": "{{count}} допісаў"
|
||||
},
|
||||
@ -467,7 +467,7 @@
|
||||
"toot": {
|
||||
"name": "Абмеркаванні",
|
||||
"remoteFetch": {
|
||||
"title": "",
|
||||
"title": "Змяшчае аддаленае змесціва",
|
||||
"message": ""
|
||||
}
|
||||
},
|
||||
|
@ -176,18 +176,14 @@ const TabMePreferencesFilter: React.FC<
|
||||
...(parseInt(expiration) && {
|
||||
expires_in: parseInt(expiration)
|
||||
}),
|
||||
...(keywords.filter(keyword => keyword.length).length
|
||||
? {
|
||||
keywords_attributes: keywords
|
||||
.filter(keyword => keyword.length)
|
||||
.map(keyword => ({ keyword, whole_word: true }))
|
||||
}
|
||||
: params.filter.keywords.length && {
|
||||
keywords_attributes: params.filter.keywords.map(keyword => ({
|
||||
...keyword,
|
||||
_destroy: true
|
||||
}))
|
||||
})
|
||||
keywords_attributes: keywords.map((keyword, index) =>
|
||||
!!params.filter.keywords[index]
|
||||
? {
|
||||
id: params.filter.keywords[index].id,
|
||||
...(keyword.length ? { keyword, whole_word: true } : { _destroy: true })
|
||||
}
|
||||
: { keyword, whole_word: true }
|
||||
)
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
|
@ -37,9 +37,10 @@ const AccountInformationActions: React.FC = () => {
|
||||
return (
|
||||
<View style={styles.base}>
|
||||
<Button
|
||||
type='text'
|
||||
round
|
||||
type='icon'
|
||||
disabled={account === undefined}
|
||||
content={t('me.stacks.profile.name')}
|
||||
content='edit-3'
|
||||
onPress={() => navigation.navigate('Tab-Me-Profile')}
|
||||
/>
|
||||
<Button
|
||||
@ -47,7 +48,7 @@ const AccountInformationActions: React.FC = () => {
|
||||
type='icon'
|
||||
disabled={account === undefined}
|
||||
content='sliders'
|
||||
style={{ marginLeft: StyleConstants.Spacing.S }}
|
||||
style={{ marginLeft: StyleConstants.Spacing.M }}
|
||||
onPress={() =>
|
||||
navigation.navigate('Tab-Me-Preferences', { screen: 'Tab-Me-Preferences-Root' })
|
||||
}
|
||||
|
@ -55,6 +55,9 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
||||
...(account._remote && { remote_id: account.id, remote_domain: account._remote })
|
||||
}
|
||||
]
|
||||
useEffect(() => {
|
||||
navigation.setParams({ queryKey: queryKeyDefault })
|
||||
}, [dataUpdatedAt])
|
||||
|
||||
const mShare = menuShare({ type: 'account', url: data?.url })
|
||||
const mAccount = menuAccount({ type: 'account', openChange: true, account: data })
|
||||
|
14
yarn.lock
14
yarn.lock
@ -9950,7 +9950,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-reanimated-zoom@npm:^0.3.3":
|
||||
"react-native-reanimated-zoom@npm:0.3.3":
|
||||
version: 0.3.3
|
||||
resolution: "react-native-reanimated-zoom@npm:0.3.3"
|
||||
peerDependencies:
|
||||
@ -9962,6 +9962,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-reanimated-zoom@patch:react-native-reanimated-zoom@npm%3A0.3.3#./.yarn/patches/react-native-reanimated-zoom-npm-0.3.3-bbb8d84109.patch::locator=tooot%40workspace%3A.":
|
||||
version: 0.3.3
|
||||
resolution: "react-native-reanimated-zoom@patch:react-native-reanimated-zoom@npm%3A0.3.3#./.yarn/patches/react-native-reanimated-zoom-npm-0.3.3-bbb8d84109.patch::version=0.3.3&hash=187ed4&locator=tooot%40workspace%3A."
|
||||
peerDependencies:
|
||||
react: "*"
|
||||
react-native: "*"
|
||||
react-native-gesture-handler: "*"
|
||||
react-native-reanimated: "*"
|
||||
checksum: b43e7db64ad15cdb964da44b313205164ae74ebcde6baf01f3852b8cd733078b90d4ada140c78fad33ac2ba70f4db5b1d8644018f6ff885bbb998d2dd0211b05
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-reanimated@npm:^3.0.2":
|
||||
version: 3.0.2
|
||||
resolution: "react-native-reanimated@npm:3.0.2"
|
||||
|
Reference in New Issue
Block a user