fix: accurate loading indicator for search, add button to clear search
parent
d5861bdb78
commit
a0e4edb508
|
@ -41,6 +41,7 @@ class _HomePageState extends State<HomePage>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
late AnimationController _controller;
|
late AnimationController _controller;
|
||||||
late LiveSearch liveSearch;
|
late LiveSearch liveSearch;
|
||||||
|
late TextEditingController _searchController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
@ -49,12 +50,14 @@ class _HomePageState extends State<HomePage>
|
||||||
vsync: this, // the SingleTickerProviderStateMixin
|
vsync: this, // the SingleTickerProviderStateMixin
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
);
|
);
|
||||||
|
_searchController = TextEditingController();
|
||||||
liveSearch = LiveSearch(widget.manager);
|
liveSearch = LiveSearch(widget.manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
|
_searchController.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +65,11 @@ class _HomePageState extends State<HomePage>
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: TextField(
|
title: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: _searchController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
hintText: "Search",
|
hintText: "Search",
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
|
@ -78,6 +85,23 @@ class _HomePageState extends State<HomePage>
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
AnimatedBuilder(
|
||||||
|
animation: _controller,
|
||||||
|
builder: (context, child) {
|
||||||
|
if (liveSearch.searchTerm.isEmpty) return Container();
|
||||||
|
return IconButton(
|
||||||
|
icon: const Icon(Icons.clear),
|
||||||
|
onPressed: () {
|
||||||
|
_searchController.clear();
|
||||||
|
liveSearch.updateSearch("");
|
||||||
|
_controller.reverse();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
actions: [HamburgerMenu(widget.manager)],
|
actions: [HamburgerMenu(widget.manager)],
|
||||||
),
|
),
|
||||||
body: SwipeTransition(
|
body: SwipeTransition(
|
||||||
|
|
|
@ -7,6 +7,8 @@ class DelayedFunctionCaller {
|
||||||
|
|
||||||
DelayedFunctionCaller(this.function, this.duration);
|
DelayedFunctionCaller(this.function, this.duration);
|
||||||
|
|
||||||
|
get scheduled => _timer != null && _timer!.isActive;
|
||||||
|
|
||||||
void call() {
|
void call() {
|
||||||
// If a timer is already active, return.
|
// If a timer is already active, return.
|
||||||
if (_timer != null && _timer!.isActive) {
|
if (_timer != null && _timer!.isActive) {
|
||||||
|
|
|
@ -9,32 +9,29 @@ class LiveSearch extends ChangeNotifier {
|
||||||
Duration minTimeBetweenRequests = const Duration(milliseconds: 200);
|
Duration minTimeBetweenRequests = const Duration(milliseconds: 200);
|
||||||
late final DelayedFunctionCaller _searchCaller;
|
late final DelayedFunctionCaller _searchCaller;
|
||||||
final MovieManager manager;
|
final MovieManager manager;
|
||||||
bool loading = false;
|
|
||||||
bool searchingOnline = false;
|
bool searchingOnline = false;
|
||||||
|
|
||||||
LiveSearch(this.manager) {
|
LiveSearch(this.manager) {
|
||||||
_searchCaller = DelayedFunctionCaller(searchOnline, minTimeBetweenRequests);
|
_searchCaller = DelayedFunctionCaller(searchOnline, minTimeBetweenRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get loading => searchingOnline || _searchCaller.scheduled;
|
||||||
|
|
||||||
void updateSearch(String search) {
|
void updateSearch(String search) {
|
||||||
searchTerm = search;
|
searchTerm = search;
|
||||||
if (searchTerm.isEmpty) {
|
if (searchTerm.isEmpty) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
searchResults = manager.localSearch(search);
|
searchResults = manager.localSearch(search);
|
||||||
loading = true;
|
|
||||||
_searchCaller.call();
|
_searchCaller.call();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void searchOnline() async {
|
void searchOnline() async {
|
||||||
if (searchTerm.isEmpty) {
|
if (searchTerm.isEmpty) {
|
||||||
loading = false;
|
|
||||||
notifyListeners();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (searchingOnline) {
|
if (searchingOnline) {
|
||||||
loading = true;
|
|
||||||
_searchCaller.call();
|
_searchCaller.call();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
return;
|
return;
|
||||||
|
@ -55,7 +52,6 @@ class LiveSearch extends ChangeNotifier {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} finally {
|
} finally {
|
||||||
searchingOnline = false;
|
searchingOnline = false;
|
||||||
loading = false;
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue