2021-08-21 01:45:43 +02:00
|
|
|
import { HeaderLeft } from '@components/Header'
|
2022-02-01 22:28:12 +01:00
|
|
|
import { displayMessage, Message } from '@components/Message'
|
2021-05-12 15:40:55 +02:00
|
|
|
import { NavigationContainer } from '@react-navigation/native'
|
2021-08-21 01:45:43 +02:00
|
|
|
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
2022-08-12 16:44:28 +02:00
|
|
|
import ScreenAccountSelection from '@screens/AccountSelection'
|
2021-01-30 01:29:15 +01:00
|
|
|
import ScreenAnnouncements from '@screens/Announcements'
|
|
|
|
import ScreenCompose from '@screens/Compose'
|
2022-12-28 23:41:36 +01:00
|
|
|
import ScreenImagesViewer from '@screens/ImageViewer'
|
2021-01-30 01:29:15 +01:00
|
|
|
import ScreenTabs from '@screens/Tabs'
|
2023-03-12 18:09:33 +01:00
|
|
|
import { useLinking } from '@utils/linking'
|
2022-12-28 23:41:36 +01:00
|
|
|
import navigationRef from '@utils/navigation/navigationRef'
|
2021-08-29 15:25:38 +02:00
|
|
|
import { RootStackParamList } from '@utils/navigation/navigators'
|
2021-03-04 01:03:53 +01:00
|
|
|
import pushUseConnect from '@utils/push/useConnect'
|
|
|
|
import pushUseReceive from '@utils/push/useReceive'
|
|
|
|
import pushUseRespond from '@utils/push/useRespond'
|
2022-12-28 23:41:36 +01:00
|
|
|
import { useEmojisQuery } from '@utils/queryHooks/emojis'
|
|
|
|
import { useFiltersQuery } from '@utils/queryHooks/filters'
|
|
|
|
import { useInstanceQuery } from '@utils/queryHooks/instance'
|
|
|
|
import { usePreferencesQuery } from '@utils/queryHooks/preferences'
|
|
|
|
import { useProfileQuery } from '@utils/queryHooks/profile'
|
2022-12-29 00:58:07 +01:00
|
|
|
import { useFollowedTagsQuery } from '@utils/queryHooks/tags'
|
2022-12-28 23:41:36 +01:00
|
|
|
import { setAccount, setGlobalStorage, useGlobalStorage } from '@utils/storage/actions'
|
2021-01-30 01:29:15 +01:00
|
|
|
import { useTheme } from '@utils/styles/ThemeManager'
|
|
|
|
import { themes } from '@utils/styles/themes'
|
2022-01-29 16:37:58 +01:00
|
|
|
import * as Linking from 'expo-linking'
|
2021-02-27 16:33:54 +01:00
|
|
|
import { addScreenshotListener } from 'expo-screen-capture'
|
2022-12-29 00:36:35 +01:00
|
|
|
import React, { useEffect, useState } from 'react'
|
2021-01-30 01:29:15 +01:00
|
|
|
import { useTranslation } from 'react-i18next'
|
2022-12-28 23:41:36 +01:00
|
|
|
import { IntlProvider } from 'react-intl'
|
2021-02-28 17:41:21 +01:00
|
|
|
import { Alert, Platform, StatusBar } from 'react-native'
|
2022-05-02 22:31:22 +02:00
|
|
|
import ShareMenu from 'react-native-share-menu'
|
2021-01-30 01:29:15 +01:00
|
|
|
|
2021-08-29 15:25:38 +02:00
|
|
|
const Stack = createNativeStackNavigator<RootStackParamList>()
|
2021-01-30 01:29:15 +01:00
|
|
|
|
2023-01-16 22:11:41 +01:00
|
|
|
const Screens: React.FC = () => {
|
2022-12-28 23:41:36 +01:00
|
|
|
const { t, i18n } = useTranslation([
|
2022-12-23 15:53:40 +01:00
|
|
|
'common',
|
|
|
|
'screens',
|
|
|
|
'screenAnnouncements',
|
|
|
|
'screenAccountSelection'
|
|
|
|
])
|
2022-12-28 23:41:36 +01:00
|
|
|
|
|
|
|
const [accounts] = useGlobalStorage.object('accounts')
|
|
|
|
const [accountActive] = useGlobalStorage.string('account.active')
|
2022-02-17 00:09:19 +01:00
|
|
|
const { colors, theme } = useTheme()
|
2021-01-30 01:29:15 +01:00
|
|
|
|
2021-03-04 01:03:53 +01:00
|
|
|
// Push hooks
|
2022-11-23 21:31:58 +01:00
|
|
|
pushUseConnect()
|
|
|
|
pushUseReceive()
|
|
|
|
pushUseRespond()
|
2021-02-28 17:41:21 +01:00
|
|
|
|
2021-02-05 01:13:57 +01:00
|
|
|
// Prevent screenshot alert
|
2021-02-27 16:33:54 +01:00
|
|
|
useEffect(() => {
|
|
|
|
const screenshotListener = addScreenshotListener(() =>
|
2022-12-23 15:53:40 +01:00
|
|
|
Alert.alert(t('screens:screenshot.title'), t('screens:screenshot.message'), [
|
2022-12-19 23:06:39 +01:00
|
|
|
{ text: t('common:buttons.confirm'), style: 'destructive' }
|
2021-02-27 16:33:54 +01:00
|
|
|
])
|
|
|
|
)
|
|
|
|
Platform.select({ ios: screenshotListener })
|
|
|
|
return () => screenshotListener.remove()
|
|
|
|
}, [])
|
2021-02-05 01:13:57 +01:00
|
|
|
|
2021-01-30 01:29:15 +01:00
|
|
|
// Lazily update users's preferences, for e.g. composing default visibility
|
2022-12-28 23:41:36 +01:00
|
|
|
useInstanceQuery({ options: { enabled: !!accountActive } })
|
|
|
|
useProfileQuery({ options: { enabled: !!accountActive } })
|
|
|
|
usePreferencesQuery({ options: { enabled: !!accountActive } })
|
|
|
|
useFiltersQuery({ options: { enabled: !!accountActive } })
|
|
|
|
useEmojisQuery({ options: { enabled: !!accountActive } })
|
2022-12-29 00:58:07 +01:00
|
|
|
useFollowedTagsQuery({ options: { enabled: !!accountActive } })
|
2021-01-30 01:29:15 +01:00
|
|
|
|
|
|
|
// Callbacks
|
2022-12-29 00:36:35 +01:00
|
|
|
const navigationContainerOnStateChange = () => {
|
2021-08-29 15:25:38 +02:00
|
|
|
const currentRoute = navigationRef.getCurrentRoute()
|
2021-01-30 01:29:15 +01:00
|
|
|
|
2021-03-21 13:15:43 +01:00
|
|
|
const matchTabName = currentRoute?.name?.match(/(Tab-.*)-Root/)
|
2022-12-28 23:41:36 +01:00
|
|
|
if (matchTabName?.[1]) {
|
|
|
|
// @ts-ignore
|
|
|
|
setGlobalStorage('app.prev_tab', matchTabName[1])
|
2021-02-11 23:42:13 +01:00
|
|
|
}
|
2022-12-29 00:36:35 +01:00
|
|
|
}
|
2021-01-30 01:29:15 +01:00
|
|
|
|
2023-03-12 18:09:33 +01:00
|
|
|
// Deep linking
|
|
|
|
useLinking()
|
2022-01-29 16:37:58 +01:00
|
|
|
|
2022-05-02 22:31:22 +02:00
|
|
|
// Share Extension
|
2022-12-29 00:36:35 +01:00
|
|
|
const handleShare = (
|
|
|
|
item?:
|
|
|
|
| {
|
|
|
|
data: { mimeType: string; data: string }[]
|
|
|
|
mimeType: undefined
|
|
|
|
}
|
|
|
|
| { data: string | string[]; mimeType: string }
|
|
|
|
) => {
|
|
|
|
if (!accountActive) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (!item || !item.data) {
|
|
|
|
return
|
|
|
|
}
|
2022-05-02 22:31:22 +02:00
|
|
|
|
2022-12-29 00:36:35 +01:00
|
|
|
let text: string | undefined = undefined
|
|
|
|
let media: { uri: string; mime: string }[] = []
|
2022-06-05 17:58:18 +02:00
|
|
|
|
2022-12-29 00:36:35 +01:00
|
|
|
const typesImage = ['png', 'jpg', 'jpeg', 'gif']
|
|
|
|
const typesVideo = ['mp4', 'm4v', 'mov', 'webm', 'mpeg']
|
|
|
|
const filterMedia = ({ uri, mime }: { uri: string; mime: string }) => {
|
|
|
|
if (mime.startsWith('image/')) {
|
|
|
|
if (!typesImage.includes(mime.split('/')[1])) {
|
|
|
|
console.warn('Image type not supported:', mime.split('/')[1])
|
|
|
|
displayMessage({
|
|
|
|
message: t('screens:shareError.imageNotSupported', {
|
|
|
|
type: mime.split('/')[1]
|
|
|
|
}),
|
|
|
|
type: 'danger'
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
media.push({ uri, mime })
|
|
|
|
} else if (mime.startsWith('video/')) {
|
|
|
|
if (!typesVideo.includes(mime.split('/')[1])) {
|
|
|
|
console.warn('Video type not supported:', mime.split('/')[1])
|
|
|
|
displayMessage({
|
|
|
|
message: t('screens:shareError.videoNotSupported', {
|
|
|
|
type: mime.split('/')[1]
|
|
|
|
}),
|
|
|
|
type: 'danger'
|
|
|
|
})
|
|
|
|
return
|
2022-06-05 17:58:18 +02:00
|
|
|
}
|
2022-12-29 00:36:35 +01:00
|
|
|
media.push({ uri, mime })
|
|
|
|
} else {
|
|
|
|
if (typesImage.includes(uri.split('.').pop() || '')) {
|
|
|
|
media.push({ uri, mime: 'image/jpg' })
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (typesVideo.includes(uri.split('.').pop() || '')) {
|
|
|
|
media.push({ uri, mime: 'video/mp4' })
|
|
|
|
return
|
|
|
|
}
|
|
|
|
text = !text ? uri : text.concat(text, `\n${uri}`)
|
2022-06-05 17:58:18 +02:00
|
|
|
}
|
2022-12-29 00:36:35 +01:00
|
|
|
}
|
2022-05-05 23:03:00 +02:00
|
|
|
|
2022-12-29 00:36:35 +01:00
|
|
|
switch (Platform.OS) {
|
|
|
|
case 'ios':
|
|
|
|
if (!Array.isArray(item.data) || !item.data) {
|
|
|
|
return
|
|
|
|
}
|
2022-05-05 23:03:00 +02:00
|
|
|
|
2022-12-29 00:36:35 +01:00
|
|
|
for (const d of item.data) {
|
|
|
|
if (typeof d !== 'string') {
|
|
|
|
filterMedia({ uri: d.data, mime: d.mimeType })
|
2022-06-05 17:58:18 +02:00
|
|
|
}
|
2022-12-29 00:36:35 +01:00
|
|
|
}
|
|
|
|
break
|
|
|
|
case 'android':
|
|
|
|
if (!item.mimeType) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (Array.isArray(item.data)) {
|
|
|
|
for (const d of item.data) {
|
|
|
|
filterMedia({ uri: d, mime: item.mimeType })
|
2022-11-20 22:42:09 +01:00
|
|
|
}
|
2022-08-12 16:44:28 +02:00
|
|
|
} else {
|
2022-12-29 00:36:35 +01:00
|
|
|
filterMedia({ uri: item.data, mime: item.mimeType })
|
2022-08-12 16:44:28 +02:00
|
|
|
}
|
2022-12-29 00:36:35 +01:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!text && !media.length) {
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
if (accounts?.length) {
|
|
|
|
navigationRef.navigate('Screen-AccountSelection', {
|
|
|
|
share: { text, media }
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
navigationRef.navigate('Screen-Compose', {
|
|
|
|
type: 'share',
|
|
|
|
text,
|
|
|
|
media
|
|
|
|
})
|
2022-05-05 23:03:00 +02:00
|
|
|
}
|
2022-12-29 00:36:35 +01:00
|
|
|
}
|
|
|
|
}
|
2022-05-02 22:31:22 +02:00
|
|
|
useEffect(() => {
|
2022-05-05 23:03:00 +02:00
|
|
|
ShareMenu.getInitialShare(handleShare)
|
2022-05-02 22:31:22 +02:00
|
|
|
}, [])
|
|
|
|
useEffect(() => {
|
2022-05-05 23:03:00 +02:00
|
|
|
const listener = ShareMenu.addNewShareListener(handleShare)
|
2022-05-02 22:31:22 +02:00
|
|
|
return () => {
|
|
|
|
listener.remove()
|
|
|
|
}
|
|
|
|
}, [])
|
|
|
|
|
2021-01-30 01:29:15 +01:00
|
|
|
return (
|
2022-12-28 23:41:36 +01:00
|
|
|
<IntlProvider locale={i18n.language}>
|
2022-05-18 00:11:02 +02:00
|
|
|
<StatusBar
|
2022-06-15 00:00:33 +02:00
|
|
|
backgroundColor={colors.backgroundDefault}
|
2023-02-11 18:12:50 +01:00
|
|
|
barStyle={theme === 'light' ? 'dark-content' : 'light-content'}
|
2022-05-18 00:11:02 +02:00
|
|
|
/>
|
2021-01-30 01:29:15 +01:00
|
|
|
<NavigationContainer
|
|
|
|
ref={navigationRef}
|
2022-02-12 14:51:01 +01:00
|
|
|
theme={themes[theme]}
|
2021-01-30 01:29:15 +01:00
|
|
|
onStateChange={navigationContainerOnStateChange}
|
|
|
|
>
|
2021-02-10 00:40:44 +01:00
|
|
|
<Stack.Navigator initialRouteName='Screen-Tabs'>
|
2021-01-30 01:29:15 +01:00
|
|
|
<Stack.Screen
|
|
|
|
name='Screen-Tabs'
|
|
|
|
component={ScreenTabs}
|
|
|
|
options={{ headerShown: false }}
|
|
|
|
/>
|
|
|
|
|
|
|
|
<Stack.Screen
|
|
|
|
name='Screen-Announcements'
|
|
|
|
component={ScreenAnnouncements}
|
2021-05-12 22:45:51 +02:00
|
|
|
options={({ navigation }) => ({
|
2021-08-21 01:45:43 +02:00
|
|
|
presentation: 'transparentModal',
|
|
|
|
animation: 'fade',
|
2021-05-12 22:45:51 +02:00
|
|
|
headerShown: true,
|
2021-08-21 01:45:43 +02:00
|
|
|
headerShadowVisible: false,
|
|
|
|
headerTransparent: true,
|
2021-05-12 22:45:51 +02:00
|
|
|
headerStyle: { backgroundColor: 'transparent' },
|
2023-01-25 00:15:46 +01:00
|
|
|
headerLeft: () => <HeaderLeft content='x' onPress={() => navigation.goBack()} />,
|
2021-12-18 23:44:08 +01:00
|
|
|
title: t('screenAnnouncements:heading')
|
2021-05-12 22:45:51 +02:00
|
|
|
})}
|
2021-01-30 01:29:15 +01:00
|
|
|
/>
|
|
|
|
<Stack.Screen
|
|
|
|
name='Screen-Compose'
|
|
|
|
component={ScreenCompose}
|
2021-02-10 00:40:44 +01:00
|
|
|
options={{
|
2021-08-21 01:45:43 +02:00
|
|
|
headerShown: false,
|
|
|
|
presentation: 'fullScreenModal'
|
2021-02-10 00:40:44 +01:00
|
|
|
}}
|
2021-01-30 01:29:15 +01:00
|
|
|
/>
|
|
|
|
<Stack.Screen
|
|
|
|
name='Screen-ImagesViewer'
|
|
|
|
component={ScreenImagesViewer}
|
2022-10-30 15:05:40 +01:00
|
|
|
options={{ headerShown: false, animation: 'fade' }}
|
2021-01-30 01:29:15 +01:00
|
|
|
/>
|
2022-08-12 16:44:28 +02:00
|
|
|
<Stack.Screen
|
|
|
|
name='Screen-AccountSelection'
|
|
|
|
component={ScreenAccountSelection}
|
|
|
|
options={({ navigation }) => ({
|
|
|
|
title: t('screenAccountSelection:heading'),
|
|
|
|
headerShadowVisible: false,
|
|
|
|
presentation: 'modal',
|
|
|
|
gestureEnabled: false,
|
|
|
|
headerLeft: () => (
|
|
|
|
<HeaderLeft
|
|
|
|
type='text'
|
|
|
|
content={t('common:buttons.cancel')}
|
|
|
|
onPress={() => navigation.goBack()}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
})}
|
|
|
|
/>
|
2021-01-30 01:29:15 +01:00
|
|
|
</Stack.Navigator>
|
|
|
|
|
2021-02-28 22:49:55 +01:00
|
|
|
<Message />
|
2021-01-30 01:29:15 +01:00
|
|
|
</NavigationContainer>
|
2022-12-28 23:41:36 +01:00
|
|
|
</IntlProvider>
|
2021-01-30 01:29:15 +01:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-12-24 01:18:20 +01:00
|
|
|
export default Screens
|