362 lines
11 KiB
Diff
362 lines
11 KiB
Diff
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,
|
|
+ },
|
|
+})
|