diff --git a/assets/instructions/Bluetooth_enable_bar.png b/assets/instructions/Bluetooth_enable_bar.png new file mode 100644 index 00000000..3283377b Binary files /dev/null and b/assets/instructions/Bluetooth_enable_bar.png differ diff --git a/assets/instructions/Bluetooth_enable_connections_bar.png b/assets/instructions/Bluetooth_enable_connections_bar.png new file mode 100644 index 00000000..616aa355 Binary files /dev/null and b/assets/instructions/Bluetooth_enable_connections_bar.png differ diff --git a/assets/lang/da.json b/assets/lang/da.json index ea4a3379..95639b38 100644 --- a/assets/lang/da.json +++ b/assets/lang/da.json @@ -111,10 +111,19 @@ "pages.devices.status.action.pair": "Par", "pages.devices.connection.instructions": "Instruktioner", "pages.devices.connection.next": "Næste", - "pages.devices.connection.ok": "OK", - "pages.devices.connection.settings": "Indstillinger", "pages.devices.connection.back": "Tilbage", "pages.devices.connection.done": "Færdig", + "pages.devices.connection.ok": "OK", + "pages.devices.connection.settings": "Indstillinger", + "pages.devices.connection.bluetooth_authorization.title": "Autoriser app", + "pages.devices.connection.bluetooth_authorization.message": "This app needs authorization to pair with Bluetooth. Please authorize the app following the steps shown in the photo below.", + "pages.devices.connection.enable_bluetooth.title": "Aktiver Bluetooth", + "pages.devices.connection.enable_bluetooth.message1": "Bluetooth skal være tændt. Åbn Bluetooth-indstillinger, og tænd for Bluetooth.", + "pages.devices.connection.enable_bluetooth.message2": "Hvis Bluetooth allerede er slået til, skal du sikre dig, at du tillader nye forbindelser.", + "pages.devices.connection.enable_bluetooth.message3": "Klik på 'Indstillinger' for at åbne Bluetooth-indstillingerne.", + "pages.devices.connection.disconnect_bluetooth.title": "Frakobl Bluetooth", + "pages.devices.connection.disconnect_bluetooth.message": "Er du sikker på, at du vil frakoble", + "pages.devices.connection.disconnect_bluetooth.disconnect": "Frakobl", "pages.devices.connection.step.how_to.title": "Sådan forbindes ", "pages.devices.connection.step.start.title": "Forbind til enhed", "pages.devices.connection.step.start.1": "Vælg navnet på den", diff --git a/assets/lang/en.json b/assets/lang/en.json index aec7baf8..e2735f00 100644 --- a/assets/lang/en.json +++ b/assets/lang/en.json @@ -116,6 +116,15 @@ "pages.devices.connection.done": "Done", "pages.devices.connection.ok": "OK", "pages.devices.connection.settings": "Settings", + "pages.devices.connection.bluetooth_authorization.title": "Authorize app", + "pages.devices.connection.bluetooth_authorization.message": "This app needs authorization to pair with Bluetooth. Please authorize the app following the steps shown in the photo below.", + "pages.devices.connection.enable_bluetooth.title": "Enable bluetooth", + "pages.devices.connection.enable_bluetooth.message1": "Bluetooth needs to be turned on. Open Bluetooth settings and turn on Bluetooth.", + "pages.devices.connection.enable_bluetooth.message2": "If Bluetooth is already turned on, make sure that you are allowing new connections.", + "pages.devices.connection.enable_bluetooth.message3": "Click 'Settings' to open Bluetooth settings.", + "pages.devices.connection.disconnect_bluetooth.title": "Disconnect Bluetooth", + "pages.devices.connection.disconnect_bluetooth.message": "Are you sure you want to disconnect the", + "pages.devices.connection.disconnect_bluetooth.disconnect": "Disconnect", "pages.devices.connection.step.how_to.title": "How to connect to", "pages.devices.connection.step.start.title": "Connect to Device", "pages.devices.connection.step.start.1": "Select the name of the", diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 86a67f31..6dee73a8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -68,8 +68,8 @@ PODS: - Flutter - polar (0.0.1): - Flutter - - PolarBleSdk (~> 5.5.0) - - PolarBleSdk (5.5.0): + - PolarBleSdk (~> 5.4.0) + - PolarBleSdk (5.4.0): - RxSwift (~> 6.5.0) - SwiftProtobuf (~> 1.0) - ReachabilitySwift (5.0.0) @@ -213,7 +213,7 @@ SPEC CHECKSUMS: audiofileplayer: 4aaff759a721ec3a850a682e0d9ec554e5f9e86f battery_plus: 091633b7f01cb33dfc4aeedb450816f4d33818fa camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb - connectivity_plus: bf0076dd84a130856aa636df1c71ccaff908fa1d + connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6 ESense: cbe103ad16c435424f2fd6f8b274f2468af84173 esense_flutter: 8bfadfdefe7b51d6f78366e43b2b64ec9b6144b6 @@ -236,8 +236,8 @@ SPEC CHECKSUMS: path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 pedometer: 381969883680ade42559782cc41a3bbd453d8234 permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6 - polar: 8efdf64c1b4e0034e8fa3b1d12b64e5b27a877f1 - PolarBleSdk: 2551160f3dcba0207723fc466a275e2d3aeda01f + polar: 3df98f4edaae7ff57d39fa6af2bd01b5b857e79d + PolarBleSdk: 980933f58cb2856c3627f40a54c91b9351a07736 ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825 RxSwift: 5710a9e6b17f3c3d6e40d6e559b9fa1e813b2ef8 screen_state: a7ae251997e97f3f001839df09b57313b0ddef18 @@ -245,8 +245,8 @@ SPEC CHECKSUMS: shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126 sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 - url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b - video_player_avfoundation: e9e6f9cae7d7a6d9b43519b0aab382bca60fcfd1 + url_launcher_ios: 68d46cc9766d0c41dbdc884310529557e3cd7a86 + video_player_avfoundation: 8563f13d8fc8b2c29dc2d09e60b660e4e8128837 PODFILE CHECKSUM: cf73571b196c8b5799c2f2111e13846fa4ef168b diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index e6171ec6..736db306 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -9,12 +9,12 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + E07D0F69CBC3FB3BBF495997 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3100990FF1D68B124520BF17 /* Pods_Runner.framework */; }; E10F125F270C58370054107C /* carp_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = E10F125E270C58370054107C /* carp_logo.png */; }; E13E6D4226E8BB2F00FA7CDB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; E13E6D4326E8BB2F00FA7CDB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; E13E6D4426E8BB2F00FA7CDB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; E18E9691285334BE00E0AC62 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = E18E9690285334BD00E0AC62 /* libc++.tbd */; }; - EF30948874E05CC2D85E826C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9EE797237CC97245D3EBEC9 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -31,9 +31,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 12D0EAF0F925774CE6C4E719 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3100990FF1D68B124520BF17 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -43,15 +43,15 @@ 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C5AA0A943DD0EACA857867AF /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - D11F565575530A15615F4606 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9B0B0DF6CA5C87B12FB8EB05 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + AD9C1C4641FD363322CE2BB4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; E10F125E270C58370054107C /* carp_logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = carp_logo.png; path = Runner/Assets.xcassets/carp_logo.imageset/carp_logo.png; sourceTree = ""; }; E18E9690285334BD00E0AC62 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; E1C4BE1A2726B5F800D42239 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; E1C4BE1B2726B5F800D42239 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; E1E629EF268DFF1000DDDF95 /* RunnerRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RunnerRelease.entitlements; sourceTree = ""; }; + E3C16927378CEC210AF2AF71 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; EF94D7F42979852000055656 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; - F9EE797237CC97245D3EBEC9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -60,7 +60,7 @@ buildActionMask = 2147483647; files = ( E18E9691285334BE00E0AC62 /* libc++.tbd in Frameworks */, - EF30948874E05CC2D85E826C /* Pods_Runner.framework in Frameworks */, + E07D0F69CBC3FB3BBF495997 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -71,7 +71,7 @@ isa = PBXGroup; children = ( E18E9690285334BD00E0AC62 /* libc++.tbd */, - F9EE797237CC97245D3EBEC9 /* Pods_Runner.framework */, + 3100990FF1D68B124520BF17 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; @@ -79,9 +79,9 @@ 818C2957FCBEAD466AC3D91E /* Pods */ = { isa = PBXGroup; children = ( - C5AA0A943DD0EACA857867AF /* Pods-Runner.debug.xcconfig */, - D11F565575530A15615F4606 /* Pods-Runner.release.xcconfig */, - 12D0EAF0F925774CE6C4E719 /* Pods-Runner.profile.xcconfig */, + 9B0B0DF6CA5C87B12FB8EB05 /* Pods-Runner.debug.xcconfig */, + E3C16927378CEC210AF2AF71 /* Pods-Runner.release.xcconfig */, + AD9C1C4641FD363322CE2BB4 /* Pods-Runner.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -141,14 +141,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 85BDE21E16C49DC31BAD0962 /* [CP] Check Pods Manifest.lock */, + 27E54DEEA6944667C79CD01C /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - CE79428E6C4500F7AD17EB04 /* [CP] Embed Pods Frameworks */, + D1836A3D203FDCC35A715392 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -208,43 +208,43 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + 27E54DEEA6944667C79CD01C /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Thin Binary"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - 85BDE21E16C49DC31BAD0962 /* [CP] Check Pods Manifest.lock */ = { + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); + name = "Thin Binary"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; @@ -261,7 +261,7 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; - CE79428E6C4500F7AD17EB04 /* [CP] Embed Pods Frameworks */ = { + D1836A3D203FDCC35A715392 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -368,7 +368,7 @@ }; 249021D4217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 12D0EAF0F925774CE6C4E719 /* Pods-Runner.profile.xcconfig */; + baseConfigurationReference = AD9C1C4641FD363322CE2BB4 /* Pods-Runner.profile.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; @@ -525,7 +525,7 @@ }; 97C147061CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C5AA0A943DD0EACA857867AF /* Pods-Runner.debug.xcconfig */; + baseConfigurationReference = 9B0B0DF6CA5C87B12FB8EB05 /* Pods-Runner.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; @@ -568,7 +568,7 @@ }; 97C147071CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D11F565575530A15615F4606 /* Pods-Runner.release.xcconfig */; + baseConfigurationReference = E3C16927378CEC210AF2AF71 /* Pods-Runner.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; BUILD_LIBRARY_FOR_DISTRIBUTION = NO; diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard index 962ed5db..80b5cbc6 100644 --- a/ios/Runner/Base.lproj/Main.storyboard +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -1,8 +1,10 @@ - - + + + - + + @@ -14,13 +16,14 @@ - + - + + - \ No newline at end of file + diff --git a/lib/blocs/app_bloc.dart b/lib/blocs/app_bloc.dart index 3c5d6528..90ca73d3 100644 --- a/lib/blocs/app_bloc.dart +++ b/lib/blocs/app_bloc.dart @@ -286,19 +286,6 @@ class StudyAppBLoC { Iterable get runningDevices => Sensing().runningDevices!.map((device) => DeviceModel(device)); - /// Map a selected device to the device in the protocol and connect to it. - void connectToDevice(BluetoothDevice selectedDevice, DeviceManager device) { - if (device is BTLEDeviceManager) { - device.btleAddress = selectedDevice.remoteId.str; - device.btleName = selectedDevice.localName; - } - - // when the device id is updated, save the deployment - Sensing().controller?.saveDeployment(); - - device.connect(); - } - /// Start sensing. Future start() async { assert(Sensing().controller != null, diff --git a/lib/main.dart b/lib/main.dart index 7a338d50..0a00cee7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,7 +14,8 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:timeago/timeago.dart' as timeago; import 'package:camera/camera.dart'; import 'package:video_player/video_player.dart'; -import 'package:open_settings/open_settings.dart'; +import 'package:app_settings/app_settings.dart'; + import 'package:google_fonts/google_fonts.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; @@ -84,11 +85,14 @@ part 'ui/pages/process_message_page.dart'; part 'ui/pages/camera_task_page.dart'; part 'ui/pages/display_picture_page.dart'; part 'ui/pages/camera_page.dart'; -part 'ui/pages/devices_page.dart'; part 'ui/pages/loading_page.dart'; part 'ui/pages/error_page.dart'; part 'ui/pages/cans_login.dart'; +part 'ui/pages/devices_page.dart'; +part 'ui/pages/devices_page.authorization_dialog.dart'; +part 'ui/pages/devices_page.enable_bluetooth_dialog.dart'; part 'ui/pages/devices_page.connection_dialog.dart'; +part 'ui/pages/devices_page.disconnection_dialog.dart'; part 'ui/pages/devices_page.list_title.dart'; part 'ui/widgets/study_card.dart'; @@ -99,6 +103,7 @@ part 'ui/widgets/details_banner.dart'; part 'ui/widgets/studies_card.dart'; part 'ui/widgets/battery_icon.dart'; part 'ui/widgets/logout_message.dart'; +part 'ui/widgets/dialog_title.dart'; part 'ui/cards/steps_card.dart'; part 'ui/cards/heart_rate_card.dart'; diff --git a/lib/ui/pages/devices_page.authorization_dialog.dart b/lib/ui/pages/devices_page.authorization_dialog.dart new file mode 100644 index 00000000..07d02f31 --- /dev/null +++ b/lib/ui/pages/devices_page.authorization_dialog.dart @@ -0,0 +1,66 @@ +part of '../../main.dart'; + +class AuthorizationDialog extends StatelessWidget { + final DeviceModel device; + + const AuthorizationDialog({super.key, required this.device}); + + @override + Widget build(BuildContext context) { + return AlertDialog( + scrollable: true, + titlePadding: const EdgeInsets.symmetric(vertical: 4), + insetPadding: const EdgeInsets.symmetric(vertical: 24, horizontal: 40), + title: const DialogTitle( + title: "pages.devices.connection.bluetooth_authorization.title", + ), + content: SizedBox( + height: MediaQuery.of(context).size.height * 0.45, + child: authorizationInstructions(context, device), + )); + } + + Widget authorizationInstructions(BuildContext context, DeviceModel device) { + RPLocalizations locale = RPLocalizations.of(context)!; + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + Text( + locale.translate( + "pages.devices.connection.bluetooth_authorization.message"), + style: aboutCardContentStyle, + textAlign: TextAlign.justify, + ), + Image( + image: const AssetImage( + 'assets/instructions/bluetooth_enable_bar.png'), + width: MediaQuery.of(context).size.height * 0.2, + height: MediaQuery.of(context).size.height * 0.2), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + child: Text(locale.translate("cancel")), + onPressed: () { + if (context.canPop()) context.pop(); + }, + ), + TextButton( + child: Text(locale + .translate("pages.devices.connection.settings")), + onPressed: () => AppSettings.openAppSettings( + type: AppSettingsType.settings), + ), + ], + ) + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/ui/pages/devices_page.connection_dialog.dart b/lib/ui/pages/devices_page.connection_dialog.dart index 064a9aaa..34c4432f 100644 --- a/lib/ui/pages/devices_page.connection_dialog.dart +++ b/lib/ui/pages/devices_page.connection_dialog.dart @@ -10,6 +10,12 @@ class ConnectionDialog extends StatefulWidget { } class _ConnectionDialogState extends State { + @override + initState() { + super.initState(); + FlutterBluePlus.startScan(); + } + CurrentStep currentStep = CurrentStep.scan; BluetoothDevice? selectedDevice; int selected = 40; @@ -32,29 +38,21 @@ class _ConnectionDialogState extends State { } Widget _buildDialogTitle(RPLocalizations locale) { - return Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - IconButton( - onPressed: () => context.pop(), - icon: const Icon(Icons.close), - padding: const EdgeInsets.only(right: 8), - ), - ], - ), - Padding( - padding: const EdgeInsets.only(left: 24, right: 24, bottom: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - stepTitle(currentStep, widget.device, context), - ], - ), - ), - ], - ); + final stepTitleMap = { + CurrentStep.scan: const DialogTitle( + title: "pages.devices.connection.step.start.title", + ), + CurrentStep.instructions: const DialogTitle( + title: "pages.devices.connection.step.how_to.title", + ), + CurrentStep.done: DialogTitle( + title: "pages.devices.connection.step.confirm.title", + deviceName: widget.device.name, + ), + }; + + return stepTitleMap[currentStep] ?? + Container(); // Return a default widget if necessary } Widget _buildStepContent(RPLocalizations locale) { @@ -89,7 +87,7 @@ class _ConnectionDialogState extends State { ], CurrentStep.instructions: [ buildTranslatedButton("pages.devices.connection.settings", () { - OpenSettings.openBluetoothSetting(); + AppSettings.openAppSettings(type: AppSettingsType.bluetooth); }), buildTranslatedButton("pages.devices.connection.ok", () { setState(() => currentStep = CurrentStep.scan); @@ -102,11 +100,11 @@ class _ConnectionDialogState extends State { buildTranslatedButton("pages.devices.connection.done", () { FlutterBluePlus.stopScan(); if (selectedDevice != null) { - bloc.connectToDevice( + widget.device.connectToDevice( selectedDevice!, widget.device.deviceManager, ); - context.pop(); + context.pop(true); } }), ], @@ -114,46 +112,6 @@ class _ConnectionDialogState extends State { return stepButtonConfigs[currentStep] ?? []; } - Widget stepTitle( - CurrentStep currentStep, - DeviceModel device, - BuildContext context, - ) { - RPLocalizations locale = RPLocalizations.of(context)!; - Widget buildStepTitle(String translationKey, BuildContext context, - {Color? color, String suffix = ""}) => - Column( - children: [ - Text( - locale.translate(translationKey) + suffix, - style: sectionTitleStyle.copyWith(color: color), - ), - ], - ); - - final stepTitleMap = { - CurrentStep.scan: buildStepTitle( - "pages.devices.connection.step.start.title", - context, - color: Theme.of(context).primaryColor, - ), - CurrentStep.instructions: buildStepTitle( - "pages.devices.connection.step.how_to.title", - context, - color: Theme.of(context).primaryColor, - suffix: " ${locale.translate(device.name!)}", - ), - CurrentStep.done: buildStepTitle( - "${locale.translate(device.name!)} ${locale.translate("pages.devices.connection.step.confirm.title")}", - context, - color: Theme.of(context).primaryColor, - ), - }; - - return stepTitleMap[currentStep] ?? - Container(); // Return a default widget if necessary - } - Widget stepContent( CurrentStep currentStep, DeviceModel device, @@ -184,14 +142,14 @@ class _ConnectionDialogState extends State { builder: (context, snapshot) => SingleChildScrollView( child: Column( children: snapshot.data! - .where((element) => element.device.localName.isNotEmpty) + .where((element) => element.device.platformName.isNotEmpty) .toList() .asMap() .entries .map( (bluetoothDevice) => ListTile( selected: bluetoothDevice.key == selected, - title: Text(bluetoothDevice.value.device.localName), + title: Text(bluetoothDevice.value.device.platformName), selectedTileColor: Theme.of(context).primaryColor.withOpacity(0.2), onTap: () { @@ -250,7 +208,7 @@ class _ConnectionDialogState extends State { width: MediaQuery.of(context).size.height * 0.2, height: MediaQuery.of(context).size.height * 0.2), Text( - ("${locale.translate("pages.devices.connection.step.confirm.1")} '${device?.localName}' ${locale.translate("pages.devices.connection.step.confirm.2")}") + ("${locale.translate("pages.devices.connection.step.confirm.1")} '${device?.platformName}' ${locale.translate("pages.devices.connection.step.confirm.2")}") .trim(), style: aboutCardContentStyle, textAlign: TextAlign.justify, diff --git a/lib/ui/pages/devices_page.dart b/lib/ui/pages/devices_page.dart index 02cd2c64..f46015c5 100644 --- a/lib/ui/pages/devices_page.dart +++ b/lib/ui/pages/devices_page.dart @@ -11,9 +11,8 @@ class DevicesPage extends StatefulWidget { } class DevicesPageState extends State { - StreamSubscription? isScanningStream; - StreamSubscription? scanResultStream; StreamSubscription? bluetoothStateStream; + BluetoothAdapterState? bluetoothAdapterState; List physicalDevices = bloc.runningDevices .where((element) => @@ -28,11 +27,18 @@ class DevicesPageState extends State { .where((element) => element.deviceManager is SmartphoneDeviceManager) .toList(); + @override + void initState() { + super.initState(); + bluetoothStateStream = FlutterBluePlus.adapterState.listen((event) { + bluetoothAdapterState = event; + setState(() {}); + }); + } + @override void dispose() { FlutterBluePlus.stopScan(); - isScanningStream?.cancel(); - scanResultStream?.cancel(); bluetoothStateStream?.cancel(); super.dispose(); } @@ -51,7 +57,7 @@ class DevicesPageState extends State { Container( color: Theme.of(context).colorScheme.secondary, child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 15), + padding: const EdgeInsets.symmetric(horizontal: 16), child: Align( alignment: Alignment.centerLeft, child: Column( @@ -214,13 +220,7 @@ class DevicesPageState extends State { ); void physicalDeviceClicked(DeviceModel device) async { - if (await FlutterBluePlus.isAvailable == false) { - warning("Bluetooth not supported by this device"); - return; - } - - if (device.status == DeviceStatus.connected || - device.status == DeviceStatus.connecting) { + if (await FlutterBluePlus.isSupported == false) { return; } @@ -229,33 +229,43 @@ class DevicesPageState extends State { await FlutterBluePlus.turnOn(); } - // wait bluetooth to be on - await FlutterBluePlus.adapterState - .where((s) => s == BluetoothAdapterState.on) - .first; - - // start scanning for BTLE devices - bool isScanning = false; + if (context.mounted) { + if (bluetoothAdapterState == BluetoothAdapterState.off && + Platform.isIOS) { + await showDialog( + context: context, + barrierDismissible: true, + builder: (context) => EnableBluetoothDialog(device: device), + ); + } else if (bluetoothAdapterState == BluetoothAdapterState.on) { + if (device.status == DeviceStatus.connected || + device.status == DeviceStatus.connecting) { + bool result = await showDialog( + context: context, + barrierDismissible: true, + builder: (context) => DisconnectionDialog(device: device), + ); - FlutterBluePlus.isScanning.listen((scanBool) => isScanning = scanBool); - - bluetoothStateStream = FlutterBluePlus.adapterState.listen((state) { - if (state == BluetoothAdapterState.on && !isScanning) { - FlutterBluePlus.startScan(); - isScanning = true; - } else { - // instantly start and stop a scan to turn on the BT adapter - FlutterBluePlus.startScan(); - FlutterBluePlus.stopScan(); + if (result == true) { + device.disconnectFromDevice(device.deviceManager); + } else { + FlutterBluePlus.stopScan(); + } + } else { + await showDialog( + context: context, + barrierDismissible: true, + builder: (context) => ConnectionDialog(device: device), + ); + } + } else if (bluetoothAdapterState == BluetoothAdapterState.unauthorized && + Platform.isIOS) { + await showDialog( + context: context, + barrierDismissible: true, + builder: (context) => AuthorizationDialog(device: device), + ); } - }); - - await showDialog( - context: context, - barrierDismissible: true, - builder: (context) => ConnectionDialog(device: device), - ); - - FlutterBluePlus.stopScan(); + } } } diff --git a/lib/ui/pages/devices_page.disconnection_dialog.dart b/lib/ui/pages/devices_page.disconnection_dialog.dart new file mode 100644 index 00000000..6f90ab52 --- /dev/null +++ b/lib/ui/pages/devices_page.disconnection_dialog.dart @@ -0,0 +1,57 @@ +part of '../../main.dart'; + +class DisconnectionDialog extends StatelessWidget { + final DeviceModel device; + + const DisconnectionDialog({super.key, required this.device}); + + @override + Widget build(BuildContext context) { + return AlertDialog( + scrollable: true, + titlePadding: const EdgeInsets.symmetric(vertical: 4), + insetPadding: const EdgeInsets.symmetric(vertical: 24, horizontal: 40), + title: const DialogTitle( + title: "pages.devices.connection.disconnect_bluetooth.title", + ), + content: SizedBox( + child: disconnectBluetooth(context, device), + )); + } + + Widget disconnectBluetooth(BuildContext context, DeviceModel device) { + RPLocalizations locale = RPLocalizations.of(context)!; + + return Column( + children: [ + Text( + "${locale.translate("pages.devices.connection.disconnect_bluetooth.message")} ${locale.translate(device.name ?? '')}?", + style: aboutCardContentStyle, + textAlign: TextAlign.justify, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + child: Text( + locale.translate("cancel"), + ), + onPressed: () { + if (context.canPop()) context.pop(false); + }, + ), + TextButton( + onPressed: () { + if (context.canPop()) context.pop(true); + }, + child: Text( + locale.translate( + "pages.devices.connection.disconnect_bluetooth.disconnect"), + ), + ), + ], + ) + ], + ); + } +} diff --git a/lib/ui/pages/devices_page.enable_bluetooth_dialog.dart b/lib/ui/pages/devices_page.enable_bluetooth_dialog.dart new file mode 100644 index 00000000..7e55dc41 --- /dev/null +++ b/lib/ui/pages/devices_page.enable_bluetooth_dialog.dart @@ -0,0 +1,83 @@ +part of '../../main.dart'; + +class EnableBluetoothDialog extends StatelessWidget { + final DeviceModel device; + + const EnableBluetoothDialog({super.key, required this.device}); + + @override + Widget build(BuildContext context) { + return AlertDialog( + scrollable: true, + titlePadding: const EdgeInsets.symmetric(vertical: 4), + insetPadding: const EdgeInsets.symmetric(vertical: 24, horizontal: 40), + title: const DialogTitle( + title: "pages.devices.connection.enable_bluetooth.title"), + content: SizedBox( + height: MediaQuery.of(context).size.height * 0.45, + child: enableBluetoothInstructions(context, device), + )); + } + + Widget enableBluetoothInstructions(BuildContext context, DeviceModel device) { + RPLocalizations locale = RPLocalizations.of(context)!; + return Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ + Text( + locale.translate( + "pages.devices.connection.enable_bluetooth.message1"), + style: aboutCardContentStyle, + textAlign: TextAlign.justify, + ), + const Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Image( + image: AssetImage( + 'assets/instructions/bluetooth_enable_bar.png'), + ), + ), + Text( + locale.translate( + "pages.devices.connection.enable_bluetooth.message2"), + style: aboutCardContentStyle, + textAlign: TextAlign.justify, + ), + + /// TODO: Localise this image, take a screenshot of the settings page in Danish + if (Platform.isAndroid || Platform.isIOS) + const Padding( + padding: EdgeInsets.symmetric(vertical: 16.0), + child: Image( + image: AssetImage( + 'assets/instructions/bluetooth_enable_connections_bar.png'), + ), + ), + Text( + locale.translate( + "pages.devices.connection.enable_bluetooth.message3"), + style: aboutCardContentStyle, + textAlign: TextAlign.justify, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextButton( + onPressed: () => context.canPop() ? context.pop() : null, + child: Text( + locale.translate("pages.devices.connection.ok"), + ), + ) + ], + ) + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/ui/pages/display_picture_page.dart b/lib/ui/pages/display_picture_page.dart index 46171e52..31e54d5f 100644 --- a/lib/ui/pages/display_picture_page.dart +++ b/lib/ui/pages/display_picture_page.dart @@ -1,4 +1,4 @@ -part of carp_study_app; +part of '../../main.dart'; class DisplayPicturePage extends StatefulWidget { final XFile file; diff --git a/lib/ui/pages/informed_consent_page.dart b/lib/ui/pages/informed_consent_page.dart index 82ce289e..b21b05d4 100644 --- a/lib/ui/pages/informed_consent_page.dart +++ b/lib/ui/pages/informed_consent_page.dart @@ -1,4 +1,4 @@ -part of carp_study_app; +part of '../../main.dart'; class InformedConsentPage extends StatefulWidget { final InformedConsentViewModel model; diff --git a/lib/ui/widgets/dialog_title.dart b/lib/ui/widgets/dialog_title.dart new file mode 100644 index 00000000..243988fd --- /dev/null +++ b/lib/ui/widgets/dialog_title.dart @@ -0,0 +1,55 @@ +part of '../../main.dart'; + +class DialogTitle extends StatelessWidget { + final String title; + final String? deviceName; + + const DialogTitle({super.key, required this.title, this.deviceName}); + + @override + Widget build(BuildContext context) { + RPLocalizations locale = RPLocalizations.of(context)!; + return _buildDialogTitle(locale, title, context); + } + + Widget _buildDialogTitle( + RPLocalizations locale, String title, BuildContext context) { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton( + onPressed: () => context.canPop() ? context.pop() : null, + icon: const Icon(Icons.close), + padding: const EdgeInsets.only(right: 8), + ), + ], + ), + Padding( + padding: const EdgeInsets.only(left: 24, right: 24, bottom: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + children: [ + Text( + (deviceName != null + ? "${locale.translate(deviceName!)} " + : "") + + locale.translate( + title, + ), + style: sectionTitleStyle.copyWith( + color: Theme.of(context).primaryColor, + ), + ), + ], + ), + ], + ), + ), + ], + ); + } +} diff --git a/lib/view_models/devices_page_model.dart b/lib/view_models/devices_page_model.dart index 2267dca7..8e974438 100644 --- a/lib/view_models/devices_page_model.dart +++ b/lib/view_models/devices_page_model.dart @@ -18,9 +18,11 @@ class DevicesPageViewModel extends ViewModel { class DeviceModel { DeviceManager deviceManager; + DeviceModel(this.deviceManager) : super(); String? get type => deviceManager.type; DeviceStatus get status => deviceManager.status; + set status(DeviceStatus status) => deviceManager.status = status; /// Stream of [DeviceStatus] events Stream get deviceEvents => deviceManager.statusEvents; @@ -64,8 +66,6 @@ class DeviceModel { 'version': 'SDK ${DeviceInfo().sdk}', }; - DeviceModel(this.deviceManager) : super(); - static Map get deviceTypeName => { Smartphone.DEVICE_TYPE: "pages.devices.type.smartphone.name", WeatherService.DEVICE_TYPE: "pages.devices.type.weather.name", @@ -137,4 +137,31 @@ class DeviceModel { ESenseDevice.DEVICE_TYPE: "pages.devices.type.esense.instructions", PolarDevice.DEVICE_TYPE: "pages.devices.type.polar.instructions", }; + + /// Map a selected device to the device in the protocol and connect to it. + void connectToDevice(BluetoothDevice selectedDevice, DeviceManager device) { + if (device is BTLEDeviceManager) { + device.btleAddress = selectedDevice.remoteId.str; + device.btleName = selectedDevice.platformName; + } + + // when the device id is updated, save the deployment + Sensing().controller?.saveDeployment(); + + device.connect(); + } + + // Disconnect from the currently connected device + void disconnectFromDevice(DeviceManager device) { + if (device is BTLEDeviceManager) { + device.btleAddress = ''; + device.btleName = ''; + } + + // when the device id is updated, save the deployment + Sensing().controller?.saveDeployment(); + + device.disconnect(); + device.status = DeviceStatus.disconnected; // Force status update + } } diff --git a/pubspec.lock b/pubspec.lock index 7ae0544f..775690e9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a url: "https://pub.dev" source: hosted - version: "64.0.0" + version: "61.0.0" air_quality: dependency: transitive description: @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: analyzer - sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562 url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "5.13.0" app_settings: dependency: "direct main" description: @@ -61,10 +61,10 @@ packages: dependency: transitive description: name: audio_session - sha256: "6fdf255ed3af86535c96452c33ecff1245990bb25a605bfb1958661ccc3d467f" + sha256: "8a2bc5e30520e18f3fb0e366793d78057fb64cd5287862c76af0c8771f2a52ad" url: "https://pub.dev" source: hosted - version: "0.1.18" + version: "0.1.16" audio_streamer: dependency: transitive description: @@ -133,10 +133,10 @@ packages: dependency: transitive description: name: build_daemon - sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.0" build_resolvers: dependency: transitive description: @@ -149,10 +149,10 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b" + sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" url: "https://pub.dev" source: hosted - version: "2.4.7" + version: "2.4.6" build_runner_core: dependency: transitive description: @@ -173,10 +173,10 @@ packages: dependency: transitive description: name: built_value - sha256: "69acb7007eb2a31dc901512bfe0f7b767168be34cb734835d54c070bfa74c1b2" + sha256: "723b4021e903217dfc445ec4cf5b42e27975aece1fc4ebbc1ca6329c2d9fb54e" url: "https://pub.dev" source: hosted - version: "8.8.0" + version: "8.7.0" camera: dependency: "direct main" description: @@ -189,10 +189,10 @@ packages: dependency: transitive description: name: camera_android - sha256: b63304d553dde613ca68fb40aaa76bbbcdbd051683bdbf2019671ec8d9645ce7 + sha256: "58463140f1b39591b8e2155861b436abad4ceb48160058be8374164ff0309ef3" url: "https://pub.dev" source: hosted - version: "0.10.8+14" + version: "0.10.8+13" camera_avfoundation: dependency: transitive description: @@ -221,90 +221,90 @@ packages: dependency: "direct main" description: name: carp_audio_package - sha256: "8a73f31ea26a8b209df5e5b07fe7fa5eedeb0b4310d29045521d97e40b8ed4b3" + sha256: "5cadf32ab31a022a7c4c92c6279e0ee6fbdea385098df4f37a4f7832e9dc70a3" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.0" carp_backend: dependency: "direct main" description: name: carp_backend - sha256: "28f2f1fa1d961f9ec3ba540daddd4fb3827bde17d643b785deee2b28a76d901b" + sha256: c3ff060d888eb42ab1a877dbdd141637672b552400544db3b458ef82ad8fc431 url: "https://pub.dev" source: hosted - version: "1.3.2" + version: "1.3.1" carp_connectivity_package: dependency: "direct main" description: name: carp_connectivity_package - sha256: db0ad6375e1a0a57c09ece799f1bff39b95c2ab65f19b6a45fa81dd27f5253ea + sha256: ea29e7a8ea02b488f4791d3611012132a056f5596329a4628263a913e4b9a51f url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.1" carp_context_package: dependency: "direct main" description: name: carp_context_package - sha256: "7e166609e89921a26ae2898af198929d5cb7e3a3d69799de05dff6cf877c9279" + sha256: "7ee2f78d501a6517b44315daa43212029fee3cfdef17df8ad6970dc39b3a6a6b" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.2" carp_core: dependency: "direct main" description: name: carp_core - sha256: ee1d2925efbdcc33fd959871a87dfd5c7d2d45376728344ac11d9b3099a2e08b + sha256: faa4b15cdb76dfc8a01324223e23ea85d83068dc6fe60d1e148f1bf5a7441edc url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.1" carp_esense_package: dependency: "direct main" description: name: carp_esense_package - sha256: adc274206efa3ddb77ee087969decfcdb6023ccf48d2928e68ba04abf37b0854 + sha256: ea493fd4ec4024f931f1974b9dd920ce476dc339e7b68d0b572edcf203f68804 url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.1" carp_health_package: dependency: "direct main" description: name: carp_health_package - sha256: "3e5ef40227b18b7840b58634a3f4612f8c343dd13cc08dc393d0f82bd45792e6" + sha256: "0dc120f8eb0b403d94b560d29e771f124ec58b0caa9e9b5859f35083701217cf" url: "https://pub.dev" source: hosted - version: "2.8.0" + version: "2.7.0" carp_mobile_sensing: dependency: "direct main" description: name: carp_mobile_sensing - sha256: "10f5dfd54dd897464a564149452e14b52d087ebfdded567e7be05d15d701ca0d" + sha256: "17f8bb6c18ba3c6c4e67bcc91e23424d03569c6b6e6f9a1121bc4e1c83869089" url: "https://pub.dev" source: hosted - version: "1.4.0+1" + version: "1.3.4" carp_polar_package: dependency: "direct main" description: name: carp_polar_package - sha256: "6956a7a5bc0144ae406bfc476d1c6e87dd5ce47153541fc9d0dddd148a977dee" + sha256: "5f7965e6a7366194dff54c7a14b2adc0823031a9297b5caa43816420b1cbbd8b" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.0" carp_serializable: dependency: "direct main" description: name: carp_serializable - sha256: "9d3faf463e27831a36f01265ea937b75194690494954b6c0926a55c89a6a2f7a" + sha256: "537f611539b6d183900a704e2b9b7821f9eaccf2f17d8936bdd01341514952cb" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.0" carp_survey_package: dependency: "direct main" description: name: carp_survey_package - sha256: be9da57d0e247897ea5318f4d724f37959d3799500c7ea2d89e78e50613e113f + sha256: "2979f4c581bbb3504648d6fb2dd50610959cf21e20aaaa577c2ed81d462e7a64" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.3.0" carp_webservices: dependency: "direct main" description: @@ -349,10 +349,10 @@ packages: dependency: transitive description: name: code_builder - sha256: b2151ce26a06171005b379ecff6e08d34c470180ffe16b8e14b6d52be292b55f + sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677" url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.7.0" cognition_package: dependency: "direct main" description: @@ -373,10 +373,10 @@ packages: dependency: transitive description: name: connectivity_plus - sha256: "224a77051d52a11fbad53dd57827594d3bd24f945af28bd70bab376d68d437f0" + sha256: "77a180d6938f78ca7d2382d2240eb626c0f6a735d0bfdce227d8ffb80f95c48b" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "4.0.2" connectivity_plus_platform_interface: dependency: transitive description: @@ -397,10 +397,10 @@ packages: dependency: transitive description: name: coverage - sha256: ac86d3abab0f165e4b8f561280ff4e066bceaac83c424dd19f1ae2c2fcd12ca9 + sha256: "595a29b55ce82d53398e1bcc2cba525d7bd7c59faeb2d2540e9d42c390cfeeeb" url: "https://pub.dev" source: hosted - version: "1.7.1" + version: "1.6.4" cron: dependency: transitive description: @@ -413,10 +413,10 @@ packages: dependency: transitive description: name: cross_file - sha256: "2f9d2cbccb76127ba28528cb3ae2c2326a122446a83de5a056aaa3880d3882c5" + sha256: "445db18de832dba8d851e287aff8ccf169bed30d2e94243cb54c7d2f1ed2142c" url: "https://pub.dev" source: hosted - version: "0.3.3+7" + version: "0.3.3+6" crypto: dependency: transitive description: @@ -437,34 +437,34 @@ packages: dependency: transitive description: name: dart_style - sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" + sha256: "1efa911ca7086affd35f463ca2fc1799584fb6aa89883cf0af8e3664d6a02d55" url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.3.2" data_serializer: dependency: transitive description: name: data_serializer - sha256: e13386c6780d5ab808af1331b241521d0d5045080a25920bfc9151fb7d701f57 + sha256: "4f5fe72aab892bb4853dedfb974fc606a2791e37c4913236a57bc10defb9137b" url: "https://pub.dev" source: hosted - version: "1.0.12" + version: "1.0.7" dbus: dependency: transitive description: name: dbus - sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac" + sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263" url: "https://pub.dev" source: hosted - version: "0.7.10" + version: "0.7.8" device_info_plus: dependency: transitive description: name: device_info_plus - sha256: "0042cb3b2a76413ea5f8a2b40cec2a33e01d0c937e91f0f7c211fde4f7739ba6" + sha256: "7035152271ff67b072a211152846e9f1259cf1be41e34cd3e0b5463d2d6b8419" url: "https://pub.dev" source: hosted - version: "9.1.1" + version: "9.1.0" device_info_plus_platform_interface: dependency: transitive description: @@ -578,10 +578,10 @@ packages: dependency: "direct main" description: name: flutter_blue_plus - sha256: b099abd98db419dbd46981ccb6c751e00420a28d2c65a50fb6e3e2018b8a319c + sha256: "1223f9a493ad57407c52a01cf5de6dc4d9e0e6f557189bc66a29e96dfefbca07" url: "https://pub.dev" source: hosted - version: "1.29.8" + version: "1.27.0" flutter_launcher_icons: dependency: "direct main" description: @@ -602,10 +602,10 @@ packages: dependency: transitive description: name: flutter_local_notifications - sha256: bb5cd63ff7c91d6efe452e41d0d0ae6348925c82eafd10ce170ef585ea04776e + sha256: "501ed9d54f1c8c0535b7991bade36f9e7e3b45a2346401f03775c1ec7a3c06ae" url: "https://pub.dev" source: hosted - version: "16.2.0" + version: "15.1.2" flutter_local_notifications_linux: dependency: transitive description: @@ -729,10 +729,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: c247a4f76071c3b97bb5ae8912968870d5565644801c5e09f3bc961b4d874895 + sha256: c5fa45fa502ee880839e3b2152d987c44abae26d064a2376d4aad434cf0f7b15 url: "https://pub.dev" source: hosted - version: "12.1.1" + version: "12.1.3" google_fonts: dependency: "direct main" description: @@ -753,10 +753,10 @@ packages: dependency: transitive description: name: health - sha256: cd486352d97ffbf77fc43814360389619c040714cd59bf29a559f4da5cfec75d + sha256: b2eea6fbae995800d2c6831359618525deb9ec148e2b638a133bf87c3ef1d5cf url: "https://pub.dev" source: hosted - version: "8.1.0" + version: "8.0.0" html: dependency: transitive description: @@ -777,10 +777,10 @@ packages: dependency: transitive description: name: http - sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.0" http_multi_server: dependency: transitive description: @@ -857,26 +857,26 @@ packages: dependency: transitive description: name: just_audio - sha256: b607cd1a43bac03d85c3aaee00448ff4a589ef2a77104e3d409889ff079bf823 + sha256: "5ed0cd723e17dfd8cd4b0253726221e67f6546841ea4553635cf895061fc335b" url: "https://pub.dev" source: hosted - version: "0.9.36" + version: "0.9.35" just_audio_platform_interface: dependency: transitive description: name: just_audio_platform_interface - sha256: c3dee0014248c97c91fe6299edb73dc4d6c6930a2f4f713579cd692d9e47f4a1 + sha256: d8409da198bbc59426cd45d4c92fca522a2ec269b576ce29459d6d6fcaeb44df url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.2.1" just_audio_web: dependency: transitive description: name: just_audio_web - sha256: "134356b0fe3d898293102b33b5fd618831ffdc72bb7a1b726140abdf22772b70" + sha256: ff62f733f437b25a0ff590f0e295fa5441dcb465f1edbdb33b3dea264705bc13 url: "https://pub.dev" source: hosted - version: "0.4.9" + version: "0.4.8" jwt_decoder: dependency: transitive description: @@ -1009,10 +1009,10 @@ packages: dependency: "direct dev" description: name: mockito - sha256: "4b693867cee1853c9d1d7ecc1871f27f39b2ef2c13c0d8d8507dfe5bebd8aaf1" + sha256: "7d5b53bcd556c1bc7ffbe4e4d5a19c3e112b7e925e9e172dd7c6ad0630812616" url: "https://pub.dev" source: hosted - version: "5.4.3" + version: "5.4.2" nested: dependency: transitive description: @@ -1089,10 +1089,10 @@ packages: dependency: transitive description: name: package_info_plus - sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79" + sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017" url: "https://pub.dev" source: hosted - version: "5.0.1" + version: "4.2.0" package_info_plus_platform_interface: dependency: transitive description: @@ -1177,58 +1177,50 @@ packages: dependency: "direct main" description: name: permission_handler - sha256: "860c6b871c94c78e202dc69546d4d8fd84bd59faeb36f8fb9888668a53ff4f78" + sha256: "284a66179cabdf942f838543e10413246f06424d960c92ba95c84439154fcac8" url: "https://pub.dev" source: hosted - version: "11.1.0" + version: "11.0.1" permission_handler_android: dependency: transitive description: name: permission_handler_android - sha256: "2f1bec180ee2f5665c22faada971a8f024761f632e93ddc23310487df52dcfa6" + sha256: f9fddd3b46109bd69ff3f9efa5006d2d309b7aec0f3c1c5637a60a2d5659e76e url: "https://pub.dev" source: hosted - version: "12.0.1" + version: "11.1.0" permission_handler_apple: dependency: transitive description: name: permission_handler_apple - sha256: "1a816084338ada8d574b1cb48390e6e8b19305d5120fe3a37c98825bacc78306" - url: "https://pub.dev" - source: hosted - version: "9.2.0" - permission_handler_html: - dependency: transitive - description: - name: permission_handler_html - sha256: d96ff56a757b7f04fa825c469d296c5aebc55f743e87bd639fef91a466a24da8 + sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5" url: "https://pub.dev" source: hosted - version: "0.1.0+1" + version: "9.1.4" permission_handler_platform_interface: dependency: transitive description: name: permission_handler_platform_interface - sha256: d87349312f7eaf6ce0adaf668daf700ac5b06af84338bd8b8574dfbd93ffe1a1 + sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4" url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "3.12.0" permission_handler_windows: dependency: transitive description: name: permission_handler_windows - sha256: "1e8640c1e39121128da6b816d236e714d2cf17fac5a105dd6acdd3403a628004" + sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098 url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.1.3" petitparser: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 url: "https://pub.dev" source: hosted - version: "6.0.2" + version: "5.4.0" platform: dependency: transitive description: @@ -1241,10 +1233,10 @@ packages: dependency: transitive description: name: plugin_platform_interface - sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.1.6" pointycastle: dependency: transitive description: @@ -1257,10 +1249,10 @@ packages: dependency: transitive description: name: polar - sha256: "25dfa3a66a6abcbf2c07c8efa60525c6508dcfb5f5bf567ab797136d5121ff47" + sha256: "43d091a9169790023f9e4708a4cd7e9bc6438781d4ea273298894d69a76b9a09" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "6.2.0" pool: dependency: transitive description: @@ -1273,10 +1265,10 @@ packages: dependency: transitive description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.0.5" pub_semver: dependency: transitive description: @@ -1369,10 +1361,10 @@ packages: dependency: transitive description: name: sensors_plus_platform_interface - sha256: bc472d6cfd622acb4f020e726433ee31788b038056691ba433fec80e448a094f + sha256: "95f0cc08791b8bf0c41c5fa99c84be2a7d5bf60a811ddc17e1438b1e68caf0d3" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.1.3" shared_preferences: dependency: transitive description: @@ -1417,10 +1409,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: @@ -1465,10 +1457,10 @@ packages: dependency: transitive description: name: signature - sha256: d072a766e9a40496296b7593c0d9dee2abded0bdcfb306d9962d0320a9763395 + sha256: d95143b8e310b395ea0be59a46bb69fa24106cb6ec79815fc56fd320268e24e6 url: "https://pub.dev" source: hosted - version: "5.4.1" + version: "5.4.0" simple_cluster: dependency: transitive description: @@ -1550,10 +1542,10 @@ packages: dependency: transitive description: name: sqflite_common - sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 + sha256: "8ed044102f3135add97be8653662052838859f5400075ef227f8ad72ae320803" url: "https://pub.dev" source: hosted - version: "2.5.0+2" + version: "2.5.0+1" stack_trace: dependency: transitive description: @@ -1710,10 +1702,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 + sha256: "4ac97281cf60e2e8c5cc703b2b28528f9b50c8f7cebc71df6bdf0845f647268a" url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.2.0" url_launcher_linux: dependency: transitive description: @@ -1742,10 +1734,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "138bd45b3a456dcfafc46d1a146787424f8d2edfbf2809c9324361e58f851cf7" + sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.0" url_launcher_windows: dependency: transitive description: @@ -1814,10 +1806,10 @@ packages: dependency: transitive description: name: video_player_avfoundation - sha256: bc923884640d6dc403050586eb40713cdb8d1d84e6886d8aca50ab04c59124c2 + sha256: fe73d636f82286a3739f5e644f95f09442cacdc436ebbe5436521dc915f3ecac url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.1" video_player_platform_interface: dependency: transitive description: @@ -1838,10 +1830,10 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "11.10.0" watcher: dependency: transitive description: @@ -1886,10 +1878,10 @@ packages: dependency: transitive description: name: win32 - sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f" + sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3" url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.0.9" win32_registry: dependency: transitive description: @@ -1910,10 +1902,10 @@ packages: dependency: transitive description: name: xml - sha256: af5e77e9b83f2f4adc5d3f0a4ece1c7f45a2467b695c2540381bac793e34e556 + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" url: "https://pub.dev" source: hosted - version: "6.4.2" + version: "6.3.0" yaml: dependency: transitive description: @@ -1923,5 +1915,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.2.0-194.0.dev <4.0.0" + flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8a890877..2a50bf69 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -90,6 +90,7 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - assets/images/ + - assets/instructions/ - assets/icons/ - assets/lang/ - assets/images/messages/