Merge pull request #67 from pangeachat/toolbar-testing

Show translation of selected text
This commit is contained in:
wcjord 2024-02-19 12:57:12 -05:00 committed by GitHub
commit 1baaa0e2ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 98 additions and 36 deletions

View file

@ -343,6 +343,8 @@ class MessageContent extends StatelessWidget {
mode: MessageMode.play,
),
),
enableInteractiveSelection:
toolbarController?.highlighted ?? false,
// text: snapshot.data ??
// event.calcLocalizedBodyFallback(
// MatrixLocals(L10n.of(context)!),

View file

@ -73,6 +73,7 @@ class ToolbarDisplayController {
: CrossAxisAlignment.start,
children: [
toolbar!,
const SizedBox(height: 6),
OverlayMessage(
pangeaMessageEvent.event,
timeline: pangeaMessageEvent.timeline,
@ -196,6 +197,7 @@ class MessageToolbarState extends State<MessageToolbar> {
child = MessageTranslationCard(
messageEvent: widget.pangeaMessageEvent,
immersionMode: widget.immersionMode,
selection: widget.textSelection,
);
}
@ -302,6 +304,9 @@ class MessageToolbarState extends State<MessageToolbar> {
children: MessageMode.values.map((mode) {
return IconButton(
icon: Icon(_getIconData(mode)),
color: _currentMode == mode
? Theme.of(context).colorScheme.primary
: null,
onPressed:
_enabledButton(mode) ? () => updateMode(mode) : null,
);

View file

@ -1,7 +1,9 @@
import 'package:fluffychat/pangea/models/pangea_message_event.dart';
import 'package:fluffychat/pangea/models/pangea_representation_event.dart';
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/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
@ -9,11 +11,13 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
class MessageTranslationCard extends StatefulWidget {
final PangeaMessageEvent messageEvent;
final bool immersionMode;
final MessageTextSelection selection;
const MessageTranslationCard({
super.key,
required this.messageEvent,
required this.immersionMode,
required this.selection,
});
@override
@ -22,25 +26,20 @@ class MessageTranslationCard extends StatefulWidget {
class MessageTranslationCardState extends State<MessageTranslationCard> {
RepresentationEvent? repEvent;
String? selectionTranslation;
String? oldSelectedText;
String? l1Code;
String? l2Code;
bool _fetchingRepresentation = false;
String? translationLangCode() {
final String? l1Code =
MatrixState.pangeaController.languageController.activeL1Code(
roomID: widget.messageEvent.room.id,
);
if (widget.immersionMode) return l1Code;
final String? l2Code =
MatrixState.pangeaController.languageController.activeL2Code(
roomID: widget.messageEvent.room.id,
);
final String? originalWrittenCode =
widget.messageEvent.originalWritten?.content.langCode;
return l1Code == originalWrittenCode ? l2Code : l1Code;
}
void fetchRepresentation(BuildContext context) {
Future<void> fetchRepresentation(BuildContext context) async {
final String? langCode = translationLangCode();
if (langCode == null) return;
@ -49,33 +48,83 @@ class MessageTranslationCardState extends State<MessageTranslationCard> {
);
if (repEvent == null && mounted) {
setState(() => _fetchingRepresentation = true);
widget.messageEvent
.representationByLanguageGlobal(
context: context,
langCode: langCode,
)
.onError(
(error, stackTrace) => ErrorHandler.logError(
e: error,
s: stackTrace,
),
)
.then((RepresentationEvent? event) => repEvent = event)
.whenComplete(
() {
setState(() => _fetchingRepresentation = false);
},
repEvent = await widget.messageEvent.representationByLanguageGlobal(
context: context,
langCode: langCode,
);
} else {
if (mounted) setState(() {});
}
}
Future<void> translateSelection() async {
final String? targetLang = translationLangCode();
if (widget.selection.selectedText == null ||
targetLang == null ||
l1Code == null ||
l2Code == null) {
selectionTranslation = null;
return;
}
oldSelectedText = widget.selection.selectedText;
final String accessToken =
await MatrixState.pangeaController.userController.accessToken;
final resp = await FullTextTranslationRepo.translate(
accessToken: accessToken,
request: FullTextTranslationRequestModel(
text: widget.selection.selectedText!,
tgtLang: translationLangCode()!,
userL1: l1Code!,
userL2: l2Code!,
srcLang: widget.messageEvent.messageDisplayLangCode,
),
);
if (mounted) {
selectionTranslation = resp.bestTranslation;
}
}
Future<void> loadTranslation(Future<void> Function() future) async {
if (!mounted) return;
setState(() => _fetchingRepresentation = true);
try {
await future();
} catch (err) {
ErrorHandler.logError(e: err);
}
if (mounted) {
setState(() => _fetchingRepresentation = false);
}
}
@override
void initState() {
super.initState();
fetchRepresentation(context);
l1Code = MatrixState.pangeaController.languageController.activeL1Code(
roomID: widget.messageEvent.room.id,
);
l2Code = MatrixState.pangeaController.languageController.activeL2Code(
roomID: widget.messageEvent.room.id,
);
setState(() {});
loadTranslation(() async {
if (widget.selection.selectedText != null) {
await translateSelection();
}
fetchRepresentation(context);
});
}
@override
void didUpdateWidget(covariant MessageTranslationCard oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldSelectedText != widget.selection.selectedText) {
loadTranslation(translateSelection);
}
}
@override
@ -91,15 +140,20 @@ class MessageTranslationCardState extends State<MessageTranslationCard> {
color: Theme.of(context).colorScheme.primary,
),
)
: repEvent != null
: selectionTranslation != null
? Text(
repEvent!.text,
selectionTranslation!,
style: BotStyle.text(context),
)
: Text(
L10n.of(context)!.oopsSomethingWentWrong,
style: BotStyle.text(context),
),
: repEvent != null
? Text(
repEvent!.text,
style: BotStyle.text(context),
)
: Text(
L10n.of(context)!.oopsSomethingWentWrong,
style: BotStyle.text(context),
),
);
}
}

View file

@ -124,6 +124,7 @@ class PangeaRichTextState extends State<PangeaRichText> {
.onTextSelection(selection);
},
onTap: () => widget.toolbarController.showToolbar(context),
enableInteractiveSelection: widget.toolbarController.highlighted,
contextMenuBuilder: (context, state) =>
widget.toolbarController.highlighted
? const SizedBox.shrink()