ai/at
1
0

fix ios patch

This commit is contained in:
2026-01-16 10:35:28 +09:00
parent 3f5ccc8d0f
commit 5288f33029
8 changed files with 59 additions and 680 deletions

View File

@@ -1,5 +1,5 @@
diff --git a/app.config.js b/app.config.js diff --git a/app.config.js b/app.config.js
index 246d8abd3..ed8f7b2b2 100644 index ca417206b..0807d7cd3 100644
--- a/app.config.js --- a/app.config.js
+++ b/app.config.js +++ b/app.config.js
@@ -18,10 +18,7 @@ module.exports = function (_config) { @@ -18,10 +18,7 @@ module.exports = function (_config) {
@@ -49,7 +49,7 @@ index 246d8abd3..ed8f7b2b2 100644
infoPlist: { infoPlist: {
UIBackgroundModes: ['remote-notification'], UIBackgroundModes: ['remote-notification'],
NSCameraUsageDescription: NSCameraUsageDescription:
@@ -113,7 +107,7 @@ module.exports = function (_config) { @@ -113,7 +108,7 @@ module.exports = function (_config) {
entitlements: { entitlements: {
'com.apple.developer.kernel.increased-memory-limit': true, 'com.apple.developer.kernel.increased-memory-limit': true,
'com.apple.developer.kernel.extended-virtual-addressing': true, 'com.apple.developer.kernel.extended-virtual-addressing': true,
@@ -58,7 +58,7 @@ index 246d8abd3..ed8f7b2b2 100644
}, },
privacyManifests: { privacyManifests: {
NSPrivacyCollectedDataTypes: [ NSPrivacyCollectedDataTypes: [
@@ -175,14 +169,14 @@ module.exports = function (_config) { @@ -175,14 +170,14 @@ module.exports = function (_config) {
barStyle: 'light-content', barStyle: 'light-content',
}, },
android: { android: {
@@ -75,7 +75,7 @@ index 246d8abd3..ed8f7b2b2 100644
intentFilters: [ intentFilters: [
{ {
action: 'VIEW', action: 'VIEW',
@@ -190,7 +184,7 @@ module.exports = function (_config) { @@ -190,7 +185,7 @@ module.exports = function (_config) {
data: [ data: [
{ {
scheme: 'https', scheme: 'https',
@@ -84,7 +84,7 @@ index 246d8abd3..ed8f7b2b2 100644
}, },
IS_DEV && { IS_DEV && {
scheme: 'http', scheme: 'http',
@@ -213,9 +207,9 @@ module.exports = function (_config) { @@ -213,9 +208,9 @@ module.exports = function (_config) {
: undefined, : undefined,
codeSigningMetadata: UPDATES_ENABLED codeSigningMetadata: UPDATES_ENABLED
? { ? {
@@ -97,7 +97,7 @@ index 246d8abd3..ed8f7b2b2 100644
: undefined, : undefined,
checkAutomatically: 'NEVER', checkAutomatically: 'NEVER',
}, },
@@ -225,7 +219,7 @@ module.exports = function (_config) { @@ -225,7 +220,7 @@ module.exports = function (_config) {
'expo-web-browser', 'expo-web-browser',
[ [
'react-native-edge-to-edge', 'react-native-edge-to-edge',
@@ -106,7 +106,7 @@ index 246d8abd3..ed8f7b2b2 100644
], ],
USE_SENTRY && [ USE_SENTRY && [
'@sentry/react-native/expo', '@sentry/react-native/expo',
@@ -264,7 +258,6 @@ module.exports = function (_config) { @@ -265,7 +260,6 @@ module.exports = function (_config) {
networkInstrumentation: true, networkInstrumentation: true,
}, },
], ],
@@ -114,7 +114,7 @@ index 246d8abd3..ed8f7b2b2 100644
'./plugins/withGradleJVMHeapSizeIncrease.js', './plugins/withGradleJVMHeapSizeIncrease.js',
'./plugins/withAndroidManifestLargeHeapPlugin.js', './plugins/withAndroidManifestLargeHeapPlugin.js',
'./plugins/withAndroidManifestFCMIconPlugin.js', './plugins/withAndroidManifestFCMIconPlugin.js',
@@ -272,8 +265,6 @@ module.exports = function (_config) { @@ -273,8 +267,6 @@ module.exports = function (_config) {
'./plugins/withAndroidStylesAccentColorPlugin.js', './plugins/withAndroidStylesAccentColorPlugin.js',
'./plugins/withAndroidDayNightThemePlugin.js', './plugins/withAndroidDayNightThemePlugin.js',
'./plugins/withAndroidNoJitpackPlugin.js', './plugins/withAndroidNoJitpackPlugin.js',
@@ -123,16 +123,16 @@ index 246d8abd3..ed8f7b2b2 100644
[ [
'expo-font', 'expo-font',
{ {
@@ -386,7 +377,7 @@ module.exports = function (_config) { @@ -387,7 +379,7 @@ module.exports = function (_config) {
}, },
}, },
], ],
- ['expo-screen-orientation', {initialOrientation: 'PORTRAIT_UP'}], - ['expo-screen-orientation', {initialOrientation: 'PORTRAIT_UP'}],
+ ['expo-screen-orientation', { initialOrientation: 'PORTRAIT_UP' }], + ['expo-screen-orientation', { initialOrientation: 'PORTRAIT_UP' }],
['expo-location'], ['expo-location'],
].filter(Boolean), [
extra: { 'expo-contacts',
@@ -394,30 +385,7 @@ module.exports = function (_config) { @@ -402,30 +394,7 @@ module.exports = function (_config) {
build: { build: {
experimental: { experimental: {
ios: { ios: {

View File

@@ -1,22 +1,22 @@
diff --git a/src/App.native.tsx b/src/App.native.tsx diff --git a/src/App.native.tsx b/src/App.native.tsx
index fb3008627..539ebc055 100644 index 2c4d6fa41..b69e2b18d 100644
--- a/src/App.native.tsx --- a/src/App.native.tsx
+++ b/src/App.native.tsx +++ b/src/App.native.tsx
@@ -92,7 +92,7 @@ if (isAndroid) { @@ -95,7 +95,7 @@ if (isAndroid) {
* Begin geolocation ASAP * Begin geolocation ASAP
*/ */
Geo.resolve() Geo.resolve()
-prefetchAgeAssuranceConfig() -prefetchAgeAssuranceConfig()
+// // // prefetchAgeAssuranceConfig() +// // // prefetchAgeAssuranceConfig()
prefetchLiveEvents()
function InnerApp() { function InnerApp() {
const [isReady, setIsReady] = React.useState(false)
diff --git a/src/routes.ts b/src/routes.ts diff --git a/src/routes.ts b/src/routes.ts
index 1ed913bb2..c80340edb 100644 index f325539c7..3e2c7b3eb 100644
--- a/src/routes.ts --- a/src/routes.ts
+++ b/src/routes.ts +++ b/src/routes.ts
@@ -71,8 +71,8 @@ export const router = new Router<AllNavigatableRoutes>({ @@ -72,9 +72,11 @@ export const router = new Router<AllNavigatableRoutes>({
MiscellaneousNotificationSettings: '/settings/notifications/miscellaneous', FindContactsSettings: '/settings/find-contacts',
// support // support
Support: '/support', Support: '/support',
- PrivacyPolicy: '/support/privacy', - PrivacyPolicy: '/support/privacy',
@@ -24,8 +24,11 @@ index 1ed913bb2..c80340edb 100644
+ PrivacyPolicy: 'https://syu.is/about/support/privacy-policy', + PrivacyPolicy: 'https://syu.is/about/support/privacy-policy',
+ TermsOfService: 'https://syu.is/about/support/tos', + TermsOfService: 'https://syu.is/about/support/tos',
CommunityGuidelines: '/support/community-guidelines', CommunityGuidelines: '/support/community-guidelines',
+ License: 'https://syu.is/about/support/license',
+ AppInfo: 'https://syu.is/about/support/app',
CopyrightPolicy: '/support/copyright', CopyrightPolicy: '/support/copyright',
// hashtags // hashtags
Hashtag: '/hashtag/:tag',
diff --git a/src/state/session/agent.ts b/src/state/session/agent.ts diff --git a/src/state/session/agent.ts b/src/state/session/agent.ts
index 5c8ce3b97..ee85beb08 100644 index 5c8ce3b97..ee85beb08 100644
--- a/src/state/session/agent.ts --- a/src/state/session/agent.ts

View File

@@ -1,16 +1,17 @@
diff --git a/src/Navigation.tsx b/src/Navigation.tsx diff --git a/src/Navigation.tsx b/src/Navigation.tsx
index fa33a9d56..13af087c2 100644 index fde223bd0..0e57c27a6 100644
--- a/src/Navigation.tsx --- a/src/Navigation.tsx
+++ b/src/Navigation.tsx +++ b/src/Navigation.tsx
@@ -62,6 +62,7 @@ import {NotFoundScreen} from '#/view/screens/NotFound' @@ -66,6 +66,8 @@ import {NotFoundScreen} from '#/view/screens/NotFound'
import {NotificationsScreen} from '#/view/screens/Notifications' import {NotificationsScreen} from '#/view/screens/Notifications'
import {PostThreadScreen} from '#/view/screens/PostThread' import {PostThreadScreen} from '#/view/screens/PostThread'
import {PrivacyPolicyScreen} from '#/view/screens/PrivacyPolicy' import {PrivacyPolicyScreen} from '#/view/screens/PrivacyPolicy'
+import {LicenseScreen} from '#/view/screens/License' +import {LicenseScreen} from '#/view/screens/License'
+import {AppInfoScreen} from '#/view/screens/AppInfo'
import {ProfileScreen} from '#/view/screens/Profile' import {ProfileScreen} from '#/view/screens/Profile'
import {ProfileFeedLikedByScreen} from '#/view/screens/ProfileFeedLikedBy' import {ProfileFeedLikedByScreen} from '#/view/screens/ProfileFeedLikedBy'
import {Storybook} from '#/view/screens/Storybook' import {StorybookScreen} from '#/view/screens/Storybook'
@@ -335,6 +336,11 @@ function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) { @@ -337,6 +339,16 @@ function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) {
getComponent={() => TermsOfServiceScreen} getComponent={() => TermsOfServiceScreen}
options={{title: title(msg`Terms of Service`)}} options={{title: title(msg`Terms of Service`)}}
/> />
@@ -18,157 +19,25 @@ index fa33a9d56..13af087c2 100644
+ name="License" + name="License"
+ getComponent={() => LicenseScreen} + getComponent={() => LicenseScreen}
+ options={{title: title(msg`License`)}} + options={{title: title(msg`License`)}}
+ />
+ <Stack.Screen
+ name="AppInfo"
+ getComponent={() => AppInfoScreen}
+ options={{title: title(msg`App Info`)}}
+ /> + />
<Stack.Screen <Stack.Screen
name="CommunityGuidelines" name="CommunityGuidelines"
getComponent={() => CommunityGuidelinesScreen} getComponent={() => CommunityGuidelinesScreen}
diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts
index c315a8341..9b2f50a83 100644 index 0a3a0d545..ec6c43ff5 100644
--- a/src/lib/routes/types.ts --- a/src/lib/routes/types.ts
+++ b/src/lib/routes/types.ts +++ b/src/lib/routes/types.ts
@@ -39,6 +39,7 @@ export type CommonNavigatorParams = { @@ -39,6 +39,8 @@ export type CommonNavigatorParams = {
Support: undefined Support: undefined
PrivacyPolicy: undefined PrivacyPolicy: undefined
TermsOfService: undefined TermsOfService: undefined
+ License: undefined + License: undefined
+ AppInfo: undefined
CommunityGuidelines: undefined CommunityGuidelines: undefined
CopyrightPolicy: undefined CopyrightPolicy: undefined
LanguageSettings: undefined LanguageSettings: undefined
diff --git a/src/view/screens/License.tsx b/src/view/screens/License.tsx
new file mode 100644
index 000000000..87f52a972
--- /dev/null
+++ b/src/view/screens/License.tsx
@@ -0,0 +1,132 @@
+import React from 'react'
+import { ScrollView, Text as RNText, StyleSheet } from 'react-native'
+import * as Layout from '#/components/Layout'
+import {useSetTitle} from '#/lib/hooks/useSetTitle'
+import {atoms as a, useTheme} from '#/alf'
+
+export function LicenseScreen() {
+ useSetTitle('License')
+ const t = useTheme()
+
+ return (
+ <Layout.Screen>
+ <Layout.Header.Outer>
+ <Layout.Header.BackButton />
+ <Layout.Header.Content>
+ <Layout.Header.TitleText>License</Layout.Header.TitleText>
+ </Layout.Header.Content>
+ <Layout.Header.Slot />
+ </Layout.Header.Outer>
+ <Layout.Content>
+ <ScrollView
+ style={[a.flex_1]}
+ contentContainerStyle={[a.p_lg, a.pt_xl, a.pb_5xl]}>
+ <RNText style={styles.text}>
+ This application is based on Bluesky Social App.
+ </RNText>
+
+ <RNText style={styles.link}>
+ https://github.com/bluesky-social/social-app
+ </RNText>
+
+ <RNText style={styles.sectionTitle}>MIT License</RNText>
+
+ <RNText style={styles.mono}>
+ Copyright (c) 2022-2025 Bluesky PBC
+ </RNText>
+
+ <RNText style={styles.text}>
+ 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:
+ </RNText>
+
+ <RNText style={styles.text}>
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+ </RNText>
+
+ <RNText style={styles.text}>
+ 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.
+ </RNText>
+
+ <RNText style={styles.sectionTitle2}>日本語訳(参考)</RNText>
+
+ <RNText style={styles.text}>
+ 本ソフトウェアおよび関連文書ファイル(以下「ソフトウェア」)のコピーを取得する
+ すべての人に対し、ソフトウェアを無制限に扱うことを無償で許可します。これには、
+ ソフトウェアのコピーを使用、複製、変更、結合、公開、配布、サブライセンス、
+ および/または販売する権利、ならびにソフトウェアを提供する相手にそうした行為を
+ 許可する権利が含まれますが、これらに限定されません。
+ </RNText>
+
+ <RNText style={styles.text}>
+ 上記の著作権表示および本許諾表示を、ソフトウェアのすべてのコピーまたは
+ 重要な部分に記載するものとします。
+ </RNText>
+
+ <RNText style={styles.text}>
+ ソフトウェアは「現状のまま」で提供され、明示黙示を問わず、商品性、特定目的への
+ 適合性、および権利非侵害についての保証を含む、いかなる種類の保証もなされません。
+ いかなる場合においても、作者または著作権者は、契約行為、不法行為、またはそれ以外で
+ あろうと、ソフトウェアに起因または関連し、あるいはソフトウェアの使用または
+ その他の扱いによって生じる一切の請求、損害、その他の義務について責任を負わないものとします。
+ </RNText>
+
+ <RNText style={styles.footer}>
+ Original License: https://github.com/bluesky-social/social-app/blob/main/LICENSE
+ </RNText>
+ </ScrollView>
+ </Layout.Content>
+ </Layout.Screen>
+ )
+}
+
+const styles = StyleSheet.create({
+ title: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ marginBottom: 16,
+ },
+ text: {
+ fontSize: 14,
+ marginBottom: 12,
+ lineHeight: 20,
+ },
+ link: {
+ fontSize: 14,
+ marginBottom: 12,
+ color: '#0066cc',
+ },
+ sectionTitle: {
+ fontSize: 18,
+ fontWeight: 'bold',
+ marginTop: 16,
+ marginBottom: 12,
+ },
+ sectionTitle2: {
+ fontSize: 18,
+ fontWeight: 'bold',
+ marginTop: 24,
+ marginBottom: 12,
+ },
+ mono: {
+ fontSize: 14,
+ marginBottom: 12,
+ fontFamily: 'monospace',
+ },
+ footer: {
+ fontSize: 12,
+ marginTop: 24,
+ color: '#666666',
+ },
+})

View File

@@ -1,15 +1,5 @@
diff --git a/src/routes.ts b/src/routes.ts
--- a/src/routes.ts
+++ b/src/routes.ts
@@ -74,6 +74,7 @@ export const router = new Router<AllNavigatableRoutes>({
PrivacyPolicy: 'https://syu.is/about/support/privacy-policy',
TermsOfService: 'https://syu.is/about/support/tos',
CommunityGuidelines: '/support/community-guidelines',
+ License: 'https://syu.is/about/support/license',
CopyrightPolicy: '/support/copyright',
// hashtags
Hashtag: '/hashtag/:tag',
diff --git a/src/view/com/auth/SplashScreen.tsx b/src/view/com/auth/SplashScreen.tsx diff --git a/src/view/com/auth/SplashScreen.tsx b/src/view/com/auth/SplashScreen.tsx
index 3442d1bdf..8ed9e3d0d 100644
--- a/src/view/com/auth/SplashScreen.tsx --- a/src/view/com/auth/SplashScreen.tsx
+++ b/src/view/com/auth/SplashScreen.tsx +++ b/src/view/com/auth/SplashScreen.tsx
@@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
@@ -58,6 +48,7 @@ diff --git a/src/view/com/auth/SplashScreen.tsx b/src/view/com/auth/SplashScreen
</ErrorBoundary> </ErrorBoundary>
</Animated.View> </Animated.View>
diff --git a/src/view/com/auth/SplashScreen.web.tsx b/src/view/com/auth/SplashScreen.web.tsx diff --git a/src/view/com/auth/SplashScreen.web.tsx b/src/view/com/auth/SplashScreen.web.tsx
index 22dd23d7f..7ceb3800e 100644
--- a/src/view/com/auth/SplashScreen.web.tsx --- a/src/view/com/auth/SplashScreen.web.tsx
+++ b/src/view/com/auth/SplashScreen.web.tsx +++ b/src/view/com/auth/SplashScreen.web.tsx
@@ -94,14 +94,6 @@ export const SplashScreen = ({ @@ -94,14 +94,6 @@ export const SplashScreen = ({

View File

@@ -1,15 +1,28 @@
diff --git a/src/env/common.ts b/src/env/common.ts diff --git a/src/env/common.ts b/src/env/common.ts
index 04e98c49c..a4ee47932 100644
--- a/src/env/common.ts --- a/src/env/common.ts
+++ b/src/env/common.ts +++ b/src/env/common.ts
@@ -107,9 +107,8 @@ export const GCP_PROJECT_ID: number = @@ -107,19 +107,17 @@ export const GCP_PROJECT_ID: number =
/** /**
* URLs for the app config web worker. Can be a * URLs for the app config web worker. Can be a
* locally running server, see `env.example` for more. * locally running server, see `env.example` for more.
+ * Disabled for self-hosted environment to avoid CORS errors + * Disabled for self-hosted environment to avoid CORS errors
*/ */
export const BAPP_CONFIG_DEV_URL = process.env.BAPP_CONFIG_DEV_URL export const GEOLOCATION_DEV_URL = process.env.GEOLOCATION_DEV_URL
export const BAPP_CONFIG_PROD_URL = `https://ip.bsky.app` export const GEOLOCATION_PROD_URL = `https://ip.bsky.app`
-export const BAPP_CONFIG_URL = IS_DEV -export const GEOLOCATION_URL = IS_DEV
- ? (BAPP_CONFIG_DEV_URL ?? BAPP_CONFIG_PROD_URL) - ? (GEOLOCATION_DEV_URL ?? GEOLOCATION_PROD_URL)
- : BAPP_CONFIG_PROD_URL - : GEOLOCATION_PROD_URL
+export const BAPP_CONFIG_URL = null +export const GEOLOCATION_URL = null
/**
* URLs for the live-event config web worker. Can be a
* locally running server, see `env.example` for more.
+ * Disabled for self-hosted environment
*/
export const LIVE_EVENTS_DEV_URL = process.env.LIVE_EVENTS_DEV_URL
export const LIVE_EVENTS_PROD_URL = `https://live-events.workers.bsky.app`
-export const LIVE_EVENTS_URL = IS_DEV
- ? (LIVE_EVENTS_DEV_URL ?? LIVE_EVENTS_PROD_URL)
- : LIVE_EVENTS_PROD_URL
+export const LIVE_EVENTS_URL = null

View File

@@ -1,361 +0,0 @@
diff --git a/src/Navigation.tsx b/src/Navigation.tsx
--- a/src/Navigation.tsx
+++ b/src/Navigation.tsx
@@ -63,6 +63,7 @@ import {NotificationsScreen} from '#/view/screens/Notifications'
import {PostThreadScreen} from '#/view/screens/PostThread'
import {PrivacyPolicyScreen} from '#/view/screens/PrivacyPolicy'
import {LicenseScreen} from '#/view/screens/License'
+import {AppInfoScreen} from '#/view/screens/AppInfo'
import {ProfileScreen} from '#/view/screens/Profile'
import {ProfileFeedLikedByScreen} from '#/view/screens/ProfileFeedLikedBy'
import {Storybook} from '#/view/screens/Storybook'
@@ -341,6 +342,11 @@ function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) {
getComponent={() => LicenseScreen}
options={{title: title(msg`License`)}}
/>
+ <Stack.Screen
+ name="AppInfo"
+ getComponent={() => AppInfoScreen}
+ options={{title: title(msg`App Info`)}}
+ />
<Stack.Screen
name="CommunityGuidelines"
getComponent={() => CommunityGuidelinesScreen}
diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts
--- a/src/lib/routes/types.ts
+++ b/src/lib/routes/types.ts
@@ -40,6 +40,7 @@ export type CommonNavigatorParams = {
PrivacyPolicy: undefined
TermsOfService: undefined
License: undefined
+ AppInfo: undefined
CommunityGuidelines: undefined
CopyrightPolicy: undefined
LanguageSettings: undefined
diff --git a/src/routes.ts b/src/routes.ts
--- a/src/routes.ts
+++ b/src/routes.ts
@@ -75,6 +75,7 @@ export const router = new Router<AllNavigatableRoutes>({
TermsOfService: 'https://syu.is/about/support/tos',
CommunityGuidelines: '/support/community-guidelines',
License: 'https://syu.is/about/support/license',
+ AppInfo: 'https://syu.is/about/support/app',
CopyrightPolicy: '/support/copyright',
// hashtags
Hashtag: '/hashtag/:tag',
diff --git a/src/view/screens/AppInfo.tsx b/src/view/screens/AppInfo.tsx
new file mode 100644
index 000000000..000000001
--- /dev/null
+++ b/src/view/screens/AppInfo.tsx
@@ -0,0 +1,310 @@
+import React, {useState} from 'react'
+import {
+ View,
+ ScrollView,
+ StyleSheet,
+ Pressable,
+ Image,
+} from 'react-native'
+import * as Clipboard from 'expo-clipboard'
+import * as WebBrowser from 'expo-web-browser'
+import {Trans} from '@lingui/macro'
+
+import * as Layout from '#/components/Layout'
+import {Text} from '#/components/Typography'
+import {useSetTitle} from '#/lib/hooks/useSetTitle'
+import {atoms as a, useTheme} from '#/alf'
+
+const APP_VERSION = '1.111.0'
+const APP_NAME = 'Aiat'
+const BITCOIN_ADDRESS = '3BqHXxraZyBapyNpJmniJDh9zqzuB8aoRr'
+
+export function AppInfoScreen() {
+ useSetTitle('App Info')
+ const t = useTheme()
+ const [copied, setCopied] = useState(false)
+
+ const copyToClipboard = async (text: string) => {
+ try {
+ await Clipboard.setStringAsync(text)
+ setCopied(true)
+ setTimeout(() => setCopied(false), 2000)
+ } catch (e) {
+ console.log('Clipboard not available')
+ }
+ }
+
+ const openUrl = (url: string) => {
+ WebBrowser.openBrowserAsync(url)
+ }
+
+ return (
+ <Layout.Screen>
+ <Layout.Header.Outer>
+ <Layout.Header.BackButton />
+ <Layout.Header.Content>
+ <Layout.Header.TitleText>
+ <Trans>App Info</Trans>
+ </Layout.Header.TitleText>
+ </Layout.Header.Content>
+ <Layout.Header.Slot />
+ </Layout.Header.Outer>
+ <Layout.Content>
+ <ScrollView
+ style={[a.flex_1]}
+ contentContainerStyle={[a.p_lg, a.pt_xl, a.pb_5xl]}>
+ {/* App Header */}
+ <View style={styles.appHeader}>
+ <View style={[styles.appIconContainer, t.atoms.bg_contrast_25]}>
+ <Image
+ source={require('../../../assets/logo.png')}
+ style={styles.appIcon}
+ resizeMode="cover"
+ />
+ </View>
+ <Text style={[styles.appName, t.atoms.text]}>
+ {APP_NAME}
+ </Text>
+ <Text style={[styles.appVersion, t.atoms.text_contrast_medium]}>
+ v{APP_VERSION}
+ </Text>
+ </View>
+
+ {/* Description Section */}
+ <View style={[styles.section, t.atoms.bg_contrast_25]}>
+ <Text style={[styles.description, t.atoms.text]}>
+ {APP_NAME} is a social networking application based on AT Protocol.
+ Connect with your community on syu.is.
+ </Text>
+ </View>
+
+ {/* App Information Section */}
+ <View style={[styles.section, t.atoms.bg_contrast_25]}>
+ <Text style={[styles.sectionTitle, t.atoms.text_contrast_medium]}>
+ App Information
+ </Text>
+ <View style={styles.infoGrid}>
+ <View style={[styles.infoItem, t.atoms.bg_contrast_50]}>
+ <Text style={[styles.infoLabel, t.atoms.text_contrast_medium]}>
+ Version
+ </Text>
+ <Text style={[styles.infoValue, t.atoms.text]}>
+ {APP_VERSION}
+ </Text>
+ </View>
+ <View style={[styles.infoItem, t.atoms.bg_contrast_50]}>
+ <Text style={[styles.infoLabel, t.atoms.text_contrast_medium]}>
+ Category
+ </Text>
+ <Text style={[styles.infoValue, t.atoms.text]}>
+ Social
+ </Text>
+ </View>
+ <View style={[styles.infoItem, t.atoms.bg_contrast_50]}>
+ <Text style={[styles.infoLabel, t.atoms.text_contrast_medium]}>
+ Supported OS
+ </Text>
+ <Text style={[styles.infoValue, t.atoms.text]}>
+ iOS 26.0+
+ </Text>
+ </View>
+ <View style={[styles.infoItem, t.atoms.bg_contrast_50]}>
+ <Text style={[styles.infoLabel, t.atoms.text_contrast_medium]}>
+ Price
+ </Text>
+ <Text style={[styles.infoValue, t.atoms.text]}>
+ Free
+ </Text>
+ </View>
+ </View>
+ </View>
+
+ {/* Developer Section */}
+ <View style={[styles.section, t.atoms.bg_contrast_25]}>
+ <Text style={[styles.sectionTitle, t.atoms.text_contrast_medium]}>
+ Developer
+ </Text>
+ <View style={styles.developerCard}>
+ <Text style={[styles.developerName, t.atoms.text]}>syui</Text>
+ </View>
+
+ <Pressable
+ onPress={() => openUrl('https://github.com/syui')}
+ style={[styles.linkRow, t.atoms.border_contrast_low]}>
+ <Text style={[styles.linkIcon, t.atoms.text_contrast_medium]}>
+ GitHub
+ </Text>
+ <Text style={[styles.linkValue, {color: '#0084ff'}]}>
+ github.com/syui
+ </Text>
+ <Text style={[styles.linkArrow, t.atoms.text_contrast_low]}>→</Text>
+ </Pressable>
+
+ <Pressable
+ onPress={() => openUrl('https://syu.is/syui')}
+ style={[styles.linkRow, t.atoms.border_contrast_low]}>
+ <Text style={[styles.linkIcon, t.atoms.text_contrast_medium]}>
+ ATProto
+ </Text>
+ <Text style={[styles.linkValue, {color: '#0084ff'}]}>
+ syu.is/syui
+ </Text>
+ <Text style={[styles.linkArrow, t.atoms.text_contrast_low]}>→</Text>
+ </Pressable>
+ </View>
+
+ {/* Bitcoin Section */}
+ <View style={[styles.section, t.atoms.bg_contrast_25]}>
+ <Text style={[styles.sectionTitle, t.atoms.text_contrast_medium]}>
+ Bitcoin
+ </Text>
+ <Pressable
+ onPress={() => copyToClipboard(BITCOIN_ADDRESS)}
+ style={styles.bitcoinRow}>
+ <Text style={styles.bitcoinLabel}>₿</Text>
+ <Text style={[styles.bitcoinAddress, t.atoms.text_contrast_medium]}>
+ {BITCOIN_ADDRESS}
+ </Text>
+ <Text style={[styles.copyHint, copied && styles.copiedHint]}>
+ {copied ? 'copied!' : 'copy'}
+ </Text>
+ </Pressable>
+ </View>
+
+ {/* Copyright */}
+ <View style={styles.copyright}>
+ <Text style={[styles.copyrightText, t.atoms.text_contrast_low]}>
+ © syui
+ </Text>
+ </View>
+ </ScrollView>
+ </Layout.Content>
+ </Layout.Screen>
+ )
+}
+
+const styles = StyleSheet.create({
+ appHeader: {
+ alignItems: 'center',
+ marginBottom: 24,
+ },
+ appIconContainer: {
+ width: 80,
+ height: 80,
+ borderRadius: 18,
+ overflow: 'hidden',
+ marginBottom: 12,
+ },
+ appIcon: {
+ width: '100%',
+ height: '100%',
+ },
+ appName: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ marginBottom: 4,
+ },
+ appVersion: {
+ fontSize: 14,
+ },
+ section: {
+ marginBottom: 16,
+ borderRadius: 16,
+ padding: 16,
+ },
+ sectionTitle: {
+ fontSize: 13,
+ fontWeight: '600',
+ textTransform: 'uppercase',
+ letterSpacing: 0.5,
+ marginBottom: 12,
+ },
+ description: {
+ fontSize: 15,
+ lineHeight: 22,
+ },
+ infoGrid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ gap: 8,
+ },
+ infoItem: {
+ flex: 1,
+ minWidth: '45%',
+ alignItems: 'center',
+ borderRadius: 12,
+ padding: 12,
+ },
+ infoLabel: {
+ fontSize: 11,
+ textTransform: 'uppercase',
+ letterSpacing: 0.5,
+ marginBottom: 4,
+ },
+ infoValue: {
+ fontSize: 16,
+ fontWeight: '600',
+ textAlign: 'center',
+ },
+ developerCard: {
+ marginBottom: 12,
+ },
+ developerName: {
+ fontSize: 18,
+ fontWeight: '600',
+ },
+ linkRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingVertical: 12,
+ borderTopWidth: 1,
+ },
+ linkIcon: {
+ fontSize: 14,
+ fontWeight: '600',
+ width: 70,
+ },
+ linkValue: {
+ flex: 1,
+ fontSize: 14,
+ },
+ linkArrow: {
+ fontSize: 16,
+ },
+ bitcoinRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: 'rgba(247, 147, 26, 0.08)',
+ borderRadius: 12,
+ padding: 14,
+ gap: 10,
+ },
+ bitcoinLabel: {
+ fontSize: 18,
+ fontWeight: '600',
+ color: '#f7931a',
+ },
+ bitcoinAddress: {
+ flex: 1,
+ fontSize: 11,
+ fontFamily: 'monospace',
+ },
+ copyHint: {
+ fontSize: 12,
+ color: '#999999',
+ minWidth: 50,
+ textAlign: 'right',
+ },
+ copiedHint: {
+ color: '#4CAF50',
+ fontWeight: '600',
+ },
+ copyright: {
+ alignItems: 'center',
+ marginTop: 20,
+ marginBottom: 20,
+ },
+ copyrightText: {
+ fontSize: 12,
+ },
+})

View File

@@ -41,7 +41,6 @@ PATCH_FILES_IOS=(
"027-social-app-ios-remove-birthdate.patch" "027-social-app-ios-remove-birthdate.patch"
"028-social-app-ios-remove-discover-feeds.patch" "028-social-app-ios-remove-discover-feeds.patch"
"029-social-app-ios-remove-feeds-discover.patch" "029-social-app-ios-remove-feeds-discover.patch"
"030-social-app-ios-appinfo.patch"
"032-social-app-ios-feed-loggedout.patch" "032-social-app-ios-feed-loggedout.patch"
"033-social-app-ios-hide-profile-tabs.patch" "033-social-app-ios-hide-profile-tabs.patch"
"036-social-app-ios-homeheader-loggedout.patch" "036-social-app-ios-homeheader-loggedout.patch"

View File

@@ -1,27 +1,3 @@
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1 @@
+node_modules
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..993c83d
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,11 @@
+FROM node:18-alpine
+
+WORKDIR /app
+
+COPY package.json yarn.lock ./
+RUN yarn install
+
+COPY . .
+
+EXPOSE 3000
+CMD ["yarn", "start"]
diff --git a/package.json b/package.json diff --git a/package.json b/package.json
index 1431a9e..6a7c33c 100644 index 1431a9e..6a7c33c 100644
--- a/package.json --- a/package.json
@@ -39,117 +15,6 @@ index 1431a9e..6a7c33c 100644
"@types/better-sqlite3": "^7.6.11", "@types/better-sqlite3": "^7.6.11",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/node": "^20.1.2", "@types/node": "^20.1.2",
diff --git a/scripts/publish.ts b/scripts/publish.ts
new file mode 100644
index 0000000..044f1d9
--- /dev/null
+++ b/scripts/publish.ts
@@ -0,0 +1,64 @@
+import dotenv from 'dotenv'
+import { AtpAgent, BlobRef } from '@atproto/api'
+import fs from 'fs/promises'
+import { ids } from '../src/lexicon/lexicons'
+
+const run = async () => {
+ dotenv.config()
+
+ const handle = process.env.FEEDGEN_HANDLE
+ const password = process.env.FEEDGEN_PASSWORD
+ const recordName = process.env.FEEDGEN_RECORD_NAME || 'app'
+ const displayName = process.env.FEEDGEN_DISPLAY_NAME || 'App Feed'
+ const description = process.env.FEEDGEN_DESCRIPTION || 'Automated App Feed'
+ const avatar = process.env.FEEDGEN_AVATAR
+ const service = process.env.FEEDGEN_SERVICE_URL || 'https://syu.is'
+
+ if (!handle || !password) {
+ throw new Error('Please provide FEEDGEN_HANDLE and FEEDGEN_PASSWORD environment variables')
+ }
+
+ if (!process.env.FEEDGEN_SERVICE_DID && !process.env.FEEDGEN_HOSTNAME) {
+ throw new Error('Please provide a hostname in the .env file')
+ }
+
+ const feedGenDid =
+ process.env.FEEDGEN_SERVICE_DID ?? `did:web:${process.env.FEEDGEN_HOSTNAME}`
+
+ const agent = new AtpAgent({ service })
+ await agent.login({ identifier: handle, password })
+
+ let avatarRef: BlobRef | undefined
+ if (avatar) {
+ let encoding: string
+ if (avatar.endsWith('png')) {
+ encoding = 'image/png'
+ } else if (avatar.endsWith('jpg') || avatar.endsWith('jpeg')) {
+ encoding = 'image/jpeg'
+ } else {
+ throw new Error('expected png or jpeg')
+ }
+ const img = await fs.readFile(avatar)
+ const blobRes = await agent.api.com.atproto.repo.uploadBlob(img, {
+ encoding,
+ })
+ avatarRef = blobRes.data.blob
+ }
+
+ await agent.api.com.atproto.repo.putRecord({
+ repo: agent.session?.did ?? '',
+ collection: ids.AppBskyFeedGenerator,
+ rkey: recordName,
+ record: {
+ did: feedGenDid,
+ displayName: displayName,
+ description: description,
+ avatar: avatarRef,
+ createdAt: new Date().toISOString(),
+ },
+ })
+
+ console.log('All done')
+}
+
+run()
diff --git a/src/algos/app.ts b/src/algos/app.ts
new file mode 100644
index 0000000..2376be9
--- /dev/null
+++ b/src/algos/app.ts
@@ -0,0 +1,35 @@
+import { QueryParams } from '../lexicon/types/app/bsky/feed/getFeedSkeleton'
+import { AppContext } from '../config'
+
+// max 15 chars
+export const shortname = 'app'
+
+export const handler = async (ctx: AppContext, params: QueryParams) => {
+ let builder = ctx.db
+ .selectFrom('post')
+ .selectAll()
+ .orderBy('indexedAt', 'desc')
+ .orderBy('cid', 'desc')
+ .limit(params.limit)
+
+ if (params.cursor) {
+ const timeStr = new Date(parseInt(params.cursor, 10)).toISOString()
+ builder = builder.where('post.indexedAt', '<', timeStr)
+ }
+ const res = await builder.execute()
+
+ const feed = res.map((row) => ({
+ post: row.uri,
+ }))
+
+ let cursor: string | undefined
+ const last = res.at(-1)
+ if (last) {
+ cursor = new Date(last.indexedAt).getTime().toString(10)
+ }
+
+ return {
+ cursor,
+ feed,
+ }
+}
diff --git a/src/algos/index.ts b/src/algos/index.ts diff --git a/src/algos/index.ts b/src/algos/index.ts
index b7ee48a..102cb93 100644 index b7ee48a..102cb93 100644
--- a/src/algos/index.ts --- a/src/algos/index.ts