diff --git a/android/app/build.gradle b/android/app/build.gradle
index bc2192c5..b95ac025 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -65,7 +65,14 @@ android {
keyPassword keyProperties.getProperty('keyPassword')
}
}
- debug {}
+ debug {
+ if (signingConfigExists) {
+ storeFile file(keyProperties.getProperty('storeFile'))
+ storePassword keyProperties.getProperty('storePassword')
+ keyAlias keyProperties.getProperty('keyAlias')
+ keyPassword keyProperties.getProperty('keyPassword')
+ }
+ }
}
buildTypes {
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 0356ad36..c459676d 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -44,14 +44,16 @@
-
+
-
+
-
+
-
-
-
-
-
-
-
-
@@ -171,15 +165,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
6.1.0)
- - PolarBleSdk (6.1.0):
- - RxSwift (~> 6.8.0)
- - SwiftProtobuf (~> 1.0)
- - Zip (~> 2.1.2)
- - RxSwift (6.8.0)
- - screen_state (1.0.0):
- - Flutter
- - SwiftProtobuf (1.33.3)
- - Zip (2.1.2)
-
-DEPENDENCIES:
- - audio_streamer (from `.symlinks/plugins/audio_streamer/ios`)
- - dchs_flutter_beacon (from `.symlinks/plugins/dchs_flutter_beacon/ios`)
- - Flutter (from `Flutter`)
- - flutter_activity_recognition (from `.symlinks/plugins/flutter_activity_recognition/ios`)
- - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- - flutter_sound (from `.symlinks/plugins/flutter_sound/ios`)
- - flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`)
- - health (from `.symlinks/plugins/health/ios`)
- - location (from `.symlinks/plugins/location/ios`)
- - mdsflutter (from `.symlinks/plugins/mdsflutter/ios`)
- - Movesense (from `https://bitbucket.org/movesense/movesense-mobile-lib/`)
- - oidc_ios (from `.symlinks/plugins/oidc_ios/ios`)
- - open_settings_plus (from `.symlinks/plugins/open_settings_plus/ios`)
- - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- - polar (from `.symlinks/plugins/polar/ios`)
- - screen_state (from `.symlinks/plugins/screen_state/ios`)
-
-SPEC REPOS:
- trunk:
- - flutter_sound_core
- - PolarBleSdk
- - RxSwift
- - SwiftProtobuf
- - Zip
-
-EXTERNAL SOURCES:
- audio_streamer:
- :path: ".symlinks/plugins/audio_streamer/ios"
- dchs_flutter_beacon:
- :path: ".symlinks/plugins/dchs_flutter_beacon/ios"
- Flutter:
- :path: Flutter
- flutter_activity_recognition:
- :path: ".symlinks/plugins/flutter_activity_recognition/ios"
- flutter_secure_storage:
- :path: ".symlinks/plugins/flutter_secure_storage/ios"
- flutter_sound:
- :path: ".symlinks/plugins/flutter_sound/ios"
- flutter_web_auth_2:
- :path: ".symlinks/plugins/flutter_web_auth_2/ios"
- health:
- :path: ".symlinks/plugins/health/ios"
- location:
- :path: ".symlinks/plugins/location/ios"
- mdsflutter:
- :path: ".symlinks/plugins/mdsflutter/ios"
- Movesense:
- :git: https://bitbucket.org/movesense/movesense-mobile-lib/
- oidc_ios:
- :path: ".symlinks/plugins/oidc_ios/ios"
- open_settings_plus:
- :path: ".symlinks/plugins/open_settings_plus/ios"
- permission_handler_apple:
- :path: ".symlinks/plugins/permission_handler_apple/ios"
- polar:
- :path: ".symlinks/plugins/polar/ios"
- screen_state:
- :path: ".symlinks/plugins/screen_state/ios"
-
-CHECKOUT OPTIONS:
- Movesense:
- :commit: 580c812f2696ff05ed2c1c1e93053c137ef7942a
- :git: https://bitbucket.org/movesense/movesense-mobile-lib/
-
-SPEC CHECKSUMS:
- audio_streamer: 2e472b9f81cec5e381c4cf7667afa3055dcb45a4
- dchs_flutter_beacon: 88d72cc467de508d621e454ea66c6231d0897d4c
- Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
- flutter_activity_recognition: 52dfad4c1e9cec99f0841b3ed0efcc9d424b3deb
- flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
- flutter_sound: d95194f6476c9ad211d22b3a414d852c12c7ca44
- flutter_sound_core: 7f2626d249d3a57bfa6da892ef7e22d234482c1a
- flutter_web_auth_2: 5c8d9dcd7848b5a9efb086d24e7a9adcae979c80
- health: fe206e65f13a9b88623605fbd8af8f029e23dc35
- location: 155caecf9da4f280ab5fe4a55f94ceccfab838f8
- mdsflutter: bd3c0b3335d50947d1a192cf70f930e0fb04a766
- Movesense: dc64047c1feb856b7f7ac6ea2c67685350d99dd5
- oidc_ios: 16966cad509ce6850ca4ca1216c5138bef2a8726
- open_settings_plus: d19f91e8a04649358a51c19b484ce2e637149d70
- permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
- polar: 0374f6063ade7e2dd85d626f87cbe2393d3eda7c
- PolarBleSdk: bfb57cf8350f0c53d441b8632ba6df363ce7c79f
- RxSwift: 4e28be97cbcfeee614af26d83415febbf2bf6f45
- screen_state: 52d6e997d31bddba6417c60d9cdd22effd0320a7
- SwiftProtobuf: e1b437c8e31a4c5577b643249a0bb62ed4f02153
- Zip: b3fef584b147b6e582b2256a9815c897d60ddc67
-
-PODFILE CHECKSUM: 45842edf150243fea66883d4dfad1e5ddb428147
-
-COCOAPODS: 1.16.2
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 7f1c67b8..a71b474b 100644
--- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,14 +1,5 @@
{
"pins" : [
- {
- "identity" : "appauth-ios",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/openid/AppAuth-iOS",
- "state" : {
- "revision" : "145104f5ea9d58ae21b60add007c33c1cc0c948e",
- "version" : "2.0.0"
- }
- },
{
"identity" : "phonenumberkit",
"kind" : "remoteSourceControl",
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index e596a992..f613b6b9 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,7 +1,7 @@
+ version = "1.7">
@@ -91,6 +91,13 @@
ReferencedContainer = "container:Runner.xcodeproj">
+
+
+
+
CFBundleURLSchemes
carp-studies
+ carp-studies-anonymous
carp-studies-auth
diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements
index b8ebe5cc..0fe07231 100644
--- a/ios/Runner/Runner.entitlements
+++ b/ios/Runner/Runner.entitlements
@@ -4,7 +4,9 @@
com.apple.developer.associated-domains
- applinks:carp.computerome.dk
+ applinks:study.app.dev.carp.dk
+ applinks:study.app.test.carp.dk
+ applinks:study.app.carp.computerome.dk
com.apple.developer.authentication-services.autofill-credential-provider
diff --git a/ios/Runner/RunnerRelease.entitlements b/ios/Runner/RunnerRelease.entitlements
index 94a192bd..8521f0b3 100644
--- a/ios/Runner/RunnerRelease.entitlements
+++ b/ios/Runner/RunnerRelease.entitlements
@@ -6,8 +6,8 @@
development
com.apple.developer.associated-domains
- webcredentials:carp.computerome.com
- applinks:carp.computerome.dk
+ applinks:app.dev.carp.dk
+ applinks:app.carp.computerome.dk
com.apple.developer.authentication-services.autofill-credential-provider
diff --git a/lib/carp_study_app.dart b/lib/carp_study_app.dart
index eb34048e..446d7a94 100644
--- a/lib/carp_study_app.dart
+++ b/lib/carp_study_app.dart
@@ -154,6 +154,26 @@ class CarpStudyAppState extends State {
return task?.widget ?? const ErrorPage();
},
),
+ // Handle external magic-link callbacks from the auth server. The
+ // identity provider posts a link like
+ // /auth/realms/Carp/login-actions/action-token?key=...
+ // We attempt to authenticate using the URI. On
+ // success we go to '/', on failure we redirect to the login page.
+ GoRoute(
+ path: '/auth/realms/Carp/login-actions/action-token',
+ parentNavigatorKey: _rootNavigatorKey,
+ redirect: (context, state) async {
+ // We don't show any page, but handle the magic link in the background.
+ try {
+ await bloc.backend.authenticateWithMagicLink(state.uri.toString());
+ return homeRoute;
+ } catch (error) {
+ debugPrint(
+ 'Magic-link authentication failed: $error, redirecting to login page');
+ return LoginPage.route;
+ }
+ },
+ ),
GoRoute(
path: LoginPage.route,
parentNavigatorKey: _rootNavigatorKey,
diff --git a/lib/data/carp_backend.dart b/lib/data/carp_backend.dart
index 52a08e8a..af666c47 100644
--- a/lib/data/carp_backend.dart
+++ b/lib/data/carp_backend.dart
@@ -57,7 +57,7 @@ class CarpBackend {
authURL: uri,
clientId: 'studies-app',
redirectURI: Uri.parse('carp-studies-auth://auth'),
- anonymousRedirectURI: Uri.parse('carp-studies:/anonymous'),
+ anonymousRedirectURI: Uri.parse('carp-studies-anonymous://anonymous'),
// For authentication at CAWS the path is '/auth/realms/Carp'
discoveryURL: uri.replace(pathSegments: [
'auth',
@@ -115,12 +115,15 @@ class CarpBackend {
Future authenticateWithMagicLink(String uri) async {
try {
await initialize();
+ if (Platform.isIOS) {
+ sleep(const Duration(seconds: 1));
+ }
user = await CarpAuthService().authenticateWithMagicLink(uri);
LocalSettings().isAnonymous = true;
- info('$runtimeType - ANONYMOUS User authenticated - user: $user');
+ print('$runtimeType - ANONYMOUS User authenticated - user: $user');
} catch (error) {
user = null;
- warning('$runtimeType - ANONYMOUS Error authenticating user - $error');
+ print('$runtimeType - ANONYMOUS Error authenticating user - $error');
}
}
diff --git a/lib/main.dart b/lib/main.dart
index 94c7a691..0fc4ec59 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -9,7 +9,6 @@ import 'dart:io';
import 'package:app_version_update/data/models/app_version_result.dart';
import 'package:async/async.dart';
-import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
diff --git a/lib/ui/pages/login_page.dart b/lib/ui/pages/login_page.dart
index fcc72f02..9bf54a7a 100644
--- a/lib/ui/pages/login_page.dart
+++ b/lib/ui/pages/login_page.dart
@@ -68,10 +68,15 @@ class _LoginPageState extends State {
child: TextButton(
onPressed: () async {
bool isConnected = await bloc.checkConnectivity();
+ print("isConnected: $isConnected");
if (isConnected) {
await bloc.backend.initialize();
await bloc.backend.authenticate();
- if (context.mounted) context.go(CarpStudyAppState.homeRoute);
+ if (context.mounted) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ context.go(CarpStudyAppState.homeRoute);
+ });
+ }
} else {
showDialog(
context: context,
diff --git a/lib/ui/pages/qr_scanner.dart b/lib/ui/pages/qr_scanner.dart
index b67ec16e..db4821e5 100644
--- a/lib/ui/pages/qr_scanner.dart
+++ b/lib/ui/pages/qr_scanner.dart
@@ -6,11 +6,11 @@ class QRViewExample extends StatefulWidget {
@override
State createState() => _QRViewExampleState();
}
+ final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
class _QRViewExampleState extends State {
qr.Barcode? result;
qr.QRViewController? controller;
- final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
// In order to get hot reload to work we need to pause the camera if the platform
// is android, or resume the camera if the platform is iOS.
@@ -115,6 +115,7 @@ class _QRViewExampleState extends State {
});
final qrcode = scanData.code;
+ print('QR code scanned: $qrcode');
if (qrcode != null && Uri.tryParse(qrcode)?.hasAbsolutePath == true) {
await bloc.backend.authenticateWithMagicLink(qrcode).then((_) {
diff --git a/pubspec.lock b/pubspec.lock
index 569ab9b3..e8d3a31a 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -93,10 +93,10 @@ packages:
dependency: transitive
description:
name: audioplayers
- sha256: a72dd459d1a48f61a6fb9c0134dba26597c9236af40639ff0eb70eb4e0baab70
+ sha256: f16640453cc47487b7de72a2b28d37c7df1ac97999849f4a46d92b1d2b0f093d
url: "https://pub.dev"
source: hosted
- version: "6.6.0"
+ version: "6.7.1"
audioplayers_android:
dependency: transitive
description:
@@ -133,18 +133,18 @@ packages:
dependency: transitive
description:
name: audioplayers_web
- sha256: faa8fa6587f996a6f604433b53af44c57a1407d4fe8dff5766cf63d6875e8de9
+ sha256: "24a6f258062bd7da8cb2157e83fccb9816a08dd306cbaaa24f9813d071470545"
url: "https://pub.dev"
source: hosted
- version: "5.2.0"
+ version: "5.2.1"
audioplayers_windows:
dependency: transitive
description:
name: audioplayers_windows
- sha256: bafff2b38b6f6d331887558ba6e0a01c9c208d9dbb3ad0005234db065122a734
+ sha256: "95f875a96c88c3dbbcb608d4f8288e300b0113d256a81d0b3197fcc18f0dc91a"
url: "https://pub.dev"
source: hosted
- version: "4.3.0"
+ version: "4.3.1"
base_codecs:
dependency: transitive
description:
@@ -370,12 +370,11 @@ packages:
source: hosted
version: "0.0.5"
carp_webservices:
- dependency: "direct main"
+ dependency: "direct overridden"
description:
- name: carp_webservices
- sha256: "6459af381237f38e65e6300763cddc04186c69e746ab97210f8134426e8a17dc"
- url: "https://pub.dev"
- source: hosted
+ path: "../carp.sensing-flutter/backends/carp_webservices"
+ relative: true
+ source: path
version: "3.8.0"
characters:
dependency: transitive
@@ -421,10 +420,10 @@ packages:
dependency: transitive
description:
name: code_assets
- sha256: "67cf6d84013f9c601e42a6f8a6b74c4c0d9dc1a1619d775f2b28b732d3551b85"
+ sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.2.1"
code_builder:
dependency: transitive
description:
@@ -557,10 +556,10 @@ packages:
dependency: transitive
description:
name: dbus
- sha256: d0c98dcd4f5169878b6cf8f6e0a52403a9dff371a3e2f019697accbf6f44a270
+ sha256: "0ce9b0a839e6dee59a37a623d2fc26a35bbbe6404213e419b0d6411023d62645"
url: "https://pub.dev"
source: hosted
- version: "0.7.12"
+ version: "0.7.14"
dchs_flutter_beacon:
dependency: transitive
description:
@@ -799,10 +798,10 @@ packages:
dependency: "direct main"
description:
name: flutter_plugin_android_lifecycle
- sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0"
+ sha256: "3854fe5e3bff0b113c658f260b90c95dea17c92db0f2addeac2e343dd9969785"
url: "https://pub.dev"
source: hosted
- version: "2.0.34"
+ version: "2.0.35"
flutter_secure_storage:
dependency: transitive
description:
@@ -977,10 +976,10 @@ packages:
dependency: transitive
description:
name: hooks
- sha256: a41af4e8fc687cd6d33de9751eb936c8c0204ebe2bcb6c15ecf707504bf47f31
+ sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
url: "https://pub.dev"
source: hosted
- version: "2.0.0"
+ version: "2.0.2"
html:
dependency: transitive
description:
@@ -1257,10 +1256,10 @@ packages:
dependency: transitive
description:
name: meta
- sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
+ sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.dev"
source: hosted
- version: "1.18.0"
+ version: "1.17.0"
mime:
dependency: transitive
description:
@@ -1585,10 +1584,10 @@ packages:
dependency: transitive
description:
name: permission_handler_apple
- sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
+ sha256: e20daf680eef1ca62ffe8c8c526b778cc386d50137c77ac71c8ec9c88c13fb9d
url: "https://pub.dev"
source: hosted
- version: "9.4.7"
+ version: "9.4.9"
permission_handler_html:
dependency: transitive
description:
@@ -1697,10 +1696,10 @@ packages:
dependency: "direct main"
description:
name: qr_code_scanner_plus
- sha256: dae0596b2763c2fd0294f5cfddb1d3a21577ae4dc7fc1449eb5aafc957872f61
+ sha256: "2bcf9df32aa639fba07c183b1ab9c3f03eb6b1d688ab4f4f6bc868a75afd824d"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
recase:
dependency: transitive
description:
@@ -2046,26 +2045,26 @@ packages:
dependency: "direct dev"
description:
name: test
- sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20"
+ sha256: "280d6d890011ca966ad08df7e8a4ddfab0fb3aa49f96ed6de56e3521347a9ae7"
url: "https://pub.dev"
source: hosted
- version: "1.31.0"
+ version: "1.30.0"
test_api:
dependency: transitive
description:
name: test_api
- sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
+ sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
url: "https://pub.dev"
source: hosted
- version: "0.7.11"
+ version: "0.7.10"
test_core:
dependency: transitive
description:
name: test_core
- sha256: "1991d4cfe85d5043241acac92962c3977c8d2f2add1ee73130c7b286417d1d34"
+ sha256: "0381bd1585d1a924763c308100f2138205252fb90c9d4eeaf28489ee65ccde51"
url: "https://pub.dev"
source: hosted
- version: "0.6.17"
+ version: "0.6.16"
timeago:
dependency: "direct main"
description:
@@ -2206,10 +2205,10 @@ packages:
dependency: transitive
description:
name: vector_graphics_compiler
- sha256: b9b3f391857781aa96acacef96066f2f49b4cd03cf9fce3ca4d8da2ef5ea129e
+ sha256: "7ee12e6dffe0fc8e755179d6d91b3b34f5924223fc104d85572ef9180d73d172"
url: "https://pub.dev"
source: hosted
- version: "1.2.3"
+ version: "1.2.5"
vector_math:
dependency: transitive
description:
@@ -2334,10 +2333,10 @@ packages:
dependency: transitive
description:
name: window_to_front
- sha256: "7aef379752b7190c10479e12b5fd7c0b9d92adc96817d9e96c59937929512aee"
+ sha256: "14fad8984db4415e2eeb30b04bb77140b180e260d6cb66b26de126a8657a9241"
url: "https://pub.dev"
source: hosted
- version: "0.0.3"
+ version: "0.0.4"
x509_plus:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 39b3f24d..e33e3d34 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -23,7 +23,7 @@ dependencies:
carp_movesense_package: ^1.7.2
carp_themes_package: ^0.0.5
- carp_webservices: ^3.8.0
+ # carp_webservices: ^3.8.0
carp_backend: ^1.9.2
research_package: ^2.2.0
@@ -93,8 +93,8 @@ dependency_overrides:
# path: ../carp/carp.sensing-flutter/packages/carp_health_package/
# carp_movesense_package:
# path: ../carp/carp.sensing-flutter/packages/carp_movesense_package/
- # carp_webservices:
- # path: ../carp.sensing-flutter/backends/carp_webservices/
+ carp_webservices:
+ path: ../carp.sensing-flutter/backends/carp_webservices/
# carp_backend:
# path: ../carp/carp.sensing-flutter/backends/carp_backend/
# research_package: