Merge pull request #510 from tooot-app/main

Fixes
This commit is contained in:
xmflsct 2022-12-04 20:10:00 +01:00 committed by GitHub
commit 8da6be7b60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 202 additions and 241 deletions

View File

@ -126,7 +126,7 @@ const renderNode = ({
}
}}
>
{(content && content !== href && content) || (showFullLink ? href : domain[1])}
{content && content !== href ? content : showFullLink ? href : domain?.[1]}
{!shouldBeTag ? (
<Icon
color={colors.blue}

View File

@ -53,10 +53,10 @@ const TimelineDefault: React.FC<Props> = ({
const status = item.reblog ? item.reblog : item
const ownAccount = status.account?.id === instanceAccount?.id
const [spoilerExpanded, setSpoilerExpanded] = useState(
instanceAccount.preferences['reading:expand:spoilers'] || false
instanceAccount?.preferences['reading:expand:spoilers'] || false
)
const spoilerHidden = status.spoiler_text?.length
? !instanceAccount.preferences['reading:expand:spoilers'] && !spoilerExpanded
? !instanceAccount?.preferences['reading:expand:spoilers'] && !spoilerExpanded
: false
const copiableContent = useRef<{ content: string; complete: boolean }>({
content: '',

View File

@ -28,9 +28,7 @@ const AttachmentAltText: React.FC<Props> = ({ sensitiveShown, text }) => {
type='text'
content='ALT'
fontBold
onPress={() => {
navigation.navigate('Screen-Actions', { type: 'alt_text', text })
}}
onPress={() => navigation.navigate('Screen-Actions', { type: 'alt_text', text })}
/>
) : null
}

View File

@ -1,8 +1,8 @@
import Button from '@components/Button'
import { StyleConstants } from '@utils/styles/constants'
import { ResizeMode, Video, VideoFullscreenUpdate } from 'expo-av'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { AppState, AppStateStatus, Pressable, View } from 'react-native'
import React, { useRef, useState } from 'react'
import { Pressable, View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import attachmentAspectRatio from './aspectRatio'
import AttachmentAltText from './AltText'
@ -27,46 +27,19 @@ const AttachmentVideo: React.FC<Props> = ({
const [videoLoading, setVideoLoading] = useState(false)
const [videoLoaded, setVideoLoaded] = useState(false)
const [videoResizeMode, setVideoResizeMode] = useState<ResizeMode>(ResizeMode.COVER)
const playOnPress = useCallback(async () => {
const playOnPress = async () => {
setVideoLoading(true)
if (!videoLoaded) {
await videoPlayer.current?.loadAsync({ uri: video.url })
}
setVideoLoading(false)
Platform.OS === 'android' && setVideoResizeMode(ResizeMode.CONTAIN)
await videoPlayer.current?.presentFullscreenPlayer()
videoPlayer.current?.playAsync()
setVideoLoading(false)
videoPlayer.current?.setOnPlaybackStatusUpdate(props => {
if (props.isLoaded) {
setVideoLoaded(true)
}
})
}, [videoLoaded])
const appState = useRef(AppState.currentState)
useEffect(() => {
const appState = AppState.addEventListener('change', _handleAppStateChange)
return () => appState.remove()
}, [])
const _handleAppStateChange = async (nextAppState: AppStateStatus) => {
if (appState.current.match(/active/) && nextAppState.match(/inactive/)) {
// await videoPlayer.current?.stopAsync()
} else if (gifv && appState.current.match(/background/) && nextAppState.match(/active/)) {
await videoPlayer.current?.setIsMutedAsync(true)
await videoPlayer.current?.playAsync()
}
appState.current = nextAppState
}
const playerStatus = useRef<any>(null)
useEffect(() => {
videoPlayer.current?.setOnPlaybackStatusUpdate(playbackStatus => {
playerStatus.current = playbackStatus
})
}, [])
return (
<View
style={{
@ -79,11 +52,7 @@ const AttachmentVideo: React.FC<Props> = ({
<Video
accessibilityLabel={video.description}
ref={videoPlayer}
style={{
width: '100%',
height: '100%',
opacity: sensitiveShown ? 0 : 1
}}
style={{ width: '100%', height: '100%', opacity: sensitiveShown ? 0 : 1 }}
usePoster
resizeMode={videoResizeMode}
{...(gifv
@ -98,11 +67,22 @@ const AttachmentVideo: React.FC<Props> = ({
posterStyle: { resizeMode: ResizeMode.COVER }
})}
useNativeControls={false}
onFullscreenUpdate={async event => {
onFullscreenUpdate={event => {
if (event.fullscreenUpdate === VideoFullscreenUpdate.PLAYER_DID_DISMISS) {
Platform.OS === 'android' && setVideoResizeMode(ResizeMode.COVER)
if (!gifv) {
await videoPlayer.current?.stopAsync()
videoPlayer.current?.pauseAsync()
} else {
videoPlayer.current?.playAsync()
}
}
}}
onPlaybackStatusUpdate={event => {
if (event.isLoaded) {
!videoLoaded && setVideoLoaded(true)
if (event.didJustFinish) {
videoPlayer.current?.setPositionAsync(0)
}
}
}}
@ -116,19 +96,14 @@ const AttachmentVideo: React.FC<Props> = ({
justifyContent: 'center',
alignItems: 'center'
}}
disabled={gifv ? (sensitiveShown ? true : false) : true}
onPress={gifv ? playOnPress : null}
>
{sensitiveShown ? (
video.blurhash ? (
<Blurhash
blurhash={video.blurhash}
style={{
width: '100%',
height: '100%'
}}
/>
<Blurhash blurhash={video.blurhash} style={{ width: '100%', height: '100%' }} />
) : null
) : !gifv || (gifv && playerStatus.current === false) ? (
) : !gifv ? (
<Button
round
overlay

View File

@ -20,23 +20,19 @@ const HeaderSharedAccount = React.memo(
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
{withoutName ? null : (
<CustomText
accessibilityHint={t(
'shared.header.shared.account.name.accessibilityHint'
)}
accessibilityHint={t('shared.header.shared.account.name.accessibilityHint')}
style={{ marginRight: StyleConstants.Spacing.XS }}
numberOfLines={1}
>
<ParseEmojis
content={account?.display_name || account?.username}
emojis={account.emojis}
emojis={account?.emojis}
fontBold
/>
</CustomText>
)}
<CustomText
accessibilityHint={t(
'shared.header.shared.account.account.accessibilityHint'
)}
accessibilityHint={t('shared.header.shared.account.account.accessibilityHint')}
style={{ flexShrink: 1, color: colors.secondary }}
numberOfLines={1}
>

View File

@ -20,8 +20,8 @@
}
},
"at": {
"direct": "",
"public": ""
"direct": "Direktnachricht",
"public": "Öffentliche Nachricht"
},
"copy": {
"action": "Tröt kopieren",

View File

@ -329,8 +329,8 @@
"name": "<0 /><1>的媒體</1>"
},
"hashtag": {
"follow": "追蹤",
"unfollow": "取消追蹤"
"follow": "跟隨",
"unfollow": "取消跟隨"
},
"history": {
"name": "編輯歷史"

View File

@ -26,10 +26,10 @@ export const uploadAttachment = async ({
}) => {
const hash = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
media.uri + Math.random()
media.uri + Math.random().toString()
)
switch (media.type.split('/')[0]) {
switch (media.type?.split('/')[0] || '') {
case 'image':
composeDispatch({
type: 'attachment/upload/start',
@ -77,15 +77,11 @@ export const uploadAttachment = async ({
payload: hash
})
Alert.alert(
i18next.t(
'screenCompose:content.root.actions.attachment.failed.alert.title'
),
i18next.t('screenCompose:content.root.actions.attachment.failed.alert.title'),
message,
[
{
text: i18next.t(
'screenCompose:content.root.actions.attachment.failed.alert.button'
),
text: i18next.t('screenCompose:content.root.actions.attachment.failed.alert.button'),
onPress: () => {}
}
]
@ -117,9 +113,7 @@ export const uploadAttachment = async ({
})
.catch((err: any) => {
uploadFailed(
err?.message && typeof err?.message === 'string'
? err?.message.slice(0, 50)
: undefined
err?.message && typeof err?.message === 'string' ? err?.message.slice(0, 50) : undefined
)
})
}

View File

@ -37,25 +37,16 @@ const composePost = async (
formData.append('poll[multiple]', composeState.poll.multiple.toString())
}
if (
composeState.attachments.uploads.filter(
upload => upload.remote && upload.remote.id
).length
) {
if (composeState.attachments.uploads.filter(upload => upload.remote && upload.remote.id).length) {
formData.append('sensitive', composeState.attachments.sensitive.toString())
composeState.attachments.uploads.forEach(e =>
formData.append('media_ids[]', e.remote!.id!)
)
composeState.attachments.uploads.forEach(e => formData.append('media_ids[]', e.remote!.id!))
}
formData.append('visibility', composeState.visibility)
return apiInstance<Mastodon.Status>({
method: params?.type === 'edit' ? 'put' : 'post',
url:
params?.type === 'edit'
? `statuses/${params.incomingStatus.id}`
: 'statuses',
url: params?.type === 'edit' ? `statuses/${params.incomingStatus.id}` : 'statuses',
headers: {
'Idempotency-Key': await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
@ -70,9 +61,7 @@ const composePost = async (
composeState.attachments.sensitive +
composeState.attachments.uploads.map(upload => upload.remote?.id) +
composeState.visibility +
(params?.type === 'edit' || params?.type === 'deleteEdit'
? Math.random()
: '')
(params?.type === 'edit' || params?.type === 'deleteEdit' ? Math.random().toString() : '')
)
},
body: formData

View File

@ -86,12 +86,7 @@ const TabLocal = React.memo(
accessibilityLabel={t('common.search.accessibilityLabel')}
accessibilityHint={t('common.search.accessibilityHint')}
content='Search'
onPress={() =>
navigation.navigate('Tab-Local', {
screen: 'Tab-Shared-Search',
params: { text: undefined }
})
}
onPress={() => navigation.navigate('Tab-Local', { screen: 'Tab-Shared-Search' })}
/>
)
}}

View File

@ -3,10 +3,7 @@ import { useNavigation } from '@react-navigation/native'
import { useAppDispatch } from '@root/store'
import { useAnnouncementQuery } from '@utils/queryHooks/announcement'
import { useListsQuery } from '@utils/queryHooks/lists'
import {
getInstanceMePage,
updateInstanceMePage
} from '@utils/slices/instancesSlice'
import { getInstanceMePage, updateInstanceMePage } from '@utils/slices/instancesSlice'
import { getInstancePush } from '@utils/slices/instancesSlice'
import React, { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
@ -41,19 +38,17 @@ const Collections: React.FC = () => {
}
})
useEffect(() => {
if (announcementsQuery.isSuccess) {
if (announcementsQuery.data) {
dispatch(
updateInstanceMePage({
announcements: {
shown: announcementsQuery.data?.length ? true : false,
unread: announcementsQuery.data?.filter(
announcement => !announcement.read
).length
shown: announcementsQuery.data.length ? true : false,
unread: announcementsQuery.data.filter(announcement => !announcement.read).length
}
})
)
}
}, [announcementsQuery.isSuccess, announcementsQuery.data?.length])
}, [announcementsQuery.data])
const instancePush = useSelector(
getInstancePush,
@ -100,9 +95,7 @@ const Collections: React.FC = () => {
})
: t('me.root.announcements.content.read')
}
onPress={() =>
navigation.navigate('Screen-Announcements', { showAll: true })
}
onPress={() => navigation.navigate('Screen-Announcements', { showAll: true })}
/>
) : null}
<MenuRow

View File

@ -50,12 +50,7 @@ const TabPublic = React.memo(
accessibilityLabel={t('common.search.accessibilityLabel')}
accessibilityHint={t('common.search.accessibilityHint')}
content='Search'
onPress={() =>
navigation.navigate('Tab-Public', {
screen: 'Tab-Shared-Search',
params: { text: undefined }
})
}
onPress={() => navigation.navigate('Tab-Public', { screen: 'Tab-Shared-Search' })}
/>
)
}),

View File

@ -81,7 +81,7 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
)
}
})
}, [])
}, [mAccount])
const { data } = useAccountQuery({ id: account.id })

View File

@ -48,8 +48,8 @@ const TabSharedAccountInLists: React.FC<
id: 'out',
title: t('shared.accountInLists.notInLists'),
data:
listsQuery?.data?.filter(
({ id }) => !accountInListsQuery?.data?.filter(d => d.id === id)?.length
listsQuery.data?.filter(
({ id }) => accountInListsQuery.data?.filter(d => d.id !== id).length
) || []
}
]

View File

@ -0,0 +1,114 @@
import ComponentHashtag from '@components/Hashtag'
import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
import { useTrendsQuery } from '@utils/queryHooks/trends'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { StyleSheet, TextInput, View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
export interface Props {
isLoading: boolean
inputRef: React.RefObject<TextInput>
setSearchTerm: React.Dispatch<React.SetStateAction<string>>
}
const SearchEmpty: React.FC<Props> = ({ isLoading, inputRef, setSearchTerm }) => {
const { colors } = useTheme()
const { t } = useTranslation('screenTabs')
const trendsTags = useTrendsQuery({ type: 'tags' })
return (
<View style={{ paddingVertical: StyleConstants.Spacing.Global.PagePadding }}>
{isLoading ? (
<View style={{ flex: 1, alignItems: 'center' }}>
<Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
</View>
) : (
<>
<View style={{ paddingHorizontal: StyleConstants.Spacing.Global.PagePadding }}>
<CustomText
fontStyle='S'
style={{
marginBottom: StyleConstants.Spacing.L,
color: colors.primaryDefault
}}
>
<Trans
i18nKey='screenTabs:shared.search.empty.general'
components={{
bold: <CustomText fontWeight='Bold' />
}}
/>
</CustomText>
<CustomText
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
fontWeight='Bold'
>
{t('shared.search.empty.advanced.header')}
</CustomText>
<CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
<CustomText style={{ color: colors.secondary }}>@username@domain</CustomText>
{' '}
{t('shared.search.empty.advanced.example.account')}
</CustomText>
<CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
<CustomText style={{ color: colors.secondary }}>#example</CustomText>
{' '}
{t('shared.search.empty.advanced.example.hashtag')}
</CustomText>
<CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
<CustomText style={{ color: colors.secondary }}>URL</CustomText>
{' '}
{t('shared.search.empty.advanced.example.statusLink')}
</CustomText>
<CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
<CustomText style={{ color: colors.secondary }}>URL</CustomText>
{' '}
{t('shared.search.empty.advanced.example.accountLink')}
</CustomText>
</View>
<CustomText
style={{
color: colors.primaryDefault,
marginTop: StyleConstants.Spacing.M,
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding
}}
fontWeight='Bold'
>
{t('shared.search.empty.trending.tags')}
</CustomText>
<View>
{trendsTags.data?.map((tag, index) => {
const hashtag = tag as Mastodon.Tag
return (
<React.Fragment key={index}>
{index !== 0 ? <ComponentSeparator /> : null}
<ComponentHashtag
hashtag={hashtag}
onPress={() => {
inputRef.current?.setNativeProps({ text: `#${hashtag.name}` })
setSearchTerm(`#${hashtag.name}`)
}}
/>
</React.Fragment>
)
})}
</View>
</>
)}
</View>
)
}
const styles = StyleSheet.create({
emptyAdvanced: {
marginBottom: StyleConstants.Spacing.S
}
})
export default SearchEmpty

View File

@ -6,31 +6,22 @@ import CustomText from '@components/Text'
import TimelineDefault from '@components/Timeline/Default'
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
import { useSearchQuery } from '@utils/queryHooks/search'
import { useTrendsQuery } from '@utils/queryHooks/trends'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import { debounce } from 'lodash'
import React, { useEffect } from 'react'
import React, { useEffect, useRef, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import {
KeyboardAvoidingView,
Platform,
SectionList,
StyleSheet,
TextInput,
View
} from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
import { KeyboardAvoidingView, Platform, SectionList, TextInput, View } from 'react-native'
import SearchEmpty from './Empty'
const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>> = ({
navigation,
route: {
params: { text }
}
navigation
}) => {
const { t } = useTranslation('screenTabs')
const { colors, mode } = useTheme()
const inputRef = useRef<TextInput>(null)
const [searchTerm, setSearchTerm] = useState<string>('')
useEffect(() => {
navigation.setOptions({
...(Platform.OS === 'ios'
@ -56,6 +47,7 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
defaultValue={t('shared.search.header.prefix')}
/>
<TextInput
ref={inputRef}
accessibilityRole='search'
keyboardAppearance={mode}
style={{
@ -65,15 +57,18 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
paddingLeft: StyleConstants.Spacing.XS
}}
autoFocus
value={text}
onChangeText={debounce((text: string) => navigation.setParams({ text }), 1000, {
trailing: true
})}
onChangeText={debounce(
text => {
setSearchTerm(text)
refetch()
},
1000,
{ trailing: true }
)}
autoCapitalize='none'
autoCorrect={false}
clearButtonMode='always'
keyboardType='web-search'
onSubmitEditing={({ nativeEvent: { text } }) => navigation.setParams({ text })}
placeholder={t('shared.search.header.placeholder')}
placeholderTextColor={colors.secondary}
returnKeyType='search'
@ -82,25 +77,23 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
)
}
})
}, [text, mode])
const trendsTags = useTrendsQuery({ type: 'tags' })
}, [mode])
const mapKeyToTranslations = {
accounts: t('shared.search.sections.accounts'),
hashtags: t('shared.search.sections.hashtags'),
statuses: t('shared.search.sections.statuses')
}
const { status, data } = useSearchQuery<
const { isLoading, data, refetch } = useSearchQuery<
{
title: string
translation: string
data: any[]
}[]
>({
term: text,
term: searchTerm,
options: {
enabled: text !== undefined,
enabled: !!searchTerm.length,
select: data =>
Object.keys(data as Mastodon.Results)
.map(key => ({
@ -110,6 +103,7 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
// @ts-ignore
data: data[key]
}))
.filter(d => d.data.length)
.sort((a, b) => {
if (!a.data.length) {
return 1
@ -122,88 +116,6 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
}
})
const listEmpty = () => {
return (
<View style={{ paddingVertical: StyleConstants.Spacing.Global.PagePadding }}>
{status === 'loading' ? (
<View style={{ flex: 1, alignItems: 'center' }}>
<Circle size={StyleConstants.Font.Size.M * 1.25} color={colors.secondary} />
</View>
) : (
<>
<View style={{ paddingHorizontal: StyleConstants.Spacing.Global.PagePadding }}>
<CustomText
fontStyle='S'
style={{
marginBottom: StyleConstants.Spacing.L,
color: colors.primaryDefault
}}
>
<Trans
i18nKey='screenTabs:shared.search.empty.general'
components={{
bold: <CustomText fontWeight='Bold' />
}}
/>
</CustomText>
<CustomText
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
fontWeight='Bold'
>
{t('shared.search.empty.advanced.header')}
</CustomText>
<CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
<CustomText style={{ color: colors.secondary }}>@username@domain</CustomText>
{' '}
{t('shared.search.empty.advanced.example.account')}
</CustomText>
<CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
<CustomText style={{ color: colors.secondary }}>#example</CustomText>
{' '}
{t('shared.search.empty.advanced.example.hashtag')}
</CustomText>
<CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
<CustomText style={{ color: colors.secondary }}>URL</CustomText>
{' '}
{t('shared.search.empty.advanced.example.statusLink')}
</CustomText>
<CustomText style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}>
<CustomText style={{ color: colors.secondary }}>URL</CustomText>
{' '}
{t('shared.search.empty.advanced.example.accountLink')}
</CustomText>
</View>
<CustomText
style={{
color: colors.primaryDefault,
marginTop: StyleConstants.Spacing.M,
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding
}}
fontWeight='Bold'
>
{t('shared.search.empty.trending.tags')}
</CustomText>
<View>
{trendsTags.data?.map((tag, index) => {
const hashtag = tag as Mastodon.Tag
return (
<React.Fragment key={index}>
{index !== 0 ? <ComponentSeparator /> : null}
<ComponentHashtag
hashtag={hashtag}
onPress={() => navigation.setParams({ text: `#${hashtag.name}` })}
/>
</React.Fragment>
)
})}
</View>
</>
)}
</View>
)
}
return (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
@ -211,6 +123,7 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
>
<SectionList
style={{ minHeight: '100%' }}
sections={data || []}
renderItem={({ item, section }: { item: any; section: any }) => {
switch (section.title) {
case 'accounts':
@ -224,8 +137,9 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
}
}}
stickySectionHeadersEnabled
sections={data || []}
ListEmptyComponent={listEmpty()}
ListEmptyComponent={
<SearchEmpty isLoading={isLoading} inputRef={inputRef} setSearchTerm={setSearchTerm} />
}
keyboardShouldPersistTaps='always'
renderSectionHeader={({ section: { translation } }) => (
<View
@ -257,7 +171,7 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
<CustomText fontStyle='S' style={{ textAlign: 'center', color: colors.secondary }}>
<Trans
i18nKey='screenTabs:shared.search.notFound'
values={{ searchTerm: text, type: translation }}
values={{ searchTerm, type: translation }}
components={{
bold: <CustomText fontWeight='Bold' />
}}
@ -274,10 +188,4 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
)
}
const styles = StyleSheet.create({
emptyAdvanced: {
marginBottom: StyleConstants.Spacing.S
}
})
export default TabSharedSearch

View File

@ -51,6 +51,8 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
scrolled.current = true
const pointer = flattenData.findIndex(({ id }) => id === toot.id)
if (pointer < 1) return
const length = flRef.current?.props.data?.length
if (!length) return
try {
setTimeout(() => {
try {

View File

@ -4,7 +4,7 @@ import log from './log'
const audio = () => {
log('log', 'audio', 'setting audio playback default options')
Audio.setAudioModeAsync({
interruptionModeIOS: InterruptionModeIOS.MixWithOthers,
interruptionModeIOS: InterruptionModeIOS.DuckOthers,
interruptionModeAndroid: InterruptionModeAndroid.DuckOthers,
playsInSilentModeIOS: true,
staysActiveInBackground: false

View File

@ -104,7 +104,7 @@ export type TabSharedStackParamList = {
'Tab-Shared-History': {
id: Mastodon.Status['id']
}
'Tab-Shared-Search': { text: string | undefined }
'Tab-Shared-Search': undefined
'Tab-Shared-Toot': {
toot: Mastodon.Status
rootQueryKey?: QueryKeyTimeline

View File

@ -27,7 +27,9 @@ const useAccountQuery = ({
export type QueryKeyAccountInLists = ['AccountInLists', { id: Mastodon.Account['id'] }]
const accountInListsQueryFunction = ({ queryKey }: QueryFunctionContext<QueryKeyAccount>) => {
const accountInListsQueryFunction = ({
queryKey
}: QueryFunctionContext<QueryKeyAccountInLists>) => {
const { id } = queryKey[1]
return apiInstance<Mastodon.List[]>({
@ -42,7 +44,7 @@ const useAccountInListsQuery = ({
}: QueryKeyAccount[1] & {
options?: UseQueryOptions<Mastodon.List[], AxiosError>
}) => {
const queryKey: QueryKeyAccount = ['Account', { ...queryKeyParams }]
const queryKey: QueryKeyAccountInLists = ['AccountInLists', { ...queryKeyParams }]
return useQuery(queryKey, accountInListsQueryFunction, options)
}

View File

@ -287,7 +287,7 @@ const instancesSlice = createSlice({
const activeIndex = findInstanceActive(state.instances)
state.instances[activeIndex].frequentEmojis = state.instances[
activeIndex
].frequentEmojis?.filter(emoji => {
]?.frequentEmojis?.filter(emoji => {
return action.payload?.find(
e => e.shortcode === emoji.emoji.shortcode && e.url === emoji.emoji.url
)