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 83015ec..9fa76b9 100644
--- a/ios/patching/008-social-app-ios-policy-tos-error.patch
+++ b/ios/patching/008-social-app-ios-policy-tos-error.patch
@@ -1,8 +1,8 @@
diff --git a/src/view/screens/PrivacyPolicy.tsx b/src/view/screens/PrivacyPolicy.tsx
-index a89eaadc4..1da393f03 100644
+index a89eaadc4..787a1409b 100644
--- a/src/view/screens/PrivacyPolicy.tsx
+++ b/src/view/screens/PrivacyPolicy.tsx
-@@ -1,52 +1,13 @@
+@@ -1,51 +1,28 @@
import React from 'react'
-import {View} from 'react-native'
-import {msg, Trans} from '@lingui/macro'
@@ -19,7 +19,7 @@ index a89eaadc4..1da393f03 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 { ScrollView } from 'react-native'
import * as Layout from '#/components/Layout'
-import {ViewHeader} from '../com/util/ViewHeader'
-
@@ -28,16 +28,19 @@ index a89eaadc4..1da393f03 100644
- const pal = usePalette('default')
- const {_} = useLingui()
- const setMinimalShellMode = useSetMinimalShellMode()
--
++import { useSetTitle } from '#/lib/hooks/useSetTitle'
++import { atoms as a, useTheme } from '#/alf'
++import { Text } from '#/components/Typography'
+
- useFocusEffect(
- React.useCallback(() => {
- setMinimalShellMode(false)
- }, [setMinimalShellMode]),
- )
-+import {useSetTitle} from '#/lib/hooks/useSetTitle'
-
+export function PrivacyPolicyScreen() {
+ useSetTitle('Privacy Policy')
++ const t = useTheme()
+
return (
-
@@ -55,16 +58,26 @@ index a89eaadc4..1da393f03 100644
-
-
-
--
-+
++
++ Privacy Policy
++
++
++ Please refer to the following page for the Privacy Policy.
++
++
++
++ https://syu.is/about/support/privacy-policy
++
+
)
- }
diff --git a/src/view/screens/TermsOfService.tsx b/src/view/screens/TermsOfService.tsx
-index d843c713c..b81767bd5 100644
+index d843c713c..28333cc5b 100644
--- a/src/view/screens/TermsOfService.tsx
+++ b/src/view/screens/TermsOfService.tsx
-@@ -1,50 +1,13 @@
+@@ -1,49 +1,28 @@
import React from 'react'
-import {View} from 'react-native'
-import {msg, Trans} from '@lingui/macro'
@@ -81,7 +94,7 @@ index d843c713c..b81767bd5 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 { ScrollView } from 'react-native'
import * as Layout from '#/components/Layout'
-import {ViewHeader} from '../com/util/ViewHeader'
-
@@ -90,16 +103,19 @@ index d843c713c..b81767bd5 100644
- const pal = usePalette('default')
- const setMinimalShellMode = useSetMinimalShellMode()
- const {_} = useLingui()
--
++import { useSetTitle } from '#/lib/hooks/useSetTitle'
++import { atoms as a, useTheme } from '#/alf'
++import { Text } from '#/components/Typography'
+
- useFocusEffect(
- React.useCallback(() => {
- setMinimalShellMode(false)
- }, [setMinimalShellMode]),
- )
-+import {useSetTitle} from '#/lib/hooks/useSetTitle'
-
+export function TermsOfServiceScreen() {
+ useSetTitle('Terms of Service')
++ const t = useTheme()
+
return (
-
@@ -115,8 +131,18 @@ index d843c713c..b81767bd5 100644
-
-
-
--
-+
++
++ Terms of Service
++
++
++ Please refer to the following page for the Terms of Service.
++
++
++
++ https://syu.is/about/support/tos
++
+
)
- }
diff --git a/ios/patching/021-social-app-ios-clean-feed.patch b/ios/patching/021-social-app-ios-clean-feed.patch
index b1be019..972bb28 100644
--- a/ios/patching/021-social-app-ios-clean-feed.patch
+++ b/ios/patching/021-social-app-ios-clean-feed.patch
@@ -1,21 +1,553 @@
-diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx
-index e058e2883..e762b1418 100644
---- a/src/view/screens/Home.tsx
-+++ b/src/view/screens/Home.tsx
-@@ -39,6 +39,16 @@ import {NoFeedsPinned} from '#/screens/Home/NoFeedsPinned'
- import * as Layout from '#/components/Layout'
- import {useDemoMode} from '#/storage/hooks/demo-mode'
+diff --git a/src/view/com/posts/FollowingEmptyState.tsx b/src/view/com/posts/FollowingEmptyState.tsx
+index 352cc1dc0..a1bae1b05 100644
+--- a/src/view/com/posts/FollowingEmptyState.tsx
++++ b/src/view/com/posts/FollowingEmptyState.tsx
+@@ -1,19 +1,19 @@
+ import React from 'react'
+-import {StyleSheet, View} from 'react-native'
++import { StyleSheet, View } from 'react-native'
+ import {
+ FontAwesomeIcon,
+ type FontAwesomeIconStyle,
+ } from '@fortawesome/react-native-fontawesome'
+-import {Trans} from '@lingui/macro'
+-import {useNavigation} from '@react-navigation/native'
++import { Trans } from '@lingui/macro'
++import { useNavigation } from '@react-navigation/native'
-+const DEFAULT_PINNED_FEEDS = [{
-+ feedDescriptor: 'following',
-+ displayName: 'Following',
-+ id: 'following',
-+ type: 'feed',
-+ savedFeed: undefined,
-+ pinned: true,
-+}]
+-import {usePalette} from '#/lib/hooks/usePalette'
+-import {MagnifyingGlassIcon} from '#/lib/icons'
+-import {type NavigationProp} from '#/lib/routes/types'
+-import {s} from '#/lib/styles'
+-import {isWeb} from '#/platform/detection'
+-import {Button} from '../util/forms/Button'
+-import {Text} from '../util/text/Text'
++import { usePalette } from '#/lib/hooks/usePalette'
++import { MagnifyingGlassIcon } from '#/lib/icons'
++import { type NavigationProp } from '#/lib/routes/types'
++import { s } from '#/lib/styles'
++import { isWeb } from '#/platform/detection'
++import { Button } from '../util/forms/Button'
++import { Text } from '../util/text/Text'
+
+ export function FollowingEmptyState() {
+ const pal = usePalette('default')
+@@ -45,36 +45,6 @@ export function FollowingEmptyState() {
+ happening.
+
+
+-
+-
+-
+- You can also discover new Custom Feeds to follow.
+-
+-
+
+
+ )
+diff --git a/src/view/com/posts/FollowingEndOfFeed.tsx b/src/view/com/posts/FollowingEndOfFeed.tsx
+index e3c84d782..362ff1ed2 100644
+--- a/src/view/com/posts/FollowingEndOfFeed.tsx
++++ b/src/view/com/posts/FollowingEndOfFeed.tsx
+@@ -1,18 +1,18 @@
+ import React from 'react'
+-import {Dimensions, StyleSheet, View} from 'react-native'
++import { Dimensions, StyleSheet, View } from 'react-native'
+ import {
+ FontAwesomeIcon,
+ type FontAwesomeIconStyle,
+ } from '@fortawesome/react-native-fontawesome'
+-import {Trans} from '@lingui/macro'
+-import {useNavigation} from '@react-navigation/native'
++import { Trans } from '@lingui/macro'
++import { useNavigation } from '@react-navigation/native'
+
+-import {usePalette} from '#/lib/hooks/usePalette'
+-import {type NavigationProp} from '#/lib/routes/types'
+-import {s} from '#/lib/styles'
+-import {isWeb} from '#/platform/detection'
+-import {Button} from '../util/forms/Button'
+-import {Text} from '../util/text/Text'
++import { usePalette } from '#/lib/hooks/usePalette'
++import { type NavigationProp } from '#/lib/routes/types'
++import { s } from '#/lib/styles'
++import { isWeb } from '#/platform/detection'
++import { Button } from '../util/forms/Button'
++import { Text } from '../util/text/Text'
+
+ export function FollowingEndOfFeed() {
+ const pal = usePalette('default')
+@@ -37,45 +37,14 @@ export function FollowingEndOfFeed() {
+ style={[
+ styles.container,
+ pal.border,
+- {minHeight: Dimensions.get('window').height * 0.75},
++ { minHeight: Dimensions.get('window').height * 0.75 },
+ ]}>
+
+
+
+- You've reached the end of your feed! Find some more accounts to
+- follow.
++ You've reached the end of your feed!
+
+
+-
+-
+-
+- You can also discover new Custom Feeds to follow.
+-
+-
+
+
+ )
+diff --git a/src/view/com/posts/PostFeed.tsx b/src/view/com/posts/PostFeed.tsx
+index 4f25468c9..0a678a217 100644
+--- a/src/view/com/posts/PostFeed.tsx
++++ b/src/view/com/posts/PostFeed.tsx
+@@ -23,23 +23,23 @@ import {
+ AppBskyEmbedVideo,
+ type AppBskyFeedDefs,
+ } from '@atproto/api'
+-import {msg} from '@lingui/macro'
+-import {useLingui} from '@lingui/react'
+-import {useQueryClient} from '@tanstack/react-query'
++import { msg } from '@lingui/macro'
++import { useLingui } from '@lingui/react'
++import { useQueryClient } from '@tanstack/react-query'
+
+-import {isStatusStillActive, validateStatus} from '#/lib/actor-status'
+-import {DISCOVER_FEED_URI, KNOWN_SHUTDOWN_FEEDS} from '#/lib/constants'
+-import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
+-import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
+-import {logEvent, useGate} from '#/lib/statsig/statsig'
+-import {isNetworkError} from '#/lib/strings/errors'
+-import {logger} from '#/logger'
+-import {isIOS, isNative, isWeb} from '#/platform/detection'
+-import {usePostAuthorShadowFilter} from '#/state/cache/profile-shadow'
+-import {listenPostCreated} from '#/state/events'
+-import {useFeedFeedbackContext} from '#/state/feed-feedback'
+-import {useTrendingSettings} from '#/state/preferences/trending'
+-import {STALE} from '#/state/queries'
++import { isStatusStillActive, validateStatus } from '#/lib/actor-status'
++import { DISCOVER_FEED_URI, KNOWN_SHUTDOWN_FEEDS } from '#/lib/constants'
++import { useInitialNumToRender } from '#/lib/hooks/useInitialNumToRender'
++import { useNonReactiveCallback } from '#/lib/hooks/useNonReactiveCallback'
++import { logEvent, useGate } from '#/lib/statsig/statsig'
++import { isNetworkError } from '#/lib/strings/errors'
++import { logger } from '#/logger'
++import { isIOS, isNative, isWeb } from '#/platform/detection'
++import { usePostAuthorShadowFilter } from '#/state/cache/profile-shadow'
++import { listenPostCreated } from '#/state/events'
++import { useFeedFeedbackContext } from '#/state/feed-feedback'
++import { useTrendingSettings } from '#/state/preferences/trending'
++import { STALE } from '#/state/queries'
+ import {
+ type AuthorFilter,
+ type FeedDescriptor,
+@@ -50,111 +50,111 @@ import {
+ RQKEY,
+ usePostFeedQuery,
+ } from '#/state/queries/post-feed'
+-import {useLiveNowConfig} from '#/state/service-config'
+-import {useSession} from '#/state/session'
+-import {useProgressGuide} from '#/state/shell/progress-guide'
+-import {useSelectedFeed} from '#/state/shell/selected-feed'
+-import {List, type ListRef} from '#/view/com/util/List'
+-import {PostFeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
+-import {LoadMoreRetryBtn} from '#/view/com/util/LoadMoreRetryBtn'
+-import {type VideoFeedSourceContext} from '#/screens/VideoFeed/types'
+-import {useBreakpoints, useLayoutBreakpoints} from '#/alf'
++import { useLiveNowConfig } from '#/state/service-config'
++import { useSession } from '#/state/session'
++import { useProgressGuide } from '#/state/shell/progress-guide'
++import { useSelectedFeed } from '#/state/shell/selected-feed'
++import { List, type ListRef } from '#/view/com/util/List'
++import { PostFeedLoadingPlaceholder } from '#/view/com/util/LoadingPlaceholder'
++import { LoadMoreRetryBtn } from '#/view/com/util/LoadMoreRetryBtn'
++import { type VideoFeedSourceContext } from '#/screens/VideoFeed/types'
++import { useBreakpoints, useLayoutBreakpoints } from '#/alf'
+ import {
+ AgeAssuranceDismissibleFeedBanner,
+ useInternalState as useAgeAssuranceBannerState,
+ } from '#/components/ageAssurance/AgeAssuranceDismissibleFeedBanner'
+-import {ProgressGuide, SuggestedFollows} from '#/components/FeedInterstitials'
++import { ProgressGuide, SuggestedFollows } from '#/components/FeedInterstitials'
+ import {
+ PostFeedVideoGridRow,
+ PostFeedVideoGridRowPlaceholder,
+ } from '#/components/feeds/PostFeedVideoGridRow'
+-import {TrendingInterstitial} from '#/components/interstitials/Trending'
+-import {TrendingVideos as TrendingVideosInterstitial} from '#/components/interstitials/TrendingVideos'
+-import {ComposerPrompt} from '../feeds/ComposerPrompt'
+-import {DiscoverFallbackHeader} from './DiscoverFallbackHeader'
+-import {FeedShutdownMsg} from './FeedShutdownMsg'
+-import {PostFeedErrorMessage} from './PostFeedErrorMessage'
+-import {PostFeedItem} from './PostFeedItem'
+-import {ShowLessFollowup} from './ShowLessFollowup'
+-import {ViewFullThread} from './ViewFullThread'
++import { TrendingInterstitial } from '#/components/interstitials/Trending'
++import { TrendingVideos as TrendingVideosInterstitial } from '#/components/interstitials/TrendingVideos'
++import { ComposerPrompt } from '../feeds/ComposerPrompt'
++import { DiscoverFallbackHeader } from './DiscoverFallbackHeader'
++import { FeedShutdownMsg } from './FeedShutdownMsg'
++import { PostFeedErrorMessage } from './PostFeedErrorMessage'
++import { PostFeedItem } from './PostFeedItem'
++import { ShowLessFollowup } from './ShowLessFollowup'
++import { ViewFullThread } from './ViewFullThread'
+
+ type FeedRow =
+ | {
+- type: 'loading'
+- key: string
+- }
++ type: 'loading'
++ key: string
++ }
+ | {
+- type: 'empty'
+- key: string
+- }
++ type: 'empty'
++ key: string
++ }
+ | {
+- type: 'error'
+- key: string
+- }
++ type: 'error'
++ key: string
++ }
+ | {
+- type: 'loadMoreError'
+- key: string
+- }
++ type: 'loadMoreError'
++ key: string
++ }
+ | {
+- type: 'feedShutdownMsg'
+- key: string
+- }
++ type: 'feedShutdownMsg'
++ key: string
++ }
+ | {
+- type: 'fallbackMarker'
+- key: string
+- }
++ type: 'fallbackMarker'
++ key: string
++ }
+ | {
+- type: 'sliceItem'
+- key: string
+- slice: FeedPostSlice
+- indexInSlice: number
+- showReplyTo: boolean
+- }
++ type: 'sliceItem'
++ key: string
++ slice: FeedPostSlice
++ indexInSlice: number
++ showReplyTo: boolean
++ }
+ | {
+- type: 'videoGridRowPlaceholder'
+- key: string
+- }
++ type: 'videoGridRowPlaceholder'
++ key: string
++ }
+ | {
+- type: 'videoGridRow'
+- key: string
+- items: FeedPostSliceItem[]
+- sourceFeedUri: string
+- feedContexts: (string | undefined)[]
+- reqIds: (string | undefined)[]
+- }
++ type: 'videoGridRow'
++ key: string
++ items: FeedPostSliceItem[]
++ sourceFeedUri: string
++ feedContexts: (string | undefined)[]
++ reqIds: (string | undefined)[]
++ }
+ | {
+- type: 'sliceViewFullThread'
+- key: string
+- uri: string
+- }
++ type: 'sliceViewFullThread'
++ key: string
++ uri: string
++ }
+ | {
+- type: 'interstitialFollows'
+- key: string
+- }
++ type: 'interstitialFollows'
++ key: string
++ }
+ | {
+- type: 'interstitialProgressGuide'
+- key: string
+- }
++ type: 'interstitialProgressGuide'
++ key: string
++ }
+ | {
+- type: 'interstitialTrending'
+- key: string
+- }
++ type: 'interstitialTrending'
++ key: string
++ }
+ | {
+- type: 'interstitialTrendingVideos'
+- key: string
+- }
++ type: 'interstitialTrendingVideos'
++ key: string
++ }
+ | {
+- type: 'showLessFollowup'
+- key: string
+- }
++ type: 'showLessFollowup'
++ key: string
++ }
+ | {
+- type: 'ageAssuranceBanner'
+- key: string
+- }
++ type: 'ageAssuranceBanner'
++ key: string
++ }
+ | {
+- type: 'composerPrompt'
+- key: string
+- }
++ type: 'composerPrompt'
++ key: string
++ }
+
+ export function getItemsForFeedback(feedRow: FeedRow): {
+ item: FeedPostSliceItem
+@@ -227,17 +227,17 @@ let PostFeed = ({
+ initialNumToRender?: number
+ isVideoFeed?: boolean
+ }): React.ReactNode => {
+- const {_} = useLingui()
++ const { _ } = useLingui()
+ const queryClient = useQueryClient()
+- const {currentAccount, hasSession} = useSession()
++ const { currentAccount, hasSession } = useSession()
+ const gate = useGate()
+ const initialNumToRender = useInitialNumToRender()
+ const feedFeedback = useFeedFeedbackContext()
+ const [isPTRing, setIsPTRing] = useState(false)
+ const lastFetchRef = useRef(Date.now())
+ const [feedType, feedUriOrActorDid, feedTab] = feed.split('|')
+- const {gtMobile} = useBreakpoints()
+- const {rightNavVisible} = useLayoutBreakpoints()
++ const { gtMobile } = useBreakpoints()
++ const { rightNavVisible } = useLayoutBreakpoints()
+ const areVideoFeedsEnabled = isNative
+
+ const [hasPressedShowLessUris, setHasPressedShowLessUris] = useState(
+@@ -256,7 +256,7 @@ let PostFeed = ({
+
+ const feedCacheKey = feedParams?.feedCacheKey
+ const opts = useMemo(
+- () => ({enabled, ignoreFilterFor}),
++ () => ({ enabled, ignoreFilterFor }),
+ [enabled, ignoreFilterFor],
+ )
+ const {
+@@ -299,7 +299,7 @@ let PostFeed = ({
+ }
+ } catch (e) {
+ if (!isNetworkError(e)) {
+- logger.error('Poll latest failed', {feed, message: String(e)})
++ logger.error('Poll latest failed', { feed, message: String(e) })
+ }
+ }
+ })
+@@ -315,7 +315,7 @@ let PostFeed = ({
+ (feed === 'following' ||
+ feed === `author|${myDid}|posts_and_author_threads`)
+ ) {
+- queryClient.invalidateQueries({queryKey: RQKEY(feed)})
++ queryClient.invalidateQueries({ queryKey: RQKEY(feed) })
+ }
+ }, [queryClient, feed, data, myDid])
+ useEffect(() => {
+@@ -360,7 +360,7 @@ let PostFeed = ({
+ const showProgressIntersitial =
+ (followProgressGuide || followAndLikeProgressGuide) && !rightNavVisible
+
+- const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings()
++ const { trendingDisabled, trendingVideoDisabled } = useTrendingSettings()
+
+ const ageAssuranceBannerState = useAgeAssuranceBannerState()
+ const selectedFeed = useSelectedFeed()
+@@ -378,7 +378,7 @@ let PostFeed = ({
+ const feedItems: FeedRow[] = useMemo(() => {
+ // wraps a slice item, and replaces it with a showLessFollowup item
+ // if the user has pressed show less on it
+- const sliceItem = (row: Extract) => {
++ const sliceItem = (row: Extract) => {
+ if (hasPressedShowLessUris.has(row.slice.items[row.indexInSlice]?.uri)) {
+ return {
+ type: 'showLessFollowup',
+@@ -543,15 +543,8 @@ let PostFeed = ({
+ })
+ }
+ } else if (feedKind === 'following') {
+- if (sliceIndex === 0) {
+- // Show composer prompt for Following feed
+- if (hasSession && gate('show_composer_prompt')) {
+- arr.push({
+- type: 'composerPrompt',
+- key: 'composerPrompt-' + sliceIndex,
+- })
+- }
+- }
++ // user requests simple feed, no injections
+
-+
- type Props = NativeStackScreenProps
- export function HomeScreen(props: Props) {
- const {setShowLoggedOut} = useLoggedOutViewControls()
+ } else if (feedKind === 'profile') {
+ if (sliceIndex === 5) {
+ arr.push({
+@@ -699,7 +692,7 @@ let PostFeed = ({
+ await refetch()
+ onHasNew?.(false)
+ } catch (err) {
+- logger.error('Failed to refresh posts feed', {message: err})
++ logger.error('Failed to refresh posts feed', { message: err })
+ }
+ setIsPTRing(false)
+ }, [refetch, setIsPTRing, onHasNew, feed, feedType])
+@@ -715,7 +708,7 @@ let PostFeed = ({
+ try {
+ await fetchNextPage()
+ } catch (err) {
+- logger.error('Failed to load more posts', {message: err})
++ logger.error('Failed to load more posts', { message: err })
+ }
+ }, [
+ isFetching,
+@@ -740,7 +733,7 @@ let PostFeed = ({
+ // =
+
+ const renderItem = useCallback(
+- ({item: row, index: rowIndex}: ListRenderItemInfo) => {
++ ({ item: row, index: rowIndex }: ListRenderItemInfo) => {
+ if (row.type === 'empty') {
+ return renderEmptyState()
+ } else if (row.type === 'error') {
+@@ -877,12 +870,12 @@ let PostFeed = ({
+ return isFetchingNextPage ? (
+
+
+-
++
+
+ ) : shouldRenderEndOfFeed ? (
+- {renderEndOfFeed()}
++ {renderEndOfFeed()}
+ ) : (
+-
++
+ )
+ }, [isFetchingNextPage, shouldRenderEndOfFeed, renderEndOfFeed, headerOffset])
+
+@@ -944,7 +937,7 @@ let PostFeed = ({
+ feedDescriptor: feedFeedback.feedDescriptor || feed,
+ position,
+ },
+- {statsig: false},
++ { statsig: false },
+ )
+ }
+
+@@ -963,7 +956,7 @@ let PostFeed = ({
+ subject: actor.did,
+ feed,
+ },
+- {statsig: false},
++ { statsig: false },
+ )
+ }
+ }
+@@ -987,7 +980,7 @@ let PostFeed = ({
+ feedDescriptor: feedFeedback.feedDescriptor || feed,
+ position,
+ },
+- {statsig: false},
++ { statsig: false },
+ )
+ }
+ }
+@@ -1031,10 +1024,10 @@ let PostFeed = ({
+ )
+ }
+ PostFeed = memo(PostFeed)
+-export {PostFeed}
++export { PostFeed }
+
+ const styles = StyleSheet.create({
+- feedFooter: {paddingTop: 20},
++ feedFooter: { paddingTop: 20 },
+ })
+
+ export function isThreadParentAt(arr: Array, i: number) {