Commit 674b1b0
Changed files (3)
app
lib
components
bluetooth_input
l10n
app/lib/components/bluetooth_input/closed_bluetooth_input.dart
@@ -0,0 +1,74 @@
+import 'package:blood_pressure_app/bluetooth/bluetooth_cubit.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+/// A closed ble input that shows the adapter state and allows to start the input.
+class ClosedBluetoothInput extends StatelessWidget {
+ /// Show adapter state and allow starting inputs
+ const ClosedBluetoothInput({super.key,
+ required this.bluetoothCubit,
+ required this.onStarted,
+ this.inputInfo,
+ });
+ // TODO: test
+
+ /// State update provider and interaction with the device.
+ final BluetoothCubit bluetoothCubit;
+
+ /// Called when the user taps on an active start button.
+ final void Function() onStarted;
+
+ /// Callback called when the user wants to know more about this input.
+ ///
+ /// The info icon is not shown when this is null.
+ final void Function()? inputInfo;
+
+ Widget _buildTile({
+ required String text,
+ required IconData icon,
+ required void Function() onTap,
+ }) => ListTile(
+ title: Text(text),
+ leading: Icon(icon),
+ onTap: onTap,
+ trailing: inputInfo == null ? null : IconButton(
+ icon: const Icon(Icons.info_outline),
+ onPressed: inputInfo!,
+ ),
+ );
+
+ @override
+ Widget build(BuildContext context) {
+ final localizations = AppLocalizations.of(context)!;
+ return BlocBuilder<BluetoothCubit, BluetoothState>(
+ bloc: bluetoothCubit,
+ builder: (context, BluetoothState state) => switch(state) {
+ BluetoothInitial() => const SizedBox.shrink(),
+ BluetoothUnfeasible() => const SizedBox.shrink(),
+ BluetoothUnauthorized() => _buildTile(
+ text: localizations.errBleNoPerms,
+ icon: Icons.bluetooth_disabled,
+ onTap: () async {
+ await bluetoothCubit.requestPermission();
+ await bluetoothCubit.forceRefresh();
+ },
+ ),
+ BluetoothDisabled() => _buildTile(
+ text: localizations.bluetoothDisabled,
+ icon: Icons.bluetooth_disabled,
+ onTap: () async {
+ await bluetoothCubit.enableBluetooth();
+ await bluetoothCubit.forceRefresh();
+ },
+ ),
+ BluetoothReady() => _buildTile(
+ text: localizations.bluetoothDisabled,
+ icon: Icons.bluetooth,
+ onTap: onStarted,
+ ),
+ },
+ );
+ }
+
+}
app/lib/components/bluetooth_input.dart
@@ -3,6 +3,7 @@ import 'dart:async';
import 'package:blood_pressure_app/bluetooth/ble_read_cubit.dart';
import 'package:blood_pressure_app/bluetooth/bluetooth_cubit.dart';
import 'package:blood_pressure_app/bluetooth/device_scan_cubit.dart';
+import 'package:blood_pressure_app/components/bluetooth_input/closed_bluetooth_input.dart';
import 'package:blood_pressure_app/components/bluetooth_input/input_card.dart';
import 'package:blood_pressure_app/model/storage/storage.dart';
import 'package:flutter/material.dart';
@@ -22,6 +23,7 @@ class BluetoothInput extends StatefulWidget {
State<BluetoothInput> createState() => _BluetoothInputState();
}
// TODO: more info
+// TODO: make toggleable in settings
class _BluetoothInputState extends State<BluetoothInput> {
/// Whether the user expanded bluetooth input
@@ -44,39 +46,7 @@ class _BluetoothInputState extends State<BluetoothInput> {
}
}
- Widget _buildIdle(BuildContext context) => BlocBuilder<BluetoothCubit, BluetoothState>(
- bloc: _bluetoothCubit,
- builder: (context, BluetoothState state) => switch(state) {
- BluetoothInitial() => const Align(
- alignment: Alignment.topRight,
- child: CircularProgressIndicator(),
- ),
- BluetoothUnfeasible() => const SizedBox.shrink(),
- BluetoothUnauthorized() => ListTile(
- title: Text(AppLocalizations.of(context)!.errBleNoPerms),
- leading: const Icon(Icons.bluetooth_disabled),
- onTap: () async {
- // TODO: test
- await _bluetoothCubit.requestPermission();
- await _bluetoothCubit.forceRefresh();
- },
- // TODO: add information icon
- ),
- BluetoothDisabled() => ListTile(
- title: Text(AppLocalizations.of(context)!.bluetoothDisabled),
- leading: const Icon(Icons.bluetooth_disabled),
- onTap: () async {
- await _bluetoothCubit.enableBluetooth();
- await _bluetoothCubit.forceRefresh();
- },
- ),
- BluetoothReady() => ListTile(
- leading: const Icon(Icons.bluetooth),
- title: Text(AppLocalizations.of(context)!.bluetoothDisabled),
- onTap: () => setState(() => _isActive = true),
- ),
- },
- );
+ // TODO: bloc dispose
Widget _buildActive(BuildContext context) {
_bluetoothSubscription = _bluetoothCubit.stream.listen((state) {
@@ -149,7 +119,20 @@ class _BluetoothInputState extends State<BluetoothInput> {
@override
Widget build(BuildContext context) {
if (_isActive) return _buildActive(context);
- return _buildIdle(context);
+ return ClosedBluetoothInput(
+ bluetoothCubit: _bluetoothCubit,
+ onStarted: () => setState(() =>_isActive = true),
+ inputInfo: () async {
+ if (context.mounted) {
+ await showDialog(
+ context: context,
+ builder: (BuildContext context) => Text(
+ AppLocalizations.of(context)!.aboutBleInput,
+ )
+ );
+ }
+ },
+ );
}
app/lib/l10n/app_en.arb
@@ -531,5 +531,7 @@
"connect": "Connect",
"@connect": {},
"bluetoothInput": "Bluetooth input",
- "@bluetoothInput": {}
+ "@bluetoothInput": {},
+ "aboutBleInput": "Some measurement devices allow automatically transmitting measurements through the BLE GATT protocol. You can pair your device here or disable this option in the settings.",
+ "@aboutBleInput": {}
}