chore(mobile): Apply stricter linting rules for Flutter and known issues (#30373)

This commit is contained in:
Adam Gastineau
2026-07-30 15:15:35 -04:00
committed by GitHub
parent 9a143f0047
commit 858aeadce8
29 changed files with 50 additions and 32 deletions
+12 -1
View File
@@ -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:
+1 -1
View File
@@ -1,4 +1,4 @@
// ignore_for_file: avoid_print
// ignore_for_file: avoid_slow_async_io, avoid_print
import 'dart:convert';
import 'dart:io';
@@ -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';
@@ -286,7 +286,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
return SizedBox(
height: double.infinity,
width: double.infinity,
child: Container(
child: ColoredBox(
color: context.scaffoldBackgroundColor.withValues(alpha: 0.8),
child: Center(
child: Column(
@@ -429,7 +429,7 @@ class _DriftUploadDetailPageState extends ConsumerState<DriftUploadDetailPage> {
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)),
@@ -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)),
@@ -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)
@@ -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)),
@@ -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)),
@@ -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,
@@ -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)),
@@ -313,7 +313,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> 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)),
@@ -157,7 +157,7 @@ class _ProfilePictureCropPageState extends ConsumerState<ProfilePictureCropPage>
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: [
@@ -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),
@@ -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),
);
@@ -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)),
@@ -112,6 +112,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> 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');
}
@@ -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)),
@@ -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(
@@ -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)),
@@ -1,3 +1,5 @@
// ignore_for_file: avoid_slow_async_io
import 'dart:async';
import 'dart:io';
@@ -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;
@@ -61,6 +61,7 @@ class ViewIntentService {
try {
final file = File(path);
// ignore: avoid_slow_async_io
if (await file.exists()) {
await file.delete();
}
+2 -2
View File
@@ -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,
@@ -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),
@@ -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();
}
@@ -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),
@@ -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),
@@ -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();