Skip to content

Commit

Permalink
Fix of DataViz & Service connectivity
Browse files Browse the repository at this point in the history
* fix of #204
* fix of #186
* misc. refactor and update to docs
  • Loading branch information
bardram committed Jan 6, 2024
1 parent 5ff3de1 commit 458f4dd
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 208 deletions.
4 changes: 2 additions & 2 deletions lib/blocs/app_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class StudyAppBLoC {

/// The overall data model for this app
CarpStudyAppViewModel get data => _data;
Future<void>? dataPageInitialization;
// Future<void>? dataPageInitialization;

/// Initialize this BLOC. Called before being used for anything.
Future<void> initialize() async {
Expand Down Expand Up @@ -158,7 +158,7 @@ class StudyAppBLoC {
await Sensing().addStudy();

// initialize the UI data models
dataPageInitialization = data.init(Sensing().controller!);
await data.init(Sensing().controller!);

// set up the messaging part
messageManager.initialize().then(
Expand Down
19 changes: 13 additions & 6 deletions lib/blocs/common.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
part of '../main.dart';

/// Enumeration of different types of deployments on the CARP Web Service (CAWS).
enum DeploymentMode {
/// Use the CARP production server to get the study deployment and store data.
production,
Expand All @@ -14,20 +15,26 @@ enum DeploymentMode {
dev,
}

/// Enumeration of of different user authentication states.
enum LoginStatus {
/// No invitation selected (tap outside the invitation box) - Navigate to login screen
/// No invitation selected (tap outside the invitation box).
/// Navigate to login screen.
noSelection,

/// Informed Consent not accepted - Navigate to message screen / login
/// Informed Consent not accepted.
/// Navigate to message screen or login.
noConsent,

/// User registered but no current ongoing studies - Navigate to message screen
/// User registered but no current ongoing studies.
/// Navigate to message screen.
noInvitation,

/// User temporary blocked for introducing the login credentials wrongly 3 times - Navigate to message screen
/// User temporary blocked based on 3 wrongly login credentials.
/// Navigate to message screen.
temporaryBlock,

/// Successful login - Navigate to home page
/// Successful login.
/// Navigate to home page.
successful,
}

Expand All @@ -37,9 +44,9 @@ enum ProcessStatus {
other,
}

/// Enumeration of different app states.
enum StudiesAppState {
initialized,
loginpage,
authenticating,
accessTokenRetrieved,
configuring,
Expand Down
2 changes: 1 addition & 1 deletion lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,6 @@ void main() async {
/// Configure the debug level and deployment mode here before running the app
/// or deploying it.
final bloc = StudyAppBLoC(
debugLevel: DebugLevel.info,
debugLevel: DebugLevel.debug,
deploymentMode: DeploymentMode.dev,
);
6 changes: 2 additions & 4 deletions lib/ui/pages/data_visualization_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,15 @@ class DataVisualizationPage extends StatefulWidget {
}

class _DataVisualizationPageState extends State<DataVisualizationPage> {
final dataPageInitialization = bloc.dataPageInitialization ??
bloc.data._dataVisualizationPageViewModel.init(Sensing().controller!);

@override
Widget build(BuildContext context) {
RPLocalizations locale = RPLocalizations.of(context)!;
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.secondary,
body: SafeArea(
child: FutureBuilder(
future: dataPageInitialization,
future: bloc.data._dataVisualizationPageViewModel
.init(Sensing().controller!),
builder: (context, data) {
if (data.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
Expand Down
58 changes: 27 additions & 31 deletions lib/ui/pages/devices_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
part of '../../main.dart';

/// State of Bluetoth connection UI.
/// State of Bluetooth connection UI.
enum CurrentStep { scan, instructions, done }

class DevicesPage extends StatefulWidget {
Expand Down Expand Up @@ -76,11 +76,11 @@ class DevicesPageState extends State<DevicesPage> {
flex: 4,
child: CustomScrollView(
slivers: [
...smartphoneDeviceListWidget(locale),
..._smartphoneDeviceListWidget(locale),
if (physicalDevices.isNotEmpty)
...physicalDevicesListWidget(locale),
..._physicalDevicesListWidget(locale),
if (onlineServices.isNotEmpty)
...onlineServicesListWidget(locale),
..._onlineServicesListWidget(locale),
],
),
),
Expand All @@ -90,14 +90,14 @@ class DevicesPageState extends State<DevicesPage> {
);
}

List<Widget> smartphoneDeviceListWidget(RPLocalizations locale) => [
List<Widget> _smartphoneDeviceListWidget(RPLocalizations locale) => [
DevicesPageListTitle(locale: locale, type: DevicesPageTypes.phone),
SliverList(
delegate:
SliverChildBuilderDelegate((BuildContext context, int index) {
return Center(
child: StudiesCard(
child: cardListBuilder(
child: _cardListBuilder(
smartphoneDevice[index].icon!,
smartphoneDevice[index].phoneInfo['name']!,
(
Expand All @@ -111,20 +111,20 @@ class DevicesPageState extends State<DevicesPage> {
),
];

List<Widget> physicalDevicesListWidget(RPLocalizations locale) => [
List<Widget> _physicalDevicesListWidget(RPLocalizations locale) => [
DevicesPageListTitle(locale: locale, type: DevicesPageTypes.devices),
SliverList(
delegate:
SliverChildBuilderDelegate((BuildContext context, int index) {
DeviceModel device = physicalDevices[index];
return devicesPageCardStream(
return _devicesPageCardStream(
device.deviceEvents,
() => cardListBuilder(
() => _cardListBuilder(
device.icon!,
locale.translate(device.name!),
(device.id, device.batteryLevel ?? 0),
enableFeedback: true,
onTap: () => physicalDeviceClicked(device),
onTap: () => _physicalDeviceClicked(device),
trailing: device.getDeviceStatusIcon is String
? Text(
locale
Expand All @@ -138,15 +138,15 @@ class DevicesPageState extends State<DevicesPage> {
),
];

List<Widget> onlineServicesListWidget(RPLocalizations locale) => [
List<Widget> _onlineServicesListWidget(RPLocalizations locale) => [
DevicesPageListTitle(locale: locale, type: DevicesPageTypes.services),
SliverList(
delegate:
SliverChildBuilderDelegate((BuildContext context, int index) {
DeviceModel service = onlineServices[index];
return devicesPageCardStream(
return _devicesPageCardStream(
service.deviceEvents,
() => cardListBuilder(
() => _cardListBuilder(
service.icon!,
locale.translate(service.name!),
null,
Expand All @@ -159,14 +159,14 @@ class DevicesPageState extends State<DevicesPage> {
color: Theme.of(context).primaryColor))
: service.getServiceStatusIcon,
isThreeLine: false,
onTap: () => onlineServiceClicked(service),
onTap: () => _onlineServiceClicked(service),
),
DeviceStatus.unknown);
}, childCount: onlineServices.length),
),
];

Widget cardListBuilder(
Widget _cardListBuilder(
Icon leading,
String title,
(String, int)? subtitle, {
Expand Down Expand Up @@ -208,7 +208,7 @@ class DevicesPageState extends State<DevicesPage> {
onTap: onTap,
);

Widget devicesPageCardStream<T>(
Widget _devicesPageCardStream<T>(
Stream<T> stream, Widget Function() childBuilder, T? initialData) =>
Center(
child: StudiesCard(
Expand All @@ -220,28 +220,24 @@ class DevicesPageState extends State<DevicesPage> {
),
);

void onlineServiceClicked(DeviceModel service) async {
void _onlineServiceClicked(DeviceModel service) {
if (service.status == DeviceStatus.connected ||
service.status == DeviceStatus.connecting) {
return;
}

switch (service.type) {
case HealthService.DEVICE_TYPE:
await service.deviceManager.requestPermissions();
await service.deviceManager.connect();

break;
case LocationService.DEVICE_TYPE:
await service.deviceManager.requestPermissions();
await service.deviceManager.connect();

break;
default:
}
service.deviceManager.hasPermissions().then((permissions) {
if (permissions) {
service.deviceManager.connect();
} else {
service.deviceManager.requestPermissions().then((_) {
service.deviceManager.connect();
});
}
});
}

void physicalDeviceClicked(DeviceModel device) async {
void _physicalDeviceClicked(DeviceModel device) async {
if (await FlutterBluePlus.isSupported == false) {
return;
}
Expand Down
2 changes: 0 additions & 2 deletions lib/view_models/cards/activity_data_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ class ActivityCardViewModel extends SerializableViewModel<WeeklyActivities> {
List<DailyActivity> activitiesByType(ActivityType type) =>
model.activitiesByType(type);

ActivityCardViewModel() : super();

/// Stream of activity measurements.
Stream<Measurement>? get activityEvents => controller?.measurements
.where((measurement) => measurement.data is Activity);
Expand Down
6 changes: 4 additions & 2 deletions lib/view_models/cards/heart_rate_data_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ class HeartRateCardViewModel extends SerializableViewModel<HourlyHeartRate> {
/// The current heart rate
double? get currentHeartRate => model.currentHeartRate;

// If the device is touching skin. Returns true if the device is touching skin, false otherwise.
// If the device is not capable of detecting skin contact, this value is always true.
/// Is the device is touching skin?
///
/// Returns true if the device is touching skin, false otherwise. If the device
/// is not capable of detecting skin contact, this value is always true.
bool contactStatus = false;

HeartRateMinMaxPrHour get dayMinMax =>
Expand Down
Loading

0 comments on commit 458f4dd

Please sign in to comment.