From a153924978cb6d5efb56a1800b72c597e03bfcc1 Mon Sep 17 00:00:00 2001 From: Mguy13 Date: Sun, 1 Jan 2023 13:04:22 +0100 Subject: [PATCH] better linting --- analysis_options.yaml | 2 + .../core/abstracts/router/app_router.dart | 2 +- .../core/abstracts/router/routes.dart | 6 +- .../core/data/constants/const_colors.dart | 2 +- .../core/data/extensions/dio_extensions.dart | 5 +- .../data/extensions/string_extensions.dart | 7 +- .../core/services/connections_service.dart | 4 +- .../core/services/local_storage_service.dart | 2 +- .../core/services/logging_service.dart | 12 +-- .../core/services/overlay_service.dart | 9 +- lib/features/core/utils/mutex.dart | 6 +- lib/features/core/views/error_page_view.dart | 2 +- lib/features/core/widgets/gap.dart | 15 ++- .../state/multi_value_listenable_builder.dart | 7 +- .../home/api/unsplash_images_api.dart | 24 +++-- .../home/data/models/image_model.dart | 26 ++--- .../services/image_cache_manager_service.dart | 2 +- .../home/views/gallery/gallery_view.dart | 2 +- .../views/gallery/gallery_view_model.dart | 2 +- .../image_carousel/image_carousel_view.dart | 4 +- .../image_carousel_view_model.dart | 8 +- lib/locator.dart | 100 +++++++++--------- pubspec.lock | 9 +- pubspec.yaml | 10 +- 24 files changed, 146 insertions(+), 122 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 0fafef6..859a6c3 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,3 +1,5 @@ +include: package:very_good_analysis/analysis_options.3.1.0.yaml + analyzer: strong-mode: implicit-dynamic: true diff --git a/lib/features/core/abstracts/router/app_router.dart b/lib/features/core/abstracts/router/app_router.dart index 2c4d3c5..8256cc7 100644 --- a/lib/features/core/abstracts/router/app_router.dart +++ b/lib/features/core/abstracts/router/app_router.dart @@ -25,7 +25,7 @@ class McgRouter { path: Routes.imageCarousel.routePath, name: Routes.imageCarousel.routeName, builder: (context, state) => ImageCarouselView( - imageCarouselViewArguments: state.extra as ImageCarouselViewArguments, + imageCarouselViewArguments: state.extra! as ImageCarouselViewArguments, ), ), ], diff --git a/lib/features/core/abstracts/router/routes.dart b/lib/features/core/abstracts/router/routes.dart index 751b821..4b847d3 100644 --- a/lib/features/core/abstracts/router/routes.dart +++ b/lib/features/core/abstracts/router/routes.dart @@ -17,11 +17,11 @@ enum Routes { } class RoutesInfo { - final String routePath; - final String routeName; - const RoutesInfo({ required this.routePath, required this.routeName, }); + + final String routePath; + final String routeName; } diff --git a/lib/features/core/data/constants/const_colors.dart b/lib/features/core/data/constants/const_colors.dart index 4f69947..e4009a3 100644 --- a/lib/features/core/data/constants/const_colors.dart +++ b/lib/features/core/data/constants/const_colors.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; abstract class ConstColours { /// Smoke Gray => a neutral grey with neutral warmth/cold - static const galleryBackgroundColour = Color.fromRGBO(127, 127, 125, 1.0); + static const galleryBackgroundColour = Color.fromRGBO(127, 127, 125, 1); static const red = Colors.red; static const white = Colors.white; diff --git a/lib/features/core/data/extensions/dio_extensions.dart b/lib/features/core/data/extensions/dio_extensions.dart index 9fa959e..bfe57e7 100644 --- a/lib/features/core/data/extensions/dio_extensions.dart +++ b/lib/features/core/data/extensions/dio_extensions.dart @@ -1,6 +1,7 @@ import 'package:dio/dio.dart'; -extension ResponseExtensions on Response { +/// Extensions on [Dio]'s [Response]. +extension ResponseExtensions on Response { /// Shorthand for getting response's successful state. - bool get isSuccessful => (data as Map)['response']; + bool get isSuccessful => (data! as Map)['response'] as bool; } diff --git a/lib/features/core/data/extensions/string_extensions.dart b/lib/features/core/data/extensions/string_extensions.dart index cf4c5cd..b51d429 100644 --- a/lib/features/core/data/extensions/string_extensions.dart +++ b/lib/features/core/data/extensions/string_extensions.dart @@ -1,3 +1,4 @@ +/// String extensions extension StringExtensions on String { /// Returns true if given word contains atleast all the characters in [targetChars], and `false` otherwise /// @@ -6,9 +7,9 @@ extension StringExtensions on String { required String targetChars, bool ignoreCase = true, }) { - final Set characterSet = ignoreCase - ? Set.from(targetChars.toLowerCase().split('')) - : Set.from(targetChars.split('')); + final characterSet = ignoreCase + ? Set.from(targetChars.toLowerCase().split('')) + : Set.from(targetChars.split('')); for (final testChar in ignoreCase ? toLowerCase().split('') : split('')) { characterSet.remove(testChar); if (characterSet.isEmpty) return true; diff --git a/lib/features/core/services/connections_service.dart b/lib/features/core/services/connections_service.dart index d22c133..388cac8 100644 --- a/lib/features/core/services/connections_service.dart +++ b/lib/features/core/services/connections_service.dart @@ -64,7 +64,7 @@ class ConnectionsService { static ConnectionsService get locate => Locator.locate(); } -extension _connectionStatusEmojiExtension on InternetConnectionStatus { +extension _ConnectionStatusEmojiExtension on InternetConnectionStatus { String get nameWithIcon { switch (this) { case InternetConnectionStatus.connected: @@ -75,7 +75,7 @@ extension _connectionStatusEmojiExtension on InternetConnectionStatus { } } -extension _connectivityEmojiExtension on ConnectivityResult { +extension _ConnectivityEmojiExtension on ConnectivityResult { String get nameWithIcon { switch (this) { case ConnectivityResult.bluetooth: diff --git a/lib/features/core/services/local_storage_service.dart b/lib/features/core/services/local_storage_service.dart index 3220b68..5e5634c 100644 --- a/lib/features/core/services/local_storage_service.dart +++ b/lib/features/core/services/local_storage_service.dart @@ -29,7 +29,7 @@ class LocalStorageService { } void updateFavourite({ - required index, + required int index, required bool newValue, }) { try { diff --git a/lib/features/core/services/logging_service.dart b/lib/features/core/services/logging_service.dart index f58f32c..6e67960 100644 --- a/lib/features/core/services/logging_service.dart +++ b/lib/features/core/services/logging_service.dart @@ -15,8 +15,8 @@ class LoggingService { useHistory: false, ), logger: TalkerLogger( - formater: - !Platform.isIOS ? const ColoredLoggerFormatter() : const ExtendedLoggerFormatter()), + formater: !Platform.isIOS ? const ColoredLoggerFormatter() : const ExtendedLoggerFormatter(), + ), loggerSettings: TalkerLoggerSettings( enableColors: !Platform.isIOS, ), @@ -49,11 +49,10 @@ class LoggingService { TalkerDioLogger( talker: Talker( logger: TalkerLogger( - formater: !Platform.isIOS - ? const ColoredLoggerFormatter() - : const ExtendedLoggerFormatter()), + formater: + !Platform.isIOS ? const ColoredLoggerFormatter() : const ExtendedLoggerFormatter(), + ), settings: TalkerSettings( - useConsoleLogs: true, useHistory: false, ), loggerSettings: TalkerLoggerSettings( @@ -63,7 +62,6 @@ class LoggingService { settings: const TalkerDioLoggerSettings( printRequestHeaders: true, printResponseHeaders: true, - printResponseMessage: true, ), ), ); diff --git a/lib/features/core/services/overlay_service.dart b/lib/features/core/services/overlay_service.dart index 2c59011..c130dee 100644 --- a/lib/features/core/services/overlay_service.dart +++ b/lib/features/core/services/overlay_service.dart @@ -24,8 +24,9 @@ class OverlayService { //todo(mehul): Fix and not ignore Overlay building while Widget building error. } on FlutterError catch (_) {} _loggingService.info('Overlay inserted with tag: $tag'); - } else + } else { _loggingService.info('Overlay with tag: $tag, NOT inserted'); + } } void removeOverlayEntry({ @@ -37,10 +38,12 @@ class OverlayService { _overlayEntryMap[tag.hashCode]?.remove(); _overlayEntryMap.remove(tag.hashCode); _loggingService.info('Overlay removed with tag: $tag'); - } else + } else { _loggingService.info('Overlay with tag: $tag already mounted OR not found. Skipped'); - } else + } + } else { _loggingService.info('Overlay with tag: $tag already exists. Skipped'); + } } void dispose() { diff --git a/lib/features/core/utils/mutex.dart b/lib/features/core/utils/mutex.dart index 70be6d3..c053cb6 100644 --- a/lib/features/core/utils/mutex.dart +++ b/lib/features/core/utils/mutex.dart @@ -4,19 +4,19 @@ import 'dart:ui'; /// A simple Mutex implementation using a [Completer]. class Mutex { - final _completerQueue = Queue(); + final _completerQueue = Queue>(); /// Runs the given [run] function-block in a thread-safe/blocked zone. A convenient `unlock()` /// is provided, which can be called anywhere to signal re-entry. FutureOr lockAndRun({ required FutureOr Function(VoidCallback unlock) run, }) async { - final completer = Completer(); + final completer = Completer(); _completerQueue.add(completer); if (_completerQueue.first != completer) { await _completerQueue.removeFirst().future; } - final value = await run(() => completer.complete()); + final value = await run(completer.complete); return value; } diff --git a/lib/features/core/views/error_page_view.dart b/lib/features/core/views/error_page_view.dart index 8f7041e..c7a9346 100644 --- a/lib/features/core/views/error_page_view.dart +++ b/lib/features/core/views/error_page_view.dart @@ -17,7 +17,7 @@ class ErrorPageView extends StatelessWidget { child: Column( children: [ Text(Strings.current.errorPageMessage), - const Gap(16), + Gap.size16, ], ), ); diff --git a/lib/features/core/widgets/gap.dart b/lib/features/core/widgets/gap.dart index 87291eb..84c10b0 100644 --- a/lib/features/core/widgets/gap.dart +++ b/lib/features/core/widgets/gap.dart @@ -1,8 +1,12 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; +/// Const evenly-sized gap. class Gap extends LeafRenderObjectWidget { - const Gap(this.size, {Key? key}) : super(key: key); + const Gap( + this.size, { + super.key, + }); final double size; @@ -58,13 +62,14 @@ class RenderGap extends RenderBox { } } +/// Animates [Gap] insertion. class AnimatedGap extends StatefulWidget { const AnimatedGap( this.gap, { - Key? key, this.duration = const Duration(milliseconds: 200), this.curve = Curves.easeInOut, - }) : super(key: key); + super.key, + }); final Duration duration; final double gap; @@ -107,10 +112,10 @@ class _AnimatedGapState extends State with SingleTickerProviderStat class AnimatedSliverGap extends StatefulWidget { const AnimatedSliverGap( this.gap, { - Key? key, this.duration = const Duration(milliseconds: 200), this.curve = Curves.easeInOut, - }) : super(key: key); + super.key, + }); final Duration duration; final double gap; diff --git a/lib/features/core/widgets/state/multi_value_listenable_builder.dart b/lib/features/core/widgets/state/multi_value_listenable_builder.dart index fb8be33..47f5a98 100644 --- a/lib/features/core/widgets/state/multi_value_listenable_builder.dart +++ b/lib/features/core/widgets/state/multi_value_listenable_builder.dart @@ -8,10 +8,13 @@ class MultiValueListenableBuilder extends StatelessWidget { required this.builder, this.child, super.key, - }) : assert(valueListenables.length != 0); + }) : assert( + valueListenables.length != 0, + 'Attached valueListenables must not be empty', + ); /// List of [ValueListenable]s to be listened to. - final List valueListenables; + final List> valueListenables; /// The builder function to be called when value of any of the [ValueListenable] changes. /// The order of values list will be same as [valueListenables] list. diff --git a/lib/features/home/api/unsplash_images_api.dart b/lib/features/home/api/unsplash_images_api.dart index abb25ba..efb53ed 100644 --- a/lib/features/home/api/unsplash_images_api.dart +++ b/lib/features/home/api/unsplash_images_api.dart @@ -9,16 +9,19 @@ import '../abstracts/images_api.dart'; import '../data/dtos/image_model_dto.dart'; class UnsplashImagesApi extends ImagesApi { + UnsplashImagesApi({required super.token}); + //final LoggingService _loggingService = LoggingService.locate; final random = Random(); - UnsplashImagesApi({required super.token}); - @override FutureOr> fetchImageUri() async { // Dummy fetching delay emulation - await Future.delayed(const Duration( - milliseconds: ConstValues.defaultEmulatedLatencyMillis * ConstValues.numberOfImages)); + await Future.delayed( + const Duration( + milliseconds: ConstValues.defaultEmulatedLatencyMillis * ConstValues.numberOfImages, + ), + ); final Iterable> fetchedImageModelDtos; try { @@ -48,8 +51,7 @@ class UnsplashImagesApi extends ImagesApi { } // Emulating deserialization - return fetchedImageModelDtos - .map((final emulatedModelSerialized) => ImageModelDTO.fromJson(emulatedModelSerialized)); + return fetchedImageModelDtos.map(ImageModelDTO.fromJson); } @override @@ -59,8 +61,11 @@ class UnsplashImagesApi extends ImagesApi { final numberOfResults = random.nextIntInRange(min: 0, max: ConstValues.numberOfImages); // Dummy fetching delay emulation - await Future.delayed( - Duration(milliseconds: ConstValues.defaultEmulatedLatencyMillis * numberOfResults)); + await Future.delayed( + Duration( + milliseconds: ConstValues.defaultEmulatedLatencyMillis * numberOfResults, + ), + ); final Iterable> searchImageModelDtos; try { @@ -87,8 +92,7 @@ class UnsplashImagesApi extends ImagesApi { return List.empty(); } - return searchImageModelDtos - .map((final emulatedModelSerialized) => ImageModelDTO.fromJson(emulatedModelSerialized)); + return searchImageModelDtos.map(ImageModelDTO.fromJson); } Uri _imageUrlGenerator({required int imageSide}) => Uri( diff --git a/lib/features/home/data/models/image_model.dart b/lib/features/home/data/models/image_model.dart index 0b04c17..2f7ed79 100644 --- a/lib/features/home/data/models/image_model.dart +++ b/lib/features/home/data/models/image_model.dart @@ -2,13 +2,24 @@ import '../dtos/image_model_dto.dart'; /// Represents an Image, that would be displayed in the gallery. class ImageModel { - const ImageModel({ + const ImageModel._({ required this.uri, required this.imageIndex, required this.imageName, required this.isFavourite, }); + factory ImageModel.fromDto({ + required ImageModelDTO imageModelDto, + required bool isFavourite, + }) => + ImageModel._( + uri: imageModelDto.uri, + imageIndex: imageModelDto.imageIndex, + imageName: imageModelDto.imageName, + isFavourite: isFavourite, + ); + /// An image's target [Uri]. /// /// Storing an image's [ByteData] is more expensive, memory-wise. @@ -23,24 +34,13 @@ class ImageModel { /// Whether the image was 'Starred' ot not. final bool isFavourite; - factory ImageModel.fromDto({ - required ImageModelDTO imageModelDto, - required bool isFavourite, - }) => - ImageModel( - uri: imageModelDto.uri, - imageIndex: imageModelDto.imageIndex, - imageName: imageModelDto.imageName, - isFavourite: isFavourite, - ); - ImageModel copyWith({ Uri? uri, int? imageIndex, String? imageName, bool? isFavourite, }) { - return ImageModel( + return ImageModel._( uri: uri ?? this.uri, imageIndex: imageIndex ?? this.imageIndex, imageName: imageName ?? this.imageName, diff --git a/lib/features/home/services/image_cache_manager_service.dart b/lib/features/home/services/image_cache_manager_service.dart index 6ded6a7..b986d14 100644 --- a/lib/features/home/services/image_cache_manager_service.dart +++ b/lib/features/home/services/image_cache_manager_service.dart @@ -22,7 +22,7 @@ class ImageCacheManagerService { final LoggingService _loggingService = LoggingService.locate; final _cacheManager = DefaultCacheManager(); - Future emptyCache() async => await _cacheManager.emptyCache(); + void emptyCache() => _cacheManager.emptyCache(); Future _init() async { _appLifecycleService.addListener( diff --git a/lib/features/home/views/gallery/gallery_view.dart b/lib/features/home/views/gallery/gallery_view.dart index 8faba98..60f5b42 100644 --- a/lib/features/home/views/gallery/gallery_view.dart +++ b/lib/features/home/views/gallery/gallery_view.dart @@ -150,8 +150,8 @@ class _SearchBox extends StatelessWidget { items: [ for (final searchOption in SearchOption.values) DropdownMenuItem( - child: Center(child: Text(searchOption.name)), value: searchOption, + child: Center(child: Text(searchOption.name)), ), ], value: searchOption, diff --git a/lib/features/home/views/gallery/gallery_view_model.dart b/lib/features/home/views/gallery/gallery_view_model.dart index 20304f6..666c74e 100644 --- a/lib/features/home/views/gallery/gallery_view_model.dart +++ b/lib/features/home/views/gallery/gallery_view_model.dart @@ -42,7 +42,7 @@ class GalleryViewModel extends BaseViewModel { ValueListenable get isViewingFavouriteListenable => _isViewingFavouriteNotifier; @override - Future initialise(bool Function() mounted, [arguments]) async { + Future initialise(bool Function() mounted, [Object? arguments]) async { super.initialise(mounted, arguments); } diff --git a/lib/features/home/views/image_carousel/image_carousel_view.dart b/lib/features/home/views/image_carousel/image_carousel_view.dart index d2563ce..a9ea153 100644 --- a/lib/features/home/views/image_carousel/image_carousel_view.dart +++ b/lib/features/home/views/image_carousel/image_carousel_view.dart @@ -40,7 +40,7 @@ class ImageCarouselView extends StatelessWidget { children: [ Expanded( child: Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(8), child: Card( elevation: 8, surfaceTintColor: ConstColours.transparent, @@ -110,7 +110,7 @@ class ImageCarouselView extends StatelessWidget { ), ), ), - const Gap(24), + Gap.size24, Padding( padding: const EdgeInsets.symmetric(horizontal: 24), // Assuming that this data is coming from an external CRM, if it is coming with the diff --git a/lib/features/home/views/image_carousel/image_carousel_view_model.dart b/lib/features/home/views/image_carousel/image_carousel_view_model.dart index 8d0f777..cdccfff 100644 --- a/lib/features/home/views/image_carousel/image_carousel_view_model.dart +++ b/lib/features/home/views/image_carousel/image_carousel_view_model.dart @@ -21,9 +21,11 @@ class ImageCarouselViewModel extends BaseViewModel { final CarouselController carouselController = CarouselController(); @override - Future initialise(bool Function() mounted, [arguments]) async { - _currentImageModelNotifier = ValueNotifier(_imagesService.imageModels - .elementAt((arguments as ImageCarouselViewArguments).imageIndexKey)); + Future initialise(bool Function() mounted, [Object? arguments]) async { + _currentImageModelNotifier = ValueNotifier( + _imagesService.imageModels + .elementAt((arguments! as ImageCarouselViewArguments).imageIndexKey), + ); log.info('Initialized with image: ${_currentImageModelNotifier.value.imageIndex}'); super.initialise(mounted, arguments); diff --git a/lib/locator.dart b/lib/locator.dart index 6547d25..881d964 100644 --- a/lib/locator.dart +++ b/lib/locator.dart @@ -58,61 +58,59 @@ class Locator { } static FutureOr _registerServices(GetIt it) async { - it.registerLazySingleton( - () => NavigationService( - mcgRouter: McgRouter.locate, - ), - ); - - it.registerFactory( - () => LoggingService(), - ); - - it.registerSingleton( - ConnectionsService( - connectivity: Connectivity(), - internetConnectionChecker: InternetConnectionChecker(), - loggingService: LoggingService.locate, - ), - signalsReady: true, - dispose: (final param) async => await param.dispose(), - ); + it + ..registerLazySingleton( + () => NavigationService( + mcgRouter: McgRouter.locate, + ), + ) + ..registerFactory( + LoggingService.new, + ) + ..registerSingleton( + ConnectionsService( + connectivity: Connectivity(), + internetConnectionChecker: InternetConnectionChecker(), + loggingService: LoggingService.locate, + ), + signalsReady: true, + dispose: (final param) async => param.dispose(), + ); await it.isReady(); - it.registerLazySingleton( - () => OverlayService( - loggingService: LoggingService.locate, - ), - dispose: (param) => param.dispose(), - ); - - it.registerSingleton( - AppLifecycleService( - loggingService: LoggingService.locate, - ), - dispose: (final param) async => await param.dispose(), - ); - - it.registerSingleton( - LocalStorageService(), - signalsReady: true, - ); + it + ..registerLazySingleton( + () => OverlayService( + loggingService: LoggingService.locate, + ), + dispose: (param) => param.dispose(), + ) + ..registerSingleton( + AppLifecycleService( + loggingService: LoggingService.locate, + ), + dispose: (final param) async => param.dispose(), + ) + ..registerSingleton( + LocalStorageService(), + signalsReady: true, + ); await it.isReady(); - it.registerSingleton( - ImagesService( - imagesApi: UnsplashImagesApi.locate, - localStorageService: LocalStorageService.locate, - loggingService: LoggingService.locate, - ), - ); - - it.registerSingleton( - ImageCacheManagerService( - appLifecycleService: AppLifecycleService.locate, - localStorageService: LocalStorageService.locate, - ), - ); + it + ..registerSingleton( + ImagesService( + imagesApi: UnsplashImagesApi.locate, + localStorageService: LocalStorageService.locate, + loggingService: LoggingService.locate, + ), + ) + ..registerSingleton( + ImageCacheManagerService( + appLifecycleService: AppLifecycleService.locate, + localStorageService: LocalStorageService.locate, + ), + ); } static FutureOr _registerRepos(GetIt locator) {} diff --git a/pubspec.lock b/pubspec.lock index b9708a4..4a5aed8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -437,7 +437,7 @@ packages: source: hosted version: "0.6.4" json_annotation: - dependency: "direct dev" + dependency: "direct main" description: name: json_annotation url: "https://pub.dartlang.org" @@ -833,6 +833,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.2" + very_good_analysis: + dependency: "direct dev" + description: + name: very_good_analysis + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" watcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9e9ae6b..05e7706 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,19 +36,19 @@ dependencies: intl_utils: ^2.8.1 connectivity_plus: ^3.0.2 internet_connection_checker: ^1.0.0+1 + json_annotation: ^4.7.0 string_similarity: ^2.0.0 # Util frontend flutter_markdown: ^0.6.13 auto_size_text: ^3.0.0 + flutter_svg: ^1.1.6 carousel_slider: ^4.2.1 # Logging talker: ^2.2.0 talker_dio_logger: ^1.0.0 - - # Assets - flutter_svg: ^1.1.6 + dev_dependencies: @@ -63,8 +63,8 @@ dev_dependencies: hive_generator: ^2.0.0 envied_generator: ^0.3.0 - # Annotations - json_annotation: ^4.7.0 + # Linters + very_good_analysis: ^3.1.0 flutter: uses-material-design: true