refactor: remove unused files in choreo folder, remove request and response models into their own files
This commit is contained in:
parent
cdd34a7f7c
commit
2637308891
46 changed files with 729 additions and 1475 deletions
|
|
@ -42,10 +42,10 @@ import 'package:fluffychat/pangea/chat/widgets/event_too_large_dialog.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/enums/edit_type.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/utils/language_mismatch_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/language_mismatch_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/utils/pangea_text_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/language_mismatch_popup.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/message_analytics_feedback.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/pangea_text_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:slugify/slugify.dart';
|
||||
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/pangea_text_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/utils/pangea_text_controller.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/utils/shrinkable_text.dart';
|
||||
import 'package:fluffychat/utils/markdown_context_builder.dart';
|
||||
import 'package:fluffychat/widgets/mxc_image.dart';
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ import 'package:flutter/material.dart';
|
|||
|
||||
class ChoreoConstants {
|
||||
static const numberOfITChoices = 4;
|
||||
// static const millisecondsToDisplayFeedback = 2500;
|
||||
static const millisecondsToDisplayFeedback = 0;
|
||||
static const commonalityThreshold = 0.9;
|
||||
static const levelThresholdForGreen = 1;
|
||||
static const levelThresholdForYellow = 2;
|
||||
static const levelThresholdForRed = 3;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ 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/utils/input_paste_listener.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/pangea_text_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/utils/pangea_text_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/paywall_card.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/any_state_holder.dart';
|
||||
|
|
|
|||
|
|
@ -1,152 +0,0 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import '../../common/constants/model_keys.dart';
|
||||
import '../../common/controllers/pangea_controller.dart';
|
||||
import '../../common/network/requests.dart';
|
||||
import '../../common/network/urls.dart';
|
||||
|
||||
class ContextualDefinitionController {
|
||||
late PangeaController _pangeaController;
|
||||
|
||||
final List<_ContextualDefinitionCacheItem> _definitions = [];
|
||||
|
||||
ContextualDefinitionController(PangeaController pangeaController) {
|
||||
_pangeaController = pangeaController;
|
||||
}
|
||||
|
||||
_ContextualDefinitionCacheItem? _getLocal(
|
||||
ContextualDefinitionRequestModel req,
|
||||
) =>
|
||||
_definitions.firstWhereOrNull(
|
||||
(e) => e.word == req.word && e.fullText == req.fullText,
|
||||
);
|
||||
|
||||
Future<ContextualDefinitionResponseModel?> get(
|
||||
ContextualDefinitionRequestModel req,
|
||||
) {
|
||||
final _ContextualDefinitionCacheItem? localItem = _getLocal(req);
|
||||
|
||||
if (localItem != null) return localItem.data;
|
||||
|
||||
_definitions.add(
|
||||
_ContextualDefinitionCacheItem(
|
||||
word: req.word,
|
||||
fullText: req.fullText,
|
||||
data: _define(req),
|
||||
),
|
||||
);
|
||||
|
||||
return _definitions.last.data;
|
||||
}
|
||||
|
||||
Future<ContextualDefinitionResponseModel?> _define(
|
||||
ContextualDefinitionRequestModel request,
|
||||
) async {
|
||||
try {
|
||||
final ContextualDefinitionResponseModel res =
|
||||
await _ContextualDefinitionRepo.define(
|
||||
_pangeaController.userController.accessToken,
|
||||
request,
|
||||
);
|
||||
return res;
|
||||
} catch (err, stack) {
|
||||
debugPrint(
|
||||
"error getting contextual definition for ${request.word} in '${request.fullText}'",
|
||||
);
|
||||
ErrorHandler.logError(e: err, s: stack, data: request.toJson());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _ContextualDefinitionCacheItem {
|
||||
String word;
|
||||
String fullText;
|
||||
Future<ContextualDefinitionResponseModel?> data;
|
||||
|
||||
_ContextualDefinitionCacheItem({
|
||||
required this.word,
|
||||
required this.fullText,
|
||||
required this.data,
|
||||
});
|
||||
}
|
||||
|
||||
class _ContextualDefinitionRepo {
|
||||
static Future<ContextualDefinitionResponseModel> define(
|
||||
String accessToken,
|
||||
ContextualDefinitionRequestModel request,
|
||||
) async {
|
||||
final Requests req = Requests(
|
||||
choreoApiKey: Environment.choreoApiKey,
|
||||
accessToken: accessToken,
|
||||
);
|
||||
|
||||
final Response res = await req.post(
|
||||
url: PApiUrls.contextualDefinition,
|
||||
body: request.toJson(),
|
||||
);
|
||||
|
||||
final ContextualDefinitionResponseModel response =
|
||||
ContextualDefinitionResponseModel.fromJson(
|
||||
jsonDecode(
|
||||
utf8.decode(res.bodyBytes).toString(),
|
||||
),
|
||||
);
|
||||
|
||||
if (response.text.isEmpty) {
|
||||
ErrorHandler.logError(
|
||||
e: Exception(
|
||||
"empty text in contextual definition response",
|
||||
),
|
||||
data: {
|
||||
"request": request.toJson(),
|
||||
"accessToken": accessToken,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
class ContextualDefinitionRequestModel {
|
||||
final String fullText;
|
||||
final String word;
|
||||
final String feedbackLang;
|
||||
final String fullTextLang;
|
||||
final String wordLang;
|
||||
|
||||
ContextualDefinitionRequestModel({
|
||||
required this.fullText,
|
||||
required this.word,
|
||||
required this.feedbackLang,
|
||||
required this.fullTextLang,
|
||||
required this.wordLang,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
ModelKey.fullText: fullText,
|
||||
ModelKey.word: word,
|
||||
ModelKey.lang: feedbackLang,
|
||||
ModelKey.fullTextLang: fullTextLang,
|
||||
ModelKey.wordLang: wordLang,
|
||||
};
|
||||
}
|
||||
|
||||
class ContextualDefinitionResponseModel {
|
||||
String text;
|
||||
|
||||
ContextualDefinitionResponseModel({required this.text});
|
||||
|
||||
factory ContextualDefinitionResponseModel.fromJson(
|
||||
Map<String, dynamic> json,
|
||||
) =>
|
||||
ContextualDefinitionResponseModel(text: json["response"]);
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import 'package:fluffychat/pangea/choreographer/controllers/span_data_controller
|
|||
import 'package:fluffychat/pangea/choreographer/models/igc_text_data_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/igc_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/igc_request_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/span_card.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_message_event.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
|
@ -48,8 +49,6 @@ class _IgnoredMatchCacheItem {
|
|||
class IgcController {
|
||||
Choreographer choreographer;
|
||||
IGCTextData? igcTextData;
|
||||
Object? igcError;
|
||||
Completer<IGCTextData> igcCompleter = Completer();
|
||||
late SpanDataController spanDataController;
|
||||
|
||||
// cache for IGC data and prev message
|
||||
|
|
@ -77,7 +76,7 @@ class IgcController {
|
|||
if (choreographer.currentText.isEmpty) return clear();
|
||||
debugPrint('getIGCTextData called with ${choreographer.currentText}');
|
||||
|
||||
final IGCRequestBody reqBody = IGCRequestBody(
|
||||
final IGCRequestModel reqBody = IGCRequestModel(
|
||||
fullText: choreographer.currentText,
|
||||
userId: choreographer.pangeaController.userController.userId!,
|
||||
userL1: choreographer.l1LangCode!,
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import 'package:fluffychat/pangea/choreographer/controllers/error_service.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/enums/edit_type.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../models/custom_input_translation_model.dart';
|
||||
import '../models/it_response_model.dart';
|
||||
import '../models/it_step.dart';
|
||||
import '../repo/custom_input_request_model.dart';
|
||||
import '../repo/interactive_translation_repo.dart';
|
||||
import '../repo/it_response_model.dart';
|
||||
import 'choreographer.dart';
|
||||
|
||||
class ITController {
|
||||
|
|
@ -23,7 +23,6 @@ class ITController {
|
|||
bool _isOpen = false;
|
||||
bool _willOpen = false;
|
||||
bool _isEditingSourceText = false;
|
||||
bool showChoiceFeedback = false;
|
||||
bool dismissed = false;
|
||||
|
||||
ITStartData? _itStartData;
|
||||
|
|
@ -41,7 +40,6 @@ class ITController {
|
|||
_willOpen = false;
|
||||
MatrixState.pAnyState.closeOverlay("it_feedback_card");
|
||||
|
||||
showChoiceFeedback = false;
|
||||
_isEditingSourceText = false;
|
||||
dismissed = false;
|
||||
|
||||
|
|
@ -309,19 +307,6 @@ class ITController {
|
|||
final itStep = ITStep(currentITStep!.continuances, chosen: chosenIndex);
|
||||
|
||||
completedITSteps.add(itStep);
|
||||
|
||||
showChoiceFeedback = true;
|
||||
|
||||
Future.delayed(
|
||||
const Duration(
|
||||
milliseconds: ChoreoConstants.millisecondsToDisplayFeedback,
|
||||
),
|
||||
() {
|
||||
showChoiceFeedback = false;
|
||||
choreographer.setState();
|
||||
},
|
||||
);
|
||||
|
||||
choreographer.onITChoiceSelect(itStep);
|
||||
choreographer.setState();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
||||
class ITFeedbackRequestModel {
|
||||
final String sourceText;
|
||||
final String currentText;
|
||||
final String bestContinuance;
|
||||
final String chosenContinuance;
|
||||
final String feedbackLang;
|
||||
final String sourceTextLang;
|
||||
final String targetLang;
|
||||
|
||||
ITFeedbackRequestModel({
|
||||
required this.sourceText,
|
||||
required this.currentText,
|
||||
required this.bestContinuance,
|
||||
required this.chosenContinuance,
|
||||
required this.feedbackLang,
|
||||
required this.sourceTextLang,
|
||||
required this.targetLang,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
ModelKey.sourceText: sourceText,
|
||||
ModelKey.currentText: currentText,
|
||||
ModelKey.bestContinuance: bestContinuance,
|
||||
ModelKey.chosenContinuance: chosenContinuance,
|
||||
ModelKey.feedbackLang: feedbackLang,
|
||||
ModelKey.srcLang: sourceTextLang,
|
||||
ModelKey.tgtLang: targetLang,
|
||||
};
|
||||
}
|
||||
|
||||
class ITFeedbackResponseModel {
|
||||
String text;
|
||||
|
||||
ITFeedbackResponseModel({required this.text});
|
||||
|
||||
factory ITFeedbackResponseModel.fromJson(
|
||||
Map<String, dynamic> json,
|
||||
) =>
|
||||
ITFeedbackResponseModel(text: json[ModelKey.text]);
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ import 'package:collection/collection.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/controllers/choreographer.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/span_data.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/span_data_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/utils/normalize_text.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/utils/text_normalization_util.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
||||
class _SpanDetailsCacheItem {
|
||||
|
|
@ -70,7 +70,8 @@ class SpanDataController {
|
|||
);
|
||||
|
||||
return correctChoice != null &&
|
||||
normalizeString(correctChoice) == normalizeString(errorSpan);
|
||||
TextNormalizationUtil.normalizeString(correctChoice) ==
|
||||
TextNormalizationUtil.normalizeString(errorSpan);
|
||||
}
|
||||
|
||||
Future<void> getSpanDetails(
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import '../../bot/utils/bot_style.dart';
|
||||
|
||||
enum UseType { wa, ta, ga, un }
|
||||
|
||||
extension UseTypeMethods on UseType {
|
||||
String get string => toString().split(".").last;
|
||||
|
||||
String tooltipString(BuildContext context) {
|
||||
final l10n = L10n.of(context);
|
||||
switch (this) {
|
||||
case UseType.ga:
|
||||
return l10n.gaTooltip;
|
||||
case UseType.ta:
|
||||
return l10n.taTooltip;
|
||||
case UseType.wa:
|
||||
return l10n.waTooltip;
|
||||
default:
|
||||
return l10n.unTooltip;
|
||||
}
|
||||
}
|
||||
|
||||
IconData get iconData {
|
||||
switch (this) {
|
||||
case UseType.ga:
|
||||
return Icons.spellcheck_outlined;
|
||||
case UseType.ta:
|
||||
return Icons.translate;
|
||||
case UseType.wa:
|
||||
return Icons.thumb_up;
|
||||
default:
|
||||
return Icons.question_mark_outlined;
|
||||
}
|
||||
}
|
||||
|
||||
Widget iconView(BuildContext context, Color color, [int size = 14]) =>
|
||||
Tooltip(
|
||||
message: tooltipString(context),
|
||||
child: Icon(
|
||||
iconData,
|
||||
color: color,
|
||||
size: size.toDouble(),
|
||||
),
|
||||
);
|
||||
|
||||
Widget iconButtonView(BuildContext context, Color color, [int size = 14]) =>
|
||||
Tooltip(
|
||||
message: tooltipString(context),
|
||||
child: Icon(
|
||||
iconData,
|
||||
color: color,
|
||||
size: size.toDouble(),
|
||||
),
|
||||
);
|
||||
|
||||
Widget textView(BuildContext context, [TextStyle? existingStyle]) => Tooltip(
|
||||
message: tooltipString(context),
|
||||
child: Text(
|
||||
string,
|
||||
style: BotStyle.text(
|
||||
context,
|
||||
existingStyle: existingStyle,
|
||||
italics: true,
|
||||
),
|
||||
textAlign: TextAlign.end,
|
||||
),
|
||||
);
|
||||
|
||||
static bool isDarkMode(BuildContext context) =>
|
||||
Theme.of(context).brightness == Brightness.dark;
|
||||
|
||||
Color color(BuildContext context) {
|
||||
switch (this) {
|
||||
case UseType.ga:
|
||||
return isDarkMode(context)
|
||||
? const Color.fromARGB(255, 157, 234, 172)
|
||||
: const Color.fromARGB(255, 31, 146, 54);
|
||||
case UseType.ta:
|
||||
return isDarkMode(context)
|
||||
? const Color.fromARGB(255, 169, 183, 237)
|
||||
: const Color.fromARGB(255, 38, 59, 141);
|
||||
case UseType.wa:
|
||||
return isDarkMode(context)
|
||||
? const Color.fromARGB(255, 212, 144, 216)
|
||||
: const Color.fromARGB(255, 163, 39, 169);
|
||||
default:
|
||||
return Theme.of(context).textTheme.bodyLarge!.color ?? Colors.blueGrey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -37,27 +37,4 @@ class ChoreoEvent {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// bool get hasAcceptedMatches =>
|
||||
// content?.steps.any(
|
||||
// (element) =>
|
||||
// element.acceptedOrIgnoredMatch?.status ==
|
||||
// PangeaMatchStatus.accepted,
|
||||
// ) ??
|
||||
// false;
|
||||
|
||||
// bool get hasIgnoredMatches =>
|
||||
// content?.steps.any(
|
||||
// (element) =>
|
||||
// element.acceptedOrIgnoredMatch?.status == PangeaMatchStatus.ignored,
|
||||
// ) ??
|
||||
// false;
|
||||
|
||||
// bool get includedIT =>
|
||||
// content?.steps.any((step) {
|
||||
// return step.acceptedOrIgnoredMatch?.status ==
|
||||
// PangeaMatchStatus.accepted &&
|
||||
// (step.acceptedOrIgnoredMatch?.isITStart ?? false);
|
||||
// }) ??
|
||||
// false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,172 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/constants/choreo_constants.dart';
|
||||
|
||||
class ITResponseModel {
|
||||
String fullTextTranslation;
|
||||
List<Continuance> continuances;
|
||||
List<Continuance>? goldContinuances;
|
||||
bool isFinal;
|
||||
String? translationId;
|
||||
int payloadId;
|
||||
|
||||
ITResponseModel({
|
||||
required this.fullTextTranslation,
|
||||
required this.continuances,
|
||||
required this.translationId,
|
||||
required this.goldContinuances,
|
||||
required this.isFinal,
|
||||
required this.payloadId,
|
||||
});
|
||||
|
||||
factory ITResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
//PTODO - is continuances a variable type? can we change that?
|
||||
if (json['continuances'].runtimeType == String) {
|
||||
debugPrint("continuances was string - ${json['continuances']}");
|
||||
json['continuances'] = [];
|
||||
json['finished'] = true;
|
||||
}
|
||||
|
||||
final List<Continuance> interimCont = (json['continuances'] as List)
|
||||
.mapIndexed((index, e) {
|
||||
e["index"] = index;
|
||||
return Continuance.fromJson(e);
|
||||
})
|
||||
.toList()
|
||||
.take(ChoreoConstants.numberOfITChoices)
|
||||
.toList()
|
||||
.cast<Continuance>()
|
||||
//can't do this on the backend because step translation can't filter them out
|
||||
.where((element) => element.inDictionary)
|
||||
.toList();
|
||||
|
||||
interimCont.shuffle();
|
||||
|
||||
return ITResponseModel(
|
||||
fullTextTranslation: json["full_text_translation"] ?? json["translation"],
|
||||
continuances: interimCont,
|
||||
translationId: json['translation_id'],
|
||||
payloadId: json['payload_id'] ?? 0,
|
||||
isFinal: json['finished'] ?? false,
|
||||
goldContinuances: json['gold_continuances'] != null
|
||||
? (json['gold_continuances'] as Iterable).map((e) {
|
||||
e["gold"] = true;
|
||||
return Continuance.fromJson(e);
|
||||
}).toList()
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['full_text_translation'] = fullTextTranslation;
|
||||
data['continuances'] = continuances.map((v) => v.toJson()).toList();
|
||||
if (translationId != null) {
|
||||
data['translation_id'] = translationId;
|
||||
}
|
||||
data['payload_id'] = payloadId;
|
||||
data["finished"] = isFinal;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Continuance {
|
||||
/// only saving this top set in a condensed json form
|
||||
double probability;
|
||||
int level;
|
||||
String text;
|
||||
// List<PangeaToken> tokens;
|
||||
|
||||
/// saving this in a full json form
|
||||
String description;
|
||||
int? indexSavedByServer;
|
||||
bool wasClicked;
|
||||
bool inDictionary;
|
||||
bool hasInfo;
|
||||
bool gold;
|
||||
|
||||
Continuance({
|
||||
required this.probability,
|
||||
required this.level,
|
||||
required this.text,
|
||||
required this.description,
|
||||
required this.indexSavedByServer,
|
||||
required this.wasClicked,
|
||||
required this.inDictionary,
|
||||
required this.hasInfo,
|
||||
required this.gold,
|
||||
// required this.tokens,
|
||||
});
|
||||
|
||||
factory Continuance.fromJson(Map<String, dynamic> json) {
|
||||
// final List<PangeaToken> tokensInternal = (json[ModelKey.tokens] != null)
|
||||
// ? (json[ModelKey.tokens] as Iterable)
|
||||
// .map<PangeaToken>(
|
||||
// (e) => PangeaToken.fromJson(e as Map<String, dynamic>),
|
||||
// )
|
||||
// .toList()
|
||||
// .cast<PangeaToken>()
|
||||
// : [];
|
||||
return Continuance(
|
||||
probability: json['probability'].toDouble(),
|
||||
level: json['level'],
|
||||
text: json['text'],
|
||||
description: json['description'] ?? "",
|
||||
indexSavedByServer: json["index"],
|
||||
inDictionary: json['in_dictionary'] ?? true,
|
||||
wasClicked: json['clkd'] ?? false,
|
||||
hasInfo: json['has_info'] ?? false,
|
||||
gold: json['gold'] ?? false,
|
||||
// tokens: tokensInternal,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson([bool condensed = false]) {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['probability'] = probability;
|
||||
data['level'] = level;
|
||||
data['text'] = text;
|
||||
data['clkd'] = wasClicked;
|
||||
// data[ModelKey.tokens] = tokens.map((e) => e.toJson()).toList();
|
||||
|
||||
if (!condensed) {
|
||||
data['description'] = description;
|
||||
data['in_dictionary'] = inDictionary;
|
||||
data['has_info'] = hasInfo;
|
||||
data["index"] = indexSavedByServer;
|
||||
data['gold'] = gold;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
Color? get color {
|
||||
if (!wasClicked) return null;
|
||||
switch (level) {
|
||||
case ChoreoConstants.levelThresholdForGreen:
|
||||
return ChoreoConstants.green;
|
||||
case ChoreoConstants.levelThresholdForYellow:
|
||||
return ChoreoConstants.yellow;
|
||||
case ChoreoConstants.levelThresholdForRed:
|
||||
return ChoreoConstants.red;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String? feedbackText(BuildContext context) {
|
||||
final L10n l10n = L10n.of(context);
|
||||
switch (level) {
|
||||
case ChoreoConstants.levelThresholdForGreen:
|
||||
return l10n.greenFeedback;
|
||||
case ChoreoConstants.levelThresholdForYellow:
|
||||
return l10n.yellowFeedback;
|
||||
case ChoreoConstants.levelThresholdForRed:
|
||||
return l10n.redFeedback;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import '../constants/choreo_constants.dart';
|
||||
import 'it_response_model.dart';
|
||||
|
||||
class ITStep {
|
||||
List<Continuance> continuances;
|
||||
|
|
@ -68,3 +68,101 @@ class ITStep {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Continuance {
|
||||
/// only saving this top set in a condensed json form
|
||||
double probability;
|
||||
int level;
|
||||
String text;
|
||||
// List<PangeaToken> tokens;
|
||||
|
||||
/// saving this in a full json form
|
||||
String description;
|
||||
int? indexSavedByServer;
|
||||
bool wasClicked;
|
||||
bool inDictionary;
|
||||
bool hasInfo;
|
||||
bool gold;
|
||||
|
||||
Continuance({
|
||||
required this.probability,
|
||||
required this.level,
|
||||
required this.text,
|
||||
required this.description,
|
||||
required this.indexSavedByServer,
|
||||
required this.wasClicked,
|
||||
required this.inDictionary,
|
||||
required this.hasInfo,
|
||||
required this.gold,
|
||||
// required this.tokens,
|
||||
});
|
||||
|
||||
factory Continuance.fromJson(Map<String, dynamic> json) {
|
||||
// final List<PangeaToken> tokensInternal = (json[ModelKey.tokens] != null)
|
||||
// ? (json[ModelKey.tokens] as Iterable)
|
||||
// .map<PangeaToken>(
|
||||
// (e) => PangeaToken.fromJson(e as Map<String, dynamic>),
|
||||
// )
|
||||
// .toList()
|
||||
// .cast<PangeaToken>()
|
||||
// : [];
|
||||
return Continuance(
|
||||
probability: json['probability'].toDouble(),
|
||||
level: json['level'],
|
||||
text: json['text'],
|
||||
description: json['description'] ?? "",
|
||||
indexSavedByServer: json["index"],
|
||||
inDictionary: json['in_dictionary'] ?? true,
|
||||
wasClicked: json['clkd'] ?? false,
|
||||
hasInfo: json['has_info'] ?? false,
|
||||
gold: json['gold'] ?? false,
|
||||
// tokens: tokensInternal,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson([bool condensed = false]) {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['probability'] = probability;
|
||||
data['level'] = level;
|
||||
data['text'] = text;
|
||||
data['clkd'] = wasClicked;
|
||||
// data[ModelKey.tokens] = tokens.map((e) => e.toJson()).toList();
|
||||
|
||||
if (!condensed) {
|
||||
data['description'] = description;
|
||||
data['in_dictionary'] = inDictionary;
|
||||
data['has_info'] = hasInfo;
|
||||
data["index"] = indexSavedByServer;
|
||||
data['gold'] = gold;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
Color? get color {
|
||||
if (!wasClicked) return null;
|
||||
switch (level) {
|
||||
case ChoreoConstants.levelThresholdForGreen:
|
||||
return ChoreoConstants.green;
|
||||
case ChoreoConstants.levelThresholdForYellow:
|
||||
return ChoreoConstants.yellow;
|
||||
case ChoreoConstants.levelThresholdForRed:
|
||||
return ChoreoConstants.red;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String? feedbackText(BuildContext context) {
|
||||
final L10n l10n = L10n.of(context);
|
||||
switch (level) {
|
||||
case ChoreoConstants.levelThresholdForGreen:
|
||||
return l10n.greenFeedback;
|
||||
case ChoreoConstants.levelThresholdForYellow:
|
||||
return l10n.yellowFeedback;
|
||||
case ChoreoConstants.levelThresholdForRed:
|
||||
return l10n.redFeedback;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,202 +0,0 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/word_data_card.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
||||
class WordData {
|
||||
final String word;
|
||||
final String fullText;
|
||||
final String? userL1;
|
||||
final String? userL2;
|
||||
// final List<LanguageSense> languageSenses;
|
||||
|
||||
final String targetPartOfSpeech;
|
||||
final String basePartOfSpeech;
|
||||
final String partOfSpeech;
|
||||
final String targetDefinition;
|
||||
final String baseDefinition;
|
||||
final String targetWord;
|
||||
final String baseWord;
|
||||
final String baseExampleSentence;
|
||||
final String targetExampleSentence;
|
||||
|
||||
WordData({
|
||||
// required this.languageSenses,
|
||||
required this.fullText,
|
||||
required this.word,
|
||||
required this.userL1,
|
||||
required this.userL2,
|
||||
required this.baseDefinition,
|
||||
required this.targetDefinition,
|
||||
required this.basePartOfSpeech,
|
||||
required this.targetPartOfSpeech,
|
||||
required this.partOfSpeech,
|
||||
required this.baseWord,
|
||||
required this.targetWord,
|
||||
required this.baseExampleSentence,
|
||||
required this.targetExampleSentence,
|
||||
});
|
||||
|
||||
// static const String _languageSensesKey = 'sense_responses';
|
||||
static const String _dataFullKey = 'data_full';
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
// _languageSensesKey: languageSenses.map((e) => e.toJson()).toList(),
|
||||
ModelKey.word: word,
|
||||
ModelKey.userL1: userL1,
|
||||
ModelKey.userL2: userL2,
|
||||
ModelKey.baseDefinition: baseDefinition,
|
||||
ModelKey.targetDefinition: targetDefinition,
|
||||
ModelKey.basePartOfSpeech: basePartOfSpeech,
|
||||
ModelKey.targetPartOfSpeech: targetPartOfSpeech,
|
||||
ModelKey.partOfSpeech: partOfSpeech,
|
||||
ModelKey.baseWord: baseWord,
|
||||
ModelKey.targetWord: targetWord,
|
||||
ModelKey.baseExampleSentence: baseExampleSentence,
|
||||
ModelKey.targetExampleSentence: targetExampleSentence,
|
||||
};
|
||||
|
||||
factory WordData.fromJson(
|
||||
Map<String, dynamic> json, {
|
||||
required String word,
|
||||
required String fullText,
|
||||
required String userL1,
|
||||
required String userL2,
|
||||
}) {
|
||||
try {
|
||||
return WordData(
|
||||
// languageSenses: (json[_languageSensesKey] as List<dynamic>)
|
||||
// .map<LanguageSense>(
|
||||
// (e) => LanguageSense.fromJson(e as Map<String, dynamic>),
|
||||
// )
|
||||
// .toList()
|
||||
// .cast<LanguageSense>(),
|
||||
baseDefinition: json[_dataFullKey][ModelKey.baseDefinition],
|
||||
targetDefinition: json[_dataFullKey][ModelKey.targetDefinition],
|
||||
basePartOfSpeech: json[_dataFullKey][ModelKey.basePartOfSpeech],
|
||||
targetPartOfSpeech: json[_dataFullKey][ModelKey.targetPartOfSpeech],
|
||||
partOfSpeech: json[_dataFullKey][ModelKey.partOfSpeech],
|
||||
baseWord: json[_dataFullKey][ModelKey.baseWord],
|
||||
targetWord: json[_dataFullKey][ModelKey.targetWord],
|
||||
baseExampleSentence: json[_dataFullKey][ModelKey.baseExampleSentence],
|
||||
targetExampleSentence: json[_dataFullKey]
|
||||
[ModelKey.targetExampleSentence],
|
||||
word: word,
|
||||
userL1: userL1,
|
||||
userL2: userL2,
|
||||
fullText: fullText,
|
||||
);
|
||||
} catch (err) {
|
||||
debugger(when: kDebugMode);
|
||||
return [] as WordData;
|
||||
}
|
||||
}
|
||||
|
||||
bool isMatch({
|
||||
required String w,
|
||||
required String f,
|
||||
required String? l1,
|
||||
required String? l2,
|
||||
}) =>
|
||||
word == w && userL1 == l1 && userL2 == l2 && fullText == f;
|
||||
|
||||
String? formattedPartOfSpeech(LanguageType languageType) {
|
||||
final String pos = languageType == LanguageType.base
|
||||
? basePartOfSpeech
|
||||
: targetPartOfSpeech;
|
||||
if (pos.isEmpty) return null;
|
||||
return pos[0].toUpperCase() + pos.substring(1);
|
||||
}
|
||||
|
||||
// List<LanguageSense> sensesForLanguage(String code) =>
|
||||
// languageSenses.where((langSense) => langSense.langCode == code).toList();
|
||||
}
|
||||
|
||||
// class LanguageSense {
|
||||
// List<Sense> senses;
|
||||
// String langCode;
|
||||
|
||||
// LanguageSense({
|
||||
// required this.senses,
|
||||
// required this.langCode,
|
||||
// });
|
||||
|
||||
// static const String _sensesKey = "senses";
|
||||
// static const String _langCodeKey = "lang_code";
|
||||
|
||||
// Map<String, dynamic> toJson() => {
|
||||
// _sensesKey: senses.map((e) => e.toJson()).toList(),
|
||||
// _langCodeKey: langCode,
|
||||
// };
|
||||
|
||||
// factory LanguageSense.fromJson(Map<String, dynamic> json) => LanguageSense(
|
||||
// senses: (json[_sensesKey] as List<dynamic>)
|
||||
// .map<Sense>(
|
||||
// (e) => Sense.fromJson(e as Map<String, dynamic>),
|
||||
// )
|
||||
// .toList()
|
||||
// .cast<Sense>(),
|
||||
// langCode: json[_langCodeKey],
|
||||
// );
|
||||
|
||||
// List<String> get partsOfSpeech =>
|
||||
// senses.map((sense) => sense.partOfSpeech).toSet().toList();
|
||||
|
||||
// List<String> definitionsForPartOfSpeech(String partOfSpeech) {
|
||||
// final List<String> definitions = [];
|
||||
// for (final Sense sense in senses) {
|
||||
// if (sense.partOfSpeech == partOfSpeech &&
|
||||
// sense.definition != null &&
|
||||
// sense.definition!.isNotEmpty) {
|
||||
// definitions.add(sense.definition!);
|
||||
// }
|
||||
// }
|
||||
// return definitions;
|
||||
// }
|
||||
|
||||
// // List<String> partOfSpeechSense(partOfSpeech) {
|
||||
// // return senses
|
||||
// // .where((sense) => sense.partOfSpeech == partOfSpeech)
|
||||
// // .map((sense) => sense.lemmas.join(', '))
|
||||
// // .toSet()
|
||||
// // .toList();
|
||||
// // }
|
||||
|
||||
// // Map<String, List<String>> get partOfSpeechSenses {
|
||||
// // final Map<String, List<String>> senses = {};
|
||||
// // for (final partOfSpeech in partsOfSpeech) {
|
||||
// // senses[partOfSpeech] = partOfSpeechSense(partOfSpeech);
|
||||
// // }
|
||||
// // return senses;
|
||||
// // }
|
||||
// }
|
||||
|
||||
// class Sense {
|
||||
// String partOfSpeech;
|
||||
// List<String> lemmas;
|
||||
// String? definition;
|
||||
|
||||
// Sense({
|
||||
// required this.partOfSpeech,
|
||||
// required this.lemmas,
|
||||
// required this.definition,
|
||||
// });
|
||||
|
||||
// static const String _posKey = "pos";
|
||||
// static const String _lemmasKey = "lemmas";
|
||||
// static const String _definitionKey = "definition";
|
||||
|
||||
// Map<String, dynamic> toJson() => {
|
||||
// _posKey: partOfSpeech,
|
||||
// _lemmasKey: lemmas.toString(),
|
||||
// _definitionKey: definition
|
||||
// };
|
||||
|
||||
// factory Sense.fromJson(Map<String, dynamic> json) => Sense(
|
||||
// partOfSpeech: json[_posKey],
|
||||
// lemmas: (json[_lemmasKey] as List<dynamic>).cast<String>(),
|
||||
// definition: json[_definitionKey],
|
||||
// );
|
||||
// }
|
||||
109
lib/pangea/choreographer/repo/contextual_definition_repo.dart
Normal file
109
lib/pangea/choreographer/repo/contextual_definition_repo.dart
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:async/async.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/repo/contextual_definition_request_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/contextual_definition_response_model.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import '../../common/network/requests.dart';
|
||||
import '../../common/network/urls.dart';
|
||||
|
||||
class ContextualDefinitionRepo {
|
||||
static final Map<String, Future<ContextualDefinitionResponseModel>> _cache =
|
||||
{};
|
||||
|
||||
static Future<Result<ContextualDefinitionResponseModel>> get(
|
||||
String accessToken,
|
||||
ContextualDefinitionRequestModel request,
|
||||
) async {
|
||||
final cached = _getCached(request);
|
||||
if (cached != null) {
|
||||
try {
|
||||
return Result.value(await cached);
|
||||
} catch (e, s) {
|
||||
_cache.remove(request.hashCode.toString());
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
s: s,
|
||||
data: request.toJson(),
|
||||
);
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
final future = _fetch(accessToken, request);
|
||||
_setCached(request, future);
|
||||
return _getResult(request, future);
|
||||
}
|
||||
|
||||
static Future<ContextualDefinitionResponseModel> _fetch(
|
||||
String accessToken,
|
||||
ContextualDefinitionRequestModel request,
|
||||
) async {
|
||||
final Requests req = Requests(
|
||||
choreoApiKey: Environment.choreoApiKey,
|
||||
accessToken: accessToken,
|
||||
);
|
||||
|
||||
final Response res = await req.post(
|
||||
url: PApiUrls.contextualDefinition,
|
||||
body: request.toJson(),
|
||||
);
|
||||
|
||||
if (res.statusCode != 200) {
|
||||
throw res;
|
||||
}
|
||||
|
||||
final ContextualDefinitionResponseModel response =
|
||||
ContextualDefinitionResponseModel.fromJson(
|
||||
jsonDecode(
|
||||
utf8.decode(res.bodyBytes).toString(),
|
||||
),
|
||||
);
|
||||
|
||||
if (response.text.isEmpty) {
|
||||
ErrorHandler.logError(
|
||||
e: Exception(
|
||||
"empty text in contextual definition response",
|
||||
),
|
||||
data: {
|
||||
"request": request.toJson(),
|
||||
"accessToken": accessToken,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<Result<ContextualDefinitionResponseModel>> _getResult(
|
||||
ContextualDefinitionRequestModel request,
|
||||
Future<ContextualDefinitionResponseModel> future,
|
||||
) async {
|
||||
try {
|
||||
final res = await future;
|
||||
return Result.value(res);
|
||||
} catch (e, s) {
|
||||
_cache.remove(request.hashCode.toString());
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
s: s,
|
||||
data: request.toJson(),
|
||||
);
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<ContextualDefinitionResponseModel>? _getCached(
|
||||
ContextualDefinitionRequestModel request,
|
||||
) =>
|
||||
_cache[request.hashCode.toString()];
|
||||
|
||||
static void _setCached(
|
||||
ContextualDefinitionRequestModel request,
|
||||
Future<ContextualDefinitionResponseModel> response,
|
||||
) =>
|
||||
_cache[request.hashCode.toString()] = response;
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
||||
class ContextualDefinitionRequestModel {
|
||||
final String fullText;
|
||||
final String word;
|
||||
final String feedbackLang;
|
||||
final String fullTextLang;
|
||||
final String wordLang;
|
||||
|
||||
ContextualDefinitionRequestModel({
|
||||
required this.fullText,
|
||||
required this.word,
|
||||
required this.feedbackLang,
|
||||
required this.fullTextLang,
|
||||
required this.wordLang,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
ModelKey.fullText: fullText,
|
||||
ModelKey.word: word,
|
||||
ModelKey.lang: feedbackLang,
|
||||
ModelKey.fullTextLang: fullTextLang,
|
||||
ModelKey.wordLang: wordLang,
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ContextualDefinitionRequestModel &&
|
||||
runtimeType == other.runtimeType &&
|
||||
fullText == other.fullText &&
|
||||
word == other.word &&
|
||||
feedbackLang == other.feedbackLang &&
|
||||
fullTextLang == other.fullTextLang &&
|
||||
wordLang == other.wordLang;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
fullText.hashCode ^
|
||||
word.hashCode ^
|
||||
feedbackLang.hashCode ^
|
||||
fullTextLang.hashCode ^
|
||||
wordLang.hashCode;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class ContextualDefinitionResponseModel {
|
||||
String text;
|
||||
|
||||
ContextualDefinitionResponseModel({required this.text});
|
||||
|
||||
factory ContextualDefinitionResponseModel.fromJson(
|
||||
Map<String, dynamic> json,
|
||||
) =>
|
||||
ContextualDefinitionResponseModel(text: json["response"]);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:fluffychat/pangea/choreographer/models/it_response_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/it_response_model.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
||||
class CustomInputRequestModel {
|
||||
|
|
@ -5,8 +5,9 @@ import 'dart:convert';
|
|||
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_request_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_response_model.dart';
|
||||
import '../../common/config/environment.dart';
|
||||
import '../../common/constants/model_keys.dart';
|
||||
import '../../common/network/requests.dart';
|
||||
import '../../common/network/urls.dart';
|
||||
|
||||
|
|
@ -87,95 +88,3 @@ class FullTextTranslationRepo {
|
|||
return responseModel;
|
||||
}
|
||||
}
|
||||
|
||||
class FullTextTranslationRequestModel {
|
||||
String text;
|
||||
String? srcLang;
|
||||
String tgtLang;
|
||||
String userL1;
|
||||
String userL2;
|
||||
bool? deepL;
|
||||
int? offset;
|
||||
int? length;
|
||||
|
||||
FullTextTranslationRequestModel({
|
||||
required this.text,
|
||||
this.srcLang,
|
||||
required this.tgtLang,
|
||||
required this.userL2,
|
||||
required this.userL1,
|
||||
this.deepL = false,
|
||||
this.offset,
|
||||
this.length,
|
||||
});
|
||||
|
||||
//PTODO throw error for null
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"text": text,
|
||||
ModelKey.srcLang: srcLang,
|
||||
ModelKey.tgtLang: tgtLang,
|
||||
ModelKey.userL2: userL2,
|
||||
ModelKey.userL1: userL1,
|
||||
ModelKey.deepL: deepL,
|
||||
ModelKey.offset: offset,
|
||||
ModelKey.length: length,
|
||||
};
|
||||
|
||||
// override equals and hashcode
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is FullTextTranslationRequestModel &&
|
||||
other.text == text &&
|
||||
other.srcLang == srcLang &&
|
||||
other.tgtLang == tgtLang &&
|
||||
other.userL2 == userL2 &&
|
||||
other.userL1 == userL1 &&
|
||||
other.deepL == deepL &&
|
||||
other.offset == offset &&
|
||||
other.length == length;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
text.hashCode ^
|
||||
srcLang.hashCode ^
|
||||
tgtLang.hashCode ^
|
||||
userL2.hashCode ^
|
||||
userL1.hashCode ^
|
||||
deepL.hashCode ^
|
||||
offset.hashCode ^
|
||||
length.hashCode;
|
||||
}
|
||||
|
||||
class FullTextTranslationResponseModel {
|
||||
List<String> translations;
|
||||
|
||||
/// detected source
|
||||
/// PTODO -
|
||||
String source;
|
||||
String? deepL;
|
||||
|
||||
FullTextTranslationResponseModel({
|
||||
required this.translations,
|
||||
required this.source,
|
||||
required this.deepL,
|
||||
});
|
||||
|
||||
factory FullTextTranslationResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
return FullTextTranslationResponseModel(
|
||||
translations: (json["translations"] as Iterable)
|
||||
.map<String>(
|
||||
(e) => e,
|
||||
)
|
||||
.toList()
|
||||
.cast<String>(),
|
||||
source: json[ModelKey.srcLang],
|
||||
deepL: json['deepl_res'],
|
||||
);
|
||||
}
|
||||
|
||||
String get bestTranslation => deepL ?? translations.first;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
||||
class FullTextTranslationRequestModel {
|
||||
String text;
|
||||
String? srcLang;
|
||||
String tgtLang;
|
||||
String userL1;
|
||||
String userL2;
|
||||
bool? deepL;
|
||||
int? offset;
|
||||
int? length;
|
||||
|
||||
FullTextTranslationRequestModel({
|
||||
required this.text,
|
||||
this.srcLang,
|
||||
required this.tgtLang,
|
||||
required this.userL2,
|
||||
required this.userL1,
|
||||
this.deepL = false,
|
||||
this.offset,
|
||||
this.length,
|
||||
});
|
||||
|
||||
//PTODO throw error for null
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"text": text,
|
||||
ModelKey.srcLang: srcLang,
|
||||
ModelKey.tgtLang: tgtLang,
|
||||
ModelKey.userL2: userL2,
|
||||
ModelKey.userL1: userL1,
|
||||
ModelKey.deepL: deepL,
|
||||
ModelKey.offset: offset,
|
||||
ModelKey.length: length,
|
||||
};
|
||||
|
||||
// override equals and hashcode
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other is FullTextTranslationRequestModel &&
|
||||
other.text == text &&
|
||||
other.srcLang == srcLang &&
|
||||
other.tgtLang == tgtLang &&
|
||||
other.userL2 == userL2 &&
|
||||
other.userL1 == userL1 &&
|
||||
other.deepL == deepL &&
|
||||
other.offset == offset &&
|
||||
other.length == length;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
text.hashCode ^
|
||||
srcLang.hashCode ^
|
||||
tgtLang.hashCode ^
|
||||
userL2.hashCode ^
|
||||
userL1.hashCode ^
|
||||
deepL.hashCode ^
|
||||
offset.hashCode ^
|
||||
length.hashCode;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
||||
class FullTextTranslationResponseModel {
|
||||
List<String> translations;
|
||||
|
||||
/// detected source
|
||||
/// PTODO -
|
||||
String source;
|
||||
String? deepL;
|
||||
|
||||
FullTextTranslationResponseModel({
|
||||
required this.translations,
|
||||
required this.source,
|
||||
required this.deepL,
|
||||
});
|
||||
|
||||
factory FullTextTranslationResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
return FullTextTranslationResponseModel(
|
||||
translations: (json["translations"] as Iterable)
|
||||
.map<String>(
|
||||
(e) => e,
|
||||
)
|
||||
.toList()
|
||||
.cast<String>(),
|
||||
source: json[ModelKey.srcLang],
|
||||
deepL: json['deepl_res'],
|
||||
);
|
||||
}
|
||||
|
||||
String get bestTranslation => deepL ?? translations.first;
|
||||
}
|
||||
|
|
@ -2,10 +2,8 @@ import 'dart:convert';
|
|||
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/models/pangea_match_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/span_data_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/igc_request_model.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import '../../common/constants/model_keys.dart';
|
||||
import '../../common/network/requests.dart';
|
||||
import '../../common/network/urls.dart';
|
||||
import '../models/igc_text_data_model.dart';
|
||||
|
|
@ -13,7 +11,7 @@ import '../models/igc_text_data_model.dart';
|
|||
class IgcRepo {
|
||||
static Future<IGCTextData> getIGC(
|
||||
String? accessToken, {
|
||||
required IGCRequestBody igcRequest,
|
||||
required IGCRequestModel igcRequest,
|
||||
}) async {
|
||||
final Requests req = Requests(
|
||||
accessToken: accessToken,
|
||||
|
|
@ -31,130 +29,4 @@ class IgcRepo {
|
|||
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future<IGCTextData> getMockData() async {
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
|
||||
final IGCTextData igcTextData = IGCTextData(
|
||||
matches: [
|
||||
PangeaMatch(
|
||||
match: spanDataRepomockSpan,
|
||||
status: PangeaMatchStatus.open,
|
||||
),
|
||||
],
|
||||
originalInput: "This be a sample text",
|
||||
fullTextCorrection: "This is a sample text",
|
||||
userL1: "es",
|
||||
userL2: "en",
|
||||
enableIT: true,
|
||||
enableIGC: true,
|
||||
);
|
||||
|
||||
return igcTextData;
|
||||
}
|
||||
}
|
||||
|
||||
/// Previous text/audio message sent in chat
|
||||
/// Contain message content, sender, and timestamp
|
||||
class PreviousMessage {
|
||||
String content;
|
||||
String sender;
|
||||
DateTime timestamp;
|
||||
|
||||
PreviousMessage({
|
||||
required this.content,
|
||||
required this.sender,
|
||||
required this.timestamp,
|
||||
});
|
||||
|
||||
factory PreviousMessage.fromJson(Map<String, dynamic> json) =>
|
||||
PreviousMessage(
|
||||
content: json[ModelKey.prevContent] ?? "",
|
||||
sender: json[ModelKey.prevSender] ?? "",
|
||||
timestamp: json[ModelKey.prevTimestamp] == null
|
||||
? DateTime.now()
|
||||
: DateTime.parse(json[ModelKey.prevTimestamp]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
ModelKey.prevContent: content,
|
||||
ModelKey.prevSender: sender,
|
||||
ModelKey.prevTimestamp: timestamp.toIso8601String(),
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
if (other is! PreviousMessage) return false;
|
||||
|
||||
return content == other.content &&
|
||||
sender == other.sender &&
|
||||
timestamp == other.timestamp;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(
|
||||
content,
|
||||
sender,
|
||||
timestamp,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class IGCRequestBody {
|
||||
String fullText;
|
||||
String userL1;
|
||||
String userL2;
|
||||
bool enableIT;
|
||||
bool enableIGC;
|
||||
String userId;
|
||||
List<PreviousMessage> prevMessages;
|
||||
|
||||
IGCRequestBody({
|
||||
required this.fullText,
|
||||
required this.userL1,
|
||||
required this.userL2,
|
||||
required this.enableIGC,
|
||||
required this.enableIT,
|
||||
required this.userId,
|
||||
required this.prevMessages,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
ModelKey.fullText: fullText,
|
||||
ModelKey.userL1: userL1,
|
||||
ModelKey.userL2: userL2,
|
||||
"enable_it": enableIT,
|
||||
"enable_igc": enableIGC,
|
||||
ModelKey.userId: userId,
|
||||
ModelKey.prevMessages:
|
||||
jsonEncode(prevMessages.map((x) => x.toJson()).toList()),
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
if (other is! IGCRequestBody) return false;
|
||||
|
||||
return fullText.trim() == other.fullText.trim() &&
|
||||
fullText == other.fullText &&
|
||||
userL1 == other.userL1 &&
|
||||
userL2 == other.userL2 &&
|
||||
enableIT == other.enableIT &&
|
||||
userId == other.userId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
fullText.trim(),
|
||||
userL1,
|
||||
userL2,
|
||||
enableIT,
|
||||
enableIGC,
|
||||
userId,
|
||||
Object.hashAll(prevMessages),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
108
lib/pangea/choreographer/repo/igc_request_model.dart
Normal file
108
lib/pangea/choreographer/repo/igc_request_model.dart
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
|
||||
class IGCRequestModel {
|
||||
String fullText;
|
||||
String userL1;
|
||||
String userL2;
|
||||
bool enableIT;
|
||||
bool enableIGC;
|
||||
String userId;
|
||||
List<PreviousMessage> prevMessages;
|
||||
|
||||
IGCRequestModel({
|
||||
required this.fullText,
|
||||
required this.userL1,
|
||||
required this.userL2,
|
||||
required this.enableIGC,
|
||||
required this.enableIT,
|
||||
required this.userId,
|
||||
required this.prevMessages,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
ModelKey.fullText: fullText,
|
||||
ModelKey.userL1: userL1,
|
||||
ModelKey.userL2: userL2,
|
||||
"enable_it": enableIT,
|
||||
"enable_igc": enableIGC,
|
||||
ModelKey.userId: userId,
|
||||
ModelKey.prevMessages:
|
||||
jsonEncode(prevMessages.map((x) => x.toJson()).toList()),
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
if (other is! IGCRequestModel) return false;
|
||||
|
||||
return fullText.trim() == other.fullText.trim() &&
|
||||
fullText == other.fullText &&
|
||||
userL1 == other.userL1 &&
|
||||
userL2 == other.userL2 &&
|
||||
enableIT == other.enableIT &&
|
||||
userId == other.userId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
fullText.trim(),
|
||||
userL1,
|
||||
userL2,
|
||||
enableIT,
|
||||
enableIGC,
|
||||
userId,
|
||||
Object.hashAll(prevMessages),
|
||||
);
|
||||
}
|
||||
|
||||
/// Previous text/audio message sent in chat
|
||||
/// Contain message content, sender, and timestamp
|
||||
class PreviousMessage {
|
||||
String content;
|
||||
String sender;
|
||||
DateTime timestamp;
|
||||
|
||||
PreviousMessage({
|
||||
required this.content,
|
||||
required this.sender,
|
||||
required this.timestamp,
|
||||
});
|
||||
|
||||
factory PreviousMessage.fromJson(Map<String, dynamic> json) =>
|
||||
PreviousMessage(
|
||||
content: json[ModelKey.prevContent] ?? "",
|
||||
sender: json[ModelKey.prevSender] ?? "",
|
||||
timestamp: json[ModelKey.prevTimestamp] == null
|
||||
? DateTime.now()
|
||||
: DateTime.parse(json[ModelKey.prevTimestamp]),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
ModelKey.prevContent: content,
|
||||
ModelKey.prevSender: sender,
|
||||
ModelKey.prevTimestamp: timestamp.toIso8601String(),
|
||||
};
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
if (other is! PreviousMessage) return false;
|
||||
|
||||
return content == other.content &&
|
||||
sender == other.sender &&
|
||||
timestamp == other.timestamp;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return Object.hash(
|
||||
content,
|
||||
sender,
|
||||
timestamp,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,8 +6,8 @@ import 'package:fluffychat/pangea/common/config/environment.dart';
|
|||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../../common/network/requests.dart';
|
||||
import '../../common/network/urls.dart';
|
||||
import '../models/custom_input_translation_model.dart';
|
||||
import '../models/it_response_model.dart';
|
||||
import 'custom_input_request_model.dart';
|
||||
import 'it_response_model.dart';
|
||||
|
||||
class ITRepo {
|
||||
static Future<ITResponseModel> customInputTranslate(
|
||||
|
|
@ -24,20 +24,4 @@ class ITRepo {
|
|||
|
||||
return ITResponseModel.fromJson(json);
|
||||
}
|
||||
|
||||
// static Future<ITResponseModel> systemChoiceTranslate(
|
||||
// SystemChoiceRequestModel subseqText,
|
||||
// ) async {
|
||||
// final Requests req = Requests(
|
||||
// choreoApiKey: Environment.choreoApiKey,
|
||||
// accessToken: MatrixState.pangeaController.userController.accessToken,
|
||||
// );
|
||||
|
||||
// final Response res =
|
||||
// await req.post(url: PApiUrls.subseqStep, body: subseqText.toJson());
|
||||
|
||||
// final decodedBody = jsonDecode(utf8.decode(res.bodyBytes).toString());
|
||||
|
||||
// return ITResponseModel.fromJson(decodedBody);
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
74
lib/pangea/choreographer/repo/it_response_model.dart
Normal file
74
lib/pangea/choreographer/repo/it_response_model.dart
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/constants/choreo_constants.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/it_step.dart';
|
||||
|
||||
class ITResponseModel {
|
||||
String fullTextTranslation;
|
||||
List<Continuance> continuances;
|
||||
List<Continuance>? goldContinuances;
|
||||
bool isFinal;
|
||||
String? translationId;
|
||||
int payloadId;
|
||||
|
||||
ITResponseModel({
|
||||
required this.fullTextTranslation,
|
||||
required this.continuances,
|
||||
required this.translationId,
|
||||
required this.goldContinuances,
|
||||
required this.isFinal,
|
||||
required this.payloadId,
|
||||
});
|
||||
|
||||
factory ITResponseModel.fromJson(Map<String, dynamic> json) {
|
||||
//PTODO - is continuances a variable type? can we change that?
|
||||
if (json['continuances'].runtimeType == String) {
|
||||
debugPrint("continuances was string - ${json['continuances']}");
|
||||
json['continuances'] = [];
|
||||
json['finished'] = true;
|
||||
}
|
||||
|
||||
final List<Continuance> interimCont = (json['continuances'] as List)
|
||||
.mapIndexed((index, e) {
|
||||
e["index"] = index;
|
||||
return Continuance.fromJson(e);
|
||||
})
|
||||
.toList()
|
||||
.take(ChoreoConstants.numberOfITChoices)
|
||||
.toList()
|
||||
.cast<Continuance>()
|
||||
//can't do this on the backend because step translation can't filter them out
|
||||
.where((element) => element.inDictionary)
|
||||
.toList();
|
||||
|
||||
interimCont.shuffle();
|
||||
|
||||
return ITResponseModel(
|
||||
fullTextTranslation: json["full_text_translation"] ?? json["translation"],
|
||||
continuances: interimCont,
|
||||
translationId: json['translation_id'],
|
||||
payloadId: json['payload_id'] ?? 0,
|
||||
isFinal: json['finished'] ?? false,
|
||||
goldContinuances: json['gold_continuances'] != null
|
||||
? (json['gold_continuances'] as Iterable).map((e) {
|
||||
e["gold"] = true;
|
||||
return Continuance.fromJson(e);
|
||||
}).toList()
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['full_text_translation'] = fullTextTranslation;
|
||||
data['continuances'] = continuances.map((v) => v.toJson()).toList();
|
||||
if (translationId != null) {
|
||||
data['translation_id'] = translationId;
|
||||
}
|
||||
data['payload_id'] = payloadId;
|
||||
data["finished"] = isFinal;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/models/language_detection_model.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/network/requests.dart';
|
||||
import 'package:fluffychat/pangea/common/network/urls.dart';
|
||||
|
||||
class LanguageDetectionRepo {
|
||||
static Future<LanguageDetectionResponse> get(
|
||||
String? accessToken, {
|
||||
required LanguageDetectionRequest request,
|
||||
}) async {
|
||||
final Requests req = Requests(
|
||||
accessToken: accessToken,
|
||||
choreoApiKey: Environment.choreoApiKey,
|
||||
);
|
||||
final Response res = await req.post(
|
||||
url: PApiUrls.languageDetection,
|
||||
body: request.toJson(),
|
||||
);
|
||||
|
||||
final Map<String, dynamic> json =
|
||||
jsonDecode(utf8.decode(res.bodyBytes).toString());
|
||||
|
||||
final LanguageDetectionResponse response =
|
||||
LanguageDetectionResponse.fromJson(json);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
class LanguageDetectionRequest {
|
||||
final String text;
|
||||
final String? senderl1;
|
||||
final String? senderl2;
|
||||
|
||||
LanguageDetectionRequest({
|
||||
required this.text,
|
||||
this.senderl1,
|
||||
this.senderl2,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'full_text': text,
|
||||
'sender_l1': senderl1,
|
||||
'sender_l2': senderl2,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class LanguageDetectionResponse {
|
||||
List<LanguageDetection> detections;
|
||||
String fullText;
|
||||
|
||||
LanguageDetectionResponse({
|
||||
required this.detections,
|
||||
required this.fullText,
|
||||
});
|
||||
|
||||
factory LanguageDetectionResponse.fromJson(Map<String, dynamic> json) {
|
||||
return LanguageDetectionResponse(
|
||||
detections: List<LanguageDetection>.from(
|
||||
(json['detections'] as Iterable).map(
|
||||
(e) => LanguageDetection.fromJson(e),
|
||||
),
|
||||
),
|
||||
fullText: json['full_text'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'detections': detections.map((e) => e.toJson()).toList(),
|
||||
'full_text': fullText,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -3,8 +3,6 @@ import 'dart:convert';
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/enums/span_choice_type.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/enums/span_data_type.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/span_data.dart';
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import '../../common/constants/model_keys.dart';
|
||||
|
|
@ -32,16 +30,6 @@ class SpanDataRepo {
|
|||
}
|
||||
}
|
||||
|
||||
// Future<SpanDetailsRepoReqAndRes> getMock(SpanDetailsRepoReqAndRes req) async {
|
||||
// await Future.delayed(const Duration(seconds: 2));
|
||||
// if (req.span.choices != null &&
|
||||
// req.span.choices!.any((element) => element.selected)) {
|
||||
// return req..span = mockReponseWithHintOne.span;
|
||||
// } else {
|
||||
// return req..span = mockReponseWithChoices.span;
|
||||
// }
|
||||
// }
|
||||
|
||||
class SpanDetailsRepoReqAndRes {
|
||||
String userL1;
|
||||
String userL2;
|
||||
|
|
@ -113,40 +101,3 @@ class SpanDetailsRepoReqAndRes {
|
|||
]);
|
||||
}
|
||||
}
|
||||
|
||||
final spanDataRepomockSpan = SpanData(
|
||||
offset: 5,
|
||||
length: 2,
|
||||
fullText: "This be a sample text",
|
||||
type: SpanDataType(typeName: SpanDataTypeEnum.correction),
|
||||
choices: [SpanChoice(value: "is", type: SpanChoiceType.bestCorrection)],
|
||||
message: null,
|
||||
rule: null,
|
||||
shortMessage: null,
|
||||
);
|
||||
|
||||
//json mock request
|
||||
final mockRequest = SpanDetailsRepoReqAndRes(
|
||||
userL1: "es",
|
||||
userL2: "en",
|
||||
enableIGC: true,
|
||||
enableIT: true,
|
||||
span: spanDataRepomockSpan,
|
||||
);
|
||||
|
||||
SpanDetailsRepoReqAndRes get mockReponseWithChoices {
|
||||
final SpanDetailsRepoReqAndRes res = mockRequest;
|
||||
res.span.choices = [
|
||||
SpanChoice(value: "is", type: SpanChoiceType.bestCorrection),
|
||||
SpanChoice(value: "are", type: SpanChoiceType.distractor),
|
||||
SpanChoice(value: "was", type: SpanChoiceType.distractor),
|
||||
];
|
||||
return res;
|
||||
}
|
||||
|
||||
// SpanDetailsRepoReqAndRes get mockReponseWithHintOne {
|
||||
// final SpanDetailsRepoReqAndRes res = mockReponseWithChoices;
|
||||
// res.span.choices![1].selected = true;
|
||||
// res.span.message = "Conjugation error";
|
||||
// return res;
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
import '../../common/constants/model_keys.dart';
|
||||
|
||||
class SystemChoiceRequestModel {
|
||||
String translationId;
|
||||
int? nextWordIndex;
|
||||
String? customInput;
|
||||
String userId;
|
||||
String roomId;
|
||||
String targetLangCode;
|
||||
String sourceLangCode;
|
||||
String? classId;
|
||||
|
||||
SystemChoiceRequestModel({
|
||||
required this.translationId,
|
||||
this.nextWordIndex,
|
||||
this.customInput,
|
||||
required this.userId,
|
||||
required this.roomId,
|
||||
required this.targetLangCode,
|
||||
required this.sourceLangCode,
|
||||
this.classId,
|
||||
});
|
||||
|
||||
toJson() => {
|
||||
'translation_id': translationId,
|
||||
'next_word_index': nextWordIndex,
|
||||
'custom_input': customInput,
|
||||
'user_id': userId,
|
||||
'room_id': roomId,
|
||||
ModelKey.tgtLang: targetLangCode,
|
||||
ModelKey.srcLang: sourceLangCode,
|
||||
'class_id': classId,
|
||||
};
|
||||
|
||||
factory SystemChoiceRequestModel.fromJson(json) => SystemChoiceRequestModel(
|
||||
translationId: json['translation_id'],
|
||||
nextWordIndex: json['next_word_index'],
|
||||
customInput: json['custom_input'],
|
||||
userId: json['user_id'],
|
||||
roomId: json['room_id'],
|
||||
targetLangCode: json[ModelKey.tgtLang],
|
||||
sourceLangCode: json[ModelKey.srcLang],
|
||||
classId: json['class_id'],
|
||||
);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/enums/edit_type.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/pangea_text_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/utils/pangea_text_controller.dart';
|
||||
|
||||
class InputPasteListener {
|
||||
final PangeaTextController controller;
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
import 'package:diacritic/diacritic.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
||||
String normalizeString(String input) {
|
||||
try {
|
||||
// Step 1: Remove diacritics (accents)
|
||||
String normalized = removeDiacritics(input);
|
||||
normalized = normalized.replaceAll(RegExp(r'[^\x00-\x7F]'), '');
|
||||
|
||||
// Step 2: Remove punctuation
|
||||
normalized = normalized.replaceAll(RegExp(r'[^\w\s]'), '');
|
||||
|
||||
// Step 3: Convert to lowercase
|
||||
normalized = normalized.toLowerCase();
|
||||
|
||||
// Step 4: Trim and normalize whitespace
|
||||
normalized = normalized.replaceAll(RegExp(r'\s+'), ' ').trim();
|
||||
|
||||
return normalized.isEmpty ? input : normalized;
|
||||
} catch (e, s) {
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
s: s,
|
||||
data: {'input': input},
|
||||
);
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,9 +10,9 @@ import 'package:fluffychat/pangea/choreographer/widgets/igc/paywall_card.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/widgets/igc/span_card.dart';
|
||||
import 'package:fluffychat/pangea/subscription/controllers/subscription_controller.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../../../common/utils/overlay.dart';
|
||||
import '../../controllers/choreographer.dart';
|
||||
import '../../enums/edit_type.dart';
|
||||
import '../../common/utils/overlay.dart';
|
||||
import '../controllers/choreographer.dart';
|
||||
import '../enums/edit_type.dart';
|
||||
|
||||
class PangeaTextController extends TextEditingController {
|
||||
Choreographer choreographer;
|
||||
31
lib/pangea/choreographer/utils/text_normalization_util.dart
Normal file
31
lib/pangea/choreographer/utils/text_normalization_util.dart
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import 'package:diacritic/diacritic.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
||||
class TextNormalizationUtil {
|
||||
static String normalizeString(String input) {
|
||||
try {
|
||||
// Step 1: Remove diacritics (accents)
|
||||
String normalized = removeDiacritics(input);
|
||||
normalized = normalized.replaceAll(RegExp(r'[^\x00-\x7F]'), '');
|
||||
|
||||
// Step 2: Remove punctuation
|
||||
normalized = normalized.replaceAll(RegExp(r'[^\w\s]'), '');
|
||||
|
||||
// Step 3: Convert to lowercase
|
||||
normalized = normalized.toLowerCase();
|
||||
|
||||
// Step 4: Trim and normalize whitespace
|
||||
normalized = normalized.replaceAll(RegExp(r'\s+'), ' ').trim();
|
||||
|
||||
return normalized.isEmpty ? input : normalized;
|
||||
} catch (e, s) {
|
||||
ErrorHandler.logError(
|
||||
e: e,
|
||||
s: s,
|
||||
data: {'input': input},
|
||||
);
|
||||
return input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
|
|
@ -9,16 +6,15 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/bot/utils/bot_style.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/contextual_definition_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/contextual_definition_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/contextual_definition_request_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/contextual_definition_response_model.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/firebase_analytics.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/constants/language_constants.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/models/language_model.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/widgets/toolbar_content_loading_indicator.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../../../learning_settings/widgets/flag.dart';
|
||||
import '../../models/word_data_model.dart';
|
||||
import 'card_error_widget.dart';
|
||||
|
||||
class WordDataCard extends StatefulWidget {
|
||||
|
|
@ -80,40 +76,33 @@ class WordDataCardController extends State<WordDataCard> {
|
|||
}
|
||||
|
||||
Future<void> getContextualDefinition() async {
|
||||
ContextualDefinitionRequestModel? req;
|
||||
try {
|
||||
req = ContextualDefinitionRequestModel(
|
||||
fullText: widget.fullText,
|
||||
word: widget.word,
|
||||
feedbackLang: activeL1?.langCode ?? LanguageKeys.defaultLanguage,
|
||||
fullTextLang: widget.fullTextLang,
|
||||
wordLang: widget.wordLang,
|
||||
);
|
||||
if (!mounted) return;
|
||||
final ContextualDefinitionRequestModel req =
|
||||
ContextualDefinitionRequestModel(
|
||||
fullText: widget.fullText,
|
||||
word: widget.word,
|
||||
feedbackLang: activeL1?.langCode ?? LanguageKeys.defaultLanguage,
|
||||
fullTextLang: widget.fullTextLang,
|
||||
wordLang: widget.wordLang,
|
||||
);
|
||||
if (!mounted) return;
|
||||
|
||||
setState(() {
|
||||
contextualDefinitionRes = null;
|
||||
definitionError = null;
|
||||
isLoadingContextualDefinition = true;
|
||||
});
|
||||
setState(() {
|
||||
contextualDefinitionRes = null;
|
||||
definitionError = null;
|
||||
isLoadingContextualDefinition = true;
|
||||
});
|
||||
|
||||
contextualDefinitionRes = await controller.definitions.get(req);
|
||||
if (contextualDefinitionRes == null) {
|
||||
definitionError = Exception("Error getting definition");
|
||||
}
|
||||
GoogleAnalytics.contextualRequest();
|
||||
} catch (err, stack) {
|
||||
debugger(when: kDebugMode);
|
||||
ErrorHandler.logError(
|
||||
e: err,
|
||||
s: stack,
|
||||
data: {
|
||||
"request": req?.toJson(),
|
||||
},
|
||||
);
|
||||
final resp = await ContextualDefinitionRepo.get(
|
||||
MatrixState.pangeaController.userController.accessToken,
|
||||
req,
|
||||
);
|
||||
|
||||
if (resp.isError) {
|
||||
definitionError = Exception("Error getting definition");
|
||||
} finally {
|
||||
if (mounted) setState(() => isLoadingContextualDefinition = false);
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
setState(() => isLoadingContextualDefinition = false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -190,133 +179,3 @@ class WordDataCardView extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WordNetInfo extends StatelessWidget {
|
||||
final WordData wordData;
|
||||
final LanguageModel activeL1;
|
||||
final LanguageModel activeL2;
|
||||
|
||||
const WordNetInfo({
|
||||
super.key,
|
||||
required this.wordData,
|
||||
required this.activeL1,
|
||||
required this.activeL2,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SensesForLanguage(
|
||||
wordData: wordData,
|
||||
languageType: LanguageType.target,
|
||||
language: activeL2,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
SensesForLanguage(
|
||||
wordData: wordData,
|
||||
languageType: LanguageType.base,
|
||||
language: activeL1,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum LanguageType {
|
||||
target,
|
||||
base,
|
||||
}
|
||||
|
||||
class SensesForLanguage extends StatelessWidget {
|
||||
String get exampleSentence => languageType == LanguageType.target
|
||||
? wordData.targetExampleSentence
|
||||
: wordData.baseExampleSentence;
|
||||
|
||||
String get definition => languageType == LanguageType.target
|
||||
? wordData.targetDefinition
|
||||
: wordData.baseDefinition;
|
||||
|
||||
String formattedTitle(BuildContext context) {
|
||||
final String word = languageType == LanguageType.target
|
||||
? wordData.targetWord
|
||||
: wordData.baseWord;
|
||||
String? pos = wordData.formattedPartOfSpeech(languageType);
|
||||
if (pos == null || pos.isEmpty) pos = L10n.of(context).unkDisplayName;
|
||||
return "$word (${wordData.formattedPartOfSpeech(languageType)})";
|
||||
}
|
||||
|
||||
const SensesForLanguage({
|
||||
super.key,
|
||||
required this.wordData,
|
||||
required this.languageType,
|
||||
required this.language,
|
||||
});
|
||||
|
||||
final LanguageModel language;
|
||||
final LanguageType languageType;
|
||||
final WordData wordData;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
LanguageFlag(language: language),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
formattedTitle(context),
|
||||
style: BotStyle.text(context, italics: true, bold: false),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (definition.isNotEmpty)
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: BotStyle.text(
|
||||
context,
|
||||
italics: false,
|
||||
bold: false,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "${L10n.of(context).definition}: ",
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
TextSpan(text: definition),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (exampleSentence.isNotEmpty)
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
style: BotStyle.text(
|
||||
context,
|
||||
italics: false,
|
||||
bold: false,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "${L10n.of(context).exampleSentence}: ",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextSpan(text: exampleSentence),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import 'package:fluffychat/l10n/l10n.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/controllers/it_feedback_controller.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/it_step.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_request_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/igc/word_data_card.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/it_feedback_card.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
|
@ -18,7 +19,6 @@ import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'
|
|||
import 'package:fluffychat/pangea/learning_settings/pages/settings_learning.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import '../../common/utils/overlay.dart';
|
||||
import '../models/it_response_model.dart';
|
||||
import 'choice_array.dart';
|
||||
|
||||
class ITBar extends StatefulWidget {
|
||||
|
|
@ -80,8 +80,7 @@ class ITBarState extends State<ITBar> with SingleTickerProviderStateMixin {
|
|||
!itController.isEditingSourceText &&
|
||||
!itController.isTranslationDone &&
|
||||
itController.currentITStep != null &&
|
||||
itController.currentITStep!.continuances.isNotEmpty &&
|
||||
!itController.showChoiceFeedback;
|
||||
itController.currentITStep!.continuances.isNotEmpty;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -225,13 +224,9 @@ class ITBarState extends State<ITBar> with SingleTickerProviderStateMixin {
|
|||
child: Center(
|
||||
child: itController.choreographer.errorService.isError
|
||||
? ITError(controller: itController)
|
||||
: itController.showChoiceFeedback
|
||||
? ChoiceFeedbackText(
|
||||
controller: itController,
|
||||
)
|
||||
: itController.isTranslationDone
|
||||
? const SizedBox()
|
||||
: ITChoices(controller: itController),
|
||||
: itController.isTranslationDone
|
||||
? const SizedBox()
|
||||
: ITChoices(controller: itController),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -246,35 +241,6 @@ class ITBarState extends State<ITBar> with SingleTickerProviderStateMixin {
|
|||
}
|
||||
}
|
||||
|
||||
class ChoiceFeedbackText extends StatelessWidget {
|
||||
const ChoiceFeedbackText({
|
||||
super.key,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
final ITController controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
//reimplement if we decide we want it
|
||||
return const SizedBox();
|
||||
// return AnimatedTextKit(
|
||||
// isRepeatingAnimation: false,
|
||||
// animatedTexts: [
|
||||
// ScaleAnimatedText(
|
||||
// controller.latestChoiceFeedback(context),
|
||||
// duration: Duration(
|
||||
// milliseconds:
|
||||
// (ChoreoConstants.millisecondsToDisplayFeedback / 2).round(),
|
||||
// ),
|
||||
// scalingFactor: 1.4,
|
||||
// textStyle: BotStyle.text(context),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
class ITChoices extends StatelessWidget {
|
||||
const ITChoices({
|
||||
super.key,
|
||||
|
|
@ -342,19 +308,11 @@ class ITChoices extends StatelessWidget {
|
|||
room: controller.choreographer.chatController.room,
|
||||
)
|
||||
: ITFeedbackCard(
|
||||
req: ITFeedbackRequestModel(
|
||||
sourceText: sourceText!,
|
||||
currentText: controller.choreographer.currentText,
|
||||
chosenContinuance:
|
||||
controller.currentITStep!.continuances[index].text,
|
||||
bestContinuance: controller.currentITStep!.best.text,
|
||||
// TODO: we want this to eventually switch between target and source lang,
|
||||
// based on the learner's proficiency - maybe with the words involved in the translation
|
||||
// maybe overall. For now, we'll just use the source lang.
|
||||
feedbackLang: controller.choreographer.l1Lang?.langCode ??
|
||||
controller.sourceLangCode,
|
||||
sourceTextLang: controller.sourceLangCode,
|
||||
targetLang: controller.targetLangCode,
|
||||
req: FullTextTranslationRequestModel(
|
||||
text: controller.currentITStep!.continuances[index].text,
|
||||
tgtLang: controller.sourceLangCode,
|
||||
userL1: controller.sourceLangCode,
|
||||
userL2: controller.targetLangCode,
|
||||
),
|
||||
choiceFeedback: choiceFeedback,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,15 +7,16 @@ import 'package:http/http.dart';
|
|||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_request_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_response_model.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
import '../../../widgets/matrix.dart';
|
||||
import '../../bot/utils/bot_style.dart';
|
||||
import '../../common/controllers/pangea_controller.dart';
|
||||
import '../controllers/it_feedback_controller.dart';
|
||||
import 'igc/card_error_widget.dart';
|
||||
|
||||
class ITFeedbackCard extends StatefulWidget {
|
||||
final ITFeedbackRequestModel req;
|
||||
final FullTextTranslationRequestModel req;
|
||||
final String choiceFeedback;
|
||||
|
||||
const ITFeedbackCard({
|
||||
|
|
@ -34,7 +35,7 @@ class ITFeedbackCardController extends State<ITFeedbackCard> {
|
|||
Object? error;
|
||||
bool isLoadingFeedback = false;
|
||||
bool isTranslating = false;
|
||||
ITFeedbackResponseModel? res;
|
||||
FullTextTranslationResponseModel? res;
|
||||
String? translatedFeedback;
|
||||
|
||||
Response get noLanguages => Response("", 405);
|
||||
|
|
@ -53,19 +54,10 @@ class ITFeedbackCardController extends State<ITFeedbackCard> {
|
|||
});
|
||||
|
||||
try {
|
||||
final resp = await FullTextTranslationRepo.translate(
|
||||
res = await FullTextTranslationRepo.translate(
|
||||
accessToken: controller.userController.accessToken,
|
||||
request: FullTextTranslationRequestModel(
|
||||
text: widget.req.chosenContinuance,
|
||||
tgtLang: controller.languageController.userL1?.langCode ??
|
||||
widget.req.sourceTextLang,
|
||||
userL1: controller.languageController.userL1?.langCode ??
|
||||
widget.req.sourceTextLang,
|
||||
userL2: controller.languageController.userL2?.langCode ??
|
||||
widget.req.targetLang,
|
||||
),
|
||||
request: widget.req,
|
||||
);
|
||||
res = ITFeedbackResponseModel(text: resp.bestTranslation);
|
||||
} catch (e, s) {
|
||||
error = e;
|
||||
ErrorHandler.logError(
|
||||
|
|
@ -112,7 +104,7 @@ class ITFeedbackCardView extends StatelessWidget {
|
|||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
controller.widget.req.chosenContinuance,
|
||||
controller.widget.req.text,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
|
|
@ -121,16 +113,15 @@ class ITFeedbackCardView extends StatelessWidget {
|
|||
style: BotStyle.text(context),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
controller.res?.text != null
|
||||
controller.res?.bestTranslation != null
|
||||
? Text(
|
||||
controller.res!.text,
|
||||
controller.res!.bestTranslation,
|
||||
style: BotStyle.text(context),
|
||||
)
|
||||
: TextLoadingShimmer(
|
||||
width: min(
|
||||
140,
|
||||
characterWidth *
|
||||
controller.widget.req.chosenContinuance.length,
|
||||
characterWidth * controller.widget.req.text.length,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/choice_animation.dart';
|
||||
|
||||
class FillingStars extends StatefulWidget {
|
||||
final int rating;
|
||||
|
||||
const FillingStars({
|
||||
super.key,
|
||||
required this.rating,
|
||||
});
|
||||
|
||||
@override
|
||||
State<FillingStars> createState() => _FillingStarsState();
|
||||
}
|
||||
|
||||
class _FillingStarsState extends State<FillingStars> {
|
||||
final List<bool> _isFilledList = List.filled(5, false);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _animate());
|
||||
}
|
||||
|
||||
Future<void> _animate() async {
|
||||
for (int i = 0; i < widget.rating; i++) {
|
||||
await Future.delayed(
|
||||
const Duration(milliseconds: choiceArrayAnimationDuration), () {
|
||||
if (mounted) {
|
||||
setState(() => _isFilledList[i] = true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(5, (index) {
|
||||
return AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: choiceArrayAnimationDuration),
|
||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||
return ScaleTransition(
|
||||
scale: animation,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
_isFilledList[index] ? Icons.star_rounded : Icons.star_rounded,
|
||||
key: ValueKey<bool>(_isFilledList[index]),
|
||||
color: _isFilledList[index]
|
||||
? AppConfig.gold
|
||||
: Theme.of(context).cardColor.withAlpha(180),
|
||||
size: 32.0,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ import 'package:fluffychat/pangea/analytics_misc/put_analytics_controller.dart';
|
|||
import 'package:fluffychat/pangea/bot/utils/bot_room_extension.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/models/bot_options_model.dart';
|
||||
import 'package:fluffychat/pangea/chat_settings/utils/bot_client_extension.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/controllers/contextual_definition_controller.dart';
|
||||
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/pangea/events/controllers/message_data_controller.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
|
|
@ -42,8 +41,6 @@ class PangeaController {
|
|||
late PutAnalyticsController putAnalytics;
|
||||
late MessageDataController messageData;
|
||||
|
||||
// TODO: make these static so we can remove from here
|
||||
late ContextualDefinitionController definitions;
|
||||
late SubscriptionController subscriptionController;
|
||||
late TextToSpeechController textToSpeech;
|
||||
late SpeechToTextController speechToText;
|
||||
|
|
@ -90,7 +87,6 @@ class PangeaController {
|
|||
getAnalytics = GetAnalyticsController(this);
|
||||
putAnalytics = PutAnalyticsController(this);
|
||||
messageData = MessageDataController(this);
|
||||
definitions = ContextualDefinitionController(this);
|
||||
subscriptionController = SubscriptionController(this);
|
||||
textToSpeech = TextToSpeechController(this);
|
||||
speechToText = SpeechToTextController(this);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:collection/collection.dart';
|
|||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:matrix/matrix.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
|
|
@ -20,7 +21,6 @@ import 'package:fluffychat/pangea/course_settings/pin_clipper.dart';
|
|||
import 'package:fluffychat/pangea/course_settings/topic_participant_list.dart';
|
||||
import 'package:fluffychat/pangea/events/constants/pangea_event_types.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
|
||||
class CourseSettings extends StatelessWidget {
|
||||
// final Room room;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:matrix/matrix.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/tokens_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_request_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_response_model.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/base_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/common/utils/error_handler.dart';
|
||||
|
|
@ -16,6 +17,7 @@ import 'package:fluffychat/pangea/events/models/representation_content_model.dar
|
|||
import 'package:fluffychat/pangea/events/models/stt_translation_model.dart';
|
||||
import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/token_api_models.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/tokens_repo.dart';
|
||||
import 'package:fluffychat/pangea/extensions/pangea_room_extension.dart';
|
||||
|
||||
// TODO - make this static and take it out of the _pangeaController
|
||||
|
|
|
|||
|
|
@ -9,14 +9,16 @@ import 'package:matrix/matrix.dart';
|
|||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/language_detection_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_request_model.dart';
|
||||
import 'package:fluffychat/pangea/common/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/events/event_wrappers/pangea_representation_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/stt_translation_model.dart';
|
||||
import 'package:fluffychat/pangea/events/models/tokens_event_content_model.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/language_detection_repo.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/language_detection_request.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/language_detection_response.dart';
|
||||
import 'package:fluffychat/pangea/learning_settings/utils/p_language_store.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
|
||||
import 'package:fluffychat/pangea/practice_activities/activity_type_enum.dart';
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import 'package:fluffychat/pangea/analytics_misc/constructs_model.dart';
|
|||
import 'package:fluffychat/pangea/choreographer/event_wrappers/pangea_choreo_event.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/choreo_record.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/models/language_detection_model.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_repo.dart';
|
||||
import 'package:fluffychat/pangea/choreographer/repo/full_text_translation_request_model.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/extensions/pangea_event_extension.dart';
|
||||
|
|
|
|||
33
lib/pangea/events/repo/language_detection_repo.dart
Normal file
33
lib/pangea/events/repo/language_detection_repo.dart
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/common/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/common/network/requests.dart';
|
||||
import 'package:fluffychat/pangea/common/network/urls.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/language_detection_request.dart';
|
||||
import 'package:fluffychat/pangea/events/repo/language_detection_response.dart';
|
||||
|
||||
class LanguageDetectionRepo {
|
||||
static Future<LanguageDetectionResponse> get(
|
||||
String? accessToken, {
|
||||
required LanguageDetectionRequest request,
|
||||
}) async {
|
||||
final Requests req = Requests(
|
||||
accessToken: accessToken,
|
||||
choreoApiKey: Environment.choreoApiKey,
|
||||
);
|
||||
final Response res = await req.post(
|
||||
url: PApiUrls.languageDetection,
|
||||
body: request.toJson(),
|
||||
);
|
||||
|
||||
final Map<String, dynamic> json =
|
||||
jsonDecode(utf8.decode(res.bodyBytes).toString());
|
||||
|
||||
final LanguageDetectionResponse response =
|
||||
LanguageDetectionResponse.fromJson(json);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
19
lib/pangea/events/repo/language_detection_request.dart
Normal file
19
lib/pangea/events/repo/language_detection_request.dart
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
class LanguageDetectionRequest {
|
||||
final String text;
|
||||
final String? senderl1;
|
||||
final String? senderl2;
|
||||
|
||||
LanguageDetectionRequest({
|
||||
required this.text,
|
||||
this.senderl1,
|
||||
this.senderl2,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'full_text': text,
|
||||
'sender_l1': senderl1,
|
||||
'sender_l2': senderl2,
|
||||
};
|
||||
}
|
||||
}
|
||||
29
lib/pangea/events/repo/language_detection_response.dart
Normal file
29
lib/pangea/events/repo/language_detection_response.dart
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import 'package:fluffychat/pangea/choreographer/models/language_detection_model.dart';
|
||||
|
||||
class LanguageDetectionResponse {
|
||||
List<LanguageDetection> detections;
|
||||
String fullText;
|
||||
|
||||
LanguageDetectionResponse({
|
||||
required this.detections,
|
||||
required this.fullText,
|
||||
});
|
||||
|
||||
factory LanguageDetectionResponse.fromJson(Map<String, dynamic> json) {
|
||||
return LanguageDetectionResponse(
|
||||
detections: List<LanguageDetection>.from(
|
||||
(json['detections'] as Iterable).map(
|
||||
(e) => LanguageDetection.fromJson(e),
|
||||
),
|
||||
),
|
||||
fullText: json['full_text'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'detections': detections.map((e) => e.toJson()).toList(),
|
||||
'full_text': fullText,
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue