From efdbe887eff6ac593ca09f05f40ededeb99ec3ea Mon Sep 17 00:00:00 2001 From: mateusz-bak <32651935+mateusz-bak@users.noreply.github.com> Date: Wed, 13 Mar 2024 23:09:20 +1100 Subject: [PATCH 1/3] feat: Added author suggestion when editing book --- lib/core/helpers/backup/backup_export.dart | 2 +- lib/core/helpers/backup/csv_export.dart | 2 +- lib/logic/cubit/book_cubit.dart | 32 ++++- lib/ui/add_book_screen/add_book_screen.dart | 23 ++-- .../widgets/book_text_field.dart | 125 ++++++++++++------ 5 files changed, 131 insertions(+), 53 deletions(-) diff --git a/lib/core/helpers/backup/backup_export.dart b/lib/core/helpers/backup/backup_export.dart index 3d9c0e47..7f68f41d 100644 --- a/lib/core/helpers/backup/backup_export.dart +++ b/lib/core/helpers/backup/backup_export.dart @@ -72,7 +72,7 @@ class BackupExport { static Future prepareTemporaryBackup(BuildContext context) async { try { - await bookCubit.getAllBooks(tags: true); + await bookCubit.getAllBooks(getTags: false, getAuthors: false); final books = await bookCubit.allBooks.first; final listOfBookJSONs = List.empty(growable: true); diff --git a/lib/core/helpers/backup/csv_export.dart b/lib/core/helpers/backup/csv_export.dart index 4dfbf5ff..5c260be8 100644 --- a/lib/core/helpers/backup/csv_export.dart +++ b/lib/core/helpers/backup/csv_export.dart @@ -76,7 +76,7 @@ class CSVExport { static Future _prepareCSVExport() async { try { - await bookCubit.getAllBooks(tags: true); + await bookCubit.getAllBooks(getAuthors: false, getTags: false); final books = await bookCubit.allBooks.first; final rows = List>.empty(growable: true); diff --git a/lib/logic/cubit/book_cubit.dart b/lib/logic/cubit/book_cubit.dart index aadfc181..12fe8b28 100644 --- a/lib/logic/cubit/book_cubit.dart +++ b/lib/logic/cubit/book_cubit.dart @@ -38,6 +38,8 @@ class BookCubit extends Cubit { BehaviorSubject>(); final BehaviorSubject> _tagsFetcher = BehaviorSubject>(); + final BehaviorSubject> _authorsFetcher = + BehaviorSubject>(); final BehaviorSubject _bookFetcher = BehaviorSubject(); final BehaviorSubject?> _booksWithSameTagFetcher = BehaviorSubject?>(); @@ -53,6 +55,7 @@ class BookCubit extends Cubit { Stream> get searchBooks => _searchBooksFetcher.stream; Stream> get finishedYears => _finishedYearsFetcher.stream; Stream> get tags => _tagsFetcher.stream; + Stream> get authors => _authorsFetcher.stream; Stream?> get booksWithSameTag => _booksWithSameTagFetcher.stream; Stream?> get booksWithSameAuthor => _booksWithSameAuthorFetcher.stream; @@ -74,11 +77,20 @@ class BookCubit extends Cubit { getAllBooks(); } - getAllBooks({bool tags = false}) async { + getAllBooks({ + bool getTags = true, + bool getAuthors = true, + }) async { List books = await repository.getAllNotDeletedBooks(); _booksFetcher.sink.add(books); - if (tags) return; - _tagsFetcher.sink.add(_getTags(books)); + + if (getTags) { + _tagsFetcher.sink.add(_getTags(books)); + } + + if (getAuthors) { + _authorsFetcher.sink.add(_getAuthors(books)); + } } removeAllBooks() async { @@ -237,6 +249,20 @@ class BookCubit extends Cubit { return tags; } + List _getAuthors(List books) { + final authors = List.empty(growable: true); + + for (var book in books) { + if (!authors.contains(book.author)) { + authors.add(book.author); + } + } + + authors.sort((a, b) => a.compareTo(b)); + + return authors; + } + Future _checkIfCoverMigrationDone() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); final bool? check = prefs.getBool('is_cover_migration_done'); diff --git a/lib/ui/add_book_screen/add_book_screen.dart b/lib/ui/add_book_screen/add_book_screen.dart index 9982e0e9..7e3577a6 100644 --- a/lib/ui/add_book_screen/add_book_screen.dart +++ b/lib/ui/add_book_screen/add_book_screen.dart @@ -446,15 +446,20 @@ class _AddBookScreenState extends State { textCapitalization: TextCapitalization.sentences, ), const SizedBox(height: 10), - BookTextField( - controller: _authorCtrl, - hint: LocaleKeys.enter_author.tr(), - icon: Icons.person, - keyboardType: TextInputType.name, - maxLines: 5, - maxLength: 255, - textCapitalization: TextCapitalization.words, - ), + StreamBuilder>( + stream: bookCubit.authors, + builder: (context, AsyncSnapshot?> snapshot) { + return BookTextField( + controller: _authorCtrl, + hint: LocaleKeys.enter_author.tr(), + icon: Icons.person, + keyboardType: TextInputType.name, + maxLines: 5, + maxLength: 255, + textCapitalization: TextCapitalization.words, + suggestions: snapshot.data, + ); + }), const Padding( padding: EdgeInsets.all(10), child: Divider(), diff --git a/lib/ui/add_book_screen/widgets/book_text_field.dart b/lib/ui/add_book_screen/widgets/book_text_field.dart index dc538ba9..12f66579 100644 --- a/lib/ui/add_book_screen/widgets/book_text_field.dart +++ b/lib/ui/add_book_screen/widgets/book_text_field.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; import 'package:openreads/core/themes/app_theme.dart'; @@ -19,6 +20,7 @@ class BookTextField extends StatefulWidget { this.textCapitalization = TextCapitalization.none, this.padding = const EdgeInsets.symmetric(horizontal: 10), this.onSubmitted, + this.suggestions, }); final TextEditingController controller; @@ -34,13 +36,13 @@ class BookTextField extends StatefulWidget { final TextCapitalization textCapitalization; final Function(String)? onSubmitted; final EdgeInsets padding; + final List? suggestions; @override State createState() => _BookTextFieldState(); } class _BookTextFieldState extends State { - final FocusNode focusNode = FocusNode(); bool showClearButton = false; @override @@ -70,46 +72,91 @@ class _BookTextFieldState extends State { border: Border.all(color: dividerColor), ), child: Scrollbar( - child: TextField( - autofocus: widget.autofocus, - keyboardType: widget.keyboardType, - inputFormatters: widget.inputFormatters, - textCapitalization: widget.textCapitalization, - controller: widget.controller, - focusNode: focusNode, - minLines: 1, - maxLines: widget.maxLines, - maxLength: widget.maxLength, - textInputAction: widget.textInputAction, - style: const TextStyle(fontSize: 14), - onSubmitted: widget.onSubmitted ?? (_) {}, - decoration: InputDecoration( - labelText: widget.hint, - labelStyle: const TextStyle(fontSize: 14), - icon: (widget.icon != null) - ? Icon( - widget.icon, - color: Theme.of(context).colorScheme.primary, - ) - : null, - border: InputBorder.none, - counterText: widget.hideCounter ? "" : null, - suffixIcon: showClearButton - ? IconButton( - onPressed: () { - widget.controller.clear(); - setState(() { - showClearButton = false; - }); - focusNode.requestFocus(); - }, - icon: const Icon(Icons.clear), - ) - : null, - ), - ), + child: widget.suggestions != null && widget.suggestions!.isNotEmpty + ? _buildTypeAheadField() + : _buildTextField(context), ), ), ); } + + TypeAheadField _buildTypeAheadField() { + return TypeAheadField( + controller: widget.controller, + hideOnLoading: true, + hideOnEmpty: true, + itemBuilder: (context, suggestion) { + return Container( + color: Theme.of(context).colorScheme.surfaceVariant, + child: ListTile( + title: Text(suggestion), + ), + ); + }, + decorationBuilder: (context, child) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(cornerRadius), + border: Border.all(color: dividerColor), + ), + child: child, + ); + }, + suggestionsCallback: (pattern) { + return widget.suggestions!.where((String option) { + return option.toLowerCase().startsWith(pattern.toLowerCase()); + }).toList(); + }, + onSelected: (suggestion) { + widget.controller.text = suggestion; + }, + builder: (_, __, focusNode) { + return _buildTextField(context, focusNode: focusNode); + }); + } + + TextField _buildTextField( + BuildContext context, { + FocusNode? focusNode, + }) { + return TextField( + autofocus: widget.autofocus, + keyboardType: widget.keyboardType, + inputFormatters: widget.inputFormatters, + textCapitalization: widget.textCapitalization, + controller: widget.controller, + focusNode: focusNode, + minLines: 1, + maxLines: widget.maxLines, + maxLength: widget.maxLength, + textInputAction: widget.textInputAction, + style: const TextStyle(fontSize: 14), + onSubmitted: widget.onSubmitted ?? (_) {}, + decoration: InputDecoration( + labelText: widget.hint, + labelStyle: const TextStyle(fontSize: 14), + icon: (widget.icon != null) + ? Icon( + widget.icon, + color: Theme.of(context).colorScheme.primary, + ) + : null, + border: InputBorder.none, + counterText: widget.hideCounter ? "" : null, + suffixIcon: showClearButton + ? IconButton( + onPressed: () { + widget.controller.clear(); + setState(() { + showClearButton = false; + }); + focusNode?.requestFocus(); + }, + icon: const Icon(Icons.clear), + ) + : null, + ), + ); + } } From 2a554e326ca5ef50b5fe62f4a1aec732e24f0e1a Mon Sep 17 00:00:00 2001 From: mateusz-bak <32651935+mateusz-bak@users.noreply.github.com> Date: Wed, 13 Mar 2024 23:09:44 +1100 Subject: [PATCH 2/3] build: Dependency upgrades --- ios/Podfile.lock | 2 +- pubspec.lock | 44 ++++++++++++++++++++++---------------------- pubspec.yaml | 4 ++-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 7d2b1476..cca91d67 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -177,7 +177,7 @@ SPEC CHECKSUMS: SwiftProtobuf: bcfd2bc231cf9ae552cdc7c4e877bd3b41fe57b1 SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863 - url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812 + url_launcher_ios: 6116280ddcfe98ab8820085d8d76ae7449447586 PODFILE CHECKSUM: 819463e6a0290f5a72f145ba7cde16e8b6ef0796 diff --git a/pubspec.lock b/pubspec.lock index c755b435..15664dfd 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -197,10 +197,10 @@ packages: dependency: "direct main" description: name: csv - sha256: "63ed2871dd6471193dffc52c0e6c76fb86269c00244d244297abbb355c84a86e" + sha256: c6aa2679b2a18cb57652920f674488d89712efaf4d3fdf2e537215b35fc19d6c url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "6.0.0" cupertino_icons: dependency: "direct main" description: @@ -253,18 +253,18 @@ packages: dependency: "direct main" description: name: dynamic_color - sha256: a866f1f8947bfdaf674d7928e769eac7230388a2e7a2542824fad4bb5b87be3b + sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d url: "https://pub.dev" source: hosted - version: "1.6.9" + version: "1.7.0" easy_localization: dependency: "direct main" description: name: easy_localization - sha256: "9c86754b22aaa3e74e471635b25b33729f958dd6fb83df0ad6612948a7b231af" + sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" easy_logger: dependency: transitive description: @@ -373,10 +373,10 @@ packages: dependency: "direct main" description: name: flex_color_picker - sha256: "0871edc170153cfc3de316d30625f40a85daecfa76ce541641f3cc0ec7757cbf" + sha256: "904373c7b0531fd4a92d29705a80ab4594b7647da2d93044487aaec4614cb6ed" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.4.0" flex_seed_scheme: dependency: transitive description: @@ -673,10 +673,10 @@ packages: dependency: transitive description: name: image_picker_platform_interface - sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b + sha256: "3d2c323daea9d60608f1caf30be32a938916f4975434b8352e6f73dae496da38" url: "https://pub.dev" source: hosted - version: "2.9.3" + version: "2.9.4" image_picker_windows: dependency: transitive description: @@ -753,10 +753,10 @@ packages: dependency: "direct main" description: name: loading_animation_widget - sha256: "1901682600273a966c34cf44a85fc5355da92a8d08a8a43c11adc4e471993e3a" + sha256: ee3659035528d19145d50cf0107632bf647e7306c88b6a32f35f3bed63f6d728 url: "https://pub.dev" source: hosted - version: "1.2.0+4" + version: "1.2.1" matcher: dependency: transitive description: @@ -1017,10 +1017,10 @@ packages: dependency: transitive description: name: provider - sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" rxdart: dependency: "direct main" description: @@ -1230,10 +1230,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c + sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_android: dependency: transitive description: @@ -1246,10 +1246,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_linux: dependency: transitive description: @@ -1326,10 +1326,10 @@ packages: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.3.0" win32_registry: dependency: transitive description: @@ -1363,5 +1363,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.0-279.1.beta <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml index 8cee900e..4b78818c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,7 +28,7 @@ dependencies: dropdown_button2: ^2.0.0 equatable: ^2.0.5 connectivity_plus: ^5.0.1 - http: ^1.0.0 + http: ^1.2.0 cached_network_image: ^3.3.0 loading_animation_widget: ^1.2.0+3 infinite_scroll_pagination: ^4.0.0 @@ -56,7 +56,7 @@ dependencies: diacritic: ^0.1.4 flutter_speed_dial: ^7.0.0 blurhash_dart: ^1.2.1 - csv: ^5.0.2 + csv: ^6.0.0 file_picker: 5.3.2 smooth_page_indicator: ^1.1.0 intl: ^0.18.1 From 64ae209342149c90f2de1a57b1da2c2f3809f0b9 Mon Sep 17 00:00:00 2001 From: mateusz-bak <32651935+mateusz-bak@users.noreply.github.com> Date: Wed, 13 Mar 2024 23:10:04 +1100 Subject: [PATCH 3/3] build: Upgraded Flutter to 3.19.3 --- submodules/flutter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/flutter b/submodules/flutter index 74829621..ba393198 160000 --- a/submodules/flutter +++ b/submodules/flutter @@ -1 +1 @@ -Subproject commit 7482962148e8d758338d8a28f589f317e1e42ba4 +Subproject commit ba393198430278b6595976de84fe170f553cc728