feat: add settings screen with WebDAV config
This commit is contained in:
parent
c51a5f494f
commit
553284f3b2
1 changed files with 133 additions and 0 deletions
133
src/screens/SettingsScreen.tsx
Normal file
133
src/screens/SettingsScreen.tsx
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import { View, Text, TextInput, TouchableOpacity, StyleSheet, Alert, ScrollView } from 'react-native'
|
||||
import * as SecureStore from 'expo-secure-store'
|
||||
import { WebDAVConfig } from '../types'
|
||||
|
||||
const CONFIG_KEY = 'weegschaal_webdav_config'
|
||||
|
||||
async function loadConfig(): Promise<WebDAVConfig | null> {
|
||||
try {
|
||||
const json = await SecureStore.getItemAsync(CONFIG_KEY)
|
||||
return json ? JSON.parse(json) : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function saveConfig(config: WebDAVConfig): Promise<void> {
|
||||
await SecureStore.setItemAsync(CONFIG_KEY, JSON.stringify(config))
|
||||
}
|
||||
|
||||
async function deleteConfig(): Promise<void> {
|
||||
await SecureStore.deleteItemAsync(CONFIG_KEY)
|
||||
}
|
||||
|
||||
export async function getWebDAVConfig(): Promise<WebDAVConfig | null> {
|
||||
return loadConfig()
|
||||
}
|
||||
|
||||
export default function SettingsScreen() {
|
||||
const [url, setUrl] = useState('')
|
||||
const [username, setUsername] = useState('')
|
||||
const [password, setPassword] = useState('')
|
||||
const [syncing, setSyncing] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
loadConfig().then(c => {
|
||||
if (c) {
|
||||
setUrl(c.url)
|
||||
setUsername(c.username)
|
||||
setPassword(c.password)
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
const handleSave = async () => {
|
||||
await saveConfig({ url, username, password })
|
||||
Alert.alert('Opgeslagen', 'WebDAV instellingen zijn opgeslagen')
|
||||
}
|
||||
|
||||
const handleClear = async () => {
|
||||
await deleteConfig()
|
||||
setUrl('')
|
||||
setUsername('')
|
||||
setPassword('')
|
||||
Alert.alert('Verwijderd', 'WebDAV instellingen zijn gewist')
|
||||
}
|
||||
|
||||
const handleSync = async () => {
|
||||
setSyncing(true)
|
||||
try {
|
||||
const { syncAll } = await import('../sync/syncService')
|
||||
const result = await syncAll()
|
||||
Alert.alert('Sync voltooid', `Lokaal: ${result.local}, WebDAV: ${result.remote}, samengevoegd: ${result.merged}`)
|
||||
} catch (e: any) {
|
||||
Alert.alert('Sync fout', e?.message ?? 'Onbekende fout')
|
||||
} finally {
|
||||
setSyncing(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
|
||||
<Text style={styles.sectionTitle}>WebDAV (Nextcloud)</Text>
|
||||
|
||||
<Text style={styles.label}>URL</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={url}
|
||||
onChangeText={setUrl}
|
||||
placeholder="https://nextcloud.example.nl/remote.php/dav/files/gebruiker/"
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
/>
|
||||
|
||||
<Text style={styles.label}>Gebruikersnaam</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={username}
|
||||
onChangeText={setUsername}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
/>
|
||||
|
||||
<Text style={styles.label}>Wachtwoord</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
value={password}
|
||||
onChangeText={setPassword}
|
||||
secureTextEntry
|
||||
/>
|
||||
|
||||
<TouchableOpacity style={styles.saveButton} onPress={handleSave}>
|
||||
<Text style={styles.buttonText}>Instellingen opslaan</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={styles.clearButton} onPress={handleClear}>
|
||||
<Text style={styles.clearButtonText}>Instellingen wissen</Text>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.syncButton, syncing && styles.syncButtonDisabled]}
|
||||
onPress={handleSync}
|
||||
disabled={syncing}
|
||||
>
|
||||
<Text style={styles.buttonText}>{syncing ? 'Bezig met sync...' : 'Nu synchroniseren'}</Text>
|
||||
</TouchableOpacity>
|
||||
</ScrollView>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: { flex: 1, backgroundColor: '#f5f5f5' },
|
||||
content: { padding: 16 },
|
||||
sectionTitle: { fontSize: 18, fontWeight: '700', marginBottom: 16 },
|
||||
label: { fontSize: 14, fontWeight: '600', color: '#333', marginBottom: 4, marginTop: 12 },
|
||||
input: { backgroundColor: '#fff', borderRadius: 8, padding: 12, fontSize: 16, borderWidth: 1, borderColor: '#ddd' },
|
||||
saveButton: { backgroundColor: '#4CAF50', padding: 14, borderRadius: 8, alignItems: 'center', marginTop: 24 },
|
||||
clearButton: { padding: 14, alignItems: 'center', marginTop: 8 },
|
||||
clearButtonText: { color: '#e53935', fontSize: 14 },
|
||||
syncButton: { backgroundColor: '#2196F3', padding: 14, borderRadius: 8, alignItems: 'center', marginTop: 24 },
|
||||
syncButtonDisabled: { opacity: 0.6 },
|
||||
buttonText: { color: '#fff', fontSize: 16, fontWeight: '700' },
|
||||
})
|
||||
Loading…
Reference in a new issue