Some checks failed
Upstream Sync / Sync latest commits from upstream repo (push) Has been cancelled
99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
import { useCallback, useEffect, useState } from 'react'
|
||
import { View, Text, ScrollView, StyleSheet, RefreshControl } from 'react-native'
|
||
import { SafeAreaView } from 'react-native-safe-area-context'
|
||
|
||
import { useBind } from '@/context/BindContext'
|
||
import { apiFetch } from '@/lib/api'
|
||
import { theme } from '@/constants/theme'
|
||
|
||
export default function NetworkScreen() {
|
||
const { bind } = useBind()
|
||
const [raw, setRaw] = useState<string>('')
|
||
const [err, setErr] = useState('')
|
||
const [refreshing, setRefreshing] = useState(false)
|
||
|
||
const load = useCallback(async () => {
|
||
if (!bind) {
|
||
setErr('未绑定')
|
||
setRaw('')
|
||
return
|
||
}
|
||
setErr('')
|
||
try {
|
||
const r = await apiFetch(bind, '/network_status')
|
||
if (!r.ok) throw new Error(String(r.status))
|
||
const j = await r.json()
|
||
setRaw(JSON.stringify(j, null, 2))
|
||
} catch (e) {
|
||
setErr(e instanceof Error ? e.message : String(e))
|
||
setRaw('')
|
||
}
|
||
}, [bind])
|
||
|
||
useEffect(() => {
|
||
void load()
|
||
}, [load])
|
||
|
||
const onRefresh = useCallback(async () => {
|
||
setRefreshing(true)
|
||
await load()
|
||
setRefreshing(false)
|
||
}, [load])
|
||
|
||
return (
|
||
<SafeAreaView style={styles.safe} edges={['bottom']}>
|
||
<ScrollView
|
||
contentContainerStyle={styles.scroll}
|
||
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={() => void onRefresh()} />}
|
||
>
|
||
<Text style={styles.h1}>网络</Text>
|
||
<Text style={styles.lead}>Google / 抖音 连通与测速。无公网时请通过「配对」页完成 EasyTier 组网。</Text>
|
||
|
||
{bind && (
|
||
<View style={styles.et}>
|
||
<Text style={styles.etTitle}>EasyTier(本机已保存)</Text>
|
||
<Text style={styles.mono}>组网名 {bind.easytier.networkName}</Text>
|
||
<Text style={styles.mutedSmall}>
|
||
密钥与 peer 已随扫码写入;与 PC 完全一致即可在虚拟网内访问 {bind.baseUrl}
|
||
</Text>
|
||
</View>
|
||
)}
|
||
|
||
{err ? <Text style={styles.err}>{err}</Text> : null}
|
||
{raw ? <Text style={styles.pre}>{raw}</Text> : !err && bind ? <Text style={styles.muted}>暂无</Text> : null}
|
||
</ScrollView>
|
||
</SafeAreaView>
|
||
)
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
safe: { flex: 1, backgroundColor: theme.bg },
|
||
scroll: { padding: 20, paddingBottom: 40 },
|
||
h1: { fontSize: 22, fontWeight: '700', color: theme.text, marginBottom: 8 },
|
||
lead: { fontSize: 14, color: theme.muted, marginBottom: 16, lineHeight: 22 },
|
||
et: {
|
||
padding: 14,
|
||
borderRadius: 12,
|
||
backgroundColor: 'rgba(124,92,255,0.08)',
|
||
borderWidth: 1,
|
||
borderColor: 'rgba(124,92,255,0.25)',
|
||
marginBottom: 16,
|
||
},
|
||
etTitle: { fontSize: 14, fontWeight: '600', color: theme.text, marginBottom: 8 },
|
||
mono: { fontFamily: 'monospace', fontSize: 12, color: theme.accent },
|
||
mutedSmall: { fontSize: 12, color: theme.muted, marginTop: 8, lineHeight: 18 },
|
||
pre: {
|
||
fontFamily: 'monospace',
|
||
fontSize: 11,
|
||
color: '#c8cdd5',
|
||
lineHeight: 18,
|
||
backgroundColor: theme.bgCard,
|
||
padding: 12,
|
||
borderRadius: 10,
|
||
borderWidth: 1,
|
||
borderColor: theme.border,
|
||
},
|
||
err: { color: theme.danger, marginBottom: 12 },
|
||
muted: { color: theme.muted },
|
||
})
|