mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Merge branch 'main' into candidate
This commit is contained in:
@@ -1 +1,4 @@
|
|||||||
Enjoy toooting! This version includes following improvements and fixes:
|
Enjoy toooting! This version includes following improvements and fixes:
|
||||||
|
- Supports mute duration
|
||||||
|
- Long press to copy toot
|
||||||
|
- Button to fetch latest on load
|
@@ -1,2 +1,5 @@
|
|||||||
tooot-ing愉快!此版本包括以下改进和修复:
|
tooot-ing愉快!此版本包括以下改进和修复:
|
||||||
- 新增neodb.social演出卡片
|
- 新增neodb.social演出卡片
|
||||||
|
- 支持选择隐藏用户时限
|
||||||
|
- 长按复制嘟文
|
||||||
|
- 新增获取最新嘟文按钮
|
@@ -17,6 +17,7 @@ export type Props = {
|
|||||||
loading?: boolean
|
loading?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
destructive?: boolean
|
destructive?: boolean
|
||||||
|
destructiveColor?: string
|
||||||
|
|
||||||
onPress: () => void
|
onPress: () => void
|
||||||
} & ({ type?: undefined; content: IconName } | { type: 'text'; content: string })
|
} & ({ type?: undefined; content: IconName } | { type: 'text'; content: string })
|
||||||
@@ -34,6 +35,7 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
loading,
|
loading,
|
||||||
disabled,
|
disabled,
|
||||||
destructive = false,
|
destructive = false,
|
||||||
|
destructiveColor,
|
||||||
onPress
|
onPress
|
||||||
}) => {
|
}) => {
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
@@ -57,7 +59,7 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
color: disabled
|
color: disabled
|
||||||
? colors.secondary
|
? colors.secondary
|
||||||
: destructive
|
: destructive
|
||||||
? colors.red
|
? destructiveColor || colors.red
|
||||||
: colors.primaryDefault,
|
: colors.primaryDefault,
|
||||||
opacity: loading ? 0 : 1
|
opacity: loading ? 0 : 1
|
||||||
}}
|
}}
|
||||||
|
@@ -36,6 +36,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
|
|||||||
adaptiveSize
|
adaptiveSize
|
||||||
numberOfLines={999}
|
numberOfLines={999}
|
||||||
color={suppressSpoiler ? colors.disabled : undefined}
|
color={suppressSpoiler ? colors.disabled : undefined}
|
||||||
|
selectable
|
||||||
/>
|
/>
|
||||||
{inThread ? (
|
{inThread ? (
|
||||||
<CustomText
|
<CustomText
|
||||||
@@ -62,6 +63,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
|
|||||||
}
|
}
|
||||||
expandHint={t('shared.content.expandHint')}
|
expandHint={t('shared.content.expandHint')}
|
||||||
setSpoilerExpanded={setSpoilerExpanded}
|
setSpoilerExpanded={setSpoilerExpanded}
|
||||||
|
selectable
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
@@ -70,6 +72,7 @@ const TimelineContent: React.FC<Props> = ({ notificationOwnToot = false, setSpoi
|
|||||||
size={highlighted ? 'L' : 'M'}
|
size={highlighted ? 'L' : 'M'}
|
||||||
adaptiveSize
|
adaptiveSize
|
||||||
numberOfLines={highlighted || inThread ? 999 : notificationOwnToot ? 2 : undefined}
|
numberOfLines={highlighted || inThread ? 999 : notificationOwnToot ? 2 : undefined}
|
||||||
|
selectable
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import Icon from '@components/Icon'
|
||||||
import ComponentSeparator from '@components/Separator'
|
import ComponentSeparator from '@components/Separator'
|
||||||
import CustomText from '@components/Text'
|
import CustomText from '@components/Text'
|
||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
@@ -10,12 +11,20 @@ import {
|
|||||||
setAccountStorage,
|
setAccountStorage,
|
||||||
useGlobalStorageListener
|
useGlobalStorageListener
|
||||||
} from '@utils/storage/actions'
|
} from '@utils/storage/actions'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { throttle } from 'lodash'
|
import { throttle } from 'lodash'
|
||||||
import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react'
|
import React, { RefObject, useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { FlatList, FlatListProps, Platform, RefreshControl } from 'react-native'
|
import {
|
||||||
|
FlatList,
|
||||||
|
FlatListProps,
|
||||||
|
Platform,
|
||||||
|
Pressable,
|
||||||
|
RefreshControl,
|
||||||
|
StyleProp,
|
||||||
|
ViewStyle
|
||||||
|
} from 'react-native'
|
||||||
import Animated, {
|
import Animated, {
|
||||||
Easing,
|
Easing,
|
||||||
runOnJS,
|
runOnJS,
|
||||||
@@ -127,6 +136,20 @@ const Timeline: React.FC<Props> = ({
|
|||||||
transform: [{ translateY: fetchedNoticeTop.value }]
|
transform: [{ translateY: fetchedNoticeTop.value }]
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
const refetchedNoticeAnimate = useAnimatedStyle(() => ({
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
translateY: withSequence(
|
||||||
|
withTiming(0),
|
||||||
|
withDelay(
|
||||||
|
3000,
|
||||||
|
withTiming(fetchedNoticeHeight.value + 32, { easing: Easing.out(Easing.ease) })
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}))
|
||||||
|
|
||||||
const scrollY = useSharedValue(0)
|
const scrollY = useSharedValue(0)
|
||||||
const fetchingType = useSharedValue<0 | 1 | 2>(0)
|
const fetchingType = useSharedValue<0 | 1 | 2>(0)
|
||||||
|
|
||||||
@@ -169,10 +192,9 @@ const Timeline: React.FC<Props> = ({
|
|||||||
throttle(() => {
|
throttle(() => {
|
||||||
if (readMarker) {
|
if (readMarker) {
|
||||||
const currentMarker = getAccountStorage.string(readMarker) || '0'
|
const currentMarker = getAccountStorage.string(readMarker) || '0'
|
||||||
|
// setAccountStorage([{ key: readMarker, value: '108425743226508521' }])
|
||||||
if (latestMarker.current > currentMarker) {
|
if (latestMarker.current > currentMarker) {
|
||||||
setAccountStorage([{ key: readMarker, value: latestMarker.current }])
|
setAccountStorage([{ key: readMarker, value: latestMarker.current }])
|
||||||
} else {
|
|
||||||
// setAccountStorage([{ key: readMarker, value: '105250709762254246' }])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 1000 * 15),
|
}, 1000 * 15),
|
||||||
@@ -242,6 +264,18 @@ const Timeline: React.FC<Props> = ({
|
|||||||
flRef.current?.scrollToOffset({ offset: 0, animated: false })
|
flRef.current?.scrollToOffset({ offset: 0, animated: false })
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const noticeDefaults: StyleProp<Animated.AnimateStyle<StyleProp<ViewStyle>>> = {
|
||||||
|
position: 'absolute',
|
||||||
|
alignSelf: 'center',
|
||||||
|
borderRadius: 99,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: colors.backgroundDefault,
|
||||||
|
shadowColor: colors.primaryDefault,
|
||||||
|
shadowOffset: { width: 0, height: 0 },
|
||||||
|
shadowOpacity: theme === 'light' ? 0.16 : 0.24
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TimelineRefresh
|
<TimelineRefresh
|
||||||
@@ -286,21 +320,14 @@ const Timeline: React.FC<Props> = ({
|
|||||||
{...customProps}
|
{...customProps}
|
||||||
/>
|
/>
|
||||||
{!disableRefresh ? (
|
{!disableRefresh ? (
|
||||||
|
<>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
position: 'absolute',
|
|
||||||
alignSelf: 'center',
|
|
||||||
top: -fetchedNoticeHeight.value - 16,
|
top: -fetchedNoticeHeight.value - 16,
|
||||||
paddingVertical: StyleConstants.Spacing.S,
|
paddingVertical: StyleConstants.Spacing.S,
|
||||||
paddingHorizontal: StyleConstants.Spacing.M,
|
paddingHorizontal: StyleConstants.Spacing.M,
|
||||||
backgroundColor: colors.backgroundDefault,
|
...noticeDefaults
|
||||||
shadowColor: colors.primaryDefault,
|
|
||||||
shadowOffset: { width: 0, height: 0 },
|
|
||||||
shadowOpacity: theme === 'light' ? 0.16 : 0.24,
|
|
||||||
borderRadius: 99,
|
|
||||||
justifyContent: 'center',
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
},
|
||||||
fetchedNoticeAnimate
|
fetchedNoticeAnimate
|
||||||
]}
|
]}
|
||||||
@@ -322,6 +349,49 @@ const Timeline: React.FC<Props> = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
|
{readMarker ? (
|
||||||
|
<Animated.View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
bottom: 16,
|
||||||
|
borderColor: colors.primaryDefault,
|
||||||
|
borderWidth: 0.5,
|
||||||
|
...noticeDefaults
|
||||||
|
},
|
||||||
|
refetchedNoticeAnimate
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Pressable
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: StyleConstants.Spacing.S,
|
||||||
|
paddingVertical: StyleConstants.Spacing.S,
|
||||||
|
paddingHorizontal: StyleConstants.Spacing.M
|
||||||
|
}}
|
||||||
|
onPress={async () => {
|
||||||
|
if (readMarker) {
|
||||||
|
setAccountStorage([{ key: readMarker, value: undefined }])
|
||||||
|
}
|
||||||
|
await refetch()
|
||||||
|
setTimeout(() => flRef.current?.scrollToOffset({ offset: 0 }), 50)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CustomText
|
||||||
|
fontStyle='M'
|
||||||
|
style={{ color: colors.primaryDefault }}
|
||||||
|
children={t('refresh.refetch')}
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
name='log-in'
|
||||||
|
color={colors.primaryDefault}
|
||||||
|
size={StyleConstants.Font.Size.M}
|
||||||
|
style={{ transform: [{ rotate: '-90deg' }] }}
|
||||||
|
/>
|
||||||
|
</Pressable>
|
||||||
|
</Animated.View>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@@ -4,6 +4,7 @@ import { useNavigation } from '@react-navigation/native'
|
|||||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
||||||
import { useQueryClient } from '@tanstack/react-query'
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
import apiInstance from '@utils/api/instance'
|
import apiInstance from '@utils/api/instance'
|
||||||
|
import { featureCheck } from '@utils/helpers/featureCheck'
|
||||||
import { checkIsMyAccount } from '@utils/helpers/isMyAccount'
|
import { checkIsMyAccount } from '@utils/helpers/isMyAccount'
|
||||||
import { TabSharedStackParamList, useNavState } from '@utils/navigation/navigators'
|
import { TabSharedStackParamList, useNavState } from '@utils/navigation/navigators'
|
||||||
import { useAccountQuery } from '@utils/queryHooks/account'
|
import { useAccountQuery } from '@utils/queryHooks/account'
|
||||||
@@ -203,13 +204,21 @@ const menuAccount = ({
|
|||||||
type: 'item',
|
type: 'item',
|
||||||
key: 'account-mute',
|
key: 'account-mute',
|
||||||
props: {
|
props: {
|
||||||
onSelect: () =>
|
onSelect: () => {
|
||||||
actualAccount &&
|
if (actualAccount) {
|
||||||
|
if (data?.muting !== true) {
|
||||||
|
if (featureCheck('mute_duration')) {
|
||||||
|
navigation.navigate('Tab-Shared-Mute', { account: actualAccount })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
timelineMutation.mutate({
|
timelineMutation.mutate({
|
||||||
type: 'updateAccountProperty',
|
type: 'updateAccountProperty',
|
||||||
id: actualAccount.id,
|
id: actualAccount.id,
|
||||||
payload: { property: 'mute', currentValue: data?.muting }
|
payload: { property: 'mute', currentValue: data?.muting }
|
||||||
}),
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
disabled: Platform.OS !== 'android' ? !data || !isFetched : false,
|
disabled: Platform.OS !== 'android' ? !data || !isFetched : false,
|
||||||
destructive: false,
|
destructive: false,
|
||||||
hidden: false
|
hidden: false
|
||||||
|
@@ -417,6 +417,20 @@
|
|||||||
"history": {
|
"history": {
|
||||||
"name": "Edit History"
|
"name": "Edit History"
|
||||||
},
|
},
|
||||||
|
"mute": {
|
||||||
|
"name": "Mute {{acct}}",
|
||||||
|
"mute": "Mute",
|
||||||
|
"description": "Hide posts from this user and posts mentioning them, but it will still allow them to see your posts and follow you.",
|
||||||
|
"notification": "Also hide notifications from this user",
|
||||||
|
"duration": {
|
||||||
|
"heading": "For duration",
|
||||||
|
"0": "Indefinitely",
|
||||||
|
"1800": "30 minutes",
|
||||||
|
"3600": "1 hour",
|
||||||
|
"86400": "1 day",
|
||||||
|
"604800": "1 week"
|
||||||
|
}
|
||||||
|
},
|
||||||
"report": {
|
"report": {
|
||||||
"name": "Report {{acct}}",
|
"name": "Report {{acct}}",
|
||||||
"report": "Report",
|
"report": "Report",
|
||||||
|
130
src/screens/Tabs/Shared/Mute.tsx
Normal file
130
src/screens/Tabs/Shared/Mute.tsx
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
import ComponentAccount from '@components/Account'
|
||||||
|
import { HeaderLeft, HeaderRight } from '@components/Header'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
|
import { displayMessage } from '@components/Message'
|
||||||
|
import { ModalScrollView } from '@components/ModalScrollView'
|
||||||
|
import Selections from '@components/Selections'
|
||||||
|
import CustomText from '@components/Text'
|
||||||
|
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
|
||||||
|
import { useTimelineMutation } from '@utils/queryHooks/timeline'
|
||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
import { Pressable, View } from 'react-native'
|
||||||
|
|
||||||
|
const TabSharedMute: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>> = ({
|
||||||
|
navigation,
|
||||||
|
route: {
|
||||||
|
params: { account }
|
||||||
|
}
|
||||||
|
}) => {
|
||||||
|
const { colors, theme } = useTheme()
|
||||||
|
const { t } = useTranslation(['common', 'screenTabs'])
|
||||||
|
|
||||||
|
const { mutateAsync, isLoading } = useTimelineMutation({
|
||||||
|
onSuccess: () =>
|
||||||
|
displayMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: t('common:message.success.message', {
|
||||||
|
function: t('componentContextMenu:account.mute.action', {
|
||||||
|
defaultValue: 'false',
|
||||||
|
context: 'false'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const [durations, setDurations] = useState<{ selected: boolean; content: string }[]>(
|
||||||
|
(['0', '1800', '3600', '86400', '604800'] as ['0', '1800', '3600', '86400', '604800']).map(
|
||||||
|
duration => ({
|
||||||
|
selected: duration === '0',
|
||||||
|
content: t(`screenTabs:shared.mute.duration.${duration}`)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
const [notification, setNotification] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
navigation.setOptions({
|
||||||
|
title: t('screenTabs:shared.mute.name', { acct: `@${account.acct}` }),
|
||||||
|
headerLeft: () => (
|
||||||
|
<HeaderLeft
|
||||||
|
type='text'
|
||||||
|
content={t('common:buttons.cancel')}
|
||||||
|
onPress={() => navigation.goBack()}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
headerRight: () => (
|
||||||
|
<HeaderRight
|
||||||
|
type='text'
|
||||||
|
content={t('screenTabs:shared.mute.mute')}
|
||||||
|
destructive
|
||||||
|
destructiveColor={colors.yellow}
|
||||||
|
onPress={async () => {
|
||||||
|
await mutateAsync({
|
||||||
|
type: 'updateAccountProperty',
|
||||||
|
id: account.id,
|
||||||
|
payload: { property: 'mute', currentValue: false }
|
||||||
|
})
|
||||||
|
navigation.pop(1)
|
||||||
|
}}
|
||||||
|
loading={isLoading}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}, [theme, isLoading, durations, notification, account.id])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalScrollView>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
margin: StyleConstants.Spacing.Global.PagePadding,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: colors.yellow,
|
||||||
|
borderRadius: StyleConstants.BorderRadius
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ComponentAccount account={account} props={{}} />
|
||||||
|
</View>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CustomText
|
||||||
|
fontStyle='M'
|
||||||
|
style={{ color: colors.primaryDefault, marginBottom: StyleConstants.Spacing.M }}
|
||||||
|
>
|
||||||
|
{t('screenTabs:shared.mute.description')}
|
||||||
|
</CustomText>
|
||||||
|
|
||||||
|
<Selections
|
||||||
|
title={t('screenTabs:shared.mute.duration.heading')}
|
||||||
|
options={durations}
|
||||||
|
setOptions={setDurations}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Pressable
|
||||||
|
style={{ flex: 1, flexDirection: 'row', marginTop: StyleConstants.Spacing.M }}
|
||||||
|
onPress={() => setNotification(!notification)}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
style={{
|
||||||
|
marginTop: (StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M) / 2,
|
||||||
|
marginRight: StyleConstants.Spacing.S
|
||||||
|
}}
|
||||||
|
name={notification ? 'check-square' : 'square'}
|
||||||
|
size={StyleConstants.Font.Size.M}
|
||||||
|
color={colors.primaryDefault}
|
||||||
|
/>
|
||||||
|
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }}>
|
||||||
|
{t('screenTabs:shared.mute.notification')}
|
||||||
|
</CustomText>
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
</ModalScrollView>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TabSharedMute
|
@@ -21,7 +21,6 @@ const TabSharedReport: React.FC<TabSharedStackScreenProps<'Tab-Shared-Report'>>
|
|||||||
params: { account, status }
|
params: { account, status }
|
||||||
}
|
}
|
||||||
}) => {
|
}) => {
|
||||||
console.log('account', account.id)
|
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { t } = useTranslation(['common', 'screenTabs'])
|
const { t } = useTranslation(['common', 'screenTabs'])
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ import TabSharedToot from '@screens/Tabs/Shared/Toot'
|
|||||||
import TabSharedUsers from '@screens/Tabs/Shared/Users'
|
import TabSharedUsers from '@screens/Tabs/Shared/Users'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import TabSharedFilter from './Filter'
|
import TabSharedFilter from './Filter'
|
||||||
|
import TabSharedMute from './Mute'
|
||||||
|
|
||||||
const TabShared = ({ Stack }: { Stack: any }) => {
|
const TabShared = ({ Stack }: { Stack: any }) => {
|
||||||
return (
|
return (
|
||||||
@@ -44,6 +45,12 @@ const TabShared = ({ Stack }: { Stack: any }) => {
|
|||||||
name='Tab-Shared-History'
|
name='Tab-Shared-History'
|
||||||
component={TabSharedHistory}
|
component={TabSharedHistory}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
key='Tab-Shared-Mute'
|
||||||
|
name='Tab-Shared-Mute'
|
||||||
|
component={TabSharedMute}
|
||||||
|
options={{ presentation: 'modal' }}
|
||||||
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
key='Tab-Shared-Report'
|
key='Tab-Shared-Report'
|
||||||
name='Tab-Shared-Report'
|
name='Tab-Shared-Report'
|
||||||
|
@@ -4,6 +4,7 @@ type Features =
|
|||||||
| 'account_follow_notify'
|
| 'account_follow_notify'
|
||||||
| 'notification_type_status'
|
| 'notification_type_status'
|
||||||
| 'account_return_suspended'
|
| 'account_return_suspended'
|
||||||
|
| 'mute_duration'
|
||||||
| 'edit_post'
|
| 'edit_post'
|
||||||
| 'deprecate_auth_follow'
|
| 'deprecate_auth_follow'
|
||||||
| 'notification_type_update'
|
| 'notification_type_update'
|
||||||
@@ -20,6 +21,7 @@ const features: { feature: Features; version: number }[] = [
|
|||||||
{ feature: 'account_follow_notify', version: 3.3 },
|
{ feature: 'account_follow_notify', version: 3.3 },
|
||||||
{ feature: 'notification_type_status', version: 3.3 },
|
{ feature: 'notification_type_status', version: 3.3 },
|
||||||
{ feature: 'account_return_suspended', version: 3.3 },
|
{ feature: 'account_return_suspended', version: 3.3 },
|
||||||
|
{ feature: 'mute_duration', version: 3.3 },
|
||||||
{ feature: 'edit_post', version: 3.5 },
|
{ feature: 'edit_post', version: 3.5 },
|
||||||
{ feature: 'deprecate_auth_follow', version: 3.5 },
|
{ feature: 'deprecate_auth_follow', version: 3.5 },
|
||||||
{ feature: 'notification_type_update', version: 3.5 },
|
{ feature: 'notification_type_update', version: 3.5 },
|
||||||
|
@@ -104,6 +104,9 @@ export type TabSharedStackParamList = {
|
|||||||
| { source: 'hashtag'; tag_name: Mastodon.Tag['name'] }
|
| { source: 'hashtag'; tag_name: Mastodon.Tag['name'] }
|
||||||
'Tab-Shared-Hashtag': { tag_name: Mastodon.Tag['name']; queryKey?: QueryKeyTimeline }
|
'Tab-Shared-Hashtag': { tag_name: Mastodon.Tag['name']; queryKey?: QueryKeyTimeline }
|
||||||
'Tab-Shared-History': { status: Mastodon.Status; detectedLanguage: string }
|
'Tab-Shared-History': { status: Mastodon.Status; detectedLanguage: string }
|
||||||
|
'Tab-Shared-Mute': {
|
||||||
|
account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'>
|
||||||
|
}
|
||||||
'Tab-Shared-Report': {
|
'Tab-Shared-Report': {
|
||||||
account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'>
|
account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'>
|
||||||
status?: Pick<Mastodon.Status, 'id' | '_remote' | 'uri'>
|
status?: Pick<Mastodon.Status, 'id' | '_remote' | 'uri'>
|
||||||
|
Reference in New Issue
Block a user