fluffychat/lib/pangea/lemmas/construct_xp_widget.dart
wcjord 0128ac42cd
Vocab-details-v2 (#2093)
* started activity in chat creation

* starting vocab tile display

* refactor(vocab_analytics_list): made into little tiles that show the user chosen emoji

* chore: comment out unused file

* chore: remove unused variable

* chore: make eventID nullable for constructs so users can set emoji from vocab details popup

---------

Co-authored-by: ggurdin <ggurdin@gmail.com>
Co-authored-by: ggurdin <46800240+ggurdin@users.noreply.github.com>
2025-03-10 10:33:39 -04:00

130 lines
3.4 KiB
Dart

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;
const ConstructXpWidget({
super.key,
required this.id,
this.onTap,
});
@override
ConstructXpWidgetState createState() => ConstructXpWidgetState();
}
class ConstructXpWidgetState extends State<ConstructXpWidget>
with SingleTickerProviderStateMixin {
ConstructLevelEnum? constructLemmaCategory;
bool didChange = false;
late AnimationController _controller;
late Animation<Offset> _offsetAnimation;
late Animation<double> _fadeAnimation;
StreamSubscription<AnalyticsStreamUpdate>? _sub;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this,
);
_offsetAnimation = Tween<Offset>(
begin: Offset.zero,
end: const Offset(0.0, -1.0),
).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.easeOut,
),
);
_fadeAnimation = Tween<double>(
begin: 1.0,
end: 0.0,
).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.easeOut,
),
);
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() ?? const SizedBox();
@override
void dispose() {
_controller.dispose();
_sub?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.onTap,
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Opacity(
opacity: constructLemmaCategory == null ? 0.2 : 1.0,
child: Stack(
alignment: Alignment.center,
children: [
AnimatedSwitcher(
duration: const Duration(milliseconds: 1000),
child: svg,
),
if (didChange)
SlideTransition(
position: _offsetAnimation,
child: FadeTransition(
opacity: _fadeAnimation,
child: svg,
),
),
],
),
),
),
);
}
}