feature complete
This commit is contained in:
parent
46df9e5381
commit
e94c76ada8
11 changed files with 578 additions and 125 deletions
|
|
@ -434,4 +434,8 @@ class CurrentITStep {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get continuance with highest level
|
||||
Continuance get best =>
|
||||
continuances.reduce((a, b) => a.level > b.level ? a : b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.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/choreographer/widgets/translation_finished_flow.dart';
|
||||
import 'package:fluffychat/pangea/constants/choreo_constants.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/word_data_card.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../config/app_config.dart';
|
||||
import '../../controllers/it_feedback_controller.dart';
|
||||
import '../../models/it_response_model.dart';
|
||||
import '../../utils/overlay.dart';
|
||||
import '../../widgets/igc/word_data_card.dart';
|
||||
import 'choice_array.dart';
|
||||
|
||||
class ITBar extends StatelessWidget {
|
||||
|
|
@ -225,17 +227,31 @@ class ITChoices extends StatelessWidget {
|
|||
]) =>
|
||||
OverlayUtil.showPositionedCard(
|
||||
context: context,
|
||||
cardToShow: WordDataCard(
|
||||
word: controller.currentITStep!.continuances[index].text,
|
||||
wordLang: controller.targetLangCode,
|
||||
fullText: sourceText ?? controller.choreographer.currentText,
|
||||
fullTextLang: sourceText != null
|
||||
? controller.sourceLangCode
|
||||
: controller.targetLangCode,
|
||||
hasInfo: controller.currentITStep!.continuances[index].hasInfo,
|
||||
choiceFeedback: choiceFeedback,
|
||||
room: controller.choreographer.chatController.room,
|
||||
),
|
||||
cardToShow: choiceFeedback == null
|
||||
? WordDataCard(
|
||||
word: controller.currentITStep!.continuances[index].text,
|
||||
wordLang: controller.targetLangCode,
|
||||
fullText: sourceText ?? controller.choreographer.currentText,
|
||||
fullTextLang: sourceText != null
|
||||
? controller.sourceLangCode
|
||||
: controller.targetLangCode,
|
||||
hasInfo: controller.currentITStep!.continuances[index].hasInfo,
|
||||
choiceFeedback: choiceFeedback,
|
||||
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,
|
||||
feedbackLang: controller.targetLangCode,
|
||||
sourceTextLang: controller.sourceLangCode,
|
||||
targetLang: controller.targetLangCode,
|
||||
),
|
||||
choiceFeedback: choiceFeedback,
|
||||
),
|
||||
cardSize: const Size(300, 300),
|
||||
borderColor: borderColor,
|
||||
transformTargetId: controller.choreographer.itBarTransformTargetKey,
|
||||
|
|
|
|||
218
lib/pangea/choreographer/widgets/it_feedback_card.dart
Normal file
218
lib/pangea/choreographer/widgets/it_feedback_card.dart
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
import 'package:fluffychat/pangea/repo/full_text_translation_repo.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/why_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import '../../../config/app_config.dart';
|
||||
import '../../../widgets/matrix.dart';
|
||||
import '../../controllers/it_feedback_controller.dart';
|
||||
import '../../controllers/pangea_controller.dart';
|
||||
import '../../utils/bot_style.dart';
|
||||
import '../../widgets/common/bot_face_svg.dart';
|
||||
import '../../widgets/igc/card_error_widget.dart';
|
||||
import '../../widgets/igc/card_header.dart';
|
||||
|
||||
class ITFeedbackCard extends StatefulWidget {
|
||||
final ITFeedbackRequestModel req;
|
||||
final String choiceFeedback;
|
||||
|
||||
const ITFeedbackCard({
|
||||
super.key,
|
||||
required this.req,
|
||||
required this.choiceFeedback,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ITFeedbackCard> createState() => ITFeedbackCardController();
|
||||
}
|
||||
|
||||
class ITFeedbackCardController extends State<ITFeedbackCard> {
|
||||
final PangeaController controller = MatrixState.pangeaController;
|
||||
|
||||
Object? error;
|
||||
bool isLoadingFeedback = false;
|
||||
bool isTranslating = false;
|
||||
ITFeedbackResponseModel? res;
|
||||
String? translatedFeedback;
|
||||
|
||||
Response get noLanguages => Response("", 405);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
if (!mounted) return;
|
||||
//any setup?
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future<void> getFeedback() async {
|
||||
setState(() {
|
||||
isLoadingFeedback = true;
|
||||
});
|
||||
controller.itFeedback
|
||||
.get(widget.req)
|
||||
.then((value) {
|
||||
res = value;
|
||||
})
|
||||
.catchError((e) => error = e)
|
||||
.whenComplete(
|
||||
() => setState(() {
|
||||
isLoadingFeedback = false;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> translateFeedback() async {
|
||||
setState(() {
|
||||
isTranslating = true;
|
||||
});
|
||||
FullTextTranslationRepo.translate(
|
||||
accessToken: await controller.userController.accessToken,
|
||||
request: FullTextTranslationRequestModel(
|
||||
text: res!.text,
|
||||
tgtLang: controller.languageController.userL1?.langCode ??
|
||||
widget.req.sourceTextLang,
|
||||
userL1: controller.languageController.userL1?.langCode ??
|
||||
widget.req.sourceTextLang,
|
||||
userL2: controller.languageController.userL2?.langCode ??
|
||||
widget.req.targetLang,
|
||||
),
|
||||
)
|
||||
.then((value) {
|
||||
translatedFeedback = value.bestTranslation;
|
||||
})
|
||||
.catchError((e) => error = e)
|
||||
.whenComplete(
|
||||
() => setState(() {
|
||||
isTranslating = false;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
void handleGetExplanationButtonPress() {
|
||||
if (isLoadingFeedback) return;
|
||||
getFeedback();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => error == null
|
||||
? ITFeedbackCardView(controller: this)
|
||||
: CardErrorWidget(error: error);
|
||||
}
|
||||
|
||||
class ITFeedbackCardView extends StatelessWidget {
|
||||
const ITFeedbackCardView({
|
||||
super.key,
|
||||
required this.controller,
|
||||
});
|
||||
|
||||
final ITFeedbackCardController controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ScrollController scrollController = ScrollController();
|
||||
|
||||
return Scrollbar(
|
||||
thumbVisibility: true,
|
||||
controller: scrollController,
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
CardHeader(
|
||||
text: controller.widget.req.chosenContinuance,
|
||||
botExpression: BotExpression.down,
|
||||
),
|
||||
Text(
|
||||
controller.widget.choiceFeedback,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (controller.res == null)
|
||||
WhyButton(
|
||||
onPress: controller.handleGetExplanationButtonPress,
|
||||
loading: controller.isLoadingFeedback,
|
||||
),
|
||||
if (controller.res != null)
|
||||
Text(
|
||||
controller.res!.text,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
// if res is not null, show a button to translate the text
|
||||
if (controller.res != null && controller.translatedFeedback == null)
|
||||
Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
TranslateButton(
|
||||
onPress: controller.translateFeedback,
|
||||
loading: controller.isTranslating,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (controller.translatedFeedback != null)
|
||||
//add little line to separate the text from the translation
|
||||
Column(
|
||||
children: [
|
||||
const Divider(
|
||||
color: AppConfig.primaryColor,
|
||||
thickness: 2,
|
||||
height: 20, // Set the space around the divider
|
||||
indent: 20, // Set the starting space (left padding)
|
||||
endIndent: 20, // Set the ending space (right padding)
|
||||
),
|
||||
Text(
|
||||
controller.translatedFeedback!,
|
||||
style: BotStyle.text(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// button to translate the text
|
||||
class TranslateButton extends StatelessWidget {
|
||||
const TranslateButton({
|
||||
super.key,
|
||||
required this.onPress,
|
||||
required this.loading,
|
||||
});
|
||||
|
||||
final VoidCallback onPress;
|
||||
final bool loading;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: loading ? null : onPress,
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all<Color>(
|
||||
AppConfig.primaryColor.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
width: 150, // set the width of the button contents here
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (!loading) const Icon(Icons.translate),
|
||||
if (loading)
|
||||
const Center(
|
||||
child: SizedBox(
|
||||
width: 24.0,
|
||||
height: 24.0,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
// const SizedBox(width: 8),
|
||||
// Text(L10n.of(context)!.translate),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ class Environment {
|
|||
}
|
||||
|
||||
static String get choreoApi {
|
||||
// return "http://localhost:8000/choreo";
|
||||
return "http://localhost:8000/choreo";
|
||||
return dotenv.env['CHOREO_API'] ?? 'Not found';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,4 +76,15 @@ class ModelKey {
|
|||
static const String targetWord = "target_word";
|
||||
static const String baseExampleSentence = "base_example_sentence";
|
||||
static const String targetExampleSentence = "target_example_sentence";
|
||||
|
||||
//add goldTranslation, goldContinuance, chosenContinuance
|
||||
static const String goldTranslation = "gold_translation";
|
||||
static const String goldContinuance = "gold_continuance";
|
||||
static const String chosenContinuance = "chosen_continuance";
|
||||
|
||||
// sourceText, currentText, bestContinuance, feedback_lang
|
||||
static const String sourceText = "src";
|
||||
static const String currentText = "current";
|
||||
static const String bestContinuance = "best_continuance";
|
||||
static const String feedbackLang = "feedback_lang";
|
||||
}
|
||||
|
|
|
|||
153
lib/pangea/controllers/it_feedback_controller.dart
Normal file
153
lib/pangea/controllers/it_feedback_controller.dart
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fluffychat/pangea/config/environment.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart';
|
||||
|
||||
import '../constants/model_keys.dart';
|
||||
import '../network/requests.dart';
|
||||
import '../network/urls.dart';
|
||||
import 'pangea_controller.dart';
|
||||
|
||||
class ITFeedbackController {
|
||||
late PangeaController _pangeaController;
|
||||
|
||||
final List<_ITFeedbackCacheItem> _feedback = [];
|
||||
|
||||
ITFeedbackController(PangeaController pangeaController) {
|
||||
_pangeaController = pangeaController;
|
||||
}
|
||||
|
||||
_ITFeedbackCacheItem? _getLocal(
|
||||
ITFeedbackRequestModel req,
|
||||
) =>
|
||||
_feedback.firstWhereOrNull(
|
||||
(e) =>
|
||||
e.chosenContinuance == req.chosenContinuance &&
|
||||
e.sourceText == req.sourceText,
|
||||
);
|
||||
|
||||
Future<ITFeedbackResponseModel?> get(
|
||||
ITFeedbackRequestModel req,
|
||||
) {
|
||||
final _ITFeedbackCacheItem? localItem = _getLocal(req);
|
||||
|
||||
if (localItem != null) return localItem.data;
|
||||
|
||||
_feedback.add(
|
||||
_ITFeedbackCacheItem(
|
||||
chosenContinuance: req.chosenContinuance,
|
||||
sourceText: req.sourceText,
|
||||
data: _get(req),
|
||||
),
|
||||
);
|
||||
|
||||
return _feedback.last.data;
|
||||
}
|
||||
|
||||
Future<ITFeedbackResponseModel?> _get(
|
||||
ITFeedbackRequestModel request,
|
||||
) async {
|
||||
try {
|
||||
final ITFeedbackResponseModel res = await _ITFeedbackRepo.get(
|
||||
await _pangeaController.userController.accessToken,
|
||||
request,
|
||||
);
|
||||
return res;
|
||||
} catch (err, stack) {
|
||||
debugPrint(
|
||||
"error getting contextual definition for ${request.chosenContinuance} in '${request.sourceText}'",
|
||||
);
|
||||
ErrorHandler.logError(e: err, s: stack, data: request.toJson());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _ITFeedbackCacheItem {
|
||||
String chosenContinuance;
|
||||
String sourceText;
|
||||
Future<ITFeedbackResponseModel?> data;
|
||||
|
||||
_ITFeedbackCacheItem({
|
||||
required this.chosenContinuance,
|
||||
required this.sourceText,
|
||||
required this.data,
|
||||
});
|
||||
}
|
||||
|
||||
class _ITFeedbackRepo {
|
||||
static Future<ITFeedbackResponseModel> get(
|
||||
String accessToken,
|
||||
ITFeedbackRequestModel request,
|
||||
) async {
|
||||
final Requests req = Requests(
|
||||
choreoApiKey: Environment.choreoApiKey,
|
||||
accessToken: accessToken,
|
||||
);
|
||||
|
||||
final Response res = await req.post(
|
||||
url: PApiUrls.itFeedback,
|
||||
body: request.toJson(),
|
||||
);
|
||||
|
||||
final ITFeedbackResponseModel response = ITFeedbackResponseModel.fromJson(
|
||||
jsonDecode(
|
||||
utf8.decode(res.bodyBytes).toString(),
|
||||
),
|
||||
);
|
||||
|
||||
if (response.text.isEmpty) {
|
||||
ErrorHandler.logError(
|
||||
e: Exception(
|
||||
"empty text in contextual definition response",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:developer';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:fluffychat/pangea/choreographer/widgets/it_feedback_card.dart';
|
||||
import 'package:fluffychat/pangea/constants/class_default_values.dart';
|
||||
import 'package:fluffychat/pangea/controllers/class_controller.dart';
|
||||
import 'package:fluffychat/pangea/controllers/contextual_definition_controller.dart';
|
||||
|
|
@ -26,6 +27,7 @@ import 'package:sentry_flutter/sentry_flutter.dart';
|
|||
import '../../config/app_config.dart';
|
||||
import '../utils/firebase_analytics.dart';
|
||||
import '../utils/p_store.dart';
|
||||
import 'it_feedback_controller.dart';
|
||||
import 'message_analytics_controller.dart';
|
||||
|
||||
class PangeaController {
|
||||
|
|
@ -40,6 +42,7 @@ class PangeaController {
|
|||
late LocalSettings localSettings;
|
||||
late MessageDataController messageData;
|
||||
late ContextualDefinitionController definitions;
|
||||
late ITFeedbackController itFeedback;
|
||||
late InstructionsController instructions;
|
||||
late SubscriptionController subscriptionController;
|
||||
|
||||
|
|
@ -86,6 +89,7 @@ class PangeaController {
|
|||
definitions = ContextualDefinitionController(this);
|
||||
instructions = InstructionsController(this);
|
||||
subscriptionController = SubscriptionController(this);
|
||||
itFeedback = ITFeedbackController(this);
|
||||
PAuthGaurd.pController = this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ class PApiUrls {
|
|||
static String similarity = "${Environment.choreoApi}/similarity";
|
||||
static String topicInfo = "${Environment.choreoApi}/vocab_list";
|
||||
|
||||
static String itFeedback = "${Environment.choreoApi}/translation/feedback";
|
||||
|
||||
static String firstStep = "/it_initialstep";
|
||||
static String subseqStep = "/it_step";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/enum/span_data_type.dart';
|
||||
import 'package:fluffychat/pangea/models/span_data.dart';
|
||||
|
|
@ -12,6 +7,10 @@ import 'package:fluffychat/pangea/utils/bot_style.dart';
|
|||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/utils/match_copy.dart';
|
||||
import 'package:fluffychat/pangea/widgets/igc/card_error_widget.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import '../../../widgets/matrix.dart';
|
||||
import '../../choreographer/widgets/choice_array.dart';
|
||||
import '../../controllers/pangea_controller.dart';
|
||||
|
|
@ -19,6 +18,7 @@ import '../../enum/span_choice_type.dart';
|
|||
import '../../models/span_card_model.dart';
|
||||
import '../common/bot_face_svg.dart';
|
||||
import 'card_header.dart';
|
||||
import 'why_button.dart';
|
||||
|
||||
const wordMatchResultsCount = 5;
|
||||
|
||||
|
|
@ -314,37 +314,13 @@ class PromptAndFeedback extends StatelessWidget {
|
|||
),
|
||||
const SizedBox(height: 8),
|
||||
if (controller.selectedChoice?.feedback == null)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
WhyButton(
|
||||
onPress: () {
|
||||
if (!controller.fetchingData) {
|
||||
controller.getSpanDetails();
|
||||
}
|
||||
},
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all<Color>(
|
||||
AppConfig.primaryColor.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
width: 150, // set the width of the button contents here
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (!controller.fetchingData)
|
||||
const Icon(Icons.lightbulb_outline),
|
||||
if (controller.fetchingData)
|
||||
const Center(
|
||||
child: SizedBox(
|
||||
width: 24.0,
|
||||
height: 24.0,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(L10n.of(context)!.why),
|
||||
],
|
||||
),
|
||||
),
|
||||
loading: controller.fetchingData,
|
||||
),
|
||||
],
|
||||
if (!controller.fetchingData &&
|
||||
|
|
|
|||
56
lib/pangea/widgets/igc/why_button.dart
Normal file
56
lib/pangea/widgets/igc/why_button.dart
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import '../../../config/app_config.dart';
|
||||
|
||||
class WhyButton extends StatelessWidget {
|
||||
const WhyButton({
|
||||
super.key,
|
||||
required this.onPress,
|
||||
required this.loading,
|
||||
});
|
||||
|
||||
final VoidCallback onPress;
|
||||
final bool loading;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: loading ? null : onPress,
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all<Color>(
|
||||
AppConfig.primaryColor.withOpacity(0.1),
|
||||
),
|
||||
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10), // Border radius
|
||||
side: const BorderSide(
|
||||
color: AppConfig.primaryColor, // Replace with your color
|
||||
style: BorderStyle.solid,
|
||||
width: 2.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
width: 150,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
if (!loading) const Icon(Icons.lightbulb_outline),
|
||||
if (loading)
|
||||
const Center(
|
||||
child: SizedBox(
|
||||
width: 24.0,
|
||||
height: 24.0,
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(L10n.of(context)!.why),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -764,7 +764,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"bn": [
|
||||
|
|
@ -1537,7 +1538,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"bo": [
|
||||
|
|
@ -2310,7 +2312,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"ca": [
|
||||
|
|
@ -3078,7 +3081,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"cs": [
|
||||
|
|
@ -3846,7 +3850,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"de": [
|
||||
|
|
@ -4614,7 +4619,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"el": [
|
||||
|
|
@ -5387,7 +5393,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"eo": [
|
||||
|
|
@ -6155,39 +6162,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
],
|
||||
|
||||
"es": [
|
||||
"notAnImage",
|
||||
"importNow",
|
||||
"importEmojis",
|
||||
"importFromZipFile",
|
||||
"importZipFile",
|
||||
"exportEmotePack",
|
||||
"savedEmotePack",
|
||||
"sendTypingNotifications",
|
||||
"reportToTeacher",
|
||||
"reportMessageTitle",
|
||||
"reportMessageBody",
|
||||
"noTeachersFound",
|
||||
"noAddToSpacePermissions",
|
||||
"alreadyInSpace",
|
||||
"yourGlobalUserIdIs",
|
||||
"noUsersFoundWithQuery",
|
||||
"searchChatsRooms",
|
||||
"groupName",
|
||||
"createGroupAndInviteUsers",
|
||||
"groupCanBeFoundViaSearch",
|
||||
"inNoSpaces",
|
||||
"createClass",
|
||||
"createExchange",
|
||||
"viewArchive",
|
||||
"trialExpiration",
|
||||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"et": [
|
||||
|
|
@ -6955,7 +6931,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"eu": [
|
||||
|
|
@ -7723,7 +7700,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"fa": [
|
||||
|
|
@ -8491,7 +8469,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"fi": [
|
||||
|
|
@ -9259,7 +9238,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
|
|
@ -10027,7 +10007,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"ga": [
|
||||
|
|
@ -10795,7 +10776,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"gl": [
|
||||
|
|
@ -11563,7 +11545,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"he": [
|
||||
|
|
@ -12331,7 +12314,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"hi": [
|
||||
|
|
@ -13104,7 +13088,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"hr": [
|
||||
|
|
@ -13872,7 +13857,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"hu": [
|
||||
|
|
@ -14640,7 +14626,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"id": [
|
||||
|
|
@ -15408,7 +15395,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"ie": [
|
||||
|
|
@ -16178,7 +16166,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"it": [
|
||||
|
|
@ -16946,7 +16935,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"ja": [
|
||||
|
|
@ -17714,7 +17704,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"ko": [
|
||||
|
|
@ -18482,7 +18473,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"lt": [
|
||||
|
|
@ -19250,7 +19242,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"lv": [
|
||||
|
|
@ -20023,7 +20016,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"nb": [
|
||||
|
|
@ -20791,7 +20785,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"nl": [
|
||||
|
|
@ -21559,7 +21554,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"pl": [
|
||||
|
|
@ -22327,7 +22323,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"pt": [
|
||||
|
|
@ -23100,7 +23097,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"pt_BR": [
|
||||
|
|
@ -23868,7 +23866,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"pt_PT": [
|
||||
|
|
@ -24636,7 +24635,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"ro": [
|
||||
|
|
@ -25404,7 +25404,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
|
|
@ -26172,7 +26173,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"sk": [
|
||||
|
|
@ -26941,7 +26943,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"sl": [
|
||||
|
|
@ -27712,7 +27715,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"sr": [
|
||||
|
|
@ -28480,7 +28484,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"sv": [
|
||||
|
|
@ -29248,7 +29253,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"ta": [
|
||||
|
|
@ -30021,7 +30027,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"th": [
|
||||
|
|
@ -30794,7 +30801,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"tr": [
|
||||
|
|
@ -31562,7 +31570,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"uk": [
|
||||
|
|
@ -32330,7 +32339,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"vi": [
|
||||
|
|
@ -33101,7 +33111,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"zh": [
|
||||
|
|
@ -33869,7 +33880,8 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
],
|
||||
|
||||
"zh_Hant": [
|
||||
|
|
@ -34637,6 +34649,7 @@
|
|||
"freeTrialDesc",
|
||||
"activateTrial",
|
||||
"successfullySubscribed",
|
||||
"clickToManageSubscription"
|
||||
"clickToManageSubscription",
|
||||
"emptyInviteWarning"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue