diff --git a/install.zsh b/install.zsh
index 48ed4d6..5e9c7d2 100755
--- a/install.zsh
+++ b/install.zsh
@@ -116,6 +116,10 @@ function at-repos-pull() {
cd $d
}
+function at-repos-social-app-ios-patch() {
+ $d/ios/setup.zsh
+}
+
function at-repos-social-app-avatar-write() {
did_admin=did:plc:6qyecktefllvenje24fcxnie
dt=$d/repos/social-app/src
@@ -139,7 +143,6 @@ function at-repos-social-app-avatar-write() {
grep -R $did_admin .|cut -d : -f 1|sort -u|xargs sediment "s/${did_admin}/${did}/g"
}
-
# Common patch function with status detection
function apply-patch() {
local patch_name=$1
@@ -496,7 +499,7 @@ case "$1" in
exit
;;
patch)
- at-repos-social-app-avatar-write
+ at-repos-social-app-ios-patch
at-repos-patch-apply-all
at-repos-ozone-patch
show-failed-patches
@@ -536,7 +539,8 @@ case "`cat /etc/hostname`" in
*)
at-repos-clone
at-repos-pull
- at-repos-social-app-avatar-write
+ at-repos-social-app-ios-patch
+ #at-repos-social-app-avatar-write
at-repos-patch-apply-all
at-repos-ozone-patch
show-failed-patches
diff --git a/ios/.env b/ios/.env
index cacfa27..11f93ae 100644
--- a/ios/.env
+++ b/ios/.env
@@ -12,3 +12,4 @@ REPO_DIR="../repos/social-app"
CONFIG_FILE="$REPO_DIR/app.config.js"
CONSTANTS_FILE="$REPO_DIR/src/lib/constants.ts"
APP_MAIL=syui@syui.ai
+PDS_HOST=syu.is
diff --git a/ios/patching/002-social-app-ios-lib.patch b/ios/patching/002-social-app-ios-lib.patch
index 0ef4ec5..d8dd7a9 100644
--- a/ios/patching/002-social-app-ios-lib.patch
+++ b/ios/patching/002-social-app-ios-lib.patch
@@ -1,5 +1,27 @@
+diff --git a/src/lib/api/feed/home.ts b/src/lib/api/feed/home.ts
+index 7a0d72d91..93554dc3e 100644
+--- a/src/lib/api/feed/home.ts
++++ b/src/lib/api/feed/home.ts
+@@ -45,7 +45,7 @@ export class HomeFeedAPI implements FeedAPI {
+ this.following = new FollowingFeedAPI({agent})
+ this.discover = new CustomFeedAPI({
+ agent,
+- feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')},
++ feedParams: {feed: PROD_DEFAULT_FEED('app')},
+ })
+ this.userInterests = userInterests
+ }
+@@ -54,7 +54,7 @@ export class HomeFeedAPI implements FeedAPI {
+ this.following = new FollowingFeedAPI({agent: this.agent})
+ this.discover = new CustomFeedAPI({
+ agent: this.agent,
+- feedParams: {feed: PROD_DEFAULT_FEED('whats-hot')},
++ feedParams: {feed: PROD_DEFAULT_FEED('app')},
+ userInterests: this.userInterests,
+ })
+ this.usingDiscover = false
diff --git a/src/lib/constants.ts b/src/lib/constants.ts
-index 231447b4f..33c51cc0a 100644
+index 231447b4f..a44b3da05 100644
--- a/src/lib/constants.ts
+++ b/src/lib/constants.ts
@@ -7,12 +7,12 @@ import {BLUESKY_PROXY_DID, CHAT_PROXY_DID} from '#/env'
@@ -20,7 +42,51 @@ index 231447b4f..33c51cc0a 100644
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 = {
+@@ -79,19 +79,17 @@ export function IS_PROD_SERVICE(url?: string) {
+ }
+
+ export const PROD_DEFAULT_FEED = (rkey: string) =>
+- `at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/${rkey}`
++ `at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/${rkey}`
+
+ export const STAGING_DEFAULT_FEED = (rkey: string) =>
+ `at://did:plc:yofh3kx63drvfljkibw5zuxo/app.bsky.feed.generator/${rkey}`
+
+ export const PROD_FEEDS = [
+- `feedgen|${PROD_DEFAULT_FEED('whats-hot')}`,
+- `feedgen|${PROD_DEFAULT_FEED('thevids')}`,
++ `feedgen|${PROD_DEFAULT_FEED('app')}`,
+ ]
+
+ export const STAGING_FEEDS = [
+- `feedgen|${STAGING_DEFAULT_FEED('whats-hot')}`,
+- `feedgen|${STAGING_DEFAULT_FEED('thevids')}`,
++ `feedgen|${STAGING_DEFAULT_FEED('app')}`,
+ ]
+
+ export const POST_IMG_MAX = {
+@@ -129,7 +127,7 @@ export const LANG_DROPDOWN_HITSLOP = {top: 10, bottom: 10, left: 4, right: 4}
+ export const BACK_HITSLOP = HITSLOP_30
+ export const MAX_POST_LINES = 25
+
+-export const BSKY_APP_ACCOUNT_DID = 'did:plc:z72i7hdynmk6r22z27h6tvur'
++export const BSKY_APP_ACCOUNT_DID = 'did:plc:6qyecktefllvenje24fcxnie'
+
+ export const BSKY_FEED_OWNER_DIDS = [
+ BSKY_APP_ACCOUNT_DID,
+@@ -138,9 +136,9 @@ export const BSKY_FEED_OWNER_DIDS = [
+ ]
+
+ export const DISCOVER_FEED_URI =
+- 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot'
++ 'at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/app'
+ export const VIDEO_FEED_URI =
+- 'at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/thevids'
++ 'at://did:plc:6qyecktefllvenje24fcxnie/app.bsky.feed.generator/app'
+ export const STAGING_VIDEO_FEED_URI =
+ 'at://did:plc:yofh3kx63drvfljkibw5zuxo/app.bsky.feed.generator/thevids'
+ export const VIDEO_FEED_URIS = [VIDEO_FEED_URI, STAGING_VIDEO_FEED_URI]
+@@ -209,8 +207,8 @@ export const urls = {
},
}
@@ -31,7 +97,7 @@ index 231447b4f..33c51cc0a 100644
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 = {
+@@ -236,8 +234,8 @@ export const BLUESKY_MOD_SERVICE_HEADERS = {
}
export const webLinks = {
@@ -42,38 +108,102 @@ index 231447b4f..33c51cc0a 100644
community: `https://bsky.social/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(
- }
+diff --git a/src/lib/demo.ts b/src/lib/demo.ts
+index 5ead62c9d..7c80dfe15 100644
+--- a/src/lib/demo.ts
++++ b/src/lib/demo.ts
+@@ -1,7 +1,7 @@
+ import {type AppBskyFeedGetFeed} from '@atproto/api'
+ import {subDays, subMinutes} from 'date-fns'
- 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 (
-
- f.value === feedUri && f.pinned,
+ )
+ const discoverFeedConfig = preferences?.savedFeeds?.find(
+- f => f.value === PROD_DEFAULT_FEED('whats-hot'),
++ f => f.value === PROD_DEFAULT_FEED('app'),
+ )
+ const hasFeedPinned = Boolean(feedConfig)
+ const hasDiscoverPinned = Boolean(discoverFeedConfig?.pinned)
+@@ -44,7 +44,7 @@ export function FeedShutdownMsg({feedUri}: {feedUri: string}) {
+ Toast.show(_(msg`Removed from your feeds`))
+ }
+ if (hasDiscoverPinned) {
+- setSelectedFeed(`feedgen|${PROD_DEFAULT_FEED('whats-hot')}`)
++ setSelectedFeed(`feedgen|${PROD_DEFAULT_FEED('app')}`)
+ }
+ } catch (err: any) {
+ Toast.show(
+@@ -63,7 +63,7 @@ export function FeedShutdownMsg({feedUri}: {feedUri: string}) {
+ forYouFeedConfig: feedConfig,
+ discoverFeedConfig,
+ })
+- setSelectedFeed(`feedgen|${PROD_DEFAULT_FEED('whats-hot')}`)
++ setSelectedFeed(`feedgen|${PROD_DEFAULT_FEED('app')}`)
+ Toast.show(_(msg`The feed has been replaced with Discover.`))
+ } catch (err: any) {
+ Toast.show(
+@@ -100,7 +100,7 @@ export function FeedShutdownMsg({feedUri}: {feedUri: string}) {
+ This feed is no longer online. We are showing{' '}
+
+ Discover
+ {' '}
diff --git a/ios/patching/003-social-app-ios-view.patch b/ios/patching/003-social-app-ios-view.patch
index 4087ba8..aa0cc29 100644
--- a/ios/patching/003-social-app-ios-view.patch
+++ b/ios/patching/003-social-app-ios-view.patch
@@ -1,5 +1,51 @@
+diff --git a/src/Splash.tsx b/src/Splash.tsx
+index 47e70b375..616f351ed 100644
+--- a/src/Splash.tsx
++++ b/src/Splash.tsx
+@@ -15,8 +15,8 @@ import Animated, {
+ withTiming,
+ } from 'react-native-reanimated'
+ import {useSafeAreaInsets} from 'react-native-safe-area-context'
+-import Svg, {Path, type SvgProps} from 'react-native-svg'
+ import {Image} from 'expo-image'
++import {type SvgProps} from 'react-native-svg'
+ import * as SplashScreen from 'expo-splash-screen'
+
+ import {Logotype} from '#/view/icons/Logotype'
+@@ -29,21 +29,18 @@ const darkSplashImageUri = RNImage.resolveAssetSource(
+ darkSplashImagePointer,
+ ).uri
+
+-export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) {
+- const width = 1000
+- const height = width * (67 / 64)
++export const Logo = React.forwardRef(function LogoImpl(props: SvgProps & {fill?: string}, ref) {
++ const size = 1000
++ // @ts-ignore
+ return (
+-
++ source={require('../assets/logo.png')}
++ style={[{width: size, height: size}, props.style]}
++ contentFit="contain"
++ accessibilityLabel="Logo"
++ />
+ )
+ })
+
diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx
-index 8a9e51a33..cb0eb7b71 100644
+index 8a9e51a33..65d643b89 100644
--- a/src/view/com/util/UserAvatar.tsx
+++ b/src/view/com/util/UserAvatar.tsx
@@ -444,7 +444,7 @@ let EditableUserAvatar = ({
@@ -11,17 +57,20 @@ index 8a9e51a33..cb0eb7b71 100644
accessibilityRole="image"
/>
) : (
-@@ -619,7 +619,7 @@ export {PreviewableUserAvatar}
+@@ -618,9 +618,8 @@ export {PreviewableUserAvatar}
+ // manually string-replace to use the smaller ones
// -prf
function hackModifyThumbnailPath(uri: string, isEnabled: boolean): string {
- return isEnabled
+- return isEnabled
- ? uri.replace('/img/avatar/plain/', '/img/avatar_thumbnail/plain/')
-+ ? uri.replace('https://cdn.web.syu.is/img/avatar/plain/', 'https://bsky.syu.is/img/avatar/plain/')
- : uri
+- : uri
++ // syu.is: avatars are served directly from bsky.syu.is, no CDN transformation needed
++ return uri
}
+ const styles = StyleSheet.create({
diff --git a/src/view/icons/Logo.tsx b/src/view/icons/Logo.tsx
-index d7208df13..b711f71c7 100644
+index d7208df13..2763800ac 100644
--- a/src/view/icons/Logo.tsx
+++ b/src/view/icons/Logo.tsx
@@ -1,75 +1,17 @@
@@ -162,49 +211,3 @@ index 270c913fc..a60ffe07c 100644
+
)
}
-diff --git a/src/Splash.tsx b/src/Splash.tsx
-index 47e70b375..616f351ed 100644
---- a/src/Splash.tsx
-+++ b/src/Splash.tsx
-@@ -15,8 +15,8 @@ import Animated, {
- withTiming,
- } from 'react-native-reanimated'
- import {useSafeAreaInsets} from 'react-native-safe-area-context'
--import Svg, {Path, type SvgProps} from 'react-native-svg'
- import {Image} from 'expo-image'
-+import {type SvgProps} from 'react-native-svg'
- import * as SplashScreen from 'expo-splash-screen'
-
- import {Logotype} from '#/view/icons/Logotype'
-@@ -29,21 +29,18 @@ const darkSplashImageUri = RNImage.resolveAssetSource(
- darkSplashImagePointer,
- ).uri
-
--export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) {
-- const width = 1000
-- const height = width * (67 / 64)
-+export const Logo = React.forwardRef(function LogoImpl(props: SvgProps & {fill?: string}, ref) {
-+ const size = 1000
-+ // @ts-ignore
- return (
--
-+ source={require('../assets/logo.png')}
-+ style={[{width: size, height: size}, props.style]}
-+ contentFit="contain"
-+ accessibilityLabel="Logo"
-+ />
- )
- })
-
diff --git a/ios/patching/008-social-app-ios-policy-tos-error.patch b/ios/patching/008-social-app-ios-policy-tos-error.patch
deleted file mode 100644
index d45a8b9..0000000
--- a/ios/patching/008-social-app-ios-policy-tos-error.patch
+++ /dev/null
@@ -1,209 +0,0 @@
-diff --git a/src/view/screens/PrivacyPolicy.tsx b/src/view/screens/PrivacyPolicy.tsx
-index a89eaadc4..d8fd51d68 100644
---- a/src/view/screens/PrivacyPolicy.tsx
-+++ b/src/view/screens/PrivacyPolicy.tsx
-@@ -1,52 +1,55 @@
- 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 {usePalette} from '#/lib/hooks/usePalette'
--import {
-- type CommonNavigatorParams,
-- type NativeStackScreenProps,
--} from '#/lib/routes/types'
--import {s} from '#/lib/styles'
--import {useSetMinimalShellMode} from '#/state/shell'
--import {TextLink} from '#/view/com/util/Link'
--import {Text} from '#/view/com/util/text/Text'
--import {ScrollView} from '#/view/com/util/Views'
-+import { ScrollView } from 'react-native'
- import * as Layout from '#/components/Layout'
--import {ViewHeader} from '../com/util/ViewHeader'
--
--type Props = NativeStackScreenProps
--export const PrivacyPolicyScreen = (_props: Props) => {
-- 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]),
-- )
-+export function PrivacyPolicyScreen() {
-+ useSetTitle('Privacy Policy')
-+ const t = useTheme()
-
- return (
-
--
--
--
--
--
-- The Privacy Policy has been moved to{' '}
--
--
-+
-+
-+
-+ Privacy Policy
-+
-+
-+
-+
-+
-+ プライバシーポリシー
-+
-+
-+ 本プライバシーポリシーは、当サービスにおける個人情報の取り扱いについて説明するものです。
-+
-+
-+ 収集する情報
-+
-+ 当サービスでは、アカウント作成時に提供いただく情報(メールアドレス、ユーザー名等)、
-+ および利用時に自動的に収集される情報(アクセスログ等)を収集します。
-+
-+
-+ 情報の利用目的
-+
-+ 収集した情報は、サービスの提供、改善、セキュリティ維持のために利用します。
-+
-+
-+ 第三者への開示
-+
-+ 法令に基づく場合を除き、ユーザーの同意なく第三者に個人情報を開示することはありません。
-+
-+
-+ お問い合わせ
-+
-+ プライバシーポリシーに関するお問い合わせは、https://syu.is までご連絡ください。
-
--
--
--
-+
-+
-
- )
- }
-diff --git a/src/view/screens/TermsOfService.tsx b/src/view/screens/TermsOfService.tsx
-index d843c713c..8d1d0d452 100644
---- a/src/view/screens/TermsOfService.tsx
-+++ b/src/view/screens/TermsOfService.tsx
-@@ -1,50 +1,61 @@
- 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 {usePalette} from '#/lib/hooks/usePalette'
--import {
-- type CommonNavigatorParams,
-- type NativeStackScreenProps,
--} from '#/lib/routes/types'
--import {s} from '#/lib/styles'
--import {useSetMinimalShellMode} from '#/state/shell'
--import {TextLink} from '#/view/com/util/Link'
--import {Text} from '#/view/com/util/text/Text'
--import {ScrollView} from '#/view/com/util/Views'
-+import { ScrollView } from 'react-native'
- import * as Layout from '#/components/Layout'
--import {ViewHeader} from '../com/util/ViewHeader'
--
--type Props = NativeStackScreenProps
--export const TermsOfServiceScreen = (_props: Props) => {
-- const pal = usePalette('default')
-- const setMinimalShellMode = useSetMinimalShellMode()
-- const {_} = useLingui()
--
-- useFocusEffect(
-- React.useCallback(() => {
-- setMinimalShellMode(false)
-- }, [setMinimalShellMode]),
-- )
-+import {useSetTitle} from '#/lib/hooks/useSetTitle'
-+import {atoms as a, useTheme} from '#/alf'
-+import {Text} from '#/components/Typography'
-+
-+export function TermsOfServiceScreen() {
-+ useSetTitle('Terms of Service')
-+ const t = useTheme()
-
- return (
-
--
--
--
--
-- The Terms of Service have been moved to{' '}
--
-+
-+
-+
-+ Terms of Service
-+
-+
-+
-+
-+
-+ 利用規約
-+
-+
-+ 本規約は、当サービスの利用条件を定めるものです。
-+
-+
-+ サービスの利用
-+
-+ ユーザーは、本規約に同意の上、当サービスを利用するものとします。
-+ 違法行為、他者への迷惑行為は禁止されています。
-+
-+
-+ アカウント
-+
-+ ユーザーは、アカウント情報を適切に管理する責任を負います。
-+ 第三者による不正利用があった場合、速やかにご連絡ください。
-+
-+
-+ 免責事項
-+
-+ 当サービスは現状のまま提供され、可用性、正確性について保証するものではありません。
-+
-+
-+ 規約の変更
-+
-+ 本規約は、必要に応じて変更されることがあります。変更後の利用をもって、変更に同意したものとみなします。
-+
-+
-+ お問い合わせ
-+
-+ 利用規約に関するお問い合わせは、https://syu.is までご連絡ください。
-
--
--
--
-+
-+
-
- )
- }
diff --git a/ios/patching/012-social-app-ios-settings-about-help.patch b/ios/patching/012-social-app-ios-settings-about-help.patch
deleted file mode 100644
index f69383e..0000000
--- a/ios/patching/012-social-app-ios-settings-about-help.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-diff --git a/src/routes.ts b/src/routes.ts
-index 1ed913bb2..e3ddf7c67 100644
---- a/src/routes.ts
-+++ b/src/routes.ts
-@@ -71,8 +71,9 @@ export const router = new Router({
- MiscellaneousNotificationSettings: '/settings/notifications/miscellaneous',
- // support
- Support: '/support',
-- PrivacyPolicy: '/support/privacy',
-+ PrivacyPolicy: '/support/privacy-policy',
- TermsOfService: '/support/tos',
-+ License: '/support/license',
- CommunityGuidelines: '/support/community-guidelines',
- CopyrightPolicy: '/support/copyright',
- // hashtags
-diff --git a/src/screens/Settings/AboutSettings.tsx b/src/screens/Settings/AboutSettings.tsx
-index 6b8257b91..c204dcc31 100644
---- a/src/screens/Settings/AboutSettings.tsx
-+++ b/src/screens/Settings/AboutSettings.tsx
-@@ -80,7 +80,7 @@ export function AboutSettingsScreen({}: Props) {
-
-
-
-
-
-@@ -88,13 +88,21 @@ export function AboutSettingsScreen({}: Props) {
-
-
-
-
-
- Privacy Policy
-
-
-+
-+
-+
-+ License
-+
-+
-
diff --git a/ios/patching/023-social-app-ios-disable-dm.patch b/ios/patching/023-social-app-ios-disable-dm.patch
new file mode 100644
index 0000000..2f2236e
--- /dev/null
+++ b/ios/patching/023-social-app-ios-disable-dm.patch
@@ -0,0 +1,70 @@
+diff --git a/src/state/messages/events/index.tsx b/src/state/messages/events/index.tsx
+index 2ff0784ae..dc314ecc5 100644
+--- a/src/state/messages/events/index.tsx
++++ b/src/state/messages/events/index.tsx
+@@ -10,13 +10,7 @@ const MessagesEventBusContext = React.createContext(
+ MessagesEventBusContext.displayName = 'MessagesEventBusContext'
+
+ export function useMessagesEventBus() {
+- const ctx = React.useContext(MessagesEventBusContext)
+- if (!ctx) {
+- throw new Error(
+- 'useMessagesEventBus must be used within a MessagesEventBusProvider',
+- )
+- }
+- return ctx
++ return React.useContext(MessagesEventBusContext)
+ }
+
+ export function MessagesEventBusProvider({
+@@ -24,18 +18,11 @@ export function MessagesEventBusProvider({
+ }: {
+ children: React.ReactNode
+ }) {
+- const {currentAccount} = useSession()
+-
+- if (!currentAccount) {
+- return (
+-
+- {children}
+-
+- )
+- }
+-
++ // DM functionality is disabled for syu.is
+ return (
+- {children}
++
++ {children}
++
+ )
+ }
+
+diff --git a/src/state/queries/messages/list-conversations.tsx b/src/state/queries/messages/list-conversations.tsx
+index c5457d1cb..5bc37bdce 100644
+--- a/src/state/queries/messages/list-conversations.tsx
++++ b/src/state/queries/messages/list-conversations.tsx
+@@ -74,17 +74,12 @@ export function useListConvos() {
+
+ const empty = {accepted: [], request: []}
+ export function ListConvosProvider({children}: {children: React.ReactNode}) {
+- const {hasSession} = useSession()
+-
+- if (!hasSession) {
+- return (
+-
+- {children}
+-
+- )
+- }
+-
+- return {children}
++ // DM functionality is disabled for syu.is - always return empty
++ return (
++
++ {children}
++
++ )
+ }
+
+ export function ListConvosProviderInner({
diff --git a/ios/patching/024-social-app-ios-disable-external-services.patch b/ios/patching/024-social-app-ios-disable-external-services.patch
new file mode 100644
index 0000000..66bd786
--- /dev/null
+++ b/ios/patching/024-social-app-ios-disable-external-services.patch
@@ -0,0 +1,15 @@
+diff --git a/src/env/common.ts b/src/env/common.ts
+--- a/src/env/common.ts
++++ b/src/env/common.ts
+@@ -107,9 +107,8 @@ export const GCP_PROJECT_ID: number =
+ /**
+ * URLs for the app config web worker. Can be a
+ * locally running server, see `env.example` for more.
++ * Disabled for self-hosted environment to avoid CORS errors
+ */
+ export const BAPP_CONFIG_DEV_URL = process.env.BAPP_CONFIG_DEV_URL
+ export const BAPP_CONFIG_PROD_URL = `https://ip.bsky.app`
+-export const BAPP_CONFIG_URL = IS_DEV
+- ? (BAPP_CONFIG_DEV_URL ?? BAPP_CONFIG_PROD_URL)
+- : BAPP_CONFIG_PROD_URL
++export const BAPP_CONFIG_URL = null
diff --git a/ios/setup.zsh b/ios/setup.zsh
index 0870ab5..43a204a 100755
--- a/ios/setup.zsh
+++ b/ios/setup.zsh
@@ -18,16 +18,16 @@ PATCH_FILES_IOS=(
"005-social-app-ios-screens.patch"
"006-social-app-ios-shell.patch"
"007-social-app-ios-misc.patch"
- "008-social-app-ios-policy-tos-error.patch"
"009-social-app-ios-license.patch"
"010-social-app-ios-remove-contact-support.patch"
"011-social-app-ios-splash-license-footer.patch"
- "012-social-app-ios-settings-about-help.patch"
"013-social-app-ios-settings-remove-help.patch"
"019-social-app-ios-entitlements-plugin.patch"
"020-social-app-ios-bypass-age-assurance.patch"
"021-social-app-ios-clean-feed.patch"
"022-social-app-ios-bskyweb-support-pages.patch"
+ "023-social-app-ios-disable-dm.patch"
+ "024-social-app-ios-disable-external-services.patch"
)
function ios-env() {