diff --git a/lib/pages/chat/events/audio_player.dart b/lib/pages/chat/events/audio_player.dart index 4c2b167ab..0dd656461 100644 --- a/lib/pages/chat/events/audio_player.dart +++ b/lib/pages/chat/events/audio_player.dart @@ -19,6 +19,7 @@ class AudioPlayerWidget extends StatefulWidget { // final Event event; final Event? event; final PangeaAudioFile? matrixFile; + final bool autoplay; // Pangea# static String? currentId; @@ -30,8 +31,9 @@ class AudioPlayerWidget extends StatefulWidget { this.color = Colors.black, // #Pangea this.matrixFile, - // Pangea# super.key, + this.autoplay = false, + // Pangea# }); @override @@ -251,7 +253,13 @@ class AudioPlayerState extends State { status = AudioPlayerStatus.downloaded; setState(() {}); } - // Pangea# + + if (widget.autoplay) { + status == AudioPlayerStatus.downloaded + ? _playAction() + : _downloadAction(); + // Pangea# + } } @override diff --git a/lib/pages/chat_list/space_view.dart b/lib/pages/chat_list/space_view.dart index 3092840ff..8e499deb8 100644 --- a/lib/pages/chat_list/space_view.dart +++ b/lib/pages/chat_list/space_view.dart @@ -61,7 +61,9 @@ class _SpaceViewState extends State { // Pangea# void _refresh() { - _lastResponse.remove(widget.controller.activeSpaceId); + // #Pangea + // _lastResponse.remove(widget.controller.activseSpaceId); + // Pangea# loadHierarchy(); } diff --git a/lib/pangea/constants/model_keys.dart b/lib/pangea/constants/model_keys.dart index d027bce1d..6f0649dbb 100644 --- a/lib/pangea/constants/model_keys.dart +++ b/lib/pangea/constants/model_keys.dart @@ -51,6 +51,8 @@ class ModelKey { static const String word = "word"; static const String lang = "lang"; static const String deepL = "deepl"; + static const String offset = "offset"; + static const String length = "length"; static const String langCode = 'lang_code'; static const String wordLang = "word_lang"; static const String lemma = "lemma"; diff --git a/lib/pangea/repo/full_text_translation_repo.dart b/lib/pangea/repo/full_text_translation_repo.dart index a781b4b0d..704bb9d63 100644 --- a/lib/pangea/repo/full_text_translation_repo.dart +++ b/lib/pangea/repo/full_text_translation_repo.dart @@ -37,6 +37,8 @@ class FullTextTranslationRequestModel { String userL1; String userL2; bool? deepL; + int? offset; + int? length; FullTextTranslationRequestModel({ required this.text, @@ -45,6 +47,8 @@ class FullTextTranslationRequestModel { required this.userL2, required this.userL1, this.deepL = false, + this.offset, + this.length, }); //PTODO throw error for null @@ -56,6 +60,8 @@ class FullTextTranslationRequestModel { ModelKey.userL2: userL2, ModelKey.userL1: userL1, ModelKey.deepL: deepL, + ModelKey.offset: offset, + ModelKey.length: length, }; } diff --git a/lib/pangea/widgets/chat/message_audio_card.dart b/lib/pangea/widgets/chat/message_audio_card.dart index d86539cb7..6c0ed78dc 100644 --- a/lib/pangea/widgets/chat/message_audio_card.dart +++ b/lib/pangea/widgets/chat/message_audio_card.dart @@ -2,6 +2,7 @@ import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pages/chat/events/audio_player.dart'; import 'package:fluffychat/pangea/models/pangea_message_event.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:matrix/matrix.dart'; @@ -113,14 +114,12 @@ class MessageAudioCardState extends State { localAudioEvent, color: Theme.of(context).colorScheme.onPrimaryContainer, matrixFile: audioFile, + autoplay: true, ), ], ), ) - : Padding( - padding: const EdgeInsets.only(left: 8), - child: playButton, - ), + : const CardErrorWidget(), ); } } diff --git a/lib/pangea/widgets/chat/message_text_selection.dart b/lib/pangea/widgets/chat/message_text_selection.dart index b41d62cbe..6263738f4 100644 --- a/lib/pangea/widgets/chat/message_text_selection.dart +++ b/lib/pangea/widgets/chat/message_text_selection.dart @@ -32,4 +32,6 @@ class MessageTextSelection { } selectionStream.add(selectedText); } + + int get offset => messageText.indexOf(selectedText!); } diff --git a/lib/pangea/widgets/chat/message_toolbar.dart b/lib/pangea/widgets/chat/message_toolbar.dart index e410305d9..913c77e4a 100644 --- a/lib/pangea/widgets/chat/message_toolbar.dart +++ b/lib/pangea/widgets/chat/message_toolbar.dart @@ -64,53 +64,56 @@ class ToolbarDisplayController { messageWidth = transformTargetSize.width; } - Widget overlayEntry; - try { - overlayEntry = Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: pangeaMessageEvent.ownMessage - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: [ - toolbar!, - const SizedBox(height: 6), - OverlayMessage( - pangeaMessageEvent.event, - timeline: pangeaMessageEvent.timeline, - immersionMode: immersionMode, - ownMessage: pangeaMessageEvent.ownMessage, - toolbarController: this, - width: messageWidth, - ), - ], - ); - } catch (err) { - ErrorHandler.logError(e: err, s: StackTrace.current); - return; - } - OverlayUtil.showOverlay( - context: context, - child: overlayEntry, - transformTargetId: targetId, - targetAnchor: pangeaMessageEvent.ownMessage - ? Alignment.bottomRight - : Alignment.bottomLeft, - followerAnchor: pangeaMessageEvent.ownMessage - ? Alignment.bottomRight - : Alignment.bottomLeft, - backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(164), - ); + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + Widget overlayEntry; + try { + overlayEntry = Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: pangeaMessageEvent.ownMessage + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: [ + toolbar!, + const SizedBox(height: 6), + OverlayMessage( + pangeaMessageEvent.event, + timeline: pangeaMessageEvent.timeline, + immersionMode: immersionMode, + ownMessage: pangeaMessageEvent.ownMessage, + toolbarController: this, + width: messageWidth, + ), + ], + ); + } catch (err) { + ErrorHandler.logError(e: err, s: StackTrace.current); + return; + } - if (MatrixState.pAnyState.overlay != null) { - overlayId = MatrixState.pAnyState.overlay.hashCode.toString(); - } - - if (mode != null) { - Future.delayed( - const Duration(milliseconds: 100), - () => toolbarModeStream.add(mode), + OverlayUtil.showOverlay( + context: context, + child: overlayEntry, + transformTargetId: targetId, + targetAnchor: pangeaMessageEvent.ownMessage + ? Alignment.bottomRight + : Alignment.bottomLeft, + followerAnchor: pangeaMessageEvent.ownMessage + ? Alignment.bottomRight + : Alignment.bottomLeft, + backgroundColor: const Color.fromRGBO(0, 0, 0, 1).withAlpha(164), ); - } + + if (MatrixState.pAnyState.overlay != null) { + overlayId = MatrixState.pAnyState.overlay.hashCode.toString(); + } + + if (mode != null) { + Future.delayed( + const Duration(milliseconds: 100), + () => toolbarModeStream.add(mode), + ); + } + }); } bool get highlighted => @@ -141,12 +144,12 @@ class MessageToolbar extends StatefulWidget { class MessageToolbarState extends State { Widget? child; - MessageMode? _currentMode; + MessageMode? currentMode; bool hasSelectedText = false; - late StreamSubscription _selectionStream; - late StreamSubscription _toolbarModeStream; + late StreamSubscription selectionStream; + late StreamSubscription toolbarModeStream; - IconData _getIconData(MessageMode mode) { + IconData getIconData(MessageMode mode) { switch (mode) { case MessageMode.translation: return Icons.g_translate; @@ -159,7 +162,7 @@ class MessageToolbarState extends State { } } - bool _enabledButton(MessageMode mode) { + bool enabledButton(MessageMode mode) { switch (mode) { case MessageMode.translation: return true; @@ -175,8 +178,8 @@ class MessageToolbarState extends State { void updateMode(MessageMode newMode) { debugPrint("updating toolbar mode"); - setState(() => _currentMode = newMode); - switch (_currentMode) { + setState(() => currentMode = newMode); + switch (currentMode) { case MessageMode.translation: showTranslation(); break; @@ -219,7 +222,7 @@ class MessageToolbarState extends State { wordLang: widget.pangeaMessageEvent.messageDisplayLangCode, fullText: widget.textSelection.messageText, fullTextLang: widget.pangeaMessageEvent.messageDisplayLangCode, - hasInfo: false, + hasInfo: true, room: widget.room, ); } @@ -240,25 +243,27 @@ class MessageToolbarState extends State { hasSelectedText = true; } - _toolbarModeStream = widget.toolbarModeStream.stream.listen((mode) { + toolbarModeStream = widget.toolbarModeStream.stream.listen((mode) { updateMode(mode); }); - _selectionStream = + Timer? timer; + + selectionStream = widget.textSelection.selectionStream.stream.listen((value) { - final bool shouldSetState = - value != null && !hasSelectedText || value == null && hasSelectedText; - hasSelectedText = value != null; - if (shouldSetState) { - setState(() {}); - } + timer?.cancel(); + timer = Timer(const Duration(milliseconds: 750), () { + if (currentMode != null || value != null && value.isNotEmpty) { + updateMode(currentMode ?? MessageMode.translation); + } + }); }); } @override void dispose() { - _selectionStream.cancel(); - _toolbarModeStream.cancel(); + selectionStream.cancel(); + toolbarModeStream.cancel(); super.dispose(); } @@ -303,12 +308,12 @@ class MessageToolbarState extends State { mainAxisSize: MainAxisSize.min, children: MessageMode.values.map((mode) { return IconButton( - icon: Icon(_getIconData(mode)), - color: _currentMode == mode + icon: Icon(getIconData(mode)), + color: currentMode == mode ? Theme.of(context).colorScheme.primary : null, onPressed: - _enabledButton(mode) ? () => updateMode(mode) : null, + enabledButton(mode) ? () => updateMode(mode) : null, ); }).toList() + [ diff --git a/lib/pangea/widgets/chat/message_translation_card.dart b/lib/pangea/widgets/chat/message_translation_card.dart index c963dd251..50f6ff371 100644 --- a/lib/pangea/widgets/chat/message_translation_card.dart +++ b/lib/pangea/widgets/chat/message_translation_card.dart @@ -4,9 +4,9 @@ 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/widgets/chat/message_text_selection.dart'; +import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; class MessageTranslationCard extends StatefulWidget { final PangeaMessageEvent messageEvent; @@ -73,11 +73,13 @@ class MessageTranslationCardState extends State { final resp = await FullTextTranslationRepo.translate( accessToken: accessToken, request: FullTextTranslationRequestModel( - text: widget.selection.selectedText!, + text: widget.selection.messageText, tgtLang: translationLangCode()!, userL1: l1Code!, userL2: l2Code!, srcLang: widget.messageEvent.messageDisplayLangCode, + length: widget.selection.selectedText!.length, + offset: widget.selection.offset, ), ); @@ -129,6 +131,12 @@ class MessageTranslationCardState extends State { @override Widget build(BuildContext context) { + if (!_fetchingRepresentation && + repEvent == null && + selectionTranslation == null) { + return const CardErrorWidget(); + } + return Padding( padding: const EdgeInsets.all(8), child: _fetchingRepresentation @@ -145,15 +153,10 @@ class MessageTranslationCardState extends State { selectionTranslation!, style: BotStyle.text(context), ) - : repEvent != null - ? Text( - repEvent!.text, - style: BotStyle.text(context), - ) - : Text( - L10n.of(context)!.oopsSomethingWentWrong, - style: BotStyle.text(context), - ), + : Text( + repEvent!.text, + style: BotStyle.text(context), + ), ); } } diff --git a/lib/pangea/widgets/igc/word_data_card.dart b/lib/pangea/widgets/igc/word_data_card.dart index 9cf3da98f..7f68db5ea 100644 --- a/lib/pangea/widgets/igc/word_data_card.dart +++ b/lib/pangea/widgets/igc/word_data_card.dart @@ -7,9 +7,7 @@ import 'package:fluffychat/pangea/models/language_model.dart'; import 'package:fluffychat/pangea/utils/bot_style.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/firebase_analytics.dart'; -import 'package:fluffychat/pangea/widgets/common/bot_face_svg.dart'; import 'package:fluffychat/pangea/widgets/common/p_circular_loader.dart'; -import 'package:fluffychat/pangea/widgets/igc/card_header.dart'; import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -183,10 +181,6 @@ class WordDataCardView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ - CardHeader( - text: controller.widget.word, - botExpression: BotExpression.down, - ), if (controller.widget.choiceFeedback != null) Text( controller.widget.choiceFeedback!, diff --git a/lib/utils/error_reporter.dart b/lib/utils/error_reporter.dart index cd051abbd..2449761c3 100644 --- a/lib/utils/error_reporter.dart +++ b/lib/utils/error_reporter.dart @@ -1,17 +1,6 @@ -import 'dart:io'; - -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:flutter_highlighter/flutter_highlighter.dart'; -import 'package:flutter_highlighter/themes/shades-of-purple.dart'; import 'package:matrix/matrix.dart'; -import 'package:url_launcher/url_launcher.dart'; - -import 'package:fluffychat/config/app_config.dart'; -import 'package:fluffychat/utils/platform_infos.dart'; class ErrorReporter { final BuildContext context; @@ -21,63 +10,72 @@ class ErrorReporter { void onErrorCallback(Object error, [StackTrace? stackTrace]) async { Logs().e(message ?? 'Error caught', error, stackTrace); - final text = '$error\n${stackTrace ?? ''}'; - final consent = await showAdaptiveDialog( - context: context, - builder: (context) => AlertDialog.adaptive( - title: Text(L10n.of(context)!.reportErrorDescription), - content: SizedBox( - height: 256, - width: 256, - child: SingleChildScrollView( - child: HighlightView( - text, - language: 'sh', - theme: shadesOfPurpleTheme, - ), - ), - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: Text(L10n.of(context)!.close), - ), - TextButton( - onPressed: () => Clipboard.setData( - ClipboardData(text: text), - ), - child: Text(L10n.of(context)!.copy), - ), - TextButton( - onPressed: () => Navigator.of(context).pop(true), - child: Text(L10n.of(context)!.report), - ), - ], - ), - ); - if (consent != true) return; - final os = kIsWeb ? 'web' : Platform.operatingSystem; - final version = await PlatformInfos.getVersion(); - final description = ''' -- Operating system: $os -- Version: $version - -### Exception -$error - -### StackTrace -${stackTrace?.toString().split('\n').take(10).join('\n')} -'''; - launchUrl( - AppConfig.newIssueUrl.resolveUri( - Uri( - queryParameters: { - 'title': '[BUG]: ${message ?? error.toString()}', - 'body': description, - }, + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + L10n.of(context)!.oopsSomethingWentWrong, ), ), - mode: LaunchMode.externalApplication, ); + // #Pangea +// final text = '$error\n${stackTrace ?? ''}'; +// final consent = await showAdaptiveDialog( +// context: context, +// builder: (context) => AlertDialog.adaptive( +// title: Text(L10n.of(context)!.reportErrorDescription), +// content: SizedBox( +// height: 256, +// width: 256, +// child: SingleChildScrollView( +// child: HighlightView( +// text, +// language: 'sh', +// theme: shadesOfPurpleTheme, +// ), +// ), +// ), +// actions: [ +// TextButton( +// onPressed: () => Navigator.of(context).pop(false), +// child: Text(L10n.of(context)!.close), +// ), +// TextButton( +// onPressed: () => Clipboard.setData( +// ClipboardData(text: text), +// ), +// child: Text(L10n.of(context)!.copy), +// ), +// TextButton( +// onPressed: () => Navigator.of(context).pop(true), +// child: Text(L10n.of(context)!.report), +// ), +// ], +// ), +// ); +// if (consent != true) return; +// final os = kIsWeb ? 'web' : Platform.operatingSystem; +// final version = await PlatformInfos.getVersion(); +// final description = ''' +// - Operating system: $os +// - Version: $version + +// ### Exception +// $error + +// ### StackTrace +// ${stackTrace?.toString().split('\n').take(10).join('\n')} +// '''; +// launchUrl( +// AppConfig.newIssueUrl.resolveUri( +// Uri( +// queryParameters: { +// 'title': '[BUG]: ${message ?? error.toString()}', +// 'body': description, +// }, +// ), +// ), +// mode: LaunchMode.externalApplication, +// ); +// Pangea# } }