Commit 5e99325
Changed files (5)
app
android
app
lib
components
l10n
app/android/app/build.gradle
@@ -52,8 +52,8 @@ android {
applicationId "com.derdilla.bloodPressureApp"
minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
- versionCode 33
- versionName "1.6.3"
+ versionCode 34
+ versionName "BLE-TESTING (#80)"
}
signingConfigs {
release {
app/lib/components/ble_input/ble_input.dart
@@ -6,94 +6,112 @@ 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{
- final bloc = BleInputBloc();
-
+ /// Create an interactive bluetooth measurement adder.
BleInput({super.key});
+ final _bloc = BleInputBloc();
+
@override
- 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(
+ 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(
itemCount: state.availableDevices.length,
itemBuilder: (context, idx) => ListTile(
title: Text(state.availableDevices[idx].name),
trailing: state.availableDevices[idx].connectable == Connectable.available
- ? Icon(Icons.bluetooth_audio)
- : Icon(Icons.bluetooth_disabled),
- onTap: () => bloc.add(BleInputDeviceSelected(state.availableDevices[idx])),
+ ? const Icon(Icons.bluetooth_audio)
+ : const 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()),
),
- 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'),
- ),
- 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}'
+ 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}'
+ ),
+ ),
+ };
+ },
+ ),
);
- // 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),
+ /// 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: child,
+ child: Stack(
+ children: [
+ Padding( // content
+ padding: const EdgeInsets.all(24),
+ child: child,
+ ),
+ Align(
+ alignment: Alignment.topRight,
+ child: IconButton(
+ icon: const Icon(Icons.close),
+ onPressed: () => _bloc.add(CloseBleInput()),
+ ),
+ ),
+ ],
+ ),
);
+ /// Builds the full card but with two centered elements.
Widget _buildTwoElementCard(
BuildContext context,
Widget top,
@@ -106,6 +124,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,7 +19,12 @@ class BleInputBloc extends Bloc<BleInputEvent, BleInputState> {
// TODO: use repo
BleInputBloc(): super(BleInputClosed()) {
- on<BleInputOpened>((event, emit) async {
+ on<CloseBleInput>((event, emit) async {
+ emit(BleInputClosed());
+ // TODO: perform needed cleanup
+ });
+
+ on<OpenBleInput>((event, emit) async {
/* testing widget
emit(BleMeasurementSuccess(BloodPressureRecord(DateTime.now(), 123, 456, 578, 'test'),
bodyMoved: null,
app/lib/components/ble_input/ble_input_events.dart
@@ -3,7 +3,11 @@ import 'package:flutter_reactive_ble/flutter_reactive_ble.dart';
sealed class BleInputEvent {}
-class BleInputOpened extends BleInputEvent {}
+/// Request expanding the input field.
+class OpenBleInput extends BleInputEvent {}
+
+/// Request closing the input field.
+class CloseBleInput extends BleInputEvent {}
class BleInputDeviceSelected extends BleInputEvent {
BleInputDeviceSelected(this.device);
app/lib/l10n/app_en.arb
@@ -506,5 +506,19 @@
"titleInCsv": "Title in CSV",
"@titleInCsv": {},
"scanningDevices": "Scanning for devices...",
- "@scanningDevices": {}
+ "@scanningDevices": {},
+ "errBleCantOpen": "Failed loading input devices. Ensure the app has all necessary permissions and report this issue in case it persists.",
+ "@errBleCantOpen": {},
+ "errBleNoDev": "No compatible BLE GATT devices found. Tap to refresh!",
+ "@errBleNoDev": {},
+ "errBleNoPerms": "Permissions error. Please allow all bluetooth permissions. On pre-Android 12 devices the location permission is required.",
+ "@errBleNoPerms": {},
+ "errBleCouldNotConnect": "Connection to bluetooth device failed. Tap to restart.",
+ "@errBleCouldNotConnect": {},
+ "bleConnecting": "Connecting to bluetooth device...",
+ "@bleConnecting": {},
+ "bleConnected": "Connected to device. Waiting for measurement...",
+ "@bleConnected": {},
+ "bleProcessing": "Processing incoming measurement...",
+ "@bleProcessing": {}
}