From e0fb75037ae575bb0c63703299c2039bf970ad65 Mon Sep 17 00:00:00 2001
From: uvok
Date: Wed, 30 Jul 2025 20:34:54 +0200
Subject: Shuffle code around / reorder
---
lib/badge_app.dart | 50 -----------
lib/device_details.dart | 101 -----------------------
lib/device_scan_select.dart | 100 ----------------------
lib/main.dart | 2 +-
lib/model/flutter_blue_plus_device.dart | 5 +-
lib/scan_page.dart | 142 --------------------------------
lib/utility.dart | 18 ++++
lib/widgets/badge_app.dart | 50 +++++++++++
lib/widgets/device_details.dart | 101 +++++++++++++++++++++++
lib/widgets/device_scan_select.dart | 86 +++++++++++++++++++
lib/widgets/notifying_list_widget.dart | 27 ++++++
lib/widgets/scan_page.dart | 142 ++++++++++++++++++++++++++++++++
12 files changed, 426 insertions(+), 398 deletions(-)
delete mode 100644 lib/badge_app.dart
delete mode 100644 lib/device_details.dart
delete mode 100644 lib/device_scan_select.dart
delete mode 100644 lib/scan_page.dart
create mode 100644 lib/utility.dart
create mode 100644 lib/widgets/badge_app.dart
create mode 100644 lib/widgets/device_details.dart
create mode 100644 lib/widgets/device_scan_select.dart
create mode 100644 lib/widgets/notifying_list_widget.dart
create mode 100644 lib/widgets/scan_page.dart
(limited to 'lib')
diff --git a/lib/badge_app.dart b/lib/badge_app.dart
deleted file mode 100644
index 37fbf4c..0000000
--- a/lib/badge_app.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2025, uvok cheetah
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-import 'package:uvok_epaper_badge/control/mock_scanner_controller.dart';
-import 'package:uvok_epaper_badge/scan_page.dart';
-import 'package:flutter/material.dart';
-
-class BadgeApp extends StatelessWidget {
- const BadgeApp({super.key});
-
- @override
- Widget build(BuildContext context) {
- final selectedScanner = MockScannerController();
-
- return MaterialApp(
- title: 'Scanner',
- theme: ThemeData(
- // This is the theme of your application.
- //
- // TRY THIS: Try running your application with "flutter run". You'll see
- // the application has a purple toolbar. Then, without quitting the app,
- // try changing the seedColor in the colorScheme below to Colors.green
- // and then invoke "hot reload" (save your changes or press the "hot
- // reload" button in a Flutter-supported IDE, or press "r" if you used
- // the command line to start the app).
- //
- // Notice that the counter didn't reset back to zero; the application
- // state is not lost during the reload. To reset the state, use hot
- // restart instead.
- //
- // This works for code too, not just values: Most code changes can be
- // tested with just a hot reload.
- colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
- ),
- home: ScanPage(title: 'Badge Scanner', deviceScanner: selectedScanner),
- );
- }
-}
diff --git a/lib/device_details.dart b/lib/device_details.dart
deleted file mode 100644
index f3754d3..0000000
--- a/lib/device_details.dart
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (C) 2025, uvok cheetah
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-import 'package:uvok_epaper_badge/model/device.dart';
-import 'package:flutter/material.dart';
-import 'package:logger/logger.dart';
-import 'package:uvok_epaper_badge/model/device_connection.dart';
-
-var logger = Logger();
-
-class DeviceDetailsScreen extends StatefulWidget {
- final Device device;
- final DeviceConnection deviceConnection;
-
- const DeviceDetailsScreen({
- super.key,
- required this.device,
- required this.deviceConnection,
- });
-
- @override
- State createState() {
- return DeviceDetailsState();
- }
-}
-
-class DeviceDetailsState extends State {
- String connectStatus = "";
-
- /// Whether the back button should be active.
- bool backActive = false;
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- appBar: AppBar(
- backgroundColor: Theme.of(context).colorScheme.inversePrimary,
- title: Text("Device details"),
- ),
- body: Center(
- child: Column(
- spacing: 20,
- children: [
- Text(connectStatus),
- ElevatedButton(
- onPressed: backActive ? backClick : null,
- child: Text("Back"),
- ),
- ],
- ),
- ),
- );
- }
-
- @override
- void initState() {
- super.initState();
- _doConnect();
- }
-
- void backClick() {
- Navigator.pop(context);
- }
-
- @override
- void deactivate() {
- super.deactivate();
- logger.i("Closing state");
- // widget.device.disconnect().ignore();
- }
-
- void _doConnect() async {
- final dev = widget.device;
-
- try {
- logger.i("Try to connect...");
- await widget.deviceConnection.connect();
- } catch (e) {
- logger.e(e);
- await widget.deviceConnection.disconnect();
- connectStatus = e.toString();
- } finally {
- backActive = true;
- if (mounted) {
- setState(() {});
- }
- }
- }
-}
diff --git a/lib/device_scan_select.dart b/lib/device_scan_select.dart
deleted file mode 100644
index a11a79a..0000000
--- a/lib/device_scan_select.dart
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2025, uvok cheetah
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-import 'package:uvok_epaper_badge/model/device.dart';
-import 'package:flutter/material.dart';
-
-abstract class NotifyingListWidget extends StatefulWidget {
- final List items;
- final ValueChanged onItemSelected;
-
- const NotifyingListWidget({
- super.key,
- required this.items,
- required this.onItemSelected,
- });
-}
-
-class DeviceScanSelection extends NotifyingListWidget {
- const DeviceScanSelection({
- super.key,
- required super.items,
- required super.onItemSelected,
- });
-
- @override
- State createState() => _DeviceScanSelectionState();
-}
-
-class _DeviceScanSelectionState extends State {
- int selectedResult = -1;
-
- @override
- Widget build(BuildContext context) {
- return Expanded(
- child: ListView.separated(
- itemCount: widget.items.length,
- itemBuilder: (context, index) {
- if (index >= widget.items.length) return null;
- final Device result = widget.items[index];
- final String name = result.name ?? "???";
-
- return ListTile(
- title: Text(name),
- subtitle: Text(result.address ?? "???"),
- trailing: Text('RSSI: ${result.rssi}'),
- selectedTileColor: Colors.amber,
- selectedColor: Colors.black,
- onTap: () {
- setState(() {
- selectedResult = index;
- });
- widget.onItemSelected(result);
- },
- selected: selectedResult == index,
- );
- },
- separatorBuilder: (BuildContext context, int index) {
- return Divider();
- },
- ),
- );
- }
-
- @override
- void didUpdateWidget(covariant DeviceScanSelection oldWidget) {
- super.didUpdateWidget(oldWidget);
-
- if (!_deviceListEqual(oldWidget.items, widget.items)) {
- setState(() {
- selectedResult = -1;
- });
- }
- }
-
- bool _deviceListEqual(List oldList, List newList) {
- if (oldList.length != newList.length) return false;
- for (int i = 0; i < oldList.length; i++) {
- if (oldList[i].address != newList[i].address) {
- return false;
- }
- }
- return true;
- }
-}
-
-String firstGiven(List list) {
- return list.firstWhere((s) => s.isNotEmpty, orElse: () => "");
-}
diff --git a/lib/main.dart b/lib/main.dart
index 39f5e27..3e6c8cd 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -13,7 +13,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-import 'package:uvok_epaper_badge/badge_app.dart';
+import 'package:uvok_epaper_badge/widgets/badge_app.dart';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
diff --git a/lib/model/flutter_blue_plus_device.dart b/lib/model/flutter_blue_plus_device.dart
index 079d9fa..101c489 100644
--- a/lib/model/flutter_blue_plus_device.dart
+++ b/lib/model/flutter_blue_plus_device.dart
@@ -1,5 +1,6 @@
import 'package:uvok_epaper_badge/model/device.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
+import 'package:uvok_epaper_badge/utility.dart';
class FlutterBluePlusDevice implements Device {
final ScanResult scanResult;
@@ -24,7 +25,3 @@ class FlutterBluePlusDevice implements Device {
return bleDevice;
}
}
-
-String firstGiven(List list) {
- return list.firstWhere((s) => s.isNotEmpty, orElse: () => "");
-}
diff --git a/lib/scan_page.dart b/lib/scan_page.dart
deleted file mode 100644
index 6256728..0000000
--- a/lib/scan_page.dart
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (C) 2025, uvok cheetah
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-import 'package:uvok_epaper_badge/control/scanner_controller.dart';
-import 'package:uvok_epaper_badge/device_details.dart';
-import 'package:uvok_epaper_badge/device_scan_select.dart';
-import 'package:uvok_epaper_badge/model/device.dart';
-import 'package:flutter/material.dart';
-import 'package:logger/logger.dart';
-import 'package:permission_handler/permission_handler.dart';
-import 'package:uvok_epaper_badge/model/device_connection.dart';
-import 'package:uvok_epaper_badge/model/device_connection_factory.dart';
-
-var logger = Logger();
-
-class ScanPage extends StatefulWidget {
- const ScanPage({super.key, required this.title, required this.deviceScanner});
-
- // Original doc: Fields in a Widget subclass are always marked "final".
-
- final String title;
- final ScannerController deviceScanner;
-
- @override
- State createState() => _ScanPageState();
-}
-
-class _ScanPageState extends State {
- Device? selectedDevice;
-
- void _doConnect() async {
- final Device? dev = selectedDevice;
- if (dev == null) return;
-
- final DeviceConnection connection =
- DeviceConnectionFactory.createConnection(dev);
- //???
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) =>
- DeviceDetailsScreen(device: dev, deviceConnection: connection),
- ),
- );
- }
-
- void _doScan() async {
- setState(() {
- selectedDevice = null;
- });
-
- // ...
- await widget.deviceScanner.startScan();
- }
-
- Future getPermissions() async {
- try {
- await Permission.bluetooth.request();
- } catch (e) {
- logger.e(e.toString());
- }
- }
-
- @override
- void initState() {
- super.initState();
- getPermissions();
- }
-
- @override
- Widget build(BuildContext context) {
- return StreamBuilder(
- stream: widget.deviceScanner.statusStream,
- initialData: ScanStatus.idle,
- builder: (context, asyncSnapshot) {
- bool isScanning = asyncSnapshot.data == ScanStatus.scanning;
- return Scaffold(
- appBar: AppBar(
- backgroundColor: Theme.of(context).colorScheme.inversePrimary,
- title: Text(widget.title),
- ),
- body: Center(
- child: Column(
- // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
- // action in the IDE, or press "p" in the console), to see the
- // wireframe for each widget.
- mainAxisAlignment: MainAxisAlignment.center,
- spacing: 24,
- children: [
- SizedBox(height: 15),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- spacing: 15.0,
- children: [
- ElevatedButton(
- onPressed: isScanning ? null : _doScan,
- child: isScanning
- ? Text("Scanning...")
- : Text("Start scan"),
- ),
- ElevatedButton(
- onPressed: (selectedDevice == null || isScanning)
- ? null
- : _doConnect,
- child: Text("Connect"),
- ),
- ],
- ),
- Expanded(
- child: StreamBuilder(
- stream: widget.deviceScanner.scanResultsStream,
- initialData: [],
- builder: (context, asyncSnapshot) {
- return DeviceScanSelection(
- items: asyncSnapshot.data ?? [],
- onItemSelected: (item) {
- setState(() => selectedDevice = item);
- },
- );
- },
- ),
- ),
- ],
- ),
- ),
- );
- },
- );
- }
-}
diff --git a/lib/utility.dart b/lib/utility.dart
new file mode 100644
index 0000000..3be1f9b
--- /dev/null
+++ b/lib/utility.dart
@@ -0,0 +1,18 @@
+// Copyright (C) 2025, uvok cheetah
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+String firstGiven(List list) {
+ return list.firstWhere((s) => s.isNotEmpty, orElse: () => "");
+}
diff --git a/lib/widgets/badge_app.dart b/lib/widgets/badge_app.dart
new file mode 100644
index 0000000..68cfce9
--- /dev/null
+++ b/lib/widgets/badge_app.dart
@@ -0,0 +1,50 @@
+// Copyright (C) 2025, uvok cheetah
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+import 'package:uvok_epaper_badge/control/mock_scanner_controller.dart';
+import 'package:uvok_epaper_badge/widgets/scan_page.dart';
+import 'package:flutter/material.dart';
+
+class BadgeApp extends StatelessWidget {
+ const BadgeApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ final selectedScanner = MockScannerController();
+
+ return MaterialApp(
+ title: 'Scanner',
+ theme: ThemeData(
+ // This is the theme of your application.
+ //
+ // TRY THIS: Try running your application with "flutter run". You'll see
+ // the application has a purple toolbar. Then, without quitting the app,
+ // try changing the seedColor in the colorScheme below to Colors.green
+ // and then invoke "hot reload" (save your changes or press the "hot
+ // reload" button in a Flutter-supported IDE, or press "r" if you used
+ // the command line to start the app).
+ //
+ // Notice that the counter didn't reset back to zero; the application
+ // state is not lost during the reload. To reset the state, use hot
+ // restart instead.
+ //
+ // This works for code too, not just values: Most code changes can be
+ // tested with just a hot reload.
+ colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
+ ),
+ home: ScanPage(title: 'Badge Scanner', deviceScanner: selectedScanner),
+ );
+ }
+}
diff --git a/lib/widgets/device_details.dart b/lib/widgets/device_details.dart
new file mode 100644
index 0000000..f3754d3
--- /dev/null
+++ b/lib/widgets/device_details.dart
@@ -0,0 +1,101 @@
+// Copyright (C) 2025, uvok cheetah
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+import 'package:uvok_epaper_badge/model/device.dart';
+import 'package:flutter/material.dart';
+import 'package:logger/logger.dart';
+import 'package:uvok_epaper_badge/model/device_connection.dart';
+
+var logger = Logger();
+
+class DeviceDetailsScreen extends StatefulWidget {
+ final Device device;
+ final DeviceConnection deviceConnection;
+
+ const DeviceDetailsScreen({
+ super.key,
+ required this.device,
+ required this.deviceConnection,
+ });
+
+ @override
+ State createState() {
+ return DeviceDetailsState();
+ }
+}
+
+class DeviceDetailsState extends State {
+ String connectStatus = "";
+
+ /// Whether the back button should be active.
+ bool backActive = false;
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ backgroundColor: Theme.of(context).colorScheme.inversePrimary,
+ title: Text("Device details"),
+ ),
+ body: Center(
+ child: Column(
+ spacing: 20,
+ children: [
+ Text(connectStatus),
+ ElevatedButton(
+ onPressed: backActive ? backClick : null,
+ child: Text("Back"),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ _doConnect();
+ }
+
+ void backClick() {
+ Navigator.pop(context);
+ }
+
+ @override
+ void deactivate() {
+ super.deactivate();
+ logger.i("Closing state");
+ // widget.device.disconnect().ignore();
+ }
+
+ void _doConnect() async {
+ final dev = widget.device;
+
+ try {
+ logger.i("Try to connect...");
+ await widget.deviceConnection.connect();
+ } catch (e) {
+ logger.e(e);
+ await widget.deviceConnection.disconnect();
+ connectStatus = e.toString();
+ } finally {
+ backActive = true;
+ if (mounted) {
+ setState(() {});
+ }
+ }
+ }
+}
diff --git a/lib/widgets/device_scan_select.dart b/lib/widgets/device_scan_select.dart
new file mode 100644
index 0000000..c89d3cf
--- /dev/null
+++ b/lib/widgets/device_scan_select.dart
@@ -0,0 +1,86 @@
+// Copyright (C) 2025, uvok cheetah
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+import 'package:uvok_epaper_badge/model/device.dart';
+import 'package:flutter/material.dart';
+import 'package:uvok_epaper_badge/widgets/notifying_list_widget.dart';
+
+class DeviceScanSelection extends NotifyingListWidget {
+ const DeviceScanSelection({
+ super.key,
+ required super.items,
+ required super.onItemSelected,
+ });
+
+ @override
+ State createState() => _DeviceScanSelectionState();
+}
+
+class _DeviceScanSelectionState extends State {
+ int selectedResult = -1;
+
+ @override
+ Widget build(BuildContext context) {
+ return Expanded(
+ child: ListView.separated(
+ itemCount: widget.items.length,
+ itemBuilder: (context, index) {
+ if (index >= widget.items.length) return null;
+ final Device result = widget.items[index];
+ final String name = result.name ?? "???";
+
+ return ListTile(
+ title: Text(name),
+ subtitle: Text(result.address ?? "???"),
+ trailing: Text('RSSI: ${result.rssi}'),
+ selectedTileColor: Colors.amber,
+ selectedColor: Colors.black,
+ onTap: () {
+ setState(() {
+ selectedResult = index;
+ });
+ widget.onItemSelected(result);
+ },
+ selected: selectedResult == index,
+ );
+ },
+ separatorBuilder: (BuildContext context, int index) {
+ return Divider();
+ },
+ ),
+ );
+ }
+
+ @override
+ void didUpdateWidget(covariant DeviceScanSelection oldWidget) {
+ super.didUpdateWidget(oldWidget);
+
+ if (!_deviceListEqual(oldWidget.items, widget.items)) {
+ setState(() {
+ selectedResult = -1;
+ });
+ }
+ }
+
+ bool _deviceListEqual(List oldList, List newList) {
+ if (oldList.length != newList.length) return false;
+ for (int i = 0; i < oldList.length; i++) {
+ if (oldList[i].address != newList[i].address) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/lib/widgets/notifying_list_widget.dart b/lib/widgets/notifying_list_widget.dart
new file mode 100644
index 0000000..7fdc2b1
--- /dev/null
+++ b/lib/widgets/notifying_list_widget.dart
@@ -0,0 +1,27 @@
+// Copyright (C) 2025, uvok cheetah
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+import 'package:flutter/material.dart';
+
+abstract class NotifyingListWidget extends StatefulWidget {
+ final List items;
+ final ValueChanged onItemSelected;
+
+ const NotifyingListWidget({
+ super.key,
+ required this.items,
+ required this.onItemSelected,
+ });
+}
diff --git a/lib/widgets/scan_page.dart b/lib/widgets/scan_page.dart
new file mode 100644
index 0000000..c557657
--- /dev/null
+++ b/lib/widgets/scan_page.dart
@@ -0,0 +1,142 @@
+// Copyright (C) 2025, uvok cheetah
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+import 'package:uvok_epaper_badge/control/scanner_controller.dart';
+import 'package:uvok_epaper_badge/widgets/device_details.dart';
+import 'package:uvok_epaper_badge/widgets/device_scan_select.dart';
+import 'package:uvok_epaper_badge/model/device.dart';
+import 'package:flutter/material.dart';
+import 'package:logger/logger.dart';
+import 'package:permission_handler/permission_handler.dart';
+import 'package:uvok_epaper_badge/model/device_connection.dart';
+import 'package:uvok_epaper_badge/model/device_connection_factory.dart';
+
+var logger = Logger();
+
+class ScanPage extends StatefulWidget {
+ const ScanPage({super.key, required this.title, required this.deviceScanner});
+
+ // Original doc: Fields in a Widget subclass are always marked "final".
+
+ final String title;
+ final ScannerController deviceScanner;
+
+ @override
+ State createState() => _ScanPageState();
+}
+
+class _ScanPageState extends State {
+ Device? selectedDevice;
+
+ void _doConnect() async {
+ final Device? dev = selectedDevice;
+ if (dev == null) return;
+
+ final DeviceConnection connection =
+ DeviceConnectionFactory.createConnection(dev);
+ //???
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) =>
+ DeviceDetailsScreen(device: dev, deviceConnection: connection),
+ ),
+ );
+ }
+
+ void _doScan() async {
+ setState(() {
+ selectedDevice = null;
+ });
+
+ // ...
+ await widget.deviceScanner.startScan();
+ }
+
+ Future getPermissions() async {
+ try {
+ await Permission.bluetooth.request();
+ } catch (e) {
+ logger.e(e.toString());
+ }
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ getPermissions();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return StreamBuilder(
+ stream: widget.deviceScanner.statusStream,
+ initialData: ScanStatus.idle,
+ builder: (context, asyncSnapshot) {
+ bool isScanning = asyncSnapshot.data == ScanStatus.scanning;
+ return Scaffold(
+ appBar: AppBar(
+ backgroundColor: Theme.of(context).colorScheme.inversePrimary,
+ title: Text(widget.title),
+ ),
+ body: Center(
+ child: Column(
+ // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
+ // action in the IDE, or press "p" in the console), to see the
+ // wireframe for each widget.
+ mainAxisAlignment: MainAxisAlignment.center,
+ spacing: 24,
+ children: [
+ SizedBox(height: 15),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ spacing: 15.0,
+ children: [
+ ElevatedButton(
+ onPressed: isScanning ? null : _doScan,
+ child: isScanning
+ ? Text("Scanning...")
+ : Text("Start scan"),
+ ),
+ ElevatedButton(
+ onPressed: (selectedDevice == null || isScanning)
+ ? null
+ : _doConnect,
+ child: Text("Connect"),
+ ),
+ ],
+ ),
+ Expanded(
+ child: StreamBuilder(
+ stream: widget.deviceScanner.scanResultsStream,
+ initialData: [],
+ builder: (context, asyncSnapshot) {
+ return DeviceScanSelection(
+ items: asyncSnapshot.data ?? [],
+ onItemSelected: (item) {
+ setState(() => selectedDevice = item);
+ },
+ );
+ },
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
--
cgit v1.2.3