From 22793b5a8ab78b23104fa222a5a236cc30903b08 Mon Sep 17 00:00:00 2001 From: syui Date: Sun, 7 Dec 2025 14:23:14 +0900 Subject: [PATCH] fix patch cmd --- ios/patching/002-social-app-ios-lib.patch | 71 +- ios/patching/004-social-app-ios-core.patch | 81 +-- ios/patching/005-social-app-ios-screens.patch | 509 ++----------- ios/patching/006-social-app-ios-shell.patch | 450 ++---------- ios/patching/007-social-app-ios-misc.patch | 128 +--- .../008-social-app-ios-policy-tos-error.patch | 330 +-------- ios/patching/009-social-app-ios-license.patch | 673 +----------------- ...ocial-app-ios-remove-contact-support.patch | 19 +- ...social-app-ios-splash-license-footer.patch | 115 +-- ...2-social-app-ios-settings-about-help.patch | 31 - ...-social-app-ios-settings-remove-help.patch | 5 +- ...9-social-app-ios-entitlements-plugin.patch | 31 + ios/setup.zsh | 4 +- 13 files changed, 224 insertions(+), 2223 deletions(-) delete mode 100644 ios/patching/012-social-app-ios-settings-about-help.patch create mode 100644 ios/patching/019-social-app-ios-entitlements-plugin.patch diff --git a/ios/patching/002-social-app-ios-lib.patch b/ios/patching/002-social-app-ios-lib.patch index 8381b72..8620436 100644 --- a/ios/patching/002-social-app-ios-lib.patch +++ b/ios/patching/002-social-app-ios-lib.patch @@ -1,79 +1,24 @@ diff --git a/src/lib/constants.ts b/src/lib/constants.ts -index 231447b4f..33c51cc0a 100644 +index e2a742056..f325d7b05 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts -@@ -7,12 +7,12 @@ import {BLUESKY_PROXY_DID, CHAT_PROXY_DID} from '#/env' - export const LOCAL_DEV_SERVICE = - Platform.OS === 'android' ? 'http://10.0.2.2:2583' : 'http://localhost:2583' - export const STAGING_SERVICE = 'https://staging.bsky.dev' --export const BSKY_SERVICE = 'https://bsky.social' --export const BSKY_SERVICE_DID = 'did:web:bsky.social' --export const PUBLIC_BSKY_SERVICE = 'https://public.api.bsky.app' -+export const BSKY_SERVICE = 'https://syu.is' -+export const BSKY_SERVICE_DID = 'did:web:syu.is' -+export const PUBLIC_BSKY_SERVICE = 'https://bsky.syu.is' +@@ -12,7 +12,7 @@ export const PUBLIC_BSKY_SERVICE = 'https://public.api.bsky.app' export const DEFAULT_SERVICE = BSKY_SERVICE --const HELP_DESK_LANG = 'en-us' + const HELP_DESK_LANG = 'en-us' -export const HELP_DESK_URL = `https://blueskyweb.zendesk.com/hc/${HELP_DESK_LANG}` -+const HELP_DESK_LANG = 'ja-jp' -+export const HELP_DESK_URL = 'https://syu.is/help' ++export const HELP_DESK_URL = `https://syu.is/about/support/help` export const EMBED_SERVICE = 'https://embed.bsky.app' export const EMBED_SCRIPT = `${EMBED_SERVICE}/static/embed.js` export const BSKY_DOWNLOAD_URL = 'https://bsky.app/download' -@@ -209,8 +209,8 @@ export const urls = { - }, - } - --export const PUBLIC_APPVIEW = 'https://api.bsky.app' --export const PUBLIC_APPVIEW_DID = 'did:web:api.bsky.app' -+export const PUBLIC_APPVIEW = 'https://bsky.syu.is' -+export const PUBLIC_APPVIEW_DID = 'did:web:bsky.syu.is' - export const PUBLIC_STAGING_APPVIEW_DID = 'did:web:api.staging.bsky.dev' - - export const DEV_ENV_APPVIEW = `http://localhost:2584` // always the same @@ -236,8 +236,8 @@ export const BLUESKY_MOD_SERVICE_HEADERS = { } export const webLinks = { - tos: `https://bsky.social/about/support/tos`, - privacy: `https://bsky.social/about/support/privacy-policy`, -+ tos: `https://bsky.social/abouthttps://syu.is/terms`, -+ privacy: `https://bsky.social/abouthttps://syu.is/privacy-policy`, - community: `https://bsky.social/about/support/community-guidelines`, +- community: `https://bsky.social/about/support/community-guidelines`, ++ tos: `https://syu.is/about/support/tos`, ++ privacy: `https://syu.is/about/support/privacy-policy`, ++ community: `https://syu.is/about/support/community-guidelines`, communityDeprecated: `https://bsky.social/about/support/community-guidelines-deprecated`, } -diff --git a/src/lib/statsig/statsig.tsx b/src/lib/statsig/statsig.tsx -index 860e841eb..a595b0868 100644 ---- a/src/lib/statsig/statsig.tsx -+++ b/src/lib/statsig/statsig.tsx -@@ -265,6 +265,7 @@ export async function tryFetchGates( - } - - export function initialize() { -+ if (!SDK_KEY) return Promise.resolve() - return Statsig.initialize(SDK_KEY, null, createStatsigOptions([])) - } - -@@ -309,6 +310,9 @@ export function Provider({children}: {children: React.ReactNode}) { - return () => clearInterval(id) - }, [handleIntervalTick]) - -+ if (!SDK_KEY) { -+ return {children} -+ } - return ( - - ({ @@ -21,52 +30,20 @@ index 1ed913bb2..c80340edb 100644 Support: '/support', - PrivacyPolicy: '/support/privacy', - TermsOfService: '/support/tos', -+ PrivacyPolicy: 'https://syu.is/privacy', -+ TermsOfService: 'https://syu.is/terms', ++ 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/state/session/agent.ts b/src/state/session/agent.ts -index 5c8ce3b97..ee85beb08 100644 +index 725679ba2..9d40fe2c4 100644 --- a/src/state/session/agent.ts +++ b/src/state/session/agent.ts -@@ -47,7 +47,8 @@ export function createPublicAgent() { - configureModerationForGuest() // Side effect but only relevant for tests - - const agent = new BskyAppAgent({service: PUBLIC_BSKY_SERVICE}) -- agent.configureProxy(BLUESKY_PROXY_HEADER.get()) -+ // Disable proxy for self-hosted environments -+ // agent.configureProxy(BLUESKY_PROXY_HEADER.get()) - return agent - } - -@@ -88,7 +89,8 @@ export async function createAgentAndResume( - // after session is attached - const aa = prefetchAgeAssuranceData({agent}) - -- agent.configureProxy(BLUESKY_PROXY_HEADER.get()) -+ // Disable proxy for self-hosted environments -+ // agent.configureProxy(BLUESKY_PROXY_HEADER.get()) - - return agent.prepare({ - resolvers: [gates, moderation, aa], -@@ -127,7 +129,8 @@ export async function createAgentAndLogin( - const moderation = configureModerationForAccount(agent, account) - const aa = prefetchAgeAssuranceData({agent}) - -- agent.configureProxy(BLUESKY_PROXY_HEADER.get()) -+ // Disable proxy for self-hosted environments -+ // agent.configureProxy(BLUESKY_PROXY_HEADER.get()) - - return agent.prepare({ - resolvers: [gates, moderation, aa], -@@ -299,7 +302,8 @@ export async function createAgentAndCreateAccount( - logger.error(e, {message: `session: failed snoozeEmailConfirmationPrompt`}) +@@ -83,7 +83,7 @@ export function getAgent() { + if (prevServiceUrl !== publicAgent.service.toString()) { + logger.warn(`Public Agent service URL changed`, {prevServiceUrl}) } - -- agent.configureProxy(BLUESKY_PROXY_HEADER.get()) -+ // Disable proxy for self-hosted environments -+ // agent.configureProxy(BLUESKY_PROXY_HEADER.get()) - - return agent.prepare({ - resolvers: [gates, moderation, aa], +- activeAgent.configureProxy(BLUESKY_PROXY_HEADER) ++ // activeAgent.configureProxy(BLUESKY_PROXY_HEADER) + return activeAgent + } diff --git a/ios/patching/005-social-app-ios-screens.patch b/ios/patching/005-social-app-ios-screens.patch index b13869d..1a0058a 100644 --- a/ios/patching/005-social-app-ios-screens.patch +++ b/ios/patching/005-social-app-ios-screens.patch @@ -1,462 +1,51 @@ diff --git a/src/screens/Settings/AboutSettings.tsx b/src/screens/Settings/AboutSettings.tsx -index 6b8257b91..35202224b 100644 +index 585c490a7..db747a8d5 100644 --- a/src/screens/Settings/AboutSettings.tsx +++ b/src/screens/Settings/AboutSettings.tsx -@@ -80,7 +80,7 @@ export function AboutSettingsScreen({}: Props) { +@@ -80,15 +80,15 @@ export function AboutSettingsScreen({}: Props) { -@@ -88,7 +88,7 @@ export function AboutSettingsScreen({}: Props) { + Terms of Service diff --git a/src/screens/Takendown.tsx b/src/screens/Takendown.tsx -index dd319a4c6..0e80f956a 100644 +index 451a3780f..a2818a514 100644 --- a/src/screens/Takendown.tsx +++ b/src/screens/Takendown.tsx -@@ -223,11 +223,11 @@ export function Takendown() { - +@@ -224,7 +224,7 @@ export function Takendown() { Your account was found to be in violation of the{' '} -- Bluesky Social Terms of Service -+ syu.is Terms of Service - - . You have been sent an email outlining the specific violation - and suspension period, if applicable. You can appeal this -diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx -index e058e2883..0f583c915 100644 ---- a/src/view/screens/Home.tsx -+++ b/src/view/screens/Home.tsx -@@ -1,23 +1,16 @@ - import React from 'react' - import {ActivityIndicator, StyleSheet} from 'react-native' - import {useFocusEffect} from '@react-navigation/native' -- - import {PROD_DEFAULT_FEED} from '#/lib/constants' - import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' - import {useOTAUpdates} from '#/lib/hooks/useOTAUpdates' - import {useSetTitle} from '#/lib/hooks/useSetTitle' - import {useRequestNotificationsPermission} from '#/lib/notifications/notifications' --import { -- type HomeTabNavigatorParams, -- type NativeStackScreenProps, --} from '#/lib/routes/types' -+import {type HomeTabNavigatorParams, type NativeStackScreenProps} from '#/lib/routes/types' - import {logEvent} from '#/lib/statsig/statsig' - import {isWeb} from '#/platform/detection' - import {emitSoftReset} from '#/state/events' --import { -- type SavedFeedSourceInfo, -- usePinnedFeedsInfos, --} from '#/state/queries/feed' -+import {type SavedFeedSourceInfo, usePinnedFeedsInfos} from '#/state/queries/feed' - import {type FeedDescriptor, type FeedParams} from '#/state/queries/post-feed' - import {usePreferencesQuery} from '#/state/queries/preferences' - import {type UsePreferencesQueryResponse} from '#/state/queries/preferences/types' -@@ -27,11 +20,7 @@ import {useLoggedOutViewControls} from '#/state/shell/logged-out' - import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed' - import {FeedPage} from '#/view/com/feeds/FeedPage' - import {HomeHeader} from '#/view/com/home/HomeHeader' --import { -- Pager, -- type PagerRef, -- type RenderTabBarFnProps, --} from '#/view/com/pager/Pager' -+import {Pager, type PagerRef, type RenderTabBarFnProps} from '#/view/com/pager/Pager' - import {CustomFeedEmptyState} from '#/view/com/posts/CustomFeedEmptyState' - import {FollowingEmptyState} from '#/view/com/posts/FollowingEmptyState' - import {FollowingEndOfFeed} from '#/view/com/posts/FollowingEndOfFeed' -@@ -39,97 +28,60 @@ import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned' - import * as Layout from '#/components/Layout' - import {useDemoMode} from '#/storage/hooks/demo-mode' - -+const DEFAULT_PINNED_FEEDS = [{ -+ feedDescriptor: 'following', -+ displayName: 'Following', -+ id: 'following', -+ type: 'feed', -+ savedFeed: undefined, -+ pinned: true, -+}] -+ - type Props = NativeStackScreenProps - export function HomeScreen(props: Props) { - const {setShowLoggedOut} = useLoggedOutViewControls() - const {data: preferences} = usePreferencesQuery() - const {currentAccount} = useSession() -- const {data: pinnedFeedInfos, isLoading: isPinnedFeedsLoading} = -- usePinnedFeedsInfos() -+ const {data: pinnedFeedInfos} = usePinnedFeedsInfos() -+ -+ const safePreferences = preferences || { feedViewPrefs: { lab_mergeFeedEnabled: false }, savedFeeds: [] } as any -+ const safePinnedFeedInfos = pinnedFeedInfos || DEFAULT_PINNED_FEEDS - - React.useEffect(() => { - if (isWeb && !currentAccount) { - const getParams = new URLSearchParams(window.location.search) - const splash = getParams.get('splash') -- if (splash === 'true') { -- setShowLoggedOut(true) -- return -- } -+ if (splash === 'true') { setShowLoggedOut(true); return } - } -- - const params = props.route.params -- if ( -- currentAccount && -- props.route.name === 'Start' && -- params?.name && -- params?.rkey -- ) { -- props.navigation.navigate('StarterPack', { -- rkey: params.rkey, -- name: params.name, -- }) -+ if (currentAccount && props.route.name === 'Start' && params?.name && params?.rkey) { -+ props.navigation.navigate('StarterPack', { rkey: params.rkey, name: params.name }) - } -- }, [ -- currentAccount, -- props.navigation, -- props.route.name, -- props.route.params, -- setShowLoggedOut, -- ]) -+ }, [currentAccount, props.navigation, props.route.name, props.route.params, setShowLoggedOut]) - -- if (preferences && pinnedFeedInfos && !isPinnedFeedsLoading) { -- return ( -- -- -- -- ) -- } else { -- return ( -- -- -- -- -- -- ) -- } -+ return ( -+ -+ -+ -+ ) - } - --function HomeScreenReady({ -- preferences, -- pinnedFeedInfos, --}: Props & { -- preferences: UsePreferencesQueryResponse -- pinnedFeedInfos: SavedFeedSourceInfo[] --}) { -- const allFeeds = React.useMemo( -- () => pinnedFeedInfos.map(f => f.feedDescriptor), -- [pinnedFeedInfos], -- ) -- const maybeRawSelectedFeed: FeedDescriptor | undefined = -- useSelectedFeed() ?? allFeeds[0] -+function HomeScreenReady({preferences, pinnedFeedInfos}: any) { -+ const allFeeds = React.useMemo(() => pinnedFeedInfos.map(f => f.feedDescriptor), [pinnedFeedInfos]) -+ const maybeRawSelectedFeed = useSelectedFeed() ?? allFeeds[0] - const setSelectedFeed = useSetSelectedFeed() - const maybeFoundIndex = allFeeds.indexOf(maybeRawSelectedFeed) - const selectedIndex = Math.max(0, maybeFoundIndex) -- const maybeSelectedFeed: FeedDescriptor | undefined = allFeeds[selectedIndex] -+ const maybeSelectedFeed = allFeeds[selectedIndex] - const requestNotificationsPermission = useRequestNotificationsPermission() -- -+ - useSetTitle(pinnedFeedInfos[selectedIndex]?.displayName) - useOTAUpdates() -- -- React.useEffect(() => { -- requestNotificationsPermission('Home') -- }, [requestNotificationsPermission]) -+ React.useEffect(() => { requestNotificationsPermission('Home') }, [requestNotificationsPermission]) - - const pagerRef = React.useRef(null) - const lastPagerReportedIndexRef = React.useRef(selectedIndex) - React.useLayoutEffect(() => { -- // Since the pager is not a controlled component, adjust it imperatively -- // if the selected index gets out of sync with what it last reported. -- // This is supposed to only happen on the web when you use the right nav. - if (selectedIndex !== lastPagerReportedIndexRef.current) { - lastPagerReportedIndexRef.current = selectedIndex - pagerRef.current?.setPage(selectedIndex) -@@ -138,205 +90,43 @@ function HomeScreenReady({ - - const {hasSession} = useSession() - const setMinimalShellMode = useSetMinimalShellMode() -- useFocusEffect( -- React.useCallback(() => { -- setMinimalShellMode(false) -- }, [setMinimalShellMode]), -- ) -- -- useFocusEffect( -- useNonReactiveCallback(() => { -- if (maybeSelectedFeed) { -- logEvent('home:feedDisplayed', { -- index: selectedIndex, -- feedType: maybeSelectedFeed.split('|')[0], -- feedUrl: maybeSelectedFeed, -- reason: 'focus', -- }) -- } -- }), -- ) -- -- const onPageSelected = React.useCallback( -- (index: number) => { -- setMinimalShellMode(false) -- const maybeFeed = allFeeds[index] -- -- // Mutate the ref before setting state to avoid the imperative syncing effect -- // above from starting a loop on Android when swiping back and forth. -- lastPagerReportedIndexRef.current = index -- setSelectedFeed(maybeFeed) -- -- if (maybeFeed) { -- logEvent('home:feedDisplayed', { -- index, -- feedType: maybeFeed.split('|')[0], -- feedUrl: maybeFeed, -- }) -- } -- }, -- [setSelectedFeed, setMinimalShellMode, allFeeds], -- ) -- -- const onPressSelected = React.useCallback(() => { -- emitSoftReset() -- }, []) -- -- const onPageScrollStateChanged = React.useCallback( -- (state: 'idle' | 'dragging' | 'settling') => { -- 'worklet' -- if (state === 'dragging') { -- setMinimalShellMode(false) -- } -- }, -- [setMinimalShellMode], -- ) -+ useFocusEffect(React.useCallback(() => { setMinimalShellMode(false) }, [setMinimalShellMode])) -+ -+ const onPageSelected = React.useCallback((index) => { -+ setMinimalShellMode(false) -+ const maybeFeed = allFeeds[index] -+ lastPagerReportedIndexRef.current = index -+ setSelectedFeed(maybeFeed) -+ }, [setSelectedFeed, setMinimalShellMode, allFeeds]) -+ -+ const onPressSelected = React.useCallback(() => { emitSoftReset() }, []) -+ const onPageScrollStateChanged = React.useCallback((state) => { -+ 'worklet' -+ if (state === 'dragging') setMinimalShellMode(false) -+ }, [setMinimalShellMode]) - - const [demoMode] = useDemoMode() -- -- const renderTabBar = React.useCallback( -- (props: RenderTabBarFnProps) => { -- if (demoMode) { -- return ( -- -- ) -- } -- return ( -- -- ) -- }, -- [onPressSelected, pinnedFeedInfos, demoMode], -- ) -- -- const renderFollowingEmptyState = React.useCallback(() => { -- return -- }, []) -- -- const renderCustomFeedEmptyState = React.useCallback(() => { -- return -- }, []) -- -- const homeFeedParams = React.useMemo(() => { -- return { -- mergeFeedEnabled: Boolean(preferences.feedViewPrefs.lab_mergeFeedEnabled), -- mergeFeedSources: preferences.feedViewPrefs.lab_mergeFeedEnabled -- ? preferences.savedFeeds -- .filter(f => f.type === 'feed' || f.type === 'list') -- .map(f => f.value) -- : [], -- } -- }, [preferences]) -- -- if (demoMode) { -- return ( -- -- -- -- -- ) -- } -- -- return hasSession ? ( -- -- {pinnedFeedInfos.length ? ( -- pinnedFeedInfos.map((feedInfo, index) => { -+ const renderTabBar = React.useCallback((props) => { -+ return -+ }, [onPressSelected, pinnedFeedInfos]) -+ -+ const renderFollowingEmptyState = React.useCallback(() => , []) -+ const renderCustomFeedEmptyState = React.useCallback(() => , []) -+ -+ const homeFeedParams = React.useMemo(() => ({ -+ mergeFeedEnabled: false, mergeFeedSources: [] -+ }), [preferences]) -+ -+ return ( -+ -+ {pinnedFeedInfos.map((feedInfo, index) => { - const feed = feedInfo.feedDescriptor - if (feed === 'following') { -- return ( -- -- ) -+ return - } -- const savedFeedConfig = feedInfo.savedFeed -- return ( -- -- ) -- }) -- ) : ( -- -- )} -- -- ) : ( -- -- -+ return -+ })} - - ) - } -- --const styles = StyleSheet.create({ -- loading: { -- height: '100%', -- alignContent: 'center', -- justifyContent: 'center', -- paddingBottom: 100, -- }, --}) -+const styles = StyleSheet.create({ loading: { height: '100%', alignContent: 'center', justifyContent: 'center', paddingBottom: 100 } }) + Bluesky Social Terms of Service diff --git a/src/view/screens/PrivacyPolicy.tsx b/src/view/screens/PrivacyPolicy.tsx -index a89eaadc4..228af4966 100644 +index 57471239c..e8888b52f 100644 --- a/src/view/screens/PrivacyPolicy.tsx +++ b/src/view/screens/PrivacyPolicy.tsx -@@ -1,52 +1,13 @@ - import React from 'react' +@@ -1,52 +1,11 @@ +-import React from 'react' -import {View} from 'react-native' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import {useFocusEffect} from '@react-navigation/native' -- ++import React from 'react'; ++import { WebView } from 'react-native-webview'; + -import {usePalette} from '#/lib/hooks/usePalette' -import { - type CommonNavigatorParams, @@ -467,12 +56,14 @@ index a89eaadc4..228af4966 100644 -import {TextLink} from '#/view/com/util/Link' -import {Text} from '#/view/com/util/text/Text' -import {ScrollView} from '#/view/com/util/Views' -+import { WebView } from 'react-native-webview' - import * as Layout from '#/components/Layout' +-import * as Layout from '#/components/Layout' -import {ViewHeader} from '../com/util/ViewHeader' -- ++import { type CommonNavigatorParams, type NativeStackScreenProps } from '#/lib/routes/types'; + -type Props = NativeStackScreenProps --export const PrivacyPolicyScreen = (_props: Props) => { ++type Props = NativeStackScreenProps; ++ + export const PrivacyPolicyScreen = (_props: Props) => { - const pal = usePalette('default') - const {_} = useLingui() - const setMinimalShellMode = useSetMinimalShellMode() @@ -482,12 +73,9 @@ index a89eaadc4..228af4966 100644 - setMinimalShellMode(false) - }, [setMinimalShellMode]), - ) -+import {useSetTitle} from '#/lib/hooks/useSetTitle' - -+export function PrivacyPolicyScreen() { -+ useSetTitle('Privacy Policy') - return ( - +- +- return ( +- - - - @@ -504,21 +92,24 @@ index a89eaadc4..228af4966 100644 - - - -+ - - ) - } +- +- ) +-} ++ return ; ++}; diff --git a/src/view/screens/TermsOfService.tsx b/src/view/screens/TermsOfService.tsx -index d843c713c..c0b34c886 100644 +index 101869e54..92850901e 100644 --- a/src/view/screens/TermsOfService.tsx +++ b/src/view/screens/TermsOfService.tsx -@@ -1,50 +1,13 @@ - import React from 'react' +@@ -1,51 +1,11 @@ +-import React from 'react' -import {View} from 'react-native' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import {useFocusEffect} from '@react-navigation/native' -- ++import React from 'react'; ++import { WebView } from 'react-native-webview'; + -import {usePalette} from '#/lib/hooks/usePalette' -import { - type CommonNavigatorParams, @@ -529,12 +120,14 @@ index d843c713c..c0b34c886 100644 -import {TextLink} from '#/view/com/util/Link' -import {Text} from '#/view/com/util/text/Text' -import {ScrollView} from '#/view/com/util/Views' -+import { WebView } from 'react-native-webview' - import * as Layout from '#/components/Layout' +-import * as Layout from '#/components/Layout' -import {ViewHeader} from '../com/util/ViewHeader' -- ++import { type CommonNavigatorParams, type NativeStackScreenProps } from '#/lib/routes/types'; + -type Props = NativeStackScreenProps --export const TermsOfServiceScreen = (_props: Props) => { ++type Props = NativeStackScreenProps; ++ + export const TermsOfServiceScreen = (_props: Props) => { - const pal = usePalette('default') - const setMinimalShellMode = useSetMinimalShellMode() - const {_} = useLingui() @@ -544,12 +137,9 @@ index d843c713c..c0b34c886 100644 - setMinimalShellMode(false) - }, [setMinimalShellMode]), - ) -+import {useSetTitle} from '#/lib/hooks/useSetTitle' - -+export function TermsOfServiceScreen() { -+ useSetTitle('Terms of Service') - return ( - +- +- return ( +- - - - @@ -564,7 +154,8 @@ index d843c713c..c0b34c886 100644 - - - -+ - - ) - } +- +- ) +-} ++ return ; ++}; diff --git a/ios/patching/006-social-app-ios-shell.patch b/ios/patching/006-social-app-ios-shell.patch index 2b81dda..8349cb7 100644 --- a/ios/patching/006-social-app-ios-shell.patch +++ b/ios/patching/006-social-app-ios-shell.patch @@ -2,12 +2,12 @@ diff --git a/src/components/dialogs/BirthDateSettings.tsx b/src/components/dialo index 9915d0a2d..c200a7c67 100644 --- a/src/components/dialogs/BirthDateSettings.tsx +++ b/src/components/dialogs/BirthDateSettings.tsx -@@ -163,7 +163,7 @@ function BirthdayInner({ +@@ -166,7 +166,7 @@ function BirthdayInner({ You must be at least 13 years old to use Bluesky. Read our{' '} Terms of Service {' '} @@ -15,7 +15,7 @@ diff --git a/src/components/dialogs/ServerInput.tsx b/src/components/dialogs/Ser index d7c02bb9f..fda1dfe4a 100644 --- a/src/components/dialogs/ServerInput.tsx +++ b/src/components/dialogs/ServerInput.tsx -@@ -165,7 +165,7 @@ function DialogInner({ +@@ -167,7 +167,7 @@ function DialogInner({ Bluesky is an open network where you can choose your own provider. If you're new here, we recommend sticking with the @@ -28,64 +28,13 @@ diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx index ed2a6cfb7..2f387b4a8 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' +@@ -9,7 +9,6 @@ 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 { + import {type PressableScale} from '#/lib/custom-animations/PressableScale' + import {useNavigationTabState} from '#/lib/hooks/useNavigationTabState' +@@ -33,22 +32,10 @@ import { Bell_Filled_Corner0_Rounded as BellFilled, Bell_Stroke2_Corner0_Rounded as Bell, } from '#/components/icons/Bell' @@ -99,68 +48,15 @@ index ed2a6cfb7..2f387b4a8 100644 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 {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 {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 => { +@@ -153,11 +140,7 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { const { isAtHome, isAtSearch, @@ -170,76 +66,26 @@ index ed2a6cfb7..2f387b4a8 100644 isAtMyProfile, - isAtMessages, } = useNavigationTabState() -- const {hasSession, currentAccount} = useSession() -- -- // events -- // = -+ const { hasSession, currentAccount } = useSession() + 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 => { +@@ -212,31 +195,6 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { + [onPressTab], ) - 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 onPressNotifications = React.useCallback( + () => onPressTab('Notifications'), + [onPressTab], + ) + + const onPressProfile = React.useCallback(() => { + onPressTab('MyProfile') + }, [onPressTab]) + - const onPressMyFeeds = React.useCallback(() => { - navigation.navigate('Feeds') - setDrawerOpen(false) @@ -255,9 +101,6 @@ index ed2a6cfb7..2f387b4a8 100644 - 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) @@ -281,31 +124,7 @@ index ed2a6cfb7..2f387b4a8 100644 - 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 => { +@@ -295,19 +253,10 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { <> @@ -323,7 +142,7 @@ index ed2a6cfb7..2f387b4a8 100644 ): React.ReactNode => { +@@ -315,7 +264,6 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { ) : ( <> @@ -331,7 +150,7 @@ index ed2a6cfb7..2f387b4a8 100644 )} -@@ -322,69 +230,11 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { +@@ -326,71 +274,12 @@ let DrawerContent = ({}: React.PropsWithoutRef<{}>): React.ReactNode => { @@ -343,9 +162,7 @@ index ed2a6cfb7..2f387b4a8 100644 ) } - DrawerContent = React.memo(DrawerContent) --export {DrawerContent} -- + -let DrawerFooter = ({ - onPressFeedback, - onPressHelp, @@ -398,29 +215,11 @@ index ed2a6cfb7..2f387b4a8 100644 - ) -} -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 { _ } = 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 = ({ +@@ -512,110 +375,6 @@ let NotificationsMenuItem = ({ } NotificationsMenuItem = React.memo(NotificationsMenuItem) @@ -552,162 +325,37 @@ index ed2a6cfb7..2f387b4a8 100644 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 ( - -- -- -- ) --} --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 ( -