From 31a3e87963523a956364aede09f7bc4b9d62c643 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Fri, 3 Jun 2022 21:25:20 +0200 Subject: [PATCH 1/4] Allow push count badge --- src/App.tsx | 15 +- src/screens/Tabs.tsx | 2 +- src/screens/Tabs/Me/Push.tsx | 9 +- src/screens/Tabs/Me/Root/Update.tsx | 2 +- src/store.ts | 4 +- src/utils/push/useConnect.ts | 137 ++++++++++-------- src/utils/slices/appSlice.ts | 71 +++++++++ src/utils/slices/instances/push/register.ts | 3 +- src/utils/slices/instances/updatePush.ts | 14 +- .../slices/instances/updatePushDecode.ts | 13 +- src/utils/slices/versionSlice.ts | 43 ------ 11 files changed, 166 insertions(+), 147 deletions(-) create mode 100644 src/utils/slices/appSlice.ts delete mode 100644 src/utils/slices/versionSlice.ts diff --git a/src/App.tsx b/src/App.tsx index d0344016..496f2c71 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,10 +17,9 @@ import { } from '@utils/slices/settingsSlice' import ThemeManager from '@utils/styles/ThemeManager' import 'expo-asset' -import * as Notifications from 'expo-notifications' import * as SplashScreen from 'expo-splash-screen' import React, { useCallback, useEffect, useState } from 'react' -import { AppState, LogBox, Platform } from 'react-native' +import { LogBox, Platform } from 'react-native' import { GestureHandlerRootView } from 'react-native-gesture-handler' import 'react-native-image-keyboard' import { enableFreeze } from 'react-native-screens' @@ -44,18 +43,6 @@ const App: React.FC = () => { log('log', 'App', 'rendering App') const [localCorrupt, setLocalCorrupt] = useState() - const appStateEffect = useCallback(() => { - Notifications.setBadgeCountAsync(0) - Notifications.dismissAllNotificationsAsync() - }, []) - useEffect(() => { - const appStateListener = AppState.addEventListener('change', appStateEffect) - - return () => { - appStateListener.remove() - } - }, []) - useEffect(() => { const delaySplash = async () => { log('log', 'App', 'delay splash') diff --git a/src/screens/Tabs.tsx b/src/screens/Tabs.tsx index 48f1cf6a..0c18965e 100644 --- a/src/screens/Tabs.tsx +++ b/src/screens/Tabs.tsx @@ -18,7 +18,7 @@ import { import { getVersionUpdate, retriveVersionLatest -} from '@utils/slices/versionSlice' +} from '@utils/slices/appSlice' import { useTheme } from '@utils/styles/ThemeManager' import React, { useCallback, useEffect, useMemo } from 'react' import { Platform } from 'react-native' diff --git a/src/screens/Tabs/Me/Push.tsx b/src/screens/Tabs/Me/Push.tsx index e49cb86e..9e739527 100644 --- a/src/screens/Tabs/Me/Push.tsx +++ b/src/screens/Tabs/Me/Push.tsx @@ -5,6 +5,7 @@ import { MenuContainer, MenuRow } from '@components/Menu' import CustomText from '@components/Text' import { useAppDispatch } from '@root/store' import { isDevelopment } from '@utils/checkEnvironment' +import { getExpoToken } from '@utils/slices/appSlice' import { updateInstancePush } from '@utils/slices/instances/updatePush' import { updateInstancePushAlert } from '@utils/slices/instances/updatePushAlert' import { updateInstancePushDecode } from '@utils/slices/instances/updatePushDecode' @@ -45,16 +46,12 @@ const TabMePush: React.FC = () => { setPushEnabled(settings.granted) setPushCanAskAgain(settings.canAskAgain) } + const expoToken = useSelector(getExpoToken) useEffect(() => { if (isDevelopment) { setPushAvailable(true) } else { - Notifications.getExpoPushTokenAsync({ - experienceId: '@xmflsct/tooot', - applicationId: 'com.xmflsct.app.tooot' - }) - .then(data => setPushAvailable(!!data)) - .catch(() => setPushAvailable(false)) + setPushAvailable(!!expoToken) } checkPush() diff --git a/src/screens/Tabs/Me/Root/Update.tsx b/src/screens/Tabs/Me/Root/Update.tsx index 2d2c2d9b..e1d9f6d2 100644 --- a/src/screens/Tabs/Me/Root/Update.tsx +++ b/src/screens/Tabs/Me/Root/Update.tsx @@ -1,5 +1,5 @@ import { MenuContainer, MenuRow } from '@components/Menu' -import { getVersionUpdate } from '@utils/slices/versionSlice' +import { getVersionUpdate } from '@utils/slices/appSlice' import React from 'react' import { useTranslation } from 'react-i18next' import { Linking, Platform } from 'react-native' diff --git a/src/store.ts b/src/store.ts index 81a06675..06942508 100644 --- a/src/store.ts +++ b/src/store.ts @@ -4,10 +4,10 @@ import { AnyAction, configureStore, Reducer } from '@reduxjs/toolkit' import contextsMigration from '@utils/migrations/contexts/migration' import instancesMigration from '@utils/migrations/instances/migration' import settingsMigration from '@utils/migrations/settings/migration' +import appSlice from '@utils/slices/appSlice' import contextsSlice, { ContextsState } from '@utils/slices/contextsSlice' import instancesSlice, { InstancesState } from '@utils/slices/instancesSlice' import settingsSlice, { SettingsState } from '@utils/slices/settingsSlice' -import versionSlice from '@utils/slices/versionSlice' import { Platform } from 'react-native' import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' import { @@ -67,7 +67,7 @@ const store = configureStore({ SettingsState, AnyAction >, - version: versionSlice + app: appSlice }, middleware: getDefaultMiddleware => getDefaultMiddleware({ diff --git a/src/utils/push/useConnect.ts b/src/utils/push/useConnect.ts index 6096f4a9..9b6453dd 100644 --- a/src/utils/push/useConnect.ts +++ b/src/utils/push/useConnect.ts @@ -3,13 +3,15 @@ import apiTooot from '@api/tooot' import { displayMessage } from '@components/Message' import navigationRef from '@helpers/navigationRef' import { useAppDispatch } from '@root/store' -import { isDevelopment } from '@utils/checkEnvironment' import { InstanceLatest } from '@utils/migrations/instances/migration' +import { getExpoToken, retriveExpoToken } from '@utils/slices/appSlice' import { disableAllPushes } from '@utils/slices/instancesSlice' import { useTheme } from '@utils/styles/ThemeManager' import * as Notifications from 'expo-notifications' import { useEffect } from 'react' import { TFunction } from 'react-i18next' +import { AppState } from 'react-native' +import { useSelector } from 'react-redux' export interface Params { t: TFunction<'screens'> @@ -19,69 +21,84 @@ export interface Params { const pushUseConnect = ({ t, instances }: Params) => { const dispatch = useAppDispatch() const { theme } = useTheme() + useEffect(() => { + dispatch(retriveExpoToken()) + }, []) + + const expoToken = useSelector(getExpoToken) + + const connect = () => { + apiTooot({ + method: 'get', + url: `push/connect/${expoToken}`, + sentry: true + }).catch(error => { + if (error?.status == 404) { + displayMessage({ + theme, + type: 'error', + duration: 'long', + message: t('pushError.message'), + description: t('pushError.description'), + onPress: () => { + navigationRef.navigate('Screen-Tabs', { + screen: 'Tab-Me', + params: { + screen: 'Tab-Me-Root' + } + }) + navigationRef.navigate('Screen-Tabs', { + screen: 'Tab-Me', + params: { + screen: 'Tab-Me-Settings' + } + }) + } + }) + + dispatch(disableAllPushes()) + + instances.forEach(instance => { + if (instance.push.global.value) { + apiGeneral<{}>({ + method: 'delete', + domain: instance.url, + url: 'api/v1/push/subscription', + headers: { + Authorization: `Bearer ${instance.token}` + } + }).catch(() => console.log('error!!!')) + } + }) + } + }) + } + + const pushEnabled = instances.filter(instance => instance.push.global.value) + + useEffect(() => { + const appStateListener = AppState.addEventListener('change', state => { + console.log('changing state to', state) + if (expoToken && pushEnabled.length && state === 'active') { + Notifications.getBadgeCountAsync().then(count => { + if (count > 0) { + Notifications.setBadgeCountAsync(0) + connect() + } + }) + } + }) + + return () => { + appStateListener.remove() + } + }, [expoToken, pushEnabled.length]) return useEffect(() => { - const connect = async () => { - const expoToken = isDevelopment - ? 'DEVELOPMENT_TOKEN_1' - : ( - await Notifications.getExpoPushTokenAsync({ - experienceId: '@xmflsct/tooot', - applicationId: 'com.xmflsct.app.tooot' - }) - ).data - - apiTooot({ - method: 'get', - url: `push/connect/${expoToken}`, - sentry: true - }).catch(error => { - if (error?.status == 404) { - displayMessage({ - theme, - type: 'error', - duration: 'long', - message: t('pushError.message'), - description: t('pushError.description'), - onPress: () => { - navigationRef.navigate('Screen-Tabs', { - screen: 'Tab-Me', - params: { - screen: 'Tab-Me-Root' - } - }) - navigationRef.navigate('Screen-Tabs', { - screen: 'Tab-Me', - params: { - screen: 'Tab-Me-Settings' - } - }) - } - }) - - dispatch(disableAllPushes()) - - instances.forEach(instance => { - if (instance.push.global.value) { - apiGeneral<{}>({ - method: 'delete', - domain: instance.url, - url: 'api/v1/push/subscription', - headers: { - Authorization: `Bearer ${instance.token}` - } - }).catch(() => console.log('error!!!')) - } - }) - } - }) - } - - const pushEnabled = instances.filter(instance => instance.push.global.value) - if (pushEnabled.length) { + if (expoToken && pushEnabled.length) { connect() } - }, [instances]) + }, [expoToken, pushEnabled.length]) } export default pushUseConnect diff --git a/src/utils/slices/appSlice.ts b/src/utils/slices/appSlice.ts new file mode 100644 index 00000000..dc793133 --- /dev/null +++ b/src/utils/slices/appSlice.ts @@ -0,0 +1,71 @@ +import apiGeneral from '@api/general' +import { createAsyncThunk, createSlice } from '@reduxjs/toolkit' +import { RootState } from '@root/store' +import { isDevelopment } from '@utils/checkEnvironment' +import Constants from 'expo-constants' +import * as Notifications from 'expo-notifications' + +export const retriveExpoToken = createAsyncThunk( + 'app/expoToken', + async (): Promise => { + if (isDevelopment) { + return 'DEVELOPMENT_TOKEN_1' + } + + const res = await Notifications.getExpoPushTokenAsync({ + experienceId: '@xmflsct/tooot', + applicationId: 'com.xmflsct.app.tooot' + }) + return res.data + } +) + +export const retriveVersionLatest = createAsyncThunk( + 'app/versionUpdate', + async (): Promise => { + const res = await apiGeneral<{ latest: string }>({ + method: 'get', + domain: 'tooot.app', + url: 'version.json' + }) + return res.body.latest + } +) + +export type AppState = { + expoToken?: string + versionUpdate: boolean +} + +export const appInitialState: AppState = { + expoToken: undefined, + versionUpdate: false +} + +const appSlice = createSlice({ + name: 'app', + initialState: appInitialState, + reducers: {}, + extraReducers: builder => { + builder + .addCase(retriveExpoToken.fulfilled, (state, action) => { + if (action.payload) { + state.expoToken = action.payload + } + }) + .addCase(retriveVersionLatest.fulfilled, (state, action) => { + if (action.payload && Constants.manifest?.version) { + if ( + parseFloat(action.payload) > parseFloat(Constants.manifest.version) + ) { + state.versionUpdate = true + } + } + }) + } +}) + +export const getExpoToken = (state: RootState) => state.app.expoToken +export const getVersionUpdate = (state: RootState) => state.app.versionUpdate + +export default appSlice.reducer diff --git a/src/utils/slices/instances/push/register.ts b/src/utils/slices/instances/push/register.ts index ff43c968..fafad15d 100644 --- a/src/utils/slices/instances/push/register.ts +++ b/src/utils/slices/instances/push/register.ts @@ -48,8 +48,9 @@ const pushRegister = async ( const accountId = instanceAccount.id const accountFull = `@${instanceAccount.acct}@${instanceUri}` + const randomPath = (Math.random() + 1).toString(36).substring(2) - const endpoint = `https://${TOOOT_API_DOMAIN}/push/send/${expoToken}/${instanceUrl}/${accountId}` + const endpoint = `https://${TOOOT_API_DOMAIN}/push/send/${expoToken}/${instanceUrl}/${accountId}/${randomPath}` const auth = base64.encodeFromByteArray(Random.getRandomBytes(16)) const alerts = instancePush.alerts diff --git a/src/utils/slices/instances/updatePush.ts b/src/utils/slices/instances/updatePush.ts index 9d11c546..7a04f9eb 100644 --- a/src/utils/slices/instances/updatePush.ts +++ b/src/utils/slices/instances/updatePush.ts @@ -1,8 +1,6 @@ import { createAsyncThunk } from '@reduxjs/toolkit' import { RootState } from '@root/store' -import { isDevelopment } from '@utils/checkEnvironment' import { InstanceLatest } from '@utils/migrations/instances/migration' -import * as Notifications from 'expo-notifications' import pushRegister from './push/register' import pushUnregister from './push/unregister' @@ -13,14 +11,10 @@ export const updateInstancePush = createAsyncThunk( { getState } ): Promise => { const state = getState() as RootState - const expoToken = isDevelopment - ? 'DEVELOPMENT_TOKEN_1' - : ( - await Notifications.getExpoPushTokenAsync({ - experienceId: '@xmflsct/tooot', - applicationId: 'com.xmflsct.app.tooot' - }) - ).data + const expoToken = state.app.expoToken + if (!expoToken) { + return Promise.reject() + } if (disable) { return await pushRegister(state, expoToken) diff --git a/src/utils/slices/instances/updatePushDecode.ts b/src/utils/slices/instances/updatePushDecode.ts index 3525d170..ac215263 100644 --- a/src/utils/slices/instances/updatePushDecode.ts +++ b/src/utils/slices/instances/updatePushDecode.ts @@ -2,7 +2,6 @@ import apiTooot from '@api/tooot' import { createAsyncThunk } from '@reduxjs/toolkit' import i18n from '@root/i18n/i18n' import { RootState } from '@root/store' -import { isDevelopment } from '@utils/checkEnvironment' import { InstanceLatest } from '@utils/migrations/instances/migration' import * as Notifications from 'expo-notifications' import { Platform } from 'react-native' @@ -21,14 +20,10 @@ export const updateInstancePushDecode = createAsyncThunk( return Promise.reject() } - const expoToken = isDevelopment - ? 'DEVELOPMENT_TOKEN_1' - : ( - await Notifications.getExpoPushTokenAsync({ - experienceId: '@xmflsct/tooot', - applicationId: 'com.xmflsct.app.tooot' - }) - ).data + const expoToken = state.app.expoToken + if (!expoToken) { + return Promise.reject() + } await apiTooot({ method: 'put', diff --git a/src/utils/slices/versionSlice.ts b/src/utils/slices/versionSlice.ts deleted file mode 100644 index 620e6f10..00000000 --- a/src/utils/slices/versionSlice.ts +++ /dev/null @@ -1,43 +0,0 @@ -import apiGeneral from '@api/general' -import { createAsyncThunk, createSlice } from '@reduxjs/toolkit' -import { RootState } from '@root/store' -import Constants from 'expo-constants' - -export const retriveVersionLatest = createAsyncThunk( - 'version/latest', - async () => { - const res = await apiGeneral<{ latest: string }>({ - method: 'get', - domain: 'tooot.app', - url: 'version.json' - }) - return res.body.latest - } -) - -export type VersionState = { - update: boolean -} - -export const versionInitialState = { - update: false -} - -const versionSlice = createSlice({ - name: 'version', - initialState: versionInitialState, - reducers: {}, - extraReducers: builder => { - builder.addCase(retriveVersionLatest.fulfilled, (state, action) => { - if (action.payload && Constants.manifest?.version) { - if (parseFloat(action.payload) > parseFloat(Constants.manifest.version)) { - state.update = true - } - } - }) - } -}) - -export const getVersionUpdate = (state: RootState) => state.version.update - -export default versionSlice.reducer From 77deb3fdeffa2642d57e3baecded79dd1a62ef63 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Fri, 3 Jun 2022 22:29:04 +0200 Subject: [PATCH 2/4] Bump packages --- package.json | 10 +++++----- yarn.lock | 32 ++++++++++++++++---------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 31e142ae..209e3464 100644 --- a/package.json +++ b/package.json @@ -68,12 +68,12 @@ "expo-updates": "0.13.1", "expo-video-thumbnails": "6.3.0", "expo-web-browser": "10.2.0", - "i18next": "21.8.4", + "i18next": "21.8.8", "li": "1.3.0", "lodash": "4.17.21", "react": "17.0.2", "react-dom": "17.0.2", - "react-i18next": "11.16.9", + "react-i18next": "11.17.0", "react-intl": "^6.0.3", "react-native": "0.68.2", "react-native-animated-spinkit": "1.5.2", @@ -93,7 +93,7 @@ "react-native-svg": "12.3.0", "react-native-swipe-list-view": "3.2.9", "react-native-tab-view": "3.1.1", - "react-query": "3.39.0", + "react-query": "3.39.1", "react-redux": "8.0.2", "redux-persist": "6.0.0", "rn-placeholder": "3.0.3", @@ -123,7 +123,7 @@ "patch-package": "6.4.7", "postinstall-postinstall": "2.1.0", "react-native-clean-project": "4.0.1", - "typescript": "4.7.2" + "typescript": "4.7.3" }, "resolutions": { "@types/react": "17.0.43", @@ -151,4 +151,4 @@ } } } -} +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 49a7062e..2171b04e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5285,10 +5285,10 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" -i18next@21.8.4: - version "21.8.4" - resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.8.4.tgz#646e23065752036b38d9fda8898c18139b9e8ebe" - integrity sha512-b3LQ5n9V1juu8UItb5x1QTI4OTvNqsNs/wetwQlBvfijEqks+N5HKMKSoevf8w0/RGUrDQ7g4cvVzF8WBp9pUw== +i18next@21.8.8: + version "21.8.8" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.8.8.tgz#725a05f2529689d059bce17221cf86fcdccf7665" + integrity sha512-iN/5JuWStyivyBgmUgy5BRiFs0lZrgCRaeV9q4yVH/eR9NID7pZSMt3rpF8C16GplchoEjDP0JalKwZMJ1CJAA== dependencies: "@babel/runtime" "^7.17.2" @@ -7440,10 +7440,10 @@ react-freeze@^1.0.0: resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.0.tgz#b21c65fe1783743007c8c9a2952b1c8879a77354" integrity sha512-yQaiOqDmoKqks56LN9MTgY06O0qQHgV4FUrikH357DydArSZHQhl0BJFqGKIZoTqi8JizF9Dxhuk1FIZD6qCaw== -react-i18next@11.16.9: - version "11.16.9" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.16.9.tgz#890cdac0c49120e075d6c520b43dbad3f91bd2df" - integrity sha512-euXxWvcEAvsY7ZVkwx9ztCq4butqtsGHEkpkuo0RMj8Ru09IF9o2KxCyN+zyv51Nr0aBh/elaTIiR6fMb8YfVg== +react-i18next@11.17.0: + version "11.17.0" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.17.0.tgz#44a0689dac7903352733e40303b743fa465eb797" + integrity sha512-ewq2S4bVUTRqOMAdM/XvzCn9xUPIryzeBQRghmJ8lC6VI/8Kp7z1GwoLyt8j7GB2ywhN2SjPk7LU4sHzVeu7aw== dependencies: "@babel/runtime" "^7.14.5" html-escaper "^2.0.2" @@ -7654,10 +7654,10 @@ react-native@0.68.2: whatwg-fetch "^3.0.0" ws "^6.1.4" -react-query@3.39.0: - version "3.39.0" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.0.tgz#0caca7b0da98e65008bbcd4df0d25618c2100050" - integrity sha512-Od0IkSuS79WJOhzWBx/ys0x13+7wFqgnn64vBqqAAnZ9whocVhl/y1padD5uuZ6EIkXbFbInax0qvY7zGM0thA== +react-query@3.39.1: + version "3.39.1" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.1.tgz#3876c0fdac7a3b5a84e195534e5fa8fbdd628847" + integrity sha512-qYKT1bavdDiQZbngWZyPotlBVzcBjDYEJg5RQLBa++5Ix5jjfbEYJmHSZRZD+USVHUSvl/ey9Hu+QfF1QAK80A== dependencies: "@babel/runtime" "^7.5.5" broadcast-channel "^3.4.1" @@ -8792,10 +8792,10 @@ typedarray-to-buffer@^3.1.2: dependencies: is-typedarray "^1.0.0" -typescript@4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4" - integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A== +typescript@4.7.3: + version "4.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" + integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA== ua-parser-js@^0.7.19, ua-parser-js@^0.7.30: version "0.7.31" From e38a45ffb2749db116f84faad051494312515c1d Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Fri, 3 Jun 2022 23:18:24 +0200 Subject: [PATCH 3/4] Fixed #315 --- src/components/Button.tsx | 3 ++ .../Timeline/Shared/Attachment/AltText.tsx | 38 ++++++++++++++ .../Timeline/Shared/Attachment/Audio.tsx | 5 ++ .../Timeline/Shared/Attachment/Image.tsx | 9 +++- .../Shared/Attachment/Unsupported.tsx | 5 ++ .../Timeline/Shared/Attachment/Video.tsx | 51 +++++++++---------- src/i18n/en/screens/actions.json | 5 +- src/screens/Actions.tsx | 5 +- src/screens/Actions/AltText.tsx | 44 ++++++++++++++++ src/screens/Actions/NotificationsFilter.tsx | 13 ++--- src/utils/navigation/navigators.ts | 4 ++ 11 files changed, 140 insertions(+), 42 deletions(-) create mode 100644 src/components/Timeline/Shared/Attachment/AltText.tsx create mode 100644 src/screens/Actions/AltText.tsx diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 579134b7..80049c5d 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -29,6 +29,7 @@ export interface Props { strokeWidth?: number size?: 'S' | 'M' | 'L' + fontBold?: boolean spacing?: 'XS' | 'S' | 'M' | 'L' round?: boolean overlay?: boolean @@ -48,6 +49,7 @@ const Button: React.FC = ({ disabled = false, strokeWidth, size = 'M', + fontBold = false, spacing = 'S', round = false, overlay = false, @@ -122,6 +124,7 @@ const Button: React.FC = ({ StyleConstants.Font.Size[size] * (size === 'L' ? 1.25 : 1), opacity: loading ? 0 : 1 }} + fontWeight={fontBold ? 'Bold' : 'Normal'} children={content} testID='text' /> diff --git a/src/components/Timeline/Shared/Attachment/AltText.tsx b/src/components/Timeline/Shared/Attachment/AltText.tsx new file mode 100644 index 00000000..59775ac5 --- /dev/null +++ b/src/components/Timeline/Shared/Attachment/AltText.tsx @@ -0,0 +1,38 @@ +import Button from '@components/Button' +import { useNavigation } from '@react-navigation/native' +import { StackNavigationProp } from '@react-navigation/stack' +import { RootStackParamList } from '@utils/navigation/navigators' +import { StyleConstants } from '@utils/styles/constants' + +export interface Props { + sensitiveShown: boolean + text?: string +} + +const AttachmentAltText: React.FC = ({ sensitiveShown, text }) => { + if (!text) { + return null + } + + const navigation = useNavigation>() + + return !sensitiveShown ? ( +