Skip to content

Commit

Permalink
Use filter chips instead of a filter menu
Browse files Browse the repository at this point in the history
  • Loading branch information
isaaclyman committed Sep 20, 2023
1 parent d0865f2 commit 0b3da82
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 88 deletions.
9 changes: 2 additions & 7 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ class _MainAppState extends State<MainApp> {
onFocusChange: (isFocused) => setState(() {
isSearchBarFocused = isFocused;
}),
filters: widget.dataRoot.searchables
.map((s) => s.category)
.toList(),
),
if (widget.searchManager.searchText.isNotEmpty)
Expanded(
Expand Down Expand Up @@ -121,27 +118,24 @@ class _MainAppState extends State<MainApp> {

class _SearchBlock extends StatelessWidget {
final void Function(bool) onFocusChange;
final List<String> filters;

const _SearchBlock({
required this.onFocusChange,
required this.filters,
});

@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
mainAxisSize: MainAxisSize.max,
children: [
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 450),
child: Padding(
padding: const EdgeInsets.only(left: 16, right: 16, top: 24),
child: CSearchBar(
onFocusChange: onFocusChange,
filters: filters,
),
),
),
Expand All @@ -154,6 +148,7 @@ class _SearchBlock extends StatelessWidget {
),
),
),
const CSearchFilters(),
],
);
}
Expand Down
169 changes: 90 additions & 79 deletions lib/search/search_bar.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import 'package:cypher_system_srd_lookup/events/event_handler.dart';
import 'package:cypher_system_srd_lookup/search/search_manager.dart';
import 'package:cypher_system_srd_lookup/theme/text.dart';
import 'package:cypher_system_srd_lookup/util/intersperse.dart';
import 'package:flutter/material.dart';

import 'package:cypher_system_srd_lookup/theme/colors.dart';
import 'package:provider/provider.dart';

class CSearchBar extends StatefulWidget {
final void Function(bool) onFocusChange;
final List<String> filters;

const CSearchBar({
super.key,
required this.onFocusChange,
required this.filters,
});

@override
Expand All @@ -22,13 +22,11 @@ class CSearchBar extends StatefulWidget {
class _CSearchBarState extends State<CSearchBar> {
final _controller = TextEditingController();
final _focusNode = FocusNode();
Map<String, bool> filterState = {};

@override
void initState() {
super.initState();
_focusNode.addListener(_onFocusChange);
filterState = {for (var filter in widget.filters) filter: true};

context.read<CSearchManager>().addListener(_onSearchChange);
}
Expand All @@ -44,8 +42,6 @@ class _CSearchBarState extends State<CSearchBar> {

void _onSearchChange() {
_controller.text = context.read<CSearchManager>().searchText;
// setState(() {
// });
}

void _onFocusChange() {
Expand All @@ -62,96 +58,111 @@ class _CSearchBarState extends State<CSearchBar> {

@override
Widget build(BuildContext context) {
return Consumer2<CEventHandler, CSearchManager>(
builder: (_, handler, searchManager, ___) => Row(
children: [
Expanded(
child: TextField(
autofocus: true,
controller: _controller,
decoration: InputDecoration(
border: _border(1),
contentPadding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 6,
),
enabledBorder: _border(1),
focusedBorder: _border(2),
labelText: "Search SRD",
suffixIcon: _controller.text.isEmpty
? null
: IconButton(
icon: const Icon(Icons.clear),
onPressed: () => setState(() {
_controller.clear();
handler.setSearchQuery("");
}),
tooltip: "Clear search",
),
),
focusNode: _focusNode,
onChanged: (value) => handler.setSearchQuery(value),
),
),
AnimatedSize(
duration: const Duration(milliseconds: 150),
child: !_focusNode.hasFocus || _controller.text.isNotEmpty
? _FilterMenu(
filterState: filterState,
onFilterChange: (filter, checked) => setState(() {
filterState[filter] = checked;
handler.setSearchFilters(filterState);
}),
)
: const SizedBox.shrink(),
return Consumer<CEventHandler>(
builder: (_, handler, ___) => TextField(
autofocus: true,
controller: _controller,
decoration: InputDecoration(
border: _border(1),
contentPadding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 6,
),
],
enabledBorder: _border(1),
focusedBorder: _border(2),
labelText: "Search SRD",
suffixIcon: _controller.text.isEmpty
? null
: IconButton(
icon: const Icon(Icons.clear),
onPressed: () => setState(() {
_controller.clear();
handler.setSearchQuery("");
}),
tooltip: "Clear search",
),
),
focusNode: _focusNode,
onChanged: (value) => handler.setSearchQuery(value),
),
);
}
}

class _FilterMenu extends StatefulWidget {
final Map<String, bool> filterState;
final void Function(String filter, bool checked) onFilterChange;

const _FilterMenu({
required this.filterState,
required this.onFilterChange,
});
class CSearchFilters extends StatefulWidget {
const CSearchFilters({super.key});

@override
State<_FilterMenu> createState() => _FilterMenuState();
State<CSearchFilters> createState() => _CSearchFiltersState();
}

class _FilterMenuState extends State<_FilterMenu> {
class _CSearchFiltersState extends State<CSearchFilters> {
@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
return MenuAnchor(
menuChildren: widget.filterState.entries
.map((kvp) => CheckboxMenuButton(
closeOnActivate: false,
onChanged: (checked) =>
widget.onFilterChange(kvp.key, checked ?? true),
value: kvp.value,
child: Text(kvp.key),
))
.toList(),
builder: (_, controller, ___) => IconButton(
icon: const Icon(Icons.tune),
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
tooltip: "Set filters",
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4,
),
child: ShaderMask(
shaderCallback: (rect) => const LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Colors.white,
Colors.transparent,
Colors.transparent,
Colors.white
],
stops: [0.0, 0.02, 0.9, 1.0],
).createShader(rect),
blendMode: BlendMode.dstOut,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 4,
),
child: Consumer2<CEventHandler, CSearchManager>(
builder: (_, handler, searchManager, __) => Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: searchManager.filterState.entries
.map<Widget>(
(kvp) => FilterChip(
label: Text(kvp.key),
labelPadding: const EdgeInsets.symmetric(
horizontal: 4,
vertical: 0,
),
labelStyle: context.text.filterChip,
selected: kvp.value,
onSelected: (value) {
final newFilters =
Map<String, bool>.from(searchManager.filterState);
newFilters[kvp.key] = value;
handler.setSearchFilters(newFilters);
},
),
)
.intersperse(
const Padding(
padding: EdgeInsets.symmetric(
horizontal: 4,
),
),
)
.toList(),
),
),
),
),
),
);
}
Expand Down
6 changes: 4 additions & 2 deletions lib/search/search_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class CSearchManager extends ChangeNotifier {
final CHasSearchables _root;

String searchText = "";
Map<String, bool> filterState = {};
Map<String, bool> filterState;
Iterable<CSearchResultCategory> results = [];
bool get hasResults => results.isNotEmpty;

Expand All @@ -17,7 +17,9 @@ class CSearchManager extends ChangeNotifier {
CSearchResult? get lastResult => pastResults.last;
bool get canGoBack => pastResults.isNotEmpty;

CSearchManager(this._root);
CSearchManager(this._root)
: filterState = Map.fromEntries(
_root.searchables.map((s) => MapEntry(s.category, true)));

void search() {
results = _getResults();
Expand Down
5 changes: 5 additions & 0 deletions lib/theme/text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class CThemeText {
fontWeight: FontWeight.w300,
);

final TextStyle filterChip = TextStyle(
color: cThemeColors.text,
fontSize: 12,
);

final TextStyle highlight = const TextStyle(
backgroundColor: Colors.yellow,
);
Expand Down

0 comments on commit 0b3da82

Please sign in to comment.