diff --git a/ios/patching/009-social-app-ios-license.patch b/ios/patching/009-social-app-ios-license.patch index 203e171..10be13b 100644 --- a/ios/patching/009-social-app-ios-license.patch +++ b/ios/patching/009-social-app-ios-license.patch @@ -1,47 +1,11 @@ -diff --git a/src/Navigation.tsx b/src/Navigation.tsx -index fa33a9d56..a9b724c4e 100644 ---- a/src/Navigation.tsx -+++ b/src/Navigation.tsx -@@ -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 {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 -+++ b/src/lib/routes/types.ts -@@ -39,6 +39,7 @@ export type CommonNavigatorParams = { - Support: undefined - PrivacyPolicy: undefined - TermsOfService: undefined -+ License: undefined - CommunityGuidelines: undefined - CopyrightPolicy: undefined - LanguageSettings: undefined diff --git a/src/view/screens/License.tsx b/src/view/screens/License.tsx new file mode 100644 -index 000000000..d35fe20ea +index 000000000..f98cd6afc --- /dev/null +++ b/src/view/screens/License.tsx @@ -0,0 +1,86 @@ +import React from 'react' -+import {ScrollView} from 'react-native' ++import { ScrollView } from 'react-native' +import * as Layout from '#/components/Layout' +import {useSetTitle} from '#/lib/hooks/useSetTitle' +import {atoms as a, useTheme} from '#/alf' @@ -127,10 +91,581 @@ index 000000000..d35fe20ea + ) +} diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx -index ed2a6cfb7..b9776af52 100644 +index ed2a6cfb7..0eba4edc4 100644 --- a/src/view/shell/Drawer.tsx +++ b/src/view/shell/Drawer.tsx -@@ -689,21 +689,25 @@ function ExtraLinks() { +@@ -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 ( +