From 5ce2a787b44f354fbad7623d0cb3439426385d5d Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Mon, 8 Sep 2025 15:25:56 -0400 Subject: [PATCH] 3890 activity start page changes (#3901) * comment out unreferenced files * decouple courses, topics, and activities * update start page * disable 'join open session' button --- lib/config/routes.dart | 40 +- lib/l10n/intl_en.arb | 6 +- lib/pages/chat/chat.dart | 10 +- lib/pages/chat/chat_event_list.dart | 105 +- lib/pages/chat/events/message.dart | 4 +- .../activity_generator.dart | 448 +++--- .../activity_generator_view.dart | 604 ++++---- .../activity_mode_list_repo.dart | 90 +- .../activity_plan_card.dart | 1256 ++++++++--------- .../activity_plan_generation_repo.dart | 76 +- .../learning_objective_list_repo.dart | 92 +- .../list_request_schema.dart | 60 +- .../activity_generator/topic_list_repo.dart | 90 +- .../activity_plan_message.dart | 546 +++---- .../activity_planner/activity_plan_model.dart | 26 - .../activity_plan_response.dart | 34 +- .../activity_planner_builder.dart | 718 +++++----- .../activity_planner_page.dart | 298 ++-- .../activity_planner_page_appbar.dart | 116 +- .../bookmarked_activity_list.dart | 216 +-- .../suggestion_form_field.dart | 112 +- .../activity_participant_list.dart | 11 +- .../activity_room_extension.dart | 8 + .../activity_finished_status_message.dart | 1 + .../activity_pinned_message.dart | 4 +- .../activity_results_carousel.dart | 94 -- .../activity_session_constants.dart} | 2 +- .../activity_session_details_row.dart} | 4 +- .../activity_session_start_page.dart | 146 +- .../activity_sessions_start_view.dart | 330 +++-- .../activity_summary_widget.dart | 124 +- .../activity_plan_repo.dart | 120 +- .../activity_plan_search_repo.dart | 172 +-- .../activity_search_enum.dart | 94 +- .../activity_search_request.dart | 68 +- .../activity_suggestion_card.dart | 7 +- .../activity_suggestion_dialog.dart | 564 ++++---- .../activity_suggestion_dialog_content.dart | 1240 ++++++++-------- .../activity_suggestions_area.dart | 582 ++++---- .../common/controllers/pangea_controller.dart | 6 +- .../course_chats/course_chats_page.dart | 13 +- .../course_chats/course_chats_view.dart | 39 +- .../course_info_chip_widget.dart | 4 +- .../course_creation/selected_course_view.dart | 21 +- .../course_plans/course_activity_repo.dart | 127 ++ .../course_location_media_repo.dart | 102 ++ .../course_plans/course_location_model.dart | 30 + .../course_plans/course_location_repo.dart | 107 ++ .../course_plans/course_media_repo.dart | 98 ++ .../course_plans/course_plan_builder.dart | 14 +- .../course_plans/course_plan_model.dart | 262 +--- .../course_plan_room_extension.dart | 80 +- .../course_plans/course_plans_repo.dart | 229 +-- .../course_plans/course_topic_model.dart | 86 ++ .../course_plans/course_topic_repo.dart | 109 ++ .../course_settings/course_settings.dart | 112 +- .../models/course_plan/cms_course_plan.dart | 15 + .../course_plan/cms_course_plan_activity.dart | 41 + .../course_plan/cms_course_plan_topic.dart | 11 + .../cms_course_plan_topic_location.dart | 9 + lib/pangea/payload_client/payload_repo.dart | 10 + .../spaces/utils/load_participants_util.dart | 10 +- .../user/controllers/user_controller.dart | 27 +- .../user/models/activities_profile_model.dart | 16 +- 64 files changed, 5249 insertions(+), 4847 deletions(-) delete mode 100644 lib/pangea/activity_sessions/activity_session_chat/activity_results_carousel.dart rename lib/pangea/{activity_suggestions/activity_suggestions_constants.dart => activity_sessions/activity_session_constants.dart} (89%) rename lib/pangea/{activity_suggestions/activity_suggestion_card_row.dart => activity_sessions/activity_session_details_row.dart} (87%) create mode 100644 lib/pangea/course_plans/course_activity_repo.dart create mode 100644 lib/pangea/course_plans/course_location_media_repo.dart create mode 100644 lib/pangea/course_plans/course_location_model.dart create mode 100644 lib/pangea/course_plans/course_location_repo.dart create mode 100644 lib/pangea/course_plans/course_media_repo.dart create mode 100644 lib/pangea/course_plans/course_topic_model.dart create mode 100644 lib/pangea/course_plans/course_topic_repo.dart create mode 100644 lib/pangea/payload_client/payload_repo.dart diff --git a/lib/config/routes.dart b/lib/config/routes.dart index 32268f90a..d584c6729 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -28,8 +28,7 @@ import 'package:fluffychat/pages/settings_notifications/settings_notifications.d import 'package:fluffychat/pages/settings_password/settings_password.dart'; import 'package:fluffychat/pages/settings_security/settings_security.dart'; import 'package:fluffychat/pages/settings_style/settings_style.dart'; -import 'package:fluffychat/pangea/activity_generator/activity_generator.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_page.dart'; +import 'package:fluffychat/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart'; import 'package:fluffychat/pangea/analytics_page/analytics_page.dart'; import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; import 'package:fluffychat/pangea/chat_settings/pages/pangea_invitation_selection.dart'; @@ -597,6 +596,19 @@ abstract class AppRoutes { routes: roomDetailsRoutes('spaceid'), ), ...roomDetailsRoutes('spaceid'), + GoRoute( + path: 'activity/:activityid', + pageBuilder: (context, state) => defaultPageBuilder( + context, + state, + ActivitySessionStartPage( + activityId: state.pathParameters['activityid']!, + isNew: state.uri.queryParameters['new'] == 'true', + parentId: state.pathParameters['spaceid']!, + ), + ), + redirect: loggedOutRedirect, + ), GoRoute( path: ':roomid', pageBuilder: (context, state) { @@ -911,30 +923,6 @@ abstract class AppRoutes { ), ), ), - GoRoute( - path: 'planner', - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - ActivityPlannerPage( - roomID: state.pathParameters[roomKey]!, - ), - ), - redirect: loggedOutRedirect, - routes: [ - GoRoute( - path: '/generator', - redirect: loggedOutRedirect, - pageBuilder: (context, state) => defaultPageBuilder( - context, - state, - ActivityGenerator( - roomID: state.pathParameters[roomKey]!, - ), - ), - ), - ], - ), GoRoute( path: 'access', pageBuilder: (context, state) => defaultPageBuilder( diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index b4be71d64..514bb9296 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -5196,5 +5196,9 @@ "@goToCourse": { "type": "String", "course": {} - } + }, + "startNewSession": "Start new session", + "joinOpenSession": "Join open session", + "less": "less", + "activityNotFound": "Activity not found" } diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 99e809a20..96ac50807 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -2242,8 +2242,14 @@ class ChatController extends State ); } - if (room.isActivitySession == true && !room.activityHasStarted) { - return ActivitySessionStartPage(room: room); + if (room.isActivitySession == true && + !room.activityHasStarted && + room.courseParent != null) { + return ActivitySessionStartPage( + activityId: room.activityId!, + room: room, + parentId: room.courseParent!.id, + ); } // Pangea# final theme = Theme.of(context); diff --git a/lib/pages/chat/chat_event_list.dart b/lib/pages/chat/chat_event_list.dart index a58e86413..0afddf744 100644 --- a/lib/pages/chat/chat_event_list.dart +++ b/lib/pages/chat/chat_event_list.dart @@ -8,9 +8,7 @@ import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pages/chat/events/message.dart'; import 'package:fluffychat/pages/chat/seen_by_row.dart'; import 'package:fluffychat/pages/chat/typing_indicators.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_message.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_user_summaries_widget.dart'; -import 'package:fluffychat/pangea/events/extensions/pangea_event_extension.dart'; import 'package:fluffychat/utils/account_config.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/filtered_timeline_extension.dart'; import 'package:fluffychat/utils/platform_infos.dart'; @@ -144,67 +142,48 @@ class ChatEventList extends StatelessWidget { key: ValueKey(event.eventId), index: i, controller: controller.scrollController, - child: - // #Pangea - event.isActivityMessage - ? ActivityPlanMessage( - event, - controller: controller, - timeline: timeline, - animateIn: animateIn, - resetAnimateIn: () { - controller.animateInEventIndex = null; - }, - highlightMarker: - controller.scrollToEventIdMarker == event.eventId, - selected: controller.selectedEvents - .any((e) => e.eventId == event.eventId), - ) - : - // Pangea# - Message( - event, - animateIn: animateIn, - resetAnimateIn: () { - controller.animateInEventIndex = null; - }, - onSwipe: () => controller.replyAction(replyTo: event), - // #Pangea - onInfoTab: (_) => {}, - // onInfoTab: controller.showEventInfo, - // Pangea# - onMention: () => controller.sendController.text += - '${event.senderFromMemoryOrFallback.mention} ', - highlightMarker: - controller.scrollToEventIdMarker == event.eventId, - // #Pangea - // onSelect: controller.onSelectMessage, - onSelect: (_) {}, - // Pangea# - scrollToEventId: (String eventId) => - controller.scrollToEventId(eventId), - longPressSelect: controller.selectedEvents.isNotEmpty, - // #Pangea - immersionMode: controller.choreographer.immersionMode, - controller: controller, - isButton: event.eventId == controller.buttonEventID, - // Pangea# - selected: controller.selectedEvents - .any((e) => e.eventId == event.eventId), - singleSelected: - controller.selectedEvents.singleOrNull?.eventId == - event.eventId, - onEdit: () => controller.editSelectedEventAction(), - timeline: timeline, - displayReadMarker: i > 0 && - controller.readMarkerEventId == event.eventId, - nextEvent: - i + 1 < events.length ? events[i + 1] : null, - previousEvent: i > 0 ? events[i - 1] : null, - wallpaperMode: hasWallpaper, - scrollController: controller.scrollController, - colors: colors, - ), + child: Message( + event, + animateIn: animateIn, + resetAnimateIn: () { + controller.animateInEventIndex = null; + }, + onSwipe: () => controller.replyAction(replyTo: event), + // #Pangea + onInfoTab: (_) => {}, + // onInfoTab: controller.showEventInfo, + // Pangea# + onMention: () => controller.sendController.text += + '${event.senderFromMemoryOrFallback.mention} ', + highlightMarker: + controller.scrollToEventIdMarker == event.eventId, + // #Pangea + // onSelect: controller.onSelectMessage, + onSelect: (_) {}, + // Pangea# + scrollToEventId: (String eventId) => + controller.scrollToEventId(eventId), + longPressSelect: controller.selectedEvents.isNotEmpty, + // #Pangea + immersionMode: controller.choreographer.immersionMode, + controller: controller, + isButton: event.eventId == controller.buttonEventID, + // Pangea# + selected: controller.selectedEvents + .any((e) => e.eventId == event.eventId), + singleSelected: + controller.selectedEvents.singleOrNull?.eventId == + event.eventId, + onEdit: () => controller.editSelectedEventAction(), + timeline: timeline, + displayReadMarker: + i > 0 && controller.readMarkerEventId == event.eventId, + nextEvent: i + 1 < events.length ? events[i + 1] : null, + previousEvent: i > 0 ? events[i - 1] : null, + wallpaperMode: hasWallpaper, + scrollController: controller.scrollController, + colors: colors, + ), ); }, // #Pangea diff --git a/lib/pages/chat/events/message.dart b/lib/pages/chat/events/message.dart index 8562956ad..52f75dde6 100644 --- a/lib/pages/chat/events/message.dart +++ b/lib/pages/chat/events/message.dart @@ -137,8 +137,10 @@ class Message extends StatelessWidget { } // #Pangea - if (event.type == PangeaEventTypes.activityPlan) { + if (event.type == PangeaEventTypes.activityPlan && + event.room.activityPlan != null) { return ActivitySummary( + activity: event.room.activityPlan!, room: event.room, showInstructions: controller.showInstructions, toggleInstructions: controller.toggleShowInstructions, diff --git a/lib/pangea/activity_generator/activity_generator.dart b/lib/pangea/activity_generator/activity_generator.dart index bc5f9319c..4e1e237d9 100644 --- a/lib/pangea/activity_generator/activity_generator.dart +++ b/lib/pangea/activity_generator/activity_generator.dart @@ -1,267 +1,267 @@ -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:collection/collection.dart'; -import 'package:matrix/matrix.dart'; +// import 'package:collection/collection.dart'; +// import 'package:matrix/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_generator/activity_generator_view.dart'; -import 'package:fluffychat/pangea/activity_generator/activity_mode_list_repo.dart'; -import 'package:fluffychat/pangea/activity_generator/activity_plan_generation_repo.dart'; -import 'package:fluffychat/pangea/activity_generator/learning_objective_list_repo.dart'; -import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; -import 'package:fluffychat/pangea/activity_generator/media_enum.dart'; -import 'package:fluffychat/pangea/activity_generator/topic_list_repo.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; -import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/config/app_config.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_generator/activity_generator_view.dart'; +// import 'package:fluffychat/pangea/activity_generator/activity_mode_list_repo.dart'; +// import 'package:fluffychat/pangea/activity_generator/activity_plan_generation_repo.dart'; +// import 'package:fluffychat/pangea/activity_generator/learning_objective_list_repo.dart'; +// import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; +// import 'package:fluffychat/pangea/activity_generator/media_enum.dart'; +// import 'package:fluffychat/pangea/activity_generator/topic_list_repo.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; +// import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +// import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; +// import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -class ActivityGenerator extends StatefulWidget { - final String roomID; - const ActivityGenerator({ - required this.roomID, - super.key, - }); +// class ActivityGenerator extends StatefulWidget { +// final String roomID; +// const ActivityGenerator({ +// required this.roomID, +// super.key, +// }); - @override - ActivityGeneratorState createState() => ActivityGeneratorState(); -} +// @override +// ActivityGeneratorState createState() => ActivityGeneratorState(); +// } -class ActivityGeneratorState extends State { - bool loading = false; - Object? error; - List? activities; +// class ActivityGeneratorState extends State { +// bool loading = false; +// Object? error; +// List? activities; - final formKey = GlobalKey(); +// final formKey = GlobalKey(); - final topicController = TextEditingController(); - final objectiveController = TextEditingController(); - final modeController = TextEditingController(); +// final topicController = TextEditingController(); +// final objectiveController = TextEditingController(); +// final modeController = TextEditingController(); - MediaEnum selectedMedia = MediaEnum.nan; - String? selectedLanguageOfInstructions; - String? selectedTargetLanguage; - LanguageLevelTypeEnum? selectedCefrLevel; - int? selectedNumberOfParticipants; +// MediaEnum selectedMedia = MediaEnum.nan; +// String? selectedLanguageOfInstructions; +// String? selectedTargetLanguage; +// LanguageLevelTypeEnum? selectedCefrLevel; +// int? selectedNumberOfParticipants; - String? filename; +// String? filename; - List? topicItems; - List? modeItems; - List? objectiveItems; +// List? topicItems; +// List? modeItems; +// List? objectiveItems; - @override - void initState() { - super.initState(); +// @override +// void initState() { +// super.initState(); - selectedLanguageOfInstructions = - MatrixState.pangeaController.languageController.userL1?.langCode; - selectedTargetLanguage = - MatrixState.pangeaController.languageController.userL2?.langCode; - selectedCefrLevel = LanguageLevelTypeEnum.a1; - selectedNumberOfParticipants = 3; - _setMode(); - _setTopic(); - _setObjective(); - } +// selectedLanguageOfInstructions = +// MatrixState.pangeaController.languageController.userL1?.langCode; +// selectedTargetLanguage = +// MatrixState.pangeaController.languageController.userL2?.langCode; +// selectedCefrLevel = LanguageLevelTypeEnum.a1; +// selectedNumberOfParticipants = 3; +// _setMode(); +// _setTopic(); +// _setObjective(); +// } - @override - void dispose() { - topicController.dispose(); - objectiveController.dispose(); - modeController.dispose(); - super.dispose(); - } +// @override +// void dispose() { +// topicController.dispose(); +// objectiveController.dispose(); +// modeController.dispose(); +// super.dispose(); +// } - ActivitySettingRequestSchema get req => ActivitySettingRequestSchema( - langCode: - MatrixState.pangeaController.languageController.userL1?.langCode ?? - LanguageKeys.defaultLanguage, - ); +// ActivitySettingRequestSchema get req => ActivitySettingRequestSchema( +// langCode: +// MatrixState.pangeaController.languageController.userL1?.langCode ?? +// LanguageKeys.defaultLanguage, +// ); - ActivityPlanRequest get planRequest => ActivityPlanRequest( - topic: topicController.text, - mode: modeController.text, - objective: objectiveController.text, - media: selectedMedia, - languageOfInstructions: selectedLanguageOfInstructions!, - targetLanguage: selectedTargetLanguage!, - cefrLevel: selectedCefrLevel!, - numberOfParticipants: selectedNumberOfParticipants!, - ); +// ActivityPlanRequest get planRequest => ActivityPlanRequest( +// topic: topicController.text, +// mode: modeController.text, +// objective: objectiveController.text, +// media: selectedMedia, +// languageOfInstructions: selectedLanguageOfInstructions!, +// targetLanguage: selectedTargetLanguage!, +// cefrLevel: selectedCefrLevel!, +// numberOfParticipants: selectedNumberOfParticipants!, +// ); - Room? get room => Matrix.of(context).client.getRoomById(widget.roomID); +// Room? get room => Matrix.of(context).client.getRoomById(widget.roomID); - String? validateNotNull(String? value) { - if (value == null || value.isEmpty) { - return L10n.of(context).interactiveTranslatorRequired; - } - return null; - } +// String? validateNotNull(String? value) { +// if (value == null || value.isEmpty) { +// return L10n.of(context).interactiveTranslatorRequired; +// } +// return null; +// } - String? get _randomTopic => (topicItems?..shuffle())?.first.name; +// String? get _randomTopic => (topicItems?..shuffle())?.first.name; - String? get _randomObjective => (objectiveItems?..shuffle())?.first.name; +// String? get _randomObjective => (objectiveItems?..shuffle())?.first.name; - String? get _randomMode => (modeItems?..shuffle())?.first.name; +// String? get _randomMode => (modeItems?..shuffle())?.first.name; - bool get randomizeEnabled => - topicItems != null && objectiveItems != null && modeItems != null; +// bool get randomizeEnabled => +// topicItems != null && objectiveItems != null && modeItems != null; - void randomizeSelections() { - final selectedTopic = _randomTopic; - final selectedObjective = _randomObjective; - final selectedMode = _randomMode; +// void randomizeSelections() { +// final selectedTopic = _randomTopic; +// final selectedObjective = _randomObjective; +// final selectedMode = _randomMode; - if (selectedTopic == null || - selectedObjective == null || - selectedMode == null) { - return; - } +// if (selectedTopic == null || +// selectedObjective == null || +// selectedMode == null) { +// return; +// } - if (mounted) { - setState(() { - topicController.text = selectedTopic; - objectiveController.text = selectedObjective; - modeController.text = selectedMode; - }); - } - } +// if (mounted) { +// setState(() { +// topicController.text = selectedTopic; +// objectiveController.text = selectedObjective; +// modeController.text = selectedMode; +// }); +// } +// } - void clearSelections() async { - setState(() { - topicController.clear(); - objectiveController.clear(); - modeController.clear(); - selectedMedia = MediaEnum.nan; - selectedLanguageOfInstructions = - MatrixState.pangeaController.languageController.userL1?.langCode; - selectedTargetLanguage = - MatrixState.pangeaController.languageController.userL2?.langCode; - selectedCefrLevel = LanguageLevelTypeEnum.a1; - selectedNumberOfParticipants = 3; - }); - } +// void clearSelections() async { +// setState(() { +// topicController.clear(); +// objectiveController.clear(); +// modeController.clear(); +// selectedMedia = MediaEnum.nan; +// selectedLanguageOfInstructions = +// MatrixState.pangeaController.languageController.userL1?.langCode; +// selectedTargetLanguage = +// MatrixState.pangeaController.languageController.userL2?.langCode; +// selectedCefrLevel = LanguageLevelTypeEnum.a1; +// selectedNumberOfParticipants = 3; +// }); +// } - void setSelectedNumberOfParticipants(int? value) { - setState(() => selectedNumberOfParticipants = value); - } +// void setSelectedNumberOfParticipants(int? value) { +// setState(() => selectedNumberOfParticipants = value); +// } - void setSelectedTargetLanguage(String? value) { - setState(() => selectedTargetLanguage = value); - } +// void setSelectedTargetLanguage(String? value) { +// setState(() => selectedTargetLanguage = value); +// } - void setSelectedLanguageOfInstructions(String? value) { - setState(() => selectedLanguageOfInstructions = value); - } +// void setSelectedLanguageOfInstructions(String? value) { +// setState(() => selectedLanguageOfInstructions = value); +// } - void setSelectedCefrLevel(LanguageLevelTypeEnum? value) { - setState(() => selectedCefrLevel = value); - } +// void setSelectedCefrLevel(LanguageLevelTypeEnum? value) { +// setState(() => selectedCefrLevel = value); +// } - ActivitySettingResponseSchema? get _selectedMode { - return modeItems?.firstWhereOrNull( - (element) => element.name.toLowerCase() == planRequest.mode.toLowerCase(), - ); - } +// ActivitySettingResponseSchema? get _selectedMode { +// return modeItems?.firstWhereOrNull( +// (element) => element.name.toLowerCase() == planRequest.mode.toLowerCase(), +// ); +// } - Future _setTopic() async { - final topic = await TopicListRepo.get(req); +// Future _setTopic() async { +// final topic = await TopicListRepo.get(req); - if (mounted) { - setState(() { - topicItems = topic; - }); - } - } +// if (mounted) { +// setState(() { +// topicItems = topic; +// }); +// } +// } - Future _setMode() async { - final mode = await ActivityModeListRepo.get(req); +// Future _setMode() async { +// final mode = await ActivityModeListRepo.get(req); - if (mounted) { - setState(() { - modeItems = mode; - }); - _setModeImageURL(); - } - } +// if (mounted) { +// setState(() { +// modeItems = mode; +// }); +// _setModeImageURL(); +// } +// } - Future _setObjective() async { - final objective = await LearningObjectiveListRepo.get(req); +// Future _setObjective() async { +// final objective = await LearningObjectiveListRepo.get(req); - if (mounted) { - setState(() { - objectiveItems = objective; - }); - } - } +// if (mounted) { +// setState(() { +// objectiveItems = objective; +// }); +// } +// } - Future _setModeImageURL() async { - final mode = _selectedMode; - if (mode == null) return; +// Future _setModeImageURL() async { +// final mode = _selectedMode; +// if (mode == null) return; - final modeName = - mode.defaultName.toLowerCase().replaceAll(RegExp(r'\s+'), ''); +// final modeName = +// mode.defaultName.toLowerCase().replaceAll(RegExp(r'\s+'), ''); - if (!mounted || activities == null) return; - final imageUrl = - "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.modeImageFileStart}$modeName.jpg"; - setState(() { - filename = imageUrl; - for (ActivityPlanModel activity in activities!) { - activity = ActivityPlanModel( - req: activity.req, - title: activity.title, - learningObjective: activity.learningObjective, - instructions: activity.instructions, - vocab: activity.vocab, - imageURL: imageUrl, - roles: activity.roles, - activityId: activity.activityId, - ); - } - }); - } +// if (!mounted || activities == null) return; +// final imageUrl = +// "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.modeImageFileStart}$modeName.jpg"; +// setState(() { +// filename = imageUrl; +// for (ActivityPlanModel activity in activities!) { +// activity = ActivityPlanModel( +// req: activity.req, +// title: activity.title, +// learningObjective: activity.learningObjective, +// instructions: activity.instructions, +// vocab: activity.vocab, +// imageURL: imageUrl, +// roles: activity.roles, +// activityId: activity.activityId, +// ); +// } +// }); +// } - void clearActivities() { - setState(() { - activities = null; - filename = null; - }); - } +// void clearActivities() { +// setState(() { +// activities = null; +// filename = null; +// }); +// } - Future generate({bool force = false}) async { - setState(() { - loading = true; - error = null; - activities = null; - }); +// Future generate({bool force = false}) async { +// setState(() { +// loading = true; +// error = null; +// activities = null; +// }); - try { - final resp = await ActivityPlanGenerationRepo.get( - planRequest, - force: force, - ); - activities = resp.activityPlans; - await _setModeImageURL(); - } catch (e, s) { - error = e; - ErrorHandler.logError( - e: e, - s: s, - data: { - 'activityPlanRequest': planRequest, - }, - ); - } finally { - if (mounted) setState(() => loading = false); - } - } +// try { +// final resp = await ActivityPlanGenerationRepo.get( +// planRequest, +// force: force, +// ); +// activities = resp.activityPlans; +// await _setModeImageURL(); +// } catch (e, s) { +// error = e; +// ErrorHandler.logError( +// e: e, +// s: s, +// data: { +// 'activityPlanRequest': planRequest, +// }, +// ); +// } finally { +// if (mounted) setState(() => loading = false); +// } +// } - @override - Widget build(BuildContext context) => ActivityGeneratorView(this); -} +// @override +// Widget build(BuildContext context) => ActivityGeneratorView(this); +// } diff --git a/lib/pangea/activity_generator/activity_generator_view.dart b/lib/pangea/activity_generator/activity_generator_view.dart index fd0fb6110..218c1c03b 100644 --- a/lib/pangea/activity_generator/activity_generator_view.dart +++ b/lib/pangea/activity_generator/activity_generator_view.dart @@ -1,309 +1,309 @@ -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:cached_network_image/cached_network_image.dart'; -import 'package:material_symbols_icons/symbols.dart'; +// import 'package:cached_network_image/cached_network_image.dart'; +// import 'package:material_symbols_icons/symbols.dart'; -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_generator/activity_generator.dart'; -import 'package:fluffychat/pangea/activity_generator/activity_plan_card.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; -import 'package:fluffychat/pangea/activity_planner/suggestion_form_field.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; -import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart'; -import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; -import 'package:fluffychat/pangea/instructions/instructions_enum.dart'; -import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'; -import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart'; -import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dropdown.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/config/app_config.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_generator/activity_generator.dart'; +// import 'package:fluffychat/pangea/activity_generator/activity_plan_card.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; +// import 'package:fluffychat/pangea/activity_planner/suggestion_form_field.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; +// import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart'; +// import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; +// import 'package:fluffychat/pangea/instructions/instructions_enum.dart'; +// import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'; +// import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart'; +// import 'package:fluffychat/pangea/learning_settings/widgets/p_language_dropdown.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -class ActivityGeneratorView extends StatelessWidget { - final ActivityGeneratorState controller; +// class ActivityGeneratorView extends StatelessWidget { +// final ActivityGeneratorState controller; - const ActivityGeneratorView( - this.controller, { - super.key, - }); +// const ActivityGeneratorView( +// this.controller, { +// super.key, +// }); - @override - Widget build(BuildContext context) { - final l10n = L10n.of(context); +// @override +// Widget build(BuildContext context) { +// final l10n = L10n.of(context); - if (controller.loading) { - return SafeArea( - child: Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).makeYourOwnActivity), - ), - body: const Padding( - padding: EdgeInsets.all(32.0), - child: Center(child: CircularProgressIndicator()), - ), - ), - ); - } else if (controller.error != null || controller.room == null) { - return SafeArea( - child: Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).makeYourOwnActivity), - ), - body: Center( - child: Column( - spacing: 16.0, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ErrorIndicator( - message: l10n.errorGenerateActivityMessage, - ), - ElevatedButton( - onPressed: controller.generate, - child: Text(l10n.tryAgain), - ), - ], - ), - ), - ), - ); - } else if (controller.activities != null && - controller.activities!.isNotEmpty) { - return SafeArea( - child: ActivityPlannerBuilder( - initialActivity: controller.activities!.first, - initialFilename: controller.filename, - room: controller.room!, - builder: (c) { - return Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).makeYourOwnActivity), - leading: BackButton( - onPressed: () { - c.isLaunching - ? c.setLaunchState(ActivityLaunchState.base) - : controller.clearActivities(); - }, - ), - ), - body: ListView.builder( - padding: const EdgeInsets.all(16), - itemCount: controller.activities!.length, - itemBuilder: (context, index) { - return ActivityPlanCard( - regenerate: () => controller.generate(force: true), - controller: c, - ); - }, - ), - ); - }, - ), - ); - } +// if (controller.loading) { +// return SafeArea( +// child: Scaffold( +// appBar: AppBar( +// title: Text(L10n.of(context).makeYourOwnActivity), +// ), +// body: const Padding( +// padding: EdgeInsets.all(32.0), +// child: Center(child: CircularProgressIndicator()), +// ), +// ), +// ); +// } else if (controller.error != null || controller.room == null) { +// return SafeArea( +// child: Scaffold( +// appBar: AppBar( +// title: Text(L10n.of(context).makeYourOwnActivity), +// ), +// body: Center( +// child: Column( +// spacing: 16.0, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// ErrorIndicator( +// message: l10n.errorGenerateActivityMessage, +// ), +// ElevatedButton( +// onPressed: controller.generate, +// child: Text(l10n.tryAgain), +// ), +// ], +// ), +// ), +// ), +// ); +// } else if (controller.activities != null && +// controller.activities!.isNotEmpty) { +// return SafeArea( +// child: ActivityPlannerBuilder( +// initialActivity: controller.activities!.first, +// initialFilename: controller.filename, +// room: controller.room!, +// builder: (c) { +// return Scaffold( +// appBar: AppBar( +// title: Text(L10n.of(context).makeYourOwnActivity), +// leading: BackButton( +// onPressed: () { +// c.isLaunching +// ? c.setLaunchState(ActivityLaunchState.base) +// : controller.clearActivities(); +// }, +// ), +// ), +// body: ListView.builder( +// padding: const EdgeInsets.all(16), +// itemCount: controller.activities!.length, +// itemBuilder: (context, index) { +// return ActivityPlanCard( +// regenerate: () => controller.generate(force: true), +// controller: c, +// ); +// }, +// ), +// ); +// }, +// ), +// ); +// } - return SafeArea( - child: Scaffold( - appBar: AppBar( - title: Text(L10n.of(context).makeYourOwnActivity), - leading: BackButton( - onPressed: () { - if (controller.activities != null && - controller.activities!.isNotEmpty) { - controller.clearActivities(); - } else { - Navigator.of(context).pop(); - } - }, - ), - ), - body: Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 600), - child: Form( - key: controller.formKey, - child: ListView( - padding: const EdgeInsets.all(16), - children: [ - const InstructionsInlineTooltip( - instructionsEnum: InstructionsEnum.activityPlannerOverview, - ), - Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12.0), - ), - clipBehavior: Clip.hardEdge, - alignment: Alignment.center, - child: ClipRRect( - child: CachedNetworkImage( - fit: BoxFit.cover, - imageUrl: - "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.makeActivityAssetPath}", - placeholder: (context, url) { - return const Center( - child: CircularProgressIndicator(), - ); - }, - errorWidget: (context, url, error) => const SizedBox(), - ), - ), - ), - const SizedBox(height: 16.0), - PLanguageDropdown( - languages: - MatrixState.pangeaController.pLanguageStore.baseOptions, - onChange: (val) => controller - .setSelectedLanguageOfInstructions(val.langCode), - initialLanguage: - controller.selectedLanguageOfInstructions != null - ? PLanguageStore.byLangCode( - controller.selectedLanguageOfInstructions!, - ) - : MatrixState - .pangeaController.languageController.userL1, - isL2List: false, - decorationText: - L10n.of(context).languageOfInstructionsLabel, - ), - const SizedBox(height: 16.0), - PLanguageDropdown( - languages: MatrixState - .pangeaController.pLanguageStore.targetOptions, - onChange: (val) => - controller.setSelectedTargetLanguage(val.langCode), - initialLanguage: controller.selectedTargetLanguage != null - ? PLanguageStore.byLangCode( - controller.selectedTargetLanguage!, - ) - : MatrixState - .pangeaController.languageController.userL2, - decorationText: L10n.of(context).targetLanguageLabel, - isL2List: true, - ), - const SizedBox(height: 16.0), - SuggestionFormField( - suggestions: controller.topicItems, - validator: controller.validateNotNull, - maxLength: 50, - label: l10n.topicLabel, - placeholder: l10n.topicPlaceholder, - controller: controller.topicController, - ), - const SizedBox(height: 16.0), - SuggestionFormField( - suggestions: controller.objectiveItems, - validator: controller.validateNotNull, - maxLength: 140, - label: l10n.learningObjectiveLabel, - placeholder: l10n.learningObjectivePlaceholder, - controller: controller.objectiveController, - ), - const SizedBox(height: 16.0), - SuggestionFormField( - suggestions: controller.modeItems, - validator: controller.validateNotNull, - maxLength: 50, - label: l10n.modeLabel, - placeholder: l10n.modePlaceholder, - controller: controller.modeController, - ), - const SizedBox(height: 16.0), - TextFormField( - decoration: InputDecoration( - labelText: l10n.numberOfLearners, - ), - textInputAction: TextInputAction.done, - validator: (value) { - if (value == null || value.isEmpty) { - return l10n.mustBeInteger; - } - final n = int.tryParse(value); - if (n == null || n <= 0) { - return l10n.mustBeInteger; - } - if (n > 50) { - return l10n.maxFifty; - } - return null; - }, - onChanged: (val) => controller - .setSelectedNumberOfParticipants(int.tryParse(val)), - initialValue: - controller.selectedNumberOfParticipants?.toString(), - onTapOutside: (_) => - FocusManager.instance.primaryFocus?.unfocus(), - onFieldSubmitted: (_) { - if (controller.formKey.currentState?.validate() ?? - false) { - controller.generate(); - } - }, - ), - const SizedBox(height: 16.0), - LanguageLevelDropdown( - onChanged: controller.setSelectedCefrLevel, - initialLevel: controller.selectedCefrLevel, - ), - const SizedBox(height: 16.0), - Row( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.only(right: 8.0), - child: ElevatedButton( - onPressed: controller.clearSelections, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Symbols.reset_focus), - const SizedBox(width: 8), - Text(L10n.of(context).clear), - ], - ), - ), - ), - ), - Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 8.0), - child: ElevatedButton( - onPressed: controller.randomizeEnabled - ? controller.randomizeSelections - : null, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.shuffle), - const SizedBox(width: 8), - Text(L10n.of(context).randomize), - ], - ), - ), - ), - ), - ], - ), - const SizedBox(height: 24.0), - ElevatedButton( - onPressed: () { - if (controller.formKey.currentState?.validate() ?? - false) { - controller.generate(); - } - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.lightbulb_outline), - const SizedBox(width: 8), - Text(l10n.generateActivitiesButton), - ], - ), - ), - ], - ), - ), - ), - ), - ), - ); - } -} +// return SafeArea( +// child: Scaffold( +// appBar: AppBar( +// title: Text(L10n.of(context).makeYourOwnActivity), +// leading: BackButton( +// onPressed: () { +// if (controller.activities != null && +// controller.activities!.isNotEmpty) { +// controller.clearActivities(); +// } else { +// Navigator.of(context).pop(); +// } +// }, +// ), +// ), +// body: Center( +// child: ConstrainedBox( +// constraints: const BoxConstraints(maxWidth: 600), +// child: Form( +// key: controller.formKey, +// child: ListView( +// padding: const EdgeInsets.all(16), +// children: [ +// const InstructionsInlineTooltip( +// instructionsEnum: InstructionsEnum.activityPlannerOverview, +// ), +// Container( +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(12.0), +// ), +// clipBehavior: Clip.hardEdge, +// alignment: Alignment.center, +// child: ClipRRect( +// child: CachedNetworkImage( +// fit: BoxFit.cover, +// imageUrl: +// "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.makeActivityAssetPath}", +// placeholder: (context, url) { +// return const Center( +// child: CircularProgressIndicator(), +// ); +// }, +// errorWidget: (context, url, error) => const SizedBox(), +// ), +// ), +// ), +// const SizedBox(height: 16.0), +// PLanguageDropdown( +// languages: +// MatrixState.pangeaController.pLanguageStore.baseOptions, +// onChange: (val) => controller +// .setSelectedLanguageOfInstructions(val.langCode), +// initialLanguage: +// controller.selectedLanguageOfInstructions != null +// ? PLanguageStore.byLangCode( +// controller.selectedLanguageOfInstructions!, +// ) +// : MatrixState +// .pangeaController.languageController.userL1, +// isL2List: false, +// decorationText: +// L10n.of(context).languageOfInstructionsLabel, +// ), +// const SizedBox(height: 16.0), +// PLanguageDropdown( +// languages: MatrixState +// .pangeaController.pLanguageStore.targetOptions, +// onChange: (val) => +// controller.setSelectedTargetLanguage(val.langCode), +// initialLanguage: controller.selectedTargetLanguage != null +// ? PLanguageStore.byLangCode( +// controller.selectedTargetLanguage!, +// ) +// : MatrixState +// .pangeaController.languageController.userL2, +// decorationText: L10n.of(context).targetLanguageLabel, +// isL2List: true, +// ), +// const SizedBox(height: 16.0), +// SuggestionFormField( +// suggestions: controller.topicItems, +// validator: controller.validateNotNull, +// maxLength: 50, +// label: l10n.topicLabel, +// placeholder: l10n.topicPlaceholder, +// controller: controller.topicController, +// ), +// const SizedBox(height: 16.0), +// SuggestionFormField( +// suggestions: controller.objectiveItems, +// validator: controller.validateNotNull, +// maxLength: 140, +// label: l10n.learningObjectiveLabel, +// placeholder: l10n.learningObjectivePlaceholder, +// controller: controller.objectiveController, +// ), +// const SizedBox(height: 16.0), +// SuggestionFormField( +// suggestions: controller.modeItems, +// validator: controller.validateNotNull, +// maxLength: 50, +// label: l10n.modeLabel, +// placeholder: l10n.modePlaceholder, +// controller: controller.modeController, +// ), +// const SizedBox(height: 16.0), +// TextFormField( +// decoration: InputDecoration( +// labelText: l10n.numberOfLearners, +// ), +// textInputAction: TextInputAction.done, +// validator: (value) { +// if (value == null || value.isEmpty) { +// return l10n.mustBeInteger; +// } +// final n = int.tryParse(value); +// if (n == null || n <= 0) { +// return l10n.mustBeInteger; +// } +// if (n > 50) { +// return l10n.maxFifty; +// } +// return null; +// }, +// onChanged: (val) => controller +// .setSelectedNumberOfParticipants(int.tryParse(val)), +// initialValue: +// controller.selectedNumberOfParticipants?.toString(), +// onTapOutside: (_) => +// FocusManager.instance.primaryFocus?.unfocus(), +// onFieldSubmitted: (_) { +// if (controller.formKey.currentState?.validate() ?? +// false) { +// controller.generate(); +// } +// }, +// ), +// const SizedBox(height: 16.0), +// LanguageLevelDropdown( +// onChanged: controller.setSelectedCefrLevel, +// initialLevel: controller.selectedCefrLevel, +// ), +// const SizedBox(height: 16.0), +// Row( +// children: [ +// Expanded( +// child: Padding( +// padding: const EdgeInsets.only(right: 8.0), +// child: ElevatedButton( +// onPressed: controller.clearSelections, +// child: Row( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// const Icon(Symbols.reset_focus), +// const SizedBox(width: 8), +// Text(L10n.of(context).clear), +// ], +// ), +// ), +// ), +// ), +// Expanded( +// child: Padding( +// padding: const EdgeInsets.only(left: 8.0), +// child: ElevatedButton( +// onPressed: controller.randomizeEnabled +// ? controller.randomizeSelections +// : null, +// child: Row( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// const Icon(Icons.shuffle), +// const SizedBox(width: 8), +// Text(L10n.of(context).randomize), +// ], +// ), +// ), +// ), +// ), +// ], +// ), +// const SizedBox(height: 24.0), +// ElevatedButton( +// onPressed: () { +// if (controller.formKey.currentState?.validate() ?? +// false) { +// controller.generate(); +// } +// }, +// child: Row( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// const Icon(Icons.lightbulb_outline), +// const SizedBox(width: 8), +// Text(l10n.generateActivitiesButton), +// ], +// ), +// ), +// ], +// ), +// ), +// ), +// ), +// ), +// ); +// } +// } diff --git a/lib/pangea/activity_generator/activity_mode_list_repo.dart b/lib/pangea/activity_generator/activity_mode_list_repo.dart index 9aec9588c..d30db5cfd 100644 --- a/lib/pangea/activity_generator/activity_mode_list_repo.dart +++ b/lib/pangea/activity_generator/activity_mode_list_repo.dart @@ -1,56 +1,56 @@ -import 'dart:convert'; +// import 'dart:convert'; -import 'package:get_storage/get_storage.dart'; -import 'package:http/http.dart'; +// import 'package:get_storage/get_storage.dart'; +// import 'package:http/http.dart'; -import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/network/urls.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../common/network/requests.dart'; +// import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; +// import 'package:fluffychat/pangea/common/config/environment.dart'; +// import 'package:fluffychat/pangea/common/network/urls.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; +// import '../common/network/requests.dart'; -class ActivityModeListRepo { - static final GetStorage _modeListStorage = GetStorage('mode_list_storage'); +// class ActivityModeListRepo { +// static final GetStorage _modeListStorage = GetStorage('mode_list_storage'); - static void set( - ActivitySettingRequestSchema request, - List response, - ) { - _modeListStorage.write( - request.storageKey, - response.map((e) => e.toJson()).toList(), - ); - } +// static void set( +// ActivitySettingRequestSchema request, +// List response, +// ) { +// _modeListStorage.write( +// request.storageKey, +// response.map((e) => e.toJson()).toList(), +// ); +// } - static List fromJson(Iterable json) { - return List.from( - json.map((x) => ActivitySettingResponseSchema.fromJson(x)), - ); - } +// static List fromJson(Iterable json) { +// return List.from( +// json.map((x) => ActivitySettingResponseSchema.fromJson(x)), +// ); +// } - static Future> get( - ActivitySettingRequestSchema request, - ) async { - final cachedJson = _modeListStorage.read(request.storageKey); - if (cachedJson != null) { - return ActivityModeListRepo.fromJson(cachedJson); - } +// static Future> get( +// ActivitySettingRequestSchema request, +// ) async { +// final cachedJson = _modeListStorage.read(request.storageKey); +// if (cachedJson != null) { +// return ActivityModeListRepo.fromJson(cachedJson); +// } - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); +// final Requests req = Requests( +// choreoApiKey: Environment.choreoApiKey, +// accessToken: MatrixState.pangeaController.userController.accessToken, +// ); - final Response res = await req.post( - url: PApiUrls.activityModeList, - body: request.toJson(), - ); +// final Response res = await req.post( +// url: PApiUrls.activityModeList, +// body: request.toJson(), +// ); - final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); - final response = ActivityModeListRepo.fromJson(decodedBody); +// final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); +// final response = ActivityModeListRepo.fromJson(decodedBody); - set(request, response); +// set(request, response); - return response; - } -} +// return response; +// } +// } diff --git a/lib/pangea/activity_generator/activity_plan_card.dart b/lib/pangea/activity_generator/activity_plan_card.dart index 67e330eeb..c80880162 100644 --- a/lib/pangea/activity_generator/activity_plan_card.dart +++ b/lib/pangea/activity_generator/activity_plan_card.dart @@ -1,638 +1,638 @@ -// ignore_for_file: depend_on_referenced_packages +// // ignore_for_file: depend_on_referenced_packages -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:cached_network_image/cached_network_image.dart'; -import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart'; -import 'package:go_router/go_router.dart'; -import 'package:material_symbols_icons/symbols.dart'; +// import 'package:cached_network_image/cached_network_image.dart'; +// import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart'; +// import 'package:go_router/go_router.dart'; +// import 'package:material_symbols_icons/symbols.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; -import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart'; -import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart'; -import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; -import 'package:fluffychat/widgets/avatar.dart'; -import 'package:fluffychat/widgets/future_loading_dialog.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/config/themes.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; +// import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart'; +// import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart'; +// import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; +// import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; +// import 'package:fluffychat/widgets/avatar.dart'; +// import 'package:fluffychat/widgets/future_loading_dialog.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -class ActivityPlanCard extends StatelessWidget { - final VoidCallback regenerate; - final ActivityPlannerBuilderState controller; +// class ActivityPlanCard extends StatelessWidget { +// final VoidCallback regenerate; +// final ActivityPlannerBuilderState controller; - const ActivityPlanCard({ - super.key, - required this.regenerate, - required this.controller, - }); +// const ActivityPlanCard({ +// super.key, +// required this.regenerate, +// required this.controller, +// }); - static const double itemPadding = 12; +// static const double itemPadding = 12; - Future _onLaunch(BuildContext context) async { - final resp = await showFutureLoadingDialog( - context: context, - future: () async { - if (!controller.room.isSpace) { - throw Exception( - "Cannot launch activity in a non-space room", - ); - } +// Future _onLaunch(BuildContext context) async { +// final resp = await showFutureLoadingDialog( +// context: context, +// future: () async { +// if (!controller.room.isSpace) { +// throw Exception( +// "Cannot launch activity in a non-space room", +// ); +// } - final ids = await controller.launchToSpace(); - ids.length == 1 - ? context.go("/rooms/spaces/${controller.room.id}/${ids.first}") - : context.go("/rooms/spaces/${controller.room.id}/details"); - Navigator.of(context).pop(); - }, - ); +// final ids = await controller.launchToSpace(); +// ids.length == 1 +// ? context.go("/rooms/spaces/${controller.room.id}/${ids.first}") +// : context.go("/rooms/spaces/${controller.room.id}/details"); +// Navigator.of(context).pop(); +// }, +// ); - if (!resp.isError) { - context.go("/rooms/spaces/${controller.room.id}/details"); - } - } +// if (!resp.isError) { +// context.go("/rooms/spaces/${controller.room.id}/details"); +// } +// } - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final l10n = L10n.of(context); - return Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 400), - child: Card( - margin: const EdgeInsets.symmetric(vertical: itemPadding), - child: Form( - key: controller.formKey, - child: Column( - children: [ - AnimatedSize( - duration: FluffyThemes.animationDuration, - child: Stack( - alignment: Alignment.bottomCenter, - children: [ - Container( - width: 200.0, - padding: const EdgeInsets.all(16.0), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12.0), - ), - clipBehavior: Clip.hardEdge, - alignment: Alignment.center, - child: controller.isLaunching - ? Avatar( - mxContent: controller.room.avatar, - name: controller.room.getLocalizedDisplayname( - MatrixLocals( - L10n.of(context), - ), - ), - borderRadius: BorderRadius.circular(12.0), - size: 200.0, - ) - : controller.imageURL != null || - controller.avatar != null - ? ClipRRect( - borderRadius: BorderRadius.circular(20.0), - child: controller.avatar == null - ? CachedNetworkImage( - fit: BoxFit.cover, - imageUrl: controller.imageURL!, - imageRenderMethodForWeb: - ImageRenderMethodForWeb.HttpGet, - httpHeaders: { - 'Authorization': - 'Bearer ${MatrixState.pangeaController.userController.accessToken}', - }, - placeholder: (context, url) { - return const Center( - child: - CircularProgressIndicator(), - ); - }, - errorWidget: (context, url, error) { - return const Padding( - padding: EdgeInsets.all(28.0), - ); - }, - ) - : Image.memory( - controller.avatar!, - fit: BoxFit.cover, - ), - ) - : const Padding( - padding: EdgeInsets.all(28.0), - ), - ), - if (controller.isEditing) - InkWell( - borderRadius: BorderRadius.circular(90), - onTap: controller.selectAvatar, - child: CircleAvatar( - backgroundColor: - Theme.of(context).colorScheme.secondary, - radius: 20.0, - child: Icon( - Icons.add_a_photo_outlined, - size: 20.0, - color: Theme.of(context).colorScheme.onSecondary, - ), - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: controller.isLaunching - ? [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Avatar( - mxContent: controller.room.avatar, - name: controller.room.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)), - ), - size: 24.0, - borderRadius: BorderRadius.circular(4.0), - ), - const SizedBox(width: itemPadding), - Expanded( - child: Text( - controller.room.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)), - ), - style: - Theme.of(context).textTheme.bodyLarge, - ), - ), - ], - ), - const SizedBox(height: itemPadding), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - ImageByUrl( - imageUrl: controller.updatedActivity.imageURL, - width: 24.0, - borderRadius: BorderRadius.circular(4.0), - replacement: const Icon( - Icons.event_note_outlined, - size: 24.0, - ), - ), - const SizedBox(width: itemPadding), - Expanded( - child: Text( - controller.updatedActivity.title, - style: - Theme.of(context).textTheme.bodyLarge, - ), - ), - ], - ), - const SizedBox(height: itemPadding), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Icon(Icons.groups, size: 24.0), - const SizedBox(width: itemPadding), - Expanded( - child: Text( - L10n.of(context) - .maximumActivityParticipants( - controller.updatedActivity.req - .numberOfParticipants, - ), - style: - Theme.of(context).textTheme.bodyLarge, - ), - ), - ], - ), - const SizedBox(height: itemPadding), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Icon(Icons.radar, size: 24.0), - const SizedBox(width: itemPadding), - Expanded( - child: Column( - spacing: 4.0, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - L10n.of(context).numberOfActivities, - style: Theme.of(context) - .textTheme - .bodyLarge, - ), - NumberCounter( - count: controller.numActivities, - update: controller.setNumActivities, - min: 1, - max: 5, - ), - ], - ), - ), - ], - ), - const SizedBox(height: itemPadding), - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: - theme.colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), - onPressed: () => _onLaunch(context), - child: Row( - children: [ - const Icon(Icons.send_outlined), - Expanded( - child: Text( - L10n.of(context).launchToSpace, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ] - : [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const Icon(Icons.event_note_outlined), - const SizedBox(width: itemPadding), - Expanded( - child: controller.isEditing - ? TextField( - controller: - controller.titleController, - decoration: InputDecoration( - labelText: - L10n.of(context).activityTitle, - ), - maxLines: null, - ) - : Text( - controller.updatedActivity.title, - style: Theme.of(context) - .textTheme - .bodyLarge, - ), - ), - if (!controller.isEditing) - IconButton( - onPressed: - controller.toggleBookmarkedActivity, - icon: Icon( - controller.isBookmarked - ? Icons.save - : Icons.save_outlined, - ), - ), - ], - ), - const SizedBox(height: itemPadding), - Row( - children: [ - Icon( - Symbols.target, - color: - Theme.of(context).colorScheme.secondary, - ), - const SizedBox(width: itemPadding), - Expanded( - child: controller.isEditing - ? TextField( - controller: controller - .learningObjectivesController, - decoration: InputDecoration( - labelText: - l10n.learningObjectiveLabel, - ), - maxLines: null, - ) - : Text( - controller.updatedActivity - .learningObjective, - style: Theme.of(context) - .textTheme - .bodyMedium, - ), - ), - ], - ), - const SizedBox(height: itemPadding), - Row( - children: [ - Icon( - Symbols.steps_rounded, - color: - Theme.of(context).colorScheme.secondary, - ), - const SizedBox(width: itemPadding), - Expanded( - child: controller.isEditing - ? TextField( - controller: - controller.instructionsController, - decoration: InputDecoration( - labelText: l10n.instructions, - ), - maxLines: null, - ) - : Text( - controller - .updatedActivity.instructions, - style: Theme.of(context) - .textTheme - .bodyMedium, - ), - ), - ], - ), - const SizedBox(height: itemPadding), - Row( - children: [ - Icon( - Icons.school_outlined, - color: - Theme.of(context).colorScheme.secondary, - ), - const SizedBox(width: itemPadding), - Expanded( - child: controller.isEditing - ? LanguageLevelDropdown( - initialLevel: - controller.languageLevel, - onChanged: - controller.setLanguageLevel, - ) - : Text( - controller - .updatedActivity.req.cefrLevel - .title(context), - style: Theme.of(context) - .textTheme - .bodyMedium, - ), - ), - ], - ), - const SizedBox(height: itemPadding), - if (controller.vocab.isNotEmpty) ...[ - Row( - children: [ - Icon( - Symbols.dictionary, - color: - Theme.of(context).colorScheme.secondary, - ), - const SizedBox(width: itemPadding), - Expanded( - child: Wrap( - spacing: 4.0, - runSpacing: 4.0, - children: List.generate( - controller.vocab.length, (int index) { - return controller.isEditing - ? Chip( - label: Text( - controller.vocab[index].lemma, - ), - onDeleted: () => controller - .removeVocab(index), - backgroundColor: - Colors.transparent, - visualDensity: - VisualDensity.compact, - shape: const StadiumBorder( - side: BorderSide( - color: Colors.transparent, - ), - ), - ) - : Chip( - label: Text( - controller.vocab[index].lemma, - ), - backgroundColor: - Colors.transparent, - visualDensity: - VisualDensity.compact, - shape: const StadiumBorder( - side: BorderSide( - color: Colors.transparent, - ), - ), - ); - }).toList(), - ), - ), - ], - ), - ], - if (controller.isEditing) ...[ - const SizedBox(height: itemPadding), - Padding( - padding: - const EdgeInsets.only(top: itemPadding), - child: Row( - children: [ - Expanded( - child: TextField( - controller: controller.vocabController, - decoration: InputDecoration( - labelText: l10n.addVocabulary, - ), - onSubmitted: (value) { - controller.addVocab(); - }, - ), - ), - IconButton( - icon: const Icon(Icons.add), - onPressed: controller.addVocab, - ), - ], - ), - ), - const SizedBox(height: itemPadding), - Row( - spacing: 12.0, - children: [ - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), - onPressed: controller.saveEdits, - child: Row( - children: [ - const Icon(Icons.save), - Expanded( - child: Text( - L10n.of(context).save, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), - onPressed: controller.clearEdits, - child: Row( - children: [ - const Icon(Icons.cancel), - Expanded( - child: Text( - L10n.of(context).cancel, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - ], - ), - ] else - Column( - spacing: 12.0, - children: [ - const SizedBox(), - Row( - spacing: 12.0, - children: [ - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: theme - .colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), - onPressed: controller.startEditing, - child: Row( - children: [ - const Icon(Icons.edit), - Expanded( - child: Text( - L10n.of(context).edit, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: theme - .colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), - onPressed: regenerate, - child: Row( - children: [ - const Icon( - Icons.lightbulb_outline, - ), - Expanded( - child: Text( - L10n.of(context).regenerate, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - ], - ), - Row( - children: [ - Expanded( - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: theme - .colorScheme.primaryContainer, - foregroundColor: theme - .colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), - onPressed: () { - controller.setLaunchState( - ActivityLaunchState.launching, - ); - }, - child: Row( - children: [ - const Icon(Icons.save_outlined), - Expanded( - child: Text( - L10n.of(context) - .saveAndLaunch, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - ], - ), - ], - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } -} +// @override +// Widget build(BuildContext context) { +// final theme = Theme.of(context); +// final l10n = L10n.of(context); +// return Center( +// child: ConstrainedBox( +// constraints: const BoxConstraints(maxWidth: 400), +// child: Card( +// margin: const EdgeInsets.symmetric(vertical: itemPadding), +// child: Form( +// key: controller.formKey, +// child: Column( +// children: [ +// AnimatedSize( +// duration: FluffyThemes.animationDuration, +// child: Stack( +// alignment: Alignment.bottomCenter, +// children: [ +// Container( +// width: 200.0, +// padding: const EdgeInsets.all(16.0), +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(12.0), +// ), +// clipBehavior: Clip.hardEdge, +// alignment: Alignment.center, +// child: controller.isLaunching +// ? Avatar( +// mxContent: controller.room.avatar, +// name: controller.room.getLocalizedDisplayname( +// MatrixLocals( +// L10n.of(context), +// ), +// ), +// borderRadius: BorderRadius.circular(12.0), +// size: 200.0, +// ) +// : controller.imageURL != null || +// controller.avatar != null +// ? ClipRRect( +// borderRadius: BorderRadius.circular(20.0), +// child: controller.avatar == null +// ? CachedNetworkImage( +// fit: BoxFit.cover, +// imageUrl: controller.imageURL!, +// imageRenderMethodForWeb: +// ImageRenderMethodForWeb.HttpGet, +// httpHeaders: { +// 'Authorization': +// 'Bearer ${MatrixState.pangeaController.userController.accessToken}', +// }, +// placeholder: (context, url) { +// return const Center( +// child: +// CircularProgressIndicator(), +// ); +// }, +// errorWidget: (context, url, error) { +// return const Padding( +// padding: EdgeInsets.all(28.0), +// ); +// }, +// ) +// : Image.memory( +// controller.avatar!, +// fit: BoxFit.cover, +// ), +// ) +// : const Padding( +// padding: EdgeInsets.all(28.0), +// ), +// ), +// if (controller.isEditing) +// InkWell( +// borderRadius: BorderRadius.circular(90), +// onTap: controller.selectAvatar, +// child: CircleAvatar( +// backgroundColor: +// Theme.of(context).colorScheme.secondary, +// radius: 20.0, +// child: Icon( +// Icons.add_a_photo_outlined, +// size: 20.0, +// color: Theme.of(context).colorScheme.onSecondary, +// ), +// ), +// ), +// ], +// ), +// ), +// Padding( +// padding: const EdgeInsets.all(16), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.start, +// children: controller.isLaunching +// ? [ +// Row( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// Avatar( +// mxContent: controller.room.avatar, +// name: controller.room.getLocalizedDisplayname( +// MatrixLocals(L10n.of(context)), +// ), +// size: 24.0, +// borderRadius: BorderRadius.circular(4.0), +// ), +// const SizedBox(width: itemPadding), +// Expanded( +// child: Text( +// controller.room.getLocalizedDisplayname( +// MatrixLocals(L10n.of(context)), +// ), +// style: +// Theme.of(context).textTheme.bodyLarge, +// ), +// ), +// ], +// ), +// const SizedBox(height: itemPadding), +// Row( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// ImageByUrl( +// imageUrl: controller.updatedActivity.imageURL, +// width: 24.0, +// borderRadius: BorderRadius.circular(4.0), +// replacement: const Icon( +// Icons.event_note_outlined, +// size: 24.0, +// ), +// ), +// const SizedBox(width: itemPadding), +// Expanded( +// child: Text( +// controller.updatedActivity.title, +// style: +// Theme.of(context).textTheme.bodyLarge, +// ), +// ), +// ], +// ), +// const SizedBox(height: itemPadding), +// Row( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// const Icon(Icons.groups, size: 24.0), +// const SizedBox(width: itemPadding), +// Expanded( +// child: Text( +// L10n.of(context) +// .maximumActivityParticipants( +// controller.updatedActivity.req +// .numberOfParticipants, +// ), +// style: +// Theme.of(context).textTheme.bodyLarge, +// ), +// ), +// ], +// ), +// const SizedBox(height: itemPadding), +// Row( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// const Icon(Icons.radar, size: 24.0), +// const SizedBox(width: itemPadding), +// Expanded( +// child: Column( +// spacing: 4.0, +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: +// CrossAxisAlignment.start, +// children: [ +// Text( +// L10n.of(context).numberOfActivities, +// style: Theme.of(context) +// .textTheme +// .bodyLarge, +// ), +// NumberCounter( +// count: controller.numActivities, +// update: controller.setNumActivities, +// min: 1, +// max: 5, +// ), +// ], +// ), +// ), +// ], +// ), +// const SizedBox(height: itemPadding), +// ElevatedButton( +// style: ElevatedButton.styleFrom( +// backgroundColor: +// theme.colorScheme.primaryContainer, +// foregroundColor: +// theme.colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ), +// onPressed: () => _onLaunch(context), +// child: Row( +// children: [ +// const Icon(Icons.send_outlined), +// Expanded( +// child: Text( +// L10n.of(context).launchToSpace, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ] +// : [ +// Row( +// mainAxisAlignment: MainAxisAlignment.start, +// children: [ +// const Icon(Icons.event_note_outlined), +// const SizedBox(width: itemPadding), +// Expanded( +// child: controller.isEditing +// ? TextField( +// controller: +// controller.titleController, +// decoration: InputDecoration( +// labelText: +// L10n.of(context).activityTitle, +// ), +// maxLines: null, +// ) +// : Text( +// controller.updatedActivity.title, +// style: Theme.of(context) +// .textTheme +// .bodyLarge, +// ), +// ), +// if (!controller.isEditing) +// IconButton( +// onPressed: +// controller.toggleBookmarkedActivity, +// icon: Icon( +// controller.isBookmarked +// ? Icons.save +// : Icons.save_outlined, +// ), +// ), +// ], +// ), +// const SizedBox(height: itemPadding), +// Row( +// children: [ +// Icon( +// Symbols.target, +// color: +// Theme.of(context).colorScheme.secondary, +// ), +// const SizedBox(width: itemPadding), +// Expanded( +// child: controller.isEditing +// ? TextField( +// controller: controller +// .learningObjectivesController, +// decoration: InputDecoration( +// labelText: +// l10n.learningObjectiveLabel, +// ), +// maxLines: null, +// ) +// : Text( +// controller.updatedActivity +// .learningObjective, +// style: Theme.of(context) +// .textTheme +// .bodyMedium, +// ), +// ), +// ], +// ), +// const SizedBox(height: itemPadding), +// Row( +// children: [ +// Icon( +// Symbols.steps_rounded, +// color: +// Theme.of(context).colorScheme.secondary, +// ), +// const SizedBox(width: itemPadding), +// Expanded( +// child: controller.isEditing +// ? TextField( +// controller: +// controller.instructionsController, +// decoration: InputDecoration( +// labelText: l10n.instructions, +// ), +// maxLines: null, +// ) +// : Text( +// controller +// .updatedActivity.instructions, +// style: Theme.of(context) +// .textTheme +// .bodyMedium, +// ), +// ), +// ], +// ), +// const SizedBox(height: itemPadding), +// Row( +// children: [ +// Icon( +// Icons.school_outlined, +// color: +// Theme.of(context).colorScheme.secondary, +// ), +// const SizedBox(width: itemPadding), +// Expanded( +// child: controller.isEditing +// ? LanguageLevelDropdown( +// initialLevel: +// controller.languageLevel, +// onChanged: +// controller.setLanguageLevel, +// ) +// : Text( +// controller +// .updatedActivity.req.cefrLevel +// .title(context), +// style: Theme.of(context) +// .textTheme +// .bodyMedium, +// ), +// ), +// ], +// ), +// const SizedBox(height: itemPadding), +// if (controller.vocab.isNotEmpty) ...[ +// Row( +// children: [ +// Icon( +// Symbols.dictionary, +// color: +// Theme.of(context).colorScheme.secondary, +// ), +// const SizedBox(width: itemPadding), +// Expanded( +// child: Wrap( +// spacing: 4.0, +// runSpacing: 4.0, +// children: List.generate( +// controller.vocab.length, (int index) { +// return controller.isEditing +// ? Chip( +// label: Text( +// controller.vocab[index].lemma, +// ), +// onDeleted: () => controller +// .removeVocab(index), +// backgroundColor: +// Colors.transparent, +// visualDensity: +// VisualDensity.compact, +// shape: const StadiumBorder( +// side: BorderSide( +// color: Colors.transparent, +// ), +// ), +// ) +// : Chip( +// label: Text( +// controller.vocab[index].lemma, +// ), +// backgroundColor: +// Colors.transparent, +// visualDensity: +// VisualDensity.compact, +// shape: const StadiumBorder( +// side: BorderSide( +// color: Colors.transparent, +// ), +// ), +// ); +// }).toList(), +// ), +// ), +// ], +// ), +// ], +// if (controller.isEditing) ...[ +// const SizedBox(height: itemPadding), +// Padding( +// padding: +// const EdgeInsets.only(top: itemPadding), +// child: Row( +// children: [ +// Expanded( +// child: TextField( +// controller: controller.vocabController, +// decoration: InputDecoration( +// labelText: l10n.addVocabulary, +// ), +// onSubmitted: (value) { +// controller.addVocab(); +// }, +// ), +// ), +// IconButton( +// icon: const Icon(Icons.add), +// onPressed: controller.addVocab, +// ), +// ], +// ), +// ), +// const SizedBox(height: itemPadding), +// Row( +// spacing: 12.0, +// children: [ +// Expanded( +// child: ElevatedButton( +// style: ElevatedButton.styleFrom( +// backgroundColor: +// theme.colorScheme.primaryContainer, +// foregroundColor: theme +// .colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ), +// onPressed: controller.saveEdits, +// child: Row( +// children: [ +// const Icon(Icons.save), +// Expanded( +// child: Text( +// L10n.of(context).save, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// Expanded( +// child: ElevatedButton( +// style: ElevatedButton.styleFrom( +// backgroundColor: +// theme.colorScheme.primaryContainer, +// foregroundColor: theme +// .colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ), +// onPressed: controller.clearEdits, +// child: Row( +// children: [ +// const Icon(Icons.cancel), +// Expanded( +// child: Text( +// L10n.of(context).cancel, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ), +// ] else +// Column( +// spacing: 12.0, +// children: [ +// const SizedBox(), +// Row( +// spacing: 12.0, +// children: [ +// Expanded( +// child: ElevatedButton( +// style: ElevatedButton.styleFrom( +// backgroundColor: theme +// .colorScheme.primaryContainer, +// foregroundColor: theme +// .colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ), +// onPressed: controller.startEditing, +// child: Row( +// children: [ +// const Icon(Icons.edit), +// Expanded( +// child: Text( +// L10n.of(context).edit, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// Expanded( +// child: ElevatedButton( +// style: ElevatedButton.styleFrom( +// backgroundColor: theme +// .colorScheme.primaryContainer, +// foregroundColor: theme +// .colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ), +// onPressed: regenerate, +// child: Row( +// children: [ +// const Icon( +// Icons.lightbulb_outline, +// ), +// Expanded( +// child: Text( +// L10n.of(context).regenerate, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ), +// Row( +// children: [ +// Expanded( +// child: ElevatedButton( +// style: ElevatedButton.styleFrom( +// backgroundColor: theme +// .colorScheme.primaryContainer, +// foregroundColor: theme +// .colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ), +// onPressed: () { +// controller.setLaunchState( +// ActivityLaunchState.launching, +// ); +// }, +// child: Row( +// children: [ +// const Icon(Icons.save_outlined), +// Expanded( +// child: Text( +// L10n.of(context) +// .saveAndLaunch, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ), +// ], +// ), +// ], +// ), +// ), +// ], +// ), +// ), +// ), +// ), +// ); +// } +// } diff --git a/lib/pangea/activity_generator/activity_plan_generation_repo.dart b/lib/pangea/activity_generator/activity_plan_generation_repo.dart index 261b41a20..5c6bc1160 100644 --- a/lib/pangea/activity_generator/activity_plan_generation_repo.dart +++ b/lib/pangea/activity_generator/activity_plan_generation_repo.dart @@ -1,49 +1,49 @@ -import 'dart:convert'; +// import 'dart:convert'; -import 'package:get_storage/get_storage.dart'; -import 'package:http/http.dart'; +// import 'package:get_storage/get_storage.dart'; +// import 'package:http/http.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_response.dart'; -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/network/urls.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../common/network/requests.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_response.dart'; +// import 'package:fluffychat/pangea/common/config/environment.dart'; +// import 'package:fluffychat/pangea/common/network/urls.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; +// import '../common/network/requests.dart'; -class ActivityPlanGenerationRepo { - static final GetStorage _activityPlanStorage = - GetStorage('activity_plan_storage'); +// class ActivityPlanGenerationRepo { +// static final GetStorage _activityPlanStorage = +// GetStorage('activity_plan_storage'); - static void set(ActivityPlanRequest request, ActivityPlanResponse response) { - _activityPlanStorage.write(request.storageKey, response.toJson()); - } +// static void set(ActivityPlanRequest request, ActivityPlanResponse response) { +// _activityPlanStorage.write(request.storageKey, response.toJson()); +// } - static Future get( - ActivityPlanRequest request, { - bool force = false, - }) async { - final cachedJson = _activityPlanStorage.read(request.storageKey); - if (cachedJson != null && !force) { - final cached = ActivityPlanResponse.fromJson(cachedJson); +// static Future get( +// ActivityPlanRequest request, { +// bool force = false, +// }) async { +// final cachedJson = _activityPlanStorage.read(request.storageKey); +// if (cachedJson != null && !force) { +// final cached = ActivityPlanResponse.fromJson(cachedJson); - return cached; - } +// return cached; +// } - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); +// final Requests req = Requests( +// choreoApiKey: Environment.choreoApiKey, +// accessToken: MatrixState.pangeaController.userController.accessToken, +// ); - final Response res = await req.post( - url: PApiUrls.activityPlanGeneration, - body: request.toJson(), - ); +// final Response res = await req.post( +// url: PApiUrls.activityPlanGeneration, +// body: request.toJson(), +// ); - final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); - final response = ActivityPlanResponse.fromJson(decodedBody); +// final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); +// final response = ActivityPlanResponse.fromJson(decodedBody); - set(request, response); +// set(request, response); - return response; - } -} +// return response; +// } +// } diff --git a/lib/pangea/activity_generator/learning_objective_list_repo.dart b/lib/pangea/activity_generator/learning_objective_list_repo.dart index 2f88256cd..c289287cd 100644 --- a/lib/pangea/activity_generator/learning_objective_list_repo.dart +++ b/lib/pangea/activity_generator/learning_objective_list_repo.dart @@ -1,57 +1,57 @@ -import 'dart:convert'; +// import 'dart:convert'; -import 'package:get_storage/get_storage.dart'; -import 'package:http/http.dart'; +// import 'package:get_storage/get_storage.dart'; +// import 'package:http/http.dart'; -import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/network/urls.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../common/network/requests.dart'; +// import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; +// import 'package:fluffychat/pangea/common/config/environment.dart'; +// import 'package:fluffychat/pangea/common/network/urls.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; +// import '../common/network/requests.dart'; -class LearningObjectiveListRepo { - static final GetStorage _objectiveListStorage = - GetStorage('objective_list_storage'); +// class LearningObjectiveListRepo { +// static final GetStorage _objectiveListStorage = +// GetStorage('objective_list_storage'); - static void set( - ActivitySettingRequestSchema request, - List response, - ) { - _objectiveListStorage.write( - request.storageKey, - response.map((e) => e.toJson()).toList(), - ); - } +// static void set( +// ActivitySettingRequestSchema request, +// List response, +// ) { +// _objectiveListStorage.write( +// request.storageKey, +// response.map((e) => e.toJson()).toList(), +// ); +// } - static List fromJson(Iterable json) { - return List.from( - json.map((x) => ActivitySettingResponseSchema.fromJson(x)), - ); - } +// static List fromJson(Iterable json) { +// return List.from( +// json.map((x) => ActivitySettingResponseSchema.fromJson(x)), +// ); +// } - static Future> get( - ActivitySettingRequestSchema request, - ) async { - final cachedJson = _objectiveListStorage.read(request.storageKey); - if (cachedJson != null) { - return LearningObjectiveListRepo.fromJson(cachedJson); - } +// static Future> get( +// ActivitySettingRequestSchema request, +// ) async { +// final cachedJson = _objectiveListStorage.read(request.storageKey); +// if (cachedJson != null) { +// return LearningObjectiveListRepo.fromJson(cachedJson); +// } - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); +// final Requests req = Requests( +// choreoApiKey: Environment.choreoApiKey, +// accessToken: MatrixState.pangeaController.userController.accessToken, +// ); - final Response res = await req.post( - url: PApiUrls.objectiveList, - body: request.toJson(), - ); +// final Response res = await req.post( +// url: PApiUrls.objectiveList, +// body: request.toJson(), +// ); - final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); - final response = LearningObjectiveListRepo.fromJson(decodedBody); +// final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); +// final response = LearningObjectiveListRepo.fromJson(decodedBody); - set(request, response); +// set(request, response); - return response; - } -} +// return response; +// } +// } diff --git a/lib/pangea/activity_generator/list_request_schema.dart b/lib/pangea/activity_generator/list_request_schema.dart index d3034820b..bc960b02d 100644 --- a/lib/pangea/activity_generator/list_request_schema.dart +++ b/lib/pangea/activity_generator/list_request_schema.dart @@ -1,37 +1,37 @@ -class ActivitySettingRequestSchema { - final String langCode; +// class ActivitySettingRequestSchema { +// final String langCode; - ActivitySettingRequestSchema({required this.langCode}); +// ActivitySettingRequestSchema({required this.langCode}); - Map toJson() { - return { - 'lang_code': langCode, - }; - } +// Map toJson() { +// return { +// 'lang_code': langCode, +// }; +// } - String get storageKey => 'topic_list-$langCode'; -} +// String get storageKey => 'topic_list-$langCode'; +// } -class ActivitySettingResponseSchema { - final String defaultName; - final String name; +// class ActivitySettingResponseSchema { +// final String defaultName; +// final String name; - ActivitySettingResponseSchema({ - required this.defaultName, - required this.name, - }); +// ActivitySettingResponseSchema({ +// required this.defaultName, +// required this.name, +// }); - factory ActivitySettingResponseSchema.fromJson(Map json) { - return ActivitySettingResponseSchema( - defaultName: json['default_name'], - name: json['name'], - ); - } +// factory ActivitySettingResponseSchema.fromJson(Map json) { +// return ActivitySettingResponseSchema( +// defaultName: json['default_name'], +// name: json['name'], +// ); +// } - Map toJson() { - return { - 'default_name': defaultName, - 'name': name, - }; - } -} +// Map toJson() { +// return { +// 'default_name': defaultName, +// 'name': name, +// }; +// } +// } diff --git a/lib/pangea/activity_generator/topic_list_repo.dart b/lib/pangea/activity_generator/topic_list_repo.dart index 3642a6ccc..efe3f6411 100644 --- a/lib/pangea/activity_generator/topic_list_repo.dart +++ b/lib/pangea/activity_generator/topic_list_repo.dart @@ -1,56 +1,56 @@ -import 'dart:convert'; +// import 'dart:convert'; -import 'package:get_storage/get_storage.dart'; -import 'package:http/http.dart'; +// import 'package:get_storage/get_storage.dart'; +// import 'package:http/http.dart'; -import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/network/urls.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../common/network/requests.dart'; +// import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; +// import 'package:fluffychat/pangea/common/config/environment.dart'; +// import 'package:fluffychat/pangea/common/network/urls.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; +// import '../common/network/requests.dart'; -class TopicListRepo { - static final GetStorage _topicListStorage = GetStorage('topic_list_storage'); +// class TopicListRepo { +// static final GetStorage _topicListStorage = GetStorage('topic_list_storage'); - static void set( - ActivitySettingRequestSchema request, - List response, - ) { - _topicListStorage.write( - request.storageKey, - response.map((e) => e.toJson()).toList(), - ); - } +// static void set( +// ActivitySettingRequestSchema request, +// List response, +// ) { +// _topicListStorage.write( +// request.storageKey, +// response.map((e) => e.toJson()).toList(), +// ); +// } - static List fromJson(Iterable json) { - return List.from( - json.map((x) => ActivitySettingResponseSchema.fromJson(x)), - ); - } +// static List fromJson(Iterable json) { +// return List.from( +// json.map((x) => ActivitySettingResponseSchema.fromJson(x)), +// ); +// } - static Future> get( - ActivitySettingRequestSchema request, - ) async { - final cachedJson = _topicListStorage.read(request.storageKey); - if (cachedJson != null) { - return TopicListRepo.fromJson(cachedJson); - } +// static Future> get( +// ActivitySettingRequestSchema request, +// ) async { +// final cachedJson = _topicListStorage.read(request.storageKey); +// if (cachedJson != null) { +// return TopicListRepo.fromJson(cachedJson); +// } - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); +// final Requests req = Requests( +// choreoApiKey: Environment.choreoApiKey, +// accessToken: MatrixState.pangeaController.userController.accessToken, +// ); - final Response res = await req.post( - url: PApiUrls.topicList, - body: request.toJson(), - ); +// final Response res = await req.post( +// url: PApiUrls.topicList, +// body: request.toJson(), +// ); - final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); - final response = TopicListRepo.fromJson(decodedBody); +// final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); +// final response = TopicListRepo.fromJson(decodedBody); - set(request, response); +// set(request, response); - return response; - } -} +// return response; +// } +// } diff --git a/lib/pangea/activity_planner/activity_plan_message.dart b/lib/pangea/activity_planner/activity_plan_message.dart index abbe6d6a7..13959452f 100644 --- a/lib/pangea/activity_planner/activity_plan_message.dart +++ b/lib/pangea/activity_planner/activity_plan_message.dart @@ -1,286 +1,286 @@ -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; -import 'package:swipe_to_action/swipe_to_action.dart'; +// import 'package:matrix/matrix.dart'; +// import 'package:swipe_to_action/swipe_to_action.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/pages/chat/chat.dart'; -import 'package:fluffychat/pages/chat/events/message_content.dart'; -import 'package:fluffychat/pages/chat/events/pangea_message_reactions.dart'; -import 'package:fluffychat/utils/date_time_extension.dart'; -import 'package:fluffychat/widgets/matrix.dart'; -import '../../../config/app_config.dart'; +// import 'package:fluffychat/config/themes.dart'; +// import 'package:fluffychat/pages/chat/chat.dart'; +// import 'package:fluffychat/pages/chat/events/message_content.dart'; +// import 'package:fluffychat/pages/chat/events/pangea_message_reactions.dart'; +// import 'package:fluffychat/utils/date_time_extension.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; +// import '../../../config/app_config.dart'; -class ActivityPlanMessage extends StatelessWidget { - final Event event; - final Timeline timeline; - final bool animateIn; - final void Function()? resetAnimateIn; - final ChatController controller; - final bool highlightMarker; - final bool selected; +// class ActivityPlanMessage extends StatelessWidget { +// final Event event; +// final Timeline timeline; +// final bool animateIn; +// final void Function()? resetAnimateIn; +// final ChatController controller; +// final bool highlightMarker; +// final bool selected; - const ActivityPlanMessage( - this.event, { - required this.timeline, - required this.controller, - required this.selected, - this.animateIn = false, - this.resetAnimateIn, - this.highlightMarker = false, - super.key, - }); +// const ActivityPlanMessage( +// this.event, { +// required this.timeline, +// required this.controller, +// required this.selected, +// this.animateIn = false, +// this.resetAnimateIn, +// this.highlightMarker = false, +// super.key, +// }); - @override - Widget build(BuildContext context) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (controller.pangeaEditingEvent?.eventId == event.eventId) { - controller.clearEditingEvent(); - } - }); +// @override +// Widget build(BuildContext context) { +// WidgetsBinding.instance.addPostFrameCallback((_) { +// if (controller.pangeaEditingEvent?.eventId == event.eventId) { +// controller.clearEditingEvent(); +// } +// }); - final theme = Theme.of(context); - final color = theme.brightness == Brightness.dark - ? theme.colorScheme.onSecondary - : theme.colorScheme.primary; - final textColor = ThemeData.light().colorScheme.onPrimary; +// final theme = Theme.of(context); +// final color = theme.brightness == Brightness.dark +// ? theme.colorScheme.onSecondary +// : theme.colorScheme.primary; +// final textColor = ThemeData.light().colorScheme.onPrimary; - final displayEvent = event.getDisplayEvent(timeline); - const roundedCorner = Radius.circular(AppConfig.borderRadius); - const borderRadius = BorderRadius.all(roundedCorner); +// final displayEvent = event.getDisplayEvent(timeline); +// const roundedCorner = Radius.circular(AppConfig.borderRadius); +// const borderRadius = BorderRadius.all(roundedCorner); - final resetAnimateIn = this.resetAnimateIn; - var animateIn = this.animateIn; +// final resetAnimateIn = this.resetAnimateIn; +// var animateIn = this.animateIn; - final row = StatefulBuilder( - builder: (context, setState) { - if (animateIn && resetAnimateIn != null) { - WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - animateIn = false; - if (context.mounted) { - setState(resetAnimateIn); - } - }); - } - return AnimatedSize( - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - clipBehavior: Clip.none, - alignment: Alignment.bottomLeft, - child: animateIn - ? const SizedBox(height: 0, width: double.infinity) - : Stack( - children: [ - Positioned( - top: 0, - bottom: 0, - left: 0, - right: 0, - child: InkWell( - onTap: () => controller.showToolbar(event), - onLongPress: () => controller.showToolbar(event), - borderRadius: - BorderRadius.circular(AppConfig.borderRadius / 2), - child: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius / 2), - color: highlightMarker - ? theme.colorScheme.secondaryContainer - .withAlpha(128) - : Colors.transparent, - ), - ), - ), - Container( - alignment: Alignment.center, - child: GestureDetector( - onTap: () => controller.showToolbar(event), - onLongPress: () => controller.showToolbar(event), - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - AnimatedOpacity( - opacity: animateIn - ? 0 - : event.messageType == - MessageTypes.BadEncrypted || - event.status.isSending - ? 0.5 - : 1, - duration: FluffyThemes.animationDuration, - curve: FluffyThemes.animationCurve, - child: Container( - decoration: BoxDecoration( - color: color, - borderRadius: borderRadius, - ), - clipBehavior: Clip.antiAlias, - child: CompositedTransformTarget( - link: MatrixState.pAnyState - .layerLinkAndKey( - event.eventId, - ) - .link, - child: Container( - key: MatrixState.pAnyState - .layerLinkAndKey( - event.eventId, - ) - .key, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular( - AppConfig.borderRadius, - ), - ), - constraints: const BoxConstraints( - maxWidth: FluffyThemes.columnWidth * 1.5, - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - MessageContent( - displayEvent, - textColor: textColor, - borderRadius: borderRadius, - controller: controller, - immersionMode: false, - timeline: timeline, - linkColor: theme.brightness == - Brightness.light - ? theme.colorScheme.primary - : theme.colorScheme.onPrimary, - selected: selected, - ), - if (event.hasAggregatedEvents( - timeline, - RelationshipTypes.edit, - )) - Padding( - padding: const EdgeInsets.only( - top: 4.0, - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (event.hasAggregatedEvents( - timeline, - RelationshipTypes.edit, - )) ...[ - Icon( - Icons.edit_outlined, - color: textColor - .withAlpha(164), - size: 14, - ), - Text( - ' - ${displayEvent.originServerTs.localizedTimeShort(context)}', - style: TextStyle( - color: - textColor.withAlpha( - 164, - ), - fontSize: 12, - ), - ), - ], - ], - ), - ), - ], - ), - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.only( - top: 4.0, - right: 4.0, - ), - child: PangeaMessageReactions( - event, - timeline, - controller, - ), - ), - ], - ), - ), - ), - ], - ), - ); - }, - ); +// final row = StatefulBuilder( +// builder: (context, setState) { +// if (animateIn && resetAnimateIn != null) { +// WidgetsBinding.instance.addPostFrameCallback((timeStamp) { +// animateIn = false; +// if (context.mounted) { +// setState(resetAnimateIn); +// } +// }); +// } +// return AnimatedSize( +// duration: FluffyThemes.animationDuration, +// curve: FluffyThemes.animationCurve, +// clipBehavior: Clip.none, +// alignment: Alignment.bottomLeft, +// child: animateIn +// ? const SizedBox(height: 0, width: double.infinity) +// : Stack( +// children: [ +// Positioned( +// top: 0, +// bottom: 0, +// left: 0, +// right: 0, +// child: InkWell( +// onTap: () => controller.showToolbar(event), +// onLongPress: () => controller.showToolbar(event), +// borderRadius: +// BorderRadius.circular(AppConfig.borderRadius / 2), +// child: Material( +// borderRadius: +// BorderRadius.circular(AppConfig.borderRadius / 2), +// color: highlightMarker +// ? theme.colorScheme.secondaryContainer +// .withAlpha(128) +// : Colors.transparent, +// ), +// ), +// ), +// Container( +// alignment: Alignment.center, +// child: GestureDetector( +// onTap: () => controller.showToolbar(event), +// onLongPress: () => controller.showToolbar(event), +// child: Column( +// crossAxisAlignment: CrossAxisAlignment.end, +// children: [ +// AnimatedOpacity( +// opacity: animateIn +// ? 0 +// : event.messageType == +// MessageTypes.BadEncrypted || +// event.status.isSending +// ? 0.5 +// : 1, +// duration: FluffyThemes.animationDuration, +// curve: FluffyThemes.animationCurve, +// child: Container( +// decoration: BoxDecoration( +// color: color, +// borderRadius: borderRadius, +// ), +// clipBehavior: Clip.antiAlias, +// child: CompositedTransformTarget( +// link: MatrixState.pAnyState +// .layerLinkAndKey( +// event.eventId, +// ) +// .link, +// child: Container( +// key: MatrixState.pAnyState +// .layerLinkAndKey( +// event.eventId, +// ) +// .key, +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular( +// AppConfig.borderRadius, +// ), +// ), +// constraints: const BoxConstraints( +// maxWidth: FluffyThemes.columnWidth * 1.5, +// ), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: +// CrossAxisAlignment.start, +// children: [ +// MessageContent( +// displayEvent, +// textColor: textColor, +// borderRadius: borderRadius, +// controller: controller, +// immersionMode: false, +// timeline: timeline, +// linkColor: theme.brightness == +// Brightness.light +// ? theme.colorScheme.primary +// : theme.colorScheme.onPrimary, +// selected: selected, +// ), +// if (event.hasAggregatedEvents( +// timeline, +// RelationshipTypes.edit, +// )) +// Padding( +// padding: const EdgeInsets.only( +// top: 4.0, +// ), +// child: Row( +// mainAxisSize: MainAxisSize.min, +// children: [ +// if (event.hasAggregatedEvents( +// timeline, +// RelationshipTypes.edit, +// )) ...[ +// Icon( +// Icons.edit_outlined, +// color: textColor +// .withAlpha(164), +// size: 14, +// ), +// Text( +// ' - ${displayEvent.originServerTs.localizedTimeShort(context)}', +// style: TextStyle( +// color: +// textColor.withAlpha( +// 164, +// ), +// fontSize: 12, +// ), +// ), +// ], +// ], +// ), +// ), +// ], +// ), +// ), +// ), +// ), +// ), +// Padding( +// padding: const EdgeInsets.only( +// top: 4.0, +// right: 4.0, +// ), +// child: PangeaMessageReactions( +// event, +// timeline, +// controller, +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ), +// ); +// }, +// ); - Widget container; +// Widget container; - container = Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (event.messageType == MessageTypes.Text) - Padding( - padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Center( - child: Padding( - padding: const EdgeInsets.only(top: 4.0), - child: Material( - borderRadius: - BorderRadius.circular(AppConfig.borderRadius * 2), - color: theme.colorScheme.surface.withAlpha(128), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 2.0, - ), - child: Text( - event.originServerTs.localizedTime(context), - style: TextStyle( - fontSize: 12 * AppConfig.fontSizeFactor, - fontWeight: FontWeight.bold, - color: theme.colorScheme.secondary, - ), - ), - ), - ), - ), - ), - ), - row, - ], - ); +// container = Column( +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// if (event.messageType == MessageTypes.Text) +// Padding( +// padding: const EdgeInsets.symmetric(vertical: 8.0), +// child: Center( +// child: Padding( +// padding: const EdgeInsets.only(top: 4.0), +// child: Material( +// borderRadius: +// BorderRadius.circular(AppConfig.borderRadius * 2), +// color: theme.colorScheme.surface.withAlpha(128), +// child: Padding( +// padding: const EdgeInsets.symmetric( +// horizontal: 8.0, +// vertical: 2.0, +// ), +// child: Text( +// event.originServerTs.localizedTime(context), +// style: TextStyle( +// fontSize: 12 * AppConfig.fontSizeFactor, +// fontWeight: FontWeight.bold, +// color: theme.colorScheme.secondary, +// ), +// ), +// ), +// ), +// ), +// ), +// ), +// row, +// ], +// ); - container = Material(type: MaterialType.transparency, child: container); +// container = Material(type: MaterialType.transparency, child: container); - return Center( - child: Swipeable( - key: ValueKey(event.eventId), - background: const Padding( - padding: EdgeInsets.symmetric(horizontal: 12.0), - child: Center( - child: Icon(Icons.check_outlined), - ), - ), - direction: AppConfig.swipeRightToLeftToReply - ? SwipeDirection.endToStart - : SwipeDirection.startToEnd, - onSwipe: (_) {}, - child: Container( - constraints: const BoxConstraints( - maxWidth: FluffyThemes.maxTimelineWidth, - ), - padding: const EdgeInsets.only( - left: 8.0, - right: 8.0, - top: 4.0, - bottom: 4.0, - ), - child: container, - ), - ), - ); - } -} +// return Center( +// child: Swipeable( +// key: ValueKey(event.eventId), +// background: const Padding( +// padding: EdgeInsets.symmetric(horizontal: 12.0), +// child: Center( +// child: Icon(Icons.check_outlined), +// ), +// ), +// direction: AppConfig.swipeRightToLeftToReply +// ? SwipeDirection.endToStart +// : SwipeDirection.startToEnd, +// onSwipe: (_) {}, +// child: Container( +// constraints: const BoxConstraints( +// maxWidth: FluffyThemes.maxTimelineWidth, +// ), +// padding: const EdgeInsets.only( +// left: 8.0, +// right: 8.0, +// top: 4.0, +// bottom: 4.0, +// ), +// child: container, +// ), +// ), +// ); +// } +// } diff --git a/lib/pangea/activity_planner/activity_plan_model.dart b/lib/pangea/activity_planner/activity_plan_model.dart index d284557db..a73ba1b48 100644 --- a/lib/pangea/activity_planner/activity_plan_model.dart +++ b/lib/pangea/activity_planner/activity_plan_model.dart @@ -49,32 +49,6 @@ class ActivityPlanModel { return defaultRoles; } - ActivityPlanModel copyWith({ - String? title, - String? description, - String? learningObjective, - String? instructions, - List? vocab, - String? imageURL, - DateTime? endAt, - Duration? duration, - Map? roles, - }) { - return ActivityPlanModel( - req: req, - title: title ?? this.title, - description: description ?? this.description, - learningObjective: learningObjective ?? this.learningObjective, - instructions: instructions ?? this.instructions, - vocab: vocab ?? this.vocab, - imageURL: imageURL ?? this.imageURL, - endAt: endAt ?? this.endAt, - duration: duration ?? this.duration, - roles: roles ?? _roles, - activityId: activityId, - ); - } - factory ActivityPlanModel.fromJson(Map json) { final req = ActivityPlanRequest.fromJson(json[ModelKey.activityPlanRequest]); diff --git a/lib/pangea/activity_planner/activity_plan_response.dart b/lib/pangea/activity_planner/activity_plan_response.dart index d0c216ef0..08b0bb36f 100644 --- a/lib/pangea/activity_planner/activity_plan_response.dart +++ b/lib/pangea/activity_planner/activity_plan_response.dart @@ -1,21 +1,21 @@ -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -class ActivityPlanResponse { - final List activityPlans; +// class ActivityPlanResponse { +// final List activityPlans; - ActivityPlanResponse({required this.activityPlans}); +// ActivityPlanResponse({required this.activityPlans}); - factory ActivityPlanResponse.fromJson(Map json) { - return ActivityPlanResponse( - activityPlans: (json['activity_plans'] as List) - .map((e) => ActivityPlanModel.fromJson(e)) - .toList(), - ); - } +// factory ActivityPlanResponse.fromJson(Map json) { +// return ActivityPlanResponse( +// activityPlans: (json['activity_plans'] as List) +// .map((e) => ActivityPlanModel.fromJson(e)) +// .toList(), +// ); +// } - Map toJson() { - return { - 'activity_plans': activityPlans.map((e) => e.toJson()).toList(), - }; - } -} +// Map toJson() { +// return { +// 'activity_plans': activityPlans.map((e) => e.toJson()).toList(), +// }; +// } +// } diff --git a/lib/pangea/activity_planner/activity_planner_builder.dart b/lib/pangea/activity_planner/activity_planner_builder.dart index a6d14fb01..94cbf5093 100644 --- a/lib/pangea/activity_planner/activity_planner_builder.dart +++ b/lib/pangea/activity_planner/activity_planner_builder.dart @@ -1,420 +1,420 @@ -import 'dart:async'; +// import 'dart:async'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart' hide Visibility; +// import 'package:flutter/foundation.dart'; +// import 'package:flutter/material.dart' hide Visibility; -import 'package:collection/collection.dart'; -import 'package:http/http.dart' as http; -import 'package:http/http.dart'; -import 'package:matrix/matrix.dart'; +// import 'package:collection/collection.dart'; +// import 'package:http/http.dart' as http; +// import 'package:http/http.dart'; +// import 'package:matrix/matrix.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_plan_repo.dart'; -import 'package:fluffychat/pangea/chat/constants/default_power_level.dart'; -import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; -import 'package:fluffychat/pangea/extensions/join_rule_extension.dart'; -import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; -import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; -import 'package:fluffychat/pangea/user/controllers/user_controller.dart'; -import 'package:fluffychat/utils/client_download_content_extension.dart'; -import 'package:fluffychat/utils/file_selector.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_plan_repo.dart'; +// import 'package:fluffychat/pangea/chat/constants/default_power_level.dart'; +// import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart'; +// import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +// import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; +// import 'package:fluffychat/pangea/extensions/join_rule_extension.dart'; +// import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; +// import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; +// import 'package:fluffychat/pangea/user/controllers/user_controller.dart'; +// import 'package:fluffychat/utils/client_download_content_extension.dart'; +// import 'package:fluffychat/utils/file_selector.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -enum ActivityLaunchState { - base, - editing, - launching, -} +// enum ActivityLaunchState { +// base, +// editing, +// launching, +// } -class ActivityPlannerBuilder extends StatefulWidget { - final ActivityPlanModel initialActivity; - final String? initialFilename; - final Room room; +// class ActivityPlannerBuilder extends StatefulWidget { +// final ActivityPlanModel initialActivity; +// final String? initialFilename; +// final Room room; - final bool enabledEdits; - final bool enableMultiLaunch; +// final bool enabledEdits; +// final bool enableMultiLaunch; - final Widget Function(ActivityPlannerBuilderState) builder; +// final Widget Function(ActivityPlannerBuilderState) builder; - const ActivityPlannerBuilder({ - super.key, - required this.initialActivity, - this.initialFilename, - required this.room, - required this.builder, - this.enabledEdits = false, - this.enableMultiLaunch = false, - }); +// const ActivityPlannerBuilder({ +// super.key, +// required this.initialActivity, +// this.initialFilename, +// required this.room, +// required this.builder, +// this.enabledEdits = false, +// this.enableMultiLaunch = false, +// }); - @override - State createState() => ActivityPlannerBuilderState(); -} +// @override +// State createState() => ActivityPlannerBuilderState(); +// } -class ActivityPlannerBuilderState extends State { - ActivityLaunchState launchState = ActivityLaunchState.base; - Uint8List? avatar; - String? imageURL; - String? filename; +// class ActivityPlannerBuilderState extends State { +// ActivityLaunchState launchState = ActivityLaunchState.base; +// Uint8List? avatar; +// String? imageURL; +// String? filename; - int numActivities = 1; +// int numActivities = 1; - final TextEditingController titleController = TextEditingController(); - final TextEditingController instructionsController = TextEditingController(); - final TextEditingController vocabController = TextEditingController(); - final TextEditingController participantsController = TextEditingController(); - final TextEditingController learningObjectivesController = - TextEditingController(); +// final TextEditingController titleController = TextEditingController(); +// final TextEditingController instructionsController = TextEditingController(); +// final TextEditingController vocabController = TextEditingController(); +// final TextEditingController participantsController = TextEditingController(); +// final TextEditingController learningObjectivesController = +// TextEditingController(); - final List vocab = []; - late LanguageLevelTypeEnum languageLevel; +// final List vocab = []; +// late LanguageLevelTypeEnum languageLevel; - final GlobalKey formKey = GlobalKey(); +// final GlobalKey formKey = GlobalKey(); - final StreamController stateStream = StreamController.broadcast(); +// final StreamController stateStream = StreamController.broadcast(); - @override - void initState() { - super.initState(); - resetActivity(); - } +// @override +// void initState() { +// super.initState(); +// resetActivity(); +// } - @override - void dispose() { - titleController.dispose(); - learningObjectivesController.dispose(); - instructionsController.dispose(); - vocabController.dispose(); - participantsController.dispose(); - stateStream.close(); - super.dispose(); - } +// @override +// void dispose() { +// titleController.dispose(); +// learningObjectivesController.dispose(); +// instructionsController.dispose(); +// vocabController.dispose(); +// participantsController.dispose(); +// stateStream.close(); +// super.dispose(); +// } - void update() { - if (mounted) setState(() {}); - if (!stateStream.isClosed) { - stateStream.add(null); - } - } +// void update() { +// if (mounted) setState(() {}); +// if (!stateStream.isClosed) { +// stateStream.add(null); +// } +// } - Room get room => widget.room; +// Room get room => widget.room; - bool get isEditing => launchState == ActivityLaunchState.editing; - bool get isLaunching => launchState == ActivityLaunchState.launching; +// bool get isEditing => launchState == ActivityLaunchState.editing; +// bool get isLaunching => launchState == ActivityLaunchState.launching; - ActivityPlanRequest get updatedRequest { - final int participants = int.tryParse(participantsController.text.trim()) ?? - widget.initialActivity.req.numberOfParticipants; - final updatedReq = widget.initialActivity.req; - updatedReq.numberOfParticipants = participants; - updatedReq.cefrLevel = languageLevel; - return updatedReq; - } +// ActivityPlanRequest get updatedRequest { +// final int participants = int.tryParse(participantsController.text.trim()) ?? +// widget.initialActivity.req.numberOfParticipants; +// final updatedReq = widget.initialActivity.req; +// updatedReq.numberOfParticipants = participants; +// updatedReq.cefrLevel = languageLevel; +// return updatedReq; +// } - ActivityPlanModel get updatedActivity { - return ActivityPlanModel( - req: updatedRequest, - title: titleController.text, - learningObjective: learningObjectivesController.text, - instructions: instructionsController.text, - vocab: vocab, - imageURL: imageURL, - roles: widget.initialActivity.roles, - activityId: widget.initialActivity.activityId, - ); - } +// ActivityPlanModel get updatedActivity { +// return ActivityPlanModel( +// req: updatedRequest, +// title: titleController.text, +// learningObjective: learningObjectivesController.text, +// instructions: instructionsController.text, +// vocab: vocab, +// imageURL: imageURL, +// roles: widget.initialActivity.roles, +// activityId: widget.initialActivity.activityId, +// ); +// } - Future resetActivity() async { - avatar = null; - filename = null; - imageURL = null; +// Future resetActivity() async { +// avatar = null; +// filename = null; +// imageURL = null; - titleController.text = widget.initialActivity.title; - learningObjectivesController.text = - widget.initialActivity.learningObjective; - instructionsController.text = widget.initialActivity.instructions; - participantsController.text = - widget.initialActivity.req.numberOfParticipants.toString(); +// titleController.text = widget.initialActivity.title; +// learningObjectivesController.text = +// widget.initialActivity.learningObjective; +// instructionsController.text = widget.initialActivity.instructions; +// participantsController.text = +// widget.initialActivity.req.numberOfParticipants.toString(); - vocab.clear(); - vocab.addAll(widget.initialActivity.vocab); +// vocab.clear(); +// vocab.addAll(widget.initialActivity.vocab); - languageLevel = widget.initialActivity.req.cefrLevel; +// languageLevel = widget.initialActivity.req.cefrLevel; - imageURL = widget.initialActivity.imageURL; - filename = widget.initialFilename; - if (widget.initialActivity.imageURL != null) { - await _setAvatarByURL(widget.initialActivity.imageURL!); - } +// imageURL = widget.initialActivity.imageURL; +// filename = widget.initialFilename; +// if (widget.initialActivity.imageURL != null) { +// await _setAvatarByURL(widget.initialActivity.imageURL!); +// } - update(); - } +// update(); +// } - Future overrideActivity(ActivityPlanModel override) async { - avatar = null; - filename = null; - imageURL = null; +// Future overrideActivity(ActivityPlanModel override) async { +// avatar = null; +// filename = null; +// imageURL = null; - titleController.text = override.title; - learningObjectivesController.text = override.learningObjective; - instructionsController.text = override.instructions; - participantsController.text = override.req.numberOfParticipants.toString(); - vocab.clear(); - vocab.addAll(override.vocab); - languageLevel = override.req.cefrLevel; +// titleController.text = override.title; +// learningObjectivesController.text = override.learningObjective; +// instructionsController.text = override.instructions; +// participantsController.text = override.req.numberOfParticipants.toString(); +// vocab.clear(); +// vocab.addAll(override.vocab); +// languageLevel = override.req.cefrLevel; - if (override.imageURL != null) { - await _setAvatarByURL(override.imageURL!); - } +// if (override.imageURL != null) { +// await _setAvatarByURL(override.imageURL!); +// } - update(); - } +// update(); +// } - void startEditing() { - setLaunchState(ActivityLaunchState.editing); - } +// void startEditing() { +// setLaunchState(ActivityLaunchState.editing); +// } - void setLaunchState(ActivityLaunchState state) { - if (state == ActivityLaunchState.launching) { - _addBookmarkedActivity(); - } +// void setLaunchState(ActivityLaunchState state) { +// if (state == ActivityLaunchState.launching) { +// _addBookmarkedActivity(); +// } - launchState = state; - update(); - } +// launchState = state; +// update(); +// } - void addVocab() { - vocab.insert( - 0, - Vocab( - lemma: vocabController.text.trim(), - pos: "", - ), - ); - vocabController.clear(); - update(); - } +// void addVocab() { +// vocab.insert( +// 0, +// Vocab( +// lemma: vocabController.text.trim(), +// pos: "", +// ), +// ); +// vocabController.clear(); +// update(); +// } - void removeVocab(int index) { - vocab.removeAt(index); - update(); - } +// void removeVocab(int index) { +// vocab.removeAt(index); +// update(); +// } - void setLanguageLevel(LanguageLevelTypeEnum level) { - languageLevel = level; - update(); - } +// void setLanguageLevel(LanguageLevelTypeEnum level) { +// languageLevel = level; +// update(); +// } - Future selectAvatar() async { - final photo = await selectFiles( - context, - type: FileSelectorType.images, - allowMultiple: false, - ); - final bytes = await photo.singleOrNull?.readAsBytes(); - avatar = bytes; - imageURL = null; - filename = photo.singleOrNull?.name; - update(); - } +// Future selectAvatar() async { +// final photo = await selectFiles( +// context, +// type: FileSelectorType.images, +// allowMultiple: false, +// ); +// final bytes = await photo.singleOrNull?.readAsBytes(); +// avatar = bytes; +// imageURL = null; +// filename = photo.singleOrNull?.name; +// update(); +// } - void setNumActivities(int count) { - numActivities = count; - update(); - } +// void setNumActivities(int count) { +// numActivities = count; +// update(); +// } - Future _setAvatarByURL(String url) async { - try { - if (avatar == null) { - if (url.startsWith("mxc")) { - final client = Matrix.of(context).client; - final mxcUri = Uri.parse(url); - final data = await client.downloadMxcCached(mxcUri); - avatar = data; - filename = Uri.encodeComponent( - mxcUri.pathSegments.last, - ); - } else { - final Response response = await http.get( - Uri.parse(url), - headers: { - 'Authorization': - 'Bearer ${MatrixState.pangeaController.userController.accessToken}', - }, - ); - if (response.statusCode != 200) { - throw Exception( - "Failed to download image from URL: ${response.statusCode}", - ); - } - avatar = response.bodyBytes; - filename = Uri.encodeComponent( - Uri.parse(url).pathSegments.last, - ); - } - } - } catch (err, s) { - ErrorHandler.logError( - e: err, - s: s, - data: { - "imageURL": widget.initialActivity.imageURL, - }, - ); - } - } +// Future _setAvatarByURL(String url) async { +// try { +// if (avatar == null) { +// if (url.startsWith("mxc")) { +// final client = Matrix.of(context).client; +// final mxcUri = Uri.parse(url); +// final data = await client.downloadMxcCached(mxcUri); +// avatar = data; +// filename = Uri.encodeComponent( +// mxcUri.pathSegments.last, +// ); +// } else { +// final Response response = await http.get( +// Uri.parse(url), +// headers: { +// 'Authorization': +// 'Bearer ${MatrixState.pangeaController.userController.accessToken}', +// }, +// ); +// if (response.statusCode != 200) { +// throw Exception( +// "Failed to download image from URL: ${response.statusCode}", +// ); +// } +// avatar = response.bodyBytes; +// filename = Uri.encodeComponent( +// Uri.parse(url).pathSegments.last, +// ); +// } +// } +// } catch (err, s) { +// ErrorHandler.logError( +// e: err, +// s: s, +// data: { +// "imageURL": widget.initialActivity.imageURL, +// }, +// ); +// } +// } - Future updateImageURL() async { - if (avatar == null) return; - final url = await Matrix.of(context).client.uploadContent( - avatar!, - filename: filename, - ); - imageURL = url.toString(); - update(); - } +// Future updateImageURL() async { +// if (avatar == null) return; +// final url = await Matrix.of(context).client.uploadContent( +// avatar!, +// filename: filename, +// ); +// imageURL = url.toString(); +// update(); +// } - Future saveEdits() async { - if (!formKey.currentState!.validate()) return; - await updateImageURL(); - setLaunchState(ActivityLaunchState.base); +// Future saveEdits() async { +// if (!formKey.currentState!.validate()) return; +// await updateImageURL(); +// setLaunchState(ActivityLaunchState.base); - await _updateBookmarkedActivity(); - update(); - } +// await _updateBookmarkedActivity(); +// update(); +// } - Future clearEdits() async { - await resetActivity(); - setLaunchState(ActivityLaunchState.base); - } +// Future clearEdits() async { +// await resetActivity(); +// setLaunchState(ActivityLaunchState.base); +// } - UserController get _userController => - MatrixState.pangeaController.userController; +// UserController get _userController => +// MatrixState.pangeaController.userController; - bool get isBookmarked => - _userController.isBookmarked(updatedActivity.activityId); +// bool get isBookmarked => +// _userController.isBookmarked(updatedActivity.activityId); - Future toggleBookmarkedActivity() async { - isBookmarked - ? await _removeBookmarkedActivity() - : await _addBookmarkedActivity(); - update(); - } +// Future toggleBookmarkedActivity() async { +// isBookmarked +// ? await _removeBookmarkedActivity() +// : await _addBookmarkedActivity(); +// update(); +// } - Future _addBookmarkedActivity() async { - await _userController.addBookmarkedActivity( - activityId: updatedActivity.activityId, - ); - await ActivityPlanRepo.set(updatedActivity); - } +// Future _addBookmarkedActivity() async { +// await _userController.addBookmarkedActivity( +// activityId: updatedActivity.activityId, +// ); +// await ActivityPlanRepo.set(updatedActivity); +// } - Future _updateBookmarkedActivity() async { - // save updates locally, in case choreo results in error - await ActivityPlanRepo.set(updatedActivity); +// Future _updateBookmarkedActivity() async { +// // save updates locally, in case choreo results in error +// await ActivityPlanRepo.set(updatedActivity); - // prevent an error or delay from the choreo endpoint bubbling up - // in the UI, since the changes are still stored locally - ActivityPlanRepo.update( - updatedActivity, - ).then((resp) { - _userController.updateBookmarkedActivity( - activityId: widget.initialActivity.activityId, - newActivityId: resp.activityId, - ); - }); - } +// // prevent an error or delay from the choreo endpoint bubbling up +// // in the UI, since the changes are still stored locally +// ActivityPlanRepo.update( +// updatedActivity, +// ).then((resp) { +// _userController.updateBookmarkedActivity( +// activityId: widget.initialActivity.activityId, +// newActivityId: resp.activityId, +// ); +// }); +// } - Future _removeBookmarkedActivity() async { - await _userController.removeBookmarkedActivity( - activityId: updatedActivity.activityId, - ); - await ActivityPlanRepo.remove(updatedActivity.activityId); - } +// Future _removeBookmarkedActivity() async { +// await _userController.removeBookmarkedActivity( +// activityId: updatedActivity.activityId, +// ); +// await ActivityPlanRepo.remove(updatedActivity.activityId); +// } - Future> launchToSpace() async { - final List activityRoomIDs = []; - try { - return Future.wait( - List.generate(numActivities, (i) async { - final id = await _launchActivityRoom(i); - activityRoomIDs.add(id); - return id; - }), - ); - } catch (e) { - _cleanupFailedLaunch(activityRoomIDs); - rethrow; - } - } +// Future> launchToSpace() async { +// final List activityRoomIDs = []; +// try { +// return Future.wait( +// List.generate(numActivities, (i) async { +// final id = await _launchActivityRoom(i); +// activityRoomIDs.add(id); +// return id; +// }), +// ); +// } catch (e) { +// _cleanupFailedLaunch(activityRoomIDs); +// rethrow; +// } +// } - Future _launchActivityRoom(int index) async { - await updateImageURL(); - final roomID = await Matrix.of(context).client.createRoom( - creationContent: { - 'type': - "${PangeaRoomTypes.activitySession}:${updatedActivity.activityId}", - }, - visibility: Visibility.private, - name: "${updatedActivity.title} ${index + 1}", - initialState: [ - StateEvent( - type: PangeaEventTypes.activityPlan, - content: updatedActivity.toJson(), - ), - if (imageURL != null) - StateEvent( - type: EventTypes.RoomAvatar, - content: {'url': imageURL}, - ), - RoomDefaults.defaultPowerLevels( - Matrix.of(context).client.userID!, - ), - await Matrix.of(context).client.pangeaJoinRules( - 'knock_restricted', - allow: [ - { - "type": "m.room_membership", - "room_id": room.id, - } - ], - ), - ], - ); +// Future _launchActivityRoom(int index) async { +// await updateImageURL(); +// final roomID = await Matrix.of(context).client.createRoom( +// creationContent: { +// 'type': +// "${PangeaRoomTypes.activitySession}:${updatedActivity.activityId}", +// }, +// visibility: Visibility.private, +// name: "${updatedActivity.title} ${index + 1}", +// initialState: [ +// StateEvent( +// type: PangeaEventTypes.activityPlan, +// content: updatedActivity.toJson(), +// ), +// if (imageURL != null) +// StateEvent( +// type: EventTypes.RoomAvatar, +// content: {'url': imageURL}, +// ), +// RoomDefaults.defaultPowerLevels( +// Matrix.of(context).client.userID!, +// ), +// await Matrix.of(context).client.pangeaJoinRules( +// 'knock_restricted', +// allow: [ +// { +// "type": "m.room_membership", +// "room_id": room.id, +// } +// ], +// ), +// ], +// ); - Room? activityRoom = room.client.getRoomById(roomID); - if (activityRoom == null) { - await room.client.waitForRoomInSync(roomID); - activityRoom = room.client.getRoomById(roomID); - if (activityRoom == null) { - throw Exception("Failed to create activity room"); - } - } +// Room? activityRoom = room.client.getRoomById(roomID); +// if (activityRoom == null) { +// await room.client.waitForRoomInSync(roomID); +// activityRoom = room.client.getRoomById(roomID); +// if (activityRoom == null) { +// throw Exception("Failed to create activity room"); +// } +// } - await room.addToSpace(activityRoom.id); - if (activityRoom.pangeaSpaceParents.isEmpty) { - await room.client.waitForRoomInSync(activityRoom.id); - } +// await room.addToSpace(activityRoom.id); +// if (activityRoom.pangeaSpaceParents.isEmpty) { +// await room.client.waitForRoomInSync(activityRoom.id); +// } - return activityRoom.id; - } +// return activityRoom.id; +// } - Future _cleanupFailedLaunch(List roomIds) async { - final futures = roomIds.map((id) async { - final room = Matrix.of(context).client.getRoomById(id); - if (room == null) return; +// Future _cleanupFailedLaunch(List roomIds) async { +// final futures = roomIds.map((id) async { +// final room = Matrix.of(context).client.getRoomById(id); +// if (room == null) return; - try { - await room.leave(); - } catch (e) { - debugPrint("Failed to leave room $id: $e"); - } - }); +// try { +// await room.leave(); +// } catch (e) { +// debugPrint("Failed to leave room $id: $e"); +// } +// }); - await Future.wait(futures); - } +// await Future.wait(futures); +// } - @override - Widget build(BuildContext context) => widget.builder(this); -} +// @override +// Widget build(BuildContext context) => widget.builder(this); +// } diff --git a/lib/pangea/activity_planner/activity_planner_page.dart b/lib/pangea/activity_planner/activity_planner_page.dart index e534a0ec9..20c356c4c 100644 --- a/lib/pangea/activity_planner/activity_planner_page.dart +++ b/lib/pangea/activity_planner/activity_planner_page.dart @@ -1,158 +1,158 @@ -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:material_symbols_icons/symbols.dart'; -import 'package:matrix/matrix.dart'; +// import 'package:go_router/go_router.dart'; +// import 'package:material_symbols_icons/symbols.dart'; +// import 'package:matrix/matrix.dart'; -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_page_appbar.dart'; -import 'package:fluffychat/pangea/activity_planner/bookmarked_activity_list.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_area.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; -import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; -import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/config/app_config.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_planner_page_appbar.dart'; +// import 'package:fluffychat/pangea/activity_planner/bookmarked_activity_list.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_area.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; +// import 'package:fluffychat/pangea/common/widgets/customized_svg.dart'; +// import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -enum PageMode { - featuredActivities, - savedActivities, -} +// enum PageMode { +// featuredActivities, +// savedActivities, +// } -class ActivityPlannerPage extends StatefulWidget { - final String roomID; - const ActivityPlannerPage({super.key, required this.roomID}); +// class ActivityPlannerPage extends StatefulWidget { +// final String roomID; +// const ActivityPlannerPage({super.key, required this.roomID}); - @override - ActivityPlannerPageState createState() => ActivityPlannerPageState(); -} +// @override +// ActivityPlannerPageState createState() => ActivityPlannerPageState(); +// } -class ActivityPlannerPageState extends State { - PageMode pageMode = PageMode.featuredActivities; - Room? get room => Matrix.of(context).client.getRoomById(widget.roomID); +// class ActivityPlannerPageState extends State { +// PageMode pageMode = PageMode.featuredActivities; +// Room? get room => Matrix.of(context).client.getRoomById(widget.roomID); - void _setPageMode(PageMode? mode) { - if (mode == null) return; - setState(() => pageMode = mode); - } +// void _setPageMode(PageMode? mode) { +// if (mode == null) return; +// setState(() => pageMode = mode); +// } - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - Widget? body; - switch (pageMode) { - case PageMode.savedActivities: - if (room != null) { - body = BookmarkedActivitiesList(room: room!); - } - break; - case PageMode.featuredActivities: - if (room != null) { - body = Expanded( - child: SingleChildScrollView( - child: ActivitySuggestionsArea( - scrollDirection: Axis.vertical, - room: room!, - ), - ), - ); - } - break; - } +// @override +// Widget build(BuildContext context) { +// final theme = Theme.of(context); +// Widget? body; +// switch (pageMode) { +// case PageMode.savedActivities: +// if (room != null) { +// body = BookmarkedActivitiesList(room: room!); +// } +// break; +// case PageMode.featuredActivities: +// if (room != null) { +// body = Expanded( +// child: SingleChildScrollView( +// child: ActivitySuggestionsArea( +// scrollDirection: Axis.vertical, +// room: room!, +// ), +// ), +// ); +// } +// break; +// } - return SafeArea( - child: Scaffold( - appBar: ActivityPlannerPageAppBar( - pageMode: pageMode, - roomID: widget.roomID, - ), - body: Center( - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 800.0), - child: Column( - children: [ - if ([PageMode.featuredActivities, PageMode.savedActivities] - .contains(pageMode)) - Padding( - padding: const EdgeInsets.all(16.0), - child: Wrap( - spacing: 12.0, - runSpacing: 12.0, - alignment: WrapAlignment.center, - children: [ - FilterChip( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(32), - ), - label: Row( - spacing: 8.0, - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Symbols.star_shine, size: 24.0), - Text(L10n.of(context).featuredActivities), - ], - ), - selected: pageMode == PageMode.featuredActivities, - onSelected: (_) => _setPageMode( - PageMode.featuredActivities, - ), - ), - FilterChip( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(32), - ), - label: Row( - spacing: 8.0, - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.save_outlined, size: 24.0), - Text(L10n.of(context).saved), - ], - ), - selected: pageMode == PageMode.savedActivities, - onSelected: (_) => _setPageMode( - PageMode.savedActivities, - ), - ), - FilterChip( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(32), - ), - label: Row( - spacing: 8.0, - mainAxisSize: MainAxisSize.min, - children: [ - CustomizedSvg( - svgUrl: - "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.crayonIconPath}", - colorReplacements: { - "#CDBEF9": colorToHex( - theme.colorScheme.secondary, - ), - }, - height: 24.0, - width: 24.0, - ), - Text(L10n.of(context).createActivityPlan), - ], - ), - selected: false, - onSelected: (_) => context.go( - '/rooms/spaces/${widget.roomID}/details/planner/generator', - ), - ), - ], - ), - ), - body ?? - ErrorIndicator( - message: L10n.of(context).oopsSomethingWentWrong, - ), - ], - ), - ), - ), - ), - ); - } -} +// return SafeArea( +// child: Scaffold( +// appBar: ActivityPlannerPageAppBar( +// pageMode: pageMode, +// roomID: widget.roomID, +// ), +// body: Center( +// child: ConstrainedBox( +// constraints: const BoxConstraints(maxWidth: 800.0), +// child: Column( +// children: [ +// if ([PageMode.featuredActivities, PageMode.savedActivities] +// .contains(pageMode)) +// Padding( +// padding: const EdgeInsets.all(16.0), +// child: Wrap( +// spacing: 12.0, +// runSpacing: 12.0, +// alignment: WrapAlignment.center, +// children: [ +// FilterChip( +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(32), +// ), +// label: Row( +// spacing: 8.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// const Icon(Symbols.star_shine, size: 24.0), +// Text(L10n.of(context).featuredActivities), +// ], +// ), +// selected: pageMode == PageMode.featuredActivities, +// onSelected: (_) => _setPageMode( +// PageMode.featuredActivities, +// ), +// ), +// FilterChip( +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(32), +// ), +// label: Row( +// spacing: 8.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// const Icon(Icons.save_outlined, size: 24.0), +// Text(L10n.of(context).saved), +// ], +// ), +// selected: pageMode == PageMode.savedActivities, +// onSelected: (_) => _setPageMode( +// PageMode.savedActivities, +// ), +// ), +// FilterChip( +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(32), +// ), +// label: Row( +// spacing: 8.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// CustomizedSvg( +// svgUrl: +// "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.crayonIconPath}", +// colorReplacements: { +// "#CDBEF9": colorToHex( +// theme.colorScheme.secondary, +// ), +// }, +// height: 24.0, +// width: 24.0, +// ), +// Text(L10n.of(context).createActivityPlan), +// ], +// ), +// selected: false, +// onSelected: (_) => context.go( +// '/rooms/spaces/${widget.roomID}/details/planner/generator', +// ), +// ), +// ], +// ), +// ), +// body ?? +// ErrorIndicator( +// message: L10n.of(context).oopsSomethingWentWrong, +// ), +// ], +// ), +// ), +// ), +// ), +// ); +// } +// } diff --git a/lib/pangea/activity_planner/activity_planner_page_appbar.dart b/lib/pangea/activity_planner/activity_planner_page_appbar.dart index 0d3a043d6..2cf387b8e 100644 --- a/lib/pangea/activity_planner/activity_planner_page_appbar.dart +++ b/lib/pangea/activity_planner/activity_planner_page_appbar.dart @@ -1,64 +1,64 @@ -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_page.dart'; +// import 'package:fluffychat/config/themes.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_planner_page.dart'; -class ActivityPlannerPageAppBar extends StatelessWidget - implements PreferredSizeWidget { - final PageMode pageMode; - final String roomID; +// class ActivityPlannerPageAppBar extends StatelessWidget +// implements PreferredSizeWidget { +// final PageMode pageMode; +// final String roomID; - const ActivityPlannerPageAppBar({ - required this.pageMode, - required this.roomID, - super.key, - }); +// const ActivityPlannerPageAppBar({ +// required this.pageMode, +// required this.roomID, +// super.key, +// }); - @override - Size get preferredSize => const Size.fromHeight(72); +// @override +// Size get preferredSize => const Size.fromHeight(72); - @override - Widget build(BuildContext context) { - final l10n = L10n.of(context); +// @override +// Widget build(BuildContext context) { +// final l10n = L10n.of(context); - return AppBar( - leading: FluffyThemes.isColumnMode(context) - ? Row( - children: [ - const SizedBox(width: 8.0), - BackButton( - onPressed: Navigator.of(context).pop, - ), - ], - ) - : null, - title: pageMode == PageMode.savedActivities - ? Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.save), - const SizedBox(width: 8), - Flexible( - child: Text(l10n.mySavedActivities), - ), - ], - ) - : Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.event_note_outlined), - const SizedBox(width: 8), - Flexible( - child: Text( - l10n.activityPlannerTitle, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ); - } -} +// return AppBar( +// leading: FluffyThemes.isColumnMode(context) +// ? Row( +// children: [ +// const SizedBox(width: 8.0), +// BackButton( +// onPressed: Navigator.of(context).pop, +// ), +// ], +// ) +// : null, +// title: pageMode == PageMode.savedActivities +// ? Row( +// mainAxisSize: MainAxisSize.min, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// const Icon(Icons.save), +// const SizedBox(width: 8), +// Flexible( +// child: Text(l10n.mySavedActivities), +// ), +// ], +// ) +// : Row( +// mainAxisSize: MainAxisSize.min, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// const Icon(Icons.event_note_outlined), +// const SizedBox(width: 8), +// Flexible( +// child: Text( +// l10n.activityPlannerTitle, +// overflow: TextOverflow.ellipsis, +// ), +// ), +// ], +// ), +// ); +// } +// } diff --git a/lib/pangea/activity_planner/bookmarked_activity_list.dart b/lib/pangea/activity_planner/bookmarked_activity_list.dart index 8860b7009..f37e3e818 100644 --- a/lib/pangea/activity_planner/bookmarked_activity_list.dart +++ b/lib/pangea/activity_planner/bookmarked_activity_list.dart @@ -1,122 +1,122 @@ -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; +// import 'package:matrix/matrix.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/pangea/user/controllers/user_controller.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/config/themes.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; +// import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +// import 'package:fluffychat/pangea/user/controllers/user_controller.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -class BookmarkedActivitiesList extends StatefulWidget { - final Room room; - const BookmarkedActivitiesList({ - super.key, - required this.room, - }); +// class BookmarkedActivitiesList extends StatefulWidget { +// final Room room; +// const BookmarkedActivitiesList({ +// super.key, +// required this.room, +// }); - @override - BookmarkedActivitiesListState createState() => - BookmarkedActivitiesListState(); -} +// @override +// BookmarkedActivitiesListState createState() => +// BookmarkedActivitiesListState(); +// } -class BookmarkedActivitiesListState extends State { - bool _loading = true; +// class BookmarkedActivitiesListState extends State { +// bool _loading = true; - @override - void initState() { - super.initState(); - _loadBookmarkedActivities(); - } +// @override +// void initState() { +// super.initState(); +// _loadBookmarkedActivities(); +// } - List get _bookmarkedActivities => - _userController.getBookmarkedActivitiesSync(); +// List get _bookmarkedActivities => +// _userController.getBookmarkedActivitiesSync(); - bool get _isColumnMode => FluffyThemes.isColumnMode(context); +// bool get _isColumnMode => FluffyThemes.isColumnMode(context); - double get cardHeight => _isColumnMode ? 325.0 : 250.0; - double get cardWidth => _isColumnMode ? 225.0 : 150.0; +// double get cardHeight => _isColumnMode ? 325.0 : 250.0; +// double get cardWidth => _isColumnMode ? 225.0 : 150.0; - UserController get _userController => - MatrixState.pangeaController.userController; +// UserController get _userController => +// MatrixState.pangeaController.userController; - Future _loadBookmarkedActivities() async { - try { - setState(() => _loading = true); - await _userController.getBookmarkedActivities(); - } catch (e, s) { - ErrorHandler.logError( - e: e, - s: s, - data: { - 'roomId': widget.room.id, - }, - ); - } finally { - if (mounted) setState(() => _loading = false); - } - } +// Future _loadBookmarkedActivities() async { +// try { +// setState(() => _loading = true); +// await _userController.getBookmarkedActivities(); +// } catch (e, s) { +// ErrorHandler.logError( +// e: e, +// s: s, +// data: { +// 'roomId': widget.room.id, +// }, +// ); +// } finally { +// if (mounted) setState(() => _loading = false); +// } +// } - @override - Widget build(BuildContext context) { - final l10n = L10n.of(context); - if (_loading) { - return const Center( - child: CircularProgressIndicator.adaptive(), - ); - } +// @override +// Widget build(BuildContext context) { +// final l10n = L10n.of(context); +// if (_loading) { +// return const Center( +// child: CircularProgressIndicator.adaptive(), +// ); +// } - if (_bookmarkedActivities.isEmpty) { - return Center( - child: Container( - constraints: const BoxConstraints(maxWidth: 200), - child: Text( - l10n.noSavedActivities, - textAlign: TextAlign.center, - ), - ), - ); - } +// if (_bookmarkedActivities.isEmpty) { +// return Center( +// child: Container( +// constraints: const BoxConstraints(maxWidth: 200), +// child: Text( +// l10n.noSavedActivities, +// textAlign: TextAlign.center, +// ), +// ), +// ); +// } - return Expanded( - child: SingleChildScrollView( - child: SizedBox( - width: 800.0, - child: Wrap( - alignment: WrapAlignment.spaceEvenly, - runSpacing: 16.0, - spacing: 4.0, - children: _bookmarkedActivities.map((activity) { - return ActivityPlannerBuilder( - initialActivity: activity, - room: widget.room, - builder: (controller) { - return ActivitySuggestionCard( - controller: controller, - onPressed: () { - showDialog( - context: context, - builder: (context) { - return ActivitySuggestionDialog( - controller: controller, - buttonText: l10n.launchActivityButton, - ); - }, - ); - }, - width: cardWidth, - height: cardHeight, - ); - }, - ); - }).toList(), - ), - ), - ), - ); - } -} +// return Expanded( +// child: SingleChildScrollView( +// child: SizedBox( +// width: 800.0, +// child: Wrap( +// alignment: WrapAlignment.spaceEvenly, +// runSpacing: 16.0, +// spacing: 4.0, +// children: _bookmarkedActivities.map((activity) { +// return ActivityPlannerBuilder( +// initialActivity: activity, +// room: widget.room, +// builder: (controller) { +// return ActivitySuggestionCard( +// controller: controller, +// onPressed: () { +// showDialog( +// context: context, +// builder: (context) { +// return ActivitySuggestionDialog( +// controller: controller, +// buttonText: l10n.launchActivityButton, +// ); +// }, +// ); +// }, +// width: cardWidth, +// height: cardHeight, +// ); +// }, +// ); +// }).toList(), +// ), +// ), +// ), +// ); +// } +// } diff --git a/lib/pangea/activity_planner/suggestion_form_field.dart b/lib/pangea/activity_planner/suggestion_form_field.dart index 2b76823fe..27ad7bffb 100644 --- a/lib/pangea/activity_planner/suggestion_form_field.dart +++ b/lib/pangea/activity_planner/suggestion_form_field.dart @@ -1,60 +1,60 @@ -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; +// import 'package:fluffychat/pangea/activity_generator/list_request_schema.dart'; -class SuggestionFormField extends StatelessWidget { - final List? suggestions; - final String? Function(String?)? validator; - final int? maxLength; - final String label; - final String placeholder; - final TextEditingController controller; +// class SuggestionFormField extends StatelessWidget { +// final List? suggestions; +// final String? Function(String?)? validator; +// final int? maxLength; +// final String label; +// final String placeholder; +// final TextEditingController controller; - const SuggestionFormField({ - super.key, - this.suggestions, - required this.placeholder, - this.validator, - this.maxLength, - required this.label, - required this.controller, - }); +// const SuggestionFormField({ +// super.key, +// this.suggestions, +// required this.placeholder, +// this.validator, +// this.maxLength, +// required this.label, +// required this.controller, +// }); - @override - Widget build(BuildContext context) { - return Autocomplete( - initialValue: TextEditingValue(text: controller.text), - optionsBuilder: (TextEditingValue textEditingValue) { - return (suggestions ?? []) - .where((ActivitySettingResponseSchema option) { - return option.name - .toLowerCase() - .contains(textEditingValue.text.toLowerCase()); - }).map((ActivitySettingResponseSchema e) => e.name); - }, - onSelected: (val) => controller.text = val, - fieldViewBuilder: ( - BuildContext context, - TextEditingController textEditingController, - FocusNode focusNode, - VoidCallback onFieldSubmitted, - ) { - textEditingController.value = controller.value; - textEditingController.addListener(() { - controller.value = textEditingController.value; - }); - return TextFormField( - controller: textEditingController, - focusNode: focusNode, - decoration: InputDecoration( - labelText: label, - hintText: placeholder, - ), - validator: validator, - maxLength: maxLength, - onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), - ); - }, - ); - } -} +// @override +// Widget build(BuildContext context) { +// return Autocomplete( +// initialValue: TextEditingValue(text: controller.text), +// optionsBuilder: (TextEditingValue textEditingValue) { +// return (suggestions ?? []) +// .where((ActivitySettingResponseSchema option) { +// return option.name +// .toLowerCase() +// .contains(textEditingValue.text.toLowerCase()); +// }).map((ActivitySettingResponseSchema e) => e.name); +// }, +// onSelected: (val) => controller.text = val, +// fieldViewBuilder: ( +// BuildContext context, +// TextEditingController textEditingController, +// FocusNode focusNode, +// VoidCallback onFieldSubmitted, +// ) { +// textEditingController.value = controller.value; +// textEditingController.addListener(() { +// controller.value = textEditingController.value; +// }); +// return TextFormField( +// controller: textEditingController, +// focusNode: focusNode, +// decoration: InputDecoration( +// labelText: label, +// hintText: placeholder, +// ), +// validator: validator, +// maxLength: maxLength, +// onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), +// ); +// }, +// ); +// } +// } diff --git a/lib/pangea/activity_sessions/activity_participant_list.dart b/lib/pangea/activity_sessions/activity_participant_list.dart index 1b0a0b7e5..7705990aa 100644 --- a/lib/pangea/activity_sessions/activity_participant_list.dart +++ b/lib/pangea/activity_sessions/activity_participant_list.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; import 'package:matrix/matrix.dart'; +import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_participant_indicator.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_role_model.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart'; @@ -10,7 +11,8 @@ import 'package:fluffychat/pangea/spaces/utils/load_participants_util.dart'; import 'package:fluffychat/widgets/avatar.dart'; class ActivityParticipantList extends StatelessWidget { - final Room room; + final ActivityPlanModel activity; + final Room? room; final Function(String)? onTap; final bool Function(String)? canSelect; @@ -19,7 +21,8 @@ class ActivityParticipantList extends StatelessWidget { const ActivityParticipantList({ super.key, - required this.room, + required this.activity, + this.room, this.onTap, this.canSelect, this.isSelected, @@ -32,8 +35,8 @@ class ActivityParticipantList extends StatelessWidget { room: room, builder: (context, participants) { final theme = Theme.of(context); - final availableRoles = room.activityPlan!.roles; - final assignedRoles = room.assignedRoles ?? {}; + final availableRoles = activity.roles; + final assignedRoles = room?.assignedRoles ?? {}; final remainingMembers = participants.participants.where( (p) => !assignedRoles.values.any((r) => r.userId == p.id), diff --git a/lib/pangea/activity_sessions/activity_room_extension.dart b/lib/pangea/activity_sessions/activity_room_extension.dart index 775d422d8..b4004668d 100644 --- a/lib/pangea/activity_sessions/activity_room_extension.dart +++ b/lib/pangea/activity_sessions/activity_room_extension.dart @@ -335,6 +335,14 @@ extension ActivityRoomExtension on Room { bool get showActivityFinished => showActivityChatUI && ownRole != null && hasCompletedActivity; + String? get activityId { + if (!isActivitySession) return null; + if (isActivityRoomType) { + return roomType!.split(":").last; + } + return activityPlan?.activityId; + } + Future getActivityAnalytics() async { // wait for local storage box to init in getAnalytics initialization if (!MatrixState.pangeaController.getAnalytics.initCompleter.isCompleted) { diff --git a/lib/pangea/activity_sessions/activity_session_chat/activity_finished_status_message.dart b/lib/pangea/activity_sessions/activity_session_chat/activity_finished_status_message.dart index 5fb6223da..5f240f532 100644 --- a/lib/pangea/activity_sessions/activity_session_chat/activity_finished_status_message.dart +++ b/lib/pangea/activity_sessions/activity_session_chat/activity_finished_status_message.dart @@ -60,6 +60,7 @@ class ActivityFinishedStatusMessage extends StatelessWidget { throw L10n.of(context).noCourseFound; } + await coursePlan.init(); final activityId = controller.room.activityPlan!.activityId; final topicId = coursePlan.topicID(activityId); if (topicId == null) { diff --git a/lib/pangea/activity_sessions/activity_session_chat/activity_pinned_message.dart b/lib/pangea/activity_sessions/activity_session_chat/activity_pinned_message.dart index e1ce17d04..a166b07cb 100644 --- a/lib/pangea/activity_sessions/activity_session_chat/activity_pinned_message.dart +++ b/lib/pangea/activity_sessions/activity_session_chat/activity_pinned_message.dart @@ -10,7 +10,7 @@ import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pages/chat/chat_app_bar_list_tile.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestions_constants.dart'; +import 'package:fluffychat/pangea/activity_sessions/activity_session_constants.dart'; import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; @@ -144,7 +144,7 @@ class ActivityPinnedMessageState extends State { ), CachedNetworkImage( imageUrl: - "${AppConfig.assetsBaseURL}/${ActivitySuggestionsConstants.endActivityAssetPath}", + "${AppConfig.assetsBaseURL}/${ActivitySessionConstants.endActivityAssetPath}", width: isColumnMode ? 240.0 : 120.0, ), Row( diff --git a/lib/pangea/activity_sessions/activity_session_chat/activity_results_carousel.dart b/lib/pangea/activity_sessions/activity_session_chat/activity_results_carousel.dart deleted file mode 100644 index cff0d4eed..000000000 --- a/lib/pangea/activity_sessions/activity_session_chat/activity_results_carousel.dart +++ /dev/null @@ -1,94 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'package:matrix/matrix.dart'; - -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/pangea/activity_sessions/activity_role_model.dart'; -import 'package:fluffychat/pangea/activity_sessions/activity_session_chat/activity_analytics_chip.dart'; -import 'package:fluffychat/pangea/activity_summary/activity_summary_analytics_model.dart'; -import 'package:fluffychat/pangea/activity_summary/activity_summary_response_model.dart'; -import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart'; -import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dart'; - -class ActivityResultsCarousel extends StatelessWidget { - final String userId; - final ActivityRoleModel selectedRole; - final ParticipantSummaryModel summary; - final ActivitySummaryAnalyticsModel? analytics; - - final User? user; - - const ActivityResultsCarousel({ - super.key, - required this.userId, - required this.selectedRole, - required this.summary, - required this.analytics, - this.user, - }); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final isColumnMode = FluffyThemes.isColumnMode(context); - - return Container( - decoration: BoxDecoration( - color: theme.colorScheme.surfaceContainerHighest, - ), - padding: const EdgeInsets.all(12.0), - alignment: Alignment.centerLeft, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - height: isColumnMode ? 80.0 : 125.0, - child: SingleChildScrollView( - child: Text( - summary.feedback, - style: const TextStyle(fontSize: 12.0), - ), - ), - ), - const SizedBox(height: 10.0), - Wrap( - spacing: 8.0, - runSpacing: 8.0, - children: [ - if (analytics != null) - ActivityAnalyticsChip( - ConstructTypeEnum.vocab.indicator.icon, - "${analytics!.uniqueConstructCountForUser(userId, ConstructTypeEnum.vocab)}", - ), - if (analytics != null) - ActivityAnalyticsChip( - ConstructTypeEnum.morph.indicator.icon, - "${analytics!.uniqueConstructCountForUser(userId, ConstructTypeEnum.morph)}", - ), - ActivityAnalyticsChip( - Icons.school, - summary.cefrLevel, - ), - ...summary.superlatives.map( - (sup) => Container( - padding: const EdgeInsets.all(4.0), - decoration: BoxDecoration( - color: theme.colorScheme.primaryContainer, - borderRadius: BorderRadius.circular(20), - ), - child: Text( - sup, - style: const TextStyle( - fontSize: 12.0, - ), - ), - ), - ), - ], - ), - ], - ), - ); - } -} diff --git a/lib/pangea/activity_suggestions/activity_suggestions_constants.dart b/lib/pangea/activity_sessions/activity_session_constants.dart similarity index 89% rename from lib/pangea/activity_suggestions/activity_suggestions_constants.dart rename to lib/pangea/activity_sessions/activity_session_constants.dart index 8d097a411..9f54dd719 100644 --- a/lib/pangea/activity_suggestions/activity_suggestions_constants.dart +++ b/lib/pangea/activity_sessions/activity_session_constants.dart @@ -1,4 +1,4 @@ -class ActivitySuggestionsConstants { +class ActivitySessionConstants { static const String plusIconPath = "add_icon.svg"; static const String crayonIconPath = "make_your_own_icon.svg"; static const String modeImageFileStart = "activityplanner_mode_"; diff --git a/lib/pangea/activity_suggestions/activity_suggestion_card_row.dart b/lib/pangea/activity_sessions/activity_session_details_row.dart similarity index 87% rename from lib/pangea/activity_suggestions/activity_suggestion_card_row.dart rename to lib/pangea/activity_sessions/activity_session_details_row.dart index 2e209021b..0e5d44a8b 100644 --- a/lib/pangea/activity_suggestions/activity_suggestion_card_row.dart +++ b/lib/pangea/activity_sessions/activity_session_details_row.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; -class ActivitySuggestionCardRow extends StatelessWidget { +class ActivitySessionDetailsRow extends StatelessWidget { final IconData? icon; final Widget? leading; final Widget child; final double? iconSize; - const ActivitySuggestionCardRow({ + const ActivitySessionDetailsRow({ required this.child, this.icon, this.leading, diff --git a/lib/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart b/lib/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart index 726c4d148..a6720f8eb 100644 --- a/lib/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart +++ b/lib/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart @@ -2,15 +2,20 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/l10n/l10n.dart'; +import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_session_start/activity_sessions_start_view.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; +import 'package:fluffychat/pangea/course_plans/course_activity_repo.dart'; +import 'package:fluffychat/pangea/course_plans/course_plan_room_extension.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; +import 'package:fluffychat/widgets/matrix.dart'; enum SessionState { notStarted, @@ -20,10 +25,16 @@ enum SessionState { } class ActivitySessionStartPage extends StatefulWidget { - final Room room; + final String activityId; + final bool isNew; + final Room? room; + final String parentId; const ActivitySessionStartPage({ super.key, - required this.room, + required this.activityId, + this.isNew = false, + this.room, + required this.parentId, }); @override @@ -32,69 +43,86 @@ class ActivitySessionStartPage extends StatefulWidget { } class ActivitySessionStartController extends State { - bool _started = false; + ActivityPlanModel? activity; + bool loading = true; + Object? error; bool showInstructions = false; String? _selectedRoleId; + @override + void initState() { + super.initState(); + _loadActivity(); + } + @override void didUpdateWidget(covariant ActivitySessionStartPage oldWidget) { super.didUpdateWidget(oldWidget); - if (oldWidget.room.id != widget.room.id) { + if (oldWidget.room?.id != widget.room?.id) { setState(() { - _started = false; _selectedRoleId = null; showInstructions = false; }); } + + if (oldWidget.activityId != widget.activityId) { + _loadActivity(); + } } - Room get room => widget.room; + Room? get room => widget.room; - bool get isBotRoomMember => room.getParticipants().any( - (p) => p.id == BotName.byEnvironment, + Room? get parent => Matrix.of(context).client.getRoomById( + widget.parentId, ); - String get displayname => room.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)), - ); + bool get isBotRoomMember => + room?.getParticipants().any( + (p) => p.id == BotName.byEnvironment, + ) ?? + false; SessionState get state { - if (room.ownRole != null) return SessionState.confirmedRole; + if (room?.ownRole != null) return SessionState.confirmedRole; if (_selectedRoleId != null) return SessionState.selectedRole; - if (room.isRoomAdmin && !_started) return SessionState.notStarted; + if (room == null) { + return widget.isNew + ? SessionState.notSelectedRole + : SessionState.notStarted; + } return SessionState.notSelectedRole; } - String get descriptionText { + String? get descriptionText { switch (state) { case SessionState.confirmedRole: - return L10n.of(context).waitingToFillRole(room.remainingRoles); + return L10n.of(context).waitingToFillRole(room!.remainingRoles); case SessionState.selectedRole: - return room.activityPlan!.learningObjective; + return activity!.description; case SessionState.notStarted: - return L10n.of(context).letsGo; + return null; + case SessionState.notSelectedRole: - return room.isRoomAdmin + return room?.isRoomAdmin ?? false ? L10n.of(context).chooseRole : L10n.of(context).chooseRoleToParticipate; } } - String get buttonText => state == SessionState.notStarted - ? L10n.of(context).start - : L10n.of(context).confirm; - bool get enableButtons => [ SessionState.notStarted, SessionState.selectedRole, ].contains(state); bool canSelectParticipant(String id) { - if (state == SessionState.confirmedRole) return false; + if (state == SessionState.confirmedRole || + state == SessionState.notStarted) { + return false; + } - final availableRoles = room.activityPlan!.roles; - final assignedRoles = room.assignedRoles ?? {}; + final availableRoles = activity!.roles; + final assignedRoles = room?.assignedRoles ?? {}; final unassignedIds = availableRoles.keys .where((id) => !assignedRoles.containsKey(id)) .toList(); @@ -103,7 +131,7 @@ class ActivitySessionStartController extends State { bool isParticipantSelected(String id) { if (state == SessionState.confirmedRole) { - return room.ownRole?.id == id; + return room?.ownRole?.id == id; } return _selectedRoleId == id; } @@ -120,33 +148,63 @@ class ActivitySessionStartController extends State { if (mounted) setState(() => _selectedRoleId = id); } + Future _loadActivity() async { + try { + setState(() { + loading = true; + error = null; + }); + + final activities = await CourseActivityRepo.get( + widget.activityId, + [widget.activityId], + ); + + if (activities.isEmpty) { + throw Exception("Activity not found"); + } + + if (mounted) setState(() => activity = activities.first); + } catch (e) { + if (mounted) setState(() => error = e); + } finally { + if (mounted) setState(() => loading = false); + } + } + Future onTap() async { - switch (state) { - case SessionState.notStarted: - if (mounted) setState(() => _started = true); - case SessionState.selectedRole: - await showFutureLoadingDialog( - context: context, - future: () => room.joinActivity( - room.activityPlan!.roles[_selectedRoleId!]!, - ), - ); - if (mounted) setState(() {}); - case SessionState.notSelectedRole: - case SessionState.confirmedRole: - break; + if (state != SessionState.selectedRole) return; + if (room != null) { + await showFutureLoadingDialog( + context: context, + future: () => room!.joinActivity( + activity!.roles[_selectedRoleId!]!, + ), + ); + } else { + final resp = await showFutureLoadingDialog( + context: context, + future: () => parent!.launchActivityRoom( + activity!, + activity!.roles[_selectedRoleId!], + ), + ); + + if (!resp.isError) { + context.go("/rooms/spaces/${widget.parentId}/${resp.result}"); + } } } Future pingCourse() async { - if (room.courseParent == null) { + if (room?.courseParent == null) { throw Exception("Activity is not part of a course"); } - await room.courseParent!.sendTextEvent( + await room!.courseParent!.sendTextEvent( L10n.of(context).pingParticipantsNotification( - room.client.userID!.localpart ?? room.client.userID!, - room.getLocalizedDisplayname(MatrixLocals(L10n.of(context))), + room!.client.userID!.localpart ?? room!.client.userID!, + room!.getLocalizedDisplayname(MatrixLocals(L10n.of(context))), ), ); } diff --git a/lib/pangea/activity_sessions/activity_session_start/activity_sessions_start_view.dart b/lib/pangea/activity_sessions/activity_session_start/activity_sessions_start_view.dart index 7493f706d..d39e1e61b 100644 --- a/lib/pangea/activity_sessions/activity_session_start/activity_sessions_start_view.dart +++ b/lib/pangea/activity_sessions/activity_session_start/activity_sessions_start_view.dart @@ -8,10 +8,12 @@ import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart import 'package:fluffychat/pangea/activity_sessions/activity_session_start/activity_session_start_page.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_summary_widget.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; +import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import 'package:fluffychat/pangea/common/widgets/share_room_button.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/utils/stream_extension.dart'; import 'package:fluffychat/widgets/future_loading_dialog.dart'; +import 'package:fluffychat/widgets/matrix.dart'; class ActivitySessionStartView extends StatelessWidget { final ActivitySessionStartController controller; @@ -23,14 +25,28 @@ class ActivitySessionStartView extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); + final buttonStyle = ElevatedButton.styleFrom( + backgroundColor: theme.colorScheme.primaryContainer, + foregroundColor: theme.colorScheme.onPrimaryContainer, + padding: const EdgeInsets.all(8.0), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + ); + return StreamBuilder( - stream: controller.room.client.onRoomState.stream + stream: Matrix.of(context) + .client + .onRoomState + .stream .rateLimit(const Duration(seconds: 1)), builder: (context, snapshot) { return Scaffold( appBar: AppBar( leadingWidth: 52.0, - title: Text(controller.displayname), + title: controller.activity == null + ? null + : Text(controller.activity!.title), leading: Padding( padding: const EdgeInsets.only(left: 12.0), child: Center( @@ -41,168 +57,190 @@ class ActivitySessionStartView extends StatelessWidget { ), ), actions: [ - Padding( - padding: const EdgeInsets.only(right: 12.0), - child: SizedBox( - width: 40.0, - height: 40.0, - child: Center( - child: ShareRoomButton(room: controller.room), + if (controller.room != null) + Padding( + padding: const EdgeInsets.only(right: 12.0), + child: SizedBox( + width: 40.0, + height: 40.0, + child: Center( + child: ShareRoomButton(room: controller.room!), + ), ), ), - ), ], ), body: SafeArea( - child: Column( - children: [ - Expanded( - child: SingleChildScrollView( - child: Container( - constraints: const BoxConstraints( - maxWidth: 600.0, - ), - padding: const EdgeInsets.all(12.0), - child: Column( - spacing: 12.0, - children: [ - ActivitySummary( - room: controller.room, - showInstructions: controller.showInstructions, - toggleInstructions: controller.toggleInstructions, - onTapParticipant: controller.selectRole, - isParticipantSelected: - controller.isParticipantSelected, - canSelectParticipant: - controller.canSelectParticipant, - ), - ], - ), - ), - ), - ), - AnimatedSize( - duration: FluffyThemes.animationDuration, - child: Container( - decoration: BoxDecoration( - border: Border( - top: BorderSide(color: theme.dividerColor), - ), - color: theme.colorScheme.surface, - ), - padding: const EdgeInsets.all(24.0), - child: Column( - spacing: 16.0, - children: [ - Text( - controller.descriptionText, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - ), - textAlign: TextAlign.center, + child: controller.loading + ? const Center(child: CircularProgressIndicator.adaptive()) + : controller.error != null + ? Center( + child: ErrorIndicator( + message: L10n.of(context).activityNotFound, ), - if (controller.state == SessionState.confirmedRole) ...[ - if (controller.room.courseParent != null) - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: - theme.colorScheme.onPrimaryContainer, - padding: const EdgeInsets.all(8.0), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), + ) + : Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Container( + constraints: const BoxConstraints( + maxWidth: 600.0, ), - ), - onPressed: () => showFutureLoadingDialog( - context: context, - future: controller.pingCourse, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - L10n.of(context).pingParticipants, - ), - ], - ), - ), - if (controller.room.isRoomAdmin) ...[ - if (!controller.isBotRoomMember) - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: - theme.colorScheme.onPrimaryContainer, - padding: const EdgeInsets.all(8.0), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - ), - onPressed: () => showFutureLoadingDialog( - context: context, - future: () => controller.room - .invite(BotName.byEnvironment), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, + padding: const EdgeInsets.all(12.0), + child: Column( + spacing: 12.0, children: [ - Text(L10n.of(context).playWithBot), + ActivitySummary( + activity: controller.activity!, + room: controller.room, + showInstructions: + controller.showInstructions, + toggleInstructions: + controller.toggleInstructions, + onTapParticipant: controller.selectRole, + isParticipantSelected: + controller.isParticipantSelected, + canSelectParticipant: + controller.canSelectParticipant, + ), ], ), ), - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: - theme.colorScheme.onPrimaryContainer, - padding: const EdgeInsets.all(8.0), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), + ), + ), + AnimatedSize( + duration: FluffyThemes.animationDuration, + child: Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide(color: theme.dividerColor), ), + color: theme.colorScheme.surface, ), - onPressed: () => context.go( - "/rooms/${controller.room.id}/invite", - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, + padding: const EdgeInsets.all(24.0), + child: Column( + spacing: 16.0, children: [ - Text(L10n.of(context).inviteFriends), + if (controller.descriptionText != null) + Text( + controller.descriptionText!, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + textAlign: TextAlign.center, + ), + if (controller.state == + SessionState.notStarted) ...[ + ElevatedButton( + style: buttonStyle, + onPressed: () => context.go( + "/rooms/spaces/${controller.widget.parentId}/activity/${controller.widget.activityId}?new=true", + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + L10n.of(context).startNewSession, + ), + ], + ), + ), + ElevatedButton( + style: buttonStyle, + onPressed: null, + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + L10n.of(context).joinOpenSession, + ), + ], + ), + ), + ] else if (controller.state == + SessionState.confirmedRole) ...[ + if (controller.room!.courseParent != null) + ElevatedButton( + style: buttonStyle, + onPressed: () => + showFutureLoadingDialog( + context: context, + future: controller.pingCourse, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + L10n.of(context).pingParticipants, + ), + ], + ), + ), + if (controller.room!.isRoomAdmin) ...[ + if (!controller.isBotRoomMember) + ElevatedButton( + style: buttonStyle, + onPressed: () => + showFutureLoadingDialog( + context: context, + future: () => controller.room! + .invite(BotName.byEnvironment), + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + L10n.of(context).playWithBot, + ), + ], + ), + ), + ElevatedButton( + style: buttonStyle, + onPressed: () => context.go( + "/rooms/${controller.room!.id}/invite", + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + L10n.of(context).inviteFriends, + ), + ], + ), + ), + ], + ] else + ElevatedButton( + style: buttonStyle, + onPressed: controller.enableButtons + ? controller.onTap + : null, + child: Row( + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Text( + controller.room?.isRoomAdmin ?? true + ? L10n.of(context).start + : L10n.of(context).confirm, + ), + ], + ), + ), ], ), ), - ], - ] else - ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: - theme.colorScheme.onPrimaryContainer, - padding: const EdgeInsets.all(8.0), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - ), - onPressed: controller.enableButtons - ? controller.onTap - : null, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(controller.buttonText), - ], - ), ), - ], - ), - ), - ), - ], - ), + ], + ), ), ); }, diff --git a/lib/pangea/activity_sessions/activity_summary_widget.dart b/lib/pangea/activity_sessions/activity_summary_widget.dart index 873cb96ac..2c0025841 100644 --- a/lib/pangea/activity_sessions/activity_summary_widget.dart +++ b/lib/pangea/activity_sessions/activity_summary_widget.dart @@ -5,15 +5,16 @@ import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; +import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_participant_list.dart'; import 'package:fluffychat/pangea/activity_sessions/activity_role_model.dart'; -import 'package:fluffychat/pangea/activity_sessions/activity_room_extension.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card_row.dart'; +import 'package:fluffychat/pangea/activity_sessions/activity_session_details_row.dart'; import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart'; import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; class ActivitySummary extends StatelessWidget { - final Room room; + final ActivityPlanModel activity; + final Room? room; final bool showInstructions; final VoidCallback toggleInstructions; @@ -25,22 +26,18 @@ class ActivitySummary extends StatelessWidget { const ActivitySummary({ super.key, - required this.room, + required this.activity, required this.showInstructions, required this.toggleInstructions, this.onTapParticipant, this.canSelectParticipant, this.isParticipantSelected, this.getParticipantOpacity, + this.room, }); @override Widget build(BuildContext context) { - final activity = room.activityPlan; - if (activity == null) { - return const SizedBox(); - } - final theme = Theme.of(context); return Center( child: Container( @@ -49,21 +46,15 @@ class ActivitySummary extends StatelessWidget { maxWidth: FluffyThemes.columnWidth * 1.5, ), child: Column( - spacing: 12.0, + spacing: 4.0, children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: ImageByUrl( - imageUrl: activity.imageURL, - width: 80.0, - borderRadius: BorderRadius.circular(20), - ), - ), - Text( - activity.learningObjective, - style: const TextStyle(fontSize: 12.0), + ImageByUrl( + imageUrl: activity.imageURL, + width: 80.0, + borderRadius: BorderRadius.circular(20), ), ActivityParticipantList( + activity: activity, room: room, onTap: onTapParticipant, canSelect: canSelectParticipant, @@ -78,60 +69,61 @@ class ActivitySummary extends StatelessWidget { spacing: 4.0, mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.symmetric( - vertical: 6.0, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + Stack( + alignment: Alignment.bottomRight, + children: [ + Text( + activity.description, + style: const TextStyle( + fontSize: 12.0, + ), + ), + TextButton( + onPressed: toggleInstructions, + style: TextButton.styleFrom( + minimumSize: Size.zero, + padding: EdgeInsets.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0.0), + ), + backgroundColor: theme.colorScheme.surface, + ), + child: Text( + showInstructions + ? L10n.of(context).less + : L10n.of(context).more, + style: TextStyle( + fontSize: 12.0, + color: theme.colorScheme.primary, + ), + ), + ), + ], + ), + if (showInstructions) ...[ + Row( + spacing: 8.0, + mainAxisSize: MainAxisSize.min, children: [ + Text( + activity.req.mode, + style: const TextStyle(fontSize: 12.0), + ), Row( - spacing: 8.0, + spacing: 4.0, mainAxisSize: MainAxisSize.min, children: [ + const Icon(Icons.school, size: 12.0), Text( - activity.req.mode, + activity.req.cefrLevel.string, style: const TextStyle(fontSize: 12.0), ), - Row( - spacing: 4.0, - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.school, size: 12.0), - Text( - activity.req.cefrLevel.string, - style: const TextStyle(fontSize: 12.0), - ), - ], - ), ], ), - GestureDetector( - onTap: toggleInstructions, - child: Row( - spacing: 4.0, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - showInstructions - ? L10n.of(context).hideInstructions - : L10n.of(context).seeInstructions, - style: const TextStyle(fontSize: 12.0), - ), - Icon( - showInstructions - ? Icons.arrow_drop_up - : Icons.arrow_drop_down, - size: 12.0, - ), - ], - ), - ), ], ), - ), - if (showInstructions) ...[ - ActivitySuggestionCardRow( + ActivitySessionDetailsRow( icon: Symbols.target, iconSize: 16.0, child: Text( @@ -139,7 +131,7 @@ class ActivitySummary extends StatelessWidget { style: const TextStyle(fontSize: 12.0), ), ), - ActivitySuggestionCardRow( + ActivitySessionDetailsRow( icon: Symbols.steps, iconSize: 16.0, child: Text( @@ -147,7 +139,7 @@ class ActivitySummary extends StatelessWidget { style: const TextStyle(fontSize: 12.0), ), ), - ActivitySuggestionCardRow( + ActivitySessionDetailsRow( icon: Symbols.dictionary, iconSize: 16.0, child: Wrap( diff --git a/lib/pangea/activity_suggestions/activity_plan_repo.dart b/lib/pangea/activity_suggestions/activity_plan_repo.dart index 9e841d547..a33efce3e 100644 --- a/lib/pangea/activity_suggestions/activity_plan_repo.dart +++ b/lib/pangea/activity_suggestions/activity_plan_repo.dart @@ -1,79 +1,79 @@ -import 'dart:convert'; +// import 'dart:convert'; -import 'package:get_storage/get_storage.dart'; -import 'package:http/http.dart'; +// import 'package:get_storage/get_storage.dart'; +// import 'package:http/http.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/network/requests.dart'; -import 'package:fluffychat/pangea/common/network/urls.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +// import 'package:fluffychat/pangea/common/config/environment.dart'; +// import 'package:fluffychat/pangea/common/network/requests.dart'; +// import 'package:fluffychat/pangea/common/network/urls.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -class ActivityPlanRepo { - static final GetStorage _activityPlanStorage = - GetStorage('activity_plan_by_id_storage'); +// class ActivityPlanRepo { +// static final GetStorage _activityPlanStorage = +// GetStorage('activity_plan_by_id_storage'); - static ActivityPlanModel? getCached(String id) { - final cachedJson = _activityPlanStorage.read(id); - if (cachedJson == null) return null; +// static ActivityPlanModel? getCached(String id) { +// final cachedJson = _activityPlanStorage.read(id); +// if (cachedJson == null) return null; - try { - return ActivityPlanModel.fromJson(cachedJson); - } catch (e) { - _removeCached(id); - return null; - } - } +// try { +// return ActivityPlanModel.fromJson(cachedJson); +// } catch (e) { +// _removeCached(id); +// return null; +// } +// } - static Future _setCached(ActivityPlanModel response) => - _activityPlanStorage.write(response.activityId, response.toJson()); +// static Future _setCached(ActivityPlanModel response) => +// _activityPlanStorage.write(response.activityId, response.toJson()); - static Future _removeCached(String id) => - _activityPlanStorage.remove(id); +// static Future _removeCached(String id) => +// _activityPlanStorage.remove(id); - static Future set(ActivityPlanModel activity) => _setCached(activity); +// static Future set(ActivityPlanModel activity) => _setCached(activity); - static Future get(String id) async { - final cached = getCached(id); - if (cached != null) return cached; +// static Future get(String id) async { +// final cached = getCached(id); +// if (cached != null) return cached; - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); +// final Requests req = Requests( +// choreoApiKey: Environment.choreoApiKey, +// accessToken: MatrixState.pangeaController.userController.accessToken, +// ); - final Response res = await req.get( - url: "${PApiUrls.activityPlan}/$id", - ); +// final Response res = await req.get( +// url: "${PApiUrls.activityPlan}/$id", +// ); - final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); - final response = ActivityPlanModel.fromJson(decodedBody["plan"]); +// final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); +// final response = ActivityPlanModel.fromJson(decodedBody["plan"]); - _setCached(response); - return response; - } +// _setCached(response); +// return response; +// } - static Future update( - ActivityPlanModel update, - ) async { - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); +// static Future update( +// ActivityPlanModel update, +// ) async { +// final Requests req = Requests( +// choreoApiKey: Environment.choreoApiKey, +// accessToken: MatrixState.pangeaController.userController.accessToken, +// ); - final Response res = await req.patch( - url: "${PApiUrls.activityPlan}/${update.activityId}", - body: update.toJson(), - ); +// final Response res = await req.patch( +// url: "${PApiUrls.activityPlan}/${update.activityId}", +// body: update.toJson(), +// ); - final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); - final response = ActivityPlanModel.fromJson(decodedBody["plan"]); +// final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); +// final response = ActivityPlanModel.fromJson(decodedBody["plan"]); - _removeCached(update.activityId); - _setCached(response); +// _removeCached(update.activityId); +// _setCached(response); - return response; - } +// return response; +// } - static Future remove(String id) => _removeCached(id); -} +// static Future remove(String id) => _removeCached(id); +// } diff --git a/lib/pangea/activity_suggestions/activity_plan_search_repo.dart b/lib/pangea/activity_suggestions/activity_plan_search_repo.dart index fdd7dcbf7..b25a77d56 100644 --- a/lib/pangea/activity_suggestions/activity_plan_search_repo.dart +++ b/lib/pangea/activity_suggestions/activity_plan_search_repo.dart @@ -1,102 +1,102 @@ -import 'dart:convert'; +// import 'dart:convert'; -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:get_storage/get_storage.dart'; -import 'package:http/http.dart'; +// import 'package:get_storage/get_storage.dart'; +// import 'package:http/http.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_response.dart'; -import 'package:fluffychat/pangea/common/config/environment.dart'; -import 'package:fluffychat/pangea/common/network/requests.dart'; -import 'package:fluffychat/pangea/common/network/urls.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_response.dart'; +// import 'package:fluffychat/pangea/common/config/environment.dart'; +// import 'package:fluffychat/pangea/common/network/requests.dart'; +// import 'package:fluffychat/pangea/common/network/urls.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -class ActivitySearchRepo { - static final GetStorage _activityPlanStorage = - GetStorage('activity_plan_search_storage'); +// class ActivitySearchRepo { +// static final GetStorage _activityPlanStorage = +// GetStorage('activity_plan_search_storage'); - static void set( - String storageKey, - ActivityPlanResponseWrapper wrappedResponse, - ) { - _activityPlanStorage.write(storageKey, wrappedResponse.toJson()); - } +// static void set( +// String storageKey, +// ActivityPlanResponseWrapper wrappedResponse, +// ) { +// _activityPlanStorage.write(storageKey, wrappedResponse.toJson()); +// } - static Future get( - ActivityPlanRequest request, - ) async { - final storageKey = "${request.storageKey}_wrapper"; - final cachedJson = _activityPlanStorage.read(storageKey); - if (cachedJson != null) { - ActivityPlanResponseWrapper? cached; - try { - cached = ActivityPlanResponseWrapper.fromJson(cachedJson); - } catch (e) { - _activityPlanStorage.remove(storageKey); - } +// static Future get( +// ActivityPlanRequest request, +// ) async { +// final storageKey = "${request.storageKey}_wrapper"; +// final cachedJson = _activityPlanStorage.read(storageKey); +// if (cachedJson != null) { +// ActivityPlanResponseWrapper? cached; +// try { +// cached = ActivityPlanResponseWrapper.fromJson(cachedJson); +// } catch (e) { +// _activityPlanStorage.remove(storageKey); +// } - if (cached is ActivityPlanResponseWrapper) { - return cached; - } - } +// if (cached is ActivityPlanResponseWrapper) { +// return cached; +// } +// } - final Requests req = Requests( - choreoApiKey: Environment.choreoApiKey, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); +// final Requests req = Requests( +// choreoApiKey: Environment.choreoApiKey, +// accessToken: MatrixState.pangeaController.userController.accessToken, +// ); - Response? res; - try { - res = await req.post( - url: PApiUrls.activityPlanSearch, - body: request.toJson(), - ); - } catch (err) { - debugPrint("err: $err, err is http response: ${err is Response}"); - if (err is Response) { - return ActivityPlanResponseWrapper( - response: ActivityPlanResponse(activityPlans: []), - statusCode: err.statusCode, - ); - } - } +// Response? res; +// try { +// res = await req.post( +// url: PApiUrls.activityPlanSearch, +// body: request.toJson(), +// ); +// } catch (err) { +// debugPrint("err: $err, err is http response: ${err is Response}"); +// if (err is Response) { +// return ActivityPlanResponseWrapper( +// response: ActivityPlanResponse(activityPlans: []), +// statusCode: err.statusCode, +// ); +// } +// } - final decodedBody = jsonDecode(utf8.decode(res!.bodyBytes)); - final response = ActivityPlanResponse.fromJson(decodedBody); - final wrappedResponse = ActivityPlanResponseWrapper( - response: response, - statusCode: res.statusCode, - ); +// final decodedBody = jsonDecode(utf8.decode(res!.bodyBytes)); +// final response = ActivityPlanResponse.fromJson(decodedBody); +// final wrappedResponse = ActivityPlanResponseWrapper( +// response: response, +// statusCode: res.statusCode, +// ); - if (res.statusCode == 200) { - set(storageKey, wrappedResponse); - } +// if (res.statusCode == 200) { +// set(storageKey, wrappedResponse); +// } - return wrappedResponse; - } -} +// return wrappedResponse; +// } +// } -class ActivityPlanResponseWrapper { - final ActivityPlanResponse response; - final int statusCode; +// class ActivityPlanResponseWrapper { +// final ActivityPlanResponse response; +// final int statusCode; - ActivityPlanResponseWrapper({ - required this.response, - required this.statusCode, - }); +// ActivityPlanResponseWrapper({ +// required this.response, +// required this.statusCode, +// }); - factory ActivityPlanResponseWrapper.fromJson(Map json) { - return ActivityPlanResponseWrapper( - response: json['activity_plan_response'].fromJson, - statusCode: json['activity_response_status'], - ); - } +// factory ActivityPlanResponseWrapper.fromJson(Map json) { +// return ActivityPlanResponseWrapper( +// response: json['activity_plan_response'].fromJson, +// statusCode: json['activity_response_status'], +// ); +// } - Map toJson() { - return { - 'activity_plan_response': response.toJson(), - 'activity_response_status': statusCode, - }; - } -} +// Map toJson() { +// return { +// 'activity_plan_response': response.toJson(), +// 'activity_response_status': statusCode, +// }; +// } +// } diff --git a/lib/pangea/activity_suggestions/activity_search_enum.dart b/lib/pangea/activity_suggestions/activity_search_enum.dart index 970d9bdca..9ab581f97 100644 --- a/lib/pangea/activity_suggestions/activity_search_enum.dart +++ b/lib/pangea/activity_suggestions/activity_search_enum.dart @@ -1,51 +1,51 @@ -import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; -/// 200: All activities successfully retrieved -/// 202: Waiting for activities to load -/// 504: Timeout -/// Other: Error -enum ActivitySearchEnum { - complete, - waiting, - timeout, - error, -} +// /// 200: All activities successfully retrieved +// /// 202: Waiting for activities to load +// /// 504: Timeout +// /// Other: Error +// enum ActivitySearchEnum { +// complete, +// waiting, +// timeout, +// error, +// } -extension ActivitySearchExtension on ActivitySearchEnum { - ActivitySearchEnum fromCode(int statusCode) { - switch (statusCode) { - case 200: - return ActivitySearchEnum.complete; - case 202: - return ActivitySearchEnum.waiting; - case 504: - return ActivitySearchEnum.timeout; - default: - return ActivitySearchEnum.error; - } - } +// extension ActivitySearchExtension on ActivitySearchEnum { +// ActivitySearchEnum fromCode(int statusCode) { +// switch (statusCode) { +// case 200: +// return ActivitySearchEnum.complete; +// case 202: +// return ActivitySearchEnum.waiting; +// case 504: +// return ActivitySearchEnum.timeout; +// default: +// return ActivitySearchEnum.error; +// } +// } - bool get hideCards { - switch (this) { - case ActivitySearchEnum.complete: - case ActivitySearchEnum.waiting: - return false; - case ActivitySearchEnum.timeout: - case ActivitySearchEnum.error: - return true; - } - } +// bool get hideCards { +// switch (this) { +// case ActivitySearchEnum.complete: +// case ActivitySearchEnum.waiting: +// return false; +// case ActivitySearchEnum.timeout: +// case ActivitySearchEnum.error: +// return true; +// } +// } - String message(L10n l10n) { - switch (this) { - case ActivitySearchEnum.waiting: - return l10n.activitySuggestionTimeoutMessage; - case ActivitySearchEnum.timeout: - return l10n.generatingNewActivities; - case ActivitySearchEnum.error: - return l10n.errorFetchingActivitiesMessage; - default: - return ''; - } - } -} +// String message(L10n l10n) { +// switch (this) { +// case ActivitySearchEnum.waiting: +// return l10n.activitySuggestionTimeoutMessage; +// case ActivitySearchEnum.timeout: +// return l10n.generatingNewActivities; +// case ActivitySearchEnum.error: +// return l10n.errorFetchingActivitiesMessage; +// default: +// return ''; +// } +// } +// } diff --git a/lib/pangea/activity_suggestions/activity_search_request.dart b/lib/pangea/activity_suggestions/activity_search_request.dart index 4ce95f7dc..1b40341b4 100644 --- a/lib/pangea/activity_suggestions/activity_search_request.dart +++ b/lib/pangea/activity_suggestions/activity_search_request.dart @@ -1,38 +1,38 @@ -import 'package:fluffychat/pangea/activity_generator/media_enum.dart'; -import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; +// import 'package:fluffychat/pangea/activity_generator/media_enum.dart'; +// import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; -class ActivitySearchRequest { - final String targetLanguage; - final String languageOfInstructions; - final LanguageLevelTypeEnum? languageLevel; +// class ActivitySearchRequest { +// final String targetLanguage; +// final String languageOfInstructions; +// final LanguageLevelTypeEnum? languageLevel; - final String? mode; - final String? learningObjective; - final String? topic; - final MediaEnum? media; - final int? numberOfParticipants; +// final String? mode; +// final String? learningObjective; +// final String? topic; +// final MediaEnum? media; +// final int? numberOfParticipants; - ActivitySearchRequest({ - required this.targetLanguage, - required this.languageOfInstructions, - this.mode, - this.learningObjective, - this.topic, - this.media, - this.numberOfParticipants = 2, - this.languageLevel = LanguageLevelTypeEnum.preA1, - }); +// ActivitySearchRequest({ +// required this.targetLanguage, +// required this.languageOfInstructions, +// this.mode, +// this.learningObjective, +// this.topic, +// this.media, +// this.numberOfParticipants = 2, +// this.languageLevel = LanguageLevelTypeEnum.preA1, +// }); - Map toJson() { - return { - 'target_language': targetLanguage, - 'language_of_instructions': languageOfInstructions, - 'language_level': languageLevel, - 'mode': mode, - 'objective': learningObjective, - 'topic': topic, - 'media': media, - 'number_of_participants': numberOfParticipants, - }; - } -} +// Map toJson() { +// return { +// 'target_language': targetLanguage, +// 'language_of_instructions': languageOfInstructions, +// 'language_level': languageLevel, +// 'mode': mode, +// 'objective': learningObjective, +// 'topic': topic, +// 'media': media, +// 'number_of_participants': numberOfParticipants, +// }; +// } +// } diff --git a/lib/pangea/activity_suggestions/activity_suggestion_card.dart b/lib/pangea/activity_suggestions/activity_suggestion_card.dart index 984d69adb..68023526d 100644 --- a/lib/pangea/activity_suggestions/activity_suggestion_card.dart +++ b/lib/pangea/activity_suggestions/activity_suggestion_card.dart @@ -3,11 +3,10 @@ import 'package:flutter/material.dart'; import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart'; class ActivitySuggestionCard extends StatelessWidget { - final ActivityPlannerBuilderState controller; + final ActivityPlanModel activity; final VoidCallback onPressed; final double width; final double height; @@ -18,7 +17,7 @@ class ActivitySuggestionCard extends StatelessWidget { const ActivitySuggestionCard({ super.key, - required this.controller, + required this.activity, required this.onPressed, required this.width, required this.height, @@ -27,8 +26,6 @@ class ActivitySuggestionCard extends StatelessWidget { this.iconSize, }); - ActivityPlanModel get activity => controller.updatedActivity; - @override Widget build(BuildContext context) { final theme = Theme.of(context); diff --git a/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart b/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart index 567ef6cde..655ecd7bc 100644 --- a/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart +++ b/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart @@ -1,312 +1,312 @@ -import 'dart:async'; +// import 'dart:async'; -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:collection/collection.dart'; -import 'package:go_router/go_router.dart'; +// import 'package:collection/collection.dart'; +// import 'package:go_router/go_router.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_generator/activity_plan_generation_repo.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog_content.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; -import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; +// import 'package:fluffychat/config/themes.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_generator/activity_plan_generation_repo.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog_content.dart'; +// import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +// import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; +// import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; -class ActivitySuggestionDialog extends StatefulWidget { - final ActivityPlannerBuilderState controller; - final String buttonText; +// class ActivitySuggestionDialog extends StatefulWidget { +// final ActivityPlannerBuilderState controller; +// final String buttonText; - final Function(ActivityPlanModel)? replaceActivity; +// final Function(ActivityPlanModel)? replaceActivity; - const ActivitySuggestionDialog({ - required this.controller, - required this.buttonText, - this.replaceActivity, - super.key, - }); +// const ActivitySuggestionDialog({ +// required this.controller, +// required this.buttonText, +// this.replaceActivity, +// super.key, +// }); - @override - ActivitySuggestionDialogState createState() => - ActivitySuggestionDialogState(); -} +// @override +// ActivitySuggestionDialogState createState() => +// ActivitySuggestionDialogState(); +// } -class ActivitySuggestionDialogState extends State { - bool _loading = false; - String? _regenerateError; - String? _launchError; +// class ActivitySuggestionDialogState extends State { +// bool _loading = false; +// String? _regenerateError; +// String? _launchError; - double get _width => FluffyThemes.isColumnMode(context) - ? 400.0 - : MediaQuery.of(context).size.width; +// double get _width => FluffyThemes.isColumnMode(context) +// ? 400.0 +// : MediaQuery.of(context).size.width; - StreamSubscription? _stateSubscription; +// StreamSubscription? _stateSubscription; - @override - void initState() { - super.initState(); - _stateSubscription = widget.controller.stateStream.stream.listen((state) { - if (mounted) setState(() {}); - }); - } +// @override +// void initState() { +// super.initState(); +// _stateSubscription = widget.controller.stateStream.stream.listen((state) { +// if (mounted) setState(() {}); +// }); +// } - @override - void dispose() { - _stateSubscription?.cancel(); - super.dispose(); - } +// @override +// void dispose() { +// _stateSubscription?.cancel(); +// super.dispose(); +// } - Future launchActivity() async { - try { - if (!widget.controller.room.isSpace) { - throw Exception( - "Cannot launch activity in a non-space room", - ); - } +// Future launchActivity() async { +// try { +// if (!widget.controller.room.isSpace) { +// throw Exception( +// "Cannot launch activity in a non-space room", +// ); +// } - setState(() { - _loading = true; - _regenerateError = null; - _launchError = null; - }); +// setState(() { +// _loading = true; +// _regenerateError = null; +// _launchError = null; +// }); - final ids = await widget.controller.launchToSpace(); - ids.length == 1 - ? context - .go("/rooms/spaces/${widget.controller.room.id}/${ids.first}") - : context.go("/rooms/spaces/${widget.controller.room.id}/details"); - Navigator.of(context).pop(); - } catch (e, s) { - _launchError = L10n.of(context).errorLaunchActivityMessage; - ErrorHandler.logError( - e: e, - s: s, - data: { - "request": widget.controller.updatedRequest.toJson(), - }, - ); - } finally { - if (mounted) { - setState(() { - _loading = false; - }); - } - } - } +// final ids = await widget.controller.launchToSpace(); +// ids.length == 1 +// ? context +// .go("/rooms/spaces/${widget.controller.room.id}/${ids.first}") +// : context.go("/rooms/spaces/${widget.controller.room.id}/details"); +// Navigator.of(context).pop(); +// } catch (e, s) { +// _launchError = L10n.of(context).errorLaunchActivityMessage; +// ErrorHandler.logError( +// e: e, +// s: s, +// data: { +// "request": widget.controller.updatedRequest.toJson(), +// }, +// ); +// } finally { +// if (mounted) { +// setState(() { +// _loading = false; +// }); +// } +// } +// } - Future onRegenerate() async { - setState(() { - _loading = true; - _regenerateError = null; - _launchError = null; - }); +// Future onRegenerate() async { +// setState(() { +// _loading = true; +// _regenerateError = null; +// _launchError = null; +// }); - try { - final resp = await ActivityPlanGenerationRepo.get( - widget.controller.updatedRequest, - force: true, - ); - final plan = resp.activityPlans.firstOrNull; - if (plan == null) { - throw Exception("No activity plan generated"); - } +// try { +// final resp = await ActivityPlanGenerationRepo.get( +// widget.controller.updatedRequest, +// force: true, +// ); +// final plan = resp.activityPlans.firstOrNull; +// if (plan == null) { +// throw Exception("No activity plan generated"); +// } - widget.replaceActivity?.call(plan); - await widget.controller.overrideActivity(plan); - } catch (e, s) { - _regenerateError = L10n.of(context).errorRegenerateActivityMessage; - ErrorHandler.logError( - e: e, - s: s, - data: { - "request": widget.controller.updatedRequest.toJson(), - }, - ); - return; - } finally { - if (mounted) { - setState(() { - _loading = false; - }); - } - } - } +// widget.replaceActivity?.call(plan); +// await widget.controller.overrideActivity(plan); +// } catch (e, s) { +// _regenerateError = L10n.of(context).errorRegenerateActivityMessage; +// ErrorHandler.logError( +// e: e, +// s: s, +// data: { +// "request": widget.controller.updatedRequest.toJson(), +// }, +// ); +// return; +// } finally { +// if (mounted) { +// setState(() { +// _loading = false; +// }); +// } +// } +// } - void _resetActivity() { - widget.controller.resetActivity(); - setState(() { - _loading = false; - _regenerateError = null; - _launchError = null; - }); - } +// void _resetActivity() { +// widget.controller.resetActivity(); +// setState(() { +// _loading = false; +// _regenerateError = null; +// _launchError = null; +// }); +// } - ButtonStyle get buttonStyle => ElevatedButton.styleFrom( - backgroundColor: Theme.of(context).colorScheme.primaryContainer, - foregroundColor: Theme.of(context).colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ); +// ButtonStyle get buttonStyle => ElevatedButton.styleFrom( +// backgroundColor: Theme.of(context).colorScheme.primaryContainer, +// foregroundColor: Theme.of(context).colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ); - double get width => FluffyThemes.isColumnMode(context) - ? 400.0 - : MediaQuery.of(context).size.width; +// double get width => FluffyThemes.isColumnMode(context) +// ? 400.0 +// : MediaQuery.of(context).size.width; - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final buttonStyle = this.buttonStyle; +// @override +// Widget build(BuildContext context) { +// final theme = Theme.of(context); +// final buttonStyle = this.buttonStyle; - final body = Stack( - alignment: Alignment.topCenter, - children: [ - DecoratedBox( - decoration: BoxDecoration( - color: theme.colorScheme.surface, - ), - child: Builder( - builder: (context) { - if (_regenerateError != null || _launchError != null) { - return Center( - child: Column( - spacing: 16.0, - mainAxisSize: MainAxisSize.min, - children: [ - ErrorIndicator( - message: _regenerateError ?? _launchError!, - ), - if (_regenerateError != null) - Row( - spacing: 8.0, - mainAxisSize: MainAxisSize.min, - children: [ - ElevatedButton( - onPressed: onRegenerate, - style: buttonStyle, - child: Text(L10n.of(context).tryAgain), - ), - ElevatedButton( - onPressed: _resetActivity, - style: buttonStyle, - child: Text(L10n.of(context).reset), - ), - ], - ) - else - ElevatedButton( - onPressed: launchActivity, - style: buttonStyle, - child: Text(L10n.of(context).tryAgain), - ), - ], - ), - ); - } +// final body = Stack( +// alignment: Alignment.topCenter, +// children: [ +// DecoratedBox( +// decoration: BoxDecoration( +// color: theme.colorScheme.surface, +// ), +// child: Builder( +// builder: (context) { +// if (_regenerateError != null || _launchError != null) { +// return Center( +// child: Column( +// spacing: 16.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// ErrorIndicator( +// message: _regenerateError ?? _launchError!, +// ), +// if (_regenerateError != null) +// Row( +// spacing: 8.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// ElevatedButton( +// onPressed: onRegenerate, +// style: buttonStyle, +// child: Text(L10n.of(context).tryAgain), +// ), +// ElevatedButton( +// onPressed: _resetActivity, +// style: buttonStyle, +// child: Text(L10n.of(context).reset), +// ), +// ], +// ) +// else +// ElevatedButton( +// onPressed: launchActivity, +// style: buttonStyle, +// child: Text(L10n.of(context).tryAgain), +// ), +// ], +// ), +// ); +// } - if (_loading) { - return const Center( - child: CircularProgressIndicator.adaptive(), - ); - } +// if (_loading) { +// return const Center( +// child: CircularProgressIndicator.adaptive(), +// ); +// } - return Form( - key: widget.controller.formKey, - child: ActivitySuggestionDialogContent(controller: this), - ); - }, - ), - ), - Positioned( - top: 4.0, - left: 4.0, - child: IconButton.filled( - style: IconButton.styleFrom( - backgroundColor: theme.colorScheme.surface.withAlpha(170), - ), - icon: Icon( - Icons.close_outlined, - color: theme.colorScheme.onSurface, - ), - onPressed: Navigator.of(context).pop, - tooltip: L10n.of(context).close, - ), - ), - ], - ); +// return Form( +// key: widget.controller.formKey, +// child: ActivitySuggestionDialogContent(controller: this), +// ); +// }, +// ), +// ), +// Positioned( +// top: 4.0, +// left: 4.0, +// child: IconButton.filled( +// style: IconButton.styleFrom( +// backgroundColor: theme.colorScheme.surface.withAlpha(170), +// ), +// icon: Icon( +// Icons.close_outlined, +// color: theme.colorScheme.onSurface, +// ), +// onPressed: Navigator.of(context).pop, +// tooltip: L10n.of(context).close, +// ), +// ), +// ], +// ); - return FullWidthDialog( - dialogContent: body, - maxWidth: _width, - maxHeight: 650.0, - ); - } -} +// return FullWidthDialog( +// dialogContent: body, +// maxWidth: _width, +// maxHeight: 650.0, +// ); +// } +// } -class NumberCounter extends StatelessWidget { - final int count; - final Function(int) update; +// class NumberCounter extends StatelessWidget { +// final int count; +// final Function(int) update; - final int? min; - final int? max; +// final int? min; +// final int? max; - const NumberCounter({ - super.key, - required this.count, - required this.update, - this.min, - this.max, - }); +// const NumberCounter({ +// super.key, +// required this.count, +// required this.update, +// this.min, +// this.max, +// }); - @override - Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12.0), - color: Theme.of(context).colorScheme.surfaceContainerHighest, - ), - child: Row( - spacing: 4.0, - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - icon: const Icon(Icons.remove), - iconSize: 24.0, - style: IconButton.styleFrom( - padding: const EdgeInsets.all(0.0), - ), - onPressed: min == null || count - 1 >= min! - ? () { - if (count > 0) { - update(count - 1); - } - } - : null, - ), - Text( - count.toString(), - style: const TextStyle( - fontSize: 16.0, - ), - ), - IconButton( - icon: const Icon(Icons.add), - iconSize: 24.0, - style: max == null || count + 1 <= max! - ? IconButton.styleFrom( - padding: const EdgeInsets.all(0.0), - ) - : null, - onPressed: max == null || count + 1 <= max! - ? () { - update(count + 1); - } - : null, - ), - ], - ), - ); - } -} +// @override +// Widget build(BuildContext context) { +// return Container( +// decoration: BoxDecoration( +// borderRadius: BorderRadius.circular(12.0), +// color: Theme.of(context).colorScheme.surfaceContainerHighest, +// ), +// child: Row( +// spacing: 4.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// IconButton( +// icon: const Icon(Icons.remove), +// iconSize: 24.0, +// style: IconButton.styleFrom( +// padding: const EdgeInsets.all(0.0), +// ), +// onPressed: min == null || count - 1 >= min! +// ? () { +// if (count > 0) { +// update(count - 1); +// } +// } +// : null, +// ), +// Text( +// count.toString(), +// style: const TextStyle( +// fontSize: 16.0, +// ), +// ), +// IconButton( +// icon: const Icon(Icons.add), +// iconSize: 24.0, +// style: max == null || count + 1 <= max! +// ? IconButton.styleFrom( +// padding: const EdgeInsets.all(0.0), +// ) +// : null, +// onPressed: max == null || count + 1 <= max! +// ? () { +// update(count + 1); +// } +// : null, +// ), +// ], +// ), +// ); +// } +// } diff --git a/lib/pangea/activity_suggestions/activity_suggestion_dialog_content.dart b/lib/pangea/activity_suggestions/activity_suggestion_dialog_content.dart index 4a8643985..5242a8d7a 100644 --- a/lib/pangea/activity_suggestions/activity_suggestion_dialog_content.dart +++ b/lib/pangea/activity_suggestions/activity_suggestion_dialog_content.dart @@ -1,656 +1,656 @@ -// ignore_for_file: depend_on_referenced_packages +// // ignore_for_file: depend_on_referenced_packages -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:collection/collection.dart'; -import 'package:material_symbols_icons/symbols.dart'; +// import 'package:collection/collection.dart'; +// import 'package:material_symbols_icons/symbols.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card_row.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; -import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart'; -import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart'; -import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; -import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; -import 'package:fluffychat/widgets/avatar.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card_row.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; +// import 'package:fluffychat/pangea/chat_settings/widgets/language_level_dropdown.dart'; +// import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart'; +// import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; +// import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; +// import 'package:fluffychat/widgets/avatar.dart'; -class ActivitySuggestionDialogContent extends StatelessWidget { - final ActivitySuggestionDialogState controller; +// class ActivitySuggestionDialogContent extends StatelessWidget { +// final ActivitySuggestionDialogState controller; - const ActivitySuggestionDialogContent({ - super.key, - required this.controller, - }); +// const ActivitySuggestionDialogContent({ +// super.key, +// required this.controller, +// }); - @override - Widget build(BuildContext context) { - switch (controller.widget.controller.launchState) { - case ActivityLaunchState.base: - return _ActivitySuggestionBaseContent(controller: controller); - case ActivityLaunchState.editing: - return _ActivitySuggestionEditContent(controller: controller); - case ActivityLaunchState.launching: - return _ActivitySuggestionLaunchContent(controller: controller); - } - } -} +// @override +// Widget build(BuildContext context) { +// switch (controller.widget.controller.launchState) { +// case ActivityLaunchState.base: +// return _ActivitySuggestionBaseContent(controller: controller); +// case ActivityLaunchState.editing: +// return _ActivitySuggestionEditContent(controller: controller); +// case ActivityLaunchState.launching: +// return _ActivitySuggestionLaunchContent(controller: controller); +// } +// } +// } -class _ActivitySuggestionDialogImage extends StatelessWidget { - final ActivityPlannerBuilderState activityController; - final double width; +// class _ActivitySuggestionDialogImage extends StatelessWidget { +// final ActivityPlannerBuilderState activityController; +// final double width; - const _ActivitySuggestionDialogImage({ - required this.activityController, - required this.width, - }); +// const _ActivitySuggestionDialogImage({ +// required this.activityController, +// required this.width, +// }); - @override - Widget build(BuildContext context) { - final imageWidth = (width / 2) + 42.0; - return Container( - padding: const EdgeInsets.all(24.0), - width: imageWidth, - child: ImageByUrl( - imageUrl: activityController.updatedActivity.imageURL, - width: imageWidth, - borderRadius: BorderRadius.circular(20.0), - ), - ); - } -} +// @override +// Widget build(BuildContext context) { +// final imageWidth = (width / 2) + 42.0; +// return Container( +// padding: const EdgeInsets.all(24.0), +// width: imageWidth, +// child: ImageByUrl( +// imageUrl: activityController.updatedActivity.imageURL, +// width: imageWidth, +// borderRadius: BorderRadius.circular(20.0), +// ), +// ); +// } +// } -class _ActivitySuggestionDialogFrame extends StatelessWidget { - final Widget topContent; - final List centerContent; - final Widget bottomContent; +// class _ActivitySuggestionDialogFrame extends StatelessWidget { +// final Widget topContent; +// final List centerContent; +// final Widget bottomContent; - const _ActivitySuggestionDialogFrame({ - required this.topContent, - required this.centerContent, - required this.bottomContent, - }); +// const _ActivitySuggestionDialogFrame({ +// required this.topContent, +// required this.centerContent, +// required this.bottomContent, +// }); - @override - Widget build(BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Flexible( - child: SingleChildScrollView( - child: Column( - spacing: 8.0, - mainAxisSize: MainAxisSize.min, - children: [ - topContent, - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, - vertical: 8.0, - ), - child: Column( - spacing: 14.0, - children: centerContent, - ), - ), - ], - ), - ), - ), - Padding( - padding: const EdgeInsets.all(16.0), - child: bottomContent, - ), - ], - ); - } -} +// @override +// Widget build(BuildContext context) { +// return Column( +// mainAxisSize: MainAxisSize.min, +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Flexible( +// child: SingleChildScrollView( +// child: Column( +// spacing: 8.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// topContent, +// Padding( +// padding: const EdgeInsets.symmetric( +// horizontal: 16.0, +// vertical: 8.0, +// ), +// child: Column( +// spacing: 14.0, +// children: centerContent, +// ), +// ), +// ], +// ), +// ), +// ), +// Padding( +// padding: const EdgeInsets.all(16.0), +// child: bottomContent, +// ), +// ], +// ); +// } +// } -class _ActivitySuggestionBaseContent extends StatelessWidget { - final ActivitySuggestionDialogState controller; +// class _ActivitySuggestionBaseContent extends StatelessWidget { +// final ActivitySuggestionDialogState controller; - const _ActivitySuggestionBaseContent({ - required this.controller, - }); +// const _ActivitySuggestionBaseContent({ +// required this.controller, +// }); - ActivityPlannerBuilderState get activityController => - controller.widget.controller; +// ActivityPlannerBuilderState get activityController => +// controller.widget.controller; - @override - Widget build(BuildContext context) { - final ThemeData theme = Theme.of(context); +// @override +// Widget build(BuildContext context) { +// final ThemeData theme = Theme.of(context); - final topContent = _ActivitySuggestionDialogImage( - activityController: activityController, - width: controller.width, - ); +// final topContent = _ActivitySuggestionDialogImage( +// activityController: activityController, +// width: controller.width, +// ); - final centerContent = [ - ActivitySuggestionCardRow( - icon: Icons.event_note_outlined, - child: Text( - activityController.updatedActivity.title, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ActivitySuggestionCardRow( - icon: Symbols.target, - child: Text( - activityController.updatedActivity.learningObjective, - style: const TextStyle(fontSize: 16), - ), - ), - ActivitySuggestionCardRow( - icon: Symbols.steps, - child: Text( - activityController.updatedActivity.instructions, - style: const TextStyle(fontSize: 16), - ), - ), - ActivitySuggestionCardRow( - icon: Icons.group_outlined, - child: Text( - L10n.of(context).countParticipants( - activityController.updatedActivity.req.numberOfParticipants, - ), - style: const TextStyle(fontSize: 16), - ), - ), - ActivitySuggestionCardRow( - icon: Icons.school_outlined, - child: Text( - activityController.updatedActivity.req.cefrLevel.title(context), - style: const TextStyle(fontSize: 16), - ), - ), - ActivitySuggestionCardRow( - icon: Symbols.dictionary, - child: ConstrainedBox( - constraints: const BoxConstraints( - maxHeight: 60.0, - ), - child: SingleChildScrollView( - child: Wrap( - spacing: 4.0, - runSpacing: 4.0, - children: activityController.vocab - .map( - (vocab) => Container( - padding: const EdgeInsets.symmetric( - vertical: 4.0, - horizontal: 8.0, - ), - decoration: BoxDecoration( - color: theme.colorScheme.primary.withAlpha( - 20, - ), - borderRadius: BorderRadius.circular( - 24.0, - ), - ), - child: Text( - vocab.lemma, - style: const TextStyle(fontSize: 12), - ), - ), - ) - .toList(), - ), - ), - ), - ), - ]; +// final centerContent = [ +// ActivitySuggestionCardRow( +// icon: Icons.event_note_outlined, +// child: Text( +// activityController.updatedActivity.title, +// style: const TextStyle( +// fontSize: 20, +// fontWeight: FontWeight.bold, +// ), +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Symbols.target, +// child: Text( +// activityController.updatedActivity.learningObjective, +// style: const TextStyle(fontSize: 16), +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Symbols.steps, +// child: Text( +// activityController.updatedActivity.instructions, +// style: const TextStyle(fontSize: 16), +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Icons.group_outlined, +// child: Text( +// L10n.of(context).countParticipants( +// activityController.updatedActivity.req.numberOfParticipants, +// ), +// style: const TextStyle(fontSize: 16), +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Icons.school_outlined, +// child: Text( +// activityController.updatedActivity.req.cefrLevel.title(context), +// style: const TextStyle(fontSize: 16), +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Symbols.dictionary, +// child: ConstrainedBox( +// constraints: const BoxConstraints( +// maxHeight: 60.0, +// ), +// child: SingleChildScrollView( +// child: Wrap( +// spacing: 4.0, +// runSpacing: 4.0, +// children: activityController.vocab +// .map( +// (vocab) => Container( +// padding: const EdgeInsets.symmetric( +// vertical: 4.0, +// horizontal: 8.0, +// ), +// decoration: BoxDecoration( +// color: theme.colorScheme.primary.withAlpha( +// 20, +// ), +// borderRadius: BorderRadius.circular( +// 24.0, +// ), +// ), +// child: Text( +// vocab.lemma, +// style: const TextStyle(fontSize: 12), +// ), +// ), +// ) +// .toList(), +// ), +// ), +// ), +// ), +// ]; - final bottomContent = Column( - spacing: 12.0, - children: [ - Row( - spacing: 12.0, - children: [ - if (activityController.widget.enabledEdits) - Expanded( - child: ElevatedButton( - style: controller.buttonStyle, - onPressed: activityController.startEditing, - child: Row( - children: [ - const Icon(Icons.edit), - Expanded( - child: Text( - L10n.of(context).edit, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - if (controller.widget.replaceActivity != null) - Expanded( - child: ElevatedButton( - style: controller.buttonStyle, - onPressed: controller.onRegenerate, - child: Row( - children: [ - const Icon( - Icons.lightbulb_outline, - ), - Expanded( - child: Text( - L10n.of(context).regenerate, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - ], - ), - Row( - children: [ - Expanded( - child: ElevatedButton( - style: controller.buttonStyle, - // onPressed: _launchActivity, - onPressed: () { - !activityController.widget.enableMultiLaunch - ? controller.launchActivity() - : activityController.setLaunchState( - ActivityLaunchState.launching, - ); - }, - child: Row( - spacing: 12.0, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.save_outlined), - Text( - controller.widget.buttonText, - textAlign: TextAlign.center, - ), - ], - ), - ), - ), - ], - ), - ], - ); +// final bottomContent = Column( +// spacing: 12.0, +// children: [ +// Row( +// spacing: 12.0, +// children: [ +// if (activityController.widget.enabledEdits) +// Expanded( +// child: ElevatedButton( +// style: controller.buttonStyle, +// onPressed: activityController.startEditing, +// child: Row( +// children: [ +// const Icon(Icons.edit), +// Expanded( +// child: Text( +// L10n.of(context).edit, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// if (controller.widget.replaceActivity != null) +// Expanded( +// child: ElevatedButton( +// style: controller.buttonStyle, +// onPressed: controller.onRegenerate, +// child: Row( +// children: [ +// const Icon( +// Icons.lightbulb_outline, +// ), +// Expanded( +// child: Text( +// L10n.of(context).regenerate, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ), +// Row( +// children: [ +// Expanded( +// child: ElevatedButton( +// style: controller.buttonStyle, +// // onPressed: _launchActivity, +// onPressed: () { +// !activityController.widget.enableMultiLaunch +// ? controller.launchActivity() +// : activityController.setLaunchState( +// ActivityLaunchState.launching, +// ); +// }, +// child: Row( +// spacing: 12.0, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// const Icon(Icons.save_outlined), +// Text( +// controller.widget.buttonText, +// textAlign: TextAlign.center, +// ), +// ], +// ), +// ), +// ), +// ], +// ), +// ], +// ); - return _ActivitySuggestionDialogFrame( - topContent: topContent, - centerContent: centerContent, - bottomContent: bottomContent, - ); - } -} +// return _ActivitySuggestionDialogFrame( +// topContent: topContent, +// centerContent: centerContent, +// bottomContent: bottomContent, +// ); +// } +// } -class _ActivitySuggestionEditContent extends StatelessWidget { - final ActivitySuggestionDialogState controller; +// class _ActivitySuggestionEditContent extends StatelessWidget { +// final ActivitySuggestionDialogState controller; - const _ActivitySuggestionEditContent({ - required this.controller, - }); +// const _ActivitySuggestionEditContent({ +// required this.controller, +// }); - ActivityPlannerBuilderState get activityController => - controller.widget.controller; +// ActivityPlannerBuilderState get activityController => +// controller.widget.controller; - @override - Widget build(BuildContext context) { - final ThemeData theme = Theme.of(context); +// @override +// Widget build(BuildContext context) { +// final ThemeData theme = Theme.of(context); - final topContent = Stack( - alignment: Alignment.bottomCenter, - children: [ - _ActivitySuggestionDialogImage( - activityController: activityController, - width: controller.width, - ), - InkWell( - borderRadius: BorderRadius.circular(90), - onTap: activityController.selectAvatar, - child: CircleAvatar( - backgroundColor: Theme.of(context).colorScheme.secondary, - radius: 20.0, - child: Icon( - Icons.add_a_photo_outlined, - size: 20.0, - color: Theme.of(context).colorScheme.onSecondary, - ), - ), - ), - ], - ); +// final topContent = Stack( +// alignment: Alignment.bottomCenter, +// children: [ +// _ActivitySuggestionDialogImage( +// activityController: activityController, +// width: controller.width, +// ), +// InkWell( +// borderRadius: BorderRadius.circular(90), +// onTap: activityController.selectAvatar, +// child: CircleAvatar( +// backgroundColor: Theme.of(context).colorScheme.secondary, +// radius: 20.0, +// child: Icon( +// Icons.add_a_photo_outlined, +// size: 20.0, +// color: Theme.of(context).colorScheme.onSecondary, +// ), +// ), +// ), +// ], +// ); - final centerContent = [ - ActivitySuggestionCardRow( - icon: Icons.event_note_outlined, - child: TextFormField( - controller: activityController.titleController, - decoration: InputDecoration( - labelText: L10n.of(context).activityTitle, - ), - maxLines: 2, - minLines: 1, - ), - ), - ActivitySuggestionCardRow( - icon: Symbols.target, - child: TextFormField( - controller: activityController.learningObjectivesController, - decoration: InputDecoration( - labelText: L10n.of(context).learningObjectiveLabel, - ), - maxLines: 4, - minLines: 1, - ), - ), - ActivitySuggestionCardRow( - icon: Symbols.steps, - child: TextFormField( - controller: activityController.instructionsController, - decoration: InputDecoration( - labelText: L10n.of(context).instructions, - ), - maxLines: 8, - minLines: 1, - ), - ), - ActivitySuggestionCardRow( - icon: Icons.group_outlined, - child: TextFormField( - controller: activityController.participantsController, - decoration: InputDecoration( - labelText: L10n.of(context).participants, - ), - maxLines: 1, - keyboardType: TextInputType.number, - validator: (value) { - if (value == null || value.isEmpty) { - return null; - } +// final centerContent = [ +// ActivitySuggestionCardRow( +// icon: Icons.event_note_outlined, +// child: TextFormField( +// controller: activityController.titleController, +// decoration: InputDecoration( +// labelText: L10n.of(context).activityTitle, +// ), +// maxLines: 2, +// minLines: 1, +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Symbols.target, +// child: TextFormField( +// controller: activityController.learningObjectivesController, +// decoration: InputDecoration( +// labelText: L10n.of(context).learningObjectiveLabel, +// ), +// maxLines: 4, +// minLines: 1, +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Symbols.steps, +// child: TextFormField( +// controller: activityController.instructionsController, +// decoration: InputDecoration( +// labelText: L10n.of(context).instructions, +// ), +// maxLines: 8, +// minLines: 1, +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Icons.group_outlined, +// child: TextFormField( +// controller: activityController.participantsController, +// decoration: InputDecoration( +// labelText: L10n.of(context).participants, +// ), +// maxLines: 1, +// keyboardType: TextInputType.number, +// validator: (value) { +// if (value == null || value.isEmpty) { +// return null; +// } - try { - final val = int.parse(value); - if (val <= 0) { - return L10n.of(context).pleaseEnterInt; - } - if (val > 50) { - return L10n.of(context).maxFifty; - } - } catch (e) { - return L10n.of(context).pleaseEnterANumber; - } - return null; - }, - ), - ), - ActivitySuggestionCardRow( - icon: Icons.school_outlined, - child: LanguageLevelDropdown( - initialLevel: activityController.languageLevel, - onChanged: activityController.setLanguageLevel, - ), - ), - ActivitySuggestionCardRow( - icon: Symbols.dictionary, - child: ConstrainedBox( - constraints: const BoxConstraints( - maxHeight: 60.0, - ), - child: SingleChildScrollView( - child: Wrap( - spacing: 4.0, - runSpacing: 4.0, - children: activityController.vocab - .mapIndexed( - (i, vocab) => Container( - padding: const EdgeInsets.symmetric( - vertical: 4.0, - horizontal: 8.0, - ), - decoration: BoxDecoration( - color: theme.colorScheme.primary.withAlpha( - 20, - ), - borderRadius: BorderRadius.circular( - 24.0, - ), - ), - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () => activityController.removeVocab( - i, - ), - child: Row( - spacing: 4.0, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - vocab.lemma, - ), - const Icon( - Icons.close, - size: 12.0, - ), - ], - ), - ), - ), - ), - ) - .toList(), - ), - ), - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 4.0, - ), - child: Row( - spacing: 4.0, - children: [ - Expanded( - child: TextFormField( - controller: activityController.vocabController, - decoration: InputDecoration( - hintText: L10n.of( - context, - ).addVocabulary, - ), - maxLines: 1, - onFieldSubmitted: (_) => activityController.addVocab(), - ), - ), - IconButton( - padding: const EdgeInsets.all( - 0.0, - ), - constraints: - const BoxConstraints(), // override default min size of 48px - iconSize: 16.0, - icon: const Icon( - Icons.add_outlined, - ), - onPressed: activityController.addVocab, - ), - ], - ), - ), - ]; +// try { +// final val = int.parse(value); +// if (val <= 0) { +// return L10n.of(context).pleaseEnterInt; +// } +// if (val > 50) { +// return L10n.of(context).maxFifty; +// } +// } catch (e) { +// return L10n.of(context).pleaseEnterANumber; +// } +// return null; +// }, +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Icons.school_outlined, +// child: LanguageLevelDropdown( +// initialLevel: activityController.languageLevel, +// onChanged: activityController.setLanguageLevel, +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Symbols.dictionary, +// child: ConstrainedBox( +// constraints: const BoxConstraints( +// maxHeight: 60.0, +// ), +// child: SingleChildScrollView( +// child: Wrap( +// spacing: 4.0, +// runSpacing: 4.0, +// children: activityController.vocab +// .mapIndexed( +// (i, vocab) => Container( +// padding: const EdgeInsets.symmetric( +// vertical: 4.0, +// horizontal: 8.0, +// ), +// decoration: BoxDecoration( +// color: theme.colorScheme.primary.withAlpha( +// 20, +// ), +// borderRadius: BorderRadius.circular( +// 24.0, +// ), +// ), +// child: MouseRegion( +// cursor: SystemMouseCursors.click, +// child: GestureDetector( +// onTap: () => activityController.removeVocab( +// i, +// ), +// child: Row( +// spacing: 4.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// Text( +// vocab.lemma, +// ), +// const Icon( +// Icons.close, +// size: 12.0, +// ), +// ], +// ), +// ), +// ), +// ), +// ) +// .toList(), +// ), +// ), +// ), +// ), +// Padding( +// padding: const EdgeInsets.symmetric( +// vertical: 4.0, +// ), +// child: Row( +// spacing: 4.0, +// children: [ +// Expanded( +// child: TextFormField( +// controller: activityController.vocabController, +// decoration: InputDecoration( +// hintText: L10n.of( +// context, +// ).addVocabulary, +// ), +// maxLines: 1, +// onFieldSubmitted: (_) => activityController.addVocab(), +// ), +// ), +// IconButton( +// padding: const EdgeInsets.all( +// 0.0, +// ), +// constraints: +// const BoxConstraints(), // override default min size of 48px +// iconSize: 16.0, +// icon: const Icon( +// Icons.add_outlined, +// ), +// onPressed: activityController.addVocab, +// ), +// ], +// ), +// ), +// ]; - final bottomContent = Row( - spacing: 12.0, - children: [ - Expanded( - child: ElevatedButton( - style: controller.buttonStyle, - onPressed: activityController.saveEdits, - child: Row( - children: [ - const Icon(Icons.save), - Expanded( - child: Text( - L10n.of(context).save, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - Expanded( - child: ElevatedButton( - style: controller.buttonStyle, - onPressed: activityController.clearEdits, - child: Row( - children: [ - const Icon(Icons.cancel), - Expanded( - child: Text( - L10n.of(context).cancel, - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ), - ], - ); +// final bottomContent = Row( +// spacing: 12.0, +// children: [ +// Expanded( +// child: ElevatedButton( +// style: controller.buttonStyle, +// onPressed: activityController.saveEdits, +// child: Row( +// children: [ +// const Icon(Icons.save), +// Expanded( +// child: Text( +// L10n.of(context).save, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// Expanded( +// child: ElevatedButton( +// style: controller.buttonStyle, +// onPressed: activityController.clearEdits, +// child: Row( +// children: [ +// const Icon(Icons.cancel), +// Expanded( +// child: Text( +// L10n.of(context).cancel, +// textAlign: TextAlign.center, +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ); - return _ActivitySuggestionDialogFrame( - topContent: topContent, - centerContent: centerContent, - bottomContent: bottomContent, - ); - } -} +// return _ActivitySuggestionDialogFrame( +// topContent: topContent, +// centerContent: centerContent, +// bottomContent: bottomContent, +// ); +// } +// } -class _ActivitySuggestionLaunchContent extends StatelessWidget { - final ActivitySuggestionDialogState controller; +// class _ActivitySuggestionLaunchContent extends StatelessWidget { +// final ActivitySuggestionDialogState controller; - const _ActivitySuggestionLaunchContent({ - required this.controller, - }); +// const _ActivitySuggestionLaunchContent({ +// required this.controller, +// }); - ActivityPlannerBuilderState get activityController => - controller.widget.controller; +// ActivityPlannerBuilderState get activityController => +// controller.widget.controller; - @override - Widget build(BuildContext context) { - final topContent = Padding( - padding: const EdgeInsets.all(24.0), - child: Avatar( - mxContent: activityController.room.avatar, - name: activityController.room.getLocalizedDisplayname( - MatrixLocals( - L10n.of(context), - ), - ), - size: (controller.width / 2), - borderRadius: BorderRadius.circular(20.0), - ), - ); +// @override +// Widget build(BuildContext context) { +// final topContent = Padding( +// padding: const EdgeInsets.all(24.0), +// child: Avatar( +// mxContent: activityController.room.avatar, +// name: activityController.room.getLocalizedDisplayname( +// MatrixLocals( +// L10n.of(context), +// ), +// ), +// size: (controller.width / 2), +// borderRadius: BorderRadius.circular(20.0), +// ), +// ); - final centerContent = [ - ActivitySuggestionCardRow( - leading: Avatar( - mxContent: activityController.room.avatar, - name: activityController.room.getLocalizedDisplayname( - MatrixLocals( - L10n.of(context), - ), - ), - size: 24.0, - borderRadius: BorderRadius.circular(4), - ), - child: Text( - activityController.room.getLocalizedDisplayname( - MatrixLocals(L10n.of(context)), - ), - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ActivitySuggestionCardRow( - leading: ImageByUrl( - imageUrl: activityController.updatedActivity.imageURL, - width: 24.0, - borderRadius: BorderRadius.circular(4.0), - replacement: const Icon( - Icons.event_note_outlined, - size: 24.0, - ), - ), - child: Text( - activityController.updatedActivity.title, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ActivitySuggestionCardRow( - icon: Icons.groups, - child: Text( - L10n.of(context).maximumActivityParticipants( - activityController.updatedActivity.req.numberOfParticipants, - ), - style: const TextStyle(fontSize: 16), - ), - ), - ActivitySuggestionCardRow( - icon: Icons.radar, - child: Column( - spacing: 4.0, - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - L10n.of(context).numberOfActivities, - style: const TextStyle(fontSize: 16), - ), - NumberCounter( - count: activityController.numActivities, - update: activityController.setNumActivities, - min: 1, - max: 5, - ), - ], - ), - ), - ]; +// final centerContent = [ +// ActivitySuggestionCardRow( +// leading: Avatar( +// mxContent: activityController.room.avatar, +// name: activityController.room.getLocalizedDisplayname( +// MatrixLocals( +// L10n.of(context), +// ), +// ), +// size: 24.0, +// borderRadius: BorderRadius.circular(4), +// ), +// child: Text( +// activityController.room.getLocalizedDisplayname( +// MatrixLocals(L10n.of(context)), +// ), +// style: const TextStyle( +// fontSize: 20, +// fontWeight: FontWeight.bold, +// ), +// ), +// ), +// ActivitySuggestionCardRow( +// leading: ImageByUrl( +// imageUrl: activityController.updatedActivity.imageURL, +// width: 24.0, +// borderRadius: BorderRadius.circular(4.0), +// replacement: const Icon( +// Icons.event_note_outlined, +// size: 24.0, +// ), +// ), +// child: Text( +// activityController.updatedActivity.title, +// style: const TextStyle( +// fontSize: 20, +// fontWeight: FontWeight.bold, +// ), +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Icons.groups, +// child: Text( +// L10n.of(context).maximumActivityParticipants( +// activityController.updatedActivity.req.numberOfParticipants, +// ), +// style: const TextStyle(fontSize: 16), +// ), +// ), +// ActivitySuggestionCardRow( +// icon: Icons.radar, +// child: Column( +// spacing: 4.0, +// mainAxisSize: MainAxisSize.min, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// Text( +// L10n.of(context).numberOfActivities, +// style: const TextStyle(fontSize: 16), +// ), +// NumberCounter( +// count: activityController.numActivities, +// update: activityController.setNumActivities, +// min: 1, +// max: 5, +// ), +// ], +// ), +// ), +// ]; - final bottomContent = ElevatedButton( - style: controller.buttonStyle, - onPressed: controller.launchActivity, - child: Row( - spacing: 12.0, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon(Icons.send_outlined), - Text( - L10n.of(context).launchToSpace, - textAlign: TextAlign.center, - ), - ], - ), - ); +// final bottomContent = ElevatedButton( +// style: controller.buttonStyle, +// onPressed: controller.launchActivity, +// child: Row( +// spacing: 12.0, +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// const Icon(Icons.send_outlined), +// Text( +// L10n.of(context).launchToSpace, +// textAlign: TextAlign.center, +// ), +// ], +// ), +// ); - return _ActivitySuggestionDialogFrame( - topContent: topContent, - centerContent: centerContent, - bottomContent: bottomContent, - ); - } -} +// return _ActivitySuggestionDialogFrame( +// topContent: topContent, +// centerContent: centerContent, +// bottomContent: bottomContent, +// ); +// } +// } diff --git a/lib/pangea/activity_suggestions/activity_suggestions_area.dart b/lib/pangea/activity_suggestions/activity_suggestions_area.dart index 0987cb210..98952559a 100644 --- a/lib/pangea/activity_suggestions/activity_suggestions_area.dart +++ b/lib/pangea/activity_suggestions/activity_suggestions_area.dart @@ -1,317 +1,317 @@ -// shows n rows of activity suggestions vertically, where n is the number of rows -// as the user tries to scroll horizontally to the right, the client will fetch more activity suggestions +// // shows n rows of activity suggestions vertically, where n is the number of rows +// // as the user tries to scroll horizontally to the right, the client will fetch more activity suggestions -import 'dart:async'; +// import 'dart:async'; -import 'package:flutter/material.dart'; +// import 'package:flutter/material.dart'; -import 'package:collection/collection.dart'; -import 'package:matrix/matrix.dart'; -import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:shimmer/shimmer.dart'; +// import 'package:collection/collection.dart'; +// import 'package:matrix/matrix.dart'; +// import 'package:sentry_flutter/sentry_flutter.dart'; +// import 'package:shimmer/shimmer.dart'; -import 'package:fluffychat/config/themes.dart'; -import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_generator/media_enum.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_plan_search_repo.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_search_enum.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; -import 'package:fluffychat/pangea/common/utils/error_handler.dart'; -import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; -import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; -import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +// import 'package:fluffychat/config/themes.dart'; +// import 'package:fluffychat/l10n/l10n.dart'; +// import 'package:fluffychat/pangea/activity_generator/media_enum.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; +// import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_plan_search_repo.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_search_enum.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card.dart'; +// import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; +// import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +// import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; +// import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; +// import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; +// import 'package:fluffychat/widgets/matrix.dart'; -class ActivitySuggestionsArea extends StatefulWidget { - final Axis? scrollDirection; - final Room room; +// class ActivitySuggestionsArea extends StatefulWidget { +// final Axis? scrollDirection; +// final Room room; - const ActivitySuggestionsArea({ - super.key, - this.scrollDirection, - required this.room, - }); - @override - ActivitySuggestionsAreaState createState() => ActivitySuggestionsAreaState(); -} +// const ActivitySuggestionsArea({ +// super.key, +// this.scrollDirection, +// required this.room, +// }); +// @override +// ActivitySuggestionsAreaState createState() => ActivitySuggestionsAreaState(); +// } -class ActivitySuggestionsAreaState extends State { - StreamSubscription? _languageStream; +// class ActivitySuggestionsAreaState extends State { +// StreamSubscription? _languageStream; - @override - void initState() { - super.initState(); - _setActivityItems(); +// @override +// void initState() { +// super.initState(); +// _setActivityItems(); - _languageStream ??= MatrixState - .pangeaController.userController.languageStream.stream - .listen((update) { - WidgetsBinding.instance.addPostFrameCallback( - (_) => _setActivityItems(), - ); - }); - } +// _languageStream ??= MatrixState +// .pangeaController.userController.languageStream.stream +// .listen((update) { +// WidgetsBinding.instance.addPostFrameCallback( +// (_) => _setActivityItems(), +// ); +// }); +// } - @override - void dispose() { - _scrollController.dispose(); - _languageStream?.cancel(); - super.dispose(); - } +// @override +// void dispose() { +// _scrollController.dispose(); +// _languageStream?.cancel(); +// super.dispose(); +// } - // _loading is true when _setActivityItems is currently requesting activities - bool _loading = true; - ActivitySearchEnum _status = ActivitySearchEnum.waiting; +// // _loading is true when _setActivityItems is currently requesting activities +// bool _loading = true; +// ActivitySearchEnum _status = ActivitySearchEnum.waiting; - bool get _isColumnMode => FluffyThemes.isColumnMode(context); +// bool get _isColumnMode => FluffyThemes.isColumnMode(context); - final List _activityItems = []; - final ScrollController _scrollController = ScrollController(); - double get cardHeight => _isColumnMode ? 325.0 : 250.0; - double get cardWidth => _isColumnMode ? 225.0 : 150.0; +// final List _activityItems = []; +// final ScrollController _scrollController = ScrollController(); +// double get cardHeight => _isColumnMode ? 325.0 : 250.0; +// double get cardWidth => _isColumnMode ? 225.0 : 150.0; - String get instructionLanguage => - MatrixState.pangeaController.languageController.userL1?.langCode ?? - LanguageKeys.defaultLanguage; - String get targetLanguage => - MatrixState.pangeaController.languageController.userL2?.langCode ?? - LanguageKeys.defaultLanguage; +// String get instructionLanguage => +// MatrixState.pangeaController.languageController.userL1?.langCode ?? +// LanguageKeys.defaultLanguage; +// String get targetLanguage => +// MatrixState.pangeaController.languageController.userL2?.langCode ?? +// LanguageKeys.defaultLanguage; - ActivityPlanRequest get _request { - return ActivityPlanRequest( - topic: "", - mode: "", - objective: "", - media: MediaEnum.nan, - cefrLevel: LanguageLevelTypeEnum.a1, - languageOfInstructions: instructionLanguage, - targetLanguage: targetLanguage, - numberOfParticipants: 3, - count: 5, - ); - } +// ActivityPlanRequest get _request { +// return ActivityPlanRequest( +// topic: "", +// mode: "", +// objective: "", +// media: MediaEnum.nan, +// cefrLevel: LanguageLevelTypeEnum.a1, +// languageOfInstructions: instructionLanguage, +// targetLanguage: targetLanguage, +// numberOfParticipants: 3, +// count: 5, +// ); +// } - Future _setActivityItems({int retries = 0}) async { - if (retries > 3) { - if (mounted) { - setState(() { - _status = ActivitySearchEnum.timeout; - _loading = false; - }); - } - return; - } +// Future _setActivityItems({int retries = 0}) async { +// if (retries > 3) { +// if (mounted) { +// setState(() { +// _status = ActivitySearchEnum.timeout; +// _loading = false; +// }); +// } +// return; +// } - try { - if (retries == 0 && mounted) { - setState(() { - _activityItems.clear(); - _loading = true; - _status = ActivitySearchEnum.waiting; - }); - } +// try { +// if (retries == 0 && mounted) { +// setState(() { +// _activityItems.clear(); +// _loading = true; +// _status = ActivitySearchEnum.waiting; +// }); +// } - final resp = await ActivitySearchRepo.get(_request).timeout( - const Duration(seconds: 5), - onTimeout: () { - if (mounted) setState(() => _status = ActivitySearchEnum.timeout); +// final resp = await ActivitySearchRepo.get(_request).timeout( +// const Duration(seconds: 5), +// onTimeout: () { +// if (mounted) setState(() => _status = ActivitySearchEnum.timeout); - Future.delayed(const Duration(seconds: 5), () { - if (mounted) _setActivityItems(retries: retries + 1); - }); +// Future.delayed(const Duration(seconds: 5), () { +// if (mounted) _setActivityItems(retries: retries + 1); +// }); - return Future.error( - TimeoutException( - L10n.of(context).activitySuggestionTimeoutMessage, - ), - ); - }, - ); - _activityItems.addAll(resp.response.activityPlans); - _status = _status.fromCode(resp.statusCode); - if (_status != ActivitySearchEnum.error) { - if (_activityItems.isEmpty) { - if (mounted && retries != 0) { - setState(() => _status = ActivitySearchEnum.timeout); - } +// return Future.error( +// TimeoutException( +// L10n.of(context).activitySuggestionTimeoutMessage, +// ), +// ); +// }, +// ); +// _activityItems.addAll(resp.response.activityPlans); +// _status = _status.fromCode(resp.statusCode); +// if (_status != ActivitySearchEnum.error) { +// if (_activityItems.isEmpty) { +// if (mounted && retries != 0) { +// setState(() => _status = ActivitySearchEnum.timeout); +// } - Future.delayed(const Duration(seconds: 5), () { - if (mounted) _setActivityItems(retries: retries + 1); - }); - } else { - if (mounted) setState(() => _loading = false); - } - } - } on TimeoutException { - rethrow; - } catch (e, s) { - ErrorHandler.logError( - e: e, - s: s, - data: { - 'retries': retries, - 'request': _request.toJson(), - }, - level: SentryLevel.warning, - ); - } - } +// Future.delayed(const Duration(seconds: 5), () { +// if (mounted) _setActivityItems(retries: retries + 1); +// }); +// } else { +// if (mounted) setState(() => _loading = false); +// } +// } +// } on TimeoutException { +// rethrow; +// } catch (e, s) { +// ErrorHandler.logError( +// e: e, +// s: s, +// data: { +// 'retries': retries, +// 'request': _request.toJson(), +// }, +// level: SentryLevel.warning, +// ); +// } +// } - void _onReplaceActivity(int index, ActivityPlanModel a) { - setState(() => _activityItems[index] = a); - } +// void _onReplaceActivity(int index, ActivityPlanModel a) { +// setState(() => _activityItems[index] = a); +// } - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); +// @override +// Widget build(BuildContext context) { +// final theme = Theme.of(context); - // Show all loaded activities, or a loading view if there are none - final List cards = _activityItems.isEmpty - ? List.generate(5, (i) { - return Shimmer.fromColors( - baseColor: theme.colorScheme.primary.withAlpha(20), - highlightColor: theme.colorScheme.primary.withAlpha(50), - child: Container( - height: cardHeight, - width: cardWidth, - decoration: BoxDecoration( - color: theme.colorScheme.surfaceContainer, - borderRadius: BorderRadius.circular(24.0), - ), - ), - ); - }) - : _activityItems - .mapIndexed((index, activity) { - return ActivityPlannerBuilder( - initialActivity: activity, - room: widget.room, - builder: (controller) { - return ActivitySuggestionCard( - controller: controller, - onPressed: () { - showDialog( - context: context, - builder: (context) { - return ActivitySuggestionDialog( - controller: controller, - buttonText: L10n.of(context).saveAndLaunch, - replaceActivity: (a) => - _onReplaceActivity(index, a), - ); - }, - ); - }, - width: cardWidth, - height: cardHeight, - ); - }, - ); - }) - .cast() - .toList(); +// // Show all loaded activities, or a loading view if there are none +// final List cards = _activityItems.isEmpty +// ? List.generate(5, (i) { +// return Shimmer.fromColors( +// baseColor: theme.colorScheme.primary.withAlpha(20), +// highlightColor: theme.colorScheme.primary.withAlpha(50), +// child: Container( +// height: cardHeight, +// width: cardWidth, +// decoration: BoxDecoration( +// color: theme.colorScheme.surfaceContainer, +// borderRadius: BorderRadius.circular(24.0), +// ), +// ), +// ); +// }) +// : _activityItems +// .mapIndexed((index, activity) { +// return ActivityPlannerBuilder( +// initialActivity: activity, +// room: widget.room, +// builder: (controller) { +// return ActivitySuggestionCard( +// controller: controller, +// onPressed: () { +// showDialog( +// context: context, +// builder: (context) { +// return ActivitySuggestionDialog( +// controller: controller, +// buttonText: L10n.of(context).saveAndLaunch, +// replaceActivity: (a) => +// _onReplaceActivity(index, a), +// ); +// }, +// ); +// }, +// width: cardWidth, +// height: cardHeight, +// ); +// }, +// ); +// }) +// .cast() +// .toList(); - final scrollDirection = widget.scrollDirection ?? - (_isColumnMode ? Axis.horizontal : Axis.vertical); +// final scrollDirection = widget.scrollDirection ?? +// (_isColumnMode ? Axis.horizontal : Axis.vertical); - return Column( - spacing: 8.0, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AnimatedSize( - duration: FluffyThemes.animationDuration, - child: _status.hideCards - ? Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - spacing: 16.0, - mainAxisSize: MainAxisSize.min, - children: [ - ErrorIndicator( - message: _status.message(L10n.of(context)), - ), - if (_loading && _status == ActivitySearchEnum.timeout) - const CircularProgressIndicator(), - if (!_loading && _status == ActivitySearchEnum.timeout) - ElevatedButton( - onPressed: _setActivityItems, - style: ElevatedButton.styleFrom( - backgroundColor: theme.colorScheme.primaryContainer, - foregroundColor: - theme.colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), - child: Text(L10n.of(context).tryAgain), - ), - ], - ), - ) - : Container( - decoration: const BoxDecoration(), - child: Column( - children: [ - scrollDirection == Axis.horizontal - ? Scrollbar( - thumbVisibility: true, - controller: _scrollController, - child: Padding( - padding: const EdgeInsets.only(bottom: 16.0), - child: SingleChildScrollView( - controller: _scrollController, - scrollDirection: Axis.horizontal, - child: Row( - spacing: 8.0, - children: cards, - ), - ), - ), - ) - : SizedBox( - width: MediaQuery.of(context).size.width, - child: Wrap( - alignment: WrapAlignment.spaceEvenly, - runSpacing: 16.0, - spacing: 4.0, - children: cards, - ), - ), - if (cards.length < 5) - Padding( - padding: const EdgeInsetsGeometry.all(16.0), - child: ErrorIndicator( - message: _status.message(L10n.of(context)), - ), - ), - if (cards.length < 5 && _loading) - const CircularProgressIndicator(), - if (cards.length < 5 && !_loading) - Padding( - padding: const EdgeInsetsGeometry.only(bottom: 16), - child: ElevatedButton( - onPressed: _setActivityItems, - style: ElevatedButton.styleFrom( - backgroundColor: - theme.colorScheme.primaryContainer, - foregroundColor: - theme.colorScheme.onPrimaryContainer, - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), - ), - child: Text(L10n.of(context).tryAgain), - ), - ), - ], - ), - ), - ), - ], - ); - } -} +// return Column( +// spacing: 8.0, +// crossAxisAlignment: CrossAxisAlignment.start, +// children: [ +// AnimatedSize( +// duration: FluffyThemes.animationDuration, +// child: _status.hideCards +// ? Padding( +// padding: const EdgeInsets.all(8.0), +// child: Column( +// spacing: 16.0, +// mainAxisSize: MainAxisSize.min, +// children: [ +// ErrorIndicator( +// message: _status.message(L10n.of(context)), +// ), +// if (_loading && _status == ActivitySearchEnum.timeout) +// const CircularProgressIndicator(), +// if (!_loading && _status == ActivitySearchEnum.timeout) +// ElevatedButton( +// onPressed: _setActivityItems, +// style: ElevatedButton.styleFrom( +// backgroundColor: theme.colorScheme.primaryContainer, +// foregroundColor: +// theme.colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ), +// child: Text(L10n.of(context).tryAgain), +// ), +// ], +// ), +// ) +// : Container( +// decoration: const BoxDecoration(), +// child: Column( +// children: [ +// scrollDirection == Axis.horizontal +// ? Scrollbar( +// thumbVisibility: true, +// controller: _scrollController, +// child: Padding( +// padding: const EdgeInsets.only(bottom: 16.0), +// child: SingleChildScrollView( +// controller: _scrollController, +// scrollDirection: Axis.horizontal, +// child: Row( +// spacing: 8.0, +// children: cards, +// ), +// ), +// ), +// ) +// : SizedBox( +// width: MediaQuery.of(context).size.width, +// child: Wrap( +// alignment: WrapAlignment.spaceEvenly, +// runSpacing: 16.0, +// spacing: 4.0, +// children: cards, +// ), +// ), +// if (cards.length < 5) +// Padding( +// padding: const EdgeInsetsGeometry.all(16.0), +// child: ErrorIndicator( +// message: _status.message(L10n.of(context)), +// ), +// ), +// if (cards.length < 5 && _loading) +// const CircularProgressIndicator(), +// if (cards.length < 5 && !_loading) +// Padding( +// padding: const EdgeInsetsGeometry.only(bottom: 16), +// child: ElevatedButton( +// onPressed: _setActivityItems, +// style: ElevatedButton.styleFrom( +// backgroundColor: +// theme.colorScheme.primaryContainer, +// foregroundColor: +// theme.colorScheme.onPrimaryContainer, +// padding: const EdgeInsets.symmetric( +// horizontal: 12.0, +// ), +// ), +// child: Text(L10n.of(context).tryAgain), +// ), +// ), +// ], +// ), +// ), +// ), +// ], +// ); +// } +// } diff --git a/lib/pangea/common/controllers/pangea_controller.dart b/lib/pangea/common/controllers/pangea_controller.dart index 7382e12bb..17f5c02ee 100644 --- a/lib/pangea/common/controllers/pangea_controller.dart +++ b/lib/pangea/common/controllers/pangea_controller.dart @@ -111,7 +111,6 @@ class PangeaController { static final List _storageKeys = [ 'mode_list_storage', 'activity_plan_storage', - 'activity_plan_by_id_storage', 'bookmarked_activities', 'objective_list_storage', 'topic_list_storage', @@ -130,6 +129,11 @@ class PangeaController { 'onboarding_storage', 'analytics_request_storage', 'activity_analytics_storage', + 'course_topic_storage', + 'course_media_storage', + 'course_location_storage', + 'course_activity_storage', + 'course_location_media_storage', ]; Future clearCache({List exclude = const []}) async { diff --git a/lib/pangea/course_chats/course_chats_page.dart b/lib/pangea/course_chats/course_chats_page.dart index a6f20271d..530dbd4ad 100644 --- a/lib/pangea/course_chats/course_chats_page.dart +++ b/lib/pangea/course_chats/course_chats_page.dart @@ -16,6 +16,7 @@ import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/course_chats/course_chats_view.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_model.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_room_extension.dart'; +import 'package:fluffychat/pangea/course_plans/course_topic_model.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/pangea/public_spaces/public_room_bottom_sheet.dart'; import 'package:fluffychat/pangea/spaces/constants/space_constants.dart'; @@ -100,29 +101,29 @@ class CourseChatsController extends State { } int get _selectedTopicIndex => - course?.topics.indexWhere((t) => t.uuid == selectedTopicId) ?? -1; + course?.loadedTopics.indexWhere((t) => t.uuid == selectedTopicId) ?? -1; bool get canMoveLeft => _selectedTopicIndex > 0; bool get canMoveRight { if (course == null) return false; - final endIndex = - room?.ownCurrentTopicIndex(course!) ?? (course!.topics.length - 1); + final endIndex = room?.ownCurrentTopicIndex(course!) ?? + (course!.loadedTopics.length - 1); return _selectedTopicIndex < endIndex; } void moveLeft() { if (canMoveLeft) { - setSelectedTopicId(course!.topics[_selectedTopicIndex - 1].uuid); + setSelectedTopicId(course!.loadedTopics[_selectedTopicIndex - 1].uuid); } } void moveRight() { if (canMoveRight) { - setSelectedTopicId(course!.topics[_selectedTopicIndex + 1].uuid); + setSelectedTopicId(course!.loadedTopics[_selectedTopicIndex + 1].uuid); } } - Topic? get selectedTopic => course?.topics.firstWhereOrNull( + CourseTopicModel? get selectedTopic => course?.loadedTopics.firstWhereOrNull( (topic) => topic.uuid == selectedTopicId, ); diff --git a/lib/pangea/course_chats/course_chats_view.dart b/lib/pangea/course_chats/course_chats_view.dart index c0582aa71..67833202b 100644 --- a/lib/pangea/course_chats/course_chats_view.dart +++ b/lib/pangea/course_chats/course_chats_view.dart @@ -13,8 +13,8 @@ import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart import 'package:fluffychat/pangea/course_chats/course_chats_page.dart'; import 'package:fluffychat/pangea/course_chats/unjoined_chat_list_item.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_builder.dart'; -import 'package:fluffychat/pangea/course_plans/course_plan_model.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_room_extension.dart'; +import 'package:fluffychat/pangea/course_plans/course_topic_model.dart'; import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; import 'package:fluffychat/pangea/space_analytics/analytics_request_indicator.dart'; import 'package:fluffychat/pangea/spaces/widgets/knocking_users_indicator.dart'; @@ -41,13 +41,13 @@ class CourseChatsView extends StatelessWidget { return CoursePlanBuilder( courseId: room.coursePlan?.uuid, - onFound: (course) { + onLoaded: (course) { controller.setCourse(course); final topic = room.ownCurrentTopic(course); if (topic != null) controller.setSelectedTopicId(topic.uuid); }, builder: (context, courseController) { - final Topic? topic = controller.selectedTopic; + final CourseTopicModel? topic = controller.selectedTopic; final List activityIds = topic?.activityIds ?? []; return StreamBuilder( @@ -220,23 +220,24 @@ class CourseChatsView extends StatelessWidget { ), ), ), - Row( - spacing: 6.0, - mainAxisSize: MainAxisSize.min, - children: [ - const Icon( - Icons.location_on, - size: 24.0, - ), - Text( - topic.location, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, + if (topic.location != null) + Row( + spacing: 6.0, + mainAxisSize: MainAxisSize.min, + children: [ + const Icon( + Icons.location_on, + size: 24.0, ), - ), - ], - ), + Text( + topic.location!, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ], + ), MouseRegion( cursor: controller.canMoveRight ? SystemMouseCursors.click diff --git a/lib/pangea/course_creation/course_info_chip_widget.dart b/lib/pangea/course_creation/course_info_chip_widget.dart index 3f0efaf76..57eb1b78d 100644 --- a/lib/pangea/course_creation/course_info_chip_widget.dart +++ b/lib/pangea/course_creation/course_info_chip_widget.dart @@ -83,14 +83,14 @@ class CourseInfoChips extends StatelessWidget { ), CourseInfoChip( icon: Icons.location_on, - text: L10n.of(context).numModules(course.topics.length), + text: L10n.of(context).numModules(course.topicIds.length), fontSize: fontSize, iconSize: iconSize, padding: padding, ), CourseInfoChip( icon: Icons.event_note_outlined, - text: L10n.of(context).numActivityPlans(course.activities), + text: L10n.of(context).numActivityPlans(course.totalActivities), fontSize: fontSize, iconSize: iconSize, padding: padding, diff --git a/lib/pangea/course_creation/selected_course_view.dart b/lib/pangea/course_creation/selected_course_view.dart index efea688dd..b14cb1367 100644 --- a/lib/pangea/course_creation/selected_course_view.dart +++ b/lib/pangea/course_creation/selected_course_view.dart @@ -52,7 +52,7 @@ class SelectedCourseView extends StatelessWidget { Padding( padding: const EdgeInsets.all(12.0), child: ListView.builder( - itemCount: course.topics.length + 2, + itemCount: course.loadedTopics.length + 2, itemBuilder: (context, index) { if (index == 0) { return Column( @@ -112,11 +112,11 @@ class SelectedCourseView extends StatelessWidget { index--; - if (index == course.topics.length) { + if (index == course.loadedTopics.length) { return const SizedBox(height: 150.0); } - final topic = course.topics[index]; + final topic = course.loadedTopics[index]; return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), @@ -186,17 +186,18 @@ class SelectedCourseView extends StatelessWidget { spacing: 8.0, mainAxisSize: MainAxisSize.min, children: [ - CourseInfoChip( - icon: Icons.location_on, - text: topic.location, - fontSize: descFontSize, - iconSize: smallIconSize, - ), + if (topic.location != null) + CourseInfoChip( + icon: Icons.location_on, + text: topic.location!, + fontSize: descFontSize, + iconSize: smallIconSize, + ), CourseInfoChip( icon: Icons.event_note_outlined, text: L10n.of(context) .numActivityPlans( - topic.activities.length, + topic.loadedActivities.length, ), fontSize: descFontSize, iconSize: smallIconSize, diff --git a/lib/pangea/course_plans/course_activity_repo.dart b/lib/pangea/course_plans/course_activity_repo.dart new file mode 100644 index 000000000..7a87dae74 --- /dev/null +++ b/lib/pangea/course_plans/course_activity_repo.dart @@ -0,0 +1,127 @@ +import 'dart:async'; + +import 'package:get_storage/get_storage.dart'; + +import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_activity.dart'; +import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_activity_media.dart'; +import 'package:fluffychat/pangea/payload_client/payload_repo.dart'; + +class CourseActivityRepo { + static final Map>> _cache = {}; + static final GetStorage _storage = GetStorage('course_activity_storage'); + + static ActivityPlanModel? _getCached(String uuid) { + final json = _storage.read>(uuid); + if (json != null) { + try { + return ActivityPlanModel.fromJson(json); + } catch (e) { + // ignore invalid cached data + _storage.remove(uuid); + } + } + return null; + } + + static Future _setCached(ActivityPlanModel activity) => + _storage.write(activity.activityId, activity.toJson()); + + static List getSync(List uuids) { + return uuids + .map((uuid) => _getCached(uuid)) + .whereType() + .toList(); + } + + static Future> get( + String topicId, + List uuids, + ) async { + final activities = []; + final toFetch = []; + + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + activities.add(cached); + } else { + toFetch.add(uuid); + } + } + + if (toFetch.isNotEmpty) { + final fetchedActivities = await _fetch(topicId, toFetch); + activities.addAll(fetchedActivities); + for (final activity in fetchedActivities) { + await _setCached(activity); + } + } + + return activities; + } + + static Future> _fetch( + String topicId, + List uuids, + ) async { + if (_cache.containsKey(topicId)) { + return _cache[topicId]!.future; + } + + final completer = Completer>(); + _cache[topicId] = completer; + + final where = { + "id": {"in": uuids.join(",")}, + }; + final limit = uuids.length; + + try { + final cmsCoursePlanActivitiesResult = await PayloadRepo.payload.find( + CmsCoursePlanActivity.slug, + CmsCoursePlanActivity.fromJson, + where: where, + limit: limit, + page: 1, + sort: "createdAt", + ); + + final imageUrls = await _fetchImageUrls( + cmsCoursePlanActivitiesResult.docs.map((a) => a.id).toList(), + ); + + final activities = cmsCoursePlanActivitiesResult.docs + .map((a) => a.toActivityPlanModel(imageUrls[a.id])) + .toList(); + + completer.complete(activities); + return activities; + } catch (e) { + completer.completeError(e); + rethrow; + } finally { + _cache.remove(topicId); + } + } + + static Future> _fetchImageUrls( + List activityIds, + ) async { + final where = { + "id": {"in": activityIds.join(",")}, + }; + final limit = activityIds.length; + final cmsCoursePlanActivityMediasResult = await PayloadRepo.payload.find( + CmsCoursePlanActivityMedia.slug, + CmsCoursePlanActivityMedia.fromJson, + where: where, + limit: limit, + page: 1, + sort: "createdAt", + ); + return Map.fromEntries( + cmsCoursePlanActivityMediasResult.docs.map((e) => MapEntry(e.id, e.url!)), + ); + } +} diff --git a/lib/pangea/course_plans/course_location_media_repo.dart b/lib/pangea/course_plans/course_location_media_repo.dart new file mode 100644 index 000000000..e855a543c --- /dev/null +++ b/lib/pangea/course_plans/course_location_media_repo.dart @@ -0,0 +1,102 @@ +import 'dart:async'; + +import 'package:get_storage/get_storage.dart'; + +import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic_location_media.dart'; +import 'package:fluffychat/pangea/payload_client/payload_repo.dart'; + +class CourseLocationMediaRepo { + static final Map>> _cache = {}; + static final GetStorage _storage = + GetStorage('course_location_media_storage'); + + static String? _getCached(String uuid) { + try { + return _storage.read(uuid) as String?; + } catch (e) { + // If parsing fails, remove the corrupted cache entry + _storage.remove(uuid); + } + return null; + } + + static Future _setCached(String uuid, String url) => + _storage.write(uuid, url); + + static List getSync(List uuids) { + final urls = []; + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + urls.add(cached); + } + } + + return urls; + } + + static Future> get(String topicId, List uuids) async { + final urls = []; + final toFetch = []; + + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + urls.add(cached); + } else { + toFetch.add(uuid); + } + } + + if (toFetch.isNotEmpty) { + final fetched = await _fetch(topicId, toFetch); + urls.addAll(fetched.values); + for (final entry in fetched.entries) { + await _setCached(entry.key, entry.value); + } + } + + return urls; + } + + static Future> _fetch( + String topicId, + List uuids, + ) async { + if (_cache.containsKey(topicId)) { + return _cache[topicId]!.future; + } + + final completer = Completer>(); + _cache[topicId] = completer; + + final where = { + "id": {"in": uuids.join(",")}, + }; + final limit = uuids.length; + + try { + final cmsCoursePlanTopicLocationMediasResult = + await PayloadRepo.payload.find( + CmsCoursePlanTopicLocationMedia.slug, + CmsCoursePlanTopicLocationMedia.fromJson, + where: where, + limit: limit, + page: 1, + sort: "createdAt", + ); + + final media = Map.fromEntries( + cmsCoursePlanTopicLocationMediasResult.docs + .map((e) => MapEntry(e.id, e.url!)), + ); + completer.complete(media); + return media; + } catch (e) { + completer.completeError(e); + rethrow; + } finally { + _cache.remove(topicId); + } + } +} diff --git a/lib/pangea/course_plans/course_location_model.dart b/lib/pangea/course_plans/course_location_model.dart new file mode 100644 index 000000000..ad931a6c9 --- /dev/null +++ b/lib/pangea/course_plans/course_location_model.dart @@ -0,0 +1,30 @@ +class CourseLocationModel { + String uuid; + String name; + List mediaIds; + + CourseLocationModel({ + required this.uuid, + required this.name, + required this.mediaIds, + }); + + factory CourseLocationModel.fromJson(Map json) { + return CourseLocationModel( + uuid: json['uuid'] as String, + name: json['name'] as String, + mediaIds: (json['media_ids'] as List?) + ?.map((e) => e as String) + .toList() ?? + [], + ); + } + + Map toJson() { + return { + 'uuid': uuid, + 'name': name, + 'media_ids': mediaIds, + }; + } +} diff --git a/lib/pangea/course_plans/course_location_repo.dart b/lib/pangea/course_plans/course_location_repo.dart new file mode 100644 index 000000000..ebb762d83 --- /dev/null +++ b/lib/pangea/course_plans/course_location_repo.dart @@ -0,0 +1,107 @@ +import 'dart:async'; + +import 'package:get_storage/get_storage.dart'; + +import 'package:fluffychat/pangea/course_plans/course_location_model.dart'; +import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic_location.dart'; +import 'package:fluffychat/pangea/payload_client/payload_repo.dart'; + +class CourseLocationRepo { + static final Map>> _cache = {}; + static final GetStorage _storage = GetStorage('course_location_storage'); + + static CourseLocationModel? _getCached(String uuid) { + final json = _storage.read(uuid); + if (json != null) { + try { + return CourseLocationModel.fromJson(Map.from(json)); + } catch (e) { + // If parsing fails, remove the corrupted cache entry + _storage.remove(uuid); + } + } + return null; + } + + static Future _setCached(String uuid, CourseLocationModel location) => + _storage.write(uuid, location.toJson()); + + static List getSync(List uuids) { + final locations = []; + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + locations.add(cached); + } + } + + return locations; + } + + static Future> get( + String courseId, + List uuids, + ) async { + final locations = []; + final toFetch = []; + + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + locations.add(cached); + } else { + toFetch.add(uuid); + } + } + + if (toFetch.isNotEmpty) { + final fetchedLocations = await _fetch(courseId, toFetch); + locations.addAll(fetchedLocations); + for (int i = 0; i < toFetch.length; i++) { + await _setCached(toFetch[i], fetchedLocations[i]); + } + } + + return locations; + } + + static Future> _fetch( + String topicId, + List uuids, + ) async { + if (_cache.containsKey(topicId)) { + return _cache[topicId]!.future; + } + + final completer = Completer>(); + _cache[topicId] = completer; + + final where = { + "id": {"in": uuids.join(",")}, + }; + final limit = uuids.length; + + try { + final cmsCoursePlanTopicLocationsResult = await PayloadRepo.payload.find( + CmsCoursePlanTopicLocation.slug, + CmsCoursePlanTopicLocation.fromJson, + where: where, + limit: limit, + page: 1, + sort: "createdAt", + ); + + final locations = cmsCoursePlanTopicLocationsResult.docs + .map((location) => location.toCourseLocationModel()) + .toList(); + + completer.complete(locations); + return locations; + } catch (e) { + completer.completeError(e); + rethrow; + } finally { + _cache.remove(topicId); + } + } +} diff --git a/lib/pangea/course_plans/course_media_repo.dart b/lib/pangea/course_plans/course_media_repo.dart new file mode 100644 index 000000000..c78656a26 --- /dev/null +++ b/lib/pangea/course_plans/course_media_repo.dart @@ -0,0 +1,98 @@ +import 'dart:async'; + +import 'package:get_storage/get_storage.dart'; + +import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_media.dart'; +import 'package:fluffychat/pangea/payload_client/payload_repo.dart'; + +class CourseMediaRepo { + static final Map>> _cache = {}; + static final GetStorage _storage = GetStorage('course_media_storage'); + + static List getSync(List uuids) { + final urls = []; + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + urls.add(cached); + } + } + + return urls; + } + + static Future> get(String courseId, List uuids) async { + final urls = []; + final toFetch = []; + + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + urls.add(cached); + } else { + toFetch.add(uuid); + } + } + + if (toFetch.isNotEmpty) { + final fetchedUrls = await _fetch(courseId, toFetch); + urls.addAll(fetchedUrls.values.toList()); + for (final entry in fetchedUrls.entries) { + await _setCached(entry.key, entry.value); + } + } + + return urls; + } + + static String? _getCached(String uuid) => _storage.read(uuid); + + static Future _setCached(String uuid, String url) => + _storage.write(uuid, url); + + static Future> _fetch( + String courseId, + List uuids, + ) async { + if (_cache.containsKey(courseId)) { + return _cache[courseId]!.future; + } + + final completer = Completer>(); + _cache[courseId] = completer; + + final where = { + "id": {"in": uuids.join(",")}, + }; + final limit = uuids.length; + + try { + final cmsCoursePlanMediaResult = await PayloadRepo.payload.find( + CmsCoursePlanMedia.slug, + CmsCoursePlanMedia.fromJson, + where: where, + limit: limit, + page: 1, + sort: "createdAt", + ); + + if (cmsCoursePlanMediaResult.docs.isEmpty) { + return {}; + } + + final media = Map.fromEntries( + cmsCoursePlanMediaResult.docs + .where((media) => media.url != null) + .map((media) => MapEntry(media.id, media.url!)), + ); + + completer.complete(media); + return media; + } catch (e) { + completer.completeError(e); + rethrow; + } finally { + _cache.remove(courseId); + } + } +} diff --git a/lib/pangea/course_plans/course_plan_builder.dart b/lib/pangea/course_plans/course_plan_builder.dart index c0f9ee343..f44ed9815 100644 --- a/lib/pangea/course_plans/course_plan_builder.dart +++ b/lib/pangea/course_plans/course_plan_builder.dart @@ -6,7 +6,7 @@ import 'package:fluffychat/pangea/course_plans/course_plans_repo.dart'; class CoursePlanBuilder extends StatefulWidget { final String? courseId; final VoidCallback? onNotFound; - final Function(CoursePlanModel course)? onFound; + final Function(CoursePlanModel course)? onLoaded; final Widget Function( BuildContext context, CoursePlanController controller, @@ -17,7 +17,7 @@ class CoursePlanBuilder extends StatefulWidget { required this.courseId, required this.builder, this.onNotFound, - this.onFound, + this.onLoaded, }); @override @@ -61,9 +61,13 @@ class CoursePlanController extends State { }); course = await CoursePlansRepo.get(widget.courseId!); - course == null - ? widget.onNotFound?.call() - : widget.onFound?.call(course!); + if (course == null) { + widget.onNotFound?.call(); + } else { + await course!.init(); + } + + widget.onLoaded?.call(course!); } catch (e) { error = e; } finally { diff --git a/lib/pangea/course_plans/course_plan_model.dart b/lib/pangea/course_plans/course_plan_model.dart index 1c1fa2add..77cff337f 100644 --- a/lib/pangea/course_plans/course_plan_model.dart +++ b/lib/pangea/course_plans/course_plan_model.dart @@ -1,71 +1,15 @@ -import 'package:fluffychat/pangea/activity_generator/media_enum.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; import 'package:fluffychat/pangea/common/config/environment.dart'; +import 'package:fluffychat/pangea/course_plans/course_media_repo.dart'; +import 'package:fluffychat/pangea/course_plans/course_topic_model.dart'; +import 'package:fluffychat/pangea/course_plans/course_topic_repo.dart'; import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; import 'package:fluffychat/pangea/learning_settings/models/language_model.dart'; import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_activity.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_activity_media.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_media.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic_location.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic_location_media.dart'; - -/// Represents a topic in the course planner response. -class Topic { - final String title; - final String description; - final String location; - final String uuid; - final String? imageUrl; - - final List activities; - - Topic({ - required this.title, - required this.description, - this.location = "Unknown", - required this.uuid, - List? activities, - this.imageUrl, - }) : activities = activities ?? []; - - /// Deserialize from JSON - factory Topic.fromJson(Map json) { - return Topic( - title: json['title'] as String, - description: json['description'] as String, - location: json['location'] as String? ?? "Unknown", - uuid: json['uuid'] as String, - activities: (json['activities'] as List?) - ?.map( - (e) => ActivityPlanModel.fromJson(e as Map), - ) - .toList() ?? - [], - imageUrl: json['image_url'] as String?, - ); - } - - /// Serialize to JSON - Map toJson() { - return { - 'title': title, - 'description': description, - 'location': location, - 'uuid': uuid, - 'activities': activities.map((e) => e.toJson()).toList(), - 'image_url': imageUrl, - }; - } - - List get activityIds => activities.map((e) => e.activityId).toList(); -} /// Represents a course plan in the course planner response. class CoursePlanModel { + final String uuid; + final String targetLanguage; final String languageOfInstructions; final LanguageLevelTypeEnum cefrLevel; @@ -73,10 +17,8 @@ class CoursePlanModel { final String title; final String description; - final String uuid; - - final List topics; - final String? imageUrl; + final List topicIds; + final List mediaIds; CoursePlanModel({ required this.targetLanguage, @@ -85,12 +27,9 @@ class CoursePlanModel { required this.title, required this.description, required this.uuid, - List? topics, - this.imageUrl, - }) : topics = topics ?? []; - - int get activities => - topics.map((t) => t.activities.length).reduce((a, b) => a + b); + required this.topicIds, + required this.mediaIds, + }); LanguageModel? get targetLanguageModel => PLanguageStore.byLangCode(targetLanguage); @@ -107,16 +46,17 @@ class CoursePlanModel { languageOfInstructions.toUpperCase(); String? topicID(String activityID) { - for (final topic in topics) { - for (final activity in topic.activities) { - if (activity.activityId == activityID) { - return topic.uuid; - } + for (final topic in loadedTopics) { + if (topic.activityIds.any((id) => id == activityID)) { + return topic.uuid; } } return null; } + int get totalActivities => + loadedTopics.fold(0, (sum, topic) => sum + topic.activityIds.length); + /// Deserialize from JSON factory CoursePlanModel.fromJson(Map json) { return CoursePlanModel( @@ -126,11 +66,14 @@ class CoursePlanModel { title: json['title'] as String, description: json['description'] as String, uuid: json['uuid'] as String, - topics: (json['topics'] as List?) - ?.map((e) => Topic.fromJson(e as Map)) + topicIds: (json['topic_ids'] as List?) + ?.map((e) => e as String) + .toList() ?? + [], + mediaIds: (json['media_ids'] as List?) + ?.map((e) => e as String) .toList() ?? [], - imageUrl: json['image_url'] as String?, ); } @@ -143,144 +86,41 @@ class CoursePlanModel { 'title': title, 'description': description, 'uuid': uuid, - 'topics': topics.map((e) => e.toJson()).toList(), - 'image_url': imageUrl, + 'topic_ids': topicIds, + 'media_ids': mediaIds, }; } - factory CoursePlanModel.fromCmsDocs( - CmsCoursePlan cmsCoursePlan, - List? cmsCoursePlanMedias, - List? cmsCoursePlanTopics, - List? cmsCoursePlanTopicLocations, - List? cmsCoursePlanTopicLocationMedias, - List? cmsCoursePlanActivities, - List? cmsCoursePlanActivityMedias, - ) { - // fetch topics - List? topics; - if (cmsCoursePlanTopics != null) { - for (final topic in cmsCoursePlanTopics) { - // select locations of current topic - List? topicLocations; - if (cmsCoursePlanTopicLocations != null) { - for (final location in cmsCoursePlanTopicLocations) { - if (location.coursePlanTopics.contains(topic.id)) { - topicLocations ??= []; - topicLocations.add(location); - } - } - } + bool get topicListComplete => topicIds.length == loadedTopics.length; + List get loadedTopics => CourseTopicRepo.getSync(topicIds); + Future> fetchTopics() => + CourseTopicRepo.get(uuid, topicIds); - // select activities of current topic - List? topicActivities; - if (cmsCoursePlanActivities != null) { - for (final activity in cmsCoursePlanActivities) { - if (activity.coursePlanTopics.contains(topic.id)) { - topicActivities ??= []; - topicActivities.add(activity); - } - } - } + bool get mediaListComplete => mediaIds.length == loadedMediaUrls.length; + List get loadedMediaUrls => CourseMediaRepo.getSync(mediaIds); + Future> fetchMediaUrls() => CourseMediaRepo.get(uuid, mediaIds); + String? get imageUrl => loadedMediaUrls.isEmpty + ? null + : "${Environment.cmsApi}${loadedMediaUrls.first}"; - List? activityPlans; - if (topicActivities != null) { - for (final activity in topicActivities) { - // select media of current activity - List? activityMedias; - if (cmsCoursePlanActivityMedias != null) { - for (final media in cmsCoursePlanActivityMedias) { - if (media.coursePlanActivities.contains(activity.id)) { - activityMedias ??= []; - activityMedias.add(media); - } - } - } + Future init() async { + final courseFutures = [ + fetchMediaUrls(), + fetchTopics(), + ]; + await Future.wait(courseFutures); - final Map roles = {}; - for (final role in activity.roles) { - roles[role.id] = ActivityRole( - id: role.id, - name: role.name, - avatarUrl: role.avatarUrl, - goal: role.goal, - ); - } - - activityPlans ??= []; - activityPlans.add( - ActivityPlanModel( - req: ActivityPlanRequest( - topic: "", - mode: "", - objective: "", - media: MediaEnum.nan, - cefrLevel: activity.cefrLevel, - languageOfInstructions: activity.l1, - targetLanguage: activity.l2, - numberOfParticipants: activity.roles.length, - ), - activityId: activity.id, - title: activity.title, - description: activity.description, - learningObjective: activity.learningObjective, - instructions: activity.instructions, - vocab: activity.vocabs - .map((v) => Vocab(lemma: v.lemma, pos: v.pos)) - .toList(), - roles: roles, - imageURL: activityMedias != null && activityMedias.isNotEmpty - ? '${Environment.cmsApi}${activityMedias.first.url}' - : null, - ), - ); - } - } - - List? topicLocationMedias; - if (cmsCoursePlanTopicLocationMedias != null && - topicLocations != null && - topicLocations.isNotEmpty) { - final location = topicLocations.first; - for (final media in cmsCoursePlanTopicLocationMedias) { - if (media.coursePlanTopicLocations.contains(location.id)) { - topicLocationMedias ??= []; - topicLocationMedias.add(media); - } - } - } - - topics ??= []; - topics.add( - Topic( - uuid: topic.id, - title: topic.title, - description: topic.description, - location: topicLocations != null && topicLocations.isNotEmpty - ? topicLocations.first.name - : "Any", - activities: activityPlans, - imageUrl: - topicLocationMedias != null && topicLocationMedias.isNotEmpty - ? '${Environment.cmsApi}${topicLocationMedias.last.url}' - : null, - ), - ); - } - } - - return CoursePlanModel( - uuid: cmsCoursePlan.id, - title: cmsCoursePlan.title, - description: cmsCoursePlan.description, - cefrLevel: - LanguageLevelTypeEnumExtension.fromString(cmsCoursePlan.cefrLevel), - languageOfInstructions: cmsCoursePlan.l1, - targetLanguage: cmsCoursePlan.l2, - topics: topics, - imageUrl: cmsCoursePlanMedias != null && cmsCoursePlanMedias.isNotEmpty - ? '${Environment.cmsApi}${cmsCoursePlanMedias.first.url}' - : null, + final topicFutures = []; + topicFutures.addAll( + loadedTopics.map( + (topic) => topic.fetchActivities(), + ), ); + topicFutures.addAll( + loadedTopics.map( + (topic) => topic.fetchLocationMedia(), + ), + ); + await Future.wait(topicFutures); } } diff --git a/lib/pangea/course_plans/course_plan_room_extension.dart b/lib/pangea/course_plans/course_plan_room_extension.dart index 8de621e8b..69e4ec29b 100644 --- a/lib/pangea/course_plans/course_plan_room_extension.dart +++ b/lib/pangea/course_plans/course_plan_room_extension.dart @@ -1,10 +1,18 @@ import 'package:matrix/matrix.dart'; +import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +import 'package:fluffychat/pangea/activity_sessions/activity_role_model.dart'; +import 'package:fluffychat/pangea/activity_sessions/activity_roles_model.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; +import 'package:fluffychat/pangea/chat/constants/default_power_level.dart'; +import 'package:fluffychat/pangea/chat_settings/constants/pangea_room_types.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_event.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_model.dart'; +import 'package:fluffychat/pangea/course_plans/course_topic_model.dart'; import 'package:fluffychat/pangea/course_plans/course_user_event.dart'; import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; +import 'package:fluffychat/pangea/extensions/join_rule_extension.dart'; +import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart'; extension CoursePlanRoomExtension on Room { CoursePlanEvent? get coursePlan { @@ -32,7 +40,7 @@ extension CoursePlanRoomExtension on Room { final state = _courseUserState(userID); if (state == null) return false; - final topicIndex = course.topics.indexWhere( + final topicIndex = course.loadedTopics.indexWhere( (t) => t.uuid == topicID, ); @@ -40,27 +48,28 @@ extension CoursePlanRoomExtension on Room { throw Exception('Topic not found'); } - final activityIds = - course.topics[topicIndex].activities.map((a) => a.activityId).toList(); + final activityIds = course.loadedTopics[topicIndex].loadedActivities + .map((a) => a.activityId) + .toList(); return state.completedActivities(topicID).toSet().containsAll(activityIds); } - Topic? currentTopic( + CourseTopicModel? currentTopic( String userID, CoursePlanModel course, ) { if (coursePlan == null) return null; - final topicIDs = course.topics.map((t) => t.uuid).toList(); + final topicIDs = course.loadedTopics.map((t) => t.uuid).toList(); if (topicIDs.isEmpty) return null; final index = topicIDs.indexWhere( (t) => !_hasCompletedTopic(userID, t, course), ); - return index == -1 ? null : course.topics[index]; + return index == -1 ? null : course.loadedTopics[index]; } - Topic? ownCurrentTopic(CoursePlanModel course) => + CourseTopicModel? ownCurrentTopic(CoursePlanModel course) => currentTopic(client.userID!, course); int currentTopicIndex( @@ -68,7 +77,7 @@ extension CoursePlanRoomExtension on Room { CoursePlanModel course, ) { if (coursePlan == null) return -1; - final topicIDs = course.topics.map((t) => t.uuid).toList(); + final topicIDs = course.loadedTopics.map((t) => t.uuid).toList(); if (topicIDs.isEmpty) return -1; final index = topicIDs.indexWhere( @@ -93,7 +102,7 @@ extension CoursePlanRoomExtension on Room { if (user.id == BotName.byEnvironment) continue; final topicIndex = currentTopicIndex(user.id, course); if (topicIndex != -1) { - final topicID = course.topics[topicIndex].uuid; + final topicID = course.loadedTopics[topicIndex].uuid; topicUserMap.putIfAbsent(topicID, () => []).add(user); } } @@ -117,4 +126,57 @@ extension CoursePlanRoomExtension on Room { state.toJson(), ); } + + Future launchActivityRoom( + ActivityPlanModel activity, + ActivityRole? role, + ) async { + final roomID = await client.createRoom( + creationContent: { + 'type': "${PangeaRoomTypes.activitySession}:${activity.activityId}", + }, + visibility: Visibility.private, + name: activity.title, + initialState: [ + StateEvent( + type: PangeaEventTypes.activityPlan, + content: activity.toJson(), + ), + if (activity.imageURL != null) + StateEvent( + type: EventTypes.RoomAvatar, + content: {'url': activity.imageURL}, + ), + if (role != null) + StateEvent( + type: PangeaEventTypes.activityRole, + content: ActivityRolesModel({ + role.id: ActivityRoleModel( + id: role.id, + userId: client.userID!, + role: role.name, + ), + }).toJson(), + ), + RoomDefaults.defaultPowerLevels( + client.userID!, + ), + await client.pangeaJoinRules( + 'knock_restricted', + allow: [ + { + "type": "m.room_membership", + "room_id": id, + } + ], + ), + ], + ); + + await addToSpace(roomID); + if (pangeaSpaceParents.isEmpty) { + await client.waitForRoomInSync(roomID); + } + return roomID; + } } diff --git a/lib/pangea/course_plans/course_plans_repo.dart b/lib/pangea/course_plans/course_plans_repo.dart index b1b4939c0..f8aee147c 100644 --- a/lib/pangea/course_plans/course_plans_repo.dart +++ b/lib/pangea/course_plans/course_plans_repo.dart @@ -1,18 +1,12 @@ +import 'dart:async'; + import 'package:get_storage/get_storage.dart'; -import 'package:fluffychat/pangea/common/config/environment.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_model.dart'; import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; import 'package:fluffychat/pangea/learning_settings/models/language_model.dart'; import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_activity.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_activity_media.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_media.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic_location.dart'; -import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic_location_media.dart'; -import 'package:fluffychat/pangea/payload_client/payload_client.dart'; -import 'package:fluffychat/widgets/matrix.dart'; +import 'package:fluffychat/pangea/payload_client/payload_repo.dart'; class CourseFilter { final LanguageModel? targetLanguage; @@ -43,13 +37,9 @@ class CourseFilter { } class CoursePlansRepo { + static final Map> cache = {}; static final GetStorage _courseStorage = GetStorage("course_storage"); - static final PayloadClient payload = PayloadClient( - baseUrl: Environment.cmsApi, - accessToken: MatrixState.pangeaController.userController.accessToken, - ); - static CoursePlanModel? _getCached(String id) { final json = _courseStorage.read(id); if (json != null) { @@ -107,15 +97,30 @@ class CoursePlansRepo { return cached; } - final cmsCoursePlan = await payload.findById( - "course-plans", - id, - CmsCoursePlan.fromJson, - ); + if (cache.containsKey(id)) { + return cache[id]!.future; + } - final coursePlan = await _fromCmsCoursePlan(cmsCoursePlan); - await _setCached(coursePlan); - return coursePlan; + final completer = Completer(); + cache[id] = completer; + + try { + final cmsCoursePlan = await PayloadRepo.payload.findById( + "course-plans", + id, + CmsCoursePlan.fromJson, + ); + + final coursePlan = cmsCoursePlan.toCoursePlanModel(); + await _setCached(coursePlan); + completer.complete(coursePlan); + return coursePlan; + } catch (e) { + completer.completeError(e); + rethrow; + } finally { + cache.remove(id); + } } static Future> search({CourseFilter? filter}) async { @@ -170,7 +175,7 @@ class CoursePlansRepo { } } - final result = await payload.find( + final result = await PayloadRepo.payload.find( CmsCoursePlan.slug, CmsCoursePlan.fromJson, page: 1, @@ -178,13 +183,11 @@ class CoursePlansRepo { where: where, ); - final coursePlans = await Future.wait( - result.docs.map( - (cmsCoursePlan) => _fromCmsCoursePlan( - cmsCoursePlan, - ), - ), - ); + final coursePlans = result.docs + .map( + (cmsCoursePlan) => cmsCoursePlan.toCoursePlanModel(), + ) + .toList(); await _setCachedSearchResults( filter ?? CourseFilter(), @@ -193,170 +196,4 @@ class CoursePlansRepo { return coursePlans; } - - static Future _fromCmsCoursePlan( - CmsCoursePlan cmsCoursePlan, - ) async { - final medias = await _getMedia(cmsCoursePlan); - final topics = await _getTopics(cmsCoursePlan); - final locations = await _getTopicLocations(topics ?? []); - final locationMedias = await _getTopicLocationMedia(locations ?? []); - final activities = await _getTopicActivities(topics ?? []); - final activityMedias = await _getActivityMedia(activities ?? []); - return CoursePlanModel.fromCmsDocs( - cmsCoursePlan, - medias, - topics, - locations, - locationMedias, - activities, - activityMedias, - ); - } - - static Future?> _getMedia( - CmsCoursePlan cmsCoursePlan, - ) async { - final docs = cmsCoursePlan.coursePlanMedia?.docs; - if (docs == null || docs.isEmpty) return null; - - final where = { - "id": {"in": docs.join(",")}, - }; - final limit = docs.length; - final cmsCoursePlanMediaResult = await payload.find( - CmsCoursePlanMedia.slug, - CmsCoursePlanMedia.fromJson, - where: where, - limit: limit, - page: 1, - sort: "createdAt", - ); - return cmsCoursePlanMediaResult.docs; - } - - static Future?> _getTopics( - CmsCoursePlan cmsCoursePlan, - ) async { - final docs = cmsCoursePlan.coursePlanTopics?.docs; - if (docs == null || docs.isEmpty) return null; - - final where = { - "id": {"in": docs.join(",")}, - }; - final limit = docs.length; - final cmsCourseTopicsResult = await payload.find( - CmsCoursePlanTopic.slug, - CmsCoursePlanTopic.fromJson, - where: where, - limit: limit, - page: 1, - sort: "createdAt", - ); - return cmsCourseTopicsResult.docs; - } - - static Future?> _getTopicLocations( - List topics, - ) async { - final List locations = []; - for (final top in topics) { - if (top.coursePlanTopicLocations?.docs != null) { - locations.addAll(top.coursePlanTopicLocations!.docs!); - } - } - if (locations.isEmpty) return null; - - final where = { - "id": {"in": locations.join(",")}, - }; - final limit = locations.length; - final cmsCoursePlanTopicLocationsResult = await payload.find( - CmsCoursePlanTopicLocation.slug, - CmsCoursePlanTopicLocation.fromJson, - where: where, - limit: limit, - page: 1, - sort: "createdAt", - ); - return cmsCoursePlanTopicLocationsResult.docs; - } - - static Future?> _getTopicLocationMedia( - List locations, - ) async { - final List mediaIds = []; - for (final loc in locations) { - if (loc.coursePlanTopicLocationMedia?.docs != null) { - mediaIds.addAll(loc.coursePlanTopicLocationMedia!.docs!); - } - } - if (mediaIds.isEmpty) return null; - - final where = { - "id": {"in": mediaIds.join(",")}, - }; - final limit = mediaIds.length; - final cmsCoursePlanTopicLocationMediasResult = await payload.find( - CmsCoursePlanTopicLocationMedia.slug, - CmsCoursePlanTopicLocationMedia.fromJson, - where: where, - limit: limit, - page: 1, - sort: "createdAt", - ); - return cmsCoursePlanTopicLocationMediasResult.docs; - } - - static Future?> _getTopicActivities( - List topics, - ) async { - final List activities = []; - for (final top in topics) { - if (top.coursePlanActivities?.docs != null) { - activities.addAll(top.coursePlanActivities!.docs!); - } - } - if (activities.isEmpty) return null; - - final where = { - "id": {"in": activities.join(",")}, - }; - final limit = activities.length; - final cmsCoursePlanActivitiesResult = await payload.find( - CmsCoursePlanActivity.slug, - CmsCoursePlanActivity.fromJson, - where: where, - limit: limit, - page: 1, - sort: "createdAt", - ); - return cmsCoursePlanActivitiesResult.docs; - } - - static Future?> _getActivityMedia( - List activity, - ) async { - final List mediaIds = []; - for (final act in activity) { - if (act.coursePlanActivityMedia?.docs != null) { - mediaIds.addAll(act.coursePlanActivityMedia!.docs!); - } - } - if (mediaIds.isEmpty) return null; - - final where = { - "id": {"in": mediaIds.join(",")}, - }; - final limit = mediaIds.length; - final cmsCoursePlanActivityMediasResult = await payload.find( - CmsCoursePlanActivityMedia.slug, - CmsCoursePlanActivityMedia.fromJson, - where: where, - limit: limit, - page: 1, - sort: "createdAt", - ); - return cmsCoursePlanActivityMediasResult.docs; - } } diff --git a/lib/pangea/course_plans/course_topic_model.dart b/lib/pangea/course_plans/course_topic_model.dart new file mode 100644 index 000000000..cc9dd3467 --- /dev/null +++ b/lib/pangea/course_plans/course_topic_model.dart @@ -0,0 +1,86 @@ +import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +import 'package:fluffychat/pangea/common/config/environment.dart'; +import 'package:fluffychat/pangea/course_plans/course_activity_repo.dart'; +import 'package:fluffychat/pangea/course_plans/course_location_media_repo.dart'; +import 'package:fluffychat/pangea/course_plans/course_location_model.dart'; +import 'package:fluffychat/pangea/course_plans/course_location_repo.dart'; + +/// Represents a topic in the course planner response. +class CourseTopicModel { + final String title; + final String description; + final String uuid; + final List locationIds; + final List activityIds; + + CourseTopicModel({ + required this.title, + required this.description, + required this.uuid, + required this.activityIds, + required this.locationIds, + }); + + bool get locationListComplete => locationIds.length == loadedLocations.length; + List get loadedLocations => + CourseLocationRepo.getSync(locationIds); + Future> fetchLocations() => + CourseLocationRepo.get(uuid, locationIds); + String? get location => loadedLocations.firstOrNull?.name; + + bool get locationMediaListComplete => + loadedLocationMediaIds.length == + loadedLocations.map((e) => e.mediaIds.length).fold(0, (a, b) => a + b); + List get loadedLocationMediaIds => loadedLocations + .map((location) => CourseLocationMediaRepo.getSync(location.mediaIds)) + .expand((e) => e) + .toList(); + Future> fetchLocationMedia() async { + final allLocationMedia = []; + for (final location in await fetchLocations()) { + allLocationMedia.addAll( + await CourseLocationMediaRepo.get(uuid, location.mediaIds), + ); + } + return allLocationMedia; + } + + String? get imageUrl => loadedLocationMediaIds.isEmpty + ? null + : "${Environment.cmsApi}${loadedLocationMediaIds.first}"; + + bool get activityListComplete => + activityIds.length == loadedActivities.length; + List get loadedActivities => + CourseActivityRepo.getSync(activityIds); + Future> fetchActivities() => + CourseActivityRepo.get(uuid, activityIds); + + /// Deserialize from JSON + factory CourseTopicModel.fromJson(Map json) { + return CourseTopicModel( + title: json['title'] as String, + description: json['description'] as String, + uuid: json['uuid'] as String, + activityIds: (json['activity_ids'] as List?) + ?.map((e) => e as String) + .toList() ?? + [], + locationIds: (json['location_ids'] as List?) + ?.map((e) => e as String) + .toList() ?? + [], + ); + } + + /// Serialize to JSON + Map toJson() { + return { + 'title': title, + 'description': description, + 'uuid': uuid, + 'activity_ids': activityIds, + 'location_ids': locationIds, + }; + } +} diff --git a/lib/pangea/course_plans/course_topic_repo.dart b/lib/pangea/course_plans/course_topic_repo.dart new file mode 100644 index 000000000..50ad83682 --- /dev/null +++ b/lib/pangea/course_plans/course_topic_repo.dart @@ -0,0 +1,109 @@ +import 'dart:async'; + +import 'package:get_storage/get_storage.dart'; + +import 'package:fluffychat/pangea/course_plans/course_topic_model.dart'; +import 'package:fluffychat/pangea/payload_client/models/course_plan/cms_course_plan_topic.dart'; +import 'package:fluffychat/pangea/payload_client/payload_repo.dart'; + +class CourseTopicRepo { + static final Map>> _cache = {}; + static final GetStorage _storage = GetStorage('course_topic_storage'); + + static List getSync(List uuids) { + final topics = []; + + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + topics.add(cached); + } + } + + return topics; + } + + static Future> get( + String courseId, + List uuids, + ) async { + final topics = []; + final toFetch = []; + + for (final uuid in uuids) { + final cached = _getCached(uuid); + if (cached != null) { + topics.add(cached); + } else { + toFetch.add(uuid); + } + } + + if (toFetch.isNotEmpty) { + final fetchedTopics = await _fetch(courseId, toFetch); + topics.addAll(fetchedTopics); + await _setCached(fetchedTopics); + } + + return topics; + } + + static CourseTopicModel? _getCached(String uuid) { + final json = _storage.read(uuid); + if (json != null) { + try { + return CourseTopicModel.fromJson(Map.from(json)); + } catch (e) { + _storage.remove(uuid); + } + } + return null; + } + + static Future _setCached(List topics) async { + for (final topic in topics) { + await _storage.write(topic.uuid, topic.toJson()); + } + } + + static Future> _fetch( + String courseId, + List uuids, + ) async { + if (_cache.containsKey(courseId)) { + return _cache[courseId]!.future; + } + + final completer = Completer>(); + _cache[courseId] = completer; + + final where = { + "id": {"in": uuids.join(",")}, + }; + + final limit = uuids.length; + + try { + final cmsCourseTopicsResult = await PayloadRepo.payload.find( + CmsCoursePlanTopic.slug, + CmsCoursePlanTopic.fromJson, + where: where, + limit: limit, + page: 1, + sort: "createdAt", + ); + + final topics = cmsCourseTopicsResult.docs.map((topic) { + return topic.toCourseTopicModel(); + }).toList(); + + completer.complete(topics); + return topics; + } catch (e) { + completer.completeError(e); + rethrow; + } finally { + _cache.remove(courseId); + } + } +} diff --git a/lib/pangea/course_settings/course_settings.dart b/lib/pangea/course_settings/course_settings.dart index bd947215f..1912f7eb2 100644 --- a/lib/pangea/course_settings/course_settings.dart +++ b/lib/pangea/course_settings/course_settings.dart @@ -2,23 +2,20 @@ import 'package:flutter/material.dart'; -import 'package:cached_network_image/cached_network_image.dart'; -import 'package:cached_network_image_platform_interface/cached_network_image_platform_interface.dart'; import 'package:collection/collection.dart'; +import 'package:go_router/go_router.dart'; import 'package:matrix/matrix.dart'; import 'package:fluffychat/config/themes.dart'; import 'package:fluffychat/l10n/l10n.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_planner_builder.dart'; import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_card.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_suggestion_dialog.dart'; import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; +import 'package:fluffychat/pangea/common/widgets/url_image_widget.dart'; import 'package:fluffychat/pangea/course_creation/course_info_chip_widget.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_builder.dart'; import 'package:fluffychat/pangea/course_plans/course_plan_room_extension.dart'; import 'package:fluffychat/pangea/course_settings/pin_clipper.dart'; import 'package:fluffychat/pangea/course_settings/topic_participant_list.dart'; -import 'package:fluffychat/widgets/matrix.dart'; class CourseSettings extends StatelessWidget { final Room room; @@ -64,7 +61,7 @@ class CourseSettings extends StatelessWidget { return Column( spacing: isColumnMode ? 40.0 : 36.0, mainAxisSize: MainAxisSize.min, - children: course.topics.mapIndexed((index, topic) { + children: course.loadedTopics.mapIndexed((index, topic) { final unlocked = index <= currentTopicIndex; final usersInTopic = topicsToUsers[topic.uuid] ?? []; return AbsorbPointer( @@ -91,45 +88,18 @@ class CourseSettings extends StatelessWidget { children: [ ClipPath( clipper: PinClipper(), - child: topic.imageUrl != null - ? CachedNetworkImage( - imageRenderMethodForWeb: - ImageRenderMethodForWeb - .HttpGet, - httpHeaders: { - 'Authorization': - 'Bearer ${MatrixState.pangeaController.userController.accessToken}', - }, - width: 54.0, - height: 54.0, - fit: BoxFit.cover, - imageUrl: topic.imageUrl!, - placeholder: (context, url) { - return const Center( - child: - CircularProgressIndicator(), - ); - }, - errorWidget: - (context, url, error) { - return Container( - width: 54.0, - height: 54.0, - decoration: BoxDecoration( - color: theme.colorScheme - .secondary, - ), - ); - }, - ) - : Container( - width: 54.0, - height: 54.0, - decoration: BoxDecoration( - color: theme - .colorScheme.secondary, - ), - ), + child: ImageByUrl( + imageUrl: topic.imageUrl, + width: 54.0, + replacement: Container( + width: 54.0, + height: 54.0, + decoration: BoxDecoration( + color: + theme.colorScheme.secondary, + ), + ), + ), ), if (!unlocked) const Positioned( @@ -153,12 +123,13 @@ class CourseSettings extends StatelessWidget { fontSize: titleFontSize, ), ), - CourseInfoChip( - icon: Icons.location_on, - text: topic.location, - fontSize: descFontSize, - iconSize: iconSize, - ), + if (topic.location != null) + CourseInfoChip( + icon: Icons.location_on, + text: topic.location!, + fontSize: descFontSize, + iconSize: iconSize, + ), if (constraints.maxWidth < 700.0) Padding( padding: const EdgeInsetsGeometry @@ -196,36 +167,21 @@ class CourseSettings extends StatelessWidget { height: 210.0, child: ListView.builder( scrollDirection: Axis.horizontal, - itemCount: topic.activities.length, + itemCount: topic.loadedActivities.length, itemBuilder: (context, index) { - final activity = topic.activities[index]; return Padding( padding: const EdgeInsets.only(right: 24.0), - child: ActivityPlannerBuilder( - initialActivity: activity, - room: room, - builder: (activityController) { - return ActivitySuggestionCard( - controller: activityController, - onPressed: () { - showDialog( - context: context, - builder: (context) { - return ActivitySuggestionDialog( - controller: activityController, - buttonText: - L10n.of(context).launchToSpace, - ); - }, - ); - }, - width: 120.0, - height: 200.0, - fontSize: 12.0, - fontSizeSmall: 8.0, - iconSize: 8.0, - ); - }, + child: ActivitySuggestionCard( + activity: topic.loadedActivities[index], + // TODO: go to activity start page + onPressed: () => context.go( + "/rooms/spaces/${room.id}/activity/${topic.loadedActivities[index].activityId}", + ), + width: 120.0, + height: 200.0, + fontSize: 12.0, + fontSizeSmall: 8.0, + iconSize: 8.0, ), ); }, diff --git a/lib/pangea/payload_client/models/course_plan/cms_course_plan.dart b/lib/pangea/payload_client/models/course_plan/cms_course_plan.dart index 6835e1e41..fa914f0d7 100644 --- a/lib/pangea/payload_client/models/course_plan/cms_course_plan.dart +++ b/lib/pangea/payload_client/models/course_plan/cms_course_plan.dart @@ -1,3 +1,5 @@ +import 'package:fluffychat/pangea/course_plans/course_plan_model.dart'; +import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; import 'package:fluffychat/pangea/payload_client/join_field.dart'; import 'package:fluffychat/pangea/payload_client/polymorphic_relationship.dart'; @@ -65,4 +67,17 @@ class CmsCoursePlan { 'createdAt': createdAt, }; } + + CoursePlanModel toCoursePlanModel() { + return CoursePlanModel( + uuid: id, + targetLanguage: l2, + languageOfInstructions: l1, + cefrLevel: LanguageLevelTypeEnumExtension.fromString(cefrLevel), + title: title, + description: description, + mediaIds: coursePlanMedia?.docs ?? [], + topicIds: coursePlanTopics?.docs ?? [], + ); + } } diff --git a/lib/pangea/payload_client/models/course_plan/cms_course_plan_activity.dart b/lib/pangea/payload_client/models/course_plan/cms_course_plan_activity.dart index 412ce42ba..c76dc21df 100644 --- a/lib/pangea/payload_client/models/course_plan/cms_course_plan_activity.dart +++ b/lib/pangea/payload_client/models/course_plan/cms_course_plan_activity.dart @@ -1,3 +1,6 @@ +import 'package:fluffychat/pangea/activity_generator/media_enum.dart'; +import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; +import 'package:fluffychat/pangea/activity_planner/activity_plan_request.dart'; import 'package:fluffychat/pangea/learning_settings/enums/language_level_type_enum.dart'; import 'package:fluffychat/pangea/payload_client/join_field.dart'; import 'package:fluffychat/pangea/payload_client/polymorphic_relationship.dart'; @@ -33,6 +36,15 @@ class CmsCoursePlanActivityRole { 'avatarUrl': avatarUrl, }; } + + ActivityRole toActivityRole() { + return ActivityRole( + id: id, + name: name, + goal: goal, + avatarUrl: avatarUrl, + ); + } } /// Represents vocabulary in a course plan activity @@ -75,6 +87,7 @@ class CmsCoursePlanActivity { final String instructions; final String l1; // Language of instruction final String l2; // Target language + final String mode; final LanguageLevelTypeEnum cefrLevel; final List roles; final List vocabs; @@ -93,6 +106,7 @@ class CmsCoursePlanActivity { required this.instructions, required this.l1, required this.l2, + required this.mode, required this.cefrLevel, required this.roles, required this.vocabs, @@ -113,6 +127,7 @@ class CmsCoursePlanActivity { instructions: json['instructions'] as String, l1: json['l1'] as String, l2: json['l2'] as String, + mode: json['mode'] as String, cefrLevel: LanguageLevelTypeEnumExtension.fromString( json['cefrLevel'] as String, ), @@ -152,6 +167,7 @@ class CmsCoursePlanActivity { 'instructions': instructions, 'l1': l1, 'l2': l2, + 'mode': mode, 'cefrLevel': cefrLevel.string, 'roles': roles.map((role) => role.toJson()).toList(), 'vocabs': vocabs.map((vocab) => vocab.toJson()).toList(), @@ -163,4 +179,29 @@ class CmsCoursePlanActivity { 'createdAt': createdAt, }; } + + ActivityPlanModel toActivityPlanModel(String? imageUrl) { + return ActivityPlanModel( + req: ActivityPlanRequest( + topic: "", + mode: mode, + objective: "", + media: MediaEnum.nan, + cefrLevel: cefrLevel, + languageOfInstructions: l1, + targetLanguage: l2, + numberOfParticipants: roles.length, + ), + activityId: id, + title: title, + description: description, + learningObjective: learningObjective, + instructions: instructions, + vocab: vocabs.map((v) => Vocab(lemma: v.lemma, pos: v.pos)).toList(), + roles: Map.fromEntries( + roles.map((role) => MapEntry(role.id, role.toActivityRole())), + ), + imageURL: imageUrl, + ); + } } diff --git a/lib/pangea/payload_client/models/course_plan/cms_course_plan_topic.dart b/lib/pangea/payload_client/models/course_plan/cms_course_plan_topic.dart index 69186f03d..d8928d8f0 100644 --- a/lib/pangea/payload_client/models/course_plan/cms_course_plan_topic.dart +++ b/lib/pangea/payload_client/models/course_plan/cms_course_plan_topic.dart @@ -1,3 +1,4 @@ +import 'package:fluffychat/pangea/course_plans/course_topic_model.dart'; import 'package:fluffychat/pangea/payload_client/join_field.dart'; import 'package:fluffychat/pangea/payload_client/polymorphic_relationship.dart'; @@ -65,4 +66,14 @@ class CmsCoursePlanTopic { 'createdAt': createdAt, }; } + + CourseTopicModel toCourseTopicModel() { + return CourseTopicModel( + title: title, + description: description, + uuid: id, + activityIds: coursePlanActivities?.docs ?? [], + locationIds: coursePlanTopicLocations?.docs ?? [], + ); + } } diff --git a/lib/pangea/payload_client/models/course_plan/cms_course_plan_topic_location.dart b/lib/pangea/payload_client/models/course_plan/cms_course_plan_topic_location.dart index ab69a5988..343d36523 100644 --- a/lib/pangea/payload_client/models/course_plan/cms_course_plan_topic_location.dart +++ b/lib/pangea/payload_client/models/course_plan/cms_course_plan_topic_location.dart @@ -1,3 +1,4 @@ +import 'package:fluffychat/pangea/course_plans/course_location_model.dart'; import 'package:fluffychat/pangea/payload_client/join_field.dart'; import 'package:fluffychat/pangea/payload_client/polymorphic_relationship.dart'; @@ -62,4 +63,12 @@ class CmsCoursePlanTopicLocation { 'createdAt': createdAt, }; } + + CourseLocationModel toCourseLocationModel() { + return CourseLocationModel( + uuid: id, + name: name, + mediaIds: coursePlanTopicLocationMedia?.docs ?? [], + ); + } } diff --git a/lib/pangea/payload_client/payload_repo.dart b/lib/pangea/payload_client/payload_repo.dart new file mode 100644 index 000000000..b851bb168 --- /dev/null +++ b/lib/pangea/payload_client/payload_repo.dart @@ -0,0 +1,10 @@ +import 'package:fluffychat/pangea/common/config/environment.dart'; +import 'package:fluffychat/pangea/payload_client/payload_client.dart'; +import 'package:fluffychat/widgets/matrix.dart'; + +class PayloadRepo { + static final PayloadClient payload = PayloadClient( + baseUrl: Environment.cmsApi, + accessToken: MatrixState.pangeaController.userController.accessToken, + ); +} diff --git a/lib/pangea/spaces/utils/load_participants_util.dart b/lib/pangea/spaces/utils/load_participants_util.dart index 1f6fd2735..b5c0fe96c 100644 --- a/lib/pangea/spaces/utils/load_participants_util.dart +++ b/lib/pangea/spaces/utils/load_participants_util.dart @@ -9,7 +9,7 @@ import 'package:fluffychat/pangea/user/models/analytics_profile_model.dart'; import 'package:fluffychat/widgets/matrix.dart'; class LoadParticipantsBuilder extends StatefulWidget { - final Room room; + final Room? room; final bool loadProfiles; final Widget Function( BuildContext context, @@ -34,7 +34,7 @@ class LoadParticipantsBuilderState extends State { final Map _levelsCache = {}; - List get participants => widget.room.getParticipants(); + List get participants => widget.room?.getParticipants() ?? []; @override void initState() { @@ -45,7 +45,7 @@ class LoadParticipantsBuilderState extends State { @override void didUpdateWidget(LoadParticipantsBuilder oldWidget) { super.didUpdateWidget(oldWidget); - if (oldWidget.room.id != widget.room.id) { + if (oldWidget.room?.id != widget.room?.id) { _loadParticipants(); } } @@ -57,7 +57,7 @@ class LoadParticipantsBuilderState extends State { error = null; }); - await widget.room.requestParticipants( + await widget.room?.requestParticipants( [Membership.join, Membership.invite, Membership.knock], false, true, @@ -70,7 +70,7 @@ class LoadParticipantsBuilderState extends State { e: err, s: s, data: { - 'roomId': widget.room.id, + 'roomId': widget.room?.id, }, ); } finally { diff --git a/lib/pangea/user/controllers/user_controller.dart b/lib/pangea/user/controllers/user_controller.dart index 43ddb251e..cc56db9d7 100644 --- a/lib/pangea/user/controllers/user_controller.dart +++ b/lib/pangea/user/controllers/user_controller.dart @@ -1,12 +1,10 @@ import 'dart:async'; import 'package:collection/collection.dart'; -import 'package:get_storage/get_storage.dart'; import 'package:jwt_decode/jwt_decode.dart'; import 'package:matrix/matrix.dart' as matrix; import 'package:sentry_flutter/sentry_flutter.dart'; -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; import 'package:fluffychat/pangea/analytics_misc/client_analytics_extension.dart'; import 'package:fluffychat/pangea/bot/utils/bot_name.dart'; import 'package:fluffychat/pangea/common/constants/model_keys.dart'; @@ -150,7 +148,6 @@ class UserController { _initializing = true; try { - await GetStorage.init('activity_plan_by_id_storage'); await _initialize(); _addProfileListener(); _addAnalyticsRoomIdsToPublicProfile(); @@ -458,21 +455,21 @@ class UserController { ); } - Future> getBookmarkedActivities() async { - if (activitiesProfile == null) { - throw Exception("Activities profile is not initialized"); - } + // Future> getBookmarkedActivities() async { + // if (activitiesProfile == null) { + // throw Exception("Activities profile is not initialized"); + // } - return activitiesProfile!.getBookmarkedActivities(); - } + // return activitiesProfile!.getBookmarkedActivities(); + // } - List getBookmarkedActivitiesSync() { - if (activitiesProfile == null) { - throw Exception("Activities profile is not initialized"); - } + // List getBookmarkedActivitiesSync() { + // if (activitiesProfile == null) { + // throw Exception("Activities profile is not initialized"); + // } - return activitiesProfile!.getBookmarkedActivitiesSync(); - } + // return activitiesProfile!.getBookmarkedActivitiesSync(); + // } Future updateBookmarkedActivity({ required String activityId, diff --git a/lib/pangea/user/models/activities_profile_model.dart b/lib/pangea/user/models/activities_profile_model.dart index 2dfca0e28..b9e9d41ed 100644 --- a/lib/pangea/user/models/activities_profile_model.dart +++ b/lib/pangea/user/models/activities_profile_model.dart @@ -1,5 +1,3 @@ -import 'package:fluffychat/pangea/activity_planner/activity_plan_model.dart'; -import 'package:fluffychat/pangea/activity_suggestions/activity_plan_repo.dart'; import 'package:fluffychat/pangea/common/constants/model_keys.dart'; import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart'; @@ -26,14 +24,14 @@ class ActivitiesProfileModel { _bookmarkedActivities.remove(activityId); } - Future> getBookmarkedActivities() => Future.wait( - _bookmarkedActivities.map((id) => ActivityPlanRepo.get(id)).toList(), - ); + // Future> getBookmarkedActivities() => Future.wait( + // _bookmarkedActivities.map((id) => ActivityPlanRepo.get(id)).toList(), + // ); - List getBookmarkedActivitiesSync() => _bookmarkedActivities - .map((id) => ActivityPlanRepo.getCached(id)) - .whereType() - .toList(); + // List getBookmarkedActivitiesSync() => _bookmarkedActivities + // .map((id) => ActivityPlanRepo.getCached(id)) + // .whereType() + // .toList(); static ActivitiesProfileModel fromJson(Map json) { if (!json.containsKey(PangeaEventTypes.profileActivities)) {