164 lines
4.6 KiB
TypeScript
164 lines
4.6 KiB
TypeScript
import { useCallback, useEffect, useState } from 'react'
|
|
import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native'
|
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
import { useRouter } from 'expo-router'
|
|
import { ChevronLeft, ChevronRight, Globe } from 'lucide-react-native'
|
|
import { PickerModal, type PickerOption } from '../src/components/PickerModal'
|
|
import {
|
|
loadTerminalLinkOpenMode,
|
|
saveTerminalLinkOpenMode,
|
|
type MobileTerminalLinkOpenMode
|
|
} from '../src/storage/preferences'
|
|
import { colors, radii, spacing, typography } from '../src/theme/mobile-theme'
|
|
|
|
const LINK_MODE_OPTIONS: PickerOption<MobileTerminalLinkOpenMode>[] = [
|
|
{
|
|
value: 'orca-browser',
|
|
label: 'Orca browser on desktop',
|
|
subtitle: 'Open in the streamed browser from your paired desktop.'
|
|
},
|
|
{
|
|
value: 'phone-browser',
|
|
label: 'Phone browser',
|
|
subtitle: 'Open in Safari, Chrome, or another browser on this phone.'
|
|
}
|
|
]
|
|
|
|
function linkModeLabel(mode: MobileTerminalLinkOpenMode): string {
|
|
return (
|
|
LINK_MODE_OPTIONS.find((option) => option.value === mode)?.label ?? LINK_MODE_OPTIONS[0]!.label
|
|
)
|
|
}
|
|
|
|
export default function BrowserSettingsScreen(): React.JSX.Element {
|
|
const router = useRouter()
|
|
const insets = useSafeAreaInsets()
|
|
const [linkMode, setLinkMode] = useState<MobileTerminalLinkOpenMode>('orca-browser')
|
|
const [pickerOpen, setPickerOpen] = useState(false)
|
|
|
|
useEffect(() => {
|
|
void loadTerminalLinkOpenMode().then(setLinkMode)
|
|
}, [])
|
|
|
|
const selectLinkMode = useCallback((mode: MobileTerminalLinkOpenMode) => {
|
|
setLinkMode(mode)
|
|
void saveTerminalLinkOpenMode(mode)
|
|
}, [])
|
|
|
|
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}>Browser</Text>
|
|
</View>
|
|
|
|
<ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
|
|
<Text style={styles.groupHeading}>LINKS</Text>
|
|
<Text style={styles.groupDescription}>
|
|
Choose where HTTP(S) links tapped in terminal output open.
|
|
</Text>
|
|
<View style={[styles.section, styles.sectionTopGap]}>
|
|
<Pressable
|
|
style={({ pressed }) => [styles.row, pressed && styles.rowPressed]}
|
|
onPress={() => setPickerOpen(true)}
|
|
>
|
|
<Globe size={16} color={colors.textSecondary} />
|
|
<View style={styles.rowContent}>
|
|
<Text style={styles.rowLabel}>Open terminal links</Text>
|
|
<Text style={styles.rowSublabel}>{linkModeLabel(linkMode)}</Text>
|
|
</View>
|
|
<ChevronRight size={16} color={colors.textMuted} />
|
|
</Pressable>
|
|
</View>
|
|
</ScrollView>
|
|
|
|
<PickerModal<MobileTerminalLinkOpenMode>
|
|
visible={pickerOpen}
|
|
title="Open terminal links"
|
|
options={LINK_MODE_OPTIONS}
|
|
selected={linkMode}
|
|
onSelect={selectLinkMode}
|
|
onClose={() => setPickerOpen(false)}
|
|
/>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: colors.bgBase,
|
|
paddingHorizontal: spacing.lg,
|
|
paddingTop: 0
|
|
},
|
|
topRow: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
marginTop: spacing.sm,
|
|
marginBottom: spacing.lg
|
|
},
|
|
backButton: {
|
|
width: 36,
|
|
height: 36,
|
|
borderRadius: 18,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginRight: spacing.sm
|
|
},
|
|
heading: {
|
|
fontSize: 20,
|
|
fontWeight: '700',
|
|
color: colors.textPrimary
|
|
},
|
|
scrollContent: {
|
|
paddingBottom: spacing.xl
|
|
},
|
|
groupHeading: {
|
|
fontSize: 11,
|
|
fontWeight: '600',
|
|
color: colors.textMuted,
|
|
letterSpacing: 0.5,
|
|
marginBottom: spacing.xs,
|
|
paddingHorizontal: spacing.xs
|
|
},
|
|
groupDescription: {
|
|
fontSize: typography.bodySize - 1,
|
|
color: colors.textSecondary,
|
|
lineHeight: 20,
|
|
paddingHorizontal: spacing.xs
|
|
},
|
|
section: {
|
|
backgroundColor: colors.bgPanel,
|
|
borderRadius: radii.card,
|
|
overflow: 'hidden'
|
|
},
|
|
sectionTopGap: {
|
|
marginTop: spacing.sm
|
|
},
|
|
row: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: spacing.sm + 2,
|
|
paddingVertical: spacing.md,
|
|
paddingHorizontal: spacing.md + 2
|
|
},
|
|
rowPressed: {
|
|
backgroundColor: colors.bgRaised
|
|
},
|
|
rowContent: {
|
|
flex: 1
|
|
},
|
|
rowLabel: {
|
|
fontSize: typography.bodySize,
|
|
fontWeight: '500',
|
|
color: colors.textPrimary
|
|
},
|
|
rowSublabel: {
|
|
fontSize: typography.bodySize - 2,
|
|
color: colors.textSecondary,
|
|
marginTop: 2
|
|
}
|
|
})
|