Add loading indicators to top and followed streams
This commit is contained in:
parent
132a2c8348
commit
8102ea6185
7 changed files with 89 additions and 13 deletions
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:frosty/screens/stream_list/stream_card.dart';
|
||||
import 'package:frosty/screens/stream_list/streams_followed/followed_streams_store.dart';
|
||||
import 'package:frosty/widgets/loading_indicator.dart';
|
||||
|
||||
class FollowedStreams extends StatelessWidget {
|
||||
final FollowedStreamsStore store;
|
||||
|
|
@ -14,6 +15,11 @@ class FollowedStreams extends StatelessWidget {
|
|||
onRefresh: store.refresh,
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
if (store.followedStreams.isEmpty && store.isLoading) {
|
||||
return const LoadingIndicator(
|
||||
subtitle: Text('Loading followed streams...'),
|
||||
);
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: store.followedStreams.length,
|
||||
itemBuilder: (context, index) {
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ class FollowedStreamsStore = _FollowedStreamsStoreBase with _$FollowedStreamsSto
|
|||
|
||||
abstract class _FollowedStreamsStoreBase with Store {
|
||||
/// The list of the fetched followed streams.
|
||||
@observable
|
||||
@readonly
|
||||
var _followedStreams = ObservableList<StreamTwitch>();
|
||||
ObservableList<StreamTwitch> get followedStreams => _followedStreams;
|
||||
|
||||
/// The loading status for pagination.
|
||||
@readonly
|
||||
bool _isLoading = false;
|
||||
|
||||
/// The pagination cursor for followed streams.
|
||||
|
|
@ -34,12 +34,15 @@ abstract class _FollowedStreamsStoreBase with Store {
|
|||
Future<void> getFollowedStreams() async {
|
||||
_isLoading = true;
|
||||
|
||||
final newFollowedStreams =
|
||||
await Twitch.getFollowedStreams(id: authStore.user.details!.id, headers: authStore.headersTwitch, cursor: _followedStreamsCurrentCursor);
|
||||
final newFollowedStreams = await Twitch.getFollowedStreams(
|
||||
id: authStore.user.details!.id,
|
||||
headers: authStore.headersTwitch,
|
||||
cursor: _followedStreamsCurrentCursor,
|
||||
);
|
||||
|
||||
if (newFollowedStreams != null) {
|
||||
if (_followedStreamsCurrentCursor == null) {
|
||||
_followedStreams = ObservableList.of(newFollowedStreams.data);
|
||||
_followedStreams = newFollowedStreams.data.asObservable();
|
||||
} else {
|
||||
_followedStreams.addAll(newFollowedStreams.data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,14 @@ mixin _$FollowedStreamsStore on _FollowedStreamsStoreBase, Store {
|
|||
final _$_followedStreamsAtom =
|
||||
Atom(name: '_FollowedStreamsStoreBase._followedStreams');
|
||||
|
||||
@override
|
||||
ObservableList<StreamTwitch> get _followedStreams {
|
||||
ObservableList<StreamTwitch> get followedStreams {
|
||||
_$_followedStreamsAtom.reportRead();
|
||||
return super._followedStreams;
|
||||
}
|
||||
|
||||
@override
|
||||
ObservableList<StreamTwitch> get _followedStreams => followedStreams;
|
||||
|
||||
@override
|
||||
set _followedStreams(ObservableList<StreamTwitch> value) {
|
||||
_$_followedStreamsAtom.reportWrite(value, super._followedStreams, () {
|
||||
|
|
@ -25,6 +27,23 @@ mixin _$FollowedStreamsStore on _FollowedStreamsStoreBase, Store {
|
|||
});
|
||||
}
|
||||
|
||||
final _$_isLoadingAtom = Atom(name: '_FollowedStreamsStoreBase._isLoading');
|
||||
|
||||
bool get isLoading {
|
||||
_$_isLoadingAtom.reportRead();
|
||||
return super._isLoading;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get _isLoading => isLoading;
|
||||
|
||||
@override
|
||||
set _isLoading(bool value) {
|
||||
_$_isLoadingAtom.reportWrite(value, super._isLoading, () {
|
||||
super._isLoading = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$getFollowedStreamsAsyncAction =
|
||||
AsyncAction('_FollowedStreamsStoreBase.getFollowedStreams');
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:frosty/screens/stream_list/stream_card.dart';
|
||||
import 'package:frosty/screens/stream_list/streams_top/top_streams_store.dart';
|
||||
import 'package:frosty/widgets/loading_indicator.dart';
|
||||
|
||||
class TopStreams extends StatelessWidget {
|
||||
final TopStreamsStore store;
|
||||
|
|
@ -14,6 +15,9 @@ class TopStreams extends StatelessWidget {
|
|||
onRefresh: store.refresh,
|
||||
child: Observer(
|
||||
builder: (_) {
|
||||
if (store.topStreams.isEmpty && store.isLoading) {
|
||||
return const LoadingIndicator(subtitle: Text('Loading top streams...'));
|
||||
}
|
||||
return ListView.builder(
|
||||
itemCount: store.topStreams.length,
|
||||
itemBuilder: (context, index) {
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ class TopStreamsStore = _TopStreamsStoreBase with _$TopStreamsStore;
|
|||
|
||||
abstract class _TopStreamsStoreBase with Store {
|
||||
/// The list of the fetched top streams.
|
||||
@observable
|
||||
@readonly
|
||||
var _topStreams = ObservableList<StreamTwitch>();
|
||||
ObservableList<StreamTwitch> get topStreams => _topStreams;
|
||||
|
||||
/// The loading status for pagination.
|
||||
@readonly
|
||||
bool _isLoading = false;
|
||||
|
||||
/// The pagination cursor for top streams.
|
||||
|
|
@ -34,11 +34,14 @@ abstract class _TopStreamsStoreBase with Store {
|
|||
Future<void> getTopStreams() async {
|
||||
_isLoading = true;
|
||||
|
||||
final newTopStreams = await Twitch.getTopStreams(headers: authStore.headersTwitch, cursor: _topStreamsCurrentCursor);
|
||||
final newTopStreams = await Twitch.getTopStreams(
|
||||
headers: authStore.headersTwitch,
|
||||
cursor: _topStreamsCurrentCursor,
|
||||
);
|
||||
|
||||
if (newTopStreams != null) {
|
||||
if (_topStreamsCurrentCursor == null) {
|
||||
_topStreams = ObservableList.of(newTopStreams.data);
|
||||
_topStreams = newTopStreams.data.asObservable();
|
||||
} else {
|
||||
_topStreams.addAll(newTopStreams.data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,14 @@ part of 'top_streams_store.dart';
|
|||
mixin _$TopStreamsStore on _TopStreamsStoreBase, Store {
|
||||
final _$_topStreamsAtom = Atom(name: '_TopStreamsStoreBase._topStreams');
|
||||
|
||||
@override
|
||||
ObservableList<StreamTwitch> get _topStreams {
|
||||
ObservableList<StreamTwitch> get topStreams {
|
||||
_$_topStreamsAtom.reportRead();
|
||||
return super._topStreams;
|
||||
}
|
||||
|
||||
@override
|
||||
ObservableList<StreamTwitch> get _topStreams => topStreams;
|
||||
|
||||
@override
|
||||
set _topStreams(ObservableList<StreamTwitch> value) {
|
||||
_$_topStreamsAtom.reportWrite(value, super._topStreams, () {
|
||||
|
|
@ -24,6 +26,23 @@ mixin _$TopStreamsStore on _TopStreamsStoreBase, Store {
|
|||
});
|
||||
}
|
||||
|
||||
final _$_isLoadingAtom = Atom(name: '_TopStreamsStoreBase._isLoading');
|
||||
|
||||
bool get isLoading {
|
||||
_$_isLoadingAtom.reportRead();
|
||||
return super._isLoading;
|
||||
}
|
||||
|
||||
@override
|
||||
bool get _isLoading => isLoading;
|
||||
|
||||
@override
|
||||
set _isLoading(bool value) {
|
||||
_$_isLoadingAtom.reportWrite(value, super._isLoading, () {
|
||||
super._isLoading = value;
|
||||
});
|
||||
}
|
||||
|
||||
final _$getTopStreamsAsyncAction =
|
||||
AsyncAction('_TopStreamsStoreBase.getTopStreams');
|
||||
|
||||
|
|
|
|||
22
lib/widgets/loading_indicator.dart
Normal file
22
lib/widgets/loading_indicator.dart
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class LoadingIndicator extends StatelessWidget {
|
||||
final Widget? subtitle;
|
||||
final double spacing;
|
||||
|
||||
const LoadingIndicator({Key? key, this.subtitle, this.spacing = 10.0}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const CircularProgressIndicator.adaptive(),
|
||||
SizedBox(height: spacing),
|
||||
if (subtitle != null) subtitle!,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue