chore: maintain state of filtering / search when navigating between vocab list and vocab details (#2316)
This commit is contained in:
parent
8b9fce8e56
commit
f1106e0aa8
3 changed files with 56 additions and 69 deletions
|
|
@ -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<AnalyticsPopupWrapper> {
|
|||
ConstructIdentifier? localConstructZoom;
|
||||
ConstructTypeEnum localView = ConstructTypeEnum.vocab;
|
||||
|
||||
// @ggurdin
|
||||
//TODO: make language-specific
|
||||
MorphFeaturesAndTags morphs = defaultMorphMapping;
|
||||
List<MorphFeature> 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<void> _setMorphs() async {
|
||||
|
|
@ -70,7 +82,7 @@ class AnalyticsPopupWrapperState extends State<AnalyticsPopupWrapper> {
|
|||
}
|
||||
}
|
||||
|
||||
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<AnalyticsPopupWrapper> {
|
|||
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<AnalyticsPopupWrapper> {
|
|||
: 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<AnalyticsPopupWrapper> {
|
|||
),
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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<VocabAnalyticsListView> {
|
||||
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<ConstructUses> get _vocab => MatrixState
|
||||
.pangeaController.getAnalytics.constructListModel
|
||||
.constructList(type: ConstructTypeEnum.vocab)
|
||||
|
|
@ -67,13 +30,13 @@ class VocabAnalyticsListViewState extends State<VocabAnalyticsListView> {
|
|||
.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<VocabAnalyticsListView> {
|
|||
.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<VocabAnalyticsListView> {
|
|||
filters.add(
|
||||
IconButton(
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
onPressed: _toggleSearching,
|
||||
onPressed: controller.toggleSearching,
|
||||
),
|
||||
);
|
||||
|
||||
|
|
@ -123,8 +88,9 @@ class VocabAnalyticsListViewState extends State<VocabAnalyticsListView> {
|
|||
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<VocabAnalyticsListView> {
|
|||
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<VocabAnalyticsListView> {
|
|||
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<VocabAnalyticsListView> {
|
|||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: _toggleSearching,
|
||||
onPressed: controller.toggleSearching,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
@ -189,7 +155,7 @@ class VocabAnalyticsListViewState extends State<VocabAnalyticsListView> {
|
|||
itemBuilder: (context, index) {
|
||||
final vocabItem = _filteredVocab[index];
|
||||
return VocabAnalyticsListTile(
|
||||
onTap: () => widget.onConstructZoom(vocabItem.id),
|
||||
onTap: () => controller.setConstructZoom(vocabItem.id),
|
||||
constructUse: vocabItem,
|
||||
);
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue