From 2bc421e6e7c26f30e506af2e1578462b24d5bf19 Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 10 Oct 2024 15:57:50 -0400 Subject: [PATCH 1/3] make popup dimensions dynamic --- .../controllers/choreographer.dart | 7 +- .../controllers/igc_controller.dart | 3 +- lib/pangea/choreographer/widgets/it_bar.dart | 3 +- lib/pangea/utils/instructions.dart | 17 +- lib/pangea/utils/overlay.dart | 229 +++++++++--------- .../common_widgets/overlay_container.dart | 19 +- .../widgets/igc/pangea_text_controller.dart | 14 +- lib/pangea/widgets/igc/span_card.dart | 82 +++---- 8 files changed, 187 insertions(+), 187 deletions(-) diff --git a/lib/pangea/choreographer/controllers/choreographer.dart b/lib/pangea/choreographer/controllers/choreographer.dart index 9053d3353..cc016b1ca 100644 --- a/lib/pangea/choreographer/controllers/choreographer.dart +++ b/lib/pangea/choreographer/controllers/choreographer.dart @@ -74,8 +74,11 @@ class Choreographer { CanSendStatus.showPaywall) { OverlayUtil.showPositionedCard( context: context, - cardToShow: const PaywallCard(), - cardSize: const Size(325, 325), + cardToShow: PaywallCard( + chatController: chatController, + ), + maxHeight: 325, + maxWidth: 325, transformTargetId: inputTransformTargetKey, ); return; diff --git a/lib/pangea/choreographer/controllers/igc_controller.dart b/lib/pangea/choreographer/controllers/igc_controller.dart index 4beea095f..e835359e6 100644 --- a/lib/pangea/choreographer/controllers/igc_controller.dart +++ b/lib/pangea/choreographer/controllers/igc_controller.dart @@ -124,7 +124,8 @@ class IgcController { ), roomId: choreographer.roomId, ), - cardSize: match.isITStart ? const Size(350, 260) : const Size(400, 400), + maxHeight: match.isITStart ? 260 : 400, + maxWidth: match.isITStart ? 350 : 400, transformTargetId: choreographer.inputTransformTargetKey, ); } diff --git a/lib/pangea/choreographer/widgets/it_bar.dart b/lib/pangea/choreographer/widgets/it_bar.dart index bfc4a174d..718e28beb 100644 --- a/lib/pangea/choreographer/widgets/it_bar.dart +++ b/lib/pangea/choreographer/widgets/it_bar.dart @@ -339,7 +339,8 @@ class ITChoices extends StatelessWidget { ), choiceFeedback: choiceFeedback, ), - cardSize: const Size(300, 300), + maxHeight: 300, + maxWidth: 300, borderColor: borderColor, transformTargetId: controller.choreographer.itBarTransformTargetKey, backDropToDismiss: false, diff --git a/lib/pangea/utils/instructions.dart b/lib/pangea/utils/instructions.dart index 9011f14ed..31b552384 100644 --- a/lib/pangea/utils/instructions.dart +++ b/lib/pangea/utils/instructions.dart @@ -106,21 +106,18 @@ class InstructionsController { onClose: () => {_instructionsClosed[key.toString()] = true}, ), const SizedBox(height: 10.0), - Expanded( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(6.0), - child: Text( - key.body(context), - style: botStyle, - ), - ), + Padding( + padding: const EdgeInsets.all(6.0), + child: Text( + key.body(context), + style: botStyle, ), ), if (showToggle) InstructionsToggle(instructionsKey: key), ], ), - cardSize: const Size(300.0, 300.0), + maxHeight: 300, + maxWidth: 300, transformTargetId: transformTargetKey, closePrevOverlay: false, ), diff --git a/lib/pangea/utils/overlay.dart b/lib/pangea/utils/overlay.dart index cb6ed626a..5bf8a5823 100644 --- a/lib/pangea/utils/overlay.dart +++ b/lib/pangea/utils/overlay.dart @@ -1,8 +1,6 @@ import 'dart:developer'; -import 'dart:math'; import 'dart:ui'; -import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/utils/any_state_holder.dart'; import 'package:fluffychat/pangea/widgets/common_widgets/overlay_container.dart'; import 'package:flutter/foundation.dart'; @@ -22,10 +20,8 @@ class OverlayUtil { required BuildContext context, required Widget child, required String transformTargetId, - // Size? size, double? width, double? height, - Offset? offset, backDropToDismiss = true, blurBackground = false, Color? borderColor, @@ -63,13 +59,13 @@ class OverlayUtil { child: (position != OverlayPositionEnum.transform) ? child : CompositedTransformFollower( - targetAnchor: targetAnchor ?? Alignment.topLeft, - followerAnchor: followerAnchor ?? Alignment.topLeft, + targetAnchor: targetAnchor ?? Alignment.topCenter, + followerAnchor: + followerAnchor ?? Alignment.bottomCenter, link: MatrixState.pAnyState .layerLinkAndKey(transformTargetId) .link, showWhenUnlinked: false, - offset: offset ?? Offset.zero, child: child, ), ), @@ -89,8 +85,9 @@ class OverlayUtil { static showPositionedCard({ required BuildContext context, required Widget cardToShow, - required Size cardSize, required String transformTargetId, + required double maxHeight, + required double maxWidth, backDropToDismiss = true, Color? borderColor, bool closePrevOverlay = true, @@ -103,11 +100,6 @@ class OverlayUtil { return; } - final Offset cardOffset = _calculateCardOffset( - cardSize: cardSize, - transformTargetContext: layerLinkAndKey.key.currentContext!, - ); - final Widget child = Material( borderOnForeground: false, color: Colors.transparent, @@ -115,16 +107,15 @@ class OverlayUtil { child: OverlayContainer( cardToShow: cardToShow, borderColor: borderColor, + maxHeight: maxHeight, + maxWidth: maxWidth, ), ); showOverlay( context: context, child: child, - width: cardSize.width, - height: cardSize.height, transformTargetId: transformTargetId, - offset: cardOffset, backDropToDismiss: backDropToDismiss, borderColor: borderColor, closePrevOverlay: closePrevOverlay, @@ -135,73 +126,73 @@ class OverlayUtil { } } - /// calculates the card offset relative to the target - /// identified by [transformTargetKey] - static Offset _calculateCardOffset({ - required Size cardSize, - required BuildContext transformTargetContext, - final double minPadding = 10.0, - }) { - // debugger(when: kDebugMode); - //Note: assumes overlay in chatview - final OverlayConstraints constraints = - ChatViewConstraints(transformTargetContext); + // /// calculates the card offset relative to the target + // /// identified by [transformTargetKey] + // static Offset _calculateCardOffset({ + // required Size cardSize, + // required BuildContext transformTargetContext, + // final double minPadding = 10.0, + // }) { + // // debugger(when: kDebugMode); + // //Note: assumes overlay in chatview + // final OverlayConstraints constraints = + // ChatViewConstraints(transformTargetContext); - final RenderObject? targetRenderBox = - transformTargetContext.findRenderObject(); - if (targetRenderBox == null) return Offset.zero; - final Offset transformTargetOffset = - (targetRenderBox as RenderBox).localToGlobal(Offset.zero); - final Size transformTargetSize = targetRenderBox.size; + // final RenderObject? targetRenderBox = + // transformTargetContext.findRenderObject(); + // if (targetRenderBox == null) return Offset.zero; + // final Offset transformTargetOffset = + // (targetRenderBox as RenderBox).localToGlobal(Offset.zero); + // final Size transformTargetSize = targetRenderBox.size; - // ideally horizontally centered on target - double dx = transformTargetSize.width / 2 - cardSize.width / 2; - // make sure it's not off the left edge of the screen - // if transformTargetOffset.dx + dc < constraints.x0 + minPadding + // // ideally horizontally centered on target + // double dx = transformTargetSize.width / 2 - cardSize.width / 2; + // // make sure it's not off the left edge of the screen + // // if transformTargetOffset.dx + dc < constraints.x0 + minPadding - if (transformTargetOffset.dx + dx < minPadding + constraints.x0) { - debugPrint("setting dx"); - dx = minPadding + constraints.x0 - transformTargetOffset.dx; - } - // make sure it's not off the right edge of the screen - if (transformTargetOffset.dx + dx + cardSize.width + minPadding > - constraints.x1) { - dx = constraints.x1 - - transformTargetOffset.dx - - cardSize.width - - minPadding; - } + // if (transformTargetOffset.dx + dx < minPadding + constraints.x0) { + // debugPrint("setting dx"); + // dx = minPadding + constraints.x0 - transformTargetOffset.dx; + // } + // // make sure it's not off the right edge of the screen + // if (transformTargetOffset.dx + dx + cardSize.width + minPadding > + // constraints.x1) { + // dx = constraints.x1 - + // transformTargetOffset.dx - + // cardSize.width - + // minPadding; + // } - // if there's more room above target, - // put the card there - // else, - // put it below - // debugPrint( - // "transformTargetOffset.dx ${transformTargetOffset.dx} transformTargetOffset.dy ${transformTargetOffset.dy}"); - // debugPrint( - // "transformTargetSize.width ${transformTargetSize.width} transformTargetSize.height ${transformTargetSize.height}"); - double dy = transformTargetOffset.dy > - constraints.y1 - - transformTargetOffset.dy - - transformTargetSize.height - ? -cardSize.height - minPadding - : transformTargetSize.height + minPadding; - // make sure it's not off the top edge of the screen - if (dy < minPadding + constraints.y0 - transformTargetOffset.dy) { - dy = minPadding + constraints.y0 - transformTargetOffset.dy; - } - // make sure it's not off the bottom edge of the screen - if (transformTargetOffset.dy + dy + cardSize.height + minPadding > - constraints.y1) { - dy = constraints.y1 - - transformTargetOffset.dy - - cardSize.height - - minPadding; - } - // debugPrint("dx $dx dy $dy"); + // // if there's more room above target, + // // put the card there + // // else, + // // put it below + // // debugPrint( + // // "transformTargetOffset.dx ${transformTargetOffset.dx} transformTargetOffset.dy ${transformTargetOffset.dy}"); + // // debugPrint( + // // "transformTargetSize.width ${transformTargetSize.width} transformTargetSize.height ${transformTargetSize.height}"); + // double dy = transformTargetOffset.dy > + // constraints.y1 - + // transformTargetOffset.dy - + // transformTargetSize.height + // ? -cardSize.height - minPadding + // : transformTargetSize.height + minPadding; + // // make sure it's not off the top edge of the screen + // if (dy < minPadding + constraints.y0 - transformTargetOffset.dy) { + // dy = minPadding + constraints.y0 - transformTargetOffset.dy; + // } + // // make sure it's not off the bottom edge of the screen + // if (transformTargetOffset.dy + dy + cardSize.height + minPadding > + // constraints.y1) { + // dy = constraints.y1 - + // transformTargetOffset.dy - + // cardSize.height - + // minPadding; + // } + // // debugPrint("dx $dx dy $dy"); - return Offset(dx, dy); - } + // return Offset(dx, dy); + // } static bool get isOverlayOpen => MatrixState.pAnyState.entries.isNotEmpty; } @@ -250,48 +241,48 @@ class TransparentBackdrop extends StatelessWidget { } } -/// global coordinates that the overlay should stay inside -abstract class OverlayConstraints { - late double x0; - late double y0; - late double x1; - late double y1; -} +// /// global coordinates that the overlay should stay inside +// abstract class OverlayConstraints { +// late double x0; +// late double y0; +// late double x1; +// late double y1; +// } -class ChatViewConstraints implements OverlayConstraints { - @override - late double x0; - @override - late double y0; - @override - late double x1; - @override - late double y1; +// class ChatViewConstraints implements OverlayConstraints { +// @override +// late double x0; +// @override +// late double y0; +// @override +// late double x1; +// @override +// late double y1; - ChatViewConstraints(BuildContext context) { - final MediaQueryData mediaQueryData = - MediaQuery.of(Scaffold.of(context).context); - final bool isColumnMode = FluffyThemes.isColumnMode(context); +// ChatViewConstraints(BuildContext context) { +// final MediaQueryData mediaQueryData = +// MediaQuery.of(Scaffold.of(context).context); +// final bool isColumnMode = FluffyThemes.isColumnMode(context); - x0 = isColumnMode - ? AppConfig.columnWidth + 70.0 - : max(mediaQueryData.viewPadding.left, mediaQueryData.viewInsets.left); - y0 = max(mediaQueryData.viewPadding.top, mediaQueryData.viewInsets.top); - x1 = mediaQueryData.size.width - - max(mediaQueryData.viewPadding.right, mediaQueryData.viewInsets.right); - y1 = mediaQueryData.size.height - - max( - mediaQueryData.viewPadding.bottom, - mediaQueryData.viewInsets.bottom, - ); +// x0 = isColumnMode +// ? AppConfig.columnWidth + 70.0 +// : max(mediaQueryData.viewPadding.left, mediaQueryData.viewInsets.left); +// y0 = max(mediaQueryData.viewPadding.top, mediaQueryData.viewInsets.top); +// x1 = mediaQueryData.size.width - +// max(mediaQueryData.viewPadding.right, mediaQueryData.viewInsets.right); +// y1 = mediaQueryData.size.height - +// max( +// mediaQueryData.viewPadding.bottom, +// mediaQueryData.viewInsets.bottom, +// ); - // https://medium.com/flutter-community/a-flutter-guide-to-visual-overlap-padding-viewpadding-and-viewinsets-a63e214be6e8 - // debugPrint( - // "viewInsets ${mediaQueryData.viewInsets.left} ${mediaQueryData.viewInsets.top} ${mediaQueryData.viewInsets.right} ${mediaQueryData.viewInsets.bottom}"); - // debugPrint( - // "padding ${mediaQueryData.padding.left} ${mediaQueryData.padding.top} ${mediaQueryData.padding.right} ${mediaQueryData.padding.bottom}"); - // debugPrint( - // "viewPadding ${mediaQueryData.viewPadding.left} ${mediaQueryData.viewPadding.top} ${mediaQueryData.viewPadding.right} ${mediaQueryData.viewPadding.bottom}"); - // debugPrint("chatViewConstraints x0: $x0 y0: $y0 x1: $x1 y1: $y1"); - } -} +// // https://medium.com/flutter-community/a-flutter-guide-to-visual-overlap-padding-viewpadding-and-viewinsets-a63e214be6e8 +// // debugPrint( +// // "viewInsets ${mediaQueryData.viewInsets.left} ${mediaQueryData.viewInsets.top} ${mediaQueryData.viewInsets.right} ${mediaQueryData.viewInsets.bottom}"); +// // debugPrint( +// // "padding ${mediaQueryData.padding.left} ${mediaQueryData.padding.top} ${mediaQueryData.padding.right} ${mediaQueryData.padding.bottom}"); +// // debugPrint( +// // "viewPadding ${mediaQueryData.viewPadding.left} ${mediaQueryData.viewPadding.top} ${mediaQueryData.viewPadding.right} ${mediaQueryData.viewPadding.bottom}"); +// // debugPrint("chatViewConstraints x0: $x0 y0: $y0 x1: $x1 y1: $y1"); +// } +// } diff --git a/lib/pangea/widgets/common_widgets/overlay_container.dart b/lib/pangea/widgets/common_widgets/overlay_container.dart index 4fc64fb3d..5e2991be7 100644 --- a/lib/pangea/widgets/common_widgets/overlay_container.dart +++ b/lib/pangea/widgets/common_widgets/overlay_container.dart @@ -2,14 +2,16 @@ import 'package:flutter/material.dart'; class OverlayContainer extends StatelessWidget { final Widget cardToShow; - final Size cardSize; final Color? borderColor; + final double maxHeight; + final double maxWidth; const OverlayContainer({ super.key, required this.cardToShow, - this.cardSize = const Size(300.0, 300.0), this.borderColor, + required this.maxHeight, + required this.maxWidth, }); @override @@ -28,14 +30,17 @@ class OverlayContainer extends StatelessWidget { ), ), constraints: BoxConstraints( - maxWidth: cardSize.width, - maxHeight: cardSize.height, - minWidth: cardSize.width, - minHeight: cardSize.height, + maxWidth: maxWidth, + maxHeight: maxHeight, ), //PTODO - position card above input/message // margin: const EdgeInsets.all(10), - child: cardToShow, + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [cardToShow], + ), + ), ); } } diff --git a/lib/pangea/widgets/igc/pangea_text_controller.dart b/lib/pangea/widgets/igc/pangea_text_controller.dart index 63c5b3f94..378c33ad7 100644 --- a/lib/pangea/widgets/igc/pangea_text_controller.dart +++ b/lib/pangea/widgets/igc/pangea_text_controller.dart @@ -54,8 +54,11 @@ class PangeaTextController extends TextEditingController { text.isNotEmpty) { OverlayUtil.showPositionedCard( context: context, - cardToShow: const PaywallCard(), - cardSize: const Size(325, 325), + cardToShow: PaywallCard( + chatController: choreographer.chatController, + ), + maxHeight: 325, + maxWidth: 325, transformTargetId: choreographer.inputTransformTargetKey, ); } @@ -112,10 +115,11 @@ class PangeaTextController extends TextEditingController { if (cardToShow != null) { OverlayUtil.showPositionedCard( context: context, - cardSize: matchIndex != -1 && + maxHeight: matchIndex != -1 && choreographer.igc.igcTextData!.matches[matchIndex].isITStart - ? const Size(350, 260) - : const Size(350, 400), + ? 260 + : 400, + maxWidth: 350, cardToShow: cardToShow, transformTargetId: choreographer.inputTransformTargetKey, ); diff --git a/lib/pangea/widgets/igc/span_card.dart b/lib/pangea/widgets/igc/span_card.dart index 816e8ed15..57991a1a9 100644 --- a/lib/pangea/widgets/igc/span_card.dart +++ b/lib/pangea/widgets/igc/span_card.dart @@ -237,49 +237,47 @@ class WordMatchContent extends StatelessWidget { ? controller.currentExpression : BotExpression.addled, ), - Expanded( - child: Scrollbar( + Scrollbar( + controller: scrollController, + thumbVisibility: true, + child: SingleChildScrollView( controller: scrollController, - thumbVisibility: true, - child: SingleChildScrollView( - controller: scrollController, - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // const SizedBox(height: 10.0), - // if (matchCopy.description != null) - // Padding( - // padding: const EdgeInsets.only(), - // child: Text( - // matchCopy.description!, - // style: BotStyle.text(context), - // ), - // ), - const SizedBox(height: 8), - if (!controller.widget.scm.pangeaMatch!.isITStart) - ChoicesArray( - originalSpan: - controller.widget.scm.pangeaMatch!.matchContent, - isLoading: controller.fetchingData, - choices: - controller.widget.scm.pangeaMatch!.match.choices - ?.map( - (e) => Choice( - text: e.value, - color: e.selected ? e.type.color : null, - isGold: e.type.name == 'bestCorrection', - ), - ) - .toList(), - onPressed: controller.onChoiceSelect, - uniqueKeyForLayerLink: (int index) => - "wordMatch$index", - selectedChoiceIndex: controller.selectedChoiceIndex, - ), - const SizedBox(height: 12), - PromptAndFeedback(controller: controller), - ], - ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // const SizedBox(height: 10.0), + // if (matchCopy.description != null) + // Padding( + // padding: const EdgeInsets.only(), + // child: Text( + // matchCopy.description!, + // style: BotStyle.text(context), + // ), + // ), + const SizedBox(height: 8), + if (!controller.widget.scm.pangeaMatch!.isITStart) + ChoicesArray( + originalSpan: + controller.widget.scm.pangeaMatch!.matchContent, + isLoading: controller.fetchingData, + choices: + controller.widget.scm.pangeaMatch!.match.choices + ?.map( + (e) => Choice( + text: e.value, + color: e.selected ? e.type.color : null, + isGold: e.type.name == 'bestCorrection', + ), + ) + .toList(), + onPressed: controller.onChoiceSelect, + uniqueKeyForLayerLink: (int index) => + "wordMatch$index", + selectedChoiceIndex: controller.selectedChoiceIndex, + ), + const SizedBox(height: 12), + PromptAndFeedback(controller: controller), + ], ), ), ), From 4ddd28b7fe6336c7bd0b610fff9954039c14ee1c Mon Sep 17 00:00:00 2001 From: ggurdin Date: Thu, 10 Oct 2024 15:59:28 -0400 Subject: [PATCH 2/3] makes toolbar have dynamic width to fit around content --- .../chat/message_selection_overlay.dart | 33 ++++------- lib/pangea/widgets/chat/message_toolbar.dart | 56 ++++++++++--------- lib/pangea/widgets/igc/paywall_card.dart | 4 ++ 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/lib/pangea/widgets/chat/message_selection_overlay.dart b/lib/pangea/widgets/chat/message_selection_overlay.dart index 428d36e79..1d6e5c2a1 100644 --- a/lib/pangea/widgets/chat/message_selection_overlay.dart +++ b/lib/pangea/widgets/chat/message_selection_overlay.dart @@ -373,24 +373,16 @@ class MessageOverlayController extends State // the default spacing between the side of the screen and the message bubble final double messageMargin = pangeaMessageEvent.ownMessage ? Avatar.defaultSize + 16 : 8; - - // the actual spacing between the side of the screen and - // the message bubble, accounts for wide screen - double extraChatSpace = FluffyThemes.isColumnMode(context) - ? ((screenWidth - - (FluffyThemes.columnWidth * 3.5) - - FluffyThemes.navRailWidth) / - 2) + - messageMargin - : messageMargin; - - if (extraChatSpace < messageMargin) { - extraChatSpace = messageMargin; - } + final horizontalPadding = FluffyThemes.isColumnMode(context) ? 8.0 : 0.0; + final chatViewWidth = screenWidth - + (FluffyThemes.isColumnMode(context) + ? (FluffyThemes.columnWidth + FluffyThemes.navRailWidth) + : 0); + final maxWidth = chatViewWidth - (2 * horizontalPadding) - messageMargin; final overlayMessage = Container( - constraints: const BoxConstraints( - maxWidth: FluffyThemes.columnWidth * 2.5, + constraints: BoxConstraints( + maxWidth: maxWidth, ), child: Material( type: MaterialType.transparency, @@ -439,21 +431,20 @@ class MessageOverlayController extends State ), ); - final horizontalPadding = FluffyThemes.isColumnMode(context) ? 8.0 : 0.0; final columnOffset = FluffyThemes.isColumnMode(context) ? FluffyThemes.columnWidth + FluffyThemes.navRailWidth : 0; - final double leftPadding = widget._pangeaMessageEvent.ownMessage - ? extraChatSpace + final double? leftPadding = widget._pangeaMessageEvent.ownMessage + ? null : messageOffset!.dx - horizontalPadding - columnOffset; - final double rightPadding = widget._pangeaMessageEvent.ownMessage + final double? rightPadding = widget._pangeaMessageEvent.ownMessage ? screenWidth - messageOffset!.dx - messageSize!.width - horizontalPadding - : extraChatSpace; + : null; final positionedOverlayMessage = _overlayPositionAnimation == null ? Positioned( diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index 704338764..b420ddcaa 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -120,34 +120,40 @@ class MessageToolbarState extends State { .layerLinkAndKey('${widget.pangeaMessageEvent.eventId}-toolbar') .key, type: MaterialType.transparency, - child: Column( + child: Row( + mainAxisSize: MainAxisSize.min, children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - border: Border.all( - width: 2, - color: Theme.of(context).colorScheme.primary.withOpacity(0.5), - ), - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - ), - constraints: const BoxConstraints( - maxHeight: AppConfig.toolbarMaxHeight, - ), - child: Row( - children: [ - Expanded( - child: SingleChildScrollView( - child: AnimatedSize( - duration: FluffyThemes.animationDuration, - child: toolbarContent, - ), + Column( + children: [ + Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + border: Border.all( + width: 2, + color: + Theme.of(context).colorScheme.primary.withOpacity(0.5), + ), + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), ), ), - ], - ), + constraints: const BoxConstraints( + maxHeight: AppConfig.toolbarMaxHeight, + ), + // child: Row( + // children: [ + // Expanded( + child: SingleChildScrollView( + child: AnimatedSize( + duration: FluffyThemes.animationDuration, + child: toolbarContent, + ), + ), + // ), + // ], + // ), + ), + ], ), ], ), diff --git a/lib/pangea/widgets/igc/paywall_card.dart b/lib/pangea/widgets/igc/paywall_card.dart index a2c35ff86..20b5fcefe 100644 --- a/lib/pangea/widgets/igc/paywall_card.dart +++ b/lib/pangea/widgets/igc/paywall_card.dart @@ -1,4 +1,5 @@ import 'package:fluffychat/config/app_config.dart'; +import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; import 'package:fluffychat/pangea/widgets/common/bot_face_svg.dart'; import 'package:fluffychat/pangea/widgets/igc/card_header.dart'; @@ -7,8 +8,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; class PaywallCard extends StatelessWidget { + final ChatController chatController; const PaywallCard({ super.key, + required this.chatController, }); @override @@ -69,6 +72,7 @@ class PaywallCard extends StatelessWidget { width: double.infinity, child: TextButton( onPressed: () { + chatController.clearSelectedEvents(); MatrixState.pangeaController.subscriptionController .showPaywall(context); }, From f1ac5709f7c56c2b79fdf328920e2725a19bb2be Mon Sep 17 00:00:00 2001 From: ggurdin Date: Tue, 22 Oct 2024 14:44:26 -0400 Subject: [PATCH 3/3] adjustment to layouts of toolbar content to make dynamic sizing work --- assets/l10n/intl_en.arb | 12 ++-- .../widgets/chat/message_audio_card.dart | 46 ++++++------ .../chat/message_speech_to_text_card.dart | 18 ++--- lib/pangea/widgets/chat/message_toolbar.dart | 60 +++++----------- .../chat/message_translation_card.dart | 62 ++++++++-------- .../widgets/common/icon_number_widget.dart | 2 +- .../practice_activity_card.dart | 71 +++++++++---------- lib/pangea/widgets/select_to_define.dart | 22 +++--- 8 files changed, 135 insertions(+), 158 deletions(-) diff --git a/assets/l10n/intl_en.arb b/assets/l10n/intl_en.arb index ffdcadc2d..51ab9d1d7 100644 --- a/assets/l10n/intl_en.arb +++ b/assets/l10n/intl_en.arb @@ -4114,14 +4114,14 @@ "placeholders": {} }, "addChatToSpaceDesc": "Adding a chat to a space will make the chat appear within the space for students and give them access.", - "addSpaceToSpaceDesc": "Adding a sub space to space will make the sub space appear in the main space''s chat list.", + "addSpaceToSpaceDesc": "Adding a sub space to space will make the sub space appear in the main space's chat list.", "spaceAnalytics": "Space Analytics", "changeAnalyticsLanguage": "Change Analytics Language", "suggestToSpace": "Suggest this space", - "suggestToSpaceDesc": "Suggested sub spaces will appear in their main space''s chat list", + "suggestToSpaceDesc": "Suggested sub spaces will appear in their main space's chat list", "practice": "Practice", "noLanguagesSet": "No languages set", - "noActivitiesFound": "That''s enough on this for now! Come back later for more.", + "noActivitiesFound": "That's enough on this for now! Come back later for more.", "hintTitle": "Hint:", "speechToTextBody": "See how well you did by looking at your Accuracy and Words Per Minute scores", "previous": "Previous", @@ -4225,14 +4225,14 @@ "discoverHomeservers": "Discover homeservers", "whatIsAHomeserver": "What is a homeserver?", "homeserverDescription": "All your data is stored on the homeserver, just like an email provider. You can choose which homeserver you want to use, while you can still communicate with everyone. Learn more at at https://matrix.org.", - "doesNotSeemToBeAValidHomeserver": "Doesn''t seem to be a compatible homeserver. Wrong URL?", + "doesNotSeemToBeAValidHomeserver": "Doesn't seem to be a compatible homeserver. Wrong URL?", "grammar": "Grammar", "contactHasBeenInvitedToTheChat": "Contact has been invited to the chat", "inviteChat": "📨 Invite chat", "chatName": "Chat name", "reportContentIssueTitle": "Report content issue", "feedback": "Optional feedback", - "reportContentIssueDescription": "Uh oh! AI can faciliate personalized learning experiences but... also hallucinates. Please provide any feedback you have and we''ll try again.", + "reportContentIssueDescription": "Uh oh! AI can faciliate personalized learning experiences but... also hallucinates. Please provide any feedback you have and we'll try again.", "clickTheWordAgainToDeselect": "Click the selected word to deselect it.", "l2SupportNa": "Not Available", "l2SupportAlpha": "Alpha", @@ -4355,7 +4355,7 @@ "grammarCopyNumber": "Number", "grammarCopyConjType": "Conjunction Type", "grammarCopyPolarity": "Polarity", - "grammarCopyNumberPsor": "Possessor''s Number", + "grammarCopyNumberPsor": "Possessor's Number", "grammarCopyCase": "Case", "grammarCopyDefinite": "Definiteness", "grammarCopyNumForm": "Numeral Form", diff --git a/lib/pangea/widgets/chat/message_audio_card.dart b/lib/pangea/widgets/chat/message_audio_card.dart index 9250aa2c4..64bb449aa 100644 --- a/lib/pangea/widgets/chat/message_audio_card.dart +++ b/lib/pangea/widgets/chat/message_audio_card.dart @@ -187,26 +187,32 @@ class MessageAudioCardState extends State { @override Widget build(BuildContext context) { - return Container( - padding: const EdgeInsets.all(8), - constraints: const BoxConstraints(minHeight: minCardHeight), - alignment: Alignment.center, - child: _isLoading - ? const ToolbarContentLoadingIndicator() - : audioFile != null - ? Column( - children: [ - AudioPlayerWidget( - null, - matrixFile: audioFile, - sectionStartMS: sectionStartMS, - sectionEndMS: sectionEndMS, - color: Theme.of(context).colorScheme.onPrimaryContainer, - ), - tts.missingVoiceButton, - ], - ) - : const CardErrorWidget(), + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: const EdgeInsets.all(8), + constraints: const BoxConstraints(minHeight: minCardHeight), + alignment: Alignment.center, + child: _isLoading + ? const ToolbarContentLoadingIndicator() + : audioFile != null + ? Column( + children: [ + AudioPlayerWidget( + null, + matrixFile: audioFile, + sectionStartMS: sectionStartMS, + sectionEndMS: sectionEndMS, + color: + Theme.of(context).colorScheme.onPrimaryContainer, + ), + tts.missingVoiceButton, + ], + ) + : const CardErrorWidget(), + ), + ], ); } } diff --git a/lib/pangea/widgets/chat/message_speech_to_text_card.dart b/lib/pangea/widgets/chat/message_speech_to_text_card.dart index 012647b5a..92489ce29 100644 --- a/lib/pangea/widgets/chat/message_speech_to_text_card.dart +++ b/lib/pangea/widgets/chat/message_speech_to_text_card.dart @@ -5,7 +5,6 @@ import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dar import 'package:fluffychat/pangea/models/speech_to_text_models.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/inline_tooltip.dart'; -import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart'; import 'package:fluffychat/pangea/widgets/common/icon_number_widget.dart'; import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart'; @@ -154,16 +153,11 @@ class MessageSpeechToTextCardState extends State { return CardErrorWidget(error: error); } - final int words = speechToTextResponse!.transcript.sttTokens.length; - final int accuracy = speechToTextResponse!.transcript.confidence; - final int total = words * accuracy; - //TODO: find better icons - return Container( + return Padding( padding: const EdgeInsets.all(8), - constraints: const BoxConstraints(minHeight: minCardHeight), - alignment: Alignment.center, child: Column( + mainAxisSize: MainAxisSize.min, children: [ const SizedBox(height: 8), RichText( @@ -171,19 +165,15 @@ class MessageSpeechToTextCardState extends State { ), const SizedBox(height: 16), Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, children: [ - // IconNumberWidget( - // icon: Icons.abc, - // number: (selectedToken == null ? words : 1).toString(), - // toolTip: L10n.of(context)!.words, - // ), IconNumberWidget( icon: Symbols.target, number: "${selectedToken?.confidence ?? speechToTextResponse!.transcript.confidence}%", toolTip: L10n.of(context)!.accuracy, ), + const SizedBox(width: 16), IconNumberWidget( icon: Icons.speed, number: wordsPerMinuteString != null diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index b204ebe54..bcffbdf2a 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -101,47 +101,25 @@ class MessageToolbar extends StatelessWidget { @override Widget build(BuildContext context) { - return Material( - key: MatrixState.pAnyState - .layerLinkAndKey('${pangeaMessageEvent.eventId}-toolbar') - .key, - type: MaterialType.transparency, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Column( - children: [ - Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, - border: Border.all( - width: 2, - color: - Theme.of(context).colorScheme.primary.withOpacity(0.5), - ), - borderRadius: const BorderRadius.all( - Radius.circular(AppConfig.borderRadius), - ), - ), - constraints: const BoxConstraints( - maxHeight: AppConfig.toolbarMaxHeight, - ), - // child: Row( - // children: [ - // Expanded( - child: SingleChildScrollView( - child: AnimatedSize( - duration: FluffyThemes.animationDuration, - child: toolbarContent, - ), - ), - // ), - // ], - // ), - ), - ], - ), - ], + return Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + border: Border.all( + width: 2, + color: Theme.of(context).colorScheme.primary.withOpacity(0.5), + ), + borderRadius: const BorderRadius.all( + Radius.circular(AppConfig.borderRadius), + ), + ), + constraints: const BoxConstraints( + maxHeight: AppConfig.toolbarMaxHeight, + ), + child: SingleChildScrollView( + child: AnimatedSize( + duration: FluffyThemes.animationDuration, + child: toolbarContent, + ), ), ); } diff --git a/lib/pangea/widgets/chat/message_translation_card.dart b/lib/pangea/widgets/chat/message_translation_card.dart index 5e66d9966..c209e7b8f 100644 --- a/lib/pangea/widgets/chat/message_translation_card.dart +++ b/lib/pangea/widgets/chat/message_translation_card.dart @@ -6,7 +6,6 @@ import 'package:fluffychat/pangea/repo/full_text_translation_repo.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/inline_tooltip.dart'; -import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/pangea/widgets/chat/toolbar_content_loading_indicator.dart'; import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart'; import 'package:fluffychat/widgets/matrix.dart'; @@ -134,36 +133,41 @@ class MessageTranslationCardState extends State { return const CardErrorWidget(); } - return Container( + return Padding( padding: const EdgeInsets.all(8), - constraints: const BoxConstraints(minHeight: minCardHeight), - alignment: Alignment.center, - child: _fetchingTranslation - ? const ToolbarContentLoadingIndicator() - : Column( - children: [ - widget.selection != null - ? Text( - selectionTranslation!, - style: BotStyle.text(context), - ) - : Text( - repEvent!.text, - style: BotStyle.text(context), - ), - if (notGoingToTranslate && widget.selection == null) - InlineTooltip( - instructionsEnum: InstructionsEnum.l1Translation, - onClose: () => setState(() {}), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _fetchingTranslation + ? const ToolbarContentLoadingIndicator() + : Flexible( + child: Column( + children: [ + widget.selection != null + ? Text( + selectionTranslation!, + style: BotStyle.text(context), + ) + : Text( + repEvent!.text, + style: BotStyle.text(context), + ), + if (notGoingToTranslate && widget.selection == null) + InlineTooltip( + instructionsEnum: InstructionsEnum.l1Translation, + onClose: () => setState(() {}), + ), + if (widget.selection != null) + InlineTooltip( + instructionsEnum: + InstructionsEnum.clickAgainToDeselect, + onClose: () => setState(() {}), + ), + ], ), - if (widget.selection != null) - InlineTooltip( - instructionsEnum: InstructionsEnum.clickAgainToDeselect, - onClose: () => setState(() {}), - ), - // if (widget.selection != null) - ], - ), + ), + ], + ), ); } } diff --git a/lib/pangea/widgets/common/icon_number_widget.dart b/lib/pangea/widgets/common/icon_number_widget.dart index 24307112c..099baf3df 100644 --- a/lib/pangea/widgets/common/icon_number_widget.dart +++ b/lib/pangea/widgets/common/icon_number_widget.dart @@ -30,7 +30,7 @@ class IconNumberWidget extends StatelessWidget { ), onPressed: onPressed, ), - const SizedBox(width: 8), + const SizedBox(width: 5), Text( number.toString(), style: TextStyle( diff --git a/lib/pangea/widgets/practice_activity/practice_activity_card.dart b/lib/pangea/widgets/practice_activity/practice_activity_card.dart index 8ac0664b3..277a8bed9 100644 --- a/lib/pangea/widgets/practice_activity/practice_activity_card.dart +++ b/lib/pangea/widgets/practice_activity/practice_activity_card.dart @@ -14,7 +14,6 @@ import 'package:fluffychat/pangea/utils/bot_style.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/widgets/animations/gain_points.dart'; import 'package:fluffychat/pangea/widgets/chat/message_selection_overlay.dart'; -import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:fluffychat/pangea/widgets/content_issue_button.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart'; import 'package:fluffychat/pangea/widgets/practice_activity/no_more_practice_card.dart'; @@ -314,45 +313,43 @@ class MessagePracticeActivityCardState extends State { return GamifiedTextWidget(userMessage: userMessage!); } - return Container( - constraints: const BoxConstraints( - maxWidth: 350, - minWidth: 350, - minHeight: minCardHeight, - ), - child: Stack( - alignment: Alignment.center, - children: [ - // Main content - const Positioned( - child: PointsGainedAnimation(), - ), - Container( - padding: const EdgeInsets.all(8), - child: activityWidget, - ), - // Conditionally show the darkening and progress indicator based on the loading state - if (!savoringTheJoy && fetchingActivity) ...[ - // Semi-transparent overlay - Container( - color: Colors.black.withOpacity(0.5), // Darkening effect + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Stack( + alignment: Alignment.center, + children: [ + // Main content + const Positioned( + child: PointsGainedAnimation(), ), - // Circular progress indicator in the center - const Center( - child: CircularProgressIndicator(), + Container( + padding: const EdgeInsets.all(8), + child: activityWidget, + ), + // Conditionally show the darkening and progress indicator based on the loading state + if (!savoringTheJoy && fetchingActivity) ...[ + // Semi-transparent overlay + Container( + color: Colors.black.withOpacity(0.5), // Darkening effect + ), + // Circular progress indicator in the center + const Center( + child: CircularProgressIndicator(), + ), + ], + // Flag button in the top right corner + Positioned( + top: 0, + right: 0, + child: ContentIssueButton( + isActive: currentActivity != null, + submitFeedback: submitFeedback, + ), ), ], - // Flag button in the top right corner - Positioned( - top: 0, - right: 0, - child: ContentIssueButton( - isActive: currentActivity != null, - submitFeedback: submitFeedback, - ), - ), - ], - ), + ), + ], ); } } diff --git a/lib/pangea/widgets/select_to_define.dart b/lib/pangea/widgets/select_to_define.dart index 7020e5e77..556cc7f94 100644 --- a/lib/pangea/widgets/select_to_define.dart +++ b/lib/pangea/widgets/select_to_define.dart @@ -1,5 +1,4 @@ import 'package:fluffychat/pangea/utils/bot_style.dart'; -import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -10,16 +9,19 @@ class SelectToDefine extends StatelessWidget { @override Widget build(BuildContext context) { - return Center( - child: Container( - constraints: const BoxConstraints(minHeight: minCardHeight), - padding: const EdgeInsets.all(8), - child: Center( - child: Text( - L10n.of(context)!.selectToDefine, - style: BotStyle.text(context), + return Padding( + padding: const EdgeInsets.all(8), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + child: Text( + L10n.of(context)!.selectToDefine, + style: BotStyle.text(context), + textAlign: TextAlign.center, + ), ), - ), + ], ), ); }