diff --git a/lib/src/proxmox_lister/proxmox_lister_list_view.dart b/lib/src/proxmox_lister/proxmox_lister_list_view.dart index 325c527..c0f927c 100644 --- a/lib/src/proxmox_lister/proxmox_lister_list_view.dart +++ b/lib/src/proxmox_lister/proxmox_lister_list_view.dart @@ -44,10 +44,27 @@ class _ProxmoxListerState extends State { Future getVms() async { await settings.loadSettings(); + final protocol = settings.get("protocol", 'https://'); + final hostname = settings.get("hostname", ""); + final username = settings.get("username", ""); + final password = settings.get("password", ""); + var port = settings.get("port", 0); + + if (hostname.isEmpty) return {}; + if (port == 0) { + if (settings.get("protocol", 'https://') == 'https://') { + port = 443; + } else { + port = 80; + } + } + _service = ProxmoxWebService( - hostname: settings.hostname, - username: settings.username, - password: settings.password, + protocol: protocol, + hostname: hostname, + port: port, + username: username, + password: password, ); final success = await _service.authenticate(); if (!success) { diff --git a/lib/src/proxmox_webservice/service.dart b/lib/src/proxmox_webservice/service.dart index d2c3e9f..39b37bc 100644 --- a/lib/src/proxmox_webservice/service.dart +++ b/lib/src/proxmox_webservice/service.dart @@ -6,12 +6,16 @@ import 'model.dart'; class ProxmoxWebService { ProxmoxWebService({ - this.hostname = "", - this.username = "", - this.password = "", + required this.protocol, + required this.hostname, + required this.port, + required this.username, + required this.password, }); + final String protocol; final String hostname; + final int port; final String username; final String password; diff --git a/lib/src/settings/settings_controller.dart b/lib/src/settings/settings_controller.dart index f29a34f..1919181 100644 --- a/lib/src/settings/settings_controller.dart +++ b/lib/src/settings/settings_controller.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:pi_dashboard/logger.dart'; import 'settings_service.dart'; @@ -9,48 +8,50 @@ import 'settings_service.dart'; /// Controllers glue Data Services to Flutter Widgets. The SettingsController /// uses the SettingsService to store and retrieve user settings. class SettingsController with ChangeNotifier { - SettingsController(this._settingsService); + SettingsController( + this._settingsService, + ) : _stringOpts = {}, + _boolOpts = {}, + _intOpts = {}; final SettingsService _settingsService; Future loadSettings() async { _themeMode = await _settingsService.themeMode(); - _hostname = await _settingsService.keyStr("hostname"); - _username = await _settingsService.keyStr("username"); - _password = await _settingsService.keyStr("password"); + _stringOpts["protocol"] = await _settingsService.get("protocol"); + _stringOpts["hostname"] = await _settingsService.get("hostname"); + _intOpts["port"] = await _settingsService.get("port"); + _stringOpts["username"] = await _settingsService.get("username"); + _stringOpts["password"] = await _settingsService.get("password"); + _boolOpts["lockApp"] = await _settingsService.get("lockApp"); // Important! Inform listeners a change has occurred. notifyListeners(); } late ThemeMode _themeMode; ThemeMode get themeMode => _themeMode; - late String _hostname; - String get hostname => _hostname; - late String _username; - String get username => _username; - late String _password; - String get password => _password; + final Map _stringOpts; + final Map _boolOpts; + final Map _intOpts; - Future _setKey(String key, String value) async { + Future set(String key, T? value) async { + if (value == null) return; + await _settingsService.set(key, value); notifyListeners(); - await _settingsService.setKeyStr(key, value); } - Future setHostname(String newHostname) async { - _hostname = newHostname; - await _setKey("hostname", hostname); - Log().debug("Hostname update: $hostname"); - } - Future setUsername(String newUsername) async { - _username = newUsername; - await _setKey("username", username); - Log().debug("username update: $username"); - } - Future setPassword(String newPassword) async { - _password = newPassword; - await _setKey("password", password); - Log().debug("password update"); + T get(String key, T default_) { + if (T is String) { + return _stringOpts.containsKey(key) ? _stringOpts[key] as T : default_; + } else if (T is bool) { + return _boolOpts.containsKey(key) ? _boolOpts[key] as T : default_; + } else if (T is int) { + return _intOpts.containsKey(key) ? _intOpts[key] as T : default_; + } else { + throw Exception("this type is not implemented"); + } } + /// Update and persist the ThemeMode based on the user's selection. Future updateThemeMode(ThemeMode? newThemeMode) async { if (newThemeMode == null) return; diff --git a/lib/src/settings/settings_service.dart b/lib/src/settings/settings_service.dart index 155348e..717d838 100644 --- a/lib/src/settings/settings_service.dart +++ b/lib/src/settings/settings_service.dart @@ -22,14 +22,30 @@ class SettingsService { prefs.setInt("theme", theme.index); } - Future keyStr(String key) async { + Future get(String key) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); - final res = prefs.getString(key); - if (res == null) return ""; + T? res; + + if (T == String) { + res = prefs.getString(key) as T?; + } else if (T == bool) { + res = prefs.getBool(key) as T?; + } else if (T == int) { + res = prefs.getInt(key) as T?; + } else { + res = null as T?; + } return res; } - Future setKeyStr(String key, String value) async { + + Future set(String k, T v) async { final SharedPreferences prefs = await SharedPreferences.getInstance(); - await prefs.setString(key, value); + if (T is String) { + await prefs.setString(k, v as String); + } else if (T is bool) { + await prefs.setBool(k, v as bool); + } else if (T is int) { + await prefs.setInt(k, v as int); + } } } diff --git a/lib/src/settings/settings_view.dart b/lib/src/settings/settings_view.dart index b272ad9..2b1d42b 100644 --- a/lib/src/settings/settings_view.dart +++ b/lib/src/settings/settings_view.dart @@ -20,57 +20,96 @@ class SettingsView extends StatelessWidget { title: const Text('Settings'), ), body: Padding( - padding: const EdgeInsets.all(16), - child: Column( + padding: const EdgeInsets.all(16), + child: Column( children: [ - DropdownButton( - value: controller.themeMode, - onChanged: controller.updateThemeMode, - items: const [ - DropdownMenuItem( - value: ThemeMode.system, - child: Text('System Theme'), - ), - DropdownMenuItem( - value: ThemeMode.light, - child: Text('Light Theme'), - ), - DropdownMenuItem( - value: ThemeMode.dark, - child: Text('Dark Theme'), - ) - ], - ), - TextFormField( - decoration: const InputDecoration( - border: UnderlineInputBorder(), - labelText: "Hostname", - ), - initialValue: controller.hostname, - onChanged: controller.setHostname, - ), - TextFormField( - decoration: const InputDecoration( - border: UnderlineInputBorder(), - labelText: "Username", - ), - initialValue: controller.username, - onChanged: controller.setUsername, - ), - TextFormField( - decoration: const InputDecoration( - border: UnderlineInputBorder(), - labelText: "Password", - ), - obscureText: true, - enableSuggestions: false, - autocorrect: false, - initialValue: controller.password, - onChanged: controller.setPassword, - ), - ], + themeSelector(), + ...hostSelector(), + ...loginForm(), + ], ), ), ); } + + Widget themeSelector() { + return DropdownButton( + value: controller.themeMode, + onChanged: controller.updateThemeMode, + items: const [ + DropdownMenuItem( + value: ThemeMode.system, + child: Text('System Theme'), + ), + DropdownMenuItem( + value: ThemeMode.light, + child: Text('Light Theme'), + ), + DropdownMenuItem( + value: ThemeMode.dark, + child: Text('Dark Theme'), + ) + ], + ); + } + + List hostSelector() { + return [ + DropdownButton( + value: controller.get('protocol', 'https://'), + onChanged: (v) => controller.set('protocol', v), + items: const [ + DropdownMenuItem( + value: 'https://', + child: Text('https://'), + ), + DropdownMenuItem( + value: 'http://', + child: Text('http://'), + ) + ], + ), + TextFormField( + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: "Hostname", + ), + initialValue: controller.get('hostname', ''), + onChanged: (v) => controller.set('hostname', v), + ), + TextFormField( + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: "Port", + ), + keyboardType: TextInputType.number, + initialValue: controller.get("port", 0).toString(), + onChanged: (v) => controller.set('port', int.parse(v)), + ), + ]; + } + + List loginForm() { + return [ + TextFormField( + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: "Username", + ), + initialValue: controller.get('username', ''), + onChanged: (v) => controller.set('username', v), + ), + TextFormField( + decoration: const InputDecoration( + border: UnderlineInputBorder(), + labelText: "Password", + ), + obscureText: true, + enableSuggestions: false, + autocorrect: false, + initialValue: controller.get('password', ''), + onChanged: (v) => controller.set('password', v), + ), + ]; + } }