Combine top and categories stores into one
This commit is contained in:
parent
8eb7f36ab1
commit
1f2b99dfce
9 changed files with 78 additions and 69 deletions
|
|
@ -92,18 +92,14 @@ class MyApp extends StatelessWidget {
|
|||
title: 'Frosty',
|
||||
theme: settingsStore.useOledTheme ? oledTheme : defaultTheme,
|
||||
home: Home(
|
||||
topStreamsStore: ListStore(
|
||||
topSectionStore: ListStore(
|
||||
authStore: authStore,
|
||||
listType: StreamListType.top,
|
||||
),
|
||||
categoriesStore: ListStore(
|
||||
authStore: authStore,
|
||||
listType: StreamListType.categories,
|
||||
listType: ListType.top,
|
||||
),
|
||||
followedStreamsStore: authStore.isLoggedIn
|
||||
? ListStore(
|
||||
authStore: authStore,
|
||||
listType: StreamListType.followed,
|
||||
listType: ListType.followed,
|
||||
)
|
||||
: null,
|
||||
searchStore: SearchStore(authStore: authStore),
|
||||
|
|
|
|||
|
|
@ -11,15 +11,13 @@ import 'package:frosty/screens/settings/stores/settings_store.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
final ListStore topStreamsStore;
|
||||
final ListStore categoriesStore;
|
||||
final ListStore topSectionStore;
|
||||
final SearchStore searchStore;
|
||||
final ListStore? followedStreamsStore;
|
||||
|
||||
const Home({
|
||||
Key? key,
|
||||
required this.topStreamsStore,
|
||||
required this.categoriesStore,
|
||||
required this.topSectionStore,
|
||||
required this.searchStore,
|
||||
required this.followedStreamsStore,
|
||||
}) : super(key: key);
|
||||
|
|
@ -77,10 +75,7 @@ class _HomeState extends State<Home> {
|
|||
index: _selectedIndex,
|
||||
children: [
|
||||
if (authStore.isLoggedIn) StreamsList(store: widget.followedStreamsStore!),
|
||||
TopSection(
|
||||
topStreamsStore: widget.topStreamsStore,
|
||||
categoriesStore: widget.categoriesStore,
|
||||
),
|
||||
TopSection(topSectionStore: widget.topSectionStore),
|
||||
Search(searchStore: widget.searchStore),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -21,17 +21,20 @@ abstract class _ListStoreBase with Store {
|
|||
bool _isLoading = false;
|
||||
|
||||
/// The pagination cursor for the streams.
|
||||
String? _currentCursor;
|
||||
String? _streamsCursor;
|
||||
|
||||
StreamListType listType;
|
||||
/// The pagination cursor for the categories.
|
||||
String? _categoriesCursor;
|
||||
|
||||
final CategoryTwitch? categoryInfo;
|
||||
|
||||
final ListType listType;
|
||||
|
||||
/// The authentication store.
|
||||
final AuthStore authStore;
|
||||
|
||||
/// Returns whether or not there are more streams and loading status for pagination.
|
||||
bool get hasMore => _isLoading == false && _currentCursor != null;
|
||||
bool get hasMore => _isLoading == false && _streamsCursor != null;
|
||||
|
||||
_ListStoreBase({
|
||||
required this.authStore,
|
||||
|
|
@ -39,59 +42,55 @@ abstract class _ListStoreBase with Store {
|
|||
this.categoryInfo,
|
||||
}) {
|
||||
switch (listType) {
|
||||
case StreamListType.followed:
|
||||
if (listType == StreamListType.followed && authStore.isLoggedIn) {
|
||||
getData();
|
||||
}
|
||||
case ListType.followed:
|
||||
if (listType == ListType.followed && authStore.isLoggedIn) getStreams();
|
||||
break;
|
||||
case StreamListType.top:
|
||||
case StreamListType.category:
|
||||
getData();
|
||||
case ListType.top:
|
||||
getStreams();
|
||||
getCategories();
|
||||
break;
|
||||
case StreamListType.categories:
|
||||
getGames();
|
||||
case ListType.category:
|
||||
getStreams();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches the streams based on the type and current cursor.
|
||||
@action
|
||||
Future<void> getData() async {
|
||||
Future<void> getStreams() async {
|
||||
_isLoading = true;
|
||||
|
||||
final StreamsTwitch? newStreams;
|
||||
switch (listType) {
|
||||
case StreamListType.followed:
|
||||
case ListType.followed:
|
||||
newStreams = await Twitch.getFollowedStreams(
|
||||
id: authStore.user.details!.id,
|
||||
headers: authStore.headersTwitch,
|
||||
cursor: _currentCursor,
|
||||
cursor: _streamsCursor,
|
||||
);
|
||||
break;
|
||||
case StreamListType.top:
|
||||
case ListType.top:
|
||||
newStreams = await Twitch.getTopStreams(
|
||||
headers: authStore.headersTwitch,
|
||||
cursor: _currentCursor,
|
||||
cursor: _streamsCursor,
|
||||
);
|
||||
break;
|
||||
case StreamListType.category:
|
||||
case ListType.category:
|
||||
newStreams = await Twitch.getStreamsUnderGame(
|
||||
gameId: categoryInfo!.id,
|
||||
headers: authStore.headersTwitch,
|
||||
cursor: _currentCursor,
|
||||
cursor: _streamsCursor,
|
||||
);
|
||||
break;
|
||||
case StreamListType.categories:
|
||||
return getGames();
|
||||
}
|
||||
|
||||
if (newStreams != null) {
|
||||
if (_currentCursor == null) {
|
||||
if (_streamsCursor == null) {
|
||||
_streams = newStreams.data.asObservable();
|
||||
} else {
|
||||
_streams.addAll(newStreams.data);
|
||||
}
|
||||
_currentCursor = newStreams.pagination['cursor'];
|
||||
_streamsCursor = newStreams.pagination['cursor'];
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
|
|
@ -99,15 +98,17 @@ abstract class _ListStoreBase with Store {
|
|||
|
||||
// Fetches the top categories based on the current cursor.
|
||||
@action
|
||||
Future<void> getGames() async {
|
||||
final result = await Twitch.getTopGames(headers: authStore.headersTwitch, cursor: _currentCursor);
|
||||
Future<void> getCategories() async {
|
||||
_isLoading = true;
|
||||
|
||||
final result = await Twitch.getTopGames(headers: authStore.headersTwitch, cursor: _categoriesCursor);
|
||||
if (result != null) {
|
||||
if (_currentCursor == null) {
|
||||
if (_categoriesCursor == null) {
|
||||
_categories = result.data.asObservable();
|
||||
} else {
|
||||
_categories.addAll(result.data);
|
||||
}
|
||||
_currentCursor = result.pagination['cursor'];
|
||||
_categoriesCursor = result.pagination['cursor'];
|
||||
}
|
||||
|
||||
_isLoading = false;
|
||||
|
|
@ -115,16 +116,23 @@ abstract class _ListStoreBase with Store {
|
|||
|
||||
/// Resets the cursor and then fetches the streams.
|
||||
@action
|
||||
Future<void> refresh() {
|
||||
_currentCursor = null;
|
||||
Future<void> refreshStreams() {
|
||||
_streamsCursor = null;
|
||||
|
||||
return getData();
|
||||
return getStreams();
|
||||
}
|
||||
|
||||
/// Resets the cursor and then fetches the categories.
|
||||
@action
|
||||
Future<void> refreshCategories() {
|
||||
_categoriesCursor = null;
|
||||
|
||||
return getCategories();
|
||||
}
|
||||
}
|
||||
|
||||
enum StreamListType {
|
||||
enum ListType {
|
||||
followed,
|
||||
top,
|
||||
category,
|
||||
categories,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,29 +60,41 @@ mixin _$ListStore on _ListStoreBase, Store {
|
|||
});
|
||||
}
|
||||
|
||||
final _$getDataAsyncAction = AsyncAction('_ListStoreBase.getData');
|
||||
final _$getStreamsAsyncAction = AsyncAction('_ListStoreBase.getStreams');
|
||||
|
||||
@override
|
||||
Future<void> getData() {
|
||||
return _$getDataAsyncAction.run(() => super.getData());
|
||||
Future<void> getStreams() {
|
||||
return _$getStreamsAsyncAction.run(() => super.getStreams());
|
||||
}
|
||||
|
||||
final _$getGamesAsyncAction = AsyncAction('_ListStoreBase.getGames');
|
||||
final _$getCategoriesAsyncAction =
|
||||
AsyncAction('_ListStoreBase.getCategories');
|
||||
|
||||
@override
|
||||
Future<void> getGames() {
|
||||
return _$getGamesAsyncAction.run(() => super.getGames());
|
||||
Future<void> getCategories() {
|
||||
return _$getCategoriesAsyncAction.run(() => super.getCategories());
|
||||
}
|
||||
|
||||
final _$_ListStoreBaseActionController =
|
||||
ActionController(name: '_ListStoreBase');
|
||||
|
||||
@override
|
||||
Future<void> refresh() {
|
||||
Future<void> refreshStreams() {
|
||||
final _$actionInfo = _$_ListStoreBaseActionController.startAction(
|
||||
name: '_ListStoreBase.refresh');
|
||||
name: '_ListStoreBase.refreshStreams');
|
||||
try {
|
||||
return super.refresh();
|
||||
return super.refreshStreams();
|
||||
} finally {
|
||||
_$_ListStoreBaseActionController.endAction(_$actionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> refreshCategories() {
|
||||
final _$actionInfo = _$_ListStoreBaseActionController.startAction(
|
||||
name: '_ListStoreBase.refreshCategories');
|
||||
try {
|
||||
return super.refreshCategories();
|
||||
} finally {
|
||||
_$_ListStoreBaseActionController.endAction(_$actionInfo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class StreamsList extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: store.refresh,
|
||||
onRefresh: store.refreshStreams,
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
if (store.streams.isEmpty && store.isLoading) {
|
||||
|
|
@ -24,7 +24,7 @@ class StreamsList extends StatelessWidget {
|
|||
itemCount: store.streams.length,
|
||||
itemBuilder: (context, index) {
|
||||
if (index > store.streams.length / 2 && store.hasMore) {
|
||||
store.getData();
|
||||
store.getStreams();
|
||||
}
|
||||
return Observer(
|
||||
builder: (context) => StreamCard(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class Categories extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: store.refresh,
|
||||
onRefresh: store.refreshCategories,
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
return GridView.builder(
|
||||
|
|
@ -24,7 +24,7 @@ class Categories extends StatelessWidget {
|
|||
itemCount: store.categories.length,
|
||||
itemBuilder: (context, index) {
|
||||
if (index > store.categories.length / 2 && store.hasMore) {
|
||||
store.getGames();
|
||||
store.getCategories();
|
||||
}
|
||||
return CategoryCard(category: store.categories[index]);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ class CategoryCard extends StatelessWidget {
|
|||
builder: (context) => CategoryStreams(
|
||||
store: ListStore(
|
||||
authStore: context.read<AuthStore>(),
|
||||
listType: StreamListType.category,
|
||||
listType: ListType.category,
|
||||
categoryInfo: category,
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class CategoryStreams extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: RefreshIndicator(
|
||||
onRefresh: store.refresh,
|
||||
onRefresh: store.refreshStreams,
|
||||
child: Observer(
|
||||
builder: (context) {
|
||||
return CustomScrollView(
|
||||
|
|
@ -44,7 +44,7 @@ class CategoryStreams extends StatelessWidget {
|
|||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
if (index > store.streams.length / 2 && store.hasMore) {
|
||||
store.getData();
|
||||
store.getStreams();
|
||||
}
|
||||
return Observer(
|
||||
builder: (context) => StreamCard(
|
||||
|
|
|
|||
|
|
@ -4,13 +4,11 @@ import 'package:frosty/screens/home/streams_list.dart';
|
|||
import 'package:frosty/screens/home/top/categories/categories.dart';
|
||||
|
||||
class TopSection extends StatelessWidget {
|
||||
final ListStore topStreamsStore;
|
||||
final ListStore categoriesStore;
|
||||
final ListStore topSectionStore;
|
||||
|
||||
const TopSection({
|
||||
Key? key,
|
||||
required this.topStreamsStore,
|
||||
required this.categoriesStore,
|
||||
required this.topSectionStore,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -28,8 +26,8 @@ class TopSection extends StatelessWidget {
|
|||
Expanded(
|
||||
child: TabBarView(
|
||||
children: [
|
||||
StreamsList(store: topStreamsStore),
|
||||
Categories(store: categoriesStore),
|
||||
StreamsList(store: topSectionStore),
|
||||
Categories(store: topSectionStore),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue