updates to improve navigation of practice activities
This commit is contained in:
parent
8fba3b667e
commit
b12efe7e80
9 changed files with 348 additions and 279 deletions
|
|
@ -4058,5 +4058,6 @@
|
|||
"suggestToSpaceDesc": "Suggested spaces will appear in the chat lists for their parent spaces",
|
||||
"practice": "Practice",
|
||||
"noLanguagesSet": "No languages set",
|
||||
"noActivitiesFound": "No practice activities found for this message"
|
||||
"noActivitiesFound": "No practice activities found for this message",
|
||||
"previous": "Previous"
|
||||
}
|
||||
|
|
@ -569,15 +569,7 @@ class PangeaMessageEvent {
|
|||
if (l2Code == null) return false;
|
||||
final List<PracticeActivityEvent> activities = practiceActivities(l2Code!);
|
||||
if (activities.isEmpty) return false;
|
||||
|
||||
// for now, only show the button if the event has no completed activities
|
||||
// TODO - revert this after adding logic to show next activity
|
||||
for (final activity in activities) {
|
||||
if (activity.isComplete) return false;
|
||||
}
|
||||
return true;
|
||||
// if (activities.isEmpty) return false;
|
||||
// return !activities.every((activity) => activity.isComplete);
|
||||
return activities.any((activity) => !(activity.isComplete));
|
||||
}
|
||||
|
||||
String? get l2Code =>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class MultipleChoice {
|
|||
return MultipleChoice(
|
||||
question: json['question'] as String,
|
||||
choices: (json['choices'] as List).map((e) => e as String).toList(),
|
||||
answer: json['answer'] as String,
|
||||
answer: json['answer'] ?? json['correct_answer'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -243,9 +243,11 @@ class PracticeActivityModel {
|
|||
.toList(),
|
||||
langCode: json['lang_code'] as String,
|
||||
msgId: json['msg_id'] as String,
|
||||
activityType: ActivityTypeEnum.values.firstWhere(
|
||||
(e) => e.string == json['activity_type'],
|
||||
),
|
||||
activityType: json['activity_type'] == "multipleChoice"
|
||||
? ActivityTypeEnum.multipleChoice
|
||||
: ActivityTypeEnum.values.firstWhere(
|
||||
(e) => e.string == json['activity_type'],
|
||||
),
|
||||
multipleChoice: json['multiple_choice'] != null
|
||||
? MultipleChoice.fromJson(
|
||||
json['multiple_choice'] as Map<String, dynamic>,
|
||||
|
|
|
|||
|
|
@ -2,26 +2,24 @@ import 'package:collection/collection.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
|
||||
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MultipleChoiceActivity extends StatelessWidget {
|
||||
final MessagePracticeActivityContentState card;
|
||||
class MultipleChoiceActivityView extends StatelessWidget {
|
||||
final PracticeActivityContentState controller;
|
||||
final Function(int) updateChoice;
|
||||
final bool isActive;
|
||||
|
||||
const MultipleChoiceActivity({
|
||||
const MultipleChoiceActivityView({
|
||||
super.key,
|
||||
required this.card,
|
||||
required this.controller,
|
||||
required this.updateChoice,
|
||||
required this.isActive,
|
||||
});
|
||||
|
||||
PracticeActivityEvent get practiceEvent => card.practiceEvent;
|
||||
PracticeActivityEvent get practiceEvent => controller.practiceEvent;
|
||||
|
||||
int? get selectedChoiceIndex => card.selectedChoiceIndex;
|
||||
|
||||
bool get submitted => card.recordSubmittedThisSession;
|
||||
int? get selectedChoiceIndex => controller.selectedChoiceIndex;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -50,10 +48,7 @@ class MultipleChoiceActivity extends StatelessWidget {
|
|||
.mapIndexed(
|
||||
(index, value) => Choice(
|
||||
text: value,
|
||||
color: (selectedChoiceIndex == index ||
|
||||
practiceActivity.multipleChoice!
|
||||
.isCorrect(index)) &&
|
||||
submitted
|
||||
color: selectedChoiceIndex == index
|
||||
? practiceActivity.multipleChoice!.choiceColor(index)
|
||||
: null,
|
||||
isGold: practiceActivity.multipleChoice!.isCorrect(index),
|
||||
104
lib/pangea/widgets/practice_activity/practice_activity.dart
Normal file
104
lib/pangea/widgets/practice_activity/practice_activity.dart
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
|
||||
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity_view.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class PracticeActivity extends StatefulWidget {
|
||||
final PracticeActivityEvent practiceEvent;
|
||||
final PangeaMessageEvent pangeaMessageEvent;
|
||||
final MessagePracticeActivityCardState controller;
|
||||
|
||||
const PracticeActivity({
|
||||
super.key,
|
||||
required this.practiceEvent,
|
||||
required this.pangeaMessageEvent,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
@override
|
||||
PracticeActivityContentState createState() => PracticeActivityContentState();
|
||||
}
|
||||
|
||||
class PracticeActivityContentState extends State<PracticeActivity> {
|
||||
PracticeActivityEvent get practiceEvent => widget.practiceEvent;
|
||||
int? selectedChoiceIndex;
|
||||
bool isSubmitted = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setRecord();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant PracticeActivity oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.practiceEvent.event.eventId !=
|
||||
widget.practiceEvent.event.eventId) {
|
||||
setRecord();
|
||||
}
|
||||
}
|
||||
|
||||
// sets the record model for the activity
|
||||
// either a new record model that will be sent after submitting the
|
||||
// activity or the record model from the user's previous response
|
||||
void setRecord() {
|
||||
if (widget.controller.recordEvent?.record == null) {
|
||||
final String question =
|
||||
practiceEvent.practiceActivity.multipleChoice!.question;
|
||||
widget.controller.recordModel =
|
||||
PracticeActivityRecordModel(question: question);
|
||||
} else {
|
||||
widget.controller.recordModel = widget.controller.recordEvent!.record;
|
||||
|
||||
// Note that only MultipleChoice activities will have this so we
|
||||
// probably should move this logic to the MultipleChoiceActivity widget
|
||||
selectedChoiceIndex =
|
||||
widget.controller.recordModel?.latestResponse != null
|
||||
? widget.practiceEvent.practiceActivity.multipleChoice
|
||||
?.choiceIndex(widget.controller.recordModel!.latestResponse!)
|
||||
: null;
|
||||
isSubmitted = widget.controller.recordModel?.latestResponse != null;
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void updateChoice(int index) {
|
||||
setState(() {
|
||||
selectedChoiceIndex = index;
|
||||
widget.controller.recordModel!.addResponse(
|
||||
text: widget
|
||||
.practiceEvent.practiceActivity.multipleChoice!.choices[index],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget get activityWidget {
|
||||
switch (widget.practiceEvent.practiceActivity.activityType) {
|
||||
case ActivityTypeEnum.multipleChoice:
|
||||
return MultipleChoiceActivityView(
|
||||
controller: this,
|
||||
updateChoice: updateChoice,
|
||||
isActive: !isSubmitted,
|
||||
);
|
||||
default:
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
debugPrint(
|
||||
"MessagePracticeActivityContentState.build with selectedChoiceIndex: $selectedChoiceIndex",
|
||||
);
|
||||
return Column(
|
||||
children: [
|
||||
activityWidget,
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,20 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:fluffychat/pangea/enum/message_mode_enum.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
|
||||
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/bot_style.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
class PracticeActivityCard extends StatefulWidget {
|
||||
final PangeaMessageEvent pangeaMessageEvent;
|
||||
|
|
@ -27,12 +32,32 @@ class PracticeActivityCard extends StatefulWidget {
|
|||
}
|
||||
|
||||
class MessagePracticeActivityCardState extends State<PracticeActivityCard> {
|
||||
List<PracticeActivityEvent> practiceActivities = [];
|
||||
PracticeActivityEvent? practiceEvent;
|
||||
PracticeActivityRecordModel? recordModel;
|
||||
bool sending = false;
|
||||
|
||||
int get practiceEventIndex => practiceActivities.indexWhere(
|
||||
(activity) => activity.event.eventId == practiceEvent?.event.eventId,
|
||||
);
|
||||
|
||||
bool get isPrevEnabled =>
|
||||
practiceEventIndex > 0 &&
|
||||
practiceActivities.length > (practiceEventIndex - 1);
|
||||
|
||||
bool get isNextEnabled =>
|
||||
practiceEventIndex >= 0 &&
|
||||
practiceEventIndex < practiceActivities.length - 1;
|
||||
|
||||
// the first record for this practice activity
|
||||
// assosiated with the current user
|
||||
PracticeActivityRecordEvent? get recordEvent =>
|
||||
practiceEvent?.userRecords.firstOrNull;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
loadInitialData();
|
||||
setPracticeActivities();
|
||||
}
|
||||
|
||||
String? get langCode {
|
||||
|
|
@ -50,46 +75,106 @@ class MessagePracticeActivityCardState extends State<PracticeActivityCard> {
|
|||
return langCode;
|
||||
}
|
||||
|
||||
void loadInitialData() {
|
||||
/// Initalizes the practice activities for the current language
|
||||
/// and sets the first activity as the current activity
|
||||
void setPracticeActivities() {
|
||||
if (langCode == null) return;
|
||||
updatePracticeActivity();
|
||||
if (practiceEvent == null) {
|
||||
debugger(when: kDebugMode);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePracticeActivity() {
|
||||
if (langCode == null) return;
|
||||
final List<PracticeActivityEvent> activities =
|
||||
practiceActivities =
|
||||
widget.pangeaMessageEvent.practiceActivities(langCode!);
|
||||
if (activities.isEmpty) return;
|
||||
final List<PracticeActivityEvent> incompleteActivities =
|
||||
activities.where((element) => !element.isComplete).toList();
|
||||
debugPrint("total events: ${activities.length}");
|
||||
debugPrint("incomplete practice events: ${incompleteActivities.length}");
|
||||
if (practiceActivities.isEmpty) return;
|
||||
|
||||
// TODO update to show next activity
|
||||
practiceEvent = activities.first;
|
||||
// // if an incomplete activity is found, show that
|
||||
// if (incompleteActivities.isNotEmpty) {
|
||||
// practiceEvent = incompleteActivities.first;
|
||||
// }
|
||||
// // if no incomplete activity is found, show the last activity
|
||||
// else if (activities.isNotEmpty) {
|
||||
// practiceEvent = activities.last;
|
||||
// }
|
||||
practiceActivities.sort(
|
||||
(a, b) => a.event.originServerTs.compareTo(b.event.originServerTs),
|
||||
);
|
||||
|
||||
// if the current activity hasn't been set yet, show the first uncompleted activity
|
||||
// if there is one. If not, show the first activity
|
||||
final List<PracticeActivityEvent> incompleteActivities =
|
||||
practiceActivities.where((element) => !element.isComplete).toList();
|
||||
practiceEvent ??= incompleteActivities.isNotEmpty
|
||||
? incompleteActivities.first
|
||||
: practiceActivities.first;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void showNextActivity() {
|
||||
if (langCode == null) return;
|
||||
updatePracticeActivity();
|
||||
widget.controller.updateMode(MessageMode.practiceActivity);
|
||||
void navigateActivities({Direction? direction, int? index}) {
|
||||
final bool enableNavigation = (direction == Direction.f && isNextEnabled) ||
|
||||
(direction == Direction.b && isPrevEnabled) ||
|
||||
(index != null && index >= 0 && index < practiceActivities.length);
|
||||
if (enableNavigation) {
|
||||
final int newIndex = index ??
|
||||
(direction == Direction.f
|
||||
? practiceEventIndex + 1
|
||||
: practiceEventIndex - 1);
|
||||
practiceEvent = practiceActivities[newIndex];
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
void sendRecord() {
|
||||
if (recordModel == null || practiceEvent == null) return;
|
||||
setState(() => sending = true);
|
||||
MatrixState.pangeaController.activityRecordController
|
||||
.send(recordModel!, practiceEvent!)
|
||||
.catchError((error) {
|
||||
ErrorHandler.logError(
|
||||
e: error,
|
||||
s: StackTrace.current,
|
||||
data: {
|
||||
'recordModel': recordModel?.toJson(),
|
||||
'practiceEvent': practiceEvent?.event.toJson(),
|
||||
},
|
||||
);
|
||||
return null;
|
||||
}).whenComplete(() => setState(() => sending = false));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (practiceEvent == null) {
|
||||
final Widget navigationButtons = Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: isPrevEnabled ? 1.0 : 0,
|
||||
child: IconButton(
|
||||
onPressed: isPrevEnabled
|
||||
? () => navigateActivities(direction: Direction.b)
|
||||
: null,
|
||||
icon: const Icon(Icons.keyboard_arrow_left_outlined),
|
||||
tooltip: L10n.of(context)!.previous,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Opacity(
|
||||
opacity: recordEvent == null ? 1.0 : 0.5,
|
||||
child: sending
|
||||
? const CircularProgressIndicator.adaptive()
|
||||
: TextButton(
|
||||
onPressed: recordEvent == null ? sendRecord : null,
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all<Color>(
|
||||
AppConfig.primaryColor,
|
||||
),
|
||||
),
|
||||
child: Text(L10n.of(context)!.submit),
|
||||
),
|
||||
),
|
||||
),
|
||||
Opacity(
|
||||
opacity: isNextEnabled ? 1.0 : 0,
|
||||
child: IconButton(
|
||||
onPressed: isNextEnabled
|
||||
? () => navigateActivities(direction: Direction.f)
|
||||
: null,
|
||||
icon: const Icon(Icons.keyboard_arrow_right_outlined),
|
||||
tooltip: L10n.of(context)!.next,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
if (practiceEvent == null || practiceActivities.isEmpty) {
|
||||
return Text(
|
||||
L10n.of(context)!.noActivitiesFound,
|
||||
style: BotStyle.text(context),
|
||||
|
|
@ -99,10 +184,15 @@ class MessagePracticeActivityCardState extends State<PracticeActivityCard> {
|
|||
// onActivityGenerated: updatePracticeActivity,
|
||||
// );
|
||||
}
|
||||
return PracticeActivityContent(
|
||||
practiceEvent: practiceEvent!,
|
||||
pangeaMessageEvent: widget.pangeaMessageEvent,
|
||||
controller: this,
|
||||
return Column(
|
||||
children: [
|
||||
PracticeActivity(
|
||||
pangeaMessageEvent: widget.pangeaMessageEvent,
|
||||
practiceEvent: practiceEvent!,
|
||||
controller: this,
|
||||
),
|
||||
navigationButtons,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,165 +0,0 @@
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart';
|
||||
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
|
||||
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart';
|
||||
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
class PracticeActivityContent extends StatefulWidget {
|
||||
final PracticeActivityEvent practiceEvent;
|
||||
final PangeaMessageEvent pangeaMessageEvent;
|
||||
final MessagePracticeActivityCardState controller;
|
||||
|
||||
const PracticeActivityContent({
|
||||
super.key,
|
||||
required this.practiceEvent,
|
||||
required this.pangeaMessageEvent,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
@override
|
||||
MessagePracticeActivityContentState createState() =>
|
||||
MessagePracticeActivityContentState();
|
||||
}
|
||||
|
||||
class MessagePracticeActivityContentState
|
||||
extends State<PracticeActivityContent> {
|
||||
int? selectedChoiceIndex;
|
||||
PracticeActivityRecordModel? recordModel;
|
||||
bool recordSubmittedThisSession = false;
|
||||
bool recordSubmittedPreviousSession = false;
|
||||
|
||||
PracticeActivityEvent get practiceEvent => widget.practiceEvent;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initalizeActivity();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant PracticeActivityContent oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.practiceEvent.event.eventId !=
|
||||
widget.practiceEvent.event.eventId) {
|
||||
initalizeActivity();
|
||||
}
|
||||
}
|
||||
|
||||
void initalizeActivity() {
|
||||
final PracticeActivityRecordEvent? recordEvent =
|
||||
widget.practiceEvent.userRecords.firstOrNull;
|
||||
if (recordEvent?.record == null) {
|
||||
recordModel = PracticeActivityRecordModel(
|
||||
question:
|
||||
widget.practiceEvent.practiceActivity.multipleChoice!.question,
|
||||
);
|
||||
} else {
|
||||
recordModel = recordEvent!.record;
|
||||
|
||||
//Note that only MultipleChoice activities will have this so we probably should move this logic to the MultipleChoiceActivity widget
|
||||
selectedChoiceIndex = recordModel?.latestResponse != null
|
||||
? widget.practiceEvent.practiceActivity.multipleChoice
|
||||
?.choiceIndex(recordModel!.latestResponse!)
|
||||
: null;
|
||||
|
||||
recordSubmittedPreviousSession = true;
|
||||
recordSubmittedThisSession = true;
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void updateChoice(int index) {
|
||||
setState(() {
|
||||
selectedChoiceIndex = index;
|
||||
recordModel!.addResponse(
|
||||
text: widget
|
||||
.practiceEvent.practiceActivity.multipleChoice!.choices[index],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget get activityWidget {
|
||||
switch (widget.practiceEvent.practiceActivity.activityType) {
|
||||
case ActivityTypeEnum.multipleChoice:
|
||||
return MultipleChoiceActivity(
|
||||
card: this,
|
||||
updateChoice: updateChoice,
|
||||
isActive:
|
||||
!recordSubmittedPreviousSession && !recordSubmittedThisSession,
|
||||
);
|
||||
default:
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
||||
void sendRecord() {
|
||||
MatrixState.pangeaController.activityRecordController
|
||||
.send(
|
||||
recordModel!,
|
||||
widget.practiceEvent,
|
||||
)
|
||||
.catchError((error) {
|
||||
ErrorHandler.logError(
|
||||
e: error,
|
||||
s: StackTrace.current,
|
||||
data: {
|
||||
'recordModel': recordModel?.toJson(),
|
||||
'practiceEvent': widget.practiceEvent.event.toJson(),
|
||||
},
|
||||
);
|
||||
return null;
|
||||
}).then((_) => widget.controller.showNextActivity());
|
||||
|
||||
setState(() {
|
||||
recordSubmittedThisSession = true;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
debugPrint(
|
||||
"MessagePracticeActivityContentState.build with selectedChoiceIndex: $selectedChoiceIndex",
|
||||
);
|
||||
return Column(
|
||||
children: [
|
||||
activityWidget,
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: selectedChoiceIndex != null &&
|
||||
!recordSubmittedThisSession &&
|
||||
!recordSubmittedPreviousSession
|
||||
? 1.0
|
||||
: 0.5,
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
if (recordSubmittedThisSession ||
|
||||
recordSubmittedPreviousSession) {
|
||||
return;
|
||||
}
|
||||
selectedChoiceIndex != null ? sendRecord() : null;
|
||||
},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStateProperty.all<Color>(
|
||||
AppConfig.primaryColor,
|
||||
),
|
||||
),
|
||||
child: Text(L10n.of(context)!.submit),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -863,7 +863,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"be": [
|
||||
|
|
@ -2363,7 +2364,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"bn": [
|
||||
|
|
@ -3859,7 +3861,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"bo": [
|
||||
|
|
@ -5359,7 +5362,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ca": [
|
||||
|
|
@ -6261,7 +6265,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"cs": [
|
||||
|
|
@ -7245,7 +7250,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"de": [
|
||||
|
|
@ -8112,7 +8118,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"el": [
|
||||
|
|
@ -9563,7 +9570,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"eo": [
|
||||
|
|
@ -10712,7 +10720,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"es": [
|
||||
|
|
@ -10727,7 +10736,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"et": [
|
||||
|
|
@ -11594,7 +11604,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"eu": [
|
||||
|
|
@ -12463,7 +12474,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"fa": [
|
||||
|
|
@ -13469,7 +13481,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"fi": [
|
||||
|
|
@ -14439,7 +14452,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"fil": [
|
||||
|
|
@ -15765,7 +15779,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
|
|
@ -16770,7 +16785,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ga": [
|
||||
|
|
@ -17904,7 +17920,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"gl": [
|
||||
|
|
@ -18771,7 +18788,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"he": [
|
||||
|
|
@ -20024,7 +20042,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"hi": [
|
||||
|
|
@ -21517,7 +21536,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"hr": [
|
||||
|
|
@ -22463,7 +22483,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"hu": [
|
||||
|
|
@ -23346,7 +23367,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ia": [
|
||||
|
|
@ -24832,7 +24854,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"id": [
|
||||
|
|
@ -25705,7 +25728,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ie": [
|
||||
|
|
@ -26962,7 +26986,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"it": [
|
||||
|
|
@ -27886,7 +27911,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ja": [
|
||||
|
|
@ -28921,7 +28947,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ka": [
|
||||
|
|
@ -30275,7 +30302,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ko": [
|
||||
|
|
@ -31144,7 +31172,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"lt": [
|
||||
|
|
@ -32179,7 +32208,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"lv": [
|
||||
|
|
@ -33054,7 +33084,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"nb": [
|
||||
|
|
@ -34253,7 +34284,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"nl": [
|
||||
|
|
@ -35216,7 +35248,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"pl": [
|
||||
|
|
@ -36188,7 +36221,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"pt": [
|
||||
|
|
@ -37666,7 +37700,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"pt_BR": [
|
||||
|
|
@ -38539,7 +38574,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"pt_PT": [
|
||||
|
|
@ -39739,7 +39775,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ro": [
|
||||
|
|
@ -40746,7 +40783,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
|
|
@ -41619,7 +41657,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"sk": [
|
||||
|
|
@ -42885,7 +42924,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"sl": [
|
||||
|
|
@ -44281,7 +44321,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"sr": [
|
||||
|
|
@ -45451,7 +45492,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"sv": [
|
||||
|
|
@ -46355,7 +46397,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"ta": [
|
||||
|
|
@ -47852,7 +47895,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"th": [
|
||||
|
|
@ -49303,7 +49347,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"tr": [
|
||||
|
|
@ -50170,7 +50215,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"uk": [
|
||||
|
|
@ -51074,7 +51120,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"vi": [
|
||||
|
|
@ -52426,7 +52473,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"zh": [
|
||||
|
|
@ -53293,7 +53341,8 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
],
|
||||
|
||||
"zh_Hant": [
|
||||
|
|
@ -54441,6 +54490,7 @@
|
|||
"suggestToSpaceDesc",
|
||||
"practice",
|
||||
"noLanguagesSet",
|
||||
"noActivitiesFound"
|
||||
"noActivitiesFound",
|
||||
"previous"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue