diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index 8caa2b9..e83de93 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -56,7 +56,7 @@ jobs: name: Android APK path: | build/app/outputs/flutter-apk/app-release.apk - build/app/outputs/flutter-apk/app-release.sha1 + build/app/outputs/flutter-apk/app-release.apk.sha1 - name: Upload APK as release uses: "marvinpinto/action-automatic-releases@latest" @@ -67,4 +67,4 @@ jobs: title: "Android APK" files: | build/app/outputs/flutter-apk/app-release.apk - build/app/outputs/flutter-apk/app-release.sha1 + build/app/outputs/flutter-apk/app-release.apk.sha1 diff --git a/android/build.gradle b/android/build.gradle index 83ae220..0582685 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.6.10' + ext.kotlin_version = '1.7.20' repositories { google() mavenCentral() diff --git a/lib/objects/bluetooth_device_entry.dart b/lib/objects/bluetooth_device_entry.dart index 3a3f11e..d1727bd 100644 --- a/lib/objects/bluetooth_device_entry.dart +++ b/lib/objects/bluetooth_device_entry.dart @@ -17,7 +17,9 @@ class BluetoothDeviceEntry extends ListTile { onTap: onTap, onLongPress: onLongPress, enabled: enabled, - leading: Icon(bluetoothObject.isConnected ? Icons.bluetooth_connected : Icons.bluetooth), + leading: bluetoothObject.isConnected + ? const Icon(Icons.bluetooth_connected, color: Colors.blue) + : const Icon(Icons.bluetooth), title: Text(bluetoothObject.name), subtitle: Text(bluetoothObject.address.toString()), trailing: Row( diff --git a/lib/objects/bluetooth_object.dart b/lib/objects/bluetooth_object.dart index 5e12759..9eef610 100644 --- a/lib/objects/bluetooth_object.dart +++ b/lib/objects/bluetooth_object.dart @@ -16,15 +16,16 @@ class BluetoothObject { String id = ""; String _primaryThumbprint = ""; - String _secondaryThumbprint = ""; + final String _secondaryThumbprint = ""; late BluetoothConnection? _connection; late Stream _connectionStream; late StreamSubscription _connectionStreamSubscription; + late BuildContext _context; - CloudServiceAPI _cloudServiceAPI = CloudServiceAPI(); + final CloudServiceAPI _cloudServiceAPI = CloudServiceAPI(); - late Uint8List _messageBufferBits; + //late Uint8List _messageBufferBits; late String _messageBufferChars = ""; bool _isDisconnecting = false; @@ -69,7 +70,7 @@ class BluetoothObject { _connection = null; } - Future bondDevice() async { + Future bondDevice(BuildContext context) async { try { bool bonded = false; if (_device.isBonded) { @@ -81,22 +82,7 @@ class BluetoothObject { bonded = (await FlutterBluetoothSerial.instance.bondDeviceAtAddress(_address))!; debugPrint('Bonding with $_address has ${bonded ? 'succed' : 'failed'}.'); } - /*setState(() { - _discoveryResults[_discoveryResults.indexOf( - result)] = - BluetoothDiscoveryResult( - device: BluetoothDevice( - name: device.name ?? '', - address: address, - type: device.type, - bondState: bonded - ? BluetoothBondState.bonded - : BluetoothBondState.none, - ), - rssi: result.rssi); - });*/ } catch (ex) { - /* showDialog( context: context, builder: (BuildContext context) { @@ -114,7 +100,7 @@ class BluetoothObject { ], ); }, - );*/ + ); } } @@ -133,12 +119,15 @@ class BluetoothObject { _connection = null; } - _connection = await BluetoothConnection.toAddress(_address); - debugPrint("Connected to the device"); - - _connectionStream = _connection!.input!; - _connectionStreamSubscription = _connectionStream.listen(_connectionOnListen); - _connectionStreamSubscription.onDone(_connectionOnDone); + try { + _connection = await BluetoothConnection.toAddress(_address); + debugPrint("Connected to the device"); + _connectionStream = _connection!.input!; + _connectionStreamSubscription = _connectionStream.listen(_connectionOnListen); + _connectionStreamSubscription.onDone(_connectionOnDone); + } catch (ex) { + debugPrint("$ex"); + } } void _connectionOnDone() { @@ -151,113 +140,58 @@ class BluetoothObject { Future _connectionOnListen(Uint8List data) async { final String dataDecoded = const AsciiDecoder().convert(data); - - debugPrint("received: $data"); debugPrint("received decoded: $dataDecoded"); - _messageBufferChars += dataDecoded; - if (data[data.length - 1] == 10) { - debugPrint("received buffer: $_messageBufferChars"); - int spaceIndex = _messageBufferChars.indexOf(" "); - String firstParameter = ""; - String secondParameter = ""; - try { - firstParameter = _messageBufferChars.substring(0, spaceIndex); - secondParameter = _messageBufferChars.substring(spaceIndex + 1, _messageBufferChars.length - 2); - } catch (ex) { - debugPrint(ex.toString()); - } - debugPrint("we still go on!"); + if (!(data[data.length - 1] == 10)) { + return; + } + if (!_messageBufferChars.contains(" ")) { _messageBufferChars = ""; - debugPrint("first: $firstParameter"); - debugPrint("second: $secondParameter"); - if (firstParameter == "fingerprint") { - debugPrint("received final buffer: $secondParameter"); - _primaryThumbprint = secondParameter; - debugPrint("{ _secondaryThumbprint: $_secondaryThumbprint }"); - debugPrint("{ id: $id, _primaryThumbprint: $_primaryThumbprint, _secondaryThumbprint: $_secondaryThumbprint }"); - await _registerDevice(); - } + return; } - /* - // Allocate buffer for parsed data - int backspacesCounter = 0; - for (var byte in data) { - if (byte == 8 || byte == 127) { - backspacesCounter++; - } + List input = _messageBufferChars.split(" "); + if (input[0] == "fingerprint") { + _primaryThumbprint = input[1].trim(); + debugPrint("_primaryThumbprint: ${const AsciiEncoder().convert(_primaryThumbprint)}"); + debugPrint("id: ${const AsciiEncoder().convert(id)}"); + debugPrint("_secondaryThumbprint: $_secondaryThumbprint"); + await _registerDevice(); } - Uint8List buffer = Uint8List(data.length - backspacesCounter); - int bufferIndex = buffer.length; - - // Apply backspace control character - backspacesCounter = 0; - for (int i = data.length - 1; i >= 0; i--) { - if (data[i] == 8 || data[i] == 127) { - backspacesCounter++; - } else { - if (backspacesCounter > 0) { - backspacesCounter--; - } else { - buffer[--bufferIndex] = data[i]; - } - } - } - - // Create message if there is new line character - String dataString = String.fromCharCodes(buffer); - int index = buffer.indexOf(13); - if (~index != 0) { - _messageBuffer = dataString.substring(index); - } else { - _messageBuffer = (backspacesCounter > 0 - ? _messageBuffer.substring(0, _messageBuffer.length - backspacesCounter) - : _messageBuffer + dataString); - } - */ + _messageBufferChars = ""; } - Future sendData(String output) async { + Future sendData(BuildContext context, String output) async { if (_connection == null) return; bool nameAvailable = await _cloudServiceAPI.checkNameAvailability(output); - // String output = "0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ";// !§%&()=?#!?"; - // String output = "myDevice123";// !§%&()=?#!?"; if (!nameAvailable) return; id = output; _connection!.output.add(Uint8List.fromList(const AsciiEncoder().convert("$output \r\n"))); await _connection!.output.allSent; + _context = context; debugPrint("sent: $output"); } Future _registerDevice() async { bool registered = false; registered = await _cloudServiceAPI.createDevice(id, _primaryThumbprint, ""); + _confirmRegistration(registered); + } - String statusText = - registered ? "das Gerät wurde erfolgreich registriert" : "das Gerät konnte nicht registriert werden"; - Fluttertoast.showToast( - msg: statusText, - toastLength: Toast.LENGTH_SHORT, - gravity: ToastGravity.BOTTOM, - timeInSecForIosWeb: 2, - backgroundColor: Colors.grey[200], - textColor: Colors.black, - fontSize: 16.0); + void _confirmRegistration(bool registered) { + showDialog( + context: _context, + builder: (BuildContext context) => AlertDialog( + title: const Text('Device Info'), + content: Text(registered ? "das Gerät wurde erfolgreich registriert" : "das Gerät konnte nicht registriert werden"), + backgroundColor: Colors.white, + actions: [ + TextButton(onPressed: () => Navigator.pop(context, 'Cancel'), + child: const Text('OK'), + ), + ], + ), + ); } } - -/*setState(() { - _discoveryResults[_discoveryResults.indexOf( - result)] = - BluetoothDiscoveryResult( - device: BluetoothDevice( - name: device.name ?? '', - address: address, - type: device.type, - isConnected: connected, - ), - rssi: result.rssi); - }); - */ diff --git a/lib/objects/cloud_service_api.dart b/lib/objects/cloud_service_api.dart index 952341e..579d200 100644 --- a/lib/objects/cloud_service_api.dart +++ b/lib/objects/cloud_service_api.dart @@ -1,6 +1,5 @@ import 'dart:convert'; import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; @@ -24,6 +23,7 @@ class CloudServiceAPI { static String _password = ""; static late Map _headers; static bool _initState = false; + static List devices = List.empty(growable: true); CloudServiceAPI() { if (!_initState) { @@ -44,6 +44,7 @@ class CloudServiceAPI { 'accept': 'application/json', }; log("init Config $_headers"); + await updateDeviceList(); } Future reloadConfig() async { @@ -64,7 +65,6 @@ class CloudServiceAPI { List remoteObjectsList = remoteObjectsMap.toList(); return remoteObjectsList; } - Future getDeviceInfo(String deviceID) async { Uri url = Uri.https(_address, '/api/devices/$deviceID'); Response response = await get(url, headers: _headers); @@ -72,12 +72,31 @@ class CloudServiceAPI { DeviceInfoModel deviceInfoModel = DeviceInfoModel.fromJson(jsonObject); return deviceInfoModel; } + Future> getDevicesInfo() async { + updateDeviceList(); + List deviceInfoModelList = List.empty(growable: true); + for(DeviceModel tmp in devices){ + deviceInfoModelList.add(await getDeviceInfo(tmp.id)); + } + return deviceInfoModelList; + } + Future updateDeviceList() async { + devices = await getDevices(); + } Future> getInformation() async { Uri url = Uri.https(_address, '/api/app'); Response response = await get(url, headers: _headers); return json.decode(response.body) as Map; } + Future deleteDevice(String clientId) async { + Uri url = Uri.https(_address, '/api/devices/$clientId'); + Response response = await delete(url, headers: _headers); + if(response.statusCode == 204){ + return true; + } + return false; + } Future createDevice(String id, String primaryThumbprint, String secondaryThumbprint) async { Uri url = Uri.https(_address, '/api/devices'); @@ -114,7 +133,7 @@ class CloudServiceAPI { String statusText = status ? "die eingegebene ID ist verfügbar" : "die eingegebene ID ist nicht verfügbar"; Fluttertoast.showToast( msg: statusText, - toastLength: Toast.LENGTH_SHORT, + toastLength: Toast.LENGTH_LONG, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 2, backgroundColor: Colors.grey[200], @@ -148,4 +167,7 @@ class CloudServiceAPI { _password = input; reloadConfig(); } + List getLoadedDevices(){ + return devices; + } } diff --git a/lib/screens/bluetooth_device_settings.dart b/lib/screens/bluetooth_device_settings.dart index 1c0ba49..2896357 100644 --- a/lib/screens/bluetooth_device_settings.dart +++ b/lib/screens/bluetooth_device_settings.dart @@ -14,8 +14,8 @@ class BluetoothDeviceSettings extends StatefulWidget { class BluetoothDeviceSettingsState extends State { late BluetoothObject _bluetoothObject; - - String _messageBuffer = ""; + bool _isRegistering = false; + String _textInput = ""; // 0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ @override void initState() { @@ -23,9 +23,6 @@ class BluetoothDeviceSettingsState extends State { _bluetoothObject = widget.bluetoothObject; } - String _textInput = "0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - String _textOuput = ""; - ButtonStyle buttonStyle = ElevatedButton.styleFrom( foregroundColor: Colors.black, backgroundColor: const Color(0xFFFDE100), // Text Color (Foreground color) @@ -53,13 +50,13 @@ class BluetoothDeviceSettingsState extends State { ), ListTile( title: const Text("Device Connection State"), - subtitle: - Text(_bluetoothObject.isConnected ? "ConnectionState.DISCONECTED" : "ConnectionState.CONNECED"), + subtitle: Text( + _bluetoothObject.isConnected ? "ConnectionState.DISCONNECTED" : "ConnectionState.CONNECTED"), ), ], ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 0.0), child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // const EdgeInsets defaultContentPadding = EdgeInsets.symmetric(horizontal: 16.0); Expanded( @@ -85,35 +82,48 @@ class BluetoothDeviceSettingsState extends State { )) ])), const Divider(), - ElevatedButton( - onPressed: () async { - _bluetoothObject.sendData(_textInput); - }, - style: buttonStyle, - child: const Text("Send Data"), - ), - ElevatedButton( - onPressed: () async { - setState(() { - _textOuput = ""; - }); - }, - style: buttonStyle, - child: const Text("Clear Output"), - ), - Text(_textOuput), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 16.0), - child: TextField( - decoration: const InputDecoration( - border: OutlineInputBorder(), - hintText: 'Enter the device name', + SingleSection(title: "Cloud Registration", children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 0.0), + child: TextFormField( + obscureText: false, + decoration: InputDecoration( + border: const OutlineInputBorder(), + hintText: 'Enter the device name', + labelText: "Device Name", + filled: false, + suffixIcon: _isRegistering + ? FittedBox( + child: Container( + height: 10, + width: 10, + margin: const EdgeInsets.all(8.0), + child: const CircularProgressIndicator( + strokeWidth: 2.0, + ), + ), + ) // : const I + : IconButton( + icon: const Icon(Icons.login), + onPressed: () async { + FocusScopeNode currentFocus = FocusScope.of(context); + currentFocus.unfocus(); + setState(() { + _isRegistering = true; + }); + await _bluetoothObject.sendData(context, _textInput); + setState(() { + _isRegistering = false; + }); + }, + )), + keyboardType: TextInputType.text, + onChanged: (String newValue) { + _textInput = newValue; + }, ), - onChanged: (String newValue) { - _textInput = newValue; - }, ), - ), + ]), ]), ]), )); diff --git a/lib/screens/bluetooth_screen.dart b/lib/screens/bluetooth_screen.dart index 449556f..7b00614 100644 --- a/lib/screens/bluetooth_screen.dart +++ b/lib/screens/bluetooth_screen.dart @@ -50,21 +50,36 @@ class _BluetoothScreen extends State { _activeObject = null; _streamSubscription = null; if (widget.start) { - _startDiscovery(); + _initAsync(); } } + Future _initAsync() async { + await _enablePermissions(); + await _enableBluetooth(); + await _startDiscovery(); + } + @override void dispose() { // Avoid memory leak (`setState` after dispose) and cancel discovery - _streamSubscription?.cancel(); - _activeObject?.disconnectDevice(); + debugPrint("called dispose"); + _disposeAsync(); + super.dispose(); + } + + Future _disposeAsync() async { + await _streamSubscription?.cancel(); + await _activeObject?.disconnectDevice(); + List bondedDevices = await FlutterBluetoothSerial.instance.getBondedDevices(); + debugPrint(bondedDevices.toString()); super.dispose(); debugPrint("called dispose"); } + + Future _enablePermissions() async { - debugPrint("Test"); PermissionStatus bluetoothScan = await Permission.bluetoothScan.request(); PermissionStatus bluetoothConnect = await Permission.bluetoothConnect.request(); bool granted = bluetoothScan.isGranted && bluetoothConnect.isGranted; @@ -74,7 +89,14 @@ class _BluetoothScreen extends State { } Future _enableBluetooth() async { - if (!_enabledPermissions) { + if (_enabledBluetooth) { + return; + } + BluetoothState state = await FlutterBluetoothSerial.instance.state; + if (state == BluetoothState.STATE_ON) { + setState(() { + _enabledBluetooth = true; + }); return; } bool? enabled = await FlutterBluetoothSerial.instance.requestEnable(); @@ -85,7 +107,8 @@ class _BluetoothScreen extends State { } Future _startDiscovery() async { - if (!_enabledPermissions) { + debugPrint("enabled: $_enabledPermissions"); + if (!_enabledPermissions && !_enabledBluetooth) { return; } setState(() => _isDiscovering = true); @@ -137,9 +160,6 @@ class _BluetoothScreen extends State { _activeObject!.isConnected ? await bluetoothObject.disconnectDevice() : await bluetoothObject.connectDevice(); } - //stty -F /dev/service 19200 parenb -parodd -cstopb cs8 - //cat /dev/service | xargs -n 1 /home/script/automaticcloud.sh - @override Widget build(BuildContext context) { return Scaffold( @@ -173,6 +193,7 @@ class _BluetoothScreen extends State { CustomListTile( title: _enabledBluetooth ? "Bluetooth Enabled" : "Please Enable Bluetooth (click me)", icon: _enabledBluetooth ? Icons.check_circle_outline_rounded : Icons.info_outline_rounded, + iconColor: _enabledPermissions ? Colors.green : Colors.red, onTap: () async { await _enableBluetooth(); }, @@ -180,6 +201,7 @@ class _BluetoothScreen extends State { CustomListTile( title: _enabledPermissions ? "Permissions Granted" : "Please Grant Permissions (click me)", icon: _enabledPermissions ? Icons.check_circle_outline_rounded : Icons.info_outline_rounded, + iconColor: _enabledPermissions ? Colors.green : Colors.red, onTap: () async { await _enablePermissions(); }, @@ -193,38 +215,6 @@ class _BluetoothScreen extends State { ), ], ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - // const EdgeInsets defaultContentPadding = EdgeInsets.symmetric(horizontal: 16.0); - Expanded( - child: ElevatedButton( - onPressed: () async { - /*await Permission.bluetoothConnect.request(); - await Permission.bluetoothScan.request(); - if (await Permission.bluetoothScan.request().isGranted) { - // Either the permission was already granted before or the user just granted it. - debugPrint("Location Permission is granted"); - } else { - debugPrint("Location Permission is denied."); - }*/ - }, - style: buttonStyle, - child: const Text("Get BT Permissions"), - ), - ), - const SizedBox(width: 16.0), - Expanded( - child: ElevatedButton( - onPressed: () async { - _restartDiscovery(); - }, - style: buttonStyle, - child: const Text("Restart Scan"), - ), - ) - ]), - ), const Divider(), SingleSection( title: "Bluetooth Devices", @@ -252,9 +242,11 @@ class _BluetoothScreen extends State { bluetoothObject: bluetoothObject, onTap: () async { await _toggleConnection(bluetoothObject); + await _restartDiscovery(); }, onLongPress: () async { - await bluetoothObject.bondDevice(); + await bluetoothObject.bondDevice(context); + await _restartDiscovery(); }, ); }, diff --git a/lib/screens/cloud_service_ui.dart b/lib/screens/cloud_service_ui.dart deleted file mode 100644 index 36b7c9a..0000000 --- a/lib/screens/cloud_service_ui.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'dart:convert'; -import 'dart:developer'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -import '../objects/cloud_service_api.dart'; -import '../widgets/sidebar.dart'; - -Future> readJson() async { - final String data = await rootBundle.loadString('config/credentials.json'); - final Map dataMap = json.decode(data); - log("loaded json input $dataMap"); - return dataMap; -} - -class CloudService extends StatefulWidget { - const CloudService({Key? key}) : super(key: key); - - @override - State createState() => _CloudService(); -} - -class _CloudService extends State { - late final Map credentials; - CloudServiceAPI cloudServiceAPI = CloudServiceAPI(); - static SharedPreferences? preferencesInstance; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text("Cloud Service"), - ), - body: Center( - child: TextButton( - onPressed: () async { - // List respond1 = await cloudServiceAPI.getDevices(); - // debugPrint('Devices: ${respond1[0].toString()}'); - // debugPrint('Devices: ${respond1[0].toString()}'); - - //dynamic respond2 = await cloudServiceAPI.getInformation(); - //debugPrint('Information: ${respond2.toString()}'); - - // dynamic respond3 = await cloudServiceAPI.createDevice('1', 'asdas', 'sdwe1'); - // debugPrint('CreateDevice: ${respond3.toString()}');*/ - - //dynamic respond4 = await cloudServiceAPI.getDeviceInfo("PFC200V3-430EB3"); - //debugPrint('Information: ${respond4.toString()}'); - - //bool respond5 = await cloudServiceAPI.createDevice("PFC200V3-430EB2", "60987668030DF277AD7706D7C1FA683F37230D202A80EE5135B05EF928E3BF88", ""); - //debugPrint('Information: ${respond5.toString()}'); - }, - child: const Text("Example"), - ), - ), - drawer: const Sidebar(), - ); - } -} diff --git a/lib/screens/registered_devices_screen.dart b/lib/screens/registered_devices_screen.dart index cbcd408..7037b17 100644 --- a/lib/screens/registered_devices_screen.dart +++ b/lib/screens/registered_devices_screen.dart @@ -63,6 +63,21 @@ class _RegisteredDevicesScreen extends State { super.initState(); } + Future searchDevice(String clientId) async { + List searchResult = List.empty(growable: true); + for(DeviceInfoModel tmp in _registeredInfoDevices!){ + if(clientId == ""){ + // _fetchRegisteredDevices(); + // break; + // missing implementation + } + if(tmp.id.contains(clientId)){ + searchResult.add(tmp); + } + } + _registeredInfoDevices = searchResult; + } + @override Widget build(BuildContext context) { return Scaffold( @@ -99,17 +114,17 @@ class _RegisteredDevicesScreen extends State { obscureText: false, decoration: InputDecoration( border: const OutlineInputBorder(), - hintText: 'Enter the server password', + hintText: 'Search for Devices', labelText: "Search", suffixIcon: IconButton( icon: const Icon(Icons.search), onPressed: () { setState(() { - // TODO Suchfunktion + searchDevice(_searchText); }); }, ), - filled: true, + filled: false, ), keyboardType: TextInputType.text, onChanged: (String newValue) { @@ -130,8 +145,39 @@ class _RegisteredDevicesScreen extends State { DeviceInfoModel entry = _registeredInfoDevices![index]; //DeviceInfoModel entryInfo = await _cloudServiceAPI.getDeviceInfo(entry.id); return CustomListTile( - title: "${entry.id} \nentrypoint: ${entry.endpoint} \nstatus: ${entry.status} \nconnection: ${entry.connectionState} \nlast activity: ${entry.lastActivityTime}", + title: entry.id, icon: Icons.devices, + onTap: () => showDialog( + context: context, + builder: (BuildContext context) => AlertDialog( + title: const Text('Device Info'), + content: Text("ID: ${entry.id} " + "\n\nentrypoint: ${entry.endpoint} " + "\n\nstatus: ${entry.status} " + "\n\nconnection: ${entry.connectionState} " + "\n\nlast activity: ${entry.lastActivityTime}" + "\n\nprimaryThumbprint: ${entry.primaryThumbprint}"), + backgroundColor: Colors.white, + actions: [ + TextButton(onPressed: () => Navigator.pop(context, 'Cancel'), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () { + _cloudServiceAPI.deleteDevice(entry.id); + Navigator.pop(context, 'delete device'); + }, + child: const Text('Delete Device'), + ), + ], + ), + ) + /* + Navigator.push(context, + MaterialPageRoute( + builder: (context) => DeviceOptions(deviceInfoModel: entry))); + */ + ); }, ), diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index d06e859..86ed486 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -85,6 +85,7 @@ class _SettingsState extends State { border: const OutlineInputBorder(), hintText: 'Enter the server password', labelText: "Password", + filled: false, suffixIcon: IconButton( icon: Icon(_passwordVisible ? Icons.visibility : Icons.visibility_off), onPressed: () { @@ -93,7 +94,6 @@ class _SettingsState extends State { }); }, ), - filled: true, ), initialValue: Settings.password, keyboardType: TextInputType.text, @@ -105,10 +105,6 @@ class _SettingsState extends State { ), ], ), - const SingleSection( - title: "Theme Settings", - children: [], - ) ]), ) ]), diff --git a/lib/widgets/custom_list_tile.dart b/lib/widgets/custom_list_tile.dart index ec38f58..a79c49c 100644 --- a/lib/widgets/custom_list_tile.dart +++ b/lib/widgets/custom_list_tile.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; class CustomListTile extends StatelessWidget { final String title; final IconData icon; + final Color? iconColor; final VoidCallback? onTap; //final Widget? trailing; @@ -11,6 +12,7 @@ class CustomListTile extends StatelessWidget { Key? key, required this.title, required this.icon, + this.iconColor, this.onTap, //this.trailing, }) : super(key: key); @@ -19,7 +21,7 @@ class CustomListTile extends StatelessWidget { Widget build(BuildContext context) { return ListTile( title: Text(title), - leading: Icon(icon), + leading: Icon(icon, color: iconColor), onTap: onTap, //trailing: trailing, ); diff --git a/lib/widgets/sidebar.dart b/lib/widgets/sidebar.dart index 2bebf8e..87d477c 100644 --- a/lib/widgets/sidebar.dart +++ b/lib/widgets/sidebar.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import '../screens/bluetooth_screen.dart'; -import '../screens/cloud_service_ui.dart'; import '../screens/main_screen.dart'; import '../screens/registered_devices_screen.dart'; import '../screens/settings.dart'; @@ -50,13 +49,6 @@ class Sidebar extends StatelessWidget { Navigator.push(context, MaterialPageRoute(builder: (context) => const Settings())); }, ), - ListTile( - leading: const Icon(Icons.cloud), - title: const Text("Cloud Service"), - onTap: () { - Navigator.push(context, MaterialPageRoute(builder: (context) => const CloudService())); - }, - ), ], ), ); diff --git a/pubspec.lock b/pubspec.lock index 098534f..d05bdf2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: "direct main" description: name: app_settings - sha256: "7a5b880e2dd41dba8877108180380a1d28d874c231f7c0f9022127a4061b88e1" + sha256: "66715a323ac36d6c8201035ba678777c0d2ea869e4d7064300d95af10c3bb8cb" url: "https://pub.dev" source: hosted - version: "4.1.8" + version: "4.2.0" async: dependency: transitive description: @@ -340,18 +340,18 @@ packages: dependency: transitive description: name: shared_preferences_linux - sha256: "28aefc1261746e7bad3d09799496054beb84e8c4ffcdfed7734e17b4ada459a5" + sha256: fbc3cd6826896b66a5f576b025e4f344f780c84ea7f8203097a353370607a2c8 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos - sha256: fbb94bf296576f49be37a1496d5951796211a8db0aa22cc0d68c46440dad808c + sha256: "81b6a60b2d27020eb0fc41f4cebc91353047309967901a79ee8203e40c42ed46" url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.0.5" shared_preferences_platform_interface: dependency: transitive description: @@ -372,10 +372,10 @@ packages: dependency: transitive description: name: shared_preferences_windows - sha256: "97f7ab9a7da96d9cf19581f5de520ceb529548498bd6b5e0ccd02d68a0d15eba" + sha256: "07c274c2115d4d5e4280622abb09f0980e2c5b1fcdc98ae9f59a3bad5bfc1f26" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" sky_engine: dependency: transitive description: flutter @@ -449,10 +449,10 @@ packages: dependency: transitive description: name: win32 - sha256: ca121dbbadb3e43b449053feab0cdf3f2bff93b107cacf0290e3d29f717374b6 + sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46 url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" xdg_directories: dependency: transitive description: diff --git a/test/widget_test.dart b/test/widget_test.dart index 7e9ed70..f2ddb50 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -9,12 +9,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_provisioning_for_iot/screens/main_screen.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:flutter_provisioning_for_iot/main.dart'; - void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MainPage()); + await tester.pumpWidget(const MainScreen()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget);