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..fd7d591 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..045f660ef 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..324b270af 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/009-social-app-ios-license.patch b/ios/patching/009-social-app-ios-license.patch
index 0d94461..70b7509 100644
--- a/ios/patching/009-social-app-ios-license.patch
+++ b/ios/patching/009-social-app-ios-license.patch
@@ -34,15 +34,719 @@ index c315a8341..9b2f50a83 100644
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..f98cd6afc
+--- /dev/null
++++ b/src/view/screens/License.tsx
+@@ -0,0 +1,86 @@
++import React from 'react'
++import { ScrollView } from 'react-native'
++import * as Layout from '#/components/Layout'
++import {useSetTitle} from '#/lib/hooks/useSetTitle'
++import {atoms as a, useTheme} from '#/alf'
++import {Text} from '#/components/Typography'
++
++export function LicenseScreen() {
++ useSetTitle('License')
++ const t = useTheme()
++
++ return (
++
++
++ License
++
++
++ This application is based on Bluesky Social App.
++
++
++
++ https://github.com/bluesky-social/social-app
++
++
++ MIT License
++
++
++ Copyright (c) 2022-2025 Bluesky PBC
++
++
++
++ Permission is hereby granted, free of charge, to any person obtaining a copy
++ of this software and associated documentation files (the "Software"), to deal
++ in the Software without restriction, including without limitation the rights
++ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ copies of the Software, and to permit persons to whom the Software is
++ furnished to do so, subject to the following conditions:
++
++
++
++ The above copyright notice and this permission notice shall be included in all
++ copies or substantial portions of the Software.
++
++
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ SOFTWARE.
++
++
++ 日本語訳(参考)
++
++
++ 本ソフトウェアおよび関連文書ファイル(以下「ソフトウェア」)のコピーを取得する
++ すべての人に対し、ソフトウェアを無制限に扱うことを無償で許可します。これには、
++ ソフトウェアのコピーを使用、複製、変更、結合、公開、配布、サブライセンス、
++ および/または販売する権利、ならびにソフトウェアを提供する相手にそうした行為を
++ 許可する権利が含まれますが、これらに限定されません。
++
++
++
++ 上記の著作権表示および本許諾表示を、ソフトウェアのすべてのコピーまたは
++ 重要な部分に記載するものとします。
++
++
++
++ ソフトウェアは「現状のまま」で提供され、明示黙示を問わず、商品性、特定目的への
++ 適合性、および権利非侵害についての保証を含む、いかなる種類の保証もなされません。
++ いかなる場合においても、作者または著作権者は、契約行為、不法行為、またはそれ以外で
++ あろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用または
++ その他の扱いによって生じる一切の請求、損害、その他の義務について責任を負わないものとします。
++
++
++
++ Original License: https://github.com/bluesky-social/social-app/blob/main/LICENSE
++
++
++
++ )
++}
diff --git a/src/view/shell/Drawer.tsx b/src/view/shell/Drawer.tsx
-index ed2a6cfb7..0b429e6f3 100644
+index ed2a6cfb7..982c40b55 100644
--- a/src/view/shell/Drawer.tsx
+++ b/src/view/shell/Drawer.tsx
-@@ -460,6 +460,11 @@ function ExtraLinks() {
-
- Privacy Policy
+@@ -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 (
+
++ navigation.navigate('PrivacyPolicy')}>
++
++ Privacy Policy
++
++
+ navigation.navigate('License')}>
+
+ License
diff --git a/ios/patching/021-social-app-ios-clean-feed.patch b/ios/patching/021-social-app-ios-clean-feed.patch
index b1be019..1d7cc0a 100644
--- a/ios/patching/021-social-app-ios-clean-feed.patch
+++ b/ios/patching/021-social-app-ios-clean-feed.patch
@@ -1,21 +1,60 @@
-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'
-
-+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()
+diff --git a/src/view/com/posts/FollowingEmptyState.tsx b/src/view/com/posts/FollowingEmptyState.tsx
+index 352cc1dc0..06987be51 100644
+--- a/src/view/com/posts/FollowingEmptyState.tsx
++++ b/src/view/com/posts/FollowingEmptyState.tsx
+@@ -45,36 +45,6 @@ export function FollowingEmptyState() {
+ happening.
+
+
+-
+-
+-
+- 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..c35ad1c1a 100644
+--- a/src/view/com/posts/PostFeed.tsx
++++ b/src/view/com/posts/PostFeed.tsx
+@@ -543,14 +543,6 @@ 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,
+- })
+- }
+ }
+ } else if (feedKind === 'profile') {
+ if (sliceIndex === 5) {