Merge branch 'main' of https://github.com/pangeachat/client into remove-duplicate-push
This commit is contained in:
commit
d8a6f935d2
16 changed files with 269 additions and 173 deletions
|
|
@ -400,7 +400,12 @@ class ChatView extends StatelessWidget {
|
|||
// #Pangea
|
||||
// Keep messages above minimum input bar height
|
||||
if (!controller.room.isAbandonedDMRoom)
|
||||
SizedBox(height: controller.inputBarHeight),
|
||||
AnimatedSize(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: SizedBox(
|
||||
height: controller.inputBarHeight,
|
||||
),
|
||||
),
|
||||
// Pangea#
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -162,65 +162,68 @@ class HtmlMessage extends StatelessWidget {
|
|||
String fullHtml,
|
||||
List<PangeaToken> remainingTokens,
|
||||
) {
|
||||
for (final node in element.nodes) {
|
||||
node.replaceWith(_tokenizeHtml(node, fullHtml, remainingTokens));
|
||||
}
|
||||
final regex = RegExp(r'(<[^>]+>)');
|
||||
|
||||
if (element is dom.Text) {
|
||||
// once a text element in reached in the HTML tree, find and
|
||||
// wrap all the spans with matching tokens until all tokens
|
||||
// have been wrapped or no more text elements remain
|
||||
String tokenizedText = element.text;
|
||||
while (remainingTokens.isNotEmpty) {
|
||||
final tokenText = remainingTokens.first.text.content;
|
||||
final matches = regex.allMatches(fullHtml);
|
||||
final List<String> result = <String>[];
|
||||
int lastEnd = 0;
|
||||
|
||||
int startIndex = tokenizedText.lastIndexOf('</token>');
|
||||
startIndex = startIndex == -1 ? 0 : startIndex + 8;
|
||||
final int tokenIndex = tokenizedText.indexOf(
|
||||
tokenText,
|
||||
startIndex,
|
||||
);
|
||||
|
||||
// if the token is not found in the text, check if the token exist in the full HTML.
|
||||
// If not, remove the token and continue. If so, break to move on to the next node in the HTML.
|
||||
if (tokenIndex == -1) {
|
||||
final fullHtmlIndex = fullHtml.indexOf(tokenText);
|
||||
if (fullHtmlIndex == -1) {
|
||||
remainingTokens.removeAt(0);
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final token = remainingTokens.removeAt(0);
|
||||
final tokenEnd = tokenIndex + tokenText.length;
|
||||
final before = tokenizedText.substring(0, tokenIndex);
|
||||
final after = tokenizedText.substring(tokenEnd);
|
||||
|
||||
tokenizedText =
|
||||
"$before<token offset=\"${token.text.offset}\" length=\"${token.text.length}\">$tokenText</token>$after";
|
||||
for (final match in matches) {
|
||||
if (match.start > lastEnd) {
|
||||
result.add(fullHtml.substring(lastEnd, match.start)); // Text before tag
|
||||
}
|
||||
|
||||
final newElement = dom.Element.html('<span>$tokenizedText</span>');
|
||||
return newElement;
|
||||
result.add(match.group(0)!); // The tag itself
|
||||
lastEnd = match.end;
|
||||
}
|
||||
|
||||
return element;
|
||||
if (lastEnd < fullHtml.length) {
|
||||
result.add(fullHtml.substring(lastEnd)); // Remaining text after last tag
|
||||
}
|
||||
|
||||
for (final PangeaToken token in tokens ?? []) {
|
||||
final String tokenText = token.text.content;
|
||||
final substringIndex = result.indexWhere(
|
||||
(string) =>
|
||||
string.contains(tokenText) &&
|
||||
!(string.startsWith('<') && string.endsWith('>')),
|
||||
);
|
||||
|
||||
if (substringIndex == -1) continue;
|
||||
final int tokenIndex = result[substringIndex].indexOf(tokenText);
|
||||
if (tokenIndex == -1) continue;
|
||||
|
||||
final int tokenLength = tokenText.characters.length;
|
||||
final before = result[substringIndex].substring(0, tokenIndex);
|
||||
final after = result[substringIndex].substring(tokenIndex + tokenLength);
|
||||
result.replaceRange(substringIndex, substringIndex + 1, [
|
||||
if (before.isNotEmpty) before,
|
||||
'<token offset="${token.text.offset}" length="${token.text.length}">$tokenText</token>',
|
||||
if (after.isNotEmpty) after,
|
||||
]);
|
||||
}
|
||||
|
||||
return dom.Element.html('<span>${result.join()}</span>');
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
/// Adding line breaks before block elements.
|
||||
List<InlineSpan> _renderWithLineBreaks(
|
||||
dom.NodeList nodes,
|
||||
BuildContext context, {
|
||||
// #Pangea
|
||||
// BuildContext context, {
|
||||
BuildContext context,
|
||||
TextStyle textStyle, {
|
||||
// Pangea#
|
||||
int depth = 1,
|
||||
}) {
|
||||
final onlyElements = nodes.whereType<dom.Element>().toList();
|
||||
return [
|
||||
for (var i = 0; i < nodes.length; i++) ...[
|
||||
// Actually render the node child:
|
||||
_renderHtml(nodes[i], context, depth: depth + 1),
|
||||
// #Pangea
|
||||
// _renderHtml(nodes[i], context, depth: depth + 1),
|
||||
_renderHtml(nodes[i], context, textStyle, depth: depth + 1),
|
||||
// Pangea#
|
||||
// Add linebreaks between blocks:
|
||||
if (nodes[i] is dom.Element &&
|
||||
onlyElements.indexOf(nodes[i] as dom.Element) <
|
||||
|
|
@ -237,7 +240,11 @@ class HtmlMessage extends StatelessWidget {
|
|||
/// Transforms a Node to an InlineSpan.
|
||||
InlineSpan _renderHtml(
|
||||
dom.Node node,
|
||||
BuildContext context, {
|
||||
// #Pangea
|
||||
// BuildContext context, {
|
||||
BuildContext context,
|
||||
TextStyle textStyle, {
|
||||
// Pangea#
|
||||
int depth = 1,
|
||||
}) {
|
||||
// We must not render elements nested more than 100 elements deep:
|
||||
|
|
@ -276,9 +283,11 @@ class HtmlMessage extends StatelessWidget {
|
|||
final renderer = TokenRenderingUtil(
|
||||
pangeaMessageEvent: pangeaMessageEvent,
|
||||
readingAssistanceMode: readingAssistanceMode,
|
||||
existingStyle: AppConfig.messageTextStyle(
|
||||
pangeaMessageEvent!.event,
|
||||
textColor,
|
||||
existingStyle: textStyle.merge(
|
||||
AppConfig.messageTextStyle(
|
||||
pangeaMessageEvent!.event,
|
||||
textColor,
|
||||
),
|
||||
),
|
||||
overlayController: overlayController,
|
||||
isTransitionAnimation: isTransitionAnimation,
|
||||
|
|
@ -418,6 +427,11 @@ class HtmlMessage extends StatelessWidget {
|
|||
children: _renderWithLineBreaks(
|
||||
node.nodes,
|
||||
context,
|
||||
// #Pangea
|
||||
textStyle.merge(
|
||||
linkStyle.copyWith(height: 1.25),
|
||||
),
|
||||
// Pangea#
|
||||
depth: depth,
|
||||
),
|
||||
style: linkStyle,
|
||||
|
|
@ -450,6 +464,9 @@ class HtmlMessage extends StatelessWidget {
|
|||
..._renderWithLineBreaks(
|
||||
node.nodes,
|
||||
context,
|
||||
// #Pangea
|
||||
textStyle,
|
||||
// Pangea#
|
||||
depth: depth,
|
||||
),
|
||||
],
|
||||
|
|
@ -478,6 +495,9 @@ class HtmlMessage extends StatelessWidget {
|
|||
children: _renderWithLineBreaks(
|
||||
node.nodes,
|
||||
context,
|
||||
// #Pangea
|
||||
textStyle.copyWith(fontStyle: FontStyle.italic),
|
||||
// Pangea#
|
||||
depth: depth,
|
||||
),
|
||||
),
|
||||
|
|
@ -576,12 +596,28 @@ class HtmlMessage extends StatelessWidget {
|
|||
node.localName == 'summary',
|
||||
)
|
||||
.map(
|
||||
(node) => _renderHtml(node, context, depth: depth),
|
||||
// #Pangea
|
||||
// (node) => _renderHtml(node, context, depth: depth),
|
||||
(node) => _renderHtml(
|
||||
node,
|
||||
context,
|
||||
textStyle.merge(
|
||||
TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
depth: depth,
|
||||
),
|
||||
// Pangea#
|
||||
)
|
||||
else
|
||||
..._renderWithLineBreaks(
|
||||
node.nodes,
|
||||
context,
|
||||
// #Pangea
|
||||
textStyle,
|
||||
// Pangea#
|
||||
depth: depth,
|
||||
),
|
||||
],
|
||||
|
|
@ -614,6 +650,11 @@ class HtmlMessage extends StatelessWidget {
|
|||
children: _renderWithLineBreaks(
|
||||
node.nodes,
|
||||
context,
|
||||
// #Pangea
|
||||
textStyle.copyWith(
|
||||
backgroundColor: obscure ? textColor : null,
|
||||
),
|
||||
// Pangea#
|
||||
depth: depth,
|
||||
),
|
||||
),
|
||||
|
|
@ -628,6 +669,36 @@ class HtmlMessage extends StatelessWidget {
|
|||
);
|
||||
block:
|
||||
default:
|
||||
// #Pangea
|
||||
final style = switch (node.localName) {
|
||||
'body' => TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: textColor,
|
||||
),
|
||||
'a' => linkStyle,
|
||||
'strong' => const TextStyle(fontWeight: FontWeight.bold),
|
||||
'em' || 'i' => const TextStyle(fontStyle: FontStyle.italic),
|
||||
'del' ||
|
||||
'strikethrough' =>
|
||||
const TextStyle(decoration: TextDecoration.lineThrough),
|
||||
'u' => const TextStyle(decoration: TextDecoration.underline),
|
||||
'h1' => TextStyle(fontSize: fontSize * 1.6, height: 2),
|
||||
'h2' => TextStyle(fontSize: fontSize * 1.5, height: 2),
|
||||
'h3' => TextStyle(fontSize: fontSize * 1.4, height: 2),
|
||||
'h4' => TextStyle(fontSize: fontSize * 1.3, height: 1.75),
|
||||
'h5' => TextStyle(fontSize: fontSize * 1.2, height: 1.75),
|
||||
'h6' => TextStyle(fontSize: fontSize * 1.1, height: 1.5),
|
||||
'span' => TextStyle(
|
||||
color: node.attributes['color']?.hexToColor ??
|
||||
node.attributes['data-mx-color']?.hexToColor ??
|
||||
textColor,
|
||||
backgroundColor: node.attributes['data-mx-bg-color']?.hexToColor,
|
||||
),
|
||||
'sup' => const TextStyle(fontFeatures: [FontFeature.superscripts()]),
|
||||
'sub' => const TextStyle(fontFeatures: [FontFeature.subscripts()]),
|
||||
_ => null,
|
||||
};
|
||||
// Pangea#
|
||||
return TextSpan(
|
||||
style: switch (node.localName) {
|
||||
'body' => TextStyle(
|
||||
|
|
@ -663,6 +734,9 @@ class HtmlMessage extends StatelessWidget {
|
|||
children: _renderWithLineBreaks(
|
||||
node.nodes,
|
||||
context,
|
||||
// #Pangea
|
||||
textStyle.merge(style ?? const TextStyle()),
|
||||
// Pangea#
|
||||
depth: depth,
|
||||
),
|
||||
);
|
||||
|
|
@ -698,6 +772,12 @@ class HtmlMessage extends StatelessWidget {
|
|||
parsed,
|
||||
// Pangea#
|
||||
context,
|
||||
// #Pangea
|
||||
TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: textColor,
|
||||
),
|
||||
// Pangea#
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ class NewGroupController extends State<NewGroup> {
|
|||
|
||||
bool requiredCodeToJoin = false;
|
||||
// bool publicGroup = false;
|
||||
|
||||
bool get canSubmit => nameController.text.trim().isNotEmpty;
|
||||
// Pangea#
|
||||
bool groupCanBeFound = false;
|
||||
|
||||
|
|
@ -250,10 +252,11 @@ class NewGroupController extends State<NewGroup> {
|
|||
focusNode.requestFocus();
|
||||
return;
|
||||
}
|
||||
// Pangea#
|
||||
|
||||
if (nameController.text.trim().isEmpty &&
|
||||
createGroupType == CreateGroupType.space) {
|
||||
// if (nameController.text.trim().isEmpty &&
|
||||
// createGroupType == CreateGroupType.space) {
|
||||
if (!canSubmit) {
|
||||
// Pangea#
|
||||
setState(() => error = L10n.of(context).pleaseFillOut);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,9 +131,9 @@ class NewGroupView extends StatelessWidget {
|
|||
onFieldSubmitted: (value) {
|
||||
controller.loading ? null : controller.submitAction();
|
||||
},
|
||||
validator: (value) => value == null || value.isEmpty
|
||||
? L10n.of(context).pleaseFillOut
|
||||
: null,
|
||||
validator: (value) => controller.canSubmit
|
||||
? null
|
||||
: L10n.of(context).pleaseFillOut,
|
||||
focusNode: controller.focusNode,
|
||||
// Pangea#
|
||||
),
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ class ChatFloatingActionButtonState extends State<ChatFloatingActionButton> {
|
|||
child: const Icon(Icons.arrow_downward_outlined),
|
||||
);
|
||||
}
|
||||
if (widget.controller.choreographer.errorService.error != null) {
|
||||
if (widget.controller.choreographer.errorService.error != null &&
|
||||
!widget.controller.choreographer.itController.willOpen) {
|
||||
return ChoreographerHasErrorButton(
|
||||
widget.controller.choreographer.errorService.error!,
|
||||
widget.controller.choreographer,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
|
|
@ -22,17 +24,27 @@ class ChatInputBar extends StatefulWidget {
|
|||
}
|
||||
|
||||
class ChatInputBarState extends State<ChatInputBar> {
|
||||
void updateHeight() {
|
||||
final renderBox = context.findRenderObject() as RenderBox?;
|
||||
if (renderBox == null || !renderBox.hasSize) return;
|
||||
widget.controller.updateInputBarHeight(renderBox.size.height);
|
||||
Timer? _debounceTimer;
|
||||
|
||||
void _updateHeight() {
|
||||
_debounceTimer = Timer(const Duration(milliseconds: 100), () {
|
||||
final renderBox = context.findRenderObject() as RenderBox?;
|
||||
if (renderBox == null || !renderBox.hasSize) return;
|
||||
widget.controller.updateInputBarHeight(renderBox.size.height);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounceTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return NotificationListener(
|
||||
onNotification: (SizeChangedLayoutNotification notification) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => updateHeight());
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _updateHeight());
|
||||
return true;
|
||||
},
|
||||
child: SizeChangedLayoutNotifier(
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import 'package:fluffychat/pangea/choreographer/enums/edit_type.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/it_step.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/language_detection_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/utils/input_paste_listener.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/pangea_text_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/paywall_card.dart';
|
||||
|
|
@ -21,7 +20,6 @@ import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
|||
import 'package:fluffychat/pangea/common/utils/any_state_holder.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/overlay.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/events/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/token_api_models.dart';
|
||||
|
|
@ -148,56 +146,57 @@ class Choreographer {
|
|||
)
|
||||
: null;
|
||||
|
||||
final detectionResp = await LanguageDetectionRepo.get(
|
||||
MatrixState.pangeaController.userController.accessToken,
|
||||
request: LanguageDetectionRequest(
|
||||
PangeaMessageTokens? tokensSent;
|
||||
PangeaRepresentation? originalSent;
|
||||
try {
|
||||
TokensResponseModel? res;
|
||||
if (l1LangCode != null && l2LangCode != null) {
|
||||
res = await pangeaController.messageData
|
||||
.getTokens(
|
||||
repEventId: null,
|
||||
room: chatController.room,
|
||||
req: TokensRequestModel(
|
||||
fullText: currentText,
|
||||
senderL1: l1LangCode!,
|
||||
senderL2: l2LangCode!,
|
||||
),
|
||||
)
|
||||
.timeout(const Duration(seconds: 10));
|
||||
}
|
||||
|
||||
originalSent = PangeaRepresentation(
|
||||
langCode: res?.detections.firstOrNull?.langCode ??
|
||||
LanguageKeys.unknownLanguage,
|
||||
text: currentText,
|
||||
senderl1: l1LangCode,
|
||||
senderl2: l2LangCode,
|
||||
),
|
||||
);
|
||||
final detections = detectionResp.detections;
|
||||
final detectedLanguage =
|
||||
detections.firstOrNull?.langCode ?? LanguageKeys.unknownLanguage;
|
||||
|
||||
final PangeaRepresentation originalSent = PangeaRepresentation(
|
||||
langCode: detectedLanguage,
|
||||
text: currentText,
|
||||
originalSent: true,
|
||||
originalWritten: originalWritten == null,
|
||||
);
|
||||
|
||||
List<PangeaToken>? res;
|
||||
if (l1LangCode != null && l2LangCode != null) {
|
||||
res = await pangeaController.messageData.getTokens(
|
||||
repEventId: null,
|
||||
room: chatController.room,
|
||||
req: TokensRequestModel(
|
||||
fullText: currentText,
|
||||
langCode: detectedLanguage,
|
||||
senderL1: l1LangCode!,
|
||||
senderL2: l2LangCode!,
|
||||
),
|
||||
originalSent: true,
|
||||
originalWritten: originalWritten == null,
|
||||
);
|
||||
|
||||
tokensSent = res != null
|
||||
? PangeaMessageTokens(
|
||||
tokens: res.tokens,
|
||||
detections: res.detections,
|
||||
)
|
||||
: null;
|
||||
} catch (e, s) {
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
s: s,
|
||||
data: {
|
||||
"currentText": currentText,
|
||||
"l1LangCode": l1LangCode,
|
||||
"l2LangCode": l2LangCode,
|
||||
"choreoRecord": choreoRecord.toJson(),
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
chatController.send(
|
||||
originalSent: originalSent,
|
||||
tokensSent: tokensSent,
|
||||
choreo: choreoRecord,
|
||||
);
|
||||
clear();
|
||||
}
|
||||
|
||||
final PangeaMessageTokens? tokensSent = res != null
|
||||
? PangeaMessageTokens(
|
||||
tokens: res,
|
||||
detections: detections,
|
||||
)
|
||||
: null;
|
||||
|
||||
chatController.send(
|
||||
// originalWritten: originalWritten,
|
||||
originalSent: originalSent,
|
||||
tokensSent: tokensSent,
|
||||
//TODO - save originalwritten tokens
|
||||
// choreo: applicableChoreo,
|
||||
choreo: choreoRecord,
|
||||
);
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
_resetDebounceTimer() {
|
||||
|
|
|
|||
|
|
@ -104,7 +104,9 @@ class IgcController {
|
|||
}
|
||||
|
||||
final IGCTextData igcTextDataResponse =
|
||||
await _igcTextDataCache[reqBody.hashCode]!.data;
|
||||
await _igcTextDataCache[reqBody.hashCode]!
|
||||
.data
|
||||
.timeout((const Duration(seconds: 10)));
|
||||
|
||||
// this will happen when the user changes the input while igc is fetching results
|
||||
if (igcTextDataResponse.originalInput != choreographer.currentText) {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class ITController {
|
|||
choreographer.setState();
|
||||
}
|
||||
|
||||
Duration get animationSpeed => const Duration(milliseconds: 500);
|
||||
Duration get animationSpeed => const Duration(milliseconds: 300);
|
||||
|
||||
Future<void> initializeIT(ITStartData itStartData) async {
|
||||
_willOpen = true;
|
||||
|
|
@ -136,7 +136,8 @@ class ITController {
|
|||
|
||||
// During first IT step, next step will not be set
|
||||
if (nextITStep == null) {
|
||||
final ITResponseModel res = await _customInputTranslation(currentText);
|
||||
final ITResponseModel res = await _customInputTranslation(currentText)
|
||||
.timeout(const Duration(seconds: 10));
|
||||
if (sourceText == null) return;
|
||||
|
||||
if (res.goldContinuances != null && res.goldContinuances!.isNotEmpty) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/constants/choreo_constants.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/it_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/it_bar_buttons.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/it_feedback_card.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/instructions/instructions_enum.dart';
|
||||
|
|
@ -206,12 +205,14 @@ class ITBarState extends State<ITBar> with SingleTickerProviderStateMixin {
|
|||
if (!itController.isEditingSourceText)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: itController.sourceText != null
|
||||
? Text(
|
||||
itController.sourceText!,
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
: const LinearProgressIndicator(),
|
||||
child: !itController.willOpen
|
||||
? const SizedBox()
|
||||
: itController.sourceText != null
|
||||
? Text(
|
||||
itController.sourceText!,
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
: const LinearProgressIndicator(),
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Container(
|
||||
|
|
@ -391,10 +392,12 @@ class ITChoices extends StatelessWidget {
|
|||
return const SizedBox();
|
||||
}
|
||||
if (controller.currentITStep == null) {
|
||||
return CircularProgressIndicator(
|
||||
strokeWidth: 2.0,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
);
|
||||
return controller.willOpen
|
||||
? CircularProgressIndicator(
|
||||
strokeWidth: 2.0,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
)
|
||||
: const SizedBox();
|
||||
}
|
||||
return ChoicesArray(
|
||||
id: controller.currentITStep.hashCode.toString(),
|
||||
|
|
@ -438,23 +441,38 @@ class ITError extends StatelessWidget {
|
|||
final ErrorCopy errorCopy = ErrorCopy(context, error);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 300),
|
||||
child: Text(
|
||||
// Text(
|
||||
"${errorCopy.title}\n${errorCopy.body}",
|
||||
// Haga clic en su mensaje para ver los significados de las palabras.
|
||||
style: TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.error_outline,
|
||||
size: 20,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
),
|
||||
TextSpan(text: " ${errorCopy.title} "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
controller.closeIT();
|
||||
controller.choreographer.errorService.resetError();
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.close,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
style: TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
ITRestartButton(controller: controller),
|
||||
],
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../controllers/it_controller.dart';
|
||||
|
||||
class ITRestartButton extends StatelessWidget {
|
||||
ITRestartButton({
|
||||
super.key,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
final ITController controller;
|
||||
final PangeaController pangeaController = MatrixState.pangeaController;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IconButton(
|
||||
onPressed: () async {
|
||||
controller.choreographer.errorService.resetError();
|
||||
controller.currentITStep = null;
|
||||
controller.choreographer.getLanguageHelp();
|
||||
},
|
||||
icon: const Icon(Icons.refresh_outlined),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,6 @@ import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
|||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/events/models/representation_content_model.dart';
|
||||
import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/token_api_models.dart';
|
||||
|
|
@ -23,7 +22,7 @@ import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
|||
class MessageDataController extends BaseController {
|
||||
late PangeaController _pangeaController;
|
||||
|
||||
final Map<int, Future<List<PangeaToken>>> _tokensCache = {};
|
||||
final Map<int, Future<TokensResponseModel>> _tokensCache = {};
|
||||
final Map<int, Future<PangeaRepresentation>> _representationCache = {};
|
||||
late Timer _cacheTimer;
|
||||
|
||||
|
|
@ -54,7 +53,7 @@ class MessageDataController extends BaseController {
|
|||
|
||||
/// get tokens from the server
|
||||
/// if repEventId is not null, send the tokens to the room
|
||||
Future<List<PangeaToken>> _getTokens({
|
||||
Future<TokensResponseModel> _getTokens({
|
||||
required String? repEventId,
|
||||
required TokensRequestModel req,
|
||||
required Room? room,
|
||||
|
|
@ -83,13 +82,13 @@ class MessageDataController extends BaseController {
|
|||
);
|
||||
}
|
||||
|
||||
return res.tokens;
|
||||
return res;
|
||||
}
|
||||
|
||||
/// get tokens from the server
|
||||
/// first check if the tokens are in the cache
|
||||
/// if repEventId is not null, send the tokens to the room
|
||||
Future<List<PangeaToken>> getTokens({
|
||||
Future<TokensResponseModel> getTokens({
|
||||
required String? repEventId,
|
||||
required TokensRequestModel req,
|
||||
required Room? room,
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ class RepresentationEvent {
|
|||
),
|
||||
);
|
||||
}
|
||||
final List<PangeaToken> res =
|
||||
final TokensResponseModel res =
|
||||
await MatrixState.pangeaController.messageData.getTokens(
|
||||
repEventId: _event?.eventId,
|
||||
room: _event?.room ?? parentMessageEvent.room,
|
||||
|
|
@ -180,7 +180,7 @@ class RepresentationEvent {
|
|||
),
|
||||
);
|
||||
|
||||
return res;
|
||||
return res.tokens;
|
||||
}
|
||||
|
||||
Future<void> sendTokensEvent(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:fluffychat/pangea/choreographer/models/language_detection_model.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_model.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart';
|
||||
|
||||
class TokensRequestModel {
|
||||
/// the text to be tokenized
|
||||
|
|
@ -24,16 +25,16 @@ class TokensRequestModel {
|
|||
|
||||
TokensRequestModel({
|
||||
required this.fullText,
|
||||
required this.langCode,
|
||||
required this.senderL1,
|
||||
required this.senderL2,
|
||||
this.langCode,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
ModelKey.fullText: fullText,
|
||||
ModelKey.userL1: senderL1,
|
||||
ModelKey.userL2: senderL2,
|
||||
ModelKey.langCode: langCode,
|
||||
ModelKey.langCode: langCode ?? LanguageKeys.unknownLanguage,
|
||||
};
|
||||
|
||||
// override equals and hashcode
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ class PublicRoomBottomSheetState extends State<PublicRoomBottomSheet> {
|
|||
child: Column(
|
||||
spacing: 16.0,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 8.0,
|
||||
|
|
@ -226,6 +227,7 @@ class PublicRoomBottomSheetState extends State<PublicRoomBottomSheet> {
|
|||
child: Text(
|
||||
chunk!.topic!,
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.start,
|
||||
maxLines: null,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class PublicSpaceCard extends StatelessWidget {
|
|||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
spacing: 4.0,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue