From 3ae7a4c0afab9deedbb312949054afb1c8ae1868 Mon Sep 17 00:00:00 2001 From: syui Date: Sun, 7 Dec 2025 22:10:41 +0900 Subject: [PATCH] fix --- ios/patching/001-social-app-ios-config.patch | 147 ++++ .../008-social-app-ios-policy-tos-error.patch | 8 +- ios/patching/009-social-app-ios-license.patch | 665 +----------------- ...social-app-ios-splash-license-footer.patch | 22 + ...2-social-app-ios-settings-about-help.patch | 123 +++- ...9-social-app-ios-entitlements-plugin.patch | 15 +- .../021-social-app-ios-clean-feed.patch | 399 +---------- ios/setup.zsh | 6 + 8 files changed, 331 insertions(+), 1054 deletions(-) create mode 100644 ios/patching/001-social-app-ios-config.patch diff --git a/ios/patching/001-social-app-ios-config.patch b/ios/patching/001-social-app-ios-config.patch new file mode 100644 index 0000000..fbaa58e --- /dev/null +++ b/ios/patching/001-social-app-ios-config.patch @@ -0,0 +1,147 @@ +diff --git a/app.config.js b/app.config.js +index 246d8abd3..349aefb3d 100644 +--- a/app.config.js ++++ b/app.config.js +@@ -18,10 +18,7 @@ module.exports = function (_config) { + const IS_DEV = !IS_TESTFLIGHT || !IS_PRODUCTION + + const ASSOCIATED_DOMAINS = [ +- 'applinks:bsky.app', +- 'applinks:staging.bsky.app', +- 'appclips:bsky.app', +- 'appclips:go.bsky.app', // Allows App Clip to work when scanning QR codes ++ 'applinks:syu.is', + // When testing local services, enter an ngrok (et al) domain here. It must use a standard HTTP/HTTPS port. + ...(IS_DEV || IS_TESTFLIGHT ? [] : []), + ] +@@ -33,27 +30,24 @@ module.exports = function (_config) { + return { + expo: { + version: VERSION, +- name: 'Bluesky', +- slug: 'bluesky', +- scheme: 'bluesky', ++ name: 'Aiat', ++ slug: 'aiat', ++ scheme: 'syui', + owner: 'blueskysocial', + runtimeVersion: { + policy: 'appVersion', + }, +- icon: './assets/app-icons/ios_icon_default_next.png', ++ icon: './assets/icon.png', + userInterfaceStyle: 'automatic', + primaryColor: '#1083fe', + newArchEnabled: false, + ios: { + supportsTablet: false, +- bundleIdentifier: 'xyz.blueskyweb.app', ++ bundleIdentifier: 'ai.syui.at', + config: { + usesNonExemptEncryption: false, + }, +- icon: +- PLATFORM === 'web' // web build doesn't like .icon files +- ? './assets/app-icons/ios_icon_default_next.png' +- : './assets/app-icons/ios_icon_default.icon', ++ icon: './assets/icon.png', + infoPlist: { + UIBackgroundModes: ['remote-notification'], + NSCameraUsageDescription: +@@ -113,7 +107,7 @@ module.exports = function (_config) { + entitlements: { + 'com.apple.developer.kernel.increased-memory-limit': true, + 'com.apple.developer.kernel.extended-virtual-addressing': true, +- 'com.apple.security.application-groups': 'group.app.bsky', ++ 'com.apple.security.application-groups': 'group.ai.syui.at', + }, + privacyManifests: { + NSPrivacyCollectedDataTypes: [ +@@ -175,14 +169,14 @@ module.exports = function (_config) { + barStyle: 'light-content', + }, + android: { +- icon: './assets/app-icons/android_icon_default_next.png', ++ icon: './assets/icon.png', + adaptiveIcon: { + foregroundImage: './assets/icon-android-foreground.png', + monochromeImage: './assets/icon-android-monochrome.png', + backgroundColor: '#006AFF', + }, + googleServicesFile: './google-services.json', +- package: 'xyz.blueskyweb.app', ++ package: 'ai.syui.at', + intentFilters: [ + { + action: 'VIEW', +@@ -190,7 +184,7 @@ module.exports = function (_config) { + data: [ + { + scheme: 'https', +- host: 'bsky.app', ++ host: 'syu.is', + }, + IS_DEV && { + scheme: 'http', +@@ -213,9 +207,9 @@ module.exports = function (_config) { + : undefined, + codeSigningMetadata: UPDATES_ENABLED + ? { +- keyid: 'main', +- alg: 'rsa-v1_5-sha256', +- } ++ keyid: 'main', ++ alg: 'rsa-v1_5-sha256', ++ } + : undefined, + checkAutomatically: 'NEVER', + }, +@@ -225,7 +219,7 @@ module.exports = function (_config) { + 'expo-web-browser', + [ + 'react-native-edge-to-edge', +- {android: {enforceNavigationBarContrast: false}}, ++ { android: { enforceNavigationBarContrast: false } }, + ], + USE_SENTRY && [ + '@sentry/react-native/expo', +@@ -386,7 +380,7 @@ module.exports = function (_config) { + }, + }, + ], +- ['expo-screen-orientation', {initialOrientation: 'PORTRAIT_UP'}], ++ ['expo-screen-orientation', { initialOrientation: 'PORTRAIT_UP' }], + ['expo-location'], + ].filter(Boolean), + extra: { +@@ -397,26 +391,22 @@ module.exports = function (_config) { + appExtensions: [ + { + targetName: 'Share-with-Bluesky', +- bundleIdentifier: 'xyz.blueskyweb.app.Share-with-Bluesky', ++ bundleIdentifier: 'ai.syui.at.Share-with-Bluesky', + entitlements: { + 'com.apple.security.application-groups': [ +- 'group.app.bsky', ++ 'group.ai.syui.at', + ], + }, + }, + { + targetName: 'BlueskyNSE', +- bundleIdentifier: 'xyz.blueskyweb.app.BlueskyNSE', ++ bundleIdentifier: 'ai.syui.at.BlueskyNSE', + entitlements: { + 'com.apple.security.application-groups': [ +- 'group.app.bsky', ++ 'group.ai.syui.at', + ], + }, + }, +- { +- targetName: 'BlueskyClip', +- bundleIdentifier: 'xyz.blueskyweb.app.AppClip', +- }, + ], + }, + }, diff --git a/ios/patching/008-social-app-ios-policy-tos-error.patch b/ios/patching/008-social-app-ios-policy-tos-error.patch index 16074e3..83015ec 100644 --- a/ios/patching/008-social-app-ios-policy-tos-error.patch +++ b/ios/patching/008-social-app-ios-policy-tos-error.patch @@ -1,5 +1,5 @@ diff --git a/src/view/screens/PrivacyPolicy.tsx b/src/view/screens/PrivacyPolicy.tsx -index a89eaadc4..19f5b4107 100644 +index a89eaadc4..1da393f03 100644 --- a/src/view/screens/PrivacyPolicy.tsx +++ b/src/view/screens/PrivacyPolicy.tsx @@ -1,52 +1,13 @@ @@ -34,7 +34,7 @@ index a89eaadc4..19f5b4107 100644 - setMinimalShellMode(false) - }, [setMinimalShellMode]), - ) -+import { useSetTitle } from '#/lib/hooks/useSetTitle' ++import {useSetTitle} from '#/lib/hooks/useSetTitle' +export function PrivacyPolicyScreen() { + useSetTitle('Privacy Policy') @@ -61,7 +61,7 @@ index a89eaadc4..19f5b4107 100644 ) } diff --git a/src/view/screens/TermsOfService.tsx b/src/view/screens/TermsOfService.tsx -index d843c713c..b96f112fc 100644 +index d843c713c..b81767bd5 100644 --- a/src/view/screens/TermsOfService.tsx +++ b/src/view/screens/TermsOfService.tsx @@ -1,50 +1,13 @@ @@ -96,7 +96,7 @@ index d843c713c..b96f112fc 100644 - setMinimalShellMode(false) - }, [setMinimalShellMode]), - ) -+import { useSetTitle } from '#/lib/hooks/useSetTitle' ++import {useSetTitle} from '#/lib/hooks/useSetTitle' +export function TermsOfServiceScreen() { + useSetTitle('Terms of Service') diff --git a/ios/patching/009-social-app-ios-license.patch b/ios/patching/009-social-app-ios-license.patch index 6bef46f..0d94461 100644 --- a/ios/patching/009-social-app-ios-license.patch +++ b/ios/patching/009-social-app-ios-license.patch @@ -1,15 +1,27 @@ diff --git a/src/Navigation.tsx b/src/Navigation.tsx -index fa33a9d56..642076b96 100644 +index fa33a9d56..a9b724c4e 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx -@@ -50,6 +50,7 @@ import { - snoozeEmailConfirmationPrompt, - } from '#/state/shell/reminders' - import {CommunityGuidelinesScreen} from '#/view/screens/CommunityGuidelines' +@@ -67,6 +67,7 @@ import {ProfileFeedLikedByScreen} from '#/view/screens/ProfileFeedLikedBy' + import {Storybook} from '#/view/screens/Storybook' + import {SupportScreen} from '#/view/screens/Support' + import {TermsOfServiceScreen} from '#/view/screens/TermsOfService' +import {LicenseScreen} from '#/view/screens/License' - import {CopyrightPolicyScreen} from '#/view/screens/CopyrightPolicy' - import {DebugModScreen} from '#/view/screens/DebugMod' - import {FeedsScreen} from '#/view/screens/Feeds' + import {BottomBar} from '#/view/shell/bottom-bar/BottomBar' + import {createNativeStackNavigatorWithAuth} from '#/view/shell/createNativeStackNavigatorWithAuth' + import {BookmarksScreen} from '#/screens/Bookmarks' +@@ -335,6 +336,11 @@ function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) { + getComponent={() => TermsOfServiceScreen} + options={{title: title(msg`Terms of Service`)}} + /> ++ LicenseScreen} ++ options={{title: title(msg`License`)}} ++ /> + CommunityGuidelinesScreen} diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts index c315a8341..9b2f50a83 100644 --- a/src/lib/routes/types.ts @@ -22,642 +34,15 @@ index c315a8341..9b2f50a83 100644 CommunityGuidelines: undefined CopyrightPolicy: undefined LanguageSettings: undefined -diff --git a/src/routes.ts b/src/routes.ts -index 1ed913bb2..77ea6deca 100644 ---- a/src/routes.ts -+++ b/src/routes.ts -@@ -71,8 +71,8 @@ export const router = new Router({ - MiscellaneousNotificationSettings: '/settings/notifications/miscellaneous', - // support - Support: '/support', -- PrivacyPolicy: '/support/privacy', -- TermsOfService: '/support/tos', -+ PrivacyPolicy: 'https://syu.is/about/support/privacy-policy', -+ TermsOfService: 'https://syu.is/about/support/tos', - CommunityGuidelines: '/support/community-guidelines', - CopyrightPolicy: '/support/copyright', - // hashtags diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx -index ed2a6cfb7..982c40b55 100644 +index ed2a6cfb7..0b429e6f3 100644 --- a/src/view/shell/Drawer.tsx +++ b/src/view/shell/Drawer.tsx -@@ -1,60 +1,50 @@ --import React, {type ComponentProps, type JSX} from 'react' --import {Linking, ScrollView, TouchableOpacity, View} from 'react-native' --import {useSafeAreaInsets} from 'react-native-safe-area-context' --import {msg, Plural, plural, Trans} from '@lingui/macro' --import {useLingui} from '@lingui/react' --import {StackActions, useNavigation} from '@react-navigation/native' -- --import {useActorStatus} from '#/lib/actor-status' --import {FEEDBACK_FORM_URL, HELP_DESK_URL} from '#/lib/constants' --import {type PressableScale} from '#/lib/custom-animations/PressableScale' --import {useNavigationTabState} from '#/lib/hooks/useNavigationTabState' --import {getTabState, TabState} from '#/lib/routes/helpers' --import {type NavigationProp} from '#/lib/routes/types' --import {sanitizeHandle} from '#/lib/strings/handles' --import {colors} from '#/lib/styles' --import {isWeb} from '#/platform/detection' --import {emitSoftReset} from '#/state/events' --import {useKawaiiMode} from '#/state/preferences/kawaii' --import {useUnreadNotifications} from '#/state/queries/notifications/unread' --import {useProfileQuery} from '#/state/queries/profile' --import {type SessionAccount, useSession} from '#/state/session' --import {useSetDrawerOpen} from '#/state/shell' --import {formatCount} from '#/view/com/util/numeric/format' --import {UserAvatar} from '#/view/com/util/UserAvatar' --import {NavSignupCard} from '#/view/shell/NavSignupCard' --import {atoms as a, tokens, useTheme, web} from '#/alf' --import {Button, ButtonIcon, ButtonText} from '#/components/Button' --import {Divider} from '#/components/Divider' -+import React, { type ComponentProps, type JSX } from 'react' -+import { Linking, ScrollView, TouchableOpacity, View } from 'react-native' -+import { useSafeAreaInsets } from 'react-native-safe-area-context' -+import { msg, Plural, plural, Trans } from '@lingui/macro' -+import { useLingui } from '@lingui/react' -+import { StackActions, useNavigation } from '@react-navigation/native' -+ -+import { useActorStatus } from '#/lib/actor-status' -+import { FEEDBACK_FORM_URL, HELP_DESK_URL } from '#/lib/constants' -+import { type PressableScale } from '#/lib/custom-animations/PressableScale' -+import { useNavigationTabState } from '#/lib/hooks/useNavigationTabState' -+import { getTabState, TabState } from '#/lib/routes/helpers' -+import { type NavigationProp } from '#/lib/routes/types' -+import { sanitizeHandle } from '#/lib/strings/handles' -+import { colors } from '#/lib/styles' -+import { isWeb } from '#/platform/detection' -+import { emitSoftReset } from '#/state/events' -+import { useKawaiiMode } from '#/state/preferences/kawaii' -+import { useUnreadNotifications } from '#/state/queries/notifications/unread' -+import { useProfileQuery } from '#/state/queries/profile' -+import { type SessionAccount, useSession } from '#/state/session' -+import { useSetDrawerOpen } from '#/state/shell' -+import { formatCount } from '#/view/com/util/numeric/format' -+import { UserAvatar } from '#/view/com/util/UserAvatar' -+import { NavSignupCard } from '#/view/shell/NavSignupCard' -+import { atoms as a, tokens, useTheme, web } from '#/alf' -+import { Button } from '#/components/Button' -+import { Divider } from '#/components/Divider' - import { - Bell_Filled_Corner0_Rounded as BellFilled, - Bell_Stroke2_Corner0_Rounded as Bell, - } from '#/components/icons/Bell' --import {Bookmark, BookmarkFilled} from '#/components/icons/Bookmark' --import {BulletList_Stroke2_Corner0_Rounded as List} from '#/components/icons/BulletList' --import { -- Hashtag_Filled_Corner0_Rounded as HashtagFilled, -- Hashtag_Stroke2_Corner0_Rounded as Hashtag, --} from '#/components/icons/Hashtag' - import { - HomeOpen_Filled_Corner0_Rounded as HomeFilled, - HomeOpen_Stoke2_Corner0_Rounded as Home, - } from '#/components/icons/HomeOpen' --import {MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled} from '#/components/icons/MagnifyingGlass' --import {MagnifyingGlass2_Stroke2_Corner0_Rounded as MagnifyingGlass} from '#/components/icons/MagnifyingGlass2' --import { -- Message_Stroke2_Corner0_Rounded as Message, -- Message_Stroke2_Corner0_Rounded_Filled as MessageFilled, --} from '#/components/icons/Message' --import {SettingsGear2_Stroke2_Corner0_Rounded as Settings} from '#/components/icons/SettingsGear2' -+import { MagnifyingGlass_Filled_Stroke2_Corner0_Rounded as MagnifyingGlassFilled } from '#/components/icons/MagnifyingGlass' -+import { MagnifyingGlass2_Stroke2_Corner0_Rounded as MagnifyingGlass } from '#/components/icons/MagnifyingGlass2' -+import { SettingsGear2_Stroke2_Corner0_Rounded as Settings } from '#/components/icons/SettingsGear2' - import { - UserCircle_Filled_Corner0_Rounded as UserCircleFilled, - UserCircle_Stroke2_Corner0_Rounded as UserCircle, - } from '#/components/icons/UserCircle' --import {InlineLinkText} from '#/components/Link' --import {Text} from '#/components/Typography' --import {useSimpleVerificationState} from '#/components/verification' --import {VerificationCheck} from '#/components/verification/VerificationCheck' -+import { InlineLinkText } from '#/components/Link' -+import { Text } from '#/components/Typography' -+import { useSimpleVerificationState } from '#/components/verification' -+import { VerificationCheck } from '#/components/verification/VerificationCheck' - - const iconWidth = 26 - -@@ -65,11 +55,11 @@ let DrawerProfileCard = ({ - account: SessionAccount - onPressProfile: () => void - }): React.ReactNode => { -- const {_, i18n} = useLingui() -+ const { _, i18n } = useLingui() - const t = useTheme() -- const {data: profile} = useProfileQuery({did: account.did}) -- const verification = useSimpleVerificationState({profile}) -- const {isActive: live} = useActorStatus(profile) -+ const { data: profile } = useProfileQuery({ did: account.did }) -+ const verification = useSimpleVerificationState({ profile }) -+ const { isActive: live } = useActorStatus(profile) - - return ( - ): React.ReactNode => { -+let DrawerContent = ({ }: React.PropsWithoutRef<{}>): React.ReactNode => { - const t = useTheme() - const insets = useSafeAreaInsets() - const setDrawerOpen = useSetDrawerOpen() -@@ -150,27 +139,20 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { - const { - isAtHome, - isAtSearch, -- isAtFeeds, -- isAtBookmarks, - isAtNotifications, - isAtMyProfile, -- isAtMessages, - } = useNavigationTabState() -- const {hasSession, currentAccount} = useSession() -- -- // events -- // = -+ const { hasSession, currentAccount } = useSession() - - const onPressTab = React.useCallback( - (tab: 'Home' | 'Search' | 'Messages' | 'Notifications' | 'MyProfile') => { - const state = navigation.getState() - setDrawerOpen(false) - if (isWeb) { -- // hack because we have flat navigator for web and MyProfile does not exist on the web navigator -ansh - if (tab === 'MyProfile') { -- navigation.navigate('Profile', {name: currentAccount!.handle}) -+ navigation.navigate('Profile', { name: currentAccount!.handle }) - } else { -- // @ts-expect-error struggles with string unions, apparently -+ // @ts-expect-error struggles with string unions - navigation.navigate(tab) - } - } else { -@@ -178,21 +160,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { - if (tabState === TabState.InsideAtRoot) { - emitSoftReset() - } else if (tabState === TabState.Inside) { -- // find the correct navigator in which to pop-to-top -- const target = state.routes.find(route => route.name === `${tab}Tab`) -- ?.state?.key -+ const target = state.routes.find(route => route.name === `${tab}Tab`)?.state?.key - if (target) { -- // if we found it, trigger pop-to-top -- navigation.dispatch({ -- ...StackActions.popToTop(), -- target, -- }) -+ navigation.dispatch({ ...StackActions.popToTop(), target }) - } else { -- // fallback: reset navigation -- navigation.reset({ -- index: 0, -- routes: [{name: `${tab}Tab`}], -- }) -+ navigation.reset({ index: 0, routes: [{ name: `${tab}Tab` }] }) - } - } else { - navigation.navigate(`${tab}Tab`) -@@ -203,76 +175,21 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { - ) - - const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab]) -- -- const onPressSearch = React.useCallback( -- () => onPressTab('Search'), -- [onPressTab], -- ) -- -- const onPressMessages = React.useCallback( -- () => onPressTab('Messages'), -- [onPressTab], -- ) -- -- const onPressNotifications = React.useCallback( -- () => onPressTab('Notifications'), -- [onPressTab], -- ) -- -- const onPressProfile = React.useCallback(() => { -- onPressTab('MyProfile') -- }, [onPressTab]) -- -- const onPressMyFeeds = React.useCallback(() => { -- navigation.navigate('Feeds') -- setDrawerOpen(false) -- }, [navigation, setDrawerOpen]) -- -- const onPressLists = React.useCallback(() => { -- navigation.navigate('Lists') -- setDrawerOpen(false) -- }, [navigation, setDrawerOpen]) -- -- const onPressBookmarks = React.useCallback(() => { -- navigation.navigate('Bookmarks') -- setDrawerOpen(false) -- }, [navigation, setDrawerOpen]) -- -+ const onPressSearch = React.useCallback(() => onPressTab('Search'), [onPressTab]) -+ const onPressNotifications = React.useCallback(() => onPressTab('Notifications'), [onPressTab]) -+ const onPressProfile = React.useCallback(() => { onPressTab('MyProfile') }, [onPressTab]) - const onPressSettings = React.useCallback(() => { - navigation.navigate('Settings') - setDrawerOpen(false) - }, [navigation, setDrawerOpen]) - -- const onPressFeedback = React.useCallback(() => { -- Linking.openURL( -- FEEDBACK_FORM_URL({ -- email: currentAccount?.email, -- handle: currentAccount?.handle, -- }), -- ) -- }, [currentAccount]) -- -- const onPressHelp = React.useCallback(() => { -- Linking.openURL(HELP_DESK_URL) -- }, []) -- -- // rendering -- // = -- - return ( - - -+ contentContainerStyle={[{ paddingTop: Math.max(insets.top + a.pt_xl.paddingTop, a.pt_xl.paddingTop) }]}> - - {hasSession && currentAccount ? ( - ): React.ReactNode => { - - - )} -- - - - -@@ -292,17 +208,10 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { - <> - - -- - -- -- -- - ): React.ReactNode => { - ) : ( - <> - -- - - - )} -@@ -322,69 +230,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { - - - -- -- - - ) - } - DrawerContent = React.memo(DrawerContent) --export {DrawerContent} -- --let DrawerFooter = ({ -- onPressFeedback, -- onPressHelp, --}: { -- onPressFeedback: () => void -- onPressHelp: () => void --}): React.ReactNode => { -- const {_} = useLingui() -- const insets = useSafeAreaInsets() -- return ( -- -- -- -- -- ) --} --DrawerFooter = React.memo(DrawerFooter) -+export { DrawerContent } - - interface MenuItemProps extends ComponentProps { - icon: JSX.Element -@@ -400,7 +250,7 @@ let SearchMenuItem = ({ - isActive: boolean - onPress: () => void - }): React.ReactNode => { -- const {_} = useLingui() -+ const { _ } = useLingui() - const t = useTheme() - return ( - void - }): React.ReactNode => { -- const {_} = useLingui() -+ const { _ } = useLingui() - const t = useTheme() - return ( - void --}): React.ReactNode => { -- const {_} = useLingui() -- const t = useTheme() -- return ( -- -- ) : ( -- -- ) -- } -- label={_(msg`Chat`)} -- bold={isActive} -- onPress={onPress} -- /> -- ) --} --ChatMenuItem = React.memo(ChatMenuItem) -- - let NotificationsMenuItem = ({ - isActive, - onPress, -@@ -478,7 +302,7 @@ let NotificationsMenuItem = ({ - isActive: boolean - onPress: () => void - }): React.ReactNode => { -- const {_} = useLingui() -+ const { _ } = useLingui() - const t = useTheme() - const numUnreadNotifications = useUnreadNotifications() - return ( -@@ -495,11 +319,11 @@ let NotificationsMenuItem = ({ - numUnreadNotifications === '' - ? '' - : _( -- msg`${plural(numUnreadNotifications ?? 0, { -- one: '# unread item', -- other: '# unread items', -- })}` || '', -- ) -+ msg`${plural(numUnreadNotifications ?? 0, { -+ one: '# unread item', -+ other: '# unread items', -+ })}` || '', -+ ) - } - count={numUnreadNotifications} - bold={isActive} -@@ -509,72 +333,6 @@ let NotificationsMenuItem = ({ - } - NotificationsMenuItem = React.memo(NotificationsMenuItem) - --let FeedsMenuItem = ({ -- isActive, -- onPress, --}: { -- isActive: boolean -- onPress: () => void --}): React.ReactNode => { -- const {_} = useLingui() -- const t = useTheme() -- return ( -- -- ) : ( -- -- ) -- } -- label={_(msg`Feeds`)} -- bold={isActive} -- onPress={onPress} -- /> -- ) --} --FeedsMenuItem = React.memo(FeedsMenuItem) -- --let ListsMenuItem = ({onPress}: {onPress: () => void}): React.ReactNode => { -- const {_} = useLingui() -- const t = useTheme() -- -- return ( -- } -- label={_(msg`Lists`)} -- onPress={onPress} -- /> -- ) --} --ListsMenuItem = React.memo(ListsMenuItem) -- --let BookmarksMenuItem = ({ -- isActive, -- onPress, --}: { -- isActive: boolean -- onPress: () => void --}): React.ReactNode => { -- const {_} = useLingui() -- const t = useTheme() -- -- return ( -- -- ) : ( -- -- ) -- } -- label={_(msg({message: 'Saved', context: 'link to bookmarks screen'}))} -- onPress={onPress} -- /> -- ) --} --BookmarksMenuItem = React.memo(BookmarksMenuItem) -- - let ProfileMenuItem = ({ - isActive, - onPress, -@@ -582,7 +340,7 @@ let ProfileMenuItem = ({ - isActive: boolean - onPress: () => void - }): React.ReactNode => { -- const {_} = useLingui() -+ const { _ } = useLingui() - const t = useTheme() - return ( - void}): React.ReactNode => { -- const {_} = useLingui() -+let SettingsMenuItem = ({ onPress }: { onPress: () => void }): React.ReactNode => { -+ const { _ } = useLingui() - const t = useTheme() - return ( - void}): React.ReactNode => { - } - SettingsMenuItem = React.memo(SettingsMenuItem) - --function MenuItem({icon, label, count, bold, onPress}: MenuItemProps) { -+function MenuItem({ icon, label, count, bold, onPress }: MenuItemProps) { - const t = useTheme() - return ( -