chore: Swap seed for hyphen for not-yet-chosen emojis in analytics

This commit is contained in:
ggurdin 2025-12-18 12:49:56 -05:00
parent 4090bab64f
commit d2a539e4dd
No known key found for this signature in database
GPG key ID: A01CB41737CBB478
4 changed files with 61 additions and 127 deletions

View file

@ -44,18 +44,10 @@ class MorphDetailsView extends StatelessWidget {
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,
),
),
],
ConstructXpWidget(
icon: construct.lemmaCategory.icon(30.0),
level: construct.lemmaCategory,
points: construct.points,
),
Padding(
padding: const EdgeInsets.all(20.0),

View file

@ -8,11 +8,12 @@ import 'package:fluffychat/pangea/analytics_details_popup/word_text_with_audio_b
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
import 'package:fluffychat/pangea/events/models/pangea_token_text_model.dart';
import 'package:fluffychat/pangea/lemmas/construct_xp_widget.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
class VocabDetailsView extends StatelessWidget {
class VocabDetailsView extends StatefulWidget {
final ConstructIdentifier constructId;
const VocabDetailsView({
@ -20,6 +21,27 @@ class VocabDetailsView extends StatelessWidget {
required this.constructId,
});
@override
State<VocabDetailsView> createState() => VocabDetailsViewState();
}
class VocabDetailsViewState extends State<VocabDetailsView> {
ConstructIdentifier get constructId => widget.constructId;
final ValueNotifier<String?> _emojiNotifier = ValueNotifier<String?>(null);
@override
void initState() {
super.initState();
_emojiNotifier.value = constructId.userLemmaInfo.emojis?.firstOrNull;
}
@override
void dispose() {
_emojiNotifier.dispose();
super.dispose();
}
List<String> get forms =>
MatrixState.pangeaController.getAnalytics.constructListModel
.getConstructUsesByLemma(constructId.lemma)
@ -30,8 +52,6 @@ class VocabDetailsView extends StatelessWidget {
.whereType<String>()
.toList();
final double _iconSize = 24.0;
@override
Widget build(BuildContext context) {
final construct = constructId.constructUses;
@ -47,23 +67,22 @@ class VocabDetailsView extends StatelessWidget {
token: PangeaTokenText.fromString(constructId.lemma),
langCode: MatrixState.pangeaController.userController.userL2Code!,
construct: constructId,
setEmoji: (emoji) => _emojiNotifier.value = emoji,
),
Column(
children: [
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,
),
child: ConstructXpWidget(
icon: ValueListenableBuilder(
valueListenable: _emojiNotifier,
builder: (context, emoji, __) => Text(
emoji ?? "-",
style: const TextStyle(fontSize: 24.0),
),
],
),
level: construct.lemmaCategory,
points: construct.points,
),
),
Padding(

View file

@ -45,7 +45,7 @@ extension ConstructLevelEnumExt on ConstructLevelEnum {
}
}
String get svgURL {
String get _svgURL {
switch (this) {
case ConstructLevelEnum.seeds:
return "${AppConfig.assetsBaseURL}/${AnalyticsConstants.seedSvgFileName}";
@ -90,7 +90,7 @@ extension ConstructLevelEnumExt on ConstructLevelEnum {
}
Widget icon([double? size]) => CustomizedSvg(
svgUrl: svgURL,
svgUrl: _svgURL,
colorReplacements: const {},
errorIcon: Text(
emoji,

View file

@ -1,114 +1,37 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:fluffychat/pangea/analytics_misc/construct_use_model.dart';
import 'package:fluffychat/pangea/analytics_misc/get_analytics_controller.dart';
import 'package:fluffychat/pangea/constructs/construct_identifier.dart';
import 'package:fluffychat/pangea/constructs/construct_level_enum.dart';
import 'package:fluffychat/widgets/matrix.dart';
/// display the construct xp widget
/// listen to analytics stream and, if the lemmaCategory has changed,
/// animate the constructSvg by making it animate in then rise up and float away
class ConstructXpWidget extends StatefulWidget {
final ConstructIdentifier id;
final VoidCallback? onTap;
final double size;
class ConstructXpWidget extends StatelessWidget {
final ConstructLevelEnum level;
final int points;
final Widget icon;
const ConstructXpWidget({
super.key,
required this.id,
this.onTap,
this.size = 24.0,
required this.level,
required this.points,
required this.icon,
});
@override
ConstructXpWidgetState createState() => ConstructXpWidgetState();
}
class ConstructXpWidgetState extends State<ConstructXpWidget>
with SingleTickerProviderStateMixin {
ConstructLevelEnum? constructLemmaCategory;
bool didChange = false;
late AnimationController _controller;
StreamSubscription<AnalyticsStreamUpdate>? _sub;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this,
);
setState(() => constructLemmaCategory = constructUse?.lemmaCategory);
debugPrint('constructLemmaCategory: $constructLemmaCategory');
_sub = stream.listen((_) {
if (constructUse?.lemmaCategory != constructLemmaCategory) {
setState(() {
constructLemmaCategory = constructUse?.lemmaCategory;
didChange = true;
//_controller.reset();
//_controller.forward();
});
}
});
}
ConstructUses? get constructUse =>
MatrixState.pangeaController.getAnalytics.constructListModel
.getConstructUses(widget.id);
Stream<AnalyticsStreamUpdate> get stream =>
MatrixState.pangeaController.getAnalytics.analyticsStream.stream;
Widget? get svg => constructLemmaCategory?.icon();
@override
void dispose() {
_controller.dispose();
_sub?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: widget.size,
height: widget.size,
child: GestureDetector(
onTap: svg != null ? widget.onTap : null,
child: MouseRegion(
cursor:
svg != null ? SystemMouseCursors.click : SystemMouseCursors.basic,
child: Stack(
alignment: Alignment.center,
children: [
//replaces rise animation, remove 116 and uncomment everything to revert
svg != null ? svg! : const SizedBox.shrink(),
// AnimatedSwitcher(
// duration: const Duration(milliseconds: 1000),
// child: svg,
// ),
// if (didChange)
// SlideTransition(
// position: _offsetAnimation,
// child: FadeTransition(
// opacity: _fadeAnimation,
// child: svg,
// ),
// ),
],
),
final Color textColor = Theme.of(context).brightness != Brightness.light
? level.color(context)
: level.darkColor(context);
return Row(
spacing: 16.0,
mainAxisAlignment: MainAxisAlignment.center,
children: [
icon,
Text(
"$points XP",
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: textColor,
),
),
),
],
);
}
}