Commit 94bbe22

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2024-03-30 23:54:02
implement ble UI
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 9e900e1
Changed files (2)
app
lib
app/lib/components/ble_input/ble_input.dart
@@ -6,112 +6,94 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
 
-/// An interactive way to add measurements over bluetooth.
 class BleInput extends StatelessWidget{
-  /// Create an interactive bluetooth measurement adder.
-  BleInput({super.key});
+  final bloc = BleInputBloc();
 
-  final _bloc = BleInputBloc();
+  BleInput({super.key});
 
   @override
-  Widget build(BuildContext context) => SizeChangedLayoutNotifier(
-    child: BlocBuilder<BleInputBloc, BleInputState>(
-      bloc: _bloc,
-      builder: (BuildContext context, BleInputState state) {
-        final localizations = AppLocalizations.of(context)!;
-        return switch (state) {
-          BleInputClosed() => IconButton(
-            icon: const Icon(Icons.bluetooth),
-            onPressed: () => _bloc.add(OpenBleInput()),
-          ),
-          BleInputLoadInProgress() => _buildTwoElementCard(context,
-            const CircularProgressIndicator(),
-            Text(localizations.scanningDevices),
-          ),
-          BleInputLoadFailure() => _buildTwoElementCard(context,
-            const Icon(Icons.bluetooth_disabled),
-            Text(localizations.errBleCantOpen),
-            onTap: () => _bloc.add(OpenBleInput()),
-          ),
-          BleInputLoadSuccess() => state.availableDevices.isEmpty
-              ? _buildTwoElementCard(context,
-            const Icon(Icons.info),
-            Text(localizations.errBleNoDev),
-            onTap: () => _bloc.add(OpenBleInput()),
-          ) : _buildMainCard(context, ListView.builder(
+  Widget build(BuildContext context) => BlocBuilder<BleInputBloc, BleInputState>(
+    bloc: bloc,
+    builder: (BuildContext context, BleInputState state) {
+      final localizations = AppLocalizations.of(context)!;
+      return switch (state) {
+        BleInputClosed() => IconButton(
+          icon: const Icon(Icons.bluetooth),
+          onPressed: () => bloc.add(BleInputOpened()),
+        ),
+        BleInputLoadInProgress() => _buildTwoElementCard(context,
+          const CircularProgressIndicator(),
+          Text(localizations.scanningDevices),
+        ),
+        BleInputLoadFailure() => _buildTwoElementCard(context,
+          const Icon(Icons.bluetooth_disabled),
+           Text('Failed loading input devices. Ensure the app has all neccessary permissions.'),
+          onTap: () => bloc.add(BleInputOpened()),
+        ),
+        BleInputLoadSuccess() => state.availableDevices.isEmpty // TODO: card
+          ? Text('No compatible BLE GATT devices found.')
+          : ListView.builder(
             itemCount: state.availableDevices.length,
             itemBuilder: (context, idx) => ListTile(
               title: Text(state.availableDevices[idx].name),
               trailing: state.availableDevices[idx].connectable == Connectable.available
-                  ? const Icon(Icons.bluetooth_audio)
-                  : const Icon(Icons.bluetooth_disabled),
-              onTap: () => _bloc.add(BleInputDeviceSelected(state.availableDevices[idx])),
+                ? Icon(Icons.bluetooth_audio)
+                : Icon(Icons.bluetooth_disabled),
+              onTap: () => bloc.add(BleInputDeviceSelected(state.availableDevices[idx])),
             ),
-          ),),
-          BleInputPermissionFailure() => _buildTwoElementCard(context,
-            const Icon(Icons.bluetooth_disabled),
-            Text(localizations.errBleNoPerms),
-            onTap: () => _bloc.add(OpenBleInput()),
-          ),
-          BleConnectInProgress() => _buildTwoElementCard(context,
-            const CircularProgressIndicator(),
-            Text(localizations.bleConnecting),
-          ),
-          BleConnectFailed() => _buildTwoElementCard(context,
-            const Icon(Icons.bluetooth_disabled),
-            Text(localizations.errBleCouldNotConnect),
-            onTap: () => _bloc.add(OpenBleInput()),
           ),
-          BleConnectSuccess() => _buildTwoElementCard(context,
-            const Icon(Icons.bluetooth_connected),
-            Text(localizations.bleConnected),
-          ),
-          BleMeasurementInProgress() => _buildTwoElementCard(context,
-            const CircularProgressIndicator(),
-            Text(localizations.bleProcessing),
-          ),
-          BleMeasurementSuccess() => _buildTwoElementCard(context,
-            const Icon(Icons.done, color: Colors.lightGreen,),
-            Text('Received measurement:' // TODO: rework this process
-                '\n${state.record}'
-                '\nCuff loose: ${state.cuffLoose}'
-                '\nIrregular pulse: ${state.irregularPulse}'
-                '\nBody moved: ${state.bodyMoved}'
-                '\nWrong measurement position: ${state.improperMeasurementPosition}'
-                '\nMeasurement status: ${state.measurementStatus}'
-            ),
-          ),
-        };
-      },
-    ),
-  );
-
-  /// Builds the container used when input is open.
-  Widget _buildMainCard(BuildContext context, Widget child) => Card.outlined(
-    color: Theme.of(context).cardColor,
-    // borderRadius: BorderRadius.circular(24),
-    // width: MediaQuery.of(context).size.width,
-    // height: MediaQuery.of(context).size.width,
-    // padding: const EdgeInsets.all(24),
-    margin: const EdgeInsets.all(8),
-    child: Stack(
-      children: [
-        Padding( // content
-          padding: const EdgeInsets.all(24),
-          child: child,
+        BleInputPermissionFailure() => _buildTwoElementCard(context,
+          const Icon(Icons.bluetooth_disabled),
+          Text('Permissions error. Please allow all bluetooth permissions.'
+              ' You also need the location permission on pre-Android 12 devices.'),
+          onTap: () => bloc.add(BleInputOpened()),
+        ),
+        BleConnectInProgress() => _buildTwoElementCard(context,
+          const CircularProgressIndicator(),
+          Text('Connecting to bluetooth device'),
         ),
-        Align(
-          alignment: Alignment.topRight,
-          child: IconButton(
-            icon: const Icon(Icons.close),
-            onPressed: () => _bloc.add(CloseBleInput()),
+        BleConnectFailed() => _buildTwoElementCard(context,
+          const Icon(Icons.bluetooth_disabled),
+          Text('Connection to bluetooth device failed :('),
+          onTap: () => bloc.add(BleInputOpened()),
+        ),
+        BleConnectSuccess() => _buildTwoElementCard(context,
+          const Icon(Icons.bluetooth_connected),
+          Text('Connected to device, waiting for measurement'),
+        ),
+        BleMeasurementInProgress() => _buildTwoElementCard(context,
+          const CircularProgressIndicator(),
+          Text('Handeling incomming measurement'),
+        ),
+        BleMeasurementSuccess() => _buildTwoElementCard(context,
+          const Icon(Icons.done, color: Colors.lightGreen,),
+          Text('Recieved measurement:'
+              '\n${state.record}'
+              '\nCuff loose: ${state.cuffLoose}'
+              '\nIrregular pulse: ${state.irregularPulse}'
+              '\nBody moved: ${state.bodyMoved}'
+              '\nWrong measurement position: ${state.improperMeasurementPosition}'
+              '\nMeasurement status: ${state.measurementStatus}'
           ),
         ),
-      ],
+      };
+    },
+  );
+  // TODO: add method for quitting
+
+  /// Wrap open connection menu in card.
+  Widget _buildMainCard(BuildContext context, Widget child) => Container(
+    decoration: BoxDecoration(
+      color: Theme.of(context).cardColor,
+      borderRadius: BorderRadius.circular(24),
     ),
+    width: MediaQuery.of(context).size.width,
+    height: MediaQuery.of(context).size.width,
+    padding: const EdgeInsets.all(24),
+    margin: const EdgeInsets.all(8),
+    child: child,
   );
 
-  /// Builds the full card but with two centered elements.
   Widget _buildTwoElementCard(
     BuildContext context,
     Widget top,
@@ -124,6 +106,6 @@ class BleInput extends StatelessWidget{
         mainAxisAlignment: MainAxisAlignment.center,
         children: [top, const SizedBox(height: 8,), bottom,],
       ),
-    ),),
+    )),
   );
 }
app/lib/components/ble_input/ble_input_bloc.dart
@@ -19,12 +19,7 @@ class BleInputBloc extends Bloc<BleInputEvent, BleInputState> {
   // TODO: use repo
 
   BleInputBloc(): super(BleInputClosed()) {
-    on<CloseBleInput>((event, emit) async {
-      emit(BleInputClosed());
-      // TODO: perform needed cleanup
-    });
-
-    on<OpenBleInput>((event, emit) async {
+    on<BleInputOpened>((event, emit) async {
       /* testing widget
       emit(BleMeasurementSuccess(BloodPressureRecord(DateTime.now(), 123, 456, 578, 'test'),
         bodyMoved: null,
@@ -49,7 +44,9 @@ class BleInputBloc extends Bloc<BleInputEvent, BleInputState> {
         return;
       }
       emit(BleInputLoadInProgress());
+
       try {
+        emit(BleInputLoadInProgress());
         await _ble.initialize();
         final deviceStream = _ble.scanForDevices(withServices: _requiredServices,);
         await emit.forEach(deviceStream, onData: (DiscoveredDevice device) {
@@ -58,6 +55,7 @@ class BleInputBloc extends Bloc<BleInputEvent, BleInputState> {
         },);
       } catch (e) {
         // TODO: check its really this type of exception
+        print(e);
         emit(BleInputLoadFailure());
       }
     });