From 23661c684b71d5d5969c33109469a6fcde5bbf75 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Sat, 10 Sep 2022 03:08:54 -0400 Subject: [PATCH] fix: rank online higher, fix results persistence (#705) * fix: rank online higher * fix flash of unstyled content * make stateful to persist --- lib/components/channel_search_results.dart | 86 ++++++++++++++-------- 1 file changed, 55 insertions(+), 31 deletions(-) diff --git a/lib/components/channel_search_results.dart b/lib/components/channel_search_results.dart index 2adbb338e..115556382 100644 --- a/lib/components/channel_search_results.dart +++ b/lib/components/channel_search_results.dart @@ -35,6 +35,33 @@ Future> fastSearch() async { }).toList(); } +Stream> search(String query, bool isShowOnlyOnline) async* { + final fast = await fastSearch(); + final fastFiltered = fast.where((result) => + result.displayName.toLowerCase().contains(query.toLowerCase())); + final fastRanked = [ + ...fastFiltered.where((element) => element.isOnline), + ...fastFiltered.where((element) => !element.isOnline) + ].take(5); + yield fastRanked.toList(); + final slow = await _search(query).then((result) { + return (result.data as List) + .map((data) => SearchResult( + channelId: data['channelId'], + provider: data['provider'], + displayName: data['displayName'], + isOnline: data['isOnline'], + imageUrl: Uri.parse(data['imageUrl']), + title: data['title'], + isPromoted: false)) + .toList(); + }); + final slowFiltered = slow.where((result) => + !fastFiltered.any((element) => element.channelId == result.channelId) && + (!isShowOnlyOnline || result.isOnline)); + yield [...fastRanked, ...slowFiltered]; +} + final url = Uri.https('chat.rtirl.com', '/auth/twitch/redirect'); class SearchResult { @@ -56,14 +83,13 @@ class SearchResult { required this.isPromoted}); } -class ChannelSearchResultsWidget extends StatelessWidget { +class ChannelSearchResultsWidget extends StatefulWidget { final String query; + final bool isShowOnlyOnline; final Function(Channel) onChannelSelect; final ScrollController? controller; - final Future> _fastSearch = fastSearch(); - final bool isShowOnlyOnline; - ChannelSearchResultsWidget( + const ChannelSearchResultsWidget( {Key? key, required this.query, required this.onChannelSelect, @@ -71,39 +97,37 @@ class ChannelSearchResultsWidget extends StatelessWidget { this.controller}) : super(key: key); - Stream> search() async* { - final fast = await _fastSearch; - final fastFiltered = fast - .where((result) => - result.displayName.toLowerCase().contains(query.toLowerCase()) && - (!isShowOnlyOnline || result.isOnline)) - .take(5); - yield fastFiltered.toList(); - final slow = await _search(query).then((result) { - return (result.data as List) - .map((data) => SearchResult( - channelId: data['channelId'], - provider: data['provider'], - displayName: data['displayName'], - isOnline: data['isOnline'], - imageUrl: Uri.parse(data['imageUrl']), - title: data['title'], - isPromoted: false)) - .toList(); - }); - final slowFiltered = slow.where((result) => - !fastFiltered.any((element) => element.channelId == result.channelId) && - (!isShowOnlyOnline || result.isOnline)); - yield [...fastFiltered, ...slowFiltered]; + @override + State createState() => + _ChannelSearchResultsWidgetState(); +} + +class _ChannelSearchResultsWidgetState + extends State { + late Stream> _results; + + @override + void initState() { + super.initState(); + _results = search(widget.query, widget.isShowOnlyOnline); + } + + @override + void didUpdateWidget(covariant ChannelSearchResultsWidget oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.query != widget.query || + oldWidget.isShowOnlyOnline != widget.isShowOnlyOnline) { + _results = search(widget.query, widget.isShowOnlyOnline); + } } @override Widget build(BuildContext context) { return ListView( - controller: controller, + controller: widget.controller, children: [ StreamBuilder>( - stream: search(), + stream: _results, builder: (context, snapshot) { return Column( children: (snapshot.data ?? []) @@ -145,7 +169,7 @@ class ChannelSearchResultsWidget extends StatelessWidget { title: Text(result.displayName), subtitle: Text(result.title), onTap: () { - onChannelSelect(Channel( + widget.onChannelSelect(Channel( "twitch", result.channelId, result.displayName,