summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--analysis_options.yaml2
-rw-r--r--lib/data.dart27
-rw-r--r--lib/db.dart90
-rw-r--r--lib/ui.dart11
-rw-r--r--pubspec.lock148
-rw-r--r--pubspec.yaml3
6 files changed, 276 insertions, 5 deletions
diff --git a/analysis_options.yaml b/analysis_options.yaml
index c8ed5db..c7d3757 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -8,3 +8,5 @@ linter:
prefer_final_fields: true
avoid_dynamic_calls: true
unnecessary_null_checks: true
+ unawaited_futures: true
+ discarded_futures: true
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);
});
}
diff --git a/pubspec.lock b/pubspec.lock
index 26b837f..30521d2 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -65,6 +65,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.2"
+ code_assets:
+ dependency: transitive
+ description:
+ name: code_assets
+ sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
collection:
dependency: transitive
description:
@@ -105,6 +113,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.0"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.1"
flutter:
dependency: "direct main"
description: flutter
@@ -131,6 +147,22 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ glob:
+ dependency: transitive
+ description:
+ name: glob
+ sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.3"
+ hooks:
+ dependency: transitive
+ description:
+ name: hooks
+ sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.2"
image:
dependency: transitive
description:
@@ -179,6 +211,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.1.0"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
matcher:
dependency: transitive
description:
@@ -211,6 +251,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "10.11.9"
+ native_toolchain_c:
+ dependency: transitive
+ description:
+ name: native_toolchain_c
+ sha256: "92b2ca62c8bd2b8d2f267cdfccf9bfbdb7322f778f8f91b3ce5b5cda23a3899f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.17.5"
nested:
dependency: transitive
description:
@@ -219,14 +267,70 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
- path:
+ objective_c:
dependency: transitive
description:
+ name: objective_c
+ sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52"
+ url: "https://pub.dev"
+ source: hosted
+ version: "9.3.0"
+ path:
+ dependency: "direct main"
+ description:
name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
+ path_provider:
+ dependency: "direct main"
+ description:
+ name: path_provider
+ sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.5"
+ path_provider_android:
+ dependency: transitive
+ description:
+ name: path_provider_android
+ sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.22"
+ path_provider_foundation:
+ dependency: transitive
+ description:
+ name: path_provider_foundation
+ sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.6.0"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.1"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ path_provider_windows:
+ dependency: transitive
+ description:
+ name: path_provider_windows
+ sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.3.0"
petitparser:
dependency: transitive
description:
@@ -235,6 +339,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "7.0.2"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.6"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.8"
posix:
dependency: transitive
description:
@@ -251,6 +371,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.1.5+1"
+ pub_semver:
+ dependency: transitive
+ description:
+ name: pub_semver
+ sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.0"
sky_engine:
dependency: transitive
description: flutter
@@ -264,6 +392,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.2"
+ sqlite3:
+ dependency: "direct main"
+ description:
+ name: sqlite3
+ sha256: caa693ad15a587a2b4fde093b728131a1827903872171089dedb16f7665d3a91
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.0"
stack_trace:
dependency: transitive
description:
@@ -336,6 +472,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.1"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
xml:
dependency: transitive
description:
@@ -354,4 +498,4 @@ packages:
version: "3.1.3"
sdks:
dart: ">=3.10.4 <4.0.0"
- flutter: ">=3.18.0-18.0.pre.54"
+ flutter: ">=3.38.4"
diff --git a/pubspec.yaml b/pubspec.yaml
index ec03450..605d9d4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -10,7 +10,10 @@ dependencies:
flutter:
sdk: flutter
mqtt_client: ^10.11.3
+ path: ^1.9.1
+ path_provider: ^2.1.5
provider: ^6.1.5
+ sqlite3: ^3.2.0
dev_dependencies:
flutter_test: