feat: persist server settings

This commit is contained in:
2026-05-07 19:51:17 +02:00
parent 7186081388
commit 711c321dcf
3 changed files with 31 additions and 25 deletions
@@ -1,10 +1,14 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import '../../../domain/models/server_config.dart';
typedef Credentials = ({String username, String password}); typedef Credentials = ({String username, String password});
class CredentialStore { class CredentialStore {
static const _usernameKey = 'localiserd_username'; static const _usernameKey = 'localiserd_username';
static const _passwordKey = 'localiserd_password'; static const _passwordKey = 'localiserd_password';
static const _hostKey = 'localiserd_host';
static const _portKey = 'localiserd_port';
final _storage = const FlutterSecureStorage(); final _storage = const FlutterSecureStorage();
@@ -24,8 +28,28 @@ class CredentialStore {
return (username: username, password: password); return (username: username, password: password);
} }
Future<void> saveServer(ServerConfig config) => Future.wait([
_storage.write(key: _hostKey, value: config.host),
_storage.write(key: _portKey, value: config.port.toString()),
]).then((_) {});
Future<ServerConfig?> loadServer() async {
final results = await Future.wait([
_storage.read(key: _hostKey),
_storage.read(key: _portKey),
]);
final host = results[0];
final portStr = results[1];
if (host == null || portStr == null) return null;
final port = int.tryParse(portStr);
if (port == null) return null;
return ServerConfig(host: host, port: port);
}
Future<void> clear() => Future.wait([ Future<void> clear() => Future.wait([
_storage.delete(key: _usernameKey), _storage.delete(key: _usernameKey),
_storage.delete(key: _passwordKey), _storage.delete(key: _passwordKey),
_storage.delete(key: _hostKey),
_storage.delete(key: _portKey),
]).then((_) {}); ]).then((_) {});
} }
+4 -23
View File
@@ -18,12 +18,6 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
bool _loading = false; bool _loading = false;
String? _error; String? _error;
@override
void initState() {
super.initState();
_tryAutoLogin();
}
@override @override
void dispose() { void dispose() {
_usernameController.dispose(); _usernameController.dispose();
@@ -31,18 +25,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
super.dispose(); super.dispose();
} }
Future<void> _tryAutoLogin() async { Future<void> _login(String username, String password) async {
final store = ref.read(credentialStoreProvider);
final saved = await store.load();
if (saved == null || !mounted) return;
_usernameController.text = saved.username;
_passwordController.text = saved.password;
await _login(saved.username, saved.password, saveCredentials: false);
}
Future<void> _login(String username, String password,
{bool saveCredentials = true}) async {
setState(() { setState(() {
_loading = true; _loading = true;
_error = null; _error = null;
@@ -59,11 +42,9 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
await realtime.connect(); await realtime.connect();
ref.read(realtimeDataClientProvider.notifier).state = realtime; ref.read(realtimeDataClientProvider.notifier).state = realtime;
if (saveCredentials) { await ref
await ref .read(credentialStoreProvider)
.read(credentialStoreProvider) .save((username: username, password: password));
.save((username: username, password: password));
}
if (mounted) context.go('/floorplan'); if (mounted) context.go('/floorplan');
} on Exception catch (e) { } on Exception catch (e) {
@@ -59,12 +59,13 @@ class _ServerDiscoveryScreenState extends ConsumerState<ServerDiscoveryScreen> {
await OnboardingClient(config: config).getChecklist(); await OnboardingClient(config: config).getChecklist();
ref.read(serverConfigProvider.notifier).state = config; ref.read(serverConfigProvider.notifier).state = config;
await ref.read(credentialStoreProvider).saveServer(config);
if (!mounted) return; if (!mounted) return;
if (!checklist.hasAdmin) { if (!checklist.hasAdmin) {
context.go('/onboarding'); context.push('/onboarding');
} else { } else {
context.go('/login'); context.push('/login');
} }
} catch (e) { } catch (e) {
setState(() => _error = e.toString()); setState(() => _error = e.toString());