Merge branch 'main' into hide-find-convo-partner
This commit is contained in:
commit
ad71fec48e
21 changed files with 408 additions and 342 deletions
|
|
@ -491,7 +491,12 @@ class InputBar extends StatelessWidget {
|
|||
textInputAction: textInputAction,
|
||||
autofocus: autofocus!,
|
||||
inputFormatters: [
|
||||
LengthLimitingTextInputFormatter((maxPDUSize / 3).floor()),
|
||||
//#Pangea
|
||||
//LengthLimitingTextInputFormatter((maxPDUSize / 3).floor()),
|
||||
//setting max character count to 1000
|
||||
//after max, nothing else can be typed
|
||||
LengthLimitingTextInputFormatter(1000),
|
||||
//Pangea#
|
||||
],
|
||||
onSubmitted: (text) {
|
||||
// fix for library for now
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ class PangeaLanguage {
|
|||
}
|
||||
|
||||
static LanguageModel byLangCode(String langCode) {
|
||||
final list = _langList;
|
||||
for (final element in _langList) {
|
||||
if (element.langCode == langCode) return element;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,11 +229,8 @@ class MyAnalyticsController {
|
|||
/// top level analytics sending function. Gather recent messages and activity records,
|
||||
/// convert them into the correct formats, and send them to the analytics room
|
||||
Future<void> _updateAnalytics() async {
|
||||
// if missing important info, don't send analytics
|
||||
if (userL2 == null || _client.userID == null) {
|
||||
debugger(when: kDebugMode);
|
||||
return;
|
||||
}
|
||||
// if missing important info, don't send analytics. Could happen if user just signed up.
|
||||
if (userL2 == null || _client.userID == null) return;
|
||||
|
||||
// analytics room for the user and current target language
|
||||
final Room analyticsRoom = await _client.getMyAnalyticsRoom(userL2!);
|
||||
|
|
|
|||
13
lib/pangea/enum/activity_display_instructions_enum.dart
Normal file
13
lib/pangea/enum/activity_display_instructions_enum.dart
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
enum ActivityDisplayInstructionsEnum { highlight, hide }
|
||||
|
||||
extension ActivityDisplayInstructionsEnumExt
|
||||
on ActivityDisplayInstructionsEnum {
|
||||
String get string {
|
||||
switch (this) {
|
||||
case ActivityDisplayInstructionsEnum.highlight:
|
||||
return 'highlight';
|
||||
case ActivityDisplayInstructionsEnum.hide:
|
||||
return 'hide';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:fluffychat/utils/platform_infos.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
|
|
@ -9,7 +10,7 @@ enum InstructionsEnum {
|
|||
tooltipInstructions,
|
||||
}
|
||||
|
||||
extension Copy on InstructionsEnum {
|
||||
extension InstructionsEnumExtension on InstructionsEnum {
|
||||
String title(BuildContext context) {
|
||||
switch (this) {
|
||||
case InstructionsEnum.itInstructions:
|
||||
|
|
@ -37,6 +38,21 @@ extension Copy on InstructionsEnum {
|
|||
: L10n.of(context)!.tooltipInstructionsBrowserBody;
|
||||
}
|
||||
}
|
||||
|
||||
bool get toggledOff {
|
||||
final instructionSettings =
|
||||
MatrixState.pangeaController.userController.profile.instructionSettings;
|
||||
switch (this) {
|
||||
case InstructionsEnum.itInstructions:
|
||||
return instructionSettings.showedItInstructions;
|
||||
case InstructionsEnum.clickMessage:
|
||||
return instructionSettings.showedClickMessage;
|
||||
case InstructionsEnum.blurMeansTranslate:
|
||||
return instructionSettings.showedBlurMeansTranslate;
|
||||
case InstructionsEnum.tooltipInstructions:
|
||||
return instructionSettings.showedTooltipInstructions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum InlineInstructions {
|
||||
|
|
|
|||
|
|
@ -687,7 +687,8 @@ class PangeaMessageEvent {
|
|||
|
||||
for (final itStep in originalSent!.choreo!.itSteps) {
|
||||
for (final continuance in itStep.continuances) {
|
||||
// this seems to always be false for continuances right now
|
||||
final List<PangeaToken> tokensToSave =
|
||||
continuance.tokens.where((t) => t.lemma.saveVocab).toList();
|
||||
|
||||
if (originalSent!.choreo!.finalMessage.contains(continuance.text)) {
|
||||
continue;
|
||||
|
|
@ -695,21 +696,25 @@ class PangeaMessageEvent {
|
|||
if (continuance.wasClicked) {
|
||||
//PTODO - account for end of flow score
|
||||
if (continuance.level != ChoreoConstants.levelThresholdForGreen) {
|
||||
uses.addAll(
|
||||
_lemmasToVocabUses(
|
||||
continuance.lemmas,
|
||||
ConstructUseTypeEnum.incIt,
|
||||
),
|
||||
);
|
||||
for (final token in tokensToSave) {
|
||||
uses.add(
|
||||
_lemmaToVocabUse(
|
||||
token.lemma,
|
||||
ConstructUseTypeEnum.incIt,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (continuance.level != ChoreoConstants.levelThresholdForGreen) {
|
||||
uses.addAll(
|
||||
_lemmasToVocabUses(
|
||||
continuance.lemmas,
|
||||
ConstructUseTypeEnum.ignIt,
|
||||
),
|
||||
);
|
||||
for (final token in tokensToSave) {
|
||||
uses.add(
|
||||
_lemmaToVocabUse(
|
||||
token.lemma,
|
||||
ConstructUseTypeEnum.ignIt,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -728,14 +733,16 @@ class PangeaMessageEvent {
|
|||
}
|
||||
|
||||
// for each token, record whether selected in ga, ta, or wa
|
||||
for (final token in originalSent!.tokens!) {
|
||||
uses.addAll(_getVocabUseForToken(token));
|
||||
for (final token in originalSent!.tokens!
|
||||
.where((token) => token.lemma.saveVocab)
|
||||
.toList()) {
|
||||
uses.add(_getVocabUseForToken(token));
|
||||
}
|
||||
|
||||
return uses;
|
||||
}
|
||||
|
||||
/// Returns a list of [OneConstructUse] objects for the given [token]
|
||||
/// Returns a [OneConstructUse] for the given [token]
|
||||
/// If there is no [originalSent] or [originalSent.choreo], the [token] is
|
||||
/// considered to be a [ConstructUseTypeEnum.wa] as long as it matches the target language.
|
||||
/// Later on, we may want to consider putting it in some category of like 'pending'
|
||||
|
|
@ -744,11 +751,11 @@ class PangeaMessageEvent {
|
|||
/// If the [token] is in the [originalSent.choreo.acceptedOrIgnoredMatch.choices],
|
||||
/// it is considered to be a [ConstructUseTypeEnum.corIt].
|
||||
/// If the [token] is not included in any choreoStep, it is considered to be a [ConstructUseTypeEnum.wa].
|
||||
List<OneConstructUse> _getVocabUseForToken(PangeaToken token) {
|
||||
OneConstructUse _getVocabUseForToken(PangeaToken token) {
|
||||
if (originalSent?.choreo == null) {
|
||||
final bool inUserL2 = originalSent?.langCode == l2Code;
|
||||
return _lemmasToVocabUses(
|
||||
token.lemmas,
|
||||
return _lemmaToVocabUse(
|
||||
token.lemma,
|
||||
inUserL2 ? ConstructUseTypeEnum.wa : ConstructUseTypeEnum.unk,
|
||||
);
|
||||
}
|
||||
|
|
@ -763,45 +770,34 @@ class PangeaMessageEvent {
|
|||
step.text.contains(r.value),
|
||||
) ??
|
||||
false)) {
|
||||
return _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.ga);
|
||||
return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.ga);
|
||||
}
|
||||
if (step.itStep != null) {
|
||||
final bool pickedThroughIT =
|
||||
step.itStep!.chosenContinuance?.text.contains(token.text.content) ??
|
||||
false;
|
||||
if (pickedThroughIT) {
|
||||
return _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.corIt);
|
||||
return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.corIt);
|
||||
//PTODO - check if added via custom input in IT flow
|
||||
}
|
||||
}
|
||||
}
|
||||
return _lemmasToVocabUses(token.lemmas, ConstructUseTypeEnum.wa);
|
||||
return _lemmaToVocabUse(token.lemma, ConstructUseTypeEnum.wa);
|
||||
}
|
||||
|
||||
/// Convert a list of [lemmas] into a list of vocab uses
|
||||
/// with the given [type]
|
||||
List<OneConstructUse> _lemmasToVocabUses(
|
||||
List<Lemma> lemmas,
|
||||
OneConstructUse _lemmaToVocabUse(
|
||||
Lemma lemma,
|
||||
ConstructUseTypeEnum type,
|
||||
) {
|
||||
final List<OneConstructUse> uses = [];
|
||||
for (final lemma in lemmas) {
|
||||
if (lemma.saveVocab) {
|
||||
uses.add(
|
||||
OneConstructUse(
|
||||
useType: type,
|
||||
chatId: event.roomId!,
|
||||
timeStamp: event.originServerTs,
|
||||
lemma: lemma.text,
|
||||
form: lemma.form,
|
||||
msgId: event.eventId,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
return uses;
|
||||
}
|
||||
) =>
|
||||
OneConstructUse(
|
||||
useType: type,
|
||||
chatId: event.roomId!,
|
||||
timeStamp: event.originServerTs,
|
||||
lemma: lemma.text,
|
||||
form: lemma.form,
|
||||
msgId: event.eventId,
|
||||
constructType: ConstructTypeEnum.vocab,
|
||||
);
|
||||
|
||||
/// get construct uses of type grammar for the message
|
||||
List<OneConstructUse> get _grammarConstructUses {
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ import 'package:collection/collection.dart';
|
|||
import 'package:fluffychat/pangea/constants/choreo_constants.dart';
|
||||
import 'package:fluffychat/pangea/constants/model_keys.dart';
|
||||
import 'package:fluffychat/pangea/extensions/my_list_extension.dart';
|
||||
import 'package:fluffychat/pangea/models/pangea_token_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
import 'lemma.dart';
|
||||
|
||||
class ITResponseModel {
|
||||
String fullTextTranslation;
|
||||
List<Continuance> continuances;
|
||||
|
|
@ -79,7 +78,7 @@ class Continuance {
|
|||
double probability;
|
||||
int level;
|
||||
String text;
|
||||
List<Lemma> lemmas;
|
||||
List<PangeaToken> tokens;
|
||||
|
||||
/// saving this in a full json form
|
||||
String description;
|
||||
|
|
@ -99,19 +98,18 @@ class Continuance {
|
|||
required this.inDictionary,
|
||||
required this.hasInfo,
|
||||
required this.gold,
|
||||
required this.lemmas,
|
||||
required this.tokens,
|
||||
});
|
||||
|
||||
factory Continuance.fromJson(Map<String, dynamic> json) {
|
||||
final List<Lemma> lemmaInternal =
|
||||
(json[ModelKey.lemma] != null && json[ModelKey.lemma] is Iterable)
|
||||
? (json[ModelKey.lemma] as Iterable)
|
||||
.map<Lemma>(
|
||||
(e) => Lemma.fromJson(e as Map<String, dynamic>),
|
||||
)
|
||||
.toList()
|
||||
.cast<Lemma>()
|
||||
: [];
|
||||
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'],
|
||||
|
|
@ -122,7 +120,7 @@ class Continuance {
|
|||
wasClicked: json['clkd'] ?? false,
|
||||
hasInfo: json['has_info'] ?? false,
|
||||
gold: json['gold'] ?? false,
|
||||
lemmas: lemmaInternal,
|
||||
tokens: tokensInternal,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +130,7 @@ class Continuance {
|
|||
data['level'] = level;
|
||||
data['text'] = text;
|
||||
data['clkd'] = wasClicked;
|
||||
data[ModelKey.lemma] = lemmas.map((e) => e.toJson()).toList();
|
||||
data[ModelKey.tokens] = tokens.map((e) => e.toJson()).toList();
|
||||
|
||||
if (!condensed) {
|
||||
data['description'] = description;
|
||||
|
|
|
|||
|
|
@ -8,22 +8,13 @@ class Lemma {
|
|||
|
||||
/// [saveVocab] true - whether to save the lemma to the user's vocabulary
|
||||
/// vocab that are not saved: emails, urls, numbers, punctuation, etc.
|
||||
/// server handles this determination
|
||||
final bool saveVocab;
|
||||
|
||||
/// [pos] ex "v" - part of speech of the lemma
|
||||
/// https://universaldependencies.org/u/pos/
|
||||
final String pos;
|
||||
|
||||
/// [morph] ex {} - morphological features of the lemma
|
||||
/// https://universaldependencies.org/u/feat/
|
||||
final Map<String, dynamic> morph;
|
||||
|
||||
Lemma({
|
||||
required this.text,
|
||||
required this.saveVocab,
|
||||
required this.form,
|
||||
this.pos = '',
|
||||
this.morph = const {},
|
||||
});
|
||||
|
||||
factory Lemma.fromJson(Map<String, dynamic> json) {
|
||||
|
|
@ -31,8 +22,6 @@ class Lemma {
|
|||
text: json['text'],
|
||||
saveVocab: json['save_vocab'] ?? json['saveVocab'] ?? false,
|
||||
form: json["form"] ?? json['text'],
|
||||
pos: json['pos'] ?? '',
|
||||
morph: json['morph'] ?? {},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -41,8 +30,6 @@ class Lemma {
|
|||
'text': text,
|
||||
'save_vocab': saveVocab,
|
||||
'form': form,
|
||||
'pos': pos,
|
||||
'morph': morph,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,55 +1,60 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import '../constants/model_keys.dart';
|
||||
import '../utils/error_handler.dart';
|
||||
import 'lemma.dart';
|
||||
|
||||
class PangeaToken {
|
||||
PangeaTokenText text;
|
||||
List<Lemma> lemmas;
|
||||
Lemma lemma;
|
||||
|
||||
/// [pos] ex "VERB" - part of speech of the token
|
||||
/// https://universaldependencies.org/u/pos/
|
||||
final String pos;
|
||||
|
||||
/// [morph] ex {} - morphological features of the token
|
||||
/// https://universaldependencies.org/u/feat/
|
||||
final Map<String, dynamic> morph;
|
||||
|
||||
PangeaToken({
|
||||
required this.text,
|
||||
required this.lemmas,
|
||||
required this.lemma,
|
||||
required this.pos,
|
||||
required this.morph,
|
||||
});
|
||||
|
||||
static getLemmas(String text, Iterable? json) {
|
||||
static Lemma _getLemmas(String text, dynamic json) {
|
||||
if (json != null) {
|
||||
return json
|
||||
.map<Lemma>(
|
||||
(e) => Lemma.fromJson(e as Map<String, dynamic>),
|
||||
)
|
||||
.toList()
|
||||
.cast<Lemma>();
|
||||
// July 24, 2024 - we're changing from a list to a single lemma and this is for backwards compatibility
|
||||
// previously sent tokens have lists of lemmas
|
||||
if (json is Iterable) {
|
||||
return json
|
||||
.map<Lemma>(
|
||||
(e) => Lemma.fromJson(e as Map<String, dynamic>),
|
||||
)
|
||||
.toList()
|
||||
.cast<Lemma>()
|
||||
.firstOrNull ??
|
||||
Lemma(text: text, saveVocab: false, form: text);
|
||||
} else {
|
||||
return Lemma.fromJson(json);
|
||||
}
|
||||
} else {
|
||||
return [Lemma(text: text, saveVocab: false, form: text)];
|
||||
// earlier still, we didn't have lemmas so this is for really old tokens
|
||||
return Lemma(text: text, saveVocab: false, form: text);
|
||||
}
|
||||
}
|
||||
|
||||
factory PangeaToken.fromJson(Map<String, dynamic> json) {
|
||||
try {
|
||||
final PangeaTokenText text =
|
||||
PangeaTokenText.fromJson(json[_textKey] as Map<String, dynamic>);
|
||||
return PangeaToken(
|
||||
text: text,
|
||||
lemmas: getLemmas(text.content, json[_lemmaKey]),
|
||||
);
|
||||
} catch (err, s) {
|
||||
debugger(when: kDebugMode);
|
||||
Sentry.addBreadcrumb(
|
||||
Breadcrumb(
|
||||
message: "PangeaToken.fromJson error",
|
||||
data: {
|
||||
"json": json,
|
||||
},
|
||||
),
|
||||
);
|
||||
ErrorHandler.logError(e: err, s: s);
|
||||
rethrow;
|
||||
}
|
||||
final PangeaTokenText text =
|
||||
PangeaTokenText.fromJson(json[_textKey] as Map<String, dynamic>);
|
||||
return PangeaToken(
|
||||
text: text,
|
||||
lemma: _getLemmas(text.content, json[_lemmaKey]),
|
||||
pos: json['pos'] ?? '',
|
||||
morph: json['morph'] ?? {},
|
||||
);
|
||||
}
|
||||
|
||||
static const String _textKey = "text";
|
||||
|
|
@ -57,7 +62,9 @@ class PangeaToken {
|
|||
|
||||
Map<String, dynamic> toJson() => {
|
||||
_textKey: text.toJson(),
|
||||
_lemmaKey: lemmas.map((e) => e.toJson()).toList(),
|
||||
_lemmaKey: [lemma.toJson()],
|
||||
'pos': pos,
|
||||
'morph': morph,
|
||||
};
|
||||
|
||||
int get end => text.offset + text.length;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MultipleChoice {
|
||||
final String question;
|
||||
final List<String> choices;
|
||||
final String answer;
|
||||
final RelevantSpanDisplayDetails? spanDisplayDetails;
|
||||
|
||||
MultipleChoice({
|
||||
required this.question,
|
||||
required this.choices,
|
||||
required this.answer,
|
||||
this.spanDisplayDetails,
|
||||
});
|
||||
|
||||
bool isCorrect(int index) => index == correctAnswerIndex;
|
||||
|
|
@ -28,6 +31,9 @@ class MultipleChoice {
|
|||
question: json['question'] as String,
|
||||
choices: (json['choices'] as List).map((e) => e as String).toList(),
|
||||
answer: json['answer'] ?? json['correct_answer'] as String,
|
||||
spanDisplayDetails: json['span_display_details'] != null
|
||||
? RelevantSpanDisplayDetails.fromJson(json['span_display_details'])
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -36,6 +42,7 @@ class MultipleChoice {
|
|||
'question': question,
|
||||
'choices': choices,
|
||||
'answer': answer,
|
||||
'span_display_details': spanDisplayDetails,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fluffychat/pangea/enum/activity_display_instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/enum/construct_type_enum.dart';
|
||||
import 'package:fluffychat/pangea/models/practice_activities.dart/multiple_choice_activity_model.dart';
|
||||
|
|
@ -279,4 +281,58 @@ class PracticeActivityModel {
|
|||
'free_response': freeResponse?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
RelevantSpanDisplayDetails? getRelevantSpanDisplayDetails() {
|
||||
switch (activityType) {
|
||||
case ActivityTypeEnum.multipleChoice:
|
||||
return multipleChoice?.spanDisplayDetails;
|
||||
case ActivityTypeEnum.listening:
|
||||
return null;
|
||||
case ActivityTypeEnum.speaking:
|
||||
return null;
|
||||
case ActivityTypeEnum.freeResponse:
|
||||
return null;
|
||||
default:
|
||||
debugger(when: kDebugMode);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For those activities with a relevant span, this class will hold the details
|
||||
/// of the span and how it should be displayed
|
||||
/// e.g. hide the span for conjugation activities
|
||||
class RelevantSpanDisplayDetails {
|
||||
final int offset;
|
||||
final int length;
|
||||
final ActivityDisplayInstructionsEnum displayInstructions;
|
||||
|
||||
RelevantSpanDisplayDetails({
|
||||
required this.offset,
|
||||
required this.length,
|
||||
required this.displayInstructions,
|
||||
});
|
||||
|
||||
factory RelevantSpanDisplayDetails.fromJson(Map<String, dynamic> json) {
|
||||
final ActivityDisplayInstructionsEnum? display =
|
||||
ActivityDisplayInstructionsEnum.values.firstWhereOrNull(
|
||||
(e) => e.string == json['display_instructions'],
|
||||
);
|
||||
if (display == null) {
|
||||
debugger(when: kDebugMode);
|
||||
}
|
||||
return RelevantSpanDisplayDetails(
|
||||
offset: json['offset'] as int,
|
||||
length: json['length'] as int,
|
||||
displayInstructions: display ?? ActivityDisplayInstructionsEnum.hide,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'offset': offset,
|
||||
'length': length,
|
||||
'display_instructions': displayInstructions,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -420,7 +420,7 @@ class PangeaProfileResponse {
|
|||
|
||||
factory PangeaProfileResponse.fromJson(Map<String, dynamic> json) {
|
||||
return PangeaProfileResponse(
|
||||
profile: PangeaProfile.fromJson(json),
|
||||
profile: PangeaProfile.fromJson(json[ModelKey.userProfile]),
|
||||
access: json[ModelKey.userAccess],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,32 +17,25 @@ class PUserAgeView extends StatelessWidget {
|
|||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 10),
|
||||
padding: const EdgeInsets.all(15),
|
||||
child: Text(
|
||||
L10n.of(context)!.yourBirthdayPlease,
|
||||
textAlign: TextAlign.justify,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onSecondaryContainer
|
||||
.withAlpha(50),
|
||||
color: Theme.of(context).colorScheme.onSecondaryContainer.withAlpha(50),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(15),
|
||||
child: Text(
|
||||
L10n.of(context)!.yourBirthdayPlease,
|
||||
textAlign: TextAlign.justify,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context)!.certifyAge(13),
|
||||
|
|
@ -70,23 +63,16 @@ class PUserAgeView extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
if (controller.error != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Text(
|
||||
controller.error!,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Hero(
|
||||
tag: 'loginButton',
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: ElevatedButton(
|
||||
onPressed: controller.createUserInPangea,
|
||||
style: ElevatedButton.styleFrom(
|
||||
minimumSize: const Size.fromHeight(50),
|
||||
),
|
||||
child: controller.loading
|
||||
? const LinearProgressIndicator()
|
||||
: Text(L10n.of(context)!.getStarted),
|
||||
|
|
@ -95,7 +81,6 @@ class PUserAgeView extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
// ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:country_picker/country_picker.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/models/space_model.dart';
|
||||
|
|
@ -17,25 +15,26 @@ class SettingsLearning extends StatefulWidget {
|
|||
}
|
||||
|
||||
class SettingsLearningController extends State<SettingsLearning> {
|
||||
late StreamSubscription _userSubscription;
|
||||
PangeaController pangeaController = MatrixState.pangeaController;
|
||||
|
||||
Future<void> changeLanguage() async {
|
||||
await pLanguageDialog(context, () {});
|
||||
}
|
||||
|
||||
Future<void> setPublicProfile(bool isPublic) async {
|
||||
setPublicProfile(bool isPublic) {
|
||||
pangeaController.userController.updateProfile((profile) {
|
||||
profile.userSettings.publicProfile = isPublic;
|
||||
return profile;
|
||||
});
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Future<void> changeCountry(Country country) async {
|
||||
pangeaController.userController.updateProfile((profile) {
|
||||
void changeLanguage() {
|
||||
pLanguageDialog(context, () {}).then((_) => setState(() {}));
|
||||
}
|
||||
|
||||
void changeCountry(Country country) {
|
||||
pangeaController.userController.updateProfile((Profile profile) {
|
||||
profile.userSettings.country = country.displayNameNoCountryCode;
|
||||
return profile;
|
||||
});
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void updateToolSetting(ToolSetting toolSetting, bool value) {
|
||||
|
|
@ -71,12 +70,6 @@ class SettingsLearningController extends State<SettingsLearning> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_userSubscription.cancel();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SettingsLearningView(this);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/pangea/models/space_model.dart';
|
||||
import 'package:fluffychat/pangea/pages/settings_learning/settings_learning.dart';
|
||||
import 'package:fluffychat/pangea/utils/error_handler.dart';
|
||||
import 'package:fluffychat/pangea/widgets/user_settings/country_picker_tile.dart';
|
||||
import 'package:fluffychat/pangea/widgets/user_settings/language_tile.dart';
|
||||
import 'package:fluffychat/pangea/widgets/user_settings/p_settings_switch_list_tile.dart';
|
||||
import 'package:fluffychat/widgets/layouts/max_width_body.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
|
||||
import '../../../config/app_config.dart';
|
||||
|
||||
class SettingsLearningView extends StatelessWidget {
|
||||
final SettingsLearningController controller;
|
||||
|
|
@ -17,97 +14,75 @@ class SettingsLearningView extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// rebuild this page each time a sync comes through with new account data
|
||||
// this prevents having to call setState each time an individual setting is changed
|
||||
return StreamBuilder(
|
||||
stream:
|
||||
controller.pangeaController.matrixState.client.onSync.stream.where(
|
||||
(update) => update.accountData != null,
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
L10n.of(context)!.learningSettings,
|
||||
),
|
||||
),
|
||||
builder: (context, snapshot) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(
|
||||
L10n.of(context)!.learningSettings,
|
||||
),
|
||||
),
|
||||
body: ListTileTheme(
|
||||
iconColor: Theme.of(context).textTheme.bodyLarge!.color,
|
||||
child: MaxWidthBody(
|
||||
withScrolling: true,
|
||||
child: Column(
|
||||
children: [
|
||||
LanguageTile(controller),
|
||||
CountryPickerTile(controller),
|
||||
const SizedBox(height: 8),
|
||||
const Divider(height: 1),
|
||||
const SizedBox(height: 8),
|
||||
if (controller.pangeaController.permissionsController
|
||||
.isUser18())
|
||||
SwitchListTile.adaptive(
|
||||
activeColor: AppConfig.activeToggleColor,
|
||||
title: Text(L10n.of(context)!.publicProfileTitle),
|
||||
subtitle: Text(L10n.of(context)!.publicProfileDesc),
|
||||
value:
|
||||
controller.pangeaController.userController.isPublic,
|
||||
onChanged: (bool isPublicProfile) =>
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () =>
|
||||
controller.setPublicProfile(isPublicProfile),
|
||||
onError: (err) => ErrorHandler.logError(
|
||||
e: err,
|
||||
s: StackTrace.current,
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
subtitle:
|
||||
Text(L10n.of(context)!.toggleToolSettingsDescription),
|
||||
),
|
||||
for (final toolSetting in ToolSetting.values)
|
||||
ProfileSettingsSwitchListTile.adaptive(
|
||||
defaultValue: controller.getToolSetting(toolSetting),
|
||||
title: toolSetting.toolName(context),
|
||||
subtitle: toolSetting.toolDescription(context),
|
||||
onChange: (bool value) => controller.updateToolSetting(
|
||||
toolSetting,
|
||||
value,
|
||||
),
|
||||
),
|
||||
ProfileSettingsSwitchListTile.adaptive(
|
||||
defaultValue: controller.pangeaController.userController
|
||||
.profile.userSettings.itAutoPlay,
|
||||
title: L10n.of(context)!
|
||||
.interactiveTranslatorAutoPlaySliderHeader,
|
||||
subtitle:
|
||||
L10n.of(context)!.interactiveTranslatorAutoPlayDesc,
|
||||
onChange: (bool value) => controller
|
||||
.pangeaController.userController
|
||||
.updateProfile((profile) {
|
||||
profile.userSettings.itAutoPlay = value;
|
||||
return profile;
|
||||
}),
|
||||
),
|
||||
ProfileSettingsSwitchListTile.adaptive(
|
||||
defaultValue: controller.pangeaController.userController
|
||||
.profile.userSettings.autoPlayMessages,
|
||||
title: L10n.of(context)!.autoPlayTitle,
|
||||
subtitle: L10n.of(context)!.autoPlayDesc,
|
||||
onChange: (bool value) => controller
|
||||
.pangeaController.userController
|
||||
.updateProfile((profile) {
|
||||
profile.userSettings.autoPlayMessages = value;
|
||||
return profile;
|
||||
}),
|
||||
),
|
||||
],
|
||||
body: ListTileTheme(
|
||||
iconColor: Theme.of(context).textTheme.bodyLarge!.color,
|
||||
child: MaxWidthBody(
|
||||
withScrolling: true,
|
||||
child: Column(
|
||||
children: [
|
||||
LanguageTile(controller),
|
||||
CountryPickerTile(controller),
|
||||
const SizedBox(height: 8),
|
||||
const Divider(height: 1),
|
||||
const SizedBox(height: 8),
|
||||
if (controller.pangeaController.permissionsController.isUser18())
|
||||
SwitchListTile.adaptive(
|
||||
activeColor: AppConfig.activeToggleColor,
|
||||
title: Text(L10n.of(context)!.publicProfileTitle),
|
||||
subtitle: Text(L10n.of(context)!.publicProfileDesc),
|
||||
value: controller.pangeaController.userController.isPublic,
|
||||
onChanged: (bool isPublicProfile) =>
|
||||
controller.setPublicProfile(isPublicProfile),
|
||||
),
|
||||
ListTile(
|
||||
subtitle: Text(L10n.of(context)!.toggleToolSettingsDescription),
|
||||
),
|
||||
),
|
||||
for (final toolSetting in ToolSetting.values)
|
||||
ProfileSettingsSwitchListTile.adaptive(
|
||||
defaultValue: controller.getToolSetting(toolSetting),
|
||||
title: toolSetting.toolName(context),
|
||||
subtitle: toolSetting.toolDescription(context),
|
||||
onChange: (bool value) => controller.updateToolSetting(
|
||||
toolSetting,
|
||||
value,
|
||||
),
|
||||
),
|
||||
ProfileSettingsSwitchListTile.adaptive(
|
||||
defaultValue: controller.pangeaController.userController.profile
|
||||
.userSettings.itAutoPlay,
|
||||
title:
|
||||
L10n.of(context)!.interactiveTranslatorAutoPlaySliderHeader,
|
||||
subtitle: L10n.of(context)!.interactiveTranslatorAutoPlayDesc,
|
||||
onChange: (bool value) => controller
|
||||
.pangeaController.userController
|
||||
.updateProfile((profile) {
|
||||
profile.userSettings.itAutoPlay = value;
|
||||
return profile;
|
||||
}),
|
||||
),
|
||||
ProfileSettingsSwitchListTile.adaptive(
|
||||
defaultValue: controller.pangeaController.userController.profile
|
||||
.userSettings.autoPlayMessages,
|
||||
title: L10n.of(context)!.autoPlayTitle,
|
||||
subtitle: L10n.of(context)!.autoPlayDesc,
|
||||
onChange: (bool value) => controller
|
||||
.pangeaController.userController
|
||||
.updateProfile((profile) {
|
||||
profile.userSettings.autoPlayMessages = value;
|
||||
return profile;
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,23 +47,33 @@ class IgcRepo {
|
|||
tokens: [
|
||||
PangeaToken(
|
||||
text: PangeaTokenText(content: "This", offset: 0, length: 4),
|
||||
lemmas: [Lemma(form: "This", text: "this", saveVocab: true)],
|
||||
lemma: Lemma(form: "This", text: "this", saveVocab: true),
|
||||
pos: "DET",
|
||||
morph: {},
|
||||
),
|
||||
PangeaToken(
|
||||
text: PangeaTokenText(content: "be", offset: 5, length: 2),
|
||||
lemmas: [Lemma(form: "be", text: "be", saveVocab: true)],
|
||||
lemma: Lemma(form: "be", text: "be", saveVocab: true),
|
||||
pos: "VERB",
|
||||
morph: {},
|
||||
),
|
||||
PangeaToken(
|
||||
text: PangeaTokenText(content: "a", offset: 8, length: 1),
|
||||
lemmas: [],
|
||||
lemma: Lemma(form: "a", text: "a", saveVocab: true),
|
||||
pos: "DET",
|
||||
morph: {},
|
||||
),
|
||||
PangeaToken(
|
||||
text: PangeaTokenText(content: "sample", offset: 10, length: 6),
|
||||
lemmas: [],
|
||||
lemma: Lemma(form: "sample", text: "sample", saveVocab: true),
|
||||
pos: "NOUN",
|
||||
morph: {},
|
||||
),
|
||||
PangeaToken(
|
||||
text: PangeaTokenText(content: "text", offset: 17, length: 4),
|
||||
lemmas: [],
|
||||
lemma: Lemma(form: "text", text: "text", saveVocab: true),
|
||||
pos: "NOUN",
|
||||
morph: {},
|
||||
),
|
||||
],
|
||||
matches: [
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:fluffychat/pangea/enum/instructions_enum.dart';
|
||||
import 'package:fluffychat/pangea/utils/inline_tooltip.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -24,8 +25,9 @@ class InstructionsController {
|
|||
final Map<String, bool> _instructionsShown = {};
|
||||
|
||||
/// Returns true if the user requested this popup not be shown again
|
||||
bool? toggledOff(String key) =>
|
||||
_pangeaController.pStoreService.read(key.toString());
|
||||
bool? toggledOff(String key) => InstructionsEnum.values
|
||||
.firstWhereOrNull((value) => value.toString() == key)
|
||||
?.toggledOff;
|
||||
|
||||
InstructionsController(PangeaController pangeaController) {
|
||||
_pangeaController = pangeaController;
|
||||
|
|
@ -33,19 +35,32 @@ class InstructionsController {
|
|||
|
||||
/// Returns true if the instructions were closed
|
||||
/// or turned off by the user via the toggle switch
|
||||
bool wereInstructionsTurnedOff(String key) =>
|
||||
toggledOff(key) ?? _instructionsClosed[key] ?? false;
|
||||
bool wereInstructionsTurnedOff(String key) {
|
||||
return toggledOff(key) ?? _instructionsClosed[key] ?? false;
|
||||
}
|
||||
|
||||
void turnOffInstruction(String key) => _instructionsClosed[key] = true;
|
||||
|
||||
Future<void> updateEnableInstructions(
|
||||
void updateEnableInstructions(
|
||||
String key,
|
||||
bool value,
|
||||
) async =>
|
||||
await _pangeaController.pStoreService.save(
|
||||
key,
|
||||
value,
|
||||
);
|
||||
) {
|
||||
_pangeaController.userController.updateProfile((profile) {
|
||||
if (key == InstructionsEnum.itInstructions.toString()) {
|
||||
profile.instructionSettings.showedItInstructions = value;
|
||||
}
|
||||
if (key == InstructionsEnum.clickMessage.toString()) {
|
||||
profile.instructionSettings.showedClickMessage = value;
|
||||
}
|
||||
if (key == InstructionsEnum.blurMeansTranslate.toString()) {
|
||||
profile.instructionSettings.showedBlurMeansTranslate = value;
|
||||
}
|
||||
if (key == InstructionsEnum.tooltipInstructions.toString()) {
|
||||
profile.instructionSettings.showedTooltipInstructions = value;
|
||||
}
|
||||
return profile;
|
||||
});
|
||||
}
|
||||
|
||||
/// Instruction Card gives users tips on
|
||||
/// how to use Pangea Chat's features
|
||||
|
|
@ -170,7 +185,7 @@ class InstructionsToggleState extends State<InstructionsToggle> {
|
|||
widget.instructionsKey.toString(),
|
||||
),
|
||||
onChanged: ((value) async {
|
||||
await pangeaController.instructions.updateEnableInstructions(
|
||||
pangeaController.instructions.updateEnableInstructions(
|
||||
widget.instructionsKey.toString(),
|
||||
value,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -193,6 +193,8 @@ class MessageToolbarState extends State<MessageToolbar> {
|
|||
late StreamSubscription<MessageMode> toolbarModeStream;
|
||||
|
||||
void updateMode(MessageMode newMode) {
|
||||
//Early exit from the function if the widget has been unmounted to prevent updates on an inactive widget.
|
||||
if (!mounted) return;
|
||||
if (updatingMode) return;
|
||||
debugPrint("updating toolbar mode");
|
||||
final bool subscribed =
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:country_picker/country_picker.dart';
|
||||
import 'package:fluffychat/pangea/controllers/pangea_controller.dart';
|
||||
import 'package:fluffychat/pangea/pages/settings_learning/settings_learning.dart';
|
||||
import 'package:fluffychat/pangea/utils/country_display.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||
|
||||
import '../../models/user_model.dart';
|
||||
|
||||
|
|
@ -21,30 +17,26 @@ class CountryPickerTile extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Profile profile = pangeaController.userController.profile;
|
||||
|
||||
final String displayName = CountryDisplayUtil.countryDisplayName(
|
||||
profile.userSettings.country,
|
||||
context,
|
||||
) ??
|
||||
'';
|
||||
|
||||
final String flag = CountryDisplayUtil.flagEmoji(
|
||||
profile.userSettings.country,
|
||||
);
|
||||
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"${L10n.of(context)!.countryInformation}: ${CountryDisplayUtil.countryDisplayName(
|
||||
profile.userSettings.country,
|
||||
context,
|
||||
) ?? ''} ${CountryDisplayUtil.flagEmoji(profile.userSettings.country)}",
|
||||
"${L10n.of(context)!.countryInformation}: $displayName $flag",
|
||||
),
|
||||
trailing: const Icon(Icons.edit_outlined),
|
||||
onTap: () => showCountryPicker(
|
||||
context: context,
|
||||
showPhoneCode:
|
||||
false, // optional. Shows phone code before the country name.
|
||||
onSelect: (Country country) async {
|
||||
showFutureLoadingDialog(
|
||||
context: context,
|
||||
future: () async {
|
||||
try {
|
||||
learningController.changeCountry(country);
|
||||
} catch (err) {
|
||||
debugger(when: kDebugMode);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
showPhoneCode: false,
|
||||
onSelect: learningController.changeCountry,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,10 @@ import '../../../widgets/matrix.dart';
|
|||
import 'p_language_dropdown.dart';
|
||||
import 'p_question_container.dart';
|
||||
|
||||
pLanguageDialog(BuildContext parentContext, Function callback) async {
|
||||
Future<void> pLanguageDialog(
|
||||
BuildContext parentContext,
|
||||
Function callback,
|
||||
) async {
|
||||
final PangeaController pangeaController = MatrixState.pangeaController;
|
||||
//PTODO: if source language not set by user, default to languge from device settings
|
||||
final LanguageModel? userL1 = pangeaController.languageController.userL1;
|
||||
|
|
|
|||
|
|
@ -11,57 +11,67 @@ class ErrorReporter {
|
|||
void onErrorCallback(Object error, [StackTrace? stackTrace]) async {
|
||||
Logs().e(message ?? 'Error caught', error, stackTrace);
|
||||
// #Pangea
|
||||
// Attempt to retrieve the L10n instance using the current context
|
||||
final L10n? l10n = L10n.of(context);
|
||||
|
||||
// Check if the L10n instance is null
|
||||
if (l10n == null) {
|
||||
// Log an error message saying that the localization object is null
|
||||
Logs().e('Localization object is null, cannot show error message.');
|
||||
// Exits early to prevent further execution
|
||||
return;
|
||||
}
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
L10n.of(context)!.oopsSomethingWentWrong,
|
||||
l10n.oopsSomethingWentWrong, // Use the non-null L10n instance to get the error message
|
||||
),
|
||||
),
|
||||
);
|
||||
// final text = '$error\n${stackTrace ?? ''}';
|
||||
// await showAdaptiveDialog(
|
||||
// context: context,
|
||||
// builder: (context) => AlertDialog.adaptive(
|
||||
// title: Text(L10n.of(context)!.reportErrorDescription),
|
||||
// content: SizedBox(
|
||||
// height: 256,
|
||||
// width: 256,
|
||||
// child: SingleChildScrollView(
|
||||
// child: HighlightView(
|
||||
// text,
|
||||
// language: 'sh',
|
||||
// theme: shadesOfPurpleTheme,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// actions: [
|
||||
// TextButton(
|
||||
// onPressed: () => Navigator.of(context).pop(),
|
||||
// child: Text(L10n.of(context)!.close),
|
||||
// ),
|
||||
// TextButton(
|
||||
// onPressed: () => Clipboard.setData(
|
||||
// ClipboardData(text: text),
|
||||
// ),
|
||||
// child: Text(L10n.of(context)!.copy),
|
||||
// ),
|
||||
// TextButton(
|
||||
// onPressed: () => launchUrl(
|
||||
// AppConfig.newIssueUrl.resolveUri(
|
||||
// Uri(
|
||||
// queryParameters: {
|
||||
// 'template': 'bug_report.yaml',
|
||||
// 'title': '[BUG]: ${message ?? error.toString()}',
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// mode: LaunchMode.externalApplication,
|
||||
// ),
|
||||
// child: Text(L10n.of(context)!.report),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// Pangea#
|
||||
}
|
||||
// final text = '$error\n${stackTrace ?? ''}';
|
||||
// await showAdaptiveDialog(
|
||||
// context: context,
|
||||
// builder: (context) => AlertDialog.adaptive(
|
||||
// title: Text(L10n.of(context)!.reportErrorDescription),
|
||||
// content: SizedBox(
|
||||
// height: 256,
|
||||
// width: 256,
|
||||
// child: SingleChildScrollView(
|
||||
// child: HighlightView(
|
||||
// text,
|
||||
// language: 'sh',
|
||||
// theme: shadesOfPurpleTheme,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// actions: [
|
||||
// TextButton(
|
||||
// onPressed: () => Navigator.of(context).pop(),
|
||||
// child: Text(L10n.of(context)!.close),
|
||||
// ),
|
||||
// TextButton(
|
||||
// onPressed: () => Clipboard.setData(
|
||||
// ClipboardData(text: text),
|
||||
// ),
|
||||
// child: Text(L10n.of(context)!.copy),
|
||||
// ),
|
||||
// TextButton(
|
||||
// onPressed: () => launchUrl(
|
||||
// AppConfig.newIssueUrl.resolveUri(
|
||||
// Uri(
|
||||
// queryParameters: {
|
||||
// 'template': 'bug_report.yaml',
|
||||
// 'title': '[BUG]: ${message ?? error.toString()}',
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// mode: LaunchMode.externalApplication,
|
||||
// ),
|
||||
// child: Text(L10n.of(context)!.report),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// Pangea#
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue