diff --git a/lib/logic/bloc/sort_bloc/sort_bloc.dart b/lib/logic/bloc/sort_bloc/sort_bloc.dart deleted file mode 100644 index 8b173b6c6..000000000 --- a/lib/logic/bloc/sort_bloc/sort_bloc.dart +++ /dev/null @@ -1,159 +0,0 @@ -import 'package:equatable/equatable.dart'; -import 'package:hydrated_bloc/hydrated_bloc.dart'; -import 'package:openreads/core/constants/enums/enums.dart'; - -part 'sort_state.dart'; -part 'sort_event.dart'; - -class SortBloc extends HydratedBloc { - SortBloc() - : super(const SetSortState( - sortType: SortType.byTitle, - isAsc: true, - onlyFavourite: false, - years: null, - tags: null, - displayTags: false, - filterTagsAsAnd: false, - bookType: null, - )) { - on((event, emit) { - emit(SetSortState( - sortType: event.sortType, - isAsc: event.isAsc, - onlyFavourite: event.onlyFavourite, - years: event.years, - tags: event.tags, - displayTags: event.displayTags, - filterTagsAsAnd: event.filterTagsAsAnd, - bookType: event.bookType, - filterOutTags: event.filterOutTags, - )); - }); - } - - @override - SortState? fromJson(Map json) { - final sortTypeInt = json['sort_type'] as int; - final isAsc = json['sort_order'] as bool; - final onlyFavourite = json['only_favourite'] as bool; - final years = json['years'] as String?; - final tags = json['tags'] as String?; - final displayTags = json['display_tags'] as bool; - final filterTagsAsAnd = json['filter_tags_as_and'] as bool; - final filterOutTags = json['filter_out_tags'] as bool; - final bookType = json['filter_book_type'] as String?; - - late SortType sortType; - - switch (sortTypeInt) { - case 0: - sortType = SortType.byTitle; - break; - case 1: - sortType = SortType.byAuthor; - break; - case 2: - sortType = SortType.byRating; - break; - case 3: - sortType = SortType.byPages; - break; - case 4: - sortType = SortType.byStartDate; - break; - case 5: - sortType = SortType.byFinishDate; - break; - case 6: - sortType = SortType.byPublicationYear; - break; - default: - sortType = SortType.byTitle; - } - - return SetSortState( - sortType: sortType, - isAsc: isAsc, - onlyFavourite: onlyFavourite, - years: years, - tags: tags, - displayTags: displayTags, - filterTagsAsAnd: filterTagsAsAnd, - bookType: bookType == 'audiobook' - ? BookFormat.audiobook - : bookType == 'ebook' - ? BookFormat.ebook - : bookType == 'paper' || bookType == 'paperback' - ? BookFormat.paperback - : bookType == 'hardcover' - ? BookFormat.hardcover - : null, - filterOutTags: filterOutTags, - ); - } - - @override - Map? toJson(SortState state) { - if (state is SetSortState) { - late int sortTypeInt; - switch (state.sortType) { - case SortType.byTitle: - sortTypeInt = 0; - break; - case SortType.byAuthor: - sortTypeInt = 1; - break; - case SortType.byRating: - sortTypeInt = 2; - break; - case SortType.byPages: - sortTypeInt = 3; - break; - case SortType.byStartDate: - sortTypeInt = 4; - break; - case SortType.byFinishDate: - sortTypeInt = 5; - break; - case SortType.byPublicationYear: - sortTypeInt = 6; - break; - default: - sortTypeInt = 0; - } - - return { - 'sort_type': sortTypeInt, - 'sort_order': state.isAsc, - 'only_favourite': state.onlyFavourite, - 'years': state.years, - 'tags': state.tags, - 'display_tags': state.displayTags, - 'filter_tags_as_and': state.filterTagsAsAnd, - 'filter_book_type': state.bookType == BookFormat.audiobook - ? 'audiobook' - : state.bookType == BookFormat.ebook - ? 'ebook' - : state.bookType == BookFormat.paperback - ? 'paperback' - : state.bookType == BookFormat.hardcover - ? 'hardcover' - : null, - 'filter_out_tags': state.filterOutTags, - }; - } else { - return { - 'sort_type': 0, - 'sort_order': true, - 'only_favourite': false, - 'years': null, - 'tags': null, - 'display_tags': false, - 'filter_tags_as_and': false, - 'filter_book_type': null, - 'filter_out_tags': false, - }; - } - } -} diff --git a/lib/logic/bloc/sort_bloc/sort_event.dart b/lib/logic/bloc/sort_bloc/sort_event.dart index 8537ba8d7..0123d4acf 100644 --- a/lib/logic/bloc/sort_bloc/sort_event.dart +++ b/lib/logic/bloc/sort_bloc/sort_event.dart @@ -1,42 +1,86 @@ -part of 'sort_bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:openreads/core/constants/enums/book_format.dart'; +import 'package:openreads/core/constants/enums/sort_type.dart'; abstract class SortEvent extends Equatable { const SortEvent(); } -class ChangeSortEvent extends SortEvent { - const ChangeSortEvent({ - required this.sortType, - required this.isAsc, - required this.onlyFavourite, - required this.years, - required this.tags, - required this.displayTags, - required this.filterTagsAsAnd, - required this.bookType, - this.filterOutTags = false, - }); - +class ChangeSortTypeEvent extends SortEvent { final SortType sortType; - final bool isAsc; + + const ChangeSortTypeEvent(this.sortType); + + @override + List get props => [sortType]; +} + +class ToggleOrderEvent extends SortEvent { + const ToggleOrderEvent(); + + @override + List get props => []; +} + +class ChangeOnlyFavouriteEvent extends SortEvent { final bool onlyFavourite; + + const ChangeOnlyFavouriteEvent(this.onlyFavourite); + + @override + List get props => []; +} + +class ChangeBookTypeEvent extends SortEvent { + final BookFormat? bookType; + + const ChangeBookTypeEvent(this.bookType); + + @override + List get props => [bookType]; +} + +class ChangeYearsEvent extends SortEvent { final String? years; + + const ChangeYearsEvent(this.years); + + @override + List get props => [years]; +} + +class ChangeTagsEvent extends SortEvent { final String? tags; - final bool displayTags; + + const ChangeTagsEvent(this.tags); + + @override + List get props => [tags]; +} + +class ChangeFilterTagsAsAnd extends SortEvent { final bool filterTagsAsAnd; - final BookFormat? bookType; + + const ChangeFilterTagsAsAnd(this.filterTagsAsAnd); + + @override + List get props => [filterTagsAsAnd]; +} + +class ChangeFilterOutTags extends SortEvent { final bool filterOutTags; + const ChangeFilterOutTags(this.filterOutTags); + + @override + List get props => [filterOutTags]; +} + +class ChangeDisplayTagsEvent extends SortEvent { + final bool displayTags; + + const ChangeDisplayTagsEvent(this.displayTags); + @override - List get props => [ - sortType, - isAsc, - onlyFavourite, - years, - tags, - displayTags, - filterTagsAsAnd, - bookType, - filterOutTags, - ]; + List get props => [displayTags]; } diff --git a/lib/logic/bloc/sort_bloc/sort_finished_books_bloc.dart b/lib/logic/bloc/sort_bloc/sort_finished_books_bloc.dart new file mode 100644 index 000000000..d2c7385b8 --- /dev/null +++ b/lib/logic/bloc/sort_bloc/sort_finished_books_bloc.dart @@ -0,0 +1,81 @@ +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:openreads/core/constants/enums/sort_type.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_event.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_state.dart'; + +class SortFinishedBooksBloc extends HydratedBloc { + SortFinishedBooksBloc() + : super( + const SortState( + sortType: SortType.byFinishDate, + isAsc: false, + onlyFavourite: false, + years: null, + tags: null, + displayTags: false, + filterTagsAsAnd: false, + bookType: null, + ), + ) { + on( + (event, emit) => emit(state.copyWith(sortType: event.sortType)), + ); + + on( + (event, emit) => emit(state.copyWith(isAsc: !state.isAsc)), + ); + + on( + (event, emit) => emit(state.copyWith(onlyFavourite: event.onlyFavourite)), + ); + + on( + (event, emit) => emit( + state.copyWith( + bookType: event.bookType, + resetBookType: event.bookType == null, + ), + ), + ); + + on( + (event, emit) => emit( + state.copyWith(years: event.years, resetYears: event.years == null), + ), + ); + + on( + (event, emit) => emit( + state.copyWith(tags: event.tags, resetTags: event.tags == null), + ), + ); + + on( + (event, emit) => emit( + state.copyWith( + filterTagsAsAnd: event.filterTagsAsAnd, + filterOutTags: false, + ), + ), + ); + + on( + (event, emit) => emit( + state.copyWith( + filterOutTags: event.filterOutTags, + filterTagsAsAnd: false, + ), + ), + ); + + on( + (event, emit) => emit(state.copyWith(displayTags: event.displayTags)), + ); + } + + @override + SortState? fromJson(Map json) => SortState.fromJson(json); + + @override + Map? toJson(SortState state) => state.toJson(); +} diff --git a/lib/logic/bloc/sort_bloc/sort_for_later_books_bloc.dart b/lib/logic/bloc/sort_bloc/sort_for_later_books_bloc.dart new file mode 100644 index 000000000..d20092b46 --- /dev/null +++ b/lib/logic/bloc/sort_bloc/sort_for_later_books_bloc.dart @@ -0,0 +1,81 @@ +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:openreads/core/constants/enums/sort_type.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_event.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_state.dart'; + +class SortForLaterBooksBloc extends HydratedBloc { + SortForLaterBooksBloc() + : super( + const SortState( + sortType: SortType.byDateAdded, + isAsc: false, + onlyFavourite: false, + years: null, + tags: null, + displayTags: false, + filterTagsAsAnd: false, + bookType: null, + ), + ) { + on( + (event, emit) => emit(state.copyWith(sortType: event.sortType)), + ); + + on( + (event, emit) => emit(state.copyWith(isAsc: !state.isAsc)), + ); + + on( + (event, emit) => emit(state.copyWith(onlyFavourite: event.onlyFavourite)), + ); + + on( + (event, emit) => emit( + state.copyWith( + bookType: event.bookType, + resetBookType: event.bookType == null, + ), + ), + ); + + on( + (event, emit) => emit( + state.copyWith(years: event.years, resetYears: event.years == null), + ), + ); + + on( + (event, emit) => emit( + state.copyWith(tags: event.tags, resetTags: event.tags == null), + ), + ); + + on( + (event, emit) => emit( + state.copyWith( + filterTagsAsAnd: event.filterTagsAsAnd, + filterOutTags: false, + ), + ), + ); + + on( + (event, emit) => emit( + state.copyWith( + filterOutTags: event.filterOutTags, + filterTagsAsAnd: false, + ), + ), + ); + + on( + (event, emit) => emit(state.copyWith(displayTags: event.displayTags)), + ); + } + + @override + SortState? fromJson(Map json) => SortState.fromJson(json); + + @override + Map? toJson(SortState state) => state.toJson(); +} diff --git a/lib/logic/bloc/sort_bloc/sort_in_progress_books_bloc.dart b/lib/logic/bloc/sort_bloc/sort_in_progress_books_bloc.dart new file mode 100644 index 000000000..69ae5407d --- /dev/null +++ b/lib/logic/bloc/sort_bloc/sort_in_progress_books_bloc.dart @@ -0,0 +1,81 @@ +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:openreads/core/constants/enums/sort_type.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_event.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_state.dart'; + +class SortInProgressBooksBloc extends HydratedBloc { + SortInProgressBooksBloc() + : super( + const SortState( + sortType: SortType.byStartDate, + isAsc: false, + onlyFavourite: false, + years: null, + tags: null, + displayTags: false, + filterTagsAsAnd: false, + bookType: null, + ), + ) { + on( + (event, emit) => emit(state.copyWith(sortType: event.sortType)), + ); + + on( + (event, emit) => emit(state.copyWith(isAsc: !state.isAsc)), + ); + + on( + (event, emit) => emit(state.copyWith(onlyFavourite: event.onlyFavourite)), + ); + + on( + (event, emit) => emit( + state.copyWith( + bookType: event.bookType, + resetBookType: event.bookType == null, + ), + ), + ); + + on( + (event, emit) => emit( + state.copyWith(years: event.years, resetYears: event.years == null), + ), + ); + + on( + (event, emit) => emit( + state.copyWith(tags: event.tags, resetTags: event.tags == null), + ), + ); + + on( + (event, emit) => emit( + state.copyWith( + filterTagsAsAnd: event.filterTagsAsAnd, + filterOutTags: false, + ), + ), + ); + + on( + (event, emit) => emit( + state.copyWith( + filterOutTags: event.filterOutTags, + filterTagsAsAnd: false, + ), + ), + ); + + on( + (event, emit) => emit(state.copyWith(displayTags: event.displayTags)), + ); + } + + @override + SortState? fromJson(Map json) => SortState.fromJson(json); + + @override + Map? toJson(SortState state) => state.toJson(); +} diff --git a/lib/logic/bloc/sort_bloc/sort_state.dart b/lib/logic/bloc/sort_bloc/sort_state.dart index 8b86a094c..32914eb71 100644 --- a/lib/logic/bloc/sort_bloc/sort_state.dart +++ b/lib/logic/bloc/sort_bloc/sort_state.dart @@ -1,10 +1,20 @@ -part of 'sort_bloc.dart'; +import 'package:equatable/equatable.dart'; +import 'package:openreads/core/constants/enums/book_format.dart'; +import 'package:openreads/core/constants/enums/sort_type.dart'; -abstract class SortState extends Equatable { - const SortState(); -} +class SortState extends Equatable { + const SortState({ + required this.sortType, + required this.isAsc, + required this.onlyFavourite, + this.years, + this.tags, + required this.displayTags, + required this.filterTagsAsAnd, + this.bookType, + this.filterOutTags = false, + }); -class SetSortState extends SortState { final SortType sortType; final bool isAsc; final bool onlyFavourite; @@ -15,23 +25,80 @@ class SetSortState extends SortState { final BookFormat? bookType; final bool filterOutTags; - const SetSortState({ - required this.sortType, - required this.isAsc, - required this.onlyFavourite, - required this.years, - required this.tags, - required this.displayTags, - required this.filterTagsAsAnd, - required this.bookType, - this.filterOutTags = false, - }); + SortState copyWith({ + SortType? sortType, + bool? isAsc, + bool? onlyFavourite, + String? years, + bool resetYears = false, + String? tags, + bool resetTags = false, + bool? displayTags, + bool? filterTagsAsAnd, + BookFormat? bookType, + bool resetBookType = false, + bool? filterOutTags, + }) { + return SortState( + sortType: sortType ?? this.sortType, + isAsc: isAsc ?? this.isAsc, + onlyFavourite: onlyFavourite ?? this.onlyFavourite, + years: resetYears ? null : years ?? this.years, + tags: resetTags ? null : tags ?? this.tags, + displayTags: displayTags ?? this.displayTags, + filterTagsAsAnd: filterTagsAsAnd ?? this.filterTagsAsAnd, + bookType: resetBookType ? null : bookType ?? this.bookType, + filterOutTags: filterOutTags ?? this.filterOutTags, + ); + } + + factory SortState.fromJson(Map json) { + final sortTypeInt = json['sort_type'] as int; + final isAsc = json['sort_order'] as bool; + final onlyFavourite = json['only_favourite'] as bool; + final years = json['years'] as String?; + final tags = json['tags'] as String?; + final displayTags = json['display_tags'] as bool; + final filterTagsAsAnd = json['filter_tags_as_and'] as bool; + final filterOutTags = json['filter_out_tags'] as bool; + final bookType = json['filter_book_type'] as String?; + + final sortType = sortTypeInt < SortType.values.length + ? SortType.values[sortTypeInt] + : SortType.byTitle; + + return SortState( + sortType: sortType, + isAsc: isAsc, + onlyFavourite: onlyFavourite, + years: years, + tags: tags, + displayTags: displayTags, + filterTagsAsAnd: filterTagsAsAnd, + bookType: bookType == null ? null : BookFormat.values.byName(bookType), + filterOutTags: filterOutTags, + ); + } + + Map? toJson() { + return { + 'sort_type': sortType.index, + 'sort_order': isAsc, + 'only_favourite': onlyFavourite, + 'years': years, + 'tags': tags, + 'display_tags': displayTags, + 'filter_tags_as_and': filterTagsAsAnd, + 'filter_book_type': bookType?.name, + 'filter_out_tags': filterOutTags, + }; + } @override List get props => [ + sortType, isAsc, onlyFavourite, - sortType, years, tags, displayTags, diff --git a/lib/logic/bloc/sort_bloc/sort_unfinished_books_bloc.dart b/lib/logic/bloc/sort_bloc/sort_unfinished_books_bloc.dart new file mode 100644 index 000000000..eaf2b6988 --- /dev/null +++ b/lib/logic/bloc/sort_bloc/sort_unfinished_books_bloc.dart @@ -0,0 +1,81 @@ +import 'package:hydrated_bloc/hydrated_bloc.dart'; +import 'package:openreads/core/constants/enums/sort_type.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_event.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_state.dart'; + +class SortUnfinishedBooksBloc extends HydratedBloc { + SortUnfinishedBooksBloc() + : super( + const SortState( + sortType: SortType.byDateModified, + isAsc: false, + onlyFavourite: false, + years: null, + tags: null, + displayTags: false, + filterTagsAsAnd: false, + bookType: null, + ), + ) { + on( + (event, emit) => emit(state.copyWith(sortType: event.sortType)), + ); + + on( + (event, emit) => emit(state.copyWith(isAsc: !state.isAsc)), + ); + + on( + (event, emit) => emit(state.copyWith(onlyFavourite: event.onlyFavourite)), + ); + + on( + (event, emit) => emit( + state.copyWith( + bookType: event.bookType, + resetBookType: event.bookType == null, + ), + ), + ); + + on( + (event, emit) => emit( + state.copyWith(years: event.years, resetYears: event.years == null), + ), + ); + + on( + (event, emit) => emit( + state.copyWith(tags: event.tags, resetTags: event.tags == null), + ), + ); + + on( + (event, emit) => emit( + state.copyWith( + filterTagsAsAnd: event.filterTagsAsAnd, + filterOutTags: false, + ), + ), + ); + + on( + (event, emit) => emit( + state.copyWith( + filterOutTags: event.filterOutTags, + filterTagsAsAnd: false, + ), + ), + ); + + on( + (event, emit) => emit(state.copyWith(displayTags: event.displayTags)), + ); + } + + @override + SortState? fromJson(Map json) => SortState.fromJson(json); + + @override + Map? toJson(SortState state) => state.toJson(); +} diff --git a/lib/logic/cubit/book_cubit.dart b/lib/logic/cubit/book_cubit.dart index 407c361a4..925f98789 100644 --- a/lib/logic/cubit/book_cubit.dart +++ b/lib/logic/cubit/book_cubit.dart @@ -74,6 +74,7 @@ class BookCubit extends Cubit { getFinishedBooks(); getInProgressBooks(); getToReadBooks(); + getUnfinishedBooks(); getAllBooks(); } diff --git a/lib/main.dart b/lib/main.dart index 9bceea43a..1bc09580e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,10 @@ import 'package:openreads/logic/bloc/migration_v1_to_v2_bloc/migration_v1_to_v2_ import 'package:openreads/logic/bloc/open_lib_bloc/open_lib_bloc.dart'; import 'package:openreads/logic/bloc/open_library_search_bloc/open_library_search_bloc.dart'; import 'package:openreads/logic/bloc/rating_type_bloc/rating_type_bloc.dart'; -import 'package:openreads/logic/bloc/sort_bloc/sort_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_finished_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_for_later_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_in_progress_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_unfinished_books_bloc.dart'; import 'package:openreads/logic/bloc/theme_bloc/theme_bloc.dart'; import 'package:openreads/logic/bloc/welcome_bloc/welcome_bloc.dart'; import 'package:openreads/logic/cubit/book_cubit.dart'; @@ -91,13 +94,19 @@ class App extends StatelessWidget { BlocProvider(create: (_) => DefaultBooksFormatCubit()), BlocProvider(create: (_) => ThemeBloc()), BlocProvider(create: (_) => DisplayBloc()), - BlocProvider(create: (_) => SortBloc()), BlocProvider(create: (_) => BooksTabIndexCubit()), BlocProvider(create: (_) => WelcomeBloc()), BlocProvider(create: (_) => RatingTypeBloc()), BlocProvider(create: (_) => MigrationV1ToV2Bloc()), ]; + final sortProviders = [ + BlocProvider(create: (_) => SortFinishedBooksBloc()), + BlocProvider(create: (_) => SortInProgressBooksBloc()), + BlocProvider(create: (_) => SortForLaterBooksBloc()), + BlocProvider(create: (_) => SortUnfinishedBooksBloc()), + ]; + final openLibraryProviders = [ BlocProvider(create: (_) => OpenLibrarySearchBloc()), BlocProvider( @@ -111,6 +120,7 @@ class App extends StatelessWidget { return [ ...bookProviders, ...settingsProviders, + ...sortProviders, ...openLibraryProviders, ]; } diff --git a/lib/ui/books_screen/books_screen.dart b/lib/ui/books_screen/books_screen.dart index d3cb1b42b..180c13dbe 100644 --- a/lib/ui/books_screen/books_screen.dart +++ b/lib/ui/books_screen/books_screen.dart @@ -8,7 +8,11 @@ import 'package:openreads/core/constants/enums/sort_type.dart'; import 'package:openreads/core/helpers/helpers.dart'; import 'package:openreads/generated/locale_keys.g.dart'; import 'package:openreads/logic/bloc/display_bloc/display_bloc.dart'; -import 'package:openreads/logic/bloc/sort_bloc/sort_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_finished_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_for_later_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_in_progress_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_state.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_unfinished_books_bloc.dart'; import 'package:openreads/logic/cubit/book_lists_order_cubit.dart'; import 'package:openreads/main.dart'; import 'package:openreads/model/book.dart'; @@ -27,7 +31,7 @@ class _BooksScreenState extends State late ScrollController _chipScrollController; List _sortReadList({ - required SetSortState state, + required SortState state, required List list, }) { if (state.onlyFavourite) { @@ -51,41 +55,11 @@ class _BooksScreenState extends State list = _filterOutBookTypes(list, state.bookType!); } - switch (state.sortType) { - case SortType.byAuthor: - list = _sortByAuthor(list: list, isAsc: state.isAsc); - break; - case SortType.byRating: - list = _sortByRating(list: list, isAsc: state.isAsc); - break; - case SortType.byPages: - list = _sortByPages(list: list, isAsc: state.isAsc); - break; - case SortType.byStartDate: - list = _sortByStartDate(list: list, isAsc: state.isAsc); - break; - case SortType.byFinishDate: - list = _sortByFinishDate(list: list, isAsc: state.isAsc); - break; - case SortType.byPublicationYear: - list = _sortByPublicationYear(list: list, isAsc: state.isAsc); - break; - case SortType.byDateAdded: - list = _sortByDateAdded(list: list, isAsc: state.isAsc); - break; - case SortType.byDateModified: - list = _sortByDateModified(list: list, isAsc: state.isAsc); - break; - - default: - list = _sortByTitle(list: list, isAsc: state.isAsc); - } - - return list; + return _sort(list: list, sortType: state.sortType, isAsc: state.isAsc); } List _sortInProgressList({ - required SetSortState state, + required SortState state, required List list, }) { if (state.tags != null) { @@ -101,35 +75,11 @@ class _BooksScreenState extends State list = _filterOutBookTypes(list, state.bookType!); } - switch (state.sortType) { - case SortType.byAuthor: - list = _sortByAuthor(list: list, isAsc: state.isAsc); - break; - - case SortType.byPages: - list = _sortByPages(list: list, isAsc: state.isAsc); - break; - case SortType.byStartDate: - list = _sortByStartDate(list: list, isAsc: state.isAsc); - break; - case SortType.byPublicationYear: - list = _sortByPublicationYear(list: list, isAsc: state.isAsc); - break; - case SortType.byDateAdded: - list = _sortByDateAdded(list: list, isAsc: state.isAsc); - break; - case SortType.byDateModified: - list = _sortByDateModified(list: list, isAsc: state.isAsc); - break; - default: - list = _sortByTitle(list: list, isAsc: state.isAsc); - } - - return list; + return _sort(list: list, sortType: state.sortType, isAsc: state.isAsc); } List _sortForLaterList({ - required SetSortState state, + required SortState state, required List list, }) { if (state.tags != null) { @@ -145,32 +95,11 @@ class _BooksScreenState extends State list = _filterOutBookTypes(list, state.bookType!); } - switch (state.sortType) { - case SortType.byAuthor: - list = _sortByAuthor(list: list, isAsc: state.isAsc); - break; - case SortType.byPages: - list = _sortByPages(list: list, isAsc: state.isAsc); - break; - case SortType.byPublicationYear: - list = _sortByPublicationYear(list: list, isAsc: state.isAsc); - break; - case SortType.byDateAdded: - list = _sortByDateAdded(list: list, isAsc: state.isAsc); - break; - case SortType.byDateModified: - list = _sortByDateModified(list: list, isAsc: state.isAsc); - break; - - default: - list = _sortByTitle(list: list, isAsc: state.isAsc); - } - - return list; + return _sort(list: list, sortType: state.sortType, isAsc: state.isAsc); } List _sortUnfinishedList({ - required SetSortState state, + required SortState state, required List list, }) { if (state.tags != null) { @@ -186,30 +115,7 @@ class _BooksScreenState extends State list = _filterOutBookTypes(list, state.bookType!); } - switch (state.sortType) { - case SortType.byAuthor: - list = _sortByAuthor(list: list, isAsc: state.isAsc); - break; - case SortType.byPages: - list = _sortByPages(list: list, isAsc: state.isAsc); - break; - case SortType.byStartDate: - list = _sortByStartDate(list: list, isAsc: state.isAsc); - break; - case SortType.byPublicationYear: - list = _sortByPublicationYear(list: list, isAsc: state.isAsc); - break; - case SortType.byDateAdded: - list = _sortByDateAdded(list: list, isAsc: state.isAsc); - break; - case SortType.byDateModified: - list = _sortByDateModified(list: list, isAsc: state.isAsc); - break; - default: - list = _sortByTitle(list: list, isAsc: state.isAsc); - } - - return list; + return _sort(list: list, sortType: state.sortType, isAsc: state.isAsc); } List _filterOutFav({required List list}) { @@ -370,6 +276,33 @@ class _BooksScreenState extends State return filteredOut; } + List _sort({ + required List list, + required SortType sortType, + required bool isAsc, + }) { + switch (sortType) { + case SortType.byTitle: + return _sortByTitle(list: list, isAsc: isAsc); + case SortType.byAuthor: + return _sortByAuthor(list: list, isAsc: isAsc); + case SortType.byRating: + return _sortByRating(list: list, isAsc: isAsc); + case SortType.byPages: + return _sortByPages(list: list, isAsc: isAsc); + case SortType.byStartDate: + return _sortByStartDate(list: list, isAsc: isAsc); + case SortType.byFinishDate: + return _sortByFinishDate(list: list, isAsc: isAsc); + case SortType.byPublicationYear: + return _sortByPublicationYear(list: list, isAsc: isAsc); + case SortType.byDateAdded: + return _sortByDateAdded(list: list, isAsc: isAsc); + case SortType.byDateModified: + return _sortByDateModified(list: list, isAsc: isAsc); + } + } + List _sortByTitle({ required List list, required bool isAsc, @@ -771,45 +704,66 @@ class _BooksScreenState extends State ); } - StreamBuilder> _buildFinishedBooksTabView() { - return _buildBooksTabView( - listNumber: 0, - stream: bookCubit.finishedBooks, - sorting: _sortReadList, + BlocBuilder _buildFinishedBooksTabView() { + return BlocBuilder( + builder: (context, state) { + return _buildBooksTabView( + listNumber: 0, + stream: bookCubit.finishedBooks, + sortState: state, + sorting: _sortReadList, + ); + }, ); } - StreamBuilder> _buildInProgressBooksTabView() { - return _buildBooksTabView( - listNumber: 1, - stream: bookCubit.inProgressBooks, - sorting: _sortInProgressList, + BlocBuilder + _buildInProgressBooksTabView() { + return BlocBuilder( + builder: (context, state) { + return _buildBooksTabView( + listNumber: 1, + stream: bookCubit.inProgressBooks, + sortState: state, + sorting: _sortInProgressList, + ); + }, ); } - StreamBuilder> _buildToReadBooksTabView() { - return _buildBooksTabView( - listNumber: 2, - stream: bookCubit.toReadBooks, - sorting: _sortForLaterList, + BlocBuilder _buildToReadBooksTabView() { + return BlocBuilder( + builder: (context, state) { + return _buildBooksTabView( + listNumber: 2, + stream: bookCubit.toReadBooks, + sortState: state, + sorting: _sortForLaterList, + ); + }, ); } - StreamBuilder> _buildUnfinishedBooksTabView() { - bookCubit.getUnfinishedBooks(); - - return _buildBooksTabView( - listNumber: 3, - stream: bookCubit.unfinishedBooks, - sorting: _sortUnfinishedList, + BlocBuilder + _buildUnfinishedBooksTabView() { + return BlocBuilder( + builder: (context, state) { + return _buildBooksTabView( + listNumber: 3, + stream: bookCubit.unfinishedBooks, + sortState: state, + sorting: _sortUnfinishedList, + ); + }, ); } StreamBuilder> _buildBooksTabView({ required int listNumber, required Stream> stream, - required List Function({ - required SetSortState state, + required SortState sortState, + List Function({ + required SortState state, required List list, })? sorting, }) { @@ -821,49 +775,37 @@ class _BooksScreenState extends State return const ThisListIsEmpty(); } - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - return BlocBuilder( - builder: (context, displayState) { - if (displayState is GridDisplayState) { - return BooksGrid( - books: sorting != null - ? sorting( - state: state, - list: snapshot.data!, - ) - : snapshot.data!, - listNumber: listNumber, - allBooksCount: snapshot.data!.length, - ); - } else { - return BooksList( - books: sorting != null - ? sorting( - state: state, - list: snapshot.data!, - ) - : snapshot.data!, - listNumber: listNumber, - allBooksCount: snapshot.data!.length, - ); - } - }, + return BlocBuilder( + builder: (context, displayState) { + if (displayState is GridDisplayState) { + return BooksGrid( + books: sorting != null + ? sorting( + state: sortState, + list: snapshot.data!, + ) + : snapshot.data!, + listNumber: listNumber, + allBooksCount: snapshot.data!.length, ); } else { - return const SizedBox.shrink(); + return BooksList( + books: sorting != null + ? sorting( + state: sortState, + list: snapshot.data!, + ) + : snapshot.data!, + listNumber: listNumber, + allBooksCount: snapshot.data!.length, + ); } }, ); } else if (snapshot.hasError) { - return Text( - snapshot.error.toString(), - ); + return Text(snapshot.error.toString()); } else { - return const Center( - child: CircularProgressIndicator(), - ); + return const Center(child: CircularProgressIndicator()); } }, ); diff --git a/lib/ui/books_screen/widgets/book_card.dart b/lib/ui/books_screen/widgets/book_card.dart index 5a6897dbc..97b0b24d1 100644 --- a/lib/ui/books_screen/widgets/book_card.dart +++ b/lib/ui/books_screen/widgets/book_card.dart @@ -9,7 +9,11 @@ import 'package:openreads/core/helpers/helpers.dart'; import 'package:openreads/core/themes/app_theme.dart'; import 'package:openreads/generated/locale_keys.g.dart'; import 'package:openreads/logic/bloc/rating_type_bloc/rating_type_bloc.dart'; -import 'package:openreads/logic/bloc/sort_bloc/sort_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_finished_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_for_later_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_in_progress_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_state.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_unfinished_books_bloc.dart'; import 'package:openreads/main.dart'; import 'package:openreads/model/book.dart'; @@ -37,55 +41,70 @@ class BookCard extends StatefulWidget { class _BookCardState extends State { Widget _buildSortAttribute() { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - if (state.sortType == SortType.byPages) { - return (widget.book.pages != null) - ? _buildPagesAttribute() - : const SizedBox(); - } else if (state.sortType == SortType.byStartDate) { - final latestStartDate = getLatestStartDate(widget.book); + switch (widget.book.status) { + case BookStatus.read: + return BlocBuilder( + builder: (_, state) => _buildSortAttributeContent(state.sortType), + ); + case BookStatus.inProgress: + return BlocBuilder( + builder: (_, state) => _buildSortAttributeContent(state.sortType), + ); + case BookStatus.forLater: + return BlocBuilder( + builder: (_, state) => _buildSortAttributeContent(state.sortType), + ); + case BookStatus.unfinished: + return BlocBuilder( + builder: (_, state) => _buildSortAttributeContent(state.sortType), + ); + } + } - return (latestStartDate != null) - ? _buildDateAttribute( - latestStartDate, - LocaleKeys.started_on_date.tr(), - false, - ) - : const SizedBox(); - } else if (state.sortType == SortType.byFinishDate) { - final latestFinishDate = getLatestFinishDate(widget.book); + Widget _buildSortAttributeContent(SortType sortType) { + if (sortType == SortType.byPages) { + return (widget.book.pages != null) + ? _buildPagesAttribute() + : const SizedBox(); + } else if (sortType == SortType.byStartDate) { + final latestStartDate = getLatestStartDate(widget.book); - return (latestFinishDate != null) - ? _buildDateAttribute( - latestFinishDate, - LocaleKeys.finished_on_date.tr(), - false, - ) - : const SizedBox(); - } else if (state.sortType == SortType.byDateAdded) { - return _buildDateAttribute( - widget.book.dateAdded, - LocaleKeys.added_on.tr(), - true, - ); - } else if (state.sortType == SortType.byDateModified) { - return _buildDateAttribute( - widget.book.dateModified, - LocaleKeys.modified_on.tr(), - true, - ); - } else if (state.sortType == SortType.byPublicationYear) { - return (widget.book.publicationYear != null) - ? _buildPublicationYearAttribute() - : const SizedBox(); - } - } + return (latestStartDate != null) + ? _buildDateAttribute( + latestStartDate, + LocaleKeys.started_on_date.tr(), + false, + ) + : const SizedBox(); + } else if (sortType == SortType.byFinishDate) { + final latestFinishDate = getLatestFinishDate(widget.book); - return const SizedBox(); - }, - ); + return (latestFinishDate != null) + ? _buildDateAttribute( + latestFinishDate, + LocaleKeys.finished_on_date.tr(), + false, + ) + : const SizedBox(); + } else if (sortType == SortType.byDateAdded) { + return _buildDateAttribute( + widget.book.dateAdded, + LocaleKeys.added_on.tr(), + true, + ); + } else if (sortType == SortType.byDateModified) { + return _buildDateAttribute( + widget.book.dateModified, + LocaleKeys.modified_on.tr(), + true, + ); + } else if (sortType == SortType.byPublicationYear) { + return (widget.book.publicationYear != null) + ? _buildPublicationYearAttribute() + : const SizedBox(); + } + + return const SizedBox(); } Text _buildPagesAttribute() => @@ -140,30 +159,43 @@ class _BookCardState extends State { } Widget _buildTags() { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - if (state.displayTags) { - return (widget.book.tags == null) - ? const SizedBox() - : Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Expanded( - child: Wrap( - children: _generateTagChips( - context: context, - ), - ), - ), - ], - ); - } - } + switch (widget.book.status) { + case BookStatus.read: + return BlocBuilder( + builder: (_, state) => _buildTagsContent(state.displayTags), + ); + case BookStatus.inProgress: + return BlocBuilder( + builder: (_, state) => _buildTagsContent(state.displayTags), + ); + case BookStatus.forLater: + return BlocBuilder( + builder: (_, state) => _buildTagsContent(state.displayTags), + ); + case BookStatus.unfinished: + return BlocBuilder( + builder: (_, state) => _buildTagsContent(state.displayTags), + ); + } + } - return const SizedBox(); - }, - ); + Widget _buildTagsContent(bool displayTags) { + if (displayTags) { + return (widget.book.tags == null) + ? const SizedBox() + : Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Expanded( + child: Wrap( + children: _generateTagChips(context: context), + ), + ), + ], + ); + } + + return const SizedBox(); } Widget _buildTagChip({ diff --git a/lib/ui/home_screen/widgets/sort_bottom_sheet.dart b/lib/ui/home_screen/widgets/sort_bottom_sheet.dart index 0661e8586..2e03c623f 100644 --- a/lib/ui/home_screen/widgets/sort_bottom_sheet.dart +++ b/lib/ui/home_screen/widgets/sort_bottom_sheet.dart @@ -9,7 +9,12 @@ import 'package:openreads/core/constants/enums/enums.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:openreads/core/themes/app_theme.dart'; import 'package:openreads/generated/locale_keys.g.dart'; -import 'package:openreads/logic/bloc/sort_bloc/sort_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_event.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_finished_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_for_later_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_in_progress_books_bloc.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_state.dart'; +import 'package:openreads/logic/bloc/sort_bloc/sort_unfinished_books_bloc.dart'; import 'package:openreads/logic/cubit/book_lists_order_cubit.dart'; import 'package:openreads/logic/cubit/books_tab_index_cubit.dart'; import 'package:openreads/main.dart'; @@ -22,304 +27,122 @@ class SortBottomSheet extends StatefulWidget { State createState() => _SortBottomSheetState(); } -final List sortOptions = [ - LocaleKeys.title.tr(), - LocaleKeys.author.tr(), - LocaleKeys.rating.tr(), - LocaleKeys.pages_uppercase.tr(), - LocaleKeys.start_date.tr(), - LocaleKeys.finish_date.tr(), - LocaleKeys.enter_publication_year.tr(), - LocaleKeys.date_added.tr(), - LocaleKeys.date_modified.tr(), -]; - -final List bookTypeOptions = [ - LocaleKeys.book_format_all.tr(), - LocaleKeys.book_format_paperback_plural.tr(), - LocaleKeys.book_format_hardcover_plural.tr(), - LocaleKeys.book_format_ebook_plural.tr(), - LocaleKeys.book_format_audiobook_plural.tr(), -]; - -List _getValidSortOptions(BookStatus bookStatus) { +List _getValidSortOptions(BookStatus bookStatus) { switch (bookStatus) { case BookStatus.read: return [ - LocaleKeys.title.tr(), - LocaleKeys.author.tr(), - LocaleKeys.rating.tr(), - LocaleKeys.pages_uppercase.tr(), - LocaleKeys.start_date.tr(), - LocaleKeys.finish_date.tr(), - LocaleKeys.enter_publication_year.tr(), - LocaleKeys.date_added.tr(), - LocaleKeys.date_modified.tr(), + SortType.byTitle, + SortType.byAuthor, + SortType.byRating, + SortType.byPages, + SortType.byStartDate, + SortType.byFinishDate, + SortType.byPublicationYear, + SortType.byDateAdded, + SortType.byDateModified, ]; case BookStatus.inProgress: return [ - LocaleKeys.title.tr(), - LocaleKeys.author.tr(), - LocaleKeys.pages_uppercase.tr(), - LocaleKeys.start_date.tr(), - LocaleKeys.enter_publication_year.tr(), - LocaleKeys.date_added.tr(), - LocaleKeys.date_modified.tr(), + SortType.byTitle, + SortType.byAuthor, + SortType.byPages, + SortType.byStartDate, + SortType.byPublicationYear, + SortType.byDateAdded, + SortType.byDateModified, ]; case BookStatus.forLater: return [ - LocaleKeys.title.tr(), - LocaleKeys.author.tr(), - LocaleKeys.pages_uppercase.tr(), - LocaleKeys.enter_publication_year.tr(), - LocaleKeys.date_added.tr(), - LocaleKeys.date_modified.tr(), + SortType.byTitle, + SortType.byAuthor, + SortType.byPages, + SortType.byPublicationYear, + SortType.byDateAdded, + SortType.byDateModified, ]; case BookStatus.unfinished: return [ - LocaleKeys.title.tr(), - LocaleKeys.author.tr(), - LocaleKeys.pages_uppercase.tr(), - LocaleKeys.start_date.tr(), - LocaleKeys.enter_publication_year.tr(), - LocaleKeys.date_added.tr(), - LocaleKeys.date_modified.tr(), + SortType.byTitle, + SortType.byAuthor, + SortType.byPages, + SortType.byStartDate, + SortType.byPublicationYear, + SortType.byDateAdded, + SortType.byDateModified, ]; - default: - return []; - } -} - -String _getSortDropdownValue(BookStatus bookStatus, SetSortState state) { - if (state.sortType == SortType.byAuthor) { - return sortOptions[1]; - } else if (bookStatus == BookStatus.read && - state.sortType == SortType.byRating) { - return sortOptions[2]; - } else if (state.sortType == SortType.byPages) { - return sortOptions[3]; - } else if (bookStatus != BookStatus.forLater && - state.sortType == SortType.byStartDate) { - return sortOptions[4]; - } else if (bookStatus == BookStatus.read && - state.sortType == SortType.byFinishDate) { - return sortOptions[5]; - } else if (state.sortType == SortType.byPublicationYear) { - return sortOptions[6]; - } else if (state.sortType == SortType.byDateAdded) { - return sortOptions[7]; - } else if (state.sortType == SortType.byDateModified) { - return sortOptions[8]; - } else { - return sortOptions[0]; } } -String _getBookTypeDropdownValue(SetSortState state) { - if (state.bookType == BookFormat.paperback) { - return bookTypeOptions[1]; - } else if (state.bookType == BookFormat.hardcover) { - return bookTypeOptions[2]; - } else if (state.bookType == BookFormat.ebook) { - return bookTypeOptions[3]; - } else if (state.bookType == BookFormat.audiobook) { - return bookTypeOptions[4]; - } else { - return bookTypeOptions[0]; +String _getSortDropdownText(SortType sortType) { + switch (sortType) { + case SortType.byTitle: + return LocaleKeys.title.tr(); + case SortType.byAuthor: + return LocaleKeys.author.tr(); + case SortType.byRating: + return LocaleKeys.rating.tr(); + case SortType.byPages: + return LocaleKeys.pages_uppercase.tr(); + case SortType.byStartDate: + return LocaleKeys.start_date.tr(); + case SortType.byFinishDate: + return LocaleKeys.finish_date.tr(); + case SortType.byPublicationYear: + return LocaleKeys.enter_publication_year.tr(); + case SortType.byDateAdded: + return LocaleKeys.date_added.tr(); + case SortType.byDateModified: + return LocaleKeys.date_modified.tr(); } } -Widget _getOrderButton(BuildContext context, SetSortState state) { - return SizedBox( - height: 40, - width: 40, - child: IconButton( - icon: (state.isAsc) - ? const FaIcon(FontAwesomeIcons.arrowUp, size: 18) - : const FaIcon(FontAwesomeIcons.arrowDown, size: 18), - onPressed: () => BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: !state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ), - ), - ); -} - -void _updateSort(BuildContext context, String? value, SetSortState state) { - late SortType sortType; - - if (value == sortOptions[1]) { - sortType = SortType.byAuthor; - } else if (value == sortOptions[2]) { - sortType = SortType.byRating; - } else if (value == sortOptions[3]) { - sortType = SortType.byPages; - } else if (value == sortOptions[4]) { - sortType = SortType.byStartDate; - } else if (value == sortOptions[5]) { - sortType = SortType.byFinishDate; - } else if (value == sortOptions[6]) { - sortType = SortType.byPublicationYear; - } else if (value == sortOptions[7]) { - sortType = SortType.byDateAdded; - } else if (value == sortOptions[8]) { - sortType = SortType.byDateModified; - } else { - sortType = SortType.byTitle; +String _getBookTypeDropdownText(BookFormat? bookFormat) { + if (bookFormat == null) return LocaleKeys.book_format_all.tr(); + switch (bookFormat) { + case BookFormat.paperback: + return LocaleKeys.book_format_paperback_plural.tr(); + case BookFormat.hardcover: + return LocaleKeys.book_format_hardcover_plural.tr(); + case BookFormat.ebook: + return LocaleKeys.book_format_ebook_plural.tr(); + case BookFormat.audiobook: + return LocaleKeys.book_format_audiobook_plural.tr(); } - - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ); } -void _updateBookType(BuildContext context, String? value, SetSortState state) { - BookFormat? bookType; - - if (value == bookTypeOptions[1]) { - bookType = BookFormat.paperback; - } else if (value == bookTypeOptions[2]) { - bookType = BookFormat.hardcover; - } else if (value == bookTypeOptions[3]) { - bookType = BookFormat.ebook; - } else if (value == bookTypeOptions[4]) { - bookType = BookFormat.audiobook; - } else { - bookType = null; +class _SortBottomSheetState extends State { + Bloc _getBlocProvider(BookStatus bookStatus) { + switch (bookStatus) { + case BookStatus.read: + return BlocProvider.of(context); + case BookStatus.inProgress: + return BlocProvider.of(context); + case BookStatus.forLater: + return BlocProvider.of(context); + case BookStatus.unfinished: + return BlocProvider.of(context); + } } - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: bookType, - filterOutTags: state.filterOutTags, - ), - ); -} - -class _SortBottomSheetState extends State { - Widget _getFavouriteSwitch( - BuildContext context, - SetSortState state, - ) { + Widget _getOrderButton(BookStatus bookStatus, SortState sortState) { return SizedBox( height: 40, - child: Switch.adaptive( - value: state.onlyFavourite, - onChanged: (value) => BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: value, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ), - ), - ); - } - - Widget _getTagsSwitch( - BuildContext context, - SetSortState state, - ) { - return Switch.adaptive( - value: state.displayTags, - onChanged: (value) => BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: value, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ), - ); - } - - Widget _getTagsAsAndSwitch( - BuildContext context, - SetSortState state, - ) { - return Switch.adaptive( - value: state.filterTagsAsAnd, - onChanged: (value) => BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: value, - bookType: state.bookType, - filterOutTags: false, - ), - ), - ); - } - - Widget _getFilterOutTagsSwitch( - BuildContext context, - SetSortState state, - ) { - return Switch.adaptive( - value: state.filterOutTags, - onChanged: (value) => BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: false, - bookType: state.bookType, - filterOutTags: value, - ), + width: 40, + child: IconButton( + icon: sortState.isAsc + ? const FaIcon(FontAwesomeIcons.arrowUp, size: 18) + : const FaIcon(FontAwesomeIcons.arrowDown, size: 18), + onPressed: () => + _getBlocProvider(bookStatus).add(const ToggleOrderEvent()), ), ); } _onYearChipPressed({ + required BookStatus bookStatus, required bool selected, required List selectedYearsList, - required List dbYears, required int dbYear, - required SetSortState state, }) { if (selectedYearsList.isNotEmpty && selectedYearsList[0] == '') { selectedYearsList.removeAt(0); @@ -334,28 +157,18 @@ class _SortBottomSheetState extends State { } } - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: (selectedYearsList.isEmpty) - ? null - : selectedYearsList.join('|||||'), - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, + _getBlocProvider(bookStatus).add( + ChangeYearsEvent( + selectedYearsList.isEmpty ? null : selectedYearsList.join('|||||'), ), ); } _onTagChipPressed({ + required BookStatus bookStatus, required bool selected, required List selectedTagsList, required String dbTag, - required SetSortState state, }) { if (selectedTagsList.isNotEmpty && selectedTagsList[0] == '') { selectedTagsList.removeAt(0); @@ -370,31 +183,24 @@ class _SortBottomSheetState extends State { } } - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: - (selectedTagsList.isEmpty) ? null : selectedTagsList.join('|||||'), - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, + _getBlocProvider(bookStatus).add( + ChangeTagsEvent( + selectedTagsList.isEmpty ? null : selectedTagsList.join('|||||'), ), ); } List _buildYearChips( - SetSortState state, + BookStatus bookStatus, List dbYears, String? selectedYears, ) { final chips = List.empty(growable: true); final inactiveChips = List.empty(growable: true); - late List selectedYearsList; + List selectedYearsList = selectedYears != null + ? selectedYears.split('|||||') + : List.empty(growable: true); final uniqueDbYears = List.empty(growable: true); @@ -404,12 +210,6 @@ class _SortBottomSheetState extends State { } } - if (selectedYears != null) { - selectedYearsList = selectedYears.split('|||||'); - } else { - selectedYearsList = List.empty(growable: true); - } - for (var selectedYear in selectedYearsList) { if (!uniqueDbYears.contains(int.parse(selectedYear))) { uniqueDbYears.add(int.parse(selectedYear)); @@ -421,15 +221,12 @@ class _SortBottomSheetState extends State { YearFilterChip chip = YearFilterChip( dbYear: dbYear, selected: isSelected, - onYearChipPressed: (bool selected) { - _onYearChipPressed( - dbYear: dbYear, - dbYears: uniqueDbYears, - selected: selected, - selectedYearsList: selectedYearsList, - state: state, - ); - }, + onYearChipPressed: (bool selected) => _onYearChipPressed( + bookStatus: bookStatus, + dbYear: dbYear, + selected: selected, + selectedYearsList: selectedYearsList, + ), ); if (isSelected) { @@ -446,23 +243,13 @@ class _SortBottomSheetState extends State { YearFilterChip( dbYear: null, selected: selectedYears == dbYears.join('|||||'), - onYearChipPressed: (bool selected) { - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: selectedYears == dbYears.join('|||||') - ? null - : dbYears.join('|||||'), - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ); - }, + onYearChipPressed: (_) => _getBlocProvider(bookStatus).add( + ChangeYearsEvent( + selectedYears == dbYears.join('|||||') + ? null + : dbYears.join('|||||'), + ), + ), ), ); @@ -470,7 +257,7 @@ class _SortBottomSheetState extends State { } List _buildTagChips( - SetSortState state, + BookStatus bookStatus, List dbTags, String? selectedTags, ) { @@ -504,10 +291,10 @@ class _SortBottomSheetState extends State { selected: isSelected, onTagChipPressed: (bool selected) { _onTagChipPressed( + bookStatus: bookStatus, dbTag: dbTag, selected: selected, selectedTagsList: selectedTagsList, - state: state, ); }, ); @@ -526,23 +313,11 @@ class _SortBottomSheetState extends State { TagFilterChip( tag: null, selected: selectedTags == dbTags.join('|||||'), - onTagChipPressed: (bool selected) { - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: selectedTags == dbTags.join('|||||') - ? null - : dbTags.join('|||||'), - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ); - }, + onTagChipPressed: (_) => _getBlocProvider(bookStatus).add( + ChangeTagsEvent( + selectedTags == dbTags.join('|||||') ? null : dbTags.join('|||||'), + ), + ), ), ); @@ -574,32 +349,37 @@ class _SortBottomSheetState extends State { ), Padding( padding: const EdgeInsets.fromLTRB(20, 10, 20, 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 5), - Text( - LocaleKeys.sort_by.tr(), - style: const TextStyle(fontSize: 16), - ), - const SizedBox(height: 5), - _buildSortDropdown(), - const SizedBox(height: 5), - _buildOnlyFavouriteSwitch(), - const SizedBox(height: 5), - Text( - LocaleKeys.filter_by_book_format.tr(), - style: const TextStyle(fontSize: 16), - ), - const SizedBox(height: 5), - _buildBookTypeFilter(), - _buildFilterByFinishYears(), - _buildFilterByTags(), - _buildFilterTagsAsAnd(), - _buildFilterOutTags(), - const SizedBox(height: 5), - _buildDisplayTags(), - ], + child: BlocBuilder>( + builder: (context, bookStatusList) { + return BlocBuilder( + builder: (context, tabIndex) { + switch (bookStatusList[tabIndex]) { + case BookStatus.read: + return BlocBuilder( + builder: (context, state) => + _buildBody(BookStatus.read, state), + ); + case BookStatus.inProgress: + return BlocBuilder( + builder: (context, state) => + _buildBody(BookStatus.inProgress, state), + ); + case BookStatus.forLater: + return BlocBuilder( + builder: (context, state) => + _buildBody(BookStatus.forLater, state), + ); + case BookStatus.unfinished: + return BlocBuilder( + builder: (context, state) => + _buildBody(BookStatus.unfinished, state), + ); + } + }, + ); + }, ), ), ], @@ -608,447 +388,351 @@ class _SortBottomSheetState extends State { ); } - BlocBuilder _buildDisplayTags() { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - return Row( - children: [ - Expanded( - child: InkWell( - onTap: () { - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: !state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ); - }, - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceVariant, - borderRadius: BorderRadius.circular(cornerRadius), - border: Border.all( - color: dividerColor, - ), - ), - child: Row( - children: [ - _getTagsSwitch(context, state), - const SizedBox(width: 10), - Text( - LocaleKeys.display_tags.tr(), - style: const TextStyle(fontSize: 16), - ), - ], - ), + Widget _buildBody(BookStatus bookStatus, SortState sortState) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 5), + Text( + LocaleKeys.sort_by.tr(), + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 5), + _buildSortDropdown(bookStatus, sortState), + const SizedBox(height: 5), + if (bookStatus == BookStatus.read) + _buildOnlyFavouriteSwitch(bookStatus, sortState.onlyFavourite), + const SizedBox(height: 5), + Text( + LocaleKeys.filter_by_book_format.tr(), + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 5), + _buildBookTypeFilter(bookStatus, sortState.bookType), + if (bookStatus == BookStatus.read) + _buildFilterByFinishYears(bookStatus, sortState.years), + _buildFilterByTags(bookStatus, sortState.tags), + _buildFilterTagsAsAnd(bookStatus, sortState.filterTagsAsAnd), + _buildFilterOutTags(bookStatus, sortState.filterOutTags), + const SizedBox(height: 5), + _buildDisplayTags(bookStatus, sortState.displayTags), + ], + ); + } + + Row _buildDisplayTags(BookStatus bookStatus, bool displayTags) { + return Row( + children: [ + Expanded( + child: InkWell( + onTap: () => _getBlocProvider(bookStatus) + .add(ChangeDisplayTagsEvent(!displayTags)), + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceVariant, + borderRadius: BorderRadius.circular(cornerRadius), + border: Border.all(color: dividerColor), + ), + child: Row( + children: [ + Switch.adaptive( + value: displayTags, + onChanged: (value) => _getBlocProvider(bookStatus) + .add(ChangeDisplayTagsEvent(value)), ), - ), + const SizedBox(width: 10), + Text( + LocaleKeys.display_tags.tr(), + style: const TextStyle(fontSize: 16), + ), + ], ), - ], - ); - } else { - return const SizedBox(); - } - }, + ), + ), + ), + ], ); } - BlocBuilder _buildFilterOutTags() { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - return Row( - children: [ - Expanded( - child: InkWell( - onTap: () { - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: false, - bookType: state.bookType, - filterOutTags: !state.filterOutTags, - ), - ); - }, - child: _buildBooksExceptTags(context, state), - ), - ), - ], - ); - } else { - return const SizedBox(); - } - }, + Row _buildFilterOutTags(BookStatus bookStatus, bool filterOutTags) { + return Row( + children: [ + Expanded( + child: InkWell( + onTap: () => _getBlocProvider(bookStatus) + .add(ChangeFilterOutTags(!filterOutTags)), + child: _buildBooksExceptTags(bookStatus, filterOutTags), + ), + ), + ], ); } - BlocBuilder _buildFilterTagsAsAnd() { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - return Row( - children: [ - Expanded( - child: InkWell( - onTap: () { - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: !state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ); - }, - child: _buildOnlyBooksWithAllTags(context, state), - ), - ), - ], - ); - } else { - return const SizedBox(); - } - }, + Row _buildFilterTagsAsAnd(BookStatus bookStatus, bool filterTagsAsAnd) { + return Row( + children: [ + Expanded( + child: InkWell( + onTap: () => _getBlocProvider(bookStatus) + .add(ChangeFilterTagsAsAnd(!filterTagsAsAnd)), + child: _buildOnlyBooksWithAllTags(bookStatus, filterTagsAsAnd), + ), + ), + ], ); } - StreamBuilder> _buildFilterByTags() { + StreamBuilder> _buildFilterByTags( + BookStatus bookStatus, + String? tags, + ) { return StreamBuilder>( stream: bookCubit.tags, builder: (context, AsyncSnapshot> snapshot) { if (snapshot.hasData) { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - if (snapshot.data!.isEmpty && state.tags == null) { - return const SizedBox(); - } + if (snapshot.data!.isEmpty && tags == null) { + return const SizedBox(); + } - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 5), - Text( - LocaleKeys.filter_by_tags.tr(), - style: const TextStyle(fontSize: 16), - ), - const SizedBox(height: 5), - Row( - children: [ - Expanded( - child: Container( - decoration: BoxDecoration( - color: - Theme.of(context).colorScheme.surfaceVariant, - borderRadius: BorderRadius.circular( - cornerRadius, - ), - border: Border.all( - color: dividerColor, - ), - ), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 5, - horizontal: 2.5, - ), - child: Row( - children: _buildTagChips( - state, - snapshot.data!, - state.tags, - ), - ), - ), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 5), + Text( + LocaleKeys.filter_by_tags.tr(), + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 5), + Row( + children: [ + Expanded( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceVariant, + borderRadius: BorderRadius.circular(cornerRadius), + border: Border.all(color: dividerColor), + ), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 5, + horizontal: 2.5, + ), + child: Row( + children: _buildTagChips( + bookStatus, + snapshot.data!, + tags, ), ), ), - ], + ), ), - ], - ); - } else { - return const SizedBox(); - } - }, + ), + ], + ), + ], ); } else if (snapshot.hasData && snapshot.data!.isEmpty) { return const SizedBox(); } else if (snapshot.hasError) { - return Text( - snapshot.error.toString(), - ); + return Text(snapshot.error.toString()); } else { - return const Center( - child: CircularProgressIndicator(), - ); + return const Center(child: CircularProgressIndicator()); } }, ); } - StreamBuilder> _buildFilterByFinishYears() { + StreamBuilder> _buildFilterByFinishYears( + BookStatus bookStatus, + String? years, + ) { return StreamBuilder>( stream: bookCubit.finishedYears, builder: (context, AsyncSnapshot> snapshot) { if (snapshot.hasData) { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - if (snapshot.data!.isEmpty && state.years == null) { - return const SizedBox(); - } + if (snapshot.data!.isEmpty && years == null) { + return const SizedBox(); + } - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox(height: 5), - Text( - LocaleKeys.filter_by_finish_year.tr(), - style: const TextStyle(fontSize: 16), - ), - const SizedBox(height: 5), - Row( - children: [ - Expanded( - child: Container( - decoration: BoxDecoration( - color: - Theme.of(context).colorScheme.surfaceVariant, - borderRadius: BorderRadius.circular( - cornerRadius, - ), - border: Border.all( - color: dividerColor, - ), - ), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 5, - horizontal: 2.5, - ), - child: Row( - children: _buildYearChips( - state, - snapshot.data!, - state.years, - ), - ), - ), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 5), + Text( + LocaleKeys.filter_by_finish_year.tr(), + style: const TextStyle(fontSize: 16), + ), + const SizedBox(height: 5), + Row( + children: [ + Expanded( + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceVariant, + borderRadius: BorderRadius.circular(cornerRadius), + border: Border.all(color: dividerColor), + ), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 5, + horizontal: 2.5, + ), + child: Row( + children: _buildYearChips( + bookStatus, + snapshot.data!, + years, ), ), ), - ], + ), ), - ], - ); - } else { - return const SizedBox(); - } - }, + ), + ], + ), + ], ); } else if (snapshot.hasData && snapshot.data!.isEmpty) { return const SizedBox(); } else if (snapshot.hasError) { - return Text( - snapshot.error.toString(), - ); + return Text(snapshot.error.toString()); } else { - return const Center( - child: CircularProgressIndicator(), - ); + return const Center(child: CircularProgressIndicator()); } }, ); } - BlocBuilder _buildOnlyFavouriteSwitch() { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - return Row( - children: [ - Expanded( - child: InkWell( - onTap: () { - BlocProvider.of(context).add( - ChangeSortEvent( - sortType: state.sortType, - isAsc: state.isAsc, - onlyFavourite: !state.onlyFavourite, - years: state.years, - tags: state.tags, - displayTags: state.displayTags, - filterTagsAsAnd: state.filterTagsAsAnd, - bookType: state.bookType, - filterOutTags: state.filterOutTags, - ), - ); - }, - child: Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceVariant, - borderRadius: BorderRadius.circular(cornerRadius), - border: Border.all( - color: dividerColor, + Row _buildOnlyFavouriteSwitch(BookStatus bookStatus, bool onlyFavourite) { + return Row( + children: [ + Expanded( + child: InkWell( + onTap: () => _getBlocProvider(bookStatus) + .add(ChangeOnlyFavouriteEvent(!onlyFavourite)), + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceVariant, + borderRadius: BorderRadius.circular(cornerRadius), + border: Border.all(color: dividerColor), + ), + child: Row( + children: [ + SizedBox( + height: 40, + child: Switch.adaptive( + value: onlyFavourite, + onChanged: (value) => _getBlocProvider(bookStatus).add( + ChangeOnlyFavouriteEvent(value), ), ), - child: Row( - children: [ - _getFavouriteSwitch(context, state), - const SizedBox(width: 8), - Text( - LocaleKeys.only_favourite.tr(), - style: const TextStyle(fontSize: 16), - ), - ], - ), ), - ), + const SizedBox(width: 8), + Text( + LocaleKeys.only_favourite.tr(), + style: const TextStyle(fontSize: 16), + ), + ], ), - ], - ); - } else { - return const SizedBox(); - } - }, + ), + ), + ), + ], ); } - BlocBuilder> _buildSortDropdown() { - return BlocBuilder>( - builder: (context, bookStatusList) { - return BlocBuilder( - builder: (context, tabIndex) { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - return Row( - children: [ - Expanded( - child: DropdownButtonHideUnderline( - child: DropdownButton2( - isExpanded: true, - buttonStyleData: ButtonStyleData( - height: 42, - decoration: BoxDecoration( - border: Border.all( - color: dividerColor, - ), - color: - Theme.of(context).colorScheme.surfaceVariant, - borderRadius: BorderRadius.circular(cornerRadius), - ), - ), - items: _getValidSortOptions(bookStatusList[tabIndex]) - .map((item) => DropdownMenuItem( - value: item, - child: Text( - item, - overflow: TextOverflow.ellipsis, - ), - )) - .toList(), - value: _getSortDropdownValue( - bookStatusList[tabIndex], state), - onChanged: (value) => _updateSort( - context, - value, - state, - ), - ), - ), - ), - const SizedBox(width: 5), - Container( - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceVariant, - borderRadius: BorderRadius.circular(cornerRadius), - border: Border.all( - color: dividerColor, - ), - ), - child: _getOrderButton(context, state), - ) - ], - ); - } else { - return const SizedBox(); - } - }, - ); - }, - ); - }); - } - - Widget _buildBookTypeFilter() { - return BlocBuilder( - builder: (context, state) { - if (state is SetSortState) { - return DropdownButtonHideUnderline( - child: DropdownButton2( + Row _buildSortDropdown(BookStatus bookStatus, SortState sortState) { + return Row( + children: [ + Expanded( + child: DropdownButtonHideUnderline( + child: DropdownButton2( isExpanded: true, buttonStyleData: ButtonStyleData( height: 42, decoration: BoxDecoration( - border: Border.all( - color: dividerColor, - ), + border: Border.all(color: dividerColor), color: Theme.of(context).colorScheme.surfaceVariant, borderRadius: BorderRadius.circular(cornerRadius), ), ), - items: bookTypeOptions + items: _getValidSortOptions(bookStatus) .map( - (item) => DropdownMenuItem( + (item) => DropdownMenuItem( value: item, child: Text( - item, + _getSortDropdownText(item), overflow: TextOverflow.ellipsis, ), ), ) .toList(), - value: _getBookTypeDropdownValue(state), - onChanged: (value) => _updateBookType( - context, - value, - state, + value: sortState.sortType, + onChanged: (value) => _getBlocProvider(bookStatus).add( + ChangeSortTypeEvent(value ?? SortType.byTitle), ), ), - ); - } else { - return const SizedBox(); - } - }, + ), + ), + const SizedBox(width: 5), + Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surfaceVariant, + borderRadius: BorderRadius.circular(cornerRadius), + border: Border.all(color: dividerColor), + ), + child: _getOrderButton(bookStatus, sortState), + ) + ], + ); + } + + Widget _buildBookTypeFilter(BookStatus bookStatus, BookFormat? bookFormat) { + return DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + buttonStyleData: ButtonStyleData( + height: 42, + decoration: BoxDecoration( + border: Border.all(color: dividerColor), + color: Theme.of(context).colorScheme.surfaceVariant, + borderRadius: BorderRadius.circular(cornerRadius), + ), + ), + items: [ + DropdownMenuItem( + value: null, + child: Text( + _getBookTypeDropdownText(null), + overflow: TextOverflow.ellipsis, + ), + ), + ...BookFormat.values.map( + (item) => DropdownMenuItem( + value: item, + child: Text( + _getBookTypeDropdownText(item), + overflow: TextOverflow.ellipsis, + ), + ), + ) + ], + value: bookFormat, + onChanged: (value) => + _getBlocProvider(bookStatus).add(ChangeBookTypeEvent(value)), + ), ); } - Widget _buildOnlyBooksWithAllTags(BuildContext context, SetSortState state) { + Widget _buildOnlyBooksWithAllTags( + BookStatus bookStatus, + bool filterTagsAsAnd, + ) { return StreamBuilder>( stream: bookCubit.tags, builder: (context, AsyncSnapshot> snapshot) { @@ -1063,7 +747,11 @@ class _SortBottomSheetState extends State { ), child: Row( children: [ - _getTagsAsAndSwitch(context, state), + Switch.adaptive( + value: filterTagsAsAnd, + onChanged: (value) => _getBlocProvider(bookStatus) + .add(ChangeFilterTagsAsAnd(value)), + ), const SizedBox(width: 10), Expanded( child: Text( @@ -1090,7 +778,7 @@ class _SortBottomSheetState extends State { ); } - Widget _buildBooksExceptTags(BuildContext context, SetSortState state) { + Widget _buildBooksExceptTags(BookStatus bookStatus, bool filterOutTags) { return StreamBuilder>( stream: bookCubit.tags, builder: (context, AsyncSnapshot> snapshot) { @@ -1105,7 +793,12 @@ class _SortBottomSheetState extends State { ), child: Row( children: [ - _getFilterOutTagsSwitch(context, state), + Switch.adaptive( + value: filterOutTags, + onChanged: (value) => _getBlocProvider(bookStatus).add( + ChangeFilterOutTags(value), + ), + ), const SizedBox(width: 10), Expanded( child: Text( @@ -1120,13 +813,9 @@ class _SortBottomSheetState extends State { } else if (snapshot.hasData && snapshot.data!.isEmpty) { return const SizedBox(); } else if (snapshot.hasError) { - return Text( - snapshot.error.toString(), - ); + return Text(snapshot.error.toString()); } else { - return const Center( - child: CircularProgressIndicator(), - ); + return const Center(child: CircularProgressIndicator()); } }, );