From 7c4514d5609430f320cdcfcd26d795b9713b7f65 Mon Sep 17 00:00:00 2001 From: Andrea Bizzotto Date: Thu, 11 Apr 2024 12:09:32 +0200 Subject: [PATCH] Pagination improvements (#16) * Modify paginated providers to return TMDBMoviesResponse * Updated UI * Improved interceptor * Cleanup * Update Xcode project --- ios/Flutter/AppFrameworkInfo.plist | 2 +- ios/Podfile | 2 +- ios/Podfile.lock | 24 +- ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- lib/src/common_widgets/top_gradient.dart | 2 +- .../movies/data/movies_repository.dart | 13 +- .../movies/data/movies_repository.g.dart | 15 +- .../movies/domain/tmdb_movie.freezed.dart | 4 +- .../domain/tmdb_movies_response.freezed.dart | 4 +- .../presentation/movies/movie_list_tile.dart | 10 +- .../movies/movie_list_tile_shimmer.dart | 7 +- .../movies/movies_search_screen.dart | 81 +++--- lib/src/utils/logger_interceptor.dart | 59 ++++- pubspec.lock | 236 ++++++++++-------- pubspec.yaml | 84 +------ 16 files changed, 285 insertions(+), 262 deletions(-) diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist index 9625e10..7c56964 100644 --- a/ios/Flutter/AppFrameworkInfo.plist +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/ios/Podfile b/ios/Podfile index 44d4503..4966789 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -54,4 +54,4 @@ post_install do |installer| config.build_settings[deployment_target_key] = minimum_deployment_target end end -end \ No newline at end of file +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock index c4553a0..6c216d7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,23 +1,16 @@ PODS: - Flutter (1.0.0) - - FMDB (2.7.5): - - FMDB/standard (= 2.7.5) - - FMDB/standard (2.7.5) - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS - sqflite (0.0.3): - Flutter - - FMDB (>= 2.7.5) + - FlutterMacOS DEPENDENCIES: - Flutter (from `Flutter`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - - sqflite (from `.symlinks/plugins/sqflite/ios`) - -SPEC REPOS: - trunk: - - FMDB + - sqflite (from `.symlinks/plugins/sqflite/darwin`) EXTERNAL SOURCES: Flutter: @@ -25,14 +18,13 @@ EXTERNAL SOURCES: path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" sqflite: - :path: ".symlinks/plugins/sqflite/ios" + :path: ".symlinks/plugins/sqflite/darwin" SPEC CHECKSUMS: - Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 - FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 - sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec -PODFILE CHECKSUM: a8bf662d8622f5e36dabb676533790e6f6c4777b +PODFILE CHECKSUM: a35cc51c57d2268949e0897e6d913905cee03701 -COCOAPODS: 1.14.2 +COCOAPODS: 1.15.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 74a88c0..7f19cba 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -155,7 +155,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a6b826d..5e31d3d 100644 --- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ > searchMovies( + Future searchMovies( {required int page, String query = '', CancelToken? cancelToken}) async { final url = Uri( scheme: 'https', @@ -30,11 +29,10 @@ class MoviesRepository { }, ).toString(); final response = await client.get(url, cancelToken: cancelToken); - final movies = TMDBMoviesResponse.fromJson(response.data); - return movies.results; + return TMDBMoviesResponse.fromJson(response.data); } - Future> nowPlayingMovies( + Future nowPlayingMovies( {required int page, CancelToken? cancelToken}) async { final url = Uri( scheme: 'https', @@ -47,8 +45,7 @@ class MoviesRepository { }, ).toString(); final response = await client.get(url, cancelToken: cancelToken); - final movies = TMDBMoviesResponse.fromJson(response.data); - return movies.results; + return TMDBMoviesResponse.fromJson(response.data); } Future movie( @@ -89,7 +86,7 @@ Future movie( /// Provider to fetch paginated movies data @riverpod -Future> fetchMovies( +Future fetchMovies( FetchMoviesRef ref, { required MoviesPagination pagination, }) async { diff --git a/lib/src/features/movies/data/movies_repository.g.dart b/lib/src/features/movies/data/movies_repository.g.dart index ab3ba58..85cc9c2 100644 --- a/lib/src/features/movies/data/movies_repository.g.dart +++ b/lib/src/features/movies/data/movies_repository.g.dart @@ -181,7 +181,7 @@ class _MovieProviderElement extends AutoDisposeFutureProviderElement int get movieId => (origin as MovieProvider).movieId; } -String _$fetchMoviesHash() => r'cd39a67f8cc6a104d1058189f2151834a8eac1d0'; +String _$fetchMoviesHash() => r'9cafe6c21952cfb7d9bb9bfdec887cc3c13a9886'; /// Provider to fetch paginated movies data /// @@ -192,7 +192,7 @@ const fetchMoviesProvider = FetchMoviesFamily(); /// Provider to fetch paginated movies data /// /// Copied from [fetchMovies]. -class FetchMoviesFamily extends Family>> { +class FetchMoviesFamily extends Family> { /// Provider to fetch paginated movies data /// /// Copied from [fetchMovies]. @@ -236,7 +236,8 @@ class FetchMoviesFamily extends Family>> { /// Provider to fetch paginated movies data /// /// Copied from [fetchMovies]. -class FetchMoviesProvider extends AutoDisposeFutureProvider> { +class FetchMoviesProvider + extends AutoDisposeFutureProvider { /// Provider to fetch paginated movies data /// /// Copied from [fetchMovies]. @@ -273,7 +274,7 @@ class FetchMoviesProvider extends AutoDisposeFutureProvider> { @override Override overrideWith( - FutureOr> Function(FetchMoviesRef provider) create, + FutureOr Function(FetchMoviesRef provider) create, ) { return ProviderOverride( origin: this, @@ -290,7 +291,7 @@ class FetchMoviesProvider extends AutoDisposeFutureProvider> { } @override - AutoDisposeFutureProviderElement> createElement() { + AutoDisposeFutureProviderElement createElement() { return _FetchMoviesProviderElement(this); } @@ -308,13 +309,13 @@ class FetchMoviesProvider extends AutoDisposeFutureProvider> { } } -mixin FetchMoviesRef on AutoDisposeFutureProviderRef> { +mixin FetchMoviesRef on AutoDisposeFutureProviderRef { /// The parameter `pagination` of this provider. MoviesPagination get pagination; } class _FetchMoviesProviderElement - extends AutoDisposeFutureProviderElement> + extends AutoDisposeFutureProviderElement with FetchMoviesRef { _FetchMoviesProviderElement(super.provider); diff --git a/lib/src/features/movies/domain/tmdb_movie.freezed.dart b/lib/src/features/movies/domain/tmdb_movie.freezed.dart index 0fc5a07..70d1514 100644 --- a/lib/src/features/movies/domain/tmdb_movie.freezed.dart +++ b/lib/src/features/movies/domain/tmdb_movie.freezed.dart @@ -12,7 +12,7 @@ part of 'tmdb_movie.dart'; T _$identity(T value) => value; final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); TMDBMovie _$TMDBMovieFromJson(Map json) { return _TMDBMovieBasic.fromJson(json); @@ -347,7 +347,7 @@ class _$TMDBMovieBasicImpl implements _TMDBMovieBasic { } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$TMDBMovieBasicImpl && diff --git a/lib/src/features/movies/domain/tmdb_movies_response.freezed.dart b/lib/src/features/movies/domain/tmdb_movies_response.freezed.dart index b6c0967..ca159f1 100644 --- a/lib/src/features/movies/domain/tmdb_movies_response.freezed.dart +++ b/lib/src/features/movies/domain/tmdb_movies_response.freezed.dart @@ -12,7 +12,7 @@ part of 'tmdb_movies_response.dart'; T _$identity(T value) => value; final _privateConstructorUsedError = UnsupportedError( - 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods'); + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); TMDBMoviesResponse _$TMDBMoviesResponseFromJson(Map json) { return _TMDBMoviesResponse.fromJson(json); @@ -196,7 +196,7 @@ class _$TMDBMoviesResponseImpl implements _TMDBMoviesResponse { } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$TMDBMoviesResponseImpl && diff --git a/lib/src/features/movies/presentation/movies/movie_list_tile.dart b/lib/src/features/movies/presentation/movies/movie_list_tile.dart index 974425d..e30418f 100644 --- a/lib/src/features/movies/presentation/movies/movie_list_tile.dart +++ b/lib/src/features/movies/presentation/movies/movie_list_tile.dart @@ -15,6 +15,8 @@ class MovieListTile extends StatelessWidget { final int? debugIndex; final VoidCallback? onPressed; + static const posterHeight = 80.0; + @override Widget build(BuildContext context) { return Padding( @@ -26,15 +28,15 @@ class MovieListTile extends StatelessWidget { child: Stack( children: [ SizedBox( - width: MoviePoster.width, - height: MoviePoster.height, + width: posterHeight * MoviePoster.width / MoviePoster.height, + height: posterHeight, child: MoviePoster(imagePath: movie.posterPath), ), if (debugIndex != null) ...[ const Positioned.fill(child: TopGradient()), Positioned( - left: 8, - top: 8, + left: 4, + top: 4, child: Text( '$debugIndex', style: const TextStyle(color: Colors.white, fontSize: 14), diff --git a/lib/src/features/movies/presentation/movies/movie_list_tile_shimmer.dart b/lib/src/features/movies/presentation/movies/movie_list_tile_shimmer.dart index a131ce2..76aab30 100644 --- a/lib/src/features/movies/presentation/movies/movie_list_tile_shimmer.dart +++ b/lib/src/features/movies/presentation/movies/movie_list_tile_shimmer.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:shimmer/shimmer.dart'; import 'package:tmdb_movie_app_riverpod/src/common_widgets/movie_poster.dart'; +import 'package:tmdb_movie_app_riverpod/src/features/movies/presentation/movies/movie_list_tile.dart'; class MovieListTileShimmer extends StatelessWidget { const MovieListTileShimmer({super.key}); @@ -15,8 +16,10 @@ class MovieListTileShimmer extends StatelessWidget { child: Row( children: [ Container( - width: MoviePoster.width, - height: MoviePoster.height, + width: MovieListTile.posterHeight * + MoviePoster.width / + MoviePoster.height, + height: MovieListTile.posterHeight, color: Colors.black, ), const SizedBox(width: 8), diff --git a/lib/src/features/movies/presentation/movies/movies_search_screen.dart b/lib/src/features/movies/presentation/movies/movies_search_screen.dart index 58cff58..e9c597c 100644 --- a/lib/src/features/movies/presentation/movies/movies_search_screen.dart +++ b/lib/src/features/movies/presentation/movies/movies_search_screen.dart @@ -16,6 +16,11 @@ class MoviesSearchScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final query = ref.watch(moviesSearchTextProvider); + // * get the first page so we can retrieve the total number of results + final moviesResponse = ref.watch( + fetchMoviesProvider(pagination: MoviesPagination(page: 1, query: query)), + ); + final totalResults = moviesResponse.valueOrNull?.totalResults; return Scaffold( appBar: AppBar( title: const Text('TMDB Movies'), @@ -35,40 +40,50 @@ class MoviesSearchScreen extends ConsumerWidget { ).future, ); }, - // TODO: Limit item count to pagination results child: ListView.custom( - childrenDelegate: SliverChildBuilderDelegate((context, index) { - final page = index ~/ pageSize + 1; - final indexInPage = index % pageSize; - // use the fact that this is an infinite list to fetch a new page - // as soon as the index exceeds the page size - // Note that ref.watch is called for up to pageSize items - // with the same page and query arguments (but this is ok since data is cached) - final moviesList = ref.watch( - fetchMoviesProvider( - pagination: MoviesPagination(page: page, query: query)), - ); - return moviesList.when( - // TODO: Improve error handling - error: (err, stack) => Text('Error $err'), - loading: () => const MovieListTileShimmer(), - data: (movies) { - if (indexInPage >= movies.length) { - return const MovieListTileShimmer(); - } - final movie = movies[indexInPage]; - return MovieListTile( - movie: movie, - debugIndex: index, - onPressed: () => context.goNamed( - AppRoute.movie.name, - pathParameters: {'id': movie.id.toString()}, - extra: movie, - ), - ); - }, - ); - }), + childrenDelegate: SliverChildBuilderDelegate( + (context, index) { + final page = index ~/ pageSize + 1; + final indexInPage = index % pageSize; + // use the fact that this is an infinite list to fetch a new page + // as soon as the index exceeds the page size + // Note that ref.watch is called for up to pageSize items + // with the same page and query arguments (but this is ok since data is cached) + final moviesResponse = ref.watch( + fetchMoviesProvider( + pagination: + MoviesPagination(page: page, query: query)), + ); + return moviesResponse.when( + // * Only show error on the first item of the page + error: (err, stack) => indexInPage == 0 + ? Padding( + padding: const EdgeInsets.all(16.0), + child: Text(err.toString()), + ) + : const SizedBox.shrink(), + loading: () => const MovieListTileShimmer(), + data: (movies) { + // * This condition should not happen if a non-null + // * childCount is given + if (indexInPage >= movies.results.length) { + return null; + } + final movie = movies.results[indexInPage]; + return MovieListTile( + movie: movie, + debugIndex: index, + onPressed: () => context.goNamed( + AppRoute.movie.name, + pathParameters: {'id': movie.id.toString()}, + extra: movie, + ), + ); + }, + ); + }, + childCount: totalResults, + ), ), ), ), diff --git a/lib/src/utils/logger_interceptor.dart b/lib/src/utils/logger_interceptor.dart index 35292ce..bd09dd1 100644 --- a/lib/src/utils/logger_interceptor.dart +++ b/lib/src/utils/logger_interceptor.dart @@ -3,27 +3,62 @@ import 'dart:developer'; import 'package:dio/dio.dart'; class LoggerInterceptor implements Interceptor { - @override - void onError(DioException err, ErrorInterceptorHandler handler) { - log('❌ Dio Error!'); - log('❌ Url: ${err.requestOptions.uri}'); - log('❌ ${err.stackTrace}'); - log('❌ Response Error: ${err.response?.data}'); - return handler.next(err); - } + final stopwatches = {}; @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { - log('🌍 Sending network request: ${options.baseUrl}${options.path}'); + final url = '${options.baseUrl}${options.path}'; + stopwatches[url] = Stopwatch()..start(); + log('🌍 Making request: $url'); return handler.next(options); } @override void onResponse(Response response, ResponseInterceptorHandler handler) { - log('⬅️ Received network response'); - log('${response.statusCode != 200 ? '❌ ${response.statusCode} ❌' : '✅ 200 ✅'} ${response.requestOptions.baseUrl}${response.requestOptions.path}'); - log('Query params: ${response.requestOptions.queryParameters}'); + final url = + '${response.requestOptions.baseUrl}${response.requestOptions.path}'; + _logMessageAndClearStopwatch( + response.statusCode, url, '⬅️ Received response'); + if (response.requestOptions.queryParameters.isNotEmpty) { + log('Query params: ${response.requestOptions.queryParameters}'); + } log('-------------------------'); return handler.next(response); } + + @override + void onError(DioException err, ErrorInterceptorHandler handler) { + final url = err.requestOptions.uri.toString(); + _logMessageAndClearStopwatch(null, url, '❌ Received error'); + log('${err.stackTrace}'); + if (err.response?.data != null) { + log('❌ Response Error: ${err.response?.data}'); + } + return handler.next(err); + } + + void _logMessageAndClearStopwatch( + int? statusCode, String url, String message) { + final stopwatch = stopwatches[url]; + if (stopwatch != null) { + stopwatch.stop(); + _logResponse(statusCode, stopwatch.elapsedMilliseconds, url); + stopwatches.remove(url); + } else { + log(message); + } + } + + void _logResponse(int? statusCode, int milliseconds, String url) { + final emoji = switch (statusCode) { + != null && >= 200 && < 300 => '✅', + != null && >= 300 && < 400 => '🟠', + _ => '❌' + }; + if (statusCode != null) { + log('$emoji $statusCode $emoji | ${milliseconds}ms | $url'); + } else { + log('$emoji | ${milliseconds}ms | $url'); + } + } } diff --git a/pubspec.lock b/pubspec.lock index 534bee7..fcf4a0f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" url: "https://pub.dev" source: hosted - version: "64.0.0" + version: "67.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.4.1" analyzer_plugin: dependency: transitive description: @@ -77,26 +77,26 @@ packages: dependency: transitive description: name: build_resolvers - sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8" + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b" + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.4.9" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.11" + version: "7.3.0" built_collection: dependency: transitive description: @@ -109,34 +109,34 @@ packages: dependency: transitive description: name: built_value - sha256: "69acb7007eb2a31dc901512bfe0f7b767168be34cb734835d54c070bfa74c1b2" + sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e url: "https://pub.dev" source: hosted - version: "8.8.0" + version: "8.9.1" cached_network_image: dependency: "direct main" description: name: cached_network_image - sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f + sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.3.1" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613" + sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f" url: "https://pub.dev" source: hosted - version: "3.0.0" + version: "4.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257" + sha256: "42a835caa27c220d1294311ac409a43361088625a4f23c820b006dd9bffb3316" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.1" characters: dependency: transitive description: @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: cli_util - sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 url: "https://pub.dev" source: hosted - version: "0.4.0" + version: "0.4.1" clock: dependency: transitive description: @@ -181,10 +181,10 @@ packages: dependency: transitive description: name: code_builder - sha256: b2151ce26a06171005b379ecff6e08d34c470180ffe16b8e14b6d52be292b55f + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 url: "https://pub.dev" source: hosted - version: "4.8.0" + version: "4.10.0" collection: dependency: transitive description: @@ -221,50 +221,58 @@ packages: dependency: transitive description: name: custom_lint - sha256: "198ec6b8e084d22f508a76556c9afcfb71706ad3f42b083fe0ee923351a96d90" + sha256: "445242371d91d2e24bd7b82e3583a2c05610094ba2d0575262484ad889c8f981" url: "https://pub.dev" source: hosted - version: "0.5.7" + version: "0.6.2" custom_lint_core: dependency: transitive description: name: custom_lint_core - sha256: f84c3fe2f27ef3b8831953e477e59d4a29c2952623f9eac450d7b40d9cdd94cc + sha256: ce5d6215f4e143f7780ce53f73dfa6fc503f39d2d30bef76c48be9ac1a09d9a6 url: "https://pub.dev" source: hosted - version: "0.5.7" + version: "0.6.2" dart_style: dependency: transitive description: name: dart_style - sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.3.6" dio: dependency: "direct main" description: name: dio - sha256: "01870acd87986f768e0c09cc4d7a19a59d814af7b34cbeb0b437d2c33bdfea4c" + sha256: "0978e9a3e45305a80a7210dbeaf79d6ee8bee33f70c8e542dc654c952070217f" url: "https://pub.dev" source: hosted - version: "5.3.4" + version: "5.4.2+1" envied: dependency: "direct main" description: name: envied - sha256: c4af8bb99203d7f216cea41f2ec70874f9dd826b2a5782cdc5bd25389c5adcc1 + sha256: bbff9c76120e4dc5e2e36a46690cf0a26feb65e7765633f4e8d916bcd173a450 url: "https://pub.dev" source: hosted - version: "0.5.2" + version: "0.5.4+1" envied_generator: dependency: "direct dev" description: name: envied_generator - sha256: "637901d274db3974afb3919ca9ba2e1a97f110fd57350ac13a3adcd20ad7d530" + sha256: "517b70de08d13dcd40e97b4e5347e216a0b1c75c99e704f3c85c0474a392d14a" + url: "https://pub.dev" + source: hosted + version: "0.5.4+1" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 url: "https://pub.dev" source: hosted - version: "0.5.2" + version: "2.0.5" fake_async: dependency: transitive description: @@ -277,10 +285,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" file: dependency: transitive description: @@ -314,18 +322,18 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" flutter_riverpod: dependency: "direct main" description: name: flutter_riverpod - sha256: da9591d1f8d5881628ccd5c25c40e74fc3eef50ba45e40c3905a06e1712412d5 + sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d" url: "https://pub.dev" source: hosted - version: "2.4.9" + version: "2.5.1" flutter_test: dependency: "direct dev" description: flutter @@ -340,10 +348,10 @@ packages: dependency: "direct dev" description: name: freezed - sha256: "21bf2825311de65501d22e563e3d7605dff57fb5e6da982db785ae5372ff018a" + sha256: a434911f643466d78462625df76fd9eb13e57348ff43fe1f77bbe909522c67a1 url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.5.2" freezed_annotation: dependency: "direct main" description: @@ -372,10 +380,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: c247a4f76071c3b97bb5ae8912968870d5565644801c5e09f3bc961b4d874895 + sha256: f6ba8eed5fa831e461122de577d4a26674a1d836e2956abe6c0f6c4d952e6673 url: "https://pub.dev" source: hosted - version: "12.1.1" + version: "13.2.3" graphs: dependency: transitive description: @@ -388,10 +396,10 @@ packages: dependency: transitive description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.2.1" http_multi_server: dependency: transitive description: @@ -420,10 +428,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.6.7" + version: "0.7.1" json_annotation: dependency: "direct main" description: @@ -440,6 +448,30 @@ packages: url: "https://pub.dev" source: hosted version: "6.7.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" lints: dependency: transitive description: @@ -460,34 +492,34 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" mime: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" octo_image: dependency: transitive description: @@ -508,34 +540,34 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_provider: dependency: transitive description: name: path_provider - sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72 + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" path_provider_linux: dependency: transitive description: @@ -548,10 +580,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -564,18 +596,18 @@ packages: dependency: transitive description: name: platform - sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.1.8" pool: dependency: transitive description: @@ -612,34 +644,34 @@ packages: dependency: transitive description: name: riverpod - sha256: "942999ee48b899f8a46a860f1e13cee36f2f77609eb54c5b7a669bb20d550b11" + sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d url: "https://pub.dev" source: hosted - version: "2.4.9" + version: "2.5.1" riverpod_analyzer_utils: dependency: transitive description: name: riverpod_analyzer_utils - sha256: d4dabc35358413bf4611fcb6abb46308a67c4ef4cd5e69fd3367b11925c59f57 + sha256: "8b71f03fc47ae27d13769496a1746332df4cec43918aeba9aff1e232783a780f" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.5.1" riverpod_annotation: dependency: "direct main" description: name: riverpod_annotation - sha256: b70e95fbd5ca7ce42f5148092022971bb2e9843b6ab71e97d479e8ab52e98979 + sha256: e5e796c0eba4030c704e9dae1b834a6541814963292839dcf9638d53eba84f5c url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.5" riverpod_generator: dependency: "direct dev" description: name: riverpod_generator - sha256: ff8f064f1d7ef3cc6af481bba8e9a3fcdb4d34df34fac1b39bbc003167065be0 + sha256: d451608bf17a372025fc36058863737636625dfdb7e3cbf6142e0dfeb366ab22 url: "https://pub.dev" source: hosted - version: "2.3.9" + version: "2.4.0" rxdart: dependency: transitive description: @@ -681,10 +713,10 @@ packages: dependency: transitive description: name: source_gen - sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.5.0" source_helper: dependency: transitive description: @@ -713,18 +745,18 @@ packages: dependency: transitive description: name: sqflite - sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.3.2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: bb4738f15b23352822f4c42a531677e5c6f522e079461fd240ead29d8d8a54a6 + sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5" url: "https://pub.dev" source: hosted - version: "2.5.0+2" + version: "2.5.3" stack_trace: dependency: transitive description: @@ -769,10 +801,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.0+1" term_glyph: dependency: transitive description: @@ -817,10 +849,10 @@ packages: dependency: transitive description: name: uuid - sha256: df5a4d8f22ee4ccd77f8839ac7cb274ebc11ef9adcce8b92be14b797fe889921 + sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 url: "https://pub.dev" source: hosted - version: "4.2.1" + version: "4.3.3" vector_math: dependency: transitive description: @@ -829,6 +861,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" watcher: dependency: transitive description: @@ -841,34 +881,34 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.5.1" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.4" win32: dependency: transitive description: name: win32 - sha256: "7c99c0e1e2fa190b48d25c81ca5e42036d5cac81430ef249027d97b0935c553f" + sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480" url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "5.3.0" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" yaml: dependency: transitive description: @@ -878,5 +918,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.10.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.16.0" diff --git a/pubspec.yaml b/pubspec.yaml index 293d28e..37e7b2b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,33 +1,12 @@ name: tmdb_movie_app_riverpod description: Flutter Movies app with Riverpod (TMDB API) - -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. version: 1.0.0+1 environment: sdk: '>=3.2.0 <4.0.0' -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter @@ -35,64 +14,23 @@ dependencies: freezed_annotation: ^2.4.1 json_annotation: ^4.8.1 transparent_image: ^2.0.1 - dio: ^5.3.4 - flutter_riverpod: ^2.4.9 - riverpod_annotation: ^2.3.3 - envied: ^0.5.2 + dio: ^5.4.2+1 + flutter_riverpod: ^2.5.1 + riverpod_annotation: ^2.3.5 + envied: ^0.5.4+1 shimmer: ^3.0.0 - cached_network_image: ^3.3.0 - go_router: ^12.1.1 + cached_network_image: ^3.3.1 + go_router: ^13.2.3 dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.4.6 - riverpod_generator: ^2.3.9 - freezed: ^2.4.5 + build_runner: ^2.4.9 + riverpod_generator: ^2.4.0 + freezed: ^2.5.2 json_serializable: ^6.7.1 - envied_generator: ^0.5.2 - - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^3.0.1 + envied_generator: ^0.5.4 + flutter_lints: ^3.0.2 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages