From 61e11c7191f4edb072124527ce7c38da0b569171 Mon Sep 17 00:00:00 2001 From: David Heredia Date: Tue, 3 Oct 2023 12:56:28 +0200 Subject: [PATCH 1/2] ref: separate loadings in a file, fix: sizes in cast(actor details) --- .github/workflows/dart_api.yml | 29 +--- lib/main.dart | 5 +- lib/network/client_api.dart | 4 +- lib/ui/components/film_actor_cast_item.dart | 56 ++++---- lib/ui/components/film_worker_cast_item.dart | 4 +- lib/ui/components/movie_carrousel_item.dart | 24 ++-- lib/ui/components/movie_list.dart | 2 +- lib/ui/pages/main/main_screen.dart | 11 +- lib/ui/pages/movieDetails/movie_details.dart | 37 ++--- lib/ui/pages/personDetails/actor_details.dart | 132 +++++++----------- lib/ui/util/extension.dart | 35 +++++ macos/Flutter/GeneratedPluginRegistrant.swift | 4 - pubspec.yaml | 4 +- 13 files changed, 153 insertions(+), 194 deletions(-) diff --git a/.github/workflows/dart_api.yml b/.github/workflows/dart_api.yml index 3ecf5f9..07a6bcd 100644 --- a/.github/workflows/dart_api.yml +++ b/.github/workflows/dart_api.yml @@ -5,29 +5,14 @@ on: branches: [api] jobs: - build: runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] - node-version: [10] - dart-version: [stable, dev] - # for now, code-version will mirror dart-version to reduce number of bots - # code-version: [stable] #, insiders] - bot: [flutter_debug, flutter_debug_chrome, flutter_test_debug, dart_web_debug, flutter_repo, dart_debug, dart, flutter, misc] - include: - - dart-version: stable - flutter-version: beta - code-version: stable - - dart-version: dev - flutter-version: dev - code-version: insiders steps: - - uses: actions/checkout@v4 - - name: Setup Dart ${{ matrix.dart-version }} - uses: DanTup/gh-actions/setup-dart@master - with: - channel: ${{ matrix.dart-version }} + - uses: actions/checkout@v3 + - uses: dart-lang/setup-dart@v1 + + - run: dart pub get + - run: dart format --output=none --set-exit-if-changed . + - run: dart analyze + - run: dart test - run: dart run ./lib/network/server_api.dart diff --git a/lib/main.dart b/lib/main.dart index dc50a3c..4c573ff 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,6 @@ //Core Packages +import 'package:FilmFlu/ui/util/utilScroll.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:responsive_framework/responsive_framework.dart'; import 'package:flutter/material.dart'; @@ -13,7 +15,6 @@ import 'package:FilmFlu/ui/theme/colors.dart'; import 'package:FilmFlu/ui/pages/main/main_screen.dart'; import 'package:FilmFlu/ui/pages/personDetails/actor_details.dart'; import 'package:FilmFlu/ui/pages/settings/settings_screen.dart'; -import 'package:FilmFlu/ui/util/utilScroll.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); @@ -38,7 +39,7 @@ class FilmFlu extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, - scrollBehavior: WebScrollBehavior(), + scrollBehavior: kIsWeb ? WebScrollBehavior() : MaterialScrollBehavior(), localizationsDelegates: [ AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, diff --git a/lib/network/client_api.dart b/lib/network/client_api.dart index e3cca49..4d8653c 100644 --- a/lib/network/client_api.dart +++ b/lib/network/client_api.dart @@ -1,7 +1,5 @@ //Core Packages import 'dart:convert'; -import 'package:FilmFlu/dto/credit_person.dart'; -import 'package:FilmFlu/dto/credits_person.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; @@ -11,6 +9,8 @@ import 'package:FilmFlu/dto/video.dart'; import 'package:FilmFlu/dto/media_item.dart'; import 'package:FilmFlu/constants.dart'; import 'package:FilmFlu/dto/person.dart'; +import 'package:FilmFlu/dto/credit_person.dart'; +import 'package:FilmFlu/dto/credits_person.dart'; class Api { MediaItem parseMovie(String responseBody) { diff --git a/lib/ui/components/film_actor_cast_item.dart b/lib/ui/components/film_actor_cast_item.dart index 5ff83ca..3da3da9 100644 --- a/lib/ui/components/film_actor_cast_item.dart +++ b/lib/ui/components/film_actor_cast_item.dart @@ -1,3 +1,4 @@ +import 'package:FilmFlu/ui/util/extension.dart'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -9,8 +10,8 @@ import 'package:FilmFlu/ui/pages/personDetails/actor_details.dart'; class FilmActorItem extends StatefulWidget { FilmActorItem({super.key, required this.index, required this.cast}); - int index; - List cast; + final int index; + final List cast; @override State createState() => _FilmActorItemState(); @@ -35,34 +36,29 @@ class _FilmActorItemState extends State { child: Image.network('$personImgBaseUrl${actor.profilePath}', height: 160, width: 150, - fit: BoxFit.cover, loadingBuilder: (BuildContext context, - Widget child, ImageChunkEvent? loadingProgress) { - if (loadingProgress == null) return child; - return Center( - child: CircularProgressIndicator( - value: loadingProgress.expectedTotalBytes != null - ? loadingProgress.cumulativeBytesLoaded / - loadingProgress.expectedTotalBytes! - : null, - ), - ); - }, errorBuilder: (context, url, error) { - if (actor.gender == 2) { - return SvgPicture.asset( - "assets/icons/actor_icon.svg", - height: 160, - fit: BoxFit.cover, - width: 150, - ); - } else { - return SvgPicture.asset( - "assets/icons/actress_icon.svg", - height: 160, - fit: BoxFit.cover, - width: 150, - ); - } - }), + fit: BoxFit.cover, + loadingBuilder: (context, child, loadingProgress) => + DefaultAsyncLoading( + child: child, + loadingProgress: loadingProgress, + ), + errorBuilder: (context, url, error) { + if (actor.gender == 2) { + return SvgPicture.asset( + "assets/icons/actor_icon.svg", + height: 160, + fit: BoxFit.cover, + width: 150, + ); + } else { + return SvgPicture.asset( + "assets/icons/actress_icon.svg", + height: 160, + fit: BoxFit.cover, + width: 150, + ); + } + }), ), ), AutoSizeText(actor.name!, diff --git a/lib/ui/components/film_worker_cast_item.dart b/lib/ui/components/film_worker_cast_item.dart index f4ba2b3..b967f85 100644 --- a/lib/ui/components/film_worker_cast_item.dart +++ b/lib/ui/components/film_worker_cast_item.dart @@ -9,8 +9,8 @@ import 'package:FilmFlu/ui/pages/personDetails/actor_details.dart'; class FilmWorkerItem extends StatefulWidget { FilmWorkerItem({super.key, required this.index, required this.crew}); - int index; - List crew; + final int index; + final List crew; @override State createState() => _FilmWorkerItemState(); diff --git a/lib/ui/components/movie_carrousel_item.dart b/lib/ui/components/movie_carrousel_item.dart index 7d8b7f5..1eb7617 100644 --- a/lib/ui/components/movie_carrousel_item.dart +++ b/lib/ui/components/movie_carrousel_item.dart @@ -1,5 +1,5 @@ //Core Packages -import 'package:auto_size_text/auto_size_text.dart'; +import 'package:FilmFlu/ui/util/extension.dart'; import 'package:flutter/material.dart'; //My Packages @@ -31,25 +31,19 @@ class MovieCarrouselItem extends StatelessWidget { ); }, child: Container( - width: 240, + width: 220, height: 300, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(62.0), + borderRadius: BorderRadius.all(Radius.circular(48)), image: DecorationImage( - fit: BoxFit.fill, + fit: BoxFit.scaleDown, image: Image.network( '$movieImgBaseURL${movie.posterPath}', - loadingBuilder: (context, child, loadingProgress) { - if (loadingProgress == null) return child; - return Center( - child: CircularProgressIndicator( - value: loadingProgress.expectedTotalBytes != null - ? loadingProgress.cumulativeBytesLoaded / - loadingProgress.expectedTotalBytes! - : null, - ), - ); - }, + loadingBuilder: (context, child, loadingProgress) => + DefaultAsyncLoading( + child: child, + loadingProgress: loadingProgress, + ), ).image, ), ), diff --git a/lib/ui/components/movie_list.dart b/lib/ui/components/movie_list.dart index 8ff871e..0d39d4d 100644 --- a/lib/ui/components/movie_list.dart +++ b/lib/ui/components/movie_list.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; class MovieList extends StatelessWidget { MovieList({super.key, required this.items}); - late List items; + final List items; @override Widget build(BuildContext context) { diff --git a/lib/ui/pages/main/main_screen.dart b/lib/ui/pages/main/main_screen.dart index 04e99d9..0ec1838 100644 --- a/lib/ui/pages/main/main_screen.dart +++ b/lib/ui/pages/main/main_screen.dart @@ -1,4 +1,5 @@ //Core Packages +import 'package:FilmFlu/ui/util/extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -45,10 +46,7 @@ class _MainPageState extends State { return Scrollbar( child: MovieList(items: snapshot.requireData)); } else { - return Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - child: Center(child: CircularProgressIndicator())); + return DefaultSyncLoading(); } }, ), @@ -72,10 +70,7 @@ class _MainPageState extends State { return Scrollbar( child: MovieList(items: snapshot.requireData)); } else { - return Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - child: Center(child: CircularProgressIndicator())); + return DefaultSyncLoading(); } }, ), diff --git a/lib/ui/pages/movieDetails/movie_details.dart b/lib/ui/pages/movieDetails/movie_details.dart index 76dd913..8365363 100644 --- a/lib/ui/pages/movieDetails/movie_details.dart +++ b/lib/ui/pages/movieDetails/movie_details.dart @@ -1,8 +1,4 @@ //Core Packages; -import 'package:FilmFlu/dto/video.dart'; -import 'package:FilmFlu/ui/components/movie_cast.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:youtube_player_iframe/youtube_player_iframe.dart'; @@ -14,6 +10,10 @@ import 'package:FilmFlu/network/client_api.dart'; import 'package:FilmFlu/ui/components/scaffold_page.dart'; import 'package:FilmFlu/constants.dart'; import 'package:FilmFlu/ui/theme/colors.dart'; +import 'package:FilmFlu/dto/video.dart'; +import 'package:FilmFlu/ui/components/movie_cast.dart'; +import 'package:FilmFlu/ui/util/extension.dart'; +import 'package:flutter/material.dart'; class MovieDetailsPage extends StatefulWidget { const MovieDetailsPage( @@ -181,24 +181,12 @@ class _MovieDetailsPageState extends State { ), image: Image.network( "$movieLandscapeBaseUrl${movie.backdropPath}", - loadingBuilder: (BuildContext context, - Widget child, - ImageChunkEvent? loadingProgress) { - if (loadingProgress == null) - return child; - return Center( - child: CircularProgressIndicator( - value: loadingProgress - .expectedTotalBytes != - null - ? loadingProgress - .cumulativeBytesLoaded / - loadingProgress - .expectedTotalBytes! - : null, - ), - ); - }, + loadingBuilder: + (context, child, loadingProgress) => + DefaultAsyncLoading( + child: child, + loadingProgress: loadingProgress, + ), ).image, ), ), @@ -271,10 +259,7 @@ class _MovieDetailsPageState extends State { ], ); } else { - return Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - child: Center(child: CircularProgressIndicator())); + return DefaultSyncLoading(); } }, ), diff --git a/lib/ui/pages/personDetails/actor_details.dart b/lib/ui/pages/personDetails/actor_details.dart index f84435c..3dfd6af 100644 --- a/lib/ui/pages/personDetails/actor_details.dart +++ b/lib/ui/pages/personDetails/actor_details.dart @@ -1,5 +1,7 @@ //Core Packages +import 'package:FilmFlu/ui/util/extension.dart'; import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter/material.dart'; @@ -13,6 +15,7 @@ import 'package:FilmFlu/ui/components/scaffold_page.dart'; import 'package:FilmFlu/dto/credits_person.dart'; import 'package:FilmFlu/ui/pages/movieDetails/movie_details.dart'; import 'package:FilmFlu/ui/theme/colors.dart'; +import 'package:material_symbols_icons/symbols.dart'; class ActorDetailsPage extends StatefulWidget { const ActorDetailsPage({super.key, required this.actorId}); @@ -37,16 +40,13 @@ class _ActorDetailsPage extends State { physics: ScrollPhysics(), scrollDirection: Axis.vertical, child: Container( - padding: EdgeInsets.all(12), + padding: EdgeInsets.all(8), child: FutureBuilder( future: Api().fetchPerson(widget.actorId), builder: (context, snapshot) { Person? person = snapshot.data; if (snapshot.connectionState == ConnectionState.waiting) { - return Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - child: Center(child: CircularProgressIndicator())); + return DefaultSyncLoading(); } else if (person != null) { return Column( children: [ @@ -108,7 +108,7 @@ class _ActorDetailsPage extends State { child: Row( children: [ Icon( - Icons.abc, + Symbols.skull, color: Colors.white, ), Padding( @@ -124,7 +124,7 @@ class _ActorDetailsPage extends State { ), ) : Container(), - SizedBox(height: 20), + SizedBox(height: 10), Row( children: [ Icon( @@ -134,7 +134,7 @@ class _ActorDetailsPage extends State { Padding( padding: const EdgeInsets.only(left: 8.0), child: SizedBox( - width: 180, + width: 220, child: AutoSizeText( "${person.placeOfBirth.trim()}", maxFontSize: 20, @@ -235,9 +235,20 @@ class _ActorDetailsPage extends State { ConnectionState.waiting && snapshot.hasData) { List creditsListAsActor = - snapshot.data!.cast; + snapshot + .data!.cast + .where((element) => + element.character != null) + .where((element) => + element.title != null) + .toList(); List? creditsListAsProduction = - snapshot.data?.crew; + snapshot.data?.crew! + .where( + (element) => element.job != null) + .where((element) => + element.title != null) + .toList(); return isActorWorkSelected ? GridView.builder( controller: @@ -245,15 +256,11 @@ class _ActorDetailsPage extends State { itemCount: creditsListAsActor.length, shrinkWrap: true, gridDelegate: - SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: 150, - mainAxisSpacing: 20, + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: kIsWeb ? 4 : 2, + mainAxisSpacing: 5, crossAxisSpacing: 40, - mainAxisExtent: 340, - childAspectRatio: - MediaQuery.of(context) - .size - .aspectRatio, + mainAxisExtent: 400, ), itemBuilder: (context, index) { CreditPerson filmPerson = @@ -282,38 +289,23 @@ class _ActorDetailsPage extends State { ClipRRect( borderRadius: BorderRadius.circular( - 32.0), + 96), child: Image.network( filmPerson.backdropPath != null ? "$personImgBaseUrl${filmPerson.backdropPath}" : "$personImgBaseUrl${person.profilePath}", - height: 220, - width: 150, - fit: BoxFit.cover, - loadingBuilder: - (BuildContext - context, - Widget child, - ImageChunkEvent? - loadingProgress) { - if (loadingProgress == - null) - return child; - return Center( - child: - CircularProgressIndicator( - value: loadingProgress - .expectedTotalBytes != - null - ? loadingProgress - .cumulativeBytesLoaded / - loadingProgress - .expectedTotalBytes! - : null, - ), - ); - }, + width: 500, + height: 300, + fit: BoxFit.scaleDown, + loadingBuilder: (context, + child, + loadingProgress) => + DefaultAsyncLoading( + child: child, + loadingProgress: + loadingProgress, + ), ), ), Padding( @@ -347,20 +339,15 @@ class _ActorDetailsPage extends State { creditsListAsProduction?.length, shrinkWrap: true, gridDelegate: - SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: 150, - mainAxisSpacing: 20, + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: kIsWeb ? 4 : 2, + mainAxisSpacing: 5, crossAxisSpacing: 40, - mainAxisExtent: 340, - childAspectRatio: - MediaQuery.of(context) - .size - .aspectRatio, + mainAxisExtent: 400, ), itemBuilder: (context, index) { CreditPerson filmPerson = creditsListAsProduction![index]; - print(filmPerson); String? movieTitle = filmPerson .title != null @@ -391,32 +378,17 @@ class _ActorDetailsPage extends State { null ? "$personImgBaseUrl${filmPerson.backdropPath}" : "$personImgBaseUrl${person.profilePath}", - height: 220, - width: 150, - fit: BoxFit.cover, - loadingBuilder: - (BuildContext - context, - Widget child, - ImageChunkEvent? - loadingProgress) { - if (loadingProgress == - null) - return child; - return Center( - child: - CircularProgressIndicator( - value: loadingProgress - .expectedTotalBytes != - null - ? loadingProgress - .cumulativeBytesLoaded / - loadingProgress - .expectedTotalBytes! - : null, - ), - ); - }, + width: 500, + height: 300, + fit: BoxFit.scaleDown, + loadingBuilder: (context, + child, + loadingProgress) => + DefaultAsyncLoading( + child: child, + loadingProgress: + loadingProgress, + ), ), ), Padding( diff --git a/lib/ui/util/extension.dart b/lib/ui/util/extension.dart index 9ba951d..51fe573 100644 --- a/lib/ui/util/extension.dart +++ b/lib/ui/util/extension.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + extension Unique on List { List unique([Id Function(E element)? id, bool inplace = true]) { final ids = Set(); @@ -6,3 +8,36 @@ extension Unique on List { return list; } } + +class DefaultAsyncLoading extends StatelessWidget { + final Widget child; + final ImageChunkEvent? loadingProgress; + + const DefaultAsyncLoading( + {super.key, required this.child, required this.loadingProgress}); + + @override + Widget build(BuildContext context) { + if (loadingProgress == null) return child; + return Center( + child: CircularProgressIndicator( + value: loadingProgress!.expectedTotalBytes != null + ? loadingProgress!.cumulativeBytesLoaded / + loadingProgress!.expectedTotalBytes! + : null, + ), + ); + } +} + +class DefaultSyncLoading extends StatelessWidget { + const DefaultSyncLoading({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + child: Center(child: CircularProgressIndicator())); + } +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 03bdd29..744bfe9 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,13 +6,9 @@ import FlutterMacOS import Foundation import package_info_plus -import path_provider_foundation -import sqflite import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin")) - PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) - SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.yaml b/pubspec.yaml index d3a9490..ad1bf86 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: FilmFlu description: A project of movies and something more publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.7+7 +version: 0.0.8+8 environment: sdk: '>=3.0.5 <4.0.0' @@ -14,7 +14,6 @@ dependencies: envied: json_annotation: ^4.8.1 http: - cached_network_image: lottie: ^2.5.0 package_info_plus: intl: @@ -22,6 +21,7 @@ dependencies: responsive_framework: ^1.1.0 shelf: ^1.1.0 auto_size_text: ^3.0.0 + material_symbols_icons: ^4.2668.0 dev_dependencies: flutter_test: From fa9b6d2fe54dea4995f8d3972317d28cdb2e4598 Mon Sep 17 00:00:00 2001 From: David Heredia Date: Tue, 3 Oct 2023 12:56:48 +0200 Subject: [PATCH 2/2] Update flutter_android.yml --- .github/workflows/flutter_android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/flutter_android.yml b/.github/workflows/flutter_android.yml index 84578f6..55ed388 100644 --- a/.github/workflows/flutter_android.yml +++ b/.github/workflows/flutter_android.yml @@ -50,8 +50,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: 0.0.7 - release_name: Version Release 0.0.7 + tag_name: 0.0.8 + release_name: Version Release 0.0.8 draft: false prerelease: true