diff --git a/android/build/reports/problems/problems-report.html b/android/build/reports/problems/problems-report.html
new file mode 100644
index 0000000..f85479d
--- /dev/null
+++ b/android/build/reports/problems/problems-report.html
@@ -0,0 +1,663 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Gradle Configuration Cache
+
+
+
+
+
+
+ Loading...
+
+
+
+
+
+
+
diff --git a/lib/dbconstants.dart b/lib/dbconstants.dart
new file mode 100644
index 0000000..959dbb0
--- /dev/null
+++ b/lib/dbconstants.dart
@@ -0,0 +1,3 @@
+class DBConstants {
+ static final String ntServerAddrKey = "ntServerAddr";
+}
diff --git a/lib/main.dart b/lib/main.dart
index bad9274..19f2a97 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,4 +1,6 @@
import 'package:helm/ntutils.dart';
+import 'dbconstants.dart';
+import 'package:shared_preferences/shared_preferences.dart';
import 'pages/dashboard.dart';
import 'package:flutter/material.dart';
@@ -9,7 +11,18 @@ void main() {
class MyApp extends StatelessWidget {
MyApp({super.key}) {
- NTUtils().connect("localhost");
+ _connectNT();
+ }
+
+ void _connectNT() {
+ SharedPreferences.getInstance().then((value) async {
+ String addr = value.getString(DBConstants.ntServerAddrKey) ?? "";
+ if (addr.isEmpty) {
+ addr = "localhost"; // Default to localhost and save
+ await value.setString(DBConstants.ntServerAddrKey, addr);
+ }
+ NTUtils().connect(addr);
+ });
}
// This widget is the root of your application.
diff --git a/lib/pages/dashboard.dart b/lib/pages/dashboard.dart
index 22d3caa..4ec8171 100644
--- a/lib/pages/dashboard.dart
+++ b/lib/pages/dashboard.dart
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:helm/ntutils.dart';
+import 'package:helm/pages/settings.dart';
import 'package:helm/widgets/base_card.dart';
import 'package:helm/widgets/posty/posty_results_card.dart';
import 'package:helm/widgets/posty/posty_summary_card.dart';
@@ -55,6 +56,23 @@ class _DashboardState extends State {
],
),
),
+ drawer: Drawer(
+ child: ListView(
+ padding: EdgeInsets.zero,
+ children: [
+ const DrawerHeader(child: Text("Helm")),
+ ListTile(
+ title: const Text("Settings"),
+ onTap: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(builder: (context) => const Settings()),
+ );
+ },
+ ),
+ ],
+ ),
+ ),
body: TabBarView(
children: [
ResponsiveGridRow(
diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart
new file mode 100644
index 0000000..170c0ac
--- /dev/null
+++ b/lib/pages/settings.dart
@@ -0,0 +1,88 @@
+import 'package:flutter/material.dart';
+import 'package:helm/dbconstants.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+class Settings extends StatefulWidget {
+ const Settings({super.key});
+
+ @override
+ State createState() => _SettingsState();
+}
+
+class _SettingsState extends State {
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(title: const Text('Settings')),
+ body: ListView(
+ children: [
+ _StringSettingTile(
+ title: "Server Address",
+ subtitle: "IP address of the Network Tables server.",
+ leading: Icon(Icons.network_wifi_sharp),
+ preferenceKey: DBConstants.ntServerAddrKey,
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class _StringSettingTile extends StatelessWidget {
+ final String title;
+ final String subtitle;
+ final Icon leading;
+ final String preferenceKey;
+
+ const _StringSettingTile({
+ required this.title,
+ required this.subtitle,
+ required this.leading,
+ required this.preferenceKey,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return ListTile(
+ title: Text(title),
+ subtitle: Text(subtitle),
+ leading: leading,
+ trailing: const Icon(Icons.edit),
+ onTap: () async {
+ final prefs = await SharedPreferences.getInstance();
+ final newValue = await showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ String tempValue = prefs.getString(preferenceKey) ?? "";
+ return AlertDialog(
+ title: Text('Edit $title'),
+ content: TextField(
+ controller: TextEditingController(text: tempValue),
+ onChanged: (value) {
+ tempValue = value;
+ },
+ decoration: InputDecoration(
+ label: Text('Enter new $title'),
+ hintText: tempValue,
+ ),
+ ),
+ actions: [
+ TextButton(
+ onPressed: () => Navigator.of(context).pop(),
+ child: const Text('Cancel'),
+ ),
+ TextButton(
+ onPressed: () => Navigator.of(context).pop(tempValue),
+ child: const Text('Save'),
+ ),
+ ],
+ );
+ },
+ );
+ if (newValue != null) {
+ await prefs.setString(preferenceKey, newValue);
+ }
+ },
+ );
+ }
+}
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index cccf817..724bb2a 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,6 +5,8 @@
import FlutterMacOS
import Foundation
+import shared_preferences_foundation
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
}
diff --git a/pubspec.lock b/pubspec.lock
index cd3b966..546b8ea 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: characters
- sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
+ sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev"
source: hosted
- version: "1.4.0"
+ version: "1.4.1"
clock:
dependency: transitive
description:
@@ -45,10 +45,10 @@ packages:
dependency: transitive
description:
name: crypto
- sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
+ sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
url: "https://pub.dev"
source: hosted
- version: "3.0.6"
+ version: "3.0.7"
cupertino_icons:
dependency: "direct main"
description:
@@ -65,6 +65,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.3"
+ ffi:
+ dependency: transitive
+ description:
+ name: ffi
+ sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
+ 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
@@ -74,15 +90,20 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
- sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1"
+ sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1"
url: "https://pub.dev"
source: hosted
- version: "5.0.0"
+ version: "6.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
+ flutter_web_plugins:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
leak_tracker:
dependency: transitive
description:
@@ -111,26 +132,26 @@ packages:
dependency: transitive
description:
name: lints
- sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7
+ sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df"
url: "https://pub.dev"
source: hosted
- version: "5.1.1"
+ version: "6.1.0"
matcher:
dependency: transitive
description:
name: matcher
- sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
+ sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
url: "https://pub.dev"
source: hosted
- version: "0.12.17"
+ version: "0.12.18"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
- sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
+ sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev"
source: hosted
- version: "0.11.1"
+ version: "0.13.0"
messagepack:
dependency: transitive
description:
@@ -171,6 +192,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
+ 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"
+ 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"
responsive_grid:
dependency: "direct main"
description:
@@ -179,6 +240,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.4.4"
+ shared_preferences:
+ dependency: "direct main"
+ description:
+ name: shared_preferences
+ sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.4"
+ shared_preferences_android:
+ dependency: transitive
+ description:
+ name: shared_preferences_android
+ sha256: "8374d6200ab33ac99031a852eba4c8eb2170c4bf20778b3e2c9eccb45384fb41"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.21"
+ shared_preferences_foundation:
+ dependency: transitive
+ description:
+ name: shared_preferences_foundation
+ sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.5.6"
+ shared_preferences_linux:
+ dependency: transitive
+ description:
+ name: shared_preferences_linux
+ sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shared_preferences_platform_interface:
+ dependency: transitive
+ description:
+ name: shared_preferences_platform_interface
+ sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
+ shared_preferences_web:
+ dependency: transitive
+ description:
+ name: shared_preferences_web
+ sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.3"
+ shared_preferences_windows:
+ dependency: transitive
+ description:
+ name: shared_preferences_windows
+ sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.1"
sky_engine:
dependency: transitive
description: flutter
@@ -188,10 +305,10 @@ packages:
dependency: transitive
description:
name: source_span
- sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
+ sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
url: "https://pub.dev"
source: hosted
- version: "1.10.1"
+ version: "1.10.2"
stack_trace:
dependency: transitive
description:
@@ -228,10 +345,10 @@ packages:
dependency: transitive
description:
name: test_api
- sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
+ sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
url: "https://pub.dev"
source: hosted
- version: "0.7.7"
+ version: "0.7.9"
typed_data:
dependency: transitive
description:
@@ -252,26 +369,34 @@ packages:
dependency: transitive
description:
name: vm_service
- sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
+ sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
url: "https://pub.dev"
source: hosted
- version: "15.0.0"
+ version: "15.0.2"
web:
dependency: transitive
description:
name: web
- sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
+ sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.dev"
source: hosted
- version: "0.5.1"
+ version: "1.1.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
- sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
+ sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev"
source: hosted
- version: "2.4.5"
+ version: "2.4.0"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
sdks:
- dart: ">=3.8.0-0 <4.0.0"
- flutter: ">=3.18.0-18.0.pre.54"
+ dart: ">=3.9.0 <4.0.0"
+ flutter: ">=3.35.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 5862621..66c2cf6 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -36,6 +36,7 @@ dependencies:
cupertino_icons: ^1.0.8
nt4: ^1.3.3
responsive_grid: ^2.4.4
+ shared_preferences: ^2.5.4
dev_dependencies:
flutter_test:
@@ -46,7 +47,7 @@ dev_dependencies:
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
- flutter_lints: ^5.0.0
+ flutter_lints: ^6.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec