summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/data.dart27
-rw-r--r--lib/db.dart90
-rw-r--r--lib/ui.dart11
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);
});
}