From 8d5429771c7bd624746b4769031554778be72597 Mon Sep 17 00:00:00 2001 From: ggurdin <46800240+ggurdin@users.noreply.github.com> Date: Tue, 20 May 2025 17:07:22 -0400 Subject: [PATCH] chore: scroll activity dialog image with other content (#2860) --- .../activity_planner_builder.dart | 2 +- .../activity_suggestion_dialog.dart | 656 +++++++++--------- 2 files changed, 346 insertions(+), 312 deletions(-) diff --git a/lib/pangea/activity_planner/activity_planner_builder.dart b/lib/pangea/activity_planner/activity_planner_builder.dart index a45521044..36e72c0c9 100644 --- a/lib/pangea/activity_planner/activity_planner_builder.dart +++ b/lib/pangea/activity_planner/activity_planner_builder.dart @@ -211,7 +211,7 @@ class ActivityPlannerBuilderState extends State { } Future clearEdits() async { - _resetActivity(); + await _resetActivity(); if (mounted) { setState(() { isEditing = false; diff --git a/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart b/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart index c2e16f87d..3a1282b3f 100644 --- a/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart +++ b/lib/pangea/activity_suggestions/activity_suggestion_dialog.dart @@ -86,320 +86,350 @@ class ActivitySuggestionDialogState extends State { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Stack( - alignment: Alignment.center, - children: [ - SizedBox( - width: _width, - child: widget.controller.avatar != null - ? Image.memory( - widget.controller.avatar!, - fit: BoxFit.cover, - ) - : widget.controller.updatedActivity.imageURL != - null - ? widget.controller.updatedActivity - .imageURL! - .startsWith("mxc") - ? MxcImage( - uri: Uri.parse( - widget.controller.updatedActivity - .imageURL!, - ), - width: _width, - height: 200, - cacheKey: widget.controller - .updatedActivity.bookmarkId, - fit: BoxFit.cover, - ) - : CachedNetworkImage( - imageUrl: widget.controller - .updatedActivity.imageURL!, - fit: BoxFit.cover, - placeholder: (context, url) => - const Center( - child: - CircularProgressIndicator(), - ), - errorWidget: - (context, url, error) => - const SizedBox(), - ) - : null, - ), - if (widget.controller.isEditing) - Positioned( - bottom: 8.0, - child: InkWell( - borderRadius: BorderRadius.circular(90), - onTap: widget.controller.selectAvatar, - child: const CircleAvatar( - radius: 24.0, - child: Icon( - Icons.add_a_photo_outlined, - size: 24.0, - ), - ), - ), - ), - ], - ), Flexible( child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - spacing: 8.0, - mainAxisSize: MainAxisSize.min, - children: [ - if (widget.controller.isEditing) - ActivitySuggestionCardRow( - icon: Icons.event_note_outlined, - child: TextFormField( - controller: - widget.controller.titleController, - decoration: InputDecoration( - labelText: - L10n.of(context).activityTitle, - ), - maxLines: 2, - minLines: 1, - ), - ) - else - ActivitySuggestionCardRow( - icon: Icons.event_note_outlined, - child: Text( - widget.controller.updatedActivity.title, - style: - theme.textTheme.titleLarge?.copyWith( - fontWeight: FontWeight.bold, - ), - maxLines: 6, - overflow: TextOverflow.ellipsis, - ), - ), - if (widget.controller.isEditing) - ActivitySuggestionCardRow( - icon: Symbols.target, - child: TextFormField( - controller: widget.controller - .learningObjectivesController, - decoration: InputDecoration( - labelText: L10n.of(context) - .learningObjectiveLabel, - ), - maxLines: 4, - minLines: 1, - ), - ) - else - ActivitySuggestionCardRow( - icon: Symbols.target, - child: Text( - widget.controller.updatedActivity - .learningObjective, - maxLines: 6, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodyLarge, - ), - ), - if (widget.controller.isEditing) - ActivitySuggestionCardRow( - icon: Symbols.steps, - child: TextFormField( - controller: widget - .controller.instructionsController, - decoration: InputDecoration( - labelText: - L10n.of(context).instructions, - ), - maxLines: 8, - minLines: 1, - ), - ) - else - ActivitySuggestionCardRow( - icon: Symbols.steps, - child: Text( - widget.controller.updatedActivity - .instructions, - maxLines: 8, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodyLarge, - ), - ), - if (widget.controller.isEditing) - ActivitySuggestionCardRow( - icon: Icons.group_outlined, - child: TextFormField( - controller: widget - .controller.participantsController, - decoration: InputDecoration( - labelText: L10n.of(context).classRoster, - ), - 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; - } - } catch (e) { - return L10n.of(context) - .pleaseEnterANumber; - } - return null; - }, - ), - ) - else - ActivitySuggestionCardRow( - icon: Icons.group_outlined, - child: Text( - L10n.of(context).countParticipants( - widget.controller.updatedActivity.req - .numberOfParticipants, - ), - style: theme.textTheme.bodyLarge, - ), - ), - if (widget.controller.isEditing) - ActivitySuggestionCardRow( - icon: Symbols.dictionary, - child: ConstrainedBox( - constraints: const BoxConstraints( - maxHeight: 60.0, - ), - child: SingleChildScrollView( - child: Wrap( - spacing: 4.0, - runSpacing: 4.0, - children: widget.controller.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: () => widget + child: Column( + spacing: 8.0, + mainAxisSize: MainAxisSize.min, + children: [ + Stack( + alignment: Alignment.center, + children: [ + SizedBox( + width: _width, + child: widget.controller.avatar != null + ? Image.memory( + widget.controller.avatar!, + fit: BoxFit.cover, + ) + : widget.controller.updatedActivity + .imageURL != + null + ? widget.controller.updatedActivity + .imageURL! + .startsWith("mxc") + ? MxcImage( + uri: Uri.parse( + widget .controller - .removeVocab(i), - child: Row( - spacing: 4.0, - mainAxisSize: - MainAxisSize.min, - children: [ - Text(vocab.lemma), - const Icon( - Icons.close, - size: 12.0, - ), - ], - ), + .updatedActivity + .imageURL!, ), - ), - ), - ) - .toList(), - ), - ), - ), - ) - else - ActivitySuggestionCardRow( - icon: Symbols.dictionary, - child: ConstrainedBox( - constraints: const BoxConstraints( - maxHeight: 60.0, - ), - child: SingleChildScrollView( - child: Wrap( - spacing: 4.0, - runSpacing: 4.0, - children: widget.controller.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, + width: _width, + height: 200, + cacheKey: widget + .controller + .updatedActivity + .bookmarkId, + fit: BoxFit.cover, + ) + : CachedNetworkImage( + imageUrl: widget + .controller + .updatedActivity + .imageURL!, + fit: BoxFit.cover, + placeholder: + (context, url) => + const Center( + child: + CircularProgressIndicator(), ), - ), - child: Text( - vocab.lemma, - style: theme - .textTheme.bodyMedium, - ), - ), - ) - .toList(), - ), - ), - ), + errorWidget: ( + context, + url, + error, + ) => + const SizedBox(), + ) + : null, ), - if (widget.controller.isEditing) - Padding( - padding: const EdgeInsets.symmetric( - vertical: 4.0, - ), - child: Row( - spacing: 4.0, - children: [ - Expanded( - child: TextFormField( - controller: widget - .controller.vocabController, - decoration: InputDecoration( - hintText: L10n.of(context) - .addVocabulary, - ), - maxLines: 1, - onFieldSubmitted: (_) => - widget.controller.addVocab(), + if (widget.controller.isEditing) + Positioned( + bottom: 8.0, + child: InkWell( + borderRadius: BorderRadius.circular(90), + onTap: widget.controller.selectAvatar, + child: const CircleAvatar( + radius: 24.0, + child: Icon( + Icons.add_a_photo_outlined, + size: 24.0, ), ), - 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: widget.controller.addVocab, - ), - ], + ), ), - ), - ], - ), + ], + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + child: Column( + children: [ + if (widget.controller.isEditing) + ActivitySuggestionCardRow( + icon: Icons.event_note_outlined, + child: TextFormField( + controller: + widget.controller.titleController, + decoration: InputDecoration( + labelText: + L10n.of(context).activityTitle, + ), + maxLines: 2, + minLines: 1, + ), + ) + else + ActivitySuggestionCardRow( + icon: Icons.event_note_outlined, + child: Text( + widget + .controller.updatedActivity.title, + style: theme.textTheme.titleLarge + ?.copyWith( + fontWeight: FontWeight.bold, + ), + maxLines: 6, + overflow: TextOverflow.ellipsis, + ), + ), + if (widget.controller.isEditing) + ActivitySuggestionCardRow( + icon: Symbols.target, + child: TextFormField( + controller: widget.controller + .learningObjectivesController, + decoration: InputDecoration( + labelText: L10n.of(context) + .learningObjectiveLabel, + ), + maxLines: 4, + minLines: 1, + ), + ) + else + ActivitySuggestionCardRow( + icon: Symbols.target, + child: Text( + widget.controller.updatedActivity + .learningObjective, + maxLines: 6, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodyLarge, + ), + ), + if (widget.controller.isEditing) + ActivitySuggestionCardRow( + icon: Symbols.steps, + child: TextFormField( + controller: widget.controller + .instructionsController, + decoration: InputDecoration( + labelText: + L10n.of(context).instructions, + ), + maxLines: 8, + minLines: 1, + ), + ) + else + ActivitySuggestionCardRow( + icon: Symbols.steps, + child: Text( + widget.controller.updatedActivity + .instructions, + maxLines: 8, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.bodyLarge, + ), + ), + if (widget.controller.isEditing) + ActivitySuggestionCardRow( + icon: Icons.group_outlined, + child: TextFormField( + controller: widget.controller + .participantsController, + decoration: InputDecoration( + labelText: + L10n.of(context).classRoster, + ), + 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; + } + } catch (e) { + return L10n.of(context) + .pleaseEnterANumber; + } + return null; + }, + ), + ) + else + ActivitySuggestionCardRow( + icon: Icons.group_outlined, + child: Text( + L10n.of(context).countParticipants( + widget.controller.updatedActivity + .req.numberOfParticipants, + ), + style: theme.textTheme.bodyLarge, + ), + ), + if (widget.controller.isEditing) + ActivitySuggestionCardRow( + icon: Symbols.dictionary, + child: ConstrainedBox( + constraints: const BoxConstraints( + maxHeight: 60.0, + ), + child: SingleChildScrollView( + child: Wrap( + spacing: 4.0, + runSpacing: 4.0, + children: widget.controller.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: () => widget + .controller + .removeVocab(i), + child: Row( + spacing: 4.0, + mainAxisSize: + MainAxisSize + .min, + children: [ + Text(vocab.lemma), + const Icon( + Icons.close, + size: 12.0, + ), + ], + ), + ), + ), + ), + ) + .toList(), + ), + ), + ), + ) + else + ActivitySuggestionCardRow( + icon: Symbols.dictionary, + child: ConstrainedBox( + constraints: const BoxConstraints( + maxHeight: 60.0, + ), + child: SingleChildScrollView( + child: Wrap( + spacing: 4.0, + runSpacing: 4.0, + children: widget.controller.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: theme.textTheme + .bodyMedium, + ), + ), + ) + .toList(), + ), + ), + ), + ), + if (widget.controller.isEditing) + Padding( + padding: const EdgeInsets.symmetric( + vertical: 4.0, + ), + child: Row( + spacing: 4.0, + children: [ + Expanded( + child: TextFormField( + controller: widget + .controller.vocabController, + decoration: InputDecoration( + hintText: L10n.of(context) + .addVocabulary, + ), + maxLines: 1, + onFieldSubmitted: (_) => widget + .controller + .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: + widget.controller.addVocab, + ), + ], + ), + ), + ], + ), + ), + ], ), ), ), @@ -459,13 +489,17 @@ class ActivitySuggestionDialogState extends State { ), ), if (widget.controller.isEditing) - GestureDetector( - child: const Icon( - Icons.close_outlined, - size: 16.0, + IconButton.filled( + style: IconButton.styleFrom( + backgroundColor: theme.colorScheme.primary, ), - onTap: () { - widget.controller.clearEdits(); + padding: const EdgeInsets.all(6.0), + constraints: + const BoxConstraints(), // override default min size of 48px + iconSize: 24.0, + icon: const Icon(Icons.close_outlined), + onPressed: () async { + await widget.controller.clearEdits(); widget.controller.setEditing(false); }, )