feat(ui): Implement filtering
This commit is contained in:
parent
632be66702
commit
d273a6deb2
@ -9,15 +9,19 @@ enum AnimeTrackingState {
|
||||
completed, // 1
|
||||
planToWatch, // 2
|
||||
dropped, // 3
|
||||
/// This is a pseudo state, i.e. it should never be set
|
||||
all, // -1
|
||||
}
|
||||
|
||||
extension AnimeTrackStateExtension on AnimeTrackingState {
|
||||
int toInteger() {
|
||||
assert(this != AnimeTrackingState.all, 'AnimeTrackingState.all must not be serialized');
|
||||
switch (this) {
|
||||
case AnimeTrackingState.watching: return 0;
|
||||
case AnimeTrackingState.completed: return 1;
|
||||
case AnimeTrackingState.planToWatch: return 2;
|
||||
case AnimeTrackingState.dropped: return 3;
|
||||
case AnimeTrackingState.all: return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ class AnimeListBloc extends Bloc<AnimeListEvent, AnimeListState> {
|
||||
on<AnimeEpisodeIncrementedEvent>(_onIncremented);
|
||||
on<AnimeEpisodeDecrementedEvent>(_onDecremented);
|
||||
on<AnimesLoadedEvent>(_onAnimesLoaded);
|
||||
on<AnimeFilterChangedEvent>(_onAnimesFiltered);
|
||||
}
|
||||
|
||||
Future<void> _onAnimeAdded(AnimeAddedEvent event, Emitter<AnimeListState> emit) async {
|
||||
@ -82,4 +83,12 @@ class AnimeListBloc extends Bloc<AnimeListEvent, AnimeListState> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onAnimesFiltered(AnimeFilterChangedEvent event, Emitter<AnimeListState> emit) async {
|
||||
emit(
|
||||
state.copyWith(
|
||||
filterState: event.filterState,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ final _privateConstructorUsedError = UnsupportedError(
|
||||
/// @nodoc
|
||||
mixin _$AnimeListState {
|
||||
List<AnimeTrackingData> get animes => throw _privateConstructorUsedError;
|
||||
AnimeTrackingState get filterState => throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$AnimeListStateCopyWith<AnimeListState> get copyWith =>
|
||||
@ -28,7 +29,7 @@ abstract class $AnimeListStateCopyWith<$Res> {
|
||||
factory $AnimeListStateCopyWith(
|
||||
AnimeListState value, $Res Function(AnimeListState) then) =
|
||||
_$AnimeListStateCopyWithImpl<$Res>;
|
||||
$Res call({List<AnimeTrackingData> animes});
|
||||
$Res call({List<AnimeTrackingData> animes, AnimeTrackingState filterState});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -43,12 +44,17 @@ class _$AnimeListStateCopyWithImpl<$Res>
|
||||
@override
|
||||
$Res call({
|
||||
Object? animes = freezed,
|
||||
Object? filterState = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
animes: animes == freezed
|
||||
? _value.animes
|
||||
: animes // ignore: cast_nullable_to_non_nullable
|
||||
as List<AnimeTrackingData>,
|
||||
filterState: filterState == freezed
|
||||
? _value.filterState
|
||||
: filterState // ignore: cast_nullable_to_non_nullable
|
||||
as AnimeTrackingState,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -60,7 +66,7 @@ abstract class _$$_AnimeListStateCopyWith<$Res>
|
||||
_$_AnimeListState value, $Res Function(_$_AnimeListState) then) =
|
||||
__$$_AnimeListStateCopyWithImpl<$Res>;
|
||||
@override
|
||||
$Res call({List<AnimeTrackingData> animes});
|
||||
$Res call({List<AnimeTrackingData> animes, AnimeTrackingState filterState});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -77,12 +83,17 @@ class __$$_AnimeListStateCopyWithImpl<$Res>
|
||||
@override
|
||||
$Res call({
|
||||
Object? animes = freezed,
|
||||
Object? filterState = freezed,
|
||||
}) {
|
||||
return _then(_$_AnimeListState(
|
||||
animes: animes == freezed
|
||||
? _value._animes
|
||||
: animes // ignore: cast_nullable_to_non_nullable
|
||||
as List<AnimeTrackingData>,
|
||||
filterState: filterState == freezed
|
||||
? _value.filterState
|
||||
: filterState // ignore: cast_nullable_to_non_nullable
|
||||
as AnimeTrackingState,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -90,7 +101,9 @@ class __$$_AnimeListStateCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
|
||||
class _$_AnimeListState implements _AnimeListState {
|
||||
_$_AnimeListState({final List<AnimeTrackingData> animes = const []})
|
||||
_$_AnimeListState(
|
||||
{final List<AnimeTrackingData> animes = const [],
|
||||
this.filterState = AnimeTrackingState.watching})
|
||||
: _animes = animes;
|
||||
|
||||
final List<AnimeTrackingData> _animes;
|
||||
@ -101,9 +114,13 @@ class _$_AnimeListState implements _AnimeListState {
|
||||
return EqualUnmodifiableListView(_animes);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final AnimeTrackingState filterState;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AnimeListState(animes: $animes)';
|
||||
return 'AnimeListState(animes: $animes, filterState: $filterState)';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -111,12 +128,16 @@ class _$_AnimeListState implements _AnimeListState {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$_AnimeListState &&
|
||||
const DeepCollectionEquality().equals(other._animes, _animes));
|
||||
const DeepCollectionEquality().equals(other._animes, _animes) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.filterState, filterState));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, const DeepCollectionEquality().hash(_animes));
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_animes),
|
||||
const DeepCollectionEquality().hash(filterState));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@ -125,12 +146,15 @@ class _$_AnimeListState implements _AnimeListState {
|
||||
}
|
||||
|
||||
abstract class _AnimeListState implements AnimeListState {
|
||||
factory _AnimeListState({final List<AnimeTrackingData> animes}) =
|
||||
_$_AnimeListState;
|
||||
factory _AnimeListState(
|
||||
{final List<AnimeTrackingData> animes,
|
||||
final AnimeTrackingState filterState}) = _$_AnimeListState;
|
||||
|
||||
@override
|
||||
List<AnimeTrackingData> get animes;
|
||||
@override
|
||||
AnimeTrackingState get filterState;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$_AnimeListStateCopyWith<_$_AnimeListState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
@ -25,3 +25,11 @@ class AnimeAddedEvent extends AnimeListEvent {
|
||||
|
||||
/// Triggered when animes are to be loaded from the database
|
||||
class AnimesLoadedEvent extends AnimeListEvent {}
|
||||
|
||||
/// Triggered when the filter is changed
|
||||
class AnimeFilterChangedEvent extends AnimeListEvent {
|
||||
AnimeFilterChangedEvent(this.filterState);
|
||||
|
||||
/// The state to filter
|
||||
final AnimeTrackingState filterState;
|
||||
}
|
||||
|
@ -4,5 +4,6 @@ part of 'anime_list_bloc.dart';
|
||||
class AnimeListState with _$AnimeListState {
|
||||
factory AnimeListState({
|
||||
@Default([]) List<AnimeTrackingData> animes,
|
||||
@Default(AnimeTrackingState.watching) AnimeTrackingState filterState,
|
||||
}) = _AnimeListState;
|
||||
}
|
||||
|
@ -21,12 +21,52 @@ class AnimeListPage extends StatelessWidget {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Animes'),
|
||||
actions: [
|
||||
PopupMenuButton(
|
||||
icon: Icon(
|
||||
Icons.filter_list,
|
||||
),
|
||||
initialValue: state.filterState,
|
||||
onSelected: (filterState) {
|
||||
context.read<AnimeListBloc>().add(
|
||||
AnimeFilterChangedEvent(filterState),
|
||||
);
|
||||
},
|
||||
itemBuilder: (_) => [
|
||||
const PopupMenuItem<AnimeTrackingState>(
|
||||
value: AnimeTrackingState.watching,
|
||||
child: Text('Watching'),
|
||||
),
|
||||
const PopupMenuItem<AnimeTrackingState>(
|
||||
value: AnimeTrackingState.completed,
|
||||
child: Text('Completed'),
|
||||
),
|
||||
const PopupMenuItem<AnimeTrackingState>(
|
||||
value: AnimeTrackingState.planToWatch,
|
||||
child: Text('Plan to watch'),
|
||||
),
|
||||
const PopupMenuItem<AnimeTrackingState>(
|
||||
value: AnimeTrackingState.dropped,
|
||||
child: Text('Dropped'),
|
||||
),
|
||||
const PopupMenuItem<AnimeTrackingState>(
|
||||
value: AnimeTrackingState.all,
|
||||
child: Text('All'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ListView.builder(
|
||||
itemCount: state.animes.length,
|
||||
itemBuilder: (context, index) {
|
||||
final anime = state.animes[index];
|
||||
if (state.filterState != AnimeTrackingState.all) {
|
||||
if (anime.state != state.filterState) return Container();
|
||||
}
|
||||
|
||||
return AnimeListWidget(
|
||||
data: state.animes[index],
|
||||
data: anime,
|
||||
onLeftSwipe: () {
|
||||
context.read<AnimeListBloc>().add(
|
||||
AnimeEpisodeDecrementedEvent(state.animes[index].id),
|
||||
|
Loading…
Reference in New Issue
Block a user