168 lines
5.5 KiB
TypeScript
168 lines
5.5 KiB
TypeScript
import { View, Text, StyleSheet, Pressable, Linking, Platform } from 'react-native'
|
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
import { useRouter } from 'expo-router'
|
|
import { ChevronLeft, Globe } from 'lucide-react-native'
|
|
import Svg, { Path } from 'react-native-svg'
|
|
import Constants from 'expo-constants'
|
|
import { OrcaLogo } from '../src/components/OrcaLogo'
|
|
import { colors, spacing, typography } from '../src/theme/mobile-theme'
|
|
|
|
// Why: read version + native build identifier from expo-constants at
|
|
// runtime so the About screen never drifts out of sync with app.json.
|
|
// nativeBuildVersion is iOS buildNumber on iOS and versionCode on
|
|
// Android — different concepts, same role (monotonic native build id).
|
|
function getVersionLabel(): string {
|
|
const version = Constants.expoConfig?.version ?? '?.?.?'
|
|
const build =
|
|
Platform.OS === 'ios'
|
|
? Constants.expoConfig?.ios?.buildNumber
|
|
: String(Constants.expoConfig?.android?.versionCode ?? '')
|
|
return build ? `v${version} (${build})` : `v${version}`
|
|
}
|
|
|
|
function GithubIcon({ size = 16, color = colors.textSecondary }) {
|
|
return (
|
|
<Svg width={size} height={size} viewBox="0 0 24 24" fill={color}>
|
|
<Path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" />
|
|
</Svg>
|
|
)
|
|
}
|
|
|
|
function XIcon({ size = 16, color = colors.textSecondary }) {
|
|
return (
|
|
<Svg width={size} height={size} viewBox="0 0 24 24" fill={color}>
|
|
<Path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" />
|
|
</Svg>
|
|
)
|
|
}
|
|
|
|
export default function AboutScreen() {
|
|
const router = useRouter()
|
|
const insets = useSafeAreaInsets()
|
|
|
|
return (
|
|
<View style={[styles.container, { paddingTop: insets.top + spacing.sm }]}>
|
|
<View style={styles.topRow}>
|
|
<Pressable style={styles.backButton} onPress={() => router.back()}>
|
|
<ChevronLeft size={22} color={colors.textSecondary} />
|
|
</Pressable>
|
|
<Text style={styles.heading}>About</Text>
|
|
</View>
|
|
|
|
<View style={styles.brand}>
|
|
<OrcaLogo size={28} />
|
|
<Text style={styles.brandName}>Orca</Text>
|
|
<Text style={styles.brandSub}>Open-source agent IDE for 100x builders</Text>
|
|
</View>
|
|
|
|
<View style={styles.section}>
|
|
<Pressable
|
|
style={({ pressed }) => [styles.row, pressed && styles.rowPressed]}
|
|
onPress={() => void Linking.openURL('https://onOrca.dev')}
|
|
>
|
|
<Globe size={16} color={colors.textSecondary} />
|
|
<Text style={styles.rowValue}>onOrca.dev</Text>
|
|
</Pressable>
|
|
<View style={styles.separator} />
|
|
<Pressable
|
|
style={({ pressed }) => [styles.row, pressed && styles.rowPressed]}
|
|
onPress={() => void Linking.openURL('https://github.com/stablyai/orca')}
|
|
>
|
|
<GithubIcon />
|
|
<Text style={styles.rowValue}>stablyai/orca</Text>
|
|
</Pressable>
|
|
<View style={styles.separator} />
|
|
<Pressable
|
|
style={({ pressed }) => [styles.row, pressed && styles.rowPressed]}
|
|
onPress={() => void Linking.openURL('https://x.com/orca_build')}
|
|
>
|
|
<XIcon />
|
|
<Text style={styles.rowValue}>@orca_build</Text>
|
|
</Pressable>
|
|
</View>
|
|
|
|
<Text style={styles.versionText}>{getVersionLabel()}</Text>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: colors.bgBase,
|
|
padding: spacing.lg
|
|
},
|
|
topRow: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
marginBottom: spacing.xl
|
|
},
|
|
backButton: {
|
|
width: 36,
|
|
height: 36,
|
|
borderRadius: 18,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginRight: spacing.sm
|
|
},
|
|
heading: {
|
|
fontSize: 20,
|
|
fontWeight: '700',
|
|
color: colors.textPrimary
|
|
},
|
|
brand: {
|
|
alignItems: 'center',
|
|
paddingVertical: spacing.xl,
|
|
marginBottom: spacing.lg
|
|
},
|
|
brandName: {
|
|
fontSize: 22,
|
|
fontWeight: '800',
|
|
color: colors.textPrimary,
|
|
marginTop: spacing.sm
|
|
},
|
|
brandSub: {
|
|
fontSize: 13,
|
|
color: colors.textMuted,
|
|
marginTop: spacing.xs
|
|
},
|
|
section: {
|
|
backgroundColor: colors.bgPanel,
|
|
borderRadius: 12,
|
|
overflow: 'hidden'
|
|
},
|
|
row: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: spacing.sm + 2,
|
|
paddingVertical: spacing.md,
|
|
paddingHorizontal: spacing.md + 2
|
|
},
|
|
rowPressed: {
|
|
backgroundColor: colors.bgRaised
|
|
},
|
|
rowLabel: {
|
|
flex: 1,
|
|
fontSize: typography.bodySize,
|
|
fontWeight: '500',
|
|
color: colors.textPrimary
|
|
},
|
|
rowValue: {
|
|
flex: 1,
|
|
textAlign: 'right',
|
|
fontSize: typography.bodySize,
|
|
color: colors.textSecondary
|
|
},
|
|
separator: {
|
|
height: StyleSheet.hairlineWidth,
|
|
backgroundColor: colors.borderSubtle,
|
|
marginHorizontal: spacing.md
|
|
},
|
|
versionText: {
|
|
marginTop: spacing.lg,
|
|
textAlign: 'center',
|
|
fontSize: typography.metaSize,
|
|
color: colors.textMuted
|
|
}
|
|
})
|