diff --git a/mobile/analysis_options.yaml b/mobile/analysis_options.yaml index 1a7b463913..b9f18d0d81 100644 --- a/mobile/analysis_options.yaml +++ b/mobile/analysis_options.yaml @@ -29,7 +29,6 @@ linter: # Formatting avoid_print: true unawaited_futures: true - use_build_context_synchronously: false require_trailing_commas: true unrelated_type_equality_checks: true prefer_const_constructors: true @@ -51,6 +50,18 @@ linter: avoid_multiple_declarations_per_line: true unnecessary_breaks: true + # Known issues + avoid_slow_async_io: true + avoid_type_to_string: true + + # Flutter specific + use_build_context_synchronously: false + sized_box_for_whitespace: true + use_colored_box: true + use_decorated_box: true + avoid_unnecessary_containers: true + use_full_hex_values_for_flutter_colors: true + # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options analyzer: diff --git a/mobile/bin/generate_keys.dart b/mobile/bin/generate_keys.dart index a4cf562bcb..1ce643be12 100644 --- a/mobile/bin/generate_keys.dart +++ b/mobile/bin/generate_keys.dart @@ -1,4 +1,4 @@ -// ignore_for_file: avoid_print +// ignore_for_file: avoid_slow_async_io, avoid_print import 'dart:convert'; import 'dart:io'; diff --git a/mobile/lib/infrastructure/repositories/storage.repository.dart b/mobile/lib/infrastructure/repositories/storage.repository.dart index 3a63812485..9500190abc 100644 --- a/mobile/lib/infrastructure/repositories/storage.repository.dart +++ b/mobile/lib/infrastructure/repositories/storage.repository.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_slow_async_io + import 'dart:io'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; diff --git a/mobile/lib/pages/backup/drift_backup_album_selection.page.dart b/mobile/lib/pages/backup/drift_backup_album_selection.page.dart index 9f60a4e193..6589741aab 100644 --- a/mobile/lib/pages/backup/drift_backup_album_selection.page.dart +++ b/mobile/lib/pages/backup/drift_backup_album_selection.page.dart @@ -286,7 +286,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState { SizedBox( width: 48, height: 48, - child: Container( + child: DecoratedBox( decoration: BoxDecoration( color: context.colorScheme.outline.withValues(alpha: 0.1), borderRadius: const BorderRadius.all(Radius.circular(8)), diff --git a/mobile/lib/pages/common/app_log_detail.page.dart b/mobile/lib/pages/common/app_log_detail.page.dart index 274231a729..ab7668f845 100644 --- a/mobile/lib/pages/common/app_log_detail.page.dart +++ b/mobile/lib/pages/common/app_log_detail.page.dart @@ -48,7 +48,7 @@ class AppLogDetailPage extends HookConsumerWidget { ), ], ), - Container( + DecoratedBox( decoration: BoxDecoration( color: context.colorScheme.surfaceContainerHigh, borderRadius: const BorderRadius.all(Radius.circular(15.0)), @@ -79,7 +79,7 @@ class AppLogDetailPage extends HookConsumerWidget { style: TextStyle(fontSize: 12.0, color: context.primaryColor, fontWeight: FontWeight.bold), ), ), - Container( + DecoratedBox( decoration: BoxDecoration( color: context.colorScheme.surfaceContainerHigh, borderRadius: const BorderRadius.all(Radius.circular(15.0)), diff --git a/mobile/lib/pages/common/large_leading_tile.dart b/mobile/lib/pages/common/large_leading_tile.dart index 4563834473..58528008ca 100644 --- a/mobile/lib/pages/common/large_leading_tile.dart +++ b/mobile/lib/pages/common/large_leading_tile.dart @@ -34,7 +34,7 @@ class LargeLeadingTile extends StatelessWidget { return InkWell( borderRadius: BorderRadius.circular(borderRadius), onTap: disabled ? null : onTap, - child: Container( + child: DecoratedBox( decoration: BoxDecoration( color: selected ? selectedTileColor ?? Theme.of(context).primaryColor.withAlpha(30) diff --git a/mobile/lib/presentation/pages/drift_activities.page.dart b/mobile/lib/presentation/pages/drift_activities.page.dart index a52f1d7358..59c9a8a1e1 100644 --- a/mobile/lib/presentation/pages/drift_activities.page.dart +++ b/mobile/lib/presentation/pages/drift_activities.page.dart @@ -71,7 +71,7 @@ class DriftActivitiesPage extends HookConsumerWidget { ), Align( alignment: Alignment.bottomCenter, - child: Container( + child: DecoratedBox( decoration: BoxDecoration( color: context.scaffoldBackgroundColor, border: Border(top: BorderSide(color: context.colorScheme.secondaryContainer, width: 1)), diff --git a/mobile/lib/presentation/pages/drift_library.page.dart b/mobile/lib/presentation/pages/drift_library.page.dart index 190ad3af6a..b2b4d250f1 100644 --- a/mobile/lib/presentation/pages/drift_library.page.dart +++ b/mobile/lib/presentation/pages/drift_library.page.dart @@ -354,7 +354,7 @@ class _QuickAccessButtonList extends ConsumerWidget { return SliverPadding( padding: const EdgeInsets.only(left: 16, top: 12, right: 16, bottom: 32), sliver: SliverToBoxAdapter( - child: Container( + child: DecoratedBox( decoration: BoxDecoration( border: Border.all(color: context.colorScheme.onSurface.withAlpha(10), width: 1), borderRadius: const BorderRadius.all(Radius.circular(20)), diff --git a/mobile/lib/presentation/pages/drift_memory.page.dart b/mobile/lib/presentation/pages/drift_memory.page.dart index 4ae97f30e1..b8f3c94a00 100644 --- a/mobile/lib/presentation/pages/drift_memory.page.dart +++ b/mobile/lib/presentation/pages/drift_memory.page.dart @@ -281,7 +281,7 @@ class DriftMemoryPage extends HookConsumerWidget { final asset = memories[mIndex].assets[index]; return Stack( children: [ - Container( + ColoredBox( color: Colors.black, child: DriftMemoryCard( asset: asset, diff --git a/mobile/lib/presentation/pages/drift_partner_detail.page.dart b/mobile/lib/presentation/pages/drift_partner_detail.page.dart index fd5b64c108..53353ce689 100644 --- a/mobile/lib/presentation/pages/drift_partner_detail.page.dart +++ b/mobile/lib/presentation/pages/drift_partner_detail.page.dart @@ -89,7 +89,7 @@ class _InfoBoxState extends ConsumerState<_InfoBox> { height: 110, child: Padding( padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 16.0), - child: Container( + child: DecoratedBox( decoration: BoxDecoration( border: Border.all(color: context.colorScheme.onSurface.withAlpha(10), width: 1), borderRadius: const BorderRadius.all(Radius.circular(20)), diff --git a/mobile/lib/presentation/pages/drift_slideshow.page.dart b/mobile/lib/presentation/pages/drift_slideshow.page.dart index 3f0c441c01..9b7c10c891 100644 --- a/mobile/lib/presentation/pages/drift_slideshow.page.dart +++ b/mobile/lib/presentation/pages/drift_slideshow.page.dart @@ -313,7 +313,7 @@ class _DriftSlideshowPageState extends ConsumerState with Si return ImageFiltered( imageFilter: ImageFilter.blur(sigmaX: 30, sigmaY: 30), - child: Container( + child: DecoratedBox( decoration: BoxDecoration( image: DecorationImage( image: getFullImageProvider(asset, size: Size(context.width, context.height)), diff --git a/mobile/lib/presentation/pages/profile/profile_picture_crop.page.dart b/mobile/lib/presentation/pages/profile/profile_picture_crop.page.dart index 3fb32b7d93..e6ae6ad44f 100644 --- a/mobile/lib/presentation/pages/profile/profile_picture_crop.page.dart +++ b/mobile/lib/presentation/pages/profile/profile_picture_crop.page.dart @@ -157,7 +157,7 @@ class _ProfilePictureCropPageState extends ConsumerState return Center( child: ConstrainedBox( constraints: BoxConstraints(maxHeight: context.height * 0.7, maxWidth: context.width * 0.9), - child: Container( + child: DecoratedBox( decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(7)), boxShadow: [ diff --git a/mobile/lib/presentation/pages/search/drift_search.page.dart b/mobile/lib/presentation/pages/search/drift_search.page.dart index 6b818bd273..4d04967b28 100644 --- a/mobile/lib/presentation/pages/search/drift_search.page.dart +++ b/mobile/lib/presentation/pages/search/drift_search.page.dart @@ -598,7 +598,7 @@ class DriftSearchPage extends HookConsumerWidget { ), ), ], - title: Container( + title: DecoratedBox( decoration: BoxDecoration( border: Border.all(color: context.colorScheme.onSurface.withAlpha(0), width: 0), borderRadius: const BorderRadius.all(Radius.circular(24)), @@ -859,7 +859,7 @@ class _QuickLinkList extends StatelessWidget { @override Widget build(BuildContext context) { - return Container( + return DecoratedBox( decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(20)), border: Border.all(color: context.colorScheme.outline.withAlpha(10), width: 1), diff --git a/mobile/lib/presentation/widgets/album/album_selector.widget.dart b/mobile/lib/presentation/widgets/album/album_selector.widget.dart index 285c6290a9..ba6c6da560 100644 --- a/mobile/lib/presentation/widgets/album/album_selector.widget.dart +++ b/mobile/lib/presentation/widgets/album/album_selector.widget.dart @@ -395,7 +395,7 @@ class _SearchBar extends StatelessWidget { return SliverPadding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), sliver: SliverToBoxAdapter( - child: Container( + child: DecoratedBox( decoration: BoxDecoration( border: Border.all(color: context.colorScheme.onSurface.withAlpha(0), width: 0), borderRadius: const BorderRadius.all(Radius.circular(24)), @@ -699,7 +699,7 @@ class _GridAlbumCard extends ConsumerWidget { ); } - return Container( + return ColoredBox( color: context.colorScheme.surfaceContainerHighest, child: const Icon(Icons.photo_album_rounded, size: 40, color: Colors.grey), ); diff --git a/mobile/lib/presentation/widgets/album/album_tile.dart b/mobile/lib/presentation/widgets/album/album_tile.dart index 1aeadf61bc..bbf7e11e5a 100644 --- a/mobile/lib/presentation/widgets/album/album_tile.dart +++ b/mobile/lib/presentation/widgets/album/album_tile.dart @@ -51,7 +51,7 @@ class AlbumTile extends ConsumerWidget { : SizedBox( width: 80, height: 80, - child: Container( + child: DecoratedBox( decoration: BoxDecoration( color: context.colorScheme.surfaceContainer, borderRadius: const BorderRadius.all(Radius.circular(16)), diff --git a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart index d007883ec9..6f2398046f 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart @@ -112,6 +112,7 @@ class _NativeVideoViewerState extends ConsumerState with Widg final localFilePath = widget.localFilePath; if (localFilePath != null) { final file = File(localFilePath); + // ignore: avoid_slow_async_io if (!await file.exists()) { throw Exception('No file found for the video'); } diff --git a/mobile/lib/presentation/widgets/images/local_album_thumbnail.widget.dart b/mobile/lib/presentation/widgets/images/local_album_thumbnail.widget.dart index b519da33c3..966e070872 100644 --- a/mobile/lib/presentation/widgets/images/local_album_thumbnail.widget.dart +++ b/mobile/lib/presentation/widgets/images/local_album_thumbnail.widget.dart @@ -14,7 +14,7 @@ class LocalAlbumThumbnail extends ConsumerWidget { return localAlbumThumbnail.when( data: (data) { if (data == null) { - return Container( + return DecoratedBox( decoration: BoxDecoration( color: context.colorScheme.surfaceContainer, borderRadius: const BorderRadius.all(Radius.circular(16)), diff --git a/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart b/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart index 7d71f0296d..1d3dcb2cf0 100644 --- a/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart +++ b/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart @@ -346,7 +346,7 @@ class _UploadProgressOverlay extends StatelessWidget { final percentage = isError ? 0 : (progress * 100).toInt(); return Positioned.fill( - child: Container( + child: ColoredBox( color: isError ? Colors.red.withValues(alpha: 0.6) : Colors.black54, child: Center( child: Column( diff --git a/mobile/lib/presentation/widgets/memory/memory_card.widget.dart b/mobile/lib/presentation/widgets/memory/memory_card.widget.dart index 2a88de8e0a..7e782a3db4 100644 --- a/mobile/lib/presentation/widgets/memory/memory_card.widget.dart +++ b/mobile/lib/presentation/widgets/memory/memory_card.widget.dart @@ -97,7 +97,7 @@ class _BlurredBackdrop extends HookWidget { final blurhash = useDriftBlurHashRef(asset).value; if (blurhash != null) { // Use a nice cheap blur hash image decoration - return Container( + return DecoratedBox( decoration: BoxDecoration( image: DecorationImage(image: MemoryImage(blurhash), fit: BoxFit.cover), ), @@ -109,7 +109,7 @@ class _BlurredBackdrop extends HookWidget { // safely use that as the image provider return ImageFiltered( imageFilter: ImageFilter.blur(sigmaX: 30, sigmaY: 30), - child: Container( + child: DecoratedBox( decoration: BoxDecoration( image: DecorationImage( image: getFullImageProvider(asset, size: Size(context.width, context.height)), diff --git a/mobile/lib/services/download.service.dart b/mobile/lib/services/download.service.dart index de8e8af3f5..f38b20cc21 100644 --- a/mobile/lib/services/download.service.dart +++ b/mobile/lib/services/download.service.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_slow_async_io + import 'dart:async'; import 'dart:io'; diff --git a/mobile/lib/services/foreground_upload.service.dart b/mobile/lib/services/foreground_upload.service.dart index 7c0352a00e..36d3975a26 100644 --- a/mobile/lib/services/foreground_upload.service.dart +++ b/mobile/lib/services/foreground_upload.service.dart @@ -419,6 +419,7 @@ class ForegroundUploadService { void Function(int bytes, int totalBytes)? onProgress, }) async { try { + // ignore: avoid_slow_async_io final stats = await file.stat(); final fileCreatedAt = stats.changed; final fileModifiedAt = stats.modified; diff --git a/mobile/lib/services/view_intent.service.dart b/mobile/lib/services/view_intent.service.dart index 22a3407e5a..e822d1ebb6 100644 --- a/mobile/lib/services/view_intent.service.dart +++ b/mobile/lib/services/view_intent.service.dart @@ -61,6 +61,7 @@ class ViewIntentService { try { final file = File(path); + // ignore: avoid_slow_async_io if (await file.exists()) { await file.delete(); } diff --git a/mobile/lib/widgets/common/tag_picker.dart b/mobile/lib/widgets/common/tag_picker.dart index 97fbff1930..a9a68fe044 100644 --- a/mobile/lib/widgets/common/tag_picker.dart +++ b/mobile/lib/widgets/common/tag_picker.dart @@ -125,7 +125,7 @@ class TagPicker extends HookConsumerWidget { // Create new tag tile return Padding( padding: const EdgeInsets.only(bottom: 2.0), - child: Container( + child: DecoratedBox( decoration: BoxDecoration( color: isCreateSelected ? context.primaryColor : context.primaryColor.withAlpha(25), borderRadius: const BorderRadius.all(Radius.circular(10)), @@ -160,7 +160,7 @@ class TagPicker extends HookConsumerWidget { return Padding( padding: const EdgeInsets.only(bottom: 2.0), - child: Container( + child: DecoratedBox( decoration: BoxDecoration( color: isSelected ? context.primaryColor : context.primaryColor.withAlpha(25), borderRadius: borderRadius, diff --git a/mobile/lib/widgets/map/map_settings/map_theme_picker.dart b/mobile/lib/widgets/map/map_settings/map_theme_picker.dart index 7866c0ecdc..e66f08c221 100644 --- a/mobile/lib/widgets/map/map_settings/map_theme_picker.dart +++ b/mobile/lib/widgets/map/map_settings/map_theme_picker.dart @@ -69,7 +69,7 @@ class _BorderedMapThumbnail extends StatelessWidget { Widget build(BuildContext context) { return Column( children: [ - Container( + DecoratedBox( decoration: BoxDecoration( border: Border.fromBorderSide( BorderSide(width: 4, color: shouldHighlight ? context.colorScheme.onSurface : Colors.transparent), diff --git a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart index 92787077a1..7bd604ae5e 100644 --- a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart +++ b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart @@ -39,6 +39,7 @@ class SyncStatusAndActions extends HookConsumerWidget { final documentsDir = await getApplicationDocumentsDirectory(); final dbFile = File(path.join(documentsDir.path, 'immich.sqlite')); + // ignore: avoid_slow_async_io if (!await dbFile.exists()) { if (context.mounted) { context.scaffoldMessenger.showSnackBar( @@ -61,6 +62,7 @@ class SyncStatusAndActions extends HookConsumerWidget { ); Future.delayed(const Duration(seconds: 30), () async { + // ignore: avoid_slow_async_io if (await exportFile.exists()) { await exportFile.delete(); } diff --git a/mobile/lib/widgets/settings/free_up_space_settings.dart b/mobile/lib/widgets/settings/free_up_space_settings.dart index 7b16c2d67d..dbec3a2dcb 100644 --- a/mobile/lib/widgets/settings/free_up_space_settings.dart +++ b/mobile/lib/widgets/settings/free_up_space_settings.dart @@ -773,7 +773,7 @@ class _DatePresetCard extends StatelessWidget { child: InkWell( onTap: onTap, borderRadius: const BorderRadius.all(Radius.circular(12)), - child: Container( + child: DecoratedBox( decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(12)), border: Border.all(color: isSelected ? context.colorScheme.primary : Colors.transparent, width: 1), diff --git a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart index 3fead2c59f..1defd2df44 100644 --- a/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart +++ b/mobile/lib/widgets/settings/preference_settings/primary_color_setting.dart @@ -69,7 +69,7 @@ class PrimaryColorSetting extends HookConsumerWidget { right: 0, top: 0, bottom: 0, - child: Container( + child: DecoratedBox( decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(100)), color: Colors.grey[900]?.withValues(alpha: .4), diff --git a/mobile/test/services/view_intent_service_test.dart b/mobile/test/services/view_intent_service_test.dart index 7b3d0b85e7..fd8f5f725c 100644 --- a/mobile/test/services/view_intent_service_test.dart +++ b/mobile/test/services/view_intent_service_test.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_slow_async_io + import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; @@ -13,11 +15,7 @@ void main() { late Directory tempRoot; late Directory cacheDir; - final attachment = ViewIntentPayload( - path: '/tmp/file.jpg', - mimeType: 'image/jpeg', - localAssetId: '42', - ); + final attachment = ViewIntentPayload(path: '/tmp/file.jpg', mimeType: 'image/jpeg', localAssetId: '42'); setUp(() { hostApi = MockViewIntentHostApi();