From c612dc1732b4c20393c0f4db4137a4fb35845c41 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Sat, 14 Mar 2026 11:02:15 -0300 Subject: [PATCH 01/19] refactor: replace BookException with RestClientException for error handling - Removed BookException and BookNotFoundException classes. - Introduced RestClientException to handle various error scenarios. - Updated GoogleBooksDataSourceImpl, RemoteBooksRepositoryImpl, and DioRestClientImpl to throw RestClientException. - Modified BookBloc to emit BookErrorState with error codes and messages. - Updated tests to reflect changes in error handling and exception types. - Added RestClientErrorCode enum and its extension for localized error messages. --- assets/lang/en_US.json | 8 +- assets/lang/it_IT.json | 8 +- assets/lang/pt_BR.json | 8 +- coverage/lcov.info | 521 ++++++++++-------- .../google_books_data_source_impl.dart | 16 +- .../core/enums/rest_client_error_code.dart | 8 + .../errors/book_exception/book_exception.dart | 19 - .../rest_client_exception.dart | 14 + .../rest_client_error_code_extension.dart | 32 ++ .../remote_books_repository_impl.dart | 95 +--- .../rest_client/dio_rest_client_impl.dart | 38 +- lib/src/features/home/views/home_page.dart | 33 +- lib/src/shared/blocs/book_bloc/book_bloc.dart | 132 +++-- .../shared/blocs/book_bloc/book_state.dart | 10 +- pubspec.yaml | 2 +- .../remote_book_data_source_impl_test.dart | 121 +++- .../remote_books_repository_test.dart | 70 +-- .../features/home/views/home_page_test.dart | 8 +- .../blocs/book_bloc/book_bloc_test.dart | 175 +++--- 19 files changed, 774 insertions(+), 544 deletions(-) create mode 100644 lib/src/core/enums/rest_client_error_code.dart delete mode 100644 lib/src/core/errors/book_exception/book_exception.dart create mode 100644 lib/src/core/errors/rest_client_exception/rest_client_exception.dart create mode 100644 lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index 66dc4bd2..eed3b55d 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -243,5 +243,11 @@ "book-on-loan-label": "on loan", "book-on-reading-label": "on reading", "previous-month-tooltip": "Previous month", - "next-month-tooltip": "Next month" + "next-month-tooltip": "Next month", + "error-rest-client-connection-timeout": "Connection timeout: %s", + "error-rest-client-receive-timeout": "Receive timeout: %s", + "error-rest-client-not-found": "Not found: %s", + "error-rest-client-socket-exception": "Network error: %s", + "error-invalid-isbn": "Invalid ISBN: %s", + "error-unknown": "Unexpected error: %s" } diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index d62248fa..180cdd4a 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -243,5 +243,11 @@ "book-on-loan-label": "in prestito", "book-on-reading-label": "in lettura", "previous-month-tooltip": "Mese precedente", - "next-month-tooltip": "Mese successivo" + "next-month-tooltip": "Mese successivo", + "error-rest-client-connection-timeout": "Timeout connessione: %s", + "error-rest-client-receive-timeout": "Timeout risposta: %s", + "error-rest-client-not-found": "Risorsa non trovata: %s", + "error-rest-client-socket-exception": "Errore di rete: %s", + "error-invalid-isbn": "ISBN non valido: %s", + "error-unknown": "Errore imprevisto: %s" } diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index 050736e1..95d22263 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -243,5 +243,11 @@ "book-on-loan-label": "em leitura", "book-on-reading-label": "em empréstimo", "previous-month-tooltip": "Mês anterior", - "next-month-tooltip": "Próximo mês" + "next-month-tooltip": "Próximo mês", + "error-rest-client-connection-timeout": "Tempo esgotado: %s", + "error-rest-client-receive-timeout": "O servidor não respondeu: %s", + "error-rest-client-not-found": "Não encontrado: %s", + "error-rest-client-socket-exception": "Erro de conexão: %s", + "error-invalid-isbn": "ISBN inválido: %s", + "error-unknown": "Erro inesperado: %s" } diff --git a/coverage/lcov.info b/coverage/lcov.info index fd4292e4..b720a999 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -846,50 +846,57 @@ DA:44,1 LF:13 LH:11 end_of_record -SF:lib/src/core/errors/book_exception/book_exception.dart -DA:4,1 -DA:6,1 -DA:8,2 -DA:13,1 -DA:15,0 -DA:17,0 -LF:6 -LH:4 -end_of_record SF:lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart -DA:13,1 +DA:8,1 +DA:10,1 +DA:12,2 DA:15,1 -DA:18,2 +DA:17,2 +DA:20,1 +DA:22,2 +DA:25,1 +DA:27,2 +DA:30,1 +DA:32,2 +DA:35,1 +DA:37,2 +LF:13 +LH:13 +end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 DA:22,0 +DA:23,0 DA:24,0 -DA:26,0 -DA:31,1 -DA:34,2 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 DA:38,0 +DA:39,0 DA:40,0 -DA:42,0 -DA:47,1 -DA:51,2 -DA:55,0 -DA:57,0 -DA:59,0 -DA:64,1 -DA:68,2 -DA:72,0 -DA:74,0 -DA:76,0 -DA:81,1 -DA:84,2 -DA:88,0 -DA:90,0 -DA:92,0 -DA:97,1 -DA:100,2 -DA:102,1 -DA:104,1 -DA:106,1 -LF:31 -LH:16 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 +LH:0 end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart DA:21,1 @@ -1271,32 +1278,38 @@ LF:23 LH:23 end_of_record SF:lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart -DA:13,1 +DA:12,1 +DA:17,1 DA:18,1 -DA:19,1 -DA:21,1 -DA:23,2 -DA:25,1 -DA:27,2 -DA:29,1 -DA:31,2 -DA:33,1 -DA:35,2 -DA:37,1 -DA:39,2 -DA:41,1 -DA:43,2 -DA:45,1 -DA:52,1 -DA:55,1 +DA:20,1 +DA:22,2 +DA:24,1 +DA:26,2 +DA:28,1 +DA:30,2 +DA:32,1 +DA:34,2 +DA:36,1 +DA:38,2 +DA:40,1 +DA:42,2 +DA:44,1 +DA:51,1 +DA:54,1 +DA:57,1 DA:58,1 DA:59,1 -DA:60,1 DA:62,1 DA:64,1 -DA:67,2 -LF:24 -LH:24 +LF:23 +LH:23 +end_of_record +SF:lib/src/core/errors/rest_client_exception/rest_client_exception.dart +DA:7,2 +DA:12,0 +DA:13,0 +LF:3 +LH:1 end_of_record SF:lib/src/core/adapters/google_books_adapter.dart DA:12,1 @@ -1337,7 +1350,7 @@ LH:5 end_of_record SF:lib/src/shared/blocs/book_bloc/book_state.dart DA:12,2 -DA:20,2 +DA:21,2 LF:2 LH:2 end_of_record @@ -1356,65 +1369,92 @@ DA:33,1 DA:34,2 DA:38,2 DA:39,1 -DA:40,0 +DA:40,1 DA:41,1 -DA:42,3 -DA:46,1 -DA:51,2 -DA:53,3 -DA:55,1 -DA:56,2 -DA:59,2 -DA:60,1 -DA:61,0 -DA:62,1 +DA:42,1 +DA:43,1 +DA:47,0 +DA:48,0 +DA:50,0 +DA:56,1 +DA:61,2 DA:63,3 -DA:67,1 -DA:72,2 -DA:75,3 -DA:77,1 -DA:78,2 -DA:82,2 -DA:83,1 -DA:84,0 -DA:85,1 -DA:86,3 -DA:90,1 -DA:95,2 -DA:98,3 -DA:100,1 -DA:101,2 -DA:105,2 +DA:65,1 +DA:66,2 +DA:69,2 +DA:70,1 +DA:71,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:78,0 +DA:79,0 +DA:81,0 +DA:87,1 +DA:92,2 +DA:94,2 +DA:95,1 +DA:98,1 +DA:99,2 +DA:103,2 +DA:104,1 +DA:105,1 DA:106,1 -DA:107,0 +DA:107,1 DA:108,1 -DA:109,3 -DA:113,1 -DA:118,2 -DA:120,2 +DA:112,0 +DA:113,0 +DA:115,0 DA:121,1 -DA:123,1 -DA:124,2 +DA:126,2 DA:128,2 DA:129,1 -DA:130,0 -DA:131,1 -DA:132,3 -DA:136,1 -DA:141,2 -DA:143,1 -DA:144,2 -DA:146,2 -DA:150,2 -DA:152,1 -DA:153,2 -DA:157,2 -DA:158,0 -DA:159,0 -DA:160,0 -DA:161,0 -LF:71 -LH:62 +DA:132,1 +DA:133,2 +DA:137,2 +DA:138,1 +DA:139,1 +DA:140,1 +DA:141,1 +DA:142,1 +DA:146,0 +DA:147,0 +DA:149,0 +DA:155,1 +DA:160,2 +DA:162,2 +DA:163,1 +DA:166,1 +DA:167,2 +DA:171,2 +DA:172,1 +DA:173,1 +DA:174,1 +DA:175,1 +DA:176,1 +DA:180,0 +DA:181,0 +DA:183,0 +DA:189,1 +DA:194,2 +DA:196,1 +DA:197,2 +DA:199,1 +DA:200,1 +DA:208,2 +DA:210,1 +DA:211,2 +DA:215,2 +DA:216,0 +DA:217,0 +DA:218,0 +DA:219,0 +DA:220,0 +DA:224,0 +DA:225,0 +DA:227,0 +LF:98 +LH:75 end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart DA:11,1 @@ -3440,88 +3480,6 @@ DA:47,0 LF:16 LH:1 end_of_record -SF:lib/src/features/loan/bloc/loan_bloc.dart -DA:17,1 -DA:21,2 -DA:22,2 -DA:23,2 -DA:26,1 -DA:31,2 -DA:33,2 -DA:35,1 -DA:36,2 -DA:40,1 -DA:41,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:48,1 -DA:53,2 -DA:55,2 -DA:56,1 -DA:59,1 -DA:60,2 -DA:64,1 -DA:65,1 -DA:66,4 -DA:67,1 -DA:68,3 -DA:72,1 -DA:76,1 -DA:78,2 -DA:79,1 -DA:80,1 -DA:81,3 -DA:86,2 -DA:87,1 -DA:90,2 -DA:91,1 -DA:94,1 -DA:96,1 -DA:97,1 -DA:101,1 -DA:104,2 -LF:40 -LH:36 -end_of_record -SF:lib/src/features/loan/bloc/loan_state.dart -DA:14,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/loan/bloc/loan_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/core/dtos/loan_dto.dart -DA:10,2 -DA:17,0 -DA:19,0 -DA:25,0 -DA:26,0 -DA:27,0 -DA:28,0 -DA:29,0 -DA:33,0 -DA:35,0 -DA:38,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:48,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:56,0 -DA:57,0 -DA:63,0 -LF:23 -LH:1 -end_of_record SF:lib/src/features/loan_detail/bloc/loan_detail_state.dart DA:10,1 DA:20,1 @@ -3616,10 +3574,92 @@ DA:96,0 LF:37 LH:1 end_of_record +SF:lib/src/core/dtos/loan_dto.dart +DA:10,2 +DA:17,0 +DA:19,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:33,0 +DA:35,0 +DA:38,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:56,0 +DA:57,0 +DA:63,0 +LF:23 +LH:1 +end_of_record SF:lib/src/features/contacts_picker/bloc/contacts_picker_event.dart LF:0 LH:0 end_of_record +SF:lib/src/features/loan/bloc/loan_bloc.dart +DA:17,1 +DA:21,2 +DA:22,2 +DA:23,2 +DA:26,1 +DA:31,2 +DA:33,2 +DA:35,1 +DA:36,2 +DA:40,1 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:48,1 +DA:53,2 +DA:55,2 +DA:56,1 +DA:59,1 +DA:60,2 +DA:64,1 +DA:65,1 +DA:66,4 +DA:67,1 +DA:68,3 +DA:72,1 +DA:76,1 +DA:78,2 +DA:79,1 +DA:80,1 +DA:81,3 +DA:86,2 +DA:87,1 +DA:90,2 +DA:91,1 +DA:94,1 +DA:96,1 +DA:97,1 +DA:101,1 +DA:104,2 +LF:40 +LH:36 +end_of_record +SF:lib/src/features/loan/bloc/loan_state.dart +DA:14,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/loan/bloc/loan_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:19,1 DA:23,2 @@ -3711,65 +3751,80 @@ LF:1 LH:1 end_of_record SF:lib/src/features/home/views/home_page.dart -DA:10,1 -DA:12,1 +DA:11,1 DA:13,1 -DA:21,1 -DA:23,1 -DA:24,2 -DA:25,1 -DA:26,3 -DA:28,3 +DA:14,1 +DA:22,1 +DA:24,1 +DA:25,2 +DA:26,1 +DA:27,3 DA:29,3 -DA:33,1 -DA:35,2 -DA:36,1 -DA:39,0 +DA:30,3 +DA:34,1 +DA:36,2 +DA:37,1 DA:40,0 DA:41,0 -DA:44,1 -DA:46,1 -DA:49,2 -DA:51,1 +DA:42,0 +DA:45,1 +DA:47,1 +DA:50,2 DA:52,1 DA:53,1 -DA:56,3 -DA:60,3 -DA:62,1 +DA:54,1 +DA:57,3 +DA:61,4 +DA:63,1 DA:64,1 -DA:70,0 +DA:65,1 DA:71,0 -DA:73,0 +DA:72,0 DA:74,0 -DA:76,0 +DA:75,0 DA:77,0 -DA:79,0 +DA:78,0 DA:80,0 -DA:82,0 +DA:81,0 DA:83,0 -DA:85,0 +DA:84,0 DA:86,0 -DA:92,1 -DA:94,1 -DA:96,1 -DA:97,0 -DA:98,3 -DA:99,1 +DA:87,0 +DA:93,1 +DA:95,1 +DA:97,1 +DA:98,0 +DA:99,3 DA:100,1 DA:101,1 DA:102,1 -DA:104,1 -DA:110,1 -DA:112,1 +DA:103,1 +DA:105,1 +DA:111,1 DA:113,1 -DA:117,1 +DA:114,1 DA:118,1 DA:119,1 -DA:120,0 +DA:120,1 DA:121,0 -DA:123,1 -LF:57 -LH:39 +DA:122,0 +DA:124,1 +LF:58 +LH:40 +end_of_record +SF:lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart +DA:5,1 +DA:9,1 +DA:10,0 +DA:13,1 +DA:14,0 +DA:17,1 +DA:20,1 +DA:21,0 +DA:24,1 +DA:27,3 +LF:10 +LH:7 end_of_record SF:lib/src/features/home/widgets/animated_search_bar/animated_search_bar.dart DA:17,1 diff --git a/lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart b/lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart index c5639bd3..4213aafe 100644 --- a/lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart +++ b/lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart @@ -1,8 +1,7 @@ -import 'dart:io'; - import 'package:bookify/src/core/adapters/google_books_adapter.dart'; import 'package:bookify/src/core/data_sources/remote_books_data_source/remote_books_data_source.dart'; -import 'package:bookify/src/core/errors/book_exception/book_exception.dart'; +import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/rest_client/rest_client.dart'; @@ -57,14 +56,13 @@ class GoogleBooksDataSourceImpl implements RemoteBooksDataSource { return books; } on TypeError { return []; - } on BookNotFoundException { - rethrow; - } on BookException { - rethrow; - } on SocketException { + } on RestClientException { rethrow; } catch (e) { - throw Exception(e.toString()); + throw RestClientException( + RestClientErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/enums/rest_client_error_code.dart b/lib/src/core/enums/rest_client_error_code.dart new file mode 100644 index 00000000..4cd4a0b0 --- /dev/null +++ b/lib/src/core/enums/rest_client_error_code.dart @@ -0,0 +1,8 @@ +enum RestClientErrorCode { + connectionTimeout, + receiveTimeout, + notFound, + invalidInput, + socketException, + unknown, +} diff --git a/lib/src/core/errors/book_exception/book_exception.dart b/lib/src/core/errors/book_exception/book_exception.dart deleted file mode 100644 index d03c5e6e..00000000 --- a/lib/src/core/errors/book_exception/book_exception.dart +++ /dev/null @@ -1,19 +0,0 @@ -class BookException implements Exception { - final String message; - - const BookException(this.message); - - @override - String toString() { - return 'Book Exception: $message'; - } -} - -class BookNotFoundException extends BookException { - const BookNotFoundException(super.message); - - @override - String toString() { - return 'BookNotFoundException: $message'; - } -} diff --git a/lib/src/core/errors/rest_client_exception/rest_client_exception.dart b/lib/src/core/errors/rest_client_exception/rest_client_exception.dart new file mode 100644 index 00000000..894caf32 --- /dev/null +++ b/lib/src/core/errors/rest_client_exception/rest_client_exception.dart @@ -0,0 +1,14 @@ +import 'package:bookify/src/core/enums/rest_client_error_code.dart'; + +class RestClientException implements Exception { + final RestClientErrorCode code; + final String? descriptionMessage; + + const RestClientException( + this.code, { + this.descriptionMessage, + }); + + @override + String toString() => 'RestClientException: [$code] $descriptionMessage'; +} diff --git a/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart b/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart new file mode 100644 index 00000000..60892cb7 --- /dev/null +++ b/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart @@ -0,0 +1,32 @@ +import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:localization/localization.dart'; + +extension RestClientErrorCodeExtension on RestClientErrorCode { + String toLocalizedMessage(String? description) { + final messageArg = description ?? '---'; + + return switch (this) { + RestClientErrorCode.connectionTimeout => + 'error-rest-client-connection-timeout'.i18n([ + messageArg, + ]), + RestClientErrorCode.receiveTimeout => + 'error-rest-client-receive-timeout'.i18n([ + messageArg, + ]), + RestClientErrorCode.notFound => 'error-rest-client-not-found'.i18n([ + messageArg, + ]), + RestClientErrorCode.socketException => + 'error-rest-client-socket-exception'.i18n([ + messageArg, + ]), + RestClientErrorCode.invalidInput => 'error-invalid-isbn'.i18n([ + messageArg, + ]), + RestClientErrorCode.unknown => 'error-unknown'.i18n([ + messageArg, + ]), + }; + } +} diff --git a/lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart b/lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart index d01e8cdd..c2cd457d 100644 --- a/lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart +++ b/lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart @@ -1,10 +1,5 @@ -import 'dart:io'; - import 'package:bookify/src/core/data_sources/remote_books_data_source/remote_books_data_source.dart'; -import 'package:bookify/src/core/errors/book_exception/book_exception.dart'; - import 'package:bookify/src/core/models/book_model.dart'; - import 'remote_books_repository.dart'; class RemoteBooksRepositoryImpl implements RemoteBooksRepository { @@ -13,98 +8,32 @@ class RemoteBooksRepositoryImpl implements RemoteBooksRepository { RemoteBooksRepositoryImpl(this._booksDataSource); @override - Future> findBooksByAuthor({required String author}) async { - try { - final books = await _booksDataSource.findBooksByAuthor( - author: author, - ); - return books; - } on BookNotFoundException { - rethrow; - } on BookException { - rethrow; - } on SocketException { - rethrow; - } + Future> findBooksByAuthor({required String author}) { + return _booksDataSource.findBooksByAuthor(author: author); } @override - Future> findBooksByIsbn({required String isbn}) async { - try { - final books = await _booksDataSource.findBooksByIsbn( - isbn: isbn, - ); - return books; - } on BookNotFoundException { - rethrow; - } on BookException { - rethrow; - } on SocketException { - rethrow; - } + Future> findBooksByIsbn({required String isbn}) { + return _booksDataSource.findBooksByIsbn(isbn: isbn); } @override - Future> findBooksByPublisher( - {required String publisher}) async { - try { - final books = await _booksDataSource.findBooksByPublisher( - publisher: publisher, - ); - return books; - } on BookNotFoundException { - rethrow; - } on BookException { - rethrow; - } on SocketException { - rethrow; - } + Future> findBooksByPublisher({required String publisher}) { + return _booksDataSource.findBooksByPublisher(publisher: publisher); } @override - Future> findBooksByCategory( - {required String category}) async { - try { - final books = await _booksDataSource.findBooksByCategory( - category: category, - ); - return books; - } on BookNotFoundException { - rethrow; - } on BookException { - rethrow; - } on SocketException { - rethrow; - } + Future> findBooksByCategory({required String category}) { + return _booksDataSource.findBooksByCategory(category: category); } @override - Future> findBooksByTitle({required String title}) async { - try { - final books = await _booksDataSource.findBooksByTitle( - title: title, - ); - return books; - } on BookNotFoundException { - rethrow; - } on BookException { - rethrow; - } on SocketException { - rethrow; - } + Future> findBooksByTitle({required String title}) { + return _booksDataSource.findBooksByTitle(title: title); } @override - Future> getAllBooks() async { - try { - final books = await _booksDataSource.getAllBooks(); - return books; - } on BookNotFoundException { - rethrow; - } on BookException { - rethrow; - } on SocketException { - rethrow; - } + Future> getAllBooks() { + return _booksDataSource.getAllBooks(); } } diff --git a/lib/src/core/rest_client/dio_rest_client_impl.dart b/lib/src/core/rest_client/dio_rest_client_impl.dart index d47ee4f1..c753cc1c 100644 --- a/lib/src/core/rest_client/dio_rest_client_impl.dart +++ b/lib/src/core/rest_client/dio_rest_client_impl.dart @@ -1,9 +1,8 @@ import 'dart:io'; - +import 'package:bookify/src/core/enums/rest_client_error_code.dart'; import 'package:dio/dio.dart'; import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; - -import 'package:bookify/src/core/errors/book_exception/book_exception.dart'; +import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; import 'rest_client.dart'; class DioRestClientImpl implements RestClient { @@ -37,19 +36,36 @@ class DioRestClientImpl implements RestClient { return response.data; } on DioException catch (e) { if (e.response?.statusCode == 404) { - throw BookNotFoundException( - e.response?.statusMessage ?? 'Book not found', + throw RestClientException( + RestClientErrorCode.notFound, + descriptionMessage: e.response?.statusMessage ?? 'Item not found', + ); + } else if (e.type == DioExceptionType.connectionTimeout) { + throw RestClientException( + RestClientErrorCode.connectionTimeout, + descriptionMessage: 'Connection timed out', ); - } else if (e.type == DioExceptionType.connectionTimeout || - e.type == DioExceptionType.receiveTimeout) { - throw BookException( - e.response?.statusMessage ?? 'An error occurred', + } else if (e.type == DioExceptionType.receiveTimeout) { + throw RestClientException( + RestClientErrorCode.receiveTimeout, + descriptionMessage: 'Receive timed out', + ); + } else if (e.error is SocketException) { + throw RestClientException( + RestClientErrorCode.socketException, + descriptionMessage: 'No internet connection', ); } else { - throw SocketException(e.message ?? e.toString()); + throw RestClientException( + RestClientErrorCode.unknown, + descriptionMessage: e.message, + ); } } catch (e) { - throw Exception(e.toString()); + throw RestClientException( + RestClientErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/features/home/views/home_page.dart b/lib/src/features/home/views/home_page.dart index 9b73985a..75c22d6c 100644 --- a/lib/src/features/home/views/home_page.dart +++ b/lib/src/features/home/views/home_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart'; import 'package:bookify/src/shared/blocs/book_bloc/book_bloc.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; import 'package:bookify/src/shared/widgets/item_state_widget/info_item_state_widget/info_item_state_widget.dart'; @@ -44,26 +45,26 @@ class _HomePageState extends State { Widget _getBookStateWidget(BuildContext context, BookState state) { return switch (state) { BooksLoadingState() => const CenterCircularProgressIndicator( - key: Key('BooksLoadingStateWidget'), - ), + key: Key('BooksLoadingStateWidget'), + ), BookEmptyState() => Center( - key: const Key('BookEmptyStateWidget'), - child: InfoItemStateWidget.withNotFoundState( - message: 'no-books-found-with-terms'.i18n(), - onPressed: _refreshPage, - ), + key: const Key('BookEmptyStateWidget'), + child: InfoItemStateWidget.withNotFoundState( + message: 'no-books-found-with-terms'.i18n(), + onPressed: _refreshPage, ), + ), BooksLoadedState(:final books) => BooksLoadedStateWidget( - key: const Key('BooksLoadedStateWidget'), - books: books, - ), - BookErrorSate(errorMessage: final message) => Center( - key: const Key('BookErrorSateWidget'), - child: InfoItemStateWidget.withErrorState( - message: message, - onPressed: _refreshPage, - ), + key: const Key('BooksLoadedStateWidget'), + books: books, + ), + BookErrorState(:final errorCode, :final errorMessage) => Center( + key: const Key('BookErrorSateWidget'), + child: InfoItemStateWidget.withErrorState( + message: errorCode.toLocalizedMessage(errorMessage), + onPressed: _refreshPage, ), + ), }; } diff --git a/lib/src/shared/blocs/book_bloc/book_bloc.dart b/lib/src/shared/blocs/book_bloc/book_bloc.dart index d998af52..bd901c3b 100644 --- a/lib/src/shared/blocs/book_bloc/book_bloc.dart +++ b/lib/src/shared/blocs/book_bloc/book_bloc.dart @@ -1,5 +1,5 @@ -import 'dart:io'; - +import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; import 'package:bookify/src/core/repositories/remote_books_repository/remote_books_repository.dart'; import 'package:bookify/src/core/utils/verifier/isbn_verifier.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -36,10 +36,20 @@ class BookBloc extends Bloc { } emit(BooksLoadedState(books: books)); - } on SocketException catch (socketException) { - emit(BookErrorSate(errorMessage: socketException.message)); - } on Exception catch (e) { - emit(BookErrorSate(errorMessage: e.toString())); + } on RestClientException catch (e) { + emit( + BookErrorState( + errorCode: e.code, + errorMessage: e.descriptionMessage, + ), + ); + } catch (e) { + emit( + BookErrorState( + errorCode: RestClientErrorCode.unknown, + errorMessage: e.toString(), + ), + ); } } @@ -57,10 +67,20 @@ class BookBloc extends Bloc { return; } emit(BooksLoadedState(books: books)); - } on SocketException catch (socketException) { - emit(BookErrorSate(errorMessage: socketException.message)); - } on Exception catch (e) { - emit(BookErrorSate(errorMessage: e.toString())); + } on RestClientException catch (e) { + emit( + BookErrorState( + errorCode: e.code, + errorMessage: e.descriptionMessage, + ), + ); + } catch (e) { + emit( + BookErrorState( + errorCode: RestClientErrorCode.unknown, + errorMessage: e.toString(), + ), + ); } } @@ -71,8 +91,9 @@ class BookBloc extends Bloc { try { emit(BooksLoadingState()); - final books = - await _booksRepository.findBooksByAuthor(author: event.author); + final books = await _booksRepository.findBooksByAuthor( + author: event.author, + ); if (books.isEmpty) { emit(BookEmptyState()); @@ -80,10 +101,20 @@ class BookBloc extends Bloc { } emit(BooksLoadedState(books: books)); - } on SocketException catch (socketException) { - emit(BookErrorSate(errorMessage: socketException.message)); - } on Exception catch (e) { - emit(BookErrorSate(errorMessage: e.toString())); + } on RestClientException catch (e) { + emit( + BookErrorState( + errorCode: e.code, + errorMessage: e.descriptionMessage, + ), + ); + } catch (e) { + emit( + BookErrorState( + errorCode: RestClientErrorCode.unknown, + errorMessage: e.toString(), + ), + ); } } @@ -94,8 +125,9 @@ class BookBloc extends Bloc { try { emit(BooksLoadingState()); - final books = - await _booksRepository.findBooksByCategory(category: event.category); + final books = await _booksRepository.findBooksByCategory( + category: event.category, + ); if (books.isEmpty) { emit(BookEmptyState()); @@ -103,10 +135,20 @@ class BookBloc extends Bloc { } emit(BooksLoadedState(books: books)); - } on SocketException catch (socketException) { - emit(BookErrorSate(errorMessage: socketException.message)); - } on Exception catch (e) { - emit(BookErrorSate(errorMessage: e.toString())); + } on RestClientException catch (e) { + emit( + BookErrorState( + errorCode: e.code, + errorMessage: e.descriptionMessage, + ), + ); + } catch (e) { + emit( + BookErrorState( + errorCode: RestClientErrorCode.unknown, + errorMessage: e.toString(), + ), + ); } } @@ -118,7 +160,8 @@ class BookBloc extends Bloc { emit(BooksLoadingState()); final books = await _booksRepository.findBooksByPublisher( - publisher: event.publisher); + publisher: event.publisher, + ); if (books.isEmpty) { emit(BookEmptyState()); @@ -126,10 +169,20 @@ class BookBloc extends Bloc { } emit(BooksLoadedState(books: books)); - } on SocketException catch (socketException) { - emit(BookErrorSate(errorMessage: socketException.message)); - } on Exception catch (e) { - emit(BookErrorSate(errorMessage: e.toString())); + } on RestClientException catch (e) { + emit( + BookErrorState( + errorCode: e.code, + errorMessage: e.descriptionMessage, + ), + ); + } catch (e) { + emit( + BookErrorState( + errorCode: RestClientErrorCode.unknown, + errorMessage: e.toString(), + ), + ); } } @@ -143,7 +196,12 @@ class BookBloc extends Bloc { final verifier = IsbnVerifier(); String? isbn = verifier.verifyIsbn(event.isbn); if (isbn == null) { - emit(BookErrorSate(errorMessage: 'Digite um ISBN Válido')); + emit( + BookErrorState( + errorCode: RestClientErrorCode.invalidInput, + errorMessage: 'Invalid ISBN provided', + ), + ); return; } @@ -155,10 +213,20 @@ class BookBloc extends Bloc { } emit(BooksLoadedState(books: books)); - } on SocketException catch (socketException) { - emit(BookErrorSate(errorMessage: socketException.message)); - } on Exception catch (e) { - emit(BookErrorSate(errorMessage: e.toString())); + } on RestClientException catch (e) { + emit( + BookErrorState( + errorCode: e.code, + errorMessage: e.descriptionMessage, + ), + ); + } catch (e) { + emit( + BookErrorState( + errorCode: RestClientErrorCode.unknown, + errorMessage: e.toString(), + ), + ); } } } diff --git a/lib/src/shared/blocs/book_bloc/book_state.dart b/lib/src/shared/blocs/book_bloc/book_state.dart index a2aa32ce..69d76f25 100644 --- a/lib/src/shared/blocs/book_bloc/book_state.dart +++ b/lib/src/shared/blocs/book_bloc/book_state.dart @@ -14,10 +14,12 @@ final class BooksLoadedState extends BookState { }); } -final class BookErrorSate extends BookState { - final String errorMessage; +final class BookErrorState extends BookState { + final RestClientErrorCode errorCode; + final String? errorMessage; - BookErrorSate({ - required this.errorMessage, + BookErrorState({ + required this.errorCode, + this.errorMessage, }); } diff --git a/pubspec.yaml b/pubspec.yaml index f528998a..fd8047a9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.10.9 +version: 2.11.0 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/core/data_sources/remote_book_data_source/remote_book_data_source_impl_test.dart b/test/src/core/data_sources/remote_book_data_source/remote_book_data_source_impl_test.dart index f0de3f1b..840aab4f 100644 --- a/test/src/core/data_sources/remote_book_data_source/remote_book_data_source_impl_test.dart +++ b/test/src/core/data_sources/remote_book_data_source/remote_book_data_source_impl_test.dart @@ -1,7 +1,6 @@ -import 'dart:io'; - import 'package:bookify/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart'; -import 'package:bookify/src/core/errors/book_exception/book_exception.dart'; +import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/rest_client/rest_client.dart'; import 'package:dio/dio.dart'; @@ -13,11 +12,16 @@ import '../../../mocks/json/books_json_mock.dart'; class RestClientMock extends Mock implements RestClient {} void main() { - final restClient = RestClientMock(); - final bookDataSource = GoogleBooksDataSourceImpl( - restClient, - 'test_api_key_12345', - ); + late RestClientMock restClient; + late GoogleBooksDataSourceImpl bookDataSource; + + setUp(() { + restClient = RestClientMock(); + bookDataSource = GoogleBooksDataSourceImpl( + restClient, + 'test_api_key_12345', + ); + }); group('Test all methods of RemoteBookDataSourceImpl:', () { test('Get a List of books by author', () async { @@ -151,57 +155,128 @@ void main() { } }); - test('test a BookException', () async { + test('test a RestClientException with NotFound code', () async { when( () => restClient.get( baseUrl: any(named: 'baseUrl'), queryParameters: any(named: 'queryParameters'), ), - ).thenThrow(const BookException('')); - expect(bookDataSource.getAllBooks(), throwsA(isA())); + ).thenThrow( + const RestClientException(RestClientErrorCode.notFound), + ); + + expect( + bookDataSource.getAllBooks(), + throwsA( + isA().having( + (e) => e.code, + 'code', + RestClientErrorCode.notFound, + ), + ), + ); }); - test('test a BookNotFoundException', () async { + test('test a Connection Timeout Exception', () async { when( () => restClient.get( baseUrl: any(named: 'baseUrl'), queryParameters: any(named: 'queryParameters'), ), - ).thenThrow(const BookNotFoundException('BookNotFoundException')); + ).thenThrow( + const RestClientException(RestClientErrorCode.connectionTimeout), + ); + expect( bookDataSource.getAllBooks(), - throwsA(isA()), + throwsA( + isA().having( + (e) => e.code, + 'code', + RestClientErrorCode.connectionTimeout, + ), + ), ); }); - test('test a SocketException', () async { + test('test a Receive Timeout Exception', () async { when( () => restClient.get( baseUrl: any(named: 'baseUrl'), queryParameters: any(named: 'queryParameters'), ), - ).thenThrow(const SocketException('message')); - expect(bookDataSource.getAllBooks(), throwsA(isA())); + ).thenThrow( + const RestClientException(RestClientErrorCode.receiveTimeout), + ); + + expect( + bookDataSource.getAllBooks(), + throwsA( + isA().having( + (e) => e.code, + 'code', + RestClientErrorCode.receiveTimeout, + ), + ), + ); }); - test('test a TypeError expecting an empty list of books', () async { + test('test a RestClientException with SocketException code', () async { when( () => restClient.get( baseUrl: any(named: 'baseUrl'), queryParameters: any(named: 'queryParameters'), ), - ).thenThrow(TypeError()); - expect(await bookDataSource.getAllBooks(), []); + ).thenThrow( + const RestClientException(RestClientErrorCode.socketException), + ); + + expect( + bookDataSource.getAllBooks(), + throwsA( + isA().having( + (e) => e.code, + 'code', + RestClientErrorCode.socketException, + ), + ), + ); }); - test('test a generic Exception', () async { + test('test a TypeError expecting an empty list of books', () async { when( () => restClient.get( baseUrl: any(named: 'baseUrl'), queryParameters: any(named: 'queryParameters'), ), - ).thenThrow(Exception()); - expect(bookDataSource.getAllBooks(), throwsA(isA())); + ).thenThrow(TypeError()); + + final result = await bookDataSource.getAllBooks(); + expect(result, isA>()); + expect(result, isEmpty); }); + + test( + 'test a generic Exception should be wrapped in RestClientException unknown', + () async { + when( + () => restClient.get( + baseUrl: any(named: 'baseUrl'), + queryParameters: any(named: 'queryParameters'), + ), + ).thenThrow(Exception('Generic Error')); + + expect( + bookDataSource.getAllBooks(), + throwsA( + isA().having( + (e) => e.code, + 'code', + RestClientErrorCode.unknown, + ), + ), + ); + }, + ); }); } diff --git a/test/src/core/repositories/remote_books_repository/remote_books_repository_test.dart b/test/src/core/repositories/remote_books_repository/remote_books_repository_test.dart index 27a1cea1..6d149cbf 100644 --- a/test/src/core/repositories/remote_books_repository/remote_books_repository_test.dart +++ b/test/src/core/repositories/remote_books_repository/remote_books_repository_test.dart @@ -1,7 +1,4 @@ -import 'dart:io'; - import 'package:bookify/src/core/data_sources/remote_books_data_source/remote_books_data_source.dart'; -import 'package:bookify/src/core/errors/book_exception/book_exception.dart'; import 'package:bookify/src/core/models/author_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart'; @@ -18,9 +15,9 @@ void main() { group('Test all methods of GoogleBookRepository:', () { test('Get a List of books by author', () async { - when(() => - booksDataSource.findBooksByAuthor(author: any(named: 'author'))) - .thenAnswer((_) async { + when( + () => booksDataSource.findBooksByAuthor(author: any(named: 'author')), + ).thenAnswer((_) async { return booksModelMock .map( (book) => book.copyWith( @@ -30,16 +27,18 @@ void main() { .toList(); }); - final books = - await bookRepository.findBooksByAuthor(author: 'J.R.R. Tolkien'); + final books = await bookRepository.findBooksByAuthor( + author: 'J.R.R. Tolkien', + ); expect(books[0].authors.first.name, 'J. R. R. Tolkien'); expect(books[1].authors.first.name, 'J. R. R. Tolkien'); }); test('Get a book by ISBN', () async { - when(() => booksDataSource.findBooksByIsbn(isbn: any(named: 'isbn'))) - .thenAnswer((_) async { + when( + () => booksDataSource.findBooksByIsbn(isbn: any(named: 'isbn')), + ).thenAnswer((_) async { return booksModelMock .map( (book) => book.copyWith( @@ -54,8 +53,11 @@ void main() { }); test('Get a List of books by publisher', () async { - when(() => booksDataSource.findBooksByPublisher( - publisher: any(named: 'publisher'))).thenAnswer((_) async { + when( + () => booksDataSource.findBooksByPublisher( + publisher: any(named: 'publisher'), + ), + ).thenAnswer((_) async { return booksModelMock .map( (book) => book.copyWith( @@ -66,7 +68,8 @@ void main() { }); final books = await bookRepository.findBooksByPublisher( - publisher: 'Alta Books Editora'); + publisher: 'Alta Books Editora', + ); for (var book in books) { expect(book.publisher, 'Alta Books Editora'); @@ -85,8 +88,9 @@ void main() { }); test('Get a list of books by title', () async { - when(() => booksDataSource.findBooksByTitle(title: any(named: 'title'))) - .thenAnswer((_) async { + when( + () => booksDataSource.findBooksByTitle(title: any(named: 'title')), + ).thenAnswer((_) async { return booksModelMock .map( (book) => book.copyWith( @@ -104,8 +108,11 @@ void main() { }); test('Get a list of books by category', () async { - when(() => booksDataSource.findBooksByCategory( - category: any(named: 'category'))).thenAnswer((_) async { + when( + () => booksDataSource.findBooksByCategory( + category: any(named: 'category'), + ), + ).thenAnswer((_) async { return booksModelMock .map( (book) => book.copyWith( @@ -115,36 +122,13 @@ void main() { .toList(); }); - final books = - await bookRepository.findBooksByCategory(category: 'Fiction'); + final books = await bookRepository.findBooksByCategory( + category: 'Fiction', + ); for (var book in books) { expect(book.categories.first.name, 'Fiction'); } }); - - test('test a BookException', () async { - when(() => booksDataSource.getAllBooks()) - .thenThrow(const BookException('')); - expect(bookRepository.getAllBooks(), throwsA(isA())); - }); - - test('test a BookNotFoundException', () async { - when(() => booksDataSource.getAllBooks()) - .thenThrow(const BookNotFoundException('BookNotFoundException')); - expect( - bookRepository.getAllBooks(), throwsA(isA())); - }); - - test('test a SocketException', () async { - when(() => booksDataSource.getAllBooks()) - .thenThrow(const SocketException('message')); - expect(bookRepository.getAllBooks(), throwsA(isA())); - }); - - test('test a generic Exception', () async { - when(() => booksDataSource.getAllBooks()).thenThrow(Exception()); - expect(bookRepository.getAllBooks(), throwsA(isA())); - }); }); } diff --git a/test/src/features/home/views/home_page_test.dart b/test/src/features/home/views/home_page_test.dart index 2ea79900..0046f2ce 100644 --- a/test/src/features/home/views/home_page_test.dart +++ b/test/src/features/home/views/home_page_test.dart @@ -1,4 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/rest_client_error_code.dart'; import 'package:bookify/src/core/models/author_model.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; @@ -98,7 +99,10 @@ void main() { testWidgets('Test Home Page when is throw error', (tester) async { when(() => bookBloc.state).thenReturn( - BookErrorSate(errorMessage: 'errorMessage'), + BookErrorState( + errorCode: RestClientErrorCode.unknown, + errorMessage: 'errorMessage', + ), ); await _initHomePage(tester, bookBloc); @@ -108,7 +112,7 @@ void main() { findsOneWidget, ); - expect(find.text('errorMessage'), findsOne); + expect(find.text('error-unknown'), findsOne); expect( find.byKey(const Key('AnimatedSearchBar')), diff --git a/test/src/shared/blocs/book_bloc/book_bloc_test.dart b/test/src/shared/blocs/book_bloc/book_bloc_test.dart index cf22d8eb..ade021d2 100644 --- a/test/src/shared/blocs/book_bloc/book_bloc_test.dart +++ b/test/src/shared/blocs/book_bloc/book_bloc_test.dart @@ -1,7 +1,8 @@ import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/rest_client_error_code.dart'; import 'package:bookify/src/core/repositories/remote_books_repository/remote_books_repository.dart'; import 'package:bookify/src/shared/blocs/book_bloc/book_bloc.dart'; -import 'package:bookify/src/core/errors/book_exception/book_exception.dart'; +import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -31,8 +32,9 @@ void main() { blocTest( '2- Test if the GetAllBooksEvent is not empty state', build: () => bookBloc, - setUp: () => when((() => repository.getAllBooks())) - .thenAnswer((_) async => booksMock), + setUp: () => when( + (() => repository.getAllBooks()), + ).thenAnswer((_) async => booksMock), act: (bloc) => bloc.add(GotAllBooksEvent()), verify: (_) { verify(() => repository.getAllBooks()).called(1); @@ -60,8 +62,9 @@ void main() { blocTest( '4- Test if the GetAllBooksEvent is a error state', - setUp: () => when((() => repository.getAllBooks())) - .thenThrow(const BookException('this is a error')), + setUp: () => when( + (() => repository.getAllBooks()), + ).thenThrow(const RestClientException(RestClientErrorCode.unknown)), build: () => bookBloc, act: (bloc) => bloc.add(GotAllBooksEvent()), verify: (_) { @@ -69,20 +72,25 @@ void main() { }, expect: () => [ isA(), - isA(), + isA().having( + (state) => state.errorCode, + 'errorCode', + RestClientErrorCode.unknown, + ), ], ); blocTest( '5- Test if the FindBookByIsbnEvent is not empty state', - setUp: () => - when((() => repository.findBooksByIsbn(isbn: '9788573076103'))) - .thenAnswer((_) async => booksMock), + setUp: () => when( + (() => repository.findBooksByIsbn(isbn: '9788573076103')), + ).thenAnswer((_) async => booksMock), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByIsbnEvent(isbn: '978-85-7307-610-3')), verify: (_) { - verify(() => repository.findBooksByIsbn(isbn: '9788573076103')) - .called(1); + verify( + () => repository.findBooksByIsbn(isbn: '9788573076103'), + ).called(1); }, expect: () => [ isA(), @@ -92,14 +100,15 @@ void main() { blocTest( '6- Test if the FindBookByIsbnEvent is empty state', - setUp: () => - when((() => repository.findBooksByIsbn(isbn: '9788573076103'))) - .thenAnswer((_) async => []), + setUp: () => when( + (() => repository.findBooksByIsbn(isbn: '9788573076103')), + ).thenAnswer((_) async => []), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByIsbnEvent(isbn: '978-8573076103')), verify: (_) { - verify(() => repository.findBooksByIsbn(isbn: '9788573076103')) - .called(1); + verify( + () => repository.findBooksByIsbn(isbn: '9788573076103'), + ).called(1); }, expect: () => [ isA(), @@ -109,20 +118,29 @@ void main() { blocTest( '7- Test if the FindBookByIsbnEvent is a error state', - setUp: () => when((() => repository.findBooksByIsbn(isbn: '11111'))) - .thenThrow(const BookException('this is a error')), + setUp: () => when( + (() => repository.findBooksByIsbn(isbn: '11111')), + ).thenThrow(const RestClientException(RestClientErrorCode.invalidInput)), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByIsbnEvent(isbn: '11111')), + verify: (_) { + verifyNever(() => repository.findBooksByIsbn(isbn: any(named: 'isbn'))); + }, expect: () => [ isA(), - isA(), + isA().having( + (state) => state.errorCode, + 'errorCode', + RestClientErrorCode.invalidInput, + ), ], ); blocTest( '8- Test if the FindBooksByAuthorEvent is not empty state', - setUp: () => when((() => repository.findBooksByAuthor(author: 'author'))) - .thenAnswer((_) async => booksMock), + setUp: () => when( + (() => repository.findBooksByAuthor(author: 'author')), + ).thenAnswer((_) async => booksMock), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByAuthorEvent(author: 'author')), verify: (_) { @@ -136,8 +154,9 @@ void main() { blocTest( '9- Test if the FindBooksByAuthorEvent is empty state', - setUp: () => when((() => repository.findBooksByAuthor(author: 'author'))) - .thenAnswer((_) async => []), + setUp: () => when( + (() => repository.findBooksByAuthor(author: 'author')), + ).thenAnswer((_) async => []), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByAuthorEvent(author: 'author')), verify: (_) { @@ -151,8 +170,9 @@ void main() { blocTest( '10- Test if the FindBooksByAuthorEvent is a error state', - setUp: () => when((() => repository.findBooksByAuthor(author: 'author'))) - .thenThrow(const BookException('this is a error')), + setUp: () => when( + (() => repository.findBooksByAuthor(author: 'author')), + ).thenThrow(const RestClientException(RestClientErrorCode.notFound)), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByAuthorEvent(author: 'author')), verify: (_) { @@ -160,20 +180,25 @@ void main() { }, expect: () => [ isA(), - isA(), + isA().having( + (state) => state.errorCode, + 'errorCode', + RestClientErrorCode.notFound, + ), ], ); blocTest( '11- Test if the FindBooksByCategoryEvent is not empty state', - setUp: () => - when((() => repository.findBooksByCategory(category: 'category'))) - .thenAnswer((_) async => booksMock), + setUp: () => when( + (() => repository.findBooksByCategory(category: 'category')), + ).thenAnswer((_) async => booksMock), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByCategoryEvent(category: 'category')), verify: (_) { - verify(() => repository.findBooksByCategory(category: 'category')) - .called(1); + verify( + () => repository.findBooksByCategory(category: 'category'), + ).called(1); }, expect: () => [ isA(), @@ -183,14 +208,15 @@ void main() { blocTest( '12- Test if the FindBooksByCategoryEvent is empty state', - setUp: () => - when((() => repository.findBooksByCategory(category: 'category'))) - .thenAnswer((_) async => []), + setUp: () => when( + (() => repository.findBooksByCategory(category: 'category')), + ).thenAnswer((_) async => []), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByCategoryEvent(category: 'category')), verify: (_) { - verify(() => repository.findBooksByCategory(category: 'category')) - .called(1); + verify( + () => repository.findBooksByCategory(category: 'category'), + ).called(1); }, expect: () => [ isA(), @@ -200,32 +226,38 @@ void main() { blocTest( '13- Test if the FindBooksByCategoryEvent is a error state', - setUp: () => - when((() => repository.findBooksByCategory(category: 'category'))) - .thenThrow(const BookException('this is a error')), + setUp: () => when( + (() => repository.findBooksByCategory(category: 'category')), + ).thenThrow(const RestClientException(RestClientErrorCode.notFound)), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByCategoryEvent(category: 'category')), verify: (_) { - verify(() => repository.findBooksByCategory(category: 'category')) - .called(1); + verify( + () => repository.findBooksByCategory(category: 'category'), + ).called(1); }, expect: () => [ isA(), - isA(), + isA().having( + (state) => state.errorCode, + 'errorCode', + RestClientErrorCode.notFound, + ), ], ); blocTest( '14- Test if the FindBooksByPublisherEvent is not empty state', - setUp: () => - when((() => repository.findBooksByPublisher(publisher: 'publisher'))) - .thenAnswer((_) async => booksMock), + setUp: () => when( + (() => repository.findBooksByPublisher(publisher: 'publisher')), + ).thenAnswer((_) async => booksMock), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByPublisherEvent(publisher: 'publisher')), verify: (_) { - verify(() => repository.findBooksByPublisher(publisher: 'publisher')) - .called(1); + verify( + () => repository.findBooksByPublisher(publisher: 'publisher'), + ).called(1); }, expect: () => [ isA(), @@ -235,15 +267,16 @@ void main() { blocTest( '15- Test if the FindBooksByPublisherEvent is empty state', - setUp: () => - when((() => repository.findBooksByPublisher(publisher: 'publisher'))) - .thenAnswer((_) async => []), + setUp: () => when( + (() => repository.findBooksByPublisher(publisher: 'publisher')), + ).thenAnswer((_) async => []), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByPublisherEvent(publisher: 'publisher')), verify: (_) { - verify(() => repository.findBooksByPublisher(publisher: 'publisher')) - .called(1); + verify( + () => repository.findBooksByPublisher(publisher: 'publisher'), + ).called(1); }, expect: () => [ isA(), @@ -253,26 +286,32 @@ void main() { blocTest( '16- Test if the FindBooksByPublisherEvent is a error state', - setUp: () => - when((() => repository.findBooksByPublisher(publisher: 'publisher'))) - .thenThrow(const BookException('this is a error')), + setUp: () => when( + (() => repository.findBooksByPublisher(publisher: 'publisher')), + ).thenThrow(const RestClientException(RestClientErrorCode.notFound)), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByPublisherEvent(publisher: 'publisher')), verify: (_) { - verify(() => repository.findBooksByPublisher(publisher: 'publisher')) - .called(1); + verify( + () => repository.findBooksByPublisher(publisher: 'publisher'), + ).called(1); }, expect: () => [ isA(), - isA(), + isA().having( + (state) => state.errorCode, + 'errorCode', + RestClientErrorCode.notFound, + ), ], ); blocTest( '17- Test if the FindBooksByTitleEvent is not empty state', - setUp: () => when((() => repository.findBooksByTitle(title: 'title'))) - .thenAnswer((_) async => booksMock), + setUp: () => when( + (() => repository.findBooksByTitle(title: 'title')), + ).thenAnswer((_) async => booksMock), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByTitleEvent(title: 'title')), verify: (_) { @@ -286,8 +325,9 @@ void main() { blocTest( '18- Test if the FindBooksByTitleEvent is empty state', - setUp: () => when((() => repository.findBooksByTitle(title: 'title'))) - .thenAnswer((_) async => []), + setUp: () => when( + (() => repository.findBooksByTitle(title: 'title')), + ).thenAnswer((_) async => []), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByTitleEvent(title: 'title')), verify: (_) { @@ -301,8 +341,9 @@ void main() { blocTest( '19- Test if the FindBooksByTitleEvent is a error state', - setUp: () => when((() => repository.findBooksByTitle(title: 'title'))) - .thenThrow(const BookException('this is a error')), + setUp: () => when( + (() => repository.findBooksByTitle(title: 'title')), + ).thenThrow(const RestClientException(RestClientErrorCode.notFound)), build: () => bookBloc, act: (bloc) => bloc.add(FoundBooksByTitleEvent(title: 'title')), verify: (_) { @@ -310,7 +351,11 @@ void main() { }, expect: () => [ isA(), - isA(), + isA().having( + (state) => state.errorCode, + 'errorCode', + RestClientErrorCode.notFound, + ), ], ); }); From f179baf71802d0e8b553332254d5eb0c485372c1 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Sat, 14 Mar 2026 11:05:39 -0300 Subject: [PATCH 02/19] fix: Update RemoteBooksRepositoryImpl methods to use async/await for better readability --- coverage/lcov.info | 186 +++++++++--------- .../remote_books_repository_impl.dart | 28 +-- 2 files changed, 109 insertions(+), 105 deletions(-) diff --git a/coverage/lcov.info b/coverage/lcov.info index b720a999..89eba430 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -853,13 +853,13 @@ DA:12,2 DA:15,1 DA:17,2 DA:20,1 -DA:22,2 -DA:25,1 -DA:27,2 -DA:30,1 -DA:32,2 -DA:35,1 -DA:37,2 +DA:24,2 +DA:27,1 +DA:31,2 +DA:34,1 +DA:36,2 +DA:39,1 +DA:41,2 LF:13 LH:13 end_of_record @@ -3480,6 +3480,92 @@ DA:47,0 LF:16 LH:1 end_of_record +SF:lib/src/features/loan/bloc/loan_bloc.dart +DA:17,1 +DA:21,2 +DA:22,2 +DA:23,2 +DA:26,1 +DA:31,2 +DA:33,2 +DA:35,1 +DA:36,2 +DA:40,1 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:48,1 +DA:53,2 +DA:55,2 +DA:56,1 +DA:59,1 +DA:60,2 +DA:64,1 +DA:65,1 +DA:66,4 +DA:67,1 +DA:68,3 +DA:72,1 +DA:76,1 +DA:78,2 +DA:79,1 +DA:80,1 +DA:81,3 +DA:86,2 +DA:87,1 +DA:90,2 +DA:91,1 +DA:94,1 +DA:96,1 +DA:97,1 +DA:101,1 +DA:104,2 +LF:40 +LH:36 +end_of_record +SF:lib/src/features/loan/bloc/loan_state.dart +DA:14,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/loan/bloc/loan_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/core/dtos/loan_dto.dart +DA:10,2 +DA:17,0 +DA:19,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:33,0 +DA:35,0 +DA:38,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:48,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:56,0 +DA:57,0 +DA:63,0 +LF:23 +LH:1 +end_of_record +SF:lib/src/features/contacts_picker/bloc/contacts_picker_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/features/loan_detail/bloc/loan_detail_state.dart DA:10,1 DA:20,1 @@ -3574,92 +3660,6 @@ DA:96,0 LF:37 LH:1 end_of_record -SF:lib/src/core/dtos/loan_dto.dart -DA:10,2 -DA:17,0 -DA:19,0 -DA:25,0 -DA:26,0 -DA:27,0 -DA:28,0 -DA:29,0 -DA:33,0 -DA:35,0 -DA:38,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:48,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:56,0 -DA:57,0 -DA:63,0 -LF:23 -LH:1 -end_of_record -SF:lib/src/features/contacts_picker/bloc/contacts_picker_event.dart -LF:0 -LH:0 -end_of_record -SF:lib/src/features/loan/bloc/loan_bloc.dart -DA:17,1 -DA:21,2 -DA:22,2 -DA:23,2 -DA:26,1 -DA:31,2 -DA:33,2 -DA:35,1 -DA:36,2 -DA:40,1 -DA:41,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:48,1 -DA:53,2 -DA:55,2 -DA:56,1 -DA:59,1 -DA:60,2 -DA:64,1 -DA:65,1 -DA:66,4 -DA:67,1 -DA:68,3 -DA:72,1 -DA:76,1 -DA:78,2 -DA:79,1 -DA:80,1 -DA:81,3 -DA:86,2 -DA:87,1 -DA:90,2 -DA:91,1 -DA:94,1 -DA:96,1 -DA:97,1 -DA:101,1 -DA:104,2 -LF:40 -LH:36 -end_of_record -SF:lib/src/features/loan/bloc/loan_state.dart -DA:14,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/loan/bloc/loan_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:19,1 DA:23,2 diff --git a/lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart b/lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart index c2cd457d..960cfeac 100644 --- a/lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart +++ b/lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart @@ -8,32 +8,36 @@ class RemoteBooksRepositoryImpl implements RemoteBooksRepository { RemoteBooksRepositoryImpl(this._booksDataSource); @override - Future> findBooksByAuthor({required String author}) { - return _booksDataSource.findBooksByAuthor(author: author); + Future> findBooksByAuthor({required String author}) async { + return await _booksDataSource.findBooksByAuthor(author: author); } @override - Future> findBooksByIsbn({required String isbn}) { - return _booksDataSource.findBooksByIsbn(isbn: isbn); + Future> findBooksByIsbn({required String isbn}) async { + return await _booksDataSource.findBooksByIsbn(isbn: isbn); } @override - Future> findBooksByPublisher({required String publisher}) { - return _booksDataSource.findBooksByPublisher(publisher: publisher); + Future> findBooksByPublisher({ + required String publisher, + }) async { + return await _booksDataSource.findBooksByPublisher(publisher: publisher); } @override - Future> findBooksByCategory({required String category}) { - return _booksDataSource.findBooksByCategory(category: category); + Future> findBooksByCategory({ + required String category, + }) async { + return await _booksDataSource.findBooksByCategory(category: category); } @override - Future> findBooksByTitle({required String title}) { - return _booksDataSource.findBooksByTitle(title: title); + Future> findBooksByTitle({required String title}) async { + return await _booksDataSource.findBooksByTitle(title: title); } @override - Future> getAllBooks() { - return _booksDataSource.getAllBooks(); + Future> getAllBooks() async { + return await _booksDataSource.getAllBooks(); } } From 5bb3af56bfaa424ca544588dd4682cc9c297cc0b Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Sat, 14 Mar 2026 12:19:28 -0300 Subject: [PATCH 03/19] feat: Add CI workflow for testing Bookify Flutter app --- .github/workflows/{pr_test.yaml => ci_tests.yaml} | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) rename .github/workflows/{pr_test.yaml => ci_tests.yaml} (87%) diff --git a/.github/workflows/pr_test.yaml b/.github/workflows/ci_tests.yaml similarity index 87% rename from .github/workflows/pr_test.yaml rename to .github/workflows/ci_tests.yaml index 9ffa3873..75623259 100644 --- a/.github/workflows/pr_test.yaml +++ b/.github/workflows/ci_tests.yaml @@ -1,6 +1,10 @@ -name: PR - Test Bookify Flutter App +name: CI - Test Bookify Flutter App on: + push: + branches: + - '**' + pull_request: branches: - main From 5db66d5e7fce7ea30032371f3df9b96cc68e1cd3 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Mon, 20 Apr 2026 21:15:10 -0300 Subject: [PATCH 04/19] Refactor authentication services and error handling - Added `clearUserData` method to `AuthRepository` and its implementation in `AuthRepositoryImpl`. - Updated `AuthServiceImpl` to clear user data upon sign-out. - Modified error handling in `BookBloc` to use `errorDescriptionMessage` instead of `errorMessage`. - Refactored tests for `AuthServiceImpl` and `ProfileBloc` to accommodate changes in error handling and user data clearing. - Updated localization message handling in `RestClientErrorCodeExtension`. - Adjusted various state management classes and events to ensure consistency in error message handling. - Incremented version number in `pubspec.yaml` to 2.11.1. --- coverage/lcov.info | 671 +++++++++--------- .../E-R Model/Bookify_conceitual.brM3 | Bin 155637 -> 157700 bytes .../rest_client_error_code_extension.dart | 4 +- .../auth_repository/auth_repository.dart | 1 + .../auth_repository/auth_repository_impl.dart | 17 +- .../auth_service/auth_service_impl.dart | 11 +- lib/src/features/home/views/home_page.dart | 16 +- .../features/profile/bloc/profile_bloc.dart | 14 - lib/src/shared/blocs/book_bloc/book_bloc.dart | 26 +- .../shared/blocs/book_bloc/book_state.dart | 4 +- .../blocs/profile_bloc_providers.dart | 1 - pubspec.yaml | 2 +- .../auth_service/auth_service_impl_test.dart | 52 +- .../features/home/views/home_page_test.dart | 2 +- .../profile/bloc/profile_bloc_test.dart | 166 ++--- 15 files changed, 473 insertions(+), 514 deletions(-) diff --git a/coverage/lcov.info b/coverage/lcov.info index 89eba430..2c8dbd22 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -259,18 +259,21 @@ end_of_record SF:lib/src/core/repositories/auth_repository/auth_repository_impl.dart DA:10,1 DA:14,1 -DA:17,2 -DA:18,1 -DA:25,1 -DA:28,1 +DA:18,2 +DA:19,1 +DA:27,1 DA:30,1 -DA:35,1 -DA:38,2 -DA:39,1 -DA:40,1 -DA:43,1 -DA:44,1 -LF:13 +DA:32,1 +DA:37,1 +DA:40,2 +DA:41,1 +DA:42,1 +DA:45,1 +DA:46,1 +DA:51,0 +DA:54,0 +DA:55,0 +LF:16 LH:13 end_of_record SF:lib/src/shared/enums/sign_in_type.dart @@ -286,6 +289,153 @@ DA:20,0 LF:9 LH:4 end_of_record +SF:lib/src/core/errors/auth_exception/auth_exception.dart +DA:4,2 +DA:6,0 +DA:7,0 +LF:3 +LH:1 +end_of_record +SF:lib/src/core/services/auth_service/auth_service_impl.dart +DA:14,1 +DA:20,1 +DA:23,2 +DA:25,1 +DA:26,2 +DA:31,1 +DA:33,1 +DA:34,2 +DA:35,0 +DA:36,0 +DA:40,1 +DA:43,2 +DA:44,1 +DA:47,2 +DA:50,1 +DA:52,0 +DA:53,0 +DA:57,0 +DA:60,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +LF:23 +LH:13 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart +DA:12,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:18,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +LF:9 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart +DA:15,0 +DA:19,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:37,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:47,0 +DA:48,0 +DA:52,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:70,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +LF:30 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart +DA:16,0 +DA:22,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:37,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:47,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:56,0 +DA:57,0 +DA:61,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:82,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +LF:34 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart +DA:12,0 +DA:18,0 +DA:21,0 +DA:22,0 +DA:27,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:36,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:54,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +LF:24 +LH:0 +end_of_record SF:lib/src/core/database/local_database.dart DA:5,0 DA:7,0 @@ -1104,152 +1254,6 @@ DA:91,1 LF:22 LH:22 end_of_record -SF:lib/src/core/errors/auth_exception/auth_exception.dart -DA:4,1 -DA:6,0 -DA:7,0 -LF:3 -LH:1 -end_of_record -SF:lib/src/core/services/auth_service/auth_service_impl.dart -DA:14,1 -DA:20,1 -DA:23,2 -DA:25,1 -DA:26,2 -DA:31,1 -DA:33,1 -DA:34,2 -DA:35,0 -DA:36,0 -DA:40,1 -DA:43,2 -DA:44,1 -DA:45,1 -DA:47,0 -DA:48,0 -DA:52,0 -DA:55,0 -DA:57,0 -DA:58,0 -DA:59,0 -DA:60,0 -LF:22 -LH:12 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart -DA:12,0 -DA:14,0 -DA:15,0 -DA:16,0 -DA:18,0 -DA:19,0 -DA:21,0 -DA:22,0 -DA:23,0 -LF:9 -LH:0 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart -DA:15,0 -DA:19,0 -DA:23,0 -DA:24,0 -DA:25,0 -DA:28,0 -DA:29,0 -DA:30,0 -DA:31,0 -DA:34,0 -DA:37,0 -DA:38,0 -DA:40,0 -DA:41,0 -DA:47,0 -DA:48,0 -DA:52,0 -DA:56,0 -DA:57,0 -DA:58,0 -DA:63,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:70,0 -DA:73,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -LF:30 -LH:0 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart -DA:16,0 -DA:22,0 -DA:26,0 -DA:27,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:34,0 -DA:37,0 -DA:40,0 -DA:41,0 -DA:43,0 -DA:47,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:56,0 -DA:57,0 -DA:61,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:82,0 -DA:85,0 -DA:86,0 -DA:88,0 -DA:89,0 -DA:90,0 -DA:91,0 -LF:34 -LH:0 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart -DA:12,0 -DA:18,0 -DA:21,0 -DA:22,0 -DA:27,0 -DA:29,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:36,0 -DA:40,0 -DA:41,0 -DA:42,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:54,0 -DA:57,0 -DA:58,0 -DA:60,0 -DA:61,0 -DA:62,0 -DA:63,0 -LF:24 -LH:0 -end_of_record SF:lib/src/core/utils/verifier/isbn_verifier.dart DA:11,9 DA:16,6 @@ -2121,76 +2125,70 @@ DA:75,2 LF:33 LH:33 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_state.dart -DA:10,2 -DA:20,2 +SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart +DA:12,1 +DA:21,1 +DA:33,1 +LF:3 +LH:3 +end_of_record +SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_event.dart +DA:9,1 +DA:16,1 LF:2 LH:2 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_bloc.dart -DA:16,1 +SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart +DA:15,1 +DA:18,2 DA:19,2 DA:20,2 -DA:21,2 -DA:22,2 -DA:25,1 +DA:23,1 +DA:28,2 DA:30,2 DA:32,1 DA:33,1 -DA:34,4 -DA:35,1 -DA:36,3 -DA:40,1 -DA:45,2 +DA:34,1 +DA:42,1 +DA:43,2 +DA:46,1 DA:47,2 DA:48,1 DA:49,4 -DA:50,1 -DA:51,3 -DA:55,1 -DA:60,2 -DA:62,1 -DA:64,2 -DA:65,2 -DA:66,2 +DA:56,1 +DA:57,1 +DA:58,1 +DA:61,1 +DA:66,1 +DA:67,2 DA:68,2 DA:69,1 -DA:70,1 -DA:77,1 -DA:78,1 -DA:79,4 -DA:80,1 -DA:81,3 -DA:85,1 -DA:86,2 -DA:88,1 -DA:89,2 -DA:93,1 -DA:96,1 -DA:98,2 -DA:100,1 -DA:101,2 -DA:105,1 -DA:108,1 -DA:112,1 -DA:114,2 -DA:115,1 -DA:116,1 -DA:117,3 -DA:122,2 -DA:123,1 -DA:129,2 -DA:132,1 -DA:137,1 -DA:140,2 -LF:55 -LH:55 +DA:70,2 +DA:71,1 +DA:75,1 +DA:80,2 +DA:82,1 +DA:84,2 +DA:85,2 +DA:86,1 +DA:87,1 +DA:90,1 +DA:91,1 +DA:92,1 +DA:93,2 +DA:100,2 +DA:101,1 +DA:102,2 +DA:103,2 +DA:104,1 +DA:105,2 +DA:106,1 +LF:44 +LH:44 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_event.dart -DA:10,1 -DA:18,1 -LF:2 -LH:2 +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 end_of_record SF:lib/src/core/dtos/bookcase_dto.dart DA:7,2 @@ -2208,10 +2206,6 @@ DA:35,0 LF:12 LH:3 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 -end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 DA:10,0 @@ -2385,6 +2379,77 @@ DA:33,0 LF:13 LH:0 end_of_record +SF:lib/src/features/bookcase/bloc/bookcase_state.dart +DA:10,2 +DA:20,2 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/bookcase/bloc/bookcase_bloc.dart +DA:16,1 +DA:19,2 +DA:20,2 +DA:21,2 +DA:22,2 +DA:25,1 +DA:30,2 +DA:32,1 +DA:33,1 +DA:34,4 +DA:35,1 +DA:36,3 +DA:40,1 +DA:45,2 +DA:47,2 +DA:48,1 +DA:49,4 +DA:50,1 +DA:51,3 +DA:55,1 +DA:60,2 +DA:62,1 +DA:64,2 +DA:65,2 +DA:66,2 +DA:68,2 +DA:69,1 +DA:70,1 +DA:77,1 +DA:78,1 +DA:79,4 +DA:80,1 +DA:81,3 +DA:85,1 +DA:86,2 +DA:88,1 +DA:89,2 +DA:93,1 +DA:96,1 +DA:98,2 +DA:100,1 +DA:101,2 +DA:105,1 +DA:108,1 +DA:112,1 +DA:114,2 +DA:115,1 +DA:116,1 +DA:117,3 +DA:122,2 +DA:123,1 +DA:129,2 +DA:132,1 +DA:137,1 +DA:140,2 +LF:55 +LH:55 +end_of_record +SF:lib/src/features/bookcase/bloc/bookcase_event.dart +DA:10,1 +DA:18,1 +LF:2 +LH:2 +end_of_record SF:lib/src/features/bookcase/views/bookcase_page.dart DA:14,1 DA:19,1 @@ -2889,67 +2954,6 @@ DA:84,3 LF:32 LH:26 end_of_record -SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart -DA:12,1 -DA:21,1 -DA:33,1 -LF:3 -LH:3 -end_of_record -SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_event.dart -DA:9,1 -DA:16,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart -DA:15,1 -DA:18,2 -DA:19,2 -DA:20,2 -DA:23,1 -DA:28,2 -DA:30,2 -DA:32,1 -DA:33,1 -DA:34,1 -DA:42,1 -DA:43,2 -DA:46,1 -DA:47,2 -DA:48,1 -DA:49,4 -DA:56,1 -DA:57,1 -DA:58,1 -DA:61,1 -DA:66,1 -DA:67,2 -DA:68,2 -DA:69,1 -DA:70,2 -DA:71,1 -DA:75,1 -DA:80,2 -DA:82,1 -DA:84,2 -DA:85,2 -DA:86,1 -DA:87,1 -DA:90,1 -DA:91,1 -DA:92,1 -DA:93,2 -DA:100,2 -DA:101,1 -DA:102,2 -DA:103,2 -DA:104,1 -DA:105,2 -DA:106,1 -LF:44 -LH:44 -end_of_record SF:lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart DA:16,0 DA:21,0 @@ -3774,43 +3778,46 @@ DA:52,1 DA:53,1 DA:54,1 DA:57,3 -DA:61,4 +DA:61,1 +DA:62,1 DA:63,1 -DA:64,1 DA:65,1 -DA:71,0 -DA:72,0 -DA:74,0 +DA:67,1 +DA:68,1 +DA:69,1 DA:75,0 -DA:77,0 +DA:76,0 DA:78,0 -DA:80,0 +DA:79,0 DA:81,0 -DA:83,0 +DA:82,0 DA:84,0 -DA:86,0 +DA:85,0 DA:87,0 -DA:93,1 -DA:95,1 +DA:88,0 +DA:90,0 +DA:91,0 DA:97,1 -DA:98,0 -DA:99,3 -DA:100,1 +DA:99,1 DA:101,1 -DA:102,1 -DA:103,1 +DA:102,0 +DA:103,3 +DA:104,1 DA:105,1 -DA:111,1 -DA:113,1 -DA:114,1 +DA:106,1 +DA:107,1 +DA:109,1 +DA:115,1 +DA:117,1 DA:118,1 -DA:119,1 -DA:120,1 -DA:121,0 -DA:122,0 +DA:122,1 +DA:123,1 DA:124,1 -LF:58 -LH:40 +DA:125,0 +DA:126,0 +DA:128,1 +LF:61 +LH:43 end_of_record SF:lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart DA:5,1 @@ -3979,44 +3986,40 @@ LF:2 LH:2 end_of_record SF:lib/src/features/profile/bloc/profile_bloc.dart -DA:14,1 -DA:17,2 -DA:18,2 -DA:19,2 -DA:22,1 -DA:27,2 -DA:29,2 -DA:32,1 -DA:33,1 -DA:40,1 -DA:41,1 +DA:12,1 +DA:14,2 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:29,1 +DA:30,1 +DA:37,1 +DA:38,1 +DA:42,1 +DA:43,2 +DA:44,2 DA:45,1 -DA:46,2 -DA:47,2 +DA:46,1 +DA:47,1 DA:48,1 -DA:49,1 -DA:50,1 -DA:51,1 -DA:57,1 +DA:54,1 +DA:59,2 +DA:61,2 DA:62,2 -DA:64,2 -DA:65,2 -DA:69,1 -DA:70,1 +DA:66,1 +DA:67,1 +DA:74,2 +DA:75,1 +DA:76,2 DA:77,2 +DA:78,1 DA:79,1 DA:80,1 DA:81,1 -DA:88,2 -DA:89,1 -DA:90,2 -DA:91,2 -DA:92,1 -DA:93,1 -DA:94,1 -DA:95,1 -LF:36 -LH:36 +LF:32 +LH:32 end_of_record SF:lib/src/features/profile/bloc/profile_event.dart DA:10,1 diff --git a/docs/design/database/E-R Model/Bookify_conceitual.brM3 b/docs/design/database/E-R Model/Bookify_conceitual.brM3 index c015c2ade505584b0462890a625065aaab4d55d7..07cbad3f3337e05c1b6d80e062908243716f6c06 100644 GIT binary patch literal 157700 zcmeIb37lL-)iz%DcK7USGFe!HVF@CT$-*KSkxXV17@Uxpge?Jw&P-?0Ff%=N_k;v6 zA_xfbv50H}FA4-?l^4VfL|+y`1Ox?9UQtj`1mwd7QC#?+=TzUV`rf+J?R4hm|B>JC zo=o*URrl1Xr>f35Rk!Y~e-MdWR_xN38O~=jgUS9(wmmtLNoR8Hhm0n({mJFY{%kU{ zD7&=zu|043%8m?~GkH-rZ=cz7=g*!$ci#NbEXuz1&(r=^RkP{^ zQ;3Zt!W?M2Ro3$TmIS$Ws&8K^ogYmOwp)+vw10Z^!Ce|3|7Y?`rbu*)c*m-aL%K!% z;;!yh%U1MutXj3AN7QyMTe`HjbJ^iX256y?85Vb~;tT~1wDt`qbGcNmD`P#Aa<6eI zu@m#^2x#Ou5OX&&8PcL>=w0aleyH2RNrW3 zwWy{>8=&^+7FFw0>4E(E)uKL~TbdcorMfaF4X+l7q0#=#=xR}wO(h5WQdG)G>Hhrs zE)hRDlNss}&DKM~zC4r5ixw$o@}&Hn<(c$wo|?L$C!NbDyHefx)G%>OksPD>^x&M1 zY&N+Gw~4K8WnY$xNcYLcj;|5Lihzbp!pl0sVO}&l&ssu1P#LxBGTBsTW-ycWNW#BB zlJxL8mr|$q^rv#E;q{q0OETG^$P6_X7(vp>4Iy#uAGQmba*W^amvQ7#`H|0i0 zQrV8-zDyP!EH5V8^4ULL}bQBo}#;ot&iJAQK4#$th$JN1hZ1 zrA+U0RoNPUx?N3r;3ZE!_rvEeTEacDF*%qXUY|shW_s6m3r~7OkErGmD8&s+x|!Br z7*mcIPP1wT>5sndu7W~#Ko79g>c@iaSb$SIp>QafYiCr|JoM+4|9)kD(iCmoqKU?W zm8*J}tvIB&tDDD*?!&v0L~6CDP4%bqfO2ZJXc$hV`l+8L2bbq_)Dwp@{pmjHpSks! zla^%%Aj%q1wH!#JPPN?{8!P;i8_S7Rsf~Gi0ObTrmM4_ah}pwEv5R{GaMzV$7J^P) zW^FE&-HbB-r21v2rfM|hQU4B7AG$L4K7(3os?}Po3|nD;y!nzlr{&H##uW9d#gq;V z|H+OMMsxX8$7r5rrF37Wn=su)EhLrSojWw$j|Q_xiw&v4)uJX@=*ToF^wS8(cat>e z)@GCGTx#iPe-f?fj4-Q3OK!L;olCAAOf65+(3$G*5mQF88LDHdKS|PZ6^1D{YENU4 zJ%HGQ9XBP9r&PgKtAcjjMD@mJSN{IMR>C65+m{?(lGM`_kv zEt*Jnmqdk`Vtt-E=wNDHo|tp_%*cu)b=GbXqd#d@*^thqsS?&~LBsOeWZ#KA2t#s= zh<$@;>X!uXJXr-KfoOBaa{E_myXwAd8lXfz8dU|1C5 zQo0iO1H{+2^7|B7bX>-IidQbw+d34 z@knYi()bclOGYT&Wb|>hzr2j|w5l!@C4bOWuRQ3*5PnIJa&9F4;ccpmX`sW?{zjMOnZ{I*IN#jY! z;NVHgO@$H3ZOf4P#-ZK^<5_%omRL9>jU&`brmu>F4^{$ii98-INaw%*p>aMbCt5$^HVInFALu+GqBXd9&v&S+wu$&aT;u4(ymczjO9}9dvKM z#rq#Hd;S5lJ3AM3%YO_podzC4?Vjj74^ zG|$@ku$R6W6Xp_8H<(HGFG==Mu#aL-`SsZpIk1EM8%GXaND{!vsUccVS1d1f%Z(0` z^E{kyPg)imTeZ3N{?xkkaH_xe#MCBwYAYLy2q?C9lb_Xy;FYo#}AoyED7bcFY}`6B#O7K&(q_jJr0naGL+Qay_+6So1!IWs!**<9+p!7N zvw+0Wkep>Z_8>NL_No(q{KIp<{|i%8uNIBnxmB5wW!XiUd_F_5zbbOjvYAmhdgOt* z?ME{;geSL=N5zG9kz4KdzvYwW@FU2w_JqgU7_M_2qsu&i#1*fA_*;w2@CwyrN8jGv zlO8~T;(|{Y6j(Tth0WnYR z9y$N{WKS|XFq)-MKobHx6kJ}H9#~1gQ+wo7L--4Jd9p)EQ(!!Sn=~T2BCadfCr9AR z@GTDIT}natJc95$Yw9NBJya(W3K9Zfs@14cn&6wL+ZZr3On>ae0dL2ilb zaa25JIdIqW&$clE!SweZ%LMt6L%{kF zO@3(_>pApIQFg?*tzw}HOo^Hq+hXmj%l_#67r(YQd#yDH@FI##`o_e^_uGUH6PK=LPUdh+b=%-s87Dw#mNA~lef%M{eX;)uED#lChA zlLg86V^Kkc2)*nG)K{zf)8teqsen0SETBtfSm2rXsh!Nl0LEeco!*ompUB z?1DVBJXVx&>7Oc|!BNJi`R3_@CRZfS=HxjG>8VJ54#YiW6`>3aTexaUkD(I82mE@B z6(>PXmp5-7gd9u)It%U{gj{#9kmxK`d9k+@s_IYA%%=OT=$>3im^qxu_GkL~7*EMT zxq2`I53)j8C@*Maz`bkzMgtU36tKXLESMd{;FPvF6fo%~) zSD^895Cww*(VEa2rt%cGC)WuJI+gB(@sKv;PNLHLPK%ND80p#}}e**ajnb_%mvht?#vb;3VT`R(`z3=KH&-kIakyl2WI@m|Z z!Wf|y($%85@WbL9ExOQ-pw(h(C%R}d%kIUY1n86D$H13gTh{V-mX`|**#`~8el4v_%`GL@Mb zkG~rvXO+aZ8L5VTquJa{(NnysmG(VYaZU=HJt(w=iHEC4#?tt=or%w5+HKB?`D3zd zJq9V2!v7|5z(elo;QB5e9vyPuq$RQ1{K$N1#?rH9kL_6n+tpnX>eZH~oddL-EM1*b z5Pv5YLr|ncDmus@RAwKvAemzH51PIM}4>LFu5w~ktSgT?`QuV0* zBli&X-Kiua5cS~%s-wU~tQS6)S>oSstOWGbd%$$L10Kzb5rYaqwxvzF1x8 zVJ-)K3sgP>WOtC+Q1gWwX{ac~G@R{F3vRsT(7oeF^-s433VYr)yQs__E*&Gof})gk z%B*|d)N8zxv3u#akKcX6t9Nd(3#WppSQO@5m=6qu*%Np~;kt(Y$MqWbygKSXh*x-! zGG?!kAu4@4U$1UcDV^A`Ixz=1eSps^6}qq?7+&F;e7+Dt`4p*xvt=+&G^4eyVg?MJ zbdy6tV91Pv2K;(B9=o@n3+rIYkkf*DxLQWJL@e4BSRbW1`Ol9(uD;H!i4iAFkUVbeU6lC}))X@hL&^Tb|L*uNn8;3c+ z%gIv4-|-C{oCcY7f`dU3yc%8RkqQeQ77~D5;uMeojh}}5UX61&^{EOA9_H&aRCI!a zK@mI-jXzgm!4)HlpXQD-!3Nbr1q=#Q*y;F9g#{1u%uj>hx{(tMJaRgnvmP3My~2Xq zvp)nZMEQy|u7e6Ru0W+0g1=Q^!NdG%#<))7U{Ew(2f_bcVZq1jDI3R=IL3MqOyLG* z3F9=7&w^YCayjh>%%}4*@?=!GeaAMg2U%?_5ds%Zb*r$L@$4pLGg1JTi8x%3vY-}Gi zH7X;8%v-S3j8({bNU^&mO)fkI1GcdfO9_dpRHiby^a}b*{~I(Z%<*fXAb*J$OU|Kc1~m>C&Ozh6Xg5wI{H1## zvrcd@D1t}AUt+<(4Cw>90~pvSaWozYe~F=@6C4bR;F0i`E`qXkPyvGil}PwY3>DqT z2?icH9jHXYUt*2xpaKR3Dz%u;CfZ+OjO#QG21Vl$^OydB!TK$be-SY;beN4GQ$P?M zH)qje(a7jpdfRTjeAmwFGwsVGz1wFp+eay%VfjpEJ5s+T;#yJTxzfsMew*}kktgLu z%E9TRz#!qq~6Nn^)g!@eYON{0M5bXRlyOHn5em>JMm3+Akdqk4F zsfRrGyeY5GL?vM<+qt;cewa#3pwz8{f?N*; z9?4G&^qGz%WrF$oGL^}tSI%cL*9ZAb^ZZ&U$Y&abI<5iXBvgfI>Eu92p$QaX$u6`K?Mv7R3hOsF;sLT zCm49-bUJ4wd?wbo4k}@;op9lFO$h9ChgWQ>? zb7N9DI{#!OPg`X%uzS6xgL$m?cun_sy{3Cm4s$sxO*~s#InAGtrmpv-oDexUofJ54 zL3s}_vGaiI79X$4o|z%{ID1XzFl0y;dri{tB8h^$CNTI|FVV^5X{m66AoAP>1RFX;goy+4j-GY+o z`cdJEw%6o`jPpoxt=9wwuh+B>se`lKs$lhKIcxkA&C6 zP|*nv21W2lcugE@)jNO(=GaUE2^pg<)OUK3+n zr*SYS8jqIO6vH4FYX+GH@;;FFgUkWJnV_+Q>73`0vE$7zZkir=sc&b8FUlckl@{1avUh9~93$ieBPz@`Wl3!E6XefH%s6WwI52@Fq^Y3Pr|YdXNsCXexnF)?7{ zWNu-%*K{38B%S~XFcZP>1oEEh8E-1%HQfk79)$vz@zVmmre&mUFh5$RGP(51c}=l1 zf+mFz`n6Dy*Mye=1sgd5jROWO;m6Lg8;3b3dadbiVSIi1cK39pGYu7e5~6sSbP zYhsM+G!6zu;}P?kF2T@oHOLl_+d%FH`3}fKAdl1jJUWMs+@{g&Acl3X)AT_e={-)< zPucpi_UFYAHjkZ8#N{;cTxsPr|4Mp#)RS_IJ#acHa6X0de#ykn1FolhoF;o-CiVcQ z33tkRrzv(0WH`0hXM$Db*f2gm6BvAKn60woASXN4yX{1pH$dff z16*B{axC;18Arrz5|4ScZJE=r;;F(FZHwHmjpvc%T8kVEUW@#jRDI62zmG*uH`yWw z!~SI&kz=vQKjdfcIqMj)x4A{#7Ws!rBC$V6fC&NyY?qDwo%8NWNj|Xu8cwpwJm&N7 zI7<_iU>z$-<%(NeCk%Xq?uq$O;9{qEzjchoq-`+IFH@OZdgUzgxICKK#{oakuZ4mv za&DJBp_72d0mGi8#JGGp7mX7Mi~LN;tP>mzir|s3$XW13kUl`;U|8hUcqA-xhKf#b zFerjY!XiHo%GN;z3<^{tVUaUbSnV39VB~al&PZ6~tZ^Mwz@R`S5*9ftTc>f{Q#2ke zi#$FFc-S6f7ZAqveEjtx5LWtOc~P@=bW<-KvUeh;DX&33n`bV!K^|Y}G05X9Q4#~q z+4{v(rIph>gVZ$NlUit}!0DvGc_7ML!^FdNppQYm*qW9h_Y{!vJ7ge^ZWjA{u|Y1a zE|QeTY#)Q1tuD^Y6|hX0t!R)3NqupM)EB=ewT}&DdnwSK^$$l;0Fi`{0O!ZCgX37_ ziysd%05XhxZ#!;K!Up<5RQ!Q(ZnDb+hGWaL^2g#beb~<+cR}Sd+`?{`=}?kL z919XK@q^)5;OZ>SYmGORS;XjpAV))i9KMks^zw6=21(msKDtb0a$PFuGX0;RMT`Z0 zEfnN3;YdZX93-G|z_1*RbFtkx%sJ7E7~h7>I>Eu92p$QSi3MK|=>s$lhV@>JN5W-d zsOSU-gCck&T&7P!**d6zL4isnTqcH!ZsY_5kDN~DjD*X?8rMMu3<^{t;W9DCbs7hQ zqVb5iOxIxOxDf=q8ROpo`7X%AAU^_mHZPiz^yO|WW6+1V=(F}1+r5s{5j@;`9H$q& zj?)V$>T)8kl?+BRbofJ5GQQj*|JY2nOmPqGpXW~OZbkLfdi9OhH zimeQqBNdYv=77EXD}FI#IIGxkIv7kgID8x@F!&fUThDO{lp4zuLGB);zJaUEYPZa< z_oUXJG(frzcbxtY^onCY;(r0bzQXut{2Zr`QX}-*ut&7Xo4Uz!&ztf(PE?Xf`JKz- zIQ61rx^605(RQ5t@Vt~H*E&vM@H$QyEjZihK8_RJWXA~%rxQ<+?P z~C?|WI-qd;aJ#acHc${aVyiYRmaGmMn zaoSc5v5&XMnV1O~CKr30(rAS`U}X4soNTmmX0E{2_uT@e{#J<8-+E8#QkUvT*P$L~ z0*mDd9#gO(GjSnEtDnb7Z_tS|ZP+6`>P_A2x#vxJJx;ufNBN!0<8fl&2d;YySF}A& zKRjPcl2dSu{>g1)?D@P)N$dMhh)Ur;T_!OblFj;-QsGzn8P3xMtX5eBmSA0<*hUd} zZ;Oj?IZyxTH`Ee0@_44ejf62S^YeJ({6-QY_lX-=SeH*4+lyo@=mHEkGJ~uBU@$OP zC1i}k8j%vWx#~T(kEj(2N4U@0|CklK`hMAdMQSj~U#T9V?}~$$zSH% z!}{Ew_e=Hd^rd=lws+ncX};*(f8Jx_Wc#9Ta?@w$hv;Ltqt^GcbM!szovfnW-^1?7 z$Hl*PwUEi6F(HRM3CRtb{~@Uz&=kIg?D< z^YvlN#KT2q#x^Q-N0_dOVcc}ht>qqy2$5n#q5FPFi1=b?{&lqfM&|YHzQiat7MNcz z6S!RZcz55ziw<128_&FI`UbZpjikLw;plHnF*I0V) zIetCY6>NRozozy}^2K8mi~J16A@2c2TW^^pQT!^jRP?qfwdQ~g36H4h8V0lO2&*_4 za4d*|kg|Zy_*BOm*Q+1#;~)(mVI|`}zT*uFm`VK+%*qi~W0tBS<4wV!BV|?91+38; zpY`j*0pa-g5mZCnNl?sy1@WpDt`LXg(N=Rf$=Vy^dpZ900-mp|D&wcZ7whb(20zX9 z{kr(4!1Gm*fDsl9is0DClsKTmf*V|Zh~N*02#!4mE{$U!Q=+57f`@!uQbI*1IIyG$ z&fd^r6&7594?oQfl@p+B9aO-eKn44l5-Te#c*w^kCB}8*Jur@u(*+gmV@e!bVZrT< z%g}7`$0g&eaUE2^pg;xtm=dW93oauJ!JU(bL!HLKplBTXm=f~j<;o3*)vOp>a59F) z61oH|X@revr@0USZPkt-yMZ9OT(vLAhe5hPdO%j?g_-V0iR5z`T!v^we(yuTdK|~3 z>hL5^f=nUeM3Unt(M|iXs`zC^De3Kz=*;P)z=@-)s!~j>XET@I(N#0837OcfNHY8e z@0TUZ+q+cNLWPo{7#b(6LTgvy*qOvXLEZxKJC`Vq4NvyDMDdkHDf@MFzUNJO;)Ey( zJkG^!@?k0wTl()STtB1#acSa&W42w~t^&7<%c4Sse;r_Zs53b?kM*7P#IKRn#~7z2 z0`1O}I2gRn(o9kZXS2^Gayd(M6FXCwK{=PGEDiX@3#ews=ll#U$62b9A5nF?g)H)~ zNW37U1q{C;HC3I$YPZ51ThCdlI;A+wu?T>&1tu@ zbRwkTldJaUdx6f<{?y&TtejjmW~sRJ@eaH6d7mfI>@XO91M!!k#Lq+@aG_XfX2aqQ+-?-kA$<-2bpz(gFz8I63)^Y5L^cp zFep%ogtK%V1lNt6VBnF{>70>pmRRFDsDMF%N+g`6zA%l0LD6``oTZyEbo@66_El8< z56BNda6DAi&p}?yi}-MIh&@xUyR;Jz^0rR~=2yM$(yRFGS|ToY32XZHF;#K+n%{B6AJy4_3Svf{0^MyO3EYI2aVcBVoQkE@KZ!AE0q!F!u0jJQC&$ zkf0Tu7*xR{VZLmJvUN}ag94REm@f}1kG1t@ZL&PbRqP^cCv#GpbY66OnIT&Hnh zT+#SMn=c0DGCS5=4dhn0fJ_I$cGzkRC)IO74ggu07gZgj`SqDBCQ$6LF?jdI&eUwP z54t*zGKva*Sc7Xbu)vl| zf-Bx%=gF1IJ)Yfv-{YS!Mb&CCX=!Fd8k_Z!eaXzyPYWpXlJv$*Ud*sF(-BeYlesy|Gqek@ zE7gM(u~iSI2a^4n4m9}%Jt8rZ97zo#VbB)88CLDwTl`j~Hs&*nlDX7jml;=_zHDH= zDPpTdb05_wo6H`W%98M?P*W~FG%}dVb)`;DQN4OZeFuxcyA<e9n?gb|`5V zzMG4ge_X(LY?Y=GUW1Nr4>Z0*Z6|hRkjy~Z@0~m{ftdN72y8lnB`B25s3f*=Whpk` zB-HeeAORK$82(64s{S}@CNehQ!H`)eI2aVcBVhwVE&~f_K^i9p1M`YYpg<)OHXvjCUwWvBe|e!22^$a!)k1|BRH#J42IS#Tr*SYS8lPwz z(7WDWodzC00kR3?(;(-7Tm*6j$d~i9FW+s6^v;`$(VeY9o;@%=O|$GJ08og$NbE6h z@8J)44MLplUfoBe$RIQ}XGObq)-Rfv<%5JEC1Z*<+Q^Vh4tByE$Ox1-&nnMrzTh1M zPkkKo#iz(v=e)zI^aR_D53}g@)YgC-V|@XDC*Z=?cP@cU3F{RLlygrhcCTsKy}a|0 z>|O|_%l@hHshj0COVge6t*D9r9LersKaaWE)QiNfqIp;8qB74D7q*qt*9vpZ{C3l-A1 z3Y93#?h@lVjRWI~#v?Yne}{&S>W4rc2SM1Q`gxF-L2yD+^;`6wV^T(Vde>$$CjvZ9 zoM$Hj+~JHT_d-?mzrEA?zbQ}RdqkXtD)T`RXVlrH zAbR4>SI4tzjv^>6CnPr{+mk2d+m~ksHw|QlZ#ZV*F&}@h@2jSWcZ=%b5xfPM>k(CJ z>BF16dr?eZBdRyb-y!=KDY?m&+&Ds_$e<9yUGwR>l!7|#^#7agzz%+iZKCTz{O`Vl zaF2MCgofa|Y=&kh)0b@WBl~hNB*(u@qwSPOjBvL7h#fXX4e(zBXw_hvs&^pKKmZZG8+>A(0I?J0 zG=Hy2ZNWV^%#jy4_}b#Waq0FnVYDKDBmL8xB-fP*%sM)|65P*F&234zpgMKzTolf*%gVvzx}@#LtF?!#&}2vGj9urbcica zD@`Pk8NBbE;T#Umra7d887g^5$3=cL4qqdEuQI9`?3jWluydt$uby5)D=SLcheQu6|#lTuS{a zeIjycHB?Mk?n$mgBE;ROx2_k0L4jzcPed-QhW749)WoL^xfALp0Wk0+;EXdBJQ2CH z$|bnLDD*A=`8S^qplCh?pcOq4xwPtqoJ%45pRVn`MAcK;uA(O*msY*N(@dl0Ap0x} zfz(6xJ(w*{3is}VID0Vha0Q%RA)iI;*6UdCNXFyzikcr%p*8mvt=SYzRXhcDU-6oa zG*vk>SHQCSw%(depw!QVNd3%vQY*WKpfF{Y!%uQ$55W%7b-+rK%Xz?BbM0&poE%fT z0Qv59mYbY$_(m$(KHo(AS5eA-bCK_PQ=S+01WH1F`{G_Zf#;jl+!VOpLr*Vt$PPsfZ++? zN*=9cjW^@61&^h1`FdLg8!z%f`@s9kV|(61lJ62_PaEWRmvK9%xdK{ z9_H>bR5V8t2rwvu!$7NftHK&r<~M$t+lzYw8rMMu3<}1vN?G&o3JV_QoV@|TS^9v^ z2?icHoz96>%35h!R}L!9gbxXYzs7Y?L8TO^V3o4ArNSBybE$4eb#xjBgQ9V)Qr2!) zVZq1jEY;#|yV^X+sUV*LIS=FuAXkB0U&84Xwce%4+S^b-iipcy;%Sl<0AKudy6n>{ zIOW)R;B->pd*_p7mYNaXxxDq>Sj z362a}TjXS9a7&TF$*|JyXWE0Ll~}i9?Ogx(!YIqJMkXa`<7!<)HVa!1;-F|a}76<`^nk!Qn|j#V*04V9XiQ!k_{M1uBs+<^UC;+2IeU@D6{M#-m`&vBtGfA&sk0 ziGndFheMslF&w_*#rQ-UbKb2Tb%#Q_K~qsXY^w<%mNRn))=sM*4-_B_%+$#GedMA`C-rQvJ!Y%yA=;nm>W z7P7tktWAt&*OfAr9zr_Ptv?%Jc!g!PRlr7PrJdcdxXACq1P6m6IL7&jUidR0m+r&_ zFz|^9HCNag$5cAe3xA9Rt>A|g3y!IDq8I+?i_CxmNPxKr1_dfL5WLdPuI)=ew&L|O z2^Ec(&QRgr=s+b33xBL}EmTP3D#oL*@Fy{@(>O4$XgpdAe|47-a_g=J!OT^Mg}S=C zL2z71-9sRc)9ZE+SK4ooB8Prc!hpVDtN|3$=E1C;NKSvifD3Ds}9 zQ^qcK3Qn<;`eG5M<4n^%7biQ@9IwcstQySvvLo$Ge-+O0kaBn&Yve;oB$M$)&z)L4 zn|`JLja^V=Ge|4*>__)7<=4Fk@=Fjbm({&s*JC~9vSZ=Kr-}dX_PxhE_wJ(9_VzvG zn`Ecxo|4bGM`aq@)BVy8?XUw(Y%ZKv6ksv|b6tQ53=-?(@MdCp0j6zL>hJ*5#Q+h` znXE(LvgTaB027dE_W~2>3`*^ddmcKp+;QFygXT} zpMtPFPGUCty$0}@5x}L7ive7Cj}NsnPr@DrwwXrx0WMI}_lcoMA_4FKgK;uv`@CFW zKo2!e=WNgjeB}D$nE{Q4qM9XxadMeja0WADCqFZu9&7w4r2C#(RMWFqWFkQ|B?bwp zvpMesbl7Jy#(mM^C_6u|l+`Wc_CH=YJq zH}XB-?n{hfqhvOo_5xR2<7Csm+{A3-(tX9XTo!5-$%PwgY~zvL`60IPDo7= z)vUjr^G-m|y}h{SvZA+5sjmys^>tCxHSkO8o%GM&6*P#!@R54VJ=+az#+W+ZxZWu> z*yOqfU2G=v`i?g!U?xcg^Xr;2yBn82-s6q)MfCbd{g#$VZgGrX9}ak@)Ijy++FL;5 z5QBklz}Cyr3f;HjXBYX8PpF#`FTqcRB{_Qyg!S&;oKLGk`YK|%NU36l&n_yhg7(4% z*H*5%7gg}9xEaufs316r(rT!{wg{qdPqe*| z7*vQ>`s||8Y8bXk&Ye&<2>_!!2{_|S1qpL;q9SuA*lbl~z5?+X~(dZuR)URQ<~!?Ebt>e>LE3g$4w88xWmr*kR0P7d6b{ z6+P=cg@##_z5W>@&O*F^SNjtl4KRJ(P?UPnz6VYx1>>t$S+K;vxtX#MTsuUghW3dRRO?ghCU!dfq!J;Nm-zkPY`LXEh-SGaz{eraK)wM?^5XN;o4*9Mtw${fMXW1UP>e=V~5 z_%XXv8*2SbVo?0dne+>1`#K(h2$9Rrq?_z#BHP!;K?AG}W$Pp!`*A-T)$ubMI=F@1 zekP0jFl7xgav<`~o@%=G}_ne0F4{YJlN*m!PC&1g#DHZnr6RGiHzfRX* zkD9LMki3RYYGN>aq^^vgiHMDHC$PSr@d!uD_Y1|?VuaYwon>}6F1>PoWSjPHWp`h2*8j@Uo;JMabl=jf1L;l$dyiL#2~G^E;MlBD zFV6$xX0M3gVO}8%e!oWJ5d40x#<5wWUVbvHa)O7sdkhtw;DCxEI5un4zf)nTD5F0= z&FzQxhe3rHRH$IHMuRN4avBeF&KN4XkrPnik<;m%*sRgeP+^VRCLv(#v-g@cu7e6R zu0Vxt`6(3^Jj|tHjO#QGj4K+igT{BNu;62MmKyNI;s$&=q~X&b=YZgg#SPfX+VEwN zo9M%aBgp~Uy_`)Y`&0dpowg>>TjH1(vGTK=t7DJ8$aE*0=(gL0GZ`CBAmVbHzCg

F;Y!x(>qqz~$xz&JfV>IvHzJLQ{x;G| zOZ5seVA8__m|c0RDO)f*Q@iagCtN57=u5EN!GVZB8p!-QuC*%Yn~lsH7-wuwM>;=IU#>wM3hKhiI_K8ed6Z$)YDH(QMJsAk5mQNdmL zN$ek~8~ZR>(7{~Py!=|6r+_bMKs*X_zY_Pb0R?l88H|?Cw(=} zWZBuu$cw!@N3*$1HZ`+9Ju{o`PY>m5wnw z5m+}Bl8`%eQU1S)MO#H;P^(zsMfuVy7#4ov3jPV22(VjF!9RK1u(FHtrPVJiO2Zh{ z)ejg|>R0JS`O<0_7S8!%7(|Idg=nQ04P z#fG@~bO1&3DFChLqI_x93yUCe|I@V{`k&Hv6yBIkOd8idzf(%F1g*D&>Q8}eWC=pB;`LYK@lwo@vmns1nqh(%jAQY@ zQ*0GrKq({WQ5uLs)^5z*Lj(tdDtMVekJ1DWF&?Dgmj`Q{1;5;@@dT2kuica;c$ihd zP|*mES0)Ta@G^rQr3oH3+5a>IDh4sAP$@I$QJUZ(bGU@c$sthTm$97AS!U3qG{M8> zXV$n5D$uwBl`?}Kr3oH3^D@RY8fT0v8ZR^GQJUa^b1I<&(;NjeD6&m|G@b$SIgpD% zt^~mbzQ$WX?gF`o)^65jGAHuVO;O}yCn~9j2YZSQ$bZQ6pm#QXkbbK_jfk^$V<1+* z3qgW%n!6RHXk2#$bxx-36C;otY4kt$=5c8K$4LEy-{BWu+--@3>7&azXu z=gsHbLzyIfnP<;PTcLLhQ6ng&ei&o`5(t|O1j8P+EHYP_nYV<@YX4+p-a{^SLH%ANxhW^IiF{-S!sm69r z&OpwIhy|GtL?<{HRKa1UHGZ(df`^%DEI5HSNaHN{ZeESUOlw?NVZp=9G=_>sa05_L z1c#Z{*j-`4L(DXjMo>LeFvKbt=NWHBg#`~Y(-{FvB`#8b_zzp`V&e5J=ZF z31oYaT|o9M3Vnnhhl0?@JT>&uv_BQs_&Sk*(1+m)eaz#~$8p45kKHK+^9~pv&(Ozz za4?GBVH?+C?5MK3VDYz^ah|Q&w2kNG;tM_pf?_^7?=3Td3&cRFBMkQKHH|$n@~6O z+~NbkSl8IN8!26Xp5!%jQWJyWBlVbjwj0=tF%0qUQ)yhMM8qz|y-{FY?yz8M&~NX_ zOoA0L8>3}*H>8?Z67uI0Qe_ zt8s)D$~bDZG{Hkc3lb_i!2uOTaD*1hIBK;t!4>!vLFKwIs1Sn+6@(VbIBK;t!9zj| z5-Pfp6Hwui)9IWDEtGN8YH5Opgcf3~aUE2kaRn*}EtGN8YH5Opgcc;mbs7i86^+Ar zFXO1y(gYuKXrbv^5~t~AkUK%X4T2Y?njQuDG01acKI)+9H@sY8?V@P<4YFfV$yxV_ zy+$gz%^I!aSoiRz?y>GMr=4QXuc5rxn0UCp#&f#&ot>H1giP$#J3E-i$K#!yCM^Dt zp%`#-yvqW<5RB)5oDPEB7)@Dcxy0@nu}er1r`nY|uPAks=bkt9BYTl5L6xSGVwB&x z+;@#rQ8HaO6|Nt-7g5TzU33-|D!e|(_E3gmZXWBXgQoS!>SK)K`!BjzZ({gdiPu?L zLh9gb=iw2GvqU%9SwgnLF}l0bPY7U@WmB>?6t4r1z0l9lazW)?Zeh3E!6M&5S%a)C zh0yg8b2~XrOhQyrPS-KwgJ`1cL!@Pmc(lG=pVm3Zo=77VcSI${#o)I))mGTw) z*i}%+X+(k=hZqd(ifG=ID}?SF31{hD5=1LFF{pw^!dYU$FV|=sf?w{{cqE)9hKf#b zKt&Ne63)`&VNf9k6)KT%mKZ9!@g7j&k<;m%k#Lq+<2tB7;|f$F;Vd!6bs7i86^%#B zS!$kxq2q%f2ZI~}vJB)X5UhYU59CFCW^FE&-H^=FJ69Oky(b;W<+cV4Quv2FBOb4* z8CF^I9ziE_rR-g1F>u-`=6o3CVMc3~YbI0zb3M%FpVw=$XJ%rz zye5|O6uj6-e;JV2*dE3CMH3Zkku7>_FM9K?kiiJ|nwn>TaViLG^=1qhP4D`7O$ZEJ zV5uec#iG<*o_pSu*K4AZkl(pHUeg6AnXbDESG2t*KdXET+U_wlWkBSX7!jrMG-s_UeixQpb{en6)I8inj};-BPT-OmeulpFVVrVcqL9?aw2<$7lMN*Jt_{ zO1Ybe<1@vpsY!og<%}OulzP#=2Tmsi&gZD877TJN_7V-3=Xa>KJuee`fX|c{@h+-a z&;+UVn(m-to6jGE*MwEPX1u-CjCYZnF9A8v&uhYo6W3amkA0;mb+6~1H|6!3s3hcf zE|1rQeYCjlEnE@zntZHs^7r&!6EP@W(@ataXX7(}6|aeIve$%c<(~697O&|GeioOr z*3=?DZ0`1&SmXytydbj+B0oToYT1#|vGu*CmK}?|rfpbinEg6kV>v!jx~5)Cpw&o? zZtf#>WxS^EL7Lm)HAz$idQBtLABov09GY+8cFa;S+AFu#)N(-3q;Roc9}e=GXloCD z!XOY*#9-V2NPWcazLD^n=7$I#Ck9pUNO(;w_c zVdz)^vKnM9$O#}>kdr}9r+5DPQyVgaqgZMR@STpfjCtUX*PB{C=kc9dK8Lb8iMV{H zDb%pPwQ|PKEK1pDX~)6oq`--jwOcM`VwV6ezmv7?*_qe_d?yrC6EsQcJg1hAAnT6d zo>R*KV8pA8Eqj7sovLMfKhNpARE@i>O2xijl={Bso;T(7oTwz^cP@|TbT>+->-&W( z+Mbi2W&UTvn)BM2&&wyoV7$uevR-MbB6Y}YFzY&~5nLZ6qMM>aG8nH)ldoh`ZY-YD zWqwwdb6{%AjV!XubBecw)D#T-f?SK-wK?u$)ARMa^jdBz@|?C&soTSJO$_6vYi{W# zJkil{+Kc-S?HSni7MA)RU~G3Fy9scUZT1sS}9c>Lvv+jGM0gy080P;sg)eV|A72Pdwk2=MHBC~EVag=lJJ1t93@@vhQ6Saniyor(ku0tgM)61(s#UZZI4gv0ckj7 znPJ|*kYz^D!7Sh{)6V76D;KhCogCzio#oeu145RGnNY_KM1s06F>pAibvwKJMj>RG zxFSq&Vo(K-Lda4It_kOWfx|g2jYlD5DWReh98f_V$|ZOdLY9eR!=OS8DpaBnvXoHK zjhuiA0%$IcMHLimSG_F7;3L#60ah=A2aYf_N3R$+!0v=|A><5Bl+FKWcECo3N zyWZD|%iAE|x*ZitHe={(#jTSe zYy$|!=azqiyyX+HOwhSxPQWs;Q&GweQSv=+$`i0eN#Jp=i4It{ycT4J_yvWn*NR(S zgRb62%eK7iR{$FGGo{!uHI%`41Q39AQXJ__5QFgup7$D~3ju^k*fHmZ2~G^E;E}Ln zAUK~#8KiMyFwr|)8jpk>1E^>PCk9pUNZ2vmVNf9k6)KUiV;JMFlJpv=$cU5EIU`}m zK;v4d5Q7SpNZ2vJxHiUz;qX;&=bUIe#``J2*3Xc1t>=M!0R+1#TdxPX6$FQnwBDN+ zRm)SE5&8WzoF;16Ujm#ZjR@D509zmO8ZZx05iM^LDLP`6Lgb`B`6WQQ-#CSt{N^cQ zQ&)Z14zb?0lM~&OLB@n@N$X`u^GlFtL7s5z2>ZmL1ik8I{J}PkUelx=#y#6MpxPjB zoO1B>u=|ej2k=^#`ydiL$^8w$_{%`mFHyl=S&G2e3C*rxHhvj_*a@4D%1Iz-wku08 zFXGRm=FcFTzj*-$;~COdtK93%=0&By0qFm}9)whEFZ>kt4ZuVlvFNG@2DOS6{sv%a z6_iI|*!$BNp>r6|)N0fNxPos$6aH<;6~yOJU2Ry|Zvd87zmT)uBt|v$V~i^GtMoSj zORJ#*TeSt_ye~o53$dL+>4la424HD5w8wJ5u=pE*5~DBTmIk9QdNEqTZvd87Ir}9I z$X{GJ*?c;HqWKhnR`eTyrB$zr@fbM1$o{8kJMMo<+g0=%fTdM$%%|10!b)lV9SE$a z*1r>(WP-qEpVS62qv#-fetU>bG@f@c7*F#ml=3z0&z1>~)SM*J`ZFR$CYtpDKyV#E zq=oILCz+Lt#S9GZb6i%D@PG$PvHz@ZK({=ItYrT|62%CC9d&srM#u*!gYNWzI5F_2 z;9DNFRS<<32ZDWi!HGc?JPI)m7Tkm{6)+rw!Gw$L(s&eN96$mIrV*SNRKcSVbFM<6w?(fCBiIJ}>f znY0fL9g`M-VCVOwkAkcOSp(7sa$;Ug;+Jysncn>RRPP9_*4QT+72+MVB2ah%%eGFC zHSd{BC*|q4mLCvtE!gy;ZF#bwobk7cQXjJKfzwIdT*SGv&53&sC-UvgJ~%Jo_<#Q| z&igW1+z(S-C|-eI;-}I@k&O7M?mHZ-c$zvB#VkxrZ+_qZoAfCt;8c)Lf^4>>+eo?O zRtD7gB1*N|_kQ8I_W-5l+xL)fPdkNs-h9qIlsTVjafO58U4XxdY@zpNJ9b)rlBQhSuylcv7*y;+|X2+ycZCrz`eX_Z=r%ggm;4QS4t- zv9U&sz#Qp_(G?{aYj_Px8&2W(q@JOMn{*ks2uF-4*(zUwpTUrL{`u!eMq~_)R{n(1 zu@FDwTb;t-KE>adDb3Co767;?nR10m;=7=5os&%r>}0zHhq2Zw-y^7;;34rHDY(wP zgy3*5U4p|{YyC58q;i6X1a2f$G=ei!6v1Jvwf?ihf-B<`Kg|u5`Y@;vg9;TGYm;Q8 zpmG`y3A0G3=v;L`1+KaaD(u`gRaoO;Ar#iQ1}c0&y8;y$Ym=m}T{(@11V<#sH5zA( zD;kHfHp%tHmoa`0wY1@I%wdm7*Fv0|L9hX65)SE~bU(6ZV*d1+Vb1$Bo3*auc&MG%<~gXV{~(W86zEAecNO zrA((AFw{IkB)}7o5d*J%H?6nz0ON4Nzj^bwFu{pI6+8;Dj~E2kt$l-m*S=jEk3#GN zNYD#T465K!h<(Jq5e5}vP@xiq*at&J=ZS-XV;?T4L?QOU8rNc+G_FD=3b7ByxK`sB z4qwIa>kNmOPABr4H{Sgnlm0J>GwE%RcZp2Km^T>*HBFud@;;FF(}`U@bRd~MhuXV4 zZ zr!1dub`pd9`0F@)vy;6+Wq|>YR!n&OY`ubunT#e&O9tGv-(5xb$&(6)ErwHO9|MvF18a zbBf^wT64r;JdM`tVcB8T0*++_M*=1G?-~{yAY1Vgc5H-x)Cx`vs^Db?M@kbsBsd}k zCrAcr9D?J_5SPZw433m0cvx_Rp`sHUP*DUgGdNP3;L6C#z;OjfV#kC*g&0(*lo=c; zO>lbv1R8=c{sL~H%N1{>2bPQ%yih4KI8vJ6A;A%;aUE2kaRn-621iO0JS;fE7}seW z7*{k7Yp#soNNIwPIXE);DBz(NWB?=sauNs@VkVyrazRmWWFK^zu;57JNgl(lkxTs; zWh^r6@oWjxsfjo3jMaFCe~$%&fdj0XmT@hh2XK}V94QSyA!`k> zkB0~j232rOr)7K)xHQ4Trc)OD(qN6V;QW0`N8@D%M@kbsWIB~l(Fo2^Q3NkDI8vJ6 zVbdx1JPpQU#Gpc@%-~3Af`?6~3>DiA^qEe9aSQ{l&RJ$~q%^_9rc>6q1}dy^1uA6* zM@kbsWIB}?*JzwEu4uf>;7DnL2TrFnkYJLduQ~|<&`!P{1TVTw#)~eK?*(}fz=?dHu{m+io6o+- zWu8ZkP~Lu!Cbkw9v9+*}pXZ9!n0Qqk29%u7i=#DQFfi3OE#kcYkp;x9R&tDKQBjOZ zN^N)00I9iyPN3A`F{Xv2*EZ_2o7-TMG=p`sHUP*DVrL*u1yz$s1R zAx5$JP#9E*L4`^bVoVY$(?Xzvg&vdWt!Gm+hmymtWB10gp^HV4kE7!0aeh`P31a z1ltC=B)9R*mAZvW)#>6EYT7n=B9Uc0xAA#NLJBpuExK)^{B(Ay{m(Hr;k3zv3B%7Z z2D5rF;h3djNycS0&{Zqv9OE|med8iUKOds#=UFZbbXf~@&ok)I2og8|8r`&k_Ph&d z;3}tWf*|!)2&6vi3n{Z(UsIEZt8+Q;xI@Z)wyrsw1TmLFfwD~)vFZZzhj5$th}m4~ zQf7I*cAUV)#khMt|A6jOIEWyz9+d`=5OxH7&fem}_ z&y>vOLYInww<}%Q#yA#yIS6kr`{B(weYfp8wbsT15I;#IUV8m zlp##G&Q`^T5`=jil%p_$Jvw2*Z%4A8#X9)YUS}Q2)wtzX;c*(DY0?t-7 z?t?mxAQIF##9$tQ=iOyDPF1B34Qca5AB0rw3H(%89k!#0ET(Ib+jxaov{fVqwTcx! zG^Df&hWNCyf*V^mi^U{tAJr4J1$t%eG0iy-=w zFo+U^3eid*8d6#fLspn1MsPT zT9uq5bZv+Jr?g!~4-F};dVwoiWCS2$P0?|=qSf|YjFFFkJO%O`$ZtSi2YCzR-+5uC z`_X~PUpEBDwHuM&JBHEyDK#7pucMm=Cz1V|L|jW*WD6R9vT~YfHD%g+6JRyEQsDeM z3T^Kgr%R+Erik%{(@v8j1*5b8c zr^wg1W!1-KdXJyfCi@#2sli}QwA2A>ST2|1HmH0G$W9=$h_qejEM(cEGn?z&H?dBN zk4c-}RHxlh7SKI!s)u{)hpB}Vl$Q*D_^Ecp>XxMm$%Av7aZ8O`I`He zmC`q@GmP6VgRYAErn!Xbsr5vOLGeTnCUtxh*%qSvV-dUU2G%FK0o@c|kPH>|K7Z%u z+c;2}vVbLWk3#p8WacI!LB=sLn21D9If(OC*88N$yD&$gKt5|q#^?OJ&;3c6#B7e1 z2`8>g<-E@+T>)@3e(TplLEh(gpbnkkL=0>=O*zbN91Os1_j9t8VYM`y!Jc?YK>Ei| zbNiJ4q93(_6N4%^)<4^RSYg4#d_@+V;zWVn0fL{2?%-$~>z{2;S6J{cC-6JaxK40l zPzA^OXPb=K&OnvN63a)HlEM#)El~uO=OMTblaCKAn>ks)q_Os8GTBXWQQ@tnn~M>pKu!r*UFXHIDVqDYDnk zfHo?E@iDtlQ;vi<9|u_nG7Pc-WHZQFAm`H?lf%iO6qN0CqIP2a+kqf3U*>h9V9!j! zZZnq?brdPZhJ^Wlic*uUQcZ9=DR5#HbjmeMJX{SvPLw?*6T9U^LF41`L60eiL572h zohY`rY)JSx9>m~hzHB|mBT(vv&`p551gYV8C`Q+WN-d3IjnrV6aH&Jxr72y|>-8X5 z7oLKHK&CA4bC+OWo@&9~xTh%PI7o;-cvD_?iAq9#E(5&X9(Ud`_cO*_?$RUN`fhiLW9=7{ctP$G zVtp3_Qjc=p%DPMcLvolGz+KvhpT;wspS!dVDU+DZ3nJ<+Jr(3Gz2etGLGIGGppLVN z1T_vZm}jGLp0yhX1Mq~qOMeX$oETKWBjGNw;MZt04#C-ea5NqXcZs2*6C6-c1doKf z^lTVZh(U!)B-|y2if-ftRCwfcpb`mpi8Zc+3N)@jB@*ruV_c_kU|i97#M~vUE=_q2 zFOg8QwJJ^_Om@(Xau z1tIdS%oJVIt(@lNMXBBGd*F0Z;CvsRu{RSB*ZX|@C3{XL_Hp-@o~1&kJX-88vB_m) z!pC1C20!~{D|#M5QZGas2KY;mn*AlO)it3~ORHETH5evb>TrJvYrRvkTYKsOAO{0k zkNEjZFfir5S1d1mqbTKgNJr57E%U{9@J>E+rhKl-2ulZTyj=wbZ2p;s@{t}1mH2bp+gzVsl zPd$qBR@Pto9_h)v5&qJl{Io!S=}=N8F`G9=(_fnU@gRTcRlgPr@|P&eM3xJYAb$yA zC|EXAbfp zL!e?1g9?=>_)8Khnvs*C!Xu~CIbjvIP4w~-Yg`8vXk39xB>W}DxJKiQaYf_N@|So+ z*Hp|6Q%?i=EXai*mxFu>$IR-AhbU|J&;_{Wl6p6LGmr zIcm|ptehqy<=&KikcA0OCk4*=DDPWL>=M8=-^XRLr)6RvZULmfjk8A7|0QR zF4Om@I=5S}H@;q!a-1Z@8oVj5%S0t1KbHaCl*eVd9VMfL!WC_oiSSGsYrDwL$Tg^r zzbV1UHD?K`^I{?aMlKl4#dzLj+z^p5a&HV1oETKWBVpvS;OA&G4#CgyYCH-?u7rwC za6m;7JPJmxxh@PU#GpbY5=JgVWgrA9174^^!N`>w*FgmuSD;dhdQ9*hDv5EO#({A~ z;}dPI1Rg%rnQ0WNJj1=I#{hUnM+|*CnJ~MMWMMv z>`d1Ia>m6A8u*6{vph!bv|039+toyh4v(P2$EgH)@;p5x)t~Q8=JQ!*^_#DN?U*&g zBSC^NDLh$jK|i<1?34(b3|9Y`HyF&xkn>zF-in-UJp-<7Ta`M%fO8!*aS`ct8rE^9 z?E?*e*0J5}U7>g#$&^Q%W7P;L`Pz$b%6P%H#|S^njU0S=?)0D>c^NOb-i~XwiI|c0^~T56bN1jpN6?{8b1F! z?aZQM!Ptyr%Z?`xEDBBYwlQrD*<9bQDPzC#$B@&BE9 z5$l|LIQ`j%9BtV7E2)RSVEy(Xcq+5nM(g}RV^|q`l zDRq^d`Y+GDGb!~Q`yTS$ZKrV0o6ot2GQUH$DD4P(`=kT56^8x8Ookl~ESv@j9ahN; zVJ2gMDmxwrXa;!y{=PJ<99{?7R;3OPGr@A3hJ$LR3ut&SAk1XgON79#ae|GP;?(YL zOb3UV80jaVEV_0N4Ko?D4MM}%!c4~O2#1;eQi@4@5Y^e3MI^{1CI({`TCbT~Br+y3 zHL6~4w7MdABuru!{39BTL-3DyHJ+g4gqy?+6`kOKiXwO0 zUIDvPjyMXKof~{xMKLmoq-=`l2 zvZ5%=#Bl;`n2GXL-{!H3t6_3a$5Lcqj0u_UBGNVpf`cF`6kICp^m!||#HY`<4F?66 z=(IhU1i~aL=X*r70ydiSqO*8O(^)agz62HUmPBFAq-8AFh`mZOGA&aIviStFZ^W-U z!NH&ij+wNK1)I_Y4+}0qE@KZ!9}tBn24fGe#xawYv0zi0;9Dw%UrN2P4F=Vmvk71>#AV9%mtg$ z1P==?F~)To2gVhRVQx#Kbhq z=ct-^mDqfPNbDStQ;Ec(@)+Fl_{AV+5lPGhnM|bqT979}ZYR=^0_h~uv>t>%qM4_^ zT3#d4x*h&{n@IDnAXr#xhG@;_6KR2Y*RmtXO&|{vnFO7+p!n9G5J?~?TGfKTAY>JS zc~z$nsljBqnNKi743=S>mo z5mhTv0|YV3EiUa5^+{&Rb!Pf8+=)bwNF=kVB*P%V>&{bnR2SIxVNNDsm`jO>Nz5UU zLnFL}9EvOR{*XzM+4HR$lt0UrZEUAO`_FG2_4ad6tZ~5sa$(aSKlpTrZvQ1sZ2Tr| zR{Ry0!xwshJ0sOgw9#ePiwjYIm1EV1TJ4|EL zo;`(9=6Fk)L#23!-vtcNlStlO{pIxx%=3Obyf$86|GX4+4~?jvY#j?fHRHnlzB`F} z&uY;yk|a5oC$kvuSBvTq`PUjzlj$2Bp=P9EdZ#sZ1qLzH=H@J?R;Cu^fp-C^X(#L1 z>oVD)WUhS){#%tz)BHF(n9RQY+6yPH{$||*QIMC2k|niTOtJr74t#W_^2x#V^m{$G!z$_kgPCs8n9Yn1 z)0EwpUrB|nrqADHhSp}2JtB^-loxy1qI-n{qF6ZYa{SkV9x@Cv*_B)X^jh5`Cfh=E zX0inl3b$JATZ@PLJ8?)&QJ$4~vM}7Ys`4y082OX()yD=l6q^8>w*2MMSO4;_mnCjB zdS>n?uQ87M+_j(oF}Udw(_f{+x3k)&fVVE&Ji6}K?J}QzeLi);mTpnKs(bmeuEnbh ze|0ZCgxUqatz5jSqtIyGqK;9TSxHSnj8yW5bmnOLuVcDJeU5JRB(npfS!&}Jq=4aM z7d3D?Pd~NVKP}FEVl7kLqRIV#^GFfiartv&A9nD7F`IP*yUt$e?N_|s4 z)jgCPAUK+97GcmB8aSLxG}a|0Q82X;w*ik0tyKG|O6?2A;9uwc_Ujki^~>Lz^bAo& z<0y&SEgIw>5?Ry*7G<*isjR#CToMt$AZ1?cW&=!WcuwINjH|-maIK0E5JX;rh;q#pP!thRK~VWnzwR(mooT{$A`Bjm~WyNm2nW20(Gmz}dWZRR&nRF)C{*jSnwlBFX*_Tab z7G{@Bcx0cOZrFLj&rMO)BVsF){dqC5=fvdt`CHO zVf2W2UoxNMzmF9)ed%O>HaVEg3-j28J)&xTDw|7Y3Y<+c)m7l(UpEftMPmQt-aa4d78ku2H*GkS%&_GM?Kr)w0<+?J~Gb#76 zE+uy2{(_BJ(dupwi&=Q?k-sfcv1Z0z{4qF52okV$wsfpC}?6P#x)rXQ$`+7mL_RA*)&ll4f# zzd(}o&7@u=`57*_E=AU|+xgoH=*``q}#Z z=URVP%bwIxxK&6l^d>twNxeguwRC+@2oa;JSqOvwJLJ#wAN`}Tp$VP5o!Y&f+x@Ql zKbJk=)Q9#oh1o5PjdX27F|k1^W`x)$F*`ueZi8Us=}%6(Y)kU1F=0@L%B4?EA&WR_ zLmZSc?dqzsHU4zFn)JYnpLq5sTQ6M9J+d)5kRDo_M3ZJ#uk99|^!grA%_C5X8{}h3teLV5!xQ1>La#r*=Z&U^3UvsH%D3jTQfTX#S7P%70&{WLkSET5yEIF#v2_fr4N zt<7v$n(c=u$BL?DKpJ(b9gelJ!aupOoLHIKn70Q|POxNoLK%&iJ=_z!xF-O2T`6WE z=+tG_P zPI}YB$$`9Rvo#>qFFQ3=qbZO2caZwfmAUsB)LLy;Yq2tHh5hBmi*KKjJL4Er)UOhg zJ23nwJ5C(Q}>EJ;IWs;@^(9?oW{j;X#RNy}9jqTHxG zjYakVVh?uQlsukN1zW5N+I17v8=qP6hXY#(izIJva%f?yiv*x2k-U`T$C8AUF`pfw zS#y z$uT1K4y37H61?+d6_5m?)fvm}U#ab?d$VbP68UIkt?C`g<}ft2IP9JL6Y(|{MD24w ziKhzWCUeA@9SUO94p76ShRDFc4{cOFb=!Q3%5U=>UFjh_EP2H3O4AUNBWNwyIBZ~8 z6yg%P68Hne*v~UMvT(+=Q_g6bLfepz`g%QbZ%aJKKER8FwY9Co^kUQ=k2EFsf;BI%^vGaet_6bwO$oxxli6na# zh9h;$^bm~>Rv{>AN&)&+B)Idh3b*#<8qJ_zanokNt)2PSO!~P2$vs@^Eg%Cw??v~$ z?SWtS*$BFCp#ktWaLOvB|3!?;Lh}{={hR)If8*5b_XHQ7zWAQT#d}Zz2;S?QJV5+^ zGpcN)fpRehOM`|)3XwQIg`99~Gjc)O-t(XQ%x8W)K}Jq!rUG2p{yz|Zu}|5Jzy1T{ z7!VHcr1LbtA(g|-$^SS-&-@Tw>@Uz1J+-rA(c)S2J7?{GzyY&9u!#QaoHcjhtOL5p z&w2l%`5&A$?}M{CI~R7$>YO*LYcc+x)wzhK$!V4g=Ly^_8p@|(K7aN2XZHO2vp;(W zLQ^Qqno@_esg9vdmS@+#ESs`2d~Cx>|2tBB_pubp>LvqbY1g9FGE%d=TQo~Yu4^fr zHw1gUp&zoFIdak=?T$>2tkdF9PmgF$S`15jDK;Q2BRD6!SmG6Ce4gr;r(i9Q3?#E> zv@|YjIc>%>s0%dMQkcXJBJX+@n(!4^6fSGUG6unnnV1*_wKp@rB2A8xXJOK~%Zs;d zsY!QF*ki^=fBT)7Fc*uuflRV*ak7_UeH41iug#{&e;w%CIDE*VBmr!k8lv@d#bD>y zMj%YScKD&T>9%g;SI=vFsgZnpG~aCIgk#rkbM$qtO=js)sVqfRvPpX6?)JUYcggSh z=trg;XL1FG(!Xk^1W*WQ;pAw87pTfHu|i9~H- z0T9z{?0)+v#V2kRD-~@+4@p!*|5U;F?tSteY>MR{y2v&Xs-VQ1K}q zWKJhJHc$v|ZJx@OCN`J7nDm!__SGL>^*i`?Kl$8)zcNMjD$&@TTbUVNnq8R5=Q9-gt0Mm_n;C(h zM-G_Vd^A&oP*y8BR9t8mdDU+BTRv$vKY|QvPjsx6#hv5WTpUvpFOkf`-&kaZm#8K? z`}XdhbU)$~7o7g+oRd2D+bq#B!>V*~=PvLc`sG*WeC68KQzRZJXxx_<@3R94-fXjJ zOaMokf(Ja3AoRL}^$1zp_7#ZTah0#Wr~myw|Ks0oF-0xHsRWLJbU!JRLIia=>cJfZ zf;@S9eu-2XYl6g32jKJu7SeTzlo z3Fu#|X()pDi$%5lSAF5Hg%oBchg!x+fR_XXbY*H8b<-{xc_mN25ZQJj#>a|@!*FnN zF21AT=63tt;o0SKhSlT(tgbDDDn&O&!3o?eq=`$09nCuY14cn&6cY-}-L6qE)L%t? zg1i#fG9Xu2N73izDQo z7YEoqOco@=k3|I)0`#&YP+zU?OOsEXqylD-vVbm`VF5$ln)s=m%tZjkA|PwJ)7vDxSen#u*^{fSk!}X9=3(kUWQz=N?MWcTHJEC70E(*K_dh1UFA0#pn#%y1%70~>=*{8+*RxckFJVfP^ws+7yE=) zkwVTi?Nq#i#%L;dBx)JZhN$3?-Zo6oOs=h9j@C4{QT@!2`f=Oo>IVj;e(}86H?)4+ z45A8biy*ojji-Ys7!-)sgw`;Xr?5S_PFT;WbSI35v>|sw-J}c#o|K(&ramwB)VATa z0%#(na@>46fPz5*Xl-8Xt*zW3#q#^MN!wM0RF8qFYdbI~ZC4joy=^x?RC}xE1aL^| z5sZo_(H|U~xd*8SKpq2m2IM)AKY+Xr@_)$0PWO?O*T$>z(m;1D2>)@{uO4;APt1+H zFxu3?K0+482rZDV5)%qPEXvWE3vCEmCE7aCMUz=}FAgI>pA1iiRz_RhH)th?mQ?xY zp7bCUmF=LF_O8@2a-7Jspr8R+jEC{&lx|T&e}4=cP-q2_wpV0RP5&NOq@DfpLLuLL@~GecVcO=8 zNN1i*WoE|XzeS-gs~on>NHO#?&E;l_p5aZcuv_s8b*hm9KA)?{zg<5d^m51#Y|5)EtYnZTS zU9*eI?BUWeGAt-cNtevJ=S}^Qw=s4v`R`Bcx&GzbueA%Of~Z&&=3JN!3`}MTJfd)2 zN&n;eBlo;I>OY89c#tw`pO7Ic!;ro{-KJ7Hv0-&$j>`G~pO-0gK|?US#5MV1A%5~H zQU_hs{~7h>4Az`U+ZW%83N7h*7$2ElP(zZMD#F&qwc z^nwI54j6jTI7ixz!<_eVQcgXi8-K?(aBv!A)(H*tXk39xEd+nF!h(l+(~NPQ#=)Ryybgl@ ztHOeh+D|sHO~FWmoCE^>FN%-&TQ0&kdFxCe?LTPV>~F)F%5LIGq$Yu`$-Tk%@;Z3kyW?4)?X5gT_g;3z(d@s;nqM6YI^Mz$9lS{9lzx1o1Nny5M3kCU0yi{@yRWqn@z`!%@3wGl~ z!e6=vGV25fgCck&{3RCrKOucUcL2kGqB}SmkA%O(P|*nv21W2l_)8Z;**d6zL4isn z{3V8pZsY_5kDLxvBH=Hw#&u8ug94RW%xB~6FEPe-8V7@-@re0LuVLtT3*=u!Objw+ z6A1hZ6VY*VPg*P*9$7=L+O3r@+IfAZ19+r&`%LC+w!SQ%$(&847{3Q`d?ubNt(@k6 zlb$a0q?|}OIGq$YFNIWigVg+hod;Z(`uI%tyo|?>wa@ed3VpiRXOdDBxYNGHfgq2{Oje5N4)-G)6PN#4{0o_pSu z*Jq-Vu$1jw+-t2hrb|&WT@Mtli2F=Fc*fBKTAv9FUZ06#8761D0VcoVGa=A1p}=rM znP&cIe5QGR7P;dynV;YmcKb}5NHTE)NPv+Dh8uvZHJdR2nGW)q=K8fzkk2#%b$kURpmD%}HGWgRJ%q`CImdgA>1oKU6C4bR z;F0i|SnxX`eSpTnaHm(}k?@&DAhS+zFerjY!e_b`g6p6H1_dgS@R=AYx{(tMJaRgn zGZH=%Yg`8vFep%ogwMnn*J&IKipHbmGnrVrGtU4y7vv(4D?qLWxe4TsJRKU7%F*E` z!+F{$i zwp*z~SDMT;^!j6vCqS?(+Wdr{*Yrthpqp&i=ZaE~d+vEtUayHtGAX}vdAz2ZP%>SQ z7p`b~O@7EYk0jT6OdP4zf4M9FPx!97=~g4=4Lmt9vseLwStrUZ-gx5A_XHRsM%8-5#eY z){WnIqn_h5@nmV`G+(Ez-}a=O7&$nd6gclic{l_q_8)d0aNP@&MA@Eqj5RUimcP@K z7cqJ*E@*;Oc3#02uwREV-=R{?KNWjT((nQ&hHW3Oi48B#%rzJX|0781r$eNE`aP*j zU27tQgnLbIkzQjT134Zf1vS6w=QUyd=UyB47Zjy_;koBcdA%ko$)x z-ConxB$0RwB*07r1Kv@No#Gj9D&sX>4?!M=0+;gB0==fCq-`)iT&6O)^vZcnvCjle z3Lo%mp&+jbF9QlTasnC$3|PXCea>zi<{a;}roV>?4hBW=NO(;w__L5cK;vL|)~oSI zcufoyo#0?l1doK*^b;sshjB0{P>F=s#8Ada+^l70~pr5PLsVyj_OMPkmDJz z(}b{j>;hzToF<+td5$1=%Y2J6KI}<3#vVAG6gYp1@_x<4&I7KW`Z!JYyo|^DJ59J# z);mqH&q0P$ihU+nRgMkg<1>N5$A;NqbA%aB8kL&kN^_|4D$h#w>j@jO7dy_a#t;z%%eX2j!S5w z60Acdsa$cB>x6+1(>*Z{3S7jzffo59(l(gqm8ncFy>b?L+z7JB5A z7Wv1aY#mga)OssJoRKTD>B@!+ZV_c_kFen<2n9KBa4AwV*+y?R; zkne*$1o8yPFY=-(NuTY;G6sG6i@s@(vEA!9$z%RJj??pA$LV<#br~``D;Ydt@c zcASo)T;kIp0hS^dK248Kw0e4OWgMqf5ad+UWpe42bDR=^ z%i9P0wNQ}bv>er64-(KgU|5gFnPE51cJ{$6Ha~S$1cOq=?dpSBT*31-Z3qSo;jT8^ zo<5kx7}eDe3`+gBuMcLOg~roC6buSPx33RoF-CQh02p`@aK@SK=7U+>d^&)FK>_G? z^ua9df4a5~VTi=h^qb>7?Lso{49i%EZHUrjN&ITQzum8;IX| z;N^Loi5ZZgwbQHH4)r(_SS(MR z0rEKz9KxTN=;v|L8+3)Q&Qg~%5gwIGH&*H%yG!7nH|6y>@h%?mIG4xc#J&$)_Y|&Z zdz^lFzKSHL;28ar-*jNl=iijHzW+1>x8!9Kvmx26Zz<6o{7OH=dAfkrDvLlQ!S#V{ z6oL1)xCoc?^lrbQmbiiaQw44$jPYeZk0;J=Bq4I2xSoY|`J}OZxgtb(L`vMi46gcv z!N6dZxRGyJBU0iPSG`B~5uZZg2=`h0AG2bn?|1E&rv{Szjp{-Aiee`A6|*z;;3KD* z{AIqqtLUzd;9I-2^W6uox4q(Y+v+6Zu;o_AbkpV#QJ)6j=qMyi&eDy zYuG)RTym&?gg)$k@{0?m{_4Wcb4_6!E9zE^tXYR3H)f5b}dpyK>-&ObU z>(%speb_SbP?4Fjol4yirfXstGhK6QxrZVEd3~Y#9wbD35j6h_+J7VS`gUJp6dMc7 zuapT~E`6-KZ{bA;F5A^}cc3go&5U)H#m!M)_WjzrBFxE33-*$@#9eE9LrrUHnt{ z{Z^2G5f%)J;Mm8MklQSInyHB3As?5Nf^P{Ce2Z7(*vFKR2g_7WaFbiqjw5l(t#O8m zPH-?Ng0nYtc!i;&z^6#?6QOJ!RKTD>r3M;bSz*CLJ}xPtq8smlag3a<&WU|YiH}!U zaC_r2G+X>}$vA6V2Nf_VP{BT?gxuLuIgHB)LkPxo8VAM|jbk5ELVBl_6TF&R)E1nK zVX>Gl0ZSTTBYI_82!OU~8ps|Xh%Q&XALL+=MIcK+j?4=)-G>srdzWgw4*~1(9FwZU zlQ;>|mUl+y_y)RVA5|6qa#895t4!u}QsBhv;Z^-iJY0NmRh9ehxyEdoYuF^V4!{=7b z=X*T6`R!bqPu&g7%DGjemWoRs>(GqLRgyttC5}(>8lUs)!$Gc6FVyivkN}SZ3_k>< zuH*_u##Oo+GV25fgCck}M(go*m00j+A$@?x!GJS;TpEvrtJDjbb%KLI5j+yE(isq3 z2Nf_VP>F=AbTtImjhtZMk<;m%k#Ln*<2tB-L4isnT&3PHje|kac*I<#n=o|T0m3fb zkMP$|K%N5mACTYVMSLhZn8Jweb(VJFLEiSr!2F8WS$YM(T>~Or8RCs&Mc+Q8Dh^N6 zn{qq>a5^b);>fD1zcR6&&E@ftRf@Z0Pszk?xl2@p;x3hUWL4FbkRkB!CzlP3w_K{e z2y!mSXFy!XK-pmg4j9vGcn$g-uoc4PH-?Nf=9x9fn3JkkUl`; z#9-|0)p#V#7a&0^I5DV#$5D^*j`W@iW$T~<1_dgSFkcud*vF)U3Q*+goRKhJpinJT zh(U!)B+M7axK881xT5j#HeU?PWp<>u8sbz>1lbW}H;{cm=7AgpvM?{II!5wqGg*x3 z*kNPv-izI++4higD&EV(Kd>L}F<`0>r{5AU5vf{3`|adEPEqbSU7JPhr;i$Rj!>#E zzdD)EXZfbzY(>nz(LqsovWyNs6cmAVZLQl1nSKuPILL#}7EOCKCEi8VthFr$k~An4 zyC3xPP1H;(`5irw$NW7LAzx>$>KGzpVda#^vP@AkURWVSColpIL+CHqpRH6A{H z&ri?&xXHWg_OiCX74NR|7C@>Opl18h`iXpr|^*3-iOSlEqtDb?7lKRoXO#*1(bPldSfOprrDY4 zfT*>}-0Wo;+Jo1X>OqRwst3~j$-YbnHG;UHMIuz4BFr~&8nSygWt;3#(ZXB zGMD=3myOFly|jOxDPpU{gkGvoHkmytl_lX(p{87VaCjh<>q?!RqI&g+`VJO>_bBGY z99uA1`0T}*>|oL^e0LW!|G0qh*dk3OjtuVzH2#CyPRwMGOha0YYf%VUkO>qA^FJc6 z<;X7#O`;iBlwt!;q#WWeAORK$82&=7Sp5msOk`}pLm;zGa4;x>N5Te#Tn3iUf;3JH z1`p(p#v@?^0ts5di9r=S5;hbdOFvo*-G zM?F<@3J>^pI4ds_d(Yi(=zU&;5SwJGQ$&gkLgUn|XxGmAMH4fSj(?8xe_z;V3Pi;88a@31dVXNZzlw$Xq zmfd>~L?FAD{u9aq6(T&BmN2`=_C)nx0`Z^SnE~c}LcWz0mDxS^V3^=wPy~;{?9PH4 zyK6K~f*ZSgH6Df8ospmwoUo({9);OG#_z1_Fb)Oa65~3J1LKOuBR0F=N64+-0)k*iHNJsTjSWK8zX$mf$lvHK$E1w# ztX`AJti$By#Cdilz#ZY8+39`_8xd@>VOL)bg_KTB{D6qFP-WgrIsanijIC5thIF0D zUI3?)icy5bo6o4TOF{I+o39SDDm^tTnomrwPqrsFHT2m{-n%HK9xJLh%HOFJaXBS7xsn@)Nfa3rnn8cfqw5k1>a^4U ze|86U@JnnHUH9XE_Z@_L#GgrM2)-L$csE+9SWvo@({AwPFPdW_j=uKWI|d;+`Ak$cr3&UF*K%#5(k6|>v?pD@9}pa>oXvzrAssx=xX z!3{|2(s&fiZbpJuaKe%*cofWTlcq*J#=)RKB?@M@#Q58KsED_{P>F)s%^KH2g*2{0 zB?@M@91e9F$9Sn|JX&UV4HmU(x&>oBV=M=s7XV@I-=82Vw=V z#3mN2*kF7gIBkQm_`nmB7>duXFkawncm&>5a=q4pqUh8nFc?*3nhx#|p5J;JJ=VC& zZ|Zk!u^M?2mdi9Qh)m+~{9jyCDKgcj=6sK7JSGi?5)ch@qm8x;6w-*A~@Oij0=z_{0s&Fat?>87wj& zB~Ka})3Jab<~pK7d;x-t@`w&*-X4zV5Lcj9nn)ruc;7q2DIAdlG*t2H{1T(O`hA^pDfO%LdB~;JP%&Y-C%MkH5Z^+*b-fS_3PdY? z9&%|lw0A$ECO&P*olrLkfPp6g2cs1{54p6;*)NK4-GqPh=>Ur6Qvh1g^N>rcUdX8w zvj6GY?(4;ESJCs3ORHYs*%c%;++ll1bImU?M!o>@M-aU0RD=CDwJ=<2CxBqNWprm( z)b8f-wQI3Iy5>nD&MKF*FBnd=0wW%x%RbA3QxDkpV753ZaN_ie+I^UKxB^bEkk2A^ z>vb&lqc>wC2o+{v4X(V?D{3C4tTo>+a={CxDizLlU-6oaG*vk>SHQCSw%wXdpwv%? zNd5GCQY*WKpfF{Y!%y<-ObB+6t^-z@T+Rc=$lBQ;^Fa z%3ArBTjd0ICVWU(?0B)vI;em_feKbBYvotlDkpfDOLYsXqtiGT6pdq*vR3ZNs+{1X zc9v>~AkKOa>_e+P3*>x|OF+H`a$O0hSJZl!CTkJxsO=}>a+i3TY|QsDe4%KJ7Gy996roL(WPWMa46C1M?u(<^G%K!ziW-6d&p;VI~ZKJF427!qFd zW!t$+fl~iEL~86ARgA9pq*l#&=+JSONY|n6QY}7OTZ=7|wKzMb_F<3}e(n z;^v~%3wD>lJ#WhEE}f=n0k6c$k3;Bztwz~NYVZ~dUb@FUY>A5_p6sOliy55Y^o{2kwI&VoQw=! zUu1AHthD=?Xl#|8Vhncq`0aP|ksLocMo`W6Ds_PA=Gw=13$$X979DbI6Mic*d=%r zj5%XU7*xQZKqV5!9H1gJJNy9^-r?`kcod8|*0>fbq;VB0Q84D@aH!KbhC{ZGoZ)c1 zjXCeuj=GPc2QCL$1%e=4-H9Mskdr|^U3^dpTX1aD@$BJqPzh!9d#R$Xi*6Jdb^JDk z>!pesSOGQHGpjw1jOD2yHCL2kF?N%XZ#*A>jVdbA~?qR@m~02!F4AlfPqg;aA`aW3x5WXpcR}LRKYQoj`zYJ zeUCW=Dqv8cf~j=87ycwvG+sJGg?ppZIis-f#~Rl{g*2{0B?=3F65~3J1LKOuF_lJV z;jiw?Bu?FxAeg!8uuxZrg|)i-K(>H9POm5S%D6~6l?yl+WVH;Bpzq)x^8Laa9{C0R zR`Yct&KjV6XUxiJyhs`U>`oQdl^RHkaEf=c?_FNR={VDL&&A2kG~yNVsWntq@i`t+ z4v%Avd?<-zGA{Srsl~JDSNh-B4RvY(nZ!Kv=^m#1y5E322l70Ky$EBhrCfF_+&G>1 z|6$ka5zoClD7B+~5BcOeH?%?blzh%TD%04J?w59GhaF&IbK(4=0Fw!r>jF$*kXRps zHxtVXFm10=hXAo?n0oNVR)`33LXf_QO37rYSFS@U@@k4wnOdTwrv{WS!0FUYJBoEa3sVHJ<}$DCL$g8}ESaWEJN@4GY(t9ZP>dusp* zI>Eu93J$AyyuXHEHitn43<^|W6_58>c@pDqLi%8+h&R1ZfmJ---@Rpx>!1P#6)Lcb z$NRgtjB%mSI5Q|3hgBS%@7~t80uMWb><+RY$N?Z90zo*azNa|AG#4{dIRU2nCdwEd zU^wP})#Db%Y%>~(U_9by2RJK#_0sKey|`fR!QvAM z8gGb!?d1BTrxC|YY&=@o`+=XFh1mLJv31WI#eLyb>!HfUr5ptFV<&}eA036jA$xlAoMgPF0bpBYb&H69P?zGoNJ z^eh&cNI*w0h(SW?9L{Tv!J}@xFtPDyefK@5sQW@FVZ4T{{zeWqfrk+kFqhZQ>(l<7ZyriYuLL+LxP{ZA`kaxQfd{ ztzz7LC2-t5cPeW21d$+Q5QFgq7i0BYI+@1cY*$-7SA2yT&~tHY4SFuJU0tREoGu`) z3h23_a2%*fBFLwplFl20^|!D@MK%2%ap`LMJ@kRwIPW<0+}mVT{vVP0>JVLD9W`A8 zzqH;Nj1Xcle54+A&vpZwF{X|;u6IfeHo2}Oe2eMK>pR|{faxR^jK(X=>~388SdTZ3 z*HHh6-_kP4EspV4N*ZXF}d2XvS$~SRzEYO0U4vZ`T?U# z{VIKSQE4?)U|R%HxF_0PNDL}OD}8oRX*INW-0Co@n*@MSo&=n6rh;b|l~%csHw+AJ zJ{>^Odxxp(+xNifq`>(s z3Z2cw!}To8p~5p@dUq+r|fmq1m#0X$ZubsyHF#p?-#D8+$*hRnteKB6cxTE z$ZS*Q2w14XI+>>a8f5kHWA+4-&d($U#m}5hzi_s@@Q4Xiu*=V+o9t&I+g)Rz0oI0c z%n=@Yyq}Hg_?Zoz+`?{;jYZxVRh4U0JMOyb0zkZl(sYFJe4XKu$**b`!+S7*j+~cm_sDnoej4Q*8ssDwFZ3>DqT38?VM>2yvuiQP-Z zTeohtmWua+B03I5eFS=zQEun7O+qe8p2AS1aUE2kaRn;atkEDpm0LNDhq+XYah=A2 zaYf_UtkK{KT2=%qqjr|qiD}pjna%(?7vv%kY-MeLJJ@g&eb{g~*-yKdv#DfXst-Me zwkFV9;+PjP`7Ps4WRJecbf?#C!kLT>1IXyOO3902Qs^#Gncu z2{UGK7*vQsg-RsM7{>T(Bz;il1jcz|g9DXFm@&|}7AnM`LM0Mr3=fAojbk`eG(O&D zjQ50^21G9#IF|YX{(2eYb&$7-G@2k3%dTEd226U0&0pSX$`;IS)NcF92^Tvh@elm+ zr6eox+c=4StN#WOqk#-$`HxeSJ5HB8poUJtN%iGdC-Zr{O>H#zO;^OM`mk(|SZ@)@ zFyT2tHic^gC61P?=QYnS;IFeCb0TgV5NA@`*`JR#&M8WrVsoBP_fD}*1gevPyvTv; ze9xV~&@Z@7!R3y(qBQrLEyj6NTjP0Da3(*At@VI6Tfl5Q?~S00I`YS*k4Xf@e@h(d z@kA+B#%GY@mqdaFGGZ|Bp@qiXSa!BD@?yWvk!&uLO-=7hPtT_N(u1j?Tskw9r2q4o z=|h=pU#7P=-AAe9K*~|+DE)}Qx~Y(a+@WEW{~{J`6^TKuVucswORHd5_=PL@Iy4br zx1fR;Xk2Yr*+u!%>K7KJVT|hP2aGE9tMsCLX*CQB=Ug5JQDRUbTIogk(rRdr<$z)F z(a#2B^hMm#VDv>VMk}}|Us~nDVnf_~I)I}26o6KAQNFb5g+-9K|LNKe{ZDDTiZ05R zR=rWjnHpySfAc{O0XYl=-}G%nNTjhBWT5CvzVk4>Y2OLTi^Se@_M7`YPqe9V6N=j_ zPrF~OfB0cDui#hTE{sztS$$_-#5(89r9bQ0jyi{V?3uXiRYxuXQ8Cvpzf(%F1Fd(1 z>Q8}eWCzlJqImVyc(fE_I z$r%pI40)6$c;Jjm=)fdLhr4m6EYmMNcMz%QqYM8-VSXpiG(L$ZJ`VB(i2b1e<9f<9 zV%5?3KBWe&lv(e&N4BbQzIBiDon@zR&zsM=hcZd}GEbh7wnB0gF{2Gsv3h8>J`J+k zCuYRjvs=d8n8(qkEpyP>>fn`0}2H!m%Rob zE5%HE3pFP|1^RNtU|{HPlp9klGp%tBgN%b~;}HomA&5?JFsOpVOlv%_!h(mHX)HK_ zHb~URtd^))aqefFB$YhXdAbWt!DhhmrABKX!$6Ph=(R3gc*Z3!p%~s?? z8c~JNhv5o+%;nI>YGSU(-jsrQ2aJzp=;K`+i{f|G##Iy7M< zWQ@pcFevsyeb+ELW>AuDioGO5MUO)HrJoT{Sjl5yT$|+0ACXW7B;$atPbG=LKvbw{ z5$7G#HbaT-lR3->Aot$sDSVW5=LY8XbedkY^dVfK0|^WU*2x_ul zsgULgh#!7N1elE{ym}n<4u7u8n5+c5&WNbuGa}^B;_9q1S{v8yB?E);2#aI^iJ&F3 zZGtkCcXt5H36jCsRHgzPAo;&zhsWmpfaJWp(#icHb%t>DC< z3Xaf183(PFCU{6_K?+WLr~)+(!O!$+98N+R2d$PSct~hLLPaMyprQzl&_Wppt(GRZ z0-qwNTpb1#Vo;%i&_Wppt(GQuNN7PqMK^K+Dm-#JofDyjG7efTP4JM=LX0)8g9?G$t34WK4$B5r!k z!*wU-bmfhm>DGjdTWug?chEu8WsqS*&`OER0=@{0=YcSOv1z1f#91z}dq(VHQp6|i zN}X4f`iAG8H}yDc{a_lm5>#m_DMtC7%YE1QBub|18-?p}_aaJ}wu{c9LWS1_*&fPJ z3^U6<=%8sGvica~`1*_P#hVyDR^oM*7Lz(S+j)3|;w;fkc9xLsyfM&#pVxuMe!b}&jRbm@My&=iGI$~F$61OHa=TscjMB>IymDv zOB1FC4Opdo!#?&EsN*yuL5)KU#%X}mo?Ibx-$*!1|0Y4Sf)j%(cqE)97W`6;#v%Bn zUX3RxIquF9Lq#VzprQyK31{iiFsKlN3YADWOAHm=cn_%X$mw*>NH|NZaUE2kaRn-o zaF!V3I*kM4ipHbmEKQh)q2nNsg&-dVSq_2?=o8j}oR}B&nKijoc6~BWZ(Lzu_nvdG zkjMH43{v=qJUNfoGyx0~_C>}9i#PTU(#`j+RD5|+>M`pcbJ{89+=B9OJi`Qg_Z@R> zfyt+MP4>);TLrI)<@6j6XY3R-K`PcFTlCgm^a*=HhIqKwG+{azcL13Pf_^u_^z)h! z7`VW$`sGEbJ3RNiDX-T=CB-Peb9ua`3s5p$cNDH@drf{;`L)!FTCa&16t9VnqKa`g zJ|kK2nsBHUmY9&O+;frH<>0kS|L6wL^TiOaNw&V*YhsbV3(&%t@>%wP$lnE|E@X6! zgV%InvDdU6OMPXCuCI)mu5TfM4V~1)VE9N~8L#PfNOJ|Segxw&&}%w^x*IVYS47ln z`ex9iaG_rx4q9Tu$#BL+M1s06F&GyCQgS$tiq{l3Lj(tdDtHvUCMoz$!5U}5Z}Mt9 z5?&KSMI(3&P*DVrgxB=*5U9k6L4`^bye0`1&B)16;gQqnoUq=;eTj)Ru7e6Ru0SOc zUK3+nqjAQ#qVb4%P4{8wU?=2p{PhgTuR(qf@+XkLW{B?n!*M##XuCl5XyP+s$ABV^H zyeY5OL?wa8xjbGI_R-?Hr*K8wYx1$m$=}m^O~jyhP18vooQ+TXRlFv;$zBt(m3zwX zXuPH``B_}fT2u2hZhg1c#3KKQ#0xUJAo7n0Qq8+^-fizSHSb#NHEqXI!|d1T`u3>l zntCyTRwFgKxsTM9@tVF5X>NhnBvBFQH4RgLBxd85XnIY}3xXzvi~Ra?8d-wwe zfsi5w19L-jhuwV<9vSbAdGUE6f`dU7JQ7|L3w|$2AJBJk?@)rDz}F~g-1@Ob4J2zVvXyd0*xzBiGzrNJ^%)khingV>Mqb)-p_~Z4aW_b)_9i{L&qGp`` z(7c$4%XgYg_kL&PjGtMQvQN^EgVRZY^Hr3G;}M$evly7m?_6zrcE;oVeJ2!DA2dno zJg4RkWZgB~b821yMtokrc^1f?Ak+Ljr~9aS-?G#ayQ?Vmpy!@9<@KDXB;^z|(A$sjoCO-(2K5ZKqPV zhv}La#!T1TT1|K&zqV%}?S88@J{R}+gVo`0wSqZXAFOu1H{bk&B2eESrf6a)?!IxE zjn}e@yD!Dbz);cddwEFrm8bEzyYEY3H6;cKDH%%~hwl4SarfOWrA{D%s~al8FlM^; z>%Q)Hi4#0!cOQ~@kRG@JMDp3eoN{s6?4vZ@rk5V4h1<3WEsfOAfL#K#=*>*^gwF$(8%DLR2Ds}n3c8WP4M0qDM@o+r|15nu@Z_mxRRR~zZ-xXu9 zLB3^YDwJ%-jpC5ggnh9{2tzo=a0?#Xg1rST7%f^jjQe+=fMtTtC36CniCv0Pc8HSi zc~hQ%B}xL1bB%YvviY?jGsG__Y<)ky8Ly9%jzM4YD*%o8nNsYS8p>ciL?p=p^Y>`8LRXc~P}2l^K>_Ps3@V1|Ouc8`XXfX++4c0P=SLTORTn zFgzQ)LFH(_14#E9aV~9XUjVe;wv!XxQ$farYf0-RdPei}AiV4Kr;Z(ApE#7DSG|l^ zWxXhh|3^(~3+~yrL7XfG%8ML)$qxhIs1mwkyz0K(2a(`O?k@nwUj(YQVs4(vQuuE7 zq6Z0@UBPT@Epv^KOCO`71z=?O9l3Tz3Fbw7D{B5Uk$@2l493&+q?Vtv>}+0C`U`;m z@9RNG#rDEaVP61D)DerWieONySm7@KmR3Pt8szWWJJp@dc&1jP9>5iR4fkO96)%Q! z1!0)F+OV=;04%M3A!ofwjB4t~7**<5=`R45Rzn50+>=}_80UQnx?YIw3`#Go^cMh2 ztD!xXGeqSVvs^Wl7=1njqnIUJ7_HzJ086W!eU6rYeK34xDGHLTiyV9hsZ>Db`zUGU@T3XUUU#Xzdghz z8qd4+gpny;g;Ktz13e}hpMu}=KXjwWL^J3|d;k!cc;gt`Pfsx`7i+CEj>#$#72CYU zFHQlZE29?7BVm03x_Jw-lKn^jsYVDGFD=Cgc^_raogNS;2L2Fy^A=kLQHXIM*rykq z7*xTd5aVFMP54p)CIc8uxY#a@MYl!HGc?JPI+6_$HEBi*aI5p@Ie&?-+-~ zxF*H{2I+A-oihqC4%WC9Dx`50Dp81WFvfK;4jv9U#^Gpuyki{RPs&W3PspA4VUWcj zM}Qm!ay-ZhAVYaEkzdNqXIAIerdAKrYK?uOQ6b*3D|H&_Y1`HbvTpE9rV}^NZ_SSo zaV^-aM%!A`aQw}p)Is(=a5||Qi#TW4oVe$3BHs*W3CI8Ye{tTI$>JVNb)l#Peu;mQ zE{bHtKk2^1@rs{OXQH@;Sw+?H`~KfVeCKfDr$9~vIo+0SBjwt`PF+Z;7CZGT&%GZ} zioaV7pE8bo``Dbg=gsHbLz(la7Mq3NtWP(5Ee1Pc#1_NNqlg&&fGXDf-ynB@+~^ZA zV!b*Mqe;-3T?bDp_7?8B^~^0mJaM{WZ@KS`K4KL6C)IYe5hE~1I%0HL3C0>;gVKgm zz`(xh#LKxwIATQY*z#LWP6JLx`Tf7r?EH|=G{+G<)y09ppb8FStwkcMa)O7%cckDt z_Y#7`y>w|D##+l;71nr2;6_44BRE4v5gf)^%fBluxZ>IH(_GOCoCdCk3Nffqfw4AG zPC1o>N=TSRLPh7Q11fNHT~L9sHc^iGl@mNHgu)uvK!p!zSD*r8ZQ_mq`X_WIvwi8ITS4q&xRmL1J%*Zx zhy-}zF=F7g@1}LO9$*}f_deCw-@^na237DV#6DPX-P$)8c^D#K_v>Y57xLAO=OY@0_i4A1lbW}H;{ek#I7DXkj$P#?cE*HoM~|F?wGVcyQp>O zL&&>7ktP{;aDPD8K!k+i3*?>0e)=dl-^K0@`E``zd73+prybWjjj0=0|$a& z12h>SjE?zKdD}OLVH3J@824aN$_|ypPN93A;0W@@C zP4KYb2t!3DIG~~kUS@ElG{KdTwFoN5gh7QERH&3094Sq3djJF)3fsbpF#a5F!GS8? zCj~4S&v~IzW^kl5!9#*0G1j;aD$uwBl`?}Pr3oGu9AS*>G!Bd_8i&19MsTDw!ABh& znY0Rcz_&Lhod}WzIT-{CF_S(A^2MUy$o}XwVZo8cO&-IpaTCf~Nu+VJ+pufg%ywV( z?FJilpCpE+6bP2m8s#)UlQ4}p5=K37vQ<_1jyreoCMv=CL{-!BQdW5E;K*_oi><~U zzXHf2FrF!4IyLd8ow15YK#v83ffj07&b5FZ$_$Q_hM$nNhS>2Tf`dU7yv*Q8X@ZAM zr!4p-!5U}5FY#);%-~3Af`?3}5-J+O87hk4Wd=t|6Fh7><({X(c#IfSsFWETDNXRO z>6D>jyMaE_DKL&&J4 zgTSQ;9yp!SK!Qn5oJ4;Bw3Ds}!HX`F@S@A4`#`pUJPz^<$gk zY);O%8FQa}s{eivDTmvw#xHmZJKinsJM3_;p=ZGH{t^}Jw;yEE8+2pRpF#ct^15A* zUsJA}okE~eE+CLLVlcbxd$D~eb)LC(j7dsuchCT-xr2_Q)ZsCvPSQtf z3;%At#6O}ZG9$!iLeMi*lO zvoR^cF{WorF^X?R*T8ytkWoww1}558xgE?hip$u5Q`#&LVicRS3r#OLF{pw^A;u&H z-(90|2)?^l<57q)nG6-3;DCxEcobqx<^y3+AqEvHQHU`~s7wig$`mhDq7Y+}8rMMu z8dsnag&32>xK881xT0}PYte}@wX$0G11NAxbnAyexL^d#U*%SOk$H?hzLDL@t85k+wUC-M9G?bOs^A&$-q<> zG%FH=F_Y!6PJ}+6ij~>$2&XK^(x((ZGN&0Q#$Jecqjr+9TW5c|r> zB?q&5FyW}B;?l=tHPBTn=N#i!Y0?%cdMni8zoNj1*~)TRpvzjIK3mtE3u%_1 z*Gl+tH&P*W5N;D6F`G-?b*~*GaB(s2Ue7 zfH~LrtzQcToULkhP)&84w7|gI;#%)wA<#G&AnTuZv^Sb55)%7jipo>11pE|s6o|Qw zShRu@gDN;Y(0chP3E6MoO=p0Nig|;dC>lpk2|nV31vgD_223<0xQXp%E{($jt$(A! z8V_5R0aUbt6N4%^Jka`gDlE9t3j8$JW&!gkw93mGjT3_k6?mWxa`mBdPzhOk0bsEQTsAwF9UxRBh zsmO3R>SdYMACfq&4}&}j@+`;;ATNWw4)S(hnCU)Xgq%);UeG0oVal`LvIXS$3s93| z9MdI3mUk{p<|+Q}yfZpuJ~f<`inN+C?MNaxT`6$>gCv-Y%?^|8<5{`9f57;dEUP?& z9_^WqA$1$b4lK9#IMvw7fLT!;s!?UR$&`v}y$j?9Ink>In_7>zw$%U940&j~G~9I|L2mPMJM+Tt7zl z(Tv1n9^(Gh_y=;)uRZQaf0>pOD?+-YzLwABrL?hioNMdl0d4$I(k3buI3E*(Vw97? zYI3$(z^EAoe}gp!Xu#ZsA&zXdW1s;)SkPmQ-}{+)PNPrWgC%mKc_m3^))EP_Jcz-> zFg$rL&RbbS{9}+N0R_(Ir}3cgXNb=yK4LZ#Wh#?Pubd%1xjg`m#_#-ED98|BN{TT4 zNhGLoh{5qbsukRzwlIU`|+L*rVE6N3tsNEqTv!!%9|s>Y*bh)+Hg zL&sqt%Rr6>`2@&X5KQZnH`2>vL&?DurYNr|z6;Mdb39xPEUDKRx2I%cw~TQXbPT?2Fc}MHllLk% z#-+uD#~^UxV~n%K#hJMRw)wKnjB%1W)EJ-K4hhc(*~8BmN5eSY(2}B**BA#kc$T=0 zal9?cSG0|BzcxOaT32g~6N6%m?@zyQww-;9ak|OIII`_rrv1nUc)=avzv~%Z`%%%Y zxL}O`!Ozrl8RJ)R7Pm1@y8%fgB0<&%F_=38CejD8(Oi+JcnZ=?g#!0yNdt{>Xq%YL zsbwmYORu0Yep8S!{*qq{1sUTXhdRiK3v3)>Fq_dh|HT!Gj4^(BnBc^q3LXh#oCV)o zqj3nnw^!qlFvb}wI>7-IMes-%wt~C}f)_3)znK?_-poLT_i%Wv zars?Ik2U@;uQmQJlz=d@%Npl-lII5)WS7!4)sx!OPJz=&fpb?XsttB-o4sVg^X{%b z*0?<<6Z@E35bG$7dm53$Do=x6IW)_9w2QMWZtuZxpNM1rhwVlZa|D>J-ku81|B zgEad>frs(ara>^j(D-4*N6hBFWh#?PubegBws(*<{<2>S1zF?R>S4mf4r(0in3##i zX}23E5_?p>7bZ9{sDekr8fU>5XfzJN@ks-h#v@^kGgNef11gH(k+8ZB zWxtQild6*f=RA~m1`|6E%A4n7klWKTv5&Pu-iG*b+l*p^Tv}b$nC)Ybv(?3!xdL`T zahrw5N$Sw>cpLoRw$Fm>>SvI%%IyY7qX9fAuR#uO@W{_XA56-LAxGhgwn0wXA}zFj z$kTNAUpRX&fe0 z3Jb0{`}{QbHs2G&ph65PRA53iuB@=&VcUEeD*Yi)>GwhfCRF3cD=fIZcnsNmIwxyf z2Nh^sfeK8h#uF+mxE(VK5S%ft(>O4$XdEU~V~H;YqRmQr>mhKPFYVHWeIrhy8UeIz zUjw-guppVRMYl55X8q@&vooE zdqgt_sU|%VN%R*|ZFVZHri|z8z$oE|xsd~Wj)jIhJ#@9n%XrScqZnnoKlf~|r=~Do z1(;^?b9us7LuC_in~Ec5<5eY8Hd^bKOCOt1*~S2%(N1&j6(&(BC2z{-ckATVeD`!W zgqpudB*?%Z1_P@bZSwsa*!$>2<-EBSB(ZG47@uj^d2GJg&kr?WQcT52!tr?pNQLrvv8Z96^7!!Wd}% zJTfieZu+jmM_fV^iRzqF+j@E_hGPtiypRaHU|T;Q^zCBfjZ$V*vN(is9g(0;OAN+! z{8U>7=-%Z7NlJoHSdiqdFu{pI6&zqICrDC~;9)Z=3;u#e;}D!*UOe5_c)3B6k^~Q% zQQM$#o#4cv3SMrIq$I(^W>mN)T8tBe3YBt$Bqa$RHls3B?hk>={oc-5ZjhuT!NX=$ z*0>HT(71x}a)Tr#2_811GRAcp2gVhRmm4H0N$}Cns7DhXrr@26DQiLCcTK@GGvzdp z&w_k`PJZGeYBNKtdy4`kv~Nc&=b^{F)->fZ?_7Er71VkbN|SRVwtLMWUtp@csQgX=^K6>-H*jc#sL}v{UW`xf>eJ z_yw6LKxEuvBLt}vHK{$_n3ln%0^+@B2hu5g$k(3QAQKkOj9D7-IMesG!TX9dG=Nd&76<*14I%k>7HKhqYs^F3i<8WOSjF-7wQ<~sm!6nAHPUFD1qVY19 zYf2Mb6I}A{z?r%mA$RINAlMr`6?>YeE(G}~2=+8jT}9`6U(B%EO9m846=pD#LMy5Q$$*RP9*UgB2_K;3qn?1 z2?8N&5H6^B6y*CvYEhY5R5fuU$UQ`A=Hsu2h*Tr|S93lHR8kN0*IZAe?hquCASkr) zW&Cvx{@RTQf0B{EYcy#olBi|t4j>S+a9|+)RXD8#fBhE-G*sB4O@FaX!)sJi9!3)D zXKnAugRU{-PNPeVWW~f|drnNQPqq&vhx*$)2a>tmf}7f&x#cI1uDZ;mldti1nrzy= z=#PNo+r_?AxR7tE!uk=sZ=`UlHhyU4ADZ)`v3IbqE0s$Ptxfi2XrFx@rF&BSsiD3k zHr)^QtxRpqXXw*i^k>I#vOh^Y_4N0mp?tb8*_X@_*OLfSitl!f3=b59J8~$EA|?_O|GC-{ zE0-5-$XSrGBbUq2GxJ;|#P7&w(`!h;yx75&TD@ds06g^GFKI*8zb8$qks)dMf&jPE zzs0|Cwm)}V=<_Jn=TT_a(?I|XHW|77B^(aG4eZU6pU7HAe=*v)CrKOwm5f=&JA;|A zE%6TcbLZeb#l1#$BJ?TlVom6F+!eWJa&MKLx0-Hn*OomU9bb+E=qrLp3G`7pRPZRl z0|bu^JS?DJ$id)j`b!Q0-0`{3b5G~~&0U*&wcVlBzRW$CJ1=)xySMsvRKGsz*FDvq zc>@VKc`p#|g&4M^Q{m}*S<%wR;Lo&o4E1uWXVZ_~`h%-GyYr@q^@ytFseXbOW90J5lG zkH%cj^d`{iRqL~2@4kXCxpvA}cv8F1h_d#m%_rRUz&9pibk2%d7NCZ+sg9vdRu$Tp zWm7(R*KL|~)UgLFUr6p_kEl)$qXTgq%I#XF`hVAO3Od1v~|>ltn5 z{%&YZyuN;`6m@TnsGe*chkk0>7v6v0MCuZ&M8j~B?s)yxY$BLRv@5nGU zBaOYg9BWr#0OMzF_A+W^YEd3d7m%8Ev7UWGCOeqSwJ*khE3;{u^hO4f*}whqxpk|) zQ@6mxOY|+AIoFl3?sI>#Xyp4vY z=f@c*?zs5c4?O;FQ#36W@#Me>$yK5zNwZKceR8T>)b#hIvnhJ`Dp5%(v~E$yD9x;(rXWTt zd3`!_wEfpH-SoL1y491+_K#$#jhm4IhLc^?!09~w)MEd%D0k9GD%(fDHRaNS!vm>Y zSL$Rk$EZ!?d1^YEV!HFGAs#>z$I>TMH|0~^gUNn^qj~H?3>t&|N08mcx}+ourZ(a> z;IW~FYTu^RzF^_KHTQRSU2w<${=uYYh$v`>S{x1L}G}ZtB diff --git a/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart b/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart index 60892cb7..48db43b4 100644 --- a/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart +++ b/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart @@ -2,8 +2,8 @@ import 'package:bookify/src/core/enums/rest_client_error_code.dart'; import 'package:localization/localization.dart'; extension RestClientErrorCodeExtension on RestClientErrorCode { - String toLocalizedMessage(String? description) { - final messageArg = description ?? '---'; + String toLocalizedMessage(String? descriptionMessage) { + final messageArg = descriptionMessage ?? '---'; return switch (this) { RestClientErrorCode.connectionTimeout => diff --git a/lib/src/core/repositories/auth_repository/auth_repository.dart b/lib/src/core/repositories/auth_repository/auth_repository.dart index e6a4a0c5..cb02da2b 100644 --- a/lib/src/core/repositories/auth_repository/auth_repository.dart +++ b/lib/src/core/repositories/auth_repository/auth_repository.dart @@ -3,4 +3,5 @@ import 'package:bookify/src/core/models/user_model.dart'; abstract interface class AuthRepository { Future getUserModel(); Future setUserModel({required UserModel userModel}); + Future clearUserData(); } diff --git a/lib/src/core/repositories/auth_repository/auth_repository_impl.dart b/lib/src/core/repositories/auth_repository/auth_repository_impl.dart index 4a778e69..348bb73b 100644 --- a/lib/src/core/repositories/auth_repository/auth_repository_impl.dart +++ b/lib/src/core/repositories/auth_repository/auth_repository_impl.dart @@ -14,9 +14,11 @@ class AuthRepositoryImpl implements AuthRepository { @override Future getUserModel() async { try { - final userJson = await _storage.getStorage( - key: _userKey, - ) as String?; + final userJson = + await _storage.getStorage( + key: _userKey, + ) + as String?; if (userJson == null) { return null; @@ -45,4 +47,13 @@ class AuthRepositoryImpl implements AuthRepository { rethrow; } } + + @override + Future clearUserData() async { + try { + return await _storage.deleteAllStorage(); + } on StorageException { + rethrow; + } + } } diff --git a/lib/src/core/services/auth_service/auth_service_impl.dart b/lib/src/core/services/auth_service/auth_service_impl.dart index 534158bb..f4d0fb0e 100644 --- a/lib/src/core/services/auth_service/auth_service_impl.dart +++ b/lib/src/core/services/auth_service/auth_service_impl.dart @@ -14,8 +14,8 @@ class AuthServiceImpl implements AuthService { const AuthServiceImpl({ required AuthRepository authRepository, required AuthStrategyFactory authStrategyFactory, - }) : _authRepository = authRepository, - _authStrategyFactory = authStrategyFactory; + }) : _authRepository = authRepository, + _authStrategyFactory = authStrategyFactory; @override Future signIn({required SignInType signInType}) async { @@ -41,7 +41,12 @@ class AuthServiceImpl implements AuthService { Future signOut({required SignInType signInType}) async { try { final authStrategy = _authStrategyFactory.create(signInType); - return await authStrategy.signOut(); + final strategyResult = await authStrategy.signOut(); + + if (strategyResult) { + await _authRepository.clearUserData(); + } + return strategyResult; } on AuthException { rethrow; } on Exception catch (e) { diff --git a/lib/src/features/home/views/home_page.dart b/lib/src/features/home/views/home_page.dart index 75c22d6c..9b3a8756 100644 --- a/lib/src/features/home/views/home_page.dart +++ b/lib/src/features/home/views/home_page.dart @@ -58,13 +58,17 @@ class _HomePageState extends State { key: const Key('BooksLoadedStateWidget'), books: books, ), - BookErrorState(:final errorCode, :final errorMessage) => Center( - key: const Key('BookErrorSateWidget'), - child: InfoItemStateWidget.withErrorState( - message: errorCode.toLocalizedMessage(errorMessage), - onPressed: _refreshPage, + BookErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => + Center( + key: const Key('BookErrorSateWidget'), + child: InfoItemStateWidget.withErrorState( + message: errorCode.toLocalizedMessage(errorDescriptionMessage), + onPressed: _refreshPage, + ), ), - ), }; } diff --git a/lib/src/features/profile/bloc/profile_bloc.dart b/lib/src/features/profile/bloc/profile_bloc.dart index 9758ee42..feedae2a 100644 --- a/lib/src/features/profile/bloc/profile_bloc.dart +++ b/lib/src/features/profile/bloc/profile_bloc.dart @@ -1,7 +1,6 @@ import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; -import 'package:bookify/src/core/services/storage_services/storage_services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'profile_event.dart'; @@ -9,11 +8,9 @@ part 'profile_state.dart'; class ProfileBloc extends Bloc { final AuthService _authService; - final StorageServices _storageServices; ProfileBloc( this._authService, - this._storageServices, ) : super(ProfileLoadingState()) { on(_gotUserProfileEvent); on(_userLoggedOutEvent); @@ -74,17 +71,6 @@ class ProfileBloc extends Bloc { return; } - final storageRemoved = await _storageServices.clearStorage(); - - if (storageRemoved == 0) { - emit( - ProfileErrorState( - errorMessage: 'Erro ao limpar as configurações do usuário', - ), - ); - return; - } - emit(ProfileLogOutState()); } on AuthException catch (e) { emit(ProfileErrorState( diff --git a/lib/src/shared/blocs/book_bloc/book_bloc.dart b/lib/src/shared/blocs/book_bloc/book_bloc.dart index bd901c3b..e6ca59c2 100644 --- a/lib/src/shared/blocs/book_bloc/book_bloc.dart +++ b/lib/src/shared/blocs/book_bloc/book_bloc.dart @@ -40,14 +40,14 @@ class BookBloc extends Bloc { emit( BookErrorState( errorCode: e.code, - errorMessage: e.descriptionMessage, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookErrorState( errorCode: RestClientErrorCode.unknown, - errorMessage: e.toString(), + errorDescriptionMessage: e.toString(), ), ); } @@ -71,14 +71,14 @@ class BookBloc extends Bloc { emit( BookErrorState( errorCode: e.code, - errorMessage: e.descriptionMessage, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookErrorState( errorCode: RestClientErrorCode.unknown, - errorMessage: e.toString(), + errorDescriptionMessage: e.toString(), ), ); } @@ -105,14 +105,14 @@ class BookBloc extends Bloc { emit( BookErrorState( errorCode: e.code, - errorMessage: e.descriptionMessage, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookErrorState( errorCode: RestClientErrorCode.unknown, - errorMessage: e.toString(), + errorDescriptionMessage: e.toString(), ), ); } @@ -139,14 +139,14 @@ class BookBloc extends Bloc { emit( BookErrorState( errorCode: e.code, - errorMessage: e.descriptionMessage, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookErrorState( errorCode: RestClientErrorCode.unknown, - errorMessage: e.toString(), + errorDescriptionMessage: e.toString(), ), ); } @@ -173,14 +173,14 @@ class BookBloc extends Bloc { emit( BookErrorState( errorCode: e.code, - errorMessage: e.descriptionMessage, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookErrorState( errorCode: RestClientErrorCode.unknown, - errorMessage: e.toString(), + errorDescriptionMessage: e.toString(), ), ); } @@ -199,7 +199,7 @@ class BookBloc extends Bloc { emit( BookErrorState( errorCode: RestClientErrorCode.invalidInput, - errorMessage: 'Invalid ISBN provided', + errorDescriptionMessage: 'Invalid ISBN provided', ), ); return; @@ -217,14 +217,14 @@ class BookBloc extends Bloc { emit( BookErrorState( errorCode: e.code, - errorMessage: e.descriptionMessage, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookErrorState( errorCode: RestClientErrorCode.unknown, - errorMessage: e.toString(), + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/shared/blocs/book_bloc/book_state.dart b/lib/src/shared/blocs/book_bloc/book_state.dart index 69d76f25..5067d9cd 100644 --- a/lib/src/shared/blocs/book_bloc/book_state.dart +++ b/lib/src/shared/blocs/book_bloc/book_state.dart @@ -16,10 +16,10 @@ final class BooksLoadedState extends BookState { final class BookErrorState extends BookState { final RestClientErrorCode errorCode; - final String? errorMessage; + final String? errorDescriptionMessage; BookErrorState({ required this.errorCode, - this.errorMessage, + this.errorDescriptionMessage, }); } diff --git a/lib/src/shared/providers/blocs/profile_bloc_providers.dart b/lib/src/shared/providers/blocs/profile_bloc_providers.dart index d65eb408..5fc12940 100644 --- a/lib/src/shared/providers/blocs/profile_bloc_providers.dart +++ b/lib/src/shared/providers/blocs/profile_bloc_providers.dart @@ -5,7 +5,6 @@ final profileBlocProviders = [ BlocProvider( create: (context) => ProfileBloc( context.read(), - context.read(), ), ), ]; diff --git a/pubspec.yaml b/pubspec.yaml index fd8047a9..7c18e30f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.0 +version: 2.11.1 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/core/services/auth_service/auth_service_impl_test.dart b/test/src/core/services/auth_service/auth_service_impl_test.dart index 8d56838f..e9141c7b 100644 --- a/test/src/core/services/auth_service/auth_service_impl_test.dart +++ b/test/src/core/services/auth_service/auth_service_impl_test.dart @@ -45,8 +45,9 @@ void main() { test( 'Test signIn success', () async { - when(() => authStrategyFactory.create(SignInType.google)) - .thenReturn(authStrategy); + when( + () => authStrategyFactory.create(SignInType.google), + ).thenReturn(authStrategy); when(() => authStrategy.signIn()).thenAnswer((_) async => userModel); when( () => authRepository.setUserModel(userModel: userModel), @@ -61,15 +62,19 @@ void main() { test( 'Test signIn throws AuthException when strategy fails', () async { - when(() => authStrategyFactory.create(SignInType.google)) - .thenReturn(authStrategy); - when(() => authStrategy.signIn()) - .thenThrow(AuthException('Strategy failed')); + when( + () => authStrategyFactory.create(SignInType.google), + ).thenReturn(authStrategy); + when( + () => authStrategy.signIn(), + ).thenThrow(AuthException('Strategy failed')); expect( () async => await authService.signIn(signInType: SignInType.google), - throwsA((Exception e) => - e is AuthException && e.message == 'Strategy failed'), + throwsA( + (Exception e) => + e is AuthException && e.message == 'Strategy failed', + ), ); }, ); @@ -77,16 +82,19 @@ void main() { test( 'Test signIn throws AuthException when repository fails', () async { - when(() => authStrategyFactory.create(SignInType.google)) - .thenReturn(authStrategy); + when( + () => authStrategyFactory.create(SignInType.google), + ).thenReturn(authStrategy); when(() => authStrategy.signIn()).thenAnswer((_) async => userModel); - when(() => authRepository.setUserModel(userModel: userModel)) - .thenThrow(StorageException('DB failed')); + when( + () => authRepository.setUserModel(userModel: userModel), + ).thenThrow(StorageException('DB failed')); expect( () async => await authService.signIn(signInType: SignInType.google), throwsA( - (Exception e) => e is AuthException && e.message == 'DB failed'), + (Exception e) => e is AuthException && e.message == 'DB failed', + ), ); }, ); @@ -96,31 +104,37 @@ void main() { test( 'Test signOut success', () async { - when(() => authStrategyFactory.create(SignInType.google)) - .thenReturn(authStrategy); + when( + () => authStrategyFactory.create(SignInType.google), + ).thenReturn(authStrategy); when(() => authStrategy.signOut()).thenAnswer((_) async => true); + when(() => authRepository.clearUserData()).thenAnswer((_) async => 1); final result = await authService.signOut(signInType: SignInType.google); expect(result, isTrue); verify(() => authStrategyFactory.create(SignInType.google)).called(1); verify(() => authStrategy.signOut()).called(1); + verify(() => authRepository.clearUserData()).called(1); }, ); test( 'Test signOut throws AuthException when strategy fails', () async { - when(() => authStrategyFactory.create(SignInType.google)) - .thenReturn(authStrategy); + when( + () => authStrategyFactory.create(SignInType.google), + ).thenReturn(authStrategy); when(() => authStrategy.signOut()).thenThrow( AuthException('Strategy failed'), ); expect( () async => await authService.signOut(signInType: SignInType.google), - throwsA((Exception e) => - e is AuthException && e.message == 'Strategy failed'), + throwsA( + (Exception e) => + e is AuthException && e.message == 'Strategy failed', + ), ); verify(() => authStrategyFactory.create(SignInType.google)).called(1); verify(() => authStrategy.signOut()).called(1); diff --git a/test/src/features/home/views/home_page_test.dart b/test/src/features/home/views/home_page_test.dart index 0046f2ce..0fb656c9 100644 --- a/test/src/features/home/views/home_page_test.dart +++ b/test/src/features/home/views/home_page_test.dart @@ -101,7 +101,7 @@ void main() { when(() => bookBloc.state).thenReturn( BookErrorState( errorCode: RestClientErrorCode.unknown, - errorMessage: 'errorMessage', + errorDescriptionMessage: 'errorMessage', ), ); diff --git a/test/src/features/profile/bloc/profile_bloc_test.dart b/test/src/features/profile/bloc/profile_bloc_test.dart index 40778e55..8d956cc3 100644 --- a/test/src/features/profile/bloc/profile_bloc_test.dart +++ b/test/src/features/profile/bloc/profile_bloc_test.dart @@ -3,24 +3,19 @@ import 'package:bookify/src/features/profile/bloc/profile_bloc.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; -import 'package:bookify/src/core/services/storage_services/storage_services.dart'; import 'package:bookify/src/shared/enums/sign_in_type.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; class AuthServiceMock extends Mock implements AuthService {} -class StorageServiceMock extends Mock implements StorageServices {} - void main() { final authService = AuthServiceMock(); - final storageService = StorageServiceMock(); late ProfileBloc profileBloc; setUp(() { profileBloc = ProfileBloc( authService, - storageService, ); }); @@ -35,15 +30,16 @@ void main() { blocTest( 'Test GotUserSettingEvent work', build: () => profileBloc, - setUp: () => when( - () => authService.getUserModel(), - ).thenAnswer( - (_) async => const UserModel( - name: 'name', - photo: 'photo', - signInType: SignInType.google, - ), - ), + setUp: () => + when( + () => authService.getUserModel(), + ).thenAnswer( + (_) async => const UserModel( + name: 'name', + photo: 'photo', + signInType: SignInType.google, + ), + ), act: (bloc) => bloc.add( GotUserProfileEvent(), ), @@ -59,11 +55,12 @@ void main() { blocTest( 'Test GotUserSettingEvent work user is null', build: () => profileBloc, - setUp: () => when( - () => authService.getUserModel(), - ).thenAnswer( - (_) async => null, - ), + setUp: () => + when( + () => authService.getUserModel(), + ).thenAnswer( + (_) async => null, + ), act: (bloc) => bloc.add( GotUserProfileEvent(), ), @@ -79,11 +76,12 @@ void main() { blocTest( 'Test GotUserSettingEvent work when throw AuthException', build: () => profileBloc, - setUp: () => when( - () => authService.getUserModel(), - ).thenThrow( - const AuthException('Error on authentication'), - ), + setUp: () => + when( + () => authService.getUserModel(), + ).thenThrow( + const AuthException('Error on authentication'), + ), act: (bloc) => bloc.add( GotUserProfileEvent(), ), @@ -99,11 +97,12 @@ void main() { blocTest( 'Test GotUserSettingEvent work when Generic Exception', build: () => profileBloc, - setUp: () => when( - () => authService.getUserModel(), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => authService.getUserModel(), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add( GotUserProfileEvent(), ), @@ -127,12 +126,6 @@ void main() { ).thenAnswer( (_) async => true, ); - - when( - () => storageService.clearStorage(), - ).thenAnswer( - (_) async => 1, - ); }, act: (bloc) => bloc.add( UserLoggedOutEvent( @@ -149,10 +142,6 @@ void main() { signInType: SignInType.google, ), ).called(1); - - verify( - () => storageService.clearStorage(), - ).called(1); }, expect: () => [ isA(), @@ -163,57 +152,14 @@ void main() { blocTest( 'Test UserLoggedOutEvent work when userLoggedOut is false', build: () => profileBloc, - setUp: () => when( - () => authService.signOut( - signInType: SignInType.google, - ), - ).thenAnswer( - (_) async => false, - ), - act: (bloc) => bloc.add( - UserLoggedOutEvent( - userModel: const UserModel( - name: 'name', - photo: 'photo', - signInType: SignInType.google, - ), - ), - ), - verify: (_) { - verify( - () => authService.signOut( - signInType: SignInType.google, - ), - ).called(1); - - verifyNever( - () => storageService.clearStorage(), - ); - }, - expect: () => [ - isA(), - isA(), - ], - ); - - blocTest( - 'Test UserLoggedOutEvent work when storageRemoved is 0', - build: () => profileBloc, - setUp: () { - when( - () => authService.signOut( - signInType: SignInType.google, + setUp: () => + when( + () => authService.signOut( + signInType: SignInType.google, + ), + ).thenAnswer( + (_) async => false, ), - ).thenAnswer( - (_) async => true, - ); - - when( - () => storageService.clearStorage(), - ).thenAnswer( - (_) async => 0, - ); - }, act: (bloc) => bloc.add( UserLoggedOutEvent( userModel: const UserModel( @@ -229,10 +175,6 @@ void main() { signInType: SignInType.google, ), ).called(1); - - verify( - () => storageService.clearStorage(), - ).called(1); }, expect: () => [ isA(), @@ -243,13 +185,14 @@ void main() { blocTest( 'Test UserLoggedOutEvent work when throw AuthException', build: () => profileBloc, - setUp: () => when( - () => authService.signOut( - signInType: SignInType.google, - ), - ).thenThrow( - const AuthException('Error on authentication'), - ), + setUp: () => + when( + () => authService.signOut( + signInType: SignInType.google, + ), + ).thenThrow( + const AuthException('Error on authentication'), + ), act: (bloc) => bloc.add( UserLoggedOutEvent( userModel: const UserModel( @@ -265,10 +208,6 @@ void main() { signInType: SignInType.google, ), ).called(1); - - verifyNever( - () => storageService.clearStorage(), - ); }, expect: () => [ isA(), @@ -279,13 +218,14 @@ void main() { blocTest( 'Test UserLoggedOutEvent work when throw Generic Exception', build: () => profileBloc, - setUp: () => when( - () => authService.signOut( - signInType: SignInType.google, - ), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => authService.signOut( + signInType: SignInType.google, + ), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add( UserLoggedOutEvent( userModel: const UserModel( @@ -301,10 +241,6 @@ void main() { signInType: SignInType.google, ), ).called(1); - - verifyNever( - () => storageService.clearStorage(), - ); }, expect: () => [ isA(), From 19560438c9caa8420f02aeef0e3ec3a1a7f943e6 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Wed, 22 Apr 2026 17:06:27 -0300 Subject: [PATCH 05/19] Refactor authentication and notification handling with Cubits - Replaced UserThemeBloc with UserThemeCubit for better state management. - Introduced UserLoggedCubit to manage user authentication state. - Added UserNotificationCubit to handle notification initialization. - Updated BookifyApp to utilize new Cubits for theme, user authentication, and notifications. - Renamed clearUserData method to deleteUserModel in AuthRepository and its implementation. - Enhanced AuthService to include userIsLoggedIn method for checking authentication status. - Updated tests to cover new Cubit implementations and refactored existing tests for clarity. - Removed obsolete UserThemeBloc test file. - Bumped version to 2.11.2 in pubspec.yaml. --- coverage/lcov.info | 1044 +++++++++-------- lib/src/bookify_app.dart | 97 +- .../auth_repository/auth_repository.dart | 2 +- .../auth_repository/auth_repository_impl.dart | 4 +- .../services/auth_service/auth_service.dart | 1 + .../auth_service/auth_service_impl.dart | 14 +- ...eading_page_timer_loaded_state_widget.dart | 7 +- .../user_logged_cubit/user_logged_cubit.dart | 38 + .../user_logged_cubit/user_logged_state.dart | 22 + .../user_notification_cubit.dart | 29 + .../user_notification_state.dart | 16 + .../providers/blocs/blocs_providers.dart | 4 +- .../blocs/user_logged_cubit_providers.dart | 10 + .../user_notification_cubit_providers.dart | 10 + ...s.dart => user_theme_cubit_providers.dart} | 2 +- lib/src/shared/providers/providers.dart | 4 +- pubspec.yaml | 2 +- .../auth_repository_impl_test.dart | 49 +- .../auth_service/auth_service_impl_test.dart | 4 +- .../user_logged_cubit_test.dart | 98 ++ .../user_notification_cubit_test.dart | 62 + .../user_theme_cubit_test.dart | 0 22 files changed, 959 insertions(+), 560 deletions(-) create mode 100644 lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart create mode 100644 lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart create mode 100644 lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart create mode 100644 lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart create mode 100644 lib/src/shared/providers/blocs/user_logged_cubit_providers.dart create mode 100644 lib/src/shared/providers/blocs/user_notification_cubit_providers.dart rename lib/src/shared/providers/blocs/{user_theme_bloc_providers.dart => user_theme_cubit_providers.dart} (87%) create mode 100644 test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart create mode 100644 test/src/shared/cubits/user_notification_cubit/user_notification_cubit_test.dart rename test/src/shared/{blocs => cubits}/user_theme_cubit/user_theme_cubit_test.dart (100%) diff --git a/coverage/lcov.info b/coverage/lcov.info index 2c8dbd22..f5b26b3b 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -270,11 +270,11 @@ DA:41,1 DA:42,1 DA:45,1 DA:46,1 -DA:51,0 -DA:54,0 -DA:55,0 +DA:51,1 +DA:54,3 +DA:55,1 LF:16 -LH:13 +LH:16 end_of_record SF:lib/src/shared/enums/sign_in_type.dart DA:7,1 @@ -289,153 +289,6 @@ DA:20,0 LF:9 LH:4 end_of_record -SF:lib/src/core/errors/auth_exception/auth_exception.dart -DA:4,2 -DA:6,0 -DA:7,0 -LF:3 -LH:1 -end_of_record -SF:lib/src/core/services/auth_service/auth_service_impl.dart -DA:14,1 -DA:20,1 -DA:23,2 -DA:25,1 -DA:26,2 -DA:31,1 -DA:33,1 -DA:34,2 -DA:35,0 -DA:36,0 -DA:40,1 -DA:43,2 -DA:44,1 -DA:47,2 -DA:50,1 -DA:52,0 -DA:53,0 -DA:57,0 -DA:60,0 -DA:62,0 -DA:63,0 -DA:64,0 -DA:65,0 -LF:23 -LH:13 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart -DA:12,0 -DA:14,0 -DA:15,0 -DA:16,0 -DA:18,0 -DA:19,0 -DA:21,0 -DA:22,0 -DA:23,0 -LF:9 -LH:0 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart -DA:15,0 -DA:19,0 -DA:23,0 -DA:24,0 -DA:25,0 -DA:28,0 -DA:29,0 -DA:30,0 -DA:31,0 -DA:34,0 -DA:37,0 -DA:38,0 -DA:40,0 -DA:41,0 -DA:47,0 -DA:48,0 -DA:52,0 -DA:56,0 -DA:57,0 -DA:58,0 -DA:63,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:70,0 -DA:73,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -LF:30 -LH:0 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart -DA:16,0 -DA:22,0 -DA:26,0 -DA:27,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:34,0 -DA:37,0 -DA:40,0 -DA:41,0 -DA:43,0 -DA:47,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:56,0 -DA:57,0 -DA:61,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:82,0 -DA:85,0 -DA:86,0 -DA:88,0 -DA:89,0 -DA:90,0 -DA:91,0 -LF:34 -LH:0 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart -DA:12,0 -DA:18,0 -DA:21,0 -DA:22,0 -DA:27,0 -DA:29,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:36,0 -DA:40,0 -DA:41,0 -DA:42,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:54,0 -DA:57,0 -DA:58,0 -DA:60,0 -DA:61,0 -DA:62,0 -DA:63,0 -LF:24 -LH:0 -end_of_record SF:lib/src/core/database/local_database.dart DA:5,0 DA:7,0 @@ -618,6 +471,34 @@ DA:122,1 LF:37 LH:37 end_of_record +SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart +DA:11,1 +DA:13,1 +DA:16,2 +DA:17,1 +DA:22,1 +DA:24,1 +DA:26,0 +DA:33,1 +DA:36,2 +DA:37,1 +DA:42,1 +DA:43,1 +DA:46,2 +DA:48,1 +DA:50,0 +DA:55,1 +DA:58,2 +DA:59,1 +DA:60,1 +DA:64,1 +DA:69,1 +DA:72,2 +DA:73,1 +DA:79,1 +LF:24 +LH:22 +end_of_record SF:lib/src/core/repositories/books_repository/books_repository_impl.dart DA:11,1 DA:13,1 @@ -682,34 +563,6 @@ DA:199,1 LF:60 LH:60 end_of_record -SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart -DA:11,1 -DA:13,1 -DA:16,2 -DA:17,1 -DA:22,1 -DA:24,1 -DA:26,0 -DA:33,1 -DA:36,2 -DA:37,1 -DA:42,1 -DA:43,1 -DA:46,2 -DA:48,1 -DA:50,0 -DA:55,1 -DA:58,2 -DA:59,1 -DA:60,1 -DA:64,1 -DA:69,1 -DA:72,2 -DA:73,1 -DA:79,1 -LF:24 -LH:22 -end_of_record SF:lib/src/core/models/loan_model.dart DA:9,5 DA:18,1 @@ -1013,41 +866,6 @@ DA:41,2 LF:13 LH:13 end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 -LH:0 -end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart DA:21,1 DA:33,1 @@ -1136,124 +954,309 @@ DA:24,0 DA:28,0 DA:30,0 DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 +LH:0 +end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 +LH:0 +end_of_record +SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart +DA:11,1 +DA:17,1 +DA:20,2 +DA:22,1 +DA:27,1 +DA:30,2 +DA:34,1 +DA:39,1 +DA:43,1 +DA:44,1 +DA:46,1 +DA:51,1 +DA:56,2 +DA:61,1 +DA:66,1 +DA:69,2 +DA:73,1 +DA:78,1 +DA:82,2 +DA:84,1 +DA:89,1 +DA:93,2 +DA:95,1 +DA:100,1 +DA:106,2 +DA:111,1 +DA:116,1 +DA:119,2 +DA:121,1 +DA:126,1 +DA:129,2 +DA:134,1 +DA:139,1 +DA:142,2 +DA:147,1 +DA:152,1 +DA:155,2 +DA:160,1 +LF:38 +LH:38 +end_of_record +SF:lib/src/core/services/loan_services/loan_service_impl.dart +DA:9,1 +DA:11,1 +DA:14,2 +DA:16,1 +DA:21,1 +DA:24,2 +DA:26,1 +DA:31,1 +DA:34,2 +DA:38,1 +DA:43,1 +DA:46,2 +DA:48,1 +DA:53,1 +DA:56,2 +DA:58,1 +DA:63,1 +DA:66,2 +DA:71,1 +DA:76,1 +DA:79,2 +DA:84,1 +LF:22 +LH:22 +end_of_record +SF:lib/src/core/services/reading_services/reading_service_impl.dart +DA:9,1 +DA:11,1 +DA:14,2 +DA:16,1 +DA:21,1 +DA:24,2 +DA:28,1 +DA:33,1 +DA:38,2 +DA:42,1 +DA:47,1 +DA:50,2 +DA:52,1 +DA:57,1 +DA:60,2 +DA:65,1 +DA:70,1 +DA:73,2 +DA:78,1 +DA:83,1 +DA:86,2 +DA:91,1 +LF:22 +LH:22 +end_of_record +SF:lib/src/core/errors/auth_exception/auth_exception.dart +DA:4,1 +DA:6,0 +DA:7,0 +LF:3 +LH:1 +end_of_record +SF:lib/src/core/services/auth_service/auth_service_impl.dart +DA:15,1 +DA:21,0 +DA:23,0 +DA:26,0 +DA:32,1 +DA:35,2 +DA:37,1 +DA:38,2 +DA:43,1 +DA:45,1 +DA:46,2 +DA:47,0 +DA:48,0 +DA:52,1 +DA:55,2 +DA:56,1 +DA:59,2 +DA:62,1 +DA:64,0 +DA:65,0 +DA:69,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +LF:26 +LH:13 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart +DA:12,0 +DA:14,0 +DA:15,0 +DA:16,0 +DA:18,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +LF:9 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart +DA:15,0 +DA:19,0 +DA:23,0 +DA:24,0 +DA:25,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:37,0 +DA:38,0 +DA:40,0 +DA:41,0 +DA:47,0 +DA:48,0 +DA:52,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:70,0 +DA:73,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +LF:30 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart +DA:16,0 +DA:22,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:37,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:47,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:56,0 +DA:57,0 +DA:61,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:82,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +LF:34 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart +DA:12,0 +DA:18,0 +DA:21,0 +DA:22,0 +DA:27,0 +DA:29,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:36,0 DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 +DA:41,0 +DA:42,0 DA:47,0 DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 +DA:49,0 +DA:50,0 +DA:54,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:61,0 +DA:62,0 +DA:63,0 +LF:24 LH:0 end_of_record -SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart -DA:11,1 -DA:17,1 -DA:20,2 -DA:22,1 -DA:27,1 -DA:30,2 -DA:34,1 -DA:39,1 -DA:43,1 -DA:44,1 -DA:46,1 -DA:51,1 -DA:56,2 -DA:61,1 -DA:66,1 -DA:69,2 -DA:73,1 -DA:78,1 -DA:82,2 -DA:84,1 -DA:89,1 -DA:93,2 -DA:95,1 -DA:100,1 -DA:106,2 -DA:111,1 -DA:116,1 -DA:119,2 -DA:121,1 -DA:126,1 -DA:129,2 -DA:134,1 -DA:139,1 -DA:142,2 -DA:147,1 -DA:152,1 -DA:155,2 -DA:160,1 -LF:38 -LH:38 -end_of_record -SF:lib/src/core/services/loan_services/loan_service_impl.dart -DA:9,1 -DA:11,1 -DA:14,2 -DA:16,1 -DA:21,1 -DA:24,2 -DA:26,1 -DA:31,1 -DA:34,2 -DA:38,1 -DA:43,1 -DA:46,2 -DA:48,1 -DA:53,1 -DA:56,2 -DA:58,1 -DA:63,1 -DA:66,2 -DA:71,1 -DA:76,1 -DA:79,2 -DA:84,1 -LF:22 -LH:22 -end_of_record -SF:lib/src/core/services/reading_services/reading_service_impl.dart -DA:9,1 -DA:11,1 -DA:14,2 -DA:16,1 -DA:21,1 -DA:24,2 -DA:28,1 -DA:33,1 -DA:38,2 -DA:42,1 -DA:47,1 -DA:50,2 -DA:52,1 -DA:57,1 -DA:60,2 -DA:65,1 -DA:70,1 -DA:73,2 -DA:78,1 -DA:83,1 -DA:86,2 -DA:91,1 -LF:22 -LH:22 -end_of_record SF:lib/src/core/utils/verifier/isbn_verifier.dart DA:11,9 DA:16,6 @@ -1504,6 +1507,110 @@ DA:19,1 LF:2 LH:2 end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +DA:11,1 +DA:19,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:11,1 +DA:13,2 +DA:15,1 +DA:17,2 +DA:19,2 +DA:21,1 +DA:22,1 +DA:24,1 +DA:25,1 +DA:26,1 +DA:27,2 +DA:30,1 +DA:31,1 +DA:32,1 +DA:33,1 +LF:15 +LH:15 +end_of_record +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart +DA:13,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart +DA:10,1 +DA:12,2 +DA:14,1 +DA:16,2 +DA:18,2 +DA:20,2 +DA:21,1 +DA:22,1 +DA:23,1 +DA:24,1 +LF:10 +LH:10 +end_of_record +SF:lib/src/core/models/custom_notification_model.dart +DA:5,0 +DA:7,0 +DA:8,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:45,2 +DA:54,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:72,0 +DA:74,0 +DA:77,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:89,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +LF:37 +LH:1 +end_of_record +SF:lib/src/features/about/bloc/about_bloc.dart +DA:11,3 +DA:12,2 +DA:15,1 +DA:20,2 +DA:21,2 +DA:22,2 +DA:24,1 +DA:25,1 +DA:26,2 +LF:9 +LH:9 +end_of_record +SF:lib/src/features/about/bloc/about_state.dart +DA:10,1 +DA:18,1 +LF:2 +LH:2 +end_of_record SF:lib/src/features/auth/bloc/auth_bloc.dart DA:12,3 DA:13,2 @@ -2125,70 +2232,76 @@ DA:75,2 LF:33 LH:33 end_of_record -SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart -DA:12,1 -DA:21,1 -DA:33,1 -LF:3 -LH:3 -end_of_record -SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_event.dart -DA:9,1 -DA:16,1 +SF:lib/src/features/bookcase/bloc/bookcase_state.dart +DA:10,2 +DA:20,2 LF:2 LH:2 end_of_record -SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart -DA:15,1 -DA:18,2 +SF:lib/src/features/bookcase/bloc/bookcase_bloc.dart +DA:16,1 DA:19,2 DA:20,2 -DA:23,1 -DA:28,2 +DA:21,2 +DA:22,2 +DA:25,1 DA:30,2 DA:32,1 DA:33,1 -DA:34,1 -DA:42,1 -DA:43,2 -DA:46,1 +DA:34,4 +DA:35,1 +DA:36,3 +DA:40,1 +DA:45,2 DA:47,2 DA:48,1 DA:49,4 -DA:56,1 -DA:57,1 -DA:58,1 -DA:61,1 -DA:66,1 -DA:67,2 +DA:50,1 +DA:51,3 +DA:55,1 +DA:60,2 +DA:62,1 +DA:64,2 +DA:65,2 +DA:66,2 DA:68,2 DA:69,1 -DA:70,2 -DA:71,1 -DA:75,1 -DA:80,2 -DA:82,1 -DA:84,2 -DA:85,2 -DA:86,1 -DA:87,1 -DA:90,1 -DA:91,1 -DA:92,1 -DA:93,2 -DA:100,2 -DA:101,1 -DA:102,2 -DA:103,2 -DA:104,1 -DA:105,2 -DA:106,1 -LF:44 -LH:44 +DA:70,1 +DA:77,1 +DA:78,1 +DA:79,4 +DA:80,1 +DA:81,3 +DA:85,1 +DA:86,2 +DA:88,1 +DA:89,2 +DA:93,1 +DA:96,1 +DA:98,2 +DA:100,1 +DA:101,2 +DA:105,1 +DA:108,1 +DA:112,1 +DA:114,2 +DA:115,1 +DA:116,1 +DA:117,3 +DA:122,2 +DA:123,1 +DA:129,2 +DA:132,1 +DA:137,1 +DA:140,2 +LF:55 +LH:55 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 +SF:lib/src/features/bookcase/bloc/bookcase_event.dart +DA:10,1 +DA:18,1 +LF:2 +LH:2 end_of_record SF:lib/src/core/dtos/bookcase_dto.dart DA:7,2 @@ -2206,6 +2319,10 @@ DA:35,0 LF:12 LH:3 end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 DA:10,0 @@ -2379,77 +2496,6 @@ DA:33,0 LF:13 LH:0 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_state.dart -DA:10,2 -DA:20,2 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_bloc.dart -DA:16,1 -DA:19,2 -DA:20,2 -DA:21,2 -DA:22,2 -DA:25,1 -DA:30,2 -DA:32,1 -DA:33,1 -DA:34,4 -DA:35,1 -DA:36,3 -DA:40,1 -DA:45,2 -DA:47,2 -DA:48,1 -DA:49,4 -DA:50,1 -DA:51,3 -DA:55,1 -DA:60,2 -DA:62,1 -DA:64,2 -DA:65,2 -DA:66,2 -DA:68,2 -DA:69,1 -DA:70,1 -DA:77,1 -DA:78,1 -DA:79,4 -DA:80,1 -DA:81,3 -DA:85,1 -DA:86,2 -DA:88,1 -DA:89,2 -DA:93,1 -DA:96,1 -DA:98,2 -DA:100,1 -DA:101,2 -DA:105,1 -DA:108,1 -DA:112,1 -DA:114,2 -DA:115,1 -DA:116,1 -DA:117,3 -DA:122,2 -DA:123,1 -DA:129,2 -DA:132,1 -DA:137,1 -DA:140,2 -LF:55 -LH:55 -end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_event.dart -DA:10,1 -DA:18,1 -LF:2 -LH:2 -end_of_record SF:lib/src/features/bookcase/views/bookcase_page.dart DA:14,1 DA:19,1 @@ -2954,6 +3000,67 @@ DA:84,3 LF:32 LH:26 end_of_record +SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart +DA:12,1 +DA:21,1 +DA:33,1 +LF:3 +LH:3 +end_of_record +SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_event.dart +DA:9,1 +DA:16,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart +DA:15,1 +DA:18,2 +DA:19,2 +DA:20,2 +DA:23,1 +DA:28,2 +DA:30,2 +DA:32,1 +DA:33,1 +DA:34,1 +DA:42,1 +DA:43,2 +DA:46,1 +DA:47,2 +DA:48,1 +DA:49,4 +DA:56,1 +DA:57,1 +DA:58,1 +DA:61,1 +DA:66,1 +DA:67,2 +DA:68,2 +DA:69,1 +DA:70,2 +DA:71,1 +DA:75,1 +DA:80,2 +DA:82,1 +DA:84,2 +DA:85,2 +DA:86,1 +DA:87,1 +DA:90,1 +DA:91,1 +DA:92,1 +DA:93,2 +DA:100,2 +DA:101,1 +DA:102,2 +DA:103,2 +DA:104,1 +DA:105,2 +DA:106,1 +LF:44 +LH:44 +end_of_record SF:lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart DA:16,0 DA:21,0 @@ -3623,47 +3730,6 @@ DA:98,2 LF:37 LH:37 end_of_record -SF:lib/src/core/models/custom_notification_model.dart -DA:5,0 -DA:7,0 -DA:8,0 -DA:12,0 -DA:14,0 -DA:15,0 -DA:19,0 -DA:21,0 -DA:23,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:45,2 -DA:54,0 -DA:62,0 -DA:63,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:72,0 -DA:74,0 -DA:77,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:89,0 -DA:91,0 -DA:92,0 -DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -LF:37 -LH:1 -end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:19,1 DA:23,2 diff --git a/lib/src/bookify_app.dart b/lib/src/bookify_app.dart index f97a20fa..54f500d1 100644 --- a/lib/src/bookify_app.dart +++ b/lib/src/bookify_app.dart @@ -1,10 +1,8 @@ -import 'dart:async'; - -import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; +import 'package:bookify/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart'; +import 'package:bookify/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart'; import 'package:bookify/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart'; import 'package:bookify/src/shared/routes/routes.dart'; import 'package:bookify/src/shared/theme/app_theme.dart'; -import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; @@ -20,69 +18,62 @@ class BookifyApp extends StatefulWidget { } class _BookifyAppState extends State { - late final UserThemeCubit _userThemeCubit; - @override void initState() { super.initState(); - _userThemeCubit = context.read()..getTheme(); - WidgetsBinding.instance.addPostFrameCallback( - (_) => _checkForNotificationsOnInitializeApp(), - ); - } + LocalJsonLocalization.delegate.directories = ['assets/lang']; - void _checkForNotificationsOnInitializeApp() { - final notificationService = context.read(); - unawaited(notificationService.checkForNotifications()); + context.read().getTheme(); + context.read().checkAuthStatus(); + context.read().initializeNotifications(); } @override Widget build(BuildContext context) { - LocalJsonLocalization.delegate.directories = ['assets/lang']; + final themeMode = context.select( + (cubit) => switch (cubit.state) { + UserThemeLoadedState(:final themeMode) => themeMode, + _ => ThemeMode.system, + }, + ); - return BlocBuilder( - bloc: _userThemeCubit, - builder: (context, state) { - final themeMode = switch (state) { - UserThemeLoadedState(:final themeMode) => themeMode, - _ => ThemeMode.system, - }; + final isLoggedIn = context.select( + (cubit) => + cubit.state is UserLoggedLoadedState && + (cubit.state as UserLoggedLoadedState).isLoggedIn, + ); - return MaterialApp( - title: 'Bookify', - theme: appLightTheme, - darkTheme: appDarkTheme, - themeMode: themeMode, - navigatorKey: Routes.navigatorKey, - routes: Routes.routes, - initialRoute: Routes.getInitialRoute( - FirebaseAuth.instance.currentUser != null, - ), - localeResolutionCallback: (locale, supportedLocales) { - if (supportedLocales.contains(locale)) { - return locale; - } + return MaterialApp( + title: 'Bookify', + theme: appLightTheme, + darkTheme: appDarkTheme, + themeMode: themeMode, + navigatorKey: Routes.navigatorKey, + routes: Routes.routes, + initialRoute: Routes.getInitialRoute(isLoggedIn), + localeResolutionCallback: (locale, supportedLocales) { + if (supportedLocales.contains(locale)) { + return locale; + } - if (locale?.languageCode == 'pt') { - return Locale('pt', 'BR'); - } + if (locale?.languageCode == 'pt') { + return Locale('pt', 'BR'); + } - return Locale('en', 'US'); - }, - localizationsDelegates: [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - LocalJsonLocalization.delegate, - ], - supportedLocales: const [ - Locale('pt', 'BR'), - Locale('en', 'US'), - Locale('it', 'IT'), - ], - ); + return Locale('en', 'US'); }, + localizationsDelegates: [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + LocalJsonLocalization.delegate, + ], + supportedLocales: const [ + Locale('pt', 'BR'), + Locale('en', 'US'), + Locale('it', 'IT'), + ], ); } } diff --git a/lib/src/core/repositories/auth_repository/auth_repository.dart b/lib/src/core/repositories/auth_repository/auth_repository.dart index cb02da2b..4590459f 100644 --- a/lib/src/core/repositories/auth_repository/auth_repository.dart +++ b/lib/src/core/repositories/auth_repository/auth_repository.dart @@ -3,5 +3,5 @@ import 'package:bookify/src/core/models/user_model.dart'; abstract interface class AuthRepository { Future getUserModel(); Future setUserModel({required UserModel userModel}); - Future clearUserData(); + Future deleteUserModel(); } diff --git a/lib/src/core/repositories/auth_repository/auth_repository_impl.dart b/lib/src/core/repositories/auth_repository/auth_repository_impl.dart index 348bb73b..708155f1 100644 --- a/lib/src/core/repositories/auth_repository/auth_repository_impl.dart +++ b/lib/src/core/repositories/auth_repository/auth_repository_impl.dart @@ -49,9 +49,9 @@ class AuthRepositoryImpl implements AuthRepository { } @override - Future clearUserData() async { + Future deleteUserModel() async { try { - return await _storage.deleteAllStorage(); + return await _storage.deleteStorage(key: _userKey); } on StorageException { rethrow; } diff --git a/lib/src/core/services/auth_service/auth_service.dart b/lib/src/core/services/auth_service/auth_service.dart index f11b468d..5715e455 100644 --- a/lib/src/core/services/auth_service/auth_service.dart +++ b/lib/src/core/services/auth_service/auth_service.dart @@ -5,4 +5,5 @@ abstract interface class AuthService { Future signIn({required SignInType signInType}); Future signOut({required SignInType signInType}); Future getUserModel(); + Future userIsLoggedIn(); } diff --git a/lib/src/core/services/auth_service/auth_service_impl.dart b/lib/src/core/services/auth_service/auth_service_impl.dart index f4d0fb0e..a12e7ad1 100644 --- a/lib/src/core/services/auth_service/auth_service_impl.dart +++ b/lib/src/core/services/auth_service/auth_service_impl.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/repositories/auth_repository/auth_repository.dart'; import 'package:bookify/src/shared/enums/sign_in_type.dart'; +import 'package:firebase_auth/firebase_auth.dart'; import 'auth_service.dart'; import 'auth_strategy/auth_strategy_factory.dart'; @@ -17,6 +18,17 @@ class AuthServiceImpl implements AuthService { }) : _authRepository = authRepository, _authStrategyFactory = authStrategyFactory; + @override + Future userIsLoggedIn() async { + final userIsLoggedIn = FirebaseAuth.instance.currentUser != null; + + if (!userIsLoggedIn) { + await _authRepository.deleteUserModel(); + return false; + } + return true; + } + @override Future signIn({required SignInType signInType}) async { try { @@ -44,7 +56,7 @@ class AuthServiceImpl implements AuthService { final strategyResult = await authStrategy.signOut(); if (strategyResult) { - await _authRepository.clearUserData(); + await _authRepository.deleteUserModel(); } return strategyResult; } on AuthException { diff --git a/lib/src/features/reading_page_timer/views/widgets/reading_page_timer_loaded_state_widget.dart b/lib/src/features/reading_page_timer/views/widgets/reading_page_timer_loaded_state_widget.dart index 71ddbe98..971e3333 100644 --- a/lib/src/features/reading_page_timer/views/widgets/reading_page_timer_loaded_state_widget.dart +++ b/lib/src/features/reading_page_timer/views/widgets/reading_page_timer_loaded_state_widget.dart @@ -57,8 +57,13 @@ class _ReadingPageTimerLoadedStateWidgetState } @override - Future dispose() async { + Future deactivate() async { await _stopWatchTimer.dispose(); + super.deactivate(); + } + + @override + void dispose() { _isTimerRunningNotifier.dispose(); WidgetsBinding.instance.removeObserver(this); super.dispose(); diff --git a/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart b/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart new file mode 100644 index 00000000..e9f40b86 --- /dev/null +++ b/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart @@ -0,0 +1,38 @@ +import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; +import 'package:bookify/src/core/services/auth_service/auth_service.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'user_logged_state.dart'; + +class UserLoggedCubit extends Cubit { + final AuthService _authService; + + UserLoggedCubit( + this._authService, + ) : super(UserLoggedLoadingState()); + + Future checkAuthStatus() async { + try { + emit(UserLoggedLoadingState()); + + final isLoggedIn = await _authService.userIsLoggedIn(); + + emit( + UserLoggedLoadedState(isLoggedIn: isLoggedIn), + ); + } on AuthException catch (e) { + emit( + UserLoggedErrorState( + errorMessage: 'Erro ao verificar a sessão: ${e.message}', + ), + ); + } on Exception catch (e) { + emit( + UserLoggedErrorState( + errorMessage: 'Erro inesperado: $e', + ), + ); + } + } +} diff --git a/lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart b/lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart new file mode 100644 index 00000000..6b1e8402 --- /dev/null +++ b/lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart @@ -0,0 +1,22 @@ +part of 'user_logged_cubit.dart'; + +@immutable +sealed class UserLoggedState {} + +final class UserLoggedLoadingState extends UserLoggedState {} + +final class UserLoggedLoadedState extends UserLoggedState { + final bool isLoggedIn; + + UserLoggedLoadedState({ + required this.isLoggedIn, + }); +} + +final class UserLoggedErrorState extends UserLoggedState { + final String errorMessage; + + UserLoggedErrorState({ + required this.errorMessage, + }); +} diff --git a/lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart b/lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart new file mode 100644 index 00000000..13c07fa4 --- /dev/null +++ b/lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart @@ -0,0 +1,29 @@ +import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +part 'user_notification_state.dart'; + +class UserNotificationCubit extends Cubit { + final NotificationsService _notificationsService; + + UserNotificationCubit( + this._notificationsService, + ) : super(UserNotificationLoadingState()); + + Future initializeNotifications() async { + try { + emit(UserNotificationLoadingState()); + + await _notificationsService.checkForNotifications(); + + emit(UserNotificationLoadedState()); + } on Exception catch (e) { + emit( + UserNotificationErrorState( + errorMessage: 'Erro ao inicializar as notificações: $e', + ), + ); + } + } +} diff --git a/lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart b/lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart new file mode 100644 index 00000000..c4294fb0 --- /dev/null +++ b/lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart @@ -0,0 +1,16 @@ +part of 'user_notification_cubit.dart'; + +@immutable +sealed class UserNotificationState {} + +final class UserNotificationLoadingState extends UserNotificationState {} + +final class UserNotificationLoadedState extends UserNotificationState {} + +final class UserNotificationErrorState extends UserNotificationState { + final String errorMessage; + + UserNotificationErrorState({ + required this.errorMessage, + }); +} diff --git a/lib/src/shared/providers/blocs/blocs_providers.dart b/lib/src/shared/providers/blocs/blocs_providers.dart index 70ba153b..13531df9 100644 --- a/lib/src/shared/providers/blocs/blocs_providers.dart +++ b/lib/src/shared/providers/blocs/blocs_providers.dart @@ -1,4 +1,6 @@ -export 'package:bookify/src/shared/providers/blocs/user_theme_bloc_providers.dart'; +export 'package:bookify/src/shared/providers/blocs/user_theme_cubit_providers.dart'; +export 'package:bookify/src/shared/providers/blocs/user_logged_cubit_providers.dart'; +export 'package:bookify/src/shared/providers/blocs/user_notification_cubit_providers.dart'; export 'package:bookify/src/shared/providers/blocs/user_information_bloc_providers.dart'; export 'package:bookify/src/shared/providers/blocs/auth_bloc_providers.dart'; export 'package:bookify/src/shared/providers/blocs/about_bloc_providers.dart'; diff --git a/lib/src/shared/providers/blocs/user_logged_cubit_providers.dart b/lib/src/shared/providers/blocs/user_logged_cubit_providers.dart new file mode 100644 index 00000000..e053e3e9 --- /dev/null +++ b/lib/src/shared/providers/blocs/user_logged_cubit_providers.dart @@ -0,0 +1,10 @@ +import 'package:bookify/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +final userLoggedCubitProviders = [ + BlocProvider( + create: (context) => UserLoggedCubit( + context.read(), + ), + ), +]; diff --git a/lib/src/shared/providers/blocs/user_notification_cubit_providers.dart b/lib/src/shared/providers/blocs/user_notification_cubit_providers.dart new file mode 100644 index 00000000..aeb33e21 --- /dev/null +++ b/lib/src/shared/providers/blocs/user_notification_cubit_providers.dart @@ -0,0 +1,10 @@ +import 'package:bookify/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +final userNotificationCubitProviders = [ + BlocProvider( + create: (context) => UserNotificationCubit( + context.read(), + ), + ), +]; diff --git a/lib/src/shared/providers/blocs/user_theme_bloc_providers.dart b/lib/src/shared/providers/blocs/user_theme_cubit_providers.dart similarity index 87% rename from lib/src/shared/providers/blocs/user_theme_bloc_providers.dart rename to lib/src/shared/providers/blocs/user_theme_cubit_providers.dart index 4adab0c7..3a11f7a4 100644 --- a/lib/src/shared/providers/blocs/user_theme_bloc_providers.dart +++ b/lib/src/shared/providers/blocs/user_theme_cubit_providers.dart @@ -1,7 +1,7 @@ import 'package:bookify/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -final userThemeBlocProviders = [ +final userThemeCubitProviders = [ BlocProvider( create: (context) => UserThemeCubit( context.read(), diff --git a/lib/src/shared/providers/providers.dart b/lib/src/shared/providers/providers.dart index 07d0e230..be7ba7d6 100644 --- a/lib/src/shared/providers/providers.dart +++ b/lib/src/shared/providers/providers.dart @@ -14,7 +14,9 @@ abstract class Providers { ...appServicesProviders, ...userSettingsServicesProviders, ...servicesProviders, - ...userThemeBlocProviders, + ...userThemeCubitProviders, + ...userLoggedCubitProviders, + ...userNotificationCubitProviders, ...userInformationBlocProviders, ...authBlocProviders, ...readingPageTimerBlocProviders, diff --git a/pubspec.yaml b/pubspec.yaml index 7c18e30f..4107bdab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.1 +version: 2.11.2 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart b/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart index 050c47bd..a478dd76 100644 --- a/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart +++ b/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart @@ -64,6 +64,19 @@ void main() { expect(userModelInserted, equals(1)); }); + + test('Test delete UserModel', () async { + when( + () => storage.deleteStorage( + key: any(named: 'key'), + ), + ).thenAnswer( + (_) async => 1, + ); + final userModelDeleted = await authRepository.deleteUserModel(); + + expect(userModelDeleted, equals(1)); + }); }); group('Test normal crud with error', () { @@ -78,9 +91,11 @@ void main() { expect( () async => await authRepository.getUserModel(), - throwsA((Exception e) => - e is StorageException && - e.message == 'impossível converter o usuário.'), + throwsA( + (Exception e) => + e is StorageException && + e.message == 'impossível converter o usuário.', + ), ); }); @@ -93,8 +108,10 @@ void main() { expect( () async => await authRepository.getUserModel(), - throwsA((Exception e) => - e is StorageException && e.message == 'Storage error'), + throwsA( + (Exception e) => + e is StorageException && e.message == 'Storage error', + ), ); }); @@ -110,8 +127,26 @@ void main() { () async => await authRepository.setUserModel( userModel: userModel, ), - throwsA((Exception e) => - e is StorageException && e.message == 'Storage error'), + throwsA( + (Exception e) => + e is StorageException && e.message == 'Storage error', + ), + ); + }); + + test('Test delete UserModel with Storage Exception', () async { + when( + () => storage.deleteStorage( + key: any(named: 'key'), + ), + ).thenThrow(const StorageException('Storage error')); + + expect( + () async => await authRepository.deleteUserModel(), + throwsA( + (Exception e) => + e is StorageException && e.message == 'Storage error', + ), ); }); }); diff --git a/test/src/core/services/auth_service/auth_service_impl_test.dart b/test/src/core/services/auth_service/auth_service_impl_test.dart index e9141c7b..36472e7c 100644 --- a/test/src/core/services/auth_service/auth_service_impl_test.dart +++ b/test/src/core/services/auth_service/auth_service_impl_test.dart @@ -108,14 +108,14 @@ void main() { () => authStrategyFactory.create(SignInType.google), ).thenReturn(authStrategy); when(() => authStrategy.signOut()).thenAnswer((_) async => true); - when(() => authRepository.clearUserData()).thenAnswer((_) async => 1); + when(() => authRepository.deleteUserModel()).thenAnswer((_) async => 1); final result = await authService.signOut(signInType: SignInType.google); expect(result, isTrue); verify(() => authStrategyFactory.create(SignInType.google)).called(1); verify(() => authStrategy.signOut()).called(1); - verify(() => authRepository.clearUserData()).called(1); + verify(() => authRepository.deleteUserModel()).called(1); }, ); diff --git a/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart b/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart new file mode 100644 index 00000000..8b2c3554 --- /dev/null +++ b/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart @@ -0,0 +1,98 @@ +import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; +import 'package:bookify/src/core/services/auth_service/auth_service.dart'; +import 'package:bookify/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +class AuthServiceMock extends Mock implements AuthService {} + +void main() { + final authService = AuthServiceMock(); + late UserLoggedCubit userLoggedCubit; + + setUp(() { + userLoggedCubit = UserLoggedCubit( + authService, + ); + }); + + group('Test UserLogged Cubit', () { + blocTest( + 'Initial state is empty', + build: () => userLoggedCubit, + verify: (cubit) async => await cubit.close(), + expect: () => [], + ); + + blocTest( + 'Test checkAuthStatus function work when user is logged in', + build: () => userLoggedCubit, + setUp: () => + when( + () => authService.userIsLoggedIn(), + ).thenAnswer( + (_) async => true, + ), + act: (cubit) => cubit.checkAuthStatus(), + verify: (_) => verify( + () => authService.userIsLoggedIn(), + ).called(1), + expect: () => [ + isA(), + isA(), + ], + ); + + blocTest( + 'Test checkAuthStatus function work when user is NOT logged in', + build: () => userLoggedCubit, + setUp: () => + when( + () => authService.userIsLoggedIn(), + ).thenAnswer( + (_) async => false, + ), + act: (cubit) => cubit.checkAuthStatus(), + verify: (_) => verify( + () => authService.userIsLoggedIn(), + ).called(1), + expect: () => [ + isA(), + isA(), + ], + ); + + blocTest( + 'Test checkAuthStatus function work when throw AuthException', + build: () => userLoggedCubit, + setUp: () => when( + () => authService.userIsLoggedIn(), + ).thenThrow(const AuthException('Error on Auth Service')), + act: (cubit) => cubit.checkAuthStatus(), + verify: (_) => verify( + () => authService.userIsLoggedIn(), + ).called(1), + expect: () => [ + isA(), + isA(), + ], + ); + + blocTest( + 'Test checkAuthStatus function work when throw Generic Exception', + build: () => userLoggedCubit, + setUp: () => when( + () => authService.userIsLoggedIn(), + ).thenThrow(Exception('Generic Error')), + act: (cubit) => cubit.checkAuthStatus(), + verify: (_) => verify( + () => authService.userIsLoggedIn(), + ).called(1), + expect: () => [ + isA(), + isA(), + ], + ); + }); +} diff --git a/test/src/shared/cubits/user_notification_cubit/user_notification_cubit_test.dart b/test/src/shared/cubits/user_notification_cubit/user_notification_cubit_test.dart new file mode 100644 index 00000000..6395e6ad --- /dev/null +++ b/test/src/shared/cubits/user_notification_cubit/user_notification_cubit_test.dart @@ -0,0 +1,62 @@ +import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; +import 'package:bookify/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mocktail/mocktail.dart'; + +class NotificationsServiceMock extends Mock implements NotificationsService {} + +void main() { + final notificationsService = NotificationsServiceMock(); + late UserNotificationCubit userNotificationCubit; + + setUp(() { + userNotificationCubit = UserNotificationCubit( + notificationsService, + ); + }); + + group('Test UserNotification Cubit', () { + blocTest( + 'Initial state is empty', + build: () => userNotificationCubit, + verify: (cubit) async => await cubit.close(), + expect: () => [], + ); + + blocTest( + 'Test initializeNotifications function work', + build: () => userNotificationCubit, + setUp: () => + when( + () => notificationsService.checkForNotifications(), + ).thenAnswer( + (_) async {}, // Simula il completamento di Future + ), + act: (cubit) => cubit.initializeNotifications(), + verify: (_) => verify( + () => notificationsService.checkForNotifications(), + ).called(1), + expect: () => [ + isA(), + isA(), + ], + ); + + blocTest( + 'Test initializeNotifications function work when throw Generic Exception', + build: () => userNotificationCubit, + setUp: () => when( + () => notificationsService.checkForNotifications(), + ).thenThrow(Exception('Generic Error')), + act: (cubit) => cubit.initializeNotifications(), + verify: (_) => verify( + () => notificationsService.checkForNotifications(), + ).called(1), + expect: () => [ + isA(), + isA(), + ], + ); + }); +} diff --git a/test/src/shared/blocs/user_theme_cubit/user_theme_cubit_test.dart b/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart similarity index 100% rename from test/src/shared/blocs/user_theme_cubit/user_theme_cubit_test.dart rename to test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart From f6d849cbc1e439f45aad0d974aaf94bbbfe10304 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Thu, 23 Apr 2026 16:07:17 -0300 Subject: [PATCH 06/19] feat: Enhance error messages for better user guidance and update version to 2.11.3 Co-authored-by: Copilot --- assets/lang/en_US.json | 12 +-- assets/lang/it_IT.json | 12 +-- assets/lang/pt_BR.json | 12 +-- coverage/lcov.info | 161 ++++++++++++++++------------------------- pubspec.yaml | 2 +- 5 files changed, 82 insertions(+), 117 deletions(-) diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index eed3b55d..e8bb813e 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -244,10 +244,10 @@ "book-on-reading-label": "on reading", "previous-month-tooltip": "Previous month", "next-month-tooltip": "Next month", - "error-rest-client-connection-timeout": "Connection timeout: %s", - "error-rest-client-receive-timeout": "Receive timeout: %s", - "error-rest-client-not-found": "Not found: %s", - "error-rest-client-socket-exception": "Network error: %s", - "error-invalid-isbn": "Invalid ISBN: %s", - "error-unknown": "Unexpected error: %s" + "error-rest-client-connection-timeout": "Connection to server failed due to timeout. Check your internet connection and try again: %s", + "error-rest-client-receive-timeout": "Server response took too long to arrive. Verify your connection quality and retry: %s", + "error-rest-client-not-found": "The requested resource was not found. Verify your search terms or try a different query: %s", + "error-rest-client-socket-exception": "Network connection error detected. Check your internet connection and try again: %s", + "error-invalid-isbn": "The ISBN format is invalid. Enter a valid ISBN number (10 or 13 digits): %s", + "error-unknown": "An unexpected error occurred. Please try again later or contact support: %s" } diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index 180cdd4a..5bfc8952 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -244,10 +244,10 @@ "book-on-reading-label": "in lettura", "previous-month-tooltip": "Mese precedente", "next-month-tooltip": "Mese successivo", - "error-rest-client-connection-timeout": "Timeout connessione: %s", - "error-rest-client-receive-timeout": "Timeout risposta: %s", - "error-rest-client-not-found": "Risorsa non trovata: %s", - "error-rest-client-socket-exception": "Errore di rete: %s", - "error-invalid-isbn": "ISBN non valido: %s", - "error-unknown": "Errore imprevisto: %s" + "error-rest-client-connection-timeout": "La connessione al server è scaduta. Controlla la tua connessione internet e riprova: %s", + "error-rest-client-receive-timeout": "Il server ha impiegato troppo tempo per rispondere. Verifica la qualità della connessione e riprova: %s", + "error-rest-client-not-found": "La risorsa cercata non è stata trovata. Verifica i termini di ricerca o prova una query diversa: %s", + "error-rest-client-socket-exception": "Errore di connessione di rete rilevato. Controlla la tua connessione internet e riprova: %s", + "error-invalid-isbn": "Il formato dell'ISBN non è valido. Inserisci un numero ISBN valido (10 o 13 cifre): %s", + "error-unknown": "Si è verificato un errore imprevisto. Riprova più tardi o contatta il supporto: %s" } diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index 95d22263..3b8e62ab 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -244,10 +244,10 @@ "book-on-reading-label": "em empréstimo", "previous-month-tooltip": "Mês anterior", "next-month-tooltip": "Próximo mês", - "error-rest-client-connection-timeout": "Tempo esgotado: %s", - "error-rest-client-receive-timeout": "O servidor não respondeu: %s", - "error-rest-client-not-found": "Não encontrado: %s", - "error-rest-client-socket-exception": "Erro de conexão: %s", - "error-invalid-isbn": "ISBN inválido: %s", - "error-unknown": "Erro inesperado: %s" + "error-rest-client-connection-timeout": "A conexão com o servidor expirou. Verifique sua conexão de internet e tente novamente: %s", + "error-rest-client-receive-timeout": "O servidor demorou muito para responder. Verifique a qualidade da sua conexão e tente novamente: %s", + "error-rest-client-not-found": "O recurso solicitado não foi encontrado. Verifique os termos de pesquisa ou tente uma busca diferente: %s", + "error-rest-client-socket-exception": "Erro de conexão de rede detectado. Verifique sua conexão de internet e tente novamente: %s", + "error-invalid-isbn": "O formato do ISBN é inválido. Digite um número ISBN válido (10 ou 13 dígitos): %s", + "error-unknown": "Ocorreu um erro inesperado. Tente novamente mais tarde ou entre em contato com o suporte: %s" } diff --git a/coverage/lcov.info b/coverage/lcov.info index f5b26b3b..9a3faef0 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -471,34 +471,6 @@ DA:122,1 LF:37 LH:37 end_of_record -SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart -DA:11,1 -DA:13,1 -DA:16,2 -DA:17,1 -DA:22,1 -DA:24,1 -DA:26,0 -DA:33,1 -DA:36,2 -DA:37,1 -DA:42,1 -DA:43,1 -DA:46,2 -DA:48,1 -DA:50,0 -DA:55,1 -DA:58,2 -DA:59,1 -DA:60,1 -DA:64,1 -DA:69,1 -DA:72,2 -DA:73,1 -DA:79,1 -LF:24 -LH:22 -end_of_record SF:lib/src/core/repositories/books_repository/books_repository_impl.dart DA:11,1 DA:13,1 @@ -563,6 +535,34 @@ DA:199,1 LF:60 LH:60 end_of_record +SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart +DA:11,1 +DA:13,1 +DA:16,2 +DA:17,1 +DA:22,1 +DA:24,1 +DA:26,0 +DA:33,1 +DA:36,2 +DA:37,1 +DA:42,1 +DA:43,1 +DA:46,2 +DA:48,1 +DA:50,0 +DA:55,1 +DA:58,2 +DA:59,1 +DA:60,1 +DA:64,1 +DA:69,1 +DA:72,2 +DA:73,1 +DA:79,1 +LF:24 +LH:22 +end_of_record SF:lib/src/core/models/loan_model.dart DA:9,5 DA:18,1 @@ -866,6 +866,41 @@ DA:41,2 LF:13 LH:13 end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 +LH:0 +end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart DA:21,1 DA:33,1 @@ -943,76 +978,6 @@ DA:244,1 LF:73 LH:72 end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 -LH:0 -end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 -LH:0 -end_of_record SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart DA:11,1 DA:17,1 diff --git a/pubspec.yaml b/pubspec.yaml index 4107bdab..bb14b914 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.2 +version: 2.11.3 environment: sdk: ">=3.10.0 <4.0.0" From 9eb035747242cdc742d3aef50fd196af1535fcb5 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Tue, 28 Apr 2026 15:19:40 -0300 Subject: [PATCH 07/19] feat: Introduce error handling enums and extensions for authentication and storage - Added AuthErrorCode enum to categorize authentication errors. - Added StorageErrorCode enum to categorize storage-related errors. - Implemented AuthErrorCodeExtension for localized error messages based on AuthErrorCode. - Implemented StorageErrorCodeExtension for localized error messages based on StorageErrorCode. - Updated various test files to utilize new error handling mechanisms, ensuring proper exception handling and message verification. Co-authored-by: Copilot --- assets/lang/en_US.json | 15 +- assets/lang/it_IT.json | 15 +- assets/lang/pt_BR.json | 15 +- coverage/lcov.info | 578 ++++++++++-------- lib/src/core/enums/auth_error_code.dart | 11 + lib/src/core/enums/storage_error_code.dart | 8 + .../errors/auth_exception/auth_exception.dart | 12 +- .../storage_exception/storage_exception.dart | 12 +- .../auth_error_code_extension.dart | 34 ++ .../storage_error_code_extension.dart | 23 + .../auth_repository/auth_repository_impl.dart | 16 +- .../user_hour_time_repository_impl.dart | 19 +- ...ser_page_reading_time_repository_impl.dart | 32 +- .../user_theme_repository_impl.dart | 11 +- .../auth_service/auth_service_impl.dart | 31 +- .../auth_strategy/apple_auth_strategy.dart | 43 +- .../auth_strategy/facebook_auth_strategy.dart | 53 +- .../auth_strategy/google_auth_strategy.dart | 53 +- .../storage/shared_preference_storage.dart | 60 +- lib/src/features/auth/bloc/auth_bloc.dart | 11 +- lib/src/features/auth/bloc/auth_state.dart | 6 +- lib/src/features/auth/views/auth_page.dart | 8 +- .../features/profile/bloc/profile_bloc.dart | 30 +- .../features/profile/bloc/profile_state.dart | 6 +- .../features/profile/views/profile_page.dart | 23 +- .../user_logged_cubit/user_logged_cubit.dart | 7 +- .../user_logged_cubit/user_logged_state.dart | 6 +- pubspec.yaml | 2 +- .../auth_repository_impl_test.dart | 37 +- .../user_hour_time_repository_impl_test.dart | 27 +- ...age_reading_time_repository_impl_test.dart | 39 +- .../user_theme_repository_impl_test.dart | 40 +- .../auth_service/auth_service_impl_test.dart | 34 +- .../features/auth/bloc/auth_bloc_test.dart | 94 +-- .../book_pages_reading_time_bloc_test.dart | 37 +- .../profile/bloc/profile_bloc_test.dart | 11 +- .../bloc/programming_reading_bloc_test.dart | 200 +++--- .../bloc/reading_page_timer_bloc_test.dart | 64 +- .../bloc/readings_timer_bloc_test.dart | 35 +- .../user_logged_cubit_test.dart | 13 +- .../user_theme_cubit_test.dart | 36 +- 41 files changed, 1201 insertions(+), 606 deletions(-) create mode 100644 lib/src/core/enums/auth_error_code.dart create mode 100644 lib/src/core/enums/storage_error_code.dart create mode 100644 lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart create mode 100644 lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index e8bb813e..d39585ab 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -249,5 +249,18 @@ "error-rest-client-not-found": "The requested resource was not found. Verify your search terms or try a different query: %s", "error-rest-client-socket-exception": "Network connection error detected. Check your internet connection and try again: %s", "error-invalid-isbn": "The ISBN format is invalid. Enter a valid ISBN number (10 or 13 digits): %s", - "error-unknown": "An unexpected error occurred. Please try again later or contact support: %s" + "error-unknown": "An unexpected error occurred. Please try again later or contact support: %s", + "error-auth-user-not-found": "Unable to log in. Check that your email is registered or sign up if you don't have an account: %s", + "error-auth-wrong-password": "Incorrect password. Verify your credentials and try again: %s", + "error-auth-invalid-email": "Invalid email format. Enter a valid email address: %s", + "error-auth-account-disabled": "Your account has been temporarily disabled. Contact support for help: %s", + "error-auth-too-many-requests": "Too many login attempts. Wait a few minutes and try again: %s", + "error-auth-operation-not-allowed": "This authentication method is not available right now. Try again later: %s", + "error-auth-network-request-failed": "Connection lost. Check your internet connection and try again: %s", + "error-auth-internal-error": "Something went wrong. If the problem persists, please contact support: %s", + "error-storage-invalid-value": "Data storage issue detected. Try logging out and logging back in: %s", + "error-storage-data-loss": "Error saving your data. Try syncing again or contact support if the issue continues: %s", + "error-storage-not-found": "Your data could not be found. Try logging in again with your credentials: %s", + "error-storage-write-failed": "Unable to save your changes. Check your storage space and try again: %s", + "error-storage-read-failed": "Unable to load your data. Check your internet connection and try again: %s" } diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index 5bfc8952..b2ae4d09 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -249,5 +249,18 @@ "error-rest-client-not-found": "La risorsa cercata non è stata trovata. Verifica i termini di ricerca o prova una query diversa: %s", "error-rest-client-socket-exception": "Errore di connessione di rete rilevato. Controlla la tua connessione internet e riprova: %s", "error-invalid-isbn": "Il formato dell'ISBN non è valido. Inserisci un numero ISBN valido (10 o 13 cifre): %s", - "error-unknown": "Si è verificato un errore imprevisto. Riprova più tardi o contatta il supporto: %s" + "error-unknown": "Si è verificato un errore imprevisto. Riprova più tardi o contatta il supporto: %s", + "error-auth-user-not-found": "Impossibile accedere. Verifica che la tua email sia registrata o iscriviti se non hai ancora un account: %s", + "error-auth-wrong-password": "Password non corretta. Verifica le tue credenziali e riprova: %s", + "error-auth-invalid-email": "Formato email non valido. Inserisci un indirizzo email valido: %s", + "error-auth-account-disabled": "Il tuo account è stato temporaneamente disabilitato. Contatta l'assistenza per ricevere aiuto: %s", + "error-auth-too-many-requests": "Troppi tentativi di accesso. Attendi alcuni minuti e riprova: %s", + "error-auth-operation-not-allowed": "Questo metodo di autenticazione non è disponibile al momento. Riprova più tardi: %s", + "error-auth-network-request-failed": "Connessione persa. Verifica la tua connessione internet e riprova: %s", + "error-auth-internal-error": "Qualcosa è andato storto. Se il problema persiste, contatta l'assistenza: %s", + "error-storage-invalid-value": "Problema rilevato nel salvataggio dei dati. Prova a disconnetterti e riconnetterti: %s", + "error-storage-data-loss": "Errore durante il salvataggio dei dati. Prova a sincronizzare di nuovo o contatta l'assistenza se il problema persiste: %s", + "error-storage-not-found": "I tuoi dati non sono stati trovati. Prova ad accedere di nuovo con le tue credenziali: %s", + "error-storage-write-failed": "Impossibile salvare le tue modifiche. Verifica lo spazio di archiviazione e riprova: %s", + "error-storage-read-failed": "Impossibile caricare i tuoi dati. Verifica la tua connessione internet e riprova: %s" } diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index 3b8e62ab..94f2352a 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -249,5 +249,18 @@ "error-rest-client-not-found": "O recurso solicitado não foi encontrado. Verifique os termos de pesquisa ou tente uma busca diferente: %s", "error-rest-client-socket-exception": "Erro de conexão de rede detectado. Verifique sua conexão de internet e tente novamente: %s", "error-invalid-isbn": "O formato do ISBN é inválido. Digite um número ISBN válido (10 ou 13 dígitos): %s", - "error-unknown": "Ocorreu um erro inesperado. Tente novamente mais tarde ou entre em contato com o suporte: %s" + "error-unknown": "Ocorreu um erro inesperado. Tente novamente mais tarde ou entre em contato com o suporte: %s", + "error-auth-user-not-found": "Impossível fazer login. Verifique se seu email está registrado ou se inscreva se não tiver uma conta: %s", + "error-auth-wrong-password": "Senha incorreta. Verifique suas credenciais e tente novamente: %s", + "error-auth-invalid-email": "Formato de email inválido. Digite um endereço de email válido: %s", + "error-auth-account-disabled": "Sua conta foi temporariamente desativada. Entre em contato com o suporte para obter ajuda: %s", + "error-auth-too-many-requests": "Muitas tentativas de login. Aguarde alguns minutos e tente novamente: %s", + "error-auth-operation-not-allowed": "Este método de autenticação não está disponível no momento. Tente novamente mais tarde: %s", + "error-auth-network-request-failed": "Conexão perdida. Verifique sua conexão com a internet e tente novamente: %s", + "error-auth-internal-error": "Algo deu errado. Se o problema persistir, entre em contato com o suporte: %s", + "error-storage-invalid-value": "Problema detectado ao salvar dados. Tente fazer logout e depois login novamente: %s", + "error-storage-data-loss": "Erro ao salvar seus dados. Tente sincronizar novamente ou entre em contato com o suporte se o problema persistir: %s", + "error-storage-not-found": "Seus dados não foram encontrados. Tente fazer login novamente com suas credenciais: %s", + "error-storage-write-failed": "Impossível salvar suas alterações. Verifique o espaço de armazenamento e tente novamente: %s", + "error-storage-read-failed": "Impossível carregar seus dados. Verifique sua conexão com a internet e tente novamente: %s" } diff --git a/coverage/lcov.info b/coverage/lcov.info index 9a3faef0..54240cfc 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -219,9 +219,9 @@ LF:15 LH:8 end_of_record SF:lib/src/core/errors/storage_exception/storage_exception.dart -DA:4,2 -DA:6,5 -DA:7,5 +DA:7,4 +DA:12,5 +DA:13,15 LF:3 LH:3 end_of_record @@ -257,23 +257,27 @@ LF:27 LH:18 end_of_record SF:lib/src/core/repositories/auth_repository/auth_repository_impl.dart -DA:10,1 -DA:14,1 -DA:18,2 -DA:19,1 -DA:27,1 -DA:30,1 -DA:32,1 -DA:37,1 -DA:40,2 +DA:11,1 +DA:15,1 +DA:19,2 +DA:20,1 +DA:28,1 +DA:31,1 +DA:36,1 DA:41,1 -DA:42,1 +DA:44,2 DA:45,1 DA:46,1 -DA:51,1 -DA:54,3 -DA:55,1 -LF:16 +DA:49,1 +DA:50,1 +DA:53,0 +DA:55,0 +DA:60,1 +DA:63,3 +DA:64,1 +DA:67,0 +DA:69,0 +LF:20 LH:16 end_of_record SF:lib/src/shared/enums/sign_in_type.dart @@ -297,7 +301,7 @@ LF:3 LH:0 end_of_record SF:lib/src/core/errors/local_database_exception/local_database_exception.dart -DA:4,3 +DA:4,2 DA:6,1 DA:7,1 LF:3 @@ -801,52 +805,87 @@ LF:47 LH:31 end_of_record SF:lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart -DA:10,1 -DA:14,1 -DA:17,2 -DA:18,1 -DA:25,1 +DA:11,1 +DA:15,1 +DA:19,2 +DA:20,1 DA:28,1 -DA:30,1 -DA:35,1 -DA:40,2 +DA:31,1 +DA:36,1 DA:41,1 -DA:42,1 +DA:46,2 +DA:47,1 +DA:48,1 +DA:51,1 +DA:52,1 +DA:55,0 +DA:57,0 +LF:15 +LH:13 +end_of_record +SF:lib/src/features/readings_timer/bloc/readings_timer_state.dart +DA:12,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/readings_timer/bloc/readings_timer_bloc.dart +DA:11,1 +DA:12,2 +DA:13,2 +DA:16,1 +DA:21,2 +DA:23,2 +DA:26,2 +DA:30,1 +DA:32,1 +DA:33,1 +DA:37,1 +DA:38,1 +DA:39,1 +DA:40,1 +DA:43,1 +DA:44,1 DA:45,1 DA:46,1 -LF:13 -LH:13 +LF:18 +LH:18 end_of_record SF:lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart -DA:11,1 -DA:15,1 -DA:18,2 -DA:19,1 -DA:22,1 -DA:27,1 +DA:12,1 +DA:16,1 +DA:20,2 +DA:21,1 +DA:25,1 DA:30,1 DA:35,1 -DA:39,2 DA:40,1 -DA:41,1 -LF:11 -LH:11 +DA:45,2 +DA:46,1 +DA:47,1 +DA:51,1 +DA:54,0 +DA:56,0 +LF:14 +LH:12 end_of_record SF:lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart -DA:10,1 -DA:14,1 -DA:17,3 -DA:20,1 -DA:22,0 -DA:24,0 -DA:29,1 -DA:31,1 -DA:36,1 -DA:39,2 +DA:11,1 +DA:15,1 +DA:18,3 +DA:21,1 +DA:23,0 +DA:25,0 +DA:30,1 +DA:35,1 DA:40,1 -DA:41,1 +DA:43,2 DA:44,1 -LF:13 +DA:45,1 +DA:48,1 +DA:51,0 +DA:53,0 +LF:15 LH:11 end_of_record SF:lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart @@ -866,41 +905,6 @@ DA:41,2 LF:13 LH:13 end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 -LH:0 -end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart DA:21,1 DA:33,1 @@ -978,6 +982,41 @@ DA:244,1 LF:73 LH:72 end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 +LH:0 +end_of_record SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart DA:11,1 DA:17,1 @@ -1073,41 +1112,49 @@ LF:22 LH:22 end_of_record SF:lib/src/core/errors/auth_exception/auth_exception.dart -DA:4,1 -DA:6,0 -DA:7,0 +DA:7,1 +DA:12,0 +DA:13,0 LF:3 LH:1 end_of_record SF:lib/src/core/services/auth_service/auth_service_impl.dart -DA:15,1 -DA:21,0 -DA:23,0 -DA:26,0 -DA:32,1 -DA:35,2 -DA:37,1 -DA:38,2 -DA:43,1 -DA:45,1 -DA:46,2 -DA:47,0 -DA:48,0 -DA:52,1 -DA:55,2 -DA:56,1 -DA:59,2 -DA:62,1 -DA:64,0 -DA:65,0 -DA:69,0 +DA:16,1 +DA:22,0 +DA:24,0 +DA:27,0 +DA:33,1 +DA:36,2 +DA:38,1 +DA:39,2 +DA:44,1 +DA:46,1 +DA:47,1 +DA:49,1 +DA:51,0 +DA:52,0 +DA:54,0 +DA:59,1 +DA:62,2 +DA:63,1 +DA:66,2 +DA:69,1 +DA:71,0 DA:72,0 DA:74,0 -DA:75,0 DA:76,0 DA:77,0 -LF:26 -LH:13 +DA:79,0 +DA:84,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:92,0 +DA:94,0 +DA:95,0 +DA:97,0 +LF:34 +LH:14 end_of_record SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart DA:12,0 @@ -1123,103 +1170,148 @@ LF:9 LH:0 end_of_record SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart -DA:15,0 -DA:19,0 -DA:23,0 +DA:16,0 +DA:20,0 DA:24,0 DA:25,0 +DA:27,0 DA:28,0 -DA:29,0 -DA:30,0 DA:31,0 +DA:32,0 +DA:33,0 DA:34,0 DA:37,0 -DA:38,0 DA:40,0 DA:41,0 -DA:47,0 -DA:48,0 -DA:52,0 -DA:56,0 -DA:57,0 -DA:58,0 -DA:63,0 -DA:64,0 -DA:65,0 +DA:43,0 +DA:44,0 +DA:50,0 +DA:51,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:61,0 DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 DA:70,0 +DA:71,0 +DA:72,0 DA:73,0 -DA:75,0 -DA:76,0 +DA:74,0 DA:77,0 -DA:78,0 -LF:30 +DA:79,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:86,0 +DA:91,0 +DA:94,0 +DA:96,0 +DA:97,0 +DA:99,0 +DA:101,0 +DA:102,0 +DA:104,0 +LF:44 LH:0 end_of_record SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart -DA:16,0 -DA:22,0 -DA:26,0 +DA:17,0 +DA:23,0 DA:27,0 DA:28,0 +DA:30,0 DA:31,0 -DA:32,0 -DA:33,0 DA:34,0 +DA:35,0 +DA:36,0 DA:37,0 DA:40,0 -DA:41,0 DA:43,0 -DA:47,0 +DA:44,0 +DA:46,0 DA:50,0 -DA:51,0 -DA:52,0 -DA:56,0 -DA:57,0 -DA:61,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:75,0 -DA:76,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:64,0 +DA:68,0 +DA:69,0 +DA:70,0 DA:77,0 -DA:78,0 +DA:79,0 +DA:81,0 DA:82,0 +DA:83,0 +DA:84,0 DA:85,0 DA:86,0 +DA:87,0 DA:88,0 DA:89,0 -DA:90,0 -DA:91,0 -LF:34 +DA:93,0 +DA:95,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:102,0 +DA:107,0 +DA:110,0 +DA:111,0 +DA:113,0 +DA:114,0 +DA:116,0 +DA:118,0 +DA:119,0 +DA:121,0 +LF:50 LH:0 end_of_record SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart -DA:12,0 -DA:18,0 -DA:21,0 +DA:13,0 +DA:19,0 DA:22,0 -DA:27,0 -DA:29,0 +DA:23,0 +DA:25,0 DA:31,0 DA:32,0 DA:33,0 +DA:35,0 DA:36,0 +DA:37,0 DA:40,0 -DA:41,0 -DA:42,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:50,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:51,0 +DA:52,0 +DA:53,0 DA:54,0 +DA:55,0 +DA:56,0 DA:57,0 DA:58,0 -DA:60,0 -DA:61,0 -DA:62,0 +DA:59,0 DA:63,0 -LF:24 +DA:65,0 +DA:67,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:86,0 +DA:88,0 +DA:89,0 +DA:91,0 +LF:39 LH:0 end_of_record SF:lib/src/core/utils/verifier/isbn_verifier.dart @@ -1474,28 +1566,29 @@ LH:2 end_of_record SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart DA:11,1 -DA:19,1 +DA:20,1 LF:2 LH:2 end_of_record SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:11,1 -DA:13,2 -DA:15,1 -DA:17,2 -DA:19,2 -DA:21,1 +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 DA:22,1 -DA:24,1 +DA:23,1 DA:25,1 DA:26,1 -DA:27,2 -DA:30,1 -DA:31,1 +DA:27,1 +DA:28,1 +DA:29,1 DA:32,1 DA:33,1 -LF:15 -LH:15 +DA:34,1 +DA:36,1 +LF:16 +LH:16 end_of_record SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart DA:13,1 @@ -1557,6 +1650,10 @@ DA:96,0 LF:37 LH:1 end_of_record +SF:lib/src/features/readings_timer/bloc/readings_timer_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/features/about/bloc/about_bloc.dart DA:11,3 DA:12,2 @@ -1577,26 +1674,27 @@ LF:2 LH:2 end_of_record SF:lib/src/features/auth/bloc/auth_bloc.dart -DA:12,3 -DA:13,2 -DA:16,1 -DA:21,2 -DA:23,2 -DA:24,1 -DA:27,1 +DA:13,3 +DA:14,2 +DA:17,1 +DA:22,2 +DA:24,2 +DA:25,1 DA:28,1 DA:29,1 -DA:36,2 -DA:37,1 -DA:38,1 -DA:39,1 -DA:40,2 +DA:30,1 +DA:39,2 +DA:40,1 +DA:41,1 +DA:42,1 DA:43,1 DA:44,1 -DA:45,1 -DA:46,1 -LF:18 -LH:18 +DA:47,1 +DA:48,1 +DA:49,1 +DA:51,1 +LF:19 +LH:19 end_of_record SF:lib/src/features/auth/bloc/auth_event.dart DA:8,1 @@ -1604,7 +1702,7 @@ LF:1 LH:1 end_of_record SF:lib/src/features/auth/bloc/auth_state.dart -DA:14,1 +DA:15,1 LF:1 LH:1 end_of_record @@ -4012,45 +4110,49 @@ LH:14 end_of_record SF:lib/src/features/profile/bloc/profile_state.dart DA:10,1 -DA:20,1 +DA:21,1 LF:2 LH:2 end_of_record SF:lib/src/features/profile/bloc/profile_bloc.dart -DA:12,1 -DA:14,2 +DA:13,1 DA:15,2 DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:29,1 +DA:17,2 +DA:20,1 +DA:25,2 +DA:27,2 DA:30,1 -DA:37,1 -DA:38,1 -DA:42,1 -DA:43,2 -DA:44,2 +DA:31,1 +DA:40,1 +DA:41,1 DA:45,1 DA:46,1 DA:47,1 DA:48,1 +DA:49,1 +DA:52,1 +DA:53,1 DA:54,1 -DA:59,2 -DA:61,2 -DA:62,2 -DA:66,1 -DA:67,1 -DA:74,2 +DA:56,1 +DA:62,1 +DA:67,2 +DA:69,2 +DA:70,2 +DA:74,1 DA:75,1 -DA:76,2 -DA:77,2 -DA:78,1 -DA:79,1 -DA:80,1 -DA:81,1 -LF:32 -LH:32 +DA:83,2 +DA:84,1 +DA:85,1 +DA:86,1 +DA:87,1 +DA:88,1 +DA:91,1 +DA:92,1 +DA:93,1 +DA:95,1 +LF:36 +LH:36 end_of_record SF:lib/src/features/profile/bloc/profile_event.dart DA:10,1 @@ -4350,34 +4452,6 @@ DA:82,1 LF:29 LH:29 end_of_record -SF:lib/src/features/readings_timer/bloc/readings_timer_state.dart -DA:12,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/readings_timer/bloc/readings_timer_bloc.dart -DA:11,1 -DA:12,2 -DA:13,2 -DA:16,1 -DA:21,2 -DA:23,2 -DA:26,2 -DA:30,1 -DA:32,1 -DA:33,1 -DA:37,1 -DA:38,1 -DA:39,1 -DA:40,1 -DA:43,1 -DA:44,1 -DA:45,1 -DA:46,1 -LF:18 -LH:18 -end_of_record SF:lib/src/features/qr_code_scanner/views/qr_code_scanner_page.dart DA:13,1 DA:15,1 diff --git a/lib/src/core/enums/auth_error_code.dart b/lib/src/core/enums/auth_error_code.dart new file mode 100644 index 00000000..d9450e3e --- /dev/null +++ b/lib/src/core/enums/auth_error_code.dart @@ -0,0 +1,11 @@ +enum AuthErrorCode { + userNotFound, + wrongPassword, + invalidEmail, + accountDisabled, + tooManyRequests, + operationNotAllowed, + networkRequestFailed, + internalError, + unknown, +} diff --git a/lib/src/core/enums/storage_error_code.dart b/lib/src/core/enums/storage_error_code.dart new file mode 100644 index 00000000..fd6f0108 --- /dev/null +++ b/lib/src/core/enums/storage_error_code.dart @@ -0,0 +1,8 @@ +enum StorageErrorCode { + invalidValue, + dataLoss, + notFound, + writeFailed, + readFailed, + unknown, +} diff --git a/lib/src/core/errors/auth_exception/auth_exception.dart b/lib/src/core/errors/auth_exception/auth_exception.dart index e0f5601c..6273c7bf 100644 --- a/lib/src/core/errors/auth_exception/auth_exception.dart +++ b/lib/src/core/errors/auth_exception/auth_exception.dart @@ -1,8 +1,14 @@ +import 'package:bookify/src/core/enums/auth_error_code.dart'; + class AuthException implements Exception { - final String message; + final AuthErrorCode code; + final String? descriptionMessage; - const AuthException(this.message); + const AuthException( + this.code, { + this.descriptionMessage, + }); @override - String toString() => message; + String toString() => 'AuthException: [$code] $descriptionMessage'; } diff --git a/lib/src/core/errors/storage_exception/storage_exception.dart b/lib/src/core/errors/storage_exception/storage_exception.dart index a6f1bb09..b878bb48 100644 --- a/lib/src/core/errors/storage_exception/storage_exception.dart +++ b/lib/src/core/errors/storage_exception/storage_exception.dart @@ -1,8 +1,14 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; + class StorageException implements Exception { - final String message; + final StorageErrorCode code; + final String? descriptionMessage; - const StorageException(this.message); + const StorageException( + this.code, { + this.descriptionMessage, + }); @override - String toString() => message; + String toString() => 'StorageException: [$code] $descriptionMessage'; } diff --git a/lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart b/lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart new file mode 100644 index 00000000..4c0664e7 --- /dev/null +++ b/lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart @@ -0,0 +1,34 @@ +import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:localization/localization.dart'; + +extension AuthErrorCodeExtension on AuthErrorCode { + String toLocalizedMessage(String? descriptionMessage) { + final messageArg = descriptionMessage ?? '---'; + + return switch (this) { + AuthErrorCode.userNotFound => 'error-auth-user-not-found'.i18n([ + messageArg, + ]), + AuthErrorCode.wrongPassword => 'error-auth-wrong-password'.i18n([ + messageArg, + ]), + AuthErrorCode.invalidEmail => 'error-auth-invalid-email'.i18n([ + messageArg, + ]), + AuthErrorCode.accountDisabled => 'error-auth-account-disabled'.i18n([ + messageArg, + ]), + AuthErrorCode.tooManyRequests => 'error-auth-too-many-requests'.i18n([ + messageArg, + ]), + AuthErrorCode.operationNotAllowed => + 'error-auth-operation-not-allowed'.i18n([messageArg]), + AuthErrorCode.networkRequestFailed => + 'error-auth-network-request-failed'.i18n([messageArg]), + AuthErrorCode.internalError => 'error-auth-internal-error'.i18n([ + messageArg, + ]), + AuthErrorCode.unknown => 'error-unknown'.i18n([messageArg]), + }; + } +} diff --git a/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart b/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart new file mode 100644 index 00000000..520af7a8 --- /dev/null +++ b/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart @@ -0,0 +1,23 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:localization/localization.dart'; + +extension StorageErrorCodeExtension on StorageErrorCode { + String toLocalizedMessage(String? descriptionMessage) { + final messageArg = descriptionMessage ?? '---'; + + return switch (this) { + StorageErrorCode.invalidValue => 'error-storage-invalid-value'.i18n([ + messageArg, + ]), + StorageErrorCode.dataLoss => 'error-storage-data-loss'.i18n([messageArg]), + StorageErrorCode.notFound => 'error-storage-not-found'.i18n([messageArg]), + StorageErrorCode.writeFailed => 'error-storage-write-failed'.i18n([ + messageArg, + ]), + StorageErrorCode.readFailed => 'error-storage-read-failed'.i18n([ + messageArg, + ]), + StorageErrorCode.unknown => 'error-unknown'.i18n([messageArg]), + }; + } +} diff --git a/lib/src/core/repositories/auth_repository/auth_repository_impl.dart b/lib/src/core/repositories/auth_repository/auth_repository_impl.dart index 708155f1..9295abd5 100644 --- a/lib/src/core/repositories/auth_repository/auth_repository_impl.dart +++ b/lib/src/core/repositories/auth_repository/auth_repository_impl.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/repositories/auth_repository/auth_repository.dart'; @@ -28,7 +29,10 @@ class AuthRepositoryImpl implements AuthRepository { return userModel; } on TypeError { - throw const StorageException('impossível converter o usuário.'); + throw const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Expected a String value for user data.', + ); } on StorageException { rethrow; } @@ -45,6 +49,11 @@ class AuthRepositoryImpl implements AuthRepository { return (userJsonInserted == 1) ? 1 : 0; } on StorageException { rethrow; + } catch (e) { + throw StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: e.toString(), + ); } } @@ -54,6 +63,11 @@ class AuthRepositoryImpl implements AuthRepository { return await _storage.deleteStorage(key: _userKey); } on StorageException { rethrow; + } catch (e) { + throw StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart b/lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart index 8ce21bd7..a5e663f0 100644 --- a/lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart +++ b/lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; @@ -14,9 +15,11 @@ class UserHourTimeRepositoryImpl implements UserHourTimeRepository { @override Future getUserHourTime() async { try { - final userHourTimeJson = await _storage.getStorage( - key: _userHourTimeKey, - ) as String?; + final userHourTimeJson = + await _storage.getStorage( + key: _userHourTimeKey, + ) + as String?; if (userHourTimeJson == null) { return null; @@ -26,7 +29,10 @@ class UserHourTimeRepositoryImpl implements UserHourTimeRepository { return userReadingTimeModel; } on TypeError { - throw const StorageException('impossível converter a hora de leitura.'); + throw const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Impossible to convert user reading time.', + ); } on StorageException { rethrow; } @@ -45,6 +51,11 @@ class UserHourTimeRepositoryImpl implements UserHourTimeRepository { return (userHourTimeJsonInserted == 1) ? 1 : 0; } on StorageException { rethrow; + } catch (e) { + throw StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart b/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart index 0f1888cb..0439a687 100644 --- a/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart +++ b/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; @@ -15,9 +16,11 @@ class UserPageReadingTimeRepositoryImpl @override Future getUserPageReadingTime() async { try { - final pageReading = await _storage.getStorage( - key: _userPageReadingTimeKey, - ) as int?; + final pageReading = + await _storage.getStorage( + key: _userPageReadingTimeKey, + ) + as int?; final userPageReadingTime = UserPageReadingTimeModel( pageReadingTimeSeconds: pageReading, @@ -26,7 +29,9 @@ class UserPageReadingTimeRepositoryImpl return userPageReadingTime; } on TypeError { throw const StorageException( - 'impossível converter o tempo de leitura da página.'); + StorageErrorCode.writeFailed, + descriptionMessage: 'Impossible to convert user page reading time.', + ); } on StorageException { rethrow; } @@ -36,11 +41,20 @@ class UserPageReadingTimeRepositoryImpl Future setUserPageReadingTime({ required UserPageReadingTimeModel userPageReadingTime, }) async { - final userPageReadingTimeInserted = await _storage.insertStorage( - key: _userPageReadingTimeKey, - value: userPageReadingTime.pageReadingTimeSeconds!, - ); + try { + final userPageReadingTimeInserted = await _storage.insertStorage( + key: _userPageReadingTimeKey, + value: userPageReadingTime.pageReadingTimeSeconds!, + ); - return userPageReadingTimeInserted; + return userPageReadingTimeInserted; + } on StorageException { + rethrow; + } catch (e) { + throw StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: e.toString(), + ); + } } } diff --git a/lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart b/lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart index d6ff81b6..8be195ff 100644 --- a/lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart +++ b/lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_theme_repository/user_theme_repository.dart'; import 'package:bookify/src/core/storage/storage.dart'; @@ -27,7 +28,10 @@ class UserThemeRepositoryImpl implements UserThemeRepository { return null; } } on TypeError { - throw const StorageException('impossível converter o tema.'); + throw const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Impossible to convert theme mode.', + ); } on StorageException { rethrow; } @@ -43,6 +47,11 @@ class UserThemeRepositoryImpl implements UserThemeRepository { return themeInserted; } on StorageException { rethrow; + } catch (e) { + throw StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/services/auth_service/auth_service_impl.dart b/lib/src/core/services/auth_service/auth_service_impl.dart index a12e7ad1..4ee44c1b 100644 --- a/lib/src/core/services/auth_service/auth_service_impl.dart +++ b/lib/src/core/services/auth_service/auth_service_impl.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; @@ -43,9 +44,15 @@ class AuthServiceImpl implements AuthService { } on AuthException { rethrow; } on StorageException catch (e) { - throw AuthException(e.message); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.descriptionMessage, + ); } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } @@ -61,8 +68,16 @@ class AuthServiceImpl implements AuthService { return strategyResult; } on AuthException { rethrow; + } on StorageException catch (e) { + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.descriptionMessage, + ); } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } @@ -72,9 +87,15 @@ class AuthServiceImpl implements AuthService { final user = await _authRepository.getUserModel(); return user; } on StorageException catch (e) { - throw AuthException(e.message); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.descriptionMessage, + ); } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart b/lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart index 908f1cf2..1dff5c38 100644 --- a/lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart +++ b/lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:math'; +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/shared/enums/sign_in_type.dart'; @@ -21,8 +22,10 @@ class AppleAuthStrategy implements AuthStrategy { '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._'; final random = Random.secure(); - return List.generate(length, (_) => charset[random.nextInt(charset.length)]) - .join(); + return List.generate( + length, + (_) => charset[random.nextInt(charset.length)], + ).join(); } String _sha256ofString(String input) { @@ -60,10 +63,28 @@ class AppleAuthStrategy implements AuthStrategy { ); return userModel; - } on FirebaseException catch (e) { - throw AuthException(e.message ?? 'With no message'); + } on FirebaseAuthException catch (e) { + final errorCode = switch (e.code) { + 'user-not-found' => AuthErrorCode.userNotFound, + 'wrong-password' => AuthErrorCode.wrongPassword, + 'invalid-email' => AuthErrorCode.invalidEmail, + 'account-disabled' => AuthErrorCode.accountDisabled, + 'too-many-requests' => AuthErrorCode.tooManyRequests, + 'operation-not-allowed' => AuthErrorCode.operationNotAllowed, + 'network-request-failed' => AuthErrorCode.networkRequestFailed, + _ => AuthErrorCode.internalError, + }; + throw AuthException( + errorCode, + descriptionMessage: e.message, + ); + } on AuthException { + rethrow; } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } @@ -72,10 +93,16 @@ class AppleAuthStrategy implements AuthStrategy { try { await _firebaseAuth.signOut(); return true; - } on FirebaseException catch (e) { - throw AuthException(e.message ?? 'With no message'); + } on FirebaseAuthException catch (e) { + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.message ?? 'Sign out failed', + ); } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart b/lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart index dd6d9b29..fa0a06cb 100644 --- a/lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart +++ b/lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:math'; +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/shared/enums/sign_in_type.dart'; @@ -16,16 +17,18 @@ class FacebookAuthStrategy implements AuthStrategy { FacebookAuthStrategy({ required FacebookAuth facebookAuth, required FirebaseAuth firebaseAuth, - }) : _facebookAuth = facebookAuth, - _firebaseAuth = firebaseAuth; + }) : _facebookAuth = facebookAuth, + _firebaseAuth = firebaseAuth; String _generateNonce([int length = 32]) { const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._'; final random = Random.secure(); - return List.generate(length, (_) => charset[random.nextInt(charset.length)]) - .join(); + return List.generate( + length, + (_) => charset[random.nextInt(charset.length)], + ).join(); } String _sha256ofString(String input) { @@ -71,11 +74,33 @@ class FacebookAuthStrategy implements AuthStrategy { return userModel; } - throw const AuthException('O usuário não autorizou a autentificação'); - } on FirebaseException catch (e) { - throw AuthException(e.message ?? 'With no message'); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: loginResult.message, + ); + } on FirebaseAuthException catch (e) { + final errorCode = switch (e.code) { + 'user-not-found' => AuthErrorCode.userNotFound, + 'wrong-password' => AuthErrorCode.wrongPassword, + 'invalid-email' => AuthErrorCode.invalidEmail, + 'account-disabled' => AuthErrorCode.accountDisabled, + 'too-many-requests' => AuthErrorCode.tooManyRequests, + 'operation-not-allowed' => AuthErrorCode.operationNotAllowed, + 'network-request-failed' => AuthErrorCode.networkRequestFailed, + _ => AuthErrorCode.internalError, + }; + + throw AuthException( + errorCode, + descriptionMessage: e.message, + ); + } on AuthException { + rethrow; } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } @@ -85,10 +110,16 @@ class FacebookAuthStrategy implements AuthStrategy { await _facebookAuth.logOut(); await _firebaseAuth.signOut(); return true; - } on FirebaseException catch (e) { - throw AuthException(e.message ?? 'With no message'); + } on FirebaseAuthException catch (e) { + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.message ?? 'Sign out failed', + ); } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart b/lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart index b2587803..db3df1a9 100644 --- a/lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart +++ b/lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/services/auth_service/auth_strategy/auth_strategy.dart'; @@ -12,21 +13,24 @@ class GoogleAuthStrategy implements AuthStrategy { GoogleAuthStrategy({ required GoogleSignIn googleSignIn, required FirebaseAuth firebaseAuth, - }) : _googleSignIn = googleSignIn, - _firebaseAuth = firebaseAuth; + }) : _googleSignIn = googleSignIn, + _firebaseAuth = firebaseAuth; @override Future signIn() async { try { await _googleSignIn.initialize().onError( - (error, _) => throw AuthException(error.toString()), - ); + (error, _) => throw AuthException( + AuthErrorCode.operationNotAllowed, + descriptionMessage: error.toString(), + ), + ); const scopes = ['https://www.googleapis.com/auth/contacts.readonly']; final googleAuth = await _googleSignIn.authenticate(); - final authorization = - await googleAuth.authorizationClient.authorizationForScopes(scopes); + final authorization = await googleAuth.authorizationClient + .authorizationForScopes(scopes); final credential = GoogleAuthProvider.credential( accessToken: authorization?.accessToken, @@ -44,10 +48,29 @@ class GoogleAuthStrategy implements AuthStrategy { ); return userModel; - } on FirebaseException catch (e) { - throw AuthException(e.message ?? 'With no message'); + } on FirebaseAuthException catch (e) { + final errorCode = switch (e.code) { + 'user-not-found' => AuthErrorCode.userNotFound, + 'wrong-password' => AuthErrorCode.wrongPassword, + 'invalid-email' => AuthErrorCode.invalidEmail, + 'account-disabled' => AuthErrorCode.accountDisabled, + 'too-many-requests' => AuthErrorCode.tooManyRequests, + 'operation-not-allowed' => AuthErrorCode.operationNotAllowed, + 'network-request-failed' => AuthErrorCode.networkRequestFailed, + _ => AuthErrorCode.internalError, + }; + + throw AuthException( + errorCode, + descriptionMessage: e.message, + ); + } on AuthException { + rethrow; } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } @@ -57,10 +80,16 @@ class GoogleAuthStrategy implements AuthStrategy { await _googleSignIn.signOut(); await _firebaseAuth.signOut(); return true; - } on FirebaseException catch (e) { - throw AuthException(e.message ?? 'With no message'); + } on FirebaseAuthException catch (e) { + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.message ?? 'Sign out failed', + ); } on Exception catch (e) { - throw AuthException(e.toString()); + throw AuthException( + AuthErrorCode.internalError, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/storage/shared_preference_storage.dart b/lib/src/core/storage/shared_preference_storage.dart index de84b542..1b4a20b6 100644 --- a/lib/src/core/storage/shared_preference_storage.dart +++ b/lib/src/core/storage/shared_preference_storage.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -11,8 +12,13 @@ class SharedPreferencesStorage implements Storage { final storageValue = sharedPreferences.get(key); return storageValue; + } on StorageException { + rethrow; } catch (e) { - throw StorageException(e.toString()); + throw StorageException( + StorageErrorCode.readFailed, + descriptionMessage: e.toString(), + ); } } @@ -26,33 +32,39 @@ class SharedPreferencesStorage implements Storage { final storageInserted = switch (value.runtimeType) { const (int) => await sharedPreferences.setInt( - key, - value as int, - ), + key, + value as int, + ), const (String) => await sharedPreferences.setString( - key, - value as String, - ), + key, + value as String, + ), const (bool) => await sharedPreferences.setBool( - key, - value as bool, - ), + key, + value as bool, + ), const (double) => await sharedPreferences.setDouble( - key, - value as double, - ), + key, + value as double, + ), const (List) => await sharedPreferences.setStringList( - key, - value as List, - ), + key, + value as List, + ), _ => throw StorageException( - 'Type of value not valid: ${value.runtimeType}', - ), + StorageErrorCode.invalidValue, + descriptionMessage: 'Unsupported type: ${value.runtimeType}', + ), }; return storageInserted == true ? 1 : 0; } catch (e) { - throw StorageException(e.toString()); + if (e is StorageException) rethrow; + + throw StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: e.toString(), + ); } } @@ -76,7 +88,10 @@ class SharedPreferencesStorage implements Storage { final deletedStorage = await sharedPreferences.remove(key); return deletedStorage == true ? 1 : 0; } catch (e) { - throw StorageException(e.toString()); + throw StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: e.toString(), + ); } } @@ -88,7 +103,10 @@ class SharedPreferencesStorage implements Storage { final clearStorage = await sharedPreferences.clear(); return clearStorage == true ? 1 : 0; } catch (e) { - throw StorageException(e.toString()); + throw StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/features/auth/bloc/auth_bloc.dart b/lib/src/features/auth/bloc/auth_bloc.dart index 57d596c8..0d0ef963 100644 --- a/lib/src/features/auth/bloc/auth_bloc.dart +++ b/lib/src/features/auth/bloc/auth_bloc.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; import 'package:bookify/src/shared/enums/sign_in_type.dart'; @@ -27,7 +28,9 @@ class AuthBloc extends Bloc { if (authSignedIn == 0) { emit( AuthErrorState( - errorMessage: 'Impossível efetuar a autentificação', + errorCode: AuthErrorCode.internalError, + errorDescriptionMessage: + 'Failed to save user data. Please try again.', ), ); return; @@ -37,13 +40,15 @@ class AuthBloc extends Bloc { } on AuthException catch (e) { emit( AuthErrorState( - errorMessage: 'Erro na autentificação: ${e.message}', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } on Exception catch (e) { emit( AuthErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: AuthErrorCode.internalError, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/auth/bloc/auth_state.dart b/lib/src/features/auth/bloc/auth_state.dart index d76dcb19..013e529f 100644 --- a/lib/src/features/auth/bloc/auth_state.dart +++ b/lib/src/features/auth/bloc/auth_state.dart @@ -9,9 +9,11 @@ final class AuthLoadingState extends AuthState {} final class AuthSignedState extends AuthState {} final class AuthErrorState extends AuthState { - final String errorMessage; + final AuthErrorCode errorCode; + final String? errorDescriptionMessage; AuthErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/auth/views/auth_page.dart b/lib/src/features/auth/views/auth_page.dart index 517cd249..aa934f6c 100644 --- a/lib/src/features/auth/views/auth_page.dart +++ b/lib/src/features/auth/views/auth_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/auth_error_code/auth_error_code_extension.dart'; import 'package:bookify/src/features/auth/bloc/auth_bloc.dart'; import 'package:bookify/src/features/auth/widgets/platform_sign_in_buttons.dart'; import 'package:bookify/src/features/auth/widgets/terms_information.dart'; @@ -77,10 +78,13 @@ class _AuthPageState extends State { }, ); break; - case AuthErrorState(): + case AuthErrorState( + :final errorCode, + :final errorDescriptionMessage, + ): SnackbarService.showSnackBar( context, - state.errorMessage, + errorCode.toLocalizedMessage(errorDescriptionMessage), SnackBarType.error, ); break; diff --git a/lib/src/features/profile/bloc/profile_bloc.dart b/lib/src/features/profile/bloc/profile_bloc.dart index feedae2a..569fa74e 100644 --- a/lib/src/features/profile/bloc/profile_bloc.dart +++ b/lib/src/features/profile/bloc/profile_bloc.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; @@ -28,7 +29,9 @@ class ProfileBloc extends Bloc { if (userModel == null) { emit( ProfileErrorState( - errorMessage: 'Erro ao buscar o usuário', + errorCode: AuthErrorCode.internalError, + errorDescriptionMessage: + 'Failed to save user data. Please try again.', ), ); return; @@ -40,12 +43,17 @@ class ProfileBloc extends Bloc { ), ); } on AuthException catch (e) { - emit(ProfileErrorState( - errorMessage: 'Erro ao buscar o usuário: ${e.message}')); + emit( + ProfileErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( ProfileErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: AuthErrorCode.internalError, + errorDescriptionMessage: e.toString(), ), ); } @@ -65,7 +73,8 @@ class ProfileBloc extends Bloc { if (!userLoggedOut) { emit( ProfileErrorState( - errorMessage: 'Erro ao fazer o logout do usuário', + errorCode: AuthErrorCode.internalError, + errorDescriptionMessage: 'Failed to logout', ), ); return; @@ -73,12 +82,17 @@ class ProfileBloc extends Bloc { emit(ProfileLogOutState()); } on AuthException catch (e) { - emit(ProfileErrorState( - errorMessage: 'Erro em fazer o logout do usuário: ${e.message}')); + emit( + ProfileErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( ProfileErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: AuthErrorCode.internalError, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/profile/bloc/profile_state.dart b/lib/src/features/profile/bloc/profile_state.dart index a43eb98c..fc14acd2 100644 --- a/lib/src/features/profile/bloc/profile_state.dart +++ b/lib/src/features/profile/bloc/profile_state.dart @@ -15,9 +15,11 @@ final class ProfileLoadedState extends ProfileState { final class ProfileLogOutState extends ProfileState {} final class ProfileErrorState extends ProfileState { - final String errorMessage; + final AuthErrorCode errorCode; + final String? errorDescriptionMessage; ProfileErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/profile/views/profile_page.dart b/lib/src/features/profile/views/profile_page.dart index 4e5f5621..eb9c693e 100644 --- a/lib/src/features/profile/views/profile_page.dart +++ b/lib/src/features/profile/views/profile_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/auth_error_code/auth_error_code_extension.dart'; import 'package:bookify/src/features/auth/views/auth_page.dart'; import 'package:bookify/src/features/profile/bloc/profile_bloc.dart'; import 'package:bookify/src/features/profile/views/widgets/profile_loaded_state_widget.dart'; @@ -28,19 +29,23 @@ class _ProfilePageState extends State { Widget _getWidgetOnProfileState(BuildContext context, ProfileState state) { return switch (state) { ProfileLoadingState() || - ProfileLogOutState() => - const CenterCircularProgressIndicator(), + ProfileLogOutState() => const CenterCircularProgressIndicator(), ProfileLoadedState(:final userModel) => ProfileLoadedStateWidget( - userModel: userModel, - onPressedLogOut: () => _bloc.add( - UserLoggedOutEvent( - userModel: userModel, - ), + userModel: userModel, + onPressedLogOut: () => _bloc.add( + UserLoggedOutEvent( + userModel: userModel, ), ), - ProfileErrorState(:final errorMessage) => Center( + ), + ProfileErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => + Center( + key: const Key('BookErrorSateWidget'), child: InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), ), diff --git a/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart b/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart index e9f40b86..ffe490a3 100644 --- a/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +++ b/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; import 'package:flutter/material.dart'; @@ -24,13 +25,15 @@ class UserLoggedCubit extends Cubit { } on AuthException catch (e) { emit( UserLoggedErrorState( - errorMessage: 'Erro ao verificar a sessão: ${e.message}', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } on Exception catch (e) { emit( UserLoggedErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: AuthErrorCode.internalError, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart b/lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart index 6b1e8402..490c0bc6 100644 --- a/lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +++ b/lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart @@ -14,9 +14,11 @@ final class UserLoggedLoadedState extends UserLoggedState { } final class UserLoggedErrorState extends UserLoggedState { - final String errorMessage; + final AuthErrorCode errorCode; + final String? errorDescriptionMessage; UserLoggedErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/pubspec.yaml b/pubspec.yaml index bb14b914..af634bdb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.3 +version: 2.11.4 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart b/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart index a478dd76..61165d51 100644 --- a/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart +++ b/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/repositories/auth_repository/auth_repository_impl.dart'; @@ -94,7 +95,8 @@ void main() { throwsA( (Exception e) => e is StorageException && - e.message == 'impossível converter o usuário.', + e.code == StorageErrorCode.invalidValue && + e.descriptionMessage == 'Expected a String value for user data.', ), ); }); @@ -104,13 +106,20 @@ void main() { () => storage.getStorage( key: 'user', ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await authRepository.getUserModel(), throwsA( (Exception e) => - e is StorageException && e.message == 'Storage error', + e is StorageException && + e.code == StorageErrorCode.writeFailed && + e.descriptionMessage == 'Storage error', ), ); }); @@ -121,7 +130,12 @@ void main() { key: 'user', value: any(named: 'value'), ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await authRepository.setUserModel( @@ -129,7 +143,9 @@ void main() { ), throwsA( (Exception e) => - e is StorageException && e.message == 'Storage error', + e is StorageException && + e.code == StorageErrorCode.writeFailed && + e.descriptionMessage == 'Storage error', ), ); }); @@ -139,13 +155,20 @@ void main() { () => storage.deleteStorage( key: any(named: 'key'), ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await authRepository.deleteUserModel(), throwsA( (Exception e) => - e is StorageException && e.message == 'Storage error', + e is StorageException && + e.code == StorageErrorCode.writeFailed && + e.descriptionMessage == 'Storage error', ), ); }); diff --git a/test/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl_test.dart b/test/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl_test.dart index 1c6f917e..7319769c 100644 --- a/test/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl_test.dart +++ b/test/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl_test.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; @@ -92,7 +93,9 @@ void main() { throwsA( (Exception e) => e is StorageException && - e.message == 'impossível converter a hora de leitura.', + e.code == StorageErrorCode.invalidValue && + e.descriptionMessage == + 'Impossible to convert user reading time.', ), ); }); @@ -102,13 +105,20 @@ void main() { () => storage.getStorage( key: any(named: 'key'), ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + const StorageException( + StorageErrorCode.readFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await userHourTimeRepository.getUserHourTime(), throwsA( (Exception e) => - e is StorageException && e.message == 'Storage error', + e is StorageException && + e.code == StorageErrorCode.readFailed && + e.descriptionMessage == 'Storage error', ), ); }); @@ -119,7 +129,12 @@ void main() { key: any(named: 'key'), value: any(named: 'value'), ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + const StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await userHourTimeRepository.setUserHourTime( @@ -127,7 +142,9 @@ void main() { ), throwsA( (Exception e) => - e is StorageException && e.message == 'Storage error', + e is StorageException && + e.code == StorageErrorCode.writeFailed && + e.descriptionMessage == 'Storage error', ), ); }); diff --git a/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart b/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart index be3a3772..5efed6bf 100644 --- a/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart +++ b/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart'; @@ -27,8 +28,8 @@ void main() { (_) async => const Duration(minutes: 10).inSeconds, ); - final userPageReadingTime = - await userPageReadingTimeRepository.getUserPageReadingTime(); + final userPageReadingTime = await userPageReadingTimeRepository + .getUserPageReadingTime(); expect( userPageReadingTime.pageReadingTimeSeconds, @@ -46,10 +47,10 @@ void main() { (_) async => 1, ); - final userPageReadingInserted = - await userPageReadingTimeRepository.setUserPageReadingTime( - userPageReadingTime: userPageReadingTime, - ); + final userPageReadingInserted = await userPageReadingTimeRepository + .setUserPageReadingTime( + userPageReadingTime: userPageReadingTime, + ); expect( userPageReadingInserted, @@ -74,7 +75,9 @@ void main() { throwsA( (Exception e) => e is StorageException && - e.message == 'impossível converter o tempo de leitura da página.', + e.code == StorageErrorCode.writeFailed && + e.descriptionMessage == + 'Impossible to convert user page reading time.', ), ); }); @@ -84,14 +87,21 @@ void main() { () => storage.getStorage( key: any(named: 'key'), ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + StorageException( + StorageErrorCode.readFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await userPageReadingTimeRepository.getUserPageReadingTime(), throwsA( (Exception e) => - e is StorageException && e.message == 'Storage error', + e is StorageException && + e.code == StorageErrorCode.readFailed && + e.descriptionMessage == 'Storage error', ), ); }); @@ -102,7 +112,12 @@ void main() { key: any(named: 'key'), value: any(named: 'value'), ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await userPageReadingTimeRepository.setUserPageReadingTime( @@ -110,7 +125,9 @@ void main() { ), throwsA( (Exception e) => - e is StorageException && e.message == 'Storage error', + e is StorageException && + e.code == StorageErrorCode.writeFailed && + e.descriptionMessage == 'Storage error', ), ); }); diff --git a/test/src/core/repositories/user_theme_repository/user_theme_repository_impl_test.dart b/test/src/core/repositories/user_theme_repository/user_theme_repository_impl_test.dart index 07d6a3af..63bcad65 100644 --- a/test/src/core/repositories/user_theme_repository/user_theme_repository_impl_test.dart +++ b/test/src/core/repositories/user_theme_repository/user_theme_repository_impl_test.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart'; import 'package:bookify/src/core/storage/storage.dart'; @@ -56,9 +57,12 @@ void main() { expect( () async => await userThemeRepository.getThemeMode(), - throwsA((Exception e) => - e is StorageException && - e.message == 'impossível converter o tema.'), + throwsA( + (Exception e) => + e is StorageException && + e.code == StorageErrorCode.invalidValue && + e.descriptionMessage == 'Impossible to convert theme mode.', + ), ); }); @@ -67,12 +71,21 @@ void main() { () => storage.getStorage( key: any(named: 'key'), ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + StorageException( + StorageErrorCode.readFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await userThemeRepository.getThemeMode(), - throwsA((Exception e) => - e is StorageException && e.message == 'Storage error'), + throwsA( + (Exception e) => + e is StorageException && + e.code == StorageErrorCode.readFailed && + e.descriptionMessage == 'Storage error', + ), ); }); @@ -82,14 +95,23 @@ void main() { key: any(named: 'key'), value: any(named: 'value'), ), - ).thenThrow(const StorageException('Storage error')); + ).thenThrow( + StorageException( + StorageErrorCode.writeFailed, + descriptionMessage: 'Storage error', + ), + ); expect( () async => await userThemeRepository.setThemeMode( themeMode: ThemeMode.light, ), - throwsA((Exception e) => - e is StorageException && e.message == 'Storage error'), + throwsA( + (Exception e) => + e is StorageException && + e.code == StorageErrorCode.writeFailed && + e.descriptionMessage == 'Storage error', + ), ); }); }); diff --git a/test/src/core/services/auth_service/auth_service_impl_test.dart b/test/src/core/services/auth_service/auth_service_impl_test.dart index 36472e7c..74c81943 100644 --- a/test/src/core/services/auth_service/auth_service_impl_test.dart +++ b/test/src/core/services/auth_service/auth_service_impl_test.dart @@ -1,3 +1,5 @@ +import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; @@ -67,13 +69,20 @@ void main() { ).thenReturn(authStrategy); when( () => authStrategy.signIn(), - ).thenThrow(AuthException('Strategy failed')); + ).thenThrow( + AuthException( + AuthErrorCode.internalError, + descriptionMessage: 'Strategy failed', + ), + ); expect( () async => await authService.signIn(signInType: SignInType.google), throwsA( (Exception e) => - e is AuthException && e.message == 'Strategy failed', + e is AuthException && + e.code == AuthErrorCode.internalError && + e.descriptionMessage == 'Strategy failed', ), ); }, @@ -88,12 +97,20 @@ void main() { when(() => authStrategy.signIn()).thenAnswer((_) async => userModel); when( () => authRepository.setUserModel(userModel: userModel), - ).thenThrow(StorageException('DB failed')); + ).thenThrow( + StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'DB failed', + ), + ); expect( () async => await authService.signIn(signInType: SignInType.google), throwsA( - (Exception e) => e is AuthException && e.message == 'DB failed', + (Exception e) => + e is AuthException && + e.code == AuthErrorCode.internalError && + e.descriptionMessage == 'DB failed', ), ); }, @@ -126,14 +143,19 @@ void main() { () => authStrategyFactory.create(SignInType.google), ).thenReturn(authStrategy); when(() => authStrategy.signOut()).thenThrow( - AuthException('Strategy failed'), + AuthException( + AuthErrorCode.internalError, + descriptionMessage: 'Strategy failed', + ), ); expect( () async => await authService.signOut(signInType: SignInType.google), throwsA( (Exception e) => - e is AuthException && e.message == 'Strategy failed', + e is AuthException && + e.code == AuthErrorCode.internalError && + e.descriptionMessage == 'Strategy failed', ), ); verify(() => authStrategyFactory.create(SignInType.google)).called(1); diff --git a/test/src/features/auth/bloc/auth_bloc_test.dart b/test/src/features/auth/bloc/auth_bloc_test.dart index f25033a6..6eb2ae1c 100644 --- a/test/src/features/auth/bloc/auth_bloc_test.dart +++ b/test/src/features/auth/bloc/auth_bloc_test.dart @@ -1,4 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/features/auth/bloc/auth_bloc.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; @@ -27,13 +28,14 @@ void main() { blocTest( 'Test SignedInAuthEvent work when Google button', build: () => authBloc, - setUp: () => when( - () => authService.signIn( - signInType: SignInType.google, - ), - ).thenAnswer( - (_) async => 1, - ), + setUp: () => + when( + () => authService.signIn( + signInType: SignInType.google, + ), + ).thenAnswer( + (_) async => 1, + ), act: (bloc) => bloc.add( SignedInAuthEvent(signInTypeButton: SignInType.google), ), @@ -51,13 +53,14 @@ void main() { blocTest( 'Test SignedInAuthEvent work emit error on Apple button', build: () => authBloc, - setUp: () => when( - () => authService.signIn( - signInType: SignInType.apple, - ), - ).thenAnswer( - (_) async => 1, - ), + setUp: () => + when( + () => authService.signIn( + signInType: SignInType.apple, + ), + ).thenAnswer( + (_) async => 1, + ), act: (bloc) => bloc.add( SignedInAuthEvent(signInTypeButton: SignInType.apple), ), @@ -75,13 +78,14 @@ void main() { blocTest( 'Test SignedInAuthEvent work when Facebook button', build: () => authBloc, - setUp: () => when( - () => authService.signIn( - signInType: SignInType.facebook, - ), - ).thenAnswer( - (_) async => 1, - ), + setUp: () => + when( + () => authService.signIn( + signInType: SignInType.facebook, + ), + ).thenAnswer( + (_) async => 1, + ), act: (bloc) => bloc.add( SignedInAuthEvent(signInTypeButton: SignInType.facebook), ), @@ -99,13 +103,14 @@ void main() { blocTest( 'Test SignedInAuthEvent work when authSignedIn is 0', build: () => authBloc, - setUp: () => when( - () => authService.signIn( - signInType: SignInType.google, - ), - ).thenAnswer( - (_) async => 0, - ), + setUp: () => + when( + () => authService.signIn( + signInType: SignInType.google, + ), + ).thenAnswer( + (_) async => 0, + ), act: (bloc) => bloc.add( SignedInAuthEvent(signInTypeButton: SignInType.google), ), @@ -123,13 +128,17 @@ void main() { blocTest( 'Test SignedInAuthEvent work when throw AuthException', build: () => authBloc, - setUp: () => when( - () => authService.signIn( - signInType: SignInType.google, - ), - ).thenThrow( - const AuthException('Error on authentication'), - ), + setUp: () => + when( + () => authService.signIn( + signInType: SignInType.google, + ), + ).thenThrow( + const AuthException( + AuthErrorCode.internalError, + descriptionMessage: 'Error on authentication', + ), + ), act: (bloc) => bloc.add( SignedInAuthEvent(signInTypeButton: SignInType.google), ), @@ -147,13 +156,14 @@ void main() { blocTest( 'Test SignedInAuthEvent work when throw Generic Exception', build: () => authBloc, - setUp: () => when( - () => authService.signIn( - signInType: SignInType.google, - ), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => authService.signIn( + signInType: SignInType.google, + ), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add( SignedInAuthEvent(signInTypeButton: SignInType.google), ), diff --git a/test/src/features/book_detail/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc_test.dart b/test/src/features/book_detail/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc_test.dart index 1237d81a..dd1420d5 100644 --- a/test/src/features/book_detail/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc_test.dart +++ b/test/src/features/book_detail/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc_test.dart @@ -1,4 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; @@ -34,11 +35,12 @@ void main() { blocTest( 'Test GotBookPagesReadingTimeEvent work', build: () => bookPagesReadingTimeBloc, - setUp: () => when( - () => userPageReadingTimeRepository.getUserPageReadingTime(), - ).thenAnswer( - (_) async => userPageReadingTime, - ), + setUp: () => + when( + () => userPageReadingTimeRepository.getUserPageReadingTime(), + ).thenAnswer( + (_) async => userPageReadingTime, + ), act: (bloc) => bloc.add(GotBookPagesReadingTimeEvent()), verify: (_) => verify( () => userPageReadingTimeRepository.getUserPageReadingTime(), @@ -52,11 +54,15 @@ void main() { blocTest( 'Test GotBookPagesReadingTimeEvent work when throw StorageException', build: () => bookPagesReadingTimeBloc, - setUp: () => when( - () => userPageReadingTimeRepository.getUserPageReadingTime(), - ).thenThrow( - const StorageException('Error on storage'), - ), + setUp: () => + when( + () => userPageReadingTimeRepository.getUserPageReadingTime(), + ).thenThrow( + const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Error on storage', + ), + ), act: (bloc) => bloc.add(GotBookPagesReadingTimeEvent()), verify: (_) => verify( () => userPageReadingTimeRepository.getUserPageReadingTime(), @@ -70,11 +76,12 @@ void main() { blocTest( 'Test GotBookPagesReadingTimeEvent work when throw Generic Exception', build: () => bookPagesReadingTimeBloc, - setUp: () => when( - () => userPageReadingTimeRepository.getUserPageReadingTime(), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => userPageReadingTimeRepository.getUserPageReadingTime(), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add(GotBookPagesReadingTimeEvent()), verify: (_) => verify( () => userPageReadingTimeRepository.getUserPageReadingTime(), diff --git a/test/src/features/profile/bloc/profile_bloc_test.dart b/test/src/features/profile/bloc/profile_bloc_test.dart index 8d956cc3..d3f3e576 100644 --- a/test/src/features/profile/bloc/profile_bloc_test.dart +++ b/test/src/features/profile/bloc/profile_bloc_test.dart @@ -1,4 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/features/profile/bloc/profile_bloc.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; @@ -80,7 +81,10 @@ void main() { when( () => authService.getUserModel(), ).thenThrow( - const AuthException('Error on authentication'), + const AuthException( + AuthErrorCode.tooManyRequests, + descriptionMessage: 'Error on authentication', + ), ), act: (bloc) => bloc.add( GotUserProfileEvent(), @@ -191,7 +195,10 @@ void main() { signInType: SignInType.google, ), ).thenThrow( - const AuthException('Error on authentication'), + const AuthException( + AuthErrorCode.tooManyRequests, + descriptionMessage: 'Error on authentication', + ), ), act: (bloc) => bloc.add( UserLoggedOutEvent( diff --git a/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart b/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart index f01e9982..5cfa40e0 100644 --- a/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart +++ b/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart @@ -1,5 +1,6 @@ import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; @@ -52,11 +53,12 @@ void main() { blocTest( 'Test GotHourTimeEvent work', build: () => programmingReadingBloc, - setUp: () => when( - () => userHourTimeRepository.getUserHourTime(), - ).thenAnswer( - (_) async => userHourTime, - ), + setUp: () => + when( + () => userHourTimeRepository.getUserHourTime(), + ).thenAnswer( + (_) async => userHourTime, + ), act: (bloc) => bloc.add(GotHourTimeEvent()), verify: (_) => verify( () => userHourTimeRepository.getUserHourTime(), @@ -70,11 +72,15 @@ void main() { blocTest( 'Test GotHourTimeEvent work when throw StorageException', build: () => programmingReadingBloc, - setUp: () => when( - () => userHourTimeRepository.getUserHourTime(), - ).thenThrow( - const StorageException('Error on storage'), - ), + setUp: () => + when( + () => userHourTimeRepository.getUserHourTime(), + ).thenThrow( + const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Error on storage', + ), + ), act: (bloc) => bloc.add(GotHourTimeEvent()), verify: (_) => verify( () => userHourTimeRepository.getUserHourTime(), @@ -88,11 +94,12 @@ void main() { blocTest( 'Test GotHourTimeEvent work when throw Generic Exception', build: () => programmingReadingBloc, - setUp: () => when( - () => userHourTimeRepository.getUserHourTime(), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => userHourTimeRepository.getUserHourTime(), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add(GotHourTimeEvent()), verify: (_) => verify( () => userHourTimeRepository.getUserHourTime(), @@ -116,14 +123,15 @@ void main() { ); when( - () => notificationsService.periodicallyShowNotificationWithSpecificDate( - id: any(named: 'id'), - title: any(named: 'title'), - body: any(named: 'body'), - notificationChannel: any(named: 'notificationChannel'), - repeatType: any(named: 'repeatType'), - scheduledDate: any(named: 'scheduledDate'), - ), + () => + notificationsService.periodicallyShowNotificationWithSpecificDate( + id: any(named: 'id'), + title: any(named: 'title'), + body: any(named: 'body'), + notificationChannel: any(named: 'notificationChannel'), + repeatType: any(named: 'repeatType'), + scheduledDate: any(named: 'scheduledDate'), + ), ).thenAnswer( (_) async {}, ); @@ -141,14 +149,15 @@ void main() { ).called(1); verify( - () => notificationsService.periodicallyShowNotificationWithSpecificDate( - id: any(named: 'id'), - title: any(named: 'title'), - body: any(named: 'body'), - notificationChannel: any(named: 'notificationChannel'), - repeatType: any(named: 'repeatType'), - scheduledDate: any(named: 'scheduledDate'), - ), + () => + notificationsService.periodicallyShowNotificationWithSpecificDate( + id: any(named: 'id'), + title: any(named: 'title'), + body: any(named: 'body'), + notificationChannel: any(named: 'notificationChannel'), + repeatType: any(named: 'repeatType'), + scheduledDate: any(named: 'scheduledDate'), + ), ).called(1); }, expect: () => [ @@ -160,13 +169,14 @@ void main() { blocTest( 'Test InsertedHourTimeEvent work when userHourTimeInserted == 0', build: () => programmingReadingBloc, - setUp: () => when( - () => userHourTimeRepository.setUserHourTime( - userHourTime: userHourTime, - ), - ).thenAnswer( - (_) async => 0, - ), + setUp: () => + when( + () => userHourTimeRepository.setUserHourTime( + userHourTime: userHourTime, + ), + ).thenAnswer( + (_) async => 0, + ), act: (bloc) => bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTime, @@ -180,14 +190,15 @@ void main() { ).called(1); verifyNever( - () => notificationsService.periodicallyShowNotificationWithSpecificDate( - id: any(named: 'id'), - title: any(named: 'title'), - body: any(named: 'body'), - notificationChannel: any(named: 'notificationChannel'), - repeatType: any(named: 'repeatType'), - scheduledDate: any(named: 'scheduledDate'), - ), + () => + notificationsService.periodicallyShowNotificationWithSpecificDate( + id: any(named: 'id'), + title: any(named: 'title'), + body: any(named: 'body'), + notificationChannel: any(named: 'notificationChannel'), + repeatType: any(named: 'repeatType'), + scheduledDate: any(named: 'scheduledDate'), + ), ); }, expect: () => [ @@ -199,13 +210,17 @@ void main() { blocTest( 'Test InsertedHourTimeEvent work when throw StorageException', build: () => programmingReadingBloc, - setUp: () => when( - () => userHourTimeRepository.setUserHourTime( - userHourTime: userHourTime, - ), - ).thenThrow( - const StorageException('Error on storage'), - ), + setUp: () => + when( + () => userHourTimeRepository.setUserHourTime( + userHourTime: userHourTime, + ), + ).thenThrow( + const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Error on storage', + ), + ), act: (bloc) => bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTime, @@ -219,14 +234,15 @@ void main() { ).called(1); verifyNever( - () => notificationsService.periodicallyShowNotificationWithSpecificDate( - id: any(named: 'id'), - title: any(named: 'title'), - body: any(named: 'body'), - notificationChannel: any(named: 'notificationChannel'), - repeatType: any(named: 'repeatType'), - scheduledDate: any(named: 'scheduledDate'), - ), + () => + notificationsService.periodicallyShowNotificationWithSpecificDate( + id: any(named: 'id'), + title: any(named: 'title'), + body: any(named: 'body'), + notificationChannel: any(named: 'notificationChannel'), + repeatType: any(named: 'repeatType'), + scheduledDate: any(named: 'scheduledDate'), + ), ); }, expect: () => [ @@ -238,13 +254,14 @@ void main() { blocTest( 'Test InsertedHourTimeEvent work when throw Generic Exception', build: () => programmingReadingBloc, - setUp: () => when( - () => userHourTimeRepository.setUserHourTime( - userHourTime: userHourTime, - ), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => userHourTimeRepository.setUserHourTime( + userHourTime: userHourTime, + ), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTime, @@ -258,14 +275,15 @@ void main() { ).called(1); verifyNever( - () => notificationsService.periodicallyShowNotificationWithSpecificDate( - id: any(named: 'id'), - title: any(named: 'title'), - body: any(named: 'body'), - notificationChannel: any(named: 'notificationChannel'), - repeatType: any(named: 'repeatType'), - scheduledDate: any(named: 'scheduledDate'), - ), + () => + notificationsService.periodicallyShowNotificationWithSpecificDate( + id: any(named: 'id'), + title: any(named: 'title'), + body: any(named: 'body'), + notificationChannel: any(named: 'notificationChannel'), + repeatType: any(named: 'repeatType'), + scheduledDate: any(named: 'scheduledDate'), + ), ); }, expect: () => [ @@ -278,13 +296,14 @@ void main() { blocTest( 'Test RemovedNotificationHourTimeEvent work', build: () => programmingReadingBloc, - setUp: () => when( - () => notificationsService.cancelNotificationById( - id: any(named: 'id'), - ), - ).thenAnswer( - (_) async {}, - ), + setUp: () => + when( + () => notificationsService.cancelNotificationById( + id: any(named: 'id'), + ), + ).thenAnswer( + (_) async {}, + ), act: (bloc) => bloc.add(RemovedNotificationHourTimeEvent()), verify: (_) { verify( @@ -302,13 +321,14 @@ void main() { blocTest( 'Test RemovedNotificationHourTimeEvent work when throw Generic Exception', build: () => programmingReadingBloc, - setUp: () => when( - () => notificationsService.cancelNotificationById( - id: any(named: 'id'), - ), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => notificationsService.cancelNotificationById( + id: any(named: 'id'), + ), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add(RemovedNotificationHourTimeEvent()), verify: (_) { verify( diff --git a/test/src/features/reading_page_timer/bloc/reading_page_timer_bloc_test.dart b/test/src/features/reading_page_timer/bloc/reading_page_timer_bloc_test.dart index 47e1b1df..c9d48c96 100644 --- a/test/src/features/reading_page_timer/bloc/reading_page_timer_bloc_test.dart +++ b/test/src/features/reading_page_timer/bloc/reading_page_timer_bloc_test.dart @@ -1,4 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; @@ -33,13 +34,14 @@ void main() { blocTest( 'Test InsertedReadingPageTimeEvent work', build: () => readingPageTimerBloc, - setUp: () => when( - () => userPageReadingTimeRepository.setUserPageReadingTime( - userPageReadingTime: userPageReadingTime, - ), - ).thenAnswer( - (_) async => 1, - ), + setUp: () => + when( + () => userPageReadingTimeRepository.setUserPageReadingTime( + userPageReadingTime: userPageReadingTime, + ), + ).thenAnswer( + (_) async => 1, + ), act: (bloc) => bloc.add( InsertedReadingPageTimeEvent( readingPageTime: 600, @@ -59,13 +61,14 @@ void main() { blocTest( 'Test InsertedReadingPageTimeEvent work when userPageReadingTimeInserted == 0', build: () => readingPageTimerBloc, - setUp: () => when( - () => userPageReadingTimeRepository.setUserPageReadingTime( - userPageReadingTime: userPageReadingTime, - ), - ).thenAnswer( - (_) async => 0, - ), + setUp: () => + when( + () => userPageReadingTimeRepository.setUserPageReadingTime( + userPageReadingTime: userPageReadingTime, + ), + ).thenAnswer( + (_) async => 0, + ), act: (bloc) => bloc.add( InsertedReadingPageTimeEvent( readingPageTime: 600, @@ -85,13 +88,17 @@ void main() { blocTest( 'Test InsertedReadingPageTimeEvent work when throw StorageException', build: () => readingPageTimerBloc, - setUp: () => when( - () => userPageReadingTimeRepository.setUserPageReadingTime( - userPageReadingTime: userPageReadingTime, - ), - ).thenThrow( - const StorageException('Error on storage'), - ), + setUp: () => + when( + () => userPageReadingTimeRepository.setUserPageReadingTime( + userPageReadingTime: userPageReadingTime, + ), + ).thenThrow( + const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Error on storage', + ), + ), act: (bloc) => bloc.add( InsertedReadingPageTimeEvent( readingPageTime: 600, @@ -111,13 +118,14 @@ void main() { blocTest( 'Test InsertedReadingPageTimeEvent work when throw Generic Exception', build: () => readingPageTimerBloc, - setUp: () => when( - () => userPageReadingTimeRepository.setUserPageReadingTime( - userPageReadingTime: userPageReadingTime, - ), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => userPageReadingTimeRepository.setUserPageReadingTime( + userPageReadingTime: userPageReadingTime, + ), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add( InsertedReadingPageTimeEvent( readingPageTime: 600, diff --git a/test/src/features/readings_timer/bloc/readings_timer_bloc_test.dart b/test/src/features/readings_timer/bloc/readings_timer_bloc_test.dart index db54aadc..d74d1f7c 100644 --- a/test/src/features/readings_timer/bloc/readings_timer_bloc_test.dart +++ b/test/src/features/readings_timer/bloc/readings_timer_bloc_test.dart @@ -1,5 +1,6 @@ import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; @@ -41,11 +42,12 @@ void main() { blocTest( 'Test GotReadingsUserTimerEvent work', build: () => readingsTimerBloc, - setUp: () => when( - () => userHourTimeRepository.getUserHourTime(), - ).thenAnswer( - (_) async => userHourTimeModel, - ), + setUp: () => + when( + () => userHourTimeRepository.getUserHourTime(), + ).thenAnswer( + (_) async => userHourTimeModel, + ), act: (bloc) => bloc.add(GotReadingsUserTimerEvent()), verify: (_) => verify( () => userHourTimeRepository.getUserHourTime(), @@ -59,11 +61,12 @@ void main() { blocTest( 'Test GotReadingsUserTimerEvent work when userHourTime is null', build: () => readingsTimerBloc, - setUp: () => when( - () => userHourTimeRepository.getUserHourTime(), - ).thenAnswer( - (_) async => null, - ), + setUp: () => + when( + () => userHourTimeRepository.getUserHourTime(), + ).thenAnswer( + (_) async => null, + ), act: (bloc) => bloc.add(GotReadingsUserTimerEvent()), verify: (_) => verify( () => userHourTimeRepository.getUserHourTime(), @@ -77,9 +80,15 @@ void main() { blocTest( 'Test GotReadingsUserTimerEvent work when throw Storage Exception', build: () => readingsTimerBloc, - setUp: () => when( - () => userHourTimeRepository.getUserHourTime(), - ).thenThrow(const StorageException('Error on storage')), + setUp: () => + when( + () => userHourTimeRepository.getUserHourTime(), + ).thenThrow( + const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Error on storage', + ), + ), act: (bloc) => bloc.add(GotReadingsUserTimerEvent()), verify: (_) => verify( () => userHourTimeRepository.getUserHourTime(), diff --git a/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart b/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart index 8b2c3554..712f8273 100644 --- a/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart +++ b/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart @@ -1,4 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; import 'package:bookify/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart'; @@ -66,9 +67,15 @@ void main() { blocTest( 'Test checkAuthStatus function work when throw AuthException', build: () => userLoggedCubit, - setUp: () => when( - () => authService.userIsLoggedIn(), - ).thenThrow(const AuthException('Error on Auth Service')), + setUp: () => + when( + () => authService.userIsLoggedIn(), + ).thenThrow( + const AuthException( + AuthErrorCode.internalError, + descriptionMessage: 'Error on Auth Service', + ), + ), act: (cubit) => cubit.checkAuthStatus(), verify: (_) => verify( () => authService.userIsLoggedIn(), diff --git a/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart b/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart index 3b000ee4..0b41e941 100644 --- a/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart +++ b/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart @@ -1,4 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_theme_repository/user_theme_repository.dart'; import 'package:bookify/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart'; @@ -29,11 +30,12 @@ void main() { blocTest( 'Test getTheme function work', build: () => userThemeCubit, - setUp: () => when( - () => userRepository.getThemeMode(), - ).thenAnswer( - (_) async => ThemeMode.light, - ), + setUp: () => + when( + () => userRepository.getThemeMode(), + ).thenAnswer( + (_) async => ThemeMode.light, + ), act: (cubit) => cubit.getTheme(), verify: (_) => verify( () => userRepository.getThemeMode(), @@ -74,9 +76,15 @@ void main() { blocTest( 'Test getTheme function work when throw StorageException', build: () => userThemeCubit, - setUp: () => when( - () => userRepository.getThemeMode(), - ).thenThrow(const StorageException('Error on storage Data')), + setUp: () => + when( + () => userRepository.getThemeMode(), + ).thenThrow( + const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Error on storage Data', + ), + ), act: (cubit) => cubit.getTheme(), verify: (_) => verify( () => userRepository.getThemeMode(), @@ -142,9 +150,15 @@ void main() { blocTest( 'Test setTheme function work when throw StorageException', build: () => userThemeCubit, - setUp: () => when( - () => userRepository.setThemeMode(themeMode: ThemeMode.system), - ).thenThrow(const StorageException('Error on storage Data')), + setUp: () => + when( + () => userRepository.setThemeMode(themeMode: ThemeMode.system), + ).thenThrow( + const StorageException( + StorageErrorCode.invalidValue, + descriptionMessage: 'Error on storage Data', + ), + ), act: (cubit) => cubit.setTheme( themeMode: ThemeMode.system, ), From 56d2cd2738d922642f71a5ebfe43c64d4c33f82d Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Mon, 4 May 2026 18:53:24 -0300 Subject: [PATCH 08/19] fix: update error handling in user page reading time repository - Changed error code from `writeFailed` to `invalidValue` in `user_page_reading_time_repository_impl.dart`. - Updated error handling in `programming_reading_bloc.dart` to use `StorageErrorCode` for better error categorization. - Refactored error handling in `reading_page_timer_bloc.dart` and `user_theme_cubit.dart` to utilize `StorageErrorCode` for consistent error messaging. - Modified state classes in `programming_reading_state.dart` and `reading_page_timer_state.dart` to include error code and description. - Updated UI components to display localized error messages based on error codes. - Adjusted localization in `pt_BR.json` for better clarity in user prompts. - Improved code formatting and readability in various files. - Bumped version to 2.11.5 in `pubspec.yaml`. --- assets/lang/it_IT.json | 2 +- assets/lang/pt_BR.json | 2 +- coverage/lcov.info | 725 +++++++++--------- ...ser_page_reading_time_repository_impl.dart | 2 +- lib/src/features/home/views/home_page.dart | 6 +- .../books_loaded_state_widget.dart | 6 +- .../bloc/programming_reading_bloc.dart | 37 +- .../bloc/programming_reading_state.dart | 6 +- .../views/programming_reading_page.dart | 9 +- .../bloc/reading_page_timer_bloc.dart | 24 +- .../bloc/reading_page_timer_state.dart | 6 +- .../views/reading_page_timer_page.dart | 8 +- lib/src/features/root/views/root_page.dart | 10 +- .../views/widgets/theme_settings.dart | 93 +-- .../user_theme_cubit/user_theme_cubit.dart | 24 +- .../user_theme_cubit/user_theme_state.dart | 6 +- pubspec.yaml | 2 +- ...age_reading_time_repository_impl_test.dart | 2 +- 18 files changed, 498 insertions(+), 472 deletions(-) diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index b2ae4d09..db940a9c 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -89,7 +89,7 @@ "no-books-found-with-terms": "Nessun libro trovato con questi termini.\nVerifica che sia stato digitato correttamente.", "enter-title-label": "Inserisci il Titolo", "enter-author-label": "Inserisci l'Autore", - "enter-category-label": "Inserisci la Categoria", + "enter-category-label": "Inserisci la Categoria (in Inglese)", "enter-publisher-label": "Inserisci l'Editore", "enter-isbn-label": "Inserisci l'ISBN", "delete-text-typed-tooltip": "Cancella il testo digitato.", diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index 94f2352a..0e3a1899 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -89,7 +89,7 @@ "no-books-found-with-terms": "Não foi encontrado nenhum livro com esses termos.\nVerifique se digitou corretamente.", "enter-title-label": "Digite o Título", "enter-author-label": "Digite o Autor", - "enter-category-label": "Digite o Gênero", + "enter-category-label": "Digite o Gênero (em Inglês)", "enter-publisher-label": "Digite a Editora", "enter-isbn-label": "Digite o ISBN", "delete-text-typed-tooltip": "Apagar o texto digitado.", diff --git a/coverage/lcov.info b/coverage/lcov.info index 54240cfc..a7ebb62d 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -220,8 +220,8 @@ LH:8 end_of_record SF:lib/src/core/errors/storage_exception/storage_exception.dart DA:7,4 -DA:12,5 -DA:13,15 +DA:12,2 +DA:13,6 LF:3 LH:3 end_of_record @@ -293,6 +293,172 @@ DA:20,0 LF:9 LH:4 end_of_record +SF:lib/src/core/enums/repeat_hour_time_type.dart +DA:5,1 +DA:7,1 +DA:8,0 +DA:9,0 +DA:13,1 +DA:15,1 +DA:16,0 +LF:7 +LH:4 +end_of_record +SF:lib/src/core/models/custom_notification_model.dart +DA:5,0 +DA:7,0 +DA:8,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:45,2 +DA:54,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:72,0 +DA:74,0 +DA:77,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:89,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +LF:37 +LH:1 +end_of_record +SF:lib/src/core/models/user_hour_time_model.dart +DA:12,1 +DA:20,2 +DA:22,1 +DA:24,4 +DA:27,4 +DA:30,1 +DA:31,1 +DA:33,0 +DA:37,1 +DA:41,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:57,1 +DA:58,1 +DA:59,2 +DA:60,1 +DA:61,1 +DA:62,1 +DA:63,1 +DA:67,1 +DA:68,1 +DA:70,2 +DA:71,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:78,3 +DA:80,1 +DA:81,2 +DA:83,0 +DA:85,0 +DA:88,2 +DA:92,3 +DA:93,3 +DA:94,3 +DA:95,3 +DA:96,3 +DA:99,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +LF:47 +LH:31 +end_of_record +SF:lib/src/features/programming_reading/bloc/programming_reading_state.dart +DA:10,1 +DA:24,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/programming_reading/bloc/programming_reading_bloc.dart +DA:18,1 +DA:21,2 +DA:22,2 +DA:23,2 +DA:24,2 +DA:27,1 +DA:32,2 +DA:34,2 +DA:36,1 +DA:37,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:48,1 +DA:49,1 +DA:50,1 +DA:58,1 +DA:63,2 +DA:65,1 +DA:67,1 +DA:68,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:82,2 +DA:83,1 +DA:86,1 +DA:87,1 +DA:88,2 +DA:89,2 +DA:90,2 +DA:91,1 +DA:92,1 +DA:97,2 +DA:98,1 +DA:99,1 +DA:100,1 +DA:105,1 +DA:106,1 +DA:107,1 +DA:115,1 +DA:120,2 +DA:122,2 +DA:123,1 +DA:126,2 +DA:127,1 +DA:128,1 +DA:129,1 +LF:48 +LH:48 +end_of_record +SF:lib/src/features/programming_reading/bloc/programming_reading_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record SF:lib/src/core/database/local_database.dart DA:5,0 DA:7,0 @@ -742,68 +908,6 @@ DA:139,1 LF:42 LH:42 end_of_record -SF:lib/src/core/enums/repeat_hour_time_type.dart -DA:5,1 -DA:7,1 -DA:8,0 -DA:9,0 -DA:13,1 -DA:15,1 -DA:16,0 -LF:7 -LH:4 -end_of_record -SF:lib/src/core/models/user_hour_time_model.dart -DA:12,1 -DA:20,2 -DA:22,1 -DA:24,4 -DA:27,4 -DA:30,1 -DA:31,1 -DA:33,0 -DA:37,1 -DA:41,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:57,1 -DA:58,1 -DA:59,2 -DA:60,1 -DA:61,1 -DA:62,1 -DA:63,1 -DA:67,1 -DA:68,1 -DA:70,2 -DA:71,1 -DA:72,1 -DA:73,1 -DA:74,1 -DA:78,3 -DA:80,1 -DA:81,2 -DA:83,0 -DA:85,0 -DA:88,2 -DA:92,3 -DA:93,3 -DA:94,3 -DA:95,3 -DA:96,3 -DA:99,0 -DA:101,0 -DA:102,0 -DA:103,0 -DA:104,0 -DA:105,0 -LF:47 -LH:31 -end_of_record SF:lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart DA:11,1 DA:15,1 @@ -823,34 +927,6 @@ DA:57,0 LF:15 LH:13 end_of_record -SF:lib/src/features/readings_timer/bloc/readings_timer_state.dart -DA:12,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/readings_timer/bloc/readings_timer_bloc.dart -DA:11,1 -DA:12,2 -DA:13,2 -DA:16,1 -DA:21,2 -DA:23,2 -DA:26,2 -DA:30,1 -DA:32,1 -DA:33,1 -DA:37,1 -DA:38,1 -DA:39,1 -DA:40,1 -DA:43,1 -DA:44,1 -DA:45,1 -DA:46,1 -LF:18 -LH:18 -end_of_record SF:lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart DA:12,1 DA:16,1 @@ -905,6 +981,41 @@ DA:41,2 LF:13 LH:13 end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 +LH:0 +end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart DA:21,1 DA:33,1 @@ -982,41 +1093,6 @@ DA:244,1 LF:73 LH:72 end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 -LH:0 -end_of_record SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart DA:11,1 DA:17,1 @@ -1521,46 +1597,42 @@ LF:98 LH:75 end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart -DA:11,1 -DA:13,2 -DA:15,1 -DA:17,2 -DA:19,2 -DA:22,2 -DA:25,1 +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:23,2 DA:26,1 -DA:31,1 +DA:27,1 DA:32,1 -DA:34,1 +DA:33,1 DA:35,1 DA:36,1 DA:37,1 -DA:40,1 -DA:41,1 DA:42,1 DA:43,1 -DA:49,1 -DA:51,2 -DA:53,2 -DA:57,1 -DA:58,1 -DA:59,1 -DA:66,1 -DA:67,1 -DA:69,1 +DA:44,1 +DA:52,1 +DA:54,2 +DA:56,2 +DA:60,1 +DA:61,1 +DA:62,1 DA:70,1 DA:71,1 -DA:72,1 +DA:73,1 +DA:74,1 DA:75,1 -DA:76,1 -DA:77,1 -DA:78,1 -LF:34 -LH:34 +DA:80,1 +DA:81,1 +DA:82,1 +LF:30 +LH:30 end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart DA:11,1 -DA:19,1 +DA:20,1 LF:2 LH:2 end_of_record @@ -1568,91 +1640,46 @@ SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart DA:11,1 DA:20,1 LF:2 -LH:2 -end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 -DA:22,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:27,1 -DA:28,1 -DA:29,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:16 -LH:16 -end_of_record -SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart -DA:13,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart -DA:10,1 -DA:12,2 -DA:14,1 -DA:16,2 -DA:18,2 -DA:20,2 -DA:21,1 -DA:22,1 -DA:23,1 -DA:24,1 -LF:10 -LH:10 -end_of_record -SF:lib/src/core/models/custom_notification_model.dart -DA:5,0 -DA:7,0 -DA:8,0 -DA:12,0 -DA:14,0 -DA:15,0 -DA:19,0 -DA:21,0 -DA:23,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:45,2 -DA:54,0 -DA:62,0 -DA:63,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:72,0 -DA:74,0 -DA:77,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:89,0 -DA:91,0 -DA:92,0 -DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -LF:37 +LH:2 +end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:22,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 +end_of_record +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart +DA:13,1 +LF:1 LH:1 end_of_record -SF:lib/src/features/readings_timer/bloc/readings_timer_event.dart -LF:0 -LH:0 +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart +DA:10,1 +DA:12,2 +DA:14,1 +DA:16,2 +DA:18,2 +DA:20,2 +DA:21,1 +DA:22,1 +DA:23,1 +DA:24,1 +LF:10 +LH:10 end_of_record SF:lib/src/features/about/bloc/about_bloc.dart DA:11,3 @@ -3889,64 +3916,62 @@ DA:13,1 DA:14,1 DA:22,1 DA:24,1 -DA:25,2 -DA:26,1 -DA:27,3 -DA:29,3 -DA:30,3 -DA:34,1 -DA:36,2 -DA:37,1 -DA:40,0 -DA:41,0 -DA:42,0 -DA:45,1 -DA:47,1 -DA:50,2 -DA:52,1 -DA:53,1 -DA:54,1 -DA:57,3 +DA:25,5 +DA:26,2 +DA:27,1 +DA:30,1 +DA:32,2 +DA:33,1 +DA:36,0 +DA:37,0 +DA:38,0 +DA:41,1 +DA:43,1 +DA:46,2 +DA:48,1 +DA:49,1 +DA:50,1 +DA:53,3 +DA:57,1 +DA:58,1 +DA:59,1 DA:61,1 -DA:62,1 DA:63,1 +DA:64,1 DA:65,1 -DA:67,1 -DA:68,1 -DA:69,1 +DA:71,0 +DA:72,0 +DA:74,0 DA:75,0 -DA:76,0 +DA:77,0 DA:78,0 -DA:79,0 +DA:80,0 DA:81,0 -DA:82,0 +DA:83,0 DA:84,0 -DA:85,0 +DA:86,0 DA:87,0 -DA:88,0 -DA:90,0 -DA:91,0 +DA:93,1 +DA:95,1 DA:97,1 -DA:99,1 +DA:98,0 +DA:99,3 +DA:100,1 DA:101,1 -DA:102,0 -DA:103,3 -DA:104,1 +DA:102,1 +DA:103,1 DA:105,1 -DA:106,1 -DA:107,1 -DA:109,1 -DA:115,1 -DA:117,1 +DA:111,1 +DA:113,1 +DA:114,1 DA:118,1 -DA:122,1 -DA:123,1 +DA:119,1 +DA:120,1 +DA:121,0 +DA:122,0 DA:124,1 -DA:125,0 -DA:126,0 -DA:128,1 -LF:61 -LH:43 +LF:59 +LH:41 end_of_record SF:lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart DA:5,1 @@ -4055,9 +4080,9 @@ SF:lib/src/features/home/widgets/book_loaded_state_widget/books_loaded_state_wid DA:9,1 DA:14,1 DA:16,1 -DA:19,1 -DA:21,1 -DA:22,0 +DA:23,1 +DA:25,1 +DA:26,0 LF:6 LH:5 end_of_record @@ -4187,96 +4212,28 @@ DA:24,1 LF:2 LH:2 end_of_record -SF:lib/src/features/programming_reading/bloc/programming_reading_state.dart -DA:10,1 -DA:23,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/programming_reading/bloc/programming_reading_bloc.dart -DA:17,1 -DA:20,2 -DA:21,2 -DA:22,2 -DA:23,2 -DA:26,1 -DA:31,2 -DA:33,2 -DA:35,1 -DA:36,1 -DA:40,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:46,1 -DA:47,1 -DA:48,1 -DA:49,1 -DA:55,1 -DA:60,2 -DA:62,1 -DA:65,2 -DA:69,1 -DA:70,1 -DA:71,1 -DA:78,2 -DA:79,1 -DA:82,1 -DA:83,1 -DA:84,2 -DA:85,2 -DA:86,2 -DA:87,1 -DA:88,1 -DA:93,2 -DA:94,1 -DA:95,1 -DA:96,1 -DA:97,1 -DA:100,1 -DA:101,1 -DA:102,1 -DA:103,1 -DA:109,1 -DA:114,2 -DA:116,2 -DA:117,1 -DA:120,2 -DA:121,1 -DA:122,1 -DA:123,1 -DA:124,1 -LF:52 -LH:52 -end_of_record -SF:lib/src/features/programming_reading/bloc/programming_reading_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart -DA:13,1 -DA:15,2 +DA:14,1 DA:16,2 -DA:19,1 -DA:24,2 -DA:26,1 +DA:17,2 +DA:20,1 +DA:25,2 DA:27,1 -DA:31,2 -DA:35,1 +DA:28,1 +DA:31,1 +DA:32,1 DA:36,1 DA:37,1 -DA:44,2 -DA:45,1 -DA:46,1 -DA:47,1 +DA:38,1 +DA:47,2 DA:48,1 -DA:51,1 -DA:52,1 -DA:53,1 -DA:54,1 -LF:20 -LH:20 +DA:49,1 +DA:50,1 +DA:56,1 +DA:57,1 +DA:58,1 +LF:19 +LH:19 end_of_record SF:lib/src/features/reading_page_timer/bloc/reading_page_timer_event.dart DA:8,1 @@ -4284,7 +4241,7 @@ LF:1 LH:1 end_of_record SF:lib/src/features/reading_page_timer/bloc/reading_page_timer_state.dart -DA:12,1 +DA:13,1 LF:1 LH:1 end_of_record @@ -4452,6 +4409,34 @@ DA:82,1 LF:29 LH:29 end_of_record +SF:lib/src/features/readings_timer/bloc/readings_timer_state.dart +DA:12,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/readings_timer/bloc/readings_timer_bloc.dart +DA:11,1 +DA:12,2 +DA:13,2 +DA:16,1 +DA:21,2 +DA:23,2 +DA:26,2 +DA:30,1 +DA:32,1 +DA:33,1 +DA:37,1 +DA:38,1 +DA:39,1 +DA:40,1 +DA:43,1 +DA:44,1 +DA:45,1 +DA:46,1 +LF:18 +LH:18 +end_of_record SF:lib/src/features/qr_code_scanner/views/qr_code_scanner_page.dart DA:13,1 DA:15,1 diff --git a/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart b/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart index 0439a687..bc690a44 100644 --- a/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart +++ b/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart @@ -29,7 +29,7 @@ class UserPageReadingTimeRepositoryImpl return userPageReadingTime; } on TypeError { throw const StorageException( - StorageErrorCode.writeFailed, + StorageErrorCode.invalidValue, descriptionMessage: 'Impossible to convert user page reading time.', ); } on StorageException { diff --git a/lib/src/features/home/views/home_page.dart b/lib/src/features/home/views/home_page.dart index 9b3a8756..b2237cc4 100644 --- a/lib/src/features/home/views/home_page.dart +++ b/lib/src/features/home/views/home_page.dart @@ -22,13 +22,9 @@ class _HomePageState extends State { @override void initState() { super.initState(); + _bookBloc = context.read()..add(GotAllBooksEvent()); _searchEC = TextEditingController(); _isSearchBarVisible = false; - _bookBloc = context.read(); - - WidgetsBinding.instance.addPostFrameCallback((_) { - _bookBloc.add(GotAllBooksEvent()); - }); } @override diff --git a/lib/src/features/home/widgets/book_loaded_state_widget/books_loaded_state_widget.dart b/lib/src/features/home/widgets/book_loaded_state_widget/books_loaded_state_widget.dart index 91e4836b..25b704c6 100644 --- a/lib/src/features/home/widgets/book_loaded_state_widget/books_loaded_state_widget.dart +++ b/lib/src/features/home/widgets/book_loaded_state_widget/books_loaded_state_widget.dart @@ -15,7 +15,11 @@ class BooksLoadedStateWidget extends StatelessWidget { Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only( - top: 8.0, right: 16.0, left: 16.0, bottom: 16.0), + top: 8.0, + right: 16.0, + left: 16.0, + bottom: 16.0, + ), child: BooksGridView( key: const Key('BooksGridView'), books: books, diff --git a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart index 1943d9ad..9796f851 100644 --- a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart +++ b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; @@ -37,16 +38,18 @@ class ProgrammingReadingBloc userHourTimeModel: userHourTimeModel, ), ); - } on StorageException catch (e) { + } on StorageException { emit( ProgrammingReadingErrorState( - errorMessage: 'Erro ao buscar a hora para leitura: $e', + errorCode: StorageErrorCode.readFailed, + errorDescriptionMessage: 'Failed to load reading hour time', ), ); - } on Exception catch (e) { + } on Exception { emit( ProgrammingReadingErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: 'Unexpected error occurred', ), ); } @@ -61,15 +64,16 @@ class ProgrammingReadingBloc final userHourTime = event.userHourTimeModel; - final userHourTimeInserted = - await _userHourTimeRepository.setUserHourTime( - userHourTime: userHourTime, - ); + final userHourTimeInserted = await _userHourTimeRepository + .setUserHourTime( + userHourTime: userHourTime, + ); if (userHourTimeInserted == 0) { emit( ProgrammingReadingErrorState( - errorMessage: 'Erro ao inserir buscar a hora de leitura', + errorCode: StorageErrorCode.writeFailed, + errorDescriptionMessage: 'Failed to insert reading hour time', ), ); return; @@ -91,16 +95,18 @@ class ProgrammingReadingBloc ); emit(ProgrammingReadingInsertedState()); - } on StorageException catch (e) { + } on StorageException { emit( ProgrammingReadingErrorState( - errorMessage: 'Erro ao inserir a hora de leitura: $e', + errorCode: StorageErrorCode.writeFailed, + errorDescriptionMessage: 'Failed to insert reading hour time', ), ); - } on Exception catch (e) { + } on Exception { emit( ProgrammingReadingErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: 'Unexpected error occurred', ), ); } @@ -118,10 +124,11 @@ class ProgrammingReadingBloc ); emit(ProgrammingReadingRemovedNotificationState()); - } on Exception catch (e) { + } on Exception { emit( ProgrammingReadingErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: 'An unexpected error occurred', ), ); } diff --git a/lib/src/features/programming_reading/bloc/programming_reading_state.dart b/lib/src/features/programming_reading/bloc/programming_reading_state.dart index 6af117c9..2120c3af 100644 --- a/lib/src/features/programming_reading/bloc/programming_reading_state.dart +++ b/lib/src/features/programming_reading/bloc/programming_reading_state.dart @@ -18,9 +18,11 @@ final class ProgrammingReadingRemovedNotificationState extends ProgrammingReadingState {} final class ProgrammingReadingErrorState extends ProgrammingReadingState { - final String errorMessage; + final StorageErrorCode errorCode; + final String? errorDescriptionMessage; ProgrammingReadingErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/programming_reading/views/programming_reading_page.dart b/lib/src/features/programming_reading/views/programming_reading_page.dart index 33b24b6a..ab546856 100644 --- a/lib/src/features/programming_reading/views/programming_reading_page.dart +++ b/lib/src/features/programming_reading/views/programming_reading_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/services/app_services/snackbar_service/snackbar_service.dart'; import 'package:bookify/src/features/programming_reading/bloc/programming_reading_bloc.dart'; @@ -50,9 +51,13 @@ class _ProgrammingHourState extends State { RemovedNotificationHourTimeEvent(), ), ), - ProgrammingReadingErrorState(:final errorMessage) => Center( + ProgrammingReadingErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => + Center( child: InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _onRefreshPage, ), ), diff --git a/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart b/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart index 1568e3aa..c9952d0e 100644 --- a/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart +++ b/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; @@ -27,31 +28,36 @@ class ReadingPageTimerBloc pageReadingTimeSeconds: event.readingPageTime, ); - final userPageReadingTimeInserted = - await _userPageReadingTimeRepository.setUserPageReadingTime( - userPageReadingTime: userPageReading, - ); + final userPageReadingTimeInserted = await _userPageReadingTimeRepository + .setUserPageReadingTime( + userPageReadingTime: userPageReading, + ); if (userPageReadingTimeInserted == 0) { emit( ReadingPageTimerErrorState( - errorMessage: 'Erro ao inserir o tempo de leitura da página', + errorCode: StorageErrorCode.writeFailed, + errorDescriptionMessage: + 'Failed to save page reading time. Please try again.', ), ); return; } emit(ReadingPageTimerInsertedState()); - } on StorageException catch (e) { + } on StorageException { emit( ReadingPageTimerErrorState( - errorMessage: 'Erro ao inserir o tempo de leitura da página: $e', + errorCode: StorageErrorCode.writeFailed, + errorDescriptionMessage: + ' Failed to save page reading time. Please try again.', ), ); - } on Exception catch (e) { + } on Exception { emit( ReadingPageTimerErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: 'An unexpected error occurred', ), ); } diff --git a/lib/src/features/reading_page_timer/bloc/reading_page_timer_state.dart b/lib/src/features/reading_page_timer/bloc/reading_page_timer_state.dart index 7b3b2581..9c359374 100644 --- a/lib/src/features/reading_page_timer/bloc/reading_page_timer_state.dart +++ b/lib/src/features/reading_page_timer/bloc/reading_page_timer_state.dart @@ -7,9 +7,11 @@ final class ReadingPageTimerLoadingState extends ReadingPageTimerState {} final class ReadingPageTimerInsertedState extends ReadingPageTimerState {} final class ReadingPageTimerErrorState extends ReadingPageTimerState { - final String errorMessage; + final StorageErrorCode errorCode; + final String? errorDescriptionMessage; ReadingPageTimerErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/reading_page_timer/views/reading_page_timer_page.dart b/lib/src/features/reading_page_timer/views/reading_page_timer_page.dart index 3b09750b..e4d1de6c 100644 --- a/lib/src/features/reading_page_timer/views/reading_page_timer_page.dart +++ b/lib/src/features/reading_page_timer/views/reading_page_timer_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/core/services/app_services/snackbar_service/snackbar_service.dart'; import 'package:bookify/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart'; import 'widgets/reading_page_timer_loaded_state_widget.dart'; @@ -49,10 +50,13 @@ class _ReadingPageTimerPageState extends State { Navigator.of(context).pop, ); break; - case ReadingPageTimerErrorState(:final errorMessage): + case ReadingPageTimerErrorState( + :final errorCode, + :final errorDescriptionMessage, + ): SnackbarService.showSnackBar( context, - errorMessage, + errorCode.toLocalizedMessage(errorDescriptionMessage), SnackBarType.error, ); break; diff --git a/lib/src/features/root/views/root_page.dart b/lib/src/features/root/views/root_page.dart index 51b55b59..876e1c7d 100644 --- a/lib/src/features/root/views/root_page.dart +++ b/lib/src/features/root/views/root_page.dart @@ -76,10 +76,12 @@ class _RootPageState extends State { } Future _scanAndGetIsbnCode(BuildContext context) async { - final isbn = await Navigator.pushNamed( - context, - QrCodeScannerPage.routeName, - ) as String?; + final isbn = + await Navigator.pushNamed( + context, + QrCodeScannerPage.routeName, + ) + as String?; if (isbn != null) { _bookBloc.add(FoundBooksByIsbnEvent(isbn: isbn)); diff --git a/lib/src/features/settings/views/widgets/theme_settings.dart b/lib/src/features/settings/views/widgets/theme_settings.dart index 1336979a..0c8bcd06 100644 --- a/lib/src/features/settings/views/widgets/theme_settings.dart +++ b/lib/src/features/settings/views/widgets/theme_settings.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/features/settings/views/widgets/settings_container.dart'; import 'package:bookify/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; @@ -25,55 +26,59 @@ class _ThemeSettingsState extends State { return switch (state) { UserThemeLoadingState() => const CenterCircularProgressIndicator(), UserThemeLoadedState(:final themeMode) => SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: RadioGroup( - groupValue: themeMode, - onChanged: _onChangedRadioButton, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'light-theme-label'.i18n(), - overflow: TextOverflow.ellipsis, - textScaler: TextScaler.noScaling, - style: TextStyle( - fontSize: 10, - color: Theme.of(context).colorScheme.primary, - ), + scrollDirection: Axis.horizontal, + child: RadioGroup( + groupValue: themeMode, + onChanged: _onChangedRadioButton, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'light-theme-label'.i18n(), + overflow: TextOverflow.ellipsis, + textScaler: TextScaler.noScaling, + style: TextStyle( + fontSize: 10, + color: Theme.of(context).colorScheme.primary, ), - Radio.adaptive( - value: ThemeMode.light, + ), + Radio.adaptive( + value: ThemeMode.light, + ), + Text( + 'dark-theme-label'.i18n(), + overflow: TextOverflow.ellipsis, + textScaler: TextScaler.noScaling, + style: TextStyle( + fontSize: 10, + color: Theme.of(context).colorScheme.primary, ), - Text( - 'dark-theme-label'.i18n(), - overflow: TextOverflow.ellipsis, - textScaler: TextScaler.noScaling, - style: TextStyle( - fontSize: 10, - color: Theme.of(context).colorScheme.primary, - ), + ), + Radio.adaptive( + value: ThemeMode.dark, + ), + Text( + 'system-theme-label'.i18n(), + overflow: TextOverflow.ellipsis, + textScaler: TextScaler.noScaling, + style: TextStyle( + fontSize: 10, + color: Theme.of(context).colorScheme.primary, ), - Radio.adaptive( - value: ThemeMode.dark, - ), - Text( - 'system-theme-label'.i18n(), - overflow: TextOverflow.ellipsis, - textScaler: TextScaler.noScaling, - style: TextStyle( - fontSize: 10, - color: Theme.of(context).colorScheme.primary, - ), - ), - Radio.adaptive( - value: ThemeMode.system, - ), - ], - ), + ), + Radio.adaptive( + value: ThemeMode.system, + ), + ], ), ), - UserThemeErrorState(:final errorMessage) => Text( - errorMessage, + ), + UserThemeErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => + Text( + errorCode.toLocalizedMessage(errorDescriptionMessage), style: const TextStyle( fontSize: 14, ), diff --git a/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart b/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart index e8c5608b..024b65b0 100644 --- a/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart +++ b/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_theme_repository/user_theme_repository.dart'; import 'package:flutter/material.dart'; @@ -31,16 +32,18 @@ class UserThemeCubit extends Cubit { emit( UserThemeLoadedState(themeMode: theme), ); - } on StorageException catch (e) { + } on StorageException { emit( UserThemeErrorState( - errorMessage: 'erro ao buscar o tema: $e', + errorCode: StorageErrorCode.readFailed, + errorDescriptionMessage: ' Failed to load theme. Please try again.', ), ); - } on Exception catch (e) { + } on Exception { emit( UserThemeErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: 'An unexpected error occurred', ), ); } @@ -57,7 +60,8 @@ class UserThemeCubit extends Cubit { if (themeInserted == 0) { emit( UserThemeErrorState( - errorMessage: 'erro ao inserir o tema', + errorCode: StorageErrorCode.writeFailed, + errorDescriptionMessage: 'Failed to save theme. Please try again.', ), ); return; @@ -66,16 +70,18 @@ class UserThemeCubit extends Cubit { emit( UserThemeLoadedState(themeMode: themeMode), ); - } on StorageException catch (e) { + } on StorageException { emit( UserThemeErrorState( - errorMessage: 'erro ao inserir o tema: $e', + errorCode: StorageErrorCode.writeFailed, + errorDescriptionMessage: 'Failed to save theme. Please try again.', ), ); - } on Exception catch (e) { + } on Exception { emit( UserThemeErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: 'An unexpected error occurred', ), ); } diff --git a/lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart b/lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart index bfdef307..9f3423a1 100644 --- a/lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart +++ b/lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart @@ -14,9 +14,11 @@ final class UserThemeLoadedState extends UserThemeState { } final class UserThemeErrorState extends UserThemeState { - final String errorMessage; + final StorageErrorCode errorCode; + final String? errorDescriptionMessage; UserThemeErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/pubspec.yaml b/pubspec.yaml index af634bdb..38c91dff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.4 +version: 2.11.5 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart b/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart index 5efed6bf..6950bdff 100644 --- a/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart +++ b/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart @@ -75,7 +75,7 @@ void main() { throwsA( (Exception e) => e is StorageException && - e.code == StorageErrorCode.writeFailed && + e.code == StorageErrorCode.invalidValue && e.descriptionMessage == 'Impossible to convert user page reading time.', ), From 7291d551a8bd78bbe916021853846bbf374f68d2 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Mon, 11 May 2026 16:34:40 -0300 Subject: [PATCH 09/19] feat: Improve error handling with detailed messages and update version to 2.11.6 --- .gitignore | 3 + coverage/lcov.info | 588 ++++++++++-------- .../bloc/book_pages_reading_time_bloc.dart | 11 +- .../bloc/book_pages_reading_time_state.dart | 6 +- .../widgets/book_pages_reading_time.dart | 29 +- .../bloc/programming_reading_bloc.dart | 31 +- .../bloc/reading_page_timer_bloc.dart | 11 +- .../user_theme_cubit/user_theme_cubit.dart | 20 +- pubspec.yaml | 2 +- 9 files changed, 379 insertions(+), 322 deletions(-) diff --git a/.gitignore b/.gitignore index 855c1273..5aeb1bb0 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,9 @@ # Web related lib/generated_plugin_registrant.dart +# Debug Symbols +/debug_symbols/ + # Symbolication related app.*.symbols diff --git a/coverage/lcov.info b/coverage/lcov.info index a7ebb62d..49a689d7 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -9,6 +9,29 @@ DA:15,9 LF:7 LH:7 end_of_record +SF:lib/src/shared/constants/database_scripts/database_scripts.dart +DA:3,0 +DA:6,4 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:18,1 +DA:21,1 +DA:24,1 +DA:27,1 +DA:30,1 +DA:34,1 +DA:41,1 +DA:44,1 +DA:47,1 +LF:19 +LH:18 +end_of_record SF:lib/src/core/models/author_model.dart DA:5,10 DA:10,9 @@ -157,29 +180,6 @@ DA:53,0 LF:22 LH:11 end_of_record -SF:lib/src/shared/constants/database_scripts/database_scripts.dart -DA:3,0 -DA:6,4 -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:11,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:18,1 -DA:21,1 -DA:24,1 -DA:27,1 -DA:30,1 -DA:34,1 -DA:41,1 -DA:44,1 -DA:47,1 -LF:19 -LH:18 -end_of_record SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart DA:14,2 DA:16,1 @@ -220,8 +220,8 @@ LH:8 end_of_record SF:lib/src/core/errors/storage_exception/storage_exception.dart DA:7,4 -DA:12,2 -DA:13,6 +DA:12,1 +DA:13,3 LF:3 LH:3 end_of_record @@ -293,172 +293,6 @@ DA:20,0 LF:9 LH:4 end_of_record -SF:lib/src/core/enums/repeat_hour_time_type.dart -DA:5,1 -DA:7,1 -DA:8,0 -DA:9,0 -DA:13,1 -DA:15,1 -DA:16,0 -LF:7 -LH:4 -end_of_record -SF:lib/src/core/models/custom_notification_model.dart -DA:5,0 -DA:7,0 -DA:8,0 -DA:12,0 -DA:14,0 -DA:15,0 -DA:19,0 -DA:21,0 -DA:23,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:45,2 -DA:54,0 -DA:62,0 -DA:63,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:72,0 -DA:74,0 -DA:77,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:89,0 -DA:91,0 -DA:92,0 -DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -LF:37 -LH:1 -end_of_record -SF:lib/src/core/models/user_hour_time_model.dart -DA:12,1 -DA:20,2 -DA:22,1 -DA:24,4 -DA:27,4 -DA:30,1 -DA:31,1 -DA:33,0 -DA:37,1 -DA:41,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:57,1 -DA:58,1 -DA:59,2 -DA:60,1 -DA:61,1 -DA:62,1 -DA:63,1 -DA:67,1 -DA:68,1 -DA:70,2 -DA:71,1 -DA:72,1 -DA:73,1 -DA:74,1 -DA:78,3 -DA:80,1 -DA:81,2 -DA:83,0 -DA:85,0 -DA:88,2 -DA:92,3 -DA:93,3 -DA:94,3 -DA:95,3 -DA:96,3 -DA:99,0 -DA:101,0 -DA:102,0 -DA:103,0 -DA:104,0 -DA:105,0 -LF:47 -LH:31 -end_of_record -SF:lib/src/features/programming_reading/bloc/programming_reading_state.dart -DA:10,1 -DA:24,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/programming_reading/bloc/programming_reading_bloc.dart -DA:18,1 -DA:21,2 -DA:22,2 -DA:23,2 -DA:24,2 -DA:27,1 -DA:32,2 -DA:34,2 -DA:36,1 -DA:37,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:48,1 -DA:49,1 -DA:50,1 -DA:58,1 -DA:63,2 -DA:65,1 -DA:67,1 -DA:68,1 -DA:72,1 -DA:73,1 -DA:74,1 -DA:82,2 -DA:83,1 -DA:86,1 -DA:87,1 -DA:88,2 -DA:89,2 -DA:90,2 -DA:91,1 -DA:92,1 -DA:97,2 -DA:98,1 -DA:99,1 -DA:100,1 -DA:105,1 -DA:106,1 -DA:107,1 -DA:115,1 -DA:120,2 -DA:122,2 -DA:123,1 -DA:126,2 -DA:127,1 -DA:128,1 -DA:129,1 -LF:48 -LH:48 -end_of_record -SF:lib/src/features/programming_reading/bloc/programming_reading_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/core/database/local_database.dart DA:5,0 DA:7,0 @@ -467,7 +301,7 @@ LF:3 LH:0 end_of_record SF:lib/src/core/errors/local_database_exception/local_database_exception.dart -DA:4,2 +DA:4,3 DA:6,1 DA:7,1 LF:3 @@ -908,6 +742,68 @@ DA:139,1 LF:42 LH:42 end_of_record +SF:lib/src/core/enums/repeat_hour_time_type.dart +DA:5,1 +DA:7,1 +DA:8,0 +DA:9,0 +DA:13,1 +DA:15,1 +DA:16,0 +LF:7 +LH:4 +end_of_record +SF:lib/src/core/models/user_hour_time_model.dart +DA:12,1 +DA:20,2 +DA:22,1 +DA:24,4 +DA:27,4 +DA:30,1 +DA:31,1 +DA:33,0 +DA:37,1 +DA:41,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:57,1 +DA:58,1 +DA:59,2 +DA:60,1 +DA:61,1 +DA:62,1 +DA:63,1 +DA:67,1 +DA:68,1 +DA:70,2 +DA:71,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:78,3 +DA:80,1 +DA:81,2 +DA:83,0 +DA:85,0 +DA:88,2 +DA:92,3 +DA:93,3 +DA:94,3 +DA:95,3 +DA:96,3 +DA:99,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +LF:47 +LH:31 +end_of_record SF:lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart DA:11,1 DA:15,1 @@ -1585,56 +1481,16 @@ DA:208,2 DA:210,1 DA:211,2 DA:215,2 -DA:216,0 -DA:217,0 -DA:218,0 -DA:219,0 -DA:220,0 -DA:224,0 -DA:225,0 -DA:227,0 -LF:98 -LH:75 -end_of_record -SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 -DA:23,2 -DA:26,1 -DA:27,1 -DA:32,1 -DA:33,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:42,1 -DA:43,1 -DA:44,1 -DA:52,1 -DA:54,2 -DA:56,2 -DA:60,1 -DA:61,1 -DA:62,1 -DA:70,1 -DA:71,1 -DA:73,1 -DA:74,1 -DA:75,1 -DA:80,1 -DA:81,1 -DA:82,1 -LF:30 -LH:30 -end_of_record -SF:lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 +DA:216,0 +DA:217,0 +DA:218,0 +DA:219,0 +DA:220,0 +DA:224,0 +DA:225,0 +DA:227,0 +LF:98 +LH:75 end_of_record SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart DA:11,1 @@ -1681,6 +1537,93 @@ DA:24,1 LF:10 LH:10 end_of_record +SF:lib/src/core/models/custom_notification_model.dart +DA:5,0 +DA:7,0 +DA:8,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:45,2 +DA:54,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:72,0 +DA:74,0 +DA:77,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:89,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +LF:37 +LH:1 +end_of_record +SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:23,2 +DA:26,1 +DA:27,1 +DA:32,1 +DA:33,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:39,1 +DA:42,1 +DA:43,1 +DA:44,1 +DA:46,1 +DA:52,1 +DA:54,2 +DA:56,2 +DA:60,1 +DA:61,1 +DA:62,1 +DA:70,1 +DA:71,1 +DA:73,1 +DA:74,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:80,1 +DA:81,1 +DA:82,1 +DA:84,1 +LF:36 +LH:36 +end_of_record +SF:lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart +DA:11,1 +DA:20,1 +LF:2 +LH:2 +end_of_record SF:lib/src/features/about/bloc/about_bloc.dart DA:11,3 DA:12,2 @@ -1833,31 +1776,44 @@ LF:8 LH:4 end_of_record SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart -DA:13,1 -DA:15,2 +DA:14,1 DA:16,2 -DA:19,1 -DA:24,2 -DA:27,2 -DA:29,1 +DA:17,2 +DA:20,1 +DA:25,2 +DA:27,1 +DA:28,1 DA:30,1 -DA:34,1 +DA:31,1 DA:35,1 DA:36,1 DA:37,1 -DA:40,1 -DA:41,1 +DA:38,1 +DA:39,1 DA:42,1 DA:43,1 -LF:16 -LH:16 +DA:44,1 +DA:46,1 +LF:18 +LH:18 end_of_record SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart DA:11,1 -DA:19,1 +DA:20,1 LF:2 LH:2 end_of_record +SF:lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart +DA:5,0 +DA:9,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:17,0 +DA:20,0 +LF:7 +LH:0 +end_of_record SF:lib/src/core/services/app_services/launcher_service/launcher_service.dart DA:4,0 DA:6,0 @@ -2132,30 +2088,34 @@ LF:12 LH:12 end_of_record SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart -DA:10,1 -DA:15,1 +DA:11,1 DA:16,1 -DA:22,1 -DA:24,1 -DA:25,3 -DA:26,1 +DA:17,1 +DA:23,1 +DA:25,1 +DA:26,3 DA:27,1 -DA:31,1 -DA:36,1 -DA:38,0 +DA:28,1 +DA:32,1 +DA:37,1 DA:39,0 -DA:41,0 +DA:40,0 DA:42,0 -DA:45,0 +DA:43,0 DA:46,0 -DA:50,0 -DA:54,0 +DA:47,0 +DA:51,0 +DA:52,0 +DA:53,0 DA:55,0 -DA:62,1 -DA:64,1 -DA:65,1 -DA:66,1 -LF:23 +DA:56,0 +DA:59,0 +DA:60,0 +DA:67,1 +DA:69,1 +DA:70,1 +DA:71,1 +LF:27 LH:14 end_of_record SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart @@ -4212,6 +4172,81 @@ DA:24,1 LF:2 LH:2 end_of_record +SF:lib/src/features/programming_reading/bloc/programming_reading_state.dart +DA:10,1 +DA:24,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/programming_reading/bloc/programming_reading_bloc.dart +DA:18,1 +DA:21,2 +DA:22,2 +DA:23,2 +DA:24,2 +DA:27,1 +DA:32,2 +DA:34,2 +DA:36,1 +DA:37,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:44,1 +DA:45,1 +DA:48,1 +DA:49,1 +DA:50,1 +DA:52,1 +DA:58,1 +DA:63,2 +DA:65,1 +DA:67,1 +DA:68,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:82,2 +DA:83,1 +DA:86,1 +DA:87,1 +DA:88,2 +DA:89,2 +DA:90,2 +DA:91,1 +DA:92,1 +DA:97,2 +DA:98,1 +DA:99,1 +DA:100,1 +DA:101,1 +DA:102,1 +DA:105,1 +DA:106,1 +DA:107,1 +DA:109,1 +DA:115,1 +DA:120,2 +DA:122,2 +DA:123,1 +DA:126,2 +DA:127,1 +DA:128,0 +DA:129,0 +DA:130,0 +DA:131,0 +DA:134,1 +DA:135,1 +DA:136,1 +DA:138,1 +LF:60 +LH:56 +end_of_record +SF:lib/src/features/programming_reading/bloc/programming_reading_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record SF:lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart DA:14,1 DA:16,2 @@ -4229,11 +4264,14 @@ DA:47,2 DA:48,1 DA:49,1 DA:50,1 +DA:51,1 +DA:52,1 +DA:55,1 DA:56,1 DA:57,1 -DA:58,1 -LF:19 -LH:19 +DA:59,1 +LF:22 +LH:22 end_of_record SF:lib/src/features/reading_page_timer/bloc/reading_page_timer_event.dart DA:8,1 diff --git a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart index ed4f56e3..402ad7fe 100644 --- a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart +++ b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; @@ -23,8 +24,8 @@ class BookPagesReadingTimeBloc try { emit(BookPagesReadingTimeLoadingState()); - final userPageReadingTime = - await _userPageReadingTimeRepository.getUserPageReadingTime(); + final userPageReadingTime = await _userPageReadingTimeRepository + .getUserPageReadingTime(); emit( BookPagesReadingTimeLoadedState( @@ -34,13 +35,15 @@ class BookPagesReadingTimeBloc } on StorageException catch (e) { emit( BookPagesReadingTimeErrorState( - errorMessage: 'Erro ao buscar o tempo de leitura da página: $e', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } on Exception catch (e) { emit( BookPagesReadingTimeErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart index 9b0cc424..f8bec512 100644 --- a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart +++ b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart @@ -14,9 +14,11 @@ final class BookPagesReadingTimeLoadedState extends BookPagesReadingTimeState { } final class BookPagesReadingTimeErrorState extends BookPagesReadingTimeState { - final String errorMessage; + final StorageErrorCode errorCode; + final String? errorDescriptionMessage; BookPagesReadingTimeErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart index 6e5f4cd3..0238fae6 100644 --- a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart +++ b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; import 'package:flutter/material.dart'; @@ -36,19 +37,23 @@ class _BookPagesReadingTimeState extends State { BookPagesReadingTimeLoadingState() => const CenterCircularProgressIndicator(), BookPagesReadingTimeLoadedState(:final userPageReadingTime) => Text( - 'hours-to-read-label'.i18n([ - userPageReadingTime - .readingTimeForTotalBookPage(widget.pagesCount) - .toString() - ]), - textScaler: TextScaler.noScaling, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - fontSize: 14, - ), + 'hours-to-read-label'.i18n([ + userPageReadingTime + .readingTimeForTotalBookPage(widget.pagesCount) + .toString(), + ]), + textScaler: TextScaler.noScaling, + style: TextStyle( + color: Theme.of(context).colorScheme.primary, + fontSize: 14, ), - BookPagesReadingTimeErrorState(:final errorMessage) => Text( - errorMessage, + ), + BookPagesReadingTimeErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => + Text( + errorCode.toLocalizedMessage(errorDescriptionMessage), overflow: TextOverflow.ellipsis, textScaler: TextScaler.noScaling, style: TextStyle( diff --git a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart index 9796f851..929e806a 100644 --- a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart +++ b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart @@ -38,18 +38,18 @@ class ProgrammingReadingBloc userHourTimeModel: userHourTimeModel, ), ); - } on StorageException { + } on StorageException catch (e) { emit( ProgrammingReadingErrorState( - errorCode: StorageErrorCode.readFailed, - errorDescriptionMessage: 'Failed to load reading hour time', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); - } on Exception { + } on Exception catch (e) { emit( ProgrammingReadingErrorState( errorCode: StorageErrorCode.unknown, - errorDescriptionMessage: 'Unexpected error occurred', + errorDescriptionMessage: e.toString(), ), ); } @@ -95,18 +95,18 @@ class ProgrammingReadingBloc ); emit(ProgrammingReadingInsertedState()); - } on StorageException { + } on StorageException catch (e) { emit( ProgrammingReadingErrorState( - errorCode: StorageErrorCode.writeFailed, - errorDescriptionMessage: 'Failed to insert reading hour time', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); - } on Exception { + } on Exception catch (e) { emit( ProgrammingReadingErrorState( errorCode: StorageErrorCode.unknown, - errorDescriptionMessage: 'Unexpected error occurred', + errorDescriptionMessage: e.toString(), ), ); } @@ -124,11 +124,18 @@ class ProgrammingReadingBloc ); emit(ProgrammingReadingRemovedNotificationState()); - } on Exception { + } on StorageException catch (e) { + emit( + ProgrammingReadingErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); + } on Exception catch (e) { emit( ProgrammingReadingErrorState( errorCode: StorageErrorCode.unknown, - errorDescriptionMessage: 'An unexpected error occurred', + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart b/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart index c9952d0e..c321c31e 100644 --- a/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart +++ b/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart @@ -45,19 +45,18 @@ class ReadingPageTimerBloc } emit(ReadingPageTimerInsertedState()); - } on StorageException { + } on StorageException catch (e) { emit( ReadingPageTimerErrorState( - errorCode: StorageErrorCode.writeFailed, - errorDescriptionMessage: - ' Failed to save page reading time. Please try again.', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); - } on Exception { + } on Exception catch (e) { emit( ReadingPageTimerErrorState( errorCode: StorageErrorCode.unknown, - errorDescriptionMessage: 'An unexpected error occurred', + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart b/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart index 024b65b0..dfc2ff9e 100644 --- a/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart +++ b/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart @@ -32,18 +32,18 @@ class UserThemeCubit extends Cubit { emit( UserThemeLoadedState(themeMode: theme), ); - } on StorageException { + } on StorageException catch (e) { emit( UserThemeErrorState( - errorCode: StorageErrorCode.readFailed, - errorDescriptionMessage: ' Failed to load theme. Please try again.', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); - } on Exception { + } on Exception catch (e) { emit( UserThemeErrorState( errorCode: StorageErrorCode.unknown, - errorDescriptionMessage: 'An unexpected error occurred', + errorDescriptionMessage: e.toString(), ), ); } @@ -70,18 +70,18 @@ class UserThemeCubit extends Cubit { emit( UserThemeLoadedState(themeMode: themeMode), ); - } on StorageException { + } on StorageException catch (e) { emit( UserThemeErrorState( - errorCode: StorageErrorCode.writeFailed, - errorDescriptionMessage: 'Failed to save theme. Please try again.', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); - } on Exception { + } on Exception catch (e) { emit( UserThemeErrorState( errorCode: StorageErrorCode.unknown, - errorDescriptionMessage: 'An unexpected error occurred', + errorDescriptionMessage: e.toString(), ), ); } diff --git a/pubspec.yaml b/pubspec.yaml index 38c91dff..8ebc5173 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.5 +version: 2.11.6 environment: sdk: ">=3.10.0 <4.0.0" From ccabca741d02635202f1bd1d18130d17cf54a75b Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Wed, 13 May 2026 16:17:04 -0300 Subject: [PATCH 10/19] refactor: move enums from core to shared for better accessibility. - Correct terms and privacy links in AuthPage --- coverage/lcov.info | 119 +++++++++++------- .../google_books_data_source_impl.dart | 2 +- .../errors/auth_exception/auth_exception.dart | 2 +- .../rest_client_exception.dart | 2 +- .../storage_exception/storage_exception.dart | 2 +- .../auth_error_code_extension.dart | 2 +- .../rest_client_error_code_extension.dart | 2 +- .../storage_error_code_extension.dart | 2 +- lib/src/core/models/user_hour_time_model.dart | 2 +- .../auth_repository/auth_repository_impl.dart | 2 +- .../user_hour_time_repository_impl.dart | 2 +- ...ser_page_reading_time_repository_impl.dart | 2 +- .../user_theme_repository_impl.dart | 2 +- .../rest_client/dio_rest_client_impl.dart | 2 +- .../notifications_service.dart | 2 +- .../notifications_service_impl.dart | 2 +- .../show_dialog_service.dart | 48 ++++--- .../auth_service/auth_service_impl.dart | 2 +- .../auth_strategy/apple_auth_strategy.dart | 16 ++- .../auth_strategy/facebook_auth_strategy.dart | 16 ++- .../auth_strategy/google_auth_strategy.dart | 16 ++- .../storage/shared_preference_storage.dart | 2 +- lib/src/features/auth/bloc/auth_bloc.dart | 2 +- .../bloc/book_pages_reading_time_bloc.dart | 2 +- .../features/profile/bloc/profile_bloc.dart | 2 +- .../bloc/programming_reading_bloc.dart | 2 +- ...programming_hour_loading_state_widget.dart | 2 +- .../bloc/reading_page_timer_bloc.dart | 2 +- lib/src/shared/blocs/book_bloc/book_bloc.dart | 2 +- .../user_logged_cubit/user_logged_cubit.dart | 2 +- .../user_theme_cubit/user_theme_cubit.dart | 2 +- .../enums/auth_error_code.dart | 0 .../enums/repeat_hour_time_type.dart | 0 .../enums/rest_client_error_code.dart | 0 .../enums/storage_error_code.dart | 0 .../remote_book_data_source_impl_test.dart | 2 +- .../auth_repository_impl_test.dart | 2 +- .../user_hour_time_repository_impl_test.dart | 4 +- ...age_reading_time_repository_impl_test.dart | 2 +- .../user_theme_repository_impl_test.dart | 2 +- .../auth_service/auth_service_impl_test.dart | 4 +- .../features/auth/bloc/auth_bloc_test.dart | 2 +- .../book_pages_reading_time_bloc_test.dart | 2 +- .../features/home/views/home_page_test.dart | 2 +- .../profile/bloc/profile_bloc_test.dart | 2 +- .../bloc/programming_reading_bloc_test.dart | 4 +- .../bloc/reading_page_timer_bloc_test.dart | 2 +- .../bloc/readings_timer_bloc_test.dart | 4 +- .../blocs/book_bloc/book_bloc_test.dart | 2 +- .../user_logged_cubit_test.dart | 2 +- .../user_theme_cubit_test.dart | 2 +- 51 files changed, 178 insertions(+), 129 deletions(-) rename lib/src/{core => shared}/enums/auth_error_code.dart (100%) rename lib/src/{core => shared}/enums/repeat_hour_time_type.dart (100%) rename lib/src/{core => shared}/enums/rest_client_error_code.dart (100%) rename lib/src/{core => shared}/enums/storage_error_code.dart (100%) diff --git a/coverage/lcov.info b/coverage/lcov.info index 49a689d7..76254a0d 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -9,29 +9,6 @@ DA:15,9 LF:7 LH:7 end_of_record -SF:lib/src/shared/constants/database_scripts/database_scripts.dart -DA:3,0 -DA:6,4 -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:11,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:18,1 -DA:21,1 -DA:24,1 -DA:27,1 -DA:30,1 -DA:34,1 -DA:41,1 -DA:44,1 -DA:47,1 -LF:19 -LH:18 -end_of_record SF:lib/src/core/models/author_model.dart DA:5,10 DA:10,9 @@ -180,6 +157,29 @@ DA:53,0 LF:22 LH:11 end_of_record +SF:lib/src/shared/constants/database_scripts/database_scripts.dart +DA:3,0 +DA:6,4 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:18,1 +DA:21,1 +DA:24,1 +DA:27,1 +DA:30,1 +DA:34,1 +DA:41,1 +DA:44,1 +DA:47,1 +LF:19 +LH:18 +end_of_record SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart DA:14,2 DA:16,1 @@ -742,7 +742,7 @@ DA:139,1 LF:42 LH:42 end_of_record -SF:lib/src/core/enums/repeat_hour_time_type.dart +SF:lib/src/shared/enums/repeat_hour_time_type.dart DA:5,1 DA:7,1 DA:8,0 @@ -1182,11 +1182,19 @@ DA:91,0 DA:94,0 DA:96,0 DA:97,0 +DA:98,0 DA:99,0 +DA:100,0 DA:101,0 DA:102,0 +DA:103,0 DA:104,0 -LF:44 +DA:107,0 +DA:109,0 +DA:111,0 +DA:112,0 +DA:114,0 +LF:52 LH:0 end_of_record SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart @@ -1236,11 +1244,19 @@ DA:110,0 DA:111,0 DA:113,0 DA:114,0 +DA:115,0 DA:116,0 +DA:117,0 DA:118,0 DA:119,0 +DA:120,0 DA:121,0 -LF:50 +DA:124,0 +DA:126,0 +DA:128,0 +DA:129,0 +DA:131,0 +LF:58 LH:0 end_of_record SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart @@ -1279,11 +1295,19 @@ DA:80,0 DA:81,0 DA:83,0 DA:84,0 +DA:85,0 DA:86,0 +DA:87,0 DA:88,0 DA:89,0 +DA:90,0 DA:91,0 -LF:39 +DA:94,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:101,0 +LF:47 LH:0 end_of_record SF:lib/src/core/utils/verifier/isbn_verifier.dart @@ -1839,37 +1863,36 @@ DA:32,2 DA:38,2 DA:39,2 DA:40,2 -DA:47,2 +DA:46,2 +DA:48,2 DA:49,2 -DA:50,2 +DA:52,2 DA:53,2 -DA:54,2 -DA:55,0 -DA:57,0 -DA:60,0 +DA:54,0 +DA:56,0 +DA:59,0 +DA:64,2 DA:65,2 -DA:66,2 -DA:68,0 -DA:71,2 -DA:84,0 -DA:88,0 -DA:90,0 +DA:67,0 +DA:70,2 +DA:83,0 +DA:87,0 +DA:89,0 +DA:97,0 DA:98,0 DA:99,0 -DA:100,0 -DA:102,0 -DA:106,0 +DA:101,0 +DA:105,0 +DA:107,0 DA:108,0 -DA:109,0 DA:110,0 -DA:112,0 +DA:111,0 DA:113,0 -DA:115,0 +DA:118,0 +DA:120,0 DA:121,0 -DA:123,0 DA:124,0 -DA:127,0 -LF:40 +LF:39 LH:18 end_of_record SF:lib/src/core/services/app_services/snackbar_service/snackbar_service.dart diff --git a/lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart b/lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart index 4213aafe..28b9a313 100644 --- a/lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart +++ b/lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart @@ -1,6 +1,6 @@ import 'package:bookify/src/core/adapters/google_books_adapter.dart'; import 'package:bookify/src/core/data_sources/remote_books_data_source/remote_books_data_source.dart'; -import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/shared/enums/rest_client_error_code.dart'; import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/rest_client/rest_client.dart'; diff --git a/lib/src/core/errors/auth_exception/auth_exception.dart b/lib/src/core/errors/auth_exception/auth_exception.dart index 6273c7bf..cd0c1bbf 100644 --- a/lib/src/core/errors/auth_exception/auth_exception.dart +++ b/lib/src/core/errors/auth_exception/auth_exception.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; class AuthException implements Exception { final AuthErrorCode code; diff --git a/lib/src/core/errors/rest_client_exception/rest_client_exception.dart b/lib/src/core/errors/rest_client_exception/rest_client_exception.dart index 894caf32..7b1a86ef 100644 --- a/lib/src/core/errors/rest_client_exception/rest_client_exception.dart +++ b/lib/src/core/errors/rest_client_exception/rest_client_exception.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/shared/enums/rest_client_error_code.dart'; class RestClientException implements Exception { final RestClientErrorCode code; diff --git a/lib/src/core/errors/storage_exception/storage_exception.dart b/lib/src/core/errors/storage_exception/storage_exception.dart index b878bb48..1d34df30 100644 --- a/lib/src/core/errors/storage_exception/storage_exception.dart +++ b/lib/src/core/errors/storage_exception/storage_exception.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; class StorageException implements Exception { final StorageErrorCode code; diff --git a/lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart b/lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart index 4c0664e7..0bb5c7a8 100644 --- a/lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart +++ b/lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:localization/localization.dart'; extension AuthErrorCodeExtension on AuthErrorCode { diff --git a/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart b/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart index 48db43b4..24c47232 100644 --- a/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart +++ b/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/shared/enums/rest_client_error_code.dart'; import 'package:localization/localization.dart'; extension RestClientErrorCodeExtension on RestClientErrorCode { diff --git a/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart b/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart index 520af7a8..ffd6fa16 100644 --- a/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart +++ b/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:localization/localization.dart'; extension StorageErrorCodeExtension on StorageErrorCode { diff --git a/lib/src/core/models/user_hour_time_model.dart b/lib/src/core/models/user_hour_time_model.dart index c28ca455..44def552 100644 --- a/lib/src/core/models/user_hour_time_model.dart +++ b/lib/src/core/models/user_hour_time_model.dart @@ -1,6 +1,6 @@ import 'dart:convert'; -import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; +import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; class UserHourTimeModel { final RepeatHourTimeType repeatHourTimeType; diff --git a/lib/src/core/repositories/auth_repository/auth_repository_impl.dart b/lib/src/core/repositories/auth_repository/auth_repository_impl.dart index 9295abd5..65f556e4 100644 --- a/lib/src/core/repositories/auth_repository/auth_repository_impl.dart +++ b/lib/src/core/repositories/auth_repository/auth_repository_impl.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/repositories/auth_repository/auth_repository.dart'; diff --git a/lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart b/lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart index a5e663f0..26f8aafe 100644 --- a/lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart +++ b/lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; diff --git a/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart b/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart index bc690a44..dce9b21a 100644 --- a/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart +++ b/lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; diff --git a/lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart b/lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart index 8be195ff..ea659308 100644 --- a/lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart +++ b/lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_theme_repository/user_theme_repository.dart'; import 'package:bookify/src/core/storage/storage.dart'; diff --git a/lib/src/core/rest_client/dio_rest_client_impl.dart b/lib/src/core/rest_client/dio_rest_client_impl.dart index c753cc1c..e7cf0a28 100644 --- a/lib/src/core/rest_client/dio_rest_client_impl.dart +++ b/lib/src/core/rest_client/dio_rest_client_impl.dart @@ -1,5 +1,5 @@ import 'dart:io'; -import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/shared/enums/rest_client_error_code.dart'; import 'package:dio/dio.dart'; import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; diff --git a/lib/src/core/services/app_services/notifications_service/notifications_service.dart b/lib/src/core/services/app_services/notifications_service/notifications_service.dart index 2d76b327..be097f45 100644 --- a/lib/src/core/services/app_services/notifications_service/notifications_service.dart +++ b/lib/src/core/services/app_services/notifications_service/notifications_service.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; +import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; import 'package:bookify/src/core/models/custom_notification_model.dart'; abstract interface class NotificationsService { diff --git a/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart b/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart index 534661c9..a02684bb 100644 --- a/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart +++ b/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; +import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; import 'package:bookify/src/core/models/custom_notification_model.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notification_navigator.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; diff --git a/lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart b/lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart index 695fb40d..61a2cd96 100644 --- a/lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart +++ b/lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart @@ -43,7 +43,6 @@ class ShowDialogService { ), ); - // if (_isAndroidPlatform) { await showAdaptiveDialog( context: context, builder: (context) { @@ -61,7 +60,7 @@ class ShowDialogService { key: const Key('ConfirmDialogButton'), onPressed: confirmButtonFunction, child: confirmButtonWidget, - ) + ), ] else ...[ CupertinoDialogAction( onPressed: @@ -105,31 +104,28 @@ class ShowDialogService { await showDialog( context: context, - builder: (context) { - if (_isAndroidPlatform) { - return SimpleDialog( - title: titleWidget, - children: [ - SimpleDialogOption( - key: const Key('OkDialogButton'), - onPressed: () => Navigator.pop(context), - child: okButtonWidget, - ), - ], - ); - } - return CupertinoAlertDialog( - title: titleWidget, - actions: [ - CupertinoDialogAction( - key: const Key('OkDialogButton'), - isDefaultAction: true, - onPressed: () => Navigator.pop(context), - child: okButtonWidget, + builder: (context) => (_isAndroidPlatform) + ? SimpleDialog( + title: titleWidget, + children: [ + SimpleDialogOption( + key: const Key('OkDialogButton'), + onPressed: () => Navigator.pop(context), + child: okButtonWidget, + ), + ], + ) + : CupertinoAlertDialog( + title: titleWidget, + actions: [ + CupertinoDialogAction( + key: const Key('OkDialogButton'), + isDefaultAction: true, + onPressed: () => Navigator.pop(context), + child: okButtonWidget, + ), + ], ), - ], - ); - }, ); } } diff --git a/lib/src/core/services/auth_service/auth_service_impl.dart b/lib/src/core/services/auth_service/auth_service_impl.dart index 4ee44c1b..31c04e99 100644 --- a/lib/src/core/services/auth_service/auth_service_impl.dart +++ b/lib/src/core/services/auth_service/auth_service_impl.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; diff --git a/lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart b/lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart index 1dff5c38..130cea2c 100644 --- a/lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart +++ b/lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'dart:math'; -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/shared/enums/sign_in_type.dart'; @@ -94,9 +94,19 @@ class AppleAuthStrategy implements AuthStrategy { await _firebaseAuth.signOut(); return true; } on FirebaseAuthException catch (e) { + final errorCode = switch (e.code) { + 'user-not-found' => AuthErrorCode.userNotFound, + 'wrong-password' => AuthErrorCode.wrongPassword, + 'invalid-email' => AuthErrorCode.invalidEmail, + 'account-disabled' => AuthErrorCode.accountDisabled, + 'too-many-requests' => AuthErrorCode.tooManyRequests, + 'operation-not-allowed' => AuthErrorCode.operationNotAllowed, + 'network-request-failed' => AuthErrorCode.networkRequestFailed, + _ => AuthErrorCode.internalError, + }; throw AuthException( - AuthErrorCode.internalError, - descriptionMessage: e.message ?? 'Sign out failed', + errorCode, + descriptionMessage: e.message, ); } on Exception catch (e) { throw AuthException( diff --git a/lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart b/lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart index fa0a06cb..4179bf6e 100644 --- a/lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart +++ b/lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart @@ -1,7 +1,7 @@ import 'dart:convert'; import 'dart:math'; -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/shared/enums/sign_in_type.dart'; @@ -111,9 +111,19 @@ class FacebookAuthStrategy implements AuthStrategy { await _firebaseAuth.signOut(); return true; } on FirebaseAuthException catch (e) { + final errorCode = switch (e.code) { + 'user-not-found' => AuthErrorCode.userNotFound, + 'wrong-password' => AuthErrorCode.wrongPassword, + 'invalid-email' => AuthErrorCode.invalidEmail, + 'account-disabled' => AuthErrorCode.accountDisabled, + 'too-many-requests' => AuthErrorCode.tooManyRequests, + 'operation-not-allowed' => AuthErrorCode.operationNotAllowed, + 'network-request-failed' => AuthErrorCode.networkRequestFailed, + _ => AuthErrorCode.internalError, + }; throw AuthException( - AuthErrorCode.internalError, - descriptionMessage: e.message ?? 'Sign out failed', + errorCode, + descriptionMessage: e.message, ); } on Exception catch (e) { throw AuthException( diff --git a/lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart b/lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart index db3df1a9..8ab5ea61 100644 --- a/lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart +++ b/lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/services/auth_service/auth_strategy/auth_strategy.dart'; @@ -81,9 +81,19 @@ class GoogleAuthStrategy implements AuthStrategy { await _firebaseAuth.signOut(); return true; } on FirebaseAuthException catch (e) { + final errorCode = switch (e.code) { + 'user-not-found' => AuthErrorCode.userNotFound, + 'wrong-password' => AuthErrorCode.wrongPassword, + 'invalid-email' => AuthErrorCode.invalidEmail, + 'account-disabled' => AuthErrorCode.accountDisabled, + 'too-many-requests' => AuthErrorCode.tooManyRequests, + 'operation-not-allowed' => AuthErrorCode.operationNotAllowed, + 'network-request-failed' => AuthErrorCode.networkRequestFailed, + _ => AuthErrorCode.internalError, + }; throw AuthException( - AuthErrorCode.internalError, - descriptionMessage: e.message ?? 'Sign out failed', + errorCode, + descriptionMessage: e.message, ); } on Exception catch (e) { throw AuthException( diff --git a/lib/src/core/storage/shared_preference_storage.dart b/lib/src/core/storage/shared_preference_storage.dart index 1b4a20b6..fbb07e47 100644 --- a/lib/src/core/storage/shared_preference_storage.dart +++ b/lib/src/core/storage/shared_preference_storage.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:shared_preferences/shared_preferences.dart'; diff --git a/lib/src/features/auth/bloc/auth_bloc.dart b/lib/src/features/auth/bloc/auth_bloc.dart index 0d0ef963..f7779b73 100644 --- a/lib/src/features/auth/bloc/auth_bloc.dart +++ b/lib/src/features/auth/bloc/auth_bloc.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; import 'package:bookify/src/shared/enums/sign_in_type.dart'; diff --git a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart index 402ad7fe..4cb8e693 100644 --- a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart +++ b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; diff --git a/lib/src/features/profile/bloc/profile_bloc.dart b/lib/src/features/profile/bloc/profile_bloc.dart index 569fa74e..54443a04 100644 --- a/lib/src/features/profile/bloc/profile_bloc.dart +++ b/lib/src/features/profile/bloc/profile_bloc.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; diff --git a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart index 929e806a..7c8be31f 100644 --- a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart +++ b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; diff --git a/lib/src/features/programming_reading/views/widgets/programming_hour_loading_state_widget.dart b/lib/src/features/programming_reading/views/widgets/programming_hour_loading_state_widget.dart index e3531b56..7e087cd5 100644 --- a/lib/src/features/programming_reading/views/widgets/programming_hour_loading_state_widget.dart +++ b/lib/src/features/programming_reading/views/widgets/programming_hour_loading_state_widget.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; +import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; import 'package:bookify/src/core/helpers/size/size_for_small_device_extension.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/features/programming_reading/views/widgets/hour_time_selected_widget.dart'; diff --git a/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart b/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart index c321c31e..72017375 100644 --- a/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart +++ b/lib/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; diff --git a/lib/src/shared/blocs/book_bloc/book_bloc.dart b/lib/src/shared/blocs/book_bloc/book_bloc.dart index e6ca59c2..3ed1b9f0 100644 --- a/lib/src/shared/blocs/book_bloc/book_bloc.dart +++ b/lib/src/shared/blocs/book_bloc/book_bloc.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/shared/enums/rest_client_error_code.dart'; import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; import 'package:bookify/src/core/repositories/remote_books_repository/remote_books_repository.dart'; import 'package:bookify/src/core/utils/verifier/isbn_verifier.dart'; diff --git a/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart b/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart index ffe490a3..ef16581a 100644 --- a/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +++ b/lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; import 'package:flutter/material.dart'; diff --git a/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart b/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart index dfc2ff9e..c550e9a0 100644 --- a/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart +++ b/lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_theme_repository/user_theme_repository.dart'; import 'package:flutter/material.dart'; diff --git a/lib/src/core/enums/auth_error_code.dart b/lib/src/shared/enums/auth_error_code.dart similarity index 100% rename from lib/src/core/enums/auth_error_code.dart rename to lib/src/shared/enums/auth_error_code.dart diff --git a/lib/src/core/enums/repeat_hour_time_type.dart b/lib/src/shared/enums/repeat_hour_time_type.dart similarity index 100% rename from lib/src/core/enums/repeat_hour_time_type.dart rename to lib/src/shared/enums/repeat_hour_time_type.dart diff --git a/lib/src/core/enums/rest_client_error_code.dart b/lib/src/shared/enums/rest_client_error_code.dart similarity index 100% rename from lib/src/core/enums/rest_client_error_code.dart rename to lib/src/shared/enums/rest_client_error_code.dart diff --git a/lib/src/core/enums/storage_error_code.dart b/lib/src/shared/enums/storage_error_code.dart similarity index 100% rename from lib/src/core/enums/storage_error_code.dart rename to lib/src/shared/enums/storage_error_code.dart diff --git a/test/src/core/data_sources/remote_book_data_source/remote_book_data_source_impl_test.dart b/test/src/core/data_sources/remote_book_data_source/remote_book_data_source_impl_test.dart index 840aab4f..ce943bde 100644 --- a/test/src/core/data_sources/remote_book_data_source/remote_book_data_source_impl_test.dart +++ b/test/src/core/data_sources/remote_book_data_source/remote_book_data_source_impl_test.dart @@ -1,5 +1,5 @@ import 'package:bookify/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart'; -import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/shared/enums/rest_client_error_code.dart'; import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/rest_client/rest_client.dart'; diff --git a/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart b/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart index 61165d51..f2df8114 100644 --- a/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart +++ b/test/src/core/repositories/auth_repository/auth_repository_impl_test.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; import 'package:bookify/src/core/repositories/auth_repository/auth_repository_impl.dart'; diff --git a/test/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl_test.dart b/test/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl_test.dart index 7319769c..e3d64420 100644 --- a/test/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl_test.dart +++ b/test/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl_test.dart @@ -1,6 +1,6 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; -import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; +import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart'; import 'package:bookify/src/core/storage/storage.dart'; diff --git a/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart b/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart index 6950bdff..ddf03dc6 100644 --- a/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart +++ b/test/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl_test.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart'; diff --git a/test/src/core/repositories/user_theme_repository/user_theme_repository_impl_test.dart b/test/src/core/repositories/user_theme_repository/user_theme_repository_impl_test.dart index 63bcad65..27770609 100644 --- a/test/src/core/repositories/user_theme_repository/user_theme_repository_impl_test.dart +++ b/test/src/core/repositories/user_theme_repository/user_theme_repository_impl_test.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart'; import 'package:bookify/src/core/storage/storage.dart'; diff --git a/test/src/core/services/auth_service/auth_service_impl_test.dart b/test/src/core/services/auth_service/auth_service_impl_test.dart index 74c81943..567bf033 100644 --- a/test/src/core/services/auth_service/auth_service_impl_test.dart +++ b/test/src/core/services/auth_service/auth_service_impl_test.dart @@ -1,5 +1,5 @@ -import 'package:bookify/src/core/enums/auth_error_code.dart'; -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; diff --git a/test/src/features/auth/bloc/auth_bloc_test.dart b/test/src/features/auth/bloc/auth_bloc_test.dart index 6eb2ae1c..fe3aa992 100644 --- a/test/src/features/auth/bloc/auth_bloc_test.dart +++ b/test/src/features/auth/bloc/auth_bloc_test.dart @@ -1,5 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/features/auth/bloc/auth_bloc.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; diff --git a/test/src/features/book_detail/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc_test.dart b/test/src/features/book_detail/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc_test.dart index dd1420d5..fb496966 100644 --- a/test/src/features/book_detail/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc_test.dart +++ b/test/src/features/book_detail/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc_test.dart @@ -1,5 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; diff --git a/test/src/features/home/views/home_page_test.dart b/test/src/features/home/views/home_page_test.dart index 0fb656c9..3e9761ff 100644 --- a/test/src/features/home/views/home_page_test.dart +++ b/test/src/features/home/views/home_page_test.dart @@ -1,5 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/shared/enums/rest_client_error_code.dart'; import 'package:bookify/src/core/models/author_model.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; diff --git a/test/src/features/profile/bloc/profile_bloc_test.dart b/test/src/features/profile/bloc/profile_bloc_test.dart index d3f3e576..82f30212 100644 --- a/test/src/features/profile/bloc/profile_bloc_test.dart +++ b/test/src/features/profile/bloc/profile_bloc_test.dart @@ -1,5 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/features/profile/bloc/profile_bloc.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/models/user_model.dart'; diff --git a/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart b/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart index 5cfa40e0..626fa8ea 100644 --- a/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart +++ b/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart @@ -1,6 +1,6 @@ -import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; +import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; diff --git a/test/src/features/reading_page_timer/bloc/reading_page_timer_bloc_test.dart b/test/src/features/reading_page_timer/bloc/reading_page_timer_bloc_test.dart index c9d48c96..8cb0d16a 100644 --- a/test/src/features/reading_page_timer/bloc/reading_page_timer_bloc_test.dart +++ b/test/src/features/reading_page_timer/bloc/reading_page_timer_bloc_test.dart @@ -1,5 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_page_reading_time_model.dart'; import 'package:bookify/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository.dart'; diff --git a/test/src/features/readings_timer/bloc/readings_timer_bloc_test.dart b/test/src/features/readings_timer/bloc/readings_timer_bloc_test.dart index d74d1f7c..356e4fdc 100644 --- a/test/src/features/readings_timer/bloc/readings_timer_bloc_test.dart +++ b/test/src/features/readings_timer/bloc/readings_timer_bloc_test.dart @@ -1,6 +1,6 @@ -import 'package:bookify/src/core/enums/repeat_hour_time_type.dart'; +import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; diff --git a/test/src/shared/blocs/book_bloc/book_bloc_test.dart b/test/src/shared/blocs/book_bloc/book_bloc_test.dart index ade021d2..696450eb 100644 --- a/test/src/shared/blocs/book_bloc/book_bloc_test.dart +++ b/test/src/shared/blocs/book_bloc/book_bloc_test.dart @@ -1,5 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/rest_client_error_code.dart'; +import 'package:bookify/src/shared/enums/rest_client_error_code.dart'; import 'package:bookify/src/core/repositories/remote_books_repository/remote_books_repository.dart'; import 'package:bookify/src/shared/blocs/book_bloc/book_bloc.dart'; import 'package:bookify/src/core/errors/rest_client_exception/rest_client_exception.dart'; diff --git a/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart b/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart index 712f8273..085fbdc1 100644 --- a/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart +++ b/test/src/shared/cubits/user_logged_cubit/user_logged_cubit_test.dart @@ -1,5 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/auth_error_code.dart'; +import 'package:bookify/src/shared/enums/auth_error_code.dart'; import 'package:bookify/src/core/errors/auth_exception/auth_exception.dart'; import 'package:bookify/src/core/services/auth_service/auth_service.dart'; import 'package:bookify/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart'; diff --git a/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart b/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart index 0b41e941..f5c267ac 100644 --- a/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart +++ b/test/src/shared/cubits/user_theme_cubit/user_theme_cubit_test.dart @@ -1,5 +1,5 @@ import 'package:bloc_test/bloc_test.dart'; -import 'package:bookify/src/core/enums/storage_error_code.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_theme_repository/user_theme_repository.dart'; import 'package:bookify/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart'; From f80334dd0ca0272d491967a90421f1250cea8e63 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Fri, 15 May 2026 17:29:15 -0300 Subject: [PATCH 11/19] feat: Add first support for localized strings for LocalDatabase --- coverage/lcov.info | 5232 +++++++++-------- .../core/database/local_database_impl.dart | 169 +- .../local_database_exception.dart | 12 +- .../local_database_error_code_extension.dart | 51 + .../authors_repository_impl.dart | 15 +- .../book_authors_repository_impl.dart | 25 +- .../book_categories_repository_impl.dart | 25 +- .../book_on_case_repository_impl.dart | 20 +- .../bookcase_repository_impl.dart | 22 +- .../books_repository_impl.dart | 45 +- .../categories_repository_impl.dart | 15 +- .../loan_repository/loan_repository_impl.dart | 22 +- .../reading_repository_impl.dart | 22 +- .../book_detail/bloc/book_detail_bloc.dart | 32 +- .../book_detail/bloc/book_detail_state.dart | 6 +- .../book_detail/views/book_detail_page.dart | 8 +- .../bloc/book_on_bookcase_detail_bloc.dart | 24 +- .../bloc/book_on_bookcase_detail_state.dart | 6 +- .../views/book_on_bookcase_detail_page.dart | 7 +- .../features/bookcase/bloc/bookcase_bloc.dart | 60 +- .../bookcase/bloc/bookcase_state.dart | 6 +- .../bookcase/views/bookcase_page.dart | 8 +- .../bloc/bookcase_books_insertion_bloc.dart | 37 +- .../bloc/bookcase_books_insertion_state.dart | 6 +- .../views/bookcase_books_insertion_page.dart | 53 +- .../bloc/bookcase_detail_bloc.dart | 55 +- .../bloc/bookcase_detail_state.dart | 6 +- .../views/bookcase_detail_page.dart | 35 +- .../bloc/bookcase_insertion_bloc.dart | 66 +- .../bloc/bookcase_insertion_state.dart | 6 +- .../views/bookcase_insertion_page.dart | 8 +- .../bloc/book_on_bookcase_picker_bloc.dart | 9 +- .../bloc/book_on_bookcase_picker_state.dart | 6 +- .../views/book_on_bookcase_widget.dart | 26 +- .../bloc/bookcase_picker_bloc.dart | 20 +- .../bloc/bookcase_picker_state.dart | 11 +- .../views/bookcase_picker_widget.dart | 20 +- .../bloc/separate_books_picker_bloc.dart | 28 +- .../bloc/separate_books_picker_state.dart | 6 +- .../views/separate_books_picker_widget.dart | 32 +- lib/src/features/loan/bloc/loan_bloc.dart | 34 +- lib/src/features/loan/bloc/loan_state.dart | 8 +- lib/src/features/loan/views/loan_page.dart | 51 +- .../loan_detail/bloc/loan_detail_bloc.dart | 34 +- .../loan_detail/bloc/loan_detail_state.dart | 8 +- .../loan_detail/views/loan_detail_page.dart | 49 +- .../bloc/loan_insertion_bloc.dart | 27 +- .../bloc/loan_insertion_state.dart | 6 +- .../views/loan_insertion_page.dart | 12 +- .../features/my_books/bloc/my_books_bloc.dart | 33 +- .../my_books/bloc/my_books_state.dart | 8 +- .../my_books/views/my_books_page.dart | 40 +- .../bloc/user_information_bloc.dart | 10 +- .../bloc/user_information_state.dart | 6 +- .../features/readings/bloc/readings_bloc.dart | 35 +- .../readings/bloc/readings_state.dart | 8 +- .../readings/views/readings_page.dart | 45 +- .../bloc/readings_detail_bloc.dart | 28 +- .../bloc/readings_detail_state.dart | 6 +- .../views/readings_detail_page.dart | 12 +- .../bloc/readings_insertion_bloc.dart | 31 +- .../bloc/readings_insertion_state.dart | 6 +- .../views/readings_insertion_page.dart | 10 +- .../enums/local_database_error_code.dart | 12 + pubspec.yaml | 2 +- .../authors_repository_impl_test.dart | 171 +- .../book_authors_repository_impl_test.dart | 132 +- .../book_categories_repository_impl_test.dart | 132 +- .../book_on_case_repository_impl_test.dart | 254 +- .../bookcase_repository_impl_test.dart | 347 +- .../books_repository_impl_test.dart | 616 +- .../categories_repository_impl_test.dart | 171 +- .../loan_repository_impl_test.dart | 289 +- .../reading_repository_impl_test.dart | 244 +- .../book_service/book_service_impl_test.dart | 469 +- .../bookcase_service_impl_test.dart | 397 +- .../loan_services/loan_service_impl_test.dart | 204 +- .../reading_service_impl_test.dart | 175 +- .../bloc/book_detail_bloc_test.dart | 67 +- .../views/book_detail_page_test.dart | 11 +- .../book_on_bookcase_detail_bloc_test.dart | 35 +- .../bookcase/bloc/bookcase_bloc_test.dart | 294 +- .../bookcase/views/bookcase_page_test.dart | 8 +- .../bookcase_books_insertion_bloc_test.dart | 329 +- .../bloc/bookcase_detail_bloc_test.dart | 174 +- .../bloc/bookcase_insertion_bloc_test.dart | 201 +- .../views/bookcase_insertion_page_test.dart | 8 +- .../book_on_bookcase_picker_bloc_test.dart | 71 +- .../bloc/bookcase_picker_bloc_test.dart | 68 +- .../bloc/separate_books_picker_bloc_test.dart | 57 +- .../features/loan/bloc/loan_bloc_test.dart | 75 +- .../bloc/loan_detail_bloc_test.dart | 13 +- .../bloc/loan_insertion_bloc_test.dart | 8 +- .../my_books/bloc/my_books_bloc_test.dart | 81 +- .../bloc/user_information_bloc_test.dart | 8 +- .../readings/bloc/readings_bloc_test.dart | 75 +- .../bloc/readings_detail_bloc_test.dart | 39 +- .../bloc/readings_insertion_bloc_test.dart | 298 +- 98 files changed, 7694 insertions(+), 4610 deletions(-) create mode 100644 lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart create mode 100644 lib/src/shared/enums/local_database_error_code.dart diff --git a/coverage/lcov.info b/coverage/lcov.info index 76254a0d..187e00ea 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -9,6 +9,20 @@ DA:15,9 LF:7 LH:7 end_of_record +SF:lib/src/core/database/local_database.dart +DA:5,0 +DA:7,0 +DA:9,0 +LF:3 +LH:0 +end_of_record +SF:lib/src/core/errors/local_database_exception/local_database_exception.dart +DA:7,7 +DA:12,1 +DA:13,3 +LF:3 +LH:3 +end_of_record SF:lib/src/core/models/author_model.dart DA:5,10 DA:10,9 @@ -35,6 +49,115 @@ DA:53,0 LF:22 LH:11 end_of_record +SF:lib/src/core/repositories/author_repository/authors_repository_impl.dart +DA:12,1 +DA:14,1 +DA:17,2 +DA:18,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:28,1 +DA:30,0 +DA:37,1 +DA:40,2 +DA:41,1 +DA:46,1 +DA:47,1 +DA:50,2 +DA:52,1 +DA:53,1 +DA:55,1 +DA:57,0 +DA:62,1 +DA:65,2 +DA:66,1 +DA:67,1 +DA:70,1 +DA:75,1 +DA:78,2 +DA:79,1 +DA:85,1 +LF:28 +LH:26 +end_of_record +SF:lib/src/shared/constants/database_scripts/database_scripts.dart +DA:3,0 +DA:6,4 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:18,1 +DA:21,1 +DA:24,1 +DA:27,1 +DA:30,1 +DA:34,1 +DA:41,1 +DA:44,1 +DA:47,1 +LF:19 +LH:18 +end_of_record +SF:lib/src/core/dtos/bookcase_dto.dart +DA:7,2 +DA:12,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:22,0 +DA:24,0 +DA:26,1 +DA:30,3 +DA:31,0 +DA:34,0 +DA:35,0 +LF:12 +LH:3 +end_of_record +SF:lib/src/core/models/bookcase_model.dart +DA:10,3 +DA:17,3 +DA:19,3 +DA:25,3 +DA:26,2 +DA:27,2 +DA:28,2 +DA:29,1 +DA:33,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:46,1 +DA:47,1 +DA:48,1 +DA:49,1 +DA:50,1 +DA:51,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,2 +DA:64,0 +DA:66,0 +DA:68,3 +DA:72,6 +DA:73,3 +DA:74,3 +DA:75,3 +DA:78,0 +DA:80,0 +LF:34 +LH:25 +end_of_record SF:lib/src/core/models/book_model.dart DA:9,2 DA:11,2 @@ -157,28 +280,92 @@ DA:53,0 LF:22 LH:11 end_of_record -SF:lib/src/shared/constants/database_scripts/database_scripts.dart -DA:3,0 -DA:6,4 -DA:7,2 -DA:8,2 -DA:9,2 +SF:lib/src/features/bookcase/bloc/bookcase_state.dart DA:10,2 -DA:11,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:18,1 -DA:21,1 -DA:24,1 -DA:27,1 -DA:30,1 +DA:21,2 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/bookcase/bloc/bookcase_bloc.dart +DA:17,1 +DA:20,2 +DA:21,2 +DA:22,2 +DA:23,2 +DA:26,1 +DA:31,2 +DA:33,1 DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 DA:41,1 -DA:44,1 -DA:47,1 -LF:19 -LH:18 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:60,1 +DA:61,1 +DA:62,1 +DA:63,1 +DA:66,1 +DA:67,1 +DA:68,1 +DA:70,1 +DA:76,1 +DA:81,2 +DA:83,1 +DA:85,2 +DA:86,2 +DA:87,2 +DA:90,2 +DA:91,1 +DA:92,1 +DA:95,3 +DA:102,1 +DA:103,1 +DA:104,1 +DA:105,1 +DA:106,1 +DA:107,1 +DA:110,1 +DA:111,1 +DA:112,1 +DA:114,1 +DA:120,1 +DA:121,2 +DA:123,1 +DA:124,2 +DA:128,1 +DA:131,1 +DA:135,2 +DA:137,1 +DA:138,2 +DA:142,1 +DA:145,1 +DA:149,1 +DA:151,2 +DA:152,1 +DA:153,1 +DA:154,1 +DA:162,2 +DA:163,1 +DA:169,2 +DA:172,1 +DA:177,1 +DA:180,2 +LF:71 +LH:71 +end_of_record +SF:lib/src/features/bookcase/bloc/bookcase_event.dart +DA:10,1 +DA:18,1 +LF:2 +LH:2 end_of_record SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart DA:14,2 @@ -199,25 +386,6 @@ DA:21,2 LF:3 LH:3 end_of_record -SF:lib/src/core/models/user_page_reading_time_model.dart -DA:4,3 -DA:8,0 -DA:11,0 -DA:12,0 -DA:16,1 -DA:17,1 -DA:21,3 -DA:22,1 -DA:24,1 -DA:30,0 -DA:32,0 -DA:34,1 -DA:38,3 -DA:41,0 -DA:42,0 -LF:15 -LH:8 -end_of_record SF:lib/src/core/errors/storage_exception/storage_exception.dart DA:7,4 DA:12,1 @@ -225,586 +393,623 @@ DA:13,3 LF:3 LH:3 end_of_record -SF:lib/src/core/models/user_model.dart -DA:9,2 -DA:15,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:27,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:31,2 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,2 -DA:39,2 -DA:43,0 -DA:45,0 -DA:47,2 -DA:51,3 -DA:52,3 -DA:53,3 -DA:56,0 -DA:57,0 -DA:59,3 -DA:61,1 -DA:62,2 -LF:27 -LH:18 -end_of_record -SF:lib/src/core/repositories/auth_repository/auth_repository_impl.dart -DA:11,1 +SF:lib/src/core/helpers/book_status/book_status_extension.dart +DA:7,0 +DA:9,0 +DA:10,0 +DA:11,0 DA:15,1 +DA:17,1 +DA:18,2 DA:19,2 -DA:20,1 -DA:28,1 -DA:31,1 -DA:36,1 -DA:41,1 -DA:44,2 -DA:45,1 -DA:46,1 -DA:49,1 -DA:50,1 -DA:53,0 -DA:55,0 -DA:60,1 -DA:63,3 -DA:64,1 -DA:67,0 -DA:69,0 -LF:20 -LH:16 +LF:8 +LH:4 end_of_record -SF:lib/src/shared/enums/sign_in_type.dart -DA:7,1 -DA:9,1 -DA:10,0 -DA:11,0 +SF:lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart +DA:7,3 +DA:11,3 DA:12,0 -DA:16,1 -DA:18,1 -DA:19,0 +DA:15,3 +DA:16,0 +DA:19,3 DA:20,0 -LF:9 -LH:4 +DA:23,3 +DA:24,0 +DA:27,3 +DA:28,0 +DA:31,3 +DA:34,3 +DA:35,0 +DA:38,3 +DA:39,0 +DA:42,3 +DA:43,0 +DA:46,9 +LF:19 +LH:11 end_of_record -SF:lib/src/core/database/local_database.dart +SF:lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart DA:5,0 -DA:7,0 DA:9,0 -LF:3 +DA:12,0 +DA:13,0 +DA:14,0 +DA:17,0 +DA:20,0 +LF:7 LH:0 end_of_record -SF:lib/src/core/errors/local_database_exception/local_database_exception.dart +SF:lib/src/core/models/user_page_reading_time_model.dart DA:4,3 -DA:6,1 -DA:7,1 -LF:3 -LH:3 -end_of_record -SF:lib/src/core/repositories/author_repository/authors_repository_impl.dart -DA:11,1 -DA:13,1 -DA:16,2 +DA:8,0 +DA:11,0 +DA:12,0 +DA:16,1 DA:17,1 +DA:21,3 DA:22,1 DA:24,1 -DA:26,0 -DA:33,1 -DA:36,2 -DA:37,1 -DA:42,1 -DA:43,1 -DA:46,2 -DA:48,1 -DA:50,0 -DA:55,1 -DA:58,2 -DA:59,1 -DA:60,1 -DA:63,1 -DA:68,1 -DA:71,2 -DA:72,1 -DA:78,1 -LF:24 -LH:22 -end_of_record -SF:lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart -DA:10,1 -DA:12,1 -DA:17,2 -DA:18,1 -DA:23,2 -DA:28,1 -DA:33,1 -DA:37,4 -DA:43,1 -DA:48,1 -DA:51,2 -DA:52,1 -DA:58,1 -LF:13 -LH:13 -end_of_record -SF:lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart -DA:10,1 -DA:12,1 -DA:17,2 -DA:18,1 -DA:23,2 -DA:28,1 -DA:33,1 -DA:37,4 -DA:43,1 -DA:48,1 -DA:51,2 -DA:52,1 -DA:58,1 -LF:13 -LH:13 -end_of_record -SF:lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart -DA:10,1 -DA:12,1 -DA:17,2 -DA:18,1 -DA:24,1 -DA:29,1 -DA:32,2 -DA:33,1 +DA:30,0 +DA:32,0 DA:34,1 -DA:39,1 -DA:41,1 -DA:43,1 -DA:48,1 -DA:52,4 -DA:58,1 -DA:63,1 -DA:66,2 -DA:67,1 -DA:73,1 -DA:78,1 -DA:84,2 -DA:85,1 -DA:92,1 -LF:23 -LH:23 +DA:38,3 +DA:41,0 +DA:42,0 +LF:15 +LH:8 end_of_record -SF:lib/src/core/models/bookcase_model.dart -DA:10,3 -DA:17,3 -DA:19,3 -DA:25,3 -DA:26,2 -DA:27,2 -DA:28,2 -DA:29,1 -DA:33,0 -DA:38,0 -DA:39,0 +SF:lib/src/core/services/app_services/launcher_service/launcher_service.dart +DA:4,0 +DA:6,0 +DA:8,0 +DA:17,0 +DA:21,0 +DA:23,0 +DA:24,0 +DA:27,0 +DA:28,0 DA:40,0 -DA:42,0 -DA:46,1 -DA:47,1 -DA:48,1 -DA:49,1 -DA:50,1 -DA:51,1 -DA:55,1 -DA:56,1 -DA:57,1 -DA:58,1 -DA:59,1 -DA:60,2 -DA:64,0 -DA:66,0 -DA:68,3 -DA:72,6 -DA:73,3 -DA:74,3 -DA:75,3 -DA:78,0 -DA:80,0 -LF:34 -LH:25 +LF:10 +LH:0 end_of_record -SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart -DA:11,1 -DA:13,1 -DA:16,3 +SF:lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart +DA:8,6 +DA:10,2 DA:17,2 -DA:20,1 -DA:24,1 -DA:29,1 +DA:25,2 +DA:30,2 +DA:31,2 DA:32,2 -DA:33,1 -DA:37,2 -DA:40,1 -DA:44,1 -DA:49,1 +DA:38,2 +DA:39,2 +DA:40,2 +DA:46,2 +DA:48,2 +DA:49,2 DA:52,2 -DA:53,1 -DA:57,1 -DA:60,1 -DA:64,1 -DA:69,1 -DA:72,2 -DA:73,1 -DA:77,1 -DA:82,1 -DA:85,2 -DA:86,1 -DA:87,1 -DA:91,1 -DA:96,1 -DA:99,2 -DA:100,1 -DA:101,1 -DA:103,1 -DA:107,1 -DA:112,1 -DA:115,2 -DA:116,1 -DA:122,1 -LF:37 -LH:37 +DA:53,2 +DA:54,0 +DA:56,0 +DA:59,0 +DA:64,2 +DA:65,2 +DA:67,0 +DA:70,2 +DA:83,0 +DA:87,0 +DA:89,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:101,0 +DA:105,0 +DA:107,0 +DA:108,0 +DA:110,0 +DA:111,0 +DA:113,0 +DA:118,0 +DA:120,0 +DA:121,0 +DA:124,0 +LF:39 +LH:18 end_of_record -SF:lib/src/core/repositories/books_repository/books_repository_impl.dart -DA:11,1 -DA:13,1 -DA:16,3 +SF:lib/src/core/services/app_services/snackbar_service/snackbar_service.dart +DA:10,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:15,2 +DA:19,2 +DA:21,2 +DA:22,2 +DA:23,2 +DA:24,2 +DA:30,2 +DA:36,2 +DA:40,2 +DA:41,2 +DA:42,2 +DA:43,2 +DA:46,2 +DA:49,2 +DA:54,2 +DA:55,2 +DA:56,2 +DA:60,2 +DA:73,2 +DA:74,2 +DA:75,2 +LF:25 +LH:25 +end_of_record +SF:lib/src/features/book_detail/bloc/book_detail_event.dart +DA:8,2 +DA:16,2 +DA:24,1 +LF:3 +LH:3 +end_of_record +SF:lib/src/features/book_detail/bloc/book_detail_state.dart +DA:10,2 +DA:19,2 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_detail/bloc/book_detail_bloc.dart +DA:15,1 DA:17,2 -DA:19,1 +DA:18,2 +DA:19,2 +DA:20,2 DA:23,1 -DA:28,1 -DA:31,2 -DA:32,1 +DA:28,2 +DA:30,2 +DA:31,1 +DA:34,2 +DA:35,1 +DA:36,1 DA:37,1 +DA:38,1 DA:39,1 DA:43,1 -DA:48,1 -DA:51,2 +DA:44,1 +DA:46,1 DA:52,1 -DA:53,1 -DA:56,1 -DA:61,1 -DA:64,2 +DA:57,2 +DA:59,2 +DA:60,1 +DA:63,1 +DA:64,1 DA:65,1 -DA:66,1 -DA:71,1 -DA:73,1 +DA:73,2 +DA:74,1 +DA:75,1 +DA:76,1 DA:77,1 +DA:78,1 DA:82,1 -DA:85,2 -DA:86,1 -DA:90,2 -DA:93,1 -DA:97,1 +DA:83,1 +DA:85,1 +DA:91,1 +DA:96,2 +DA:98,3 +DA:100,1 +DA:101,1 DA:102,1 DA:105,2 -DA:106,1 -DA:111,1 -DA:116,1 -DA:119,2 -DA:120,1 -DA:121,1 -DA:126,2 -DA:128,1 +DA:111,3 +DA:112,1 +DA:113,1 +DA:114,1 +DA:121,2 +DA:123,1 +DA:124,1 +DA:125,1 +DA:126,1 +DA:127,1 +DA:131,1 DA:132,1 -DA:137,1 -DA:143,2 -DA:144,1 -DA:147,2 -DA:151,1 -DA:156,1 -DA:161,2 -DA:164,2 -DA:165,1 -DA:168,1 -DA:172,1 -DA:177,1 -DA:180,2 -DA:181,1 -DA:185,1 -DA:190,1 -DA:193,2 -DA:194,1 -DA:199,1 -LF:60 -LH:60 -end_of_record -SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart -DA:11,1 -DA:13,1 -DA:16,2 -DA:17,1 -DA:22,1 -DA:24,1 -DA:26,0 -DA:33,1 -DA:36,2 -DA:37,1 -DA:42,1 -DA:43,1 -DA:46,2 -DA:48,1 -DA:50,0 -DA:55,1 -DA:58,2 -DA:59,1 -DA:60,1 -DA:64,1 -DA:69,1 -DA:72,2 -DA:73,1 -DA:79,1 -LF:24 -LH:22 +DA:134,1 +LF:54 +LH:54 end_of_record -SF:lib/src/core/models/loan_model.dart -DA:9,5 -DA:18,1 +SF:lib/src/features/book_detail/views/book_detail_page.dart DA:19,1 -DA:20,1 -DA:21,1 -DA:22,2 -DA:23,2 DA:24,1 DA:25,1 -DA:29,1 -DA:30,1 -DA:31,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -DA:37,1 -DA:39,1 -DA:40,1 -DA:44,0 -DA:46,0 -DA:49,1 +DA:51,1 +DA:53,1 +DA:55,2 +DA:56,1 DA:57,1 -DA:58,1 -DA:59,1 -DA:60,1 -DA:61,0 +DA:60,3 +DA:61,1 DA:62,1 -DA:63,1 -DA:67,2 -DA:71,6 -DA:72,6 -DA:73,6 -DA:74,6 -DA:75,6 -DA:76,6 +DA:63,3 +DA:68,1 +DA:71,1 +DA:73,3 +DA:74,2 +DA:75,1 DA:79,0 +DA:80,0 DA:81,0 -DA:82,0 -DA:83,0 DA:84,0 DA:85,0 DA:86,0 -LF:43 -LH:33 -end_of_record -SF:lib/src/core/repositories/loan_repository/loan_repository_impl.dart -DA:12,1 -DA:14,1 -DA:17,2 -DA:18,1 -DA:22,2 -DA:25,1 -DA:29,1 -DA:34,1 -DA:37,2 -DA:38,3 -DA:39,1 -DA:40,1 -DA:41,2 -DA:42,2 -DA:47,2 -DA:50,1 -DA:54,1 -DA:59,1 -DA:62,2 -DA:63,1 -DA:67,1 -DA:70,1 -DA:74,1 -DA:79,1 -DA:82,2 -DA:83,1 -DA:87,1 -DA:92,1 -DA:95,2 -DA:96,1 -DA:97,1 -DA:101,1 -DA:106,1 -DA:109,2 +DA:88,0 +DA:90,0 +DA:91,0 +DA:95,1 +DA:100,1 +DA:102,1 +DA:105,1 +DA:107,2 DA:110,1 -DA:111,1 +DA:112,1 DA:113,1 +DA:114,1 +DA:115,1 DA:117,1 -DA:122,1 -DA:125,2 -DA:126,1 -DA:132,1 -LF:42 -LH:42 +DA:125,1 +DA:128,1 +DA:129,1 +DA:130,1 +DA:133,1 +DA:135,1 +DA:137,1 +DA:144,1 +DA:145,1 +DA:146,1 +DA:147,1 +DA:148,3 +DA:149,1 +DA:150,0 +DA:151,0 +DA:152,0 +DA:156,3 +DA:160,1 +DA:162,2 +DA:163,1 +DA:164,3 +DA:165,1 +DA:166,1 +DA:167,1 +DA:168,3 +DA:169,1 +DA:170,1 +DA:172,2 +DA:174,1 +DA:175,1 +DA:176,1 +DA:177,1 +DA:178,1 +DA:179,1 +DA:181,1 +DA:182,1 +DA:183,1 +DA:184,1 +DA:188,1 +DA:189,1 +DA:191,1 +DA:194,1 +DA:199,1 +DA:206,1 +DA:207,1 +DA:208,1 +DA:210,1 +DA:211,1 +DA:212,1 +DA:214,2 +DA:223,1 +DA:224,1 +DA:226,1 +DA:230,1 +DA:232,1 +DA:233,1 +DA:235,4 +DA:237,1 +DA:238,1 +DA:243,1 +DA:245,1 +DA:250,1 +DA:253,1 +DA:254,1 +DA:255,1 +DA:257,1 +DA:259,0 +DA:260,0 +DA:264,1 +DA:265,1 +DA:268,1 +DA:272,1 +DA:273,1 +DA:274,1 +DA:276,2 +DA:277,1 +DA:284,1 +DA:286,1 +DA:288,1 +DA:294,1 +DA:296,0 +DA:297,0 +DA:299,1 +DA:300,1 +DA:301,1 +DA:303,1 +DA:313,1 +DA:316,1 +DA:317,1 +DA:318,1 +DA:319,1 +DA:321,1 +DA:323,1 +DA:329,1 +DA:331,1 +DA:332,1 +DA:337,1 +DA:338,1 +DA:341,1 +DA:342,1 +DA:344,1 +DA:346,1 +DA:352,1 +DA:354,1 +DA:355,1 +DA:357,1 +DA:359,1 +LF:144 +LH:128 end_of_record -SF:lib/src/core/models/reading_model.dart -DA:7,5 +SF:lib/src/shared/widgets/book_widget/book_widget.dart +DA:13,1 +DA:23,1 +DA:33,2 +DA:35,4 +DA:37,2 +DA:38,2 +DA:39,2 +DA:40,2 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:55,0 +DA:57,0 +DA:59,0 +DA:69,2 +DA:70,0 +DA:72,0 +LF:21 +LH:9 +end_of_record +SF:lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart +DA:7,1 +DA:10,1 +DA:12,1 +DA:13,1 DA:14,1 +DA:15,1 +DA:18,3 DA:20,1 DA:21,1 -DA:22,0 +DA:22,1 DA:23,1 -DA:24,1 +DA:24,4 +LF:12 +LH:12 +end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart +DA:14,1 +DA:16,2 +DA:17,2 +DA:20,1 +DA:25,2 +DA:27,1 DA:28,1 -DA:29,1 DA:30,1 DA:31,1 -DA:32,2 -DA:33,1 +DA:35,1 +DA:36,1 DA:37,1 DA:38,1 -DA:39,2 -DA:40,1 -DA:41,1 -DA:42,2 +DA:39,1 +DA:42,1 +DA:43,1 DA:44,1 -DA:48,0 -DA:50,0 -DA:53,3 -DA:57,6 -DA:58,6 -DA:59,6 -DA:60,6 -DA:63,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -LF:32 -LH:24 +DA:46,1 +LF:18 +LH:18 end_of_record -SF:lib/src/core/repositories/reading_repository/reading_repository_impl.dart -DA:12,1 -DA:16,1 -DA:19,2 +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart +DA:11,1 DA:20,1 -DA:25,2 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart +DA:11,1 +DA:16,1 +DA:17,1 +DA:23,1 +DA:25,1 +DA:26,3 +DA:27,1 DA:28,1 DA:32,1 DA:37,1 -DA:42,2 -DA:43,3 -DA:44,1 -DA:45,1 -DA:46,2 -DA:47,2 -DA:53,2 -DA:56,1 -DA:60,1 -DA:65,1 -DA:68,2 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:59,0 +DA:60,0 +DA:67,1 DA:69,1 -DA:74,1 -DA:77,1 -DA:81,1 -DA:86,1 -DA:89,2 -DA:90,1 -DA:94,1 -DA:99,1 -DA:102,2 -DA:103,1 -DA:104,1 -DA:108,1 -DA:113,1 -DA:116,2 -DA:117,1 -DA:118,1 -DA:120,1 -DA:124,1 -DA:129,1 -DA:132,2 -DA:133,1 -DA:139,1 -LF:42 -LH:42 +DA:70,1 +DA:71,1 +LF:27 +LH:14 end_of_record -SF:lib/src/shared/enums/repeat_hour_time_type.dart -DA:5,1 -DA:7,1 -DA:8,0 -DA:9,0 -DA:13,1 -DA:15,1 -DA:16,0 -LF:7 +SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart +DA:6,2 +DA:11,4 +DA:13,4 +DA:14,4 +LF:4 LH:4 end_of_record -SF:lib/src/core/models/user_hour_time_model.dart -DA:12,1 -DA:20,2 +SF:lib/src/features/book_detail/views/widgets/book_rating/book_rating.dart +DA:10,1 +DA:16,1 +DA:18,2 +DA:20,1 +DA:21,1 DA:22,1 -DA:24,4 -DA:27,4 -DA:30,1 +DA:23,2 +DA:25,1 +DA:28,1 DA:31,1 -DA:33,0 +DA:32,1 +DA:34,1 +DA:35,4 DA:37,1 -DA:41,0 -DA:48,0 -DA:49,0 +DA:38,1 +LF:15 +LH:15 +end_of_record +SF:lib/src/shared/widgets/bookify_rating/bookify_rating_widget.dart +DA:13,1 +DA:24,1 +DA:27,2 +DA:29,0 +DA:30,5 +DA:33,1 +DA:36,1 +DA:39,1 +DA:45,1 +DA:47,2 +DA:48,2 +DA:49,2 +DA:51,1 +DA:52,1 +DA:54,1 +DA:55,2 +LF:16 +LH:15 +end_of_record +SF:lib/src/shared/widgets/buttons/bookify_elevated_button.dart +DA:10,1 +DA:19,2 +DA:28,3 +DA:30,3 +DA:32,3 +DA:33,7 +DA:34,3 +DA:35,3 +DA:36,3 +DA:37,3 +DA:38,0 +DA:39,0 +DA:40,0 +DA:44,6 +DA:45,3 +DA:46,3 DA:50,0 DA:51,0 DA:52,0 DA:53,0 -DA:57,1 -DA:58,1 -DA:59,2 +DA:54,0 +DA:55,0 +DA:59,0 +DA:60,0 +LF:24 +LH:13 +end_of_record +SF:lib/src/shared/widgets/buttons/bookify_outlined_button.dart +DA:10,1 +DA:19,2 +DA:28,3 +DA:30,3 +DA:32,3 +DA:33,7 +DA:34,3 +DA:35,2 +DA:36,2 +DA:37,2 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:48,0 +DA:51,4 +DA:52,2 +DA:53,2 +DA:55,2 +DA:56,2 DA:60,1 DA:61,1 DA:62,1 -DA:63,1 -DA:67,1 -DA:68,1 -DA:70,2 -DA:71,1 -DA:72,1 -DA:73,1 -DA:74,1 -DA:78,3 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:73,0 +DA:76,1 +DA:77,1 +DA:79,1 DA:80,1 -DA:81,2 -DA:83,0 -DA:85,0 -DA:88,2 -DA:92,3 -DA:93,3 -DA:94,3 -DA:95,3 -DA:96,3 -DA:99,0 -DA:101,0 -DA:102,0 -DA:103,0 -DA:104,0 -DA:105,0 -LF:47 -LH:31 +LF:36 +LH:22 end_of_record -SF:lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart +SF:lib/src/core/models/user_model.dart +DA:9,2 +DA:15,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:27,1 +DA:28,1 +DA:29,1 +DA:30,1 +DA:31,2 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,2 +DA:39,2 +DA:43,0 +DA:45,0 +DA:47,2 +DA:51,3 +DA:52,3 +DA:53,3 +DA:56,0 +DA:57,0 +DA:59,3 +DA:61,1 +DA:62,2 +LF:27 +LH:18 +end_of_record +SF:lib/src/core/repositories/auth_repository/auth_repository_impl.dart DA:11,1 DA:15,1 DA:19,2 @@ -813,1588 +1018,1461 @@ DA:28,1 DA:31,1 DA:36,1 DA:41,1 -DA:46,2 -DA:47,1 -DA:48,1 -DA:51,1 -DA:52,1 +DA:44,2 +DA:45,1 +DA:46,1 +DA:49,1 +DA:50,1 +DA:53,0 DA:55,0 -DA:57,0 -LF:15 -LH:13 +DA:60,1 +DA:63,3 +DA:64,1 +DA:67,0 +DA:69,0 +LF:20 +LH:16 end_of_record -SF:lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart -DA:12,1 +SF:lib/src/shared/enums/sign_in_type.dart +DA:7,1 +DA:9,1 +DA:10,0 +DA:11,0 +DA:12,0 DA:16,1 -DA:20,2 -DA:21,1 -DA:25,1 -DA:30,1 -DA:35,1 -DA:40,1 -DA:45,2 -DA:46,1 -DA:47,1 -DA:51,1 -DA:54,0 -DA:56,0 -LF:14 -LH:12 +DA:18,1 +DA:19,0 +DA:20,0 +LF:9 +LH:4 end_of_record -SF:lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 +end_of_record +SF:lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart DA:11,1 -DA:15,1 -DA:18,3 -DA:21,1 -DA:23,0 -DA:25,0 -DA:30,1 -DA:35,1 +DA:13,1 +DA:18,2 +DA:19,1 +DA:24,2 +DA:32,1 +DA:33,0 +DA:35,0 DA:40,1 DA:43,2 DA:44,1 DA:45,1 -DA:48,1 -DA:51,0 -DA:53,0 -LF:15 -LH:11 +DA:52,1 +DA:57,1 +DA:60,2 +DA:61,1 +DA:67,1 +LF:17 +LH:15 end_of_record -SF:lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart -DA:8,1 -DA:10,1 -DA:12,2 -DA:15,1 -DA:17,2 -DA:20,1 +SF:lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart +DA:11,1 +DA:13,1 +DA:18,2 +DA:19,1 DA:24,2 -DA:27,1 -DA:31,2 -DA:34,1 -DA:36,2 -DA:39,1 -DA:41,2 -LF:13 -LH:13 -end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 +DA:32,1 DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 +DA:35,0 +DA:40,1 +DA:43,2 +DA:44,1 +DA:45,1 +DA:52,1 +DA:57,1 +DA:60,2 +DA:61,1 +DA:67,1 +LF:17 +LH:15 end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 -LH:0 +SF:lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart +DA:11,1 +DA:13,1 +DA:18,2 +DA:19,1 +DA:25,1 +DA:30,1 +DA:33,2 +DA:34,1 +DA:35,1 +DA:40,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:47,1 +DA:52,1 +DA:55,2 +DA:56,1 +DA:57,1 +DA:64,1 +DA:69,1 +DA:72,2 +DA:73,1 +DA:79,1 +DA:84,1 +DA:90,2 +DA:91,1 +DA:98,1 +LF:27 +LH:27 end_of_record -SF:lib/src/core/services/book_service/book_service_impl.dart +SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart +DA:12,1 +DA:14,1 +DA:17,3 +DA:18,2 DA:21,1 -DA:33,1 -DA:36,2 -DA:38,3 -DA:40,3 -DA:41,3 -DA:48,1 -DA:53,1 -DA:56,2 -DA:58,1 +DA:22,1 +DA:24,1 +DA:26,1 +DA:31,1 +DA:34,2 +DA:35,1 +DA:39,2 +DA:42,1 +DA:43,1 +DA:45,1 +DA:47,1 +DA:52,1 +DA:55,2 +DA:56,1 DA:60,1 +DA:63,1 +DA:64,1 DA:66,1 -DA:71,1 -DA:74,2 -DA:76,3 -DA:78,3 -DA:79,3 +DA:68,1 +DA:73,1 +DA:76,2 +DA:77,1 +DA:81,1 DA:86,1 +DA:89,2 +DA:90,1 DA:91,1 -DA:94,2 -DA:96,1 -DA:98,2 -DA:99,2 +DA:95,1 DA:100,1 DA:103,2 -DA:104,2 -DA:107,2 -DA:108,1 -DA:113,1 -DA:115,2 -DA:116,2 -DA:117,1 -DA:120,2 -DA:122,0 -DA:125,2 +DA:104,1 +DA:105,1 +DA:107,1 +DA:111,1 +DA:116,1 +DA:119,2 +DA:120,1 DA:126,1 -DA:132,1 -DA:137,1 -DA:141,2 -DA:143,1 -DA:148,1 -DA:151,2 -DA:153,1 -DA:158,1 -DA:161,2 -DA:163,1 -DA:168,1 -DA:174,2 -DA:179,1 -DA:184,1 -DA:190,2 -DA:195,1 -DA:200,1 -DA:203,2 -DA:205,1 -DA:210,1 -DA:213,2 -DA:215,1 -DA:220,1 -DA:222,2 -DA:225,3 -DA:226,1 -DA:228,1 -DA:229,2 -DA:230,2 -DA:231,1 -DA:235,2 -DA:238,3 -DA:239,1 -DA:241,1 -DA:242,2 -DA:243,2 -DA:244,1 -LF:73 -LH:72 +LF:43 +LH:43 end_of_record -SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart -DA:11,1 -DA:17,1 -DA:20,2 -DA:22,1 -DA:27,1 -DA:30,2 +SF:lib/src/core/repositories/books_repository/books_repository_impl.dart +DA:12,1 +DA:14,1 +DA:17,3 +DA:18,2 +DA:20,1 +DA:21,1 +DA:23,1 +DA:25,1 +DA:30,1 +DA:33,2 DA:34,1 DA:39,1 -DA:43,1 +DA:41,1 +DA:42,1 DA:44,1 DA:46,1 DA:51,1 -DA:56,2 -DA:61,1 -DA:66,1 -DA:69,2 -DA:73,1 -DA:78,1 -DA:82,2 -DA:84,1 -DA:89,1 -DA:93,2 -DA:95,1 -DA:100,1 -DA:106,2 -DA:111,1 -DA:116,1 -DA:119,2 -DA:121,1 -DA:126,1 -DA:129,2 -DA:134,1 -DA:139,1 -DA:142,2 -DA:147,1 -DA:152,1 -DA:155,2 -DA:160,1 -LF:38 -LH:38 +DA:54,2 +DA:55,1 +DA:56,1 +DA:59,1 +DA:64,1 +DA:67,2 +DA:68,1 +DA:69,1 +DA:74,1 +DA:76,1 +DA:77,1 +DA:79,1 +DA:81,1 +DA:86,1 +DA:89,2 +DA:90,1 +DA:94,2 +DA:97,1 +DA:98,1 +DA:100,1 +DA:102,1 +DA:107,1 +DA:110,2 +DA:111,1 +DA:116,1 +DA:121,1 +DA:124,2 +DA:125,1 +DA:126,1 +DA:131,2 +DA:133,1 +DA:134,1 +DA:136,1 +DA:138,1 +DA:143,1 +DA:149,2 +DA:150,1 +DA:153,2 +DA:157,1 +DA:162,1 +DA:167,2 +DA:170,2 +DA:171,1 +DA:174,1 +DA:178,1 +DA:183,1 +DA:186,2 +DA:187,1 +DA:191,1 +DA:196,1 +DA:199,2 +DA:200,1 +DA:205,1 +LF:70 +LH:70 end_of_record -SF:lib/src/core/services/loan_services/loan_service_impl.dart -DA:9,1 -DA:11,1 -DA:14,2 -DA:16,1 -DA:21,1 -DA:24,2 +SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart +DA:12,1 +DA:14,1 +DA:17,2 +DA:18,1 +DA:23,1 +DA:25,1 DA:26,1 -DA:31,1 -DA:34,2 -DA:38,1 -DA:43,1 -DA:46,2 -DA:48,1 +DA:28,1 +DA:30,0 +DA:37,1 +DA:40,2 +DA:41,1 +DA:46,1 +DA:47,1 +DA:50,2 +DA:52,1 DA:53,1 -DA:56,2 -DA:58,1 -DA:63,1 -DA:66,2 +DA:55,1 +DA:57,0 +DA:62,1 +DA:65,2 +DA:66,1 +DA:67,1 DA:71,1 DA:76,1 DA:79,2 -DA:84,1 -LF:22 -LH:22 +DA:80,1 +DA:86,1 +LF:28 +LH:26 end_of_record -SF:lib/src/core/services/reading_services/reading_service_impl.dart -DA:9,1 -DA:11,1 -DA:14,2 -DA:16,1 +SF:lib/src/core/models/loan_model.dart +DA:9,5 +DA:18,1 +DA:19,1 +DA:20,1 DA:21,1 -DA:24,2 -DA:28,1 +DA:22,2 +DA:23,2 +DA:24,1 +DA:25,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,1 DA:33,1 -DA:38,2 +DA:34,1 +DA:36,1 +DA:37,1 +DA:39,1 +DA:40,1 +DA:44,0 +DA:46,0 +DA:49,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,1 +DA:61,0 +DA:62,1 +DA:63,1 +DA:67,2 +DA:71,6 +DA:72,6 +DA:73,6 +DA:74,6 +DA:75,6 +DA:76,6 +DA:79,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +LF:43 +LH:33 +end_of_record +SF:lib/src/core/repositories/loan_repository/loan_repository_impl.dart +DA:13,1 +DA:15,1 +DA:18,2 +DA:19,1 +DA:23,2 +DA:26,1 +DA:27,1 +DA:29,1 +DA:31,1 +DA:36,1 +DA:39,2 +DA:40,3 +DA:41,1 DA:42,1 -DA:47,1 -DA:50,2 +DA:43,2 +DA:44,2 +DA:49,2 DA:52,1 +DA:53,1 +DA:55,1 DA:57,1 -DA:60,2 -DA:65,1 +DA:62,1 +DA:65,2 +DA:66,1 DA:70,1 -DA:73,2 +DA:73,1 +DA:74,1 +DA:76,1 DA:78,1 DA:83,1 DA:86,2 +DA:87,1 DA:91,1 -LF:22 -LH:22 -end_of_record -SF:lib/src/core/errors/auth_exception/auth_exception.dart -DA:7,1 -DA:12,0 -DA:13,0 -LF:3 -LH:1 +DA:96,1 +DA:99,2 +DA:100,1 +DA:101,1 +DA:105,1 +DA:110,1 +DA:113,2 +DA:114,1 +DA:115,1 +DA:117,1 +DA:121,1 +DA:126,1 +DA:129,2 +DA:130,1 +DA:136,1 +LF:48 +LH:48 end_of_record -SF:lib/src/core/services/auth_service/auth_service_impl.dart -DA:16,1 +SF:lib/src/core/models/reading_model.dart +DA:7,5 +DA:14,1 +DA:20,1 +DA:21,1 DA:22,0 -DA:24,0 -DA:27,0 +DA:23,1 +DA:24,1 +DA:28,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,2 DA:33,1 -DA:36,2 +DA:37,1 DA:38,1 DA:39,2 +DA:40,1 +DA:41,1 +DA:42,2 DA:44,1 +DA:48,0 +DA:50,0 +DA:53,3 +DA:57,6 +DA:58,6 +DA:59,6 +DA:60,6 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +LF:32 +LH:24 +end_of_record +SF:lib/src/core/repositories/reading_repository/reading_repository_impl.dart +DA:13,1 +DA:17,1 +DA:20,2 +DA:21,1 +DA:26,2 +DA:29,1 +DA:30,1 +DA:32,1 +DA:34,1 +DA:39,1 +DA:44,2 +DA:45,3 DA:46,1 DA:47,1 -DA:49,1 -DA:51,0 -DA:52,0 -DA:54,0 -DA:59,1 -DA:62,2 -DA:63,1 -DA:66,2 -DA:69,1 -DA:71,0 -DA:72,0 -DA:74,0 -DA:76,0 -DA:77,0 -DA:79,0 -DA:84,0 -DA:87,0 -DA:89,0 -DA:90,0 -DA:92,0 -DA:94,0 -DA:95,0 -DA:97,0 -LF:34 -LH:14 +DA:48,2 +DA:49,2 +DA:55,2 +DA:58,1 +DA:59,1 +DA:61,1 +DA:63,1 +DA:68,1 +DA:71,2 +DA:72,1 +DA:77,1 +DA:80,1 +DA:81,1 +DA:83,1 +DA:85,1 +DA:90,1 +DA:93,2 +DA:94,1 +DA:98,1 +DA:103,1 +DA:106,2 +DA:107,1 +DA:108,1 +DA:112,1 +DA:117,1 +DA:120,2 +DA:121,1 +DA:122,1 +DA:124,1 +DA:128,1 +DA:133,1 +DA:136,2 +DA:137,1 +DA:143,1 +LF:48 +LH:48 end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart -DA:12,0 -DA:14,0 -DA:15,0 +SF:lib/src/shared/enums/repeat_hour_time_type.dart +DA:5,1 +DA:7,1 +DA:8,0 +DA:9,0 +DA:13,1 +DA:15,1 DA:16,0 -DA:18,0 -DA:19,0 -DA:21,0 -DA:22,0 -DA:23,0 -LF:9 -LH:0 +LF:7 +LH:4 end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart -DA:16,0 -DA:20,0 -DA:24,0 -DA:25,0 -DA:27,0 -DA:28,0 -DA:31,0 -DA:32,0 +SF:lib/src/core/models/user_hour_time_model.dart +DA:12,1 +DA:20,2 +DA:22,1 +DA:24,4 +DA:27,4 +DA:30,1 +DA:31,1 DA:33,0 -DA:34,0 -DA:37,0 -DA:40,0 +DA:37,1 DA:41,0 -DA:43,0 -DA:44,0 +DA:48,0 +DA:49,0 DA:50,0 DA:51,0 -DA:55,0 -DA:59,0 -DA:60,0 -DA:61,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:69,0 -DA:70,0 -DA:71,0 -DA:72,0 -DA:73,0 -DA:74,0 -DA:77,0 -DA:79,0 -DA:81,0 +DA:52,0 +DA:53,0 +DA:57,1 +DA:58,1 +DA:59,2 +DA:60,1 +DA:61,1 +DA:62,1 +DA:63,1 +DA:67,1 +DA:68,1 +DA:70,2 +DA:71,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:78,3 +DA:80,1 +DA:81,2 DA:83,0 -DA:84,0 -DA:86,0 -DA:91,0 -DA:94,0 -DA:96,0 -DA:97,0 -DA:98,0 +DA:85,0 +DA:88,2 +DA:92,3 +DA:93,3 +DA:94,3 +DA:95,3 +DA:96,3 DA:99,0 -DA:100,0 DA:101,0 DA:102,0 DA:103,0 DA:104,0 -DA:107,0 -DA:109,0 -DA:111,0 -DA:112,0 -DA:114,0 -LF:52 -LH:0 +DA:105,0 +LF:47 +LH:31 end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart -DA:17,0 +SF:lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart +DA:11,1 +DA:15,1 +DA:19,2 +DA:20,1 +DA:28,1 +DA:31,1 +DA:36,1 +DA:41,1 +DA:46,2 +DA:47,1 +DA:48,1 +DA:51,1 +DA:52,1 +DA:55,0 +DA:57,0 +LF:15 +LH:13 +end_of_record +SF:lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart +DA:12,1 +DA:16,1 +DA:20,2 +DA:21,1 +DA:25,1 +DA:30,1 +DA:35,1 +DA:40,1 +DA:45,2 +DA:46,1 +DA:47,1 +DA:51,1 +DA:54,0 +DA:56,0 +LF:14 +LH:12 +end_of_record +SF:lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart +DA:11,1 +DA:15,1 +DA:18,3 +DA:21,1 DA:23,0 -DA:27,0 +DA:25,0 +DA:30,1 +DA:35,1 +DA:40,1 +DA:43,2 +DA:44,1 +DA:45,1 +DA:48,1 +DA:51,0 +DA:53,0 +LF:15 +LH:11 +end_of_record +SF:lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart +DA:8,1 +DA:10,1 +DA:12,2 +DA:15,1 +DA:17,2 +DA:20,1 +DA:24,2 +DA:27,1 +DA:31,2 +DA:34,1 +DA:36,2 +DA:39,1 +DA:41,2 +LF:13 +LH:13 +end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 DA:28,0 DA:30,0 -DA:31,0 -DA:34,0 -DA:35,0 -DA:36,0 +DA:33,0 DA:37,0 +DA:38,0 +DA:39,0 DA:40,0 DA:43,0 -DA:44,0 +DA:45,0 DA:46,0 -DA:50,0 -DA:53,0 -DA:54,0 -DA:55,0 -DA:59,0 -DA:60,0 -DA:64,0 -DA:68,0 -DA:69,0 -DA:70,0 -DA:77,0 -DA:79,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:87,0 -DA:88,0 -DA:89,0 -DA:93,0 -DA:95,0 -DA:97,0 -DA:99,0 -DA:100,0 -DA:102,0 -DA:107,0 -DA:110,0 -DA:111,0 -DA:113,0 -DA:114,0 -DA:115,0 -DA:116,0 -DA:117,0 -DA:118,0 -DA:119,0 -DA:120,0 -DA:121,0 -DA:124,0 -DA:126,0 -DA:128,0 -DA:129,0 -DA:131,0 -LF:58 -LH:0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 DA:13,0 -DA:19,0 -DA:22,0 -DA:23,0 -DA:25,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:35,0 -DA:36,0 -DA:37,0 -DA:40,0 -DA:44,0 -DA:45,0 -DA:46,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:54,0 -DA:55,0 -DA:56,0 -DA:57,0 -DA:58,0 -DA:59,0 -DA:63,0 -DA:65,0 -DA:67,0 -DA:69,0 -DA:70,0 -DA:72,0 -DA:77,0 -DA:80,0 -DA:81,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:87,0 -DA:88,0 -DA:89,0 -DA:90,0 -DA:91,0 -DA:94,0 -DA:96,0 -DA:98,0 -DA:99,0 -DA:101,0 -LF:47 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 LH:0 end_of_record -SF:lib/src/core/utils/verifier/isbn_verifier.dart -DA:11,9 -DA:16,6 -DA:25,2 -DA:26,2 -DA:28,6 -DA:29,4 -DA:31,4 -DA:43,2 -DA:44,4 -DA:48,2 -DA:49,1 -DA:50,2 -DA:51,1 -DA:52,1 +SF:lib/src/core/services/book_service/book_service_impl.dart +DA:21,1 +DA:33,1 +DA:36,2 +DA:38,3 +DA:40,3 +DA:41,3 +DA:48,1 DA:53,1 DA:56,2 -DA:69,2 -DA:70,4 -DA:74,4 -DA:75,2 -DA:76,4 -DA:78,2 -DA:81,4 -LF:23 -LH:23 -end_of_record -SF:lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart -DA:12,1 -DA:17,1 -DA:18,1 -DA:20,1 -DA:22,2 -DA:24,1 -DA:26,2 -DA:28,1 -DA:30,2 -DA:32,1 -DA:34,2 -DA:36,1 -DA:38,2 -DA:40,1 -DA:42,2 -DA:44,1 -DA:51,1 -DA:54,1 -DA:57,1 DA:58,1 -DA:59,1 -DA:62,1 -DA:64,1 -LF:23 -LH:23 -end_of_record -SF:lib/src/core/errors/rest_client_exception/rest_client_exception.dart -DA:7,2 -DA:12,0 -DA:13,0 -LF:3 -LH:1 -end_of_record -SF:lib/src/core/adapters/google_books_adapter.dart -DA:12,1 -DA:13,1 -DA:14,0 -DA:16,1 -DA:17,3 -DA:18,1 -DA:23,1 -DA:24,1 -DA:25,1 -DA:26,2 -DA:28,3 -DA:29,3 -DA:30,1 -DA:31,2 -DA:33,2 -DA:34,1 -DA:35,3 -DA:36,3 -DA:37,1 -DA:38,2 -DA:39,3 -DA:41,2 -DA:43,3 -DA:44,2 -LF:24 -LH:23 -end_of_record -SF:lib/src/shared/blocs/book_bloc/book_event.dart -DA:10,1 -DA:18,1 -DA:26,1 -DA:34,1 -DA:42,1 -LF:5 -LH:5 -end_of_record -SF:lib/src/shared/blocs/book_bloc/book_state.dart -DA:12,2 -DA:21,2 -LF:2 -LH:2 -end_of_record -SF:lib/src/shared/blocs/book_bloc/book_bloc.dart -DA:15,3 -DA:16,2 -DA:17,2 -DA:18,2 -DA:19,2 -DA:20,2 -DA:21,2 -DA:24,1 -DA:29,2 -DA:31,2 -DA:33,1 -DA:34,2 -DA:38,2 -DA:39,1 -DA:40,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:47,0 -DA:48,0 -DA:50,0 -DA:56,1 -DA:61,2 -DA:63,3 -DA:65,1 -DA:66,2 -DA:69,2 -DA:70,1 +DA:60,1 +DA:66,1 DA:71,1 -DA:72,1 -DA:73,1 -DA:74,1 -DA:78,0 -DA:79,0 -DA:81,0 -DA:87,1 -DA:92,2 +DA:74,2 +DA:76,3 +DA:78,3 +DA:79,3 +DA:86,1 +DA:91,1 DA:94,2 -DA:95,1 -DA:98,1 +DA:96,1 +DA:98,2 DA:99,2 +DA:100,1 DA:103,2 -DA:104,1 -DA:105,1 -DA:106,1 -DA:107,1 +DA:104,2 +DA:107,2 DA:108,1 -DA:112,0 -DA:113,0 -DA:115,0 -DA:121,1 -DA:126,2 -DA:128,2 -DA:129,1 +DA:113,1 +DA:115,2 +DA:116,2 +DA:117,1 +DA:120,2 +DA:122,0 +DA:125,2 +DA:126,1 DA:132,1 -DA:133,2 -DA:137,2 -DA:138,1 -DA:139,1 -DA:140,1 -DA:141,1 -DA:142,1 -DA:146,0 -DA:147,0 -DA:149,0 -DA:155,1 -DA:160,2 -DA:162,2 +DA:137,1 +DA:141,2 +DA:143,1 +DA:148,1 +DA:151,2 +DA:153,1 +DA:158,1 +DA:161,2 DA:163,1 -DA:166,1 -DA:167,2 -DA:171,2 -DA:172,1 -DA:173,1 -DA:174,1 -DA:175,1 -DA:176,1 -DA:180,0 -DA:181,0 -DA:183,0 -DA:189,1 -DA:194,2 -DA:196,1 -DA:197,2 -DA:199,1 +DA:168,1 +DA:174,2 +DA:179,1 +DA:184,1 +DA:190,2 +DA:195,1 DA:200,1 -DA:208,2 +DA:203,2 +DA:205,1 DA:210,1 -DA:211,2 -DA:215,2 -DA:216,0 -DA:217,0 -DA:218,0 -DA:219,0 -DA:220,0 -DA:224,0 -DA:225,0 -DA:227,0 -LF:98 -LH:75 +DA:213,2 +DA:215,1 +DA:220,1 +DA:222,2 +DA:225,3 +DA:226,1 +DA:228,1 +DA:229,2 +DA:230,2 +DA:231,1 +DA:235,2 +DA:238,3 +DA:239,1 +DA:241,1 +DA:242,2 +DA:243,2 +DA:244,1 +LF:73 +LH:72 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart DA:11,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 +DA:17,1 DA:20,2 DA:22,1 -DA:23,1 -DA:25,1 -DA:26,1 DA:27,1 -DA:28,1 -DA:29,1 -DA:32,1 -DA:33,1 +DA:30,2 DA:34,1 -DA:36,1 -LF:16 -LH:16 -end_of_record -SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart -DA:13,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart -DA:10,1 -DA:12,2 -DA:14,1 -DA:16,2 -DA:18,2 -DA:20,2 -DA:21,1 -DA:22,1 -DA:23,1 -DA:24,1 -LF:10 -LH:10 -end_of_record -SF:lib/src/core/models/custom_notification_model.dart -DA:5,0 -DA:7,0 -DA:8,0 -DA:12,0 -DA:14,0 -DA:15,0 -DA:19,0 -DA:21,0 -DA:23,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:45,2 -DA:54,0 -DA:62,0 -DA:63,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:72,0 -DA:74,0 -DA:77,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:89,0 -DA:91,0 -DA:92,0 -DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -LF:37 -LH:1 -end_of_record -SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 -DA:23,2 -DA:26,1 -DA:27,1 -DA:32,1 -DA:33,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 DA:39,1 -DA:42,1 DA:43,1 DA:44,1 DA:46,1 -DA:52,1 -DA:54,2 +DA:51,1 DA:56,2 -DA:60,1 DA:61,1 -DA:62,1 -DA:70,1 -DA:71,1 +DA:66,1 +DA:69,2 DA:73,1 -DA:74,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:80,1 -DA:81,1 -DA:82,1 +DA:78,1 +DA:82,2 DA:84,1 -LF:36 -LH:36 -end_of_record -SF:lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/about/bloc/about_bloc.dart -DA:11,3 -DA:12,2 -DA:15,1 -DA:20,2 -DA:21,2 -DA:22,2 -DA:24,1 -DA:25,1 -DA:26,2 -LF:9 -LH:9 -end_of_record -SF:lib/src/features/about/bloc/about_state.dart -DA:10,1 -DA:18,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/auth/bloc/auth_bloc.dart -DA:13,3 -DA:14,2 -DA:17,1 -DA:22,2 -DA:24,2 -DA:25,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:39,2 -DA:40,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:44,1 -DA:47,1 -DA:48,1 -DA:49,1 -DA:51,1 -LF:19 -LH:19 -end_of_record -SF:lib/src/features/auth/bloc/auth_event.dart -DA:8,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/features/auth/bloc/auth_state.dart -DA:15,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/features/about/bloc/about_bloc.dart -DA:11,3 -DA:12,2 -DA:15,1 -DA:20,2 -DA:21,2 -DA:22,2 -DA:24,1 -DA:25,1 -DA:26,2 -LF:9 -LH:9 -end_of_record -SF:lib/src/features/about/bloc/about_state.dart -DA:10,1 -DA:18,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/book_detail/bloc/book_detail_event.dart -DA:8,2 -DA:16,2 -DA:24,1 -LF:3 -LH:3 +DA:89,1 +DA:93,2 +DA:95,1 +DA:100,1 +DA:106,2 +DA:111,1 +DA:116,1 +DA:119,2 +DA:121,1 +DA:126,1 +DA:129,2 +DA:134,1 +DA:139,1 +DA:142,2 +DA:147,1 +DA:152,1 +DA:155,2 +DA:160,1 +LF:38 +LH:38 end_of_record -SF:lib/src/features/book_detail/bloc/book_detail_state.dart -DA:10,2 -DA:18,2 -LF:2 -LH:2 +SF:lib/src/core/services/loan_services/loan_service_impl.dart +DA:9,1 +DA:11,1 +DA:14,2 +DA:16,1 +DA:21,1 +DA:24,2 +DA:26,1 +DA:31,1 +DA:34,2 +DA:38,1 +DA:43,1 +DA:46,2 +DA:48,1 +DA:53,1 +DA:56,2 +DA:58,1 +DA:63,1 +DA:66,2 +DA:71,1 +DA:76,1 +DA:79,2 +DA:84,1 +LF:22 +LH:22 end_of_record -SF:lib/src/features/book_detail/bloc/book_detail_bloc.dart -DA:14,1 -DA:16,2 -DA:17,2 -DA:18,2 -DA:19,2 -DA:22,1 -DA:27,2 -DA:29,2 -DA:30,1 -DA:33,2 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,2 -DA:41,1 +SF:lib/src/core/services/reading_services/reading_service_impl.dart +DA:9,1 +DA:11,1 +DA:14,2 +DA:16,1 +DA:21,1 +DA:24,2 +DA:28,1 +DA:33,1 +DA:38,2 DA:42,1 -DA:43,2 -DA:49,1 -DA:54,2 -DA:56,2 +DA:47,1 +DA:50,2 +DA:52,1 DA:57,1 -DA:60,1 -DA:61,1 -DA:62,1 -DA:67,2 -DA:68,1 -DA:69,1 +DA:60,2 +DA:65,1 DA:70,1 -DA:71,2 -DA:75,1 -DA:76,1 -DA:77,2 +DA:73,2 +DA:78,1 DA:83,1 -DA:88,2 -DA:90,3 -DA:92,1 -DA:93,1 -DA:94,1 -DA:96,2 -DA:102,3 -DA:103,1 -DA:104,1 -DA:105,1 -DA:111,2 -DA:113,1 -DA:114,1 -DA:115,1 -DA:116,2 -DA:120,1 -DA:121,1 -DA:122,2 -LF:51 -LH:51 +DA:86,2 +DA:91,1 +LF:22 +LH:22 end_of_record -SF:lib/src/core/helpers/book_status/book_status_extension.dart -DA:7,0 -DA:9,0 -DA:10,0 -DA:11,0 -DA:15,1 -DA:17,1 -DA:18,2 -DA:19,2 -LF:8 -LH:4 +SF:lib/src/core/errors/auth_exception/auth_exception.dart +DA:7,1 +DA:12,0 +DA:13,0 +LF:3 +LH:1 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart -DA:14,1 -DA:16,2 -DA:17,2 -DA:20,1 -DA:25,2 -DA:27,1 -DA:28,1 -DA:30,1 -DA:31,1 -DA:35,1 -DA:36,1 -DA:37,1 +SF:lib/src/core/services/auth_service/auth_service_impl.dart +DA:16,1 +DA:22,0 +DA:24,0 +DA:27,0 +DA:33,1 +DA:36,2 DA:38,1 -DA:39,1 -DA:42,1 -DA:43,1 +DA:39,2 DA:44,1 DA:46,1 -LF:18 -LH:18 -end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 +DA:47,1 +DA:49,1 +DA:51,0 +DA:52,0 +DA:54,0 +DA:59,1 +DA:62,2 +DA:63,1 +DA:66,2 +DA:69,1 +DA:71,0 +DA:72,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:79,0 +DA:84,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:92,0 +DA:94,0 +DA:95,0 +DA:97,0 +LF:34 +LH:14 end_of_record -SF:lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart -DA:5,0 -DA:9,0 +SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart DA:12,0 -DA:13,0 DA:14,0 -DA:17,0 +DA:15,0 +DA:16,0 +DA:18,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +LF:9 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart +DA:16,0 DA:20,0 -LF:7 +DA:24,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:37,0 +DA:40,0 +DA:41,0 +DA:43,0 +DA:44,0 +DA:50,0 +DA:51,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:77,0 +DA:79,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:86,0 +DA:91,0 +DA:94,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:107,0 +DA:109,0 +DA:111,0 +DA:112,0 +DA:114,0 +LF:52 LH:0 end_of_record -SF:lib/src/core/services/app_services/launcher_service/launcher_service.dart -DA:4,0 -DA:6,0 -DA:8,0 +SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart DA:17,0 -DA:21,0 DA:23,0 -DA:24,0 DA:27,0 DA:28,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 DA:40,0 -LF:10 -LH:0 -end_of_record -SF:lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart -DA:8,6 -DA:10,2 -DA:17,2 -DA:25,2 -DA:30,2 -DA:31,2 -DA:32,2 -DA:38,2 -DA:39,2 -DA:40,2 -DA:46,2 -DA:48,2 -DA:49,2 -DA:52,2 -DA:53,2 +DA:43,0 +DA:44,0 +DA:46,0 +DA:50,0 +DA:53,0 DA:54,0 -DA:56,0 +DA:55,0 DA:59,0 -DA:64,2 -DA:65,2 -DA:67,0 -DA:70,2 +DA:60,0 +DA:64,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:77,0 +DA:79,0 +DA:81,0 +DA:82,0 DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 DA:87,0 +DA:88,0 DA:89,0 +DA:93,0 +DA:95,0 DA:97,0 -DA:98,0 DA:99,0 -DA:101,0 -DA:105,0 +DA:100,0 +DA:102,0 DA:107,0 -DA:108,0 DA:110,0 DA:111,0 DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 DA:118,0 +DA:119,0 DA:120,0 DA:121,0 DA:124,0 -LF:39 -LH:18 +DA:126,0 +DA:128,0 +DA:129,0 +DA:131,0 +LF:58 +LH:0 end_of_record -SF:lib/src/core/services/app_services/snackbar_service/snackbar_service.dart -DA:10,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:15,2 -DA:19,2 -DA:21,2 -DA:22,2 -DA:23,2 -DA:24,2 -DA:30,2 -DA:36,2 -DA:40,2 -DA:41,2 -DA:42,2 +SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart +DA:13,0 +DA:19,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:40,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:63,0 +DA:65,0 +DA:67,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:94,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:101,0 +LF:47 +LH:0 +end_of_record +SF:lib/src/core/utils/verifier/isbn_verifier.dart +DA:11,9 +DA:16,6 +DA:25,2 +DA:26,2 +DA:28,6 +DA:29,4 +DA:31,4 DA:43,2 -DA:46,2 -DA:49,2 -DA:54,2 -DA:55,2 +DA:44,4 +DA:48,2 +DA:49,1 +DA:50,2 +DA:51,1 +DA:52,1 +DA:53,1 DA:56,2 -DA:60,2 -DA:73,2 -DA:74,2 +DA:69,2 +DA:70,4 +DA:74,4 DA:75,2 -LF:25 -LH:25 +DA:76,4 +DA:78,2 +DA:81,4 +LF:23 +LH:23 end_of_record -SF:lib/src/features/book_detail/views/book_detail_page.dart +SF:lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart +DA:12,1 +DA:17,1 +DA:18,1 +DA:20,1 +DA:22,2 +DA:24,1 +DA:26,2 +DA:28,1 +DA:30,2 +DA:32,1 +DA:34,2 +DA:36,1 +DA:38,2 +DA:40,1 +DA:42,2 +DA:44,1 +DA:51,1 +DA:54,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:62,1 +DA:64,1 +LF:23 +LH:23 +end_of_record +SF:lib/src/core/errors/rest_client_exception/rest_client_exception.dart +DA:7,2 +DA:12,0 +DA:13,0 +LF:3 +LH:1 +end_of_record +SF:lib/src/core/adapters/google_books_adapter.dart +DA:12,1 +DA:13,1 +DA:14,0 +DA:16,1 +DA:17,3 DA:18,1 DA:23,1 DA:24,1 -DA:50,1 -DA:52,1 -DA:54,2 -DA:55,1 +DA:25,1 +DA:26,2 +DA:28,3 +DA:29,3 +DA:30,1 +DA:31,2 +DA:33,2 +DA:34,1 +DA:35,3 +DA:36,3 +DA:37,1 +DA:38,2 +DA:39,3 +DA:41,2 +DA:43,3 +DA:44,2 +LF:24 +LH:23 +end_of_record +SF:lib/src/shared/blocs/book_bloc/book_event.dart +DA:10,1 +DA:18,1 +DA:26,1 +DA:34,1 +DA:42,1 +LF:5 +LH:5 +end_of_record +SF:lib/src/shared/blocs/book_bloc/book_state.dart +DA:12,2 +DA:21,2 +LF:2 +LH:2 +end_of_record +SF:lib/src/shared/blocs/book_bloc/book_bloc.dart +DA:15,3 +DA:16,2 +DA:17,2 +DA:18,2 +DA:19,2 +DA:20,2 +DA:21,2 +DA:24,1 +DA:29,2 +DA:31,2 +DA:33,1 +DA:34,2 +DA:38,2 +DA:39,1 +DA:40,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:47,0 +DA:48,0 +DA:50,0 DA:56,1 -DA:59,3 -DA:60,1 -DA:61,1 -DA:62,3 -DA:67,1 +DA:61,2 +DA:63,3 +DA:65,1 +DA:66,2 +DA:69,2 DA:70,1 -DA:72,3 -DA:73,2 +DA:71,1 +DA:72,1 +DA:73,1 DA:74,1 DA:78,0 DA:79,0 -DA:80,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:87,0 -DA:89,0 -DA:90,0 -DA:94,1 -DA:99,1 -DA:101,1 +DA:81,0 +DA:87,1 +DA:92,2 +DA:94,2 +DA:95,1 +DA:98,1 +DA:99,2 +DA:103,2 DA:104,1 -DA:106,2 -DA:109,1 -DA:111,1 -DA:112,1 -DA:113,1 -DA:114,1 -DA:116,1 -DA:124,1 -DA:127,2 +DA:105,1 +DA:106,1 +DA:107,1 +DA:108,1 +DA:112,0 +DA:113,0 +DA:115,0 +DA:121,1 +DA:126,2 +DA:128,2 DA:129,1 -DA:131,1 +DA:132,1 +DA:133,2 +DA:137,2 +DA:138,1 +DA:139,1 DA:140,1 DA:141,1 DA:142,1 -DA:143,1 -DA:144,3 -DA:145,1 DA:146,0 DA:147,0 -DA:148,0 -DA:152,3 -DA:156,1 -DA:158,2 -DA:159,1 -DA:160,3 -DA:161,1 -DA:162,1 +DA:149,0 +DA:155,1 +DA:160,2 +DA:162,2 DA:163,1 -DA:164,3 -DA:165,1 DA:166,1 -DA:168,2 -DA:170,1 -DA:171,1 +DA:167,2 +DA:171,2 DA:172,1 DA:173,1 DA:174,1 DA:175,1 -DA:177,1 -DA:178,1 -DA:179,1 -DA:180,1 -DA:184,1 -DA:185,1 -DA:187,1 -DA:190,1 -DA:195,1 -DA:202,1 -DA:203,1 -DA:204,1 -DA:206,1 -DA:207,1 -DA:208,1 -DA:210,2 -DA:219,1 -DA:220,1 -DA:222,1 -DA:226,1 -DA:228,1 -DA:229,1 -DA:231,4 -DA:233,1 -DA:234,1 -DA:239,1 -DA:241,1 -DA:246,1 -DA:249,1 -DA:250,1 -DA:251,1 -DA:253,1 -DA:255,0 -DA:256,0 -DA:260,1 -DA:261,1 -DA:264,1 -DA:268,1 -DA:269,1 -DA:270,1 -DA:272,2 -DA:273,1 -DA:280,1 -DA:282,1 -DA:284,1 -DA:290,1 -DA:292,0 -DA:293,0 -DA:295,1 -DA:296,1 -DA:297,1 -DA:299,1 -DA:309,1 -DA:312,1 -DA:313,1 -DA:314,1 -DA:315,1 -DA:317,1 -DA:319,1 -DA:325,1 -DA:327,1 -DA:328,1 -DA:333,1 -DA:334,1 -DA:337,1 -DA:338,1 -DA:340,1 -DA:342,1 -DA:348,1 -DA:350,1 -DA:351,1 -DA:353,1 -DA:355,1 -LF:141 -LH:125 -end_of_record -SF:lib/src/shared/widgets/book_widget/book_widget.dart -DA:13,1 -DA:23,1 -DA:33,2 -DA:35,4 -DA:37,2 -DA:38,2 -DA:39,2 -DA:40,2 -DA:41,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:55,0 -DA:57,0 -DA:59,0 -DA:69,2 -DA:70,0 -DA:72,0 -LF:21 -LH:9 +DA:176,1 +DA:180,0 +DA:181,0 +DA:183,0 +DA:189,1 +DA:194,2 +DA:196,1 +DA:197,2 +DA:199,1 +DA:200,1 +DA:208,2 +DA:210,1 +DA:211,2 +DA:215,2 +DA:216,0 +DA:217,0 +DA:218,0 +DA:219,0 +DA:220,0 +DA:224,0 +DA:225,0 +DA:227,0 +LF:98 +LH:75 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart -DA:7,1 -DA:10,1 -DA:12,1 -DA:13,1 -DA:14,1 -DA:15,1 -DA:18,3 +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +DA:11,1 DA:20,1 -DA:21,1 -DA:22,1 -DA:23,1 -DA:24,4 -LF:12 -LH:12 +LF:2 +LH:2 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart -DA:11,1 +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 DA:16,1 -DA:17,1 +DA:18,2 +DA:20,2 +DA:22,1 DA:23,1 DA:25,1 -DA:26,3 +DA:26,1 DA:27,1 DA:28,1 +DA:29,1 DA:32,1 -DA:37,1 -DA:39,0 -DA:40,0 -DA:42,0 -DA:43,0 -DA:46,0 -DA:47,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:55,0 -DA:56,0 -DA:59,0 -DA:60,0 -DA:67,1 -DA:69,1 -DA:70,1 -DA:71,1 -LF:27 -LH:14 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 end_of_record -SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart -DA:6,1 -DA:11,4 -DA:13,4 -DA:14,4 -LF:4 -LH:4 +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart +DA:13,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart +DA:10,1 +DA:12,2 +DA:14,1 +DA:16,2 +DA:18,2 +DA:20,2 +DA:21,1 +DA:22,1 +DA:23,1 +DA:24,1 +LF:10 +LH:10 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_rating/book_rating.dart -DA:10,1 +SF:lib/src/core/models/custom_notification_model.dart +DA:5,0 +DA:7,0 +DA:8,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:45,2 +DA:54,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:72,0 +DA:74,0 +DA:77,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:89,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +LF:37 +LH:1 +end_of_record +SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart +DA:12,1 +DA:14,2 DA:16,1 DA:18,2 -DA:20,1 -DA:21,1 -DA:22,1 +DA:20,2 DA:23,2 -DA:25,1 -DA:28,1 -DA:31,1 +DA:26,1 +DA:27,1 DA:32,1 -DA:34,1 -DA:35,4 -DA:37,1 -DA:38,1 -LF:15 -LH:15 -end_of_record -SF:lib/src/shared/widgets/bookify_rating/bookify_rating_widget.dart -DA:13,1 -DA:24,1 -DA:27,2 -DA:29,0 -DA:30,5 DA:33,1 +DA:35,1 DA:36,1 +DA:37,1 +DA:38,1 DA:39,1 -DA:45,1 -DA:47,2 -DA:48,2 -DA:49,2 -DA:51,1 +DA:42,1 +DA:43,1 +DA:44,1 +DA:46,1 DA:52,1 -DA:54,1 -DA:55,2 -LF:16 -LH:15 -end_of_record -SF:lib/src/shared/widgets/buttons/bookify_elevated_button.dart -DA:10,1 -DA:19,2 -DA:28,3 -DA:30,3 -DA:32,3 -DA:33,7 -DA:34,3 -DA:35,3 -DA:36,3 -DA:37,3 -DA:38,0 -DA:39,0 -DA:40,0 -DA:44,6 -DA:45,3 -DA:46,3 -DA:50,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:54,0 -DA:55,0 -DA:59,0 -DA:60,0 -LF:24 -LH:13 -end_of_record -SF:lib/src/shared/widgets/buttons/bookify_outlined_button.dart -DA:10,1 -DA:19,2 -DA:28,3 -DA:30,3 -DA:32,3 -DA:33,7 -DA:34,3 -DA:35,2 -DA:36,2 -DA:37,2 -DA:38,0 -DA:39,0 -DA:40,0 -DA:42,0 -DA:43,0 -DA:45,0 -DA:48,0 -DA:51,4 -DA:52,2 -DA:53,2 -DA:55,2 +DA:54,2 DA:56,2 DA:60,1 DA:61,1 DA:62,1 -DA:63,0 -DA:64,0 -DA:65,0 -DA:67,0 -DA:68,0 -DA:70,0 -DA:73,0 +DA:70,1 +DA:71,1 +DA:73,1 +DA:74,1 +DA:75,1 DA:76,1 DA:77,1 -DA:79,1 DA:80,1 +DA:81,1 +DA:82,1 +DA:84,1 LF:36 -LH:22 +LH:36 end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_event.dart -DA:8,1 -DA:17,1 +SF:lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart +DA:11,1 +DA:20,1 LF:2 LH:2 end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart -DA:11,1 -DA:22,1 +SF:lib/src/features/about/bloc/about_bloc.dart +DA:11,3 +DA:12,2 +DA:15,1 +DA:20,2 +DA:21,2 +DA:22,2 +DA:24,1 +DA:25,1 +DA:26,2 +LF:9 +LH:9 +end_of_record +SF:lib/src/features/about/bloc/about_state.dart +DA:10,1 +DA:18,1 LF:2 LH:2 end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart -DA:12,1 +SF:lib/src/features/auth/bloc/auth_bloc.dart +DA:13,3 DA:14,2 -DA:15,2 -DA:16,2 -DA:19,1 +DA:17,1 +DA:22,2 DA:24,2 -DA:26,2 -DA:27,1 +DA:25,1 +DA:28,1 +DA:29,1 DA:30,1 -DA:31,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,2 +DA:39,2 DA:40,1 DA:41,1 -DA:42,2 +DA:42,1 +DA:43,1 +DA:44,1 DA:47,1 -DA:52,2 -DA:54,2 -DA:55,1 -DA:56,1 -DA:59,1 -DA:60,1 -DA:61,1 -DA:67,2 -DA:68,1 -DA:69,1 -DA:70,1 -DA:71,2 -DA:73,1 -DA:74,1 -DA:75,2 -LF:33 -LH:33 +DA:48,1 +DA:49,1 +DA:51,1 +LF:19 +LH:19 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_state.dart -DA:10,2 -DA:20,2 +SF:lib/src/features/auth/bloc/auth_event.dart +DA:8,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/features/auth/bloc/auth_state.dart +DA:15,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_event.dart +DA:8,1 +DA:17,1 LF:2 LH:2 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_bloc.dart -DA:16,1 -DA:19,2 -DA:20,2 -DA:21,2 -DA:22,2 -DA:25,1 -DA:30,2 +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart +DA:11,1 +DA:23,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart +DA:13,1 +DA:15,2 +DA:16,2 +DA:17,2 +DA:20,1 +DA:25,2 +DA:27,2 +DA:28,1 +DA:31,1 DA:32,1 -DA:33,1 -DA:34,4 -DA:35,1 -DA:36,3 +DA:36,1 +DA:37,1 +DA:38,1 +DA:39,1 DA:40,1 -DA:45,2 -DA:47,2 -DA:48,1 -DA:49,4 -DA:50,1 -DA:51,3 -DA:55,1 +DA:43,1 +DA:44,1 +DA:45,1 +DA:47,1 +DA:53,1 +DA:58,2 DA:60,2 +DA:61,1 DA:62,1 -DA:64,2 -DA:65,2 -DA:66,2 -DA:68,2 -DA:69,1 -DA:70,1 +DA:65,1 +DA:66,1 +DA:67,1 +DA:76,2 DA:77,1 DA:78,1 -DA:79,4 +DA:79,1 DA:80,1 -DA:81,3 +DA:81,1 +DA:84,1 DA:85,1 -DA:86,2 +DA:86,1 DA:88,1 -DA:89,2 -DA:93,1 -DA:96,1 -DA:98,2 -DA:100,1 -DA:101,2 -DA:105,1 -DA:108,1 -DA:112,1 -DA:114,2 -DA:115,1 -DA:116,1 -DA:117,3 -DA:122,2 -DA:123,1 -DA:129,2 -DA:132,1 -DA:137,1 -DA:140,2 -LF:55 -LH:55 -end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_event.dart -DA:10,1 -DA:18,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/core/dtos/bookcase_dto.dart -DA:7,2 -DA:12,0 -DA:16,0 -DA:17,0 -DA:18,0 -DA:22,0 -DA:24,0 -DA:26,1 -DA:30,3 -DA:31,0 -DA:34,0 -DA:35,0 -LF:12 -LH:3 -end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 +LF:37 +LH:37 end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 @@ -2428,91 +2506,91 @@ LF:5 LH:0 end_of_record SF:lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart -DA:23,0 -DA:29,0 -DA:31,0 -DA:38,0 -DA:40,0 +DA:24,0 +DA:30,0 +DA:32,0 +DA:39,0 DA:41,0 DA:42,0 DA:43,0 DA:44,0 -DA:47,0 -DA:50,0 -DA:54,0 +DA:45,0 +DA:48,0 +DA:51,0 DA:55,0 DA:56,0 -DA:59,0 -DA:61,0 -DA:65,0 +DA:57,0 +DA:60,0 +DA:62,0 DA:66,0 DA:67,0 DA:68,0 -DA:72,0 +DA:69,0 DA:73,0 DA:74,0 -DA:77,0 -DA:79,0 +DA:75,0 +DA:78,0 +DA:80,0 DA:81,0 -DA:85,0 DA:86,0 DA:87,0 DA:88,0 -DA:95,0 -DA:97,0 -DA:99,0 +DA:89,0 +DA:96,0 +DA:98,0 DA:100,0 DA:101,0 DA:102,0 -DA:104,0 +DA:103,0 DA:105,0 -DA:111,0 +DA:106,0 DA:112,0 DA:113,0 DA:114,0 DA:115,0 DA:116,0 -DA:118,0 +DA:117,0 DA:119,0 -DA:123,0 +DA:120,0 DA:124,0 DA:125,0 DA:126,0 -DA:131,0 -DA:133,0 -DA:135,0 +DA:127,0 +DA:132,0 +DA:134,0 DA:136,0 -DA:141,0 +DA:137,0 DA:142,0 -DA:144,0 +DA:143,0 DA:145,0 -DA:148,0 +DA:146,0 DA:149,0 DA:150,0 -DA:157,0 +DA:151,0 DA:158,0 -DA:165,0 +DA:159,0 DA:166,0 -DA:168,0 +DA:167,0 DA:169,0 -DA:179,0 +DA:170,0 DA:180,0 -DA:182,0 -DA:185,0 +DA:181,0 +DA:183,0 DA:186,0 DA:187,0 DA:188,0 DA:189,0 -DA:194,0 -DA:196,0 +DA:190,0 +DA:195,0 DA:197,0 DA:198,0 -DA:200,0 +DA:199,0 DA:201,0 DA:202,0 DA:203,0 DA:204,0 -DA:207,0 +DA:205,0 +DA:208,0 LF:85 LH:0 end_of_record @@ -2570,49 +2648,52 @@ LF:13 LH:0 end_of_record SF:lib/src/features/bookcase/views/bookcase_page.dart -DA:14,1 -DA:19,1 +DA:15,1 DA:20,1 -DA:26,1 -DA:28,1 -DA:30,5 -DA:33,0 -DA:35,0 +DA:21,1 +DA:27,1 +DA:29,1 +DA:31,5 +DA:34,0 DA:36,0 DA:37,0 -DA:40,0 -DA:45,0 +DA:38,0 +DA:41,0 DA:46,0 -DA:53,0 +DA:47,0 DA:54,0 -DA:57,1 -DA:59,1 -DA:62,2 -DA:63,1 -DA:65,1 -DA:66,0 -DA:69,2 -DA:70,1 -DA:73,1 -DA:74,0 +DA:55,0 +DA:58,1 +DA:60,1 +DA:63,2 +DA:64,1 +DA:66,1 +DA:67,0 +DA:70,2 +DA:71,1 +DA:74,1 DA:75,0 -DA:80,2 -DA:82,1 +DA:76,0 +DA:81,2 DA:83,1 -DA:85,2 +DA:84,1 DA:86,1 -DA:89,1 -DA:94,0 -DA:96,0 -DA:97,0 -DA:102,0 -DA:105,0 -DA:109,1 -DA:111,1 -DA:112,1 +DA:87,1 +DA:88,1 +DA:90,1 +DA:92,1 +DA:93,1 +DA:98,0 +DA:100,0 +DA:101,0 +DA:106,0 +DA:109,0 DA:113,1 -LF:41 -LH:24 +DA:115,1 +DA:116,1 +DA:117,1 +LF:44 +LH:27 end_of_record SF:lib/src/features/bookcase/views/widgets/bookcase_loaded_state_widget/bookcase_loaded_state_widget.dart DA:16,1 @@ -2709,137 +2790,140 @@ LF:90 LH:52 end_of_record SF:lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart -DA:32,1 -DA:40,1 +DA:33,1 DA:41,1 -DA:54,1 -DA:58,1 -DA:64,1 +DA:42,1 +DA:55,1 +DA:59,1 DA:65,1 -DA:78,1 -DA:80,1 -DA:82,1 -DA:84,3 -DA:86,5 +DA:66,1 +DA:79,1 +DA:81,1 +DA:83,1 +DA:85,3 DA:87,5 -DA:88,4 -DA:91,1 -DA:93,2 +DA:88,5 +DA:89,4 +DA:92,1 DA:94,2 -DA:95,1 -DA:101,0 +DA:95,2 +DA:96,1 DA:102,0 DA:103,0 DA:104,0 -DA:106,0 +DA:105,0 DA:107,0 -DA:123,1 -DA:124,3 -DA:125,2 -DA:128,2 -DA:129,1 -DA:130,3 -DA:131,4 -DA:133,3 -DA:134,1 -DA:138,2 +DA:108,0 +DA:124,1 +DA:125,3 +DA:126,2 +DA:129,2 +DA:130,1 +DA:131,3 +DA:132,4 +DA:134,3 +DA:135,1 DA:139,2 -DA:140,1 +DA:140,2 DA:141,1 -DA:142,3 -DA:143,4 -DA:145,3 -DA:146,1 -DA:150,4 -DA:151,0 +DA:142,1 +DA:143,3 +DA:144,4 +DA:146,3 +DA:147,1 +DA:151,4 DA:152,0 DA:153,0 -DA:155,1 -DA:156,3 +DA:154,0 +DA:156,1 DA:157,3 -DA:158,1 -DA:162,2 -DA:163,1 -DA:168,1 -DA:173,1 -DA:174,0 -DA:176,0 -DA:181,1 +DA:158,3 +DA:159,1 +DA:163,2 +DA:164,1 +DA:169,1 +DA:174,1 +DA:175,0 +DA:177,0 DA:182,1 -DA:184,1 -DA:190,2 -DA:191,1 +DA:183,1 +DA:185,1 +DA:191,2 DA:192,1 -DA:193,3 -DA:195,1 -DA:201,2 +DA:193,1 +DA:194,3 +DA:196,1 DA:202,1 -DA:208,2 -DA:209,1 -DA:210,1 -DA:211,2 -DA:219,1 -DA:221,2 -DA:224,1 -DA:225,1 -DA:227,2 +DA:203,1 +DA:204,1 +DA:206,1 +DA:208,1 +DA:212,2 +DA:213,1 +DA:214,1 +DA:215,2 +DA:223,1 +DA:225,2 +DA:228,1 DA:229,1 -DA:230,1 -DA:231,1 -DA:232,1 +DA:231,2 DA:233,1 +DA:234,1 DA:235,1 +DA:236,1 +DA:237,1 DA:239,1 -DA:240,1 -DA:242,1 DA:243,1 -DA:248,1 -DA:249,1 -DA:251,1 +DA:244,1 +DA:246,1 +DA:247,1 DA:252,1 DA:253,1 -DA:254,1 +DA:255,1 +DA:256,1 DA:257,1 DA:258,1 -DA:260,1 DA:261,1 -DA:263,1 +DA:262,1 DA:264,1 DA:265,1 -DA:266,1 +DA:267,1 DA:268,1 +DA:269,1 DA:270,1 -DA:274,2 -DA:276,1 -DA:277,1 +DA:272,1 +DA:274,1 +DA:278,2 +DA:280,1 DA:281,1 -DA:283,1 -DA:284,1 -DA:285,2 +DA:285,1 DA:287,1 DA:288,1 +DA:289,2 +DA:291,1 DA:292,1 -DA:297,0 -DA:298,0 -DA:299,0 +DA:296,1 DA:301,0 -DA:304,0 -DA:305,1 -DA:306,1 -DA:308,1 +DA:302,0 +DA:303,0 +DA:305,0 +DA:308,0 +DA:309,1 DA:310,1 -DA:313,1 +DA:312,1 DA:314,1 -DA:315,2 -DA:316,1 -DA:325,1 -DA:326,1 -DA:327,1 +DA:317,1 +DA:318,1 +DA:319,2 +DA:320,1 +DA:329,1 +DA:330,1 DA:331,1 -DA:333,1 -DA:334,1 -LF:129 -LH:113 +DA:335,1 +DA:337,1 +DA:338,1 +LF:132 +LH:116 end_of_record SF:lib/src/shared/widgets/item_state_widget/item_empty_state_widget/item_empty_widget.dart DA:7,1 @@ -2879,18 +2963,18 @@ LF:16 LH:15 end_of_record SF:lib/src/features/bookcase_detail/views/bookcase_detail_page.dart -DA:24,0 -DA:29,0 +DA:25,0 DA:30,0 -DA:50,0 -DA:52,0 +DA:31,0 +DA:51,0 DA:53,0 -DA:55,0 -DA:57,0 +DA:54,0 +DA:56,0 DA:58,0 -DA:62,0 -DA:67,0 +DA:59,0 +DA:63,0 DA:68,0 +DA:69,0 DA:70,0 DA:72,0 DA:73,0 @@ -2904,76 +2988,79 @@ DA:82,0 DA:83,0 DA:88,0 DA:89,0 -DA:91,0 -DA:96,0 +DA:90,0 +DA:92,0 +DA:93,0 +DA:94,0 DA:99,0 -DA:100,0 +DA:102,0 DA:103,0 -DA:104,0 -DA:105,0 DA:106,0 -DA:110,0 -DA:111,0 -DA:116,0 -DA:126,0 -DA:128,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:113,0 +DA:114,0 +DA:119,0 DA:129,0 -DA:130,0 DA:133,0 +DA:134,0 DA:135,0 -DA:139,0 +DA:138,0 DA:140,0 -DA:141,0 -DA:142,0 -DA:149,0 -DA:150,0 -DA:153,0 +DA:144,0 +DA:145,0 +DA:146,0 +DA:147,0 DA:154,0 DA:155,0 DA:158,0 +DA:159,0 DA:161,0 DA:164,0 -DA:165,0 -DA:170,0 +DA:168,0 +DA:171,0 DA:172,0 -DA:173,0 -DA:174,0 -DA:175,0 -DA:176,0 -DA:178,0 -DA:184,0 -DA:186,0 -DA:187,0 -DA:188,0 -DA:189,0 -DA:190,0 -DA:192,0 +DA:177,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:185,0 +DA:191,0 DA:193,0 DA:194,0 DA:195,0 DA:196,0 -DA:198,0 +DA:197,0 DA:199,0 DA:200,0 DA:201,0 DA:202,0 DA:203,0 DA:205,0 -DA:211,0 -DA:216,0 +DA:206,0 +DA:207,0 +DA:208,0 +DA:209,0 +DA:210,0 +DA:212,0 DA:218,0 -DA:219,0 -DA:220,0 -DA:221,0 -DA:222,0 DA:223,0 -DA:224,0 DA:225,0 DA:226,0 DA:227,0 +DA:228,0 +DA:229,0 +DA:230,0 +DA:231,0 +DA:232,0 +DA:233,0 DA:234,0 -DA:235,0 -LF:94 +DA:241,0 +DA:242,0 +LF:97 LH:0 end_of_record SF:lib/src/shared/widgets/bookcase_widget/bookcase_widget.dart @@ -3076,7 +3163,7 @@ end_of_record SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart DA:12,1 DA:21,1 -DA:33,1 +DA:34,1 LF:3 LH:3 end_of_record @@ -3087,107 +3174,116 @@ LF:2 LH:2 end_of_record SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart -DA:15,1 -DA:18,2 -DA:19,2 +DA:17,1 DA:20,2 -DA:23,1 -DA:28,2 +DA:21,2 +DA:22,2 +DA:25,1 DA:30,2 -DA:32,1 -DA:33,1 +DA:32,2 DA:34,1 -DA:42,1 -DA:43,2 -DA:46,1 -DA:47,2 +DA:35,1 +DA:36,1 +DA:44,1 +DA:45,2 DA:48,1 -DA:49,4 -DA:56,1 -DA:57,1 +DA:49,2 +DA:50,1 +DA:51,4 DA:58,1 -DA:61,1 -DA:66,1 -DA:67,2 -DA:68,2 +DA:59,1 +DA:60,1 +DA:63,1 +DA:68,1 DA:69,1 -DA:70,2 +DA:70,1 DA:71,1 +DA:72,1 DA:75,1 -DA:80,2 -DA:82,1 -DA:84,2 -DA:85,2 -DA:86,1 -DA:87,1 -DA:90,1 -DA:91,1 +DA:76,1 +DA:77,1 +DA:79,1 +DA:85,1 +DA:90,2 DA:92,1 -DA:93,2 -DA:100,2 +DA:94,2 +DA:95,2 +DA:96,1 +DA:97,1 +DA:100,1 DA:101,1 -DA:102,2 -DA:103,2 -DA:104,1 -DA:105,2 -DA:106,1 -LF:44 -LH:44 +DA:102,1 +DA:104,2 +DA:111,2 +DA:112,1 +DA:113,1 +DA:114,1 +DA:115,1 +DA:116,1 +DA:119,1 +DA:120,1 +DA:121,1 +DA:123,1 +LF:50 +LH:50 end_of_record SF:lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart -DA:16,0 -DA:21,0 -DA:23,0 -DA:31,0 -DA:33,0 +DA:17,0 +DA:22,0 +DA:24,0 +DA:32,0 DA:34,0 DA:35,0 DA:36,0 -DA:39,0 +DA:37,0 DA:40,0 -DA:43,0 -DA:48,0 +DA:41,0 +DA:44,0 DA:49,0 -DA:51,0 +DA:50,0 DA:52,0 -DA:57,0 +DA:53,0 DA:58,0 -DA:61,0 +DA:59,0 DA:62,0 DA:63,0 DA:64,0 -DA:70,0 +DA:65,0 DA:71,0 +DA:72,0 DA:73,0 -DA:78,0 +DA:75,0 +DA:76,0 +DA:77,0 DA:82,0 -DA:83,0 -DA:84,0 +DA:86,0 DA:87,0 -DA:89,0 +DA:88,0 +DA:91,0 DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -DA:103,0 -DA:104,0 -DA:105,0 -DA:106,0 -DA:111,0 -DA:113,0 -DA:114,0 -DA:116,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:110,0 +DA:115,0 DA:117,0 DA:118,0 -DA:119,0 DA:120,0 DA:121,0 +DA:122,0 DA:123,0 DA:124,0 DA:125,0 +DA:127,0 DA:128,0 -DA:131,0 -LF:52 +DA:129,0 +DA:132,0 +DA:134,0 +LF:55 LH:0 end_of_record SF:lib/src/features/bookcase_books_insertion/widgets/bookcase_books_insertion_loaded_state_widget/bookcase_books_insertion_loaded_state.dart @@ -3269,64 +3365,70 @@ LF:17 LH:0 end_of_record SF:lib/src/features/bookcase_detail/bloc/bookcase_detail_bloc.dart -DA:16,1 -DA:19,2 +DA:17,1 DA:20,2 DA:21,2 DA:22,2 -DA:25,1 -DA:30,2 -DA:32,2 -DA:33,1 +DA:23,2 +DA:26,1 +DA:31,2 +DA:33,2 DA:34,1 DA:35,1 -DA:36,2 -DA:39,1 -DA:40,1 -DA:41,1 -DA:46,1 -DA:49,2 -DA:52,3 -DA:54,2 -DA:55,2 -DA:60,2 -DA:61,1 -DA:62,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,2 DA:63,1 -DA:64,2 -DA:67,1 -DA:68,1 -DA:69,1 +DA:64,1 +DA:72,2 +DA:73,1 DA:74,1 -DA:79,2 +DA:75,1 +DA:77,1 DA:81,1 -DA:83,2 -DA:84,2 -DA:85,2 -DA:87,2 -DA:88,2 -DA:89,2 -DA:94,2 -DA:95,1 -DA:96,1 +DA:82,1 +DA:84,1 +DA:90,1 +DA:95,2 DA:97,1 -DA:98,2 +DA:99,2 +DA:100,2 DA:101,1 DA:102,1 -DA:103,1 -DA:108,1 -DA:112,1 -DA:113,1 -DA:115,1 -DA:116,2 +DA:105,2 +DA:106,1 +DA:107,1 +DA:110,2 +DA:117,2 +DA:118,1 +DA:119,1 DA:120,1 -DA:122,2 -DA:123,2 -DA:124,1 +DA:121,1 +DA:122,1 +DA:126,1 DA:127,1 -DA:130,2 -LF:56 -LH:56 +DA:129,1 +DA:135,1 +DA:139,1 +DA:140,1 +DA:142,1 +DA:143,2 +DA:147,1 +DA:149,2 +DA:150,2 +DA:151,1 +DA:154,1 +DA:157,2 +LF:62 +LH:62 end_of_record SF:lib/src/features/bookcase_detail/bloc/bookcase_detail_event.dart DA:9,1 @@ -3337,7 +3439,7 @@ LH:3 end_of_record SF:lib/src/features/bookcase_detail/bloc/bookcase_detail_state.dart DA:13,1 -DA:21,1 +DA:22,1 LF:2 LH:2 end_of_record @@ -3463,50 +3565,58 @@ LF:2 LH:2 end_of_record SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart -DA:14,1 -DA:16,2 -DA:17,2 +DA:16,1 DA:18,2 -DA:21,1 -DA:26,2 -DA:28,1 -DA:29,1 +DA:19,2 +DA:20,2 +DA:23,1 +DA:28,2 DA:30,1 DA:31,1 -DA:35,2 -DA:37,1 -DA:38,2 -DA:43,2 -DA:45,1 -DA:46,2 -DA:47,2 -DA:48,1 -DA:49,2 -DA:50,1 -DA:54,1 -DA:59,2 -DA:61,1 -DA:62,1 +DA:32,1 +DA:33,1 +DA:36,2 +DA:40,1 +DA:41,1 +DA:42,1 +DA:51,1 +DA:52,1 +DA:56,1 +DA:57,1 +DA:58,1 +DA:60,1 DA:63,1 DA:64,1 DA:65,1 -DA:68,2 -DA:72,1 +DA:67,1 DA:73,1 -DA:74,1 -DA:81,2 +DA:78,2 +DA:80,1 +DA:81,1 +DA:82,1 DA:83,1 -DA:84,2 -DA:85,2 -DA:86,1 +DA:84,1 DA:87,2 -DA:88,1 -LF:38 -LH:38 +DA:91,1 +DA:92,1 +DA:93,1 +DA:102,1 +DA:103,1 +DA:107,1 +DA:108,1 +DA:109,1 +DA:110,1 +DA:111,1 +DA:114,1 +DA:115,1 +DA:116,1 +DA:118,1 +LF:46 +LH:46 end_of_record SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart DA:11,2 -DA:17,2 +DA:18,2 LF:2 LH:2 end_of_record @@ -3521,69 +3631,73 @@ LF:1 LH:1 end_of_record SF:lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc.dart -DA:15,1 -DA:18,2 +DA:16,1 DA:19,2 -DA:22,1 -DA:27,2 -DA:29,1 -DA:30,2 -DA:32,1 -DA:33,2 -DA:37,1 -DA:39,2 +DA:20,2 +DA:23,1 +DA:28,2 +DA:30,1 +DA:31,2 +DA:33,1 +DA:34,2 +DA:38,1 DA:40,2 -DA:41,1 -DA:44,2 -DA:45,1 -DA:49,1 -DA:50,0 -DA:54,2 -DA:55,1 +DA:41,2 +DA:42,1 +DA:45,2 +DA:46,1 +DA:50,1 +DA:51,0 +DA:55,2 DA:56,1 DA:57,1 -DA:58,2 -DA:61,1 -DA:62,1 -DA:63,1 -LF:25 -LH:24 +DA:58,1 +DA:59,1 +DA:60,1 +DA:64,1 +DA:65,1 +DA:67,1 +LF:26 +LH:25 end_of_record SF:lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_state.dart DA:13,1 -DA:21,1 +DA:22,1 LF:2 LH:2 -end_of_record -SF:lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart -DA:16,1 -DA:19,2 -DA:20,2 -DA:23,1 -DA:28,2 -DA:30,2 -DA:32,1 -DA:33,2 -DA:37,1 -DA:39,2 -DA:40,1 -DA:43,1 +end_of_record +SF:lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart +DA:17,1 +DA:20,2 +DA:21,2 +DA:24,1 +DA:29,2 +DA:31,2 +DA:33,1 +DA:34,2 +DA:38,1 +DA:40,2 +DA:41,1 DA:44,1 -DA:45,2 -DA:50,2 -DA:57,2 -DA:60,1 -DA:65,1 +DA:45,1 +DA:53,2 +DA:60,2 +DA:63,1 DA:68,1 -DA:69,0 -DA:73,2 -DA:74,1 -DA:75,2 +DA:71,1 +DA:72,0 DA:76,2 DA:77,1 -DA:78,3 -LF:26 -LH:25 +DA:78,1 +DA:79,1 +DA:80,1 +DA:81,1 +DA:84,1 +DA:85,1 +DA:86,1 +DA:88,1 +LF:29 +LH:28 end_of_record SF:lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_state.dart DA:12,1 @@ -3593,30 +3707,35 @@ LH:2 end_of_record SF:lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_state.dart DA:12,1 -DA:20,1 +DA:21,1 LF:2 LH:2 end_of_record SF:lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart -DA:13,1 -DA:14,2 +DA:14,1 DA:15,2 -DA:18,1 -DA:22,2 +DA:16,2 +DA:19,1 DA:24,2 -DA:26,1 -DA:27,2 -DA:32,5 -DA:34,1 -DA:35,2 -DA:39,2 -DA:40,1 -DA:41,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:34,4 +DA:35,1 +DA:37,1 +DA:38,2 DA:42,2 DA:43,1 -DA:44,3 -LF:17 -LH:17 +DA:44,1 +DA:45,1 +DA:46,1 +DA:47,1 +DA:50,1 +DA:51,1 +DA:52,1 +DA:54,1 +LF:22 +LH:22 end_of_record SF:lib/src/features/contacts_picker/bloc/contacts_picker_state.dart DA:12,1 @@ -3665,52 +3784,62 @@ LF:16 LH:1 end_of_record SF:lib/src/features/loan/bloc/loan_bloc.dart -DA:17,1 -DA:21,2 +DA:18,1 DA:22,2 DA:23,2 -DA:26,1 -DA:31,2 -DA:33,2 -DA:35,1 -DA:36,2 -DA:40,1 -DA:41,0 +DA:24,2 +DA:27,1 +DA:32,2 +DA:34,2 +DA:36,1 +DA:37,2 +DA:41,1 DA:42,0 DA:43,0 DA:44,0 -DA:48,1 -DA:53,2 -DA:55,2 -DA:56,1 +DA:45,0 +DA:46,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:53,0 DA:59,1 -DA:60,2 -DA:64,1 -DA:65,1 -DA:66,4 +DA:64,2 +DA:66,2 DA:67,1 -DA:68,3 -DA:72,1 +DA:70,1 +DA:71,2 +DA:75,1 DA:76,1 -DA:78,2 +DA:77,1 +DA:78,1 DA:79,1 DA:80,1 -DA:81,3 -DA:86,2 +DA:83,1 +DA:84,1 +DA:85,1 DA:87,1 -DA:90,2 -DA:91,1 -DA:94,1 -DA:96,1 +DA:93,1 DA:97,1 +DA:99,2 +DA:100,1 DA:101,1 -DA:104,2 -LF:40 -LH:36 +DA:102,1 +DA:110,2 +DA:111,1 +DA:114,2 +DA:115,1 +DA:118,1 +DA:120,1 +DA:121,1 +DA:125,1 +DA:128,2 +LF:50 +LH:41 end_of_record SF:lib/src/features/loan/bloc/loan_state.dart DA:14,1 -DA:20,1 +DA:21,1 LF:2 LH:2 end_of_record @@ -3752,7 +3881,7 @@ LH:0 end_of_record SF:lib/src/features/loan_detail/bloc/loan_detail_state.dart DA:10,1 -DA:20,1 +DA:21,1 LF:2 LH:2 end_of_record @@ -3763,86 +3892,95 @@ LF:2 LH:2 end_of_record SF:lib/src/features/loan_detail/bloc/loan_detail_bloc.dart -DA:19,1 -DA:24,2 +DA:20,1 DA:25,2 DA:26,2 -DA:29,1 -DA:34,2 -DA:36,3 +DA:27,2 +DA:30,1 +DA:35,2 DA:37,3 DA:38,3 -DA:40,1 -DA:43,1 +DA:39,3 +DA:41,1 DA:44,1 -DA:47,1 +DA:45,1 DA:48,1 -DA:52,1 +DA:49,1 DA:53,1 -DA:54,3 +DA:54,1 +DA:55,1 +DA:56,1 DA:57,1 -DA:58,2 -DA:63,1 -DA:68,2 -DA:70,3 -DA:71,2 -DA:72,1 -DA:74,1 -DA:75,1 -DA:76,1 -DA:82,3 +DA:61,1 +DA:62,1 +DA:64,1 +DA:70,1 +DA:75,2 +DA:77,3 +DA:78,2 +DA:79,1 +DA:83,1 DA:84,1 DA:85,1 -DA:86,1 -DA:91,2 -DA:92,1 -DA:93,1 -DA:94,3 +DA:93,3 +DA:95,1 +DA:96,1 DA:97,1 -DA:98,2 -LF:37 -LH:37 +DA:105,2 +DA:106,1 +DA:107,1 +DA:108,1 +DA:109,1 +DA:110,1 +DA:114,1 +DA:115,1 +DA:117,1 +LF:43 +LH:43 end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart -DA:19,1 -DA:23,2 +DA:20,1 DA:24,2 -DA:27,1 -DA:32,2 -DA:34,2 -DA:35,1 -DA:39,1 +DA:25,2 +DA:28,1 +DA:33,2 +DA:35,2 +DA:36,1 DA:40,1 DA:41,1 -DA:49,1 -DA:50,1 +DA:42,1 DA:51,1 DA:52,1 DA:53,1 DA:54,1 -DA:57,2 -DA:59,1 -DA:60,1 +DA:55,1 +DA:56,1 +DA:59,2 DA:61,1 -DA:68,1 -DA:70,1 -DA:71,1 +DA:62,1 +DA:63,1 DA:72,1 -DA:73,1 +DA:74,1 +DA:75,1 DA:76,1 DA:77,1 +DA:80,1 DA:81,1 -DA:82,2 -DA:83,2 -DA:84,1 -DA:85,2 +DA:85,1 DA:86,1 -DA:90,1 -DA:97,1 -DA:101,4 -DA:107,2 -LF:37 -LH:37 +DA:87,1 +DA:88,1 +DA:89,1 +DA:92,1 +DA:93,1 +DA:94,1 +DA:96,1 +DA:103,1 +DA:110,1 +DA:114,4 +DA:120,2 +LF:40 +LH:40 end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_event.dart DA:14,1 @@ -3851,42 +3989,53 @@ LH:1 end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_state.dart DA:10,1 -DA:18,1 +DA:19,1 LF:2 LH:2 end_of_record SF:lib/src/features/my_books/bloc/my_books_state.dart DA:12,1 -DA:20,1 +DA:21,1 LF:2 LH:2 end_of_record SF:lib/src/features/my_books/bloc/my_books_bloc.dart -DA:13,3 -DA:14,2 +DA:14,3 DA:15,2 -DA:18,1 -DA:23,2 -DA:25,2 -DA:27,1 -DA:28,2 -DA:32,2 -DA:33,1 -DA:34,4 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,2 +DA:34,1 DA:35,1 -DA:36,3 -DA:40,1 -DA:45,2 -DA:47,3 -DA:49,1 -DA:50,2 -DA:54,2 -DA:55,1 -DA:56,4 -DA:57,1 -DA:58,3 -LF:23 -LH:23 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,1 +DA:63,2 +DA:67,2 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:79,1 +LF:34 +LH:34 end_of_record SF:lib/src/features/my_books/bloc/my_books_event.dart DA:10,1 @@ -4168,30 +4317,32 @@ LF:1 LH:1 end_of_record SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart -DA:18,1 -DA:23,2 +DA:19,1 DA:24,2 -DA:27,1 -DA:32,2 -DA:34,2 +DA:25,2 +DA:28,1 +DA:33,2 DA:35,2 DA:36,2 DA:37,2 -DA:39,1 +DA:38,2 DA:40,1 -DA:47,1 +DA:41,1 DA:48,1 DA:49,1 -DA:50,2 +DA:50,1 +DA:51,1 DA:52,1 -DA:53,1 -DA:54,2 -LF:18 -LH:18 +DA:55,1 +DA:56,1 +DA:57,1 +DA:59,1 +LF:20 +LH:20 end_of_record SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart DA:13,1 -DA:24,1 +DA:25,1 LF:2 LH:2 end_of_record @@ -4308,48 +4459,58 @@ LH:1 end_of_record SF:lib/src/features/readings/bloc/readings_state.dart DA:14,1 -DA:20,1 +DA:21,1 LF:2 LH:2 end_of_record SF:lib/src/features/readings/bloc/readings_bloc.dart -DA:15,1 -DA:18,2 +DA:16,1 DA:19,2 DA:20,2 -DA:23,1 -DA:28,2 -DA:30,2 -DA:32,1 -DA:33,2 -DA:37,1 +DA:21,2 +DA:24,1 +DA:29,2 +DA:31,2 +DA:33,1 +DA:34,2 DA:38,1 -DA:39,4 +DA:39,1 DA:40,1 -DA:41,3 -DA:45,1 -DA:50,2 -DA:52,2 -DA:53,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:46,1 +DA:47,1 +DA:48,1 +DA:50,1 DA:56,1 -DA:57,2 -DA:61,1 -DA:62,1 -DA:63,4 +DA:61,2 +DA:63,2 DA:64,1 -DA:65,3 -DA:69,1 +DA:67,1 +DA:68,2 +DA:72,1 DA:73,1 -DA:75,2 +DA:74,1 +DA:75,1 DA:76,1 DA:77,1 -DA:78,3 -DA:82,3 +DA:80,1 +DA:81,1 +DA:82,1 DA:84,1 -DA:89,1 -DA:92,2 -LF:35 -LH:35 +DA:90,1 +DA:94,1 +DA:96,2 +DA:97,1 +DA:98,1 +DA:99,1 +DA:107,3 +DA:109,1 +DA:114,1 +DA:117,2 +LF:45 +LH:45 end_of_record SF:lib/src/features/readings/bloc/readings_event.dart DA:10,1 @@ -4380,52 +4541,54 @@ LF:2 LH:2 end_of_record SF:lib/src/features/readings_detail/bloc/readings_detail_state.dart -DA:14,1 +DA:15,1 LF:1 LH:1 end_of_record SF:lib/src/features/readings_detail/bloc/readings_detail_bloc.dart -DA:16,1 -DA:19,2 +DA:17,1 DA:20,2 DA:21,2 -DA:24,1 -DA:29,2 -DA:31,2 -DA:32,1 -DA:35,1 +DA:22,2 +DA:25,1 +DA:30,2 +DA:32,2 +DA:33,1 DA:36,1 DA:37,1 -DA:42,2 -DA:43,1 -DA:44,1 -DA:45,1 +DA:38,1 DA:46,2 +DA:47,1 +DA:48,1 +DA:49,1 DA:50,1 DA:51,1 -DA:52,1 +DA:55,1 +DA:56,1 DA:58,1 -DA:63,2 -DA:65,2 -DA:66,1 -DA:70,1 -DA:71,1 +DA:64,1 +DA:69,2 +DA:71,2 DA:72,1 -DA:77,2 +DA:76,1 +DA:77,1 DA:78,1 -DA:81,1 -DA:82,1 -DA:83,1 -DA:88,2 -DA:89,1 +DA:86,2 +DA:87,1 DA:90,1 DA:91,1 -DA:92,2 -DA:96,1 -DA:97,1 -DA:98,1 -LF:39 -LH:39 +DA:92,1 +DA:100,2 +DA:101,1 +DA:102,1 +DA:103,1 +DA:104,1 +DA:105,1 +DA:109,1 +DA:110,1 +DA:112,1 +LF:41 +LH:41 end_of_record SF:lib/src/features/readings_insertion/bloc/readings_insertion_event.dart DA:9,1 @@ -4433,42 +4596,45 @@ LF:1 LH:1 end_of_record SF:lib/src/features/readings_insertion/bloc/readings_insertion_state.dart -DA:12,1 +DA:13,1 LF:1 LH:1 end_of_record SF:lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart -DA:16,1 -DA:19,2 +DA:17,1 DA:20,2 -DA:23,1 -DA:28,2 -DA:30,1 -DA:32,2 -DA:33,1 -DA:37,1 +DA:21,2 +DA:24,1 +DA:29,2 +DA:31,1 +DA:33,2 +DA:34,1 DA:38,1 DA:39,1 -DA:47,2 -DA:48,1 +DA:40,1 +DA:50,2 DA:51,1 -DA:52,1 -DA:53,1 -DA:60,2 -DA:61,1 -DA:63,1 -DA:67,1 +DA:54,1 +DA:55,1 +DA:56,1 +DA:65,2 +DA:66,1 DA:68,1 -DA:69,1 -DA:76,2 -DA:77,1 -DA:78,2 -DA:79,2 -DA:80,1 -DA:81,2 -DA:82,1 -LF:29 -LH:29 +DA:72,1 +DA:73,1 +DA:74,1 +DA:83,2 +DA:84,1 +DA:85,1 +DA:86,1 +DA:87,1 +DA:88,1 +DA:91,1 +DA:92,1 +DA:93,1 +DA:95,1 +LF:32 +LH:32 end_of_record SF:lib/src/features/readings_timer/bloc/readings_timer_state.dart DA:12,1 diff --git a/lib/src/core/database/local_database_impl.dart b/lib/src/core/database/local_database_impl.dart index 2e84b518..3a2f9064 100644 --- a/lib/src/core/database/local_database_impl.dart +++ b/lib/src/core/database/local_database_impl.dart @@ -1,6 +1,7 @@ import 'package:bookify/src/shared/constants/database_scripts/database_scripts.dart'; import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:path/path.dart'; import 'package:sqflite/sqflite.dart'; @@ -29,7 +30,12 @@ class LocalDatabaseImpl implements LocalDatabase { version: 1, ); } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -65,7 +71,12 @@ class LocalDatabaseImpl implements LocalDatabase { ); return queryItems; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -95,7 +106,12 @@ class LocalDatabaseImpl implements LocalDatabase { return queryItems; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -115,7 +131,12 @@ class LocalDatabaseImpl implements LocalDatabase { ); return queryItem.first; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -142,7 +163,12 @@ class LocalDatabaseImpl implements LocalDatabase { return queryItems; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -165,7 +191,12 @@ class LocalDatabaseImpl implements LocalDatabase { return queryItems; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -190,7 +221,12 @@ class LocalDatabaseImpl implements LocalDatabase { return queryItems.first; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -209,7 +245,12 @@ class LocalDatabaseImpl implements LocalDatabase { return newId; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -235,7 +276,12 @@ class LocalDatabaseImpl implements LocalDatabase { return rowUpdated; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -247,13 +293,21 @@ class LocalDatabaseImpl implements LocalDatabase { }) async { try { final db = await database; - final queryMap = await db! - .query(table, where: '$column = ?', whereArgs: [columnValue]); + final queryMap = await db!.query( + table, + where: '$column = ?', + whereArgs: [columnValue], + ); final itemFound = queryMap.isNotEmpty; return itemFound; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -272,7 +326,12 @@ class LocalDatabaseImpl implements LocalDatabase { return 0; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -295,7 +354,12 @@ class LocalDatabaseImpl implements LocalDatabase { return 0; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -319,7 +383,12 @@ class LocalDatabaseImpl implements LocalDatabase { return rowCount; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -345,7 +414,12 @@ class LocalDatabaseImpl implements LocalDatabase { return rowCount; } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -355,7 +429,68 @@ class LocalDatabaseImpl implements LocalDatabase { final db = await database; await db!.close(); } on DatabaseException catch (e) { - throw LocalDatabaseException(e.toString()); + throw _toLocalDatabaseMapper(e); + } catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } + + LocalDatabaseException _toLocalDatabaseMapper(DatabaseException e) { + if (e.isNoSuchTableError()) { + return LocalDatabaseException( + LocalDatabaseErrorCode.noSuchTable, + descriptionMessage: e.toString(), + ); + } + if (e.isDuplicateColumnError()) { + return LocalDatabaseException( + LocalDatabaseErrorCode.duplicateColumn, + descriptionMessage: e.toString(), + ); + } + if (e.isSyntaxError()) { + return LocalDatabaseException( + LocalDatabaseErrorCode.syntaxError, + descriptionMessage: e.toString(), + ); + } + if (e.isOpenFailedError()) { + return LocalDatabaseException( + LocalDatabaseErrorCode.openFailed, + descriptionMessage: e.toString(), + ); + } + if (e.isDatabaseClosedError()) { + return LocalDatabaseException( + LocalDatabaseErrorCode.databaseClosed, + descriptionMessage: e.toString(), + ); + } + if (e.isReadOnlyError()) { + return LocalDatabaseException( + LocalDatabaseErrorCode.readOnly, + descriptionMessage: e.toString(), + ); + } + if (e.isUniqueConstraintError()) { + return LocalDatabaseException( + LocalDatabaseErrorCode.uniqueConstraint, + descriptionMessage: e.toString(), + ); + } + if (e.isNotNullConstraintError()) { + return LocalDatabaseException( + LocalDatabaseErrorCode.notNullConstraint, + descriptionMessage: e.toString(), + ); + } + + return LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } diff --git a/lib/src/core/errors/local_database_exception/local_database_exception.dart b/lib/src/core/errors/local_database_exception/local_database_exception.dart index 76071d55..6675ddc1 100644 --- a/lib/src/core/errors/local_database_exception/local_database_exception.dart +++ b/lib/src/core/errors/local_database_exception/local_database_exception.dart @@ -1,8 +1,14 @@ +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; + class LocalDatabaseException implements Exception { - final String message; + final LocalDatabaseErrorCode code; + final String? descriptionMessage; - const LocalDatabaseException(this.message); + const LocalDatabaseException( + this.code, { + this.descriptionMessage, + }); @override - String toString() => message; + String toString() => 'LocalDatabaseException: [$code] $descriptionMessage'; } diff --git a/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart b/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart new file mode 100644 index 00000000..a2df415d --- /dev/null +++ b/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart @@ -0,0 +1,51 @@ +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; +import 'package:localization/localization.dart'; + +// TODO Localizate the messages + +extension LocalDatabaseErrorCodeExtension on LocalDatabaseErrorCode { + String toLocalizedMessage(String? descriptionMessage) { + final messageArg = descriptionMessage ?? '---'; + + return switch (this) { + LocalDatabaseErrorCode.noSuchTable => + 'error-local-database-no-such-table'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.duplicateColumn => + 'error-local-database-duplicate-column'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.syntaxError => + 'error-local-database-syntax-error'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.openFailed => + 'error-local-database-open-failed'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.databaseClosed => + 'error-local-database-database-closed'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.readOnly => 'error-local-database-read-only'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.uniqueConstraint => + 'error-local-database-unique-constraint'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.notNullConstraint => + 'error-local-database-not-null-constraint'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.invalidData => + 'error-local-database-invalid-data'.i18n([ + messageArg, + ]), + LocalDatabaseErrorCode.unknown => 'error-local-database-unknown'.i18n([ + messageArg, + ]), + }; + } +} diff --git a/lib/src/core/repositories/author_repository/authors_repository_impl.dart b/lib/src/core/repositories/author_repository/authors_repository_impl.dart index e2eb5c36..e5c492b2 100644 --- a/lib/src/core/repositories/author_repository/authors_repository_impl.dart +++ b/lib/src/core/repositories/author_repository/authors_repository_impl.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/author_model.dart'; import 'package:bookify/src/core/repositories/author_repository/authors_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class AuthorsRepositoryImpl implements AuthorsRepository { final LocalDatabase _database; @@ -21,8 +22,11 @@ class AuthorsRepositoryImpl implements AuthorsRepository { final authorModel = AuthorModel.fromMap(authorsMap); return authorModel; - } on TypeError { - throw const LocalDatabaseException('Impossível converter o dado do database'); + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), + ); } on LocalDatabaseException { rethrow; } @@ -45,8 +49,11 @@ class AuthorsRepositoryImpl implements AuthorsRepository { final actualAuthorId = authorMap.last['id'] as int; return actualAuthorId; - } on TypeError { - throw const LocalDatabaseException('Impossível converter o dado do database'); + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), + ); } on LocalDatabaseException { rethrow; } diff --git a/lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart b/lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart index 0307b847..99c201e7 100644 --- a/lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart +++ b/lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/shared/constants/database_scripts/database_scripts.d import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/repositories/book_authors_repository/book_authors_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class BookAuthorsRepositoryImpl implements BookAuthorsRepository { final LocalDatabase _database; @@ -21,23 +22,31 @@ class BookAuthorsRepositoryImpl implements BookAuthorsRepository { ); if (bookAuthorsRelationships.last.isEmpty) { - throw const LocalDatabaseException('Impossível buscar os dados'); + throw const LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: 'Impossible to fetch data', + ); } return bookAuthorsRelationships; - } on LocalDatabaseException { - rethrow; + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), + ); } } @override Future insert({required String bookId, required int authorId}) async { try { - final rowInserted = - await _database.insert(table: _bookAuthorsTableName, values: { - 'bookId': bookId, - 'authorId': authorId, - }); + final rowInserted = await _database.insert( + table: _bookAuthorsTableName, + values: { + 'bookId': bookId, + 'authorId': authorId, + }, + ); return rowInserted; } on LocalDatabaseException { diff --git a/lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart b/lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart index a165ce9f..3b7dd7a4 100644 --- a/lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart +++ b/lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/shared/constants/database_scripts/database_scripts.d import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/repositories/book_categories_repository/book_categories_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class BookCategoriesRepositoryImpl implements BookCategoriesRepository { final LocalDatabase _database; @@ -21,23 +22,31 @@ class BookCategoriesRepositoryImpl implements BookCategoriesRepository { ); if (bookCategoriesRelationships.last.isEmpty) { - throw const LocalDatabaseException('Impossível buscar os dados'); + throw const LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: 'Impossible to fetch data', + ); } return bookCategoriesRelationships; - } on LocalDatabaseException { - rethrow; + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), + ); } } @override Future insert({required String bookId, required int categoryId}) async { try { - final rowInserted = - await _database.insert(table: _bookCategoriesTableName, values: { - 'bookId': bookId, - 'categoryId': categoryId, - }); + final rowInserted = await _database.insert( + table: _bookCategoriesTableName, + values: { + 'bookId': bookId, + 'categoryId': categoryId, + }, + ); return rowInserted; } on LocalDatabaseException { diff --git a/lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart b/lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart index 5e89d489..7355e449 100644 --- a/lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart +++ b/lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/shared/constants/database_scripts/database_scripts.d import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/repositories/book_on_case_repository/book_on_case_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class BookOnCaseRepositoryImpl implements BookOnCaseRepository { final LocalDatabase _database; @@ -38,8 +39,11 @@ class BookOnCaseRepositoryImpl implements BookOnCaseRepository { final bookId = bookRelationshipMap['bookId'] as String?; return bookId; - } on TypeError { - throw const LocalDatabaseException('Impossível converter o dado do database'); + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), + ); } on LocalDatabaseException { rethrow; } @@ -48,11 +52,13 @@ class BookOnCaseRepositoryImpl implements BookOnCaseRepository { @override Future insert({required int bookcaseId, required String bookId}) async { try { - final rowInserted = - await _database.insert(table: _bookOnCaseTableName, values: { - 'bookId': bookId, - 'bookcaseId': bookcaseId, - }); + final rowInserted = await _database.insert( + table: _bookOnCaseTableName, + values: { + 'bookId': bookId, + 'bookcaseId': bookcaseId, + }, + ); return rowInserted; } on LocalDatabaseException { diff --git a/lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart b/lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart index 78165af6..f8648983 100644 --- a/lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart +++ b/lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/core/repositories/bookcase_repository/bookcase_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class BookcaseRepositoryImpl implements BookcaseRepository { final LocalDatabase _database; @@ -17,9 +18,10 @@ class BookcaseRepositoryImpl implements BookcaseRepository { final bookcases = bookcasesMap.map(BookcaseModel.fromMap).toList(); return bookcases; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar as estantes no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -37,9 +39,10 @@ class BookcaseRepositoryImpl implements BookcaseRepository { final bookcases = bookcasesMap.map(BookcaseModel.fromMap).toList(); return bookcases; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar as estantes no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -57,9 +60,10 @@ class BookcaseRepositoryImpl implements BookcaseRepository { final bookcase = BookcaseModel.fromMap(bookcaseMap); return bookcase; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar a estante no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; diff --git a/lib/src/core/repositories/books_repository/books_repository_impl.dart b/lib/src/core/repositories/books_repository/books_repository_impl.dart index bd33506f..f52f6820 100644 --- a/lib/src/core/repositories/books_repository/books_repository_impl.dart +++ b/lib/src/core/repositories/books_repository/books_repository_impl.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/repositories/books_repository/books_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class BooksRepositoryImpl implements BooksRepository { final LocalDatabase _database; @@ -16,9 +17,10 @@ class BooksRepositoryImpl implements BooksRepository { final booksMap = await _database.getAll(table: _bookTableName); final booksModel = booksMap.map(BookModel.fromMap).toList(); return booksModel; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível converter o dado do database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -36,9 +38,10 @@ class BooksRepositoryImpl implements BooksRepository { final bookModel = BookModel.fromMap(bookMap); return bookModel; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível converter o dado do database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -70,9 +73,10 @@ class BooksRepositoryImpl implements BooksRepository { final bookImage = imageMap['imageUrl'] as String; return bookImage; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível converter o dado do database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -90,9 +94,10 @@ class BooksRepositoryImpl implements BooksRepository { final books = booksMap.map(BookModel.fromMap).toList(); return books; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar os livros com esse título no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -125,9 +130,10 @@ class BooksRepositoryImpl implements BooksRepository { final bookStatus = BookStatus.fromMap(statusMap['status'] as int); return bookStatus!; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar o status do livro no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -158,9 +164,9 @@ class BooksRepositoryImpl implements BooksRepository { required String id, required int pageCount, }) async { - assert(pageCount > 0, 'pagesCount must be greater than 0'); - try { + assert(pageCount > 0, 'pagesCount must be greater than 0'); + final bookPagesCountUpdate = await _database.update( table: _bookTableName, idColumn: 'id', @@ -171,6 +177,11 @@ class BooksRepositoryImpl implements BooksRepository { return bookPagesCountUpdate; } on LocalDatabaseException { rethrow; + } on AssertionError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), + ); } } diff --git a/lib/src/core/repositories/category_repository/categories_repository_impl.dart b/lib/src/core/repositories/category_repository/categories_repository_impl.dart index 70cd2b92..a5d1536a 100644 --- a/lib/src/core/repositories/category_repository/categories_repository_impl.dart +++ b/lib/src/core/repositories/category_repository/categories_repository_impl.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/repositories/category_repository/categories_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class CategoriesRepositoryImpl implements CategoriesRepository { final LocalDatabase _database; @@ -21,8 +22,11 @@ class CategoriesRepositoryImpl implements CategoriesRepository { final categoryModel = CategoryModel.fromMap(categoryMap); return categoryModel; - } on TypeError { - throw const LocalDatabaseException('Impossível converter o dado do database'); + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), + ); } on LocalDatabaseException { rethrow; } @@ -45,8 +49,11 @@ class CategoriesRepositoryImpl implements CategoriesRepository { final actualAuthorId = categoryMap.last['id'] as int; return actualAuthorId; - } on TypeError { - throw const LocalDatabaseException('Impossível converter o dado do database'); + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), + ); } on LocalDatabaseException { rethrow; } diff --git a/lib/src/core/repositories/loan_repository/loan_repository_impl.dart b/lib/src/core/repositories/loan_repository/loan_repository_impl.dart index 50bbe1ba..1fa9b2c6 100644 --- a/lib/src/core/repositories/loan_repository/loan_repository_impl.dart +++ b/lib/src/core/repositories/loan_repository/loan_repository_impl.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/loan_model.dart'; import 'package:bookify/src/core/repositories/loan_repository/loan_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class LoanRepositoryImpl implements LoanRepository { final LocalDatabase _database; @@ -22,9 +23,10 @@ class LoanRepositoryImpl implements LoanRepository { final loans = loanMap.map(LoanModel.fromMap).toList(); return loans; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar os empréstimos no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -47,9 +49,10 @@ class LoanRepositoryImpl implements LoanRepository { final loans = loanMap.map(LoanModel.fromMap).toList(); return loans; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar os empréstimos no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -67,9 +70,10 @@ class LoanRepositoryImpl implements LoanRepository { final loan = LoanModel.fromMap(loanMap); return loan; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar o empréstimo no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; diff --git a/lib/src/core/repositories/reading_repository/reading_repository_impl.dart b/lib/src/core/repositories/reading_repository/reading_repository_impl.dart index 8134c363..adcfa4e2 100644 --- a/lib/src/core/repositories/reading_repository/reading_repository_impl.dart +++ b/lib/src/core/repositories/reading_repository/reading_repository_impl.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/repositories/reading_repository/reading_repository.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; class ReadingRepositoryImpl implements ReadingRepository { final LocalDatabase _database; @@ -25,9 +26,10 @@ class ReadingRepositoryImpl implements ReadingRepository { final readings = readingMap.map(ReadingModel.fromMap).toList(); return readings; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar as leituras no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -53,9 +55,10 @@ class ReadingRepositoryImpl implements ReadingRepository { final readings = readingMap.map(ReadingModel.fromMap).toList(); return readings; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar as leituras no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; @@ -74,9 +77,10 @@ class ReadingRepositoryImpl implements ReadingRepository { final reading = ReadingModel.fromMap(readingMap); return reading; - } on TypeError { - throw const LocalDatabaseException( - 'Impossível encontrar a leitura no database', + } on TypeError catch (e) { + throw LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: e.toString(), ); } on LocalDatabaseException { rethrow; diff --git a/lib/src/features/book_detail/bloc/book_detail_bloc.dart b/lib/src/features/book_detail/bloc/book_detail_bloc.dart index 5934ec4f..ee08fba5 100644 --- a/lib/src/features/book_detail/bloc/book_detail_bloc.dart +++ b/lib/src/features/book_detail/bloc/book_detail_bloc.dart @@ -1,6 +1,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/helpers/book_status/book_status_extension.dart'; import 'package:bookify/src/core/models/book_model.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; @@ -34,13 +35,15 @@ class BookDetailBloc extends Bloc { } on LocalDatabaseException catch (e) { emit( BookDetailErrorState( - errorMessage: 'Ocorreu um erro no database: ${e.toString()}', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookDetailErrorState( - errorMessage: 'Ocorreu um erro não esperado: ${e.toString()}', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } @@ -59,7 +62,10 @@ class BookDetailBloc extends Bloc { if (bookInserted != 1) { emit( - BookDetailErrorState(errorMessage: 'Erro no inserimento do livro'), + BookDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error on insert book', + ), ); return; } @@ -68,13 +74,15 @@ class BookDetailBloc extends Bloc { } on LocalDatabaseException catch (e) { emit( BookDetailErrorState( - errorMessage: 'Ocorreu um erro no database: ${e.toString()}', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookDetailErrorState( - errorMessage: 'Ocorreu um erro não esperado: ${e.toString()}', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } @@ -92,8 +100,9 @@ class BookDetailBloc extends Bloc { if (bookStatus != BookStatus.library) { emit( BookDetailErrorState( - errorMessage: - 'Impossível remover o livro porque está ${bookStatus.label}.', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'Impossible to remove this book because is: ${bookStatus.label}.', ), ); return; @@ -103,7 +112,8 @@ class BookDetailBloc extends Bloc { if (bookRemoved != 1) { emit( BookDetailErrorState( - errorMessage: 'Erro ao remover o livro', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error on remove book', ), ); return; @@ -113,13 +123,15 @@ class BookDetailBloc extends Bloc { } on LocalDatabaseException catch (e) { emit( BookDetailErrorState( - errorMessage: 'Ocorreu um erro no database: ${e.toString()}', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( BookDetailErrorState( - errorMessage: 'Ocorreu um erro não esperado: ${e.toString()}', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/book_detail/bloc/book_detail_state.dart b/lib/src/features/book_detail/bloc/book_detail_state.dart index a3d08164..fee35846 100644 --- a/lib/src/features/book_detail/bloc/book_detail_state.dart +++ b/lib/src/features/book_detail/bloc/book_detail_state.dart @@ -13,9 +13,11 @@ final class BookDetailLoadedState extends BookDetailState { } final class BookDetailErrorState extends BookDetailState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; BookDetailErrorState({ - required this.errorMessage, + required this.errorCode, + required this.errorDescriptionMessage, }); } diff --git a/lib/src/features/book_detail/views/book_detail_page.dart b/lib/src/features/book_detail/views/book_detail_page.dart index 8e885d23..dae06035 100644 --- a/lib/src/features/book_detail/views/book_detail_page.dart +++ b/lib/src/features/book_detail/views/book_detail_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/book_detail/bloc/book_detail_bloc.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/services/app_services/launcher_service/launcher_service.dart'; @@ -124,13 +125,16 @@ class _BookDetailPageState extends State { _isCallVerifyBookEvent = false; break; - case BookDetailErrorState(errorMessage: final message): + case BookDetailErrorState( + :final errorCode, + :final errorDescriptionMessage, + ): // enable the click on ElevatedButton. _canClickToInsertOrRemoveButton = true; SnackbarService.showSnackBar( context, - message, + errorCode.toLocalizedMessage(errorDescriptionMessage), SnackBarType.error, ); break; diff --git a/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart b/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart index 2286e9d5..187f6587 100644 --- a/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart +++ b/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart @@ -1,5 +1,6 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'book_on_bookcase_detail_event.dart'; @@ -35,11 +36,16 @@ class BookOnBookcaseDetailBloc } on LocalDatabaseException catch (e) { emit( BookOnBookcaseDetailErrorState( - errorMessage: 'Erro no database: ${e.message}'), + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), ); } on Exception catch (e) { emit( - BookOnBookcaseDetailErrorState(errorMessage: 'Erro inesperado: $e'), + BookOnBookcaseDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } @@ -59,7 +65,10 @@ class BookOnBookcaseDetailBloc if (deletedBook != 1) { emit( BookOnBookcaseDetailErrorState( - errorMessage: 'Erro ao deletar o livro'), + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'Failed to delete the book from the bookcase. Please try again.', + ), ); return; } @@ -68,11 +77,16 @@ class BookOnBookcaseDetailBloc } on LocalDatabaseException catch (e) { emit( BookOnBookcaseDetailErrorState( - errorMessage: 'Erro no database: ${e.message}'), + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), ); } on Exception catch (e) { emit( - BookOnBookcaseDetailErrorState(errorMessage: 'Erro inesperado: $e'), + BookOnBookcaseDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } diff --git a/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart b/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart index acb384fe..3e501611 100644 --- a/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart +++ b/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart @@ -17,9 +17,11 @@ final class BookOnBookcaseDetailDeletedState extends BookOnBookcaseDetailState {} final class BookOnBookcaseDetailErrorState extends BookOnBookcaseDetailState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; BookOnBookcaseDetailErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart b/lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart index ff636f4f..76566fb9 100644 --- a/lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart +++ b/lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart @@ -1,4 +1,5 @@ import 'package:bookify/src/core/helpers/book_status/book_status_extension.dart'; +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/book_detail/views/book_detail_page.dart'; import 'package:bookify/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart'; import 'package:bookify/src/features/book_on_bookcase_detail/views/widgets/widgets.dart'; @@ -74,11 +75,11 @@ class _BookOnBookcaseDetailPageState extends State { _canPopPage = false; }); - final errorMessage = state.errorMessage; - SnackbarService.showSnackBar( context, - 'error-snackbar'.i18n([errorMessage]), + 'error-snackbar'.i18n([ + state.errorCode.toLocalizedMessage(state.errorDescriptionMessage), + ]), SnackBarType.error, ); diff --git a/lib/src/features/bookcase/bloc/bookcase_bloc.dart b/lib/src/features/bookcase/bloc/bookcase_bloc.dart index 2952d329..7591d760 100644 --- a/lib/src/features/bookcase/bloc/bookcase_bloc.dart +++ b/lib/src/features/bookcase/bloc/bookcase_bloc.dart @@ -1,6 +1,7 @@ import 'package:bookify/src/core/dtos/bookcase_dto.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; @@ -31,9 +32,19 @@ class BookcaseBloc extends Bloc { await _getAllBookcases(emit); } on LocalDatabaseException catch (e) { - emit(BookcaseErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + BookcaseErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(BookcaseErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + BookcaseErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -46,9 +57,19 @@ class BookcaseBloc extends Bloc { await _findBookcaseByName(emit, event.searchQueryName); } on LocalDatabaseException catch (e) { - emit(BookcaseErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + BookcaseErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(BookcaseErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + BookcaseErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -63,12 +84,16 @@ class BookcaseBloc extends Bloc { for (var bookcaseDto in selectedList) { int bookcaseDeletedRow = await _bookcaseService.deleteBookcase( - bookcaseId: bookcaseDto.bookcase.id!); + bookcaseId: bookcaseDto.bookcase.id!, + ); if (bookcaseDeletedRow == -1) { emit( BookcaseErrorState( - errorMessage: 'Não foi possível deletar a estante'), + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'Failed to delete the bookcase ${bookcaseDto.bookcase.name}.', + ), ); return; } @@ -76,9 +101,19 @@ class BookcaseBloc extends Bloc { await _getAllBookcases(emit); } on LocalDatabaseException catch (e) { - emit(BookcaseErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + BookcaseErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(BookcaseErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + BookcaseErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -94,7 +129,9 @@ class BookcaseBloc extends Bloc { } Future _findBookcaseByName( - Emitter emit, String name) async { + Emitter emit, + String name, + ) async { final bookcases = await _bookcaseService.getBookcasesByName(name: name); if (bookcases.isEmpty) { @@ -114,7 +151,10 @@ class BookcaseBloc extends Bloc { for (BookcaseModel bookcase in bookcases) { if (bookcase.id == null) { emit( - BookcaseErrorState(errorMessage: 'Erro inesperado: ${bookcase.id}'), + BookcaseErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Bookcase with null ID found.', + ), ); return; } diff --git a/lib/src/features/bookcase/bloc/bookcase_state.dart b/lib/src/features/bookcase/bloc/bookcase_state.dart index 101a8c43..1a7ea2cd 100644 --- a/lib/src/features/bookcase/bloc/bookcase_state.dart +++ b/lib/src/features/bookcase/bloc/bookcase_state.dart @@ -15,9 +15,11 @@ final class BookcaseEmptyState extends BookcaseState {} final class BookcaseNotFoundState extends BookcaseState {} final class BookcaseErrorState extends BookcaseState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; BookcaseErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/bookcase/views/bookcase_page.dart b/lib/src/features/bookcase/views/bookcase_page.dart index 81f9ecc2..da5419d9 100644 --- a/lib/src/features/bookcase/views/bookcase_page.dart +++ b/lib/src/features/bookcase/views/bookcase_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/bookcase/views/widgets/bookcase_loaded_state_widget/bookcase_loaded_state_widget.dart'; import 'package:bookify/src/features/bookcase_insertion/views/bookcase_insertion_page.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; @@ -82,10 +83,13 @@ class _BookcasePageState extends State { message: 'bookcase-not-found-whit-this-terms'.i18n(), onPressed: _refreshPage, ), - BookcaseErrorState(errorMessage: final message) => + BookcaseErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( key: const Key('BookcaseErrorStateWidget'), - message: message, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; diff --git a/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart b/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart index e743aa42..b3f8862b 100644 --- a/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart +++ b/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart @@ -2,11 +2,13 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'bookcase_books_insertion_event.dart'; part 'bookcase_books_insertion_state.dart'; +//TODO - Remove EmptyState String class BookcaseBooksInsertionBloc extends Bloc { final BookService _bookService; @@ -64,11 +66,19 @@ class BookcaseBooksInsertionBloc ), ); } on LocalDatabaseException catch (e) { - emit(BookcaseBooksInsertionErrorState( - errorMessage: 'Erro no database: ${e.message}')); + emit( + BookcaseBooksInsertionErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(BookcaseBooksInsertionErrorState( - errorMessage: 'Erro inesperado: $e')); + emit( + BookcaseBooksInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -90,7 +100,8 @@ class BookcaseBooksInsertionBloc if (insertedRow == 0) { emit( BookcaseBooksInsertionErrorState( - errorMessage: 'Erro ao inserir o livro ${book.title}', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error on insert book: ${book.title}', ), ); return; @@ -99,11 +110,19 @@ class BookcaseBooksInsertionBloc emit(BookcaseBooksInsertionInsertedState()); } on LocalDatabaseException catch (e) { - emit(BookcaseBooksInsertionErrorState( - errorMessage: 'Erro no database: ${e.message}')); + emit( + BookcaseBooksInsertionErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(BookcaseBooksInsertionErrorState( - errorMessage: 'Erro inesperado: $e')); + emit( + BookcaseBooksInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } } diff --git a/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart b/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart index b0f07fb6..b7425b15 100644 --- a/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart +++ b/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart @@ -28,9 +28,11 @@ final class BookcaseBooksInsertionInsertedState final class BookcaseBooksInsertionErrorState extends BookcaseBooksInsertionState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; BookcaseBooksInsertionErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart b/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart index 21f3635d..b30eda69 100644 --- a/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart +++ b/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/bookcase_books_insertion/widgets/bookcase_books_insertion_loaded_state_widget/bookcase_books_insertion_loaded_state.dart'; import 'package:bookify/src/core/services/app_services/snackbar_service/snackbar_service.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; @@ -48,12 +49,12 @@ class _BookcaseBooksInsertionPageState BookcaseBooksInsertionLoadingState() || BookcaseBooksInsertionInsertedState() => const CenterCircularProgressIndicator(), - BookcaseBooksInsertionEmptyState(:final message) => Center( - child: Text( - message, - textAlign: TextAlign.center, - ), + BookcaseBooksInsertionEmptyState() => Center( + child: Text( + 'Nenhum livro cadastrado. Volte à Página início para cadastrar.', + textAlign: TextAlign.center, ), + ), BookcaseBooksInsertionLoadedState(:final books) => BookcaseBooksInsertionLoadedStateWidget( key: const Key('BookcaseBooksInsertionLoadedStateWidget'), @@ -67,9 +68,12 @@ class _BookcaseBooksInsertionPageState ); }, ), - BookcaseBooksInsertionErrorState(:final errorMessage) => + BookcaseBooksInsertionErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; @@ -114,24 +118,27 @@ class _BookcaseBooksInsertionPageState canPop: _canPop, child: BlocConsumer( - bloc: _bloc, - listener: _handleBookcaseInsertionState, - builder: (context, state) { - return Scaffold( - appBar: AppBar( - centerTitle: true, - title: Text( - 'select-books-title'.i18n(), - style: TextStyle(fontSize: 16), - ), + bloc: _bloc, + listener: _handleBookcaseInsertionState, + builder: (context, state) { + return Scaffold( + appBar: AppBar( + centerTitle: true, + title: Text( + 'select-books-title'.i18n(), + style: TextStyle(fontSize: 16), ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: - _getWidgetOnBookcaseBooksInsertionState(context, state), + ), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: _getWidgetOnBookcaseBooksInsertionState( + context, + state, ), - ); - }), + ), + ); + }, + ), ); } } diff --git a/lib/src/features/bookcase_detail/bloc/bookcase_detail_bloc.dart b/lib/src/features/bookcase_detail/bloc/bookcase_detail_bloc.dart index 10a4f73a..19ced350 100644 --- a/lib/src/features/bookcase_detail/bloc/bookcase_detail_bloc.dart +++ b/lib/src/features/bookcase_detail/bloc/bookcase_detail_bloc.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/foundation.dart'; @@ -33,27 +34,38 @@ class BookcaseDetailBloc } on LocalDatabaseException catch (e) { emit( BookcaseDetailErrorState( - errorMessage: 'Erro no database: ${e.message}'), + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), ); } catch (e) { emit( BookcaseDetailErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e'), + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } Future _deletedBookcase( - DeletedBookcaseEvent event, Emitter emit) async { + DeletedBookcaseEvent event, + Emitter emit, + ) async { try { emit(BookcaseDetailLoadingState()); - final bookcaseDeletedRow = - await _bookcaseService.deleteBookcase(bookcaseId: event.bookcaseId); + final bookcaseDeletedRow = await _bookcaseService.deleteBookcase( + bookcaseId: event.bookcaseId, + ); if (bookcaseDeletedRow == -1) { - emit(BookcaseDetailErrorState( - errorMessage: 'Impossível deletar a estante')); + emit( + BookcaseDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Impossible delete the bookcase', + ), + ); return; } @@ -61,12 +73,16 @@ class BookcaseDetailBloc } on LocalDatabaseException catch (e) { emit( BookcaseDetailErrorState( - errorMessage: 'Erro no database: ${e.message}'), + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), ); } catch (e) { emit( BookcaseDetailErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e'), + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } @@ -82,11 +98,18 @@ class BookcaseDetailBloc for (var book in books) { final rowDeleted = await _bookcaseService.deleteBookcaseRelationship( - bookcaseId: event.bookcaseId, bookId: book.id); + bookcaseId: event.bookcaseId, + bookId: book.id, + ); if (rowDeleted == -1) { - emit(BookcaseDetailErrorState( - errorMessage: 'Impossível deletar o livro: ${book.title}')); + emit( + BookcaseDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'Impossible delete the book: ${book.title}', + ), + ); return; } } @@ -95,12 +118,16 @@ class BookcaseDetailBloc } on LocalDatabaseException catch (e) { emit( BookcaseDetailErrorState( - errorMessage: 'Erro no database: ${e.message}'), + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), ); } catch (e) { emit( BookcaseDetailErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e'), + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } diff --git a/lib/src/features/bookcase_detail/bloc/bookcase_detail_state.dart b/lib/src/features/bookcase_detail/bloc/bookcase_detail_state.dart index 67bddff8..81f88807 100644 --- a/lib/src/features/bookcase_detail/bloc/bookcase_detail_state.dart +++ b/lib/src/features/bookcase_detail/bloc/bookcase_detail_state.dart @@ -16,9 +16,11 @@ final class BookcaseDetailBooksLoadedState extends BookcaseDetailState { final class BookcaseDetailDeletedState extends BookcaseDetailState {} final class BookcaseDetailErrorState extends BookcaseDetailState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; BookcaseDetailErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/bookcase_detail/views/bookcase_detail_page.dart b/lib/src/features/bookcase_detail/views/bookcase_detail_page.dart index b44f47da..c11a742d 100644 --- a/lib/src/features/bookcase_detail/views/bookcase_detail_page.dart +++ b/lib/src/features/bookcase_detail/views/bookcase_detail_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart'; import 'package:bookify/src/features/bookcase_detail/bloc/bookcase_detail_bloc.dart'; import 'package:bookify/src/features/bookcase_detail/widgets/widgets.dart'; @@ -65,13 +66,12 @@ class _BookcaseDetailPageState extends State { ) { return switch (state) { BookcaseDetailLoadingState() || - BookcaseDetailDeletedState() => - const CenterCircularProgressIndicator(), + BookcaseDetailDeletedState() => const CenterCircularProgressIndicator(), BookcaseDetailBooksEmptyState() => ItemEmptyStateWidget( - key: const Key('BookcaseDetailBooksEmptyState'), - label: 'add-new-books-button'.i18n(), - onTap: () async => await _addNewBooksBottomSheet(), - ), + key: const Key('BookcaseDetailBooksEmptyState'), + label: 'add-new-books-button'.i18n(), + onTap: () async => await _addNewBooksBottomSheet(), + ), BookcaseDetailBooksLoadedState(:final books) => BookcaseDetailLoadedStateWidget( books: books, @@ -85,9 +85,12 @@ class _BookcaseDetailPageState extends State { ), ), ), - BookcaseDetailErrorState(:final errorMessage) => + BookcaseDetailErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; @@ -124,7 +127,9 @@ class _BookcaseDetailPageState extends State { /// /// **Note**: If there is an error removing the [_bookcase], the state will always be [BookcaseDetailErrorState]. Future _handleBookcaseDetailsStateListener( - BookcaseDetailState state, BuildContext context) async { + BookcaseDetailState state, + BuildContext context, + ) async { if (state is BookcaseDetailDeletedState) { setState(() { _canPopPage = false; @@ -152,11 +157,13 @@ class _BookcaseDetailPageState extends State { Future _popupMenuOnSelected(String value, BuildContext context) async { if (value == _popupMenuItemsSet.first) { - final result = await Navigator.pushNamed( - context, - BookcaseInsertionPage.routeName, - arguments: _actualBookcase, - ) as List?; + final result = + await Navigator.pushNamed( + context, + BookcaseInsertionPage.routeName, + arguments: _actualBookcase, + ) + as List?; final bookcaseUpdated = result?[1] as BookcaseModel?; diff --git a/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart b/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart index bf593ba0..64ab54db 100644 --- a/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart +++ b/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart @@ -1,12 +1,14 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'bookcase_insertion_event.dart'; part 'bookcase_insertion_state.dart'; +//TODO - Remove SuccessMessage String class BookcaseInsertionBloc extends Bloc { final BookcaseService _bookcaseService; @@ -31,23 +33,40 @@ class BookcaseInsertionBloc color: event.color, ); - final newBookcaseId = - await _bookcaseService.insertBookcase(bookcaseModel: bookcaseModel); + final newBookcaseId = await _bookcaseService.insertBookcase( + bookcaseModel: bookcaseModel, + ); if (newBookcaseId == 0) { - emit(BookcaseInsertionErrorState( - errorMessage: 'Ocorreu um erro ao inserir a estante')); + emit( + BookcaseInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'An error occurred while inserting the bookcase', + ), + ); return; } - emit(BookcaseInsertionInsertedState( - bookcaseInsertionMessage: 'Estante inserida com sucesso')); + emit( + BookcaseInsertionInsertedState( + bookcaseInsertionMessage: 'Estante inserida com sucesso', + ), + ); } on LocalDatabaseException catch (e) { - emit(BookcaseInsertionErrorState( - errorMessage: 'Ocorreu um erro no database: ${e.message}')); + emit( + BookcaseInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(BookcaseInsertionErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e')); + emit( + BookcaseInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -72,20 +91,33 @@ class BookcaseInsertionBloc if (bookcaseRowUpdated < 1) { emit( BookcaseInsertionErrorState( - errorMessage: 'Ocorreu um erro ao atualizar a estante', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'An error occurred while updating the bookcase', ), ); return; } - emit(BookcaseInsertionInsertedState( - bookcaseInsertionMessage: 'Estante atualizada com sucesso')); + emit( + BookcaseInsertionInsertedState( + bookcaseInsertionMessage: 'Estante atualizada com sucesso', + ), + ); } on LocalDatabaseException catch (e) { - emit(BookcaseInsertionErrorState( - errorMessage: 'Ocorreu um erro no database: ${e.message}')); + emit( + BookcaseInsertionErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(BookcaseInsertionErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e')); + emit( + BookcaseInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } } diff --git a/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart b/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart index 460c2396..5d2fba71 100644 --- a/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart +++ b/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart @@ -12,9 +12,11 @@ final class BookcaseInsertionInsertedState extends BookcaseInsertionState { } final class BookcaseInsertionErrorState extends BookcaseInsertionState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; BookcaseInsertionErrorState({ - required this.errorMessage, + required this.errorCode, + required this.errorDescriptionMessage, }); } diff --git a/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart b/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart index 491673b2..1075c08c 100644 --- a/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart +++ b/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart'; import 'package:bookify/src/core/helpers/textfield_unfocus/textfield_unfocus_extension.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; @@ -198,10 +199,13 @@ class _BookcaseInsertionPageState extends State { }, ); break; - case BookcaseInsertionErrorState(:final errorMessage): + case BookcaseInsertionErrorState( + :final errorCode, + :final errorDescriptionMessage, + ): SnackbarService.showSnackBar( context, - errorMessage, + errorCode.toLocalizedMessage(errorDescriptionMessage), SnackBarType.error, ); diff --git a/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc.dart b/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc.dart index 71310d8f..1f28ddb2 100644 --- a/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc.dart +++ b/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'book_on_bookcase_picker_event.dart'; @@ -55,12 +56,16 @@ class BookOnBookcasePickerBloc } on LocalDatabaseException catch (e) { emit( BookOnBookcasePickerErrorState( - errorMessage: 'Erro no database: ${e.message}'), + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), ); } catch (e) { emit( BookOnBookcasePickerErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e'), + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } diff --git a/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_state.dart b/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_state.dart index 9e0ee6f5..6f0fa56c 100644 --- a/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_state.dart +++ b/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_state.dart @@ -16,9 +16,11 @@ final class BookOnBookcasePickerLoadedState extends BookOnBookcasePickerState { } final class BookOnBookcasePickerErrorState extends BookOnBookcasePickerState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; BookOnBookcasePickerErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/views/book_on_bookcase_widget.dart b/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/views/book_on_bookcase_widget.dart index 738b6006..30b8bee6 100644 --- a/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/views/book_on_bookcase_widget.dart +++ b/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/views/book_on_bookcase_widget.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc.dart'; import 'package:bookify/src/features/books_picker/views/widgets/book_selector_widget/book_selector_widget.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; @@ -41,23 +42,28 @@ class _BookOnBookcaseWidgetState extends State { } Widget _getWidgetOnBookOnBookcasePickerState( - BuildContext context, BookOnBookcasePickerState state) { + BuildContext context, + BookOnBookcasePickerState state, + ) { return switch (state) { BookOnBookcasePickerLoadingState() => const CenterCircularProgressIndicator(), BookOnBookcasePickerEmptyState() => Center( - child: Text( - 'empty-bookcase-or-not-contains-books-message'.i18n(), - textAlign: TextAlign.center, - ), + child: Text( + 'empty-bookcase-or-not-contains-books-message'.i18n(), + textAlign: TextAlign.center, ), + ), BookOnBookcasePickerLoadedState(:final books) => BookSelectorWidget( - books: books, - onSelectBook: (book) => Navigator.pop(context, book), - ), - BookOnBookcasePickerErrorState(:final errorMessage) => + books: books, + onSelectBook: (book) => Navigator.pop(context, book), + ), + BookOnBookcasePickerErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; diff --git a/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart b/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart index e6f818b9..3380ea08 100644 --- a/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart +++ b/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'bookcase_picker_event.dart'; @@ -42,7 +43,9 @@ class BookcasePickerBloc if (bookcaseId == null) { emit( BookcasePickerErrorState( - errorMessage: 'Erro inesperado: ${bookcase.id}'), + errorCode: LocalDatabaseErrorCode.invalidData, + errorDescriptionMessage: 'Error: Bookcase not found', + ), ); return; } @@ -72,10 +75,19 @@ class BookcasePickerBloc emit(BookcasePickerLoadedState(bookcasesDto: bookcasesDto)); } on LocalDatabaseException catch (e) { - emit(BookcasePickerErrorState( - errorMessage: 'Erro no database: ${e.message}')); + emit( + BookcasePickerErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(BookcasePickerErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + BookcasePickerErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } } diff --git a/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_state.dart b/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_state.dart index 970ab5d0..ab2a1f7c 100644 --- a/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_state.dart +++ b/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_state.dart @@ -7,14 +7,17 @@ final class BookcasePickerLoadingState extends BookcasePickerState {} final class BookcasePickerEmptyState extends BookcasePickerState {} final class BookcasePickerLoadedState extends BookcasePickerState { - final List bookcasesDto; + final List bookcasesDto; BookcasePickerLoadedState({required this.bookcasesDto}); - } final class BookcasePickerErrorState extends BookcasePickerState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; - BookcasePickerErrorState({required this.errorMessage}); + BookcasePickerErrorState({ + required this.errorCode, + this.errorDescriptionMessage, + }); } diff --git a/lib/src/features/books_picker/views/widgets/bookcase_picker/views/bookcase_picker_widget.dart b/lib/src/features/books_picker/views/widgets/bookcase_picker/views/bookcase_picker_widget.dart index 90ebfe89..34706a22 100644 --- a/lib/src/features/books_picker/views/widgets/bookcase_picker/views/bookcase_picker_widget.dart +++ b/lib/src/features/books_picker/views/widgets/bookcase_picker/views/bookcase_picker_widget.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart'; import 'package:bookify/src/features/books_picker/views/widgets/bookcase_picker/views/widgets/bookcase_picker_loaded_state_widget/bookcase_picker_loaded_state_widget.dart'; import 'package:bookify/src/core/models/book_model.dart'; @@ -34,23 +35,28 @@ class _BookcasePickerWidgetState extends State { } Widget _getWidgetOnBookcasePickerState( - BuildContext context, BookcasePickerState state) { + BuildContext context, + BookcasePickerState state, + ) { return switch (state) { BookcasePickerLoadingState() => const CenterCircularProgressIndicator(), BookcasePickerEmptyState() => Center( - child: Text( - 'no-bookcases-to-add-message'.i18n(), - textAlign: TextAlign.center, - ), + child: Text( + 'no-bookcases-to-add-message'.i18n(), + textAlign: TextAlign.center, ), + ), BookcasePickerLoadedState(:final bookcasesDto) => BookcasePickerLoadedStateWidget( bookcasesDto: bookcasesDto, onSelectBookModel: widget.onSelectBookModel, ), - BookcasePickerErrorState(:final errorMessage) => + BookcasePickerErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; diff --git a/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart b/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart index 2e8028db..94edad19 100644 --- a/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart +++ b/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart @@ -1,6 +1,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'separate_books_picker_event.dart'; @@ -11,13 +12,14 @@ class SeparateBooksPickerBloc final BookService _bookService; SeparateBooksPickerBloc(this._bookService) - : super(SeparateBooksPickerLoadingState()) { + : super(SeparateBooksPickerLoadingState()) { on(_gotAllSeparatedBooksPickerEvent); } Future _gotAllSeparatedBooksPickerEvent( - GotAllSeparatedBooksPickerEvent event, - Emitter emit) async { + GotAllSeparatedBooksPickerEvent event, + Emitter emit, + ) async { try { emit(SeparateBooksPickerLoadingState()); @@ -28,8 +30,9 @@ class SeparateBooksPickerBloc return; } - final bookForPicker = - books.where((book) => book.status == BookStatus.library).toList(); + final bookForPicker = books + .where((book) => book.status == BookStatus.library) + .toList(); if (bookForPicker.isEmpty) { emit(SeparateBooksPickerEmptyState()); @@ -38,10 +41,19 @@ class SeparateBooksPickerBloc emit(SeparateBooksPickerLoadedState(books: bookForPicker)); } on LocalDatabaseException catch (e) { - emit(SeparateBooksPickerErrorState( - errorMessage: 'Erro no database: ${e.message}')); + emit( + SeparateBooksPickerErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(SeparateBooksPickerErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + SeparateBooksPickerErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } } diff --git a/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_state.dart b/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_state.dart index 0e5cc02c..dfc9dc6f 100644 --- a/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_state.dart +++ b/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_state.dart @@ -15,9 +15,11 @@ final class SeparateBooksPickerLoadedState extends SeparateBooksPickerState { } final class SeparateBooksPickerErrorState extends SeparateBooksPickerState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; SeparateBooksPickerErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/books_picker/views/widgets/separate_books_picker/views/separate_books_picker_widget.dart b/lib/src/features/books_picker/views/widgets/separate_books_picker/views/separate_books_picker_widget.dart index c6a64e39..0e6fd72a 100644 --- a/lib/src/features/books_picker/views/widgets/separate_books_picker/views/separate_books_picker_widget.dart +++ b/lib/src/features/books_picker/views/widgets/separate_books_picker/views/separate_books_picker_widget.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/widgets/book_selector_widget/book_selector_widget.dart'; import 'package:bookify/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart'; import 'package:bookify/src/core/models/book_model.dart'; @@ -37,27 +38,32 @@ class _SeparateBooksPickerWidgetState extends State { } Widget _getWidgetOnBookcasePickerState( - BuildContext context, SeparateBooksPickerState state) { + BuildContext context, + SeparateBooksPickerState state, + ) { return switch (state) { SeparateBooksPickerLoadingState() => const CenterCircularProgressIndicator(), SeparateBooksPickerEmptyState() => Center( - child: Padding( - padding: EdgeInsets.all(8.0), - child: Text( - 'no-books-to-add-message'.i18n(), - textAlign: TextAlign.center, - ), + child: Padding( + padding: EdgeInsets.all(8.0), + child: Text( + 'no-books-to-add-message'.i18n(), + textAlign: TextAlign.center, ), ), + ), SeparateBooksPickerLoadedState(:final books) => BookSelectorWidget( - key: const Key('BookSelectorWidget'), - books: books, - onSelectBook: (book) => Navigator.pop(context, book), - ), - SeparateBooksPickerErrorState(:final errorMessage) => + key: const Key('BookSelectorWidget'), + books: books, + onSelectBook: (book) => Navigator.pop(context, book), + ), + SeparateBooksPickerErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; diff --git a/lib/src/features/loan/bloc/loan_bloc.dart b/lib/src/features/loan/bloc/loan_bloc.dart index 57d70a38..37cfca2a 100644 --- a/lib/src/features/loan/bloc/loan_bloc.dart +++ b/lib/src/features/loan/bloc/loan_bloc.dart @@ -4,6 +4,7 @@ import 'package:bookify/src/core/models/loan_model.dart'; import 'package:bookify/src/core/services/app_services/contacts_service/contacts_service.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/loan_services/loan_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'loan_event.dart'; @@ -39,9 +40,19 @@ class LoanBloc extends Bloc { await _mountLoanDto(loans, emit); } on LocalDatabaseException catch (e) { - emit(LoanErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + LoanErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(LoanErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + LoanErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -63,9 +74,19 @@ class LoanBloc extends Bloc { await _mountLoanDto(loans, emit); } on LocalDatabaseException catch (e) { - emit(LoanErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + LoanErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(LoanErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + LoanErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -78,7 +99,10 @@ class LoanBloc extends Bloc { for (LoanModel loan in loans) { if (loan.id == null) { emit( - LoanErrorState(errorMessage: 'Erro inesperado: ${loan.id}'), + LoanErrorState( + errorCode: LocalDatabaseErrorCode.invalidData, + errorDescriptionMessage: 'Error: Loan not found', + ), ); return; } diff --git a/lib/src/features/loan/bloc/loan_state.dart b/lib/src/features/loan/bloc/loan_state.dart index 1bc22d41..e7ff8235 100644 --- a/lib/src/features/loan/bloc/loan_state.dart +++ b/lib/src/features/loan/bloc/loan_state.dart @@ -15,7 +15,11 @@ final class LoanLoadedState extends LoanState { } final class LoanErrorState extends LoanState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; - LoanErrorState({required this.errorMessage}); + LoanErrorState({ + required this.errorCode, + this.errorDescriptionMessage, + }); } diff --git a/lib/src/features/loan/views/loan_page.dart b/lib/src/features/loan/views/loan_page.dart index 57eeb970..bc031ba9 100644 --- a/lib/src/features/loan/views/loan_page.dart +++ b/lib/src/features/loan/views/loan_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/loan/bloc/loan_bloc.dart'; import 'package:bookify/src/features/loan/widgets/loan_loaded_state_widget/loan_loaded_state_widget.dart'; import 'package:bookify/src/features/loan_insertion/views/loan_insertion_page.dart'; @@ -57,33 +58,39 @@ class _LoanPageState extends State { return switch (state) { LoanLoadingState() => const CenterCircularProgressIndicator(), LoanEmptyState() => Center( - child: ItemEmptyStateWidget( - key: const Key('LoanEmptyState'), - label: 'create-new-loan-button'.i18n(), - onTap: () async { - final loanInserted = await Navigator.pushNamed( - context, - LoanInsertionPage.routeName, - ) as bool?; + child: ItemEmptyStateWidget( + key: const Key('LoanEmptyState'), + label: 'create-new-loan-button'.i18n(), + onTap: () async { + final loanInserted = + await Navigator.pushNamed( + context, + LoanInsertionPage.routeName, + ) + as bool?; - if (loanInserted != null && loanInserted) { - _refreshPage(); - } - }, - ), + if (loanInserted != null && loanInserted) { + _refreshPage(); + } + }, ), + ), LoanLoadedState(:final loansDto) => LoanLoadedStateWidget( - key: const Key('LoanLoadedState'), - loansDto: loansDto, - refreshPage: _refreshPage, - ), + key: const Key('LoanLoadedState'), + loansDto: loansDto, + refreshPage: _refreshPage, + ), LoanNotFoundState() => InfoItemStateWidget.withNotFoundState( - message: 'no-loans-found-with-terms'.i18n(), - onPressed: _refreshPage, - ), - LoanErrorState(:final errorMessage) => Center( + message: 'no-loans-found-with-terms'.i18n(), + onPressed: _refreshPage, + ), + LoanErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => + Center( child: InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), ), diff --git a/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart b/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart index 87ff081f..d16e789d 100644 --- a/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart +++ b/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/services/app_services/contacts_service/contacts import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/loan_services/loan_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'loan_detail_event.dart'; @@ -51,11 +52,17 @@ class LoanDetailBloc extends Bloc { ); } on LocalDatabaseException catch (e) { emit( - LoanDetailErrorState(errorMessage: 'Erro no database: ${e.message}'), + LoanDetailErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), ); } catch (e) { emit( - LoanDetailErrorState(errorMessage: 'Ocorreu um erro não esperado: $e'), + LoanDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } @@ -69,12 +76,16 @@ class LoanDetailBloc extends Bloc { await _notificationsService.cancelNotificationById(id: event.loanId); final bookStatusUpdated = await _bookService.updateStatus( - id: event.bookId, status: BookStatus.library); + id: event.bookId, + status: BookStatus.library, + ); if (bookStatusUpdated != 1) { emit( LoanDetailErrorState( - errorMessage: 'Impossível remover o livro do empréstimo'), + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Impossible to remove the book status', + ), ); return; } @@ -83,7 +94,10 @@ class LoanDetailBloc extends Bloc { if (loanRemovedRow != 1) { emit( - LoanDetailErrorState(errorMessage: 'Impossível remover o empréstimo'), + LoanDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Impossible to remove the loan', + ), ); return; } @@ -91,11 +105,17 @@ class LoanDetailBloc extends Bloc { emit(LoanDetailFinishedState()); } on LocalDatabaseException catch (e) { emit( - LoanDetailErrorState(errorMessage: 'Erro no database: ${e.message}'), + LoanDetailErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), ); } catch (e) { emit( - LoanDetailErrorState(errorMessage: 'Ocorreu um erro não esperado: $e'), + LoanDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Ocorreu um erro não esperado: $e', + ), ); } } diff --git a/lib/src/features/loan_detail/bloc/loan_detail_state.dart b/lib/src/features/loan_detail/bloc/loan_detail_state.dart index 09d92892..aab1fae5 100644 --- a/lib/src/features/loan_detail/bloc/loan_detail_state.dart +++ b/lib/src/features/loan_detail/bloc/loan_detail_state.dart @@ -15,7 +15,11 @@ final class LoanDetailLoadedState extends LoanDetailState { final class LoanDetailFinishedState extends LoanDetailState {} final class LoanDetailErrorState extends LoanDetailState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; - LoanDetailErrorState({required this.errorMessage}); + LoanDetailErrorState({ + required this.errorCode, + this.errorDescriptionMessage, + }); } diff --git a/lib/src/features/loan_detail/views/loan_detail_page.dart b/lib/src/features/loan_detail/views/loan_detail_page.dart index 176f14ac..f668ac46 100644 --- a/lib/src/features/loan_detail/views/loan_detail_page.dart +++ b/lib/src/features/loan_detail/views/loan_detail_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/loan_detail/bloc/loan_detail_bloc.dart'; import 'package:bookify/src/features/loan_detail/views/widgets/loan_detail_loaded_widget.dart'; import 'package:bookify/src/core/services/app_services/show_dialog_service/show_dialog_service.dart'; @@ -46,31 +47,33 @@ class _LoanDetailPageState extends State { ) { return switch (state) { LoanDetailLoadingState() || - LoanDetailFinishedState() => - const CenterCircularProgressIndicator(), + LoanDetailFinishedState() => const CenterCircularProgressIndicator(), LoanDetailLoadedState(:final loanDto) => LoanDetailLoadedWidget( - key: const Key('LoanDetailLoadedState'), - loanDto: loanDto, - onPressedButton: () async { - await ShowDialogService.showAlertDialog( - context: context, - title: 'finish-loan-title'.i18n(), - content: 'finish-loan-description'.i18n(), - confirmButtonFunction: () { - _bloc.add( - FinishedLoanDetailEvent( - loanId: loanDto.loanModel.id!, - bookId: loanDto.loanModel.bookId, - ), - ); - Navigator.of(context).pop(); - }, - ); - }, - ), - LoanDetailErrorState(:final errorMessage) => + key: const Key('LoanDetailLoadedState'), + loanDto: loanDto, + onPressedButton: () async { + await ShowDialogService.showAlertDialog( + context: context, + title: 'finish-loan-title'.i18n(), + content: 'finish-loan-description'.i18n(), + confirmButtonFunction: () { + _bloc.add( + FinishedLoanDetailEvent( + loanId: loanDto.loanModel.id!, + bookId: loanDto.loanModel.bookId, + ), + ); + Navigator.of(context).pop(); + }, + ); + }, + ), + LoanDetailErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; diff --git a/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart b/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart index 75171cbf..6fa5d8d6 100644 --- a/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart +++ b/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart @@ -6,6 +6,7 @@ import 'package:bookify/src/core/models/custom_notification_model.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/loan_services/loan_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'loan_insertion_event.dart'; @@ -39,8 +40,9 @@ class LoanInsertionBloc extends Bloc { if (bookUpdatedStatus < 1) { emit( LoanInsertionErrorState( - errorMessage: - 'Ocorreu um erro ao adicionar o livro ao empréstimo. Verifique se o livro já não foi emprestado ou em lista de leitura', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'An error occurred while updating the book status to loaned. Verify is already loaned or if the book exists.', ), ); return; @@ -59,7 +61,9 @@ class LoanInsertionBloc extends Bloc { if (loanId < 1) { emit( LoanInsertionErrorState( - errorMessage: 'Ocorreu um erro ao criar o empréstimo', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'An error occurred while creating the loan', ), ); return; @@ -79,14 +83,23 @@ class LoanInsertionBloc extends Bloc { ), ); } on LocalDatabaseException catch (e) { - emit(LoanInsertionErrorState( - errorMessage: 'Ocorreu um erro no database: ${e.message}')); + emit( + LoanInsertionErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(LoanInsertionErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e')); + emit( + LoanInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } + // TODO Create a localizated notification message Future _createNotification( int loanId, String contactName, diff --git a/lib/src/features/loan_insertion/bloc/loan_insertion_state.dart b/lib/src/features/loan_insertion/bloc/loan_insertion_state.dart index 300ec540..8fd54610 100644 --- a/lib/src/features/loan_insertion/bloc/loan_insertion_state.dart +++ b/lib/src/features/loan_insertion/bloc/loan_insertion_state.dart @@ -13,9 +13,11 @@ final class LoanInsertionInsertedState extends LoanInsertionState { } final class LoanInsertionErrorState extends LoanInsertionState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; LoanInsertionErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/loan_insertion/views/loan_insertion_page.dart b/lib/src/features/loan_insertion/views/loan_insertion_page.dart index d0bde1b2..702f175a 100644 --- a/lib/src/features/loan_insertion/views/loan_insertion_page.dart +++ b/lib/src/features/loan_insertion/views/loan_insertion_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/books_picker_page.dart'; import 'package:bookify/src/features/contacts_picker/views/contacts_picker_page.dart'; import 'package:bookify/src/features/loan_insertion/bloc/loan_insertion_bloc.dart'; @@ -241,8 +242,8 @@ class _LoanInsertionPageState extends State { break; case LoanInsertionInsertedState( - loanInsertionMessage: final successMessage, - ): + loanInsertionMessage: final successMessage, + ): SnackbarService.showSnackBar( context, successMessage, @@ -257,10 +258,13 @@ class _LoanInsertionPageState extends State { }, ); break; - case LoanInsertionErrorState(:final errorMessage): + case LoanInsertionErrorState( + :final errorCode, + :final errorDescriptionMessage, + ): SnackbarService.showSnackBar( context, - errorMessage, + errorCode.toLocalizedMessage(errorDescriptionMessage), SnackBarType.error, ); diff --git a/lib/src/features/my_books/bloc/my_books_bloc.dart b/lib/src/features/my_books/bloc/my_books_bloc.dart index 10a64e04..66761b90 100644 --- a/lib/src/features/my_books/bloc/my_books_bloc.dart +++ b/lib/src/features/my_books/bloc/my_books_bloc.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'my_books_event.dart'; @@ -31,9 +32,19 @@ class MyBooksBloc extends Bloc { emit(MyBooksLoadedState(books: books)); } on LocalDatabaseException catch (e) { - emit(MyBooksErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + MyBooksErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(MyBooksErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + MyBooksErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -44,7 +55,9 @@ class MyBooksBloc extends Bloc { try { emit(MyBooksLoadingState()); - final books = await _bookService.getBooksByTitle(title: event.searchQuery); + final books = await _bookService.getBooksByTitle( + title: event.searchQuery, + ); if (books.isEmpty) { emit(MyBooksNotFoundState()); @@ -53,9 +66,19 @@ class MyBooksBloc extends Bloc { emit(MyBooksLoadedState(books: books)); } on LocalDatabaseException catch (e) { - emit(MyBooksErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + MyBooksErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(MyBooksErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + MyBooksErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } } diff --git a/lib/src/features/my_books/bloc/my_books_state.dart b/lib/src/features/my_books/bloc/my_books_state.dart index 333b6987..9e91093d 100644 --- a/lib/src/features/my_books/bloc/my_books_state.dart +++ b/lib/src/features/my_books/bloc/my_books_state.dart @@ -15,7 +15,11 @@ final class MyBooksLoadedState extends MyBooksState { final class MyBooksNotFoundState extends MyBooksState {} final class MyBooksErrorState extends MyBooksState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; - MyBooksErrorState({required this.errorMessage}); + MyBooksErrorState({ + required this.errorCode, + required this.errorDescriptionMessage, + }); } diff --git a/lib/src/features/my_books/views/my_books_page.dart b/lib/src/features/my_books/views/my_books_page.dart index e6cfb5f6..291bfd4f 100644 --- a/lib/src/features/my_books/views/my_books_page.dart +++ b/lib/src/features/my_books/views/my_books_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/book_detail/views/book_detail_page.dart'; import 'package:bookify/src/features/my_books/bloc/my_books_bloc.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; @@ -52,28 +53,31 @@ class _MyBooksPageState extends State { return switch (state) { MyBooksLoadingState() => const CenterCircularProgressIndicator(), MyBooksEmptyState() => Center( - child: SizedBox( - child: Text('no-books-saved-message'.i18n()), - ), + child: SizedBox( + child: Text('no-books-saved-message'.i18n()), ), + ), MyBooksLoadedState(:final books) => BooksGridView( - books: books, - onTap: (book) async { - await Navigator.pushNamed( - context, - BookDetailPage.routeName, - arguments: book, - ); - _refreshPage(); - }, - ), + books: books, + onTap: (book) async { + await Navigator.pushNamed( + context, + BookDetailPage.routeName, + arguments: book, + ); + _refreshPage(); + }, + ), MyBooksNotFoundState() => InfoItemStateWidget.withNotFoundState( - message: 'no-books-found-with-terms'.i18n(), - onPressed: _refreshPage, - ), - MyBooksErrorState(:final errorMessage) => + message: 'no-books-found-with-terms'.i18n(), + onPressed: _refreshPage, + ), + MyBooksErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; diff --git a/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart b/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart index 8bb7e1ed..353821b8 100644 --- a/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart +++ b/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; import 'package:bookify/src/core/services/loan_services/loan_service.dart'; import 'package:bookify/src/core/services/reading_services/reading_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'user_information_event.dart'; @@ -47,11 +48,16 @@ class UserInformationBloc } on LocalDatabaseException catch (e) { emit( UserInformationErrorState( - errorMessage: 'Erro no database: ${e.message}'), + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), ); } on Exception catch (e) { emit( - UserInformationErrorState(errorMessage: 'Erro inesperado: $e'), + UserInformationErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } diff --git a/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart b/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart index dd2aa1da..a4aaa58d 100644 --- a/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart +++ b/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart @@ -19,9 +19,11 @@ final class UserInformationLoadedState extends UserInformationState { } final class UserInformationErrorState extends UserInformationState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; UserInformationErrorState({ - required this.errorMessage, + required this.errorCode, + required this.errorDescriptionMessage, }); } diff --git a/lib/src/features/readings/bloc/readings_bloc.dart b/lib/src/features/readings/bloc/readings_bloc.dart index 10a141af..643d1536 100644 --- a/lib/src/features/readings/bloc/readings_bloc.dart +++ b/lib/src/features/readings/bloc/readings_bloc.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/reading_services/reading_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'readings_event.dart'; @@ -36,9 +37,19 @@ class ReadingsBloc extends Bloc { await _mountReadingsDto(readings, emit); } on LocalDatabaseException catch (e) { - emit(ReadingsErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + ReadingsErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(ReadingsErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + ReadingsErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -60,9 +71,19 @@ class ReadingsBloc extends Bloc { await _mountReadingsDto(readings, emit); } on LocalDatabaseException catch (e) { - emit(ReadingsErrorState(errorMessage: 'Erro no database: ${e.message}')); + emit( + ReadingsErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(ReadingsErrorState(errorMessage: 'Erro inesperado: $e')); + emit( + ReadingsErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } @@ -75,7 +96,11 @@ class ReadingsBloc extends Bloc { for (ReadingModel reading in readings) { if (reading.id == null) { emit( - ReadingsErrorState(errorMessage: 'Erro inesperado: ${reading.id}')); + ReadingsErrorState( + errorCode: LocalDatabaseErrorCode.invalidData, + errorDescriptionMessage: 'Reading not found', + ), + ); return; } diff --git a/lib/src/features/readings/bloc/readings_state.dart b/lib/src/features/readings/bloc/readings_state.dart index 68a2df07..6290d6fb 100644 --- a/lib/src/features/readings/bloc/readings_state.dart +++ b/lib/src/features/readings/bloc/readings_state.dart @@ -15,7 +15,11 @@ final class ReadingsLoadedState extends ReadingsState { } final class ReadingsErrorState extends ReadingsState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; - ReadingsErrorState({required this.errorMessage}); + ReadingsErrorState({ + required this.errorCode, + this.errorDescriptionMessage, + }); } diff --git a/lib/src/features/readings/views/readings_page.dart b/lib/src/features/readings/views/readings_page.dart index 0d037eb2..c88d5eea 100644 --- a/lib/src/features/readings/views/readings_page.dart +++ b/lib/src/features/readings/views/readings_page.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/books_picker_page.dart'; import 'package:bookify/src/features/readings/bloc/readings_bloc.dart'; import 'package:bookify/src/features/readings/views/widgets/readings_loaded_state_widget.dart'; @@ -74,31 +75,35 @@ class _ReadingsPageState extends State { return switch (state) { ReadingsLoadingState() => const CenterCircularProgressIndicator(), ReadingsEmptyState() => Center( - key: const Key('ReadingsEmptyState'), - child: ItemEmptyStateWidget( - label: 'start-new-reading-title'.i18n(), - onTap: () => _insertNewReading(context), - ), + key: const Key('ReadingsEmptyState'), + child: ItemEmptyStateWidget( + label: 'start-new-reading-title'.i18n(), + onTap: () => _insertNewReading(context), ), + ), ReadingsNotFoundState() => Center( - child: InfoItemStateWidget.withNotFoundState( - message: 'no-readings-found-with-terms'.i18n(), - onPressed: () { - _searchController.clear(); - _toggleSearchBarVisible(); - _refreshPage(); - }, - ), + child: InfoItemStateWidget.withNotFoundState( + message: 'no-readings-found-with-terms'.i18n(), + onPressed: () { + _searchController.clear(); + _toggleSearchBarVisible(); + _refreshPage(); + }, ), + ), ReadingsLoadedState(:final readingsDto) => ReadingsLoadedStateWidget( - key: const Key('ReadingsLoadedState'), - readingsDto: readingsDto, - onNewReading: () => _insertNewReading(context), - onRefreshPage: _refreshPage, - ), - ReadingsErrorState(:final errorMessage) => Center( + key: const Key('ReadingsLoadedState'), + readingsDto: readingsDto, + onNewReading: () => _insertNewReading(context), + onRefreshPage: _refreshPage, + ), + ReadingsErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => + Center( child: InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), ), diff --git a/lib/src/features/readings_detail/bloc/readings_detail_bloc.dart b/lib/src/features/readings_detail/bloc/readings_detail_bloc.dart index 6f336cd2..0cb040aa 100644 --- a/lib/src/features/readings_detail/bloc/readings_detail_bloc.dart +++ b/lib/src/features/readings_detail/bloc/readings_detail_bloc.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/reading_services/reading_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'readings_detail_event.dart'; @@ -34,7 +35,10 @@ class ReadingsDetailBloc if (readingUpdatedRow != 1) { emit( - ReadingsDetailErrorState(errorMessage: 'Erro ao atualizar a leitura'), + ReadingsDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error on updating reading', + ), ); return; } @@ -43,13 +47,15 @@ class ReadingsDetailBloc } on LocalDatabaseException catch (e) { emit( ReadingsDetailErrorState( - errorMessage: 'Erro no database: ${e.message}', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( ReadingsDetailErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } @@ -69,7 +75,10 @@ class ReadingsDetailBloc if (bookUpdatedStatusRow != 1) { emit( - ReadingsDetailErrorState(errorMessage: 'Erro ao atualizar o livro'), + ReadingsDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error on updating book status', + ), ); return; } @@ -80,7 +89,10 @@ class ReadingsDetailBloc if (readingDeletedRow != 1) { emit( - ReadingsDetailErrorState(errorMessage: 'Erro ao finalizar a leitura'), + ReadingsDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error on deleting reading', + ), ); return; } @@ -89,13 +101,15 @@ class ReadingsDetailBloc } on LocalDatabaseException catch (e) { emit( ReadingsDetailErrorState( - errorMessage: 'Erro no database: ${e.message}', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } catch (e) { emit( ReadingsDetailErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/readings_detail/bloc/readings_detail_state.dart b/lib/src/features/readings_detail/bloc/readings_detail_state.dart index 88506115..71631755 100644 --- a/lib/src/features/readings_detail/bloc/readings_detail_state.dart +++ b/lib/src/features/readings_detail/bloc/readings_detail_state.dart @@ -9,9 +9,11 @@ final class ReadingsDetailUpdatedState extends ReadingsDetailState {} final class ReadingsDetailFinishedState extends ReadingsDetailState {} final class ReadingsDetailErrorState extends ReadingsDetailState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; ReadingsDetailErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/readings_detail/views/readings_detail_page.dart b/lib/src/features/readings_detail/views/readings_detail_page.dart index f69388c6..ec5eb43d 100644 --- a/lib/src/features/readings_detail/views/readings_detail_page.dart +++ b/lib/src/features/readings_detail/views/readings_detail_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/readings_detail/bloc/readings_detail_bloc.dart'; import 'package:bookify/src/features/readings_timer/views/readings_timer.page.dart'; import 'package:bookify/src/core/dtos/reading_dto.dart'; @@ -84,10 +85,13 @@ class _ReadingsDetailPageState extends State { ); break; - case ReadingsDetailErrorState(:final errorMessage): + case ReadingsDetailErrorState( + :final errorCode, + :final errorDescriptionMessage, + ): SnackbarService.showSnackBar( context, - errorMessage, + errorCode.toLocalizedMessage(errorDescriptionMessage), SnackBarType.error, ); @@ -201,7 +205,7 @@ class _ReadingsDetailPageState extends State { fontSize: 14, fontWeight: FontWeight.normal, ), - ) + ), ], ), ), @@ -278,7 +282,7 @@ class _ReadingsDetailPageState extends State { await _updateReadingOnPressedButton(); } }, - ) + ), ], ), ), diff --git a/lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart b/lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart index 8dd5f653..1e351d3a 100644 --- a/lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart +++ b/lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/reading_services/reading_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'readings_insertion_event.dart'; @@ -37,7 +38,9 @@ class ReadingsInsertionBloc if (bookPageCountUpdated != 1) { emit( ReadingsInsertionErrorState( - errorMessage: 'Ocorreu um erro ao atualizar as páginas do livro.', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'An error occurred while updating the book page count.', ), ); return; @@ -51,7 +54,9 @@ class ReadingsInsertionBloc if (bookStatusUpdated != 1) { emit( ReadingsInsertionErrorState( - errorMessage: 'Ocorreu um erro ao atualizar o livro.', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'An error occurred while updating the book status.', ), ); return; @@ -67,19 +72,29 @@ class ReadingsInsertionBloc if (newReadingId < 1) { emit( ReadingsInsertionErrorState( - errorMessage: 'Ocorreu um erro ao inserir a leitura.', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: + 'An error occurred while inserting the reading.', ), ); return; } - emit(ReadingsInsertionInsertedState()); + emit(ReadingsInsertionInsertedState()); } on LocalDatabaseException catch (e) { - emit(ReadingsInsertionErrorState( - errorMessage: 'Ocorreu um erro no database: ${e.message}')); + emit( + ReadingsInsertionErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { - emit(ReadingsInsertionErrorState( - errorMessage: 'Ocorreu um erro não esperado: $e')); + emit( + ReadingsInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), + ); } } } diff --git a/lib/src/features/readings_insertion/bloc/readings_insertion_state.dart b/lib/src/features/readings_insertion/bloc/readings_insertion_state.dart index bfe7b09a..da94519e 100644 --- a/lib/src/features/readings_insertion/bloc/readings_insertion_state.dart +++ b/lib/src/features/readings_insertion/bloc/readings_insertion_state.dart @@ -7,9 +7,11 @@ final class ReadingsInsertionLoadingState extends ReadingsInsertionState {} final class ReadingsInsertionInsertedState extends ReadingsInsertionState {} final class ReadingsInsertionErrorState extends ReadingsInsertionState { - final String errorMessage; + final LocalDatabaseErrorCode errorCode; + final String? errorDescriptionMessage; ReadingsInsertionErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/readings_insertion/views/readings_insertion_page.dart b/lib/src/features/readings_insertion/views/readings_insertion_page.dart index 1319f304..3656a06b 100644 --- a/lib/src/features/readings_insertion/views/readings_insertion_page.dart +++ b/lib/src/features/readings_insertion/views/readings_insertion_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/readings_insertion/bloc/readings_insertion_bloc.dart'; import 'package:bookify/src/core/helpers/textfield_unfocus/textfield_unfocus_extension.dart'; import 'package:bookify/src/core/models/book_model.dart'; @@ -82,10 +83,13 @@ class _ReadingsInsertionPageState extends State { }, ); break; - case ReadingsInsertionErrorState(:final errorMessage): + case ReadingsInsertionErrorState( + :final errorCode, + :final errorDescriptionMessage, + ): SnackbarService.showSnackBar( context, - errorMessage, + errorCode.toLocalizedMessage(errorDescriptionMessage), SnackBarType.error, ); @@ -167,7 +171,7 @@ class _ReadingsInsertionPageState extends State { 1, 2000, 'enter-pages-between-1-and-2000'.i18n(), - ) + ), ], ), onTapOutside: (_) => context.unfocus(), diff --git a/lib/src/shared/enums/local_database_error_code.dart b/lib/src/shared/enums/local_database_error_code.dart new file mode 100644 index 00000000..b1578294 --- /dev/null +++ b/lib/src/shared/enums/local_database_error_code.dart @@ -0,0 +1,12 @@ +enum LocalDatabaseErrorCode { + noSuchTable, + duplicateColumn, + syntaxError, + openFailed, + databaseClosed, + readOnly, + uniqueConstraint, + notNullConstraint, + invalidData, + unknown, +} diff --git a/pubspec.yaml b/pubspec.yaml index 8ebc5173..90f76b8c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.6 +version: 2.11.7 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/core/repositories/author_repository/authors_repository_impl_test.dart b/test/src/core/repositories/author_repository/authors_repository_impl_test.dart index 20b03d2e..f941c932 100644 --- a/test/src/core/repositories/author_repository/authors_repository_impl_test.dart +++ b/test/src/core/repositories/author_repository/authors_repository_impl_test.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/author_model.dart'; import 'package:bookify/src/core/repositories/author_repository/authors_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -13,10 +14,12 @@ void main() { group('Test normal CRUD author without error ||', () { test('insert a new author', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenAnswer((_) async => 1); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenAnswer((_) async => 1); final authorId = await authorsRepository.insert( authorModel: AuthorModel(name: 'Machado de Assis'), @@ -26,13 +29,17 @@ void main() { }); test('get actual author id by name', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'), - )).thenAnswer((_) async => [ - {'id': 1, 'name': 'Machado de Assis'} - ]); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer( + (_) async => [ + {'id': 1, 'name': 'Machado de Assis'}, + ], + ); final authorId = await authorsRepository.getAuthorIdByColumnName( authorName: 'Machado de Assis', @@ -42,11 +49,13 @@ void main() { }); test('get -1 when is a empty list', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'), - )).thenAnswer((_) async => []); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => []); final authorId = await authorsRepository.getAuthorIdByColumnName( authorName: 'Machado de Assis', @@ -56,11 +65,13 @@ void main() { }); test('get author by Id', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {'id': 1, 'name': 'Machado de Assis'}); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'id': 1, 'name': 'Machado de Assis'}); final authorModel = await authorsRepository.getAuthorById(id: 1); @@ -69,11 +80,13 @@ void main() { }); test('delete author by Id', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => 1); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => 1); final rowDeleted = await authorsRepository.deleteAuthorById(id: 1); expect(rowDeleted, equals(1)); @@ -82,65 +95,113 @@ void main() { group('Test normal CRUD author with error ||', () { test('insert a new author', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await authorsRepository.insert( authorModel: AuthorModel(name: 'Machado de Assis'), ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get actual author id by name', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'), - )).thenAnswer((_) async => [{}]); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => [{}]); expect( () async => await authorsRepository.getAuthorIdByColumnName( authorName: 'Machado de Assis', ), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível converter o dado do database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('get author by Id', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {'id': '1'}); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'id': '1'}); expect( () async => await authorsRepository.getAuthorById(id: 1), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível converter o dado do database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('delete author by Id', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await authorsRepository.deleteAuthorById( id: 1, ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/repositories/book_authors_repository/book_authors_repository_impl_test.dart b/test/src/core/repositories/book_authors_repository/book_authors_repository_impl_test.dart index c0b9dbb6..fe304fcf 100644 --- a/test/src/core/repositories/book_authors_repository/book_authors_repository_impl_test.dart +++ b/test/src/core/repositories/book_authors_repository/book_authors_repository_impl_test.dart @@ -1,6 +1,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -12,10 +13,12 @@ void main() { group('Test normal CRUD book/authors without error ||', () { test('insert book/authors relationship', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenAnswer((_) async => 1); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenAnswer((_) async => 1); final bookAuthorsRelationship = await bookAuthorsRepository.insert( bookId: '1', @@ -26,30 +29,37 @@ void main() { }); test('get book/authors relationship', () async { - when(() => - localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenAnswer((_) async => [ - {'bookId': '1', 'authorId': 1}, - ]); - - final bookAuthorsRelationshipMap = - await bookAuthorsRepository.getRelationshipsById(bookId: '1'); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer( + (_) async => [ + {'bookId': '1', 'authorId': 1}, + ], + ); + + final bookAuthorsRelationshipMap = await bookAuthorsRepository + .getRelationshipsById(bookId: '1'); expect(bookAuthorsRelationshipMap.last['bookId'], equals('1')); expect(bookAuthorsRelationshipMap.last['authorId'], equals(1)); }); test('delete book/authors relationship', () async { - when(() => localDatabase.delete( + when( + () => localDatabase.delete( table: any(named: 'table'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer((_) async => 1); + id: any(named: 'id'), + ), + ).thenAnswer((_) async => 1); - final deletedRelationshipRow = - await bookAuthorsRepository.delete(bookId: '1'); + final deletedRelationshipRow = await bookAuthorsRepository.delete( + bookId: '1', + ); expect(deletedRelationshipRow, equals(1)); }); @@ -57,48 +67,90 @@ void main() { group('Test normal CRUD book/authors with error ||', () { test('insert book/authors relationship', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookAuthorsRepository.insert( bookId: '1', authorId: 1, ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get book/authors relationship', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenAnswer((_) async => [{}]); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => [{}]); expect( () async => await bookAuthorsRepository.getRelationshipsById(bookId: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível buscar os dados'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('delete book/authors relationship', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookAuthorsRepository.delete(bookId: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/repositories/book_categories_repository/book_categories_repository_impl_test.dart b/test/src/core/repositories/book_categories_repository/book_categories_repository_impl_test.dart index 9b52ae37..9c856576 100644 --- a/test/src/core/repositories/book_categories_repository/book_categories_repository_impl_test.dart +++ b/test/src/core/repositories/book_categories_repository/book_categories_repository_impl_test.dart @@ -1,6 +1,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -11,10 +12,12 @@ void main() { final bookCategoriesRepository = BookCategoriesRepositoryImpl(localDatabase); group('Test normal CRUD of book/categories without error ||', () { test('insert book/categories relationship', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenAnswer((_) async => 1); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenAnswer((_) async => 1); final bookAuthorsRelationship = await bookCategoriesRepository.insert( bookId: '1', @@ -25,30 +28,37 @@ void main() { }); test('get book/categories relationship', () async { - when(() => - localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenAnswer((_) async => [ - {'bookId': '1', 'categoryId': 1}, - ]); - - final bookAuthorsRelationshipMap = - await bookCategoriesRepository.getRelationshipsById(bookId: '1'); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer( + (_) async => [ + {'bookId': '1', 'categoryId': 1}, + ], + ); + + final bookAuthorsRelationshipMap = await bookCategoriesRepository + .getRelationshipsById(bookId: '1'); expect(bookAuthorsRelationshipMap.last['bookId'], equals('1')); expect(bookAuthorsRelationshipMap.last['categoryId'], equals(1)); }); test('delete book/categories relationship', () async { - when(() => localDatabase.delete( + when( + () => localDatabase.delete( table: any(named: 'table'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer((_) async => 1); + id: any(named: 'id'), + ), + ).thenAnswer((_) async => 1); - final deletedRelationshipRow = - await bookCategoriesRepository.delete(bookId: '1'); + final deletedRelationshipRow = await bookCategoriesRepository.delete( + bookId: '1', + ); expect(deletedRelationshipRow, equals(1)); }); @@ -56,48 +66,90 @@ void main() { group('Test normal CRUD of book/categories with error ||', () { test('insert book/categories relationship', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookCategoriesRepository.insert( bookId: '1', categoryId: 1, ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get book/categories relationship', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenAnswer((_) async => [{}]); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => [{}]); expect( () async => await bookCategoriesRepository.getRelationshipsById(bookId: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível buscar os dados'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('delete book/categories relationship', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookCategoriesRepository.delete(bookId: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/repositories/book_on_case_repository/book_on_case_repository_impl_test.dart b/test/src/core/repositories/book_on_case_repository/book_on_case_repository_impl_test.dart index 85c69f9d..88f59a7a 100644 --- a/test/src/core/repositories/book_on_case_repository/book_on_case_repository_impl_test.dart +++ b/test/src/core/repositories/book_on_case_repository/book_on_case_repository_impl_test.dart @@ -1,6 +1,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -12,18 +13,21 @@ void main() { group('Test normal CRUD of bookcase/book without error ||', () { test('get bookcase/book relationships', () async { - when(() => localDatabase.getItemsByColumn( + when( + () => localDatabase.getItemsByColumn( table: any(named: 'table'), column: any(named: 'column'), - columnValues: any(named: 'columnValues'))).thenAnswer( + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer( (_) async => [ {'bookId': '1', 'bookcaseId': 1}, {'bookId': '2', 'bookcaseId': 1}, ], ); - final bookOnCaseRelationship = - await bookOnCaseRepository.getBooksOnCaseRelationship(bookcaseId: 1); + final bookOnCaseRelationship = await bookOnCaseRepository + .getBooksOnCaseRelationship(bookcaseId: 1); expect(bookOnCaseRelationship[0]['bookId'], equals('1')); expect(bookOnCaseRelationship[0]['bookcaseId'], equals(1)); @@ -32,39 +36,49 @@ void main() { }); test('getBookIdForImagePreview when bookId is null', () async { - when(() => localDatabase.getColumnsById( - table: any(named: 'table'), - columns: any(named: 'columns'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {}); - - final bookId = - await bookOnCaseRepository.getBookIdForImagePreview(bookcaseId: 3); + when( + () => localDatabase.getColumnsById( + table: any(named: 'table'), + columns: any(named: 'columns'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {}); + + final bookId = await bookOnCaseRepository.getBookIdForImagePreview( + bookcaseId: 3, + ); expect(bookId, equals(null)); }); test('getBookIdForImagePreview', () async { - when(() => localDatabase.getColumnsById( - table: any(named: 'table'), - columns: any(named: 'columns'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {'bookId': '1'}); - - final bookId = - await bookOnCaseRepository.getBookIdForImagePreview(bookcaseId: 3); + when( + () => localDatabase.getColumnsById( + table: any(named: 'table'), + columns: any(named: 'columns'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'bookId': '1'}); + + final bookId = await bookOnCaseRepository.getBookIdForImagePreview( + bookcaseId: 3, + ); expect(bookId, equals('1')); }); test('insert relationship', () async { when( () => localDatabase.insert( - table: any(named: 'table'), values: any(named: 'values')), + table: any(named: 'table'), + values: any(named: 'values'), + ), ).thenAnswer((invocation) async => 1); - final relationshipRowInserted = - await bookOnCaseRepository.insert(bookcaseId: 1, bookId: '1'); + final relationshipRowInserted = await bookOnCaseRepository.insert( + bookcaseId: 1, + bookId: '1', + ); expect(relationshipRowInserted, equals(1)); }); @@ -77,8 +91,9 @@ void main() { ), ).thenAnswer((_) async => 2); - final bookcasesCount = - await bookOnCaseRepository.countBookcasesByBook(bookId: 'bookId'); + final bookcasesCount = await bookOnCaseRepository.countBookcasesByBook( + bookId: 'bookId', + ); expect(bookcasesCount, equals(2)); }); @@ -86,11 +101,12 @@ void main() { test('delete relationship', () async { when( () => localDatabase.deleteWithAnotherColumn( - table: any(named: 'table'), - otherColumn: any(named: 'otherColumn'), - value: any(named: 'value'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id')), + table: any(named: 'table'), + otherColumn: any(named: 'otherColumn'), + value: any(named: 'value'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), ).thenAnswer((invocation) async => 1); final relationshipRowDeleted = await bookOnCaseRepository @@ -101,64 +117,125 @@ void main() { group('Test normal CRUD of bookcase/book with error ||', () { test('get bookcase/book relationships -- LocalDatabaseException', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookOnCaseRepository.getBooksOnCaseRelationship( - bookcaseId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + bookcaseId: 1, + ), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('getBookIdForImagePreview -- LocalDatabaseException', () async { - when(() => localDatabase.getColumnsById( - table: any(named: 'table'), - columns: any(named: 'columns'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.getColumnsById( + table: any(named: 'table'), + columns: any(named: 'columns'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookOnCaseRepository.getBookIdForImagePreview(bookcaseId: 3), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('getBookIdForImagePreview -- TypeError', () async { - when(() => localDatabase.getColumnsById( - table: any(named: 'table'), - columns: any(named: 'columns'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {'bookId': 1}); + when( + () => localDatabase.getColumnsById( + table: any(named: 'table'), + columns: any(named: 'columns'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'bookId': 1}); expect( () async => await bookOnCaseRepository.getBookIdForImagePreview(bookcaseId: 3), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível converter o dado do database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('insert relationship', () async { when( () => localDatabase.insert( - table: any(named: 'table'), values: any(named: 'values')), - ).thenThrow(const LocalDatabaseException('Error on database')); + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookOnCaseRepository.insert(bookcaseId: 1, bookId: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -169,33 +246,66 @@ void main() { idColumn: any(named: 'idColumn'), id: any(named: 'id'), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookOnCaseRepository.countBookcasesByBook(bookId: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('delete relationship', () async { when( () => localDatabase.deleteWithAnotherColumn( - table: any(named: 'table'), - otherColumn: any(named: 'otherColumn'), - value: any(named: 'value'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id')), - ).thenThrow(const LocalDatabaseException('Error on database')); + table: any(named: 'table'), + otherColumn: any(named: 'otherColumn'), + value: any(named: 'value'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookOnCaseRepository.deleteBookcaseRelationship( bookcaseId: 1, bookId: '1', ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/repositories/bookcase_repository/bookcase_repository_impl_test.dart b/test/src/core/repositories/bookcase_repository/bookcase_repository_impl_test.dart index cd1144a2..ba3f9a6a 100644 --- a/test/src/core/repositories/bookcase_repository/bookcase_repository_impl_test.dart +++ b/test/src/core/repositories/bookcase_repository/bookcase_repository_impl_test.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/helpers/color_to_int/color_to_int_extension.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -36,8 +37,9 @@ void main() { group('Test normal CRUD bookcase without error ||', () { test('getAll()', () async { - when(() => localDatabase.getAll(table: any(named: 'table'))) - .thenAnswer((_) async => bookcasesMap); + when( + () => localDatabase.getAll(table: any(named: 'table')), + ).thenAnswer((_) async => bookcasesMap); final bookcasesModel = await bookcaseRepository.getAll(); @@ -63,14 +65,17 @@ void main() { }); test('get by name()', () async { - when(() => localDatabase.researchBy( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenAnswer((_) async => [bookcasesMap[0]]); + when( + () => localDatabase.researchBy( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => [bookcasesMap[0]]); - final bookcaseModelByName = - await bookcaseRepository.getBookcasesByName(name: 'Fantasia'); + final bookcaseModelByName = await bookcaseRepository.getBookcasesByName( + name: 'Fantasia', + ); expect(bookcaseModelByName[0].id, equals(1)); expect(bookcaseModelByName[0].name, 'Fantasia'); @@ -84,10 +89,13 @@ void main() { }); test('getById()', () async { - when(() => localDatabase.getItemById( + when( + () => localDatabase.getItemById( table: any(named: 'table'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer((_) async => bookcasesMap[0]); + id: any(named: 'id'), + ), + ).thenAnswer((_) async => bookcasesMap[0]); final bookcasesModel = await bookcaseRepository.getById(bookcaseId: 1); @@ -117,25 +125,33 @@ void main() { }); test('insert()', () async { - when(() => localDatabase.insert( + when( + () => localDatabase.insert( table: any(named: 'table'), - values: any(named: 'values'))).thenAnswer((_) async => 3); + values: any(named: 'values'), + ), + ).thenAnswer((_) async => 3); - final bookcaseInsertedId = - await bookcaseRepository.insert(bookcaseModel: bookcaseModel); + final bookcaseInsertedId = await bookcaseRepository.insert( + bookcaseModel: bookcaseModel, + ); expect(bookcaseInsertedId, equals(3)); }); test('update()', () async { - when(() => localDatabase.update( + when( + () => localDatabase.update( table: any(named: 'table'), values: any(named: 'values'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer((_) async => 1); + id: any(named: 'id'), + ), + ).thenAnswer((_) async => 1); final bookcaseUpdatedRow = await bookcaseRepository.update( - bookcaseModel: bookcaseModel.copyWith(color: Colors.blue)); + bookcaseModel: bookcaseModel.copyWith(color: Colors.blue), + ); expect(bookcaseUpdatedRow, equals(1)); }); @@ -156,83 +172,158 @@ void main() { group('Test normal CRUD bookcase with error ||', () { test('getAll() -- LocalDatabaseException', () async { - when(() => localDatabase.getAll(table: any(named: 'table'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.getAll(table: any(named: 'table')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( - () async => await bookcaseRepository.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database')); + () async => await bookcaseRepository.getAll(), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), + ); }); test('getAll() -- TypeError', () async { - when(() => localDatabase.getAll(table: any(named: 'table'))) - .thenAnswer((_) async => [ - {'id': 1} - ]); + when(() => localDatabase.getAll(table: any(named: 'table'))).thenAnswer( + (_) async => [ + {'id': 1}, + ], + ); expect( () async => await bookcaseRepository.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar as estantes no database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('get by name() -- LocalDatabaseException', () async { - when(() => localDatabase.researchBy( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.researchBy( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( - () async => - await bookcaseRepository.getBookcasesByName(name: 'Fantasia'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database')); + () async => + await bookcaseRepository.getBookcasesByName(name: 'Fantasia'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), + ); }); }); test('get by name() -- TypeError', () async { - when(() => localDatabase.researchBy( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenAnswer((_) async => [{}]); + when( + () => localDatabase.researchBy( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => [{}]); expect( - () async => - await bookcaseRepository.getBookcasesByName(name: 'Fantasia'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar as estantes no database')); + () async => await bookcaseRepository.getBookcasesByName(name: 'Fantasia'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), + ); }); test('getById() -- LocalDatabaseException', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( - () async => await bookcaseRepository.getById(bookcaseId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database')); + () async => await bookcaseRepository.getById(bookcaseId: 1), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), + ); }); test('getById() -- TypeError', () async { - when(() => localDatabase.getItemById( + when( + () => localDatabase.getItemById( table: any(named: 'table'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer((_) async => {'id': 1}); + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'id': 1}); expect( - () async => await bookcaseRepository.getById(bookcaseId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar a estante no database')); + () async => await bookcaseRepository.getById(bookcaseId: 1), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), + ); }); test('countBookcases() -- LocalDatabaseException', () async { @@ -240,52 +331,126 @@ void main() { () => localDatabase.countItems( table: any(named: 'table'), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseRepository.countBookcases(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('insert() -- LocalDatabaseException', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), values: any(named: 'values'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( - () async => - await bookcaseRepository.insert(bookcaseModel: bookcaseModel), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database')); + () async => await bookcaseRepository.insert(bookcaseModel: bookcaseModel), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), + ); }); test('update() -- LocalDatabaseException', () async { - when(() => localDatabase.update( - table: any(named: 'table'), - values: any(named: 'values'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.update( + table: any(named: 'table'), + values: any(named: 'values'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( - () async => await bookcaseRepository.update( - bookcaseModel: bookcaseModel.copyWith(color: Colors.blue)), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database')); + () async => await bookcaseRepository.update( + bookcaseModel: bookcaseModel.copyWith(color: Colors.blue), + ), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), + ); }); test('delete() -- LocalDatabaseException', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( - () async => await bookcaseRepository.delete(bookcaseId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database')); + () async => await bookcaseRepository.delete(bookcaseId: 1), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), + ); }); } diff --git a/test/src/core/repositories/books_repository/books_repository_impl_test.dart b/test/src/core/repositories/books_repository/books_repository_impl_test.dart index 26c6d2ec..391de7d5 100644 --- a/test/src/core/repositories/books_repository/books_repository_impl_test.dart +++ b/test/src/core/repositories/books_repository/books_repository_impl_test.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/repositories/books_repository/books_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -16,36 +17,44 @@ void main() { group('Test normal CRUD book without error ||', () { test('insert book', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenAnswer((_) async => 1); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenAnswer((_) async => 1); final bookInsertedRow = await bookRepository.insert(bookModel: bookModel); expect(bookInsertedRow, equals(1)); }); test('delete book', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => 1); - - final bookRemovedRow = - await bookRepository.deleteBookById(id: bookModel.id); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => 1); + + final bookRemovedRow = await bookRepository.deleteBookById( + id: bookModel.id, + ); expect(bookRemovedRow, equals(1)); }); test('verify book is already inserted', () async { - when(() => localDatabase.verifyItemIsAlreadyInserted( - table: any(named: 'table'), - column: any(named: 'column'), - columnValue: any(named: 'columnValue'), - )).thenAnswer((_) async => true); - - final bookIsInserted = - await bookRepository.verifyBookIsAlreadyInserted(id: bookModel.id); + when( + () => localDatabase.verifyItemIsAlreadyInserted( + table: any(named: 'table'), + column: any(named: 'column'), + columnValue: any(named: 'columnValue'), + ), + ).thenAnswer((_) async => true); + + final bookIsInserted = await bookRepository.verifyBookIsAlreadyInserted( + id: bookModel.id, + ); expect(bookIsInserted, equals(true)); }); @@ -63,19 +72,23 @@ void main() { 'status': 1, }; - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => bookMap); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => bookMap); final bookModelFromMap = await bookRepository.getBookById(id: '1'); expect(bookModelFromMap.id, equals('1')); expect(bookModelFromMap.title, equals('Memórias Póstumas De Brás Cubas')); expect(bookModelFromMap.publisher, equals('FTD Editora')); - expect(bookModelFromMap.description, - equals('É narrada pelo defunto Brás Cubas...')); + expect( + bookModelFromMap.description, + equals('É narrada pelo defunto Brás Cubas...'), + ); expect(bookModelFromMap.pageCount, equals(320)); expect(bookModelFromMap.imageUrl, equals('imageUrl')); expect(bookModelFromMap.buyLink, equals('buyLink')); @@ -100,14 +113,17 @@ void main() { 'status': 1, }; - when(() => localDatabase.researchBy( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenAnswer((_) async => [bookMap]); + when( + () => localDatabase.researchBy( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => [bookMap]); final bookModelByName = await bookRepository.getBooksByTitle( - title: 'Memórias Póstumas De Brás Cubas'); + title: 'Memórias Póstumas De Brás Cubas', + ); expect(bookModelByName[0].id, equals('1')); expect(bookModelByName[0].title, 'Memórias Póstumas De Brás Cubas'); @@ -127,9 +143,11 @@ void main() { }); test('get all books', () async { - when(() => localDatabase.getAll( - table: any(named: 'table'), - )).thenAnswer( + when( + () => localDatabase.getAll( + table: any(named: 'table'), + ), + ).thenAnswer( (_) async => booksModelMock.map((book) => book.toMap()).toList(), ); @@ -147,12 +165,14 @@ void main() { }); test('get book image', () async { - when(() => localDatabase.getColumnsById( - table: any(named: 'table'), - columns: any(named: 'columns'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer( + when( + () => localDatabase.getColumnsById( + table: any(named: 'table'), + columns: any(named: 'columns'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer( (_) async => {'imageUrl': 'http:www//imageurl.com'}, ); @@ -177,32 +197,40 @@ void main() { }); test('update book status', () async { - when(() => localDatabase.update( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - values: any(named: 'values'), - )).thenAnswer( + when( + () => localDatabase.update( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + values: any(named: 'values'), + ), + ).thenAnswer( (_) async => 1, ); final bookUpdated = await bookRepository.updateBookStatus( - id: '1', status: BookStatus.reading); + id: '1', + status: BookStatus.reading, + ); expect(bookUpdated, equals(1)); }); test('update book page Count', () async { - when(() => localDatabase.update( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - values: any(named: 'values'), - )).thenAnswer( + when( + () => localDatabase.update( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + values: any(named: 'values'), + ), + ).thenAnswer( (_) async => 1, ); - final bookUpdated = - await bookRepository.updateBookPageCount(id: '1', pageCount: 100); + final bookUpdated = await bookRepository.updateBookPageCount( + id: '1', + pageCount: 100, + ); expect(bookUpdated, equals(1)); }); @@ -223,160 +251,315 @@ void main() { group('Test normal CRUD book with error ||', () { test('insert book -- LocalDatabaseException', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.insert(bookModel: bookModel), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('delete book -- LocalDatabaseException', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.deleteBookById(id: bookModel.id), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('verify book is already inserted -- LocalDatabaseException', () async { - when(() => localDatabase.verifyItemIsAlreadyInserted( - table: any(named: 'table'), - column: any(named: 'column'), - columnValue: any(named: 'columnValue'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.verifyItemIsAlreadyInserted( + table: any(named: 'table'), + column: any(named: 'column'), + columnValue: any(named: 'columnValue'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.verifyBookIsAlreadyInserted(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get book by id -- TypeError', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {'id': '1'}); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'id': '1'}); expect( () async => await bookRepository.getBookById(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível converter o dado do database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('get book by id -- LocalDatabaseException', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.getBookById(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get book by Title -- TypeError', () async { - when(() => localDatabase.researchBy( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenAnswer((_) async => [{}]); + when( + () => localDatabase.researchBy( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => [{}]); expect( - () async => await bookRepository.getBooksByTitle( - title: 'Memórias Póstumas de Bras Cubas'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == - 'Impossível encontrar os livros com esse título no database')); + () async => await bookRepository.getBooksByTitle( + title: 'Memórias Póstumas de Bras Cubas', + ), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), + ); }); test('get book by Title -- LocalDatabaseException', () async { - when(() => localDatabase.researchBy( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.researchBy( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( - () async => await bookRepository.getBooksByTitle( - title: 'Memórias Póstumas de Bras Cubas'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database')); + () async => await bookRepository.getBooksByTitle( + title: 'Memórias Póstumas de Bras Cubas', + ), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), + ); }); test('get all books -- TypeError', () async { - when(() => localDatabase.getAll( - table: any(named: 'table'), - )).thenAnswer((_) async => [ - {'id': '1'} - ]); + when( + () => localDatabase.getAll( + table: any(named: 'table'), + ), + ).thenAnswer( + (_) async => [ + {'id': '1'}, + ], + ); expect( () async => await bookRepository.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível converter o dado do database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('get all books -- LocalDatabaseException', () async { - when(() => localDatabase.getAll( - table: any(named: 'table'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.getAll( + table: any(named: 'table'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get book image -- TypeError', () async { - when(() => localDatabase.getColumnsById( - table: any(named: 'table'), - columns: any(named: 'columns'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {}); + when( + () => localDatabase.getColumnsById( + table: any(named: 'table'), + columns: any(named: 'columns'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {}); expect( () async => await bookRepository.getBookImageById(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível converter o dado do database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('get book image -- LocalDatabaseException', () async { - when(() => localDatabase.getColumnsById( - table: any(named: 'table'), - columns: any(named: 'columns'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => localDatabase.getColumnsById( + table: any(named: 'table'), + columns: any(named: 'columns'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.getBookImageById(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -392,9 +575,13 @@ void main() { expect( () async => await bookRepository.getBookStatus(id: 'bookId'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar o status do livro no database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); @@ -406,40 +593,80 @@ void main() { idColumn: any(named: 'idColumn'), id: any(named: 'id'), ), - ).thenThrow(const LocalDatabaseException('error on database')); - + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.getBookStatus(id: 'bookId'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('update book status -- LocalDatabaseException', () async { - when(() => localDatabase.update( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - values: any(named: 'values'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.update( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.updateBookStatus( id: '1', status: BookStatus.reading, ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('update book page Count -- assertion failed', () async { - when(() => localDatabase.update( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - values: any(named: 'values'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.update( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.invalidData, + descriptionMessage: 'Invalid page count', + ), + ); expect( () async => await bookRepository.updateBookPageCount( @@ -447,27 +674,48 @@ void main() { pageCount: 0, ), throwsA( - (AssertionError e) => - e.message == 'pagesCount must be greater than 0', + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), ), ); }); test('update book page Count -- LocalDatabaseException', () async { - when(() => localDatabase.update( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - values: any(named: 'values'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.update( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.updateBookPageCount( id: '1', pageCount: 100, ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -476,12 +724,28 @@ void main() { () => localDatabase.countItems( table: any(named: 'table'), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookRepository.countBooks(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/repositories/category_repository/categories_repository_impl_test.dart b/test/src/core/repositories/category_repository/categories_repository_impl_test.dart index a9ceacf1..cfc4216d 100644 --- a/test/src/core/repositories/category_repository/categories_repository_impl_test.dart +++ b/test/src/core/repositories/category_repository/categories_repository_impl_test.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/repositories/category_repository/categories_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -13,10 +14,12 @@ void main() { group('Test normal CRUD category without error ||', () { test('insert new category', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenAnswer((_) async => 1); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenAnswer((_) async => 1); final categoryId = await categoriesRepository.insert( categoryModel: CategoryModel(name: 'Fiction'), @@ -26,13 +29,17 @@ void main() { }); test('get actual category id by name', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'), - )).thenAnswer((_) async => [ - {'id': 1, 'name': 'Fiction'} - ]); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer( + (_) async => [ + {'id': 1, 'name': 'Fiction'}, + ], + ); final categoryId = await categoriesRepository.getCategoryIdByColumnName( categoryName: 'Fiction', @@ -42,11 +49,13 @@ void main() { }); test('get -1 when is a empty list', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'), - )).thenAnswer((_) async => []); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => []); final categoryId = await categoriesRepository.getCategoryIdByColumnName( categoryName: 'Fiction', @@ -56,11 +65,13 @@ void main() { }); test('get category by Id', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {'id': 1, 'name': 'Fiction'}); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'id': 1, 'name': 'Fiction'}); final categoryModel = await categoriesRepository.getCategoryById(id: 1); @@ -69,11 +80,13 @@ void main() { }); test('delete category by Id', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => 1); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => 1); final rowDeleted = await categoriesRepository.deleteCategoryById(id: 1); expect(rowDeleted, equals(1)); @@ -82,63 +95,111 @@ void main() { group('Test normal CRUD category with error ||', () { test('insert new category', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), - values: any(named: 'values'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await categoriesRepository.insert( categoryModel: CategoryModel(name: 'Fiction'), ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get actual category id by name', () async { - when(() => localDatabase.getItemsByColumn( - table: any(named: 'table'), - column: any(named: 'column'), - columnValues: any(named: 'columnValues'), - )).thenAnswer((_) async => [{}]); + when( + () => localDatabase.getItemsByColumn( + table: any(named: 'table'), + column: any(named: 'column'), + columnValues: any(named: 'columnValues'), + ), + ).thenAnswer((_) async => [{}]); expect( () async => await categoriesRepository.getCategoryIdByColumnName( categoryName: 'Fiction', ), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível converter o dado do database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('get category by Id', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenAnswer((_) async => {'id': '1', 'name': 'Fiction'}); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'id': '1', 'name': 'Fiction'}); expect( () async => await categoriesRepository.getCategoryById(id: 1), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível converter o dado do database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); test('delete category by Id', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await categoriesRepository.deleteCategoryById(id: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/repositories/loan_repository/loan_repository_impl_test.dart b/test/src/core/repositories/loan_repository/loan_repository_impl_test.dart index 917419ae..ea21e36e 100644 --- a/test/src/core/repositories/loan_repository/loan_repository_impl_test.dart +++ b/test/src/core/repositories/loan_repository/loan_repository_impl_test.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/loan_model.dart'; import 'package:bookify/src/core/repositories/loan_repository/loan_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -19,8 +20,10 @@ void main() { 'id': 1, 'observation': 'observation', 'loanDate': DateTime(2024, 01, 10).millisecondsSinceEpoch, - 'devolutionDate': - DateTime(DateTime.april, 2024).millisecondsSinceEpoch, + 'devolutionDate': DateTime( + DateTime.april, + 2024, + ).millisecondsSinceEpoch, 'idContact': 'idContact', 'bookId': 'bookId', }, @@ -28,8 +31,10 @@ void main() { 'id': 2, 'observation': 'observation', 'loanDate': DateTime(2024, 01, 10).millisecondsSinceEpoch, - 'devolutionDate': - DateTime(DateTime.april, 2024).millisecondsSinceEpoch, + 'devolutionDate': DateTime( + DateTime.april, + 2024, + ).millisecondsSinceEpoch, 'idContact': 'idContact', 'bookId': 'bookId', }, @@ -37,8 +42,10 @@ void main() { 'id': 3, 'observation': 'observation', 'loanDate': DateTime(2024, 01, 10).millisecondsSinceEpoch, - 'devolutionDate': - DateTime(DateTime.april, 2024).millisecondsSinceEpoch, + 'devolutionDate': DateTime( + DateTime.april, + 2024, + ).millisecondsSinceEpoch, 'idContact': 'idContact', 'bookId': 'bookId', }, @@ -71,10 +78,11 @@ void main() { equals(DateTime(2024, 01, 10)), ); expect( - loansModel[0].devolutionDate, - equals( - DateTime(DateTime.april, 2024), - )); + loansModel[0].devolutionDate, + equals( + DateTime(DateTime.april, 2024), + ), + ); expect(loansModel[0].idContact, equals('idContact')); expect(loansModel[0].bookId, equals('bookId')); }); @@ -93,8 +101,9 @@ void main() { ), ).thenAnswer((_) async => loansMap); - final loansModel = - await loanRepository.getLoansByBookTitle(title: 'title'); + final loansModel = await loanRepository.getLoansByBookTitle( + title: 'title', + ); expect(loansModel.length, equals(3)); expect(loansModel[0].id, equals(1)); @@ -104,19 +113,23 @@ void main() { equals(DateTime(2024, 01, 10)), ); expect( - loansModel[0].devolutionDate, - equals( - DateTime(DateTime.april, 2024), - )); + loansModel[0].devolutionDate, + equals( + DateTime(DateTime.april, 2024), + ), + ); expect(loansModel[0].idContact, equals('idContact')); expect(loansModel[0].bookId, equals('bookId')); }); test('get by Id', () async { - when(() => localDatabase.getItemById( + when( + () => localDatabase.getItemById( table: any(named: 'table'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer( + id: any(named: 'id'), + ), + ).thenAnswer( (_) async => loansMap.where((element) => element['id'] == 2).first, ); @@ -129,10 +142,11 @@ void main() { equals(DateTime(2024, 01, 10)), ); expect( - loanModel.devolutionDate, - equals( - DateTime(DateTime.april, 2024), - )); + loanModel.devolutionDate, + equals( + DateTime(DateTime.april, 2024), + ), + ); expect(loanModel.idContact, equals('idContact')); expect(loanModel.bookId, equals('bookId')); }); @@ -209,15 +223,21 @@ void main() { orderColumn: any(named: 'orderColumn'), orderBy: any(named: 'orderBy'), ), - ).thenAnswer((_) async => [ - {'id': 1} - ]); + ).thenAnswer( + (_) async => [ + {'id': 1}, + ], + ); expect( () async => await loanRepository.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar os empréstimos no database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); @@ -228,12 +248,28 @@ void main() { orderColumn: any(named: 'orderColumn'), orderBy: any(named: 'orderBy'), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanRepository.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -249,15 +285,21 @@ void main() { whereArgs: any(named: 'whereArgs'), usingLikeCondition: true, ), - ).thenAnswer((_) async => [ - {'id': 1} - ]); + ).thenAnswer( + (_) async => [ + {'id': 1}, + ], + ); expect( () async => await loanRepository.getLoansByBookTitle(title: 'title'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar os empréstimos no database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); @@ -273,43 +315,80 @@ void main() { whereArgs: any(named: 'whereArgs'), usingLikeCondition: true, ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanRepository.getLoansByBookTitle(title: 'title'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('getById -- TypeError', () async { - when(() => localDatabase.getItemById( + when( + () => localDatabase.getItemById( table: any(named: 'table'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer((_) async => {'id': 1}); + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'id': 1}); expect( () async => await loanRepository.getById(loanId: 1), throwsA( - (Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar o empréstimo no database', + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), ), ); }); test('getById -- LocalDatabaseException', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanRepository.getById(loanId: 1), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); @@ -319,65 +398,127 @@ void main() { () => localDatabase.countItems( table: any(named: 'table'), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanRepository.countLoans(), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); test('insert -- LocalDatabaseException', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), values: any(named: 'values'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanRepository.insert( - loanModel: LoanModel.fromMap(loansMap[0])), + loanModel: LoanModel.fromMap(loansMap[0]), + ), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); test('update -- LocalDatabaseException', () async { - when(() => localDatabase.update( + when( + () => localDatabase.update( table: any(named: 'table'), values: any(named: 'values'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenThrow( + id: any(named: 'id'), + ), + ).thenThrow( const LocalDatabaseException( - 'Error on database', + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', ), ); expect( () async => await loanRepository.update( - loanModel: LoanModel.fromMap(loansMap[0])), + loanModel: LoanModel.fromMap(loansMap[0]), + ), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); test('delete -- LocalDatabaseException', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanRepository.delete(loanId: 1), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); diff --git a/test/src/core/repositories/reading_repository/reading_repository_impl_test.dart b/test/src/core/repositories/reading_repository/reading_repository_impl_test.dart index 9615c700..f81fe85d 100644 --- a/test/src/core/repositories/reading_repository/reading_repository_impl_test.dart +++ b/test/src/core/repositories/reading_repository/reading_repository_impl_test.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/database/local_database.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/repositories/reading_repository/reading_repository_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -77,8 +78,9 @@ void main() { ), ).thenAnswer((_) async => readingsMap); - final readings = - await readingRepository.getReadingsByBookTitle(title: 'title'); + final readings = await readingRepository.getReadingsByBookTitle( + title: 'title', + ); expect(readings.length, equals(3)); expect(readings[0].id, equals(1)); @@ -93,10 +95,13 @@ void main() { }); test('get by Id', () async { - when(() => localDatabase.getItemById( + when( + () => localDatabase.getItemById( table: any(named: 'table'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer( + id: any(named: 'id'), + ), + ).thenAnswer( (_) async => readingsMap.where((element) => element['id'] == 2).first, ); @@ -185,15 +190,21 @@ void main() { orderColumn: any(named: 'orderColumn'), orderBy: any(named: 'orderBy'), ), - ).thenAnswer((_) async => [ - {'id': 1} - ]); + ).thenAnswer( + (_) async => [ + {'id': 1}, + ], + ); expect( () async => await readingRepository.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar as leituras no database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); @@ -204,12 +215,28 @@ void main() { orderColumn: any(named: 'orderColumn'), orderBy: any(named: 'orderBy'), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingRepository.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -225,16 +252,22 @@ void main() { whereArgs: any(named: 'whereArgs'), usingLikeCondition: true, ), - ).thenAnswer((_) async => [ - {'id': 1} - ]); + ).thenAnswer( + (_) async => [ + {'id': 1}, + ], + ); expect( () async => await readingRepository.getReadingsByBookTitle(title: 'title'), - throwsA((Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar as leituras no database'), + throwsA( + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), + ), ); }); @@ -250,44 +283,81 @@ void main() { whereArgs: any(named: 'whereArgs'), usingLikeCondition: true, ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingRepository.getReadingsByBookTitle(title: 'title'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('getById -- TypeError', () async { - when(() => localDatabase.getItemById( + when( + () => localDatabase.getItemById( table: any(named: 'table'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenAnswer((_) async => {'id': 1}); + id: any(named: 'id'), + ), + ).thenAnswer((_) async => {'id': 1}); expect( () async => await readingRepository.getById(readingId: 1), throwsA( - (Exception e) => - e is LocalDatabaseException && - e.message == 'Impossível encontrar a leitura no database', + isA().having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.invalidData, + ), ), ); }); test('getById -- LocalDatabaseException', () async { - when(() => localDatabase.getItemById( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.getItemById( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingRepository.getById(readingId: 1), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); @@ -297,65 +367,127 @@ void main() { () => localDatabase.countItems( table: any(named: 'table'), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingRepository.countReadings(), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); test('insert -- LocalDatabaseException', () async { - when(() => localDatabase.insert( - table: any(named: 'table'), values: any(named: 'values'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.insert( + table: any(named: 'table'), + values: any(named: 'values'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingRepository.insert( - readingModel: ReadingModel.fromMap(readingsMap[0])), + readingModel: ReadingModel.fromMap(readingsMap[0]), + ), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); test('update -- LocalDatabaseException', () async { - when(() => localDatabase.update( + when( + () => localDatabase.update( table: any(named: 'table'), values: any(named: 'values'), idColumn: any(named: 'idColumn'), - id: any(named: 'id'))).thenThrow( + id: any(named: 'id'), + ), + ).thenThrow( const LocalDatabaseException( - 'Error on database', + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', ), ); expect( () async => await readingRepository.update( - readingModel: ReadingModel.fromMap(readingsMap[0])), + readingModel: ReadingModel.fromMap(readingsMap[0]), + ), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); test('delete -- LocalDatabaseException', () async { - when(() => localDatabase.delete( - table: any(named: 'table'), - idColumn: any(named: 'idColumn'), - id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => localDatabase.delete( + table: any(named: 'table'), + idColumn: any(named: 'idColumn'), + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingRepository.delete(readingId: 1), throwsA( - (Exception e) => - e is LocalDatabaseException && e.message == 'Error on database', + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), ), ); }); diff --git a/test/src/core/services/book_service/book_service_impl_test.dart b/test/src/core/services/book_service/book_service_impl_test.dart index 2901949b..6b321e2e 100644 --- a/test/src/core/services/book_service/book_service_impl_test.dart +++ b/test/src/core/services/book_service/book_service_impl_test.dart @@ -8,6 +8,7 @@ import 'package:bookify/src/core/repositories/book_categories_repository/book_ca import 'package:bookify/src/core/repositories/books_repository/books_repository.dart'; import 'package:bookify/src/core/repositories/category_repository/categories_repository.dart'; import 'package:bookify/src/core/services/book_service/book_service_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -64,22 +65,28 @@ void main() { ).thenAnswer((_) async => [bookModel]); //for author repository - when(() => authorsRepository.getAuthorById(id: any(named: 'id'))) - .thenAnswer((_) async => authorModel); + when( + () => authorsRepository.getAuthorById(id: any(named: 'id')), + ).thenAnswer((_) async => authorModel); // for category repository - when(() => categoriesRepository.getCategoryById(id: any(named: 'id'))) - .thenAnswer((_) async => categoryModel); + when( + () => categoriesRepository.getCategoryById(id: any(named: 'id')), + ).thenAnswer((_) async => categoryModel); // for book authors repository - when(() => bookAuthorsRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookAuthorsRelationship]); + when( + () => bookAuthorsRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookAuthorsRelationship]); // for book categories repository - when(() => bookCategoriesRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookCategoriesRelationship]); + when( + () => bookCategoriesRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookCategoriesRelationship]); final booksModel = await bookService.getAllBook(); @@ -95,22 +102,28 @@ void main() { ).thenAnswer((_) async => [bookModel]); //for author repository - when(() => authorsRepository.getAuthorById(id: any(named: 'id'))) - .thenAnswer((_) async => authorModel); + when( + () => authorsRepository.getAuthorById(id: any(named: 'id')), + ).thenAnswer((_) async => authorModel); // for category repository - when(() => categoriesRepository.getCategoryById(id: any(named: 'id'))) - .thenAnswer((_) async => categoryModel); + when( + () => categoriesRepository.getCategoryById(id: any(named: 'id')), + ).thenAnswer((_) async => categoryModel); // for book authors repository - when(() => bookAuthorsRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookAuthorsRelationship]); + when( + () => bookAuthorsRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookAuthorsRelationship]); // for book categories repository - when(() => bookCategoriesRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookCategoriesRelationship]); + when( + () => bookCategoriesRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookCategoriesRelationship]); final booksModel = await bookService.getBooksByTitle(title: 'title'); @@ -129,22 +142,28 @@ void main() { ).thenAnswer((_) async => bookModel); //for author repository - when(() => authorsRepository.getAuthorById(id: any(named: 'id'))) - .thenAnswer((_) async => authorModel); + when( + () => authorsRepository.getAuthorById(id: any(named: 'id')), + ).thenAnswer((_) async => authorModel); // for category repository - when(() => categoriesRepository.getCategoryById(id: any(named: 'id'))) - .thenAnswer((_) async => categoryModel); + when( + () => categoriesRepository.getCategoryById(id: any(named: 'id')), + ).thenAnswer((_) async => categoryModel); // for book authors repository - when(() => bookAuthorsRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookAuthorsRelationship]); + when( + () => bookAuthorsRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookAuthorsRelationship]); // for book categories repository - when(() => bookCategoriesRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookCategoriesRelationship]); + when( + () => bookCategoriesRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookCategoriesRelationship]); final completeBookModel = await bookService.getBookById(id: '1'); @@ -167,8 +186,10 @@ void main() { test('insert complete book', () async { // setUp all when - final completeBookModel = bookModel - .copyWith(authors: [authorModel], categories: [categoryModel]); + final completeBookModel = bookModel.copyWith( + authors: [authorModel], + categories: [categoryModel], + ); //for book repository when( @@ -178,7 +199,8 @@ void main() { //for author repository when( () => authorsRepository.getAuthorIdByColumnName( - authorName: any(named: 'authorName')), + authorName: any(named: 'authorName'), + ), ).thenAnswer((_) async => -1); when( @@ -188,7 +210,8 @@ void main() { // for category repository when( () => categoriesRepository.getCategoryIdByColumnName( - categoryName: any(named: 'categoryName')), + categoryName: any(named: 'categoryName'), + ), ).thenAnswer((_) async => 1); // for book authors repository @@ -207,19 +230,23 @@ void main() { ), ).thenAnswer((_) async => 1); - final isInserted = - await bookService.insertCompleteBook(bookModel: completeBookModel); + final isInserted = await bookService.insertCompleteBook( + bookModel: completeBookModel, + ); expect(isInserted, equals(1)); }); test('verify book is exist', () async { - when(() => booksRepository.verifyBookIsAlreadyInserted( - id: any(named: 'id'), - )).thenAnswer((_) async => true); + when( + () => booksRepository.verifyBookIsAlreadyInserted( + id: any(named: 'id'), + ), + ).thenAnswer((_) async => true); - final bookIsInserted = - await bookService.verifyBookIsAlreadyInserted(id: '1'); + final bookIsInserted = await bookService.verifyBookIsAlreadyInserted( + id: '1', + ); expect(bookIsInserted, isTrue); }); @@ -235,7 +262,9 @@ void main() { test('update status', () async { when( () => booksRepository.updateBookStatus( - id: any(named: 'id'), status: BookStatus.reading), + id: any(named: 'id'), + status: BookStatus.reading, + ), ).thenAnswer((_) async => 1); final bookRowUpdated = await bookService.updateStatus( @@ -248,7 +277,9 @@ void main() { test('update pageCount', () async { when( () => booksRepository.updateBookPageCount( - id: any(named: 'id'), pageCount: any(named: 'pageCount')), + id: any(named: 'id'), + pageCount: any(named: 'pageCount'), + ), ).thenAnswer((_) async => 1); final bookRowUpdated = await bookService.updatePageCount( @@ -268,8 +299,9 @@ void main() { }); test('delete book', () async { - when(() => booksRepository.deleteBookById(id: any(named: 'id'))) - .thenAnswer((_) async => 1); + when( + () => booksRepository.deleteBookById(id: any(named: 'id')), + ).thenAnswer((_) async => 1); final deleteBookRow = await bookService.deleteBook(id: '1'); @@ -281,60 +313,104 @@ void main() { test('get all book', () async { when( () => booksRepository.getAll(), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); //for author repository - when(() => authorsRepository.getAuthorById(id: any(named: 'id'))) - .thenAnswer((_) async => authorModel); + when( + () => authorsRepository.getAuthorById(id: any(named: 'id')), + ).thenAnswer((_) async => authorModel); // for category repository - when(() => categoriesRepository.getCategoryById(id: any(named: 'id'))) - .thenAnswer((_) async => categoryModel); + when( + () => categoriesRepository.getCategoryById(id: any(named: 'id')), + ).thenAnswer((_) async => categoryModel); // for book authors repository - when(() => bookAuthorsRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookAuthorsRelationship]); + when( + () => bookAuthorsRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookAuthorsRelationship]); // for book categories repository - when(() => bookCategoriesRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookCategoriesRelationship]); + when( + () => bookCategoriesRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookCategoriesRelationship]); expect( () async => await bookService.getAllBook(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get book by name', () async { when( () => booksRepository.getBooksByTitle(title: any(named: 'title')), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); //for author repository - when(() => authorsRepository.getAuthorById(id: any(named: 'id'))) - .thenAnswer((_) async => authorModel); + when( + () => authorsRepository.getAuthorById(id: any(named: 'id')), + ).thenAnswer((_) async => authorModel); // for category repository - when(() => categoriesRepository.getCategoryById(id: any(named: 'id'))) - .thenAnswer((_) async => categoryModel); + when( + () => categoriesRepository.getCategoryById(id: any(named: 'id')), + ).thenAnswer((_) async => categoryModel); // for book authors repository - when(() => bookAuthorsRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookAuthorsRelationship]); + when( + () => bookAuthorsRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookAuthorsRelationship]); // for book categories repository - when(() => bookCategoriesRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookCategoriesRelationship]); + when( + () => bookCategoriesRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookCategoriesRelationship]); expect( () async => await bookService.getBooksByTitle(title: 'title'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -347,46 +423,86 @@ void main() { ).thenAnswer((_) async => bookModel); //for author repository - when(() => authorsRepository.getAuthorById(id: any(named: 'id'))) - .thenAnswer((_) async => authorModel); + when( + () => authorsRepository.getAuthorById(id: any(named: 'id')), + ).thenAnswer((_) async => authorModel); // for category repository - when(() => categoriesRepository.getCategoryById(id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => categoriesRepository.getCategoryById(id: any(named: 'id')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); // for book authors repository - when(() => bookAuthorsRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookAuthorsRelationship]); + when( + () => bookAuthorsRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookAuthorsRelationship]); // for book categories repository - when(() => bookCategoriesRepository.getRelationshipsById( - bookId: any(named: 'bookId'))) - .thenAnswer((_) async => [bookCategoriesRelationship]); + when( + () => bookCategoriesRepository.getRelationshipsById( + bookId: any(named: 'bookId'), + ), + ).thenAnswer((_) async => [bookCategoriesRelationship]); expect( () async => await bookService.getBookById(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('countBooks', () async { when( () => booksRepository.countBooks(), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookService.countBooks(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('insert complete book', () async { // setUp all when - final completeBookModel = bookModel - .copyWith(authors: [authorModel], categories: [categoryModel]); + final completeBookModel = bookModel.copyWith( + authors: [authorModel], + categories: [categoryModel], + ); //for book repository when( @@ -396,17 +512,24 @@ void main() { //for author repository when( () => authorsRepository.getAuthorIdByColumnName( - authorName: any(named: 'authorName')), + authorName: any(named: 'authorName'), + ), ).thenAnswer((_) async => -1); when( () => authorsRepository.insert(authorModel: authorModel), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); // for category repository when( () => categoriesRepository.getCategoryIdByColumnName( - categoryName: any(named: 'categoryName')), + categoryName: any(named: 'categoryName'), + ), ).thenAnswer((_) async => 1); // for book authors repository @@ -428,87 +551,201 @@ void main() { expect( () async => await bookService.insertCompleteBook(bookModel: completeBookModel), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('verify book is exist', () async { - when(() => booksRepository.verifyBookIsAlreadyInserted( - id: any(named: 'id'), - )).thenThrow(const LocalDatabaseException('Error on database')); + when( + () => booksRepository.verifyBookIsAlreadyInserted( + id: any(named: 'id'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookService.verifyBookIsAlreadyInserted(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get status', () async { when( () => booksRepository.getBookStatus(id: any(named: 'id')), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookService.getBookStatus(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('update status', () async { when( () => booksRepository.updateBookStatus( - id: any(named: 'id'), status: BookStatus.reading), - ).thenThrow(const LocalDatabaseException('Error on database')); + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookService.updateStatus( id: '1', status: BookStatus.reading, ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('update pageCount', () async { when( () => booksRepository.updateBookPageCount( - id: any(named: 'id'), pageCount: any(named: 'pageCount')), - ).thenThrow(const LocalDatabaseException('Error on database')); + id: any(named: 'id'), + pageCount: any(named: 'pageCount'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookService.updatePageCount( id: '1', pageCount: 100, ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get book Image', () async { when( () => booksRepository.getBookImageById(id: any(named: 'id')), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookService.getBookImage(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('delete book', () async { - when(() => booksRepository.deleteBookById(id: any(named: 'id'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => booksRepository.deleteBookById(id: any(named: 'id')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookService.deleteBook(id: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/services/bookcase_service/bookcase_service_impl_test.dart b/test/src/core/services/bookcase_service/bookcase_service_impl_test.dart index 7c5780f6..c6b919fc 100644 --- a/test/src/core/services/bookcase_service/bookcase_service_impl_test.dart +++ b/test/src/core/services/bookcase_service/bookcase_service_impl_test.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/core/repositories/book_on_case_repository/book_on_case_repository.dart'; import 'package:bookify/src/core/repositories/bookcase_repository/bookcase_repository.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -36,8 +37,9 @@ void main() { group('test normal CRUD of complete book without error ||', () { test('getAllBookcases()', () async { - when(() => bookcaseRepository.getAll()) - .thenAnswer((_) async => bookcases); + when( + () => bookcaseRepository.getAll(), + ).thenAnswer((_) async => bookcases); final bookcasesModel = await bookcaseService.getAllBookcases(); @@ -50,12 +52,13 @@ void main() { }); test('getBookcasesByName()', () async { - when(() => - bookcaseRepository.getBookcasesByName(name: any(named: 'name'))) - .thenAnswer((_) async => [bookcases[0]]); + when( + () => bookcaseRepository.getBookcasesByName(name: any(named: 'name')), + ).thenAnswer((_) async => [bookcases[0]]); - final bookcaseModel = - await bookcaseService.getBookcasesByName(name: 'name'); + final bookcaseModel = await bookcaseService.getBookcasesByName( + name: 'name', + ); expect(bookcaseModel[0].name, equals('name')); expect(bookcaseModel[0].description, equals('description')); @@ -63,17 +66,21 @@ void main() { }); test('getAllBookcaseRelationships()', () async { - when(() => bookOnCaseRepository - .getBooksOnCaseRelationship(bookcaseId: any(named: 'bookcaseId'))) - .thenAnswer((_) async => [ - {'bookcaseId': 1, 'bookId': '1'}, - {'bookcaseId': 1, 'bookId': '2'}, - {'bookcaseId': 1, 'bookId': '5'}, - {'bookcaseId': 1, 'bookId': '6'}, - ]); - - final bookcasesRelationships = - await bookcaseService.getAllBookcaseRelationships(bookcaseId: 1); + when( + () => bookOnCaseRepository.getBooksOnCaseRelationship( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( + (_) async => [ + {'bookcaseId': 1, 'bookId': '1'}, + {'bookcaseId': 1, 'bookId': '2'}, + {'bookcaseId': 1, 'bookId': '5'}, + {'bookcaseId': 1, 'bookId': '6'}, + ], + ); + + final bookcasesRelationships = await bookcaseService + .getAllBookcaseRelationships(bookcaseId: 1); expect(bookcasesRelationships[0]['bookcaseId'], equals(1)); expect(bookcasesRelationships[0]['bookId'], equals('1')); @@ -86,31 +93,39 @@ void main() { }); test('getBookIdForImagePreview()', () async { - when(() => bookOnCaseRepository.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId'))) - .thenAnswer((_) async => 'bookId'); + when( + () => bookOnCaseRepository.getBookIdForImagePreview( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => 'bookId'); - final bookId = - await bookcaseService.getBookIdForImagePreview(bookcaseId: 1); + final bookId = await bookcaseService.getBookIdForImagePreview( + bookcaseId: 1, + ); expect(bookId, equals('bookId')); }); test('getBookIdForImagePreview() -- with null', () async { - when(() => bookOnCaseRepository.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer((_) async => null); + when( + () => bookOnCaseRepository.getBookIdForImagePreview( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => null); - final bookId = - await bookcaseService.getBookIdForImagePreview(bookcaseId: 1); + final bookId = await bookcaseService.getBookIdForImagePreview( + bookcaseId: 1, + ); expect(bookId, isNull); }); test('getBookcaseById()', () async { - when(() => - bookcaseRepository.getById(bookcaseId: any(named: 'bookcaseId'))) - .thenAnswer((_) async => bookcases[0]); + when( + () => bookcaseRepository.getById(bookcaseId: any(named: 'bookcaseId')), + ).thenAnswer((_) async => bookcases[0]); - final bookcaseModel = - await bookcaseService.getBookcaseById(bookcaseId: 1); + final bookcaseModel = await bookcaseService.getBookcaseById( + bookcaseId: 1, + ); expect(bookcaseModel.name, equals('name')); expect(bookcaseModel.description, equals('description')); @@ -122,8 +137,9 @@ void main() { () => bookcaseRepository.insert(bookcaseModel: bookcases[0]), ).thenAnswer((_) async => 1); - final newBookcaseId = - await bookcaseService.insertBookcase(bookcaseModel: bookcases[0]); + final newBookcaseId = await bookcaseService.insertBookcase( + bookcaseModel: bookcases[0], + ); expect(newBookcaseId, equals(1)); }); @@ -131,7 +147,9 @@ void main() { test('insertBookcaseRelationship()', () async { when( () => bookOnCaseRepository.insert( - bookcaseId: any(named: 'bookcaseId'), bookId: any(named: 'bookId')), + bookcaseId: any(named: 'bookcaseId'), + bookId: any(named: 'bookId'), + ), ).thenAnswer((_) async => 1); final newRelationshipRow = await bookcaseService @@ -172,8 +190,9 @@ void main() { () => bookcaseRepository.update(bookcaseModel: bookcases[0]), ).thenAnswer((_) async => 1); - final bookcaseRowUpdated = - await bookcaseService.updateBookcase(bookcaseModel: bookcases[0]); + final bookcaseRowUpdated = await bookcaseService.updateBookcase( + bookcaseModel: bookcases[0], + ); expect(bookcaseRowUpdated, equals(1)); }); @@ -183,8 +202,9 @@ void main() { () => bookcaseRepository.delete(bookcaseId: any(named: 'bookcaseId')), ).thenAnswer((_) async => 1); - final bookcaseRowDeleted = - await bookcaseService.deleteBookcase(bookcaseId: 1); + final bookcaseRowDeleted = await bookcaseService.deleteBookcase( + bookcaseId: 1, + ); expect(bookcaseRowDeleted, equals(1)); }); @@ -206,102 +226,239 @@ void main() { group('test normal CRUD of complete book with error ||', () { test('getAllBookcases()', () async { - when(() => bookcaseRepository.getAll()) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => bookcaseRepository.getAll(), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.getAllBookcases(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('getBookcasesByName()', () async { - when(() => - bookcaseRepository.getBookcasesByName(name: any(named: 'name'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => bookcaseRepository.getBookcasesByName(name: any(named: 'name')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.getBookcasesByName(name: 'name'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('getAllBookcaseRelationships()', () async { - when(() => bookOnCaseRepository.getBooksOnCaseRelationship( - bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => bookOnCaseRepository.getBooksOnCaseRelationship( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('getBookIdForImagePreview()', () async { - when(() => bookOnCaseRepository.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => bookOnCaseRepository.getBookIdForImagePreview( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.getBookIdForImagePreview(bookcaseId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('getBookcaseById()', () async { - when(() => - bookcaseRepository.getById(bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(const LocalDatabaseException('Error on database')); + when( + () => bookcaseRepository.getById(bookcaseId: any(named: 'bookcaseId')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.getBookcaseById(bookcaseId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('insertBookcase()', () async { when( () => bookcaseRepository.insert(bookcaseModel: bookcases[0]), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.insertBookcase(bookcaseModel: bookcases[0]), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('insertBookcaseRelationship()', () async { when( () => bookOnCaseRepository.insert( - bookcaseId: any(named: 'bookcaseId'), bookId: any(named: 'bookId')), - ).thenThrow(const LocalDatabaseException('Error on database')); + bookcaseId: any(named: 'bookcaseId'), + bookId: any(named: 'bookId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.insertBookcaseRelationship( - bookcaseId: 1, bookId: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + bookcaseId: 1, + bookId: '1', + ), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('countBookcases()', () async { when( () => bookcaseRepository.countBookcases(), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.countBookcases(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -312,39 +469,87 @@ void main() { named: 'bookId', ), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.countBookcasesByBook( bookId: '1', ), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('updateBookcase()', () async { when( () => bookcaseRepository.update(bookcaseModel: bookcases[0]), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.updateBookcase(bookcaseModel: bookcases[0]), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('deleteBookcase()', () async { when( () => bookcaseRepository.delete(bookcaseId: any(named: 'bookcaseId')), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.deleteBookcase(bookcaseId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -354,13 +559,31 @@ void main() { bookcaseId: any(named: 'bookcaseId'), bookId: any(named: 'bookId'), ), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await bookcaseService.deleteBookcaseRelationship( - bookcaseId: 1, bookId: '1'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on database'), + bookcaseId: 1, + bookId: '1', + ), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/services/loan_services/loan_service_impl_test.dart b/test/src/core/services/loan_services/loan_service_impl_test.dart index 28fb664e..f72d447a 100644 --- a/test/src/core/services/loan_services/loan_service_impl_test.dart +++ b/test/src/core/services/loan_services/loan_service_impl_test.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/loan_model.dart'; import 'package:bookify/src/core/repositories/loan_repository/loan_repository.dart'; import 'package:bookify/src/core/services/loan_services/loan_service_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -62,10 +63,11 @@ void main() { equals(DateTime(2024, 01, 10)), ); expect( - loansModel[0].devolutionDate, - equals( - DateTime(DateTime.april, 2024), - )); + loansModel[0].devolutionDate, + equals( + DateTime(DateTime.april, 2024), + ), + ); expect(loansModel[0].idContact, equals('idContact')); expect(loansModel[0].bookId, equals('bookId')); }); @@ -89,17 +91,19 @@ void main() { equals(DateTime(2024, 01, 10)), ); expect( - loansModel[0].devolutionDate, - equals( - DateTime(DateTime.april, 2024), - )); + loansModel[0].devolutionDate, + equals( + DateTime(DateTime.april, 2024), + ), + ); expect(loansModel[0].idContact, equals('idContact')); expect(loansModel[0].bookId, equals('bookId')); }); test('get by Id', () async { - when(() => loanRepository.getById(loanId: any(named: 'loanId'))) - .thenAnswer( + when( + () => loanRepository.getById(loanId: any(named: 'loanId')), + ).thenAnswer( (_) async => loans[1], ); @@ -112,10 +116,11 @@ void main() { equals(DateTime(2024, 01, 10)), ); expect( - loanModel.devolutionDate, - equals( - DateTime(DateTime.april, 2024), - )); + loanModel.devolutionDate, + equals( + DateTime(DateTime.april, 2024), + ), + ); expect(loanModel.idContact, equals('idContact')); expect(loanModel.bookId, equals('bookId')); }); @@ -172,13 +177,30 @@ void main() { group('test normal CRUD of loan service with error ||', () { test('get all -- LocalDatabaseException', () async { - when(() => loanRepository.getAll()) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => loanRepository.getAll(), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanService.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -187,68 +209,168 @@ void main() { () => loanRepository.getLoansByBookTitle( title: any(named: 'title'), ), - ).thenThrow(const LocalDatabaseException('Error on Database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanService.getLoansByBookTitle(title: 'title'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get by Id -- LocalDatabaseException', () async { - when(() => loanRepository.getById(loanId: any(named: 'loanId'))) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => loanRepository.getById(loanId: any(named: 'loanId')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanService.getById(loanId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('countLoans -- LocalDatabaseException', () async { when( () => loanRepository.countLoans(), - ).thenThrow(const LocalDatabaseException('Error on Database')); - + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); + expect( () async => await loanService.countLoans(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('insert -- LocalDatabaseException', () async { - when(() => loanRepository.insert(loanModel: loans[1])) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => loanRepository.insert(loanModel: loans[1]), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanService.insert(loanModel: loans[1]), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('update -- LocalDatabaseException', () async { - when(() => loanRepository.update(loanModel: loans[1])) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => loanRepository.update(loanModel: loans[1]), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanService.update(loanModel: loans[1]), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('delete -- LocalDatabaseException', () async { - when(() => loanRepository.delete(loanId: any(named: 'loanId'))) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => loanRepository.delete(loanId: any(named: 'loanId')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await loanService.delete(loanId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/core/services/reading_services/reading_service_impl_test.dart b/test/src/core/services/reading_services/reading_service_impl_test.dart index 524acd64..dcffee72 100644 --- a/test/src/core/services/reading_services/reading_service_impl_test.dart +++ b/test/src/core/services/reading_services/reading_service_impl_test.dart @@ -2,6 +2,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/repositories/reading_repository/reading_repository.dart'; import 'package:bookify/src/core/services/reading_services/reading_service_impl.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -82,8 +83,9 @@ void main() { }); test('get by Id', () async { - when(() => readingRepository.getById(readingId: any(named: 'readingId'))) - .thenAnswer( + when( + () => readingRepository.getById(readingId: any(named: 'readingId')), + ).thenAnswer( (_) async => readings[1], ); @@ -150,13 +152,30 @@ void main() { group('test normal CRUD of reading service with error ||', () { test('get all -- LocalDatabaseException', () async { - when(() => readingRepository.getAll()) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => readingRepository.getAll(), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingService.getAll(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); @@ -165,68 +184,168 @@ void main() { () => readingRepository.getReadingsByBookTitle( title: any(named: 'title'), ), - ).thenThrow(const LocalDatabaseException('Error on Database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingService.getReadingsByBookTitle(title: 'title'), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('get by Id -- LocalDatabaseException', () async { - when(() => readingRepository.getById(readingId: any(named: 'readingId'))) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => readingRepository.getById(readingId: any(named: 'readingId')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingService.getById(readingId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('countReadings -- LocalDatabaseException', () async { when( () => readingRepository.countReadings(), - ).thenThrow(const LocalDatabaseException('Error on Database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingService.countReadings(), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('insert -- LocalDatabaseException', () async { - when(() => readingRepository.insert(readingModel: readings[1])) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => readingRepository.insert(readingModel: readings[1]), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingService.insert(readingModel: readings[1]), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('update -- LocalDatabaseException', () async { - when(() => readingRepository.update(readingModel: readings[1])) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => readingRepository.update(readingModel: readings[1]), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingService.update(readingModel: readings[1]), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); test('delete -- LocalDatabaseException', () async { - when(() => readingRepository.delete(readingId: any(named: 'readingId'))) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => readingRepository.delete(readingId: any(named: 'readingId')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); expect( () async => await readingService.delete(readingId: 1), - throwsA((Exception e) => - e is LocalDatabaseException && e.message == 'Error on Database'), + throwsA( + isA() + .having( + (e) => e.code, + 'code', + LocalDatabaseErrorCode.unknown, + ) + .having( + (e) => e.descriptionMessage, + 'descriptionMessage', + 'Error on database', + ), + ), ); }); }); diff --git a/test/src/features/book_detail/bloc/book_detail_bloc_test.dart b/test/src/features/book_detail/bloc/book_detail_bloc_test.dart index 1bc2d5e0..770f8cf8 100644 --- a/test/src/features/book_detail/bloc/book_detail_bloc_test.dart +++ b/test/src/features/book_detail/bloc/book_detail_bloc_test.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/models/author_model.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -48,8 +49,9 @@ void main() { ).thenAnswer((_) async => true), act: (bloc) => bloc.add(VerifiedBookIsInsertedEvent(bookId: '1')), verify: (_) { - verify(() => bookService.verifyBookIsAlreadyInserted(id: '1')) - .called(1); + verify( + () => bookService.verifyBookIsAlreadyInserted(id: '1'), + ).called(1); }, expect: () => [ isA(), @@ -60,13 +62,20 @@ void main() { blocTest( 'test if VerifiedBookIsInsertedEvent work with error state', build: () => bookDetailBloc, - setUp: () => when( - () => bookService.verifyBookIsAlreadyInserted(id: any(named: 'id')), - ).thenThrow(const LocalDatabaseException('error on database')), + setUp: () => + when( + () => bookService.verifyBookIsAlreadyInserted(id: any(named: 'id')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add(VerifiedBookIsInsertedEvent(bookId: '1')), verify: (_) { - verify(() => bookService.verifyBookIsAlreadyInserted(id: '1')) - .called(1); + verify( + () => bookService.verifyBookIsAlreadyInserted(id: '1'), + ).called(1); }, expect: () => [ isA(), @@ -82,8 +91,9 @@ void main() { ).thenThrow(Exception('generic exception')), act: (bloc) => bloc.add(VerifiedBookIsInsertedEvent(bookId: '1')), verify: (_) { - verify(() => bookService.verifyBookIsAlreadyInserted(id: '1')) - .called(1); + verify( + () => bookService.verifyBookIsAlreadyInserted(id: '1'), + ).called(1); }, expect: () => [ isA(), @@ -99,8 +109,9 @@ void main() { ).thenAnswer((_) async => 1), act: (bloc) => bloc.add(BookInsertedEvent(bookModel: bookModel)), verify: (_) { - verify(() => bookService.insertCompleteBook(bookModel: bookModel)) - .called(1); + verify( + () => bookService.insertCompleteBook(bookModel: bookModel), + ).called(1); }, expect: () => [ isA(), @@ -116,8 +127,9 @@ void main() { ).thenAnswer((_) async => 0), act: (bloc) => bloc.add(BookInsertedEvent(bookModel: bookModel)), verify: (_) { - verify(() => bookService.insertCompleteBook(bookModel: bookModel)) - .called(1); + verify( + () => bookService.insertCompleteBook(bookModel: bookModel), + ).called(1); }, expect: () => [ isA(), @@ -128,13 +140,20 @@ void main() { blocTest( 'test if BookInsertedEvent work with error state', build: () => bookDetailBloc, - setUp: () => when( - () => bookService.insertCompleteBook(bookModel: bookModel), - ).thenThrow(const LocalDatabaseException('error on database')), + setUp: () => + when( + () => bookService.insertCompleteBook(bookModel: bookModel), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add(BookInsertedEvent(bookModel: bookModel)), verify: (_) { - verify(() => bookService.insertCompleteBook(bookModel: bookModel)) - .called(1); + verify( + () => bookService.insertCompleteBook(bookModel: bookModel), + ).called(1); }, expect: () => [ isA(), @@ -150,8 +169,9 @@ void main() { ).thenThrow(Exception('generic exception')), act: (bloc) => bloc.add(BookInsertedEvent(bookModel: bookModel)), verify: (_) { - verify(() => bookService.insertCompleteBook(bookModel: bookModel)) - .called(1); + verify( + () => bookService.insertCompleteBook(bookModel: bookModel), + ).called(1); }, expect: () => [ isA(), @@ -243,7 +263,12 @@ void main() { setUp: () { when( () => bookService.deleteBook(id: '1'), - ).thenThrow(const LocalDatabaseException('error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); when( () => bookService.getBookStatus(id: '1'), ).thenAnswer((_) async => BookStatus.library); diff --git a/test/src/features/book_detail/views/book_detail_page_test.dart b/test/src/features/book_detail/views/book_detail_page_test.dart index 726fad98..f778616a 100644 --- a/test/src/features/book_detail/views/book_detail_page_test.dart +++ b/test/src/features/book_detail/views/book_detail_page_test.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/features/book_detail/bloc/book_detail_bloc.dart'; import 'package:bookify/src/features/book_detail/views/book_detail_page.dart'; import 'package:bookify/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -271,7 +272,8 @@ void main() { BookDetailLoadedState(bookIsInserted: false), BookDetailLoadingState(), BookDetailErrorState( - errorMessage: 'Error on inserting the book in database', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error on inserting the book in database', ), ]), ); @@ -289,7 +291,7 @@ void main() { expect( find.widgetWithText( SnackBar, - 'Error on inserting the book in database', + 'error-local-database-unknown', ), findsOneWidget, ); @@ -377,7 +379,8 @@ void main() { BookDetailLoadedState(bookIsInserted: true), BookDetailLoadingState(), BookDetailErrorState( - errorMessage: 'Error on removing the book from database', + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error on removing the book from database', ), ]), ); @@ -398,7 +401,7 @@ void main() { expect( find.widgetWithText( SnackBar, - 'Error on removing the book from database', + 'error-local-database-unknown', ), findsOneWidget, ); diff --git a/test/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc_test.dart b/test/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc_test.dart index 510bf889..dc2bc9d1 100644 --- a/test/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc_test.dart +++ b/test/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc_test.dart @@ -2,6 +2,7 @@ import 'package:bloc_test/bloc_test.dart'; import 'package:bookify/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -49,11 +50,17 @@ void main() { blocTest( 'test GotCountOfBookcasesByBookEvent work when throw LocalDatabaseException', build: () => bookOnBookcaseDetailBloc, - setUp: () => when( - () => bookcaseService.countBookcasesByBook( - bookId: any(named: 'bookId'), - ), - ).thenThrow(const LocalDatabaseException('Error on Database')), + setUp: () => + when( + () => bookcaseService.countBookcasesByBook( + bookId: any(named: 'bookId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add( GotCountOfBookcasesByBookEvent(bookId: 'bookId'), ), @@ -147,12 +154,18 @@ void main() { blocTest( 'test DeletedBookOnBookcaseEvent work throw LocalDatabaseException', build: () => bookOnBookcaseDetailBloc, - setUp: () => when( - () => bookcaseService.deleteBookcaseRelationship( - bookId: any(named: 'bookId'), - bookcaseId: any(named: 'bookcaseId'), - ), - ).thenThrow(const LocalDatabaseException('Error on Database')), + setUp: () => + when( + () => bookcaseService.deleteBookcaseRelationship( + bookId: any(named: 'bookId'), + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add( DeletedBookOnBookcaseEvent( bookId: 'bookId', diff --git a/test/src/features/bookcase/bloc/bookcase_bloc_test.dart b/test/src/features/bookcase/bloc/bookcase_bloc_test.dart index 6327f346..8101eeb1 100644 --- a/test/src/features/bookcase/bloc/bookcase_bloc_test.dart +++ b/test/src/features/bookcase/bloc/bookcase_bloc_test.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -52,22 +53,27 @@ void main() { 'test if GotAllBookcaseEvent work', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()) - .thenAnswer((_) async => bookcasesModel); + when( + () => bookcaseService.getAllBookcases(), + ).thenAnswer((_) async => bookcasesModel); - when(() => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId'))) - .thenAnswer((_) async => 'bookId'); + when( + () => bookcaseService.getBookIdForImagePreview( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => 'bookId'); - when(() => bookService.getBookImage(id: any(named: 'id'))) - .thenAnswer((_) async => 'bookImg'); + when( + () => bookService.getBookImage(id: any(named: 'id')), + ).thenAnswer((_) async => 'bookImg'); }, act: (bloc) => bloc.add(GotAllBookcasesEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verify( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ).called(2); verify(() => bookService.getBookImage(id: any(named: 'id'))).called(2); }, @@ -81,15 +87,17 @@ void main() { 'test if GotAllBookcaseEvent work when is empty List', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()) - .thenAnswer((_) async => []); + when( + () => bookcaseService.getAllBookcases(), + ).thenAnswer((_) async => []); }, act: (bloc) => bloc.add(GotAllBookcasesEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -103,20 +111,23 @@ void main() { 'test if GotAllBookcaseEvent work when bookcaseId is null', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()).thenAnswer((_) async => [ - const BookcaseModel( - name: 'name', - description: 'description', - color: Colors.black, - ), - ]); + when(() => bookcaseService.getAllBookcases()).thenAnswer( + (_) async => [ + const BookcaseModel( + name: 'name', + description: 'description', + color: Colors.black, + ), + ], + ); }, act: (bloc) => bloc.add(GotAllBookcasesEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -130,15 +141,22 @@ void main() { 'test if GotAllBookcaseEvent work when throw LocalDatabaseException', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => bookcaseService.getAllBookcases(), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add(GotAllBookcasesEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -152,15 +170,17 @@ void main() { 'test if GotAllBookcaseEvent work when throw Generic Exception', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()) - .thenThrow(Exception('Generic Error')); + when( + () => bookcaseService.getAllBookcases(), + ).thenThrow(Exception('Generic Error')); }, act: (bloc) => bloc.add(GotAllBookcasesEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -174,31 +194,38 @@ void main() { 'test if FoundBookcaseByNameEvent work', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .thenAnswer((_) async => [ - const BookcaseModel( - id: 1, - name: 'Fantasia', - description: 'Fantasia Description', - color: Colors.black, - ), - ]); - when(() => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId'))) - .thenAnswer((_) async => 'bookId'); + when( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).thenAnswer( + (_) async => [ + const BookcaseModel( + id: 1, + name: 'Fantasia', + description: 'Fantasia Description', + color: Colors.black, + ), + ], + ); + when( + () => bookcaseService.getBookIdForImagePreview( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => 'bookId'); - when(() => bookService.getBookImage(id: any(named: 'id'))) - .thenAnswer((_) async => 'bookImg'); + when( + () => bookService.getBookImage(id: any(named: 'id')), + ).thenAnswer((_) async => 'bookImg'); }, act: (bloc) => bloc.add(FoundBookcaseByNameEvent(searchQueryName: 'Fantasia')), verify: (_) { - verify(() => - bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .called(1); + verify( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).called(1); verify( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ).called(1); verify(() => bookService.getBookImage(id: any(named: 'id'))).called(1); }, @@ -212,15 +239,16 @@ void main() { 'test if FoundBookcaseByNameEvent work hen is empty List', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .thenAnswer((_) async => []); + when( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).thenAnswer((_) async => []); }, act: (bloc) => bloc.add(FoundBookcaseByNameEvent(searchQueryName: 'Fantasia')), verify: (_) { - verify(() => - bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .called(1); + verify( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( bookcaseId: any(named: 'bookcaseId'), @@ -242,24 +270,28 @@ void main() { 'test if FoundBookcaseByNameEvent work when bookcaseId is null', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .thenAnswer((_) async => [ - const BookcaseModel( - name: 'Fantasia', - description: 'description', - color: Colors.black, - ), - ]); + when( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).thenAnswer( + (_) async => [ + const BookcaseModel( + name: 'Fantasia', + description: 'description', + color: Colors.black, + ), + ], + ); }, act: (bloc) => bloc.add(FoundBookcaseByNameEvent(searchQueryName: 'Fantasia')), verify: (_) { - verify(() => - bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .called(1); + verify( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -273,18 +305,25 @@ void main() { 'test if FoundBookcaseByNameEvent work when throw LocalDatabaseException', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add(FoundBookcaseByNameEvent(searchQueryName: 'Fantasia')), verify: (_) { - verify(() => - bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .called(1); + verify( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -298,18 +337,20 @@ void main() { 'test if FoundBookcaseByNameEvent work when throw Generic Exception', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .thenThrow(Exception('Generic Error')); + when( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).thenThrow(Exception('Generic Error')); }, act: (bloc) => bloc.add(FoundBookcaseByNameEvent(searchQueryName: 'Fantasia')), verify: (_) { - verify(() => - bookcaseService.getBookcasesByName(name: any(named: 'name'))) - .called(1); + verify( + () => bookcaseService.getBookcasesByName(name: any(named: 'name')), + ).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -323,15 +364,22 @@ void main() { 'test if DeletedBookcasesEvent work', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer((_) async => 1); - when(() => bookcaseService.getAllBookcases()) - .thenAnswer((_) async => bookcasesModel); - when(() => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId'))) - .thenAnswer((_) async => 'bookId'); - when(() => bookService.getBookImage(id: any(named: 'id'))) - .thenAnswer((_) async => 'bookImg'); + when( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => 1); + when( + () => bookcaseService.getAllBookcases(), + ).thenAnswer((_) async => bookcasesModel); + when( + () => bookcaseService.getBookIdForImagePreview( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => 'bookId'); + when( + () => bookService.getBookImage(id: any(named: 'id')), + ).thenAnswer((_) async => 'bookImg'); }, act: (bloc) => bloc.add( DeletedBookcasesEvent( @@ -341,8 +389,11 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).called(1); + verify( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).called(1); verify(() => bookcaseService.getAllBookcases()).called(1); verify( () => bookcaseService.getBookIdForImagePreview( @@ -361,8 +412,11 @@ void main() { 'test if DeletedBookcasesEvent work with error on delete', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer((_) async => -1); + when( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => -1); }, act: (bloc) => bloc.add( DeletedBookcasesEvent( @@ -372,8 +426,11 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).called(1); + verify( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).called(1); verifyNever(() => bookcaseService.getAllBookcases()); verifyNever( () => bookcaseService.getBookIdForImagePreview( @@ -392,10 +449,14 @@ void main() { 'test if DeletedBookcasesEvent work with empty list', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer((_) async => 1); - when(() => bookcaseService.getAllBookcases()) - .thenAnswer((_) async => []); + when( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => 1); + when( + () => bookcaseService.getAllBookcases(), + ).thenAnswer((_) async => []); }, act: (bloc) => bloc.add( DeletedBookcasesEvent( @@ -405,12 +466,16 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).called(1); + verify( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).called(1); verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -424,9 +489,16 @@ void main() { 'test if DeletedBookcasesEvent work when throw LocalDatabaseException', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add( DeletedBookcasesEvent( @@ -436,12 +508,16 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).called(1); + verify( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).called(1); verifyNever(() => bookcaseService.getAllBookcases()); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -455,9 +531,11 @@ void main() { 'test if DeletedBookcasesEvent work when throw Generic Exception', build: () => bookcaseBloc, setUp: () async { - when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(Exception('Generic Exception')); + when( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenThrow(Exception('Generic Exception')); }, act: (bloc) => bloc.add( DeletedBookcasesEvent( @@ -467,12 +545,16 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).called(1); + verify( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).called(1); verifyNever(() => bookcaseService.getAllBookcases()); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, diff --git a/test/src/features/bookcase/views/bookcase_page_test.dart b/test/src/features/bookcase/views/bookcase_page_test.dart index ab2a19a7..2078376c 100644 --- a/test/src/features/bookcase/views/bookcase_page_test.dart +++ b/test/src/features/bookcase/views/bookcase_page_test.dart @@ -3,6 +3,7 @@ import 'package:bookify/src/core/dtos/bookcase_dto.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/features/bookcase/bloc/bookcase_bloc.dart'; import 'package:bookify/src/features/bookcase/views/bookcase_page.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -95,7 +96,10 @@ void main() { 'Test find Bookcase Error state Widget when Bloc emit Error', (tester) async { when(() => bookcaseBloc.state).thenReturn( - BookcaseErrorState(errorMessage: 'Error message'), + BookcaseErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Error message', + ), ); await _initBookcasePage(tester, bookcaseBloc); @@ -106,7 +110,7 @@ void main() { ); expect( - find.text('Error message'), + find.text('error-local-database-unknown'), findsOne, ); }, diff --git a/test/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc_test.dart b/test/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc_test.dart index e1f7ba20..7e46cfae 100644 --- a/test/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc_test.dart +++ b/test/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc_test.dart @@ -6,6 +6,7 @@ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -54,7 +55,7 @@ void main() { buyLink: 'buyLink', averageRating: 4.5, ratingsCount: 720, - ) + ), ]; final bookRelationShip = [ @@ -93,8 +94,11 @@ void main() { act: (bloc) => bloc.add(GotAllBooksForThisBookcaseEvent(bookcaseId: 1)), verify: (_) { verify(() => bookService.getAllBook()).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).called(1); }, expect: () => [ isA(), @@ -123,8 +127,11 @@ void main() { act: (bloc) => bloc.add(GotAllBooksForThisBookcaseEvent(bookcaseId: 1)), verify: (_) { verify(() => bookService.getAllBook()).called(1); - verifyNever(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))); + verifyNever( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ); }, expect: () => [ isA(), @@ -146,7 +153,7 @@ void main() { { 'bookcaseId': 1, 'bookId': '2', - } + }, ], ); @@ -159,8 +166,11 @@ void main() { act: (bloc) => bloc.add(GotAllBooksForThisBookcaseEvent(bookcaseId: 1)), verify: (_) { verify(() => bookService.getAllBook()).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).called(1); }, expect: () => [ isA(), @@ -182,19 +192,27 @@ void main() { { 'bookcaseId': 1, 'bookId': '2', - } + }, ], ); when( () => bookService.getAllBook(), - ).thenThrow(const LocalDatabaseException('Error on Database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add(GotAllBooksForThisBookcaseEvent(bookcaseId: 1)), verify: (_) { verify(() => bookService.getAllBook()).called(1); - verifyNever(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))); + verifyNever( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ); }, expect: () => [ isA(), @@ -216,7 +234,7 @@ void main() { { 'bookcaseId': 1, 'bookId': '2', - } + }, ], ); @@ -242,45 +260,48 @@ void main() { blocTest( 'Test if InsertBooksOnBookcaseEvent work', build: () => bloc, - setUp: () => when( - () => bookcaseService.insertBookcaseRelationship( - bookcaseId: any(named: 'bookcaseId'), - bookId: any(named: 'bookId'), + setUp: () => + when( + () => bookcaseService.insertBookcaseRelationship( + bookcaseId: any(named: 'bookcaseId'), + bookId: any(named: 'bookId'), + ), + ).thenAnswer( + (invocation) async => 1, + ), + act: (bloc) => bloc.add( + InsertBooksOnBookcaseEvent( + bookcaseId: 2, + books: [ + BookModel( + id: '1', + title: 'title', + authors: [AuthorModel.withEmptyName()], + publisher: 'publisher', + description: 'description', + categories: [CategoryModel.withEmptyName()], + pageCount: 320, + imageUrl: 'imageUrl', + buyLink: 'buyLink', + averageRating: 4.5, + ratingsCount: 720, + ), + BookModel( + id: '2', + title: 'title', + authors: [AuthorModel.withEmptyName()], + publisher: 'publisher', + description: 'description', + categories: [CategoryModel.withEmptyName()], + pageCount: 320, + imageUrl: 'imageUrl', + buyLink: 'buyLink', + averageRating: 4.5, + ratingsCount: 720, + ), + ], ), - ).thenAnswer( - (invocation) async => 1, ), - act: (bloc) => bloc.add(InsertBooksOnBookcaseEvent( - bookcaseId: 2, - books: [ - BookModel( - id: '1', - title: 'title', - authors: [AuthorModel.withEmptyName()], - publisher: 'publisher', - description: 'description', - categories: [CategoryModel.withEmptyName()], - pageCount: 320, - imageUrl: 'imageUrl', - buyLink: 'buyLink', - averageRating: 4.5, - ratingsCount: 720, - ), - BookModel( - id: '2', - title: 'title', - authors: [AuthorModel.withEmptyName()], - publisher: 'publisher', - description: 'description', - categories: [CategoryModel.withEmptyName()], - pageCount: 320, - imageUrl: 'imageUrl', - buyLink: 'buyLink', - averageRating: 4.5, - ratingsCount: 720, - ) - ], - )), verify: (_) => verify( () => bookcaseService.insertBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), @@ -302,37 +323,39 @@ void main() { bookId: any(named: 'bookId'), ), ).thenAnswer((_) async => 0), - act: (bloc) => bloc.add(InsertBooksOnBookcaseEvent( - bookcaseId: 2, - books: [ - BookModel( - id: '1', - title: 'title', - authors: [AuthorModel.withEmptyName()], - publisher: 'publisher', - description: 'description', - categories: [CategoryModel.withEmptyName()], - pageCount: 320, - imageUrl: 'imageUrl', - buyLink: 'buyLink', - averageRating: 4.5, - ratingsCount: 720, - ), - BookModel( - id: '2', - title: 'title', - authors: [AuthorModel.withEmptyName()], - publisher: 'publisher', - description: 'description', - categories: [CategoryModel.withEmptyName()], - pageCount: 320, - imageUrl: 'imageUrl', - buyLink: 'buyLink', - averageRating: 4.5, - ratingsCount: 720, - ) - ], - )), + act: (bloc) => bloc.add( + InsertBooksOnBookcaseEvent( + bookcaseId: 2, + books: [ + BookModel( + id: '1', + title: 'title', + authors: [AuthorModel.withEmptyName()], + publisher: 'publisher', + description: 'description', + categories: [CategoryModel.withEmptyName()], + pageCount: 320, + imageUrl: 'imageUrl', + buyLink: 'buyLink', + averageRating: 4.5, + ratingsCount: 720, + ), + BookModel( + id: '2', + title: 'title', + authors: [AuthorModel.withEmptyName()], + publisher: 'publisher', + description: 'description', + categories: [CategoryModel.withEmptyName()], + pageCount: 320, + imageUrl: 'imageUrl', + buyLink: 'buyLink', + averageRating: 4.5, + ratingsCount: 720, + ), + ], + ), + ), verify: (_) => verify( () => bookcaseService.insertBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), @@ -348,43 +371,51 @@ void main() { blocTest( 'Test if InsertBooksOnBookcaseEvent work when throw LocalDatabaseException', build: () => bloc, - setUp: () => when( - () => bookcaseService.insertBookcaseRelationship( - bookcaseId: any(named: 'bookcaseId'), - bookId: any(named: 'bookId'), - ), - ).thenThrow(const LocalDatabaseException('Error on Database')), - act: (bloc) => bloc.add(InsertBooksOnBookcaseEvent( - bookcaseId: 2, - books: [ - BookModel( - id: '1', - title: 'title', - authors: [AuthorModel.withEmptyName()], - publisher: 'publisher', - description: 'description', - categories: [CategoryModel.withEmptyName()], - pageCount: 320, - imageUrl: 'imageUrl', - buyLink: 'buyLink', - averageRating: 4.5, - ratingsCount: 720, + setUp: () => + when( + () => bookcaseService.insertBookcaseRelationship( + bookcaseId: any(named: 'bookcaseId'), + bookId: any(named: 'bookId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), ), - BookModel( - id: '2', - title: 'title', - authors: [AuthorModel.withEmptyName()], - publisher: 'publisher', - description: 'description', - categories: [CategoryModel.withEmptyName()], - pageCount: 320, - imageUrl: 'imageUrl', - buyLink: 'buyLink', - averageRating: 4.5, - ratingsCount: 720, - ) - ], - )), + act: (bloc) => bloc.add( + InsertBooksOnBookcaseEvent( + bookcaseId: 2, + books: [ + BookModel( + id: '1', + title: 'title', + authors: [AuthorModel.withEmptyName()], + publisher: 'publisher', + description: 'description', + categories: [CategoryModel.withEmptyName()], + pageCount: 320, + imageUrl: 'imageUrl', + buyLink: 'buyLink', + averageRating: 4.5, + ratingsCount: 720, + ), + BookModel( + id: '2', + title: 'title', + authors: [AuthorModel.withEmptyName()], + publisher: 'publisher', + description: 'description', + categories: [CategoryModel.withEmptyName()], + pageCount: 320, + imageUrl: 'imageUrl', + buyLink: 'buyLink', + averageRating: 4.5, + ratingsCount: 720, + ), + ], + ), + ), verify: (_) => verify( () => bookcaseService.insertBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), @@ -406,37 +437,39 @@ void main() { bookId: any(named: 'bookId'), ), ).thenThrow(Exception('Generic Exception')), - act: (bloc) => bloc.add(InsertBooksOnBookcaseEvent( - bookcaseId: 2, - books: [ - BookModel( - id: '1', - title: 'title', - authors: [AuthorModel.withEmptyName()], - publisher: 'publisher', - description: 'description', - categories: [CategoryModel.withEmptyName()], - pageCount: 320, - imageUrl: 'imageUrl', - buyLink: 'buyLink', - averageRating: 4.5, - ratingsCount: 720, - ), - BookModel( - id: '2', - title: 'title', - authors: [AuthorModel.withEmptyName()], - publisher: 'publisher', - description: 'description', - categories: [CategoryModel.withEmptyName()], - pageCount: 320, - imageUrl: 'imageUrl', - buyLink: 'buyLink', - averageRating: 4.5, - ratingsCount: 720, - ) - ], - )), + act: (bloc) => bloc.add( + InsertBooksOnBookcaseEvent( + bookcaseId: 2, + books: [ + BookModel( + id: '1', + title: 'title', + authors: [AuthorModel.withEmptyName()], + publisher: 'publisher', + description: 'description', + categories: [CategoryModel.withEmptyName()], + pageCount: 320, + imageUrl: 'imageUrl', + buyLink: 'buyLink', + averageRating: 4.5, + ratingsCount: 720, + ), + BookModel( + id: '2', + title: 'title', + authors: [AuthorModel.withEmptyName()], + publisher: 'publisher', + description: 'description', + categories: [CategoryModel.withEmptyName()], + pageCount: 320, + imageUrl: 'imageUrl', + buyLink: 'buyLink', + averageRating: 4.5, + ratingsCount: 720, + ), + ], + ), + ), verify: (_) => verify( () => bookcaseService.insertBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), diff --git a/test/src/features/bookcase_detail/bloc/bookcase_detail_bloc_test.dart b/test/src/features/bookcase_detail/bloc/bookcase_detail_bloc_test.dart index e78afd13..08e77500 100644 --- a/test/src/features/bookcase_detail/bloc/bookcase_detail_bloc_test.dart +++ b/test/src/features/bookcase_detail/bloc/bookcase_detail_bloc_test.dart @@ -6,6 +6,7 @@ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -55,8 +56,11 @@ void main() { () => bookService.getBookById(id: any(named: 'id')), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [ {'bookcaseId': 1, 'bookId': 'id'}, ], @@ -65,8 +69,9 @@ void main() { act: (bloc) => bloc.add(GotBookcaseBooksEvent(bookcaseId: 1)), verify: (bloc) { verify(() => bookService.getBookById(id: 'id')).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -82,16 +87,20 @@ void main() { () => bookService.getBookById(id: any(named: 'id')), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [], ); }, act: (bloc) => bloc.add(GotBookcaseBooksEvent(bookcaseId: 1)), verify: (_) { verifyNever(() => bookService.getBookById(id: 'id')); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -105,10 +114,18 @@ void main() { setUp: () { when( () => bookService.getBookById(id: any(named: 'id')), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [ {'bookcaseId': 1, 'bookId': 'id'}, ], @@ -117,8 +134,9 @@ void main() { act: (bloc) => bloc.add(GotBookcaseBooksEvent(bookcaseId: 1)), verify: (_) { verify(() => bookService.getBookById(id: 'id')).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -134,8 +152,11 @@ void main() { () => bookService.getBookById(id: any(named: 'id')), ).thenThrow(Exception('Generic Error')); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [ {'bookcaseId': 1, 'bookId': 'id'}, ], @@ -144,8 +165,9 @@ void main() { act: (bloc) => bloc.add(GotBookcaseBooksEvent(bookcaseId: 1)), verify: (_) { verify(() => bookService.getBookById(id: 'id')).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -157,8 +179,10 @@ void main() { blocTest( 'test if DeletedBookcaseEvent work', build: () => bloc, - setUp: () => when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer((_) async => 1), + setUp: () => when( + () => + bookcaseService.deleteBookcase(bookcaseId: any(named: 'bookcaseId')), + ).thenAnswer((_) async => 1), act: (bloc) => bloc.add(DeletedBookcaseEvent(bookcaseId: 1)), verify: (_) { verify(() => bookcaseService.deleteBookcase(bookcaseId: 1)).called(1); @@ -172,8 +196,10 @@ void main() { blocTest( 'test if DeletedBookcaseEvent work with deleted is -1', build: () => bloc, - setUp: () => when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer((_) async => -1), + setUp: () => when( + () => + bookcaseService.deleteBookcase(bookcaseId: any(named: 'bookcaseId')), + ).thenAnswer((_) async => -1), act: (bloc) => bloc.add(DeletedBookcaseEvent(bookcaseId: 1)), verify: (_) { verify(() => bookcaseService.deleteBookcase(bookcaseId: 1)).called(1); @@ -187,9 +213,17 @@ void main() { blocTest( 'test if DeletedBookcaseEvent work when throw LocalDatabaseException', build: () => bloc, - setUp: () => when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(const LocalDatabaseException('Error on database')), + setUp: () => + when( + () => bookcaseService.deleteBookcase( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add(DeletedBookcaseEvent(bookcaseId: 1)), verify: (_) { verify(() => bookcaseService.deleteBookcase(bookcaseId: 1)).called(1); @@ -203,9 +237,10 @@ void main() { blocTest( 'test if DeletedBookcaseEvent work when throw Generic Exception', build: () => bloc, - setUp: () => when(() => bookcaseService.deleteBookcase( - bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(Exception('Generic Error')), + setUp: () => when( + () => + bookcaseService.deleteBookcase(bookcaseId: any(named: 'bookcaseId')), + ).thenThrow(Exception('Generic Error')), act: (bloc) => bloc.add(DeletedBookcaseEvent(bookcaseId: 1)), verify: (_) { verify(() => bookcaseService.deleteBookcase(bookcaseId: 1)).called(1); @@ -233,8 +268,11 @@ void main() { id: any(named: 'id'), ), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [ {'bookcaseId': 1, 'bookId': 'id'}, ], @@ -247,12 +285,16 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcaseRelationship( + verify( + () => bookcaseService.deleteBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), - bookId: any(named: 'bookId'))).called(1); + bookId: any(named: 'bookId'), + ), + ).called(1); verify(() => bookService.getBookById(id: 'id')).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -277,8 +319,11 @@ void main() { id: any(named: 'id'), ), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [ {'bookcaseId': 1, 'bookId': 'id'}, ], @@ -291,12 +336,16 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcaseRelationship( + verify( + () => bookcaseService.deleteBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), - bookId: any(named: 'bookId'))).called(1); + bookId: any(named: 'bookId'), + ), + ).called(1); verifyNever(() => bookService.getBookById(id: 'id')); verifyNever( - () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)); + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ); }, expect: () => [ isA(), @@ -321,8 +370,11 @@ void main() { id: any(named: 'id'), ), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [], ); }, @@ -333,9 +385,12 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcaseRelationship( + verify( + () => bookcaseService.deleteBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), - bookId: any(named: 'bookId'))).called(1); + bookId: any(named: 'bookId'), + ), + ).called(1); verifyNever(() => bookService.getBookById(id: 'id')); verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)); }, @@ -362,9 +417,16 @@ void main() { id: any(named: 'id'), ), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add( DeletedBooksOnBookcaseEvent( @@ -373,9 +435,12 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcaseRelationship( + verify( + () => bookcaseService.deleteBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), - bookId: any(named: 'bookId'))).called(1); + bookId: any(named: 'bookId'), + ), + ).called(1); verifyNever(() => bookService.getBookById(id: 'id')); verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)); }, @@ -402,9 +467,11 @@ void main() { id: any(named: 'id'), ), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))) - .thenThrow(Exception('Generic Exception')); + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenThrow(Exception('Generic Exception')); }, act: (bloc) => bloc.add( DeletedBooksOnBookcaseEvent( @@ -413,9 +480,12 @@ void main() { ), ), verify: (_) { - verify(() => bookcaseService.deleteBookcaseRelationship( + verify( + () => bookcaseService.deleteBookcaseRelationship( bookcaseId: any(named: 'bookcaseId'), - bookId: any(named: 'bookId'))).called(1); + bookId: any(named: 'bookId'), + ), + ).called(1); verifyNever(() => bookService.getBookById(id: 'id')); verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)); }, diff --git a/test/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc_test.dart b/test/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc_test.dart index 26a2110d..5164d23a 100644 --- a/test/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc_test.dart +++ b/test/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc_test.dart @@ -4,6 +4,7 @@ import 'package:bookify/src/features/bookcase_insertion/bloc/bookcase_insertion_ import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -37,18 +38,20 @@ void main() { blocTest( 'Test InsertedBookcaseEvent() work', build: () => bookcaseInsertionBloc, - setUp: () => when(() => - bookcaseService.insertBookcase(bookcaseModel: bookcaseModel)) - .thenAnswer((_) async => 4), - act: (bloc) => bloc.add(InsertedBookcaseEvent( - name: 'name', - description: 'description', - color: Colors.pink, - )), + setUp: () => when( + () => bookcaseService.insertBookcase(bookcaseModel: bookcaseModel), + ).thenAnswer((_) async => 4), + act: (bloc) => bloc.add( + InsertedBookcaseEvent( + name: 'name', + description: 'description', + color: Colors.pink, + ), + ), verify: (_) { - verify(() => - bookcaseService.insertBookcase(bookcaseModel: bookcaseModel)) - .called(1); + verify( + () => bookcaseService.insertBookcase(bookcaseModel: bookcaseModel), + ).called(1); }, expect: () => [ isA(), @@ -59,18 +62,20 @@ void main() { blocTest( 'Test InsertedBookcaseEvent() with Error on insertion work', build: () => bookcaseInsertionBloc, - setUp: () => when(() => - bookcaseService.insertBookcase(bookcaseModel: bookcaseModel)) - .thenAnswer((_) async => 0), - act: (bloc) => bloc.add(InsertedBookcaseEvent( - name: 'name', - description: 'description', - color: Colors.pink, - )), + setUp: () => when( + () => bookcaseService.insertBookcase(bookcaseModel: bookcaseModel), + ).thenAnswer((_) async => 0), + act: (bloc) => bloc.add( + InsertedBookcaseEvent( + name: 'name', + description: 'description', + color: Colors.pink, + ), + ), verify: (_) { - verify(() => - bookcaseService.insertBookcase(bookcaseModel: bookcaseModel)) - .called(1); + verify( + () => bookcaseService.insertBookcase(bookcaseModel: bookcaseModel), + ).called(1); }, expect: () => [ isA(), @@ -81,18 +86,26 @@ void main() { blocTest( 'Test InsertedBookcaseEvent() with LocalDatabaseException work', build: () => bookcaseInsertionBloc, - setUp: () => when(() => - bookcaseService.insertBookcase(bookcaseModel: bookcaseModel)) - .thenThrow(const LocalDatabaseException('Error on database')), - act: (bloc) => bloc.add(InsertedBookcaseEvent( - name: 'name', - description: 'description', - color: Colors.pink, - )), + setUp: () => + when( + () => bookcaseService.insertBookcase(bookcaseModel: bookcaseModel), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), + act: (bloc) => bloc.add( + InsertedBookcaseEvent( + name: 'name', + description: 'description', + color: Colors.pink, + ), + ), verify: (_) { - verify(() => - bookcaseService.insertBookcase(bookcaseModel: bookcaseModel)) - .called(1); + verify( + () => bookcaseService.insertBookcase(bookcaseModel: bookcaseModel), + ).called(1); }, expect: () => [ isA(), @@ -103,18 +116,20 @@ void main() { blocTest( 'Test InsertedBookcaseEvent() with generic Exception work', build: () => bookcaseInsertionBloc, - setUp: () => when(() => - bookcaseService.insertBookcase(bookcaseModel: bookcaseModel)) - .thenThrow(Exception('Generic Exception')), - act: (bloc) => bloc.add(InsertedBookcaseEvent( - name: 'name', - description: 'description', - color: Colors.pink, - )), + setUp: () => when( + () => bookcaseService.insertBookcase(bookcaseModel: bookcaseModel), + ).thenThrow(Exception('Generic Exception')), + act: (bloc) => bloc.add( + InsertedBookcaseEvent( + name: 'name', + description: 'description', + color: Colors.pink, + ), + ), verify: (_) { - verify(() => - bookcaseService.insertBookcase(bookcaseModel: bookcaseModel)) - .called(1); + verify( + () => bookcaseService.insertBookcase(bookcaseModel: bookcaseModel), + ).called(1); }, expect: () => [ isA(), @@ -130,15 +145,20 @@ void main() { bookcaseModel: bookcaseModel.copyWith(id: 1), ), ).thenAnswer((_) async => 1), - act: (bloc) => bloc.add(UpdatedBookcaseEvent( - id: 1, - name: 'name', - description: 'description', - color: Colors.pink, - )), + act: (bloc) => bloc.add( + UpdatedBookcaseEvent( + id: 1, + name: 'name', + description: 'description', + color: Colors.pink, + ), + ), verify: (_) { - verify(() => bookcaseService.updateBookcase( - bookcaseModel: bookcaseModel.copyWith(id: 1))).called(1); + verify( + () => bookcaseService.updateBookcase( + bookcaseModel: bookcaseModel.copyWith(id: 1), + ), + ).called(1); }, expect: () => [ isA(), @@ -154,15 +174,20 @@ void main() { bookcaseModel: bookcaseModel.copyWith(id: 1), ), ).thenAnswer((_) async => 0), - act: (bloc) => bloc.add(UpdatedBookcaseEvent( - id: 1, - name: 'name', - description: 'description', - color: Colors.pink, - )), + act: (bloc) => bloc.add( + UpdatedBookcaseEvent( + id: 1, + name: 'name', + description: 'description', + color: Colors.pink, + ), + ), verify: (_) { - verify(() => bookcaseService.updateBookcase( - bookcaseModel: bookcaseModel.copyWith(id: 1))).called(1); + verify( + () => bookcaseService.updateBookcase( + bookcaseModel: bookcaseModel.copyWith(id: 1), + ), + ).called(1); }, expect: () => [ isA(), @@ -173,20 +198,31 @@ void main() { blocTest( 'Test UpdatedBookcaseEvent() with LocalDatabaseException work', build: () => bookcaseInsertionBloc, - setUp: () => when( - () => bookcaseService.updateBookcase( - bookcaseModel: bookcaseModel.copyWith(id: 1), + setUp: () => + when( + () => bookcaseService.updateBookcase( + bookcaseModel: bookcaseModel.copyWith(id: 1), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), + act: (bloc) => bloc.add( + UpdatedBookcaseEvent( + id: 1, + name: 'name', + description: 'description', + color: Colors.pink, ), - ).thenThrow(const LocalDatabaseException('Error on database')), - act: (bloc) => bloc.add(UpdatedBookcaseEvent( - id: 1, - name: 'name', - description: 'description', - color: Colors.pink, - )), + ), verify: (_) { - verify(() => bookcaseService.updateBookcase( - bookcaseModel: bookcaseModel.copyWith(id: 1))).called(1); + verify( + () => bookcaseService.updateBookcase( + bookcaseModel: bookcaseModel.copyWith(id: 1), + ), + ).called(1); }, expect: () => [ isA(), @@ -202,15 +238,20 @@ void main() { bookcaseModel: bookcaseModel.copyWith(id: 1), ), ).thenThrow(Exception('Generic Exception')), - act: (bloc) => bloc.add(UpdatedBookcaseEvent( - id: 1, - name: 'name', - description: 'description', - color: Colors.pink, - )), + act: (bloc) => bloc.add( + UpdatedBookcaseEvent( + id: 1, + name: 'name', + description: 'description', + color: Colors.pink, + ), + ), verify: (_) { - verify(() => bookcaseService.updateBookcase( - bookcaseModel: bookcaseModel.copyWith(id: 1))).called(1); + verify( + () => bookcaseService.updateBookcase( + bookcaseModel: bookcaseModel.copyWith(id: 1), + ), + ).called(1); }, expect: () => [ isA(), diff --git a/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart b/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart index f4517a71..219e20dc 100644 --- a/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart +++ b/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart @@ -2,6 +2,7 @@ import 'package:bloc_test/bloc_test.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart'; import 'package:bookify/src/features/bookcase_insertion/views/bookcase_insertion_page.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -115,7 +116,10 @@ void main() { whenListen( bookcaseInsertionBloc, Stream.fromIterable([ - BookcaseInsertionErrorState(errorMessage: 'Database Error'), + BookcaseInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: 'Database Error', + ), ]), ); @@ -130,7 +134,7 @@ void main() { await tester.pumpAndSettle(); expect(find.byType(SnackBar), findsOneWidget); - expect(find.text('Database Error'), findsOneWidget); + expect(find.text('error-local-database-unknown'), findsOneWidget); await tester.pumpAndSettle(const Duration(seconds: 2)); expect(find.byType(BookcaseInsertionPage), findsNothing); diff --git a/test/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc_test.dart b/test/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc_test.dart index d2a1cb0d..b9d61ce3 100644 --- a/test/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc_test.dart +++ b/test/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc_test.dart @@ -6,6 +6,7 @@ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -56,8 +57,11 @@ void main() { () => bookService.getBookById(id: any(named: 'id')), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [ {'bookcaseId': 1, 'bookId': 'id'}, ], @@ -66,8 +70,9 @@ void main() { act: (bloc) => bloc.add(GotAllBookOnBookcasePickerEvent(bookcaseId: 1)), verify: (bloc) { verify(() => bookService.getBookById(id: 'id')).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -83,16 +88,20 @@ void main() { () => bookService.getBookById(id: any(named: 'id')), ).thenAnswer((_) async => bookModel); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [], ); }, act: (bloc) => bloc.add(GotAllBookOnBookcasePickerEvent(bookcaseId: 1)), verify: (_) { verifyNever(() => bookService.getBookById(id: 'id')); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -107,18 +116,23 @@ void main() { when( () => bookService.getBookById(id: any(named: 'id')), ).thenAnswer( - (_) async => bookModel.copyWith(status: BookStatus.loaned)); + (_) async => bookModel.copyWith(status: BookStatus.loaned), + ); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [], ); }, act: (bloc) => bloc.add(GotAllBookOnBookcasePickerEvent(bookcaseId: 1)), verify: (_) { verifyNever(() => bookService.getBookById(id: 'id')); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -132,10 +146,18 @@ void main() { setUp: () { when( () => bookService.getBookById(id: any(named: 'id')), - ).thenThrow(const LocalDatabaseException('Error on database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [ {'bookcaseId': 1, 'bookId': 'id'}, ], @@ -144,8 +166,9 @@ void main() { act: (bloc) => bloc.add(GotAllBookOnBookcasePickerEvent(bookcaseId: 1)), verify: (_) { verify(() => bookService.getBookById(id: 'id')).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), @@ -161,8 +184,11 @@ void main() { () => bookService.getBookById(id: any(named: 'id')), ).thenThrow(Exception('Generic Error')); - when(() => bookcaseService.getAllBookcaseRelationships( - bookcaseId: any(named: 'bookcaseId'))).thenAnswer( + when( + () => bookcaseService.getAllBookcaseRelationships( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer( (_) async => [ {'bookcaseId': 1, 'bookId': 'id'}, ], @@ -171,8 +197,9 @@ void main() { act: (bloc) => bloc.add(GotAllBookOnBookcasePickerEvent(bookcaseId: 1)), verify: (_) { verify(() => bookService.getBookById(id: 'id')).called(1); - verify(() => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1)) - .called(1); + verify( + () => bookcaseService.getAllBookcaseRelationships(bookcaseId: 1), + ).called(1); }, expect: () => [ isA(), diff --git a/test/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc_test.dart b/test/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc_test.dart index c1ca55db..8bfe74c2 100644 --- a/test/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc_test.dart +++ b/test/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc_test.dart @@ -4,6 +4,7 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_ import 'package:bookify/src/core/models/bookcase_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -51,21 +52,26 @@ void main() { 'test if GotAllBookcasePickerEvent work', build: () => bookcasePickerBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()) - .thenAnswer((_) async => bookcasesModel); - when(() => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId'))) - .thenAnswer((_) async => 'bookId'); + when( + () => bookcaseService.getAllBookcases(), + ).thenAnswer((_) async => bookcasesModel); + when( + () => bookcaseService.getBookIdForImagePreview( + bookcaseId: any(named: 'bookcaseId'), + ), + ).thenAnswer((_) async => 'bookId'); - when(() => bookService.getBookImage(id: any(named: 'id'))) - .thenAnswer((_) async => 'bookImg'); + when( + () => bookService.getBookImage(id: any(named: 'id')), + ).thenAnswer((_) async => 'bookImg'); }, act: (bloc) => bloc.add(GotAllBookcasesPickerEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verify( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ).called(2); verify(() => bookService.getBookImage(id: any(named: 'id'))).called(2); }, @@ -79,15 +85,17 @@ void main() { 'test if GotAllBookcasePickerEvent work when is empty List', build: () => bookcasePickerBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()) - .thenAnswer((_) async => []); + when( + () => bookcaseService.getAllBookcases(), + ).thenAnswer((_) async => []); }, act: (bloc) => bloc.add(GotAllBookcasesPickerEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -101,20 +109,23 @@ void main() { 'test if GotAllBookcasePickerEvent work when bookcaseId is null', build: () => bookcasePickerBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()).thenAnswer((_) async => [ - const BookcaseModel( - name: 'name', - description: 'description', - color: Colors.black, - ), - ]); + when(() => bookcaseService.getAllBookcases()).thenAnswer( + (_) async => [ + const BookcaseModel( + name: 'name', + description: 'description', + color: Colors.black, + ), + ], + ); }, act: (bloc) => bloc.add(GotAllBookcasesPickerEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -128,15 +139,20 @@ void main() { 'test if GotAllBookcasePickerEvent work when throw LocalDatabaseException', build: () => bookcasePickerBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()) - .thenThrow(const LocalDatabaseException('Error on Database')); + when(() => bookcaseService.getAllBookcases()).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add(GotAllBookcasesPickerEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, @@ -150,15 +166,17 @@ void main() { 'test if GotAllBookcasePickerEvent work when throw Exception', build: () => bookcasePickerBloc, setUp: () async { - when(() => bookcaseService.getAllBookcases()) - .thenThrow(Exception('Generic Error')); + when( + () => bookcaseService.getAllBookcases(), + ).thenThrow(Exception('Generic Error')); }, act: (bloc) => bloc.add(GotAllBookcasesPickerEvent()), verify: (_) { verify(() => bookcaseService.getAllBookcases()).called(1); verifyNever( () => bookcaseService.getBookIdForImagePreview( - bookcaseId: any(named: 'bookcaseId')), + bookcaseId: any(named: 'bookcaseId'), + ), ); verifyNever(() => bookService.getBookImage(id: any(named: 'id'))); }, diff --git a/test/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc_test.dart b/test/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc_test.dart index b8a4dcad..8d12bc94 100644 --- a/test/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc_test.dart +++ b/test/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc_test.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/models/author_model.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -60,11 +61,12 @@ void main() { blocTest( 'Test if GotAllBooksEvent work', build: () => bloc, - setUp: () => when( - () => bookService.getAllBook(), - ).thenAnswer( - (_) async => booksModel, - ), + setUp: () => + when( + () => bookService.getAllBook(), + ).thenAnswer( + (_) async => booksModel, + ), act: (bloc) => bloc.add(GotAllSeparatedBooksPickerEvent()), verify: (_) => verify(() => bookService.getAllBook()).called(1), expect: () => [ @@ -76,11 +78,12 @@ void main() { blocTest( 'Test if GotAllBooksEvent work with empty state', build: () => bloc, - setUp: () => when( - () => bookService.getAllBook(), - ).thenAnswer( - (_) async => [], - ), + setUp: () => + when( + () => bookService.getAllBook(), + ).thenAnswer( + (_) async => [], + ), act: (bloc) => bloc.add(GotAllSeparatedBooksPickerEvent()), verify: (_) => verify(() => bookService.getAllBook()).called(1), expect: () => [ @@ -92,11 +95,12 @@ void main() { blocTest( 'Test if GotAllBooksEvent work with empty bookService', build: () => bloc, - setUp: () => when( - () => bookService.getAllBook(), - ).thenAnswer( - (_) async => [], - ), + setUp: () => + when( + () => bookService.getAllBook(), + ).thenAnswer( + (_) async => [], + ), act: (bloc) => bloc.add(GotAllSeparatedBooksPickerEvent()), verify: (_) => verify(() => bookService.getAllBook()).called(1), expect: () => [ @@ -108,11 +112,12 @@ void main() { blocTest( 'Test if GotAllBooksEvent work with empty book', build: () => bloc, - setUp: () => when( - () => bookService.getAllBook(), - ).thenAnswer( - (_) async => [booksModel.first.copyWith(status: BookStatus.loaned)], - ), + setUp: () => + when( + () => bookService.getAllBook(), + ).thenAnswer( + (_) async => [booksModel.first.copyWith(status: BookStatus.loaned)], + ), act: (bloc) => bloc.add(GotAllSeparatedBooksPickerEvent()), verify: (_) => verify(() => bookService.getAllBook()).called(1), expect: () => [ @@ -124,9 +129,15 @@ void main() { blocTest( 'Test if GotAllBooksEvent work when throw LocalDatabaseException', build: () => bloc, - setUp: () => when( - () => bookService.getAllBook(), - ).thenThrow(const LocalDatabaseException('Error on Database')), + setUp: () => + when( + () => bookService.getAllBook(), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add(GotAllSeparatedBooksPickerEvent()), verify: (_) => verify(() => bookService.getAllBook()).called(1), expect: () => [ diff --git a/test/src/features/loan/bloc/loan_bloc_test.dart b/test/src/features/loan/bloc/loan_bloc_test.dart index 7919587a..3642d5d1 100644 --- a/test/src/features/loan/bloc/loan_bloc_test.dart +++ b/test/src/features/loan/bloc/loan_bloc_test.dart @@ -11,6 +11,7 @@ import 'package:bookify/src/core/models/loan_model.dart'; import 'package:bookify/src/core/services/app_services/contacts_service/contacts_service.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/loan_services/loan_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -74,8 +75,9 @@ void main() { ), ); - when(() => contactsService.getContactById(id: any(named: 'id'))) - .thenAnswer( + when( + () => contactsService.getContactById(id: any(named: 'id')), + ).thenAnswer( (_) async => ContactModel( id: 'id', name: 'name', @@ -88,8 +90,9 @@ void main() { verify: (_) { verify(() => loanService.getAll()).called(1); verify(() => bookService.getBookById(id: any(named: 'id'))).called(1); - verify(() => contactsService.getContactById(id: any(named: 'id'))) - .called(1); + verify( + () => contactsService.getContactById(id: any(named: 'id')), + ).called(1); }, expect: () => [ isA(), @@ -161,7 +164,10 @@ void main() { id: any(named: 'id'), ), ).thenThrow( - const LocalDatabaseException('Error on Database'), + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), ); }, act: (bloc) => bloc.add(GotAllLoansEvent()), @@ -247,8 +253,9 @@ void main() { ), ); - when(() => contactsService.getContactById(id: any(named: 'id'))) - .thenAnswer( + when( + () => contactsService.getContactById(id: any(named: 'id')), + ).thenAnswer( (_) async => ContactModel( id: 'id', name: 'name', @@ -267,8 +274,9 @@ void main() { ), ).called(1); verify(() => bookService.getBookById(id: any(named: 'id'))).called(1); - verify(() => contactsService.getContactById(id: any(named: 'id'))) - .called(1); + verify( + () => contactsService.getContactById(id: any(named: 'id')), + ).called(1); }, expect: () => [ isA(), @@ -279,15 +287,17 @@ void main() { blocTest( 'Test FoundLoanByBookTitleEvent work when loans are empty', build: () => loanBloc, - setUp: () => when( - () => loanService.getLoansByBookTitle( - title: any(named: 'title'), - ), - ).thenAnswer( - (_) async => [], + setUp: () => + when( + () => loanService.getLoansByBookTitle( + title: any(named: 'title'), + ), + ).thenAnswer( + (_) async => [], + ), + act: (bloc) => bloc.add( + FoundLoanByBookTitleEvent(searchQueryName: 'searchQueryName'), ), - act: (bloc) => bloc - .add(FoundLoanByBookTitleEvent(searchQueryName: 'searchQueryName')), verify: (_) { verify( () => loanService.getLoansByBookTitle( @@ -307,8 +317,9 @@ void main() { 'Test FoundLoanByBookTitleEvent work when loan id is empty', build: () => loanBloc, setUp: () { - when(() => loanService.getLoansByBookTitle(title: any(named: 'title'))) - .thenAnswer( + when( + () => loanService.getLoansByBookTitle(title: any(named: 'title')), + ).thenAnswer( (_) async => [ LoanModel( observation: 'observation', @@ -320,8 +331,9 @@ void main() { ], ); }, - act: (bloc) => bloc - .add(FoundLoanByBookTitleEvent(searchQueryName: 'searchQueryName')), + act: (bloc) => bloc.add( + FoundLoanByBookTitleEvent(searchQueryName: 'searchQueryName'), + ), verify: (_) { verify( () => loanService.getLoansByBookTitle( @@ -341,8 +353,9 @@ void main() { 'Test FoundLoanByBookTitleEvent work when throw LocalDatabaseException', build: () => loanBloc, setUp: () { - when(() => loanService.getLoansByBookTitle(title: any(named: 'title'))) - .thenAnswer( + when( + () => loanService.getLoansByBookTitle(title: any(named: 'title')), + ).thenAnswer( (_) async => [ LoanModel( id: 1, @@ -359,16 +372,19 @@ void main() { id: any(named: 'id'), ), ).thenThrow( - const LocalDatabaseException('Error on Database'), + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), ); }, act: (bloc) => bloc.add( FoundLoanByBookTitleEvent(searchQueryName: 'searchQueryName'), ), verify: (_) { - verify(() => - loanService.getLoansByBookTitle(title: any(named: 'title'))) - .called(1); + verify( + () => loanService.getLoansByBookTitle(title: any(named: 'title')), + ).called(1); verify(() => bookService.getBookById(id: any(named: 'id'))).called(1); verifyNever(() => contactsService.getContactById(id: any(named: 'id'))); }, @@ -382,8 +398,9 @@ void main() { 'Test FoundLoanByBookTitleEvent work when throw Generic Exception', build: () => loanBloc, setUp: () { - when(() => loanService.getLoansByBookTitle(title: any(named: 'title'))) - .thenAnswer( + when( + () => loanService.getLoansByBookTitle(title: any(named: 'title')), + ).thenAnswer( (_) async => [ LoanModel( id: 1, diff --git a/test/src/features/loan_detail/bloc/loan_detail_bloc_test.dart b/test/src/features/loan_detail/bloc/loan_detail_bloc_test.dart index e4fdc217..f3c5f310 100644 --- a/test/src/features/loan_detail/bloc/loan_detail_bloc_test.dart +++ b/test/src/features/loan_detail/bloc/loan_detail_bloc_test.dart @@ -10,6 +10,7 @@ import 'package:bookify/src/core/services/app_services/contacts_service/contacts import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/loan_services/loan_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:mocktail/mocktail.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -144,7 +145,10 @@ void main() { id: any(named: 'id'), ), ).thenThrow( - const LocalDatabaseException('Error on database'), + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), ); }, act: (bloc) => bloc.add( @@ -413,7 +417,12 @@ void main() { () => loanService.delete( loanId: any(named: 'loanId'), ), - ).thenThrow(const LocalDatabaseException('Error on Database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add( FinishedLoanDetailEvent( diff --git a/test/src/features/loan_insertion/bloc/loan_insertion_bloc_test.dart b/test/src/features/loan_insertion/bloc/loan_insertion_bloc_test.dart index c6bef423..1ee53820 100644 --- a/test/src/features/loan_insertion/bloc/loan_insertion_bloc_test.dart +++ b/test/src/features/loan_insertion/bloc/loan_insertion_bloc_test.dart @@ -7,6 +7,7 @@ import 'package:bookify/src/core/models/custom_notification_model.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/loan_services/loan_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -210,7 +211,12 @@ void main() { id: 'bookId', status: BookStatus.loaned, ), - ).thenThrow(const LocalDatabaseException('Error on Database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add( InsertedLoanInsertionEvent( diff --git a/test/src/features/my_books/bloc/my_books_bloc_test.dart b/test/src/features/my_books/bloc/my_books_bloc_test.dart index 3c009533..db3ec2ca 100644 --- a/test/src/features/my_books/bloc/my_books_bloc_test.dart +++ b/test/src/features/my_books/bloc/my_books_bloc_test.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/models/author_model.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -58,11 +59,12 @@ void main() { blocTest( 'Test if GotAllBooksEvent work', build: () => bloc, - setUp: () => when( - () => bookService.getAllBook(), - ).thenAnswer( - (_) async => booksModel, - ), + setUp: () => + when( + () => bookService.getAllBook(), + ).thenAnswer( + (_) async => booksModel, + ), act: (bloc) => bloc.add(GotAllBooksEvent()), verify: (_) => verify(() => bookService.getAllBook()).called(1), expect: () => [ @@ -74,11 +76,12 @@ void main() { blocTest( 'Test if GotAllBooksEvent work with empty state', build: () => bloc, - setUp: () => when( - () => bookService.getAllBook(), - ).thenAnswer( - (_) async => [], - ), + setUp: () => + when( + () => bookService.getAllBook(), + ).thenAnswer( + (_) async => [], + ), act: (bloc) => bloc.add(GotAllBooksEvent()), verify: (_) => verify(() => bookService.getAllBook()).called(1), expect: () => [ @@ -90,9 +93,15 @@ void main() { blocTest( 'Test if GotAllBooksEvent work when throw LocalDatabaseException', build: () => bloc, - setUp: () => when( - () => bookService.getAllBook(), - ).thenThrow(const LocalDatabaseException('Error on Database')), + setUp: () => + when( + () => bookService.getAllBook(), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add(GotAllBooksEvent()), verify: (_) => verify(() => bookService.getAllBook()).called(1), expect: () => [ @@ -118,13 +127,14 @@ void main() { blocTest( 'Test if SearchedEvent work', build: () => bloc, - setUp: () => when( - () => bookService.getBooksByTitle( - title: any(named: 'title'), - ), - ).thenAnswer( - (_) async => booksModel, - ), + setUp: () => + when( + () => bookService.getBooksByTitle( + title: any(named: 'title'), + ), + ).thenAnswer( + (_) async => booksModel, + ), act: (bloc) => bloc.add( SearchedBooksEvent(searchQuery: 'title'), ), @@ -142,13 +152,14 @@ void main() { blocTest( 'Test if SearchedEvent work with not found state', build: () => bloc, - setUp: () => when( - () => bookService.getBooksByTitle( - title: any(named: 'title'), - ), - ).thenAnswer( - (_) async => [], - ), + setUp: () => + when( + () => bookService.getBooksByTitle( + title: any(named: 'title'), + ), + ).thenAnswer( + (_) async => [], + ), act: (bloc) => bloc.add( SearchedBooksEvent(searchQuery: 'title'), ), @@ -166,11 +177,17 @@ void main() { blocTest( 'Test if SearchedEvent work when throw LocalDatabaseException', build: () => bloc, - setUp: () => when( - () => bookService.getBooksByTitle( - title: any(named: 'title'), - ), - ).thenThrow(const LocalDatabaseException('Error on Database')), + setUp: () => + when( + () => bookService.getBooksByTitle( + title: any(named: 'title'), + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add( SearchedBooksEvent(searchQuery: 'title'), ), diff --git a/test/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc_test.dart b/test/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc_test.dart index 988c5cc1..00ca12af 100644 --- a/test/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc_test.dart +++ b/test/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc_test.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/bookcase_service/bookcase_service.dart'; import 'package:bookify/src/core/services/loan_services/loan_service.dart'; import 'package:bookify/src/core/services/reading_services/reading_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -104,7 +105,12 @@ void main() { when( () => bookcaseService.countBookcases(), - ).thenThrow(const LocalDatabaseException('Error on Database')); + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add(GotUserInformationEvent()), verify: (_) { diff --git a/test/src/features/readings/bloc/readings_bloc_test.dart b/test/src/features/readings/bloc/readings_bloc_test.dart index cc141f3b..5fb87ede 100644 --- a/test/src/features/readings/bloc/readings_bloc_test.dart +++ b/test/src/features/readings/bloc/readings_bloc_test.dart @@ -7,6 +7,7 @@ import 'package:bookify/src/core/models/category_model.dart'; import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/reading_services/reading_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -135,7 +136,10 @@ void main() { id: any(named: 'id'), ), ).thenThrow( - const LocalDatabaseException('Error on Database'), + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), ); }, act: (bloc) => bloc.add(GotAllReadingsEvent()), @@ -236,13 +240,14 @@ void main() { blocTest( 'Test FoundReadingByBookTitleEvent work when readings are empty', build: () => readingsBloc, - setUp: () => when( - () => readingService.getReadingsByBookTitle( - title: any(named: 'title'), - ), - ).thenAnswer( - (_) async => [], - ), + setUp: () => + when( + () => readingService.getReadingsByBookTitle( + title: any(named: 'title'), + ), + ).thenAnswer( + (_) async => [], + ), act: (bloc) => bloc.add( FoundReadingByBookTitleEvent(searchQueryName: 'searchQueryName'), ), @@ -263,19 +268,20 @@ void main() { blocTest( 'Test FoundReadingByBookTitleEvent work when reading id is empty', build: () => readingsBloc, - setUp: () => when( - () => readingService.getReadingsByBookTitle( - title: any(named: 'title'), - ), - ).thenAnswer( - (_) async => [ - ReadingModel( - pagesReaded: 100, - lastReadingDate: DateTime(2024, 03, 06), - bookId: 'bookId', + setUp: () => + when( + () => readingService.getReadingsByBookTitle( + title: any(named: 'title'), + ), + ).thenAnswer( + (_) async => [ + ReadingModel( + pagesReaded: 100, + lastReadingDate: DateTime(2024, 03, 06), + bookId: 'bookId', + ), + ], ), - ], - ), act: (bloc) => bloc.add( FoundReadingByBookTitleEvent(searchQueryName: 'searchQueryName'), ), @@ -297,8 +303,10 @@ void main() { 'Test FoundReadingByBookTitleEvent work when throw LocalDatabaseException', build: () => readingsBloc, setUp: () { - when(() => readingService.getReadingsByBookTitle( - title: any(named: 'title'))).thenAnswer( + when( + () => + readingService.getReadingsByBookTitle(title: any(named: 'title')), + ).thenAnswer( (_) async => [ ReadingModel( id: 1, @@ -313,15 +321,20 @@ void main() { id: any(named: 'id'), ), ).thenThrow( - const LocalDatabaseException('Error on Database'), + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), ); }, act: (bloc) => bloc.add( FoundReadingByBookTitleEvent(searchQueryName: 'searchQueryName'), ), verify: (_) { - verify(() => readingService.getReadingsByBookTitle( - title: any(named: 'title'))).called(1); + verify( + () => + readingService.getReadingsByBookTitle(title: any(named: 'title')), + ).called(1); verify(() => bookService.getBookById(id: any(named: 'id'))).called(1); }, expect: () => [ @@ -334,8 +347,10 @@ void main() { 'Test FoundReadingByBookTitleEvent work when throw Generic Exception', build: () => readingsBloc, setUp: () { - when(() => readingService.getReadingsByBookTitle( - title: any(named: 'title'))).thenAnswer( + when( + () => + readingService.getReadingsByBookTitle(title: any(named: 'title')), + ).thenAnswer( (_) async => [ ReadingModel( id: 1, @@ -357,8 +372,10 @@ void main() { FoundReadingByBookTitleEvent(searchQueryName: 'searchQueryName'), ), verify: (_) { - verify(() => readingService.getReadingsByBookTitle( - title: any(named: 'title'))).called(1); + verify( + () => + readingService.getReadingsByBookTitle(title: any(named: 'title')), + ).called(1); verify(() => bookService.getBookById(id: any(named: 'id'))).called(1); }, expect: () => [ diff --git a/test/src/features/readings_detail/bloc/readings_detail_bloc_test.dart b/test/src/features/readings_detail/bloc/readings_detail_bloc_test.dart index 547a65a2..d1428eb5 100644 --- a/test/src/features/readings_detail/bloc/readings_detail_bloc_test.dart +++ b/test/src/features/readings_detail/bloc/readings_detail_bloc_test.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/reading_services/reading_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -90,13 +91,17 @@ void main() { blocTest( 'Test UpdatedReadingsEvent work when throw LocalDatabaseException', build: () => readingsDetailBloc, - setUp: () => when( - () => readingService.update( - readingModel: readingModel, - ), - ).thenThrow( - const LocalDatabaseException('Error on Database'), - ), + setUp: () => + when( + () => readingService.update( + readingModel: readingModel, + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ), act: (bloc) => bloc.add( UpdatedReadingsEvent( readingModel: readingModel, @@ -116,13 +121,14 @@ void main() { blocTest( 'Test UpdatedReadingsEvent work when throw Generic Exception', build: () => readingsDetailBloc, - setUp: () => when( - () => readingService.update( - readingModel: readingModel, - ), - ).thenThrow( - Exception('Generic Error'), - ), + setUp: () => + when( + () => readingService.update( + readingModel: readingModel, + ), + ).thenThrow( + Exception('Generic Error'), + ), act: (bloc) => bloc.add( UpdatedReadingsEvent( readingModel: readingModel, @@ -270,7 +276,10 @@ void main() { readingId: any(named: 'readingId'), ), ).thenThrow( - const LocalDatabaseException('Error on Database'), + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), ); }, act: (bloc) => bloc.add( diff --git a/test/src/features/readings_insertion/bloc/readings_insertion_bloc_test.dart b/test/src/features/readings_insertion/bloc/readings_insertion_bloc_test.dart index 5f1b371d..ef4d9cd3 100644 --- a/test/src/features/readings_insertion/bloc/readings_insertion_bloc_test.dart +++ b/test/src/features/readings_insertion/bloc/readings_insertion_bloc_test.dart @@ -5,6 +5,7 @@ import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/reading_model.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; import 'package:bookify/src/core/services/reading_services/reading_service.dart'; +import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; @@ -41,23 +42,31 @@ void main() { 'Test InsertedLoanEvent work', build: () => readingsInsertionBloc, setUp: () { - when(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).thenAnswer((_) async => 1); - when(() => readingService.insert( - readingModel: readingModel, - )).thenAnswer((_) async => 1); + when( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).thenAnswer((_) async => 1); + when( + () => readingService.insert( + readingModel: readingModel, + ), + ).thenAnswer((_) async => 1); }, act: (bloc) => bloc.add(InsertedReadingsEvent(bookId: 'bookId')), verify: (_) { - verify(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).called(1); - verify(() => readingService.insert( - readingModel: readingModel, - )).called(1); + verify( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).called(1); + verify( + () => readingService.insert( + readingModel: readingModel, + ), + ).called(1); }, expect: () => [ isA(), @@ -69,32 +78,44 @@ void main() { 'Test InsertedLoanEvent work when pageCount != 0', build: () => readingsInsertionBloc, setUp: () { - when(() => bookService.updatePageCount( - id: any(named: 'id'), - pageCount: any(named: 'pageCount'), - )).thenAnswer((_) async => 1); - when(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).thenAnswer((_) async => 1); - when(() => readingService.insert( - readingModel: readingModel, - )).thenAnswer((_) async => 1); + when( + () => bookService.updatePageCount( + id: any(named: 'id'), + pageCount: any(named: 'pageCount'), + ), + ).thenAnswer((_) async => 1); + when( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).thenAnswer((_) async => 1); + when( + () => readingService.insert( + readingModel: readingModel, + ), + ).thenAnswer((_) async => 1); }, act: (bloc) => bloc.add(InsertedReadingsEvent(bookId: 'bookId', pagesUpdated: 100)), verify: (_) { - verify(() => bookService.updatePageCount( - id: any(named: 'id'), - pageCount: any(named: 'pageCount'), - )).called(1); - verify(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).called(1); - verify(() => readingService.insert( - readingModel: readingModel, - )).called(1); + verify( + () => bookService.updatePageCount( + id: any(named: 'id'), + pageCount: any(named: 'pageCount'), + ), + ).called(1); + verify( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).called(1); + verify( + () => readingService.insert( + readingModel: readingModel, + ), + ).called(1); }, expect: () => [ isA(), @@ -106,32 +127,44 @@ void main() { 'Test InsertedLoanEvent work when pageCount != 0 with error update', build: () => readingsInsertionBloc, setUp: () { - when(() => bookService.updatePageCount( - id: any(named: 'id'), - pageCount: any(named: 'pageCount'), - )).thenAnswer((_) async => 0); - when(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).thenAnswer((_) async => 1); - when(() => readingService.insert( - readingModel: readingModel, - )).thenAnswer((_) async => 1); + when( + () => bookService.updatePageCount( + id: any(named: 'id'), + pageCount: any(named: 'pageCount'), + ), + ).thenAnswer((_) async => 0); + when( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).thenAnswer((_) async => 1); + when( + () => readingService.insert( + readingModel: readingModel, + ), + ).thenAnswer((_) async => 1); }, act: (bloc) => bloc.add(InsertedReadingsEvent(bookId: 'bookId', pagesUpdated: 100)), verify: (_) { - verify(() => bookService.updatePageCount( - id: any(named: 'id'), - pageCount: any(named: 'pageCount'), - )).called(1); - verifyNever(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )); - verifyNever(() => readingService.insert( - readingModel: readingModel, - )); + verify( + () => bookService.updatePageCount( + id: any(named: 'id'), + pageCount: any(named: 'pageCount'), + ), + ).called(1); + verifyNever( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ); + verifyNever( + () => readingService.insert( + readingModel: readingModel, + ), + ); }, expect: () => [ isA(), @@ -143,23 +176,31 @@ void main() { 'Test InsertedLoanEvent work when update status error', build: () => readingsInsertionBloc, setUp: () { - when(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).thenAnswer((_) async => 0); - when(() => readingService.insert( - readingModel: readingModel, - )).thenAnswer((_) async => 1); + when( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).thenAnswer((_) async => 0); + when( + () => readingService.insert( + readingModel: readingModel, + ), + ).thenAnswer((_) async => 1); }, act: (bloc) => bloc.add(InsertedReadingsEvent(bookId: 'bookId')), verify: (_) { - verify(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).called(1); - verifyNever(() => readingService.insert( - readingModel: readingModel, - )); + verify( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).called(1); + verifyNever( + () => readingService.insert( + readingModel: readingModel, + ), + ); }, expect: () => [ isA(), @@ -171,23 +212,31 @@ void main() { 'Test InsertedLoanEvent work when reading insertion error', build: () => readingsInsertionBloc, setUp: () { - when(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).thenAnswer((_) async => 1); - when(() => readingService.insert( - readingModel: readingModel, - )).thenAnswer((_) async => 0); + when( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).thenAnswer((_) async => 1); + when( + () => readingService.insert( + readingModel: readingModel, + ), + ).thenAnswer((_) async => 0); }, act: (bloc) => bloc.add(InsertedReadingsEvent(bookId: 'bookId')), verify: (_) { - verify(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).called(1); - verify(() => readingService.insert( - readingModel: readingModel, - )).called(1); + verify( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).called(1); + verify( + () => readingService.insert( + readingModel: readingModel, + ), + ).called(1); }, expect: () => [ isA(), @@ -199,23 +248,36 @@ void main() { 'Test InsertedLoanEvent work when throw LocalDatabaseException', build: () => readingsInsertionBloc, setUp: () { - when(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).thenAnswer((_) async => 1); - when(() => readingService.insert( - readingModel: readingModel, - )).thenThrow(const LocalDatabaseException('Error on Database')); + when( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).thenAnswer((_) async => 1); + when( + () => readingService.insert( + readingModel: readingModel, + ), + ).thenThrow( + const LocalDatabaseException( + LocalDatabaseErrorCode.unknown, + descriptionMessage: 'Error on database', + ), + ); }, act: (bloc) => bloc.add(InsertedReadingsEvent(bookId: 'bookId')), verify: (_) { - verify(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).called(1); - verify(() => readingService.insert( - readingModel: readingModel, - )).called(1); + verify( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).called(1); + verify( + () => readingService.insert( + readingModel: readingModel, + ), + ).called(1); }, expect: () => [ isA(), @@ -227,23 +289,31 @@ void main() { 'Test InsertedLoanEvent work when throw Generic Exception', build: () => readingsInsertionBloc, setUp: () { - when(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).thenAnswer((_) async => 1); - when(() => readingService.insert( - readingModel: readingModel, - )).thenThrow(Exception('Generic Error')); + when( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).thenAnswer((_) async => 1); + when( + () => readingService.insert( + readingModel: readingModel, + ), + ).thenThrow(Exception('Generic Error')); }, act: (bloc) => bloc.add(InsertedReadingsEvent(bookId: 'bookId')), verify: (_) { - verify(() => bookService.updateStatus( - id: any(named: 'id'), - status: BookStatus.reading, - )).called(1); - verify(() => readingService.insert( - readingModel: readingModel, - )).called(1); + verify( + () => bookService.updateStatus( + id: any(named: 'id'), + status: BookStatus.reading, + ), + ).called(1); + verify( + () => readingService.insert( + readingModel: readingModel, + ), + ).called(1); }, expect: () => [ isA(), From 00646c4ca7f796a11c16ebe12c2f58ce1e9e7c9a Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Tue, 19 May 2026 06:42:38 -0300 Subject: [PATCH 12/19] Refactor local database error handling and localization - Simplified error mapping in LocalDatabaseImpl by removing unnecessary checks for specific error types. - Updated LocalDatabaseErrorCode to include operationFailed and removed unused error codes. - Modified BookDetailBloc, BookOnBookcaseDetailBloc, BookcaseBloc, and other relevant blocs to use operationFailed for error handling. - Introduced BookcaseBooksEmptyReason and BookcaseInsertionSuccessReason enums for better state management and localization. - Updated UI components to reflect changes in state and display localized messages for success and error scenarios. - Adjusted tests to align with the new state management and localization structure. --- assets/lang/en_US.json | 12 +- assets/lang/it_IT.json | 16 +- assets/lang/pt_BR.json | 12 +- coverage/lcov.info | 4791 +++++++++-------- .../core/database/local_database_impl.dart | 32 +- .../local_database_error_code_extension.dart | 26 +- .../book_detail/bloc/book_detail_bloc.dart | 6 +- .../book_detail/bloc/book_detail_state.dart | 2 +- .../bloc/book_on_bookcase_detail_bloc.dart | 2 +- .../features/bookcase/bloc/bookcase_bloc.dart | 2 +- .../bloc/bookcase_books_insertion_bloc.dart | 9 +- .../bloc/bookcase_books_insertion_state.dart | 9 +- .../views/bookcase_books_insertion_page.dart | 9 +- .../bloc/bookcase_insertion_bloc.dart | 9 +- .../bloc/bookcase_insertion_state.dart | 9 +- .../views/bookcase_insertion_page.dart | 11 +- .../bloc/loan_insertion_bloc.dart | 2 +- .../bloc/readings_insertion_bloc.dart | 6 +- .../enums/local_database_error_code.dart | 8 +- pubspec.yaml | 2 +- .../views/bookcase_insertion_page_test.dart | 8 +- 21 files changed, 2490 insertions(+), 2493 deletions(-) diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index d39585ab..0563f2bf 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -87,6 +87,7 @@ "page-tooltip": "Page %s", "try-again-button": "Try again", "no-books-found-with-terms": "No books were found with these terms.\nCheck that you have typed them correctly.", + "no-books-registered": "No books registered. Go back to the home page to register.", "enter-title-label": "Enter the Title", "enter-author-label": "Enter the Author", "enter-category-label": "Enter the Category", @@ -101,6 +102,8 @@ "search-by-isbn-tooltip": "Search by ISBN", "book-successfully-added-snackbar": "Book successfully added.", "book-successfully-removed-snackbar": "Book successfully removed.", + "bookcase-inserted-success-snackbar": "Bookcase successfully added.", + "bookcase-updated-success-snackbar": "Bookcase successfully updated.", "remove-book-title": "Remove the book %s", "remove-book-description": "By clicking \"CONFIRM\" you will remove this book from your bookcase.\nAre you sure?", "pages-label": "%s PAGES", @@ -153,6 +156,7 @@ "delete-bookcase-description": "By clicking \"CONFIRM\" you will delete the bookcase %s.\nAre you sure?", "delete-books-title": "Delete books", "delete-books-description": "By clicking \"CONFIRM\" you will delete the selected books in this bookcase.\nAre you sure?", + "all-books-already-inserted": "All registered books have already been added to this bookcase.", "book-added-successfully-snackbar": "Book added successfully.\nWait until you are redirected to the previous page.", "select-books-title": "Select the books", "selected-books-quantity-label": "Selected books: %s", @@ -262,5 +266,11 @@ "error-storage-data-loss": "Error saving your data. Try syncing again or contact support if the issue continues: %s", "error-storage-not-found": "Your data could not be found. Try logging in again with your credentials: %s", "error-storage-write-failed": "Unable to save your changes. Check your storage space and try again: %s", - "error-storage-read-failed": "Unable to load your data. Check your internet connection and try again: %s" + "error-storage-read-failed": "Unable to load your data. Check your internet connection and try again: %s", + "error-local-database-invalid-data": "The data provided is not valid. %s", + "error-local-database-not-null-constraint": "A required field is empty. %s", + "error-local-database-open-failed": "Could not open the database. %s", + "error-local-database-operation-failed": "Database operation failed during read, write, or update. %s", + "error-local-database-unique-constraint": "This record already exists in the database. %s", + "error-local-database-unknown": "Unknown error in the database. %s" } diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index db940a9c..a7549238 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -20,7 +20,7 @@ "auth-success-snackbar": "Autenticazione avvenuta con successo.", "reading-time-success-snackbar": "Tempo di lettura calcolato con successo.", "reading-instruction-title": "Calcoliamo la tua velocità di lettura?", - "reading-instruction-description": "Leggi un breve estratto da un libro generato dall'IA mentre tracciamo il tuo tempo con un cronometro. Dopo il calcolo, ti verrà comunicato il tempo medio che ti ci è voluto per finire di leggere qualsiasi libro nell'app, basato sul tempo impiegato per leggere il testo.", + "reading-instruction-description": "Leggi un breve estratto da un libro generato dalla IA mentre tracciamo il tuo tempo con un cronometro. Dopo il calcolo, ti verrà comunicato il tempo medio che ti ci è voluto per finire di leggere qualsiasi libro nell'app, basato sul tempo impiegato per leggere il testo.", "calculate-later-button": "Calcola più tardi", "calculate-time-button": "Calcola tempo", "close-page-button-tooltip": "Chiudi la pagina", @@ -87,6 +87,7 @@ "page-tooltip": "Pagina %s", "try-again-button": "Riprova", "no-books-found-with-terms": "Nessun libro trovato con questi termini.\nVerifica che sia stato digitato correttamente.", + "no-books-registered": "Nessun libro registrato. Torna alla pagina iniziale per registrare.", "enter-title-label": "Inserisci il Titolo", "enter-author-label": "Inserisci l'Autore", "enter-category-label": "Inserisci la Categoria (in Inglese)", @@ -100,8 +101,8 @@ "search-by-publisher-tooltip": "Cerca per editore", "search-by-isbn-tooltip": "Cerca per ISBN", "book-successfully-added-snackbar": "Libro aggiunto con successo.", - "book-successfully-removed-snackbar": "Libro rimosso con successo.", - "remove-book-title": "Rimuovere il libro %s", + "book-successfully-removed-snackbar": "Libro rimosso con successo.", "bookcase-inserted-success-snackbar": "Libreria aggiunta con successo.", + "bookcase-updated-success-snackbar": "Libreria aggiornata con successo.", "remove-book-title": "Rimuovere il libro %s", "remove-book-description": "Cliccando su “CONFERMA” rimuoverai questo libro dal tuo Scaffale.\nSei sicuro?", "pages-label": "%s PAGINE", "go-to-store-button": "Vai allo store", @@ -153,6 +154,7 @@ "delete-bookcase-description": "Cliccando su “CONFERMA” eliminerai il scaffale %s.\nSei sicuro?", "delete-books-title": "Eliminare libri", "delete-books-description": "Cliccando su “CONFERMA” eliminerai i libri selezionati in questo scaffale.\nSei sicuro?", + "all-books-already-inserted": "Tutti i libri registrati sono già stati aggiunti a questo scaffale.", "books-added-successfully-snackbar": "Libro aggiunto con successo.\nAttendere fino al ritorno alla pagina precedente.", "select-books-title": "Seleziona i libri", "selected-books-quantity-label": "Libri selezionati: %s", @@ -262,5 +264,11 @@ "error-storage-data-loss": "Errore durante il salvataggio dei dati. Prova a sincronizzare di nuovo o contatta l'assistenza se il problema persiste: %s", "error-storage-not-found": "I tuoi dati non sono stati trovati. Prova ad accedere di nuovo con le tue credenziali: %s", "error-storage-write-failed": "Impossibile salvare le tue modifiche. Verifica lo spazio di archiviazione e riprova: %s", - "error-storage-read-failed": "Impossibile caricare i tuoi dati. Verifica la tua connessione internet e riprova: %s" + "error-storage-read-failed": "Impossibile caricare i tuoi dati. Verifica la tua connessione internet e riprova: %s", + "error-local-database-invalid-data": "I dati forniti non sono validi. %s", + "error-local-database-not-null-constraint": "Un campo obbligatorio è vuoto. %s", + "error-local-database-open-failed": "Impossibile aprire il database. %s", + "error-local-database-operation-failed": "Operazione del database fallita durante lettura, scrittura o aggiornamento. %s", + "error-local-database-unique-constraint": "Questo record esiste già nel database. %s", + "error-local-database-unknown": "Errore sconosciuto nel database. %s" } diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index 0e3a1899..dfb4fda8 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -87,6 +87,7 @@ "page-tooltip": "Página %s", "try-again-button": "Tentar novamente", "no-books-found-with-terms": "Não foi encontrado nenhum livro com esses termos.\nVerifique se digitou corretamente.", + "no-books-registered": "Nenhum livro cadastrado. Volte à página início para cadastrar.", "enter-title-label": "Digite o Título", "enter-author-label": "Digite o Autor", "enter-category-label": "Digite o Gênero (em Inglês)", @@ -101,6 +102,8 @@ "search-by-isbn-tooltip": "Buscar por ISBN", "book-successfully-added-snackbar": "Livro adicionado com sucesso.", "book-successfully-removed-snackbar": "Livro removido com sucesso.", + "bookcase-inserted-success-snackbar": "Estante inserida com sucesso.", + "bookcase-updated-success-snackbar": "Estante atualizada com sucesso.", "remove-book-title": "Remover o livro %s", "remove-book-description": "Clicando em \"CONFIRMAR\" você removerá este livro da sua estante.\nTem Certeza?", "pages-label": "%s PÁGINAS", @@ -153,6 +156,7 @@ "delete-bookcase-description": "Clicando em \"CONFIRMAR\" você removerá a estante %s.\nTem Certeza?", "delete-books-title": "Deletar livros", "delete-books-description": "Clicando em \"CONFIRMAR\" você removerá os livros selecionados dessa estante.\nTem certeza?", + "all-books-already-inserted": "Todos os livros cadastrados já foram adicionados nessa estante.", "books-added-successfully-snackbar": "Livro adicionado com sucesso.\nAguarde até voltar à página anterior.", "select-books-title": "Selecionar os livros", "selected-books-quantity-label": "Livros selecionados: %s", @@ -262,5 +266,11 @@ "error-storage-data-loss": "Erro ao salvar seus dados. Tente sincronizar novamente ou entre em contato com o suporte se o problema persistir: %s", "error-storage-not-found": "Seus dados não foram encontrados. Tente fazer login novamente com suas credenciais: %s", "error-storage-write-failed": "Impossível salvar suas alterações. Verifique o espaço de armazenamento e tente novamente: %s", - "error-storage-read-failed": "Impossível carregar seus dados. Verifique sua conexão com a internet e tente novamente: %s" + "error-storage-read-failed": "Impossível carregar seus dados. Verifique sua conexão com a internet e tente novamente: %s", + "error-local-database-invalid-data": "Os dados fornecidos não são válidos. %s", + "error-local-database-not-null-constraint": "Um campo obrigatório está vazio. %s", + "error-local-database-open-failed": "Não foi possível abrir o banco de dados. %s", + "error-local-database-operation-failed": "Operação do banco de dados falhou durante leitura, escrita ou atualização. %s", + "error-local-database-unique-constraint": "Este registro já existe no banco de dados. %s", + "error-local-database-unknown": "Erro desconhecido no banco de dados. %s" } diff --git a/coverage/lcov.info b/coverage/lcov.info index 187e00ea..583ec734 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -9,116 +9,34 @@ DA:15,9 LF:7 LH:7 end_of_record -SF:lib/src/core/database/local_database.dart -DA:5,0 -DA:7,0 -DA:9,0 -LF:3 -LH:0 -end_of_record SF:lib/src/core/errors/local_database_exception/local_database_exception.dart DA:7,7 -DA:12,1 -DA:13,3 +DA:12,0 +DA:13,0 LF:3 -LH:3 +LH:1 end_of_record -SF:lib/src/core/models/author_model.dart -DA:5,10 -DA:10,9 -DA:15,1 -DA:18,0 -DA:21,0 -DA:22,0 -DA:24,0 -DA:28,0 +SF:lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart +DA:5,3 +DA:9,3 +DA:10,0 +DA:14,3 +DA:15,0 +DA:18,3 +DA:19,0 +DA:22,3 +DA:23,0 +DA:26,9 DA:29,0 DA:30,0 -DA:34,2 -DA:35,2 -DA:36,2 -DA:37,2 -DA:41,2 -DA:42,2 -DA:43,4 -DA:44,2 -DA:48,0 -DA:51,0 -DA:52,0 -DA:53,0 -LF:22 -LH:11 -end_of_record -SF:lib/src/core/repositories/author_repository/authors_repository_impl.dart -DA:12,1 -DA:14,1 -DA:17,2 -DA:18,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:28,1 -DA:30,0 -DA:37,1 -DA:40,2 -DA:41,1 -DA:46,1 -DA:47,1 -DA:50,2 -DA:52,1 -DA:53,1 -DA:55,1 -DA:57,0 -DA:62,1 -DA:65,2 -DA:66,1 -DA:67,1 -DA:70,1 -DA:75,1 -DA:78,2 -DA:79,1 -DA:85,1 -LF:28 -LH:26 -end_of_record -SF:lib/src/shared/constants/database_scripts/database_scripts.dart -DA:3,0 -DA:6,4 -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:11,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:18,1 -DA:21,1 -DA:24,1 -DA:27,1 -DA:30,1 -DA:34,1 -DA:41,1 -DA:44,1 -DA:47,1 -LF:19 -LH:18 -end_of_record -SF:lib/src/core/dtos/bookcase_dto.dart -DA:7,2 -DA:12,0 -DA:16,0 -DA:17,0 -DA:18,0 -DA:22,0 -DA:24,0 -DA:26,1 -DA:30,3 -DA:31,0 -DA:34,0 -DA:35,0 LF:12 -LH:3 +LH:6 +end_of_record +SF:lib/src/core/helpers/textfield_unfocus/textfield_unfocus_extension.dart +DA:8,0 +DA:23,6 +LF:2 +LH:1 end_of_record SF:lib/src/core/models/bookcase_model.dart DA:10,3 @@ -158,286 +76,474 @@ DA:80,0 LF:34 LH:25 end_of_record -SF:lib/src/core/models/book_model.dart -DA:9,2 -DA:11,2 -DA:12,2 +SF:lib/src/core/services/app_services/color_picker_dialog_service/color_picker_dialog_service.dart +DA:6,0 DA:13,0 -DA:17,1 -DA:19,1 -DA:21,0 -DA:23,0 -DA:45,18 -DA:60,3 -DA:74,3 -DA:75,3 -DA:76,3 -DA:77,2 -DA:78,3 -DA:79,3 -DA:80,2 -DA:81,3 -DA:82,3 -DA:83,3 -DA:84,3 -DA:85,3 -DA:86,2 -DA:90,1 -DA:92,3 -DA:93,3 -DA:94,3 -DA:95,3 -DA:96,3 -DA:97,3 -DA:98,3 -DA:99,3 -DA:100,3 -DA:101,3 -DA:102,2 -DA:105,3 -DA:109,1 -DA:110,3 -DA:111,0 -DA:112,0 -DA:113,0 -DA:114,0 -DA:115,0 -DA:116,0 -DA:117,0 -DA:118,0 -DA:119,0 -DA:120,0 -DA:123,2 -DA:124,2 -DA:125,2 -DA:126,2 -DA:127,2 -DA:128,2 -DA:129,2 -DA:130,2 -DA:131,2 -DA:132,2 -DA:133,2 -DA:134,2 -DA:138,1 -DA:139,1 -DA:140,1 -DA:141,1 -DA:142,1 -DA:143,3 -DA:144,0 -DA:147,1 -DA:148,1 -DA:149,1 -DA:150,3 -DA:151,0 -DA:154,1 -DA:155,1 -DA:156,1 -DA:157,1 -DA:158,1 -DA:159,2 -DA:163,0 -DA:166,0 -DA:167,0 -DA:168,0 -DA:169,0 -DA:170,0 -DA:171,0 -DA:172,0 -DA:173,0 -DA:174,0 -DA:175,0 -DA:176,0 -DA:177,0 -DA:178,0 -LF:92 -LH:63 +DA:15,0 +DA:25,0 +DA:26,0 +LF:5 +LH:0 end_of_record -SF:lib/src/core/models/category_model.dart -DA:5,10 -DA:10,9 -DA:15,1 -DA:18,0 -DA:21,0 -DA:22,0 -DA:24,0 -DA:28,0 -DA:29,0 -DA:30,0 -DA:34,2 -DA:35,2 +SF:lib/src/core/services/app_services/snackbar_service/snackbar_service.dart +DA:10,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:15,2 +DA:19,2 +DA:21,2 +DA:22,2 +DA:23,2 +DA:24,2 +DA:30,2 DA:36,2 -DA:37,2 +DA:40,2 DA:41,2 DA:42,2 -DA:43,4 -DA:44,2 -DA:48,0 -DA:51,0 -DA:52,0 -DA:53,0 -LF:22 -LH:11 +DA:43,2 +DA:46,2 +DA:49,2 +DA:54,2 +DA:55,2 +DA:56,2 +DA:60,2 +DA:73,2 +DA:74,2 +DA:75,2 +LF:25 +LH:25 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_state.dart -DA:10,2 -DA:21,2 +SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_event.dart +DA:11,2 +DA:24,2 LF:2 LH:2 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_bloc.dart -DA:17,1 -DA:20,2 -DA:21,2 -DA:22,2 -DA:23,2 -DA:26,1 -DA:31,2 -DA:33,1 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 +SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart +DA:15,1 +DA:17,2 +DA:18,2 +DA:19,2 +DA:22,1 +DA:27,2 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,1 +DA:35,2 +DA:39,1 +DA:40,1 DA:41,1 -DA:42,1 -DA:43,1 -DA:45,1 +DA:50,1 DA:51,1 -DA:56,2 -DA:58,2 +DA:55,1 +DA:56,1 +DA:57,1 DA:59,1 -DA:60,1 -DA:61,1 DA:62,1 DA:63,1 +DA:64,1 DA:66,1 -DA:67,1 -DA:68,1 -DA:70,1 -DA:76,1 -DA:81,2 +DA:72,1 +DA:77,2 +DA:79,1 +DA:80,1 +DA:81,1 +DA:82,1 DA:83,1 -DA:85,2 DA:86,2 -DA:87,2 -DA:90,2 +DA:90,1 DA:91,1 DA:92,1 -DA:95,3 +DA:101,1 DA:102,1 -DA:103,1 -DA:104,1 -DA:105,1 DA:106,1 DA:107,1 +DA:108,1 +DA:109,1 DA:110,1 -DA:111,1 -DA:112,1 +DA:113,1 DA:114,1 -DA:120,1 -DA:121,2 -DA:123,1 -DA:124,2 -DA:128,1 -DA:131,1 -DA:135,2 -DA:137,1 -DA:138,2 -DA:142,1 -DA:145,1 -DA:149,1 -DA:151,2 -DA:152,1 -DA:153,1 -DA:154,1 -DA:162,2 -DA:163,1 -DA:169,2 -DA:172,1 -DA:177,1 -DA:180,2 -LF:71 -LH:71 +DA:115,1 +DA:117,1 +LF:46 +LH:46 end_of_record -SF:lib/src/features/bookcase/bloc/bookcase_event.dart -DA:10,1 -DA:18,1 +SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart +DA:16,2 +DA:23,2 LF:2 LH:2 end_of_record -SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart -DA:14,2 -DA:16,1 -DA:17,2 -DA:18,2 -DA:32,1 -DA:34,1 -DA:35,1 -DA:36,1 -LF:8 -LH:8 -end_of_record -SF:lib/src/core/helpers/locale_decimal_format/locale_decimal_format_extension.dart -DA:12,2 -DA:16,2 -DA:21,2 -LF:3 -LH:3 -end_of_record -SF:lib/src/core/errors/storage_exception/storage_exception.dart -DA:7,4 -DA:12,1 -DA:13,3 -LF:3 -LH:3 +SF:lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart +DA:33,1 +DA:41,1 +DA:42,1 +DA:55,1 +DA:59,1 +DA:65,1 +DA:66,1 +DA:79,1 +DA:81,1 +DA:83,1 +DA:85,3 +DA:87,5 +DA:88,5 +DA:89,4 +DA:92,1 +DA:94,2 +DA:95,2 +DA:96,1 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:107,0 +DA:108,0 +DA:124,1 +DA:125,3 +DA:126,2 +DA:129,2 +DA:130,1 +DA:131,3 +DA:132,4 +DA:134,3 +DA:135,1 +DA:139,2 +DA:140,2 +DA:141,1 +DA:142,1 +DA:143,3 +DA:144,4 +DA:146,3 +DA:147,1 +DA:151,4 +DA:152,0 +DA:153,0 +DA:154,0 +DA:156,1 +DA:157,3 +DA:158,3 +DA:159,1 +DA:163,2 +DA:164,1 +DA:169,1 +DA:174,1 +DA:175,0 +DA:177,0 +DA:182,2 +DA:183,1 +DA:186,1 +DA:187,1 +DA:188,1 +DA:189,1 +DA:194,2 +DA:195,1 +DA:196,1 +DA:197,3 +DA:199,1 +DA:205,1 +DA:206,1 +DA:207,1 +DA:209,1 +DA:211,1 +DA:215,2 +DA:216,1 +DA:217,1 +DA:218,2 +DA:226,1 +DA:228,2 +DA:231,1 +DA:232,1 +DA:234,2 +DA:236,1 +DA:237,1 +DA:238,1 +DA:239,1 +DA:240,1 +DA:242,1 +DA:246,1 +DA:247,1 +DA:249,1 +DA:250,1 +DA:255,1 +DA:256,1 +DA:258,1 +DA:259,1 +DA:260,1 +DA:261,1 +DA:264,1 +DA:265,1 +DA:267,1 +DA:268,1 +DA:270,1 +DA:271,1 +DA:272,1 +DA:273,1 +DA:275,1 +DA:277,1 +DA:281,2 +DA:283,1 +DA:284,1 +DA:288,1 +DA:290,1 +DA:291,1 +DA:292,2 +DA:294,1 +DA:295,1 +DA:299,1 +DA:304,0 +DA:305,0 +DA:306,0 +DA:308,0 +DA:311,0 +DA:312,1 +DA:313,1 +DA:315,1 +DA:317,1 +DA:320,1 +DA:321,1 +DA:322,2 +DA:323,1 +DA:332,1 +DA:333,1 +DA:334,1 +DA:338,1 +DA:340,1 +DA:341,1 +LF:135 +LH:119 end_of_record -SF:lib/src/core/helpers/book_status/book_status_extension.dart -DA:7,0 -DA:9,0 -DA:10,0 -DA:11,0 -DA:15,1 -DA:17,1 -DA:18,2 +SF:lib/src/shared/widgets/buttons/bookify_outlined_button.dart +DA:10,1 DA:19,2 -LF:8 -LH:4 -end_of_record -SF:lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart -DA:7,3 -DA:11,3 -DA:12,0 -DA:15,3 -DA:16,0 -DA:19,3 -DA:20,0 -DA:23,3 -DA:24,0 -DA:27,3 -DA:28,0 -DA:31,3 +DA:28,3 +DA:30,3 +DA:32,3 +DA:33,7 DA:34,3 -DA:35,0 -DA:38,3 +DA:35,2 +DA:36,2 +DA:37,2 +DA:38,0 DA:39,0 -DA:42,3 +DA:40,0 +DA:42,0 DA:43,0 -DA:46,9 +DA:45,0 +DA:48,0 +DA:51,4 +DA:52,2 +DA:53,2 +DA:55,2 +DA:56,2 +DA:60,1 +DA:61,1 +DA:62,1 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:73,0 +DA:76,1 +DA:77,1 +DA:79,1 +DA:80,1 +LF:36 +LH:22 +end_of_record +SF:lib/src/shared/constants/database_scripts/database_scripts.dart +DA:3,0 +DA:6,4 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:18,1 +DA:21,1 +DA:24,1 +DA:27,1 +DA:30,1 +DA:34,1 +DA:41,1 +DA:44,1 +DA:47,1 LF:19 +LH:18 +end_of_record +SF:lib/src/core/models/author_model.dart +DA:5,10 +DA:10,9 +DA:15,1 +DA:18,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:34,2 +DA:35,2 +DA:36,2 +DA:37,2 +DA:41,2 +DA:42,2 +DA:43,4 +DA:44,2 +DA:48,0 +DA:51,0 +DA:52,0 +DA:53,0 +LF:22 LH:11 end_of_record -SF:lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart -DA:5,0 -DA:9,0 -DA:12,0 +SF:lib/src/core/models/book_model.dart +DA:9,2 +DA:11,2 +DA:12,2 DA:13,0 -DA:14,0 -DA:17,0 -DA:20,0 -LF:7 -LH:0 +DA:17,1 +DA:19,1 +DA:21,0 +DA:23,0 +DA:45,18 +DA:60,3 +DA:74,3 +DA:75,3 +DA:76,3 +DA:77,2 +DA:78,3 +DA:79,3 +DA:80,2 +DA:81,3 +DA:82,3 +DA:83,3 +DA:84,3 +DA:85,3 +DA:86,2 +DA:90,1 +DA:92,3 +DA:93,3 +DA:94,3 +DA:95,3 +DA:96,3 +DA:97,3 +DA:98,3 +DA:99,3 +DA:100,3 +DA:101,3 +DA:102,2 +DA:105,3 +DA:109,1 +DA:110,3 +DA:111,0 +DA:112,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:123,2 +DA:124,2 +DA:125,2 +DA:126,2 +DA:127,2 +DA:128,2 +DA:129,2 +DA:130,2 +DA:131,2 +DA:132,2 +DA:133,2 +DA:134,2 +DA:138,1 +DA:139,1 +DA:140,1 +DA:141,1 +DA:142,1 +DA:143,3 +DA:144,0 +DA:147,1 +DA:148,1 +DA:149,1 +DA:150,3 +DA:151,0 +DA:154,1 +DA:155,1 +DA:156,1 +DA:157,1 +DA:158,1 +DA:159,2 +DA:163,0 +DA:166,0 +DA:167,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:171,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:177,0 +DA:178,0 +LF:92 +LH:63 +end_of_record +SF:lib/src/core/models/category_model.dart +DA:5,10 +DA:10,9 +DA:15,1 +DA:18,0 +DA:21,0 +DA:22,0 +DA:24,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:34,2 +DA:35,2 +DA:36,2 +DA:37,2 +DA:41,2 +DA:42,2 +DA:43,4 +DA:44,2 +DA:48,0 +DA:51,0 +DA:52,0 +DA:53,0 +LF:22 +LH:11 +end_of_record +SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart +DA:14,2 +DA:16,1 +DA:17,2 +DA:18,2 +DA:32,1 +DA:34,1 +DA:35,1 +DA:36,1 +LF:8 +LH:8 +end_of_record +SF:lib/src/core/helpers/locale_decimal_format/locale_decimal_format_extension.dart +DA:12,2 +DA:16,2 +DA:21,2 +LF:3 +LH:3 end_of_record SF:lib/src/core/models/user_page_reading_time_model.dart DA:4,3 @@ -458,558 +564,599 @@ DA:42,0 LF:15 LH:8 end_of_record -SF:lib/src/core/services/app_services/launcher_service/launcher_service.dart -DA:4,0 -DA:6,0 -DA:8,0 -DA:17,0 -DA:21,0 -DA:23,0 -DA:24,0 -DA:27,0 -DA:28,0 -DA:40,0 -LF:10 -LH:0 +SF:lib/src/core/errors/storage_exception/storage_exception.dart +DA:7,4 +DA:12,1 +DA:13,3 +LF:3 +LH:3 end_of_record -SF:lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart -DA:8,6 -DA:10,2 -DA:17,2 -DA:25,2 -DA:30,2 +SF:lib/src/core/models/user_model.dart +DA:9,2 +DA:15,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:27,1 +DA:28,1 +DA:29,1 +DA:30,1 DA:31,2 -DA:32,2 +DA:35,1 +DA:36,1 +DA:37,1 DA:38,2 DA:39,2 -DA:40,2 -DA:46,2 -DA:48,2 -DA:49,2 -DA:52,2 -DA:53,2 -DA:54,0 +DA:43,0 +DA:45,0 +DA:47,2 +DA:51,3 +DA:52,3 +DA:53,3 DA:56,0 -DA:59,0 -DA:64,2 -DA:65,2 -DA:67,0 -DA:70,2 -DA:83,0 -DA:87,0 -DA:89,0 -DA:97,0 -DA:98,0 -DA:99,0 -DA:101,0 -DA:105,0 -DA:107,0 -DA:108,0 -DA:110,0 -DA:111,0 -DA:113,0 -DA:118,0 -DA:120,0 -DA:121,0 -DA:124,0 -LF:39 +DA:57,0 +DA:59,3 +DA:61,1 +DA:62,2 +LF:27 LH:18 end_of_record -SF:lib/src/core/services/app_services/snackbar_service/snackbar_service.dart -DA:10,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:15,2 +SF:lib/src/core/repositories/auth_repository/auth_repository_impl.dart +DA:11,1 +DA:15,1 DA:19,2 -DA:21,2 -DA:22,2 -DA:23,2 -DA:24,2 -DA:30,2 -DA:36,2 -DA:40,2 -DA:41,2 -DA:42,2 -DA:43,2 -DA:46,2 -DA:49,2 -DA:54,2 -DA:55,2 -DA:56,2 -DA:60,2 -DA:73,2 -DA:74,2 -DA:75,2 -LF:25 -LH:25 +DA:20,1 +DA:28,1 +DA:31,1 +DA:36,1 +DA:41,1 +DA:44,2 +DA:45,1 +DA:46,1 +DA:49,1 +DA:50,1 +DA:53,0 +DA:55,0 +DA:60,1 +DA:63,3 +DA:64,1 +DA:67,0 +DA:69,0 +LF:20 +LH:16 end_of_record -SF:lib/src/features/book_detail/bloc/book_detail_event.dart -DA:8,2 -DA:16,2 -DA:24,1 -LF:3 -LH:3 +SF:lib/src/shared/enums/sign_in_type.dart +DA:7,1 +DA:9,1 +DA:10,0 +DA:11,0 +DA:12,0 +DA:16,1 +DA:18,1 +DA:19,0 +DA:20,0 +LF:9 +LH:4 end_of_record -SF:lib/src/features/book_detail/bloc/book_detail_state.dart -DA:10,2 -DA:19,2 -LF:2 -LH:2 +SF:lib/src/core/database/local_database.dart +DA:5,0 +DA:7,0 +DA:9,0 +LF:3 +LH:0 end_of_record -SF:lib/src/features/book_detail/bloc/book_detail_bloc.dart -DA:15,1 +SF:lib/src/core/repositories/author_repository/authors_repository_impl.dart +DA:12,1 +DA:14,1 DA:17,2 -DA:18,2 -DA:19,2 -DA:20,2 +DA:18,1 DA:23,1 -DA:28,2 -DA:30,2 -DA:31,1 -DA:34,2 -DA:35,1 -DA:36,1 +DA:25,1 +DA:26,1 +DA:28,1 +DA:30,0 DA:37,1 -DA:38,1 -DA:39,1 -DA:43,1 -DA:44,1 +DA:40,2 +DA:41,1 DA:46,1 +DA:47,1 +DA:50,2 DA:52,1 -DA:57,2 -DA:59,2 -DA:60,1 -DA:63,1 -DA:64,1 -DA:65,1 -DA:73,2 -DA:74,1 +DA:53,1 +DA:55,1 +DA:57,0 +DA:62,1 +DA:65,2 +DA:66,1 +DA:67,1 +DA:70,1 DA:75,1 -DA:76,1 -DA:77,1 -DA:78,1 -DA:82,1 -DA:83,1 +DA:78,2 +DA:79,1 DA:85,1 -DA:91,1 -DA:96,2 -DA:98,3 -DA:100,1 -DA:101,1 -DA:102,1 -DA:105,2 -DA:111,3 -DA:112,1 -DA:113,1 -DA:114,1 -DA:121,2 -DA:123,1 -DA:124,1 -DA:125,1 -DA:126,1 -DA:127,1 -DA:131,1 -DA:132,1 -DA:134,1 -LF:54 -LH:54 +LF:28 +LH:26 end_of_record -SF:lib/src/features/book_detail/views/book_detail_page.dart +SF:lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart +DA:11,1 +DA:13,1 +DA:18,2 DA:19,1 -DA:24,1 -DA:25,1 -DA:51,1 -DA:53,1 -DA:55,2 -DA:56,1 +DA:24,2 +DA:32,1 +DA:33,0 +DA:35,0 +DA:40,1 +DA:43,2 +DA:44,1 +DA:45,1 +DA:52,1 DA:57,1 -DA:60,3 +DA:60,2 DA:61,1 -DA:62,1 -DA:63,3 -DA:68,1 -DA:71,1 -DA:73,3 -DA:74,2 -DA:75,1 -DA:79,0 -DA:80,0 -DA:81,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:88,0 -DA:90,0 -DA:91,0 -DA:95,1 -DA:100,1 -DA:102,1 -DA:105,1 -DA:107,2 -DA:110,1 -DA:112,1 -DA:113,1 -DA:114,1 -DA:115,1 -DA:117,1 -DA:125,1 -DA:128,1 -DA:129,1 -DA:130,1 -DA:133,1 -DA:135,1 -DA:137,1 -DA:144,1 -DA:145,1 -DA:146,1 -DA:147,1 -DA:148,3 -DA:149,1 -DA:150,0 -DA:151,0 -DA:152,0 -DA:156,3 -DA:160,1 -DA:162,2 -DA:163,1 -DA:164,3 -DA:165,1 -DA:166,1 -DA:167,1 -DA:168,3 -DA:169,1 -DA:170,1 -DA:172,2 -DA:174,1 -DA:175,1 -DA:176,1 -DA:177,1 -DA:178,1 -DA:179,1 -DA:181,1 -DA:182,1 -DA:183,1 -DA:184,1 -DA:188,1 -DA:189,1 -DA:191,1 -DA:194,1 -DA:199,1 -DA:206,1 -DA:207,1 -DA:208,1 -DA:210,1 -DA:211,1 -DA:212,1 -DA:214,2 -DA:223,1 -DA:224,1 -DA:226,1 -DA:230,1 -DA:232,1 -DA:233,1 -DA:235,4 -DA:237,1 -DA:238,1 -DA:243,1 -DA:245,1 -DA:250,1 -DA:253,1 -DA:254,1 -DA:255,1 -DA:257,1 -DA:259,0 -DA:260,0 -DA:264,1 -DA:265,1 -DA:268,1 -DA:272,1 -DA:273,1 -DA:274,1 -DA:276,2 -DA:277,1 -DA:284,1 -DA:286,1 -DA:288,1 -DA:294,1 -DA:296,0 -DA:297,0 -DA:299,1 -DA:300,1 -DA:301,1 -DA:303,1 -DA:313,1 -DA:316,1 -DA:317,1 -DA:318,1 -DA:319,1 -DA:321,1 -DA:323,1 -DA:329,1 -DA:331,1 -DA:332,1 -DA:337,1 -DA:338,1 -DA:341,1 -DA:342,1 -DA:344,1 -DA:346,1 -DA:352,1 -DA:354,1 -DA:355,1 -DA:357,1 -DA:359,1 -LF:144 -LH:128 +DA:67,1 +LF:17 +LH:15 end_of_record -SF:lib/src/shared/widgets/book_widget/book_widget.dart +SF:lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart +DA:11,1 DA:13,1 -DA:23,1 +DA:18,2 +DA:19,1 +DA:24,2 +DA:32,1 +DA:33,0 +DA:35,0 +DA:40,1 +DA:43,2 +DA:44,1 +DA:45,1 +DA:52,1 +DA:57,1 +DA:60,2 +DA:61,1 +DA:67,1 +LF:17 +LH:15 +end_of_record +SF:lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart +DA:11,1 +DA:13,1 +DA:18,2 +DA:19,1 +DA:25,1 +DA:30,1 DA:33,2 -DA:35,4 -DA:37,2 -DA:38,2 -DA:39,2 -DA:40,2 -DA:41,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:55,0 -DA:57,0 -DA:59,0 -DA:69,2 -DA:70,0 -DA:72,0 -LF:21 -LH:9 +DA:34,1 +DA:35,1 +DA:40,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:47,1 +DA:52,1 +DA:55,2 +DA:56,1 +DA:57,1 +DA:64,1 +DA:69,1 +DA:72,2 +DA:73,1 +DA:79,1 +DA:84,1 +DA:90,2 +DA:91,1 +DA:98,1 +LF:27 +LH:27 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart -DA:7,1 -DA:10,1 +SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart DA:12,1 -DA:13,1 DA:14,1 -DA:15,1 -DA:18,3 -DA:20,1 +DA:17,3 +DA:18,2 DA:21,1 DA:22,1 -DA:23,1 -DA:24,4 -LF:12 -LH:12 +DA:24,1 +DA:26,1 +DA:31,1 +DA:34,2 +DA:35,1 +DA:39,2 +DA:42,1 +DA:43,1 +DA:45,1 +DA:47,1 +DA:52,1 +DA:55,2 +DA:56,1 +DA:60,1 +DA:63,1 +DA:64,1 +DA:66,1 +DA:68,1 +DA:73,1 +DA:76,2 +DA:77,1 +DA:81,1 +DA:86,1 +DA:89,2 +DA:90,1 +DA:91,1 +DA:95,1 +DA:100,1 +DA:103,2 +DA:104,1 +DA:105,1 +DA:107,1 +DA:111,1 +DA:116,1 +DA:119,2 +DA:120,1 +DA:126,1 +LF:43 +LH:43 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart +SF:lib/src/core/repositories/books_repository/books_repository_impl.dart +DA:12,1 DA:14,1 -DA:16,2 -DA:17,2 +DA:17,3 +DA:18,2 DA:20,1 -DA:25,2 -DA:27,1 -DA:28,1 +DA:21,1 +DA:23,1 +DA:25,1 DA:30,1 -DA:31,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 +DA:33,2 +DA:34,1 DA:39,1 +DA:41,1 DA:42,1 -DA:43,1 DA:44,1 DA:46,1 -LF:18 -LH:18 -end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 +DA:51,1 +DA:54,2 +DA:55,1 +DA:56,1 +DA:59,1 +DA:64,1 +DA:67,2 +DA:68,1 +DA:69,1 +DA:74,1 +DA:76,1 +DA:77,1 +DA:79,1 +DA:81,1 +DA:86,1 +DA:89,2 +DA:90,1 +DA:94,2 +DA:97,1 +DA:98,1 +DA:100,1 +DA:102,1 +DA:107,1 +DA:110,2 +DA:111,1 +DA:116,1 +DA:121,1 +DA:124,2 +DA:125,1 +DA:126,1 +DA:131,2 +DA:133,1 +DA:134,1 +DA:136,1 +DA:138,1 +DA:143,1 +DA:149,2 +DA:150,1 +DA:153,2 +DA:157,1 +DA:162,1 +DA:168,2 +DA:170,2 +DA:171,1 +DA:174,1 +DA:178,1 +DA:180,1 +DA:181,1 +DA:183,1 +DA:188,1 +DA:191,2 +DA:192,1 +DA:196,1 +DA:201,1 +DA:204,2 +DA:205,1 +DA:210,1 +LF:73 +LH:73 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart -DA:11,1 -DA:16,1 -DA:17,1 +SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart +DA:12,1 +DA:14,1 +DA:17,2 +DA:18,1 DA:23,1 DA:25,1 -DA:26,3 -DA:27,1 +DA:26,1 DA:28,1 -DA:32,1 +DA:30,0 DA:37,1 -DA:39,0 -DA:40,0 -DA:42,0 -DA:43,0 -DA:46,0 -DA:47,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:55,0 -DA:56,0 -DA:59,0 -DA:60,0 +DA:40,2 +DA:41,1 +DA:46,1 +DA:47,1 +DA:50,2 +DA:52,1 +DA:53,1 +DA:55,1 +DA:57,0 +DA:62,1 +DA:65,2 +DA:66,1 DA:67,1 -DA:69,1 -DA:70,1 DA:71,1 -LF:27 -LH:14 -end_of_record -SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart -DA:6,2 -DA:11,4 -DA:13,4 -DA:14,4 -LF:4 -LH:4 +DA:76,1 +DA:79,2 +DA:80,1 +DA:86,1 +LF:28 +LH:26 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_rating/book_rating.dart -DA:10,1 -DA:16,1 -DA:18,2 +SF:lib/src/core/models/loan_model.dart +DA:9,5 +DA:18,1 +DA:19,1 DA:20,1 DA:21,1 -DA:22,1 +DA:22,2 DA:23,2 +DA:24,1 DA:25,1 -DA:28,1 +DA:29,1 +DA:30,1 DA:31,1 DA:32,1 +DA:33,1 DA:34,1 -DA:35,4 +DA:36,1 DA:37,1 -DA:38,1 -LF:15 -LH:15 +DA:39,1 +DA:40,1 +DA:44,0 +DA:46,0 +DA:49,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,1 +DA:61,0 +DA:62,1 +DA:63,1 +DA:67,2 +DA:71,6 +DA:72,6 +DA:73,6 +DA:74,6 +DA:75,6 +DA:76,6 +DA:79,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +LF:43 +LH:33 end_of_record -SF:lib/src/shared/widgets/bookify_rating/bookify_rating_widget.dart +SF:lib/src/core/repositories/loan_repository/loan_repository_impl.dart DA:13,1 +DA:15,1 +DA:18,2 +DA:19,1 +DA:23,2 +DA:26,1 +DA:27,1 +DA:29,1 +DA:31,1 +DA:36,1 +DA:39,2 +DA:40,3 +DA:41,1 +DA:42,1 +DA:43,2 +DA:44,2 +DA:49,2 +DA:52,1 +DA:53,1 +DA:55,1 +DA:57,1 +DA:62,1 +DA:65,2 +DA:66,1 +DA:70,1 +DA:73,1 +DA:74,1 +DA:76,1 +DA:78,1 +DA:83,1 +DA:86,2 +DA:87,1 +DA:91,1 +DA:96,1 +DA:99,2 +DA:100,1 +DA:101,1 +DA:105,1 +DA:110,1 +DA:113,2 +DA:114,1 +DA:115,1 +DA:117,1 +DA:121,1 +DA:126,1 +DA:129,2 +DA:130,1 +DA:136,1 +LF:48 +LH:48 +end_of_record +SF:lib/src/core/models/reading_model.dart +DA:7,5 +DA:14,1 +DA:20,1 +DA:21,1 +DA:22,0 +DA:23,1 DA:24,1 -DA:27,2 -DA:29,0 -DA:30,5 +DA:28,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,2 DA:33,1 -DA:36,1 +DA:37,1 +DA:38,1 +DA:39,2 +DA:40,1 +DA:41,1 +DA:42,2 +DA:44,1 +DA:48,0 +DA:50,0 +DA:53,3 +DA:57,6 +DA:58,6 +DA:59,6 +DA:60,6 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +LF:32 +LH:24 +end_of_record +SF:lib/src/core/repositories/reading_repository/reading_repository_impl.dart +DA:13,1 +DA:17,1 +DA:20,2 +DA:21,1 +DA:26,2 +DA:29,1 +DA:30,1 +DA:32,1 +DA:34,1 DA:39,1 -DA:45,1 -DA:47,2 +DA:44,2 +DA:45,3 +DA:46,1 +DA:47,1 DA:48,2 DA:49,2 -DA:51,1 -DA:52,1 -DA:54,1 DA:55,2 -LF:16 -LH:15 +DA:58,1 +DA:59,1 +DA:61,1 +DA:63,1 +DA:68,1 +DA:71,2 +DA:72,1 +DA:77,1 +DA:80,1 +DA:81,1 +DA:83,1 +DA:85,1 +DA:90,1 +DA:93,2 +DA:94,1 +DA:98,1 +DA:103,1 +DA:106,2 +DA:107,1 +DA:108,1 +DA:112,1 +DA:117,1 +DA:120,2 +DA:121,1 +DA:122,1 +DA:124,1 +DA:128,1 +DA:133,1 +DA:136,2 +DA:137,1 +DA:143,1 +LF:48 +LH:48 end_of_record -SF:lib/src/shared/widgets/buttons/bookify_elevated_button.dart -DA:10,1 -DA:19,2 -DA:28,3 -DA:30,3 -DA:32,3 -DA:33,7 -DA:34,3 -DA:35,3 -DA:36,3 -DA:37,3 -DA:38,0 -DA:39,0 -DA:40,0 -DA:44,6 -DA:45,3 -DA:46,3 +SF:lib/src/shared/enums/repeat_hour_time_type.dart +DA:5,1 +DA:7,1 +DA:8,0 +DA:9,0 +DA:13,1 +DA:15,1 +DA:16,0 +LF:7 +LH:4 +end_of_record +SF:lib/src/core/models/user_hour_time_model.dart +DA:12,1 +DA:20,2 +DA:22,1 +DA:24,4 +DA:27,4 +DA:30,1 +DA:31,1 +DA:33,0 +DA:37,1 +DA:41,0 +DA:48,0 +DA:49,0 DA:50,0 DA:51,0 DA:52,0 DA:53,0 -DA:54,0 -DA:55,0 -DA:59,0 -DA:60,0 -LF:24 -LH:13 -end_of_record -SF:lib/src/shared/widgets/buttons/bookify_outlined_button.dart -DA:10,1 -DA:19,2 -DA:28,3 -DA:30,3 -DA:32,3 -DA:33,7 -DA:34,3 -DA:35,2 -DA:36,2 -DA:37,2 -DA:38,0 -DA:39,0 -DA:40,0 -DA:42,0 -DA:43,0 -DA:45,0 -DA:48,0 -DA:51,4 -DA:52,2 -DA:53,2 -DA:55,2 -DA:56,2 +DA:57,1 +DA:58,1 +DA:59,2 DA:60,1 DA:61,1 DA:62,1 -DA:63,0 -DA:64,0 -DA:65,0 -DA:67,0 -DA:68,0 -DA:70,0 -DA:73,0 -DA:76,1 -DA:77,1 -DA:79,1 +DA:63,1 +DA:67,1 +DA:68,1 +DA:70,2 +DA:71,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:78,3 DA:80,1 -LF:36 -LH:22 -end_of_record -SF:lib/src/core/models/user_model.dart -DA:9,2 -DA:15,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:27,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:31,2 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,2 -DA:39,2 -DA:43,0 -DA:45,0 -DA:47,2 -DA:51,3 -DA:52,3 -DA:53,3 -DA:56,0 -DA:57,0 -DA:59,3 -DA:61,1 -DA:62,2 -LF:27 -LH:18 +DA:81,2 +DA:83,0 +DA:85,0 +DA:88,2 +DA:92,3 +DA:93,3 +DA:94,3 +DA:95,3 +DA:96,3 +DA:99,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +LF:47 +LH:31 end_of_record -SF:lib/src/core/repositories/auth_repository/auth_repository_impl.dart +SF:lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart DA:11,1 DA:15,1 DA:19,2 @@ -1018,1461 +1165,1522 @@ DA:28,1 DA:31,1 DA:36,1 DA:41,1 -DA:44,2 -DA:45,1 -DA:46,1 -DA:49,1 -DA:50,1 -DA:53,0 +DA:46,2 +DA:47,1 +DA:48,1 +DA:51,1 +DA:52,1 DA:55,0 -DA:60,1 -DA:63,3 -DA:64,1 -DA:67,0 -DA:69,0 -LF:20 -LH:16 +DA:57,0 +LF:15 +LH:13 end_of_record -SF:lib/src/shared/enums/sign_in_type.dart -DA:7,1 -DA:9,1 -DA:10,0 -DA:11,0 -DA:12,0 +SF:lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart +DA:12,1 DA:16,1 -DA:18,1 -DA:19,0 -DA:20,0 -LF:9 -LH:4 -end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 -end_of_record -SF:lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart -DA:11,1 -DA:13,1 -DA:18,2 -DA:19,1 -DA:24,2 -DA:32,1 -DA:33,0 -DA:35,0 -DA:40,1 -DA:43,2 -DA:44,1 -DA:45,1 -DA:52,1 -DA:57,1 -DA:60,2 -DA:61,1 -DA:67,1 -LF:17 -LH:15 -end_of_record -SF:lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart -DA:11,1 -DA:13,1 -DA:18,2 -DA:19,1 -DA:24,2 -DA:32,1 -DA:33,0 -DA:35,0 -DA:40,1 -DA:43,2 -DA:44,1 -DA:45,1 -DA:52,1 -DA:57,1 -DA:60,2 -DA:61,1 -DA:67,1 -LF:17 -LH:15 -end_of_record -SF:lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart -DA:11,1 -DA:13,1 -DA:18,2 -DA:19,1 +DA:20,2 +DA:21,1 DA:25,1 DA:30,1 -DA:33,2 -DA:34,1 DA:35,1 DA:40,1 -DA:42,1 -DA:43,1 -DA:45,1 +DA:45,2 +DA:46,1 DA:47,1 -DA:52,1 -DA:55,2 -DA:56,1 -DA:57,1 -DA:64,1 -DA:69,1 -DA:72,2 -DA:73,1 -DA:79,1 -DA:84,1 -DA:90,2 -DA:91,1 -DA:98,1 -LF:27 -LH:27 +DA:51,1 +DA:54,0 +DA:56,0 +LF:14 +LH:12 end_of_record -SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart -DA:12,1 -DA:14,1 -DA:17,3 -DA:18,2 +SF:lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart +DA:11,1 +DA:15,1 +DA:18,3 DA:21,1 -DA:22,1 -DA:24,1 -DA:26,1 -DA:31,1 -DA:34,2 +DA:23,0 +DA:25,0 +DA:30,1 DA:35,1 -DA:39,2 -DA:42,1 -DA:43,1 +DA:40,1 +DA:43,2 +DA:44,1 DA:45,1 -DA:47,1 -DA:52,1 -DA:55,2 -DA:56,1 +DA:48,1 +DA:51,0 +DA:53,0 +LF:15 +LH:11 +end_of_record +SF:lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart +DA:8,1 +DA:10,1 +DA:12,2 +DA:15,1 +DA:17,2 +DA:20,1 +DA:24,2 +DA:27,1 +DA:31,2 +DA:34,1 +DA:36,2 +DA:39,1 +DA:41,2 +LF:13 +LH:13 +end_of_record +SF:lib/src/core/services/book_service/book_service_impl.dart +DA:21,1 +DA:33,1 +DA:36,2 +DA:38,3 +DA:40,3 +DA:41,3 +DA:48,1 +DA:53,1 +DA:56,2 +DA:58,1 DA:60,1 -DA:63,1 -DA:64,1 DA:66,1 -DA:68,1 -DA:73,1 -DA:76,2 -DA:77,1 -DA:81,1 +DA:71,1 +DA:74,2 +DA:76,3 +DA:78,3 +DA:79,3 DA:86,1 -DA:89,2 -DA:90,1 DA:91,1 -DA:95,1 +DA:94,2 +DA:96,1 +DA:98,2 +DA:99,2 DA:100,1 DA:103,2 -DA:104,1 -DA:105,1 -DA:107,1 -DA:111,1 -DA:116,1 -DA:119,2 -DA:120,1 +DA:104,2 +DA:107,2 +DA:108,1 +DA:113,1 +DA:115,2 +DA:116,2 +DA:117,1 +DA:120,2 +DA:122,0 +DA:125,2 DA:126,1 -LF:43 -LH:43 +DA:132,1 +DA:137,1 +DA:141,2 +DA:143,1 +DA:148,1 +DA:151,2 +DA:153,1 +DA:158,1 +DA:161,2 +DA:163,1 +DA:168,1 +DA:174,2 +DA:179,1 +DA:184,1 +DA:190,2 +DA:195,1 +DA:200,1 +DA:203,2 +DA:205,1 +DA:210,1 +DA:213,2 +DA:215,1 +DA:220,1 +DA:222,2 +DA:225,3 +DA:226,1 +DA:228,1 +DA:229,2 +DA:230,2 +DA:231,1 +DA:235,2 +DA:238,3 +DA:239,1 +DA:241,1 +DA:242,2 +DA:243,2 +DA:244,1 +LF:73 +LH:72 end_of_record -SF:lib/src/core/repositories/books_repository/books_repository_impl.dart -DA:12,1 -DA:14,1 -DA:17,3 -DA:18,2 -DA:20,1 -DA:21,1 -DA:23,1 -DA:25,1 -DA:30,1 -DA:33,2 +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 +LH:0 +end_of_record +SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart +DA:11,1 +DA:17,1 +DA:20,2 +DA:22,1 +DA:27,1 +DA:30,2 DA:34,1 DA:39,1 -DA:41,1 -DA:42,1 +DA:43,1 DA:44,1 DA:46,1 DA:51,1 -DA:54,2 -DA:55,1 -DA:56,1 -DA:59,1 -DA:64,1 -DA:67,2 -DA:68,1 -DA:69,1 -DA:74,1 -DA:76,1 -DA:77,1 -DA:79,1 -DA:81,1 -DA:86,1 -DA:89,2 -DA:90,1 -DA:94,2 -DA:97,1 -DA:98,1 +DA:56,2 +DA:61,1 +DA:66,1 +DA:69,2 +DA:73,1 +DA:78,1 +DA:82,2 +DA:84,1 +DA:89,1 +DA:93,2 +DA:95,1 DA:100,1 -DA:102,1 -DA:107,1 -DA:110,2 +DA:106,2 DA:111,1 DA:116,1 +DA:119,2 DA:121,1 -DA:124,2 -DA:125,1 DA:126,1 -DA:131,2 -DA:133,1 +DA:129,2 DA:134,1 -DA:136,1 -DA:138,1 -DA:143,1 -DA:149,2 -DA:150,1 -DA:153,2 -DA:157,1 -DA:162,1 -DA:167,2 -DA:170,2 -DA:171,1 -DA:174,1 -DA:178,1 -DA:183,1 -DA:186,2 -DA:187,1 -DA:191,1 -DA:196,1 -DA:199,2 -DA:200,1 -DA:205,1 -LF:70 -LH:70 +DA:139,1 +DA:142,2 +DA:147,1 +DA:152,1 +DA:155,2 +DA:160,1 +LF:38 +LH:38 end_of_record -SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart -DA:12,1 -DA:14,1 -DA:17,2 -DA:18,1 -DA:23,1 -DA:25,1 +SF:lib/src/core/services/loan_services/loan_service_impl.dart +DA:9,1 +DA:11,1 +DA:14,2 +DA:16,1 +DA:21,1 +DA:24,2 DA:26,1 -DA:28,1 -DA:30,0 -DA:37,1 -DA:40,2 -DA:41,1 -DA:46,1 -DA:47,1 -DA:50,2 -DA:52,1 +DA:31,1 +DA:34,2 +DA:38,1 +DA:43,1 +DA:46,2 +DA:48,1 DA:53,1 -DA:55,1 -DA:57,0 -DA:62,1 -DA:65,2 -DA:66,1 -DA:67,1 +DA:56,2 +DA:58,1 +DA:63,1 +DA:66,2 DA:71,1 DA:76,1 DA:79,2 -DA:80,1 -DA:86,1 -LF:28 -LH:26 +DA:84,1 +LF:22 +LH:22 end_of_record -SF:lib/src/core/models/loan_model.dart -DA:9,5 -DA:18,1 -DA:19,1 -DA:20,1 +SF:lib/src/core/services/reading_services/reading_service_impl.dart +DA:9,1 +DA:11,1 +DA:14,2 +DA:16,1 DA:21,1 -DA:22,2 -DA:23,2 -DA:24,1 -DA:25,1 -DA:29,1 -DA:30,1 -DA:31,1 -DA:32,1 +DA:24,2 +DA:28,1 DA:33,1 -DA:34,1 -DA:36,1 -DA:37,1 -DA:39,1 -DA:40,1 -DA:44,0 -DA:46,0 -DA:49,1 -DA:57,1 -DA:58,1 -DA:59,1 -DA:60,1 -DA:61,0 -DA:62,1 -DA:63,1 -DA:67,2 -DA:71,6 -DA:72,6 -DA:73,6 -DA:74,6 -DA:75,6 -DA:76,6 -DA:79,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -LF:43 -LH:33 -end_of_record -SF:lib/src/core/repositories/loan_repository/loan_repository_impl.dart -DA:13,1 -DA:15,1 -DA:18,2 -DA:19,1 -DA:23,2 -DA:26,1 -DA:27,1 -DA:29,1 -DA:31,1 -DA:36,1 -DA:39,2 -DA:40,3 -DA:41,1 +DA:38,2 DA:42,1 -DA:43,2 -DA:44,2 -DA:49,2 +DA:47,1 +DA:50,2 DA:52,1 -DA:53,1 -DA:55,1 DA:57,1 -DA:62,1 -DA:65,2 -DA:66,1 +DA:60,2 +DA:65,1 DA:70,1 -DA:73,1 -DA:74,1 -DA:76,1 +DA:73,2 DA:78,1 DA:83,1 DA:86,2 -DA:87,1 DA:91,1 -DA:96,1 -DA:99,2 -DA:100,1 -DA:101,1 -DA:105,1 -DA:110,1 -DA:113,2 -DA:114,1 -DA:115,1 -DA:117,1 -DA:121,1 -DA:126,1 -DA:129,2 -DA:130,1 -DA:136,1 -LF:48 -LH:48 +LF:22 +LH:22 end_of_record -SF:lib/src/core/models/reading_model.dart -DA:7,5 -DA:14,1 -DA:20,1 -DA:21,1 +SF:lib/src/core/errors/auth_exception/auth_exception.dart +DA:7,1 +DA:12,0 +DA:13,0 +LF:3 +LH:1 +end_of_record +SF:lib/src/core/services/auth_service/auth_service_impl.dart +DA:16,1 DA:22,0 -DA:23,1 -DA:24,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:31,1 -DA:32,2 +DA:24,0 +DA:27,0 DA:33,1 -DA:37,1 +DA:36,2 DA:38,1 DA:39,2 -DA:40,1 -DA:41,1 -DA:42,2 DA:44,1 -DA:48,0 -DA:50,0 -DA:53,3 -DA:57,6 -DA:58,6 -DA:59,6 -DA:60,6 -DA:63,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -LF:32 -LH:24 -end_of_record -SF:lib/src/core/repositories/reading_repository/reading_repository_impl.dart -DA:13,1 -DA:17,1 -DA:20,2 -DA:21,1 -DA:26,2 -DA:29,1 -DA:30,1 -DA:32,1 -DA:34,1 -DA:39,1 -DA:44,2 -DA:45,3 DA:46,1 DA:47,1 -DA:48,2 -DA:49,2 -DA:55,2 -DA:58,1 +DA:49,1 +DA:51,0 +DA:52,0 +DA:54,0 DA:59,1 -DA:61,1 +DA:62,2 DA:63,1 -DA:68,1 -DA:71,2 -DA:72,1 -DA:77,1 -DA:80,1 -DA:81,1 -DA:83,1 -DA:85,1 -DA:90,1 -DA:93,2 -DA:94,1 -DA:98,1 -DA:103,1 -DA:106,2 -DA:107,1 -DA:108,1 -DA:112,1 -DA:117,1 -DA:120,2 -DA:121,1 -DA:122,1 -DA:124,1 -DA:128,1 -DA:133,1 -DA:136,2 -DA:137,1 -DA:143,1 -LF:48 -LH:48 -end_of_record -SF:lib/src/shared/enums/repeat_hour_time_type.dart -DA:5,1 -DA:7,1 -DA:8,0 -DA:9,0 -DA:13,1 -DA:15,1 +DA:66,2 +DA:69,1 +DA:71,0 +DA:72,0 +DA:74,0 +DA:76,0 +DA:77,0 +DA:79,0 +DA:84,0 +DA:87,0 +DA:89,0 +DA:90,0 +DA:92,0 +DA:94,0 +DA:95,0 +DA:97,0 +LF:34 +LH:14 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart +DA:12,0 +DA:14,0 +DA:15,0 DA:16,0 -LF:7 -LH:4 +DA:18,0 +DA:19,0 +DA:21,0 +DA:22,0 +DA:23,0 +LF:9 +LH:0 end_of_record -SF:lib/src/core/models/user_hour_time_model.dart -DA:12,1 -DA:20,2 -DA:22,1 -DA:24,4 -DA:27,4 -DA:30,1 -DA:31,1 +SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart +DA:16,0 +DA:20,0 +DA:24,0 +DA:25,0 +DA:27,0 +DA:28,0 +DA:31,0 +DA:32,0 DA:33,0 -DA:37,1 +DA:34,0 +DA:37,0 +DA:40,0 DA:41,0 -DA:48,0 -DA:49,0 +DA:43,0 +DA:44,0 DA:50,0 DA:51,0 -DA:52,0 -DA:53,0 -DA:57,1 -DA:58,1 -DA:59,2 -DA:60,1 -DA:61,1 -DA:62,1 -DA:63,1 -DA:67,1 -DA:68,1 -DA:70,2 -DA:71,1 -DA:72,1 -DA:73,1 -DA:74,1 -DA:78,3 -DA:80,1 -DA:81,2 +DA:55,0 +DA:59,0 +DA:60,0 +DA:61,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:77,0 +DA:79,0 +DA:81,0 DA:83,0 -DA:85,0 -DA:88,2 -DA:92,3 -DA:93,3 -DA:94,3 -DA:95,3 -DA:96,3 +DA:84,0 +DA:86,0 +DA:91,0 +DA:94,0 +DA:96,0 +DA:97,0 +DA:98,0 DA:99,0 +DA:100,0 DA:101,0 DA:102,0 DA:103,0 DA:104,0 -DA:105,0 +DA:107,0 +DA:109,0 +DA:111,0 +DA:112,0 +DA:114,0 +LF:52 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart +DA:17,0 +DA:23,0 +DA:27,0 +DA:28,0 +DA:30,0 +DA:31,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:40,0 +DA:43,0 +DA:44,0 +DA:46,0 +DA:50,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:59,0 +DA:60,0 +DA:64,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:77,0 +DA:79,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:93,0 +DA:95,0 +DA:97,0 +DA:99,0 +DA:100,0 +DA:102,0 +DA:107,0 +DA:110,0 +DA:111,0 +DA:113,0 +DA:114,0 +DA:115,0 +DA:116,0 +DA:117,0 +DA:118,0 +DA:119,0 +DA:120,0 +DA:121,0 +DA:124,0 +DA:126,0 +DA:128,0 +DA:129,0 +DA:131,0 +LF:58 +LH:0 +end_of_record +SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart +DA:13,0 +DA:19,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:40,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:63,0 +DA:65,0 +DA:67,0 +DA:69,0 +DA:70,0 +DA:72,0 +DA:77,0 +DA:80,0 +DA:81,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:89,0 +DA:90,0 +DA:91,0 +DA:94,0 +DA:96,0 +DA:98,0 +DA:99,0 +DA:101,0 LF:47 -LH:31 +LH:0 end_of_record -SF:lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart -DA:11,1 -DA:15,1 -DA:19,2 +SF:lib/src/core/utils/verifier/isbn_verifier.dart +DA:11,9 +DA:16,6 +DA:25,2 +DA:26,2 +DA:28,6 +DA:29,4 +DA:31,4 +DA:43,2 +DA:44,4 +DA:48,2 +DA:49,1 +DA:50,2 +DA:51,1 +DA:52,1 +DA:53,1 +DA:56,2 +DA:69,2 +DA:70,4 +DA:74,4 +DA:75,2 +DA:76,4 +DA:78,2 +DA:81,4 +LF:23 +LH:23 +end_of_record +SF:lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart +DA:12,1 +DA:17,1 +DA:18,1 DA:20,1 +DA:22,2 +DA:24,1 +DA:26,2 DA:28,1 -DA:31,1 +DA:30,2 +DA:32,1 +DA:34,2 DA:36,1 -DA:41,1 -DA:46,2 -DA:47,1 -DA:48,1 +DA:38,2 +DA:40,1 +DA:42,2 +DA:44,1 DA:51,1 -DA:52,1 -DA:55,0 -DA:57,0 -LF:15 -LH:13 +DA:54,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:62,1 +DA:64,1 +LF:23 +LH:23 end_of_record -SF:lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart +SF:lib/src/core/errors/rest_client_exception/rest_client_exception.dart +DA:7,2 +DA:12,0 +DA:13,0 +LF:3 +LH:1 +end_of_record +SF:lib/src/core/adapters/google_books_adapter.dart DA:12,1 +DA:13,1 +DA:14,0 DA:16,1 -DA:20,2 -DA:21,1 +DA:17,3 +DA:18,1 +DA:23,1 +DA:24,1 DA:25,1 +DA:26,2 +DA:28,3 +DA:29,3 DA:30,1 -DA:35,1 -DA:40,1 -DA:45,2 -DA:46,1 -DA:47,1 -DA:51,1 -DA:54,0 -DA:56,0 -LF:14 -LH:12 +DA:31,2 +DA:33,2 +DA:34,1 +DA:35,3 +DA:36,3 +DA:37,1 +DA:38,2 +DA:39,3 +DA:41,2 +DA:43,3 +DA:44,2 +LF:24 +LH:23 end_of_record -SF:lib/src/core/repositories/user_theme_repository/user_theme_repository_impl.dart +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart DA:11,1 -DA:15,1 -DA:18,3 -DA:21,1 -DA:23,0 -DA:25,0 -DA:30,1 -DA:35,1 -DA:40,1 -DA:43,2 -DA:44,1 -DA:45,1 -DA:48,1 -DA:51,0 -DA:53,0 -LF:15 -LH:11 +DA:20,1 +LF:2 +LH:2 end_of_record -SF:lib/src/core/repositories/remote_books_repository/remote_books_repository_impl.dart -DA:8,1 +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:22,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 +end_of_record +SF:lib/src/shared/blocs/book_bloc/book_event.dart DA:10,1 +DA:18,1 +DA:26,1 +DA:34,1 +DA:42,1 +LF:5 +LH:5 +end_of_record +SF:lib/src/shared/blocs/book_bloc/book_state.dart DA:12,2 -DA:15,1 +DA:21,2 +LF:2 +LH:2 +end_of_record +SF:lib/src/shared/blocs/book_bloc/book_bloc.dart +DA:15,3 +DA:16,2 DA:17,2 -DA:20,1 -DA:24,2 -DA:27,1 +DA:18,2 +DA:19,2 +DA:20,2 +DA:21,2 +DA:24,1 +DA:29,2 DA:31,2 -DA:34,1 -DA:36,2 +DA:33,1 +DA:34,2 +DA:38,2 DA:39,1 -DA:41,2 -LF:13 -LH:13 -end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 +DA:40,1 +DA:41,1 +DA:42,1 +DA:43,1 DA:47,0 DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 -LH:0 -end_of_record -SF:lib/src/core/services/book_service/book_service_impl.dart -DA:21,1 -DA:33,1 -DA:36,2 -DA:38,3 -DA:40,3 -DA:41,3 -DA:48,1 -DA:53,1 -DA:56,2 -DA:58,1 -DA:60,1 -DA:66,1 +DA:50,0 +DA:56,1 +DA:61,2 +DA:63,3 +DA:65,1 +DA:66,2 +DA:69,2 +DA:70,1 DA:71,1 -DA:74,2 -DA:76,3 -DA:78,3 -DA:79,3 -DA:86,1 -DA:91,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:78,0 +DA:79,0 +DA:81,0 +DA:87,1 +DA:92,2 DA:94,2 -DA:96,1 -DA:98,2 +DA:95,1 +DA:98,1 DA:99,2 -DA:100,1 DA:103,2 -DA:104,2 -DA:107,2 +DA:104,1 +DA:105,1 +DA:106,1 +DA:107,1 DA:108,1 -DA:113,1 -DA:115,2 -DA:116,2 -DA:117,1 -DA:120,2 -DA:122,0 -DA:125,2 -DA:126,1 +DA:112,0 +DA:113,0 +DA:115,0 +DA:121,1 +DA:126,2 +DA:128,2 +DA:129,1 DA:132,1 -DA:137,1 -DA:141,2 -DA:143,1 -DA:148,1 -DA:151,2 -DA:153,1 -DA:158,1 -DA:161,2 +DA:133,2 +DA:137,2 +DA:138,1 +DA:139,1 +DA:140,1 +DA:141,1 +DA:142,1 +DA:146,0 +DA:147,0 +DA:149,0 +DA:155,1 +DA:160,2 +DA:162,2 DA:163,1 -DA:168,1 -DA:174,2 -DA:179,1 -DA:184,1 -DA:190,2 -DA:195,1 +DA:166,1 +DA:167,2 +DA:171,2 +DA:172,1 +DA:173,1 +DA:174,1 +DA:175,1 +DA:176,1 +DA:180,0 +DA:181,0 +DA:183,0 +DA:189,1 +DA:194,2 +DA:196,1 +DA:197,2 +DA:199,1 DA:200,1 -DA:203,2 -DA:205,1 +DA:208,2 DA:210,1 -DA:213,2 -DA:215,1 -DA:220,1 -DA:222,2 -DA:225,3 -DA:226,1 -DA:228,1 -DA:229,2 -DA:230,2 -DA:231,1 -DA:235,2 -DA:238,3 -DA:239,1 -DA:241,1 -DA:242,2 -DA:243,2 -DA:244,1 -LF:73 -LH:72 +DA:211,2 +DA:215,2 +DA:216,0 +DA:217,0 +DA:218,0 +DA:219,0 +DA:220,0 +DA:224,0 +DA:225,0 +DA:227,0 +LF:98 +LH:75 end_of_record -SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart -DA:11,1 -DA:17,1 +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart +DA:13,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart +DA:10,1 +DA:12,2 +DA:14,1 +DA:16,2 +DA:18,2 DA:20,2 +DA:21,1 DA:22,1 +DA:23,1 +DA:24,1 +LF:10 +LH:10 +end_of_record +SF:lib/src/core/models/custom_notification_model.dart +DA:5,0 +DA:7,0 +DA:8,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:19,0 +DA:21,0 +DA:23,0 +DA:28,0 +DA:31,0 +DA:32,0 +DA:45,2 +DA:54,0 +DA:62,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:72,0 +DA:74,0 +DA:77,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:89,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +LF:37 +LH:1 +end_of_record +SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:23,2 +DA:26,1 DA:27,1 -DA:30,2 -DA:34,1 +DA:32,1 +DA:33,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 DA:39,1 +DA:42,1 DA:43,1 DA:44,1 DA:46,1 -DA:51,1 +DA:52,1 +DA:54,2 DA:56,2 +DA:60,1 DA:61,1 -DA:66,1 -DA:69,2 +DA:62,1 +DA:70,1 +DA:71,1 DA:73,1 -DA:78,1 -DA:82,2 +DA:74,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:80,1 +DA:81,1 +DA:82,1 DA:84,1 -DA:89,1 -DA:93,2 -DA:95,1 -DA:100,1 -DA:106,2 -DA:111,1 -DA:116,1 -DA:119,2 -DA:121,1 -DA:126,1 -DA:129,2 -DA:134,1 -DA:139,1 -DA:142,2 -DA:147,1 -DA:152,1 -DA:155,2 -DA:160,1 -LF:38 -LH:38 +LF:36 +LH:36 end_of_record -SF:lib/src/core/services/loan_services/loan_service_impl.dart -DA:9,1 +SF:lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart DA:11,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/about/bloc/about_bloc.dart +DA:11,3 +DA:12,2 +DA:15,1 +DA:20,2 +DA:21,2 +DA:22,2 +DA:24,1 +DA:25,1 +DA:26,2 +LF:9 +LH:9 +end_of_record +SF:lib/src/features/about/bloc/about_state.dart +DA:10,1 +DA:18,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/auth/bloc/auth_bloc.dart +DA:13,3 DA:14,2 -DA:16,1 -DA:21,1 +DA:17,1 +DA:22,2 DA:24,2 -DA:26,1 +DA:25,1 +DA:28,1 +DA:29,1 +DA:30,1 +DA:39,2 +DA:40,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:44,1 +DA:47,1 +DA:48,1 +DA:49,1 +DA:51,1 +LF:19 +LH:19 +end_of_record +SF:lib/src/features/auth/bloc/auth_event.dart +DA:8,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/features/auth/bloc/auth_state.dart +DA:15,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/features/book_detail/bloc/book_detail_event.dart +DA:8,2 +DA:16,2 +DA:24,1 +LF:3 +LH:3 +end_of_record +SF:lib/src/features/book_detail/bloc/book_detail_state.dart +DA:10,2 +DA:19,2 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_detail/bloc/book_detail_bloc.dart +DA:15,1 +DA:17,2 +DA:18,2 +DA:19,2 +DA:20,2 +DA:23,1 +DA:28,2 +DA:30,2 DA:31,1 DA:34,2 +DA:35,1 +DA:36,1 +DA:37,1 DA:38,1 +DA:39,1 DA:43,1 -DA:46,2 -DA:48,1 -DA:53,1 -DA:56,2 -DA:58,1 -DA:63,1 -DA:66,2 -DA:71,1 -DA:76,1 -DA:79,2 -DA:84,1 -LF:22 -LH:22 -end_of_record -SF:lib/src/core/services/reading_services/reading_service_impl.dart -DA:9,1 -DA:11,1 -DA:14,2 -DA:16,1 -DA:21,1 -DA:24,2 -DA:28,1 -DA:33,1 -DA:38,2 -DA:42,1 -DA:47,1 -DA:50,2 +DA:44,1 +DA:46,1 DA:52,1 -DA:57,1 -DA:60,2 +DA:57,2 +DA:59,2 +DA:60,1 +DA:63,1 +DA:64,1 DA:65,1 -DA:70,1 DA:73,2 +DA:74,1 +DA:75,1 +DA:76,1 +DA:77,1 DA:78,1 +DA:82,1 DA:83,1 -DA:86,2 +DA:85,1 DA:91,1 -LF:22 -LH:22 +DA:96,2 +DA:98,3 +DA:100,1 +DA:101,1 +DA:102,1 +DA:105,2 +DA:111,3 +DA:112,1 +DA:113,1 +DA:114,1 +DA:121,2 +DA:123,1 +DA:124,1 +DA:125,1 +DA:126,1 +DA:127,1 +DA:131,1 +DA:132,1 +DA:134,1 +LF:54 +LH:54 end_of_record -SF:lib/src/core/errors/auth_exception/auth_exception.dart -DA:7,1 -DA:12,0 -DA:13,0 -LF:3 -LH:1 +SF:lib/src/core/helpers/book_status/book_status_extension.dart +DA:7,0 +DA:9,0 +DA:10,0 +DA:11,0 +DA:15,1 +DA:17,1 +DA:18,2 +DA:19,2 +LF:8 +LH:4 end_of_record -SF:lib/src/core/services/auth_service/auth_service_impl.dart -DA:16,1 -DA:22,0 -DA:24,0 -DA:27,0 -DA:33,1 -DA:36,2 +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_event.dart +DA:8,1 +DA:17,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart +DA:11,1 +DA:23,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart +DA:13,1 +DA:15,2 +DA:16,2 +DA:17,2 +DA:20,1 +DA:25,2 +DA:27,2 +DA:28,1 +DA:31,1 +DA:32,1 +DA:36,1 +DA:37,1 DA:38,1 -DA:39,2 +DA:39,1 +DA:40,1 +DA:43,1 DA:44,1 -DA:46,1 +DA:45,1 DA:47,1 -DA:49,1 -DA:51,0 -DA:52,0 -DA:54,0 -DA:59,1 -DA:62,2 -DA:63,1 -DA:66,2 -DA:69,1 -DA:71,0 -DA:72,0 -DA:74,0 -DA:76,0 -DA:77,0 -DA:79,0 -DA:84,0 -DA:87,0 -DA:89,0 -DA:90,0 -DA:92,0 -DA:94,0 -DA:95,0 -DA:97,0 -LF:34 -LH:14 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart -DA:12,0 -DA:14,0 -DA:15,0 -DA:16,0 -DA:18,0 -DA:19,0 -DA:21,0 -DA:22,0 -DA:23,0 -LF:9 -LH:0 +DA:53,1 +DA:58,2 +DA:60,2 +DA:61,1 +DA:62,1 +DA:65,1 +DA:66,1 +DA:67,1 +DA:76,2 +DA:77,1 +DA:78,1 +DA:79,1 +DA:80,1 +DA:81,1 +DA:84,1 +DA:85,1 +DA:86,1 +DA:88,1 +LF:37 +LH:37 end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/apple_auth_strategy.dart -DA:16,0 -DA:20,0 -DA:24,0 -DA:25,0 -DA:27,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:34,0 -DA:37,0 -DA:40,0 -DA:41,0 -DA:43,0 -DA:44,0 -DA:50,0 -DA:51,0 -DA:55,0 -DA:59,0 -DA:60,0 -DA:61,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:69,0 -DA:70,0 -DA:71,0 -DA:72,0 -DA:73,0 -DA:74,0 -DA:77,0 -DA:79,0 -DA:81,0 -DA:83,0 -DA:84,0 -DA:86,0 -DA:91,0 -DA:94,0 -DA:96,0 -DA:97,0 -DA:98,0 -DA:99,0 -DA:100,0 -DA:101,0 -DA:102,0 -DA:103,0 -DA:104,0 -DA:107,0 -DA:109,0 -DA:111,0 -DA:112,0 -DA:114,0 -LF:52 +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart +DA:14,1 +DA:16,2 +DA:17,2 +DA:20,1 +DA:25,2 +DA:27,1 +DA:28,1 +DA:30,1 +DA:31,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:39,1 +DA:42,1 +DA:43,1 +DA:44,1 +DA:46,1 +LF:18 +LH:18 +end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart +DA:11,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart +DA:5,0 +DA:9,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:17,0 +DA:20,0 +LF:7 LH:0 end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/facebook_auth_strategy.dart +SF:lib/src/core/services/app_services/launcher_service/launcher_service.dart +DA:4,0 +DA:6,0 +DA:8,0 DA:17,0 +DA:21,0 DA:23,0 +DA:24,0 DA:27,0 DA:28,0 -DA:30,0 -DA:31,0 -DA:34,0 -DA:35,0 -DA:36,0 -DA:37,0 DA:40,0 -DA:43,0 -DA:44,0 -DA:46,0 -DA:50,0 -DA:53,0 +LF:10 +LH:0 +end_of_record +SF:lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart +DA:8,6 +DA:10,2 +DA:17,2 +DA:25,2 +DA:30,2 +DA:31,2 +DA:32,2 +DA:38,2 +DA:39,2 +DA:40,2 +DA:46,2 +DA:48,2 +DA:49,2 +DA:52,2 +DA:53,2 DA:54,0 -DA:55,0 +DA:56,0 DA:59,0 -DA:60,0 -DA:64,0 -DA:68,0 -DA:69,0 -DA:70,0 -DA:77,0 -DA:79,0 -DA:81,0 -DA:82,0 +DA:64,2 +DA:65,2 +DA:67,0 +DA:70,2 DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 DA:87,0 -DA:88,0 DA:89,0 -DA:93,0 -DA:95,0 DA:97,0 +DA:98,0 DA:99,0 -DA:100,0 -DA:102,0 +DA:101,0 +DA:105,0 DA:107,0 +DA:108,0 DA:110,0 DA:111,0 DA:113,0 -DA:114,0 -DA:115,0 -DA:116,0 -DA:117,0 DA:118,0 -DA:119,0 DA:120,0 -DA:121,0 -DA:124,0 -DA:126,0 -DA:128,0 -DA:129,0 -DA:131,0 -LF:58 -LH:0 -end_of_record -SF:lib/src/core/services/auth_service/auth_strategy/google_auth_strategy.dart -DA:13,0 -DA:19,0 -DA:22,0 -DA:23,0 -DA:25,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:35,0 -DA:36,0 -DA:37,0 -DA:40,0 -DA:44,0 -DA:45,0 -DA:46,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:54,0 -DA:55,0 -DA:56,0 -DA:57,0 -DA:58,0 -DA:59,0 -DA:63,0 -DA:65,0 -DA:67,0 -DA:69,0 -DA:70,0 -DA:72,0 -DA:77,0 -DA:80,0 -DA:81,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:87,0 -DA:88,0 -DA:89,0 -DA:90,0 -DA:91,0 -DA:94,0 -DA:96,0 -DA:98,0 -DA:99,0 -DA:101,0 -LF:47 -LH:0 -end_of_record -SF:lib/src/core/utils/verifier/isbn_verifier.dart -DA:11,9 -DA:16,6 -DA:25,2 -DA:26,2 -DA:28,6 -DA:29,4 -DA:31,4 -DA:43,2 -DA:44,4 -DA:48,2 -DA:49,1 -DA:50,2 -DA:51,1 -DA:52,1 -DA:53,1 -DA:56,2 -DA:69,2 -DA:70,4 -DA:74,4 -DA:75,2 -DA:76,4 -DA:78,2 -DA:81,4 -LF:23 -LH:23 -end_of_record -SF:lib/src/core/data_sources/remote_books_data_source/google_books_data_source_impl.dart -DA:12,1 -DA:17,1 -DA:18,1 -DA:20,1 -DA:22,2 -DA:24,1 -DA:26,2 -DA:28,1 -DA:30,2 -DA:32,1 -DA:34,2 -DA:36,1 -DA:38,2 -DA:40,1 -DA:42,2 -DA:44,1 -DA:51,1 -DA:54,1 -DA:57,1 -DA:58,1 -DA:59,1 -DA:62,1 -DA:64,1 -LF:23 -LH:23 -end_of_record -SF:lib/src/core/errors/rest_client_exception/rest_client_exception.dart -DA:7,2 -DA:12,0 -DA:13,0 -LF:3 -LH:1 -end_of_record -SF:lib/src/core/adapters/google_books_adapter.dart -DA:12,1 -DA:13,1 -DA:14,0 -DA:16,1 -DA:17,3 -DA:18,1 -DA:23,1 -DA:24,1 -DA:25,1 -DA:26,2 -DA:28,3 -DA:29,3 -DA:30,1 -DA:31,2 -DA:33,2 -DA:34,1 -DA:35,3 -DA:36,3 -DA:37,1 -DA:38,2 -DA:39,3 -DA:41,2 -DA:43,3 -DA:44,2 -LF:24 -LH:23 -end_of_record -SF:lib/src/shared/blocs/book_bloc/book_event.dart -DA:10,1 -DA:18,1 -DA:26,1 -DA:34,1 -DA:42,1 -LF:5 -LH:5 -end_of_record -SF:lib/src/shared/blocs/book_bloc/book_state.dart -DA:12,2 -DA:21,2 -LF:2 -LH:2 +DA:121,0 +DA:124,0 +LF:39 +LH:18 end_of_record -SF:lib/src/shared/blocs/book_bloc/book_bloc.dart -DA:15,3 -DA:16,2 -DA:17,2 -DA:18,2 -DA:19,2 -DA:20,2 -DA:21,2 +SF:lib/src/features/book_detail/views/book_detail_page.dart +DA:19,1 DA:24,1 -DA:29,2 -DA:31,2 -DA:33,1 -DA:34,2 -DA:38,2 -DA:39,1 -DA:40,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:47,0 -DA:48,0 -DA:50,0 +DA:25,1 +DA:51,1 +DA:53,1 +DA:55,2 DA:56,1 -DA:61,2 +DA:57,1 +DA:60,3 +DA:61,1 +DA:62,1 DA:63,3 -DA:65,1 -DA:66,2 -DA:69,2 -DA:70,1 +DA:68,1 DA:71,1 -DA:72,1 -DA:73,1 -DA:74,1 -DA:78,0 +DA:73,3 +DA:74,2 +DA:75,1 DA:79,0 +DA:80,0 DA:81,0 -DA:87,1 -DA:92,2 -DA:94,2 +DA:84,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:90,0 +DA:91,0 DA:95,1 -DA:98,1 -DA:99,2 -DA:103,2 -DA:104,1 +DA:100,1 +DA:102,1 DA:105,1 -DA:106,1 -DA:107,1 -DA:108,1 -DA:112,0 -DA:113,0 -DA:115,0 -DA:121,1 -DA:126,2 -DA:128,2 +DA:107,2 +DA:110,1 +DA:112,1 +DA:113,1 +DA:114,1 +DA:115,1 +DA:117,1 +DA:125,1 +DA:128,1 DA:129,1 -DA:132,1 -DA:133,2 -DA:137,2 -DA:138,1 -DA:139,1 -DA:140,1 -DA:141,1 -DA:142,1 -DA:146,0 -DA:147,0 -DA:149,0 -DA:155,1 -DA:160,2 +DA:130,1 +DA:133,1 +DA:135,1 +DA:137,1 +DA:144,1 +DA:145,1 +DA:146,1 +DA:147,1 +DA:148,3 +DA:149,1 +DA:150,0 +DA:151,0 +DA:152,0 +DA:156,3 +DA:160,1 DA:162,2 DA:163,1 +DA:164,3 +DA:165,1 DA:166,1 -DA:167,2 -DA:171,2 -DA:172,1 -DA:173,1 +DA:167,1 +DA:168,3 +DA:169,1 +DA:170,1 +DA:172,2 DA:174,1 DA:175,1 DA:176,1 -DA:180,0 -DA:181,0 -DA:183,0 +DA:177,1 +DA:178,1 +DA:179,1 +DA:181,1 +DA:182,1 +DA:183,1 +DA:184,1 +DA:188,1 DA:189,1 -DA:194,2 -DA:196,1 -DA:197,2 +DA:191,1 +DA:194,1 DA:199,1 -DA:200,1 -DA:208,2 +DA:206,1 +DA:207,1 +DA:208,1 DA:210,1 -DA:211,2 -DA:215,2 -DA:216,0 -DA:217,0 -DA:218,0 -DA:219,0 -DA:220,0 -DA:224,0 -DA:225,0 -DA:227,0 -LF:98 -LH:75 +DA:211,1 +DA:212,1 +DA:214,2 +DA:223,1 +DA:224,1 +DA:226,1 +DA:230,1 +DA:232,1 +DA:233,1 +DA:235,4 +DA:237,1 +DA:238,1 +DA:243,1 +DA:245,1 +DA:250,1 +DA:253,1 +DA:254,1 +DA:255,1 +DA:257,1 +DA:259,0 +DA:260,0 +DA:264,1 +DA:265,1 +DA:268,1 +DA:272,1 +DA:273,1 +DA:274,1 +DA:276,2 +DA:277,1 +DA:284,1 +DA:286,1 +DA:288,1 +DA:294,1 +DA:296,0 +DA:297,0 +DA:299,1 +DA:300,1 +DA:301,1 +DA:303,1 +DA:313,1 +DA:316,1 +DA:317,1 +DA:318,1 +DA:319,1 +DA:321,1 +DA:323,1 +DA:329,1 +DA:331,1 +DA:332,1 +DA:337,1 +DA:338,1 +DA:341,1 +DA:342,1 +DA:344,1 +DA:346,1 +DA:352,1 +DA:354,1 +DA:355,1 +DA:357,1 +DA:359,1 +LF:144 +LH:128 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart -DA:11,1 +SF:lib/src/shared/widgets/book_widget/book_widget.dart +DA:13,1 +DA:23,1 +DA:33,2 +DA:35,4 +DA:37,2 +DA:38,2 +DA:39,2 +DA:40,2 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:55,0 +DA:57,0 +DA:59,0 +DA:69,2 +DA:70,0 +DA:72,0 +LF:21 +LH:9 +end_of_record +SF:lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart +DA:7,1 +DA:10,1 +DA:12,1 +DA:13,1 +DA:14,1 +DA:15,1 +DA:18,3 DA:20,1 -LF:2 -LH:2 +DA:21,1 +DA:22,1 +DA:23,1 +DA:24,4 +LF:12 +LH:12 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart +DA:11,1 DA:16,1 -DA:18,2 -DA:20,2 -DA:22,1 +DA:17,1 DA:23,1 DA:25,1 -DA:26,1 +DA:26,3 DA:27,1 DA:28,1 -DA:29,1 DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:16 -LH:16 +DA:37,1 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:46,0 +DA:47,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:55,0 +DA:56,0 +DA:59,0 +DA:60,0 +DA:67,1 +DA:69,1 +DA:70,1 +DA:71,1 +LF:27 +LH:14 end_of_record -SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart -DA:13,1 -LF:1 -LH:1 +SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart +DA:6,2 +DA:11,4 +DA:13,4 +DA:14,4 +LF:4 +LH:4 end_of_record -SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart +SF:lib/src/features/book_detail/views/widgets/book_rating/book_rating.dart DA:10,1 -DA:12,2 -DA:14,1 -DA:16,2 +DA:16,1 DA:18,2 -DA:20,2 +DA:20,1 DA:21,1 DA:22,1 -DA:23,1 -DA:24,1 -LF:10 -LH:10 -end_of_record -SF:lib/src/core/models/custom_notification_model.dart -DA:5,0 -DA:7,0 -DA:8,0 -DA:12,0 -DA:14,0 -DA:15,0 -DA:19,0 -DA:21,0 -DA:23,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:45,2 -DA:54,0 -DA:62,0 -DA:63,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:72,0 -DA:74,0 -DA:77,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:89,0 -DA:91,0 -DA:92,0 -DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -LF:37 -LH:1 -end_of_record -SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 DA:23,2 -DA:26,1 -DA:27,1 +DA:25,1 +DA:28,1 +DA:31,1 DA:32,1 -DA:33,1 -DA:35,1 -DA:36,1 +DA:34,1 +DA:35,4 DA:37,1 DA:38,1 -DA:39,1 -DA:42,1 -DA:43,1 -DA:44,1 -DA:46,1 -DA:52,1 -DA:54,2 -DA:56,2 -DA:60,1 -DA:61,1 -DA:62,1 -DA:70,1 -DA:71,1 -DA:73,1 -DA:74,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:80,1 -DA:81,1 -DA:82,1 -DA:84,1 -LF:36 -LH:36 -end_of_record -SF:lib/src/shared/cubits/user_theme_cubit/user_theme_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 +LF:15 +LH:15 end_of_record -SF:lib/src/features/about/bloc/about_bloc.dart -DA:11,3 -DA:12,2 -DA:15,1 -DA:20,2 -DA:21,2 -DA:22,2 +SF:lib/src/shared/widgets/bookify_rating/bookify_rating_widget.dart +DA:13,1 DA:24,1 -DA:25,1 -DA:26,2 -LF:9 -LH:9 -end_of_record -SF:lib/src/features/about/bloc/about_state.dart -DA:10,1 -DA:18,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/auth/bloc/auth_bloc.dart -DA:13,3 -DA:14,2 -DA:17,1 -DA:22,2 -DA:24,2 -DA:25,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:39,2 -DA:40,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:44,1 -DA:47,1 -DA:48,1 -DA:49,1 +DA:27,2 +DA:29,0 +DA:30,5 +DA:33,1 +DA:36,1 +DA:39,1 +DA:45,1 +DA:47,2 +DA:48,2 +DA:49,2 DA:51,1 -LF:19 -LH:19 -end_of_record -SF:lib/src/features/auth/bloc/auth_event.dart -DA:8,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/features/auth/bloc/auth_state.dart -DA:15,1 -LF:1 -LH:1 +DA:52,1 +DA:54,1 +DA:55,2 +LF:16 +LH:15 end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_event.dart -DA:8,1 -DA:17,1 -LF:2 -LH:2 +SF:lib/src/shared/widgets/buttons/bookify_elevated_button.dart +DA:10,1 +DA:19,2 +DA:28,3 +DA:30,3 +DA:32,3 +DA:33,7 +DA:34,3 +DA:35,3 +DA:36,3 +DA:37,3 +DA:38,0 +DA:39,0 +DA:40,0 +DA:44,6 +DA:45,3 +DA:46,3 +DA:50,0 +DA:51,0 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:59,0 +DA:60,0 +LF:24 +LH:13 end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart -DA:11,1 -DA:23,1 +SF:lib/src/features/bookcase/bloc/bookcase_state.dart +DA:10,2 +DA:21,2 LF:2 LH:2 end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart -DA:13,1 -DA:15,2 -DA:16,2 -DA:17,2 -DA:20,1 -DA:25,2 -DA:27,2 -DA:28,1 -DA:31,1 -DA:32,1 +SF:lib/src/features/bookcase/bloc/bookcase_bloc.dart +DA:17,1 +DA:20,2 +DA:21,2 +DA:22,2 +DA:23,2 +DA:26,1 +DA:31,2 +DA:33,1 +DA:34,1 +DA:35,1 DA:36,1 DA:37,1 DA:38,1 -DA:39,1 -DA:40,1 +DA:41,1 +DA:42,1 DA:43,1 -DA:44,1 DA:45,1 -DA:47,1 -DA:53,1 +DA:51,1 +DA:56,2 DA:58,2 -DA:60,2 +DA:59,1 +DA:60,1 DA:61,1 DA:62,1 -DA:65,1 +DA:63,1 DA:66,1 DA:67,1 -DA:76,2 -DA:77,1 -DA:78,1 -DA:79,1 -DA:80,1 -DA:81,1 -DA:84,1 -DA:85,1 -DA:86,1 -DA:88,1 -LF:37 -LH:37 +DA:68,1 +DA:70,1 +DA:76,1 +DA:81,2 +DA:83,1 +DA:85,2 +DA:86,2 +DA:87,2 +DA:90,2 +DA:91,1 +DA:92,1 +DA:95,3 +DA:102,1 +DA:103,1 +DA:104,1 +DA:105,1 +DA:106,1 +DA:107,1 +DA:110,1 +DA:111,1 +DA:112,1 +DA:114,1 +DA:120,1 +DA:121,2 +DA:123,1 +DA:124,2 +DA:128,1 +DA:131,1 +DA:135,2 +DA:137,1 +DA:138,2 +DA:142,1 +DA:145,1 +DA:149,1 +DA:151,2 +DA:152,1 +DA:153,1 +DA:154,1 +DA:162,2 +DA:163,1 +DA:169,2 +DA:172,1 +DA:177,1 +DA:180,2 +LF:71 +LH:71 +end_of_record +SF:lib/src/features/bookcase/bloc/bookcase_event.dart +DA:10,1 +DA:18,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/core/dtos/bookcase_dto.dart +DA:7,2 +DA:12,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:22,0 +DA:24,0 +DA:26,1 +DA:30,3 +DA:31,0 +DA:34,0 +DA:35,0 +LF:12 +LH:3 end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 @@ -2490,21 +2698,6 @@ DA:44,0 LF:12 LH:0 end_of_record -SF:lib/src/core/helpers/textfield_unfocus/textfield_unfocus_extension.dart -DA:8,0 -DA:23,6 -LF:2 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/color_picker_dialog_service/color_picker_dialog_service.dart -DA:6,0 -DA:13,0 -DA:15,0 -DA:25,0 -DA:26,0 -LF:5 -LH:0 -end_of_record SF:lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart DA:24,0 DA:30,0 @@ -2789,142 +2982,6 @@ DA:197,1 LF:90 LH:52 end_of_record -SF:lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart -DA:33,1 -DA:41,1 -DA:42,1 -DA:55,1 -DA:59,1 -DA:65,1 -DA:66,1 -DA:79,1 -DA:81,1 -DA:83,1 -DA:85,3 -DA:87,5 -DA:88,5 -DA:89,4 -DA:92,1 -DA:94,2 -DA:95,2 -DA:96,1 -DA:102,0 -DA:103,0 -DA:104,0 -DA:105,0 -DA:107,0 -DA:108,0 -DA:124,1 -DA:125,3 -DA:126,2 -DA:129,2 -DA:130,1 -DA:131,3 -DA:132,4 -DA:134,3 -DA:135,1 -DA:139,2 -DA:140,2 -DA:141,1 -DA:142,1 -DA:143,3 -DA:144,4 -DA:146,3 -DA:147,1 -DA:151,4 -DA:152,0 -DA:153,0 -DA:154,0 -DA:156,1 -DA:157,3 -DA:158,3 -DA:159,1 -DA:163,2 -DA:164,1 -DA:169,1 -DA:174,1 -DA:175,0 -DA:177,0 -DA:182,1 -DA:183,1 -DA:185,1 -DA:191,2 -DA:192,1 -DA:193,1 -DA:194,3 -DA:196,1 -DA:202,1 -DA:203,1 -DA:204,1 -DA:206,1 -DA:208,1 -DA:212,2 -DA:213,1 -DA:214,1 -DA:215,2 -DA:223,1 -DA:225,2 -DA:228,1 -DA:229,1 -DA:231,2 -DA:233,1 -DA:234,1 -DA:235,1 -DA:236,1 -DA:237,1 -DA:239,1 -DA:243,1 -DA:244,1 -DA:246,1 -DA:247,1 -DA:252,1 -DA:253,1 -DA:255,1 -DA:256,1 -DA:257,1 -DA:258,1 -DA:261,1 -DA:262,1 -DA:264,1 -DA:265,1 -DA:267,1 -DA:268,1 -DA:269,1 -DA:270,1 -DA:272,1 -DA:274,1 -DA:278,2 -DA:280,1 -DA:281,1 -DA:285,1 -DA:287,1 -DA:288,1 -DA:289,2 -DA:291,1 -DA:292,1 -DA:296,1 -DA:301,0 -DA:302,0 -DA:303,0 -DA:305,0 -DA:308,0 -DA:309,1 -DA:310,1 -DA:312,1 -DA:314,1 -DA:317,1 -DA:318,1 -DA:319,2 -DA:320,1 -DA:329,1 -DA:330,1 -DA:331,1 -DA:335,1 -DA:337,1 -DA:338,1 -LF:132 -LH:116 -end_of_record SF:lib/src/shared/widgets/item_state_widget/item_empty_state_widget/item_empty_widget.dart DA:7,1 DA:13,1 @@ -3161,9 +3218,9 @@ LF:32 LH:26 end_of_record SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart -DA:12,1 -DA:21,1 -DA:34,1 +DA:17,1 +DA:26,1 +DA:39,1 LF:3 LH:3 end_of_record @@ -3174,56 +3231,56 @@ LF:2 LH:2 end_of_record SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart -DA:17,1 +DA:16,1 +DA:19,2 DA:20,2 DA:21,2 -DA:22,2 -DA:25,1 -DA:30,2 -DA:32,2 +DA:24,1 +DA:29,2 +DA:31,2 +DA:33,1 DA:34,1 DA:35,1 -DA:36,1 -DA:44,1 -DA:45,2 +DA:42,1 +DA:43,2 +DA:46,1 +DA:47,2 DA:48,1 -DA:49,2 -DA:50,1 -DA:51,4 +DA:49,4 +DA:56,1 +DA:57,1 DA:58,1 -DA:59,1 -DA:60,1 -DA:63,1 +DA:61,1 +DA:65,1 +DA:66,1 +DA:67,1 DA:68,1 DA:69,1 -DA:70,1 -DA:71,1 DA:72,1 -DA:75,1 +DA:73,1 +DA:74,1 DA:76,1 -DA:77,1 -DA:79,1 -DA:85,1 -DA:90,2 -DA:92,1 -DA:94,2 -DA:95,2 -DA:96,1 +DA:82,1 +DA:87,2 +DA:89,1 +DA:91,2 +DA:92,2 +DA:93,1 +DA:94,1 DA:97,1 -DA:100,1 -DA:101,1 -DA:102,1 -DA:104,2 -DA:111,2 +DA:98,1 +DA:99,1 +DA:101,2 +DA:108,2 +DA:109,1 +DA:110,1 +DA:111,1 DA:112,1 DA:113,1 -DA:114,1 -DA:115,1 DA:116,1 -DA:119,1 +DA:117,1 +DA:118,1 DA:120,1 -DA:121,1 -DA:123,1 LF:50 LH:50 end_of_record @@ -3243,47 +3300,51 @@ DA:49,0 DA:50,0 DA:52,0 DA:53,0 +DA:55,0 +DA:56,0 +DA:57,0 DA:58,0 -DA:59,0 -DA:62,0 DA:63,0 DA:64,0 -DA:65,0 -DA:71,0 -DA:72,0 -DA:73,0 -DA:75,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 DA:76,0 DA:77,0 +DA:78,0 +DA:80,0 +DA:81,0 DA:82,0 -DA:86,0 DA:87,0 -DA:88,0 DA:91,0 +DA:92,0 DA:93,0 -DA:97,0 +DA:96,0 DA:98,0 -DA:99,0 -DA:100,0 -DA:107,0 -DA:108,0 -DA:109,0 -DA:110,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:112,0 +DA:113,0 +DA:114,0 DA:115,0 -DA:117,0 -DA:118,0 DA:120,0 -DA:121,0 DA:122,0 DA:123,0 -DA:124,0 DA:125,0 +DA:126,0 DA:127,0 DA:128,0 DA:129,0 +DA:130,0 DA:132,0 +DA:133,0 DA:134,0 -LF:55 +DA:137,0 +DA:139,0 +LF:59 LH:0 end_of_record SF:lib/src/features/bookcase_books_insertion/widgets/bookcase_books_insertion_loaded_state_widget/bookcase_books_insertion_loaded_state.dart @@ -3558,73 +3619,15 @@ DA:183,0 LF:86 LH:0 end_of_record -SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_event.dart -DA:11,2 -DA:24,2 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart -DA:16,1 -DA:18,2 -DA:19,2 -DA:20,2 -DA:23,1 -DA:28,2 -DA:30,1 -DA:31,1 -DA:32,1 -DA:33,1 -DA:36,2 -DA:40,1 -DA:41,1 -DA:42,1 -DA:51,1 -DA:52,1 -DA:56,1 -DA:57,1 -DA:58,1 -DA:60,1 -DA:63,1 -DA:64,1 -DA:65,1 -DA:67,1 -DA:73,1 -DA:78,2 -DA:80,1 -DA:81,1 -DA:82,1 -DA:83,1 -DA:84,1 -DA:87,2 -DA:91,1 -DA:92,1 -DA:93,1 -DA:102,1 -DA:103,1 -DA:107,1 -DA:108,1 -DA:109,1 -DA:110,1 -DA:111,1 -DA:114,1 -DA:115,1 -DA:116,1 -DA:118,1 -LF:46 -LH:46 -end_of_record -SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart -DA:11,2 -DA:18,2 -LF:2 -LH:2 -end_of_record SF:lib/src/shared/constants/images/bookify_images.dart DA:7,0 LF:1 LH:0 end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_event.dart DA:8,1 LF:1 @@ -3938,6 +3941,55 @@ DA:117,1 LF:43 LH:43 end_of_record +SF:lib/src/features/my_books/bloc/my_books_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_bloc.dart +DA:14,3 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,2 +DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,1 +DA:63,2 +DA:67,2 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:79,1 +LF:34 +LH:34 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:20,1 DA:24,2 @@ -3993,55 +4045,6 @@ DA:19,1 LF:2 LH:2 end_of_record -SF:lib/src/features/my_books/bloc/my_books_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_bloc.dart -DA:14,3 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,2 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:45,1 -DA:51,1 -DA:56,2 -DA:58,2 -DA:59,1 -DA:62,1 -DA:63,2 -DA:67,2 -DA:68,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:72,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:79,1 -LF:34 -LH:34 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/features/home/views/home_page.dart DA:11,1 DA:13,1 diff --git a/lib/src/core/database/local_database_impl.dart b/lib/src/core/database/local_database_impl.dart index 3a2f9064..d4c00443 100644 --- a/lib/src/core/database/local_database_impl.dart +++ b/lib/src/core/database/local_database_impl.dart @@ -439,48 +439,20 @@ class LocalDatabaseImpl implements LocalDatabase { } LocalDatabaseException _toLocalDatabaseMapper(DatabaseException e) { - if (e.isNoSuchTableError()) { - return LocalDatabaseException( - LocalDatabaseErrorCode.noSuchTable, - descriptionMessage: e.toString(), - ); - } - if (e.isDuplicateColumnError()) { - return LocalDatabaseException( - LocalDatabaseErrorCode.duplicateColumn, - descriptionMessage: e.toString(), - ); - } - if (e.isSyntaxError()) { - return LocalDatabaseException( - LocalDatabaseErrorCode.syntaxError, - descriptionMessage: e.toString(), - ); - } if (e.isOpenFailedError()) { return LocalDatabaseException( LocalDatabaseErrorCode.openFailed, descriptionMessage: e.toString(), ); } - if (e.isDatabaseClosedError()) { - return LocalDatabaseException( - LocalDatabaseErrorCode.databaseClosed, - descriptionMessage: e.toString(), - ); - } - if (e.isReadOnlyError()) { - return LocalDatabaseException( - LocalDatabaseErrorCode.readOnly, - descriptionMessage: e.toString(), - ); - } + if (e.isUniqueConstraintError()) { return LocalDatabaseException( LocalDatabaseErrorCode.uniqueConstraint, descriptionMessage: e.toString(), ); } + if (e.isNotNullConstraintError()) { return LocalDatabaseException( LocalDatabaseErrorCode.notNullConstraint, diff --git a/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart b/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart index a2df415d..a5cce1e8 100644 --- a/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart +++ b/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart @@ -1,36 +1,16 @@ import 'package:bookify/src/shared/enums/local_database_error_code.dart'; import 'package:localization/localization.dart'; -// TODO Localizate the messages - extension LocalDatabaseErrorCodeExtension on LocalDatabaseErrorCode { String toLocalizedMessage(String? descriptionMessage) { final messageArg = descriptionMessage ?? '---'; return switch (this) { - LocalDatabaseErrorCode.noSuchTable => - 'error-local-database-no-such-table'.i18n([ - messageArg, - ]), - LocalDatabaseErrorCode.duplicateColumn => - 'error-local-database-duplicate-column'.i18n([ - messageArg, - ]), - LocalDatabaseErrorCode.syntaxError => - 'error-local-database-syntax-error'.i18n([ - messageArg, - ]), LocalDatabaseErrorCode.openFailed => 'error-local-database-open-failed'.i18n([ messageArg, ]), - LocalDatabaseErrorCode.databaseClosed => - 'error-local-database-database-closed'.i18n([ - messageArg, - ]), - LocalDatabaseErrorCode.readOnly => 'error-local-database-read-only'.i18n([ - messageArg, - ]), + LocalDatabaseErrorCode.uniqueConstraint => 'error-local-database-unique-constraint'.i18n([ messageArg, @@ -46,6 +26,10 @@ extension LocalDatabaseErrorCodeExtension on LocalDatabaseErrorCode { LocalDatabaseErrorCode.unknown => 'error-local-database-unknown'.i18n([ messageArg, ]), + LocalDatabaseErrorCode.operationFailed => + 'error-local-database-operation-failed'.i18n([ + messageArg, + ]), }; } } diff --git a/lib/src/features/book_detail/bloc/book_detail_bloc.dart b/lib/src/features/book_detail/bloc/book_detail_bloc.dart index ee08fba5..c09d5ce6 100644 --- a/lib/src/features/book_detail/bloc/book_detail_bloc.dart +++ b/lib/src/features/book_detail/bloc/book_detail_bloc.dart @@ -63,7 +63,7 @@ class BookDetailBloc extends Bloc { if (bookInserted != 1) { emit( BookDetailErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'Error on insert book', ), ); @@ -100,7 +100,7 @@ class BookDetailBloc extends Bloc { if (bookStatus != BookStatus.library) { emit( BookDetailErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'Impossible to remove this book because is: ${bookStatus.label}.', ), @@ -112,7 +112,7 @@ class BookDetailBloc extends Bloc { if (bookRemoved != 1) { emit( BookDetailErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'Error on remove book', ), ); diff --git a/lib/src/features/book_detail/bloc/book_detail_state.dart b/lib/src/features/book_detail/bloc/book_detail_state.dart index fee35846..f474bacc 100644 --- a/lib/src/features/book_detail/bloc/book_detail_state.dart +++ b/lib/src/features/book_detail/bloc/book_detail_state.dart @@ -18,6 +18,6 @@ final class BookDetailErrorState extends BookDetailState { BookDetailErrorState({ required this.errorCode, - required this.errorDescriptionMessage, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart b/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart index 187f6587..6544bf1d 100644 --- a/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart +++ b/lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart @@ -65,7 +65,7 @@ class BookOnBookcaseDetailBloc if (deletedBook != 1) { emit( BookOnBookcaseDetailErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'Failed to delete the book from the bookcase. Please try again.', ), diff --git a/lib/src/features/bookcase/bloc/bookcase_bloc.dart b/lib/src/features/bookcase/bloc/bookcase_bloc.dart index 7591d760..fbc7b45f 100644 --- a/lib/src/features/bookcase/bloc/bookcase_bloc.dart +++ b/lib/src/features/bookcase/bloc/bookcase_bloc.dart @@ -90,7 +90,7 @@ class BookcaseBloc extends Bloc { if (bookcaseDeletedRow == -1) { emit( BookcaseErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'Failed to delete the bookcase ${bookcaseDto.bookcase.name}.', ), diff --git a/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart b/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart index b3f8862b..e33b51f5 100644 --- a/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart +++ b/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_bloc.dart @@ -8,7 +8,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; part 'bookcase_books_insertion_event.dart'; part 'bookcase_books_insertion_state.dart'; -//TODO - Remove EmptyState String class BookcaseBooksInsertionBloc extends Bloc { final BookService _bookService; @@ -34,8 +33,7 @@ class BookcaseBooksInsertionBloc if (booksList.isEmpty) { emit( BookcaseBooksInsertionEmptyState( - message: - 'Nenhum livro cadastrado. Volte à Página início para cadastrar.', + reason: BookcaseBooksEmptyReason.noBooksRegistered, ), ); return; @@ -61,8 +59,7 @@ class BookcaseBooksInsertionBloc books: booksList, ) : BookcaseBooksInsertionEmptyState( - message: - 'Todos os livros cadastrados já foram adicionados nessa estante.', + reason: BookcaseBooksEmptyReason.allBooksAlreadyInserted, ), ); } on LocalDatabaseException catch (e) { @@ -100,7 +97,7 @@ class BookcaseBooksInsertionBloc if (insertedRow == 0) { emit( BookcaseBooksInsertionErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'Error on insert book: ${book.title}', ), ); diff --git a/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart b/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart index b7425b15..9614b0d1 100644 --- a/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart +++ b/lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart @@ -1,5 +1,10 @@ part of 'bookcase_books_insertion_bloc.dart'; +enum BookcaseBooksEmptyReason { + noBooksRegistered, + allBooksAlreadyInserted, +} + sealed class BookcaseBooksInsertionState {} final class BookcaseBooksInsertionLoadingState @@ -7,10 +12,10 @@ final class BookcaseBooksInsertionLoadingState final class BookcaseBooksInsertionEmptyState extends BookcaseBooksInsertionState { - final String message; + final BookcaseBooksEmptyReason reason; BookcaseBooksInsertionEmptyState({ - required this.message, + required this.reason, }); } diff --git a/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart b/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart index b30eda69..905a2a09 100644 --- a/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart +++ b/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart @@ -49,9 +49,14 @@ class _BookcaseBooksInsertionPageState BookcaseBooksInsertionLoadingState() || BookcaseBooksInsertionInsertedState() => const CenterCircularProgressIndicator(), - BookcaseBooksInsertionEmptyState() => Center( + BookcaseBooksInsertionEmptyState(:final reason) => Center( child: Text( - 'Nenhum livro cadastrado. Volte à Página início para cadastrar.', + switch (reason) { + BookcaseBooksEmptyReason.noBooksRegistered => + 'no-books-registered'.i18n(), + BookcaseBooksEmptyReason.allBooksAlreadyInserted => + 'all-books-already-inserted'.i18n(), + }, textAlign: TextAlign.center, ), ), diff --git a/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart b/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart index 64ab54db..b4b9ee34 100644 --- a/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart +++ b/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart @@ -8,7 +8,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; part 'bookcase_insertion_event.dart'; part 'bookcase_insertion_state.dart'; -//TODO - Remove SuccessMessage String class BookcaseInsertionBloc extends Bloc { final BookcaseService _bookcaseService; @@ -40,7 +39,7 @@ class BookcaseInsertionBloc if (newBookcaseId == 0) { emit( BookcaseInsertionErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'An error occurred while inserting the bookcase', ), @@ -50,7 +49,7 @@ class BookcaseInsertionBloc emit( BookcaseInsertionInsertedState( - bookcaseInsertionMessage: 'Estante inserida com sucesso', + reason: BookcaseInsertionSuccessReason.inserted, ), ); } on LocalDatabaseException catch (e) { @@ -91,7 +90,7 @@ class BookcaseInsertionBloc if (bookcaseRowUpdated < 1) { emit( BookcaseInsertionErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'An error occurred while updating the bookcase', ), @@ -101,7 +100,7 @@ class BookcaseInsertionBloc emit( BookcaseInsertionInsertedState( - bookcaseInsertionMessage: 'Estante atualizada com sucesso', + reason: BookcaseInsertionSuccessReason.updated, ), ); } on LocalDatabaseException catch (e) { diff --git a/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart b/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart index 5d2fba71..abc3854a 100644 --- a/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart +++ b/lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart @@ -1,14 +1,19 @@ part of 'bookcase_insertion_bloc.dart'; +enum BookcaseInsertionSuccessReason { + inserted, + updated, +} + @immutable sealed class BookcaseInsertionState {} final class BookcaseInsertionLoadingState extends BookcaseInsertionState {} final class BookcaseInsertionInsertedState extends BookcaseInsertionState { - final String bookcaseInsertionMessage; + final BookcaseInsertionSuccessReason reason; - BookcaseInsertionInsertedState({required this.bookcaseInsertionMessage}); + BookcaseInsertionInsertedState({required this.reason}); } final class BookcaseInsertionErrorState extends BookcaseInsertionState { diff --git a/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart b/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart index 1075c08c..6346a1bf 100644 --- a/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart +++ b/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart @@ -179,12 +179,15 @@ class _BookcaseInsertionPageState extends State { ); break; - case BookcaseInsertionInsertedState( - bookcaseInsertionMessage: final successMessage, - ): + case BookcaseInsertionInsertedState(:final reason): SnackbarService.showSnackBar( context, - successMessage, + switch (reason) { + BookcaseInsertionSuccessReason.inserted => + 'bookcase-inserted-success-snackbar'.i18n(), + BookcaseInsertionSuccessReason.updated => + 'bookcase-updated-success-snackbar'.i18n(), + }, SnackBarType.success, ); diff --git a/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart b/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart index 6fa5d8d6..ae614d3d 100644 --- a/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart +++ b/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart @@ -99,7 +99,7 @@ class LoanInsertionBloc extends Bloc { } } - // TODO Create a localizated notification message + // TODO Create a localized notification message Future _createNotification( int loanId, String contactName, diff --git a/lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart b/lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart index 1e351d3a..3fac7f61 100644 --- a/lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart +++ b/lib/src/features/readings_insertion/bloc/readings_insertion_bloc.dart @@ -38,7 +38,7 @@ class ReadingsInsertionBloc if (bookPageCountUpdated != 1) { emit( ReadingsInsertionErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'An error occurred while updating the book page count.', ), @@ -54,7 +54,7 @@ class ReadingsInsertionBloc if (bookStatusUpdated != 1) { emit( ReadingsInsertionErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'An error occurred while updating the book status.', ), @@ -72,7 +72,7 @@ class ReadingsInsertionBloc if (newReadingId < 1) { emit( ReadingsInsertionErrorState( - errorCode: LocalDatabaseErrorCode.unknown, + errorCode: LocalDatabaseErrorCode.operationFailed, errorDescriptionMessage: 'An error occurred while inserting the reading.', ), diff --git a/lib/src/shared/enums/local_database_error_code.dart b/lib/src/shared/enums/local_database_error_code.dart index b1578294..38ba65b8 100644 --- a/lib/src/shared/enums/local_database_error_code.dart +++ b/lib/src/shared/enums/local_database_error_code.dart @@ -1,12 +1,8 @@ enum LocalDatabaseErrorCode { - noSuchTable, - duplicateColumn, - syntaxError, - openFailed, - databaseClosed, - readOnly, uniqueConstraint, notNullConstraint, + openFailed, invalidData, + operationFailed, unknown, } diff --git a/pubspec.yaml b/pubspec.yaml index 90f76b8c..09f6015a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.7 +version: 2.11.8 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart b/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart index 219e20dc..23bd3bfa 100644 --- a/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart +++ b/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart @@ -64,7 +64,7 @@ void main() { bookcaseInsertionBloc, Stream.fromIterable([ BookcaseInsertionInsertedState( - bookcaseInsertionMessage: 'Bookcase inserted successfully', + reason: BookcaseInsertionSuccessReason.inserted, ), ]), ); @@ -86,7 +86,7 @@ void main() { await tester.pumpAndSettle(); expect(find.byType(SnackBar), findsOneWidget); - expect(find.text('Bookcase inserted successfully'), findsOneWidget); + expect(find.text('bookcase-inserted-success-snackbar'), findsOneWidget); await tester.pumpAndSettle(const Duration(seconds: 2)); @@ -174,7 +174,7 @@ void main() { bookcaseInsertionBloc, Stream.fromIterable([ BookcaseInsertionInsertedState( - bookcaseInsertionMessage: 'Updated successfully', + reason: BookcaseInsertionSuccessReason.updated, ), ]), ); @@ -192,7 +192,7 @@ void main() { await tester.tap(find.byKey(const Key('ConfirmBookcaseInsertionButton'))); await tester.pumpAndSettle(); - expect(find.text('Updated successfully'), findsOneWidget); + expect(find.text('bookcase-updated-success-snackbar'), findsOneWidget); await tester.pumpAndSettle(const Duration(seconds: 2)); expect(find.byType(BookcaseInsertionPage), findsNothing); }); From 7a36d3f9c44e3a152da38da47c098d01100ff03a Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Fri, 22 May 2026 06:22:13 -0300 Subject: [PATCH 13/19] Refactor notification channel model and improve notification handling - Added NotificationChannelExtension for better localization of channel descriptions and labels. - Enhanced NotificationsServiceImpl to use localized labels for notification channels. - Updated ProgrammingReadingBloc to use localized notification titles and bodies. - Adjusted InsertedHourTimeEvent to include notification title and body. - Updated ProgrammingReadingPage to pass localized notification messages. - Updated pubspec.yaml and pubspec.lock for dependency version upgrades. - Added tests for new notification title and body handling in programming reading bloc. --- assets/lang/en_US.json | 8 +- assets/lang/it_IT.json | 14 +- assets/lang/pt_BR.json | 8 +- coverage/lcov.info | 1172 ++++++++--------- .../notification_channel_extension.dart | 22 + .../models/custom_notification_model.dart | 17 - .../contacts_service_impl.dart | 10 +- .../notifications_service_impl.dart | 5 +- .../loan_detail/bloc/loan_detail_bloc.dart | 2 +- .../bloc/programming_reading_bloc.dart | 4 +- .../bloc/programming_reading_event.dart | 4 + .../views/programming_reading_page.dart | 2 + pubspec.lock | 12 +- pubspec.yaml | 4 +- .../bloc/programming_reading_bloc_test.dart | 8 + 15 files changed, 665 insertions(+), 627 deletions(-) create mode 100644 lib/src/core/helpers/notification_channel/notification_channel_extension.dart diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index 0563f2bf..ce7f228d 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -35,6 +35,8 @@ "reading-time-description": "Scheduling time for reading is the first step to creating a habit.\n\nSet the days and times that work best for your reading, and we'll remind you here in the notifications!", "reading-time-calculate-success-snackbar": "Reading time successfully calculated.", "reading-time-notification-removed-success-snackbar": "Notification successfully removed.", + "reading-time-notification-title": "Time to read!", + "reading-time-notification-body": "Many adventures await you!", "repeat-time-title": "Set the repetition to be notified for your readings:", "daily-dropdown-menu-entry": "Daily", "weekly-dropdown-menu-entry": "Weekly", @@ -272,5 +274,9 @@ "error-local-database-open-failed": "Could not open the database. %s", "error-local-database-operation-failed": "Database operation failed during read, write, or update. %s", "error-local-database-unique-constraint": "This record already exists in the database. %s", - "error-local-database-unknown": "Unknown error in the database. %s" + "error-local-database-unknown": "Unknown error in the database. %s", + "notification-channel-loan-description": "Channel that notifies when it's time to receive your loaned book.", + "notification-channel-loan-label": "Loans", + "notification-channel-read-description": "Channel that notifies when it's time for reading.", + "notification-channel-read-label": "Readings" } diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index a7549238..03933246 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -35,6 +35,8 @@ "reading-time-description": "Pianificare un momento dedicato alla lettura è il primo passo per creare l'abitudine.\n\nDecidi quali giorni e quali sono gli orari migliori per le tue letture e noi te lo ricorderemo qui nelle notifiche!", "reading-time-calculate-success-snackbar": "Tempo di lettura calcolato con successo.", "reading-time-notification-removed-success-snackbar": "Notifica rimossa con successo.", + "reading-time-notification-title": "È l'ora di leggere!", + "reading-time-notification-body": "Molte avventure ti aspettano!", "repeat-time-title": "Imposta la ripetizione per ricevere una notifica per le tue letture:", "daily-dropdown-menu-entry": "Giornaliera", "weekly-dropdown-menu-entry": "Settimanale", @@ -101,8 +103,10 @@ "search-by-publisher-tooltip": "Cerca per editore", "search-by-isbn-tooltip": "Cerca per ISBN", "book-successfully-added-snackbar": "Libro aggiunto con successo.", - "book-successfully-removed-snackbar": "Libro rimosso con successo.", "bookcase-inserted-success-snackbar": "Libreria aggiunta con successo.", - "bookcase-updated-success-snackbar": "Libreria aggiornata con successo.", "remove-book-title": "Rimuovere il libro %s", + "book-successfully-removed-snackbar": "Libro rimosso con successo.", + "bookcase-inserted-success-snackbar": "Libreria aggiunta con successo.", + "bookcase-updated-success-snackbar": "Libreria aggiornata con successo.", + "remove-book-title": "Rimuovere il libro %s", "remove-book-description": "Cliccando su “CONFERMA” rimuoverai questo libro dal tuo Scaffale.\nSei sicuro?", "pages-label": "%s PAGINE", "go-to-store-button": "Vai allo store", @@ -270,5 +274,9 @@ "error-local-database-open-failed": "Impossibile aprire il database. %s", "error-local-database-operation-failed": "Operazione del database fallita durante lettura, scrittura o aggiornamento. %s", "error-local-database-unique-constraint": "Questo record esiste già nel database. %s", - "error-local-database-unknown": "Errore sconosciuto nel database. %s" + "error-local-database-unknown": "Errore sconosciuto del database. %s", + "notification-channel-loan-description": "Canale che notifica quando è il momento di ricevere il libro prestato.", + "notification-channel-loan-label": "Prestiti", + "notification-channel-read-description": "Canale che notifica quando è il momento della lettura.", + "notification-channel-read-label": "Letture" } diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index dfb4fda8..ee3accb5 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -35,6 +35,8 @@ "reading-time-description": "A programação para um momento de leitura é o primeiro passo para criar o hábito.\n\nDefina quais dias e o melhor horário para as suas leituras, e a gente te lembrará aqui nas notificações!", "reading-time-calculate-success-snackbar": "Hora de leitura calculado com sucesso.", "reading-time-notification-removed-success-snackbar": "Notificação removida com sucesso.", + "reading-time-notification-title": "A hora da leitura chegou!", + "reading-time-notification-body": "Muitas aventuras te aguardam!", "repeat-time-title": "Defina a repetição para ser notificado para a suas leituras:", "daily-dropdown-menu-entry": "Diariamente", "weekly-dropdown-menu-entry": "Semanalmente", @@ -272,5 +274,9 @@ "error-local-database-open-failed": "Não foi possível abrir o banco de dados. %s", "error-local-database-operation-failed": "Operação do banco de dados falhou durante leitura, escrita ou atualização. %s", "error-local-database-unique-constraint": "Este registro já existe no banco de dados. %s", - "error-local-database-unknown": "Erro desconhecido no banco de dados. %s" + "error-local-database-unknown": "Erro desconhecido no banco de dados. %s", + "notification-channel-loan-description": "Canal que notifica quando é o dia de receber o livro emprestado.", + "notification-channel-loan-label": "Empréstimos", + "notification-channel-read-description": "Canal que notifica que está na hora da leitura.", + "notification-channel-read-label": "Leituras" } diff --git a/coverage/lcov.info b/coverage/lcov.info index 583ec734..46905bdf 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -9,375 +9,6 @@ DA:15,9 LF:7 LH:7 end_of_record -SF:lib/src/core/errors/local_database_exception/local_database_exception.dart -DA:7,7 -DA:12,0 -DA:13,0 -LF:3 -LH:1 -end_of_record -SF:lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart -DA:5,3 -DA:9,3 -DA:10,0 -DA:14,3 -DA:15,0 -DA:18,3 -DA:19,0 -DA:22,3 -DA:23,0 -DA:26,9 -DA:29,0 -DA:30,0 -LF:12 -LH:6 -end_of_record -SF:lib/src/core/helpers/textfield_unfocus/textfield_unfocus_extension.dart -DA:8,0 -DA:23,6 -LF:2 -LH:1 -end_of_record -SF:lib/src/core/models/bookcase_model.dart -DA:10,3 -DA:17,3 -DA:19,3 -DA:25,3 -DA:26,2 -DA:27,2 -DA:28,2 -DA:29,1 -DA:33,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:42,0 -DA:46,1 -DA:47,1 -DA:48,1 -DA:49,1 -DA:50,1 -DA:51,1 -DA:55,1 -DA:56,1 -DA:57,1 -DA:58,1 -DA:59,1 -DA:60,2 -DA:64,0 -DA:66,0 -DA:68,3 -DA:72,6 -DA:73,3 -DA:74,3 -DA:75,3 -DA:78,0 -DA:80,0 -LF:34 -LH:25 -end_of_record -SF:lib/src/core/services/app_services/color_picker_dialog_service/color_picker_dialog_service.dart -DA:6,0 -DA:13,0 -DA:15,0 -DA:25,0 -DA:26,0 -LF:5 -LH:0 -end_of_record -SF:lib/src/core/services/app_services/snackbar_service/snackbar_service.dart -DA:10,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:15,2 -DA:19,2 -DA:21,2 -DA:22,2 -DA:23,2 -DA:24,2 -DA:30,2 -DA:36,2 -DA:40,2 -DA:41,2 -DA:42,2 -DA:43,2 -DA:46,2 -DA:49,2 -DA:54,2 -DA:55,2 -DA:56,2 -DA:60,2 -DA:73,2 -DA:74,2 -DA:75,2 -LF:25 -LH:25 -end_of_record -SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_event.dart -DA:11,2 -DA:24,2 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart -DA:15,1 -DA:17,2 -DA:18,2 -DA:19,2 -DA:22,1 -DA:27,2 -DA:29,1 -DA:30,1 -DA:31,1 -DA:32,1 -DA:35,2 -DA:39,1 -DA:40,1 -DA:41,1 -DA:50,1 -DA:51,1 -DA:55,1 -DA:56,1 -DA:57,1 -DA:59,1 -DA:62,1 -DA:63,1 -DA:64,1 -DA:66,1 -DA:72,1 -DA:77,2 -DA:79,1 -DA:80,1 -DA:81,1 -DA:82,1 -DA:83,1 -DA:86,2 -DA:90,1 -DA:91,1 -DA:92,1 -DA:101,1 -DA:102,1 -DA:106,1 -DA:107,1 -DA:108,1 -DA:109,1 -DA:110,1 -DA:113,1 -DA:114,1 -DA:115,1 -DA:117,1 -LF:46 -LH:46 -end_of_record -SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart -DA:16,2 -DA:23,2 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart -DA:33,1 -DA:41,1 -DA:42,1 -DA:55,1 -DA:59,1 -DA:65,1 -DA:66,1 -DA:79,1 -DA:81,1 -DA:83,1 -DA:85,3 -DA:87,5 -DA:88,5 -DA:89,4 -DA:92,1 -DA:94,2 -DA:95,2 -DA:96,1 -DA:102,0 -DA:103,0 -DA:104,0 -DA:105,0 -DA:107,0 -DA:108,0 -DA:124,1 -DA:125,3 -DA:126,2 -DA:129,2 -DA:130,1 -DA:131,3 -DA:132,4 -DA:134,3 -DA:135,1 -DA:139,2 -DA:140,2 -DA:141,1 -DA:142,1 -DA:143,3 -DA:144,4 -DA:146,3 -DA:147,1 -DA:151,4 -DA:152,0 -DA:153,0 -DA:154,0 -DA:156,1 -DA:157,3 -DA:158,3 -DA:159,1 -DA:163,2 -DA:164,1 -DA:169,1 -DA:174,1 -DA:175,0 -DA:177,0 -DA:182,2 -DA:183,1 -DA:186,1 -DA:187,1 -DA:188,1 -DA:189,1 -DA:194,2 -DA:195,1 -DA:196,1 -DA:197,3 -DA:199,1 -DA:205,1 -DA:206,1 -DA:207,1 -DA:209,1 -DA:211,1 -DA:215,2 -DA:216,1 -DA:217,1 -DA:218,2 -DA:226,1 -DA:228,2 -DA:231,1 -DA:232,1 -DA:234,2 -DA:236,1 -DA:237,1 -DA:238,1 -DA:239,1 -DA:240,1 -DA:242,1 -DA:246,1 -DA:247,1 -DA:249,1 -DA:250,1 -DA:255,1 -DA:256,1 -DA:258,1 -DA:259,1 -DA:260,1 -DA:261,1 -DA:264,1 -DA:265,1 -DA:267,1 -DA:268,1 -DA:270,1 -DA:271,1 -DA:272,1 -DA:273,1 -DA:275,1 -DA:277,1 -DA:281,2 -DA:283,1 -DA:284,1 -DA:288,1 -DA:290,1 -DA:291,1 -DA:292,2 -DA:294,1 -DA:295,1 -DA:299,1 -DA:304,0 -DA:305,0 -DA:306,0 -DA:308,0 -DA:311,0 -DA:312,1 -DA:313,1 -DA:315,1 -DA:317,1 -DA:320,1 -DA:321,1 -DA:322,2 -DA:323,1 -DA:332,1 -DA:333,1 -DA:334,1 -DA:338,1 -DA:340,1 -DA:341,1 -LF:135 -LH:119 -end_of_record -SF:lib/src/shared/widgets/buttons/bookify_outlined_button.dart -DA:10,1 -DA:19,2 -DA:28,3 -DA:30,3 -DA:32,3 -DA:33,7 -DA:34,3 -DA:35,2 -DA:36,2 -DA:37,2 -DA:38,0 -DA:39,0 -DA:40,0 -DA:42,0 -DA:43,0 -DA:45,0 -DA:48,0 -DA:51,4 -DA:52,2 -DA:53,2 -DA:55,2 -DA:56,2 -DA:60,1 -DA:61,1 -DA:62,1 -DA:63,0 -DA:64,0 -DA:65,0 -DA:67,0 -DA:68,0 -DA:70,0 -DA:73,0 -DA:76,1 -DA:77,1 -DA:79,1 -DA:80,1 -LF:36 -LH:22 -end_of_record -SF:lib/src/shared/constants/database_scripts/database_scripts.dart -DA:3,0 -DA:6,4 -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:11,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:18,1 -DA:21,1 -DA:24,1 -DA:27,1 -DA:30,1 -DA:34,1 -DA:41,1 -DA:44,1 -DA:47,1 -LF:19 -LH:18 -end_of_record SF:lib/src/core/models/author_model.dart DA:5,10 DA:10,9 @@ -526,6 +157,29 @@ DA:53,0 LF:22 LH:11 end_of_record +SF:lib/src/shared/constants/database_scripts/database_scripts.dart +DA:3,0 +DA:6,4 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:18,1 +DA:21,1 +DA:24,1 +DA:27,1 +DA:30,1 +DA:34,1 +DA:41,1 +DA:44,1 +DA:47,1 +LF:19 +LH:18 +end_of_record SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart DA:14,2 DA:16,1 @@ -646,6 +300,13 @@ DA:9,0 LF:3 LH:0 end_of_record +SF:lib/src/core/errors/local_database_exception/local_database_exception.dart +DA:7,8 +DA:12,0 +DA:13,0 +LF:3 +LH:1 +end_of_record SF:lib/src/core/repositories/author_repository/authors_repository_impl.dart DA:12,1 DA:14,1 @@ -751,6 +412,44 @@ DA:98,1 LF:27 LH:27 end_of_record +SF:lib/src/core/models/bookcase_model.dart +DA:10,3 +DA:17,3 +DA:19,3 +DA:25,3 +DA:26,2 +DA:27,2 +DA:28,2 +DA:29,1 +DA:33,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:46,1 +DA:47,1 +DA:48,1 +DA:49,1 +DA:50,1 +DA:51,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,2 +DA:64,0 +DA:66,0 +DA:68,3 +DA:72,6 +DA:73,3 +DA:74,3 +DA:75,3 +DA:78,0 +DA:80,0 +LF:34 +LH:25 +end_of_record SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart DA:12,1 DA:14,1 @@ -1751,32 +1450,6 @@ DA:44,2 LF:24 LH:23 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 -DA:22,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:27,1 -DA:28,1 -DA:29,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:16 -LH:16 -end_of_record SF:lib/src/shared/blocs/book_bloc/book_event.dart DA:10,1 DA:18,1 @@ -1894,6 +1567,32 @@ DA:227,0 LF:98 LH:75 end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +DA:11,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:22,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 +end_of_record SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart DA:13,1 LF:1 @@ -1920,38 +1619,32 @@ DA:8,0 DA:12,0 DA:14,0 DA:15,0 -DA:19,0 -DA:21,0 -DA:23,0 -DA:28,0 -DA:31,0 -DA:32,0 -DA:45,2 -DA:54,0 -DA:62,0 -DA:63,0 +DA:28,2 +DA:37,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:55,0 +DA:57,0 +DA:60,0 DA:64,0 DA:65,0 DA:66,0 DA:67,0 DA:68,0 +DA:69,0 DA:72,0 DA:74,0 +DA:75,0 +DA:76,0 DA:77,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -DA:89,0 -DA:91,0 -DA:92,0 -DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -LF:37 +DA:78,0 +DA:79,0 +LF:31 LH:1 end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart @@ -2000,25 +1693,6 @@ DA:20,1 LF:2 LH:2 end_of_record -SF:lib/src/features/about/bloc/about_bloc.dart -DA:11,3 -DA:12,2 -DA:15,1 -DA:20,2 -DA:21,2 -DA:22,2 -DA:24,1 -DA:25,1 -DA:26,2 -LF:9 -LH:9 -end_of_record -SF:lib/src/features/about/bloc/about_state.dart -DA:10,1 -DA:18,1 -LF:2 -LH:2 -end_of_record SF:lib/src/features/auth/bloc/auth_bloc.dart DA:13,3 DA:14,2 @@ -2052,6 +1726,25 @@ DA:15,1 LF:1 LH:1 end_of_record +SF:lib/src/features/about/bloc/about_bloc.dart +DA:11,3 +DA:12,2 +DA:15,1 +DA:20,2 +DA:21,2 +DA:22,2 +DA:24,1 +DA:25,1 +DA:26,2 +LF:9 +LH:9 +end_of_record +SF:lib/src/features/about/bloc/about_state.dart +DA:10,1 +DA:18,1 +LF:2 +LH:2 +end_of_record SF:lib/src/features/book_detail/bloc/book_detail_event.dart DA:8,2 DA:16,2 @@ -2100,93 +1793,40 @@ DA:78,1 DA:82,1 DA:83,1 DA:85,1 -DA:91,1 -DA:96,2 -DA:98,3 -DA:100,1 -DA:101,1 -DA:102,1 -DA:105,2 -DA:111,3 -DA:112,1 -DA:113,1 -DA:114,1 -DA:121,2 -DA:123,1 -DA:124,1 -DA:125,1 -DA:126,1 -DA:127,1 -DA:131,1 -DA:132,1 -DA:134,1 -LF:54 -LH:54 -end_of_record -SF:lib/src/core/helpers/book_status/book_status_extension.dart -DA:7,0 -DA:9,0 -DA:10,0 -DA:11,0 -DA:15,1 -DA:17,1 -DA:18,2 -DA:19,2 -LF:8 -LH:4 -end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_event.dart -DA:8,1 -DA:17,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart -DA:11,1 -DA:23,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart -DA:13,1 -DA:15,2 -DA:16,2 -DA:17,2 -DA:20,1 -DA:25,2 -DA:27,2 -DA:28,1 -DA:31,1 -DA:32,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:39,1 -DA:40,1 -DA:43,1 -DA:44,1 -DA:45,1 -DA:47,1 -DA:53,1 -DA:58,2 -DA:60,2 -DA:61,1 -DA:62,1 -DA:65,1 -DA:66,1 -DA:67,1 -DA:76,2 -DA:77,1 -DA:78,1 -DA:79,1 -DA:80,1 -DA:81,1 -DA:84,1 -DA:85,1 -DA:86,1 -DA:88,1 -LF:37 -LH:37 +DA:91,1 +DA:96,2 +DA:98,3 +DA:100,1 +DA:101,1 +DA:102,1 +DA:105,2 +DA:111,3 +DA:112,1 +DA:113,1 +DA:114,1 +DA:121,2 +DA:123,1 +DA:124,1 +DA:125,1 +DA:126,1 +DA:127,1 +DA:131,1 +DA:132,1 +DA:134,1 +LF:54 +LH:54 +end_of_record +SF:lib/src/core/helpers/book_status/book_status_extension.dart +DA:7,0 +DA:9,0 +DA:10,0 +DA:11,0 +DA:15,1 +DA:17,1 +DA:18,2 +DA:19,2 +LF:8 +LH:4 end_of_record SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart DA:14,1 @@ -2216,6 +1856,22 @@ DA:20,1 LF:2 LH:2 end_of_record +SF:lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart +DA:5,3 +DA:9,3 +DA:10,0 +DA:14,3 +DA:15,0 +DA:18,3 +DA:19,0 +DA:22,3 +DA:23,0 +DA:26,9 +DA:29,0 +DA:30,0 +LF:12 +LH:6 +end_of_record SF:lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart DA:5,0 DA:9,0 @@ -2284,6 +1940,35 @@ DA:124,0 LF:39 LH:18 end_of_record +SF:lib/src/core/services/app_services/snackbar_service/snackbar_service.dart +DA:10,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:15,2 +DA:19,2 +DA:21,2 +DA:22,2 +DA:23,2 +DA:24,2 +DA:30,2 +DA:36,2 +DA:40,2 +DA:41,2 +DA:42,2 +DA:43,2 +DA:46,2 +DA:49,2 +DA:54,2 +DA:55,2 +DA:56,2 +DA:60,2 +DA:73,2 +DA:74,2 +DA:75,2 +LF:25 +LH:25 +end_of_record SF:lib/src/features/book_detail/views/book_detail_page.dart DA:19,1 DA:24,1 @@ -2505,7 +2190,7 @@ LF:27 LH:14 end_of_record SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart -DA:6,2 +DA:6,1 DA:11,4 DA:13,4 DA:14,4 @@ -2579,6 +2264,99 @@ DA:60,0 LF:24 LH:13 end_of_record +SF:lib/src/shared/widgets/buttons/bookify_outlined_button.dart +DA:10,1 +DA:19,2 +DA:28,3 +DA:30,3 +DA:32,3 +DA:33,7 +DA:34,3 +DA:35,2 +DA:36,2 +DA:37,2 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:45,0 +DA:48,0 +DA:51,4 +DA:52,2 +DA:53,2 +DA:55,2 +DA:56,2 +DA:60,1 +DA:61,1 +DA:62,1 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:73,0 +DA:76,1 +DA:77,1 +DA:79,1 +DA:80,1 +LF:36 +LH:22 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_event.dart +DA:8,1 +DA:17,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart +DA:11,1 +DA:23,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart +DA:13,1 +DA:15,2 +DA:16,2 +DA:17,2 +DA:20,1 +DA:25,2 +DA:27,2 +DA:28,1 +DA:31,1 +DA:32,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:39,1 +DA:40,1 +DA:43,1 +DA:44,1 +DA:45,1 +DA:47,1 +DA:53,1 +DA:58,2 +DA:60,2 +DA:61,1 +DA:62,1 +DA:65,1 +DA:66,1 +DA:67,1 +DA:76,2 +DA:77,1 +DA:78,1 +DA:79,1 +DA:80,1 +DA:81,1 +DA:84,1 +DA:85,1 +DA:86,1 +DA:88,1 +LF:37 +LH:37 +end_of_record SF:lib/src/features/bookcase/bloc/bookcase_state.dart DA:10,2 DA:21,2 @@ -2682,6 +2460,10 @@ DA:35,0 LF:12 LH:3 end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 DA:10,0 @@ -2698,6 +2480,21 @@ DA:44,0 LF:12 LH:0 end_of_record +SF:lib/src/core/helpers/textfield_unfocus/textfield_unfocus_extension.dart +DA:8,0 +DA:23,6 +LF:2 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/color_picker_dialog_service/color_picker_dialog_service.dart +DA:6,0 +DA:13,0 +DA:15,0 +DA:25,0 +DA:26,0 +LF:5 +LH:0 +end_of_record SF:lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart DA:24,0 DA:30,0 @@ -2973,14 +2770,153 @@ DA:182,1 DA:183,0 DA:186,1 DA:187,1 -DA:189,0 -DA:190,1 -DA:194,1 +DA:189,0 +DA:190,1 +DA:194,1 +DA:195,1 +DA:196,1 +DA:197,1 +LF:90 +LH:52 +end_of_record +SF:lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart +DA:33,1 +DA:41,1 +DA:42,1 +DA:55,1 +DA:59,1 +DA:65,1 +DA:66,1 +DA:79,1 +DA:81,1 +DA:83,1 +DA:85,3 +DA:87,5 +DA:88,5 +DA:89,4 +DA:92,1 +DA:94,2 +DA:95,2 +DA:96,1 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:107,0 +DA:108,0 +DA:124,1 +DA:125,3 +DA:126,2 +DA:129,2 +DA:130,1 +DA:131,3 +DA:132,4 +DA:134,3 +DA:135,1 +DA:139,2 +DA:140,2 +DA:141,1 +DA:142,1 +DA:143,3 +DA:144,4 +DA:146,3 +DA:147,1 +DA:151,4 +DA:152,0 +DA:153,0 +DA:154,0 +DA:156,1 +DA:157,3 +DA:158,3 +DA:159,1 +DA:163,2 +DA:164,1 +DA:169,1 +DA:174,1 +DA:175,0 +DA:177,0 +DA:182,2 +DA:183,1 +DA:186,1 +DA:187,1 +DA:188,1 +DA:189,1 +DA:194,2 DA:195,1 DA:196,1 -DA:197,1 -LF:90 -LH:52 +DA:197,3 +DA:199,1 +DA:205,1 +DA:206,1 +DA:207,1 +DA:209,1 +DA:211,1 +DA:215,2 +DA:216,1 +DA:217,1 +DA:218,2 +DA:226,1 +DA:228,2 +DA:231,1 +DA:232,1 +DA:234,2 +DA:236,1 +DA:237,1 +DA:238,1 +DA:239,1 +DA:240,1 +DA:242,1 +DA:246,1 +DA:247,1 +DA:249,1 +DA:250,1 +DA:255,1 +DA:256,1 +DA:258,1 +DA:259,1 +DA:260,1 +DA:261,1 +DA:264,1 +DA:265,1 +DA:267,1 +DA:268,1 +DA:270,1 +DA:271,1 +DA:272,1 +DA:273,1 +DA:275,1 +DA:277,1 +DA:281,2 +DA:283,1 +DA:284,1 +DA:288,1 +DA:290,1 +DA:291,1 +DA:292,2 +DA:294,1 +DA:295,1 +DA:299,1 +DA:304,0 +DA:305,0 +DA:306,0 +DA:308,0 +DA:311,0 +DA:312,1 +DA:313,1 +DA:315,1 +DA:317,1 +DA:320,1 +DA:321,1 +DA:322,2 +DA:323,1 +DA:332,1 +DA:333,1 +DA:334,1 +DA:338,1 +DA:340,1 +DA:341,1 +LF:135 +LH:119 end_of_record SF:lib/src/shared/widgets/item_state_widget/item_empty_state_widget/item_empty_widget.dart DA:7,1 @@ -3619,15 +3555,73 @@ DA:183,0 LF:86 LH:0 end_of_record +SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_event.dart +DA:11,2 +DA:24,2 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart +DA:15,1 +DA:17,2 +DA:18,2 +DA:19,2 +DA:22,1 +DA:27,2 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,1 +DA:35,2 +DA:39,1 +DA:40,1 +DA:41,1 +DA:50,1 +DA:51,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:59,1 +DA:62,1 +DA:63,1 +DA:64,1 +DA:66,1 +DA:72,1 +DA:77,2 +DA:79,1 +DA:80,1 +DA:81,1 +DA:82,1 +DA:83,1 +DA:86,2 +DA:90,1 +DA:91,1 +DA:92,1 +DA:101,1 +DA:102,1 +DA:106,1 +DA:107,1 +DA:108,1 +DA:109,1 +DA:110,1 +DA:113,1 +DA:114,1 +DA:115,1 +DA:117,1 +LF:46 +LH:46 +end_of_record +SF:lib/src/features/bookcase_insertion/bloc/bookcase_insertion_state.dart +DA:16,2 +DA:23,2 +LF:2 +LH:2 +end_of_record SF:lib/src/shared/constants/images/bookify_images.dart DA:7,0 LF:1 LH:0 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 -end_of_record SF:lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_event.dart DA:8,1 LF:1 @@ -3941,55 +3935,6 @@ DA:117,1 LF:43 LH:43 end_of_record -SF:lib/src/features/my_books/bloc/my_books_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_bloc.dart -DA:14,3 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,2 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:45,1 -DA:51,1 -DA:56,2 -DA:58,2 -DA:59,1 -DA:62,1 -DA:63,2 -DA:67,2 -DA:68,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:72,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:79,1 -LF:34 -LH:34 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:20,1 DA:24,2 @@ -4045,6 +3990,55 @@ DA:19,1 LF:2 LH:2 end_of_record +SF:lib/src/features/my_books/bloc/my_books_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_bloc.dart +DA:14,3 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,2 +DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,1 +DA:63,2 +DA:67,2 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:79,1 +LF:34 +LH:34 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record SF:lib/src/features/home/views/home_page.dart DA:11,1 DA:13,1 @@ -4385,6 +4379,8 @@ DA:73,1 DA:74,1 DA:82,2 DA:83,1 +DA:84,1 +DA:85,1 DA:86,1 DA:87,1 DA:88,2 @@ -4416,11 +4412,11 @@ DA:134,1 DA:135,1 DA:136,1 DA:138,1 -LF:60 -LH:56 +LF:62 +LH:58 end_of_record SF:lib/src/features/programming_reading/bloc/programming_reading_event.dart -DA:10,1 +DA:12,1 LF:1 LH:1 end_of_record diff --git a/lib/src/core/helpers/notification_channel/notification_channel_extension.dart b/lib/src/core/helpers/notification_channel/notification_channel_extension.dart new file mode 100644 index 00000000..92b581c0 --- /dev/null +++ b/lib/src/core/helpers/notification_channel/notification_channel_extension.dart @@ -0,0 +1,22 @@ +import 'package:bookify/src/core/models/custom_notification_model.dart'; +import 'package:localization/localization.dart'; + +extension NotificationChannelExtension on NotificationChannel { + String description() { + return switch (this) { + NotificationChannel.loanChannel => + 'notification-channel-loan-description'.i18n(), + NotificationChannel.readChannel => + 'notification-channel-read-description'.i18n(), + }; + } + + String get label { + return switch (this) { + NotificationChannel.loanChannel => + 'notification-channel-loan-label'.i18n(), + NotificationChannel.readChannel => + 'notification-channel-read-label'.i18n(), + }; + } +} diff --git a/lib/src/core/models/custom_notification_model.dart b/lib/src/core/models/custom_notification_model.dart index 39b2af99..0e8acf8a 100644 --- a/lib/src/core/models/custom_notification_model.dart +++ b/lib/src/core/models/custom_notification_model.dart @@ -15,23 +15,6 @@ enum NotificationChannel { '1' || _ => NotificationChannel.loanChannel, }; } - - String description() { - return switch (this) { - NotificationChannel.loanChannel => - 'Canal que notifica quando é o dia de receber o livro emprestado.', - NotificationChannel.readChannel => - 'Canal que notifica que está na hora da leitura.', - }; - } - - @override - String toString() { - return switch (this) { - NotificationChannel.loanChannel => 'Empréstimos', - NotificationChannel.readChannel => 'Leituras', - }; - } } class CustomNotificationModel { diff --git a/lib/src/core/services/app_services/contacts_service/contacts_service_impl.dart b/lib/src/core/services/app_services/contacts_service/contacts_service_impl.dart index dcebc4bb..7df29b6e 100644 --- a/lib/src/core/services/app_services/contacts_service/contacts_service_impl.dart +++ b/lib/src/core/services/app_services/contacts_service/contacts_service_impl.dart @@ -22,8 +22,9 @@ class ContactsServiceImpl implements ContactsService { return ContactModel( id: contact.id, name: contact.displayName, - phoneNumber: - (contact.phones.isNotEmpty) ? contact.phones.first.number : null, + phoneNumber: (contact.phones.isNotEmpty) + ? contact.phones.first.number + : null, photo: photo, ); } @@ -52,8 +53,9 @@ class ContactsServiceImpl implements ContactsService { final contactDto = ContactModel( id: contact.id, name: contact.displayName, - phoneNumber: - (contact.phones.isNotEmpty) ? contact.phones.first.number : null, + phoneNumber: (contact.phones.isNotEmpty) + ? contact.phones.first.number + : null, photo: photo, ); diff --git a/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart b/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart index a02684bb..ecccdf96 100644 --- a/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart +++ b/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; import 'package:bookify/src/core/models/custom_notification_model.dart'; +import 'package:bookify/src/core/helpers/notification_channel/notification_channel_extension.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notification_navigator.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; import 'package:bookify/src/shared/theme/colors.dart'; @@ -94,7 +95,7 @@ class NotificationsServiceImpl implements NotificationsService { return NotificationDetails( android: AndroidNotificationDetails( channel.channelId(), - channel.toString(), + channel.label, channelDescription: channel.description(), color: AppColor.bookifySecondaryColor, styleInformation: BigTextStyleInformation( @@ -103,7 +104,7 @@ class NotificationsServiceImpl implements NotificationsService { importance: Importance.high, ), iOS: DarwinNotificationDetails( - categoryIdentifier: channel.toString(), + categoryIdentifier: channel.label, ), ); } diff --git a/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart b/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart index d16e789d..889facb3 100644 --- a/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart +++ b/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart @@ -114,7 +114,7 @@ class LoanDetailBloc extends Bloc { emit( LoanDetailErrorState( errorCode: LocalDatabaseErrorCode.unknown, - errorDescriptionMessage: 'Ocorreu um erro não esperado: $e', + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart index 7c8be31f..d6c2323d 100644 --- a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart +++ b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart @@ -81,8 +81,8 @@ class ProgrammingReadingBloc await _notificationsService.periodicallyShowNotificationWithSpecificDate( id: _readingNotificationId, - title: 'A hora da leitura chegou!', - body: 'A história está esperando a gente!', + title: event.readingTimeNotificationTitle, + body: event.readingTimeNotificationBody, repeatType: userHourTime.repeatHourTimeType, scheduledDate: DateTime( DateTime.now().year, diff --git a/lib/src/features/programming_reading/bloc/programming_reading_event.dart b/lib/src/features/programming_reading/bloc/programming_reading_event.dart index b6b2d681..ec001763 100644 --- a/lib/src/features/programming_reading/bloc/programming_reading_event.dart +++ b/lib/src/features/programming_reading/bloc/programming_reading_event.dart @@ -6,9 +6,13 @@ final class GotHourTimeEvent extends ProgrammingReadingEvent {} final class InsertedHourTimeEvent extends ProgrammingReadingEvent { final UserHourTimeModel userHourTimeModel; + final String readingTimeNotificationTitle; + final String readingTimeNotificationBody; InsertedHourTimeEvent({ required this.userHourTimeModel, + required this.readingTimeNotificationTitle, + required this.readingTimeNotificationBody, }); } diff --git a/lib/src/features/programming_reading/views/programming_reading_page.dart b/lib/src/features/programming_reading/views/programming_reading_page.dart index ab546856..802aabb3 100644 --- a/lib/src/features/programming_reading/views/programming_reading_page.dart +++ b/lib/src/features/programming_reading/views/programming_reading_page.dart @@ -44,6 +44,8 @@ class _ProgrammingHourState extends State { _bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTimeModel, + readingTimeNotificationTitle: 'reading_time_title'.i18n(), + readingTimeNotificationBody: 'reading_time_body'.i18n(), ), ); }, diff --git a/pubspec.lock b/pubspec.lock index 2b4b5769..788129e3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1057,26 +1057,26 @@ packages: dependency: "direct dev" description: name: patrol - sha256: "7825a6e96a8f0755f68eec600a91a08b19bd0975488a70885b3696f6b65ffc0f" + sha256: baebcc5e7dbd22ac6838512b7efdd432f33188ad5f3c4b3bfe00680c1bbef453 url: "https://pub.dev" source: hosted - version: "4.5.0" + version: "4.6.0" patrol_finders: dependency: transitive description: name: patrol_finders - sha256: "9970eac0669a90b20ec7e1bcaabd0475655655998068ca656f4df9f6ec84f336" + sha256: "915da1e63fe7fd024418ab30b2394b1c8d6e812ce25be7d0b11634202521f0a9" url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "3.4.0" patrol_log: dependency: transitive description: name: patrol_log - sha256: a2360db165c34692665c0de146e5157887d6b584fdccca8f141f947a5acf1b2e + sha256: "16ab747b28621640115d9493138eae82a1d410a613857cb0caf9000ce62fc546" url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.9.0" permission_handler: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 09f6015a..d7a99038 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.8 +version: 2.11.9 environment: sdk: ">=3.10.0 <4.0.0" @@ -64,7 +64,7 @@ dev_dependencies: mocktail: ^1.0.5 bloc_test: ^10.0.0 sqflite_common_ffi: ^2.4.0+3 - patrol: ^4.5.0 + patrol: ^4.6.0 envied_generator: ^1.3.5 build_runner: ^2.15.0 diff --git a/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart b/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart index 626fa8ea..7d92bd86 100644 --- a/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart +++ b/test/src/features/programming_reading/bloc/programming_reading_bloc_test.dart @@ -139,6 +139,8 @@ void main() { act: (bloc) => bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTime, + readingTimeNotificationTitle: 'notificationTitle', + readingTimeNotificationBody: 'notificationBody', ), ), verify: (_) { @@ -180,6 +182,8 @@ void main() { act: (bloc) => bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTime, + readingTimeNotificationTitle: 'notificationTitle', + readingTimeNotificationBody: 'notificationBody', ), ), verify: (_) { @@ -224,6 +228,8 @@ void main() { act: (bloc) => bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTime, + readingTimeNotificationTitle: 'notificationTitle', + readingTimeNotificationBody: 'notificationBody', ), ), verify: (_) { @@ -265,6 +271,8 @@ void main() { act: (bloc) => bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTime, + readingTimeNotificationTitle: 'notificationTitle', + readingTimeNotificationBody: 'notificationBody', ), ), verify: (_) { From e3c09e78a26c77f53134c6fb24c946d92c96aeff Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Fri, 22 May 2026 18:01:55 -0300 Subject: [PATCH 14/19] feat: Add localized notifications for loan insertion and improve related event handling --- assets/lang/en_US.json | 3 + assets/lang/it_IT.json | 3 + assets/lang/pt_BR.json | 3 + coverage/lcov.info | 822 +++++++++--------- .../bloc/loan_insertion_bloc.dart | 27 +- .../bloc/loan_insertion_event.dart | 8 +- .../bloc/loan_insertion_state.dart | 8 +- .../views/loan_insertion_page.dart | 22 +- .../views/widgets/notification_widget.dart | 5 +- .../views/programming_reading_page.dart | 6 +- pubspec.yaml | 2 +- .../bloc/loan_insertion_bloc_test.dart | 20 +- 12 files changed, 468 insertions(+), 461 deletions(-) diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index ce7f228d..ea75cd4b 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -184,6 +184,9 @@ "contact-required-field": "Contact *", "observation-optional-field": "Observation (optional)", "loan-date-required-field": "Loan date *", + "loan-notification-title": "Hey, your book is coming back!", + "loan-notification-body": "Hi! Just dropping by to remind you that it's time for %s0 to return %s1 that you loaned on %s2.", + "loan-insertion-success-snackbar": "Loan added successfully!", "devolution-date-required-field": "Devolution date *", "send-button": "Send", "contact-selected-label": "Contact selected", diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index 03933246..2458534f 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -184,6 +184,9 @@ "contact-required-field": "Contatto *", "observation-optional-field": "Osservazione (opzionale)", "loan-date-required-field": "Data del prestito *", + "loan-notification-title": "Ehi, il tuo libro sta per tornare!", + "loan-notification-body": "Ciao! Solo un promemoria per ricordarti che è ora che %s0 restituisca il libro %s1 che hai prestato il giorno %s2.", + "loan-insertion-success-snackbar": "Prestito inserito con successo!", "devolution-date-required-field": "Data di restituzione *", "send-button": "Inviare", "contact-selected-label": "Contatto selezionato", diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index ee3accb5..d48faace 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -184,6 +184,9 @@ "contact-required-field": "Contato *", "observation-optional-field": "Observação (opcional)", "loan-date-required-field": "Data do empréstimo *", + "loan-notification-title": "Ei, seu livro tá voltando!", + "loan-notification-body": "Olá! Só passando pra lembrar que tá na hora de %s0 devolver o %s1 que você emprestou no dia %s2.", + "loan-insertion-success-snackbar": "Empréstimo inserido com sucesso!", "devolution-date-required-field": "Data para devolução *", "send-button": "Enviar", "contact-selected-label": "Contato selecionado", diff --git a/coverage/lcov.info b/coverage/lcov.info index 46905bdf..40c41fd8 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -9,6 +9,29 @@ DA:15,9 LF:7 LH:7 end_of_record +SF:lib/src/shared/constants/database_scripts/database_scripts.dart +DA:3,0 +DA:6,4 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:18,1 +DA:21,1 +DA:24,1 +DA:27,1 +DA:30,1 +DA:34,1 +DA:41,1 +DA:44,1 +DA:47,1 +LF:19 +LH:18 +end_of_record SF:lib/src/core/models/author_model.dart DA:5,10 DA:10,9 @@ -157,34 +180,218 @@ DA:53,0 LF:22 LH:11 end_of_record -SF:lib/src/shared/constants/database_scripts/database_scripts.dart -DA:3,0 -DA:6,4 -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:11,2 -DA:12,2 -DA:13,2 -DA:14,2 +SF:lib/src/core/errors/local_database_exception/local_database_exception.dart +DA:7,7 +DA:12,0 +DA:13,0 +LF:3 +LH:1 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_bloc.dart +DA:14,3 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,2 +DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,1 +DA:63,2 +DA:67,2 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:79,1 +LF:34 +LH:34 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/core/models/bookcase_model.dart +DA:10,3 +DA:17,3 +DA:19,3 +DA:25,3 +DA:26,2 +DA:27,2 +DA:28,2 +DA:29,1 +DA:33,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:46,1 +DA:47,1 +DA:48,1 +DA:49,1 +DA:50,1 +DA:51,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,2 +DA:64,0 +DA:66,0 +DA:68,3 +DA:72,6 +DA:73,3 +DA:74,3 +DA:75,3 +DA:78,0 +DA:80,0 +LF:34 +LH:25 +end_of_record +SF:lib/src/core/models/loan_model.dart +DA:9,5 DA:18,1 +DA:19,1 +DA:20,1 DA:21,1 +DA:22,2 +DA:23,2 DA:24,1 -DA:27,1 +DA:25,1 +DA:29,1 DA:30,1 +DA:31,1 +DA:32,1 +DA:33,1 DA:34,1 +DA:36,1 +DA:37,1 +DA:39,1 +DA:40,1 +DA:44,0 +DA:46,0 +DA:49,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,1 +DA:61,0 +DA:62,1 +DA:63,1 +DA:67,2 +DA:71,6 +DA:72,6 +DA:73,6 +DA:74,6 +DA:75,6 +DA:76,6 +DA:79,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +LF:43 +LH:33 +end_of_record +SF:lib/src/core/models/reading_model.dart +DA:7,5 +DA:14,1 +DA:20,1 +DA:21,1 +DA:22,0 +DA:23,1 +DA:24,1 +DA:28,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,2 +DA:33,1 +DA:37,1 +DA:38,1 +DA:39,2 +DA:40,1 DA:41,1 +DA:42,2 DA:44,1 -DA:47,1 -LF:19 -LH:18 +DA:48,0 +DA:50,0 +DA:53,3 +DA:57,6 +DA:58,6 +DA:59,6 +DA:60,6 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +LF:32 +LH:24 +end_of_record +SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart +DA:19,1 +DA:24,2 +DA:25,2 +DA:28,1 +DA:33,2 +DA:35,2 +DA:36,2 +DA:37,2 +DA:38,2 +DA:40,1 +DA:41,1 +DA:48,1 +DA:49,1 +DA:50,1 +DA:51,1 +DA:52,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:59,1 +LF:20 +LH:20 +end_of_record +SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart +DA:13,1 +DA:25,1 +LF:2 +LH:2 end_of_record SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart -DA:14,2 +DA:14,1 DA:16,1 -DA:17,2 -DA:18,2 +DA:17,1 +DA:18,1 DA:32,1 DA:34,1 DA:35,1 @@ -300,13 +507,6 @@ DA:9,0 LF:3 LH:0 end_of_record -SF:lib/src/core/errors/local_database_exception/local_database_exception.dart -DA:7,8 -DA:12,0 -DA:13,0 -LF:3 -LH:1 -end_of_record SF:lib/src/core/repositories/author_repository/authors_repository_impl.dart DA:12,1 DA:14,1 @@ -412,47 +612,9 @@ DA:98,1 LF:27 LH:27 end_of_record -SF:lib/src/core/models/bookcase_model.dart -DA:10,3 -DA:17,3 -DA:19,3 -DA:25,3 -DA:26,2 -DA:27,2 -DA:28,2 -DA:29,1 -DA:33,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:42,0 -DA:46,1 -DA:47,1 -DA:48,1 -DA:49,1 -DA:50,1 -DA:51,1 -DA:55,1 -DA:56,1 -DA:57,1 -DA:58,1 -DA:59,1 -DA:60,2 -DA:64,0 -DA:66,0 -DA:68,3 -DA:72,6 -DA:73,3 -DA:74,3 -DA:75,3 -DA:78,0 -DA:80,0 -LF:34 -LH:25 -end_of_record -SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart -DA:12,1 -DA:14,1 +SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart +DA:12,1 +DA:14,1 DA:17,3 DA:18,2 DA:21,1 @@ -497,6 +659,42 @@ DA:126,1 LF:43 LH:43 end_of_record +SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_event.dart +LF:0 +LH:0 +end_of_record +SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart +DA:12,1 +DA:14,1 +DA:17,2 +DA:18,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:28,1 +DA:30,0 +DA:37,1 +DA:40,2 +DA:41,1 +DA:46,1 +DA:47,1 +DA:50,2 +DA:52,1 +DA:53,1 +DA:55,1 +DA:57,0 +DA:62,1 +DA:65,2 +DA:66,1 +DA:67,1 +DA:71,1 +DA:76,1 +DA:79,2 +DA:80,1 +DA:86,1 +LF:28 +LH:26 +end_of_record SF:lib/src/core/repositories/books_repository/books_repository_impl.dart DA:12,1 DA:14,1 @@ -574,85 +772,6 @@ DA:210,1 LF:73 LH:73 end_of_record -SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart -DA:12,1 -DA:14,1 -DA:17,2 -DA:18,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:28,1 -DA:30,0 -DA:37,1 -DA:40,2 -DA:41,1 -DA:46,1 -DA:47,1 -DA:50,2 -DA:52,1 -DA:53,1 -DA:55,1 -DA:57,0 -DA:62,1 -DA:65,2 -DA:66,1 -DA:67,1 -DA:71,1 -DA:76,1 -DA:79,2 -DA:80,1 -DA:86,1 -LF:28 -LH:26 -end_of_record -SF:lib/src/core/models/loan_model.dart -DA:9,5 -DA:18,1 -DA:19,1 -DA:20,1 -DA:21,1 -DA:22,2 -DA:23,2 -DA:24,1 -DA:25,1 -DA:29,1 -DA:30,1 -DA:31,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -DA:37,1 -DA:39,1 -DA:40,1 -DA:44,0 -DA:46,0 -DA:49,1 -DA:57,1 -DA:58,1 -DA:59,1 -DA:60,1 -DA:61,0 -DA:62,1 -DA:63,1 -DA:67,2 -DA:71,6 -DA:72,6 -DA:73,6 -DA:74,6 -DA:75,6 -DA:76,6 -DA:79,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -LF:43 -LH:33 -end_of_record SF:lib/src/core/repositories/loan_repository/loan_repository_impl.dart DA:13,1 DA:15,1 @@ -705,42 +824,6 @@ DA:136,1 LF:48 LH:48 end_of_record -SF:lib/src/core/models/reading_model.dart -DA:7,5 -DA:14,1 -DA:20,1 -DA:21,1 -DA:22,0 -DA:23,1 -DA:24,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:31,1 -DA:32,2 -DA:33,1 -DA:37,1 -DA:38,1 -DA:39,2 -DA:40,1 -DA:41,1 -DA:42,2 -DA:44,1 -DA:48,0 -DA:50,0 -DA:53,3 -DA:57,6 -DA:58,6 -DA:59,6 -DA:60,6 -DA:63,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -LF:32 -LH:24 -end_of_record SF:lib/src/core/repositories/reading_repository/reading_repository_impl.dart DA:13,1 DA:17,1 @@ -874,6 +957,92 @@ DA:57,0 LF:15 LH:13 end_of_record +SF:lib/src/core/models/custom_notification_model.dart +DA:5,0 +DA:7,0 +DA:8,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:28,2 +DA:37,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:55,0 +DA:57,0 +DA:60,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +LF:31 +LH:1 +end_of_record +SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart +DA:19,1 +DA:23,2 +DA:24,2 +DA:27,1 +DA:32,2 +DA:34,2 +DA:35,1 +DA:39,1 +DA:40,1 +DA:41,1 +DA:50,1 +DA:51,1 +DA:52,1 +DA:53,1 +DA:54,1 +DA:55,1 +DA:58,2 +DA:62,1 +DA:63,1 +DA:64,1 +DA:73,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:80,2 +DA:81,1 +DA:82,1 +DA:83,1 +DA:84,1 +DA:85,1 +DA:88,1 +DA:89,1 +DA:90,1 +DA:92,1 +DA:98,1 +DA:104,1 +DA:113,2 +LF:37 +LH:37 +end_of_record +SF:lib/src/features/loan_insertion/bloc/loan_insertion_event.dart +DA:14,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/features/loan_insertion/bloc/loan_insertion_state.dart +DA:13,1 +LF:1 +LH:1 +end_of_record SF:lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart DA:12,1 DA:16,1 @@ -928,6 +1097,41 @@ DA:41,2 LF:13 LH:13 end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:6,0 +DA:8,0 +DA:10,0 +DA:12,0 +DA:13,0 +DA:14,0 +DA:15,0 +DA:16,0 +LF:8 +LH:0 +end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart DA:21,1 DA:33,1 @@ -1005,41 +1209,6 @@ DA:244,1 LF:73 LH:72 end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 -DA:8,0 -DA:10,0 -DA:12,0 -DA:13,0 -DA:14,0 -DA:15,0 -DA:16,0 -LF:8 -LH:0 -end_of_record SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart DA:11,1 DA:17,1 @@ -1450,6 +1619,32 @@ DA:44,2 LF:24 LH:23 end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +DA:11,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:22,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 +end_of_record SF:lib/src/shared/blocs/book_bloc/book_event.dart DA:10,1 DA:18,1 @@ -1567,32 +1762,6 @@ DA:227,0 LF:98 LH:75 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 -DA:22,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:27,1 -DA:28,1 -DA:29,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:16 -LH:16 -end_of_record SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart DA:13,1 LF:1 @@ -1612,41 +1781,6 @@ DA:24,1 LF:10 LH:10 end_of_record -SF:lib/src/core/models/custom_notification_model.dart -DA:5,0 -DA:7,0 -DA:8,0 -DA:12,0 -DA:14,0 -DA:15,0 -DA:28,2 -DA:37,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:51,0 -DA:55,0 -DA:57,0 -DA:60,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:69,0 -DA:72,0 -DA:74,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:79,0 -LF:31 -LH:1 -end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart DA:12,1 DA:14,2 @@ -3935,110 +4069,6 @@ DA:117,1 LF:43 LH:43 end_of_record -SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart -DA:20,1 -DA:24,2 -DA:25,2 -DA:28,1 -DA:33,2 -DA:35,2 -DA:36,1 -DA:40,1 -DA:41,1 -DA:42,1 -DA:51,1 -DA:52,1 -DA:53,1 -DA:54,1 -DA:55,1 -DA:56,1 -DA:59,2 -DA:61,1 -DA:62,1 -DA:63,1 -DA:72,1 -DA:74,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:80,1 -DA:81,1 -DA:85,1 -DA:86,1 -DA:87,1 -DA:88,1 -DA:89,1 -DA:92,1 -DA:93,1 -DA:94,1 -DA:96,1 -DA:103,1 -DA:110,1 -DA:114,4 -DA:120,2 -LF:40 -LH:40 -end_of_record -SF:lib/src/features/loan_insertion/bloc/loan_insertion_event.dart -DA:14,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/features/loan_insertion/bloc/loan_insertion_state.dart -DA:10,1 -DA:19,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_bloc.dart -DA:14,3 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,2 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:45,1 -DA:51,1 -DA:56,2 -DA:58,2 -DA:59,1 -DA:62,1 -DA:63,2 -DA:67,2 -DA:68,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:72,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:79,1 -LF:34 -LH:34 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/features/home/views/home_page.dart DA:11,1 DA:13,1 @@ -4313,36 +4343,6 @@ DA:10,1 LF:1 LH:1 end_of_record -SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart -DA:19,1 -DA:24,2 -DA:25,2 -DA:28,1 -DA:33,2 -DA:35,2 -DA:36,2 -DA:37,2 -DA:38,2 -DA:40,1 -DA:41,1 -DA:48,1 -DA:49,1 -DA:50,1 -DA:51,1 -DA:52,1 -DA:55,1 -DA:56,1 -DA:57,1 -DA:59,1 -LF:20 -LH:20 -end_of_record -SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart -DA:13,1 -DA:25,1 -LF:2 -LH:2 -end_of_record SF:lib/src/features/programming_reading/bloc/programming_reading_state.dart DA:10,1 DA:24,1 diff --git a/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart b/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart index ae614d3d..54e4d951 100644 --- a/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart +++ b/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart @@ -1,5 +1,4 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; -import 'package:bookify/src/core/helpers/date_time_format/date_time_format_extension.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/loan_model.dart'; import 'package:bookify/src/core/models/custom_notification_model.dart'; @@ -56,7 +55,9 @@ class LoanInsertionBloc extends Bloc { idContact: event.idContact, ); - final loanId = await _loanService.insert(loanModel: loanModel); + final loanId = await _loanService.insert( + loanModel: loanModel, + ); if (loanId < 1) { emit( @@ -71,17 +72,12 @@ class LoanInsertionBloc extends Bloc { await _createNotification( loanId, - event.contactName, - event.bookTitle, - event.loanDate, event.devolutionDate, + event.notificationTitle, + event.notificationBody, ); - emit( - LoanInsertionInsertedState( - loanInsertionMessage: 'Empréstimo inserido com sucesso', - ), - ); + emit(LoanInsertionInsertedState()); } on LocalDatabaseException catch (e) { emit( LoanInsertionErrorState( @@ -99,19 +95,16 @@ class LoanInsertionBloc extends Bloc { } } - // TODO Create a localized notification message Future _createNotification( int loanId, - String contactName, - String bookTitle, - DateTime loanDate, DateTime devolutionDate, + String title, + String body, ) async { final customNotification = CustomNotificationModel( id: loanId, - title: 'Ei, seu livro tá voltando!', - body: - 'Olá! Só passando pra lembrar que tá na hora de ${contactName.toUpperCase()} devolver o ${bookTitle.toUpperCase()} que você emprestou no dia ${loanDate.toFormattedDate()}.', + title: title, + body: body, notificationChannel: NotificationChannel.loanChannel, scheduledDate: devolutionDate, payload: '/loan_detail', diff --git a/lib/src/features/loan_insertion/bloc/loan_insertion_event.dart b/lib/src/features/loan_insertion/bloc/loan_insertion_event.dart index bc72895b..5a29b561 100644 --- a/lib/src/features/loan_insertion/bloc/loan_insertion_event.dart +++ b/lib/src/features/loan_insertion/bloc/loan_insertion_event.dart @@ -7,17 +7,17 @@ final class InsertedLoanInsertionEvent extends LoanInsertionEvent { final DateTime loanDate; final DateTime devolutionDate; final String idContact; - final String contactName; final String bookId; - final String bookTitle; + final String notificationTitle; + final String notificationBody; InsertedLoanInsertionEvent({ this.observation, required this.loanDate, required this.devolutionDate, - required this.contactName, required this.idContact, required this.bookId, - required this.bookTitle, + required this.notificationTitle, + required this.notificationBody, }); } diff --git a/lib/src/features/loan_insertion/bloc/loan_insertion_state.dart b/lib/src/features/loan_insertion/bloc/loan_insertion_state.dart index 8fd54610..cf33e7d1 100644 --- a/lib/src/features/loan_insertion/bloc/loan_insertion_state.dart +++ b/lib/src/features/loan_insertion/bloc/loan_insertion_state.dart @@ -4,13 +4,7 @@ sealed class LoanInsertionState {} final class LoanInsertionLoadingState extends LoanInsertionState {} -final class LoanInsertionInsertedState extends LoanInsertionState { - final String loanInsertionMessage; - - LoanInsertionInsertedState({ - required this.loanInsertionMessage, - }); -} +final class LoanInsertionInsertedState extends LoanInsertionState {} final class LoanInsertionErrorState extends LoanInsertionState { final LocalDatabaseErrorCode errorCode; diff --git a/lib/src/features/loan_insertion/views/loan_insertion_page.dart b/lib/src/features/loan_insertion/views/loan_insertion_page.dart index 702f175a..60e3f83f 100644 --- a/lib/src/features/loan_insertion/views/loan_insertion_page.dart +++ b/lib/src/features/loan_insertion/views/loan_insertion_page.dart @@ -187,15 +187,25 @@ class _LoanInsertionPageState extends State { ), ); + final formattedLoanDate = _loanDateEC.text; + final contactNameUpper = _contactNameEC.text.toUpperCase(); + final bookTitleUpper = _bookModel!.title.toUpperCase(); + _bloc.add( InsertedLoanInsertionEvent( idContact: _contact!.id, bookId: _bookModel!.id, - bookTitle: _bookModel!.title, - contactName: _contactNameEC.text, observation: _observationEC.text.isEmpty ? null : _observationEC.text, - loanDate: _loanDateEC.text.parseFormattedDate(), + loanDate: formattedLoanDate.parseFormattedDate(), devolutionDate: devolutionDateWithHours, + notificationTitle: 'loan-notification-title'.i18n(), + notificationBody: 'loan-notification-body'.i18n( + [ + contactNameUpper, + bookTitleUpper, + formattedLoanDate, + ], + ), ), ); @@ -241,12 +251,10 @@ class _LoanInsertionPageState extends State { break; - case LoanInsertionInsertedState( - loanInsertionMessage: final successMessage, - ): + case LoanInsertionInsertedState(): SnackbarService.showSnackBar( context, - successMessage, + 'loan-insertion-success-snackbar'.i18n(), SnackBarType.success, ); diff --git a/lib/src/features/notifications/views/widgets/notification_widget.dart b/lib/src/features/notifications/views/widgets/notification_widget.dart index 2b974d3d..dcb0b521 100644 --- a/lib/src/features/notifications/views/widgets/notification_widget.dart +++ b/lib/src/features/notifications/views/widgets/notification_widget.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/notification_channel/notification_channel_extension.dart'; import 'package:bookify/src/core/models/custom_notification_model.dart'; import 'package:flutter/material.dart'; @@ -63,7 +64,7 @@ class NotificationWidget extends StatelessWidget { ), ), Text( - 'channel: ${notification.notificationChannel.channelId()}', + notification.notificationChannel.label, textScaler: TextScaler.noScaling, style: TextStyle( fontSize: 14, @@ -71,7 +72,7 @@ class NotificationWidget extends StatelessWidget { ), ), ], - ) + ), ], ), ), diff --git a/lib/src/features/programming_reading/views/programming_reading_page.dart b/lib/src/features/programming_reading/views/programming_reading_page.dart index 802aabb3..0cf3de1b 100644 --- a/lib/src/features/programming_reading/views/programming_reading_page.dart +++ b/lib/src/features/programming_reading/views/programming_reading_page.dart @@ -44,8 +44,10 @@ class _ProgrammingHourState extends State { _bloc.add( InsertedHourTimeEvent( userHourTimeModel: userHourTimeModel, - readingTimeNotificationTitle: 'reading_time_title'.i18n(), - readingTimeNotificationBody: 'reading_time_body'.i18n(), + readingTimeNotificationTitle: 'reading-time-notification-title' + .i18n(), + readingTimeNotificationBody: 'reading-time-notification-body' + .i18n(), ), ); }, diff --git a/pubspec.yaml b/pubspec.yaml index d7a99038..e4b30fcb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.9 +version: 2.11.10 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/features/loan_insertion/bloc/loan_insertion_bloc_test.dart b/test/src/features/loan_insertion/bloc/loan_insertion_bloc_test.dart index 1ee53820..323abb18 100644 --- a/test/src/features/loan_insertion/bloc/loan_insertion_bloc_test.dart +++ b/test/src/features/loan_insertion/bloc/loan_insertion_bloc_test.dart @@ -79,10 +79,10 @@ void main() { observation: 'observation', loanDate: DateTime(2024, 02, 23), devolutionDate: DateTime(2024, 03, 22), - contactName: 'contactName', idContact: 'idContact', bookId: 'bookId', - bookTitle: 'bookTitle', + notificationTitle: 'notificationTitle', + notificationBody: 'notificationBody', ), ), verify: (_) { @@ -123,10 +123,10 @@ void main() { observation: 'observation', loanDate: DateTime(2024, 02, 23), devolutionDate: DateTime(2024, 03, 22), - contactName: 'contactName', idContact: 'idContact', bookId: 'bookId', - bookTitle: 'bookTitle', + notificationTitle: 'notificationTitle', + notificationBody: 'notificationBody', ), ), verify: (_) { @@ -174,10 +174,10 @@ void main() { observation: 'observation', loanDate: DateTime(2024, 02, 23), devolutionDate: DateTime(2024, 03, 22), - contactName: 'contactName', idContact: 'idContact', bookId: 'bookId', - bookTitle: 'bookTitle', + notificationTitle: 'notificationTitle', + notificationBody: 'notificationBody', ), ), verify: (_) { @@ -223,10 +223,10 @@ void main() { observation: 'observation', loanDate: DateTime(2024, 02, 23), devolutionDate: DateTime(2024, 03, 22), - contactName: 'contactName', idContact: 'idContact', bookId: 'bookId', - bookTitle: 'bookTitle', + notificationTitle: 'notificationTitle', + notificationBody: 'notificationBody', ), ), verify: (_) { @@ -267,10 +267,10 @@ void main() { observation: 'observation', loanDate: DateTime(2024, 02, 23), devolutionDate: DateTime(2024, 03, 22), - contactName: 'contactName', idContact: 'idContact', bookId: 'bookId', - bookTitle: 'bookTitle', + notificationTitle: 'notificationTitle', + notificationBody: 'notificationBody', ), ), verify: (_) { From 304e7b2ef0dd381b304dfb4b4583eb886ddde352 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Sun, 24 May 2026 20:19:20 -0300 Subject: [PATCH 15/19] feat: Implement platform exception handling across services and blocs - Introduced PlatformException class to standardize error handling. - Added PlatformErrorCode enum for categorizing platform-related errors. - Enhanced error handling in AppVersionService, ContactsService, LauncherService, NotificationsService, PlayAlarmSoundService, and UserNotificationCubit. - Updated AboutBloc, ContactsPickerBloc, LoanBloc, LoanDetailBloc, LoanInsertionBloc, NotificationsBloc, and ProgrammingReadingBloc to emit detailed error states. - Implemented localized error messages using PlatformErrorCodeExtension. - Updated tests to reflect changes in error handling logic. --- assets/lang/en_US.json | 5 +- assets/lang/it_IT.json | 5 +- assets/lang/pt_BR.json | 5 +- coverage/lcov.info | 1375 +++++++++-------- .../platform_exception.dart | 14 + .../platform_error_code_extension.dart | 25 + .../app_version_service_impl.dart | 27 +- .../contacts_service_impl.dart | 114 +- .../launcher_service/launcher_service.dart | 48 +- .../notifications_service_impl.dart | 170 +- .../play_alarm_sound_service.dart | 70 +- lib/src/features/about/bloc/about_bloc.dart | 14 +- lib/src/features/about/bloc/about_state.dart | 6 +- lib/src/features/about/views/about_page.dart | 8 +- .../bloc/contacts_picker_bloc.dart | 27 +- .../bloc/contacts_picker_state.dart | 6 +- .../views/contacts_picker_page.dart | 17 +- lib/src/features/loan/bloc/loan_bloc.dart | 15 + .../loan_detail/bloc/loan_detail_bloc.dart | 15 + .../bloc/loan_insertion_bloc.dart | 8 + .../bloc/notifications_bloc.dart | 13 +- .../bloc/notifications_state.dart | 6 +- .../views/notifications_page.dart | 20 +- .../bloc/programming_reading_bloc.dart | 15 + .../user_notification_cubit.dart | 12 +- .../user_notification_state.dart | 6 +- lib/src/shared/enums/platform_error_code.dart | 6 + pubspec.yaml | 2 +- .../bloc/contacts_picker_bloc_test.dart | 2 +- 29 files changed, 1209 insertions(+), 847 deletions(-) create mode 100644 lib/src/core/errors/platform_exception/platform_exception.dart create mode 100644 lib/src/core/helpers/platform_error_code/platform_error_code_extension.dart create mode 100644 lib/src/shared/enums/platform_error_code.dart diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index ea75cd4b..0724f99c 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -281,5 +281,8 @@ "notification-channel-loan-description": "Channel that notifies when it's time to receive your loaned book.", "notification-channel-loan-label": "Loans", "notification-channel-read-description": "Channel that notifies when it's time for reading.", - "notification-channel-read-label": "Readings" + "notification-channel-read-label": "Readings", + "error-platform-permission-denied": "Permission denied: %s", + "error-platform-permission-permanently-denied": "Permission permanently denied. Open settings to grant it: %s", + "error-platform-unsupported": "Operation not supported on this device: %s" } diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index 2458534f..67d79c3a 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -281,5 +281,8 @@ "notification-channel-loan-description": "Canale che notifica quando è il momento di ricevere il libro prestato.", "notification-channel-loan-label": "Prestiti", "notification-channel-read-description": "Canale che notifica quando è il momento della lettura.", - "notification-channel-read-label": "Letture" + "notification-channel-read-label": "Letture", + "error-platform-permission-denied": "Permesso negato: %s", + "error-platform-permission-permanently-denied": "Permesso negato permanentemente. Apri le impostazioni per concederlo: %s", + "error-platform-unsupported": "Operazione non supportata su questo dispositivo: %s" } diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index d48faace..baeb0fdc 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -281,5 +281,8 @@ "notification-channel-loan-description": "Canal que notifica quando é o dia de receber o livro emprestado.", "notification-channel-loan-label": "Empréstimos", "notification-channel-read-description": "Canal que notifica que está na hora da leitura.", - "notification-channel-read-label": "Leituras" + "notification-channel-read-label": "Leituras", + "error-platform-permission-denied": "Permissão negada: %s", + "error-platform-permission-permanently-denied": "Permissão negada permanentemente. Abra as configurações para concedê-la: %s", + "error-platform-unsupported": "Operação não suportada neste dispositivo: %s" } diff --git a/coverage/lcov.info b/coverage/lcov.info index 40c41fd8..92b2a9b3 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -9,29 +9,6 @@ DA:15,9 LF:7 LH:7 end_of_record -SF:lib/src/shared/constants/database_scripts/database_scripts.dart -DA:3,0 -DA:6,4 -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:11,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:18,1 -DA:21,1 -DA:24,1 -DA:27,1 -DA:30,1 -DA:34,1 -DA:41,1 -DA:44,1 -DA:47,1 -LF:19 -LH:18 -end_of_record SF:lib/src/core/models/author_model.dart DA:5,10 DA:10,9 @@ -180,212 +157,28 @@ DA:53,0 LF:22 LH:11 end_of_record -SF:lib/src/core/errors/local_database_exception/local_database_exception.dart -DA:7,7 -DA:12,0 -DA:13,0 -LF:3 -LH:1 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_bloc.dart -DA:14,3 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,2 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:45,1 -DA:51,1 -DA:56,2 -DA:58,2 -DA:59,1 -DA:62,1 -DA:63,2 -DA:67,2 -DA:68,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:72,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:79,1 -LF:34 -LH:34 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/core/models/bookcase_model.dart -DA:10,3 -DA:17,3 -DA:19,3 -DA:25,3 -DA:26,2 -DA:27,2 -DA:28,2 -DA:29,1 -DA:33,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:42,0 -DA:46,1 -DA:47,1 -DA:48,1 -DA:49,1 -DA:50,1 -DA:51,1 -DA:55,1 -DA:56,1 -DA:57,1 -DA:58,1 -DA:59,1 -DA:60,2 -DA:64,0 -DA:66,0 -DA:68,3 -DA:72,6 -DA:73,3 -DA:74,3 -DA:75,3 -DA:78,0 -DA:80,0 -LF:34 -LH:25 -end_of_record -SF:lib/src/core/models/loan_model.dart -DA:9,5 +SF:lib/src/shared/constants/database_scripts/database_scripts.dart +DA:3,0 +DA:6,4 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,2 DA:18,1 -DA:19,1 -DA:20,1 DA:21,1 -DA:22,2 -DA:23,2 DA:24,1 -DA:25,1 -DA:29,1 +DA:27,1 DA:30,1 -DA:31,1 -DA:32,1 -DA:33,1 DA:34,1 -DA:36,1 -DA:37,1 -DA:39,1 -DA:40,1 -DA:44,0 -DA:46,0 -DA:49,1 -DA:57,1 -DA:58,1 -DA:59,1 -DA:60,1 -DA:61,0 -DA:62,1 -DA:63,1 -DA:67,2 -DA:71,6 -DA:72,6 -DA:73,6 -DA:74,6 -DA:75,6 -DA:76,6 -DA:79,0 -DA:81,0 -DA:82,0 -DA:83,0 -DA:84,0 -DA:85,0 -DA:86,0 -LF:43 -LH:33 -end_of_record -SF:lib/src/core/models/reading_model.dart -DA:7,5 -DA:14,1 -DA:20,1 -DA:21,1 -DA:22,0 -DA:23,1 -DA:24,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:31,1 -DA:32,2 -DA:33,1 -DA:37,1 -DA:38,1 -DA:39,2 -DA:40,1 DA:41,1 -DA:42,2 DA:44,1 -DA:48,0 -DA:50,0 -DA:53,3 -DA:57,6 -DA:58,6 -DA:59,6 -DA:60,6 -DA:63,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -LF:32 -LH:24 -end_of_record -SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart -DA:19,1 -DA:24,2 -DA:25,2 -DA:28,1 -DA:33,2 -DA:35,2 -DA:36,2 -DA:37,2 -DA:38,2 -DA:40,1 -DA:41,1 -DA:48,1 -DA:49,1 -DA:50,1 -DA:51,1 -DA:52,1 -DA:55,1 -DA:56,1 -DA:57,1 -DA:59,1 -LF:20 -LH:20 -end_of_record -SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart -DA:13,1 -DA:25,1 -LF:2 -LH:2 +DA:47,1 +LF:19 +LH:18 end_of_record SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart DA:14,1 @@ -507,6 +300,13 @@ DA:9,0 LF:3 LH:0 end_of_record +SF:lib/src/core/errors/local_database_exception/local_database_exception.dart +DA:7,9 +DA:12,0 +DA:13,0 +LF:3 +LH:1 +end_of_record SF:lib/src/core/repositories/author_repository/authors_repository_impl.dart DA:12,1 DA:14,1 @@ -612,18 +412,56 @@ DA:98,1 LF:27 LH:27 end_of_record -SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart -DA:12,1 -DA:14,1 +SF:lib/src/core/models/bookcase_model.dart +DA:10,3 DA:17,3 -DA:18,2 -DA:21,1 -DA:22,1 -DA:24,1 -DA:26,1 -DA:31,1 -DA:34,2 -DA:35,1 +DA:19,3 +DA:25,3 +DA:26,2 +DA:27,2 +DA:28,2 +DA:29,1 +DA:33,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:42,0 +DA:46,1 +DA:47,1 +DA:48,1 +DA:49,1 +DA:50,1 +DA:51,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,2 +DA:64,0 +DA:66,0 +DA:68,3 +DA:72,6 +DA:73,3 +DA:74,3 +DA:75,3 +DA:78,0 +DA:80,0 +LF:34 +LH:25 +end_of_record +SF:lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart +DA:12,1 +DA:14,1 +DA:17,3 +DA:18,2 +DA:21,1 +DA:22,1 +DA:24,1 +DA:26,1 +DA:31,1 +DA:34,2 +DA:35,1 DA:39,2 DA:42,1 DA:43,1 @@ -659,42 +497,6 @@ DA:126,1 LF:43 LH:43 end_of_record -SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_event.dart -LF:0 -LH:0 -end_of_record -SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart -DA:12,1 -DA:14,1 -DA:17,2 -DA:18,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:28,1 -DA:30,0 -DA:37,1 -DA:40,2 -DA:41,1 -DA:46,1 -DA:47,1 -DA:50,2 -DA:52,1 -DA:53,1 -DA:55,1 -DA:57,0 -DA:62,1 -DA:65,2 -DA:66,1 -DA:67,1 -DA:71,1 -DA:76,1 -DA:79,2 -DA:80,1 -DA:86,1 -LF:28 -LH:26 -end_of_record SF:lib/src/core/repositories/books_repository/books_repository_impl.dart DA:12,1 DA:14,1 @@ -772,6 +574,85 @@ DA:210,1 LF:73 LH:73 end_of_record +SF:lib/src/core/repositories/category_repository/categories_repository_impl.dart +DA:12,1 +DA:14,1 +DA:17,2 +DA:18,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:28,1 +DA:30,0 +DA:37,1 +DA:40,2 +DA:41,1 +DA:46,1 +DA:47,1 +DA:50,2 +DA:52,1 +DA:53,1 +DA:55,1 +DA:57,0 +DA:62,1 +DA:65,2 +DA:66,1 +DA:67,1 +DA:71,1 +DA:76,1 +DA:79,2 +DA:80,1 +DA:86,1 +LF:28 +LH:26 +end_of_record +SF:lib/src/core/models/loan_model.dart +DA:9,5 +DA:18,1 +DA:19,1 +DA:20,1 +DA:21,1 +DA:22,2 +DA:23,2 +DA:24,1 +DA:25,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +DA:37,1 +DA:39,1 +DA:40,1 +DA:44,0 +DA:46,0 +DA:49,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,1 +DA:61,0 +DA:62,1 +DA:63,1 +DA:67,2 +DA:71,6 +DA:72,6 +DA:73,6 +DA:74,6 +DA:75,6 +DA:76,6 +DA:79,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +LF:43 +LH:33 +end_of_record SF:lib/src/core/repositories/loan_repository/loan_repository_impl.dart DA:13,1 DA:15,1 @@ -824,6 +705,42 @@ DA:136,1 LF:48 LH:48 end_of_record +SF:lib/src/core/models/reading_model.dart +DA:7,5 +DA:14,1 +DA:20,1 +DA:21,1 +DA:22,0 +DA:23,1 +DA:24,1 +DA:28,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,2 +DA:33,1 +DA:37,1 +DA:38,1 +DA:39,2 +DA:40,1 +DA:41,1 +DA:42,2 +DA:44,1 +DA:48,0 +DA:50,0 +DA:53,3 +DA:57,6 +DA:58,6 +DA:59,6 +DA:60,6 +DA:63,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +LF:32 +LH:24 +end_of_record SF:lib/src/core/repositories/reading_repository/reading_repository_impl.dart DA:13,1 DA:17,1 @@ -957,92 +874,6 @@ DA:57,0 LF:15 LH:13 end_of_record -SF:lib/src/core/models/custom_notification_model.dart -DA:5,0 -DA:7,0 -DA:8,0 -DA:12,0 -DA:14,0 -DA:15,0 -DA:28,2 -DA:37,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:51,0 -DA:55,0 -DA:57,0 -DA:60,0 -DA:64,0 -DA:65,0 -DA:66,0 -DA:67,0 -DA:68,0 -DA:69,0 -DA:72,0 -DA:74,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:79,0 -LF:31 -LH:1 -end_of_record -SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart -DA:19,1 -DA:23,2 -DA:24,2 -DA:27,1 -DA:32,2 -DA:34,2 -DA:35,1 -DA:39,1 -DA:40,1 -DA:41,1 -DA:50,1 -DA:51,1 -DA:52,1 -DA:53,1 -DA:54,1 -DA:55,1 -DA:58,2 -DA:62,1 -DA:63,1 -DA:64,1 -DA:73,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:80,2 -DA:81,1 -DA:82,1 -DA:83,1 -DA:84,1 -DA:85,1 -DA:88,1 -DA:89,1 -DA:90,1 -DA:92,1 -DA:98,1 -DA:104,1 -DA:113,2 -LF:37 -LH:37 -end_of_record -SF:lib/src/features/loan_insertion/bloc/loan_insertion_event.dart -DA:14,1 -LF:1 -LH:1 -end_of_record -SF:lib/src/features/loan_insertion/bloc/loan_insertion_state.dart -DA:13,1 -LF:1 -LH:1 -end_of_record SF:lib/src/core/repositories/user_page_reading_time_repository/user_page_reading_time_repository_impl.dart DA:12,1 DA:16,1 @@ -1121,15 +952,25 @@ LF:19 LH:1 end_of_record SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:6,0 DA:8,0 DA:10,0 -DA:12,0 DA:13,0 -DA:14,0 DA:15,0 DA:16,0 -LF:8 +DA:17,0 +DA:18,0 +DA:19,0 +DA:23,0 +DA:26,0 +DA:28,0 +LF:11 +LH:0 +end_of_record +SF:lib/src/core/errors/platform_exception/platform_exception.dart +DA:7,0 +DA:12,0 +DA:13,0 +LF:3 LH:0 end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart @@ -1609,41 +1450,15 @@ DA:31,2 DA:33,2 DA:34,1 DA:35,3 -DA:36,3 -DA:37,1 -DA:38,2 -DA:39,3 -DA:41,2 -DA:43,3 -DA:44,2 -LF:24 -LH:23 -end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 -DA:22,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:27,1 -DA:28,1 -DA:29,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:16 -LH:16 +DA:36,3 +DA:37,1 +DA:38,2 +DA:39,3 +DA:41,2 +DA:43,3 +DA:44,2 +LF:24 +LH:23 end_of_record SF:lib/src/shared/blocs/book_bloc/book_event.dart DA:10,1 @@ -1762,24 +1577,31 @@ DA:227,0 LF:98 LH:75 end_of_record -SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart -DA:13,1 -LF:1 -LH:1 +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +DA:11,1 +DA:20,1 +LF:2 +LH:2 end_of_record -SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart -DA:10,1 -DA:12,2 -DA:14,1 -DA:16,2 +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 DA:18,2 DA:20,2 -DA:21,1 DA:22,1 DA:23,1 -DA:24,1 -LF:10 -LH:10 +DA:25,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart DA:12,1 @@ -1827,6 +1649,65 @@ DA:20,1 LF:2 LH:2 end_of_record +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart +DA:14,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:22,2 +DA:23,1 +DA:24,0 +DA:25,0 +DA:26,0 +DA:27,0 +DA:30,1 +DA:31,1 +DA:32,1 +DA:34,1 +LF:15 +LH:11 +end_of_record +SF:lib/src/core/models/custom_notification_model.dart +DA:5,0 +DA:7,0 +DA:8,0 +DA:12,0 +DA:14,0 +DA:15,0 +DA:28,2 +DA:37,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:51,0 +DA:55,0 +DA:57,0 +DA:60,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:72,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +LF:31 +LH:1 +end_of_record SF:lib/src/features/auth/bloc/auth_bloc.dart DA:13,3 DA:14,2 @@ -1861,21 +1742,27 @@ LF:1 LH:1 end_of_record SF:lib/src/features/about/bloc/about_bloc.dart -DA:11,3 -DA:12,2 -DA:15,1 -DA:20,2 -DA:21,2 +DA:13,3 +DA:14,2 +DA:17,1 DA:22,2 -DA:24,1 +DA:23,2 +DA:24,2 DA:25,1 -DA:26,2 -LF:9 -LH:9 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:15 +LH:11 end_of_record SF:lib/src/features/about/bloc/about_state.dart DA:10,1 -DA:18,1 +DA:19,1 LF:2 LH:2 end_of_record @@ -1962,6 +1849,59 @@ DA:19,2 LF:8 LH:4 end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_event.dart +DA:8,1 +DA:17,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart +DA:11,1 +DA:23,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart +DA:13,1 +DA:15,2 +DA:16,2 +DA:17,2 +DA:20,1 +DA:25,2 +DA:27,2 +DA:28,1 +DA:31,1 +DA:32,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:39,1 +DA:40,1 +DA:43,1 +DA:44,1 +DA:45,1 +DA:47,1 +DA:53,1 +DA:58,2 +DA:60,2 +DA:61,1 +DA:62,1 +DA:65,1 +DA:66,1 +DA:67,1 +DA:76,2 +DA:77,1 +DA:78,1 +DA:79,1 +DA:80,1 +DA:81,1 +DA:84,1 +DA:85,1 +DA:86,1 +DA:88,1 +LF:37 +LH:37 +end_of_record SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart DA:14,1 DA:16,2 @@ -2018,17 +1958,22 @@ LF:7 LH:0 end_of_record SF:lib/src/core/services/app_services/launcher_service/launcher_service.dart -DA:4,0 DA:6,0 DA:8,0 -DA:17,0 -DA:21,0 -DA:23,0 -DA:24,0 -DA:27,0 +DA:10,0 +DA:11,0 DA:28,0 +DA:31,0 +DA:33,0 +DA:38,0 DA:40,0 -LF:10 +DA:41,0 +DA:44,0 +DA:45,0 +DA:62,0 +DA:65,0 +DA:67,0 +LF:15 LH:0 end_of_record SF:lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart @@ -2324,7 +2269,7 @@ LF:27 LH:14 end_of_record SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart -DA:6,1 +DA:6,2 DA:11,4 DA:13,4 DA:14,4 @@ -2416,80 +2361,27 @@ DA:42,0 DA:43,0 DA:45,0 DA:48,0 -DA:51,4 -DA:52,2 -DA:53,2 -DA:55,2 -DA:56,2 -DA:60,1 -DA:61,1 -DA:62,1 -DA:63,0 -DA:64,0 -DA:65,0 -DA:67,0 -DA:68,0 -DA:70,0 -DA:73,0 -DA:76,1 -DA:77,1 -DA:79,1 -DA:80,1 -LF:36 -LH:22 -end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_event.dart -DA:8,1 -DA:17,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_state.dart -DA:11,1 -DA:23,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart -DA:13,1 -DA:15,2 -DA:16,2 -DA:17,2 -DA:20,1 -DA:25,2 -DA:27,2 -DA:28,1 -DA:31,1 -DA:32,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:39,1 -DA:40,1 -DA:43,1 -DA:44,1 -DA:45,1 -DA:47,1 -DA:53,1 -DA:58,2 -DA:60,2 +DA:51,4 +DA:52,2 +DA:53,2 +DA:55,2 +DA:56,2 +DA:60,1 DA:61,1 DA:62,1 -DA:65,1 -DA:66,1 -DA:67,1 -DA:76,2 +DA:63,0 +DA:64,0 +DA:65,0 +DA:67,0 +DA:68,0 +DA:70,0 +DA:73,0 +DA:76,1 DA:77,1 -DA:78,1 DA:79,1 DA:80,1 -DA:81,1 -DA:84,1 -DA:85,1 -DA:86,1 -DA:88,1 -LF:37 -LH:37 +LF:36 +LH:22 end_of_record SF:lib/src/features/bookcase/bloc/bookcase_state.dart DA:10,2 @@ -2579,7 +2471,7 @@ LF:2 LH:2 end_of_record SF:lib/src/core/dtos/bookcase_dto.dart -DA:7,2 +DA:7,3 DA:12,0 DA:16,0 DA:17,0 @@ -2594,10 +2486,6 @@ DA:35,0 LF:12 LH:3 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 -end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 DA:10,0 @@ -3756,6 +3644,10 @@ DA:7,0 LF:1 LH:0 end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_event.dart DA:8,1 LF:1 @@ -3797,6 +3689,38 @@ DA:22,1 LF:2 LH:2 end_of_record +SF:lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart +DA:14,1 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:34,4 +DA:35,1 +DA:37,1 +DA:38,2 +DA:42,2 +DA:43,1 +DA:44,1 +DA:45,1 +DA:46,1 +DA:47,1 +DA:50,1 +DA:51,1 +DA:52,1 +DA:54,1 +LF:22 +LH:22 +end_of_record SF:lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart DA:17,1 DA:20,2 @@ -3836,62 +3760,34 @@ DA:19,1 LF:2 LH:2 end_of_record -SF:lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_state.dart +SF:lib/src/features/contacts_picker/bloc/contacts_picker_state.dart DA:12,1 DA:21,1 LF:2 LH:2 end_of_record -SF:lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart +SF:lib/src/features/contacts_picker/bloc/contacts_picker_bloc.dart DA:14,1 DA:15,2 DA:16,2 DA:19,1 DA:24,2 DA:26,2 -DA:28,1 -DA:29,2 -DA:34,4 -DA:35,1 +DA:27,1 +DA:28,4 +DA:31,1 +DA:32,2 +DA:36,2 DA:37,1 -DA:38,2 -DA:42,2 -DA:43,1 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 DA:44,1 DA:45,1 DA:46,1 -DA:47,1 -DA:50,1 -DA:51,1 -DA:52,1 -DA:54,1 -LF:22 -LH:22 -end_of_record -SF:lib/src/features/contacts_picker/bloc/contacts_picker_state.dart -DA:12,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/contacts_picker/bloc/contacts_picker_bloc.dart -DA:12,1 -DA:13,2 -DA:14,2 -DA:17,1 -DA:22,2 -DA:24,2 -DA:25,1 -DA:26,4 -DA:30,1 -DA:31,1 -DA:38,1 -DA:39,2 -DA:43,2 -DA:45,1 -DA:46,1 -DA:47,1 -LF:16 +DA:48,1 +LF:20 LH:16 end_of_record SF:lib/src/core/models/contact_model.dart @@ -3915,58 +3811,66 @@ LF:16 LH:1 end_of_record SF:lib/src/features/loan/bloc/loan_bloc.dart -DA:18,1 -DA:22,2 +DA:19,1 DA:23,2 DA:24,2 -DA:27,1 -DA:32,2 -DA:34,2 -DA:36,1 -DA:37,2 -DA:41,1 -DA:42,0 +DA:25,2 +DA:28,1 +DA:33,2 +DA:35,2 +DA:37,1 +DA:38,2 +DA:42,1 DA:43,0 DA:44,0 DA:45,0 DA:46,0 -DA:49,0 +DA:47,0 DA:50,0 DA:51,0 -DA:53,0 -DA:59,1 -DA:64,2 -DA:66,2 +DA:52,0 +DA:54,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:61,0 DA:67,1 -DA:70,1 -DA:71,2 +DA:72,2 +DA:74,2 DA:75,1 -DA:76,1 -DA:77,1 DA:78,1 -DA:79,1 -DA:80,1 +DA:79,2 DA:83,1 DA:84,1 DA:85,1 +DA:86,1 DA:87,1 -DA:93,1 -DA:97,1 -DA:99,2 +DA:88,1 +DA:91,1 +DA:92,0 +DA:93,0 +DA:95,0 +DA:98,1 +DA:99,1 DA:100,1 -DA:101,1 DA:102,1 -DA:110,2 -DA:111,1 +DA:108,1 +DA:112,1 DA:114,2 DA:115,1 -DA:118,1 -DA:120,1 -DA:121,1 -DA:125,1 -DA:128,2 -LF:50 -LH:41 +DA:116,1 +DA:117,1 +DA:125,2 +DA:126,1 +DA:129,2 +DA:130,1 +DA:133,1 +DA:135,1 +DA:136,1 +DA:140,1 +DA:143,2 +LF:58 +LH:42 end_of_record SF:lib/src/features/loan/bloc/loan_state.dart DA:14,1 @@ -4006,10 +3910,6 @@ DA:63,0 LF:23 LH:1 end_of_record -SF:lib/src/features/contacts_picker/bloc/contacts_picker_event.dart -LF:0 -LH:0 -end_of_record SF:lib/src/features/loan_detail/bloc/loan_detail_state.dart DA:10,1 DA:21,1 @@ -4023,51 +3923,167 @@ LF:2 LH:2 end_of_record SF:lib/src/features/loan_detail/bloc/loan_detail_bloc.dart +DA:21,1 +DA:26,2 +DA:27,2 +DA:28,2 +DA:31,1 +DA:36,2 +DA:38,3 +DA:39,3 +DA:40,3 +DA:42,1 +DA:45,1 +DA:46,1 +DA:49,1 +DA:50,1 +DA:54,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:58,1 +DA:61,1 +DA:62,0 +DA:63,0 +DA:65,0 +DA:69,1 +DA:70,1 +DA:72,1 +DA:78,1 +DA:83,2 +DA:85,3 +DA:86,2 +DA:87,1 +DA:91,1 +DA:92,1 +DA:93,1 +DA:101,3 +DA:103,1 +DA:104,1 +DA:105,1 +DA:113,2 +DA:114,1 +DA:115,1 +DA:116,1 +DA:117,1 +DA:118,1 +DA:121,1 +DA:122,0 +DA:123,0 +DA:125,0 +DA:129,1 +DA:130,1 +DA:132,1 +LF:51 +LH:45 +end_of_record +SF:lib/src/features/contacts_picker/bloc/contacts_picker_event.dart +LF:0 +LH:0 +end_of_record +SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:20,1 +DA:24,2 DA:25,2 -DA:26,2 -DA:27,2 -DA:30,1 +DA:28,1 +DA:33,2 DA:35,2 -DA:37,3 -DA:38,3 -DA:39,3 +DA:36,1 +DA:40,1 DA:41,1 -DA:44,1 -DA:45,1 -DA:48,1 -DA:49,1 +DA:42,1 +DA:51,1 +DA:52,1 DA:53,1 DA:54,1 DA:55,1 DA:56,1 -DA:57,1 -DA:61,1 -DA:62,1 +DA:59,2 +DA:63,1 DA:64,1 -DA:70,1 -DA:75,2 -DA:77,3 -DA:78,2 -DA:79,1 +DA:65,1 +DA:74,1 +DA:76,1 +DA:77,1 +DA:78,1 +DA:81,2 +DA:82,1 DA:83,1 DA:84,1 DA:85,1 -DA:93,3 -DA:95,1 +DA:86,1 +DA:89,1 +DA:90,0 +DA:91,0 +DA:93,0 DA:96,1 DA:97,1 -DA:105,2 +DA:98,1 +DA:100,1 DA:106,1 -DA:107,1 -DA:108,1 -DA:109,1 -DA:110,1 -DA:114,1 -DA:115,1 -DA:117,1 -LF:43 -LH:43 +DA:112,1 +DA:121,2 +LF:41 +LH:38 +end_of_record +SF:lib/src/features/loan_insertion/bloc/loan_insertion_event.dart +DA:14,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/features/loan_insertion/bloc/loan_insertion_state.dart +DA:13,1 +LF:1 +LH:1 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_bloc.dart +DA:14,3 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,2 +DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,1 +DA:63,2 +DA:67,2 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:79,1 +LF:34 +LH:34 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_event.dart +DA:10,1 +LF:1 +LH:1 end_of_record SF:lib/src/features/home/views/home_page.dart DA:11,1 @@ -4270,27 +4286,32 @@ LH:18 end_of_record SF:lib/src/features/notifications/bloc/notifications_state.dart DA:12,1 -DA:20,1 +DA:21,1 LF:2 LH:2 end_of_record SF:lib/src/features/notifications/bloc/notifications_bloc.dart -DA:11,1 -DA:13,2 -DA:14,2 -DA:17,1 -DA:22,2 +DA:13,1 +DA:15,2 +DA:16,2 +DA:19,1 DA:24,2 -DA:26,1 -DA:27,2 -DA:31,1 -DA:32,1 -DA:36,1 -DA:37,1 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,1 +DA:34,1 DA:38,1 -DA:39,2 -LF:14 -LH:14 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:45,1 +DA:46,1 +DA:47,1 +DA:49,1 +LF:19 +LH:15 end_of_record SF:lib/src/features/profile/bloc/profile_state.dart DA:10,1 @@ -4343,6 +4364,36 @@ DA:10,1 LF:1 LH:1 end_of_record +SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart +DA:19,1 +DA:24,2 +DA:25,2 +DA:28,1 +DA:33,2 +DA:35,2 +DA:36,2 +DA:37,2 +DA:38,2 +DA:40,1 +DA:41,1 +DA:48,1 +DA:49,1 +DA:50,1 +DA:51,1 +DA:52,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:59,1 +LF:20 +LH:20 +end_of_record +SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_state.dart +DA:13,1 +DA:25,1 +LF:2 +LH:2 +end_of_record SF:lib/src/features/programming_reading/bloc/programming_reading_state.dart DA:10,1 DA:24,1 @@ -4350,70 +4401,78 @@ LF:2 LH:2 end_of_record SF:lib/src/features/programming_reading/bloc/programming_reading_bloc.dart -DA:18,1 -DA:21,2 +DA:19,1 DA:22,2 DA:23,2 DA:24,2 -DA:27,1 -DA:32,2 -DA:34,2 -DA:36,1 +DA:25,2 +DA:28,1 +DA:33,2 +DA:35,2 DA:37,1 -DA:41,1 +DA:38,1 DA:42,1 DA:43,1 DA:44,1 DA:45,1 -DA:48,1 +DA:46,1 DA:49,1 DA:50,1 -DA:52,1 -DA:58,1 -DA:63,2 -DA:65,1 -DA:67,1 +DA:51,1 +DA:53,1 +DA:59,1 +DA:64,2 +DA:66,1 DA:68,1 -DA:72,1 +DA:69,1 DA:73,1 DA:74,1 -DA:82,2 -DA:83,1 +DA:75,1 +DA:83,2 DA:84,1 DA:85,1 DA:86,1 DA:87,1 -DA:88,2 +DA:88,1 DA:89,2 DA:90,2 -DA:91,1 +DA:91,2 DA:92,1 -DA:97,2 -DA:98,1 +DA:93,1 +DA:98,2 DA:99,1 DA:100,1 DA:101,1 DA:102,1 -DA:105,1 +DA:103,1 DA:106,1 -DA:107,1 -DA:109,1 +DA:107,0 +DA:108,0 +DA:110,0 +DA:113,1 +DA:114,1 DA:115,1 -DA:120,2 -DA:122,2 +DA:117,1 DA:123,1 -DA:126,2 -DA:127,1 -DA:128,0 -DA:129,0 -DA:130,0 -DA:131,0 -DA:134,1 +DA:128,2 +DA:130,2 +DA:131,1 +DA:134,2 DA:135,1 -DA:136,1 -DA:138,1 -LF:62 -LH:58 +DA:136,0 +DA:137,0 +DA:138,0 +DA:139,0 +DA:142,1 +DA:143,0 +DA:144,0 +DA:146,0 +DA:149,1 +DA:150,1 +DA:151,1 +DA:153,1 +LF:70 +LH:60 end_of_record SF:lib/src/features/programming_reading/bloc/programming_reading_event.dart DA:12,1 diff --git a/lib/src/core/errors/platform_exception/platform_exception.dart b/lib/src/core/errors/platform_exception/platform_exception.dart new file mode 100644 index 00000000..802c1fe9 --- /dev/null +++ b/lib/src/core/errors/platform_exception/platform_exception.dart @@ -0,0 +1,14 @@ +import 'package:bookify/src/shared/enums/platform_error_code.dart'; + +class PlatformException implements Exception { + final PlatformErrorCode code; + final String? descriptionMessage; + + const PlatformException( + this.code, { + this.descriptionMessage, + }); + + @override + String toString() => 'PlatformException: [$code] $descriptionMessage'; +} diff --git a/lib/src/core/helpers/platform_error_code/platform_error_code_extension.dart b/lib/src/core/helpers/platform_error_code/platform_error_code_extension.dart new file mode 100644 index 00000000..4a7125ec --- /dev/null +++ b/lib/src/core/helpers/platform_error_code/platform_error_code_extension.dart @@ -0,0 +1,25 @@ +import 'package:bookify/src/shared/enums/platform_error_code.dart'; // Assicurati che l'import sia corretto +import 'package:localization/localization.dart'; + +extension PlatformErrorCodeExtension on PlatformErrorCode { + String toLocalizedMessage(String? descriptionMessage) { + final messageArg = descriptionMessage ?? '---'; + + return switch (this) { + PlatformErrorCode.permissionDenied => + 'error-platform-permission-denied'.i18n([ + messageArg, + ]), + PlatformErrorCode.permissionPermanentlyDenied => + 'error-platform-permission-permanently-denied'.i18n([ + messageArg, + ]), + PlatformErrorCode.unsupported => 'error-platform-unsupported'.i18n([ + messageArg, + ]), + PlatformErrorCode.unknown => 'error-unknown'.i18n([ + messageArg, + ]), + }; + } +} diff --git a/lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart b/lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart index 03ef7b6e..5b0ee20d 100644 --- a/lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +++ b/lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart @@ -1,5 +1,7 @@ +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/models/app_version_model.dart'; import 'package:bookify/src/core/services/app_services/app_version_service/app_version_service.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; import 'package:package_info_plus/package_info_plus.dart'; class AppVersionServiceImpl implements AppVersionService { @@ -7,15 +9,24 @@ class AppVersionServiceImpl implements AppVersionService { @override Future getAppVersion() async { - final packageInfo = await PackageInfo.fromPlatform(); + try { + final packageInfo = await PackageInfo.fromPlatform(); - final appVersion = AppVersionModel( - appName: packageInfo.appName, - appPackageName: packageInfo.packageName, - version: packageInfo.version, - buildNumber: packageInfo.buildNumber, - ); + final appVersion = AppVersionModel( + appName: packageInfo.appName, + appPackageName: packageInfo.packageName, + version: packageInfo.version, + buildNumber: packageInfo.buildNumber, + ); - return appVersion; + return appVersion; + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } } diff --git a/lib/src/core/services/app_services/contacts_service/contacts_service_impl.dart b/lib/src/core/services/app_services/contacts_service/contacts_service_impl.dart index 7df29b6e..1f6605c7 100644 --- a/lib/src/core/services/app_services/contacts_service/contacts_service_impl.dart +++ b/lib/src/core/services/app_services/contacts_service/contacts_service_impl.dart @@ -1,71 +1,91 @@ +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/models/contact_model.dart'; import 'package:bookify/src/core/services/app_services/contacts_service/contacts_service.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:fast_contacts/fast_contacts.dart'; class ContactsServiceImpl implements ContactsService { @override Future getContactById({required String id}) async { - final permissionStatus = await Permission.contacts.request(); + try { + final permissionStatus = await Permission.contacts.request(); - if (permissionStatus.isGranted) { - final contact = await FastContacts.getContact( - id, - fields: [ - ContactField.displayName, - ContactField.phoneNumbers, - ], - ); - final photo = await FastContacts.getContactImage(id); - - if (contact != null) { - return ContactModel( - id: contact.id, - name: contact.displayName, - phoneNumber: (contact.phones.isNotEmpty) - ? contact.phones.first.number - : null, - photo: photo, + if (permissionStatus.isGranted) { + final contact = await FastContacts.getContact( + id, + fields: [ + ContactField.displayName, + ContactField.phoneNumbers, + ], ); + final photo = await FastContacts.getContactImage(id); + + if (contact != null) { + return ContactModel( + id: contact.id, + name: contact.displayName, + phoneNumber: (contact.phones.isNotEmpty) + ? contact.phones.first.number + : null, + photo: photo, + ); + } + } else if (permissionStatus.isPermanentlyDenied) { + openAppSettings(); } - } else if (permissionStatus.isPermanentlyDenied) { - openAppSettings(); + return null; + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); } - return null; } @override Future?> getContacts() async { - final permissionStatus = await Permission.contacts.request(); + try { + final permissionStatus = await Permission.contacts.request(); - if (permissionStatus.isGranted) { - final contacts = await FastContacts.getAllContacts( - fields: [ - ContactField.displayName, - ContactField.phoneNumbers, - ], - ); + if (permissionStatus.isGranted) { + final contacts = await FastContacts.getAllContacts( + fields: [ + ContactField.displayName, + ContactField.phoneNumbers, + ], + ); - final List contactsDto = []; - for (Contact contact in contacts) { - final photo = await FastContacts.getContactImage(contact.id); + final List contactsDto = []; + for (Contact contact in contacts) { + final photo = await FastContacts.getContactImage(contact.id); - final contactDto = ContactModel( - id: contact.id, - name: contact.displayName, - phoneNumber: (contact.phones.isNotEmpty) - ? contact.phones.first.number - : null, - photo: photo, - ); + final contactDto = ContactModel( + id: contact.id, + name: contact.displayName, + phoneNumber: (contact.phones.isNotEmpty) + ? contact.phones.first.number + : null, + photo: photo, + ); - contactsDto.add(contactDto); - } + contactsDto.add(contactDto); + } - return contactsDto; - } else if (permissionStatus.isPermanentlyDenied) { - openAppSettings(); + return contactsDto; + } else if (permissionStatus.isPermanentlyDenied) { + openAppSettings(); + } + return null; + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); } - return null; } } diff --git a/lib/src/core/services/app_services/launcher_service/launcher_service.dart b/lib/src/core/services/app_services/launcher_service/launcher_service.dart index a5adb337..ec9ca7eb 100644 --- a/lib/src/core/services/app_services/launcher_service/launcher_service.dart +++ b/lib/src/core/services/app_services/launcher_service/launcher_service.dart @@ -1,3 +1,5 @@ +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; import 'package:url_launcher/url_launcher.dart'; class LauncherService { @@ -5,16 +7,31 @@ class LauncherService { try { final uri = Uri.parse(url); - final urlIsLaunched = await launchUrl( - uri, - mode: LaunchMode.externalApplication, - ); + if (await canLaunchUrl(uri)) { + final urlIsLaunched = await launchUrl( + uri, + mode: LaunchMode.externalApplication, + ); - if (!urlIsLaunched) { - throw 'Erro ao abrir o link'; + if (!urlIsLaunched) { + throw const PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: 'Impossible to launch the URL', + ); + } + } else { + throw const PlatformException( + PlatformErrorCode.unsupported, + descriptionMessage: 'The URL scheme is not supported', + ); } + } on PlatformException { + rethrow; } catch (e) { - throw Exception('Ocorreu um erro inesperado: $e'); + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @@ -31,13 +48,24 @@ class LauncherService { ); if (!callIsLaunched) { - throw 'Erro ao efetuar a chamada'; + throw const PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: 'Impossible to launch the call', + ); } } else { - throw 'Não foi possível executar a ação de chamada'; + throw const PlatformException( + PlatformErrorCode.unsupported, + descriptionMessage: 'The phone number format is not supported', + ); } + } on PlatformException { + rethrow; } catch (e) { - throw Exception('Ocorreu um erro inesperado: $e'); + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } } diff --git a/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart b/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart index ecccdf96..1bc782ce 100644 --- a/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart +++ b/lib/src/core/services/app_services/notifications_service/notifications_service_impl.dart @@ -1,5 +1,7 @@ import 'dart:io'; +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; import 'package:bookify/src/shared/enums/repeat_hour_time_type.dart'; import 'package:bookify/src/core/models/custom_notification_model.dart'; import 'package:bookify/src/core/helpers/notification_channel/notification_channel_extension.dart'; @@ -29,17 +31,20 @@ class NotificationsServiceImpl implements NotificationsService { if (Platform.isAndroid) { await _notifications .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>()! + AndroidFlutterLocalNotificationsPlugin + >()! .requestNotificationsPermission(); await _notifications .resolvePlatformSpecificImplementation< - AndroidFlutterLocalNotificationsPlugin>()! + AndroidFlutterLocalNotificationsPlugin + >()! .requestExactAlarmsPermission(); } else if (Platform.isIOS) { await _notifications .resolvePlatformSpecificImplementation< - IOSFlutterLocalNotificationsPlugin>()! + IOSFlutterLocalNotificationsPlugin + >()! .requestPermissions(); } } @@ -113,21 +118,30 @@ class NotificationsServiceImpl implements NotificationsService { Future scheduleNotification( CustomNotificationModel notification, ) async { - await _notifications.zonedSchedule( - id: notification.id, - title: notification.title, - body: notification.body, - scheduledDate: tz.TZDateTime.from( - notification.scheduledDate, - tz.local, - ), - notificationDetails: _getNotificationDetails( - notification.notificationChannel, - notification.body, - ), - payload: notification.payload, - androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, - ); + try { + await _notifications.zonedSchedule( + id: notification.id, + title: notification.title, + body: notification.body, + scheduledDate: tz.TZDateTime.from( + notification.scheduledDate, + tz.local, + ), + notificationDetails: _getNotificationDetails( + notification.notificationChannel, + notification.body, + ), + payload: notification.payload, + androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, + ); + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } @override @@ -139,62 +153,96 @@ class NotificationsServiceImpl implements NotificationsService { required DateTime scheduledDate, required NotificationChannel notificationChannel, }) async { - final dateTimeComponents = switch (repeatType) { - RepeatHourTimeType.daily => DateTimeComponents.time, - RepeatHourTimeType.weekly => DateTimeComponents.dayOfWeekAndTime, - }; - - await _notifications.zonedSchedule( - id: id, - title: title, - body: body, - scheduledDate: tz.TZDateTime.from( - scheduledDate, - tz.local, - ), - notificationDetails: _getNotificationDetails( - notificationChannel, - body, - ), - androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, - matchDateTimeComponents: dateTimeComponents, - ); + try { + final dateTimeComponents = switch (repeatType) { + RepeatHourTimeType.daily => DateTimeComponents.time, + RepeatHourTimeType.weekly => DateTimeComponents.dayOfWeekAndTime, + }; + + await _notifications.zonedSchedule( + id: id, + title: title, + body: body, + scheduledDate: tz.TZDateTime.from( + scheduledDate, + tz.local, + ), + notificationDetails: _getNotificationDetails( + notificationChannel, + body, + ), + androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, + matchDateTimeComponents: dateTimeComponents, + ); + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } @override Future cancelNotificationById({required int id}) async { - await _notifications.cancel(id: id); + try { + await _notifications.cancel(id: id); + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } @override Future checkForNotifications() async { - final details = await _notifications.getNotificationAppLaunchDetails(); - if (details != null && details.didNotificationLaunchApp) { - if (details.notificationResponse != null) { - _onTapOnNotification(details.notificationResponse!); + try { + final details = await _notifications.getNotificationAppLaunchDetails(); + if (details != null && details.didNotificationLaunchApp) { + if (details.notificationResponse != null) { + _onTapOnNotification(details.notificationResponse!); + } } + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); } } @override Future> getNotifications() async { - final pendingNotifications = - await _notifications.pendingNotificationRequests(); - - final notifications = pendingNotifications - .map( - (notification) => CustomNotificationModel( - id: notification.id, - notificationChannel: notification.payload!.isEmpty - ? NotificationChannel.readChannel - : NotificationChannel.loanChannel, - title: notification.title ?? 'sem título', - body: notification.body ?? 'sem corpo', - scheduledDate: DateTime.now(), - ), - ) - .toList(); - - return notifications; + try { + final pendingNotifications = await _notifications + .pendingNotificationRequests(); + + final notifications = pendingNotifications + .map( + (notification) => CustomNotificationModel( + id: notification.id, + notificationChannel: notification.payload!.isEmpty + ? NotificationChannel.readChannel + : NotificationChannel.loanChannel, + title: notification.title ?? '--', + body: notification.body ?? '--', + scheduledDate: DateTime.now(), + ), + ) + .toList(); + + return notifications; + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } } diff --git a/lib/src/core/services/app_services/play_alarm_sound_service/play_alarm_sound_service.dart b/lib/src/core/services/app_services/play_alarm_sound_service/play_alarm_sound_service.dart index 0ea6f20b..26773f1c 100644 --- a/lib/src/core/services/app_services/play_alarm_sound_service/play_alarm_sound_service.dart +++ b/lib/src/core/services/app_services/play_alarm_sound_service/play_alarm_sound_service.dart @@ -1,7 +1,9 @@ import 'dart:async'; +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/shared/constants/audios/bookify_audios.dart'; import 'package:audioplayers/audioplayers.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; class PlayAlarmSoundService { final String assetSound; @@ -34,33 +36,67 @@ class PlayAlarmSoundService { } Future playAlarm() async { - await _playSound(volume); + try { + await _playSound(volume); + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } Future stop() async { - await player.stop(); + try { + await player.stop(); + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } Future dispose() async { - await player.dispose(); + try { + await player.dispose(); + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } Future _playSound(double volume) async { - await player.play( - AssetSource( - assetSound.replaceRange(0, 7, ''), - ), - ctx: AudioContext( - android: const AudioContextAndroid( - usageType: AndroidUsageType.alarm, - stayAwake: true, - audioMode: AndroidAudioMode.ringtone, + try { + await player.play( + AssetSource( + assetSound.replaceRange(0, 7, ''), ), - iOS: AudioContextIOS( - category: AVAudioSessionCategory.ambient, + ctx: AudioContext( + android: const AudioContextAndroid( + usageType: AndroidUsageType.alarm, + stayAwake: true, + audioMode: AndroidAudioMode.ringtone, + ), + iOS: AudioContextIOS( + category: AVAudioSessionCategory.ambient, + ), ), - ), - volume: volume, - ); + volume: volume, + ); + } on PlatformException { + rethrow; + } catch (e) { + throw PlatformException( + PlatformErrorCode.unknown, + descriptionMessage: e.toString(), + ); + } } } diff --git a/lib/src/features/about/bloc/about_bloc.dart b/lib/src/features/about/bloc/about_bloc.dart index 3cecc694..f03a3936 100644 --- a/lib/src/features/about/bloc/about_bloc.dart +++ b/lib/src/features/about/bloc/about_bloc.dart @@ -1,5 +1,7 @@ +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/models/app_version_model.dart'; import 'package:bookify/src/core/services/app_services/app_version_service/app_version_service.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'about_event.dart'; @@ -20,10 +22,18 @@ class AboutBloc extends Bloc { emit(AboutLoadingState()); final appVersion = await _appVersionService.getAppVersion(); emit(AboutLoadedState(appVersionModel: appVersion)); - } catch (e) { + } on PlatformException catch (e) { emit( AboutErrorState( - errorMessage: 'Erro ao buscar a versão: ${e.toString()}', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); + } on Exception catch (e) { + emit( + AboutErrorState( + errorCode: PlatformErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/about/bloc/about_state.dart b/lib/src/features/about/bloc/about_state.dart index 912686d1..ba8f09a0 100644 --- a/lib/src/features/about/bloc/about_state.dart +++ b/lib/src/features/about/bloc/about_state.dart @@ -13,9 +13,11 @@ final class AboutLoadedState extends AboutState { } final class AboutErrorState extends AboutState { - final String errorMessage; + final PlatformErrorCode errorCode; + final String? errorDescriptionMessage; AboutErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/about/views/about_page.dart b/lib/src/features/about/views/about_page.dart index 4e024545..d0d5b8dc 100644 --- a/lib/src/features/about/views/about_page.dart +++ b/lib/src/features/about/views/about_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/platform_error_code/platform_error_code_extension.dart'; import 'package:bookify/src/features/about/bloc/about_bloc.dart'; import 'package:bookify/src/features/about/views/widgets/about_loaded_state_widget.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; @@ -30,9 +31,12 @@ class _AboutPageState extends State { AboutLoadingState() => const CenterCircularProgressIndicator(), AboutLoadedState(appVersionModel: final appVersion) => AboutLoadedStateWidget(appVersionModel: appVersion), - AboutErrorState(:final errorMessage) => + AboutErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _refreshPage, ), }; diff --git a/lib/src/features/contacts_picker/bloc/contacts_picker_bloc.dart b/lib/src/features/contacts_picker/bloc/contacts_picker_bloc.dart index b3261d22..0ba01f39 100644 --- a/lib/src/features/contacts_picker/bloc/contacts_picker_bloc.dart +++ b/lib/src/features/contacts_picker/bloc/contacts_picker_bloc.dart @@ -1,5 +1,7 @@ +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/models/contact_model.dart'; import 'package:bookify/src/core/services/app_services/contacts_service/contacts_service.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'contacts_picker_event.dart'; @@ -10,7 +12,7 @@ class ContactsPickerBloc final ContactsService _contactsService; ContactsPickerBloc(this._contactsService) - : super(ContactsPickerLoadingState()) { + : super(ContactsPickerLoadingState()) { on(_gotContactsPicker); } @@ -26,25 +28,24 @@ class ContactsPickerBloc (a, b) => a.name.compareTo(b.name), ); - if (contacts == null) { - emit( - ContactsPickerErrorState( - errorMessage: 'Aconteceu um problema ao carregar os contatos.', - ), - ); - return; - } - - if (contacts.isEmpty) { + if (contacts == null || contacts.isEmpty) { emit(ContactsPickerEmptyState()); return; } emit(ContactsPickerLoadedState(contacts: contacts)); - } catch (e) { + } on PlatformException catch (e) { + emit( + ContactsPickerErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); + } on Exception catch (e) { emit( ContactsPickerErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: PlatformErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/contacts_picker/bloc/contacts_picker_state.dart b/lib/src/features/contacts_picker/bloc/contacts_picker_state.dart index b21dd75d..7cdc4e39 100644 --- a/lib/src/features/contacts_picker/bloc/contacts_picker_state.dart +++ b/lib/src/features/contacts_picker/bloc/contacts_picker_state.dart @@ -15,9 +15,11 @@ final class ContactsPickerLoadedState extends ContactsPickerState { } final class ContactsPickerErrorState extends ContactsPickerState { - final String errorMessage; + final PlatformErrorCode errorCode; + final String? errorDescriptionMessage; ContactsPickerErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/contacts_picker/views/contacts_picker_page.dart b/lib/src/features/contacts_picker/views/contacts_picker_page.dart index d8bd3249..39887fb2 100644 --- a/lib/src/features/contacts_picker/views/contacts_picker_page.dart +++ b/lib/src/features/contacts_picker/views/contacts_picker_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/platform_error_code/platform_error_code_extension.dart'; import 'package:bookify/src/features/contacts_picker/bloc/contacts_picker_bloc.dart'; import 'package:bookify/src/features/contacts_picker/views/widgets/contacts_picker_loaded_state_widget.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; @@ -36,20 +37,24 @@ class _ContactsPickerPageState extends State { return switch (state) { ContactsPickerLoadingState() => const CenterCircularProgressIndicator(), ContactsPickerEmptyState() => Center( - child: InfoItemStateWidget.withNotFoundState( - message: 'no-contacts-found'.i18n(), - onPressed: _onRefresh, - ), + child: InfoItemStateWidget.withNotFoundState( + message: 'no-contacts-found'.i18n(), + onPressed: _onRefresh, ), + ), ContactsPickerLoadedState(:final contacts) => ContactsPickerLoadedStateWidget( key: const Key('ContactsPickerLoadedStateWidget'), contacts: contacts, onSelectedContact: (contactDto) => Navigator.pop(context, contactDto), ), - ContactsPickerErrorState(:final errorMessage) => Center( + ContactsPickerErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => + Center( child: InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _onRefresh, ), ), diff --git a/lib/src/features/loan/bloc/loan_bloc.dart b/lib/src/features/loan/bloc/loan_bloc.dart index 37cfca2a..4d4af935 100644 --- a/lib/src/features/loan/bloc/loan_bloc.dart +++ b/lib/src/features/loan/bloc/loan_bloc.dart @@ -1,5 +1,6 @@ import 'package:bookify/src/core/dtos/loan_dto.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/models/loan_model.dart'; import 'package:bookify/src/core/services/app_services/contacts_service/contacts_service.dart'; import 'package:bookify/src/core/services/book_service/book_service.dart'; @@ -46,6 +47,13 @@ class LoanBloc extends Bloc { errorDescriptionMessage: e.descriptionMessage, ), ); + } on PlatformException catch (e) { + emit( + LoanErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( LoanErrorState( @@ -80,6 +88,13 @@ class LoanBloc extends Bloc { errorDescriptionMessage: e.descriptionMessage, ), ); + } on PlatformException catch (e) { + emit( + LoanErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( LoanErrorState( diff --git a/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart b/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart index 889facb3..e4b4947c 100644 --- a/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart +++ b/lib/src/features/loan_detail/bloc/loan_detail_bloc.dart @@ -1,5 +1,6 @@ import 'package:bookify/src/core/dtos/loan_dto.dart'; import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/services/app_services/contacts_service/contacts_service.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; @@ -57,6 +58,13 @@ class LoanDetailBloc extends Bloc { errorDescriptionMessage: e.descriptionMessage, ), ); + } on PlatformException catch (e) { + emit( + LoanDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } catch (e) { emit( LoanDetailErrorState( @@ -110,6 +118,13 @@ class LoanDetailBloc extends Bloc { errorDescriptionMessage: e.descriptionMessage, ), ); + } on PlatformException catch (e) { + emit( + LoanDetailErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } catch (e) { emit( LoanDetailErrorState( diff --git a/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart b/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart index 54e4d951..4dc898be 100644 --- a/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart +++ b/lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart @@ -1,4 +1,5 @@ import 'package:bookify/src/core/errors/local_database_exception/local_database_exception.dart'; +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/models/loan_model.dart'; import 'package:bookify/src/core/models/custom_notification_model.dart'; @@ -85,6 +86,13 @@ class LoanInsertionBloc extends Bloc { errorDescriptionMessage: e.descriptionMessage, ), ); + } on PlatformException catch (e) { + emit( + LoanInsertionErrorState( + errorCode: LocalDatabaseErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( LoanInsertionErrorState( diff --git a/lib/src/features/notifications/bloc/notifications_bloc.dart b/lib/src/features/notifications/bloc/notifications_bloc.dart index 10ef1b6d..9222f8a4 100644 --- a/lib/src/features/notifications/bloc/notifications_bloc.dart +++ b/lib/src/features/notifications/bloc/notifications_bloc.dart @@ -1,5 +1,7 @@ +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/models/custom_notification_model.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'notifications_event.dart'; @@ -33,10 +35,19 @@ class NotificationsBloc extends Bloc { notifications: notifications, ), ); + } on PlatformException catch (e) { + emit( + NotificationErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( NotificationErrorState( - errorMessage: 'Erro inesperado: ${e.toString()}'), + errorCode: PlatformErrorCode.unknown, + errorDescriptionMessage: e.toString(), + ), ); } } diff --git a/lib/src/features/notifications/bloc/notifications_state.dart b/lib/src/features/notifications/bloc/notifications_state.dart index 5e143ab8..6da08d2f 100644 --- a/lib/src/features/notifications/bloc/notifications_state.dart +++ b/lib/src/features/notifications/bloc/notifications_state.dart @@ -15,9 +15,11 @@ final class NotificationsLoadedState extends NotificationsState { } final class NotificationErrorState extends NotificationsState { - final String errorMessage; + final PlatformErrorCode errorCode; + final String? errorDescriptionMessage; NotificationErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/notifications/views/notifications_page.dart b/lib/src/features/notifications/views/notifications_page.dart index 229adc92..277cfcbb 100644 --- a/lib/src/features/notifications/views/notifications_page.dart +++ b/lib/src/features/notifications/views/notifications_page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/platform_error_code/platform_error_code_extension.dart'; import 'package:bookify/src/features/notifications/bloc/notifications_bloc.dart'; import 'package:bookify/src/features/notifications/views/widgets/notifications_loaded_state_widget.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; @@ -35,21 +36,24 @@ class _NotificationsPageState extends State { return switch (state) { NotificationsLoadingState() => const CenterCircularProgressIndicator(), NotificationEmptyState() => Center( - child: Padding( - padding: EdgeInsets.all(16.0), - child: Text( - 'no-notifications-found'.i18n(), - textAlign: TextAlign.center, - ), + child: Padding( + padding: EdgeInsets.all(16.0), + child: Text( + 'no-notifications-found'.i18n(), + textAlign: TextAlign.center, ), ), + ), NotificationsLoadedState(:final notifications) => NotificationsLoadedStateWidget( notifications: notifications, ), - NotificationErrorState(:final errorMessage) => + NotificationErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _onRefreshPage, ), }; diff --git a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart index d6c2323d..56757e56 100644 --- a/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart +++ b/lib/src/features/programming_reading/bloc/programming_reading_bloc.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; @@ -102,6 +103,13 @@ class ProgrammingReadingBloc errorDescriptionMessage: e.descriptionMessage, ), ); + } on PlatformException catch (e) { + emit( + ProgrammingReadingErrorState( + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( ProgrammingReadingErrorState( @@ -131,6 +139,13 @@ class ProgrammingReadingBloc errorDescriptionMessage: e.descriptionMessage, ), ); + } on PlatformException catch (e) { + emit( + ProgrammingReadingErrorState( + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( ProgrammingReadingErrorState( diff --git a/lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart b/lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart index 13c07fa4..802bdce5 100644 --- a/lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart +++ b/lib/src/shared/cubits/user_notification_cubit/user_notification_cubit.dart @@ -1,4 +1,6 @@ +import 'package:bookify/src/core/errors/platform_exception/platform_exception.dart'; import 'package:bookify/src/core/services/app_services/notifications_service/notifications_service.dart'; +import 'package:bookify/src/shared/enums/platform_error_code.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -18,10 +20,18 @@ class UserNotificationCubit extends Cubit { await _notificationsService.checkForNotifications(); emit(UserNotificationLoadedState()); + } on PlatformException catch (e) { + emit( + UserNotificationErrorState( + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, + ), + ); } on Exception catch (e) { emit( UserNotificationErrorState( - errorMessage: 'Erro ao inicializar as notificações: $e', + errorCode: PlatformErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart b/lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart index c4294fb0..8ca85705 100644 --- a/lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart +++ b/lib/src/shared/cubits/user_notification_cubit/user_notification_state.dart @@ -8,9 +8,11 @@ final class UserNotificationLoadingState extends UserNotificationState {} final class UserNotificationLoadedState extends UserNotificationState {} final class UserNotificationErrorState extends UserNotificationState { - final String errorMessage; + final PlatformErrorCode errorCode; + final String? errorDescriptionMessage; UserNotificationErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/shared/enums/platform_error_code.dart b/lib/src/shared/enums/platform_error_code.dart new file mode 100644 index 00000000..8afe7a7c --- /dev/null +++ b/lib/src/shared/enums/platform_error_code.dart @@ -0,0 +1,6 @@ +enum PlatformErrorCode { + permissionDenied, + permissionPermanentlyDenied, + unsupported, + unknown, +} diff --git a/pubspec.yaml b/pubspec.yaml index e4b30fcb..820372f7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.10 +version: 2.11.11 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/features/contacts_picker/bloc/contacts_picker_bloc_test.dart b/test/src/features/contacts_picker/bloc/contacts_picker_bloc_test.dart index 79a6f05d..058133ae 100644 --- a/test/src/features/contacts_picker/bloc/contacts_picker_bloc_test.dart +++ b/test/src/features/contacts_picker/bloc/contacts_picker_bloc_test.dart @@ -52,7 +52,7 @@ void main() { verify: (_) => verify(() => contactsService.getContacts()).called(1), expect: () => [ isA(), - isA(), + isA(), ], ); From cf6a5cc703d512dc8af71ea9b8b600f96dd1e2ed Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Tue, 26 May 2026 15:14:47 -0300 Subject: [PATCH 16/19] Refactor error code handling by restructuring error code extensions - Removed old error code extension files for auth, local database, platform, REST client, and storage errors. - Created new error code extension files under a unified error code directory structure. - Updated import paths in various feature files to reflect the new error code structure. - Modified error handling in the readings timer bloc to utilize the new error code extensions for better localization support. - Updated tests to check for localized error messages instead of hardcoded strings. - Bumped version number to 2.11.12 in pubspec.yaml. --- assets/lang/en_US.json | 4 - assets/lang/it_IT.json | 6 +- assets/lang/pt_BR.json | 6 +- coverage/lcov.info | 238 +++++++++--------- .../auth_error_code_extension.dart | 0 .../local_database_error_code_extension.dart | 2 +- .../platform_error_code_extension.dart | 0 .../rest_client_error_code_extension.dart | 0 .../storage_error_code_extension.dart | 2 - .../launcher_service/launcher_service.dart | 21 +- lib/src/features/about/views/about_page.dart | 2 +- lib/src/features/auth/views/auth_page.dart | 2 +- .../book_detail/views/book_detail_page.dart | 2 +- .../widgets/book_pages_reading_time.dart | 2 +- .../views/book_on_bookcase_detail_page.dart | 2 +- .../bookcase/views/bookcase_page.dart | 2 +- .../views/bookcase_books_insertion_page.dart | 2 +- .../views/bookcase_detail_page.dart | 2 +- .../views/bookcase_insertion_page.dart | 2 +- .../views/book_on_bookcase_widget.dart | 2 +- .../views/bookcase_picker_widget.dart | 2 +- .../views/separate_books_picker_widget.dart | 2 +- .../views/contacts_picker_page.dart | 2 +- lib/src/features/home/views/home_page.dart | 2 +- lib/src/features/loan/views/loan_page.dart | 2 +- .../loan_detail/views/loan_detail_page.dart | 2 +- .../views/loan_insertion_page.dart | 2 +- .../my_books/views/my_books_page.dart | 2 +- .../views/notifications_page.dart | 2 +- .../features/profile/views/profile_page.dart | 2 +- .../views/programming_reading_page.dart | 2 +- .../views/reading_page_timer_page.dart | 2 +- .../readings/views/readings_page.dart | 2 +- .../views/readings_detail_page.dart | 2 +- .../views/readings_insertion_page.dart | 2 +- .../bloc/readings_timer_bloc.dart | 9 +- .../bloc/readings_timer_state.dart | 6 +- .../views/readings_timer.page.dart | 21 +- .../views/widgets/theme_settings.dart | 2 +- lib/src/shared/enums/storage_error_code.dart | 2 - pubspec.yaml | 2 +- .../views/book_detail_page_test.dart | 4 +- .../bookcase/views/bookcase_page_test.dart | 2 +- .../views/bookcase_insertion_page_test.dart | 2 +- 44 files changed, 181 insertions(+), 198 deletions(-) rename lib/src/core/helpers/{ => error_code}/auth_error_code/auth_error_code_extension.dart (100%) rename lib/src/core/helpers/{ => error_code}/local_database_error_code/local_database_error_code_extension.dart (93%) rename lib/src/core/helpers/{ => error_code}/platform_error_code/platform_error_code_extension.dart (100%) rename lib/src/core/helpers/{ => error_code}/rest_client_error_code/rest_client_error_code_extension.dart (100%) rename lib/src/core/helpers/{ => error_code}/storage_error_code/storage_error_code_extension.dart (81%) diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index 0724f99c..3d462798 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -127,7 +127,6 @@ "field-cannot-be-empty-error": "This field cannot be empty", "invalid-ISBN-format-error": "Invalid ISBN format", "camera-error": "An error occurred with the camera: %s", - "unknown-error": "unknown error", "enter-loaned-title-label": "Enter the title of the loaned book.", "enter-title-your-book-label": "Enter the title of your book.", "enter-bookcase-name-label": "Enter the name of the bookcase.", @@ -268,8 +267,6 @@ "error-auth-network-request-failed": "Connection lost. Check your internet connection and try again: %s", "error-auth-internal-error": "Something went wrong. If the problem persists, please contact support: %s", "error-storage-invalid-value": "Data storage issue detected. Try logging out and logging back in: %s", - "error-storage-data-loss": "Error saving your data. Try syncing again or contact support if the issue continues: %s", - "error-storage-not-found": "Your data could not be found. Try logging in again with your credentials: %s", "error-storage-write-failed": "Unable to save your changes. Check your storage space and try again: %s", "error-storage-read-failed": "Unable to load your data. Check your internet connection and try again: %s", "error-local-database-invalid-data": "The data provided is not valid. %s", @@ -277,7 +274,6 @@ "error-local-database-open-failed": "Could not open the database. %s", "error-local-database-operation-failed": "Database operation failed during read, write, or update. %s", "error-local-database-unique-constraint": "This record already exists in the database. %s", - "error-local-database-unknown": "Unknown error in the database. %s", "notification-channel-loan-description": "Channel that notifies when it's time to receive your loaned book.", "notification-channel-loan-label": "Loans", "notification-channel-read-description": "Channel that notifies when it's time for reading.", diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index 67d79c3a..2a2ec9b2 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -92,7 +92,7 @@ "no-books-registered": "Nessun libro registrato. Torna alla pagina iniziale per registrare.", "enter-title-label": "Inserisci il Titolo", "enter-author-label": "Inserisci l'Autore", - "enter-category-label": "Inserisci la Categoria (in Inglese)", + "enter-category-label": "Inserisci la Categoria (Inglese)", "enter-publisher-label": "Inserisci l'Editore", "enter-isbn-label": "Inserisci l'ISBN", "delete-text-typed-tooltip": "Cancella il testo digitato.", @@ -127,7 +127,6 @@ "field-cannot-be-empty-error": "Questo campo non può essere vuoto", "invalid-ISBN-format-error": "Formato del ISBN non valido", "camera-error": "Si è verificato un errore con la fotocamera: %s", - "unknown-error": "errore sconosciuto", "enter-loaned-title-label": "Inserisci il titolo del libro in prestito.", "enter-title-your-book-label": "Inserisci il titolo del tuo libro.", "enter-bookcase-name-label": "Inserisci il nome dello scaffale.", @@ -268,8 +267,6 @@ "error-auth-network-request-failed": "Connessione persa. Verifica la tua connessione internet e riprova: %s", "error-auth-internal-error": "Qualcosa è andato storto. Se il problema persiste, contatta l'assistenza: %s", "error-storage-invalid-value": "Problema rilevato nel salvataggio dei dati. Prova a disconnetterti e riconnetterti: %s", - "error-storage-data-loss": "Errore durante il salvataggio dei dati. Prova a sincronizzare di nuovo o contatta l'assistenza se il problema persiste: %s", - "error-storage-not-found": "I tuoi dati non sono stati trovati. Prova ad accedere di nuovo con le tue credenziali: %s", "error-storage-write-failed": "Impossibile salvare le tue modifiche. Verifica lo spazio di archiviazione e riprova: %s", "error-storage-read-failed": "Impossibile caricare i tuoi dati. Verifica la tua connessione internet e riprova: %s", "error-local-database-invalid-data": "I dati forniti non sono validi. %s", @@ -277,7 +274,6 @@ "error-local-database-open-failed": "Impossibile aprire il database. %s", "error-local-database-operation-failed": "Operazione del database fallita durante lettura, scrittura o aggiornamento. %s", "error-local-database-unique-constraint": "Questo record esiste già nel database. %s", - "error-local-database-unknown": "Errore sconosciuto del database. %s", "notification-channel-loan-description": "Canale che notifica quando è il momento di ricevere il libro prestato.", "notification-channel-loan-label": "Prestiti", "notification-channel-read-description": "Canale che notifica quando è il momento della lettura.", diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index baeb0fdc..97beb612 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -92,7 +92,7 @@ "no-books-registered": "Nenhum livro cadastrado. Volte à página início para cadastrar.", "enter-title-label": "Digite o Título", "enter-author-label": "Digite o Autor", - "enter-category-label": "Digite o Gênero (em Inglês)", + "enter-category-label": "Digite o Gênero (Inglês)", "enter-publisher-label": "Digite a Editora", "enter-isbn-label": "Digite o ISBN", "delete-text-typed-tooltip": "Apagar o texto digitado.", @@ -127,7 +127,6 @@ "field-cannot-be-empty-error": "Esse campo não pode estar vazio", "invalid-ISBN-format-error": "Formato do ISBN inválido", "camera-error": "Ocorreu algum erro com a câmera: %s", - "unknown-error": "erro desconhecido", "enter-loaned-title-label": "Digite o título do livro emprestado.", "enter-title-your-book-label": "Digite o título do seu livro.", "enter-bookcase-name-label": "Digite o nome da estante.", @@ -268,8 +267,6 @@ "error-auth-network-request-failed": "Conexão perdida. Verifique sua conexão com a internet e tente novamente: %s", "error-auth-internal-error": "Algo deu errado. Se o problema persistir, entre em contato com o suporte: %s", "error-storage-invalid-value": "Problema detectado ao salvar dados. Tente fazer logout e depois login novamente: %s", - "error-storage-data-loss": "Erro ao salvar seus dados. Tente sincronizar novamente ou entre em contato com o suporte se o problema persistir: %s", - "error-storage-not-found": "Seus dados não foram encontrados. Tente fazer login novamente com suas credenciais: %s", "error-storage-write-failed": "Impossível salvar suas alterações. Verifique o espaço de armazenamento e tente novamente: %s", "error-storage-read-failed": "Impossível carregar seus dados. Verifique sua conexão com a internet e tente novamente: %s", "error-local-database-invalid-data": "Os dados fornecidos não são válidos. %s", @@ -277,7 +274,6 @@ "error-local-database-open-failed": "Não foi possível abrir o banco de dados. %s", "error-local-database-operation-failed": "Operação do banco de dados falhou durante leitura, escrita ou atualização. %s", "error-local-database-unique-constraint": "Este registro já existe no banco de dados. %s", - "error-local-database-unknown": "Erro desconhecido no banco de dados. %s", "notification-channel-loan-description": "Canal que notifica quando é o dia de receber o livro emprestado.", "notification-channel-loan-label": "Empréstimos", "notification-channel-read-description": "Canal que notifica que está na hora da leitura.", diff --git a/coverage/lcov.info b/coverage/lcov.info index 92b2a9b3..32d0069e 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -220,10 +220,10 @@ LH:8 end_of_record SF:lib/src/core/errors/storage_exception/storage_exception.dart DA:7,4 -DA:12,1 -DA:13,3 +DA:12,0 +DA:13,0 LF:3 -LH:3 +LH:1 end_of_record SF:lib/src/core/models/user_model.dart DA:9,2 @@ -1460,6 +1460,32 @@ DA:44,2 LF:24 LH:23 end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +DA:11,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:22,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 +end_of_record SF:lib/src/shared/blocs/book_bloc/book_event.dart DA:10,1 DA:18,1 @@ -1577,32 +1603,6 @@ DA:227,0 LF:98 LH:75 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 -DA:22,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:27,1 -DA:28,1 -DA:29,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:16 -LH:16 -end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart DA:12,1 DA:14,2 @@ -1930,7 +1930,7 @@ DA:20,1 LF:2 LH:2 end_of_record -SF:lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart +SF:lib/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart DA:5,3 DA:9,3 DA:10,0 @@ -1946,34 +1946,31 @@ DA:30,0 LF:12 LH:6 end_of_record -SF:lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart +SF:lib/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart DA:5,0 DA:9,0 DA:12,0 -DA:13,0 -DA:14,0 -DA:17,0 -DA:20,0 -LF:7 +DA:15,0 +DA:18,0 +LF:5 LH:0 end_of_record SF:lib/src/core/services/app_services/launcher_service/launcher_service.dart DA:6,0 DA:8,0 DA:10,0 -DA:11,0 -DA:28,0 +DA:21,0 +DA:24,0 +DA:26,0 DA:31,0 DA:33,0 +DA:34,0 +DA:37,0 DA:38,0 -DA:40,0 -DA:41,0 -DA:44,0 -DA:45,0 -DA:62,0 -DA:65,0 -DA:67,0 -LF:15 +DA:55,0 +DA:58,0 +DA:60,0 +LF:14 LH:0 end_of_record SF:lib/src/core/services/app_services/show_dialog_service/show_dialog_service.dart @@ -2269,7 +2266,7 @@ LF:27 LH:14 end_of_record SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart -DA:6,2 +DA:6,1 DA:11,4 DA:13,4 DA:14,4 @@ -2471,7 +2468,7 @@ LF:2 LH:2 end_of_record SF:lib/src/core/dtos/bookcase_dto.dart -DA:7,3 +DA:7,2 DA:12,0 DA:16,0 DA:17,0 @@ -2486,6 +2483,10 @@ DA:35,0 LF:12 LH:3 end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 DA:10,0 @@ -2874,9 +2875,9 @@ DA:207,1 DA:209,1 DA:211,1 DA:215,2 -DA:216,1 -DA:217,1 -DA:218,2 +DA:216,0 +DA:217,0 +DA:218,0 DA:226,1 DA:228,2 DA:231,1 @@ -2938,7 +2939,7 @@ DA:338,1 DA:340,1 DA:341,1 LF:135 -LH:119 +LH:116 end_of_record SF:lib/src/shared/widgets/item_state_widget/item_empty_state_widget/item_empty_widget.dart DA:7,1 @@ -3644,10 +3645,6 @@ DA:7,0 LF:1 LH:0 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 -end_of_record SF:lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_event.dart DA:8,1 LF:1 @@ -3981,6 +3978,55 @@ SF:lib/src/features/contacts_picker/bloc/contacts_picker_event.dart LF:0 LH:0 end_of_record +SF:lib/src/features/my_books/bloc/my_books_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_bloc.dart +DA:14,3 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,2 +DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,1 +DA:63,2 +DA:67,2 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:79,1 +LF:34 +LH:34 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:20,1 DA:24,2 @@ -4036,55 +4082,6 @@ DA:13,1 LF:1 LH:1 end_of_record -SF:lib/src/features/my_books/bloc/my_books_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_bloc.dart -DA:14,3 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,2 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:45,1 -DA:51,1 -DA:56,2 -DA:58,2 -DA:59,1 -DA:62,1 -DA:63,2 -DA:67,2 -DA:68,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:72,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:79,1 -LF:34 -LH:34 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/features/home/views/home_page.dart DA:11,1 DA:13,1 @@ -4148,7 +4145,7 @@ DA:124,1 LF:59 LH:41 end_of_record -SF:lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart +SF:lib/src/core/helpers/error_code/rest_client_error_code/rest_client_error_code_extension.dart DA:5,1 DA:9,1 DA:10,0 @@ -4696,31 +4693,32 @@ LH:32 end_of_record SF:lib/src/features/readings_timer/bloc/readings_timer_state.dart DA:12,1 -DA:20,1 +DA:21,1 LF:2 LH:2 end_of_record SF:lib/src/features/readings_timer/bloc/readings_timer_bloc.dart -DA:11,1 -DA:12,2 +DA:12,1 DA:13,2 -DA:16,1 -DA:21,2 -DA:23,2 -DA:26,2 -DA:30,1 -DA:32,1 +DA:14,2 +DA:17,1 +DA:22,2 +DA:24,2 +DA:27,2 +DA:31,1 DA:33,1 -DA:37,1 +DA:34,1 DA:38,1 DA:39,1 DA:40,1 -DA:43,1 -DA:44,1 +DA:41,1 +DA:42,1 DA:45,1 DA:46,1 -LF:18 -LH:18 +DA:47,1 +DA:49,1 +LF:19 +LH:19 end_of_record SF:lib/src/features/qr_code_scanner/views/qr_code_scanner_page.dart DA:13,1 diff --git a/lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart b/lib/src/core/helpers/error_code/auth_error_code/auth_error_code_extension.dart similarity index 100% rename from lib/src/core/helpers/auth_error_code/auth_error_code_extension.dart rename to lib/src/core/helpers/error_code/auth_error_code/auth_error_code_extension.dart diff --git a/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart b/lib/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart similarity index 93% rename from lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart rename to lib/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart index a5cce1e8..1beff5db 100644 --- a/lib/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart +++ b/lib/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart @@ -23,7 +23,7 @@ extension LocalDatabaseErrorCodeExtension on LocalDatabaseErrorCode { 'error-local-database-invalid-data'.i18n([ messageArg, ]), - LocalDatabaseErrorCode.unknown => 'error-local-database-unknown'.i18n([ + LocalDatabaseErrorCode.unknown => 'error-unknown'.i18n([ messageArg, ]), LocalDatabaseErrorCode.operationFailed => diff --git a/lib/src/core/helpers/platform_error_code/platform_error_code_extension.dart b/lib/src/core/helpers/error_code/platform_error_code/platform_error_code_extension.dart similarity index 100% rename from lib/src/core/helpers/platform_error_code/platform_error_code_extension.dart rename to lib/src/core/helpers/error_code/platform_error_code/platform_error_code_extension.dart diff --git a/lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart b/lib/src/core/helpers/error_code/rest_client_error_code/rest_client_error_code_extension.dart similarity index 100% rename from lib/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart rename to lib/src/core/helpers/error_code/rest_client_error_code/rest_client_error_code_extension.dart diff --git a/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart b/lib/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart similarity index 81% rename from lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart rename to lib/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart index ffd6fa16..8271a78d 100644 --- a/lib/src/core/helpers/storage_error_code/storage_error_code_extension.dart +++ b/lib/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart @@ -9,8 +9,6 @@ extension StorageErrorCodeExtension on StorageErrorCode { StorageErrorCode.invalidValue => 'error-storage-invalid-value'.i18n([ messageArg, ]), - StorageErrorCode.dataLoss => 'error-storage-data-loss'.i18n([messageArg]), - StorageErrorCode.notFound => 'error-storage-not-found'.i18n([messageArg]), StorageErrorCode.writeFailed => 'error-storage-write-failed'.i18n([ messageArg, ]), diff --git a/lib/src/core/services/app_services/launcher_service/launcher_service.dart b/lib/src/core/services/app_services/launcher_service/launcher_service.dart index ec9ca7eb..d620210f 100644 --- a/lib/src/core/services/app_services/launcher_service/launcher_service.dart +++ b/lib/src/core/services/app_services/launcher_service/launcher_service.dart @@ -7,22 +7,15 @@ class LauncherService { try { final uri = Uri.parse(url); - if (await canLaunchUrl(uri)) { - final urlIsLaunched = await launchUrl( - uri, - mode: LaunchMode.externalApplication, - ); + final urlIsLaunched = await launchUrl( + uri, + mode: LaunchMode.externalApplication, + ); - if (!urlIsLaunched) { - throw const PlatformException( - PlatformErrorCode.unknown, - descriptionMessage: 'Impossible to launch the URL', - ); - } - } else { + if (!urlIsLaunched) { throw const PlatformException( - PlatformErrorCode.unsupported, - descriptionMessage: 'The URL scheme is not supported', + PlatformErrorCode.unknown, + descriptionMessage: 'Impossible to launch the URL', ); } } on PlatformException { diff --git a/lib/src/features/about/views/about_page.dart b/lib/src/features/about/views/about_page.dart index d0d5b8dc..71e85c18 100644 --- a/lib/src/features/about/views/about_page.dart +++ b/lib/src/features/about/views/about_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/platform_error_code/platform_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/platform_error_code/platform_error_code_extension.dart'; import 'package:bookify/src/features/about/bloc/about_bloc.dart'; import 'package:bookify/src/features/about/views/widgets/about_loaded_state_widget.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; diff --git a/lib/src/features/auth/views/auth_page.dart b/lib/src/features/auth/views/auth_page.dart index aa934f6c..af2fb2f8 100644 --- a/lib/src/features/auth/views/auth_page.dart +++ b/lib/src/features/auth/views/auth_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/auth_error_code/auth_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/auth_error_code/auth_error_code_extension.dart'; import 'package:bookify/src/features/auth/bloc/auth_bloc.dart'; import 'package:bookify/src/features/auth/widgets/platform_sign_in_buttons.dart'; import 'package:bookify/src/features/auth/widgets/terms_information.dart'; diff --git a/lib/src/features/book_detail/views/book_detail_page.dart b/lib/src/features/book_detail/views/book_detail_page.dart index dae06035..757ab50b 100644 --- a/lib/src/features/book_detail/views/book_detail_page.dart +++ b/lib/src/features/book_detail/views/book_detail_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/book_detail/bloc/book_detail_bloc.dart'; import 'package:bookify/src/core/models/book_model.dart'; import 'package:bookify/src/core/services/app_services/launcher_service/launcher_service.dart'; diff --git a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart index 0238fae6..690c56b8 100644 --- a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart +++ b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/widgets/book_pages_reading_time.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/storage_error_code/storage_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_bloc.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; import 'package:flutter/material.dart'; diff --git a/lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart b/lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart index 76566fb9..54cf07d5 100644 --- a/lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart +++ b/lib/src/features/book_on_bookcase_detail/views/book_on_bookcase_detail_page.dart @@ -1,5 +1,5 @@ import 'package:bookify/src/core/helpers/book_status/book_status_extension.dart'; -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/book_detail/views/book_detail_page.dart'; import 'package:bookify/src/features/book_on_bookcase_detail/bloc/book_on_bookcase_detail_bloc.dart'; import 'package:bookify/src/features/book_on_bookcase_detail/views/widgets/widgets.dart'; diff --git a/lib/src/features/bookcase/views/bookcase_page.dart b/lib/src/features/bookcase/views/bookcase_page.dart index da5419d9..8286191f 100644 --- a/lib/src/features/bookcase/views/bookcase_page.dart +++ b/lib/src/features/bookcase/views/bookcase_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/bookcase/views/widgets/bookcase_loaded_state_widget/bookcase_loaded_state_widget.dart'; import 'package:bookify/src/features/bookcase_insertion/views/bookcase_insertion_page.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; diff --git a/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart b/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart index 905a2a09..f6898bd4 100644 --- a/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart +++ b/lib/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/bookcase_books_insertion/widgets/bookcase_books_insertion_loaded_state_widget/bookcase_books_insertion_loaded_state.dart'; import 'package:bookify/src/core/services/app_services/snackbar_service/snackbar_service.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; diff --git a/lib/src/features/bookcase_detail/views/bookcase_detail_page.dart b/lib/src/features/bookcase_detail/views/bookcase_detail_page.dart index c11a742d..09990401 100644 --- a/lib/src/features/bookcase_detail/views/bookcase_detail_page.dart +++ b/lib/src/features/bookcase_detail/views/bookcase_detail_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/bookcase_books_insertion/views/bookcase_books_insertion_page.dart'; import 'package:bookify/src/features/bookcase_detail/bloc/bookcase_detail_bloc.dart'; import 'package:bookify/src/features/bookcase_detail/widgets/widgets.dart'; diff --git a/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart b/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart index 6346a1bf..947907d8 100644 --- a/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart +++ b/lib/src/features/bookcase_insertion/views/bookcase_insertion_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/bookcase_insertion/bloc/bookcase_insertion_bloc.dart'; import 'package:bookify/src/core/helpers/textfield_unfocus/textfield_unfocus_extension.dart'; import 'package:bookify/src/core/models/bookcase_model.dart'; diff --git a/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/views/book_on_bookcase_widget.dart b/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/views/book_on_bookcase_widget.dart index 30b8bee6..96038346 100644 --- a/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/views/book_on_bookcase_widget.dart +++ b/lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/views/book_on_bookcase_widget.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_bloc.dart'; import 'package:bookify/src/features/books_picker/views/widgets/book_selector_widget/book_selector_widget.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; diff --git a/lib/src/features/books_picker/views/widgets/bookcase_picker/views/bookcase_picker_widget.dart b/lib/src/features/books_picker/views/widgets/bookcase_picker/views/bookcase_picker_widget.dart index 34706a22..5c8f122c 100644 --- a/lib/src/features/books_picker/views/widgets/bookcase_picker/views/bookcase_picker_widget.dart +++ b/lib/src/features/books_picker/views/widgets/bookcase_picker/views/bookcase_picker_widget.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart'; import 'package:bookify/src/features/books_picker/views/widgets/bookcase_picker/views/widgets/bookcase_picker_loaded_state_widget/bookcase_picker_loaded_state_widget.dart'; import 'package:bookify/src/core/models/book_model.dart'; diff --git a/lib/src/features/books_picker/views/widgets/separate_books_picker/views/separate_books_picker_widget.dart b/lib/src/features/books_picker/views/widgets/separate_books_picker/views/separate_books_picker_widget.dart index 0e6fd72a..02e60588 100644 --- a/lib/src/features/books_picker/views/widgets/separate_books_picker/views/separate_books_picker_widget.dart +++ b/lib/src/features/books_picker/views/widgets/separate_books_picker/views/separate_books_picker_widget.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/widgets/book_selector_widget/book_selector_widget.dart'; import 'package:bookify/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_bloc.dart'; import 'package:bookify/src/core/models/book_model.dart'; diff --git a/lib/src/features/contacts_picker/views/contacts_picker_page.dart b/lib/src/features/contacts_picker/views/contacts_picker_page.dart index 39887fb2..275e45af 100644 --- a/lib/src/features/contacts_picker/views/contacts_picker_page.dart +++ b/lib/src/features/contacts_picker/views/contacts_picker_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/platform_error_code/platform_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/platform_error_code/platform_error_code_extension.dart'; import 'package:bookify/src/features/contacts_picker/bloc/contacts_picker_bloc.dart'; import 'package:bookify/src/features/contacts_picker/views/widgets/contacts_picker_loaded_state_widget.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; diff --git a/lib/src/features/home/views/home_page.dart b/lib/src/features/home/views/home_page.dart index b2237cc4..d89684c5 100644 --- a/lib/src/features/home/views/home_page.dart +++ b/lib/src/features/home/views/home_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/rest_client_error_code/rest_client_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/rest_client_error_code/rest_client_error_code_extension.dart'; import 'package:bookify/src/shared/blocs/book_bloc/book_bloc.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; import 'package:bookify/src/shared/widgets/item_state_widget/info_item_state_widget/info_item_state_widget.dart'; diff --git a/lib/src/features/loan/views/loan_page.dart b/lib/src/features/loan/views/loan_page.dart index bc031ba9..738a7675 100644 --- a/lib/src/features/loan/views/loan_page.dart +++ b/lib/src/features/loan/views/loan_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/loan/bloc/loan_bloc.dart'; import 'package:bookify/src/features/loan/widgets/loan_loaded_state_widget/loan_loaded_state_widget.dart'; import 'package:bookify/src/features/loan_insertion/views/loan_insertion_page.dart'; diff --git a/lib/src/features/loan_detail/views/loan_detail_page.dart b/lib/src/features/loan_detail/views/loan_detail_page.dart index f668ac46..2a08e039 100644 --- a/lib/src/features/loan_detail/views/loan_detail_page.dart +++ b/lib/src/features/loan_detail/views/loan_detail_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/loan_detail/bloc/loan_detail_bloc.dart'; import 'package:bookify/src/features/loan_detail/views/widgets/loan_detail_loaded_widget.dart'; import 'package:bookify/src/core/services/app_services/show_dialog_service/show_dialog_service.dart'; diff --git a/lib/src/features/loan_insertion/views/loan_insertion_page.dart b/lib/src/features/loan_insertion/views/loan_insertion_page.dart index 60e3f83f..b77b888d 100644 --- a/lib/src/features/loan_insertion/views/loan_insertion_page.dart +++ b/lib/src/features/loan_insertion/views/loan_insertion_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/books_picker_page.dart'; import 'package:bookify/src/features/contacts_picker/views/contacts_picker_page.dart'; import 'package:bookify/src/features/loan_insertion/bloc/loan_insertion_bloc.dart'; diff --git a/lib/src/features/my_books/views/my_books_page.dart b/lib/src/features/my_books/views/my_books_page.dart index 291bfd4f..9ac55d7a 100644 --- a/lib/src/features/my_books/views/my_books_page.dart +++ b/lib/src/features/my_books/views/my_books_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/book_detail/views/book_detail_page.dart'; import 'package:bookify/src/features/my_books/bloc/my_books_bloc.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; diff --git a/lib/src/features/notifications/views/notifications_page.dart b/lib/src/features/notifications/views/notifications_page.dart index 277cfcbb..aa2e7301 100644 --- a/lib/src/features/notifications/views/notifications_page.dart +++ b/lib/src/features/notifications/views/notifications_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/platform_error_code/platform_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/platform_error_code/platform_error_code_extension.dart'; import 'package:bookify/src/features/notifications/bloc/notifications_bloc.dart'; import 'package:bookify/src/features/notifications/views/widgets/notifications_loaded_state_widget.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; diff --git a/lib/src/features/profile/views/profile_page.dart b/lib/src/features/profile/views/profile_page.dart index eb9c693e..d9931c40 100644 --- a/lib/src/features/profile/views/profile_page.dart +++ b/lib/src/features/profile/views/profile_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/auth_error_code/auth_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/auth_error_code/auth_error_code_extension.dart'; import 'package:bookify/src/features/auth/views/auth_page.dart'; import 'package:bookify/src/features/profile/bloc/profile_bloc.dart'; import 'package:bookify/src/features/profile/views/widgets/profile_loaded_state_widget.dart'; diff --git a/lib/src/features/programming_reading/views/programming_reading_page.dart b/lib/src/features/programming_reading/views/programming_reading_page.dart index 0cf3de1b..103151a9 100644 --- a/lib/src/features/programming_reading/views/programming_reading_page.dart +++ b/lib/src/features/programming_reading/views/programming_reading_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/storage_error_code/storage_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/core/models/user_hour_time_model.dart'; import 'package:bookify/src/core/services/app_services/snackbar_service/snackbar_service.dart'; import 'package:bookify/src/features/programming_reading/bloc/programming_reading_bloc.dart'; diff --git a/lib/src/features/reading_page_timer/views/reading_page_timer_page.dart b/lib/src/features/reading_page_timer/views/reading_page_timer_page.dart index e4d1de6c..8b16776a 100644 --- a/lib/src/features/reading_page_timer/views/reading_page_timer_page.dart +++ b/lib/src/features/reading_page_timer/views/reading_page_timer_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/storage_error_code/storage_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/core/services/app_services/snackbar_service/snackbar_service.dart'; import 'package:bookify/src/features/reading_page_timer/bloc/reading_page_timer_bloc.dart'; import 'widgets/reading_page_timer_loaded_state_widget.dart'; diff --git a/lib/src/features/readings/views/readings_page.dart b/lib/src/features/readings/views/readings_page.dart index c88d5eea..b23a9fab 100644 --- a/lib/src/features/readings/views/readings_page.dart +++ b/lib/src/features/readings/views/readings_page.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/books_picker/views/books_picker_page.dart'; import 'package:bookify/src/features/readings/bloc/readings_bloc.dart'; import 'package:bookify/src/features/readings/views/widgets/readings_loaded_state_widget.dart'; diff --git a/lib/src/features/readings_detail/views/readings_detail_page.dart b/lib/src/features/readings_detail/views/readings_detail_page.dart index ec5eb43d..525a393b 100644 --- a/lib/src/features/readings_detail/views/readings_detail_page.dart +++ b/lib/src/features/readings_detail/views/readings_detail_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/readings_detail/bloc/readings_detail_bloc.dart'; import 'package:bookify/src/features/readings_timer/views/readings_timer.page.dart'; import 'package:bookify/src/core/dtos/reading_dto.dart'; diff --git a/lib/src/features/readings_insertion/views/readings_insertion_page.dart b/lib/src/features/readings_insertion/views/readings_insertion_page.dart index 3656a06b..60ba1d89 100644 --- a/lib/src/features/readings_insertion/views/readings_insertion_page.dart +++ b/lib/src/features/readings_insertion/views/readings_insertion_page.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/local_database_error_code/local_database_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart'; import 'package:bookify/src/features/readings_insertion/bloc/readings_insertion_bloc.dart'; import 'package:bookify/src/core/helpers/textfield_unfocus/textfield_unfocus_extension.dart'; import 'package:bookify/src/core/models/book_model.dart'; diff --git a/lib/src/features/readings_timer/bloc/readings_timer_bloc.dart b/lib/src/features/readings_timer/bloc/readings_timer_bloc.dart index 79c011b8..b1619517 100644 --- a/lib/src/features/readings_timer/bloc/readings_timer_bloc.dart +++ b/lib/src/features/readings_timer/bloc/readings_timer_bloc.dart @@ -1,5 +1,6 @@ import 'package:bookify/src/core/errors/storage_exception/storage_exception.dart'; import 'package:bookify/src/core/repositories/user_hour_time_repository/user_hour_time_repository.dart'; +import 'package:bookify/src/shared/enums/storage_error_code.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; part 'readings_timer_event.dart'; @@ -9,7 +10,7 @@ class ReadingsTimerBloc extends Bloc { final UserHourTimeRepository _userHourTimeRepository; ReadingsTimerBloc(this._userHourTimeRepository) - : super(ReadingsTimerLoadingState()) { + : super(ReadingsTimerLoadingState()) { on(_gotReadingsUserTimerEvent); } @@ -37,13 +38,15 @@ class ReadingsTimerBloc extends Bloc { } on StorageException catch (e) { emit( ReadingsTimerErrorState( - errorMessage: 'Erro ao buscar a hora do timer: $e', + errorCode: e.code, + errorDescriptionMessage: e.descriptionMessage, ), ); } on Exception catch (e) { emit( ReadingsTimerErrorState( - errorMessage: 'Erro inesperado: $e', + errorCode: StorageErrorCode.unknown, + errorDescriptionMessage: e.toString(), ), ); } diff --git a/lib/src/features/readings_timer/bloc/readings_timer_state.dart b/lib/src/features/readings_timer/bloc/readings_timer_state.dart index 04d2e4a0..b6aaea85 100644 --- a/lib/src/features/readings_timer/bloc/readings_timer_state.dart +++ b/lib/src/features/readings_timer/bloc/readings_timer_state.dart @@ -15,9 +15,11 @@ final class ReadingsTimerLoadedState extends ReadingsTimerState { } final class ReadingsTimerErrorState extends ReadingsTimerState { - final String errorMessage; + final StorageErrorCode errorCode; + final String? errorDescriptionMessage; ReadingsTimerErrorState({ - required this.errorMessage, + required this.errorCode, + this.errorDescriptionMessage, }); } diff --git a/lib/src/features/readings_timer/views/readings_timer.page.dart b/lib/src/features/readings_timer/views/readings_timer.page.dart index a8eb08f1..f33f6bb4 100644 --- a/lib/src/features/readings_timer/views/readings_timer.page.dart +++ b/lib/src/features/readings_timer/views/readings_timer.page.dart @@ -1,3 +1,4 @@ +import 'package:bookify/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/features/readings_timer/bloc/readings_timer_bloc.dart'; import 'package:bookify/src/core/dtos/reading_dto.dart'; import 'package:bookify/src/features/readings_timer/views/widgets/readings_timer_widget.dart'; @@ -39,16 +40,18 @@ class _ReadingsTimerPageState extends State { return switch (state) { ReadingsTimerLoadingState() => const CenterCircularProgressIndicator(), ReadingsTimerEmptyState() || - ReadingsTimerLoadedState() => - ReadingsTimerWidget( - readingDto: widget.readingDto, - timerDurationInSeconds: state is ReadingsTimerLoadedState - ? state.initialUserTimerInSeconds - : 300, - ), - ReadingsTimerErrorState(:final errorMessage) => + ReadingsTimerLoadedState() => ReadingsTimerWidget( + readingDto: widget.readingDto, + timerDurationInSeconds: state is ReadingsTimerLoadedState + ? state.initialUserTimerInSeconds + : 300, + ), + ReadingsTimerErrorState( + :final errorCode, + :final errorDescriptionMessage, + ) => InfoItemStateWidget.withErrorState( - message: errorMessage, + message: errorCode.toLocalizedMessage(errorDescriptionMessage), onPressed: _onRefreshPage, ), }; diff --git a/lib/src/features/settings/views/widgets/theme_settings.dart b/lib/src/features/settings/views/widgets/theme_settings.dart index 0c8bcd06..44bf6bce 100644 --- a/lib/src/features/settings/views/widgets/theme_settings.dart +++ b/lib/src/features/settings/views/widgets/theme_settings.dart @@ -1,4 +1,4 @@ -import 'package:bookify/src/core/helpers/storage_error_code/storage_error_code_extension.dart'; +import 'package:bookify/src/core/helpers/error_code/storage_error_code/storage_error_code_extension.dart'; import 'package:bookify/src/features/settings/views/widgets/settings_container.dart'; import 'package:bookify/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart'; import 'package:bookify/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart'; diff --git a/lib/src/shared/enums/storage_error_code.dart b/lib/src/shared/enums/storage_error_code.dart index fd6f0108..8662ddc3 100644 --- a/lib/src/shared/enums/storage_error_code.dart +++ b/lib/src/shared/enums/storage_error_code.dart @@ -1,7 +1,5 @@ enum StorageErrorCode { invalidValue, - dataLoss, - notFound, writeFailed, readFailed, unknown, diff --git a/pubspec.yaml b/pubspec.yaml index 820372f7..ed4c5472 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.11 +version: 2.11.12 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/features/book_detail/views/book_detail_page_test.dart b/test/src/features/book_detail/views/book_detail_page_test.dart index f778616a..dc51863e 100644 --- a/test/src/features/book_detail/views/book_detail_page_test.dart +++ b/test/src/features/book_detail/views/book_detail_page_test.dart @@ -291,7 +291,7 @@ void main() { expect( find.widgetWithText( SnackBar, - 'error-local-database-unknown', + 'error-unknown', ), findsOneWidget, ); @@ -401,7 +401,7 @@ void main() { expect( find.widgetWithText( SnackBar, - 'error-local-database-unknown', + 'error-unknown', ), findsOneWidget, ); diff --git a/test/src/features/bookcase/views/bookcase_page_test.dart b/test/src/features/bookcase/views/bookcase_page_test.dart index 2078376c..810a4f2c 100644 --- a/test/src/features/bookcase/views/bookcase_page_test.dart +++ b/test/src/features/bookcase/views/bookcase_page_test.dart @@ -110,7 +110,7 @@ void main() { ); expect( - find.text('error-local-database-unknown'), + find.text('error-unknown'), findsOne, ); }, diff --git a/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart b/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart index 23bd3bfa..44625204 100644 --- a/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart +++ b/test/src/features/bookcase_insertion/views/bookcase_insertion_page_test.dart @@ -134,7 +134,7 @@ void main() { await tester.pumpAndSettle(); expect(find.byType(SnackBar), findsOneWidget); - expect(find.text('error-local-database-unknown'), findsOneWidget); + expect(find.text('error-unknown'), findsOneWidget); await tester.pumpAndSettle(const Duration(seconds: 2)); expect(find.byType(BookcaseInsertionPage), findsNothing); From 30a283538044d3688f1d7f41b4ebe6faf648ced2 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Tue, 26 May 2026 15:21:55 -0300 Subject: [PATCH 17/19] Refactor: Use dart format command --- coverage/lcov.info | 960 +++++++++--------- .../core/adapters/google_books_adapter.dart | 22 +- .../core/database/local_database_impl.dart | 2 +- lib/src/core/models/book_model.dart | 2 +- lib/src/core/models/loan_model.dart | 2 +- lib/src/core/models/user_hour_time_model.dart | 11 +- .../book_categories_repository.dart | 5 +- .../book_on_case_repository.dart | 5 +- .../books_repository/books_repository.dart | 7 +- .../categories_repository.dart | 4 +- .../time_picker_dialog_service.dart | 5 +- .../auth_strategy/auth_strategy_factory.dart | 16 +- .../book_service/book_service_impl.dart | 38 +- .../bookcase_service_impl.dart | 35 +- .../storage_services/storage_services.dart | 2 +- .../input_formatter/isbn_input_formatter.dart | 14 +- .../core/utils/verifier/isbn_verifier.dart | 3 +- .../book_description_widget.dart | 7 +- .../bloc/book_pages_reading_time_state.dart | 2 +- .../book_detail/views/widgets/widgets.dart | 2 +- .../views/widgets/widgets.dart | 2 +- .../bookcase_loaded_state_widget.dart | 10 +- .../widgets/widgets.dart | 2 +- .../bookcase_description_widget.dart | 5 +- .../bookcase_detail_loaded_state_widget.dart | 18 +- .../bookcase_detail/widgets/widgets.dart | 2 +- .../bookcase_tab_view/views/pages/pages.dart | 2 +- .../books_picker/views/books_picker_page.dart | 2 +- .../book_selector_widget.dart | 85 +- .../bookcase_picker_loaded_state_widget.dart | 30 +- .../bloc/separate_books_picker_event.dart | 2 +- .../views/widgets/widgets.dart | 2 +- .../animated_search_bar.dart | 16 +- lib/src/features/home/widgets/widgets.dart | 2 +- .../loan_loaded_state_widget.dart | 22 +- .../loan/widgets/loan_widget/loan_widget.dart | 13 +- .../loan_detail/views/widgets/book_card.dart | 2 +- .../views/widgets/contact_card.dart | 2 +- .../widgets/loan_detail_loaded_widget.dart | 4 +- .../views/widgets/loan_is_late_widget.dart | 2 +- .../widgets/empty_book_button_widget.dart | 1 - .../widgets/empty_contact_button_widget.dart | 1 - .../my_books/bloc/my_books_event.dart | 2 +- lib/src/features/on_boarding/pages/pages.dart | 2 +- .../on_boarding/views/on_boarding_page.dart | 2 +- .../bloc/user_information_event.dart | 2 +- .../user_information_row.dart | 20 +- .../widgets/hour_time_selected_widget.dart | 12 +- ...programming_hour_loading_state_widget.dart | 35 +- .../reading_page_time_calculator_page.dart | 2 +- .../views/widgets/reading_widget.dart | 4 +- .../widgets/readings_loaded_state_widget.dart | 7 +- .../settings/views/widgets/widgets.dart | 2 +- .../time_picker/views/time_picker_page.dart | 96 +- .../views/widgets/time_picker_widget.dart | 2 +- .../constants/audios/bookify_audios.dart | 3 +- .../database_scripts/database_scripts.dart | 31 +- .../shared/constants/icons/bookify_icons.dart | 28 +- lib/src/shared/enums/sign_in_type.dart | 3 +- .../blocs/books_picker_bloc_providers.dart | 2 +- .../providers/blocs/loan_bloc_providers.dart | 2 +- .../user_information_bloc_providers.dart | 2 +- lib/src/shared/routes/routes.dart | 32 +- lib/src/shared/theme/app_theme.dart | 16 +- .../book_with_detail_widget.dart | 2 +- .../bookcase_widget/bookcase_widget.dart | 2 +- lib/src/shared/widgets/buttons/buttons.dart | 2 +- .../rectangle_floating_action_button.dart | 3 +- .../selected_item_row/selected_item_row.dart | 20 +- pubspec.yaml | 2 +- .../core/database/sqllite_database_test.dart | 194 ++-- .../locale_decimal_format_extension_test.dart | 14 +- test/src/core/models/book_model_test.dart | 18 +- .../features/about/bloc/about_bloc_test.dart | 5 +- .../bloc/notifications_bloc_test.dart | 36 +- .../views/qr_code_scanner_page_test.dart | 5 +- test/src/mocks/json/books_json_mock.dart | 180 ++-- 77 files changed, 1157 insertions(+), 1004 deletions(-) diff --git a/coverage/lcov.info b/coverage/lcov.info index 32d0069e..7dc362cb 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -281,15 +281,15 @@ LF:20 LH:16 end_of_record SF:lib/src/shared/enums/sign_in_type.dart -DA:7,1 -DA:9,1 +DA:6,1 +DA:8,1 +DA:9,0 DA:10,0 DA:11,0 -DA:12,0 -DA:16,1 -DA:18,1 +DA:15,1 +DA:17,1 +DA:18,0 DA:19,0 -DA:20,0 LF:9 LH:4 end_of_record @@ -830,30 +830,31 @@ DA:62,1 DA:63,1 DA:67,1 DA:68,1 -DA:70,2 -DA:71,1 +DA:69,1 +DA:70,1 DA:72,1 DA:73,1 DA:74,1 -DA:78,3 -DA:80,1 -DA:81,2 -DA:83,0 -DA:85,0 -DA:88,2 -DA:92,3 +DA:75,1 +DA:79,3 +DA:81,1 +DA:82,2 +DA:84,0 +DA:86,0 +DA:89,2 DA:93,3 DA:94,3 DA:95,3 DA:96,3 -DA:99,0 -DA:101,0 +DA:97,3 +DA:100,0 DA:102,0 DA:103,0 DA:104,0 DA:105,0 -LF:47 -LH:31 +DA:106,0 +LF:48 +LH:32 end_of_record SF:lib/src/core/repositories/user_hour_time_repository/user_hour_time_repository_impl.dart DA:11,1 @@ -978,77 +979,81 @@ DA:21,1 DA:33,1 DA:36,2 DA:38,3 -DA:40,3 -DA:41,3 -DA:48,1 -DA:53,1 -DA:56,2 -DA:58,1 -DA:60,1 -DA:66,1 -DA:71,1 -DA:74,2 -DA:76,3 -DA:78,3 -DA:79,3 -DA:86,1 -DA:91,1 -DA:94,2 -DA:96,1 -DA:98,2 -DA:99,2 -DA:100,1 -DA:103,2 -DA:104,2 -DA:107,2 -DA:108,1 -DA:113,1 -DA:115,2 -DA:116,2 -DA:117,1 -DA:120,2 -DA:122,0 -DA:125,2 -DA:126,1 -DA:132,1 -DA:137,1 -DA:141,2 -DA:143,1 -DA:148,1 -DA:151,2 -DA:153,1 -DA:158,1 -DA:161,2 -DA:163,1 -DA:168,1 -DA:174,2 -DA:179,1 -DA:184,1 -DA:190,2 -DA:195,1 -DA:200,1 -DA:203,2 -DA:205,1 -DA:210,1 -DA:213,2 -DA:215,1 -DA:220,1 -DA:222,2 -DA:225,3 +DA:39,1 +DA:40,2 +DA:42,3 +DA:49,1 +DA:54,1 +DA:57,2 +DA:59,1 +DA:61,1 +DA:67,1 +DA:72,1 +DA:75,2 +DA:77,3 +DA:78,1 +DA:79,2 +DA:81,3 +DA:88,1 +DA:93,1 +DA:96,2 +DA:98,1 +DA:100,2 +DA:101,2 +DA:102,1 +DA:105,2 +DA:106,2 +DA:109,2 +DA:110,1 +DA:115,1 +DA:117,2 +DA:118,2 +DA:119,1 +DA:122,2 +DA:123,0 +DA:128,2 +DA:129,1 +DA:135,1 +DA:140,1 +DA:143,2 +DA:147,1 +DA:152,1 +DA:155,2 +DA:157,1 +DA:162,1 +DA:165,2 +DA:167,1 +DA:172,1 +DA:178,2 +DA:183,1 +DA:188,1 +DA:194,2 +DA:199,1 +DA:204,1 +DA:207,2 +DA:209,1 +DA:214,1 +DA:217,2 +DA:219,1 +DA:224,1 +DA:225,1 DA:226,1 -DA:228,1 -DA:229,2 -DA:230,2 -DA:231,1 -DA:235,2 -DA:238,3 +DA:229,3 +DA:230,1 +DA:232,1 +DA:233,2 +DA:234,2 +DA:235,1 +DA:238,1 DA:239,1 -DA:241,1 -DA:242,2 -DA:243,2 -DA:244,1 -LF:73 -LH:72 +DA:242,3 +DA:243,1 +DA:245,1 +DA:246,2 +DA:247,2 +DA:248,1 +LF:77 +LH:76 end_of_record SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart DA:11,1 @@ -1059,38 +1064,39 @@ DA:27,1 DA:30,2 DA:34,1 DA:39,1 -DA:43,1 DA:44,1 -DA:46,1 -DA:51,1 -DA:56,2 -DA:61,1 -DA:66,1 -DA:69,2 -DA:73,1 -DA:78,1 -DA:82,2 -DA:84,1 -DA:89,1 -DA:93,2 -DA:95,1 +DA:45,1 +DA:47,1 +DA:52,1 +DA:58,1 +DA:59,1 +DA:64,1 +DA:69,1 +DA:72,2 +DA:76,1 +DA:81,1 +DA:84,2 +DA:88,1 +DA:93,1 +DA:96,2 DA:100,1 -DA:106,2 -DA:111,1 +DA:105,1 +DA:111,2 DA:116,1 -DA:119,2 DA:121,1 +DA:124,2 DA:126,1 -DA:129,2 -DA:134,1 +DA:131,1 +DA:134,2 DA:139,1 -DA:142,2 -DA:147,1 +DA:144,1 +DA:147,2 DA:152,1 -DA:155,2 -DA:160,1 -LF:38 -LH:38 +DA:157,1 +DA:160,2 +DA:165,1 +LF:39 +LH:39 end_of_record SF:lib/src/core/services/loan_services/loan_service_impl.dart DA:9,1 @@ -1373,28 +1379,28 @@ LH:0 end_of_record SF:lib/src/core/utils/verifier/isbn_verifier.dart DA:11,9 -DA:16,6 -DA:25,2 +DA:17,6 DA:26,2 -DA:28,6 -DA:29,4 -DA:31,4 -DA:43,2 -DA:44,4 -DA:48,2 -DA:49,1 -DA:50,2 -DA:51,1 +DA:27,2 +DA:29,6 +DA:30,4 +DA:32,4 +DA:44,2 +DA:45,4 +DA:49,2 +DA:50,1 +DA:51,2 DA:52,1 DA:53,1 -DA:56,2 -DA:69,2 -DA:70,4 -DA:74,4 -DA:75,2 -DA:76,4 -DA:78,2 -DA:81,4 +DA:54,1 +DA:57,2 +DA:70,2 +DA:71,4 +DA:75,4 +DA:76,2 +DA:77,4 +DA:79,2 +DA:82,4 LF:23 LH:23 end_of_record @@ -1436,77 +1442,48 @@ SF:lib/src/core/adapters/google_books_adapter.dart DA:12,1 DA:13,1 DA:14,0 -DA:16,1 -DA:17,3 -DA:18,1 +DA:16,5 +DA:21,1 +DA:22,1 DA:23,1 -DA:24,1 +DA:24,2 DA:25,1 DA:26,2 -DA:28,3 -DA:29,3 -DA:30,1 -DA:31,2 -DA:33,2 -DA:34,1 -DA:35,3 +DA:27,4 +DA:28,2 +DA:30,2 +DA:31,1 +DA:32,3 +DA:33,4 +DA:34,2 DA:36,3 -DA:37,1 -DA:38,2 -DA:39,3 -DA:41,2 -DA:43,3 -DA:44,2 -LF:24 -LH:23 +DA:39,2 +DA:41,3 +DA:42,2 +LF:21 +LH:20 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart -DA:11,1 -DA:20,1 +SF:lib/src/shared/blocs/book_bloc/book_event.dart +DA:10,1 +DA:18,1 +DA:26,1 +DA:34,1 +DA:42,1 +LF:5 +LH:5 +end_of_record +SF:lib/src/shared/blocs/book_bloc/book_state.dart +DA:12,2 +DA:21,2 LF:2 LH:2 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 +SF:lib/src/shared/blocs/book_bloc/book_bloc.dart +DA:15,3 +DA:16,2 +DA:17,2 DA:18,2 -DA:20,2 -DA:22,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:27,1 -DA:28,1 -DA:29,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:16 -LH:16 -end_of_record -SF:lib/src/shared/blocs/book_bloc/book_event.dart -DA:10,1 -DA:18,1 -DA:26,1 -DA:34,1 -DA:42,1 -LF:5 -LH:5 -end_of_record -SF:lib/src/shared/blocs/book_bloc/book_state.dart -DA:12,2 -DA:21,2 -LF:2 -LH:2 -end_of_record -SF:lib/src/shared/blocs/book_bloc/book_bloc.dart -DA:15,3 -DA:16,2 -DA:17,2 -DA:18,2 -DA:19,2 +DA:19,2 DA:20,2 DA:21,2 DA:24,1 @@ -1603,6 +1580,32 @@ DA:227,0 LF:98 LH:75 end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +DA:11,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:22,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 +end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart DA:12,1 DA:14,2 @@ -1708,6 +1711,31 @@ DA:79,0 LF:31 LH:1 end_of_record +SF:lib/src/features/about/bloc/about_bloc.dart +DA:13,3 +DA:14,2 +DA:17,1 +DA:22,2 +DA:23,2 +DA:24,2 +DA:25,1 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:15 +LH:11 +end_of_record +SF:lib/src/features/about/bloc/about_state.dart +DA:10,1 +DA:19,1 +LF:2 +LH:2 +end_of_record SF:lib/src/features/auth/bloc/auth_bloc.dart DA:13,3 DA:14,2 @@ -1741,31 +1769,6 @@ DA:15,1 LF:1 LH:1 end_of_record -SF:lib/src/features/about/bloc/about_bloc.dart -DA:13,3 -DA:14,2 -DA:17,1 -DA:22,2 -DA:23,2 -DA:24,2 -DA:25,1 -DA:26,0 -DA:27,0 -DA:28,0 -DA:29,0 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:15 -LH:11 -end_of_record -SF:lib/src/features/about/bloc/about_state.dart -DA:10,1 -DA:19,1 -LF:2 -LH:2 -end_of_record SF:lib/src/features/book_detail/bloc/book_detail_event.dart DA:8,2 DA:16,2 @@ -2220,17 +2223,17 @@ LH:9 end_of_record SF:lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart DA:7,1 -DA:10,1 -DA:12,1 DA:13,1 -DA:14,1 DA:15,1 -DA:18,3 -DA:20,1 -DA:21,1 -DA:22,1 +DA:16,1 +DA:17,1 +DA:18,1 +DA:21,3 DA:23,1 -DA:24,4 +DA:24,1 +DA:25,1 +DA:26,1 +DA:27,4 LF:12 LH:12 end_of_record @@ -2468,7 +2471,7 @@ LF:2 LH:2 end_of_record SF:lib/src/core/dtos/bookcase_dto.dart -DA:7,2 +DA:7,3 DA:12,0 DA:16,0 DA:17,0 @@ -2743,62 +2746,62 @@ DA:88,0 DA:89,0 DA:90,0 DA:94,0 -DA:95,0 -DA:100,0 -DA:103,0 -DA:107,1 -DA:113,3 -DA:114,1 +DA:96,0 +DA:102,0 +DA:105,0 +DA:109,1 +DA:115,3 DA:116,1 -DA:117,1 -DA:118,2 -DA:121,1 -DA:124,1 +DA:118,1 +DA:119,1 +DA:120,2 +DA:123,1 DA:126,1 DA:128,1 -DA:129,0 +DA:130,1 DA:131,0 DA:133,0 -DA:134,0 -DA:139,1 +DA:135,0 +DA:136,0 DA:141,1 -DA:142,0 +DA:143,1 DA:144,0 -DA:146,2 -DA:147,1 -DA:152,1 -DA:154,2 -DA:155,2 -DA:157,1 -DA:158,1 +DA:146,0 +DA:148,2 +DA:149,1 +DA:154,1 +DA:156,2 +DA:157,2 DA:159,1 -DA:160,2 +DA:160,1 DA:161,1 -DA:162,1 -DA:163,2 +DA:162,2 +DA:163,1 DA:164,1 -DA:165,1 -DA:166,0 -DA:167,0 +DA:165,2 +DA:166,1 +DA:167,1 DA:168,0 -DA:169,1 -DA:170,1 +DA:169,0 +DA:170,0 +DA:171,1 DA:172,1 -DA:173,1 -DA:174,0 -DA:175,0 +DA:174,1 +DA:175,1 DA:176,0 -DA:181,1 -DA:182,1 -DA:183,0 -DA:186,1 -DA:187,1 -DA:189,0 -DA:190,1 -DA:194,1 -DA:195,1 +DA:177,0 +DA:178,0 +DA:183,1 +DA:184,1 +DA:185,0 +DA:188,1 +DA:189,1 +DA:191,0 +DA:192,1 DA:196,1 DA:197,1 +DA:198,1 +DA:199,1 LF:90 LH:52 end_of_record @@ -2875,9 +2878,9 @@ DA:207,1 DA:209,1 DA:211,1 DA:215,2 -DA:216,0 -DA:217,0 -DA:218,0 +DA:216,1 +DA:217,1 +DA:218,2 DA:226,1 DA:228,2 DA:231,1 @@ -2939,7 +2942,7 @@ DA:338,1 DA:340,1 DA:341,1 LF:135 -LH:116 +LH:119 end_of_record SF:lib/src/shared/widgets/item_state_widget/item_empty_state_widget/item_empty_widget.dart DA:7,1 @@ -3145,36 +3148,37 @@ DA:11,1 DA:20,1 DA:21,1 DA:27,1 -DA:31,1 DA:32,1 -DA:33,0 -DA:36,1 +DA:33,1 +DA:34,0 DA:37,1 -DA:43,1 -DA:45,2 -DA:46,3 -DA:47,2 -DA:48,0 -DA:50,1 -DA:52,1 -DA:53,2 -DA:57,1 +DA:38,1 +DA:44,1 +DA:46,2 +DA:47,3 +DA:48,2 +DA:49,0 +DA:51,1 +DA:53,1 +DA:54,2 DA:58,1 DA:59,1 -DA:60,3 -DA:61,1 -DA:63,1 -DA:67,1 -DA:68,0 +DA:60,1 +DA:61,3 +DA:62,1 +DA:64,1 +DA:68,1 DA:69,0 DA:70,0 DA:71,0 -DA:75,1 -DA:80,1 -DA:82,2 -DA:84,3 -LF:32 -LH:26 +DA:72,0 +DA:76,1 +DA:81,1 +DA:83,2 +DA:84,2 +DA:85,1 +LF:33 +LH:27 end_of_record SF:lib/src/features/bookcase_books_insertion/bloc/bookcase_books_insertion_state.dart DA:17,1 @@ -3467,25 +3471,27 @@ SF:lib/src/features/bookcase_detail/widgets/bookcase_description_widget/bookcase DA:11,0 DA:19,0 DA:21,0 +DA:22,0 DA:23,0 -DA:25,0 -DA:27,0 +DA:24,0 +DA:26,0 DA:28,0 -DA:32,0 +DA:29,0 DA:33,0 DA:34,0 DA:35,0 -DA:44,0 +DA:36,0 DA:45,0 -DA:54,0 +DA:46,0 DA:55,0 -DA:58,0 +DA:56,0 DA:59,0 -DA:63,0 +DA:60,0 DA:64,0 DA:65,0 DA:66,0 -LF:21 +DA:67,0 +LF:23 LH:0 end_of_record SF:lib/src/features/bookcase_detail/widgets/bookcase_detail_loaded_state_widget/bookcase_detail_loaded_state_widget.dart @@ -3496,39 +3502,37 @@ DA:36,0 DA:38,0 DA:39,0 DA:42,0 -DA:43,0 -DA:46,0 -DA:48,0 -DA:53,0 -DA:57,0 -DA:58,0 +DA:44,0 +DA:47,0 +DA:49,0 +DA:55,0 DA:59,0 DA:60,0 DA:61,0 DA:62,0 +DA:63,0 DA:64,0 -DA:67,0 -DA:71,0 -DA:72,0 +DA:66,0 +DA:69,0 DA:73,0 DA:74,0 +DA:75,0 DA:76,0 -DA:79,0 -DA:83,0 -DA:84,0 -DA:87,0 -DA:88,0 +DA:78,0 +DA:81,0 +DA:85,0 +DA:86,0 DA:89,0 +DA:90,0 DA:91,0 -DA:97,0 -DA:98,0 +DA:93,0 DA:99,0 DA:100,0 -DA:104,0 +DA:101,0 +DA:102,0 DA:106,0 -DA:107,0 +DA:108,0 DA:109,0 -DA:110,0 DA:111,0 DA:112,0 DA:113,0 @@ -3541,40 +3545,42 @@ DA:119,0 DA:120,0 DA:121,0 DA:122,0 +DA:123,0 DA:124,0 -DA:125,0 DA:126,0 DA:127,0 DA:128,0 -DA:133,0 -DA:134,0 +DA:129,0 +DA:130,0 DA:135,0 -DA:141,0 -DA:142,0 +DA:136,0 +DA:137,0 DA:143,0 DA:144,0 DA:145,0 DA:146,0 -DA:149,0 -DA:150,0 +DA:147,0 +DA:148,0 +DA:151,0 DA:152,0 DA:154,0 -DA:155,0 +DA:156,0 DA:157,0 -DA:158,0 +DA:159,0 DA:160,0 DA:162,0 DA:164,0 -DA:165,0 DA:166,0 DA:167,0 DA:168,0 DA:169,0 DA:170,0 -DA:178,0 -DA:179,0 -DA:182,0 -DA:183,0 +DA:171,0 +DA:172,0 +DA:180,0 +DA:181,0 +DA:184,0 +DA:185,0 LF:86 LH:0 end_of_record @@ -3978,55 +3984,6 @@ SF:lib/src/features/contacts_picker/bloc/contacts_picker_event.dart LF:0 LH:0 end_of_record -SF:lib/src/features/my_books/bloc/my_books_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_bloc.dart -DA:14,3 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,2 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:45,1 -DA:51,1 -DA:56,2 -DA:58,2 -DA:59,1 -DA:62,1 -DA:63,2 -DA:67,2 -DA:68,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:72,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:79,1 -LF:34 -LH:34 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:20,1 DA:24,2 @@ -4082,6 +4039,55 @@ DA:13,1 LF:1 LH:1 end_of_record +SF:lib/src/features/my_books/bloc/my_books_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_bloc.dart +DA:14,3 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,2 +DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,1 +DA:63,2 +DA:67,2 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:79,1 +LF:34 +LH:34 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record SF:lib/src/features/home/views/home_page.dart DA:11,1 DA:13,1 @@ -4160,91 +4166,91 @@ LF:10 LH:7 end_of_record SF:lib/src/features/home/widgets/animated_search_bar/animated_search_bar.dart +DA:11,1 DA:17,1 -DA:23,1 -DA:24,1 -DA:31,0 +DA:18,1 +DA:25,0 +DA:26,0 +DA:29,1 +DA:30,1 +DA:31,3 DA:32,0 -DA:35,1 -DA:36,1 -DA:37,3 -DA:38,0 +DA:33,0 +DA:34,0 +DA:36,0 +DA:37,0 DA:39,0 -DA:40,0 -DA:42,0 -DA:43,0 -DA:45,0 -DA:48,4 -DA:51,1 -DA:53,3 -DA:54,1 -DA:56,1 -DA:58,1 -DA:59,1 -DA:61,2 -DA:62,0 +DA:42,4 +DA:45,1 +DA:47,3 +DA:48,1 +DA:50,1 +DA:52,1 +DA:53,1 +DA:55,2 +DA:56,0 +DA:57,0 +DA:58,0 +DA:60,0 +DA:61,0 DA:63,0 -DA:64,0 -DA:66,0 -DA:67,0 -DA:69,0 -DA:73,1 +DA:67,1 +DA:71,1 +DA:72,1 +DA:73,2 +DA:74,1 +DA:75,2 +DA:76,1 DA:77,1 DA:78,1 -DA:79,2 -DA:80,1 -DA:81,2 DA:82,1 -DA:83,1 -DA:84,1 DA:88,1 -DA:94,1 -DA:96,1 -DA:97,0 -DA:98,0 -DA:99,0 -DA:100,0 -DA:103,1 +DA:90,1 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:97,1 +DA:98,1 +DA:99,1 DA:104,1 -DA:105,1 +DA:108,1 DA:110,1 -DA:114,1 -DA:116,1 -DA:124,1 +DA:118,1 +DA:119,1 +DA:122,1 +DA:123,1 DA:125,1 +DA:127,1 DA:128,1 DA:129,1 -DA:131,1 -DA:133,1 -DA:134,1 +DA:130,2 DA:135,1 -DA:136,2 -DA:141,1 -DA:142,1 +DA:136,1 +DA:138,1 +DA:139,1 +DA:140,1 DA:144,1 -DA:145,1 DA:146,1 -DA:150,1 +DA:147,1 +DA:148,1 DA:152,1 -DA:153,1 DA:154,1 -DA:158,1 +DA:155,1 +DA:156,1 DA:160,1 -DA:161,1 DA:162,1 -DA:166,1 +DA:163,1 +DA:164,1 DA:168,1 -DA:169,1 DA:170,1 -DA:174,1 -DA:176,1 +DA:171,1 +DA:172,1 DA:177,1 -DA:178,1 -DA:183,1 -DA:184,0 -DA:185,0 -DA:186,0 -DA:187,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:181,0 LF:85 LH:63 end_of_record @@ -4281,35 +4287,6 @@ DA:43,3 LF:19 LH:18 end_of_record -SF:lib/src/features/notifications/bloc/notifications_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/notifications/bloc/notifications_bloc.dart -DA:13,1 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,1 -DA:34,1 -DA:38,1 -DA:39,0 -DA:40,0 -DA:41,0 -DA:42,0 -DA:45,1 -DA:46,1 -DA:47,1 -DA:49,1 -LF:19 -LH:15 -end_of_record SF:lib/src/features/profile/bloc/profile_state.dart DA:10,1 DA:21,1 @@ -4361,6 +4338,35 @@ DA:10,1 LF:1 LH:1 end_of_record +SF:lib/src/features/notifications/bloc/notifications_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/notifications/bloc/notifications_bloc.dart +DA:13,1 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,1 +DA:34,1 +DA:38,1 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:45,1 +DA:46,1 +DA:47,1 +DA:49,1 +LF:19 +LH:15 +end_of_record SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart DA:19,1 DA:24,2 diff --git a/lib/src/core/adapters/google_books_adapter.dart b/lib/src/core/adapters/google_books_adapter.dart index 2a3c9cfc..7dfe6539 100644 --- a/lib/src/core/adapters/google_books_adapter.dart +++ b/lib/src/core/adapters/google_books_adapter.dart @@ -13,9 +13,7 @@ abstract class GoogleBooksAdapter { if (json['items'] == null) { return []; } - return (json['items'] as List) - .map((bookMap) => fromJson(bookMap)) - .toList(); + return (json['items'] as List).map((bookMap) => fromJson(bookMap)).toList(); } /// This method was extracted from the [BookModel] class in order to ensure that if one were to change the book API, @@ -24,21 +22,21 @@ abstract class GoogleBooksAdapter { return BookModel( id: map['id'], title: map['volumeInfo']['title'], - authors: - List.from(map['volumeInfo']['authors'] ?? ['Unknown Author']) - .map((author) => AuthorModel(name: author)) - .toList(), + authors: List.from( + map['volumeInfo']['authors'] ?? ['Unknown Author'], + ).map((author) => AuthorModel(name: author)).toList(), publisher: map['volumeInfo']['publisher'] ?? 'Unknown Publisher', description: map['volumeInfo']['description'] ?? 'No description available', categories: List.from( - map['volumeInfo']['categories'] ?? ['Unknown category']) - .map((category) => CategoryModel(name: category)) - .toList(), + map['volumeInfo']['categories'] ?? ['Unknown category'], + ).map((category) => CategoryModel(name: category)).toList(), pageCount: map['volumeInfo']['pageCount'] ?? 0, - imageUrl: (map['volumeInfo']['imageLinks']?['thumbnail'] ?? + imageUrl: + (map['volumeInfo']['imageLinks']?['thumbnail'] ?? 'https://books.google.com.br/googlebooks/images/no_cover_thumb.gif'), - buyLink: map['volumeInfo']['infoLink'] ?? + buyLink: + map['volumeInfo']['infoLink'] ?? 'https://play.google.com/store/books?', averageRating: (map['volumeInfo']['averageRating'] ?? 0.0).toDouble(), ratingsCount: map['volumeInfo']['ratingsCount'] ?? 0, diff --git a/lib/src/core/database/local_database_impl.dart b/lib/src/core/database/local_database_impl.dart index d4c00443..aa909239 100644 --- a/lib/src/core/database/local_database_impl.dart +++ b/lib/src/core/database/local_database_impl.dart @@ -452,7 +452,7 @@ class LocalDatabaseImpl implements LocalDatabase { descriptionMessage: e.toString(), ); } - + if (e.isNotNullConstraintError()) { return LocalDatabaseException( LocalDatabaseErrorCode.notNullConstraint, diff --git a/lib/src/core/models/book_model.dart b/lib/src/core/models/book_model.dart index 5b0ffa0c..cc2177e2 100644 --- a/lib/src/core/models/book_model.dart +++ b/lib/src/core/models/book_model.dart @@ -10,7 +10,7 @@ enum BookStatus { return switch (this) { BookStatus.library => 1, BookStatus.reading => 2, - BookStatus.loaned => 3 + BookStatus.loaned => 3, }; } diff --git a/lib/src/core/models/loan_model.dart b/lib/src/core/models/loan_model.dart index 51efb7c4..370647d5 100644 --- a/lib/src/core/models/loan_model.dart +++ b/lib/src/core/models/loan_model.dart @@ -6,7 +6,7 @@ class LoanModel { final String idContact; final String bookId; - const LoanModel({ + const LoanModel({ this.id, this.observation, required this.loanDate, diff --git a/lib/src/core/models/user_hour_time_model.dart b/lib/src/core/models/user_hour_time_model.dart index 44def552..d545c581 100644 --- a/lib/src/core/models/user_hour_time_model.dart +++ b/lib/src/core/models/user_hour_time_model.dart @@ -23,17 +23,17 @@ class UserHourTimeModel { // Calculate total minutes in starting time int startingTimeInMinutes = (startingHour * 60) + startingMinute; -// Calculate total minutes in ending time + // Calculate total minutes in ending time int endingTimeInMinutes = (endingHour * 60) + endingMinute; -// Calculate the difference in minutes (handling negative values) + // Calculate the difference in minutes (handling negative values) int differenceInMinutes = endingTimeInMinutes - startingTimeInMinutes; if (differenceInMinutes < 0) { // Add a day's worth of minutes if negative differenceInMinutes += 24 * 60; } -// Convert the difference in minutes to seconds + // Convert the difference in minutes to seconds int differenceInSeconds = differenceInMinutes * 60; return differenceInSeconds; } @@ -66,8 +66,9 @@ class UserHourTimeModel { factory UserHourTimeModel.fromMap(Map map) { return UserHourTimeModel( - repeatHourTimeType: - RepeatHourTimeType.toType(map['repeatHourTimeType'] as int), + repeatHourTimeType: RepeatHourTimeType.toType( + map['repeatHourTimeType'] as int, + ), startingHour: map['startingHour'] as int, startingMinute: map['startingMinute'] as int, endingHour: map['endingHour'] as int, diff --git a/lib/src/core/repositories/book_categories_repository/book_categories_repository.dart b/lib/src/core/repositories/book_categories_repository/book_categories_repository.dart index fad8c1b3..f27a11ca 100644 --- a/lib/src/core/repositories/book_categories_repository/book_categories_repository.dart +++ b/lib/src/core/repositories/book_categories_repository/book_categories_repository.dart @@ -1,6 +1,7 @@ abstract interface class BookCategoriesRepository { - Future>> getRelationshipsById( - {required String bookId}); + Future>> getRelationshipsById({ + required String bookId, + }); Future insert({required String bookId, required int categoryId}); Future delete({required String bookId}); } diff --git a/lib/src/core/repositories/book_on_case_repository/book_on_case_repository.dart b/lib/src/core/repositories/book_on_case_repository/book_on_case_repository.dart index b83e14bb..b293abeb 100644 --- a/lib/src/core/repositories/book_on_case_repository/book_on_case_repository.dart +++ b/lib/src/core/repositories/book_on_case_repository/book_on_case_repository.dart @@ -1,6 +1,7 @@ abstract interface class BookOnCaseRepository { - Future>> getBooksOnCaseRelationship( - {required int bookcaseId}); + Future>> getBooksOnCaseRelationship({ + required int bookcaseId, + }); Future insert({ required int bookcaseId, required String bookId, diff --git a/lib/src/core/repositories/books_repository/books_repository.dart b/lib/src/core/repositories/books_repository/books_repository.dart index b29d894a..0ec30444 100644 --- a/lib/src/core/repositories/books_repository/books_repository.dart +++ b/lib/src/core/repositories/books_repository/books_repository.dart @@ -7,8 +7,11 @@ abstract interface class BooksRepository { Future> getBooksByTitle({required String title}); Future insert({required BookModel bookModel}); Future verifyBookIsAlreadyInserted({required String id}); - FuturegetBookStatus({required String id}); - Future updateBookStatus({required String id, required BookStatus status}); + Future getBookStatus({required String id}); + Future updateBookStatus({ + required String id, + required BookStatus status, + }); Future updateBookPageCount({required String id, required int pageCount}); Future countBooks(); Future deleteBookById({required String id}); diff --git a/lib/src/core/repositories/category_repository/categories_repository.dart b/lib/src/core/repositories/category_repository/categories_repository.dart index 91b0b67e..4f3ead67 100644 --- a/lib/src/core/repositories/category_repository/categories_repository.dart +++ b/lib/src/core/repositories/category_repository/categories_repository.dart @@ -1,8 +1,8 @@ import 'package:bookify/src/core/models/category_model.dart'; abstract interface class CategoriesRepository { - Future getCategoryById({required int id}); + Future getCategoryById({required int id}); Future insert({required CategoryModel categoryModel}); Future getCategoryIdByColumnName({required String categoryName}); Future deleteCategoryById({required int id}); -} \ No newline at end of file +} diff --git a/lib/src/core/services/app_services/time_picker_dialog_service.dart/time_picker_dialog_service.dart b/lib/src/core/services/app_services/time_picker_dialog_service.dart/time_picker_dialog_service.dart index 6a5aaf2b..89ab53b2 100644 --- a/lib/src/core/services/app_services/time_picker_dialog_service.dart/time_picker_dialog_service.dart +++ b/lib/src/core/services/app_services/time_picker_dialog_service.dart/time_picker_dialog_service.dart @@ -34,8 +34,9 @@ class TimePickerDialogService { context: context, builder: (context) { return CupertinoTimerPicker( - backgroundColor: - CupertinoColors.systemBackground.resolveFrom(context), + backgroundColor: CupertinoColors.systemBackground.resolveFrom( + context, + ), mode: CupertinoTimerPickerMode.hm, initialTimerDuration: initialTimerDuration, onTimerDurationChanged: (duration) { diff --git a/lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart b/lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart index 51bcbb44..d21d2899 100644 --- a/lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart +++ b/lib/src/core/services/auth_service/auth_strategy/auth_strategy_factory.dart @@ -12,16 +12,16 @@ class AuthStrategyFactory { AuthStrategy create(SignInType signInType) { return switch (signInType) { SignInType.google => GoogleAuthStrategy( - googleSignIn: GoogleSignIn.instance, - firebaseAuth: FirebaseAuth.instance, - ), + googleSignIn: GoogleSignIn.instance, + firebaseAuth: FirebaseAuth.instance, + ), SignInType.apple => AppleAuthStrategy( - firebaseAuth: FirebaseAuth.instance, - ), + firebaseAuth: FirebaseAuth.instance, + ), SignInType.facebook => FacebookAuthStrategy( - facebookAuth: FacebookAuth.instance, - firebaseAuth: FirebaseAuth.instance, - ), + facebookAuth: FacebookAuth.instance, + firebaseAuth: FirebaseAuth.instance, + ), }; } } diff --git a/lib/src/core/services/book_service/book_service_impl.dart b/lib/src/core/services/book_service/book_service_impl.dart index b965b62d..4f6e9bcf 100644 --- a/lib/src/core/services/book_service/book_service_impl.dart +++ b/lib/src/core/services/book_service/book_service_impl.dart @@ -24,11 +24,11 @@ class BookServiceImpl implements BookService { required CategoriesRepository categoriesRepository, required BookAuthorsRepository bookAuthorsRepository, required BookCategoriesRepository bookCategoriesRepository, - }) : _booksRepository = booksRepository, - _authorsRepository = authorsRepository, - _categoriesRepository = categoriesRepository, - _bookAuthorsRepository = bookAuthorsRepository, - _bookCategoriesRepository = bookCategoriesRepository; + }) : _booksRepository = booksRepository, + _authorsRepository = authorsRepository, + _categoriesRepository = categoriesRepository, + _bookAuthorsRepository = bookAuthorsRepository, + _bookCategoriesRepository = bookCategoriesRepository; @override Future> getAllBook() async { @@ -36,8 +36,9 @@ class BookServiceImpl implements BookService { final booksModel = await _booksRepository.getAll(); for (var index = 0; index < booksModel.length; index++) { - final (authors, categories) = - await _getBookComponents(booksModel[index].id); + final (authors, categories) = await _getBookComponents( + booksModel[index].id, + ); booksModel[index] = booksModel[index].copyWith( authors: authors, categories: categories, @@ -74,8 +75,9 @@ class BookServiceImpl implements BookService { final booksModel = await _booksRepository.getBooksByTitle(title: title); for (var index = 0; index < booksModel.length; index++) { - final (authors, categories) = - await _getBookComponents(booksModel[index].id); + final (authors, categories) = await _getBookComponents( + booksModel[index].id, + ); booksModel[index] = booksModel[index].copyWith( authors: authors, categories: categories, @@ -118,8 +120,9 @@ class BookServiceImpl implements BookService { ); if (categoryId == -1) { - categoryId = - await _categoriesRepository.insert(categoryModel: category); + categoryId = await _categoriesRepository.insert( + categoryModel: category, + ); } await _bookCategoriesRepository.insert( @@ -137,8 +140,9 @@ class BookServiceImpl implements BookService { @override Future verifyBookIsAlreadyInserted({required String id}) async { try { - final isInserted = - await _booksRepository.verifyBookIsAlreadyInserted(id: id); + final isInserted = await _booksRepository.verifyBookIsAlreadyInserted( + id: id, + ); return isInserted; } on LocalDatabaseException { rethrow; @@ -218,8 +222,8 @@ class BookServiceImpl implements BookService { } Future _getBookComponents(String bookId) async { - final bookAuthorsRelationShip = - await _bookAuthorsRepository.getRelationshipsById(bookId: bookId); + final bookAuthorsRelationShip = await _bookAuthorsRepository + .getRelationshipsById(bookId: bookId); final authorsId = bookAuthorsRelationShip .map((relationship) => relationship['authorId'] as int) @@ -231,8 +235,8 @@ class BookServiceImpl implements BookService { authors.add(author); } - final bookCategoriesRelationShip = - await _bookCategoriesRepository.getRelationshipsById(bookId: bookId); + final bookCategoriesRelationShip = await _bookCategoriesRepository + .getRelationshipsById(bookId: bookId); final categoriesId = bookCategoriesRelationShip .map((relationship) => relationship['categoryId'] as int) diff --git a/lib/src/core/services/bookcase_service/bookcase_service_impl.dart b/lib/src/core/services/bookcase_service/bookcase_service_impl.dart index fd9271f5..7c81ebb9 100644 --- a/lib/src/core/services/bookcase_service/bookcase_service_impl.dart +++ b/lib/src/core/services/bookcase_service/bookcase_service_impl.dart @@ -11,8 +11,8 @@ class BookcaseServiceImpl implements BookcaseService { BookcaseServiceImpl({ required BookcaseRepository bookcaseRepository, required BookOnCaseRepository bookOnCaseRepository, - }) : _bookcaseRepository = bookcaseRepository, - _bookOnCaseRepository = bookOnCaseRepository; + }) : _bookcaseRepository = bookcaseRepository, + _bookOnCaseRepository = bookOnCaseRepository; @override Future> getAllBookcases() async { @@ -37,8 +37,9 @@ class BookcaseServiceImpl implements BookcaseService { } @override - Future>> getAllBookcaseRelationships( - {required int bookcaseId}) async { + Future>> getAllBookcaseRelationships({ + required int bookcaseId, + }) async { try { final bookcasesRelationships = await _bookOnCaseRepository .getBooksOnCaseRelationship(bookcaseId: bookcaseId); @@ -49,14 +50,16 @@ class BookcaseServiceImpl implements BookcaseService { } @override - Future deleteBookcaseRelationship( - {required int bookcaseId, required String bookId}) async { + Future deleteBookcaseRelationship({ + required int bookcaseId, + required String bookId, + }) async { try { - final bookcaseRelationshipRowDeleted = - await _bookOnCaseRepository.deleteBookcaseRelationship( - bookcaseId: bookcaseId, - bookId: bookId, - ); + final bookcaseRelationshipRowDeleted = await _bookOnCaseRepository + .deleteBookcaseRelationship( + bookcaseId: bookcaseId, + bookId: bookId, + ); return bookcaseRelationshipRowDeleted; } on LocalDatabaseException { rethrow; @@ -78,8 +81,9 @@ class BookcaseServiceImpl implements BookcaseService { @override Future getBookcaseById({required int bookcaseId}) async { try { - final bookcaseModel = - await _bookcaseRepository.getById(bookcaseId: bookcaseId); + final bookcaseModel = await _bookcaseRepository.getById( + bookcaseId: bookcaseId, + ); return bookcaseModel; } on LocalDatabaseException { rethrow; @@ -89,8 +93,9 @@ class BookcaseServiceImpl implements BookcaseService { @override Future insertBookcase({required BookcaseModel bookcaseModel}) async { try { - final newBookcaseId = - _bookcaseRepository.insert(bookcaseModel: bookcaseModel); + final newBookcaseId = _bookcaseRepository.insert( + bookcaseModel: bookcaseModel, + ); return newBookcaseId; } on LocalDatabaseException { rethrow; diff --git a/lib/src/core/services/storage_services/storage_services.dart b/lib/src/core/services/storage_services/storage_services.dart index c8c89662..1f17f5b8 100644 --- a/lib/src/core/services/storage_services/storage_services.dart +++ b/lib/src/core/services/storage_services/storage_services.dart @@ -1,3 +1,3 @@ abstract interface class StorageServices { Future clearStorage(); -} \ No newline at end of file +} diff --git a/lib/src/core/utils/input_formatter/isbn_input_formatter.dart b/lib/src/core/utils/input_formatter/isbn_input_formatter.dart index 140a2761..fef34bb9 100644 --- a/lib/src/core/utils/input_formatter/isbn_input_formatter.dart +++ b/lib/src/core/utils/input_formatter/isbn_input_formatter.dart @@ -15,13 +15,13 @@ class IsbnMaskTextInputFormatter extends MaskTextInputFormatter { /// /// Initializes the formatter with the ISBN-10 mask and a filter for digits and 'X'. IsbnMaskTextInputFormatter() - : super( - mask: _maskIsbn10, - filter: { - '#': RegExp(r'[0-9]'), // Matches any digit. - 'S': RegExp(r'[xX0-9]'), // Matches 'X', 'x', or any digit. - }, - ); + : super( + mask: _maskIsbn10, + filter: { + '#': RegExp(r'[0-9]'), // Matches any digit. + 'S': RegExp(r'[xX0-9]'), // Matches 'X', 'x', or any digit. + }, + ); @override TextEditingValue formatEditUpdate( diff --git a/lib/src/core/utils/verifier/isbn_verifier.dart b/lib/src/core/utils/verifier/isbn_verifier.dart index 5ff7c362..3665f84a 100644 --- a/lib/src/core/utils/verifier/isbn_verifier.dart +++ b/lib/src/core/utils/verifier/isbn_verifier.dart @@ -9,7 +9,8 @@ class IsbnVerifier { // This regex ensures the ISBN code contains only digits, 'X', or '-', and follows the structure of ISBN codes. // It checks for the presence of 9 digits followed by an 'X' or a digit, and optionally 3 more digits. static final _isbnRegExp = RegExp( - r'^(?=(?:[^0-9]*[0-9]){9}[^0-9xX]*[0-9xX](?:(?:[^0-9]*[0-9]){3})?$)[\dXx-]+$'); + r'^(?=(?:[^0-9]*[0-9]){9}[^0-9xX]*[0-9xX](?:(?:[^0-9]*[0-9]){3})?$)[\dXx-]+$', + ); /// Getter for the ISBN format regular expression. /// This regex is used to validate if a given string is in a valid ISBN format. diff --git a/lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart b/lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart index 185c3563..d7743ac4 100644 --- a/lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart +++ b/lib/src/features/book_detail/views/widgets/book_description/book_description_widget.dart @@ -4,8 +4,11 @@ class BookDescriptionWidget extends StatelessWidget { final String title; final String content; - const BookDescriptionWidget( - {super.key, required this.title, required this.content}); + const BookDescriptionWidget({ + super.key, + required this.title, + required this.content, + }); @override Widget build(BuildContext context) { diff --git a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart index f8bec512..ecc6c580 100644 --- a/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart +++ b/lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_state.dart @@ -18,7 +18,7 @@ final class BookPagesReadingTimeErrorState extends BookPagesReadingTimeState { final String? errorDescriptionMessage; BookPagesReadingTimeErrorState({ - required this.errorCode, + required this.errorCode, this.errorDescriptionMessage, }); } diff --git a/lib/src/features/book_detail/views/widgets/widgets.dart b/lib/src/features/book_detail/views/widgets/widgets.dart index d7fd0035..0f7bb8e3 100644 --- a/lib/src/features/book_detail/views/widgets/widgets.dart +++ b/lib/src/features/book_detail/views/widgets/widgets.dart @@ -1,3 +1,3 @@ export 'book_description/book_description_widget.dart'; export 'book_rating/book_rating.dart'; -export 'book_pages_reading_time/widgets/book_pages_reading_time.dart'; \ No newline at end of file +export 'book_pages_reading_time/widgets/book_pages_reading_time.dart'; diff --git a/lib/src/features/book_on_bookcase_detail/views/widgets/widgets.dart b/lib/src/features/book_on_bookcase_detail/views/widgets/widgets.dart index f12bd1bd..b5b013ee 100644 --- a/lib/src/features/book_on_bookcase_detail/views/widgets/widgets.dart +++ b/lib/src/features/book_on_bookcase_detail/views/widgets/widgets.dart @@ -1,2 +1,2 @@ export 'package:bookify/src/features/book_on_bookcase_detail/views/widgets/book_state_widget.dart'; -export 'package:bookify/src/features/book_on_bookcase_detail/views/widgets/bookcases_count_widget.dart'; \ No newline at end of file +export 'package:bookify/src/features/book_on_bookcase_detail/views/widgets/bookcases_count_widget.dart'; diff --git a/lib/src/features/bookcase/views/widgets/bookcase_loaded_state_widget/bookcase_loaded_state_widget.dart b/lib/src/features/bookcase/views/widgets/bookcase_loaded_state_widget/bookcase_loaded_state_widget.dart index 23c2542c..c8603fe3 100644 --- a/lib/src/features/bookcase/views/widgets/bookcase_loaded_state_widget/bookcase_loaded_state_widget.dart +++ b/lib/src/features/bookcase/views/widgets/bookcase_loaded_state_widget/bookcase_loaded_state_widget.dart @@ -92,10 +92,12 @@ class _BookcaseLoadedStateWidgetState extends State { } Future _onAddNewBookcase(BuildContext context) async { - var bookcaseInsertionList = await Navigator.pushNamed( - context, - BookcaseInsertionPage.routeName, - ) as List?; + var bookcaseInsertionList = + await Navigator.pushNamed( + context, + BookcaseInsertionPage.routeName, + ) + as List?; final isInserted = bookcaseInsertionList?[0] as bool?; diff --git a/lib/src/features/bookcase_books_insertion/widgets/widgets.dart b/lib/src/features/bookcase_books_insertion/widgets/widgets.dart index 79a40f66..9431419d 100644 --- a/lib/src/features/bookcase_books_insertion/widgets/widgets.dart +++ b/lib/src/features/bookcase_books_insertion/widgets/widgets.dart @@ -1 +1 @@ -export 'bookcase_books_insertion_loaded_state_widget/bookcase_books_insertion_loaded_state.dart'; \ No newline at end of file +export 'bookcase_books_insertion_loaded_state_widget/bookcase_books_insertion_loaded_state.dart'; diff --git a/lib/src/features/bookcase_detail/widgets/bookcase_description_widget/bookcase_description_widget.dart b/lib/src/features/bookcase_detail/widgets/bookcase_description_widget/bookcase_description_widget.dart index 025bcc7e..baa95e4b 100644 --- a/lib/src/features/bookcase_detail/widgets/bookcase_description_widget/bookcase_description_widget.dart +++ b/lib/src/features/bookcase_detail/widgets/bookcase_description_widget/bookcase_description_widget.dart @@ -19,8 +19,9 @@ class BookcaseDescriptionWidget extends StatelessWidget { @override Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; - final bookTextQuantity = - (booksQuantity == 1) ? 'book-label'.i18n() : 'books-label'.i18n(); + final bookTextQuantity = (booksQuantity == 1) + ? 'book-label'.i18n() + : 'books-label'.i18n(); return Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/src/features/bookcase_detail/widgets/bookcase_detail_loaded_state_widget/bookcase_detail_loaded_state_widget.dart b/lib/src/features/bookcase_detail/widgets/bookcase_detail_loaded_state_widget/bookcase_detail_loaded_state_widget.dart index 232ea90a..5612f97d 100644 --- a/lib/src/features/bookcase_detail/widgets/bookcase_detail_loaded_state_widget/bookcase_detail_loaded_state_widget.dart +++ b/lib/src/features/bookcase_detail/widgets/bookcase_detail_loaded_state_widget/bookcase_detail_loaded_state_widget.dart @@ -40,14 +40,16 @@ class _BookcaseDetailLoadedStateWidgetState } Future _normalOnTap(BuildContext context, BookModel book) async { - final bookIsChanged = await Navigator.pushNamed( - context, - BookOnBookcaseDetailPage.routeName, - arguments: [ - book, - widget.bookcaseId, - ], - ) as bool?; + final bookIsChanged = + await Navigator.pushNamed( + context, + BookOnBookcaseDetailPage.routeName, + arguments: [ + book, + widget.bookcaseId, + ], + ) + as bool?; if (bookIsChanged != null && bookIsChanged) { widget.refreshPage(); diff --git a/lib/src/features/bookcase_detail/widgets/widgets.dart b/lib/src/features/bookcase_detail/widgets/widgets.dart index 2fd3b09c..deceb737 100644 --- a/lib/src/features/bookcase_detail/widgets/widgets.dart +++ b/lib/src/features/bookcase_detail/widgets/widgets.dart @@ -1,2 +1,2 @@ export 'bookcase_detail_loaded_state_widget/bookcase_detail_loaded_state_widget.dart'; -export 'bookcase_description_widget/bookcase_description_widget.dart'; \ No newline at end of file +export 'bookcase_description_widget/bookcase_description_widget.dart'; diff --git a/lib/src/features/bookcase_tab_view/views/pages/pages.dart b/lib/src/features/bookcase_tab_view/views/pages/pages.dart index 0f3b3c11..e4b9fda4 100644 --- a/lib/src/features/bookcase_tab_view/views/pages/pages.dart +++ b/lib/src/features/bookcase_tab_view/views/pages/pages.dart @@ -1,3 +1,3 @@ export 'package:bookify/src/features/bookcase/views/bookcase_page.dart'; export 'package:bookify/src/features/loan/views/loan_page.dart'; -export 'package:bookify/src/features/my_books/views/my_books_page.dart'; \ No newline at end of file +export 'package:bookify/src/features/my_books/views/my_books_page.dart'; diff --git a/lib/src/features/books_picker/views/books_picker_page.dart b/lib/src/features/books_picker/views/books_picker_page.dart index f2502dcd..fedd4bf6 100644 --- a/lib/src/features/books_picker/views/books_picker_page.dart +++ b/lib/src/features/books_picker/views/books_picker_page.dart @@ -79,7 +79,7 @@ class _BooksPickerPageState extends State { }, ), ), - ) + ), ], ), body: !isSelectionBook diff --git a/lib/src/features/books_picker/views/widgets/book_selector_widget/book_selector_widget.dart b/lib/src/features/books_picker/views/widgets/book_selector_widget/book_selector_widget.dart index 7fac5587..79e37308 100644 --- a/lib/src/features/books_picker/views/widgets/book_selector_widget/book_selector_widget.dart +++ b/lib/src/features/books_picker/views/widgets/book_selector_widget/book_selector_widget.dart @@ -68,54 +68,57 @@ class _BookSelectorWidgetState extends State { Expanded( child: GestureDetector( onTap: () => selectedBook != null ? _clearData() : null, - child: LayoutBuilder(builder: (context, constraints) { - return GridView.builder( - keyboardDismissBehavior: - ScrollViewKeyboardDismissBehavior.onDrag, - itemCount: widget.books.length, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - childAspectRatio: .7, - crossAxisCount: constraints.maxWidth > 500 ? 6 : 3, - ), - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.all(4.0), - child: Tooltip( - message: widget.books[index].title, - child: Material( - child: InkWell( - splashColor: Colors.transparent, - onTap: () => - _clickOnBook(widget.books[index], index), - child: (selectedBook == widget.books[index]) - ? Container( - decoration: BoxDecoration( - color: colorScheme.secondary, - border: Border.all( - color: Colors.transparent, + child: LayoutBuilder( + builder: (context, constraints) { + return GridView.builder( + keyboardDismissBehavior: + ScrollViewKeyboardDismissBehavior.onDrag, + itemCount: widget.books.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: .7, + crossAxisCount: constraints.maxWidth > 500 ? 6 : 3, + ), + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: Tooltip( + message: widget.books[index].title, + child: Material( + child: InkWell( + splashColor: Colors.transparent, + onTap: () => + _clickOnBook(widget.books[index], index), + child: (selectedBook == widget.books[index]) + ? Container( + decoration: BoxDecoration( + color: colorScheme.secondary, + border: Border.all( + color: Colors.transparent, + ), + borderRadius: const BorderRadius.all( + Radius.circular(15), + ), ), - borderRadius: const BorderRadius.all( - Radius.circular(15), + padding: const EdgeInsets.all(4.0), + child: BookWidget( + key: const Key('SelectedBookWidget'), + bookImageUrl: + widget.books[index].imageUrl, ), - ), - padding: const EdgeInsets.all(4.0), - child: BookWidget( - key: const Key('SelectedBookWidget'), + ) + : BookWidget( + key: const Key('BookWidget'), bookImageUrl: widget.books[index].imageUrl, ), - ) - : BookWidget( - key: const Key('BookWidget'), - bookImageUrl: widget.books[index].imageUrl, - ), + ), ), ), - ), - ); - }, - ); - }), + ); + }, + ); + }, + ), ), ), ], diff --git a/lib/src/features/books_picker/views/widgets/bookcase_picker/views/widgets/bookcase_picker_loaded_state_widget/bookcase_picker_loaded_state_widget.dart b/lib/src/features/books_picker/views/widgets/bookcase_picker/views/widgets/bookcase_picker_loaded_state_widget/bookcase_picker_loaded_state_widget.dart index efc81d10..896cfb8c 100644 --- a/lib/src/features/books_picker/views/widgets/bookcase_picker/views/widgets/bookcase_picker_loaded_state_widget/bookcase_picker_loaded_state_widget.dart +++ b/lib/src/features/books_picker/views/widgets/bookcase_picker/views/widgets/bookcase_picker_loaded_state_widget/bookcase_picker_loaded_state_widget.dart @@ -26,20 +26,22 @@ class BookcasePickerLoadedStateWidget extends StatelessWidget { return BookcaseWidget( bookcaseDto: bookcasesDto[index], onTap: () async { - final book = await showModalBottomSheet( - context: context, - constraints: BoxConstraints.loose( - Size( - MediaQuery.of(context).size.width, - MediaQuery.of(context).size.height * 0.75, - ), - ), - isScrollControlled: true, - showDragHandle: true, - builder: (context) => BookOnBookcaseWidget( - bookcaseId: bookcasesDto[index].bookcase.id!, - ), - ) as BookModel?; + final book = + await showModalBottomSheet( + context: context, + constraints: BoxConstraints.loose( + Size( + MediaQuery.of(context).size.width, + MediaQuery.of(context).size.height * 0.75, + ), + ), + isScrollControlled: true, + showDragHandle: true, + builder: (context) => BookOnBookcaseWidget( + bookcaseId: bookcasesDto[index].bookcase.id!, + ), + ) + as BookModel?; if (book != null) { onSelectBookModel(book); diff --git a/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_event.dart b/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_event.dart index 81257fdd..b4a40631 100644 --- a/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_event.dart +++ b/lib/src/features/books_picker/views/widgets/separate_books_picker/bloc/separate_books_picker_event.dart @@ -2,4 +2,4 @@ part of 'separate_books_picker_bloc.dart'; sealed class SeparateBooksPickerEvent {} -final class GotAllSeparatedBooksPickerEvent extends SeparateBooksPickerEvent{} +final class GotAllSeparatedBooksPickerEvent extends SeparateBooksPickerEvent {} diff --git a/lib/src/features/contacts_picker/views/widgets/widgets.dart b/lib/src/features/contacts_picker/views/widgets/widgets.dart index 4d86ba94..2454c855 100644 --- a/lib/src/features/contacts_picker/views/widgets/widgets.dart +++ b/lib/src/features/contacts_picker/views/widgets/widgets.dart @@ -1,2 +1,2 @@ export 'package:bookify/src/features/contacts_picker/views/widgets/contact_selected_row.dart'; -export 'package:bookify/src/features/contacts_picker/views/widgets/contact_widget.dart'; \ No newline at end of file +export 'package:bookify/src/features/contacts_picker/views/widgets/contact_widget.dart'; diff --git a/lib/src/features/home/widgets/animated_search_bar/animated_search_bar.dart b/lib/src/features/home/widgets/animated_search_bar/animated_search_bar.dart index 0fd843bf..ce955050 100644 --- a/lib/src/features/home/widgets/animated_search_bar/animated_search_bar.dart +++ b/lib/src/features/home/widgets/animated_search_bar/animated_search_bar.dart @@ -2,13 +2,7 @@ import 'package:bookify/src/shared/constants/icons/bookify_icons.dart'; import 'package:flutter/material.dart'; import 'package:localization/localization.dart'; -enum SearchType { - title, - author, - category, - publisher, - isbn; -} +enum SearchType { title, author, category, publisher, isbn } class AnimatedSearchBar extends StatefulWidget { final TextEditingController searchEC; @@ -37,11 +31,11 @@ class _AnimatedSearchBarState extends State { SearchType.title => {'enter-title-label'.i18n(): Icons.menu_book_rounded}, SearchType.author => {'enter-author-label'.i18n(): Icons.person_rounded}, SearchType.category => { - 'enter-category-label'.i18n(): Icons.category_rounded - }, + 'enter-category-label'.i18n(): Icons.category_rounded, + }, SearchType.publisher => { - 'enter-publisher-label'.i18n(): Icons.publish_rounded - }, + 'enter-publisher-label'.i18n(): Icons.publish_rounded, + }, SearchType.isbn => {'enter-isbn-label'.i18n(): BookifyIcons.isbn}, }; diff --git a/lib/src/features/home/widgets/widgets.dart b/lib/src/features/home/widgets/widgets.dart index a1357b65..648a3aa8 100644 --- a/lib/src/features/home/widgets/widgets.dart +++ b/lib/src/features/home/widgets/widgets.dart @@ -1,2 +1,2 @@ export 'animated_search_bar/animated_search_bar.dart'; -export 'book_loaded_state_widget/books_loaded_state_widget.dart'; \ No newline at end of file +export 'book_loaded_state_widget/books_loaded_state_widget.dart'; diff --git a/lib/src/features/loan/widgets/loan_loaded_state_widget/loan_loaded_state_widget.dart b/lib/src/features/loan/widgets/loan_loaded_state_widget/loan_loaded_state_widget.dart index 9cf05c75..eb64b557 100644 --- a/lib/src/features/loan/widgets/loan_loaded_state_widget/loan_loaded_state_widget.dart +++ b/lib/src/features/loan/widgets/loan_loaded_state_widget/loan_loaded_state_widget.dart @@ -25,10 +25,12 @@ class LoanLoadedStateWidget extends StatelessWidget { child: AddNewItemTextButton( label: 'loan-book-label'.i18n(), onPressed: () async { - final loanInserted = await Navigator.pushNamed( - context, - LoanInsertionPage.routeName, - ) as bool?; + final loanInserted = + await Navigator.pushNamed( + context, + LoanInsertionPage.routeName, + ) + as bool?; if (loanInserted != null && loanInserted) { refreshPage(); @@ -49,11 +51,13 @@ class LoanLoadedStateWidget extends StatelessWidget { key: const Key('LoanWidget'), loan: loansDto[index], onTap: () async { - final loanChanged = await Navigator.pushNamed( - context, - LoanDetailPage.routeName, - arguments: loansDto[index].loanModel.id!, - ) as bool?; + final loanChanged = + await Navigator.pushNamed( + context, + LoanDetailPage.routeName, + arguments: loansDto[index].loanModel.id!, + ) + as bool?; if (loanChanged != null && loanChanged) { refreshPage(); diff --git a/lib/src/features/loan/widgets/loan_widget/loan_widget.dart b/lib/src/features/loan/widgets/loan_widget/loan_widget.dart index 4a7fdc66..64cf01db 100644 --- a/lib/src/features/loan/widgets/loan_widget/loan_widget.dart +++ b/lib/src/features/loan/widgets/loan_widget/loan_widget.dart @@ -78,7 +78,8 @@ class LoanWidget extends StatelessWidget { top: -3, right: -3, child: ContactCircleAvatar( - name: loan.contactModel?.name ?? + name: + loan.contactModel?.name ?? 'no-name-label'.i18n(), photo: loan.contactModel?.photo, ), @@ -114,13 +115,15 @@ class LoanWidget extends StatelessWidget { ContactInformationWidget( iconData: Icons.person_outlined, title: 'name-label'.i18n(), - content: loan.contactModel?.name ?? + content: + loan.contactModel?.name ?? 'no-name-label'.i18n(), ), ContactInformationWidget( iconData: Icons.smartphone_outlined, title: 'contact-label'.i18n(), - content: loan.contactModel?.phoneNumber ?? + content: + loan.contactModel?.phoneNumber ?? 'no-contact-number-label'.i18n(), ), ], @@ -137,8 +140,8 @@ class LoanWidget extends StatelessWidget { ContactInformationWidget( iconData: Icons.calendar_month_outlined, title: 'loan-label'.i18n(), - content: - loan.loanModel.loanDate.toFormattedDate(), + content: loan.loanModel.loanDate + .toFormattedDate(), ), ContactInformationWidget( iconData: Icons.calendar_month_outlined, diff --git a/lib/src/features/loan_detail/views/widgets/book_card.dart b/lib/src/features/loan_detail/views/widgets/book_card.dart index 8187385f..b52b3650 100644 --- a/lib/src/features/loan_detail/views/widgets/book_card.dart +++ b/lib/src/features/loan_detail/views/widgets/book_card.dart @@ -81,7 +81,7 @@ class BookCard extends StatelessWidget { content: devolutionDate, ), ], - ) + ), ], ), ), diff --git a/lib/src/features/loan_detail/views/widgets/contact_card.dart b/lib/src/features/loan_detail/views/widgets/contact_card.dart index 03ef15e8..872550a5 100644 --- a/lib/src/features/loan_detail/views/widgets/contact_card.dart +++ b/lib/src/features/loan_detail/views/widgets/contact_card.dart @@ -68,7 +68,7 @@ class ContactCard extends StatelessWidget { ), ), ], - ) + ), ], ), ); diff --git a/lib/src/features/loan_detail/views/widgets/loan_detail_loaded_widget.dart b/lib/src/features/loan_detail/views/widgets/loan_detail_loaded_widget.dart index e6d96409..10d16318 100644 --- a/lib/src/features/loan_detail/views/widgets/loan_detail_loaded_widget.dart +++ b/lib/src/features/loan_detail/views/widgets/loan_detail_loaded_widget.dart @@ -52,8 +52,8 @@ class LoanDetailLoadedWidget extends StatelessWidget { bookTitle: loanDto.bookTitlePreview, observation: loanDto.loanModel.observation, loanDate: loanDto.loanModel.loanDate.toFormattedDate(), - devolutionDate: - loanDto.loanModel.devolutionDate.toFormattedDate(), + devolutionDate: loanDto.loanModel.devolutionDate + .toFormattedDate(), ), const SizedBox( height: 20, diff --git a/lib/src/features/loan_detail/views/widgets/loan_is_late_widget.dart b/lib/src/features/loan_detail/views/widgets/loan_is_late_widget.dart index ef6c0b7d..5aec4527 100644 --- a/lib/src/features/loan_detail/views/widgets/loan_is_late_widget.dart +++ b/lib/src/features/loan_detail/views/widgets/loan_is_late_widget.dart @@ -31,7 +31,7 @@ class LoanIsLateWidget extends StatelessWidget { fontSize: 12, fontWeight: FontWeight.bold, ), - ) + ), ], ), ); diff --git a/lib/src/features/loan_insertion/views/widgets/empty_book_button_widget.dart b/lib/src/features/loan_insertion/views/widgets/empty_book_button_widget.dart index b31ec828..de8cfe9d 100644 --- a/lib/src/features/loan_insertion/views/widgets/empty_book_button_widget.dart +++ b/lib/src/features/loan_insertion/views/widgets/empty_book_button_widget.dart @@ -19,7 +19,6 @@ class EmptyBookButtonWidget extends StatelessWidget { final colorScheme = Theme.of(context).colorScheme; final colorBorder = bookIsValid ? Colors.grey[300]! : colorScheme.error; - return GestureDetector( onTap: onTap, child: Container( diff --git a/lib/src/features/loan_insertion/views/widgets/empty_contact_button_widget.dart b/lib/src/features/loan_insertion/views/widgets/empty_contact_button_widget.dart index 1d86b5bd..86b6ed86 100644 --- a/lib/src/features/loan_insertion/views/widgets/empty_contact_button_widget.dart +++ b/lib/src/features/loan_insertion/views/widgets/empty_contact_button_widget.dart @@ -18,7 +18,6 @@ class EmptyContactButtonWidget extends StatelessWidget { Widget build(BuildContext context) { final colorScheme = Theme.of(context).colorScheme; - final borderColor = contactIsValid ? Colors.grey[300]! : colorScheme.error; return GestureDetector( diff --git a/lib/src/features/my_books/bloc/my_books_event.dart b/lib/src/features/my_books/bloc/my_books_event.dart index 881165fa..1fa34f62 100644 --- a/lib/src/features/my_books/bloc/my_books_event.dart +++ b/lib/src/features/my_books/bloc/my_books_event.dart @@ -4,7 +4,7 @@ sealed class MyBooksEvent {} final class GotAllBooksEvent extends MyBooksEvent {} -final class SearchedBooksEvent extends MyBooksEvent{ +final class SearchedBooksEvent extends MyBooksEvent { final String searchQuery; SearchedBooksEvent({required this.searchQuery}); diff --git a/lib/src/features/on_boarding/pages/pages.dart b/lib/src/features/on_boarding/pages/pages.dart index f96ffe94..ff2751f8 100644 --- a/lib/src/features/on_boarding/pages/pages.dart +++ b/lib/src/features/on_boarding/pages/pages.dart @@ -1,4 +1,4 @@ export 'package:bookify/src/features/on_boarding/pages/illustration_1_page.dart'; export 'package:bookify/src/features/on_boarding/pages/illustration_2_page.dart'; export 'package:bookify/src/features/on_boarding/pages/illustration_3_page.dart'; -export 'package:bookify/src/features/on_boarding/pages/illustration_4_page.dart'; \ No newline at end of file +export 'package:bookify/src/features/on_boarding/pages/illustration_4_page.dart'; diff --git a/lib/src/features/on_boarding/views/on_boarding_page.dart b/lib/src/features/on_boarding/views/on_boarding_page.dart index aaaa641c..fb4fb8c8 100644 --- a/lib/src/features/on_boarding/views/on_boarding_page.dart +++ b/lib/src/features/on_boarding/views/on_boarding_page.dart @@ -135,7 +135,7 @@ class _OnBoardingPageState extends State { ), ), ], - ) + ), ], ), ), diff --git a/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_event.dart b/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_event.dart index c8e67c18..2b58978f 100644 --- a/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_event.dart +++ b/lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_event.dart @@ -2,4 +2,4 @@ part of 'user_information_bloc.dart'; sealed class UserInformationEvent {} -final class GotUserInformationEvent extends UserInformationEvent{} +final class GotUserInformationEvent extends UserInformationEvent {} diff --git a/lib/src/features/profile/views/widgets/user_information_row/user_information_row.dart b/lib/src/features/profile/views/widgets/user_information_row/user_information_row.dart index 43351961..cacf889b 100644 --- a/lib/src/features/profile/views/widgets/user_information_row/user_information_row.dart +++ b/lib/src/features/profile/views/widgets/user_information_row/user_information_row.dart @@ -54,16 +54,18 @@ class _UserInformationRowState extends State { ), ItemStatusColumn( quantity: bookCount, - label: - bookCount == 1 ? 'book-label'.i18n() : 'books-label'.i18n(), + label: bookCount == 1 + ? 'book-label'.i18n() + : 'books-label'.i18n(), ), const SizedBox( width: 5, ), ItemStatusColumn( quantity: loansCount, - label: - loansCount == 1 ? 'loan-label'.i18n() : 'loans-label'.i18n(), + label: loansCount == 1 + ? 'loan-label'.i18n() + : 'loans-label'.i18n(), ), const SizedBox( width: 5, @@ -77,13 +79,13 @@ class _UserInformationRowState extends State { ], ), UserInformationErrorState() => Center( - child: Text( - 'error-on-loading-data'.i18n(), - style: TextStyle( - fontSize: 10, - ), + child: Text( + 'error-on-loading-data'.i18n(), + style: TextStyle( + fontSize: 10, ), ), + ), }; } diff --git a/lib/src/features/programming_reading/views/widgets/hour_time_selected_widget.dart b/lib/src/features/programming_reading/views/widgets/hour_time_selected_widget.dart index f5e00383..1c5e3b31 100644 --- a/lib/src/features/programming_reading/views/widgets/hour_time_selected_widget.dart +++ b/lib/src/features/programming_reading/views/widgets/hour_time_selected_widget.dart @@ -6,7 +6,7 @@ import 'package:localization/localization.dart'; class HourTimeSelectedWidget extends StatefulWidget { final void Function(TimeOfDay startingTime, TimeOfDay endingTime) - onSelectedTimes; + onSelectedTimes; final UserHourTimeModel? userHourTimeModel; const HourTimeSelectedWidget({ @@ -45,10 +45,12 @@ class _HourTimeSelectedWidgetState extends State { return Material( child: InkWell( onTap: () async { - final times = await Navigator.of(context).pushNamed( - TimePickerPage.routeName, - arguments: widget.userHourTimeModel, - ) as List?; + final times = + await Navigator.of(context).pushNamed( + TimePickerPage.routeName, + arguments: widget.userHourTimeModel, + ) + as List?; if (times != null) { setState(() { diff --git a/lib/src/features/programming_reading/views/widgets/programming_hour_loading_state_widget.dart b/lib/src/features/programming_reading/views/widgets/programming_hour_loading_state_widget.dart index 7e087cd5..c55cd478 100644 --- a/lib/src/features/programming_reading/views/widgets/programming_hour_loading_state_widget.dart +++ b/lib/src/features/programming_reading/views/widgets/programming_hour_loading_state_widget.dart @@ -33,7 +33,8 @@ class _ProgrammingHourLoadingStateWidgetState void initState() { super.initState(); userHourTimeModel = UserHourTimeModel( - repeatHourTimeType: widget.initialUserHourTimeModel?.repeatHourTimeType ?? + repeatHourTimeType: + widget.initialUserHourTimeModel?.repeatHourTimeType ?? RepeatHourTimeType.daily, startingHour: widget.initialUserHourTimeModel?.startingHour ?? 7, startingMinute: widget.initialUserHourTimeModel?.startingMinute ?? 0, @@ -74,8 +75,9 @@ class _ProgrammingHourLoadingStateWidgetState height: 10, ), RepeatTimeWidget( - initialRepeatTimeSelected: - userHourTimeModel.repeatHourTimeType.toIntValue(), + initialRepeatTimeSelected: userHourTimeModel + .repeatHourTimeType + .toIntValue(), onSelectedRepeatTime: (int selectedRepeatTime) { setState(() { userHourTimeModel = userHourTimeModel.copyWith( @@ -91,19 +93,20 @@ class _ProgrammingHourLoadingStateWidgetState ), HourTimeSelectedWidget( userHourTimeModel: userHourTimeModel, - onSelectedTimes: ( - TimeOfDay startingTime, - TimeOfDay endingTime, - ) { - setState(() { - userHourTimeModel = userHourTimeModel.copyWith( - startingHour: startingTime.hour, - startingMinute: startingTime.minute, - endingHour: endingTime.hour, - endingMinute: endingTime.minute, - ); - }); - }, + onSelectedTimes: + ( + TimeOfDay startingTime, + TimeOfDay endingTime, + ) { + setState(() { + userHourTimeModel = userHourTimeModel.copyWith( + startingHour: startingTime.hour, + startingMinute: startingTime.minute, + endingHour: endingTime.hour, + endingMinute: endingTime.minute, + ); + }); + }, ), const Spacer(), BookifyOutlinedButton.expanded( diff --git a/lib/src/features/reading_page_time_calculator/views/reading_page_time_calculator_page.dart b/lib/src/features/reading_page_time_calculator/views/reading_page_time_calculator_page.dart index a3cb7e9d..d05acb39 100644 --- a/lib/src/features/reading_page_time_calculator/views/reading_page_time_calculator_page.dart +++ b/lib/src/features/reading_page_time_calculator/views/reading_page_time_calculator_page.dart @@ -38,7 +38,7 @@ class ReadingPageTimeCalculatorPage extends StatelessWidget { child: BookifyElevatedButton.expanded( text: 'calculate-time-button'.i18n(), onPressed: () async { - await Navigator.pushNamed( + await Navigator.pushNamed( context, ReadingPageTimerPage.routeName, ); diff --git a/lib/src/features/readings/views/widgets/reading_widget.dart b/lib/src/features/readings/views/widgets/reading_widget.dart index 93fe807e..2c40bd00 100644 --- a/lib/src/features/readings/views/widgets/reading_widget.dart +++ b/lib/src/features/readings/views/widgets/reading_widget.dart @@ -148,10 +148,10 @@ class ReadingWidget extends StatelessWidget { ), ), ], - ) + ), ], ), - ) + ), ], ), ), diff --git a/lib/src/features/readings/views/widgets/readings_loaded_state_widget.dart b/lib/src/features/readings/views/widgets/readings_loaded_state_widget.dart index ca28dde5..3dec794a 100644 --- a/lib/src/features/readings/views/widgets/readings_loaded_state_widget.dart +++ b/lib/src/features/readings/views/widgets/readings_loaded_state_widget.dart @@ -43,9 +43,10 @@ class ReadingsLoadedStateWidget extends StatelessWidget { onTap: () async { final readingIsChanged = await Navigator.of(context).pushNamed( - ReadingsDetailPage.routeName, - arguments: readingsDto[index], - ) as bool?; + ReadingsDetailPage.routeName, + arguments: readingsDto[index], + ) + as bool?; if (readingIsChanged != null && readingIsChanged) { onRefreshPage(); diff --git a/lib/src/features/settings/views/widgets/widgets.dart b/lib/src/features/settings/views/widgets/widgets.dart index cfd89194..18378688 100644 --- a/lib/src/features/settings/views/widgets/widgets.dart +++ b/lib/src/features/settings/views/widgets/widgets.dart @@ -1,3 +1,3 @@ export 'package:bookify/src/features/settings/views/widgets/theme_settings.dart'; export 'package:bookify/src/features/settings/views/widgets/time_reading_settings.dart'; -export 'package:bookify/src/features/settings/views/widgets/hour_reading_settings.dart'; \ No newline at end of file +export 'package:bookify/src/features/settings/views/widgets/hour_reading_settings.dart'; diff --git a/lib/src/features/time_picker/views/time_picker_page.dart b/lib/src/features/time_picker/views/time_picker_page.dart index 39082d69..50522448 100644 --- a/lib/src/features/time_picker/views/time_picker_page.dart +++ b/lib/src/features/time_picker/views/time_picker_page.dart @@ -80,56 +80,58 @@ class _TimePickerPageState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), - body: LayoutBuilder(builder: (context, constraints) { - final isSmallDevice = constraints.biggest.isSmallDevice(); + body: LayoutBuilder( + builder: (context, constraints) { + final isSmallDevice = constraints.biggest.isSmallDevice(); - return SingleChildScrollView( - child: SizedBox( - height: isSmallDevice - ? MediaQuery.sizeOf(context).height - : constraints.biggest.height, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16.0, - horizontal: 30.0, - ), - child: Column( - children: [ - const SizedBox( - height: 10, - ), - TimePickerWidget( - onTimeSelected: (TimeOfDay time) { - setState(() { - startingTime = time; - }); - }, - hour: startingTime.hour, - minute: startingTime.minute, - ), - const Text('|'), - Text('to-time'.i18n()), - const Text('|'), - TimePickerWidget( - onTimeSelected: (TimeOfDay time) { - setState(() { - endingTime = time; - }); - }, - hour: endingTime.hour, - minute: endingTime.minute, - ), - const Spacer(), - BookifyOutlinedButton.expanded( - text: 'define-return-button'.i18n(), - onPressed: _defineTimer, - ) - ], + return SingleChildScrollView( + child: SizedBox( + height: isSmallDevice + ? MediaQuery.sizeOf(context).height + : constraints.biggest.height, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 16.0, + horizontal: 30.0, + ), + child: Column( + children: [ + const SizedBox( + height: 10, + ), + TimePickerWidget( + onTimeSelected: (TimeOfDay time) { + setState(() { + startingTime = time; + }); + }, + hour: startingTime.hour, + minute: startingTime.minute, + ), + const Text('|'), + Text('to-time'.i18n()), + const Text('|'), + TimePickerWidget( + onTimeSelected: (TimeOfDay time) { + setState(() { + endingTime = time; + }); + }, + hour: endingTime.hour, + minute: endingTime.minute, + ), + const Spacer(), + BookifyOutlinedButton.expanded( + text: 'define-return-button'.i18n(), + onPressed: _defineTimer, + ), + ], + ), ), ), - ), - ); - }), + ); + }, + ), ); } } diff --git a/lib/src/features/time_picker/views/widgets/time_picker_widget.dart b/lib/src/features/time_picker/views/widgets/time_picker_widget.dart index fc8cce3f..97af8531 100644 --- a/lib/src/features/time_picker/views/widgets/time_picker_widget.dart +++ b/lib/src/features/time_picker/views/widgets/time_picker_widget.dart @@ -118,7 +118,7 @@ class TimePickerWidget extends StatelessWidget { ), ), ], - ) + ), ], ), ), diff --git a/lib/src/shared/constants/audios/bookify_audios.dart b/lib/src/shared/constants/audios/bookify_audios.dart index dc108ae8..fcc9b460 100644 --- a/lib/src/shared/constants/audios/bookify_audios.dart +++ b/lib/src/shared/constants/audios/bookify_audios.dart @@ -1,7 +1,6 @@ - class BookifyAudios { BookifyAudios._(); /// Audio for timer ![](bookify/assets/audios/timer.mp3) static const timerAudio = 'assets/audios/timer.mp3'; -} \ No newline at end of file +} diff --git a/lib/src/shared/constants/database_scripts/database_scripts.dart b/lib/src/shared/constants/database_scripts/database_scripts.dart index 2c07e8c6..7da40777 100644 --- a/lib/src/shared/constants/database_scripts/database_scripts.dart +++ b/lib/src/shared/constants/database_scripts/database_scripts.dart @@ -2,7 +2,7 @@ class DatabaseScripts { ///Get the name of database : bookify.db String get databaseName => _databaseName; -//Table Names Getters + //Table Names Getters String get bookTableName => _bookTableName; String get authorTableName => _authorTableName; String get categoryTableName => _categoryTableName; @@ -13,7 +13,7 @@ class DatabaseScripts { String get bookcaseTableName => _bookcaseTableName; String get bookOnCaseTableName => _bookOnCaseTableName; -//Tables Scripts Getters + //Tables Scripts Getters /// Create a table for [BookModel] String get bookScript => _bookScript; @@ -58,7 +58,8 @@ class DatabaseScripts { static const String _bookcaseTableName = 'bookcase'; static const String _bookOnCaseTableName = 'bookOnCase'; - static const String _bookScript = ''' + static const String _bookScript = + ''' CREATE TABLE $_bookTableName ( id TEXT UNIQUE NOT NULL PRIMARY KEY, title TEXT NOT NULL, @@ -73,21 +74,24 @@ class DatabaseScripts { ) '''; - static const String _authorScript = ''' + static const String _authorScript = + ''' CREATE TABLE $_authorTableName ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL ) '''; - static const String _categoryScript = ''' + static const String _categoryScript = + ''' CREATE TABLE $_categoryTableName ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL ) '''; - static const String _bookAuthorsScript = ''' + static const String _bookAuthorsScript = + ''' CREATE TABLE $_bookAuthorsTableName ( bookId TEXT NOT NULL, authorId INTEGER NOT NULL, @@ -97,7 +101,8 @@ class DatabaseScripts { ) '''; - static const String _bookCategoriesScript = ''' + static const String _bookCategoriesScript = + ''' CREATE TABLE $_bookCategoriesTableName ( bookId TEXT NOT NULL, categoryId INTEGER NOT NULL, @@ -107,7 +112,8 @@ class DatabaseScripts { ) '''; - static const String _bookReadingScript = ''' + static const String _bookReadingScript = + ''' CREATE TABLE $_bookReadingTableName ( id INTEGER PRIMARY KEY AUTOINCREMENT, pagesReaded INTEGER NOT NULL, @@ -117,7 +123,8 @@ class DatabaseScripts { ) '''; - static const String _loanScript = ''' + static const String _loanScript = + ''' CREATE TABLE $_loanTableName ( id INTEGER PRIMARY KEY AUTOINCREMENT, observation TEXT, @@ -129,7 +136,8 @@ class DatabaseScripts { ) '''; - static const String _bookCaseScript = ''' + static const String _bookCaseScript = + ''' CREATE TABLE $_bookcaseTableName ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, @@ -138,7 +146,8 @@ class DatabaseScripts { ) '''; - static const String _bookOnCaseScript = ''' + static const String _bookOnCaseScript = + ''' CREATE TABLE $_bookOnCaseTableName ( bookId TEXT NOT NULL, bookcaseId INTEGER NOT NULL, diff --git a/lib/src/shared/constants/icons/bookify_icons.dart b/lib/src/shared/constants/icons/bookify_icons.dart index 10c7c55b..9b367083 100644 --- a/lib/src/shared/constants/icons/bookify_icons.dart +++ b/lib/src/shared/constants/icons/bookify_icons.dart @@ -14,12 +14,24 @@ class BookifyIcons { static const _kFontFam = 'BookifyIcons'; static const String? _kFontPkg = null; - static const IconData qr_code = - IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData bookcase = - IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData bookcase_outlined = - IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); - static const IconData isbn = - IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData qr_code = IconData( + 0xe800, + fontFamily: _kFontFam, + fontPackage: _kFontPkg, + ); + static const IconData bookcase = IconData( + 0xe801, + fontFamily: _kFontFam, + fontPackage: _kFontPkg, + ); + static const IconData bookcase_outlined = IconData( + 0xe802, + fontFamily: _kFontFam, + fontPackage: _kFontPkg, + ); + static const IconData isbn = IconData( + 0xe803, + fontFamily: _kFontFam, + fontPackage: _kFontPkg, + ); } diff --git a/lib/src/shared/enums/sign_in_type.dart b/lib/src/shared/enums/sign_in_type.dart index b0b7a562..6dc02a07 100644 --- a/lib/src/shared/enums/sign_in_type.dart +++ b/lib/src/shared/enums/sign_in_type.dart @@ -1,8 +1,7 @@ enum SignInType { google, apple, - facebook - ; + facebook; static SignInType toType(int value) { return switch (value) { diff --git a/lib/src/shared/providers/blocs/books_picker_bloc_providers.dart b/lib/src/shared/providers/blocs/books_picker_bloc_providers.dart index 38d1138d..690141f9 100644 --- a/lib/src/shared/providers/blocs/books_picker_bloc_providers.dart +++ b/lib/src/shared/providers/blocs/books_picker_bloc_providers.dart @@ -20,5 +20,5 @@ final booksPickerBlocProviders = [ create: (context) => SeparateBooksPickerBloc( context.read(), ), - ) + ), ]; diff --git a/lib/src/shared/providers/blocs/loan_bloc_providers.dart b/lib/src/shared/providers/blocs/loan_bloc_providers.dart index 3cae9be8..597838f3 100644 --- a/lib/src/shared/providers/blocs/loan_bloc_providers.dart +++ b/lib/src/shared/providers/blocs/loan_bloc_providers.dart @@ -9,4 +9,4 @@ final loanBlocProviders = [ context.read(), ), ), -]; \ No newline at end of file +]; diff --git a/lib/src/shared/providers/blocs/user_information_bloc_providers.dart b/lib/src/shared/providers/blocs/user_information_bloc_providers.dart index 6caa86a3..2f5f9591 100644 --- a/lib/src/shared/providers/blocs/user_information_bloc_providers.dart +++ b/lib/src/shared/providers/blocs/user_information_bloc_providers.dart @@ -10,4 +10,4 @@ final userInformationBlocProviders = [ context.read(), ), ), -]; \ No newline at end of file +]; diff --git a/lib/src/shared/routes/routes.dart b/lib/src/shared/routes/routes.dart index 324c878b..3796f63f 100644 --- a/lib/src/shared/routes/routes.dart +++ b/lib/src/shared/routes/routes.dart @@ -45,19 +45,19 @@ abstract class Routes { ProgrammingReadingPage.routeName: (context) => const ProgrammingReadingPage(), TimePickerPage.routeName: (context) => TimePickerPage( - userHourTimeModel: - ModalRoute.of(context)!.settings.arguments as UserHourTimeModel?, - ), + userHourTimeModel: + ModalRoute.of(context)!.settings.arguments as UserHourTimeModel?, + ), NotificationsPage.routeName: (context) => const NotificationsPage(), RootPage.routeName: (context) => const RootPage(), BookDetailPage.routeName: (context) => BookDetailPage( - bookModel: ModalRoute.of(context)!.settings.arguments as BookModel, - ), + bookModel: ModalRoute.of(context)!.settings.arguments as BookModel, + ), QrCodeScannerPage.routeName: (context) => const QrCodeScannerPage(), BookcaseDetailPage.routeName: (context) => BookcaseDetailPage( - bookcaseModel: - ModalRoute.of(context)!.settings.arguments as BookcaseModel, - ), + bookcaseModel: + ModalRoute.of(context)!.settings.arguments as BookcaseModel, + ), BookOnBookcaseDetailPage.routeName: (context) { final arguments = ModalRoute.of(context)!.settings.arguments as List; @@ -82,17 +82,17 @@ abstract class Routes { ), LoanInsertionPage.routeName: (context) => const LoanInsertionPage(), LoanDetailPage.routeName: (context) => LoanDetailPage( - loanId: ModalRoute.of(context)!.settings.arguments as int, - ), + loanId: ModalRoute.of(context)!.settings.arguments as int, + ), ReadingsInsertionPage.routeName: (context) => ReadingsInsertionPage( - book: ModalRoute.of(context)!.settings.arguments as BookModel, - ), + book: ModalRoute.of(context)!.settings.arguments as BookModel, + ), ReadingsDetailPage.routeName: (context) => ReadingsDetailPage( - readingDto: ModalRoute.of(context)!.settings.arguments as ReadingDto, - ), + readingDto: ModalRoute.of(context)!.settings.arguments as ReadingDto, + ), ReadingsTimerPage.routeName: (context) => ReadingsTimerPage( - readingDto: ModalRoute.of(context)!.settings.arguments as ReadingDto, - ), + readingDto: ModalRoute.of(context)!.settings.arguments as ReadingDto, + ), ContactsPickerPage.routeName: (context) => const ContactsPickerPage(), BooksPickerPage.routeName: (context) => const BooksPickerPage(), SettingsPage.routeName: (context) => const SettingsPage(), diff --git a/lib/src/shared/theme/app_theme.dart b/lib/src/shared/theme/app_theme.dart index 7afd9d48..64f665b2 100644 --- a/lib/src/shared/theme/app_theme.dart +++ b/lib/src/shared/theme/app_theme.dart @@ -229,7 +229,8 @@ const _segmentedButtonTheme = SegmentedButtonThemeData( ), ), side: WidgetStatePropertyAll( - BorderSide(color: AppColor.bookifySecondaryColor)), + BorderSide(color: AppColor.bookifySecondaryColor), + ), iconColor: WidgetStatePropertyAll(AppColor.bookifySecondaryColor), ), ); @@ -258,12 +259,13 @@ final _sliderTheme = SliderThemeData( ); const _radioTheme = RadioThemeData( - fillColor: WidgetStatePropertyAll( - AppColor.bookifySecondaryColor, - ), - overlayColor: WidgetStatePropertyAll( - AppColor.bookifySecondaryColor, - )); + fillColor: WidgetStatePropertyAll( + AppColor.bookifySecondaryColor, + ), + overlayColor: WidgetStatePropertyAll( + AppColor.bookifySecondaryColor, + ), +); const _textButtonTheme = TextButtonThemeData( style: ButtonStyle( diff --git a/lib/src/shared/widgets/book_with_detail_widget/book_with_detail_widget.dart b/lib/src/shared/widgets/book_with_detail_widget/book_with_detail_widget.dart index 7f1a0a62..476755ad 100644 --- a/lib/src/shared/widgets/book_with_detail_widget/book_with_detail_widget.dart +++ b/lib/src/shared/widgets/book_with_detail_widget/book_with_detail_widget.dart @@ -31,7 +31,7 @@ class BookWithDetailWidget extends StatelessWidget { ), BookifyRatingWidget( averageRating: bookAverageRating, - ) + ), ], ), const SizedBox( diff --git a/lib/src/shared/widgets/bookcase_widget/bookcase_widget.dart b/lib/src/shared/widgets/bookcase_widget/bookcase_widget.dart index e2baf151..97521387 100644 --- a/lib/src/shared/widgets/bookcase_widget/bookcase_widget.dart +++ b/lib/src/shared/widgets/bookcase_widget/bookcase_widget.dart @@ -128,7 +128,7 @@ class BookcaseWidget extends StatelessWidget { style: const TextStyle(fontSize: 14), ), ), - ) + ), ], ), ), diff --git a/lib/src/shared/widgets/buttons/buttons.dart b/lib/src/shared/widgets/buttons/buttons.dart index 0a98c61b..1e94e883 100644 --- a/lib/src/shared/widgets/buttons/buttons.dart +++ b/lib/src/shared/widgets/buttons/buttons.dart @@ -1,2 +1,2 @@ export 'bookify_outlined_button.dart'; -export 'bookify_elevated_button.dart'; \ No newline at end of file +export 'bookify_elevated_button.dart'; diff --git a/lib/src/shared/widgets/floating_action_button/rectangle_floating_action_button.dart b/lib/src/shared/widgets/floating_action_button/rectangle_floating_action_button.dart index 5fa30d92..497a29a9 100644 --- a/lib/src/shared/widgets/floating_action_button/rectangle_floating_action_button.dart +++ b/lib/src/shared/widgets/floating_action_button/rectangle_floating_action_button.dart @@ -6,7 +6,8 @@ class _FloatingActionButtonAlignedCenterDockerLocation @override Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) { - final double centerWidth = (scaffoldGeometry.scaffoldSize.width - + final double centerWidth = + (scaffoldGeometry.scaffoldSize.width - scaffoldGeometry.floatingActionButtonSize.width) / 2.0; diff --git a/lib/src/shared/widgets/list/selected_item_row/selected_item_row.dart b/lib/src/shared/widgets/list/selected_item_row/selected_item_row.dart index 2fdf545c..b952ee6a 100644 --- a/lib/src/shared/widgets/list/selected_item_row/selected_item_row.dart +++ b/lib/src/shared/widgets/list/selected_item_row/selected_item_row.dart @@ -27,16 +27,17 @@ class _SelectedItemRowState extends State { ( String selectedAllText, IconData selectedAllIcon, - ) _getAllIconButtonProperties() { + ) + _getAllIconButtonProperties() { return switch (_isSelectedAll) { true => ( - 'deselect-all-button'.i18n(), - Icons.deselect_rounded, - ), + 'deselect-all-button'.i18n(), + Icons.deselect_rounded, + ), false => ( - 'select-all-button'.i18n(), - Icons.select_all_rounded, - ), + 'select-all-button'.i18n(), + Icons.select_all_rounded, + ), }; } @@ -80,8 +81,9 @@ class _SelectedItemRowState extends State { IconButton( key: const Key('DeleteSelectedItemsButton'), onPressed: widget.onPressedDeleteButton, - tooltip: - 'delete-item-button-tooltip'.i18n([itemText.toLowerCase()]), + tooltip: 'delete-item-button-tooltip'.i18n([ + itemText.toLowerCase(), + ]), icon: const Icon(Icons.delete_rounded), ), ], diff --git a/pubspec.yaml b/pubspec.yaml index ed4c5472..b4e7008b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.12 +version: 2.11.13 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/core/database/sqllite_database_test.dart b/test/src/core/database/sqllite_database_test.dart index 01ef2bad..5c336838 100644 --- a/test/src/core/database/sqllite_database_test.dart +++ b/test/src/core/database/sqllite_database_test.dart @@ -86,21 +86,27 @@ void main() { final categories = [ ...booksModel[0].categories, - CategoryModel(name: 'category2') + CategoryModel(name: 'category2'), ]; // TEST insertion of book int bookRowsInserted = 0; for (var book in booksModel) { - bookRowsInserted = - await _insertOnDatabase(database, bookTableName, book.toMap()); + bookRowsInserted = await _insertOnDatabase( + database, + bookTableName, + book.toMap(), + ); } expect(bookRowsInserted, equals(2)); // TEST insertion of authors and retrive id for (var author in authors) { - author.id = - await _insertOnDatabase(database, authorTableName, author.toMap()); + author.id = await _insertOnDatabase( + database, + authorTableName, + author.toMap(), + ); } expect(authors[0].id, equals(1)); expect(authors[1].id, equals(2)); @@ -110,22 +116,35 @@ void main() { //TEST insertion of categories and retrive id for (var category in categories) { category.id = await _insertOnDatabase( - database, categoryTableName, category.toMap()); + database, + categoryTableName, + category.toMap(), + ); } expect(categories[0].id, equals(1)); expect(categories[1].id, equals(2)); // Insertion of relationship between books and authors - await _insertOnDatabase(database, bookAuthorsTableName, - {'bookId': booksModel[0].id, 'authorId': authors[0].id}); - await _insertOnDatabase(database, bookAuthorsTableName, - {'bookId': booksModel[0].id, 'authorId': authors[1].id}); - await _insertOnDatabase(database, bookAuthorsTableName, - {'bookId': booksModel[1].id, 'authorId': authors[0].id}); - await _insertOnDatabase(database, bookAuthorsTableName, - {'bookId': booksModel[1].id, 'authorId': authors[2].id}); - await _insertOnDatabase(database, bookAuthorsTableName, - {'bookId': booksModel[1].id, 'authorId': authors[3].id}); + await _insertOnDatabase(database, bookAuthorsTableName, { + 'bookId': booksModel[0].id, + 'authorId': authors[0].id, + }); + await _insertOnDatabase(database, bookAuthorsTableName, { + 'bookId': booksModel[0].id, + 'authorId': authors[1].id, + }); + await _insertOnDatabase(database, bookAuthorsTableName, { + 'bookId': booksModel[1].id, + 'authorId': authors[0].id, + }); + await _insertOnDatabase(database, bookAuthorsTableName, { + 'bookId': booksModel[1].id, + 'authorId': authors[2].id, + }); + await _insertOnDatabase(database, bookAuthorsTableName, { + 'bookId': booksModel[1].id, + 'authorId': authors[3].id, + }); final bookAuthorsList = await _queryOnDatabaseWhenId( database, @@ -139,15 +158,25 @@ void main() { expect(bookAuthorsList[2]['bookId'], equals('2')); // Insertion of relationship between books and categories - await _insertOnDatabase(database, bookCategoriesTableName, - {'bookId': booksModel[0].id, 'categoryId': categories[0].id}); - await _insertOnDatabase(database, bookCategoriesTableName, - {'bookId': booksModel[0].id, 'categoryId': categories[1].id}); - await _insertOnDatabase(database, bookCategoriesTableName, - {'bookId': booksModel[1].id, 'categoryId': categories[1].id}); + await _insertOnDatabase(database, bookCategoriesTableName, { + 'bookId': booksModel[0].id, + 'categoryId': categories[0].id, + }); + await _insertOnDatabase(database, bookCategoriesTableName, { + 'bookId': booksModel[0].id, + 'categoryId': categories[1].id, + }); + await _insertOnDatabase(database, bookCategoriesTableName, { + 'bookId': booksModel[1].id, + 'categoryId': categories[1].id, + }); final bookCategoriesList = await _queryOnDatabaseWhenId( - database, bookCategoriesTableName, 'bookId', [booksModel[0].id]); + database, + bookCategoriesTableName, + 'bookId', + [booksModel[0].id], + ); expect(bookCategoriesList[0]['bookId'], equals('1')); expect(bookCategoriesList[1]['bookId'], equals('1')); @@ -235,8 +264,11 @@ void main() { // TEST insertion of book int bookRowsInserted = 0; for (var book in booksModel) { - bookRowsInserted = - await _insertOnDatabase(database, bookTableName, book.toMap()); + bookRowsInserted = await _insertOnDatabase( + database, + bookTableName, + book.toMap(), + ); } expect(bookRowsInserted, equals(2)); @@ -248,11 +280,15 @@ void main() { }); // UPDATE book with status "reading" = 2 - await _updateRowWhenId(database, bookTableName, 'id', [ - booksModel[0].id - ], { - 'status': BookStatus.reading.statusNumber, - }); + await _updateRowWhenId( + database, + bookTableName, + 'id', + [booksModel[0].id], + { + 'status': BookStatus.reading.statusNumber, + }, + ); await _insertOnDatabase(database, readingTableName, { 'pagesReaded': 75, @@ -261,26 +297,40 @@ void main() { }); // UPDATE book with status "reading" = 2 - await _updateRowWhenId(database, bookTableName, 'id', [ - booksModel[1].id - ], { - 'status': BookStatus.reading.statusNumber, - }); + await _updateRowWhenId( + database, + bookTableName, + 'id', + [booksModel[1].id], + { + 'status': BookStatus.reading.statusNumber, + }, + ); // VERiFY that there are two books with the status "reading" = 2 - final booksUpdated = await database - .query(bookTableName, where: 'status = ?', whereArgs: ['2']); + final booksUpdated = await database.query( + bookTableName, + where: 'status = ?', + whereArgs: ['2'], + ); expect(booksUpdated.length, equals(2)); - final readingsListMap = await database.query(readingTableName, - orderBy: 'lastReadingDate DESC'); + final readingsListMap = await database.query( + readingTableName, + orderBy: 'lastReadingDate DESC', + ); expect(readingsListMap[0]['id'], equals(2)); expect(readingsListMap[1]['id'], equals(1)); //TEST UPDATE reading with id 2 final readingRowChanges = await _updateRowWhenId( - database, readingTableName, 'id', [1], {'pagesReaded': 55}); + database, + readingTableName, + 'id', + [1], + {'pagesReaded': 55}, + ); expect(readingRowChanges, equals(1)); final newReadingMap = await _queryOnDatabaseWhenId( @@ -315,7 +365,10 @@ void main() { // TEST insertion of book final bookRowInserted = await _insertOnDatabase( - database, bookTableName, booksModel[0].toMap()); + database, + bookTableName, + booksModel[0].toMap(), + ); expect(bookRowInserted, equals(1)); @@ -332,25 +385,34 @@ void main() { expect(loanId, equals(1)); //TEST UPDATE loan - final updateLoanRow = - await _updateRowWhenId(database, loanTableName, 'id', [ - loanId - ], { - 'devolutionDate': DateTime(2023, 06, 20).millisecondsSinceEpoch, - }); + final updateLoanRow = await _updateRowWhenId( + database, + loanTableName, + 'id', + [loanId], + { + 'devolutionDate': DateTime(2023, 06, 20).millisecondsSinceEpoch, + }, + ); expect(updateLoanRow, equals(1)); - final newLoanMap = - await _queryOnDatabaseWhenId(database, loanTableName, 'id', [loanId]); + final newLoanMap = await _queryOnDatabaseWhenId( + database, + loanTableName, + 'id', + [loanId], + ); expect(newLoanMap.first['id'], equals(1)); expect( DateTime.fromMillisecondsSinceEpoch( - newLoanMap.first['loanDate'] as int), + newLoanMap.first['loanDate'] as int, + ), equals(DateTime(2023, 05, 23)), ); expect( DateTime.fromMillisecondsSinceEpoch( - newLoanMap.first['devolutionDate'] as int), + newLoanMap.first['devolutionDate'] as int, + ), equals(DateTime(2023, 06, 20)), ); expect(newLoanMap.first['idContact'], equals('idContact')); @@ -358,11 +420,19 @@ void main() { //TEST DELETE book and expect its relations to be deleted. final bookDeletedRow = await _deleteRowWhenId( - database, bookTableName, 'id', [booksModel[0].id]); + database, + bookTableName, + 'id', + [booksModel[0].id], + ); expect(bookDeletedRow, equals(1)); - final deletedLoanRelationship = - await _queryOnDatabaseWhenId(database, loanTableName, 'id', [loanId]); + final deletedLoanRelationship = await _queryOnDatabaseWhenId( + database, + loanTableName, + 'id', + [loanId], + ); expect(deletedLoanRelationship, isEmpty); }); @@ -374,8 +444,11 @@ void main() { // TEST insertion of book int bookRowsInserted = 0; for (var book in booksModel) { - bookRowsInserted = - await _insertOnDatabase(database, bookTableName, book.toMap()); + bookRowsInserted = await _insertOnDatabase( + database, + bookTableName, + book.toMap(), + ); } expect(bookRowsInserted, equals(2)); @@ -432,7 +505,9 @@ void main() { ); expect(newBookcase.last['name'], equals('Tecnologia')); expect( - newBookcase.last['description'], equals('Meus livros de tecnologia')); + newBookcase.last['description'], + equals('Meus livros de tecnologia'), + ); //TEST DELETE bookcase and expect its relations to be deleted. final bookcaseRowDeleted = await _deleteRowWhenId( @@ -464,7 +539,10 @@ void main() { } Future _insertOnDatabase( - Database db, String table, Map values) async { + Database db, + String table, + Map values, +) async { return await db.insert(table, values); } diff --git a/test/src/core/helpers/locale_decimal_format/locale_decimal_format_extension_test.dart b/test/src/core/helpers/locale_decimal_format/locale_decimal_format_extension_test.dart index c3a14ee9..c96792e1 100644 --- a/test/src/core/helpers/locale_decimal_format/locale_decimal_format_extension_test.dart +++ b/test/src/core/helpers/locale_decimal_format/locale_decimal_format_extension_test.dart @@ -13,12 +13,14 @@ void main() { }); group('Test double to locale-specific String conversion ||', () { - test('should format number for pt_BR locale with default decimal digits', - () { - Intl.defaultLocale = 'pt_BR'; - final formattedNumber = number.toLocaleDecimalFormat(); - expect(formattedNumber, '1.234,56'); - }); + test( + 'should format number for pt_BR locale with default decimal digits', + () { + Intl.defaultLocale = 'pt_BR'; + final formattedNumber = number.toLocaleDecimalFormat(); + expect(formattedNumber, '1.234,56'); + }, + ); test('should format number for it_IT locale with 2 decimal digits', () { final formattedNumber = number.toLocaleDecimalFormat( diff --git a/test/src/core/models/book_model_test.dart b/test/src/core/models/book_model_test.dart index dbf2d32f..5998312f 100644 --- a/test/src/core/models/book_model_test.dart +++ b/test/src/core/models/book_model_test.dart @@ -33,15 +33,17 @@ void main() { ); test( - 'should return false when comparing instances with different properties', - () { - expect(book1 == book2, false); - }); + 'should return false when comparing instances with different properties', + () { + expect(book1 == book2, false); + }, + ); test( - 'should return a different hashCode for instances with different properties', - () { - expect(book1.hashCode != book2.hashCode, true); - }); + 'should return a different hashCode for instances with different properties', + () { + expect(book1.hashCode != book2.hashCode, true); + }, + ); }); } diff --git a/test/src/features/about/bloc/about_bloc_test.dart b/test/src/features/about/bloc/about_bloc_test.dart index ee301c0c..bc3a5b8c 100644 --- a/test/src/features/about/bloc/about_bloc_test.dart +++ b/test/src/features/about/bloc/about_bloc_test.dart @@ -44,8 +44,9 @@ void main() { blocTest( 'Test GotAppVersionEvent work when throw Generic Exception', build: () => aboutBloc, - setUp: () => when(() => appVersionService.getAppVersion()) - .thenThrow(Exception('Generic Error')), + setUp: () => when( + () => appVersionService.getAppVersion(), + ).thenThrow(Exception('Generic Error')), act: (bloc) => bloc.add(GotAppVersionEvent()), verify: (_) => verify(() => appVersionService.getAppVersion()).called(1), expect: () => [ diff --git a/test/src/features/notifications/bloc/notifications_bloc_test.dart b/test/src/features/notifications/bloc/notifications_bloc_test.dart index bab174f4..c93381a8 100644 --- a/test/src/features/notifications/bloc/notifications_bloc_test.dart +++ b/test/src/features/notifications/bloc/notifications_bloc_test.dart @@ -30,19 +30,20 @@ void main() { blocTest( 'Test GotNotificationsEvent work', build: () => notificationsBloc, - setUp: () => when( - () => notificationsService.getNotifications(), - ).thenAnswer( - (_) async => [ - CustomNotificationModel( - id: 1, - notificationChannel: NotificationChannel.loanChannel, - title: 'title', - body: 'body', - scheduledDate: DateTime.now(), + setUp: () => + when( + () => notificationsService.getNotifications(), + ).thenAnswer( + (_) async => [ + CustomNotificationModel( + id: 1, + notificationChannel: NotificationChannel.loanChannel, + title: 'title', + body: 'body', + scheduledDate: DateTime.now(), + ), + ], ), - ], - ), act: (bloc) => bloc.add( GotNotificationsEvent(), ), @@ -58,11 +59,12 @@ void main() { blocTest( 'Test GotNotificationsEvent work when notifications is empty', build: () => notificationsBloc, - setUp: () => when( - () => notificationsService.getNotifications(), - ).thenAnswer( - (_) async => [], - ), + setUp: () => + when( + () => notificationsService.getNotifications(), + ).thenAnswer( + (_) async => [], + ), act: (bloc) => bloc.add( GotNotificationsEvent(), ), diff --git a/test/src/features/qr_code_scanner/views/qr_code_scanner_page_test.dart b/test/src/features/qr_code_scanner/views/qr_code_scanner_page_test.dart index f3ce2445..b16d7b0e 100644 --- a/test/src/features/qr_code_scanner/views/qr_code_scanner_page_test.dart +++ b/test/src/features/qr_code_scanner/views/qr_code_scanner_page_test.dart @@ -4,8 +4,9 @@ import 'package:flutter_test/flutter_test.dart'; const qrCodeScannerWidgetKey = Key('qrCodeScannerWidget'); const changeModeTextButtonKey = Key('changeModeTextButton'); -const isbnManuallyTextFormFieldWidgetKey = - Key('isbnManuallyTextFormFieldWidget'); +const isbnManuallyTextFormFieldWidgetKey = Key( + 'isbnManuallyTextFormFieldWidget', +); const isbnManuallyOutlinedButtonKey = Key('isbnManuallyOutlinedButton'); const isbnManuallyTextFormFieldKey = Key('isbnManuallyTextFormField'); diff --git a/test/src/mocks/json/books_json_mock.dart b/test/src/mocks/json/books_json_mock.dart index f2fed8f5..f0084edb 100644 --- a/test/src/mocks/json/books_json_mock.dart +++ b/test/src/mocks/json/books_json_mock.dart @@ -16,11 +16,11 @@ const authorJsonBooksMock = { 'ratingsCount': 2, 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=IsuqmVlFo30C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=IsuqmVlFo30C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=IsuqmVlFo30C&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=IsuqmVlFo30C&source=gbs_api', + }, }, //2 @@ -38,11 +38,11 @@ const authorJsonBooksMock = { 'ratingsCount': 58, 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=dFlImpewmqUC&printsec=frontcover&img=1&zoom=1&source=gbs_api' + 'http://books.google.com/books/content?id=dFlImpewmqUC&printsec=frontcover&img=1&zoom=1&source=gbs_api', }, 'infoLink': - 'http://books.google.com.br/books?id=dFlImpewmqUC&dq=inauthor:J.R.R.+Tolkien%27&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api' - } + 'http://books.google.com.br/books?id=dFlImpewmqUC&dq=inauthor:J.R.R.+Tolkien%27&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api', + }, }, //3 @@ -58,11 +58,11 @@ const authorJsonBooksMock = { 'categories': ['Fiction'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=HTgpAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=HTgpAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=HTgpAwAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=HTgpAwAAQBAJ&source=gbs_api', + }, }, //4 @@ -80,11 +80,11 @@ const authorJsonBooksMock = { 'ratingsCount': 22, 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=05Cj67qkoaoC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=05Cj67qkoaoC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=05Cj67qkoaoC&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=05Cj67qkoaoC&source=gbs_api', + }, }, //5 @@ -102,13 +102,13 @@ const authorJsonBooksMock = { 'ratingsCount': 28, 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=HbG0jd66h3EC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=HbG0jd66h3EC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'http://books.google.com.br/books?id=HbG0jd66h3EC&dq=inauthor:J.R.R.+Tolkien%27&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api' - } - } - ] + 'http://books.google.com.br/books?id=HbG0jd66h3EC&dq=inauthor:J.R.R.+Tolkien%27&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api', + }, + }, + ], }; // this is a const list of 5 google books by Author @@ -127,11 +127,11 @@ const publisherJsonBooksMock = { 'categories': ['Computers'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=mKW6BAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=mKW6BAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=mKW6BAAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=mKW6BAAAQBAJ&source=gbs_api', + }, }, //2 @@ -147,11 +147,11 @@ const publisherJsonBooksMock = { 'categories': ['Health & Fitness'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=TjziAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=TjziAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=TjziAwAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=TjziAwAAQBAJ&source=gbs_api', + }, }, //3 @@ -167,11 +167,11 @@ const publisherJsonBooksMock = { 'categories': ['Mathematics'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=TXblAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=TXblAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=TXblAwAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=TXblAwAAQBAJ&source=gbs_api', + }, }, //4 @@ -187,11 +187,11 @@ const publisherJsonBooksMock = { 'categories': ['Computers'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=JMKbBAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=JMKbBAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=JMKbBAAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=JMKbBAAAQBAJ&source=gbs_api', + }, }, //5 @@ -207,13 +207,13 @@ const publisherJsonBooksMock = { 'categories': ['Computers'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=I0MlDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=I0MlDQAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=I0MlDQAAQBAJ&source=gbs_api' - } - } - ] + 'https://play.google.com/store/books/details?id=I0MlDQAAQBAJ&source=gbs_api', + }, + }, + ], }; // this is a const list of 5 google books @@ -234,11 +234,11 @@ const allBooksMock = { 'ratingsCount': 1, 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=5unrAgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=5unrAgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=5unrAgAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=5unrAgAAQBAJ&source=gbs_api', + }, }, //2 @@ -254,11 +254,11 @@ const allBooksMock = { 'categories': ['Health & Fitness'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=Pm4uBAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=Pm4uBAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=Pm4uBAAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=Pm4uBAAAQBAJ&source=gbs_api', + }, }, //3 @@ -271,8 +271,8 @@ const allBooksMock = { 'Desde pequenos, descobrimos que os amigos são um bem precioso. Muitas crianças logo encontram seus pares. Outras têm mais dificuldades em se relacionar e se sentem sós, sem amigos. Artur era um desses. Todos os dias esperava na estação de trem que alguém viesse visitá-lo, mas nunca vinha ninguém. Até o dia em que ele resolveu procurar seus amigos em outras estações. As ilustrações, do próprio autor, enfatizam o texto, enchendo as páginas de amigos.', 'pageCount': 28, 'infoLink': - 'http://books.google.com.br/books?id=sQmtPwAACAAJ&dq=*&hl=&source=gbs_api' - } + 'http://books.google.com.br/books?id=sQmtPwAACAAJ&dq=*&hl=&source=gbs_api', + }, }, //4 @@ -283,7 +283,7 @@ const allBooksMock = { 'authors': [ 'Maria Cecília de Souza Minayo', 'Edinilsa Ramos de Souza', - 'Patrícia Constantino' + 'Patrícia Constantino', ], 'publisher': 'SciELO - Editora FIOCRUZ', 'description': @@ -292,11 +292,11 @@ const allBooksMock = { 'categories': ['Technology & Engineering'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=T-jrAgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=T-jrAgAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=T-jrAgAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=T-jrAgAAQBAJ&source=gbs_api', + }, }, //5 @@ -313,13 +313,13 @@ const allBooksMock = { 'categories': ['Juvenile Fiction'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=e6-tAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=e6-tAwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=e6-tAwAAQBAJ&source=gbs_api' - } - } - ] + 'https://play.google.com/store/books/details?id=e6-tAwAAQBAJ&source=gbs_api', + }, + }, + ], }; // this is a const list of 5 google books by title @@ -338,11 +338,11 @@ const titleBooksMock = { 'categories': ['Computers'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=RY7kp2dT0jwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=RY7kp2dT0jwC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=RY7kp2dT0jwC&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=RY7kp2dT0jwC&source=gbs_api', + }, }, //2 @@ -358,11 +358,11 @@ const titleBooksMock = { 'categories': ['Architecture'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=CWawDAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=CWawDAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=CWawDAAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=CWawDAAAQBAJ&source=gbs_api', + }, }, //3 @@ -378,11 +378,11 @@ const titleBooksMock = { 'categories': ['Architecture'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=o1rwDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=o1rwDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=o1rwDwAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=o1rwDwAAQBAJ&source=gbs_api', + }, }, //4 @@ -398,11 +398,11 @@ const titleBooksMock = { 'categories': ['Architecture'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=-DfnDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=-DfnDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=-DfnDwAAQBAJ&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=-DfnDwAAQBAJ&source=gbs_api', + }, }, //5 @@ -413,7 +413,7 @@ const titleBooksMock = { 'authors': [ 'Maria Aldecy Rodrigues de Lima', 'Cleidson de Jesus Rocha', - 'Ana Flávia de Lima Rocha' + 'Ana Flávia de Lima Rocha', ], 'publisher': 'Editora CRV', 'description': @@ -422,13 +422,13 @@ const titleBooksMock = { 'categories': ['Education'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=m61TEAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=m61TEAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=m61TEAAAQBAJ&source=gbs_api' - } - } - ] + 'https://play.google.com/store/books/details?id=m61TEAAAQBAJ&source=gbs_api', + }, + }, + ], }; // this is a const list of 5 google books by Category @@ -447,11 +447,11 @@ const categoryBooksMock = { 'categories': ['Fiction'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=OajEDNw4lMUC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=OajEDNw4lMUC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=OajEDNw4lMUC&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=OajEDNw4lMUC&source=gbs_api', + }, }, //2 @@ -467,11 +467,11 @@ const categoryBooksMock = { 'categories': ['Fiction'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=AUbf_9h5D6oC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=AUbf_9h5D6oC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'https://play.google.com/store/books/details?id=AUbf_9h5D6oC&source=gbs_api' - } + 'https://play.google.com/store/books/details?id=AUbf_9h5D6oC&source=gbs_api', + }, }, //3 @@ -487,11 +487,11 @@ const categoryBooksMock = { 'categories': ['Fiction'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=D0gVVh_FLJ8C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=D0gVVh_FLJ8C&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'http://books.google.com.br/books?id=D0gVVh_FLJ8C&dq=subject:Fiction&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api' - } + 'http://books.google.com.br/books?id=D0gVVh_FLJ8C&dq=subject:Fiction&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api', + }, }, //4 @@ -507,11 +507,11 @@ const categoryBooksMock = { 'categories': ['Fiction'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=nAQkDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=nAQkDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'http://books.google.com.br/books?id=nAQkDwAAQBAJ&dq=subject:Fiction&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api' - } + 'http://books.google.com.br/books?id=nAQkDwAAQBAJ&dq=subject:Fiction&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api', + }, }, //5 @@ -527,13 +527,13 @@ const categoryBooksMock = { 'categories': ['Fiction'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=1Uuexwzku9gC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=1Uuexwzku9gC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': - 'http://books.google.com.br/books?id=1Uuexwzku9gC&dq=subject:Fiction&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api' - } - } - ] + 'http://books.google.com.br/books?id=1Uuexwzku9gC&dq=subject:Fiction&hl=&as_ebook=1&as_pt=BOOKS&source=gbs_api', + }, + }, + ], }; // this is a const list of Google book by ISBN @@ -551,11 +551,11 @@ const isbnJsonBookMock = { 'categories': ['Computers'], 'imageLinks': { 'thumbnail': - 'http://books.google.com/books/content?id=BOaPDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api' + 'http://books.google.com/books/content?id=BOaPDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api', }, 'infoLink': 'http://books.google.com.br/books?id=BOaPDwAAQBAJ&dq=isbn:9788550808161&hl=&source=gbs_api', - } - } - ] + }, + }, + ], }; From 16281733b64c602b5f7b4bc03e93ca0b78ae9dd9 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Tue, 26 May 2026 15:46:15 -0300 Subject: [PATCH 18/19] Refactor: Rename code for LocalDatabaseErrorCode (invalidData) to (conversionFailed) --- assets/lang/en_US.json | 2 +- assets/lang/it_IT.json | 2 +- assets/lang/pt_BR.json | 2 +- coverage/lcov.info | 296 +++++++++--------- .../local_database_error_code_extension.dart | 4 +- .../authors_repository_impl.dart | 4 +- .../book_authors_repository_impl.dart | 4 +- .../book_categories_repository_impl.dart | 4 +- .../book_on_case_repository_impl.dart | 2 +- .../bookcase_repository_impl.dart | 6 +- .../books_repository_impl.dart | 12 +- .../categories_repository_impl.dart | 4 +- .../loan_repository/loan_repository_impl.dart | 6 +- .../reading_repository_impl.dart | 6 +- .../bloc/bookcase_picker_bloc.dart | 2 +- lib/src/features/loan/bloc/loan_bloc.dart | 2 +- .../features/readings/bloc/readings_bloc.dart | 2 +- .../enums/local_database_error_code.dart | 2 +- pubspec.yaml | 2 +- .../authors_repository_impl_test.dart | 4 +- .../book_authors_repository_impl_test.dart | 2 +- .../book_categories_repository_impl_test.dart | 6 +- .../book_on_case_repository_impl_test.dart | 2 +- .../bookcase_repository_impl_test.dart | 6 +- .../books_repository_impl_test.dart | 14 +- .../categories_repository_impl_test.dart | 4 +- .../loan_repository_impl_test.dart | 6 +- .../reading_repository_impl_test.dart | 6 +- 28 files changed, 207 insertions(+), 207 deletions(-) diff --git a/assets/lang/en_US.json b/assets/lang/en_US.json index 3d462798..cee5ff47 100644 --- a/assets/lang/en_US.json +++ b/assets/lang/en_US.json @@ -269,7 +269,7 @@ "error-storage-invalid-value": "Data storage issue detected. Try logging out and logging back in: %s", "error-storage-write-failed": "Unable to save your changes. Check your storage space and try again: %s", "error-storage-read-failed": "Unable to load your data. Check your internet connection and try again: %s", - "error-local-database-invalid-data": "The data provided is not valid. %s", + "error-local-database-conversion-failed": "Failed to process data from database. %s", "error-local-database-not-null-constraint": "A required field is empty. %s", "error-local-database-open-failed": "Could not open the database. %s", "error-local-database-operation-failed": "Database operation failed during read, write, or update. %s", diff --git a/assets/lang/it_IT.json b/assets/lang/it_IT.json index 2a2ec9b2..2b578146 100644 --- a/assets/lang/it_IT.json +++ b/assets/lang/it_IT.json @@ -269,7 +269,7 @@ "error-storage-invalid-value": "Problema rilevato nel salvataggio dei dati. Prova a disconnetterti e riconnetterti: %s", "error-storage-write-failed": "Impossibile salvare le tue modifiche. Verifica lo spazio di archiviazione e riprova: %s", "error-storage-read-failed": "Impossibile caricare i tuoi dati. Verifica la tua connessione internet e riprova: %s", - "error-local-database-invalid-data": "I dati forniti non sono validi. %s", + "error-local-database-conversion-failed": "Errore nell'elaborazione dei dati dal database. %s", "error-local-database-not-null-constraint": "Un campo obbligatorio è vuoto. %s", "error-local-database-open-failed": "Impossibile aprire il database. %s", "error-local-database-operation-failed": "Operazione del database fallita durante lettura, scrittura o aggiornamento. %s", diff --git a/assets/lang/pt_BR.json b/assets/lang/pt_BR.json index 97beb612..40d7c444 100644 --- a/assets/lang/pt_BR.json +++ b/assets/lang/pt_BR.json @@ -269,7 +269,7 @@ "error-storage-invalid-value": "Problema detectado ao salvar dados. Tente fazer logout e depois login novamente: %s", "error-storage-write-failed": "Impossível salvar suas alterações. Verifique o espaço de armazenamento e tente novamente: %s", "error-storage-read-failed": "Impossível carregar seus dados. Verifique sua conexão com a internet e tente novamente: %s", - "error-local-database-invalid-data": "Os dados fornecidos não são válidos. %s", + "error-local-database-conversion-failed": "Falha ao processar dados do banco de dados. %s", "error-local-database-not-null-constraint": "Um campo obrigatório está vazio. %s", "error-local-database-open-failed": "Não foi possível abrir o banco de dados. %s", "error-local-database-operation-failed": "Operação do banco de dados falhou durante leitura, escrita ou atualização. %s", diff --git a/coverage/lcov.info b/coverage/lcov.info index 7dc362cb..6ced6eca 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -9,6 +9,29 @@ DA:15,9 LF:7 LH:7 end_of_record +SF:lib/src/shared/constants/database_scripts/database_scripts.dart +DA:3,0 +DA:6,4 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:11,2 +DA:12,2 +DA:13,2 +DA:14,2 +DA:18,1 +DA:21,1 +DA:24,1 +DA:27,1 +DA:30,1 +DA:34,1 +DA:41,1 +DA:44,1 +DA:47,1 +LF:19 +LH:18 +end_of_record SF:lib/src/core/models/author_model.dart DA:5,10 DA:10,9 @@ -157,29 +180,6 @@ DA:53,0 LF:22 LH:11 end_of_record -SF:lib/src/shared/constants/database_scripts/database_scripts.dart -DA:3,0 -DA:6,4 -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:11,2 -DA:12,2 -DA:13,2 -DA:14,2 -DA:18,1 -DA:21,1 -DA:24,1 -DA:27,1 -DA:30,1 -DA:34,1 -DA:41,1 -DA:44,1 -DA:47,1 -LF:19 -LH:18 -end_of_record SF:lib/src/core/helpers/date_time_format/date_time_format_extension.dart DA:14,1 DA:16,1 @@ -929,51 +929,6 @@ DA:41,2 LF:13 LH:13 end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:8,0 -DA:10,0 -DA:13,0 -DA:15,0 -DA:16,0 -DA:17,0 -DA:18,0 -DA:19,0 -DA:23,0 -DA:26,0 -DA:28,0 -LF:11 -LH:0 -end_of_record -SF:lib/src/core/errors/platform_exception/platform_exception.dart -DA:7,0 -DA:12,0 -DA:13,0 -LF:3 -LH:0 -end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart DA:21,1 DA:33,1 @@ -1055,6 +1010,51 @@ DA:248,1 LF:77 LH:76 end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:8,0 +DA:10,0 +DA:13,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:23,0 +DA:26,0 +DA:28,0 +LF:11 +LH:0 +end_of_record +SF:lib/src/core/errors/platform_exception/platform_exception.dart +DA:7,0 +DA:12,0 +DA:13,0 +LF:3 +LH:0 +end_of_record SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart DA:11,1 DA:17,1 @@ -1463,6 +1463,32 @@ DA:42,2 LF:21 LH:20 end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart +DA:11,1 +DA:20,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart +DA:12,1 +DA:14,2 +DA:16,1 +DA:18,2 +DA:20,2 +DA:22,1 +DA:23,1 +DA:25,1 +DA:26,1 +DA:27,1 +DA:28,1 +DA:29,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:36,1 +LF:16 +LH:16 +end_of_record SF:lib/src/shared/blocs/book_bloc/book_event.dart DA:10,1 DA:18,1 @@ -1580,32 +1606,6 @@ DA:227,0 LF:98 LH:75 end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_state.dart -DA:11,1 -DA:20,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/shared/cubits/user_logged_cubit/user_logged_cubit.dart -DA:12,1 -DA:14,2 -DA:16,1 -DA:18,2 -DA:20,2 -DA:22,1 -DA:23,1 -DA:25,1 -DA:26,1 -DA:27,1 -DA:28,1 -DA:29,1 -DA:32,1 -DA:33,1 -DA:34,1 -DA:36,1 -LF:16 -LH:16 -end_of_record SF:lib/src/shared/cubits/user_theme_cubit/user_theme_cubit.dart DA:12,1 DA:14,2 @@ -2269,7 +2269,7 @@ LF:27 LH:14 end_of_record SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart -DA:6,1 +DA:6,2 DA:11,4 DA:13,4 DA:14,4 @@ -2486,10 +2486,6 @@ DA:35,0 LF:12 LH:3 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 -end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 DA:10,0 @@ -3651,6 +3647,10 @@ DA:7,0 LF:1 LH:0 end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_event.dart DA:8,1 LF:1 @@ -3984,6 +3984,55 @@ SF:lib/src/features/contacts_picker/bloc/contacts_picker_event.dart LF:0 LH:0 end_of_record +SF:lib/src/features/my_books/bloc/my_books_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_bloc.dart +DA:14,3 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,2 +DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:45,1 +DA:51,1 +DA:56,2 +DA:58,2 +DA:59,1 +DA:62,1 +DA:63,2 +DA:67,2 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:75,1 +DA:76,1 +DA:77,1 +DA:79,1 +LF:34 +LH:34 +end_of_record +SF:lib/src/features/my_books/bloc/my_books_event.dart +DA:10,1 +LF:1 +LH:1 +end_of_record SF:lib/src/features/loan_insertion/bloc/loan_insertion_bloc.dart DA:20,1 DA:24,2 @@ -4039,55 +4088,6 @@ DA:13,1 LF:1 LH:1 end_of_record -SF:lib/src/features/my_books/bloc/my_books_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_bloc.dart -DA:14,3 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,2 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:45,1 -DA:51,1 -DA:56,2 -DA:58,2 -DA:59,1 -DA:62,1 -DA:63,2 -DA:67,2 -DA:68,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:72,1 -DA:75,1 -DA:76,1 -DA:77,1 -DA:79,1 -LF:34 -LH:34 -end_of_record -SF:lib/src/features/my_books/bloc/my_books_event.dart -DA:10,1 -LF:1 -LH:1 -end_of_record SF:lib/src/features/home/views/home_page.dart DA:11,1 DA:13,1 diff --git a/lib/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart b/lib/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart index 1beff5db..179bd63c 100644 --- a/lib/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart +++ b/lib/src/core/helpers/error_code/local_database_error_code/local_database_error_code_extension.dart @@ -19,8 +19,8 @@ extension LocalDatabaseErrorCodeExtension on LocalDatabaseErrorCode { 'error-local-database-not-null-constraint'.i18n([ messageArg, ]), - LocalDatabaseErrorCode.invalidData => - 'error-local-database-invalid-data'.i18n([ + LocalDatabaseErrorCode.conversionFailed => + 'error-local-database-conversion-failed'.i18n([ messageArg, ]), LocalDatabaseErrorCode.unknown => 'error-unknown'.i18n([ diff --git a/lib/src/core/repositories/author_repository/authors_repository_impl.dart b/lib/src/core/repositories/author_repository/authors_repository_impl.dart index e5c492b2..0619a28f 100644 --- a/lib/src/core/repositories/author_repository/authors_repository_impl.dart +++ b/lib/src/core/repositories/author_repository/authors_repository_impl.dart @@ -24,7 +24,7 @@ class AuthorsRepositoryImpl implements AuthorsRepository { return authorModel; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -51,7 +51,7 @@ class AuthorsRepositoryImpl implements AuthorsRepository { return actualAuthorId; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { diff --git a/lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart b/lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart index 99c201e7..7accdef0 100644 --- a/lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart +++ b/lib/src/core/repositories/book_authors_repository/book_authors_repository_impl.dart @@ -23,7 +23,7 @@ class BookAuthorsRepositoryImpl implements BookAuthorsRepository { if (bookAuthorsRelationships.last.isEmpty) { throw const LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: 'Impossible to fetch data', ); } @@ -31,7 +31,7 @@ class BookAuthorsRepositoryImpl implements BookAuthorsRepository { return bookAuthorsRelationships; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } diff --git a/lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart b/lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart index 3b7dd7a4..4d4c5931 100644 --- a/lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart +++ b/lib/src/core/repositories/book_categories_repository/book_categories_repository_impl.dart @@ -23,7 +23,7 @@ class BookCategoriesRepositoryImpl implements BookCategoriesRepository { if (bookCategoriesRelationships.last.isEmpty) { throw const LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: 'Impossible to fetch data', ); } @@ -31,7 +31,7 @@ class BookCategoriesRepositoryImpl implements BookCategoriesRepository { return bookCategoriesRelationships; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } diff --git a/lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart b/lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart index 7355e449..39cdd6e3 100644 --- a/lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart +++ b/lib/src/core/repositories/book_on_case_repository/book_on_case_repository_impl.dart @@ -41,7 +41,7 @@ class BookOnCaseRepositoryImpl implements BookOnCaseRepository { return bookId; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { diff --git a/lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart b/lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart index f8648983..4c43268a 100644 --- a/lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart +++ b/lib/src/core/repositories/bookcase_repository/bookcase_repository_impl.dart @@ -20,7 +20,7 @@ class BookcaseRepositoryImpl implements BookcaseRepository { return bookcases; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -41,7 +41,7 @@ class BookcaseRepositoryImpl implements BookcaseRepository { return bookcases; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -62,7 +62,7 @@ class BookcaseRepositoryImpl implements BookcaseRepository { return bookcase; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { diff --git a/lib/src/core/repositories/books_repository/books_repository_impl.dart b/lib/src/core/repositories/books_repository/books_repository_impl.dart index f52f6820..892fad5e 100644 --- a/lib/src/core/repositories/books_repository/books_repository_impl.dart +++ b/lib/src/core/repositories/books_repository/books_repository_impl.dart @@ -19,7 +19,7 @@ class BooksRepositoryImpl implements BooksRepository { return booksModel; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -40,7 +40,7 @@ class BooksRepositoryImpl implements BooksRepository { return bookModel; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -75,7 +75,7 @@ class BooksRepositoryImpl implements BooksRepository { return bookImage; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -96,7 +96,7 @@ class BooksRepositoryImpl implements BooksRepository { return books; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -132,7 +132,7 @@ class BooksRepositoryImpl implements BooksRepository { return bookStatus!; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -179,7 +179,7 @@ class BooksRepositoryImpl implements BooksRepository { rethrow; } on AssertionError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } diff --git a/lib/src/core/repositories/category_repository/categories_repository_impl.dart b/lib/src/core/repositories/category_repository/categories_repository_impl.dart index a5d1536a..7a404e52 100644 --- a/lib/src/core/repositories/category_repository/categories_repository_impl.dart +++ b/lib/src/core/repositories/category_repository/categories_repository_impl.dart @@ -24,7 +24,7 @@ class CategoriesRepositoryImpl implements CategoriesRepository { return categoryModel; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -51,7 +51,7 @@ class CategoriesRepositoryImpl implements CategoriesRepository { return actualAuthorId; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { diff --git a/lib/src/core/repositories/loan_repository/loan_repository_impl.dart b/lib/src/core/repositories/loan_repository/loan_repository_impl.dart index 1fa9b2c6..5f7c5cdc 100644 --- a/lib/src/core/repositories/loan_repository/loan_repository_impl.dart +++ b/lib/src/core/repositories/loan_repository/loan_repository_impl.dart @@ -25,7 +25,7 @@ class LoanRepositoryImpl implements LoanRepository { return loans; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -51,7 +51,7 @@ class LoanRepositoryImpl implements LoanRepository { return loans; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -72,7 +72,7 @@ class LoanRepositoryImpl implements LoanRepository { return loan; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { diff --git a/lib/src/core/repositories/reading_repository/reading_repository_impl.dart b/lib/src/core/repositories/reading_repository/reading_repository_impl.dart index adcfa4e2..518443b3 100644 --- a/lib/src/core/repositories/reading_repository/reading_repository_impl.dart +++ b/lib/src/core/repositories/reading_repository/reading_repository_impl.dart @@ -28,7 +28,7 @@ class ReadingRepositoryImpl implements ReadingRepository { return readings; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -57,7 +57,7 @@ class ReadingRepositoryImpl implements ReadingRepository { return readings; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { @@ -79,7 +79,7 @@ class ReadingRepositoryImpl implements ReadingRepository { return reading; } on TypeError catch (e) { throw LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: e.toString(), ); } on LocalDatabaseException { diff --git a/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart b/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart index 3380ea08..61cf4fd4 100644 --- a/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart +++ b/lib/src/features/books_picker/views/widgets/bookcase_picker/bloc/bookcase_picker_bloc.dart @@ -43,7 +43,7 @@ class BookcasePickerBloc if (bookcaseId == null) { emit( BookcasePickerErrorState( - errorCode: LocalDatabaseErrorCode.invalidData, + errorCode: LocalDatabaseErrorCode.conversionFailed, errorDescriptionMessage: 'Error: Bookcase not found', ), ); diff --git a/lib/src/features/loan/bloc/loan_bloc.dart b/lib/src/features/loan/bloc/loan_bloc.dart index 4d4af935..668c2b28 100644 --- a/lib/src/features/loan/bloc/loan_bloc.dart +++ b/lib/src/features/loan/bloc/loan_bloc.dart @@ -115,7 +115,7 @@ class LoanBloc extends Bloc { if (loan.id == null) { emit( LoanErrorState( - errorCode: LocalDatabaseErrorCode.invalidData, + errorCode: LocalDatabaseErrorCode.conversionFailed, errorDescriptionMessage: 'Error: Loan not found', ), ); diff --git a/lib/src/features/readings/bloc/readings_bloc.dart b/lib/src/features/readings/bloc/readings_bloc.dart index 643d1536..c215f614 100644 --- a/lib/src/features/readings/bloc/readings_bloc.dart +++ b/lib/src/features/readings/bloc/readings_bloc.dart @@ -97,7 +97,7 @@ class ReadingsBloc extends Bloc { if (reading.id == null) { emit( ReadingsErrorState( - errorCode: LocalDatabaseErrorCode.invalidData, + errorCode: LocalDatabaseErrorCode.conversionFailed, errorDescriptionMessage: 'Reading not found', ), ); diff --git a/lib/src/shared/enums/local_database_error_code.dart b/lib/src/shared/enums/local_database_error_code.dart index 38ba65b8..8abb8f08 100644 --- a/lib/src/shared/enums/local_database_error_code.dart +++ b/lib/src/shared/enums/local_database_error_code.dart @@ -2,7 +2,7 @@ enum LocalDatabaseErrorCode { uniqueConstraint, notNullConstraint, openFailed, - invalidData, + conversionFailed, operationFailed, unknown, } diff --git a/pubspec.yaml b/pubspec.yaml index b4e7008b..7400357e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.13 +version: 2.11.14 environment: sdk: ">=3.10.0 <4.0.0" diff --git a/test/src/core/repositories/author_repository/authors_repository_impl_test.dart b/test/src/core/repositories/author_repository/authors_repository_impl_test.dart index f941c932..e49aaa92 100644 --- a/test/src/core/repositories/author_repository/authors_repository_impl_test.dart +++ b/test/src/core/repositories/author_repository/authors_repository_impl_test.dart @@ -144,7 +144,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -165,7 +165,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); diff --git a/test/src/core/repositories/book_authors_repository/book_authors_repository_impl_test.dart b/test/src/core/repositories/book_authors_repository/book_authors_repository_impl_test.dart index fe304fcf..3ed70709 100644 --- a/test/src/core/repositories/book_authors_repository/book_authors_repository_impl_test.dart +++ b/test/src/core/repositories/book_authors_repository/book_authors_repository_impl_test.dart @@ -116,7 +116,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); diff --git a/test/src/core/repositories/book_categories_repository/book_categories_repository_impl_test.dart b/test/src/core/repositories/book_categories_repository/book_categories_repository_impl_test.dart index 9c856576..b89c3952 100644 --- a/test/src/core/repositories/book_categories_repository/book_categories_repository_impl_test.dart +++ b/test/src/core/repositories/book_categories_repository/book_categories_repository_impl_test.dart @@ -115,7 +115,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -130,7 +130,7 @@ void main() { ), ).thenThrow( const LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: 'Error on database', ), ); @@ -142,7 +142,7 @@ void main() { .having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ) .having( (e) => e.descriptionMessage, diff --git a/test/src/core/repositories/book_on_case_repository/book_on_case_repository_impl_test.dart b/test/src/core/repositories/book_on_case_repository/book_on_case_repository_impl_test.dart index 88f59a7a..72f406c1 100644 --- a/test/src/core/repositories/book_on_case_repository/book_on_case_repository_impl_test.dart +++ b/test/src/core/repositories/book_on_case_repository/book_on_case_repository_impl_test.dart @@ -201,7 +201,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); diff --git a/test/src/core/repositories/bookcase_repository/bookcase_repository_impl_test.dart b/test/src/core/repositories/bookcase_repository/bookcase_repository_impl_test.dart index ba3f9a6a..7beb547c 100644 --- a/test/src/core/repositories/bookcase_repository/bookcase_repository_impl_test.dart +++ b/test/src/core/repositories/bookcase_repository/bookcase_repository_impl_test.dart @@ -212,7 +212,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -267,7 +267,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -320,7 +320,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); diff --git a/test/src/core/repositories/books_repository/books_repository_impl_test.dart b/test/src/core/repositories/books_repository/books_repository_impl_test.dart index 391de7d5..186e6f33 100644 --- a/test/src/core/repositories/books_repository/books_repository_impl_test.dart +++ b/test/src/core/repositories/books_repository/books_repository_impl_test.dart @@ -360,7 +360,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -415,7 +415,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -472,7 +472,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -524,7 +524,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -579,7 +579,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -663,7 +663,7 @@ void main() { ), ).thenThrow( const LocalDatabaseException( - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, descriptionMessage: 'Invalid page count', ), ); @@ -677,7 +677,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); diff --git a/test/src/core/repositories/category_repository/categories_repository_impl_test.dart b/test/src/core/repositories/category_repository/categories_repository_impl_test.dart index cfc4216d..ab8a4abc 100644 --- a/test/src/core/repositories/category_repository/categories_repository_impl_test.dart +++ b/test/src/core/repositories/category_repository/categories_repository_impl_test.dart @@ -144,7 +144,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -165,7 +165,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); diff --git a/test/src/core/repositories/loan_repository/loan_repository_impl_test.dart b/test/src/core/repositories/loan_repository/loan_repository_impl_test.dart index ea21e36e..f6dd41bc 100644 --- a/test/src/core/repositories/loan_repository/loan_repository_impl_test.dart +++ b/test/src/core/repositories/loan_repository/loan_repository_impl_test.dart @@ -235,7 +235,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -297,7 +297,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -355,7 +355,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); diff --git a/test/src/core/repositories/reading_repository/reading_repository_impl_test.dart b/test/src/core/repositories/reading_repository/reading_repository_impl_test.dart index f81fe85d..422ab43a 100644 --- a/test/src/core/repositories/reading_repository/reading_repository_impl_test.dart +++ b/test/src/core/repositories/reading_repository/reading_repository_impl_test.dart @@ -202,7 +202,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -265,7 +265,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); @@ -324,7 +324,7 @@ void main() { isA().having( (e) => e.code, 'code', - LocalDatabaseErrorCode.invalidData, + LocalDatabaseErrorCode.conversionFailed, ), ), ); From 70a92ccdfcb85a3f4d9a6dd50e2aa1a21fa056f3 Mon Sep 17 00:00:00 2001 From: Edoardo Fabrizio De Iovanna Date: Wed, 27 May 2026 10:52:10 -0300 Subject: [PATCH 19/19] chore(android): temporarily ignore JVM target validation Bypass Kotlin JVM target validation in gradle.properties to unblock the release build. This is a temporary workaround due to an inconsistency between Java (11) and Kotlin (17) tasks inside the 'flutter_facebook_auth' plugin. The validation will be re-enabled once the plugin is updated. --- android/gradle.properties | 3 + coverage/lcov.info | 160 +++++++++++++++++++------------------- pubspec.yaml | 2 +- 3 files changed, 84 insertions(+), 81 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index 487ca27f..7f559cfb 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -14,3 +14,6 @@ android.uniquePackageNames=false android.dependency.useConstraints=true android.r8.strictFullModeForKeepRules=false android.r8.optimizedResourceShrinking=false + +#! TODO: Temporarily ignore JVM target validation until Facebook Auth Plugin is updated to support Java 17. --- IGNORE --- +kotlin.jvm.target.validation.mode = IGNORE diff --git a/coverage/lcov.info b/coverage/lcov.info index 6ced6eca..32f5d64d 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -929,6 +929,51 @@ DA:41,2 LF:13 LH:13 end_of_record +SF:lib/src/core/models/app_version_model.dart +DA:7,1 +DA:14,0 +DA:20,0 +DA:21,0 +DA:22,0 +DA:23,0 +DA:24,0 +DA:28,0 +DA:30,0 +DA:33,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +LF:19 +LH:1 +end_of_record +SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart +DA:8,0 +DA:10,0 +DA:13,0 +DA:15,0 +DA:16,0 +DA:17,0 +DA:18,0 +DA:19,0 +DA:23,0 +DA:26,0 +DA:28,0 +LF:11 +LH:0 +end_of_record +SF:lib/src/core/errors/platform_exception/platform_exception.dart +DA:7,0 +DA:12,0 +DA:13,0 +LF:3 +LH:0 +end_of_record SF:lib/src/core/services/book_service/book_service_impl.dart DA:21,1 DA:33,1 @@ -1010,51 +1055,6 @@ DA:248,1 LF:77 LH:76 end_of_record -SF:lib/src/core/models/app_version_model.dart -DA:7,1 -DA:14,0 -DA:20,0 -DA:21,0 -DA:22,0 -DA:23,0 -DA:24,0 -DA:28,0 -DA:30,0 -DA:33,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:40,0 -DA:43,0 -DA:45,0 -DA:46,0 -DA:47,0 -DA:48,0 -LF:19 -LH:1 -end_of_record -SF:lib/src/core/services/app_services/app_version_service/app_version_service_impl.dart -DA:8,0 -DA:10,0 -DA:13,0 -DA:15,0 -DA:16,0 -DA:17,0 -DA:18,0 -DA:19,0 -DA:23,0 -DA:26,0 -DA:28,0 -LF:11 -LH:0 -end_of_record -SF:lib/src/core/errors/platform_exception/platform_exception.dart -DA:7,0 -DA:12,0 -DA:13,0 -LF:3 -LH:0 -end_of_record SF:lib/src/core/services/bookcase_service/bookcase_service_impl.dart DA:11,1 DA:17,1 @@ -1432,7 +1432,7 @@ LF:23 LH:23 end_of_record SF:lib/src/core/errors/rest_client_exception/rest_client_exception.dart -DA:7,2 +DA:7,1 DA:12,0 DA:13,0 LF:3 @@ -2269,7 +2269,7 @@ LF:27 LH:14 end_of_record SF:lib/src/shared/widgets/center_circular_progress_indicator/center_circular_progress_indicator.dart -DA:6,2 +DA:6,1 DA:11,4 DA:13,4 DA:14,4 @@ -2486,6 +2486,10 @@ DA:35,0 LF:12 LH:3 end_of_record +SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart +LF:0 +LH:0 +end_of_record SF:lib/src/core/helpers/color_brightness/color_brightness_extension.dart DA:9,0 DA:10,0 @@ -3647,10 +3651,6 @@ DA:7,0 LF:1 LH:0 end_of_record -SF:lib/src/features/book_detail/views/widgets/book_pages_reading_time/bloc/book_pages_reading_time_event.dart -LF:0 -LH:0 -end_of_record SF:lib/src/features/books_picker/views/widgets/book_on_bookcase_picker/bloc/book_on_bookcase_picker_event.dart DA:8,1 LF:1 @@ -4287,6 +4287,35 @@ DA:43,3 LF:19 LH:18 end_of_record +SF:lib/src/features/notifications/bloc/notifications_state.dart +DA:12,1 +DA:21,1 +LF:2 +LH:2 +end_of_record +SF:lib/src/features/notifications/bloc/notifications_bloc.dart +DA:13,1 +DA:15,2 +DA:16,2 +DA:19,1 +DA:24,2 +DA:26,2 +DA:28,1 +DA:29,2 +DA:33,1 +DA:34,1 +DA:38,1 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:45,1 +DA:46,1 +DA:47,1 +DA:49,1 +LF:19 +LH:15 +end_of_record SF:lib/src/features/profile/bloc/profile_state.dart DA:10,1 DA:21,1 @@ -4338,35 +4367,6 @@ DA:10,1 LF:1 LH:1 end_of_record -SF:lib/src/features/notifications/bloc/notifications_state.dart -DA:12,1 -DA:21,1 -LF:2 -LH:2 -end_of_record -SF:lib/src/features/notifications/bloc/notifications_bloc.dart -DA:13,1 -DA:15,2 -DA:16,2 -DA:19,1 -DA:24,2 -DA:26,2 -DA:28,1 -DA:29,2 -DA:33,1 -DA:34,1 -DA:38,1 -DA:39,0 -DA:40,0 -DA:41,0 -DA:42,0 -DA:45,1 -DA:46,1 -DA:47,1 -DA:49,1 -LF:19 -LH:15 -end_of_record SF:lib/src/features/profile/views/widgets/user_information_row/bloc/user_information_bloc.dart DA:19,1 DA:24,2 diff --git a/pubspec.yaml b/pubspec.yaml index 7400357e..7b371c09 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A Flutter project that helps you search for books, add them to your publish_to: "none" -version: 2.11.14 +version: 2.11.15 environment: sdk: ">=3.10.0 <4.0.0"