Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions app/lib/screens/app_onboarding/iframe_helper.dart
Original file line number Diff line number Diff line change
@@ -1,25 +1,43 @@
import 'dart:convert';

import 'package:studyu_app/models/app_state.dart';
import 'package:studyu_core/core.dart';
import 'package:studyu_core/core.dart' show Study;
import 'package:studyu_core/env.dart' as env;
import "package:universal_html/html.dart" as html;

class IFrameHelper {
String _designerOrigin() {
final referrer = html.document.referrer;
if (referrer.isNotEmpty) {
final uri = Uri.tryParse(referrer);
if (uri != null && uri.hasScheme && uri.host.isNotEmpty) {
return uri.origin;
}
}
return env.designerUrl!;
}

void postPreviewStatus({required String status, String? message}) {
html.window.parent!.postMessage(
jsonEncode({
'type': 'previewStatus',
'status': status,
if (message != null) 'message': message,
}),
_designerOrigin(),
);
}

void postRouteFinished() {
// Go back to the selected origin route
html.window.parent!.postMessage('routeFinished', env.designerUrl!);
html.window.parent!.postMessage('routeFinished', _designerOrigin());
}

void listen(AppState state) {
html.window.onMessage.listen((event) {
final message = event.data as String;
final messageContent = jsonDecode(message) as Map<String, dynamic>;
// if (messageContent['intervention'] != null) {
// print(messageContent['intervention']);
// print("AppListen: " + messageContent.toString());
state.updateStudy(Study.fromJson(messageContent));
// }
});
}
}
55 changes: 44 additions & 11 deletions app/lib/screens/app_onboarding/loading_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class LoadingScreen extends StatefulWidget {
}

class _LoadingScreenState extends State<LoadingScreen> {
final IFrameHelper _iFrameHelper = IFrameHelper();

@override
void initState() {
super.initState();
Expand All @@ -32,7 +34,21 @@ class _LoadingScreenState extends State<LoadingScreen> {

Future<void> initStudy() async {
final state = context.read<AppState>();
await _initPreview(state);
try {
await _initPreview(state);
} catch (error, stackTrace) {
StudyULogger.error(
'Preview failed to initialize.',
error: error,
stackTrace: stackTrace,
);
_iFrameHelper.postPreviewStatus(
status: 'error',
message:
'The preview could not be opened for this study yet. Please try resetting the preview.',
);
rethrow;
}

final selectedSubjectId = await getActiveSubjectId();
if (!mounted) return;
Expand Down Expand Up @@ -69,6 +85,7 @@ class _LoadingScreenState extends State<LoadingScreen> {
final route = onBoarded ? Routes.terms : Routes.onboarding;

if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
Navigator.pushReplacementNamed(context, route);
}

Expand Down Expand Up @@ -125,41 +142,49 @@ class _LoadingScreenState extends State<LoadingScreen> {
);
final lang = AppLanguage(AppLocalizations.supportedLocales);
final preview = study_preview.Preview(widget.queryParameters, lang);
final iFrameHelper = IFrameHelper();
state.isPreview = true;
_iFrameHelper.postPreviewStatus(status: 'loading');
await preview.init();

// Authorize
if (!await preview.handleAuthorization()) {
final isAuthorized = await preview.handleAuthorization();
if (!isAuthorized) {
_iFrameHelper.postPreviewStatus(
status: 'error',
message:
'The preview could not be opened right now. Please try resetting the preview.',
);
return;
}
state.selectedStudy = preview.study;

await preview.runCommands();

iFrameHelper.listen(state);
_iFrameHelper.listen(state);

if (preview.hasRoute()) {
// print('[PreviewApp]: Found preview route:: ${preview.selectedRoute}');

// ELIGIBILITY CHECK
if (preview.selectedRoute == '/eligibilityCheck') {
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
// if we remove the await, we can push multiple times. warning: do not run in while(true)
await Navigator.push<EligibilityResult>(
context,
EligibilityScreen.routeFor(study: preview.study),
);
// either do the same navigator push again or --> send a message back to designer and let it reload the whole page <--
iFrameHelper.postRouteFinished();
_iFrameHelper.postRouteFinished();
return;
}

// INTERVENTION SELECTION
if (preview.selectedRoute == Routes.interventionSelection) {
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
await Navigator.pushNamed(context, Routes.interventionSelection);
iFrameHelper.postRouteFinished();
_iFrameHelper.postRouteFinished();
return;
}

Expand All @@ -171,24 +196,27 @@ class _LoadingScreenState extends State<LoadingScreen> {
// CONSENT
if (preview.selectedRoute == Routes.consent) {
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
await Navigator.pushNamed<bool>(context, Routes.consent);
iFrameHelper.postRouteFinished();
_iFrameHelper.postRouteFinished();
return;
}

// JOURNEY
if (preview.selectedRoute == Routes.journey) {
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
await Navigator.pushNamed(context, Routes.journey);
iFrameHelper.postRouteFinished();
_iFrameHelper.postRouteFinished();
return;
}

// DASHBOARD
if (preview.selectedRoute == Routes.dashboard) {
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
await Navigator.pushReplacementNamed(context, Routes.dashboard);
iFrameHelper.postRouteFinished();
_iFrameHelper.postRouteFinished();
return;
}

Expand All @@ -200,8 +228,9 @@ class _LoadingScreenState extends State<LoadingScreen> {
state.selectedStudy!.schedule.includeBaseline = false;
state.activeSubject!.study.schedule.includeBaseline = false;
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
await Navigator.pushReplacementNamed(context, Routes.dashboard);
iFrameHelper.postRouteFinished();
_iFrameHelper.postRouteFinished();
return;
}

Expand All @@ -213,6 +242,7 @@ class _LoadingScreenState extends State<LoadingScreen> {
),
];
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
await Navigator.push<bool>(
context,
TaskScreen.routeFor(
Expand All @@ -222,7 +252,7 @@ class _LoadingScreenState extends State<LoadingScreen> {
),
),
);
iFrameHelper.postRouteFinished();
_iFrameHelper.postRouteFinished();
return;
}
} else {
Expand All @@ -231,15 +261,18 @@ class _LoadingScreenState extends State<LoadingScreen> {
if (subject != null) {
state.activeSubject = subject;
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
Navigator.pushReplacementNamed(context, Routes.dashboard);
return;
} else {
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
Navigator.pushReplacementNamed(context, Routes.studyOverview);
return;
}
} else {
if (!mounted) return;
_iFrameHelper.postPreviewStatus(status: 'loaded');
Navigator.pushReplacementNamed(context, Routes.welcome);
return;
}
Expand Down
37 changes: 29 additions & 8 deletions app/lib/screens/app_onboarding/preview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ class Preview {

Future init() async {
previewSubjectIdKey();
selectedStudyObjectId = await getActiveSubjectId();
try {
selectedStudyObjectId = await getActiveSubjectId().timeout(
const Duration(seconds: 5),
);
} catch (_) {
selectedStudyObjectId = null;
}

if (containsQuery('languageCode')) {
final locale = Locale(queryParameters!['languageCode']!);
Expand Down Expand Up @@ -228,17 +234,32 @@ class Preview {

List<String> getInterventionIds() {
final interventionList = study!.interventions.map((i) => i.id).toList();
if (interventionList.isEmpty) {
return const [];
}

List<String> newInterventionList = [];
// If we have a specific intervention we want to show, select that and another one
if (selectedRoute == '/intervention' && extra != null) {
final String intId = interventionList.firstWhere((id) => id == extra);
newInterventionList
..add(intId)
..add(interventionList.firstWhere((id) => id != intId));
assert(newInterventionList.length == 2);
final String? selectedInterventionId = interventionList
.cast<String?>()
.firstWhere((id) => id == extra, orElse: () => null);

if (selectedInterventionId != null) {
newInterventionList.add(selectedInterventionId);
}

final String? alternativeInterventionId = interventionList
.cast<String?>()
.firstWhere(
(id) => id != null && id != selectedInterventionId,
orElse: () => null,
);
if (alternativeInterventionId != null) {
newInterventionList.add(alternativeInterventionId);
}
} else {
// just take the first two
newInterventionList = interventionList.sublist(0, 2);
newInterventionList = interventionList.take(2).toList();
}
return newInterventionList;
}
Expand Down
Loading
Loading