diff options
| author | xengineering <me@xengineering.eu> | 2026-04-06 17:03:46 +0200 |
|---|---|---|
| committer | xengineering <me@xengineering.eu> | 2026-04-06 17:03:46 +0200 |
| commit | 877a39e186699164e68ea969012a4f1ec6840ef8 (patch) | |
| tree | 92932f23c5b1d2798a9e63467b0ad4de70caa39f /lib | |
| parent | 1809a88c679fcd17f29c13ddd47732bb65db96b2 (diff) | |
| parent | fcfb2a17733a38b690f4e034c78bc414be5527ef (diff) | |
| download | sia-app-877a39e186699164e68ea969012a4f1ec6840ef8.tar sia-app-877a39e186699164e68ea969012a4f1ec6840ef8.tar.zst sia-app-877a39e186699164e68ea969012a4f1ec6840ef8.zip | |
Merge persisting server fully qualified domain name
This allows to save the server fully qualified domain name (FQDN). The
user does not have to insert this on every app start.
Saved is the value of the corresponding text field on the last press on
the connect button.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/data.dart | 27 | ||||
| -rw-r--r-- | lib/db.dart | 90 | ||||
| -rw-r--r-- | lib/ui.dart | 11 |
3 files changed, 125 insertions, 3 deletions
diff --git a/lib/data.dart b/lib/data.dart index 365f5bc..ca350e5 100644 --- a/lib/data.dart +++ b/lib/data.dart @@ -1,7 +1,12 @@ +import 'dart:io'; +import 'dart:async'; + import 'package:flutter/foundation.dart'; import 'package:mqtt_client/mqtt_client.dart'; import 'package:mqtt_client/mqtt_server_client.dart'; +import 'db.dart'; + const int brokerPort = 1883; const String topicPrefix = 'sia'; @@ -22,6 +27,8 @@ enum MachineEvent { } class AppState with ChangeNotifier { + final DB db = DB(); + static const Map<MachineState, Map<MachineEvent, MachineState>> machine = <MachineState, Map<MachineEvent, MachineState>> { MachineState.init: <MachineEvent, MachineState> { MachineEvent.connect: MachineState.disconnected, @@ -46,9 +53,25 @@ class AppState with ChangeNotifier { Map<String, bool> contacts = <String, bool>{}; late MqttServerClient _client; + late Directory supportDir; String fqdn = ''; - AppState(); + AppState() { + unawaited(loadPersistence()); + } + + Future<void> loadPersistence() async { + await db.connect(); + String? dbFqdn = await db.getServerFqdn(); + if (dbFqdn == null) return; + fqdn = dbFqdn; + notifyListeners(); + } + + void setFqdn(String value) { + fqdn = value; + unawaited(db.setServerFqdn(value)); + } void process(MachineEvent event) { MachineState lastState = state; @@ -103,7 +126,7 @@ class AppState with ChangeNotifier { _client.onAutoReconnected = _onAutoReconnected; try { - _client.connect(); + unawaited(_client.connect()); } catch (e) { _client.disconnect(); return; diff --git a/lib/db.dart b/lib/db.dart new file mode 100644 index 0000000..0b2cf7a --- /dev/null +++ b/lib/db.dart @@ -0,0 +1,90 @@ +import 'dart:io'; +import 'dart:async'; + +import 'package:path_provider/path_provider.dart'; +import 'package:sqlite3/sqlite3.dart'; +import 'package:path/path.dart' as p; + +class DB { + final Completer<Database?> _dbCompleter = Completer<Database?>(); + static const List<String> migrations = <String>[ + ''' +PRAGMA user_version = 1; +CREATE TABLE "key_value" ( + "key" TEXT NOT NULL UNIQUE, + "value" TEXT, + PRIMARY KEY("key") +); + ''', + ]; + + Future<void> connect() async { + String path = await _getDbPath(); + Database candidate = sqlite3.open(path); + + migrate(candidate); + + _dbCompleter.complete(candidate); + } + + void dispose() async { + if (_dbCompleter.isCompleted == false) { + return; + } + Database? db = await _dbCompleter.future; + if (db == null) return; + db.close(); + } + + static Future<String> _getDbPath() async { + Directory supportDir = await getApplicationSupportDirectory(); + return p.join(supportDir.path, 'main.sqlite3'); + } + + static void migrate(Database db) { + for (int i=0; i<migrations.length; i++) { + int? userVersion = _getUserVersion(db); + if (userVersion == null) return; + + if (i == userVersion) { + db.execute(migrations[i]); + } + } + } + + static int? _getUserVersion(Database db) { + ResultSet result = db.select('PRAGMA user_version;'); + if (result.length != 1) return null; + return result.first.values.first as int; + } + + Future<String?> getServerFqdn() async { + Database? db = await _dbCompleter.future; + if (db == null) return null; + + ResultSet result = db.select( + 'SELECT value FROM key_value WHERE key = \'server_fqdn\';' + ); + if (result.length != 1) return null; + + return result[0]['value']; + } + + Future<void> setServerFqdn(String value) async { + Database? db = await _dbCompleter.future; + if (db == null) return; + + String? current = await getServerFqdn(); + if (current == null) { + db.execute( + 'INSERT INTO key_value (key, value) VALUES (\'server_fqdn\', ?);', + <Object?>[value], + ); + } else { + db.execute( + 'UPDATE key_value SET value = ? WHERE key = \'server_fqdn\';', + <Object?>[value], + ); + } + } +} diff --git a/lib/ui.dart b/lib/ui.dart index 9603562..3a98be9 100644 --- a/lib/ui.dart +++ b/lib/ui.dart @@ -41,8 +41,17 @@ class _ConnectionPageState extends State<ConnectionPage> { final AppState provider = context.read<AppState>(); controller = TextEditingController(text: provider.fqdn); + provider.addListener(() { + if (controller.text != provider.fqdn) { + controller.text = provider.fqdn; + controller.selection = TextSelection.fromPosition( + TextPosition(offset: controller.text.length), + ); + } + }); + controller.addListener(() { - provider.fqdn = controller.text; + provider.setFqdn(controller.text); }); } |
