Add search results & search store

This commit is contained in:
tommyxchow 2021-11-14 04:21:39 -05:00
parent 6b40f9e76f
commit 0bbf7f80d4
3 changed files with 177 additions and 38 deletions

View file

@ -1,7 +1,8 @@
import 'package:flutter/material.dart';
import 'package:frosty/api/twitch_api.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:frosty/screens/video_chat.dart';
import 'package:frosty/stores/auth_store.dart';
import 'package:frosty/stores/search_store.dart';
import 'package:provider/provider.dart';
class Search extends StatefulWidget {
@ -12,50 +13,93 @@ class Search extends StatefulWidget {
}
class _SearchState extends State<Search> {
final _textController = TextEditingController();
late final SearchStore searchStore;
@override
void initState() {
super.initState();
searchStore = SearchStore(authStore: context.read<AuthStore>());
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: TextField(
controller: _textController,
autocorrect: false,
decoration: const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.all(8.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
return Column(
children: [
Padding(
padding: const EdgeInsets.all(15.0),
child: TextField(
controller: searchStore.textController,
autocorrect: false,
decoration: const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.all(8.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
),
hintText: 'Search for a channel',
),
onSubmitted: searchStore.handleQuery,
),
hintText: 'Search for a channel',
),
onSubmitted: (string) async {
final user = await Twitch.getUser(userLogin: string, headers: context.read<AuthStore>().headersTwitch);
if (user != null) {
final channelInfo = await Twitch.getChannel(userId: user.id, headers: context.read<AuthStore>().headersTwitch);
if (channelInfo != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) {
return VideoChat(
userLogin: channelInfo.broadcasterLogin,
userName: channelInfo.broadcasterName,
Expanded(
child: Observer(
builder: (_) {
return ListView.builder(
itemCount: searchStore.searchResults.length + 1,
itemBuilder: (context, index) {
if (index == searchStore.searchResults.length) {
if (searchStore.textController.text.isEmpty) {
return const SizedBox();
}
return ListTile(
title: Text('Go to ${searchStore.textController.text}'),
onTap: () => searchStore.handleSearch(searchStore.textController.text, context),
);
},
),
}
final channel = searchStore.searchResults[index];
return ListTile(
title: Text(channel.displayName),
trailing: channel.isLive
? ClipRRect(
borderRadius: BorderRadius.circular(5.0),
child: Container(
color: Colors.red,
padding: const EdgeInsets.all(8.0),
child: const Text(
'LIVE',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
)
: null,
subtitle: channel.isLive ? Text('Uptime: ${DateTime.now().difference(DateTime.parse(channel.startedAt)).toString().split('.')[0]}') : null,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) {
return VideoChat(
userLogin: channel.broadcasterLogin,
userName: channel.displayName,
);
},
),
);
},
);
},
);
} else {
const snackBar = SnackBar(content: Text('Failed to get channel info :('));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
} else {
const snackBar = SnackBar(content: Text('User does not exist :('));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
_textController.clear();
},
),
},
),
),
],
);
}
@override
void dispose() {
searchStore.dispose();
super.dispose();
}
}

View file

@ -0,0 +1,62 @@
import 'package:flutter/material.dart';
import 'package:frosty/api/twitch_api.dart';
import 'package:frosty/models/channel.dart';
import 'package:frosty/screens/video_chat.dart';
import 'package:frosty/stores/auth_store.dart';
import 'package:mobx/mobx.dart';
import 'package:provider/provider.dart';
part 'search_store.g.dart';
class SearchStore = _SearchStoreBase with _$SearchStore;
abstract class _SearchStoreBase with Store {
final textController = TextEditingController();
final AuthStore authStore;
@observable
var _searchResults = ObservableList<ChannelQuery>();
ObservableList<ChannelQuery> get searchResults => _searchResults;
_SearchStoreBase({required this.authStore});
@action
Future<void> handleQuery(String query) async {
final results = await Twitch.searchChannels(query: query, headers: authStore.headersTwitch);
results.sort((c1, c2) => c2.isLive ? 1 : -1);
_searchResults = ObservableList.of(results);
}
Future<void> handleSearch(String search, BuildContext context) async {
final user = await Twitch.getUser(userLogin: search, headers: authStore.headersTwitch);
if (user != null) {
final channelInfo = await Twitch.getChannel(userId: user.id, headers: context.read<AuthStore>().headersTwitch);
if (channelInfo != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) {
return VideoChat(
userLogin: channelInfo.broadcasterLogin,
userName: channelInfo.broadcasterName,
);
},
),
);
} else {
const snackBar = SnackBar(content: Text('Failed to get channel info :('));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
} else {
const snackBar = SnackBar(content: Text('User does not exist :('));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
textController.clear();
}
void dispose() {
textController.dispose();
}
}

View file

@ -0,0 +1,33 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'search_store.dart';
// **************************************************************************
// StoreGenerator
// **************************************************************************
// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
mixin _$SearchStore on _SearchStoreBase, Store {
final _$_searchResultsAtom = Atom(name: '_SearchStoreBase._searchResults');
@override
ObservableList<ChannelQuery> get _searchResults {
_$_searchResultsAtom.reportRead();
return super._searchResults;
}
@override
set _searchResults(ObservableList<ChannelQuery> value) {
_$_searchResultsAtom.reportWrite(value, super._searchResults, () {
super._searchResults = value;
});
}
@override
String toString() {
return '''
''';
}
}