diff --git a/example/.flutter-plugins b/example/.flutter-plugins index 62971ca..faaebcb 100644 --- a/example/.flutter-plugins +++ b/example/.flutter-plugins @@ -1,7 +1,8 @@ # This is a generated file; do not edit or check into version control. -file_picker=/Users/andrespacheco/.pub-cache/hosted/pub.dev/file_picker-6.1.1/ -flutter_plugin_android_lifecycle=/Users/andrespacheco/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.17/ -permission_handler=/Users/andrespacheco/.pub-cache/hosted/pub.dev/permission_handler-11.0.1/ -permission_handler_android=/Users/andrespacheco/.pub-cache/hosted/pub.dev/permission_handler_android-11.1.0/ -permission_handler_apple=/Users/andrespacheco/.pub-cache/hosted/pub.dev/permission_handler_apple-9.1.4/ -permission_handler_windows=/Users/andrespacheco/.pub-cache/hosted/pub.dev/permission_handler_windows-0.1.3/ +file_picker=/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/file_picker-6.2.1/ +flutter_plugin_android_lifecycle=/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.24/ +permission_handler=/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler-11.3.1/ +permission_handler_android=/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler_android-12.0.13/ +permission_handler_apple=/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler_apple-9.4.5/ +permission_handler_html=/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler_html-0.1.3+5/ +permission_handler_windows=/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler_windows-0.2.1/ diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index f84b0fb..0674d15 100644 --- a/example/.flutter-plugins-dependencies +++ b/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"file_picker","path":"/Users/andrespacheco/.pub-cache/hosted/pub.dev/file_picker-6.1.1/","native_build":true,"dependencies":[]},{"name":"permission_handler_apple","path":"/Users/andrespacheco/.pub-cache/hosted/pub.dev/permission_handler_apple-9.1.4/","native_build":true,"dependencies":[]}],"android":[{"name":"file_picker","path":"/Users/andrespacheco/.pub-cache/hosted/pub.dev/file_picker-6.1.1/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","path":"/Users/andrespacheco/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.17/","native_build":true,"dependencies":[]},{"name":"permission_handler_android","path":"/Users/andrespacheco/.pub-cache/hosted/pub.dev/permission_handler_android-11.1.0/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[{"name":"permission_handler_windows","path":"/Users/andrespacheco/.pub-cache/hosted/pub.dev/permission_handler_windows-0.1.3/","native_build":true,"dependencies":[]}],"web":[{"name":"file_picker","path":"/Users/andrespacheco/.pub-cache/hosted/pub.dev/file_picker-6.1.1/","dependencies":[]}]},"dependencyGraph":[{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]}],"date_created":"2025-01-15 16:39:31.651420","version":"3.24.1","swift_package_manager_enabled":false} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"file_picker","path":"/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/file_picker-6.2.1/","native_build":true,"dependencies":[]},{"name":"permission_handler_apple","path":"/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler_apple-9.4.5/","native_build":true,"dependencies":[]}],"android":[{"name":"file_picker","path":"/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/file_picker-6.2.1/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","path":"/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.24/","native_build":true,"dependencies":[]},{"name":"permission_handler_android","path":"/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler_android-12.0.13/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[{"name":"permission_handler_windows","path":"/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler_windows-0.2.1/","native_build":true,"dependencies":[]}],"web":[{"name":"file_picker","path":"/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/file_picker-6.2.1/","dependencies":[]},{"name":"permission_handler_html","path":"/Users/carlosdoffiny/.pub-cache/hosted/pub.dev/permission_handler_html-0.1.3+5/","dependencies":[]}]},"dependencyGraph":[{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_html","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_html","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]}],"date_created":"2025-02-03 12:59:21.332048","version":"3.24.3","swift_package_manager_enabled":false} \ No newline at end of file diff --git a/example/android/local.properties b/example/android/local.properties index d2faec8..d9cb6aa 100644 --- a/example/android/local.properties +++ b/example/android/local.properties @@ -1,2 +1,2 @@ -sdk.dir=/Users/andrespacheco/Library/Android/sdk -flutter.sdk=/Users/andrespacheco/Library/flutter \ No newline at end of file +sdk.dir=/Users/carlosdoffiny/Library/Android/sdk +flutter.sdk=/Users/carlosdoffiny/development/flutter \ No newline at end of file diff --git a/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_bloc.dart b/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_bloc.dart index f09871d..409838b 100644 --- a/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_bloc.dart +++ b/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_bloc.dart @@ -14,6 +14,7 @@ export 'package:avilatek_bloc/src/remote_data_paginated/paged_remote_data_state. /// /// Any Object/Primitive Data can be accessed via the /// [PagedRemoteDataInitialized.data] property. +/// Or via the [getDataFromState] method. abstract class PagedRemoteDataBloc extends Bloc> { /// @@ -21,13 +22,29 @@ abstract class PagedRemoteDataBloc _handler = PagedRemoteDataEventHandler(); on(_mapFetchNextPageRemoteDataToState); - on((event, emit) { + on((event, emit) { emit(PagedRemoteDataUninitialized()); add(const PagedRemoteDataFetchNextPage()); }); + + on((event, emit) { + add(const PagedRemoteDataFetchNextPage()); + }); } late PagedRemoteDataEventHandler _handler; + /// This method is used to access the data from the current state. + /// It returns a [List] if the state is [PagedRemoteDataInitialized], + /// otherwise it returns null. + /// This method is useful for accessing the data from the current state + /// without having to check the state type. + List? getDataFromState(PagedRemoteDataState state) { + if (state is PagedRemoteDataInitialized) { + return state.data; + } + return null; + } + /// Propagates the [PagedRemoteDataFetchNextPage] event down to the corresponding event /// handler. Future _mapFetchNextPageRemoteDataToState( @@ -48,7 +65,7 @@ abstract class PagedRemoteDataBloc ), onNextPageFetched: () => _handler.mapFetchNextPageRemoteDataToState( event, - state as PagedRemoteDataNextPageFetched, + state as PagedRemoteDataInitialized, emit, fetchAndParseNextPage, ), @@ -67,7 +84,8 @@ abstract class PagedRemoteDataBloc } else if (state is PagedRemoteDataUninitialized && onPagedRemoteDataUninitialized != null) { return onPagedRemoteDataUninitialized(); - } else if (state is PagedRemoteDataNextPageFetched && + } else if ((state is PagedRemoteDataNextPageFetched || + state is PagedRemoteDataNextPageFetchingFailure) && onNextPageFetched != null) { return onNextPageFetched(); } else { diff --git a/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_event.dart b/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_event.dart index cf26b7b..bf55985 100644 --- a/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_event.dart +++ b/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_event.dart @@ -31,12 +31,26 @@ class PagedRemoteDataFetchNextPage extends PagedRemoteDataEvent { /// {@template restart_remote_data} /// Event that triggers a restart, erasing currently loaded data. /// {@endtemplate} -class PagedRemoteDataRestart extends PagedRemoteDataEvent { +class PagedRemoteDataRestarted extends PagedRemoteDataEvent { /// {@macro restart_remote_data} - const PagedRemoteDataRestart({this.simulateError = false}); + const PagedRemoteDataRestarted({this.simulateError = false}); /// If true, the [PagedRemoteDataBloc] will simulate an error. final bool? simulateError; @override List get props => [simulateError]; } + +/// {@template fetch_remote_data} +/// Event that triggers the retry of the fetching of the next page. +/// {@endtemplate} +class PagedRemoteDataRetryFetchNextPage extends PagedRemoteDataEvent { + /// {@macro fetch_remote_data} + const PagedRemoteDataRetryFetchNextPage({this.simulateError = false}); + + /// If true, the [PagedRemoteDataBloc] will simulate an error. + final bool? simulateError; + + @override + List get props => [simulateError]; +} diff --git a/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_handler.dart b/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_handler.dart index 4633c22..1bdc359 100644 --- a/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_handler.dart +++ b/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_handler.dart @@ -41,11 +41,11 @@ class PagedRemoteDataEventHandler { } } catch (e) { emit(PagedRemoteDataFirstPageFetchingFailure(e)); - emit(PagedRemoteDataUninitialized()); } } - /// Handler for [PagedRemoteDataFetchNextPage] + [PagedRemoteDataNextPageFetched] combination. + /// Handler for [PagedRemoteDataFetchNextPage] + [PagedRemoteDataNextPageFetched] combination, and + /// [PagedRemoteDataNextPageFetchingFailure] to retry the fetch. /// Handles refetch of the remote data. /// /// On success it emits: [PagedRemoteDataNextPageFetching], @@ -55,7 +55,7 @@ class PagedRemoteDataEventHandler { /// [PagedRemoteDataNextPageFetchingFailure]. Future mapFetchNextPageRemoteDataToState( PagedRemoteDataFetchNextPage event, - PagedRemoteDataNextPageFetched state, + PagedRemoteDataInitialized state, Emitter> emit, Future<(List, bool)> Function( PagedRemoteDataState, @@ -63,6 +63,8 @@ class PagedRemoteDataEventHandler { ) fetchAndParseNextPage, ) async { try { + if (state is PagedRemoteDataLastPageFetched) return; + emit(PagedRemoteDataNextPageFetching(state)); if (event.simulateError ?? false) { diff --git a/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_state.dart b/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_state.dart index 73be21d..0e2ba9f 100644 --- a/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_state.dart +++ b/packages/avilatek_bloc/lib/src/remote_data_paginated/paged_remote_data_state.dart @@ -164,7 +164,7 @@ class PagedRemoteDataNextPageFetchingSuccess /// Temporal State that represents the failed fetch of the next page of data. /// {@endtemplate} class PagedRemoteDataNextPageFetchingFailure - extends PagedRemoteDataInitialized with PagedRemoteDataFailure { + extends PagedRemoteDataInitialized { /// {@macro remote_data_refetching_failed} PagedRemoteDataNextPageFetchingFailure(super.oldState, this.error) : super.clone(); @@ -175,3 +175,15 @@ class PagedRemoteDataNextPageFetchingFailure @override List get props => [...super.props, error]; } + +/// This state is emitted when the next page is being fetched again after a +/// failure. + +class PagedRemoteDataRetryNextPageFetching + extends PagedRemoteDataInitialized { + /// {@macro remote_data_loaded} + const PagedRemoteDataRetryNextPageFetching(super.data); + + /// {@macro remote_data_initialized.clone} + PagedRemoteDataRetryNextPageFetching.clone(super.oldState) : super.clone(); +} diff --git a/packages/avilatek_bloc/pubspec.yaml b/packages/avilatek_bloc/pubspec.yaml index bac5ae2..fc5432e 100644 --- a/packages/avilatek_bloc/pubspec.yaml +++ b/packages/avilatek_bloc/pubspec.yaml @@ -1,6 +1,6 @@ name: avilatek_bloc description: Avila Tek Blocs/Cubits -version: 0.2.0 +version: 0.2.1 publish_to: none environment: diff --git a/packages/avilatek_bloc/test/src/remote_data_paginated/paged_remote_data_bloc_test.dart b/packages/avilatek_bloc/test/src/remote_data_paginated/paged_remote_data_bloc_test.dart index 646dd96..451d33c 100644 --- a/packages/avilatek_bloc/test/src/remote_data_paginated/paged_remote_data_bloc_test.dart +++ b/packages/avilatek_bloc/test/src/remote_data_paginated/paged_remote_data_bloc_test.dart @@ -98,7 +98,7 @@ void main() { '''should restart the bloc and emit PagedRemoteDataFirstPageFetching when PagedRemoteDataRestart is added''', build: () => bloc, seed: () => const PagedRemoteDataLastPageFetched([1, 2, 3]), - act: (bloc) => bloc.add(const PagedRemoteDataRestart()), + act: (bloc) => bloc.add(const PagedRemoteDataRestarted()), expect: () => [ PagedRemoteDataUninitialized(), PagedRemoteDataFirstPageFetching(), diff --git a/packages/avilatek_bloc/test/src/remote_data_paginated/paged_remote_data_event_test.dart b/packages/avilatek_bloc/test/src/remote_data_paginated/paged_remote_data_event_test.dart index d1f8d51..63122ed 100644 --- a/packages/avilatek_bloc/test/src/remote_data_paginated/paged_remote_data_event_test.dart +++ b/packages/avilatek_bloc/test/src/remote_data_paginated/paged_remote_data_event_test.dart @@ -20,11 +20,11 @@ void main() { 'should return the correct properties of PagedRemoteDataRestart', () { expect( - const PagedRemoteDataRestart().props, + const PagedRemoteDataRestarted().props, containsAll([false]), ); expect( - const PagedRemoteDataRestart(simulateError: true).props, + const PagedRemoteDataRestarted(simulateError: true).props, containsAll([true]), ); },