diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 96240c3f4..a5ab0d16e 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -837,35 +837,35 @@ class ChatController extends State PangeaTextController get sendController => choreographer.textController; // Pangea# - // #Pangea - // void setSendingClient(Client c) { - // // first cancel typing with the old sending client - // if (currentlyTyping) { - // // no need to have the setting typing to false be blocking - // typingCoolDown?.cancel(); - // typingCoolDown = null; - // room.setTyping(false); - // currentlyTyping = false; - // } - // // then cancel the old timeline - // // fixes bug with read reciepts and quick switching - // loadTimelineFuture = _getTimeline(eventContextId: room.fullyRead).onError( - // ErrorReporter( - // context, - // 'Unable to load timeline after changing sending Client', - // ).onErrorCallback, - // ); + void setSendingClient(Client c) { + // #Pangea + // // first cancel typing with the old sending client + // if (currentlyTyping) { + // // no need to have the setting typing to false be blocking + // typingCoolDown?.cancel(); + // typingCoolDown = null; + // room.setTyping(false); + // currentlyTyping = false; + // } + // // then cancel the old timeline + // // fixes bug with read reciepts and quick switching + // loadTimelineFuture = _getTimeline(eventContextId: room.fullyRead).onError( + // ErrorReporter( + // context, + // 'Unable to load timeline after changing sending Client', + // ).onErrorCallback, + // ); - // // then set the new sending client - // setState(() => sendingClient = c); - // } + // // then set the new sending client + // setState(() => sendingClient = c); + // } - // void setActiveClient(Client c) { - // setState(() { - // Matrix.of(context).setActiveClient(c); - // }); - // } - // Pangea# + // void setActiveClient(Client c) { + // setState(() { + // Matrix.of(context).setActiveClient(c); + // }); + // Pangea# + } // #Pangea Event? pangeaEditingEvent; @@ -2188,6 +2188,23 @@ class ChatController extends State l1 != activityLang; } + void showNextMatch() { + final match = choreographer.igcController.firstOpenMatch; + if (match == null) { + inputFocus.requestFocus(); + return; + } + + match.updatedMatch.isITStart + ? choreographer.openIT(match) + : OverlayUtil.showIGCMatch( + match, + choreographer, + context, + showNextMatch, + ); + } + Future onRequestWritingAssistance({ bool manual = false, bool autosend = false, @@ -2198,14 +2215,7 @@ class ChatController extends State await choreographer.requestWritingAssistance(manual: manual); if (choreographer.assistanceState == AssistanceStateEnum.fetched) { - final match = choreographer.igcController.firstOpenMatch!; - match.updatedMatch.isITStart - ? choreographer.openIT(match) - : OverlayUtil.showIGCMatch( - match, - choreographer, - context, - ); + showNextMatch(); } else if (autosend) { await send(); } else { diff --git a/lib/pages/chat/chat_input_row.dart b/lib/pages/chat/chat_input_row.dart index 1bf8f4d98..3874ee4d8 100644 --- a/lib/pages/chat/chat_input_row.dart +++ b/lib/pages/chat/chat_input_row.dart @@ -7,6 +7,8 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/l10n/l10n.dart'; import 'package:fluffychat/utils/other_party_can_receive.dart'; import 'package:fluffychat/utils/platform_infos.dart'; +import 'package:fluffychat/widgets/avatar.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import '../../config/themes.dart'; import 'chat.dart'; import 'input_bar.dart'; @@ -254,17 +256,15 @@ class ChatInputRow extends StatelessWidget { onPressed: controller.emojiPickerAction, ), ), - // #Pangea - // if (Matrix.of(context).isMultiAccount && - // Matrix.of(context).hasComplexBundles && - // Matrix.of(context).currentBundle!.length > 1) - // Container( - // width: height, - // height: height, - // alignment: Alignment.center, - // child: _ChatAccountPicker(controller), - // ), - // Pangea# + if (Matrix.of(context).isMultiAccount && + Matrix.of(context).hasComplexBundles && + Matrix.of(context).currentBundle!.length > 1) + Container( + width: height, + height: height, + alignment: Alignment.center, + child: _ChatAccountPicker(controller), + ), Expanded( child: Padding( padding: const EdgeInsets.symmetric(vertical: 0.0), @@ -301,6 +301,7 @@ class ChatInputRow extends StatelessWidget { onChanged: controller.onInputBarChanged, // #Pangea choreographer: controller.choreographer, + showNextMatch: controller.showNextMatch, // Pangea# ), ), @@ -341,62 +342,60 @@ class ChatInputRow extends StatelessWidget { } } -// #Pangea -// class _ChatAccountPicker extends StatelessWidget { -// final ChatController controller; +class _ChatAccountPicker extends StatelessWidget { + final ChatController controller; -// const _ChatAccountPicker(this.controller); + const _ChatAccountPicker(this.controller); -// void _popupMenuButtonSelected(String mxid, BuildContext context) { -// final client = Matrix.of(context) -// .currentBundle! -// .firstWhere((cl) => cl!.userID == mxid, orElse: () => null); -// if (client == null) { -// Logs().w('Attempted to switch to a non-existing client $mxid'); -// return; -// } -// controller.setSendingClient(client); -// } + void _popupMenuButtonSelected(String mxid, BuildContext context) { + final client = Matrix.of(context) + .currentBundle! + .firstWhere((cl) => cl!.userID == mxid, orElse: () => null); + if (client == null) { + Logs().w('Attempted to switch to a non-existing client $mxid'); + return; + } + controller.setSendingClient(client); + } -// @override -// Widget build(BuildContext context) { -// final clients = controller.currentRoomBundle; -// return Padding( -// padding: const EdgeInsets.all(8.0), -// child: FutureBuilder( -// future: controller.sendingClient.fetchOwnProfile(), -// builder: (context, snapshot) => PopupMenuButton( -// useRootNavigator: true, -// onSelected: (mxid) => _popupMenuButtonSelected(mxid, context), -// itemBuilder: (BuildContext context) => clients -// .map( -// (client) => PopupMenuItem( -// value: client!.userID, -// child: FutureBuilder( -// future: client.fetchOwnProfile(), -// builder: (context, snapshot) => ListTile( -// leading: Avatar( -// mxContent: snapshot.data?.avatarUrl, -// name: snapshot.data?.displayName ?? -// client.userID!.localpart, -// size: 20, -// ), -// title: Text(snapshot.data?.displayName ?? client.userID!), -// contentPadding: const EdgeInsets.all(0), -// ), -// ), -// ), -// ) -// .toList(), -// child: Avatar( -// mxContent: snapshot.data?.avatarUrl, -// name: snapshot.data?.displayName ?? -// Matrix.of(context).client.userID!.localpart, -// size: 20, -// ), -// ), -// ), -// ); -// } -// } -// Pangea# + @override + Widget build(BuildContext context) { + final clients = controller.currentRoomBundle; + return Padding( + padding: const EdgeInsets.all(8.0), + child: FutureBuilder( + future: controller.sendingClient.fetchOwnProfile(), + builder: (context, snapshot) => PopupMenuButton( + useRootNavigator: true, + onSelected: (mxid) => _popupMenuButtonSelected(mxid, context), + itemBuilder: (BuildContext context) => clients + .map( + (client) => PopupMenuItem( + value: client!.userID, + child: FutureBuilder( + future: client.fetchOwnProfile(), + builder: (context, snapshot) => ListTile( + leading: Avatar( + mxContent: snapshot.data?.avatarUrl, + name: snapshot.data?.displayName ?? + client.userID!.localpart, + size: 20, + ), + title: Text(snapshot.data?.displayName ?? client.userID!), + contentPadding: const EdgeInsets.all(0), + ), + ), + ), + ) + .toList(), + child: Avatar( + mxContent: snapshot.data?.avatarUrl, + name: snapshot.data?.displayName ?? + Matrix.of(context).client.userID!.localpart, + size: 20, + ), + ), + ), + ); + } +} diff --git a/lib/pages/chat/input_bar.dart b/lib/pages/chat/input_bar.dart index 6e2f691ab..c4ab933d3 100644 --- a/lib/pages/chat/input_bar.dart +++ b/lib/pages/chat/input_bar.dart @@ -13,7 +13,6 @@ import 'package:fluffychat/pangea/choreographer/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/choreographer_state_extension.dart'; import 'package:fluffychat/pangea/choreographer/text_editing/pangea_text_controller.dart'; import 'package:fluffychat/pangea/common/utils/overlay.dart'; -import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart'; import 'package:fluffychat/pangea/subscription/controllers/subscription_controller.dart'; import 'package:fluffychat/pangea/subscription/widgets/paywall_card.dart'; import 'package:fluffychat/pangea/toolbar/utils/shrinkable_text.dart'; @@ -36,6 +35,7 @@ class InputBar extends StatelessWidget { // final TextEditingController? controller; final PangeaTextController? controller; final Choreographer choreographer; + final VoidCallback showNextMatch; // Pangea# final InputDecoration? decoration; final ValueChanged? onChanged; @@ -58,6 +58,7 @@ class InputBar extends StatelessWidget { this.readOnly = false, // #Pangea required this.choreographer, + required this.showNextMatch, // Pangea# super.key, }); @@ -429,58 +430,61 @@ class InputBar extends StatelessWidget { } // #Pangea - String hintText(BuildContext context) { - if (choreographer.itController.open.value) { - return L10n.of(context).buildTranslation; - } + SubscriptionStatus get _subscriptionStatus => + MatrixState.pangeaController.subscriptionController.subscriptionStatus; - return MatrixState.pangeaController.languageController.userL1 != null && - MatrixState.pangeaController.languageController.userL2 != null && - MatrixState.pangeaController.languageController.userL1!.langCode != - LanguageKeys.unknownLanguage && - MatrixState.pangeaController.languageController.userL2!.langCode != - LanguageKeys.unknownLanguage + String _defaultHintText(BuildContext context) { + final lang = MatrixState.pangeaController.languageController; + return lang.languagesSet ? L10n.of(context).writeAMessageLangCodes( - MatrixState.pangeaController.languageController.userL1!.displayName, - MatrixState.pangeaController.languageController.userL2!.displayName, + lang.userL1!.displayName, + lang.userL2!.displayName, ) : L10n.of(context).writeAMessage; } - void onInputTap(BuildContext context) { - if (controller == null || controller!.text.isEmpty) return; - final choreographer = controller!.choreographer; + void _onInputTap(BuildContext context) { + if (_shouldShowPaywall(context)) return; - final subscriptionStatus = - MatrixState.pangeaController.subscriptionController.subscriptionStatus; - if (subscriptionStatus == SubscriptionStatus.shouldShowPaywall) { - PaywallCard.show(context, ChoreoConstants.inputTransformTargetKey); - return; - } - - // Normalization matchs are widget spans that mess with offsets, - // so we need to adjust the offset accordingly - int adjustedOffset = controller!.selection.baseOffset; - final normalizationMatches = - choreographer.igcController.recentAutomaticCorrections; - if (normalizationMatches != null) { - for (final match in normalizationMatches) { - if (match.updatedMatch.match.offset < adjustedOffset && - match.updatedMatch.match.length > 0) { - adjustedOffset += (match.updatedMatch.match.length - 1); - } - } - } + final baseOffset = controller?.selection.baseOffset; + if (baseOffset == null) return; + final adjustedOffset = _adjustOffsetForNormalization(baseOffset); final match = choreographer.igcController.getMatchByOffset(adjustedOffset); if (match == null) return; - match.updatedMatch.isITStart - ? choreographer.openIT(match) - : OverlayUtil.showIGCMatch( - match, - choreographer, - context, - ); + + if (match.updatedMatch.isITStart) { + choreographer.openIT(match); + } else { + OverlayUtil.showIGCMatch( + match, + choreographer, + context, + showNextMatch, + ); + } + } + + bool _shouldShowPaywall(BuildContext context) { + if (_subscriptionStatus == SubscriptionStatus.shouldShowPaywall) { + PaywallCard.show(context, ChoreoConstants.inputTransformTargetKey); + return true; + } + return false; + } + + int _adjustOffsetForNormalization(int baseOffset) { + int adjustedOffset = baseOffset; + final corrections = choreographer.igcController.recentAutomaticCorrections; + if (corrections == null) return adjustedOffset; + + for (final correction in corrections) { + final match = correction.updatedMatch.match; + if (match.offset < adjustedOffset && match.length > 0) { + adjustedOffset += (match.length - 1); + } + } + return adjustedOffset; } // Pangea# @@ -492,7 +496,6 @@ class InputBar extends StatelessWidget { builder: (context, _, __) { final enableAutocorrect = MatrixState.pangeaController.userController .profile.toolSettings.enableAutocorrect; - // Pangea# return TypeAheadField>( direction: VerticalDirection.up, hideOnEmpty: true, @@ -501,8 +504,6 @@ class InputBar extends StatelessWidget { focusNode: focusNode, hideOnSelect: false, debounceDuration: const Duration(milliseconds: 50), - // show suggestions after 50ms idle time (default is 300) - // #Pangea builder: (context, _, focusNode) { final textField = TextField( enableSuggestions: enableAutocorrect, @@ -550,7 +551,7 @@ class InputBar extends StatelessWidget { style: controller?.exceededMaxLength ?? false ? const TextStyle(color: Colors.red) : null, - onTap: () => onInputTap(context), + onTap: () => _onInputTap(context), decoration: decoration!, onChanged: (text) { // fix for the library for now @@ -567,7 +568,9 @@ class InputBar extends StatelessWidget { Padding( padding: const EdgeInsets.only(left: 8.0), child: ShrinkableText( - text: hintText(context), + text: controller!.choreographer.itController.open.value + ? L10n.of(context).buildTranslation + : _defaultHintText(context), maxWidth: double.infinity, style: Theme.of(context).textTheme.bodyLarge?.copyWith( color: Theme.of(context).disabledColor, @@ -578,49 +581,6 @@ class InputBar extends StatelessWidget { ], ); }, - // builder: (context, controller, focusNode) => TextField( - // controller: controller, - // focusNode: focusNode, - // readOnly: readOnly, - // contextMenuBuilder: (c, e) => markdownContextBuilder(c, e, controller), - // contentInsertionConfiguration: ContentInsertionConfiguration( - // onContentInserted: (KeyboardInsertedContent content) { - // final data = content.data; - // if (data == null) return; - - // final file = MatrixFile( - // mimeType: content.mimeType, - // bytes: data, - // name: content.uri.split('/').last, - // ); - // room.sendFileEvent( - // file, - // shrinkImageMaxDimension: 1600, - // ); - // }, - // ), - // minLines: minLines, - // maxLines: maxLines, - // keyboardType: keyboardType!, - // textInputAction: textInputAction, - // autofocus: autofocus!, - // inputFormatters: [ - // LengthLimitingTextInputFormatter((maxPDUSize / 3).floor()), - // ], - // onSubmitted: (text) { - // // fix for library for now - // // it sets the types for the callback incorrectly - // onSubmitted!(text); - // }, - // decoration: decoration!, - // onChanged: (text) { - // // fix for the library for now - // // it sets the types for the callback incorrectly - // onChanged!(text); - // }, - // textCapitalization: TextCapitalization.sentences, - // ), - // Pangea# suggestionsCallback: getSuggestions, itemBuilder: (c, s) => buildSuggestion(c, s, Matrix.of(context).client), @@ -635,5 +595,71 @@ class InputBar extends StatelessWidget { ); }, ); + // return TypeAheadField>( + // direction: VerticalDirection.up, + // hideOnEmpty: true, + // hideOnLoading: true, + // controller: controller, + // focusNode: focusNode, + // hideOnSelect: false, + // debounceDuration: const Duration(milliseconds: 50), + // // show suggestions after 50ms idle time (default is 300) + // builder: (context, controller, focusNode) => TextField( + // controller: controller, + // focusNode: focusNode, + // readOnly: readOnly, + // contextMenuBuilder: (c, e) => markdownContextBuilder(c, e, controller), + // contentInsertionConfiguration: ContentInsertionConfiguration( + // onContentInserted: (KeyboardInsertedContent content) { + // final data = content.data; + // if (data == null) return; + + // final file = MatrixFile( + // mimeType: content.mimeType, + // bytes: data, + // name: content.uri.split('/').last, + // ); + // room.sendFileEvent( + // file, + // shrinkImageMaxDimension: 1600, + // ); + // }, + // ), + // minLines: minLines, + // maxLines: maxLines, + // keyboardType: keyboardType!, + // textInputAction: textInputAction, + // autofocus: autofocus!, + // inputFormatters: [ + // LengthLimitingTextInputFormatter((maxPDUSize / 3).floor()), + // ], + // onSubmitted: (text) { + // // fix for library for now + // // it sets the types for the callback incorrectly + // onSubmitted!(text); + // }, + // maxLength: + // AppSettings.textMessageMaxLength.getItem(Matrix.of(context).store), + // decoration: decoration, + // onChanged: (text) { + // // fix for the library for now + // // it sets the types for the callback incorrectly + // onChanged!(text); + // }, + // textCapitalization: TextCapitalization.sentences, + // ), + + // suggestionsCallback: getSuggestions, + // itemBuilder: (c, s) => buildSuggestion(c, s, Matrix.of(context).client), + // onSelected: (Map suggestion) => + // insertSuggestion(context, suggestion), + // errorBuilder: (BuildContext context, Object? error) => + // const SizedBox.shrink(), + // loadingBuilder: (BuildContext context) => const SizedBox.shrink(), + // // fix loading briefly flickering a dark box + // emptyBuilder: (BuildContext context) => + // const SizedBox.shrink(), // fix loading briefly showing no suggestions + // ); + // Pangea# } } diff --git a/lib/pangea/chat/widgets/pangea_chat_input_row.dart b/lib/pangea/chat/widgets/pangea_chat_input_row.dart index f0c211231..f0d466d01 100644 --- a/lib/pangea/chat/widgets/pangea_chat_input_row.dart +++ b/lib/pangea/chat/widgets/pangea_chat_input_row.dart @@ -205,6 +205,7 @@ class PangeaChatInputRow extends StatelessWidget { ), onChanged: controller.onInputBarChanged, choreographer: controller.choreographer, + showNextMatch: controller.showNextMatch, ), ), ), diff --git a/lib/pangea/choreographer/igc/span_card.dart b/lib/pangea/choreographer/igc/span_card.dart index 0259489ad..d4cb848d1 100644 --- a/lib/pangea/choreographer/igc/span_card.dart +++ b/lib/pangea/choreographer/igc/span_card.dart @@ -8,23 +8,22 @@ import 'package:fluffychat/pangea/choreographer/choreographer.dart'; import 'package:fluffychat/pangea/choreographer/igc/pangea_match_state_model.dart'; import 'package:fluffychat/pangea/choreographer/igc/span_choice_type_enum.dart'; import 'package:fluffychat/pangea/choreographer/igc/span_data_model.dart'; -import 'package:fluffychat/pangea/choreographer/igc/span_data_type_enum.dart'; import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/common/utils/feedback_model.dart'; -import 'package:fluffychat/pangea/common/utils/overlay.dart'; import 'package:fluffychat/pangea/common/widgets/error_indicator.dart'; import '../../../widgets/matrix.dart'; import '../../common/widgets/choice_array.dart'; -import 'why_button.dart'; class SpanCard extends StatefulWidget { final PangeaMatchState match; final Choreographer choreographer; + final VoidCallback showNextMatch; const SpanCard({ super.key, required this.match, required this.choreographer, + required this.showNextMatch, }); @override @@ -125,6 +124,7 @@ class SpanCardState extends State { void _onMatchUpdate(VoidCallback updateFunc) async { try { updateFunc(); + widget.showNextMatch(); } catch (e, s) { ErrorHandler.logError( e: e, @@ -137,7 +137,6 @@ class SpanCardState extends State { widget.choreographer.clearMatches(e); return; } - _showFirstMatch(); } void _onAcceptReplacement() => _onMatchUpdate(() { @@ -148,19 +147,6 @@ class SpanCardState extends State { widget.choreographer.onIgnoreReplacement(match: widget.match); }); - void _showFirstMatch() { - final match = widget.choreographer.igcController.firstOpenMatch; - if (match == null) { - MatrixState.pAnyState.closeAllOverlays(); - return; - } - OverlayUtil.showIGCMatch( - match, - widget.choreographer, - context, - ); - } - @override Widget build(BuildContext context) { return SizedBox( @@ -196,54 +182,10 @@ class SpanCardState extends State { .pangeaController.languageController .activeL2Code(), ), - ConstrainedBox( - constraints: const BoxConstraints( - minHeight: 100.0, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ListenableBuilder( - listenable: _feedbackModel, - builder: (context, _) { - if (_loadingChoices) { - return const SizedBox( - width: 24.0, - height: 24.0, - child: CircularProgressIndicator(), - ); - } - - final state = _feedbackModel.state; - return switch (state) { - FeedbackIdle() => - _selectedChoice == null - ? Text( - widget.match.updatedMatch.match.type - .typeName - .defaultPrompt(context), - style: - BotStyle.text(context).copyWith( - fontStyle: FontStyle.italic, - ), - ) - : WhyButton( - onPress: _fetchFeedback, - loading: false, - ), - FeedbackLoading() => WhyButton( - onPress: _fetchFeedback, - loading: true, - ), - FeedbackError(:final error) => - ErrorIndicator(message: error.toString()), - FeedbackLoaded(:final value) => - Text(value, style: BotStyle.text(context)), - }; - }, - ), - ], - ), + _SpanCardFeedback( + _selectedChoice != null, + _fetchFeedback, + _feedbackModel, ), ], ), @@ -251,52 +193,126 @@ class SpanCardState extends State { ), ), ), - Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor, + _SpanCardButtons( + onAccept: _onAcceptReplacement, + onIgnore: _onIgnoreMatch, + selectedChoice: _selectedChoice, + ), + ], + ), + ); + } +} + +class _SpanCardFeedback extends StatelessWidget { + final bool hasSelectedChoice; + final VoidCallback fetchFeedback; + final FeedbackModel feedbackModel; + + const _SpanCardFeedback( + this.hasSelectedChoice, + this.fetchFeedback, + this.feedbackModel, + ); + + @override + Widget build(BuildContext context) { + return ConstrainedBox( + constraints: const BoxConstraints( + minHeight: 100.0, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ListenableBuilder( + listenable: feedbackModel, + builder: (context, _) { + final state = feedbackModel.state; + return switch (state) { + FeedbackIdle() => hasSelectedChoice + ? IconButton( + onPressed: fetchFeedback, + icon: const Icon(Icons.lightbulb_outline, size: 24), + ) + : Text( + L10n.of(context).correctionDefaultPrompt, + style: BotStyle.text(context).copyWith( + fontStyle: FontStyle.italic, + ), + ), + FeedbackLoading() => const SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator(), + ), + FeedbackError(:final error) => + ErrorIndicator(message: error.toString()), + FeedbackLoaded(:final value) => + Text(value, style: BotStyle.text(context)), + }; + }, + ), + ], + ), + ); + } +} + +class _SpanCardButtons extends StatelessWidget { + final VoidCallback onAccept; + final VoidCallback onIgnore; + final SpanChoice? selectedChoice; + + const _SpanCardButtons({ + required this.onAccept, + required this.onIgnore, + required this.selectedChoice, + }); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + ), + padding: const EdgeInsets.only(top: 12.0), + child: Row( + spacing: 10.0, + children: [ + Expanded( + child: Opacity( + opacity: 0.8, + child: TextButton( + style: TextButton.styleFrom( + backgroundColor: + Theme.of(context).colorScheme.primary.withAlpha(25), + ), + onPressed: onIgnore, + child: Center( + child: Text(L10n.of(context).ignoreInThisText), + ), + ), ), - padding: const EdgeInsets.only(top: 12.0), - child: Row( - spacing: 10.0, - children: [ - Expanded( - child: Opacity( - opacity: 0.8, - child: TextButton( - style: TextButton.styleFrom( - backgroundColor: - Theme.of(context).colorScheme.primary.withAlpha(25), - ), - onPressed: _onIgnoreMatch, - child: Center( - child: Text(L10n.of(context).ignoreInThisText), - ), - ), - ), + ), + Expanded( + child: Opacity( + opacity: selectedChoice != null ? 1.0 : 0.5, + child: TextButton( + onPressed: selectedChoice != null ? onAccept : null, + style: TextButton.styleFrom( + backgroundColor: (selectedChoice?.color ?? + Theme.of(context).colorScheme.primary) + .withAlpha(50), + side: selectedChoice != null + ? BorderSide( + color: selectedChoice!.color, + style: BorderStyle.solid, + width: 2.0, + ) + : null, ), - Expanded( - child: Opacity( - opacity: _selectedChoice != null ? 1.0 : 0.5, - child: TextButton( - onPressed: - _selectedChoice != null ? _onAcceptReplacement : null, - style: TextButton.styleFrom( - backgroundColor: (_selectedChoice?.color ?? - Theme.of(context).colorScheme.primary) - .withAlpha(50), - side: _selectedChoice != null - ? BorderSide( - color: _selectedChoice!.color, - style: BorderStyle.solid, - width: 2.0, - ) - : null, - ), - child: Text(L10n.of(context).replace), - ), - ), - ), - ], + child: Text(L10n.of(context).replace), + ), ), ), ], diff --git a/lib/pangea/choreographer/igc/why_button.dart b/lib/pangea/choreographer/igc/why_button.dart deleted file mode 100644 index a45946ecf..000000000 --- a/lib/pangea/choreographer/igc/why_button.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; - -class WhyButton extends StatelessWidget { - const WhyButton({ - super.key, - required this.onPress, - required this.loading, - }); - - final VoidCallback onPress; - final bool loading; - - @override - Widget build(BuildContext context) { - return IconButton( - onPressed: loading ? null : onPress, - icon: loading - ? const SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator(), - ) - : const Icon(Icons.lightbulb_outline, size: 24), - ); - } -} diff --git a/lib/pangea/common/utils/overlay.dart b/lib/pangea/common/utils/overlay.dart index 9dd4e09bf..d3074dee0 100644 --- a/lib/pangea/common/utils/overlay.dart +++ b/lib/pangea/common/utils/overlay.dart @@ -220,6 +220,7 @@ class OverlayUtil { PangeaMatchState match, Choreographer choreographer, BuildContext context, + VoidCallback showNextMatch, ) { MatrixState.pAnyState.closeAllOverlays(); showPositionedCard( @@ -229,6 +230,7 @@ class OverlayUtil { cardToShow: SpanCard( match: match, choreographer: choreographer, + showNextMatch: showNextMatch, ), maxHeight: 325, maxWidth: 325,