feat: show word card in vocab details page
This commit is contained in:
parent
d8685841ed
commit
602020cb40
5 changed files with 175 additions and 247 deletions
|
|
@ -1,82 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/lemma_usage_dots.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/lemma_use_example_messages.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
|
||||
|
||||
class AnalyticsDetailsViewContent extends StatelessWidget {
|
||||
final Widget title;
|
||||
final Widget subtitle;
|
||||
final Widget headerContent;
|
||||
final Widget xpIcon;
|
||||
final ConstructIdentifier constructId;
|
||||
|
||||
const AnalyticsDetailsViewContent({
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.xpIcon,
|
||||
required this.headerContent,
|
||||
required this.constructId,
|
||||
super.key,
|
||||
});
|
||||
|
||||
ConstructUses get construct => constructId.constructUses;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Color textColor = (Theme.of(context).brightness != Brightness.light
|
||||
? construct.lemmaCategory.color(context)
|
||||
: construct.lemmaCategory.darkColor(context));
|
||||
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
title,
|
||||
const SizedBox(height: 16.0),
|
||||
subtitle,
|
||||
const SizedBox(height: 16.0),
|
||||
headerContent,
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 16.0),
|
||||
child: Divider(),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
xpIcon,
|
||||
const SizedBox(width: 16.0),
|
||||
Text(
|
||||
"${construct.points} XP",
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
children: [
|
||||
LemmaUseExampleMessages(construct: construct),
|
||||
...LearningSkillsEnum.values
|
||||
.where((v) => v.isVisible)
|
||||
.map((skill) {
|
||||
return LemmaUsageDots(
|
||||
construct: construct,
|
||||
category: skill,
|
||||
tooltip: skill.tooltip(context),
|
||||
icon: skill.icon,
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/lemma_usage_dots.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/lemma_use_example_messages.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/learning_skills_enum.dart';
|
||||
|
||||
class AnalyticsDetailsUsageContent extends StatelessWidget {
|
||||
final ConstructUses construct;
|
||||
|
||||
const AnalyticsDetailsUsageContent({
|
||||
required this.construct,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
LemmaUseExampleMessages(construct: construct),
|
||||
...LearningSkillsEnum.values.where((v) => v.isVisible).map((skill) {
|
||||
return LemmaUsageDots(
|
||||
construct: construct,
|
||||
category: skill,
|
||||
tooltip: skill.tooltip(context),
|
||||
icon: skill.icon,
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup_content.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_usage_content.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/morph_meaning_widget.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
|
||||
import 'package:fluffychat/pangea/lemmas/construct_xp_widget.dart';
|
||||
|
|
@ -18,31 +17,54 @@ class MorphDetailsView extends StatelessWidget {
|
|||
super.key,
|
||||
});
|
||||
|
||||
ConstructUses get _construct => constructId.constructUses;
|
||||
MorphFeaturesEnum get _morphFeature =>
|
||||
MorphFeaturesEnumExtension.fromString(constructId.category);
|
||||
String get _morphTag => constructId.lemma;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final construct = constructId.constructUses;
|
||||
final Color textColor = Theme.of(context).brightness != Brightness.light
|
||||
? _construct.lemmaCategory.color(context)
|
||||
: _construct.lemmaCategory.darkColor(context);
|
||||
? construct.lemmaCategory.color(context)
|
||||
: construct.lemmaCategory.darkColor(context);
|
||||
|
||||
return AnalyticsDetailsViewContent(
|
||||
subtitle: MorphFeatureDisplay(morphFeature: _morphFeature),
|
||||
title: MorphTagDisplay(
|
||||
morphFeature: _morphFeature,
|
||||
morphTag: _morphTag,
|
||||
textColor: textColor,
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
MorphTagDisplay(
|
||||
morphFeature: _morphFeature,
|
||||
morphTag: _morphTag,
|
||||
textColor: textColor,
|
||||
),
|
||||
MorphFeatureDisplay(morphFeature: _morphFeature),
|
||||
MorphMeaningWidget(
|
||||
feature: _morphFeature,
|
||||
tag: _morphTag,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
const Divider(),
|
||||
Row(
|
||||
spacing: 16.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
ConstructXpWidget(id: constructId),
|
||||
Text(
|
||||
"${construct.points} XP",
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: AnalyticsDetailsUsageContent(
|
||||
construct: construct,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
headerContent: MorphMeaningWidget(
|
||||
feature: _morphFeature,
|
||||
tag: _morphTag,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
xpIcon: ConstructXpWidget(id: constructId),
|
||||
constructId: constructId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,18 +3,12 @@ import 'package:flutter/material.dart';
|
|||
import 'package:collection/collection.dart';
|
||||
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup_content.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/vocab_details_emoji_selector.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_usage_content.dart';
|
||||
import 'package:fluffychat/pangea/analytics_details_popup/word_text_with_audio_button.dart';
|
||||
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
|
||||
import 'package:fluffychat/pangea/common/widgets/shrinkable_text.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
|
||||
import 'package:fluffychat/pangea/lemmas/lemma_meaning_widget.dart';
|
||||
import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_features_enum.dart';
|
||||
import 'package:fluffychat/pangea/morphs/morph_icon.dart';
|
||||
import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_widget.dart';
|
||||
import 'package:fluffychat/pangea/events/models/pangea_token_text_model.dart';
|
||||
import 'package:fluffychat/pangea/toolbar/word_card/word_zoom_widget.dart';
|
||||
import 'package:fluffychat/widgets/matrix.dart';
|
||||
|
||||
/// Displays information about selected lemma, and its usage
|
||||
|
|
@ -26,15 +20,9 @@ class VocabDetailsView extends StatelessWidget {
|
|||
required this.constructId,
|
||||
});
|
||||
|
||||
ConstructUses get _construct => constructId.constructUses;
|
||||
|
||||
/// Get the language code for the current lemma
|
||||
String? get _userL2 =>
|
||||
MatrixState.pangeaController.userController.userL2?.langCode;
|
||||
|
||||
List<String> get forms =>
|
||||
MatrixState.pangeaController.getAnalytics.constructListModel
|
||||
.getConstructUsesByLemma(_construct.lemma)
|
||||
.getConstructUsesByLemma(constructId.lemma)
|
||||
.map((e) => e.uses)
|
||||
.expand((element) => element)
|
||||
.map((e) => e.form?.toLowerCase())
|
||||
|
|
@ -46,140 +34,110 @@ class VocabDetailsView extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final construct = constructId.constructUses;
|
||||
final Color textColor = (Theme.of(context).brightness != Brightness.light
|
||||
? _construct.lemmaCategory.color(context)
|
||||
: _construct.lemmaCategory.darkColor(context));
|
||||
? construct.lemmaCategory.color(context)
|
||||
: construct.lemmaCategory.darkColor(context));
|
||||
|
||||
return AnalyticsDetailsViewContent(
|
||||
title: Column(
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
spacing: 16.0,
|
||||
children: [
|
||||
LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return ShrinkableText(
|
||||
text: _construct.lemma,
|
||||
maxWidth: constraints.maxWidth - 40.0,
|
||||
style: Theme.of(context).textTheme.headlineLarge?.copyWith(
|
||||
color: textColor,
|
||||
),
|
||||
);
|
||||
},
|
||||
WordZoomWidget(
|
||||
token: PangeaTokenText.fromString(constructId.lemma),
|
||||
langCode: MatrixState.pangeaController.userController.userL2Code!,
|
||||
construct: constructId,
|
||||
),
|
||||
if (MatrixState.pangeaController.userController.showTranscription)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: PhoneticTranscriptionWidget(
|
||||
text: _construct.lemma,
|
||||
textLanguage:
|
||||
MatrixState.pangeaController.userController.userL2!,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: textColor.withAlpha((0.7 * 255).toInt()),
|
||||
fontSize: 18,
|
||||
),
|
||||
iconSize: _iconSize * 0.8,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
subtitle: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 8.0,
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
getGrammarCopy(
|
||||
category: "POS",
|
||||
lemma: _construct.category,
|
||||
context: context,
|
||||
) ??
|
||||
_construct.lemma,
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
color: textColor,
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Row(
|
||||
spacing: 16.0,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
construct.lemmaCategory.icon(_iconSize + 6.0),
|
||||
Text(
|
||||
"${construct.points} XP",
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: _iconSize,
|
||||
height: _iconSize,
|
||||
child: MorphIcon(
|
||||
morphFeature: MorphFeaturesEnum.Pos,
|
||||
morphTag: _construct.category,
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: _VocabForms(
|
||||
lemma: constructId.lemma,
|
||||
forms: forms,
|
||||
textColor: textColor,
|
||||
),
|
||||
),
|
||||
AnalyticsDetailsUsageContent(
|
||||
construct: construct,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
Text(
|
||||
L10n.of(context).vocabEmoji,
|
||||
style: Theme.of(context).textTheme.labelMedium?.copyWith(
|
||||
fontStyle: FontStyle.italic,
|
||||
color: textColor,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: VocabDetailsEmojiSelector(constructId),
|
||||
),
|
||||
],
|
||||
),
|
||||
headerContent: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 10, 20, 20),
|
||||
child: Column(
|
||||
spacing: 8.0,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: _userL2 == null
|
||||
? Text(L10n.of(context).meaningNotFound)
|
||||
: LemmaMeaningWidget(
|
||||
constructId: constructId,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
leading: TextSpan(
|
||||
text: L10n.of(context).meaningSectionHeader,
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.start,
|
||||
runAlignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).formSectionHeader,
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6.0),
|
||||
...forms.mapIndexed(
|
||||
(i, form) => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
WordTextWithAudioButton(
|
||||
text: form,
|
||||
style:
|
||||
Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
color: textColor,
|
||||
),
|
||||
uniqueID: "$form-${_construct.lemma}-$i",
|
||||
langCode: _userL2!,
|
||||
),
|
||||
if (i != forms.length - 1) const Text(", "),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
xpIcon: _construct.lemmaCategory.icon(_iconSize + 6.0),
|
||||
constructId: constructId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _VocabForms extends StatelessWidget {
|
||||
final String lemma;
|
||||
final List<String> forms;
|
||||
final Color textColor;
|
||||
|
||||
const _VocabForms({
|
||||
required this.lemma,
|
||||
required this.forms,
|
||||
required this.textColor,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.start,
|
||||
runAlignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
L10n.of(context).formSectionHeader,
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6.0),
|
||||
...forms.mapIndexed(
|
||||
(i, form) => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
WordTextWithAudioButton(
|
||||
text: form,
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
color: textColor,
|
||||
),
|
||||
uniqueID: "$form-$lemma-$i",
|
||||
langCode:
|
||||
MatrixState.pangeaController.userController.userL2Code!,
|
||||
),
|
||||
if (i != forms.length - 1) const Text(", "),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:fluffychat/pangea/analytics_misc/text_loading_shimmer.dart';
|
|||
import 'package:fluffychat/pangea/common/widgets/error_indicator.dart';
|
||||
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
|
||||
import 'package:fluffychat/pangea/lemmas/lemma_meaning_builder.dart';
|
||||
import 'package:fluffychat/pangea/morphs/get_grammar_copy.dart';
|
||||
|
||||
class LemmaMeaningDisplay extends StatelessWidget {
|
||||
final String langCode;
|
||||
|
|
@ -38,15 +39,12 @@ class LemmaMeaningDisplay extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
if (constructId.lemma.toLowerCase() == text.toLowerCase()) {
|
||||
return Text(
|
||||
controller.lemmaInfo!.meaning,
|
||||
style: const TextStyle(
|
||||
fontSize: 14.0,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
}
|
||||
final pos = getGrammarCopy(
|
||||
category: "POS",
|
||||
lemma: constructId.category,
|
||||
context: context,
|
||||
) ??
|
||||
L10n.of(context).other;
|
||||
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
|
|
@ -55,7 +53,7 @@ class LemmaMeaningDisplay extends StatelessWidget {
|
|||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: constructId.lemma,
|
||||
text: "${constructId.lemma} ($pos)",
|
||||
),
|
||||
const WidgetSpan(
|
||||
child: SizedBox(width: 8.0),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue