diff --git a/lib/pangea/analytics_details_popup/analytics_details_popup.dart b/lib/pangea/analytics_details_popup/analytics_details_popup.dart index f2ec166d0..53c6fe851 100644 --- a/lib/pangea/analytics_details_popup/analytics_details_popup.dart +++ b/lib/pangea/analytics_details_popup/analytics_details_popup.dart @@ -13,6 +13,7 @@ import 'package:fluffychat/pangea/analytics_summary/progress_indicators_enum.dar import 'package:fluffychat/pangea/common/utils/error_handler.dart'; import 'package:fluffychat/pangea/common/widgets/full_width_dialog.dart'; import 'package:fluffychat/pangea/constructs/construct_identifier.dart'; +import 'package:fluffychat/pangea/constructs/construct_level_enum.dart'; import 'package:fluffychat/pangea/morphs/default_morph_mapping.dart'; import 'package:fluffychat/pangea/morphs/morph_models.dart'; import 'package:fluffychat/pangea/morphs/morph_repo.dart'; @@ -36,17 +37,28 @@ class AnalyticsPopupWrapperState extends State { ConstructIdentifier? localConstructZoom; ConstructTypeEnum localView = ConstructTypeEnum.vocab; - // @ggurdin - //TODO: make language-specific MorphFeaturesAndTags morphs = defaultMorphMapping; List features = defaultMorphMapping.displayFeatures; + bool isSearching = false; + final TextEditingController searchController = TextEditingController(); + ConstructLevelEnum? selectedConstructLevel; + @override void initState() { super.initState(); localView = widget.view; - _setConstructZoom(widget.constructZoom); + setConstructZoom(widget.constructZoom); _setMorphs(); + searchController.addListener(() { + if (mounted) setState(() {}); + }); + } + + @override + void dispose() { + searchController.dispose(); + super.dispose(); } Future _setMorphs() async { @@ -70,7 +82,7 @@ class AnalyticsPopupWrapperState extends State { } } - void _setConstructZoom(ConstructIdentifier? id) { + void setConstructZoom(ConstructIdentifier? id) { if (id != null && id.type != localView) { localView = id.type; } @@ -78,6 +90,20 @@ class AnalyticsPopupWrapperState extends State { setState(() => {}); } + void setSelectedConstructLevel(ConstructLevelEnum level) { + setState(() { + selectedConstructLevel = selectedConstructLevel == level ? null : level; + }); + } + + void toggleSearching() { + setState(() { + isSearching = !isSearching; + selectedConstructLevel = null; + searchController.clear(); + }); + } + @override Widget build(BuildContext context) { return FullWidthDialog( @@ -96,7 +122,7 @@ class AnalyticsPopupWrapperState extends State { : const Icon(Icons.arrow_back), onPressed: localConstructZoom == null ? () => Navigator.of(context).pop() - : () => _setConstructZoom(null), + : () => setConstructZoom(null), ), actions: [ TextButton.icon( @@ -137,13 +163,10 @@ class AnalyticsPopupWrapperState extends State { ), body: localView == ConstructTypeEnum.morph ? localConstructZoom == null - ? MorphAnalyticsListView( - onConstructZoom: _setConstructZoom, - controller: this, - ) + ? MorphAnalyticsListView(controller: this) : MorphDetailsView(constructId: localConstructZoom!) : localConstructZoom == null - ? VocabAnalyticsListView(onConstructZoom: _setConstructZoom) + ? VocabAnalyticsListView(controller: this) : VocabDetailsView(constructId: localConstructZoom!), ), maxWidth: 600, diff --git a/lib/pangea/analytics_details_popup/morph_analytics_list_view.dart b/lib/pangea/analytics_details_popup/morph_analytics_list_view.dart index 55dd12a8e..5201b6eb1 100644 --- a/lib/pangea/analytics_details_popup/morph_analytics_list_view.dart +++ b/lib/pangea/analytics_details_popup/morph_analytics_list_view.dart @@ -17,11 +17,9 @@ import 'package:fluffychat/pangea/user/client_extension.dart'; import 'package:fluffychat/widgets/matrix.dart'; class MorphAnalyticsListView extends StatelessWidget { - final void Function(ConstructIdentifier) onConstructZoom; final AnalyticsPopupWrapperState controller; const MorphAnalyticsListView({ - required this.onConstructZoom, required this.controller, super.key, }); @@ -51,7 +49,7 @@ class MorphAnalyticsListView extends StatelessWidget { .getDisplayTags(feature.feature) .map((tag) => tag.toLowerCase()) .toSet(), - onConstructZoom: onConstructZoom, + onConstructZoom: controller.setConstructZoom, ) : const SizedBox.shrink(); }, diff --git a/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart b/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart index a47df1a51..7f3db077d 100644 --- a/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart +++ b/lib/pangea/analytics_details_popup/vocab_analytics_list_view.dart @@ -2,10 +2,10 @@ import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; +import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart'; import 'package:fluffychat/pangea/analytics_details_popup/vocab_analytics_list_tile.dart'; import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.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/instructions/instructions_enum.dart'; import 'package:fluffychat/pangea/instructions/instructions_inline_tooltip.dart'; @@ -13,51 +13,14 @@ import 'package:fluffychat/widgets/matrix.dart'; /// Displays vocab analytics, sorted into categories /// (flowers, greens, and seeds) by points -class VocabAnalyticsListView extends StatefulWidget { - final void Function(ConstructIdentifier) onConstructZoom; +class VocabAnalyticsListView extends StatelessWidget { + final AnalyticsPopupWrapperState controller; const VocabAnalyticsListView({ super.key, - required this.onConstructZoom, + required this.controller, }); - @override - VocabAnalyticsListViewState createState() => VocabAnalyticsListViewState(); -} - -class VocabAnalyticsListViewState extends State { - bool _isSearching = false; - final TextEditingController _searchController = TextEditingController(); - ConstructLevelEnum? _selectedConstructLevel; - - @override - void initState() { - super.initState(); - _searchController.addListener(() { - if (mounted) setState(() {}); - }); - } - - @override - void dispose() { - _searchController.dispose(); - super.dispose(); - } - - void _setSelectedConstructLevel(ConstructLevelEnum level) { - setState(() { - _selectedConstructLevel = _selectedConstructLevel == level ? null : level; - }); - } - - void _toggleSearching() { - setState(() { - _isSearching = !_isSearching; - _selectedConstructLevel = null; - _searchController.clear(); - }); - } - List get _vocab => MatrixState .pangeaController.getAnalytics.constructListModel .constructList(type: ConstructTypeEnum.vocab) @@ -67,13 +30,13 @@ class VocabAnalyticsListViewState extends State { .where( (use) => use.lemma.isNotEmpty && - (_selectedConstructLevel == null + (controller.selectedConstructLevel == null ? true - : use.lemmaCategory == _selectedConstructLevel) && - (_isSearching + : use.lemmaCategory == controller.selectedConstructLevel) && + (controller.isSearching ? use.lemma .toLowerCase() - .contains(_searchController.text.toLowerCase()) + .contains(controller.searchController.text.toLowerCase()) : true), ) .toList(); @@ -86,14 +49,16 @@ class VocabAnalyticsListViewState extends State { .where((e) => e.lemmaCategory == constructLevelCategory) .length; return InkWell( - onTap: () => _setSelectedConstructLevel(constructLevelCategory), + onTap: () => + controller.setSelectedConstructLevel(constructLevelCategory), customBorder: const CircleBorder(), child: Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: _selectedConstructLevel == constructLevelCategory - ? constructLevelCategory.color(context).withAlpha(50) - : null, + color: + controller.selectedConstructLevel == constructLevelCategory + ? constructLevelCategory.color(context).withAlpha(50) + : null, ), padding: const EdgeInsets.all(8.0), child: Badge( @@ -109,7 +74,7 @@ class VocabAnalyticsListViewState extends State { filters.add( IconButton( icon: const Icon(Icons.search_outlined), - onPressed: _toggleSearching, + onPressed: controller.toggleSearching, ), ); @@ -123,8 +88,9 @@ class VocabAnalyticsListViewState extends State { AnimatedContainer( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, - padding: - EdgeInsets.symmetric(horizontal: _isSearching ? 8.0 : 24.0), + padding: EdgeInsets.symmetric( + horizontal: controller.isSearching ? 8.0 : 24.0, + ), child: Container( height: 60, alignment: Alignment.center, @@ -139,7 +105,7 @@ class VocabAnalyticsListViewState extends State { opacity: animation, child: child, ), - child: _isSearching + child: controller.isSearching ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, key: const ValueKey('search'), @@ -147,7 +113,7 @@ class VocabAnalyticsListViewState extends State { Expanded( child: TextField( autofocus: true, - controller: _searchController, + controller: controller.searchController, decoration: const InputDecoration( contentPadding: EdgeInsets.symmetric( vertical: 6.0, @@ -160,7 +126,7 @@ class VocabAnalyticsListViewState extends State { ), IconButton( icon: const Icon(Icons.close), - onPressed: _toggleSearching, + onPressed: controller.toggleSearching, ), ], ) @@ -189,7 +155,7 @@ class VocabAnalyticsListViewState extends State { itemBuilder: (context, index) { final vocabItem = _filteredVocab[index]; return VocabAnalyticsListTile( - onTap: () => widget.onConstructZoom(vocabItem.id), + onTap: () => controller.setConstructZoom(vocabItem.id), constructUse: vocabItem, ); },