chore(mobile): Apply stricter linting rules for formatting (#30370)

* chore(mobile): Apply stricter linting rules for formatting

* Formatting fixes
This commit is contained in:
Adam Gastineau 2026-07-30 01:56:46 -07:00 committed by GitHub
parent 0293414abd
commit d864a90811
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
208 changed files with 515 additions and 533 deletions

View file

@ -26,8 +26,8 @@ linter:
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Formatting
avoid_print: true
unawaited_futures: true
use_build_context_synchronously: false
require_trailing_commas: true
@ -35,6 +35,21 @@ linter:
prefer_const_constructors: true
always_use_package_imports: true
always_put_control_body_on_new_line: true
unnecessary_null_checks: true
unnecessary_parenthesis: true
prefer_final_locals: true
prefer_const_declarations: true
prefer_const_literals_to_create_immutables: true
use_super_parameters: true
directives_ordering: true
no_leading_underscores_for_local_identifiers: true
always_declare_return_types: true
avoid_void_async: true
noop_primitive_operations: true
use_named_constants: true
combinators_ordering: true
avoid_multiple_declarations_per_line: true
unnecessary_breaks: true
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
@ -46,20 +61,12 @@ analyzer:
- lib/**/*.g.dart
- lib/**/*.drift.dart
# TODO: Re-enable after upgrading custom_lint
# plugins:
# - custom_lint
# NOTE: We explicitly do not use riverpod_lint as there are analyzer version conflicts between
# our Flutter version and the required old riverpod_lint 2.x
errors:
unawaited_futures: warning
always_put_control_body_on_new_line: warning
custom_lint:
rules:
- avoid_build_context_in_providers: false
- avoid_public_notifier_properties: false
- avoid_manual_providers_as_generated_provider_dependency: false
- unsupported_provider_value: false
dart_code_metrics:
rules:
- banned-usage:

View file

@ -42,8 +42,8 @@ class CropAspectRatio {
}
}
const aspectRatioFree = CropAspectRatio(customLabel: "Free", icon: Icons.crop_free);
const aspectRatioOriginal = CropAspectRatio(customLabel: "Original", icon: Icons.crop_original);
const aspectRatioFree = CropAspectRatio.free;
const aspectRatioOriginal = CropAspectRatio.original;
final aspectRatioPresets = [
CropAspectRatio.free,

View file

@ -53,7 +53,7 @@ sealed class BaseAsset {
if (durationMs != null) {
return Duration(milliseconds: durationMs);
}
return const Duration();
return Duration.zero;
}
bool get hasRemote => storage == AssetState.remote || storage == AssetState.merged;

View file

@ -1,4 +1,4 @@
import "package:openapi/api.dart" show CropParameters, RotateParameters, MirrorParameters;
import "package:openapi/api.dart" show CropParameters, MirrorParameters, RotateParameters;
enum AssetEditAction { rotate, crop, mirror, other }

View file

@ -190,9 +190,9 @@ class AppConfig {
.viewerTapToNavigate => copyWith(viewer: viewer.copyWith(tapToNavigate: value as bool)),
.networkAutoEndpointSwitching => copyWith(network: network.copyWith(autoEndpointSwitching: value as bool)),
.networkPreferredWifiName => copyWith(
network: network.copyWith(preferredWifiName: .fromNullable((value as String?))),
network: network.copyWith(preferredWifiName: .fromNullable(value as String?)),
),
.networkLocalEndpoint => copyWith(network: network.copyWith(localEndpoint: .fromNullable((value as String?)))),
.networkLocalEndpoint => copyWith(network: network.copyWith(localEndpoint: .fromNullable(value as String?))),
.networkExternalEndpointList => copyWith(network: network.copyWith(externalEndpointList: value as List<String>)),
.networkCustomHeaders => copyWith(network: network.copyWith(customHeaders: value as Map<String, String>)),
.albumSortMode => copyWith(album: album.copyWith(sortMode: value as AlbumSortMode)),

View file

@ -105,10 +105,8 @@ class RemoteAlbumService {
switch (filterMode) {
case QuickFilterMode.myAlbums:
filtered = filtered.where((album) => album.ownerId == userId).toList();
break;
case QuickFilterMode.sharedWithMe:
filtered = filtered.where((album) => album.ownerId != userId).toList();
break;
case QuickFilterMode.all:
break;
}

View file

@ -155,7 +155,7 @@ class SyncStreamService {
}
Future<void> _handleEvents(List<SyncEvent> events, Function() abort, Function() reset) async {
List<SyncEvent> items = [];
final List<SyncEvent> items = [];
for (final event in events) {
if (isCancelled) {
_logger.warning("Sync stream cancelled");

View file

@ -178,7 +178,7 @@ class TimelineService {
if (!hasRange(index, count)) {
throw RangeError('TimelineService::getAssets Index out of range');
}
int start = index - _bufferOffset;
final int start = index - _bufferOffset;
return _buffer.slice(start, start + count);
}

View file

@ -15,8 +15,8 @@ extension DTOToAsset on api.AssetResponseDto {
ownerId: ownerId,
visibility: visibility.toAssetVisibility(),
durationMs: duration,
height: height?.toInt(),
width: width?.toInt(),
height: height,
width: width,
isFavorite: isFavorite,
livePhotoVideoId: livePhotoVideoId.orElse(null),
thumbHash: thumbhash,
@ -38,8 +38,8 @@ extension DTOToAsset on api.AssetResponseDto {
ownerId: ownerId,
visibility: visibility.toAssetVisibility(),
durationMs: duration,
height: height?.toInt(),
width: width?.toInt(),
height: height,
width: width,
isFavorite: isFavorite,
livePhotoVideoId: livePhotoVideoId.orElse(null),
thumbHash: thumbhash,

View file

@ -5,7 +5,8 @@ import 'package:collection/collection.dart';
extension ListExtension<E> on List<E> {
List<E> uniqueConsecutive({int Function(E a, E b)? compare, void Function(E a, E b)? onDuplicate}) {
compare ??= (E a, E b) => a == b ? 0 : 1;
int i = 1, j = 1;
int i = 1;
int j = 1;
for (; i < length; i++) {
if (compare(this[i - 1], this[i]) != 0) {
if (i != j) {

View file

@ -4,7 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
extension TimeAgoExtension on DateTime {
/// Displays the time difference of this [DateTime] object to the current time as a [String]
String timeAgo({bool numericDates = true}) {
DateTime date = toLocal();
final DateTime date = toLocal();
final now = DateTime.now().toLocal();
final difference = now.difference(date);
@ -13,27 +13,27 @@ extension TimeAgoExtension on DateTime {
} else if (difference.inSeconds < 60) {
return '${difference.inSeconds} seconds ago';
} else if (difference.inMinutes <= 1) {
return (numericDates) ? '1 minute ago' : 'A minute ago';
return numericDates ? '1 minute ago' : 'A minute ago';
} else if (difference.inMinutes < 60) {
return '${difference.inMinutes} minutes ago';
} else if (difference.inHours <= 1) {
return (numericDates) ? '1 hour ago' : 'An hour ago';
return numericDates ? '1 hour ago' : 'An hour ago';
} else if (difference.inHours < 60) {
return '${difference.inHours} hours ago';
} else if (difference.inDays <= 1) {
return (numericDates) ? '1 day ago' : 'Yesterday';
return numericDates ? '1 day ago' : 'Yesterday';
} else if (difference.inDays < 6) {
return '${difference.inDays} days ago';
} else if ((difference.inDays / 7).ceil() <= 1) {
return (numericDates) ? '1 week ago' : 'Last week';
return numericDates ? '1 week ago' : 'Last week';
} else if ((difference.inDays / 7).ceil() < 4) {
return '${(difference.inDays / 7).ceil()} weeks ago';
} else if ((difference.inDays / 30).ceil() <= 1) {
return (numericDates) ? '1 month ago' : 'Last month';
return numericDates ? '1 month ago' : 'Last month';
} else if ((difference.inDays / 30).ceil() < 30) {
return '${(difference.inDays / 30).ceil()} months ago';
} else if ((difference.inDays / 365).ceil() <= 1) {
return (numericDates) ? '1 year ago' : 'Last year';
return numericDates ? '1 year ago' : 'Last year';
}
return '${(difference.inDays / 365).floor()} years ago';
}

View file

@ -79,8 +79,8 @@ extension RemoteExifEntityDataDomainEx on RemoteExifEntityData {
orientation: orientation,
latitude: latitude,
longitude: longitude,
f: fNumber?.toDouble(),
mm: focalLength?.toDouble(),
f: fNumber,
mm: focalLength,
lens: lens,
isFlipped: ExifDtoConverter.isOrientationFlipped(orientation),
exposureSeconds: ExifDtoConverter.exposureTimeToSeconds(exposureTime),

View file

@ -1,6 +1,6 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/infrastructure/entities/log.entity.drift.dart';
import 'package:immich_mobile/domain/models/log.model.dart' as domain;
import 'package:immich_mobile/infrastructure/entities/log.entity.drift.dart';
class LogMessageEntity extends Table {
const LogMessageEntity();

View file

@ -18,7 +18,7 @@ abstract class ImageRequest {
final int requestId = _nextRequestId++;
bool _isCancelled = false;
get isCancelled => _isCancelled;
bool get isCancelled => _isCancelled;
ImageRequest();

View file

@ -14,8 +14,13 @@ class RemoteImageRequest extends ImageRequest {
final info = await remoteImageApi.requestImage(uri, requestId: requestId, preferEncoded: false);
// Android falls back to encoded data if native decoding fails, so check for both shapes of the response.
final frame = switch (info) {
{'pointer': int pointer, 'length': int length} => await _fromEncodedPlatformImage(pointer, length),
{'pointer': int pointer, 'width': int width, 'height': int height, 'rowBytes': int rowBytes} =>
{'pointer': final int pointer, 'length': final int length} => await _fromEncodedPlatformImage(pointer, length),
{
'pointer': final int pointer,
'width': final int width,
'height': final int height,
'rowBytes': final int rowBytes,
} =>
await _fromDecodedPlatformImage(pointer, width, height, rowBytes),
_ => null,
};

View file

@ -4,6 +4,7 @@ import 'package:drift/drift.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.drift.dart';
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
@ -16,7 +17,7 @@ class DriftBackupRepository extends DriftDatabaseRepository {
final Drift _db;
const DriftBackupRepository(this._db) : super(_db);
_getExcludedSubquery() {
JoinedSelectStatement<$LocalAlbumAssetEntityTable, LocalAlbumAssetEntityData> _getExcludedSubquery() {
return _db.localAlbumAssetEntity.selectOnly()
..addColumns([_db.localAlbumAssetEntity.assetId])
..join([

View file

@ -356,7 +356,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
return _deleteAssets(assetIds);
}
List<String> assetsToDelete = [];
final List<String> assetsToDelete = [];
List<String> assetsToUnLink = [];
final uniqueAssets = await _getUniqueAssetsInAlbum(albumId);

View file

@ -1,7 +1,7 @@
import 'package:drift/drift.dart';
import 'package:immich_mobile/domain/models/ocr.model.dart';
import 'package:immich_mobile/infrastructure/entities/asset_ocr.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:drift/drift.dart';
class OcrRepository extends DriftDatabaseRepository {
final Drift _db;

View file

@ -21,28 +21,28 @@ class SearchApiRepository extends ApiRepository {
(filter.assetId != null && filter.assetId!.isNotEmpty)) {
return _api.searchSmart(
SmartSearchDto(
query: filter.context == null ? const Optional.absent() : Optional.present(filter.context!),
queryAssetId: filter.assetId == null ? const Optional.absent() : Optional.present(filter.assetId!),
language: filter.language == null ? const Optional.absent() : Optional.present(filter.language!),
query: filter.context == null ? const Optional.absent() : Optional.present(filter.context),
queryAssetId: filter.assetId == null ? const Optional.absent() : Optional.present(filter.assetId),
language: filter.language == null ? const Optional.absent() : Optional.present(filter.language),
country: filter.location.country == null
? const Optional.absent()
: Optional.present(filter.location.country!),
state: filter.location.state == null ? const Optional.absent() : Optional.present(filter.location.state!),
city: filter.location.city == null ? const Optional.absent() : Optional.present(filter.location.city!),
make: filter.camera.make == null ? const Optional.absent() : Optional.present(filter.camera.make!),
model: filter.camera.model == null ? const Optional.absent() : Optional.present(filter.camera.model!),
: Optional.present(filter.location.country),
state: filter.location.state == null ? const Optional.absent() : Optional.present(filter.location.state),
city: filter.location.city == null ? const Optional.absent() : Optional.present(filter.location.city),
make: filter.camera.make == null ? const Optional.absent() : Optional.present(filter.camera.make),
model: filter.camera.model == null ? const Optional.absent() : Optional.present(filter.camera.model),
takenAfter: filter.date.takenAfter == null
? const Optional.absent()
: Optional.present(filter.date.takenAfter!),
: Optional.present(filter.date.takenAfter),
takenBefore: filter.date.takenBefore == null
? const Optional.absent()
: Optional.present(filter.date.takenBefore!),
: Optional.present(filter.date.takenBefore),
visibility: Optional.present(filter.display.isArchive ? AssetVisibility.archive : AssetVisibility.timeline),
rating: filter.rating.rating.toOptional(),
isFavorite: filter.display.isFavorite ? const Optional.present(true) : const Optional.absent(),
isNotInAlbum: filter.display.isNotInAlbum ? const Optional.present(true) : const Optional.absent(),
personIds: Optional.present(filter.people.map((e) => e.id).toList()),
tagIds: filter.tagIds == null ? const Optional.absent() : Optional.present(filter.tagIds!),
tagIds: filter.tagIds == null ? const Optional.absent() : Optional.present(filter.tagIds),
type: type == null ? const Optional.absent() : Optional.present(type),
page: Optional.present(page),
size: const Optional.present(100),
@ -53,29 +53,27 @@ class SearchApiRepository extends ApiRepository {
return _api.searchAssets(
MetadataSearchDto(
originalFileName: filter.filename != null && filter.filename!.isNotEmpty
? Optional.present(filter.filename!)
? Optional.present(filter.filename)
: const Optional.absent(),
country: filter.location.country == null ? const Optional.absent() : Optional.present(filter.location.country!),
country: filter.location.country == null ? const Optional.absent() : Optional.present(filter.location.country),
description: filter.description != null && filter.description!.isNotEmpty
? Optional.present(filter.description!)
? Optional.present(filter.description)
: const Optional.absent(),
ocr: filter.ocr != null && filter.ocr!.isNotEmpty ? Optional.present(filter.ocr!) : const Optional.absent(),
state: filter.location.state == null ? const Optional.absent() : Optional.present(filter.location.state!),
city: filter.location.city == null ? const Optional.absent() : Optional.present(filter.location.city!),
make: filter.camera.make == null ? const Optional.absent() : Optional.present(filter.camera.make!),
model: filter.camera.model == null ? const Optional.absent() : Optional.present(filter.camera.model!),
takenAfter: filter.date.takenAfter == null
? const Optional.absent()
: Optional.present(filter.date.takenAfter!),
ocr: filter.ocr != null && filter.ocr!.isNotEmpty ? Optional.present(filter.ocr) : const Optional.absent(),
state: filter.location.state == null ? const Optional.absent() : Optional.present(filter.location.state),
city: filter.location.city == null ? const Optional.absent() : Optional.present(filter.location.city),
make: filter.camera.make == null ? const Optional.absent() : Optional.present(filter.camera.make),
model: filter.camera.model == null ? const Optional.absent() : Optional.present(filter.camera.model),
takenAfter: filter.date.takenAfter == null ? const Optional.absent() : Optional.present(filter.date.takenAfter),
takenBefore: filter.date.takenBefore == null
? const Optional.absent()
: Optional.present(filter.date.takenBefore!),
: Optional.present(filter.date.takenBefore),
visibility: Optional.present(filter.display.isArchive ? AssetVisibility.archive : AssetVisibility.timeline),
rating: filter.rating.rating.toOptional(),
isFavorite: filter.display.isFavorite ? const Optional.present(true) : const Optional.absent(),
isNotInAlbum: filter.display.isNotInAlbum ? const Optional.present(true) : const Optional.absent(),
personIds: Optional.present(filter.people.map((e) => e.id).toList()),
tagIds: filter.tagIds == null ? const Optional.absent() : Optional.present(filter.tagIds!),
tagIds: filter.tagIds == null ? const Optional.absent() : Optional.present(filter.tagIds),
type: type == null ? const Optional.absent() : Optional.present(type),
page: Optional.present(page),
size: const Optional.present(1000),

View file

@ -80,7 +80,7 @@ class SyncApiRepository {
);
String previousChunk = '';
List<String> lines = [];
final List<String> lines = [];
bool shouldAbort = false;
@ -105,7 +105,7 @@ class SyncApiRepository {
}
previousChunk += chunk;
final parts = previousChunk.toString().split('\n');
final parts = previousChunk.split('\n');
previousChunk = parts.removeLast();
lines.addAll(parts);

View file

@ -31,8 +31,8 @@ import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.drift
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/infrastructure/utils/exif.converter.dart';
import 'package:logging/logging.dart';
import 'package:openapi/api.dart' as api show AssetVisibility, AlbumUserRole, UserMetadataKey, AssetEditAction;
import 'package:openapi/api.dart' hide UserMetadataKey, AssetEditAction, AssetVisibility, AlbumUserRole;
import 'package:openapi/api.dart' as api show AlbumUserRole, AssetEditAction, AssetVisibility, UserMetadataKey;
import 'package:openapi/api.dart' hide AlbumUserRole, AssetEditAction, AssetVisibility, UserMetadataKey;
class SyncStreamRepository extends DriftDatabaseRepository {
final Logger _logger = Logger('DriftSyncStreamRepository');
@ -287,8 +287,8 @@ class SyncStreamRepository extends DriftDatabaseRepository {
fNumber: Value(exif.fNumber),
fileSize: Value(exif.fileSizeInByte),
focalLength: Value(exif.focalLength),
latitude: Value(exif.latitude?.toDouble()),
longitude: Value(exif.longitude?.toDouble()),
latitude: Value(exif.latitude),
longitude: Value(exif.longitude),
iso: Value(exif.iso),
make: Value(exif.make),
model: Value(exif.model),

View file

@ -66,7 +66,7 @@ class DriftTrashedLocalAssetRepository extends DriftDatabaseRepository {
return;
}
final assetIds = trashedAssets.map((e) => e.asset.id).toSet();
Map<String, String> localChecksumById = await _getCachedChecksums(assetIds);
final Map<String, String> localChecksumById = await _getCachedChecksums(assetIds);
return _db.transaction(() async {
await _db.batch((batch) {

View file

@ -21,7 +21,7 @@ abstract final class ExifDtoConverter {
lens: dto.lensModel.orElse(null),
f: dto.fNumber.orElse(null)?.toDouble(),
mm: dto.focalLength.orElse(null)?.toDouble(),
iso: dto.iso.orElse(null)?.toInt(),
iso: dto.iso.orElse(null),
exposureSeconds: exposureTimeToSeconds(dto.exposureTime.orElse(null)),
);
}
@ -40,7 +40,7 @@ abstract final class ExifDtoConverter {
if (second == null) {
return null;
}
double? value = double.tryParse(second);
final double? value = double.tryParse(second);
if (value != null) {
return value;
}

View file

@ -24,13 +24,13 @@ import 'package:immich_mobile/pages/common/splash_screen.page.dart';
import 'package:immich_mobile/platform/background_worker_lock_api.g.dart';
import 'package:immich_mobile/providers/app_life_cycle.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/share_intent_upload.provider.dart';
import 'package:immich_mobile/providers/view_intent/view_intent_handler.provider.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/providers/locale_provider.dart';
import 'package:immich_mobile/providers/routes.provider.dart';
import 'package:immich_mobile/providers/theme.provider.dart';
import 'package:immich_mobile/providers/view_intent/view_intent_handler.provider.dart';
import 'package:immich_mobile/routing/app_navigation_observer.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/services/deep_link.service.dart';
@ -84,7 +84,7 @@ Future<void> initApp() async {
FlutterError.presentError(details);
log.severe(
'FlutterError - Catch all',
"${details.toString()}\nException: ${details.exception}\nLibrary: ${details.library}\nContext: ${details.context}",
"$details\nException: ${details.exception}\nLibrary: ${details.library}\nContext: ${details.context}",
details.stack,
);
};
@ -130,23 +130,18 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
dPrint(() => "[APP STATE] resumed");
ref.read(appStateProvider.notifier).handleAppResume();
unawaited(ref.read(viewIntentHandlerProvider).onAppResumed());
break;
case AppLifecycleState.inactive:
dPrint(() => "[APP STATE] inactive");
ref.read(appStateProvider.notifier).handleAppInactivity();
break;
case AppLifecycleState.paused:
dPrint(() => "[APP STATE] paused");
ref.read(appStateProvider.notifier).handleAppPause();
break;
case AppLifecycleState.detached:
dPrint(() => "[APP STATE] detached");
ref.read(appStateProvider.notifier).handleAppDetached();
break;
case AppLifecycleState.hidden:
dPrint(() => "[APP STATE] hidden");
ref.read(appStateProvider.notifier).handleAppHidden();
break;
}
}
@ -219,7 +214,7 @@ class ImmichAppState extends ConsumerState<ImmichApp> with WidgetsBindingObserve
}
@override
initState() {
void initState() {
super.initState();
initApp().then((_) => dPrint(() => "App Init Completed"));
WidgetsBinding.instance.addPostFrameCallback((_) {

View file

@ -67,7 +67,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
}
@override
dispose() {
void dispose() {
super.dispose();
WakelockPlus.disable();
}

View file

@ -12,8 +12,8 @@ import 'package:immich_mobile/infrastructure/repositories/settings.repository.da
import 'package:immich_mobile/providers/background_sync.provider.dart';
import 'package:immich_mobile/providers/backup/backup_album.provider.dart';
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/widgets/backup/drift_album_info_list_tile.dart';
import 'package:immich_mobile/widgets/common/search_field.dart';
@ -321,9 +321,9 @@ class _AlbumSelectionList extends StatelessWidget {
return SliverPadding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(((context, index) {
delegate: SliverChildBuilderDelegate((context, index) {
return DriftAlbumInfoListTile(album: filteredAlbums[index]);
}), childCount: filteredAlbums.length),
}, childCount: filteredAlbums.length),
),
);
}
@ -345,9 +345,9 @@ class _AlbumSelectionGrid extends StatelessWidget {
crossAxisSpacing: 12,
),
itemCount: filteredAlbums.length,
itemBuilder: ((context, index) {
itemBuilder: (context, index) {
return DriftAlbumInfoListTile(album: filteredAlbums[index]);
}),
},
),
);
}

View file

@ -20,7 +20,7 @@ class DriftBackupAssetDetailPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
AsyncValue<List<LocalAsset>> result = ref.watch(driftBackupCandidateProvider);
final AsyncValue<List<LocalAsset>> result = ref.watch(driftBackupCandidateProvider);
return Scaffold(
appBar: AppBar(title: Text('backup_controller_page_remainder'.t(context: context))),
body: result.when(

View file

@ -520,7 +520,7 @@ class _CurrentUploadThumbnail extends ConsumerWidget {
),
clipBehavior: Clip.antiAlias,
child: snapshot.data != null
? Thumbnail.fromAsset(asset: snapshot.data!, size: const Size(48, 48), fit: BoxFit.cover)
? Thumbnail.fromAsset(asset: snapshot.data, size: const Size(48, 48), fit: BoxFit.cover)
: Icon(Icons.image, size: 24, color: context.colorScheme.primary),
),
);

View file

@ -90,7 +90,7 @@ class AppLogPage extends HookConsumerWidget {
},
itemCount: logMessages.data?.length ?? 0,
itemBuilder: (context, index) {
var logMessage = logMessages.data![index];
final logMessage = logMessages.data![index];
return ListTile(
onTap: () => context.pushRoute(AppLogDetailRoute(logMessage: logMessage)),
trailing: const Icon(Icons.arrow_forward_ios_rounded),
@ -116,7 +116,7 @@ class AppLogPage extends HookConsumerWidget {
/// Truncate the log message to a certain number of lines
/// @param int maxLines - Max number of lines to truncate
String truncateLogMessage(String message, int maxLines) {
List<String> messageLines = message.split("\n");
final List<String> messageLines = message.split("\n");
if (messageLines.length < maxLines) {
return message;
}

View file

@ -14,7 +14,7 @@ class AppLogDetailPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
buildTextWithCopyButton(String header, String text) {
Padding buildTextWithCopyButton(String header, String text) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
@ -66,7 +66,7 @@ class AppLogDetailPage extends HookConsumerWidget {
);
}
buildLogContext(String logger) {
Padding buildLogContext(String logger) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
@ -87,7 +87,7 @@ class AppLogDetailPage extends HookConsumerWidget {
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SelectableText(
logger.toString(),
logger,
style: const TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold, fontFamily: "GoogleSansCode"),
),
),

View file

@ -14,7 +14,7 @@ class DownloadPanel extends ConsumerWidget {
final tasks = ref.watch(downloadStateProvider.select((state) => state.taskProgress)).entries.toList();
onCancelDownload(String id) {
void onCancelDownload(String id) {
ref.watch(downloadStateProvider.notifier).cancelDownload(id);
}

View file

@ -41,7 +41,7 @@ class HeaderSettingsPage extends HookConsumerWidget {
}
setInitialHeaders.value = true;
var list = [
final list = [
...headers.value.map((headerValue) {
return HeaderKeyValueSettings(
header: headerValue,
@ -81,7 +81,7 @@ class HeaderSettingsPage extends HookConsumerWidget {
);
}
saveHeaders(WidgetRef ref, List<SettingsHeader> headers) async {
Future<void> saveHeaders(WidgetRef ref, List<SettingsHeader> headers) async {
final headersMap = <String, String>{};
for (final header in headers) {
final key = header.key.trim();

View file

@ -25,7 +25,7 @@ import 'package:immich_mobile/theme/theme_data.dart';
import 'package:immich_mobile/widgets/common/immich_logo.dart';
import 'package:immich_mobile/widgets/common/immich_title_text.dart';
import 'package:logging/logging.dart';
import 'package:url_launcher/url_launcher.dart' show launchUrl, LaunchMode;
import 'package:url_launcher/url_launcher.dart' show LaunchMode, launchUrl;
class BootstrapErrorWidget extends StatelessWidget {
final String error;
@ -297,7 +297,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
log.info("Resuming session at $endpoint");
}
void resumeSession() async {
Future<void> resumeSession() async {
final serverUrl = Store.tryGet(StoreKey.serverUrl);
final endpoint = Store.tryGet(StoreKey.serverEndpoint);
final accessToken = Store.tryGet(StoreKey.accessToken);

View file

@ -89,7 +89,7 @@ class FolderPage extends HookConsumerWidget {
if (folder == null) {
return FolderContent(folder: rootFolder, root: rootFolder, sortOrder: sortOrder.value);
} else {
return FolderContent(folder: currentFolder.value!, root: rootFolder, sortOrder: sortOrder.value);
return FolderContent(folder: currentFolder.value, root: rootFolder, sortOrder: sortOrder.value);
}
},
loading: () => const Center(child: CircularProgressIndicator()),
@ -126,7 +126,7 @@ class FolderContent extends HookConsumerWidget {
return Center(child: const Text("folder_not_found").tr());
}
getSubtitle(int subFolderCount) {
String getSubtitle(int subFolderCount) {
if (subFolderCount > 0) {
return "$subFolderCount ${tr("folders")}".toLowerCase();
}

View file

@ -38,7 +38,7 @@ class PinAuthPage extends HookConsumerWidget {
}
}
enableBiometricAuth() {
void enableBiometricAuth() {
showDialog(
context: context,
builder: (buildContext) {

View file

@ -4,8 +4,8 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/widgets/forms/login/login_form.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/widgets/forms/login/login_form.dart';
import 'package:package_info_plus/package_info_plus.dart';
@RoutePage()
@ -16,8 +16,8 @@ class LoginPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final appVersion = useState('0.0.0');
getAppInfo() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
Future<void> getAppInfo() async {
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
appVersion.value = packageInfo.version;
}

View file

@ -41,13 +41,13 @@ class MapLocationPickerPage extends HookConsumerWidget {
}
Future<void> getCurrentLocation() async {
var (currentLocation, _) = await MapUtils.checkPermAndGetLocation(context: context);
final (currentLocation, _) = await MapUtils.checkPermAndGetLocation(context: context);
if (currentLocation == null) {
return;
}
var currentLatLng = LatLng(currentLocation.latitude, currentLocation.longitude);
final currentLatLng = LatLng(currentLocation.latitude, currentLocation.longitude);
selectedLatLng.value = currentLatLng;
await controller.value?.animateCamera(CameraUpdate.newLatLngZoom(currentLatLng, 12));
}

View file

@ -35,7 +35,7 @@ class ShareIntentPage extends ConsumerWidget {
ref.read(shareIntentUploadProvider.notifier).addAttachments(attachments);
}
void upload() async {
Future<void> upload() async {
final files = candidates.map((candidate) => candidate.file).toList();
await ref.read(shareIntentUploadProvider.notifier).uploadAll(files);
}
@ -102,7 +102,7 @@ class ShareIntentPage extends ConsumerWidget {
Icons.image,
color: Colors.white,
size: 20,
shadows: [Shadow(offset: Offset(0, 0), blurRadius: 8.0, color: Colors.black45)],
shadows: [Shadow(offset: Offset.zero, blurRadius: 8.0, color: Colors.black45)],
),
),
],

View file

@ -1,9 +1,9 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/presentation/widgets/feature_message/feature_message_dialog.widget.dart';
import 'package:immich_mobile/presentation/widgets/memory/memory_lane.widget.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
import 'package:immich_mobile/presentation/widgets/feature_message/feature_message_dialog.widget.dart';
import 'package:immich_mobile/providers/feature_message.provider.dart';
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';

View file

@ -14,14 +14,14 @@ class DownloadInfoPage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final tasks = ref.watch(downloadStateProvider.select((state) => state.taskProgress)).entries.toList();
onCancelDownload(String id) {
void onCancelDownload(String id) {
ref.watch(downloadStateProvider.notifier).cancelDownload(id);
}
return Scaffold(
appBar: AppBar(
title: Text("download".t(context: context)),
actions: [],
actions: const [],
),
body: ListView.builder(
physics: const ClampingScrollPhysics(),

View file

@ -45,7 +45,7 @@ class DriftActivitiesPage extends HookConsumerWidget {
if (assetName != null) Text(assetName!, style: context.textTheme.bodySmall),
],
),
actions: [const LikeActivityActionButton(iconOnly: true)],
actions: const [LikeActivityActionButton(iconOnly: true)],
actionsPadding: const EdgeInsets.only(right: 8),
),
body: activities.widgetWhen(

View file

@ -43,7 +43,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
);
}
void leaveAlbum() async {
Future<void> leaveAlbum() async {
try {
await ref.read(remoteAlbumProvider.notifier).leaveAlbum(album.id, userId: userId);
unawaited(context.navigateTo(const DriftAlbumsRoute()));
@ -52,7 +52,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
}
}
void removeUserFromAlbum(UserDto user) async {
Future<void> removeUserFromAlbum(UserDto user) async {
try {
await ref.read(remoteAlbumProvider.notifier).removeUser(album.id, user.id);
ref.invalidate(remoteAlbumSharedUsersProvider(album.id));
@ -83,11 +83,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
ref.invalidate(remoteAlbumSharedUsersProvider(album.id));
} catch (e) {
ImmichToast.show(
context: context,
msg: "Failed to add users to album: ${e.toString()}",
toastType: ToastType.error,
);
ImmichToast.show(context: context, msg: "Failed to add users to album: $e", toastType: ToastType.error);
}
}
@ -129,7 +125,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
);
}
buildOwnerInfo() {
Widget buildOwnerInfo() {
if (isOwner) {
final owner = ref.watch(currentUserProvider);
return ListTile(
@ -160,7 +156,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
}
}
buildSharedUsersList() {
Widget buildSharedUsersList() {
return sharedUsersAsync.maybeWhen(
data: (sharedUsers) => ListView.builder(
primary: false,
@ -181,7 +177,7 @@ class DriftAlbumOptionsPage extends HookConsumerWidget {
);
}
buildSectionTitle(String text) {
Padding buildSectionTitle(String text) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Text(text, style: context.textTheme.bodySmall),

View file

@ -370,7 +370,7 @@ class _QuickAccessButtonList extends ConsumerWidget {
),
child: ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(0),
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
children: [
ListTile(
@ -422,7 +422,7 @@ class _PartnerList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView.builder(
padding: const EdgeInsets.all(0),
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
itemCount: partners.length,
shrinkWrap: true,

View file

@ -7,10 +7,10 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/models/memory.model.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
import 'package:immich_mobile/presentation/widgets/memory/memory_bottom_info.widget.dart';
import 'package:immich_mobile/presentation/widgets/memory/memory_card.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
import 'package:immich_mobile/utils/system_ui.utils.dart';
import 'package:immich_mobile/widgets/memories/memory_epilogue.dart';
@ -54,7 +54,7 @@ class DriftMemoryPage extends HookConsumerWidget {
};
});
toNextMemory() {
void toNextMemory() {
memoryPageController.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn);
}
@ -83,10 +83,10 @@ class DriftMemoryPage extends HookConsumerWidget {
}
}
toNextAsset(int currentAssetIndex) {
void toNextAsset(int currentAssetIndex) {
if (currentAssetIndex + 1 < currentMemory.value.assets.length) {
// Go to the next asset
PageController controller = memoryAssetPageControllers[currentMemoryIndex.value];
final PageController controller = memoryAssetPageControllers[currentMemoryIndex.value];
controller.nextPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500));
} else {
@ -95,10 +95,10 @@ class DriftMemoryPage extends HookConsumerWidget {
}
}
toPreviousAsset(int currentAssetIndex) {
void toPreviousAsset(int currentAssetIndex) {
if (currentAssetIndex > 0) {
// Go to the previous asset
PageController controller = memoryAssetPageControllers[currentMemoryIndex.value];
final PageController controller = memoryAssetPageControllers[currentMemoryIndex.value];
controller.previousPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500));
} else {
@ -107,12 +107,12 @@ class DriftMemoryPage extends HookConsumerWidget {
}
}
updateProgressText() {
void updateProgressText() {
assetProgress.value = "${currentAssetPage.value + 1}|${currentMemory.value.assets.length}";
}
/// Downloads and caches the image for the asset at this [currentMemory]'s index
precacheAsset(int index) async {
Future<void> precacheAsset(int index) async {
// Guard index out of range
if (index < 0) {
return;

View file

@ -56,7 +56,7 @@ class _InfoBoxState extends ConsumerState<_InfoBox> {
_inTimeline = widget.partner.inTimeline;
}
_toggleInTimeline() async {
Future<void> _toggleInTimeline() async {
final user = ref.read(currentUserProvider);
if (user == null) {
return;

View file

@ -4,8 +4,8 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/string_extensions.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
import 'package:immich_mobile/utils/people.utils.dart';

View file

@ -24,7 +24,7 @@ class _DriftPersonPageState extends ConsumerState<DriftPersonPage> {
late DriftPerson _person;
@override
initState() {
void initState() {
super.initState();
_person = widget.person;
}

View file

@ -82,11 +82,7 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
ref.invalidate(remoteAlbumSharedUsersProvider(_album.id));
} catch (e) {
ImmichToast.show(
context: context,
msg: "Failed to add users to album: ${e.toString()}",
toastType: ToastType.error,
);
ImmichToast.show(context: context, msg: "Failed to add users to album: $e", toastType: ToastType.error);
}
}

View file

@ -54,7 +54,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
bool _disableAnimations = false;
@override
initState() {
void initState() {
super.initState();
_config = ref.read(appConfigProvider.select((s) => s.slideshow));
final asset = ref.read(assetViewerProvider).currentAsset;
@ -78,7 +78,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
}
@override
dispose() {
void dispose() {
_timer.cancel();
_stopwatch.stop();
_pageController.dispose();
@ -151,7 +151,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
}
}
void _nextPage() async {
Future<void> _nextPage() async {
if (_nextIndex < 0 || _nextIndex >= widget.timeline.totalAssets) {
if (_config.repeat) {
final wrapped = _config.direction == SlideshowDirection.forward ? 0 : widget.timeline.totalAssets - 1;
@ -267,7 +267,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
_updateNextIndex();
}
void _onTapUp() async {
Future<void> _onTapUp() async {
await (_showAppBar ? SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive) : restoreEdgeToEdge());
WidgetsBinding.instance.addPostFrameCallback((_) {
@ -295,7 +295,7 @@ class _DriftSlideshowPageState extends ConsumerState<DriftSlideshowPage> with Si
} else {
return LinearProgressIndicator(
color: context.colorScheme.primary,
borderRadius: const BorderRadius.all(Radius.zero),
borderRadius: BorderRadius.zero,
minHeight: 5,
value:
ref.watch(videoPlayerProvider(asset.heroTag).select((s) => s.position)).inMilliseconds /
@ -539,7 +539,7 @@ class _SlideshowProgressBarState extends State<_SlideshowProgressBar> with Singl
animation: _controller,
builder: (context, _) => LinearProgressIndicator(
color: widget.color,
borderRadius: const BorderRadius.all(Radius.zero),
borderRadius: BorderRadius.zero,
minHeight: 5,
value: _controller.value,
),

View file

@ -6,8 +6,8 @@ import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/trash_bottom_sheet.widget.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/presentation/widgets/timeline/timeline.widget.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/providers/server_info.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
@ -41,7 +41,7 @@ class DriftTrashPage extends StatelessWidget {
pinned: true,
centerTitle: true,
elevation: 0,
actions: [const _TrashKebabMenu()],
actions: const [_TrashKebabMenu()],
),
topSliverWidgetHeight: 24,
topSliverWidget: Consumer(

View file

@ -52,11 +52,11 @@ class DriftUserSelectionPage extends HookConsumerWidget {
final AsyncValue<List<UserDto>> suggestedShareUsers = ref.watch(driftUsersProvider);
final sharedUsersList = useState<Set<UserDto>>({});
addNewUsersHandler() {
void addNewUsersHandler() {
context.maybePop(sharedUsersList.value.map((e) => e.id).toList());
}
buildTileIcon(UserDto user) {
Widget buildTileIcon(UserDto user) {
if (sharedUsersList.value.contains(user)) {
return CircleAvatar(backgroundColor: context.primaryColor, child: const Icon(Icons.check_rounded, size: 25));
} else {
@ -64,8 +64,8 @@ class DriftUserSelectionPage extends HookConsumerWidget {
}
}
buildUserList(List<UserDto> users) {
List<Widget> usersChip = [];
ListView buildUserList(List<UserDto> users) {
final List<Widget> usersChip = [];
for (var user in sharedUsersList.value) {
usersChip.add(
@ -91,7 +91,7 @@ class DriftUserSelectionPage extends HookConsumerWidget {
ListView.builder(
primary: false,
shrinkWrap: true,
itemBuilder: ((context, index) {
itemBuilder: (context, index) {
return ListTile(
leading: buildTileIcon(users[index]),
dense: true,
@ -107,7 +107,7 @@ class DriftUserSelectionPage extends HookConsumerWidget {
}
},
);
}),
},
itemCount: users.length,
),
],

View file

@ -15,7 +15,7 @@ import 'package:immich_mobile/theme/theme_data.dart';
import 'package:immich_mobile/utils/editor.utils.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:immich_ui/immich_ui.dart';
import 'package:openapi/api.dart' show RotateParameters, MirrorParameters, MirrorAxis;
import 'package:openapi/api.dart' show MirrorAxis, MirrorParameters, RotateParameters;
@RoutePage()
class DriftEditImagePage extends ConsumerStatefulWidget {

View file

@ -25,7 +25,7 @@ class EditorProvider extends Notifier<EditorState> {
final originalWidth = exifInfo.isFlipped ? exifInfo.height : exifInfo.width;
final originalHeight = exifInfo.isFlipped ? exifInfo.width : exifInfo.height;
Rect crop = existingCrop != null && originalWidth != null && originalHeight != null
final Rect crop = existingCrop != null && originalWidth != null && originalHeight != null
? convertCropParametersToRect(existingCrop.parameters, originalWidth, originalHeight)
: const Rect.fromLTRB(0, 0, 1, 1);

View file

@ -80,7 +80,7 @@ class DriftSearchPage extends HookConsumerWidget {
final userPreferences = ref.watch(userMetadataPreferencesProvider);
search(SearchFilter f) {
void search(SearchFilter f) {
if (f == filter.value) {
return;
}
@ -94,7 +94,7 @@ class DriftSearchPage extends HookConsumerWidget {
}
}
loadMoreSearchResults() {
void loadMoreSearchResults() {
unawaited(ref.read(paginatedSearchProvider.notifier).search(filter.value));
}
@ -123,19 +123,19 @@ class DriftSearchPage extends HookConsumerWidget {
return null;
}, [preFilter]);
showPeoplePicker() {
void showPeoplePicker() {
var people = filter.value.people;
handleOnSelect(Set<PersonDto> value) {
void handleOnSelect(Set<PersonDto> value) {
people = value;
}
handleClear() {
void handleClear() {
peopleCurrentFilterWidget.value = null;
search(filter.value.copyWith(people: {}));
}
handleApply() {
void handleApply() {
final label = people.map((e) => e.name != '' ? e.name : 'no_name'.t(context: context)).join(', ');
peopleCurrentFilterWidget.value = label.isNotEmpty ? Text(label, style: context.textTheme.labelLarge) : null;
search(filter.value.copyWith(people: people));
@ -157,21 +157,21 @@ class DriftSearchPage extends HookConsumerWidget {
);
}
showTagPicker() {
void showTagPicker() {
var tagIds = filter.value.tagIds ?? [];
String tagLabel = '';
handleOnSelect(Iterable<Tag> tags) {
void handleOnSelect(Iterable<Tag> tags) {
tagIds = tags.map((t) => t.id).toList();
tagLabel = tags.map((t) => t.value).join(', ');
}
handleClear() {
void handleClear() {
tagCurrentFilterWidget.value = null;
search(filter.value.copyWith(tagIds: []));
}
handleApply() {
void handleApply() {
tagCurrentFilterWidget.value = tagLabel.isNotEmpty ? Text(tagLabel, style: context.textTheme.labelLarge) : null;
search(filter.value.copyWith(tagIds: tagIds));
}
@ -192,19 +192,19 @@ class DriftSearchPage extends HookConsumerWidget {
);
}
showLocationPicker() {
void showLocationPicker() {
var location = filter.value.location;
handleOnSelect(Map<String, String?> value) {
void handleOnSelect(Map<String, String?> value) {
location = SearchLocationFilter(country: value['country'], city: value['city'], state: value['state']);
}
handleClear() {
void handleClear() {
locationCurrentFilterWidget.value = null;
search(filter.value.copyWith(location: SearchLocationFilter()));
}
handleApply() {
void handleApply() {
final locationText = [
if (location.country != null) location.country!,
if (location.state != null) location.state!,
@ -238,19 +238,19 @@ class DriftSearchPage extends HookConsumerWidget {
);
}
showCameraPicker() {
void showCameraPicker() {
var camera = filter.value.camera;
handleOnSelect(Map<String, String?> value) {
void handleOnSelect(Map<String, String?> value) {
camera = SearchCameraFilter(make: value['make'], model: value['model']);
}
handleClear() {
void handleClear() {
cameraCurrentFilterWidget.value = null;
search(filter.value.copyWith(camera: SearchCameraFilter()));
}
handleApply() {
void handleApply() {
final make = camera.make ?? '';
final model = camera.model ?? '';
cameraCurrentFilterWidget.value = (make.isNotEmpty || model.isNotEmpty)
@ -275,7 +275,7 @@ class DriftSearchPage extends HookConsumerWidget {
);
}
datePicked(DateFilterInputModel? selectedDate) {
void datePicked(DateFilterInputModel? selectedDate) {
dateInputFilter.value = selectedDate;
if (selectedDate == null) {
dateRangeCurrentFilterWidget.value = null;
@ -298,7 +298,7 @@ class DriftSearchPage extends HookConsumerWidget {
);
}
showDatePicker() async {
Future<void> showDatePicker() async {
final firstDate = DateTime(1900);
final lastDate = DateTime.now();
@ -338,7 +338,7 @@ class DriftSearchPage extends HookConsumerWidget {
}
}
showQuickDatePicker() {
void showQuickDatePicker() {
showFilterBottomSheet(
context: context,
child: FilterBottomSheetScaffold(
@ -361,19 +361,19 @@ class DriftSearchPage extends HookConsumerWidget {
}
// MEDIA PICKER
showMediaTypePicker() {
void showMediaTypePicker() {
var mediaType = filter.value.mediaType;
handleOnSelected(AssetType assetType) {
void handleOnSelected(AssetType assetType) {
mediaType = assetType;
}
handleClear() {
void handleClear() {
mediaTypeCurrentFilterWidget.value = null;
search(filter.value.copyWith(mediaType: AssetType.other));
}
handleApply() {
void handleApply() {
mediaTypeCurrentFilterWidget.value = mediaType != AssetType.other
? Text(
mediaType == AssetType.image ? 'image'.t(context: context) : 'video'.t(context: context),
@ -395,19 +395,19 @@ class DriftSearchPage extends HookConsumerWidget {
}
// STAR RATING PICKER
showStarRatingPicker() {
void showStarRatingPicker() {
var rating = filter.value.rating;
handleOnSelected(SearchRatingFilter value) {
void handleOnSelected(SearchRatingFilter value) {
rating = value;
}
handleClear() {
void handleClear() {
ratingCurrentFilterWidget.value = null;
search(filter.value.copyWith(rating: SearchRatingFilter()));
}
handleApply() {
void handleApply() {
ratingCurrentFilterWidget.value = rating.rating.isSome
? Text(
'rating_count'.t(args: {'count': rating.rating.unwrapOrNull ?? 0}),
@ -430,10 +430,10 @@ class DriftSearchPage extends HookConsumerWidget {
}
// DISPLAY OPTION
showDisplayOptionPicker() {
void showDisplayOptionPicker() {
var display = filter.value.display;
handleOnSelect(Map<DisplayOption, bool> value) {
void handleOnSelect(Map<DisplayOption, bool> value) {
display = display.copyWith(
isNotInAlbum: value[DisplayOption.notInAlbum],
isArchive: value[DisplayOption.archive],
@ -441,7 +441,7 @@ class DriftSearchPage extends HookConsumerWidget {
);
}
handleClear() {
void handleClear() {
displayOptionCurrentFilterWidget.value = null;
search(
filter.value.copyWith(
@ -450,7 +450,7 @@ class DriftSearchPage extends HookConsumerWidget {
);
}
handleApply() {
void handleApply() {
final filterText = [
if (display.isNotInAlbum) 'search_filter_display_option_not_in_album'.t(context: context),
if (display.isArchive) 'archive'.t(context: context),
@ -473,7 +473,7 @@ class DriftSearchPage extends HookConsumerWidget {
);
}
handleTextSubmitted(String value) => search(switch (textSearchType.value) {
void handleTextSubmitted(String value) => search(switch (textSearchType.value) {
TextSearchType.context => filter.value.copyWith(filename: '', context: value, description: '', ocr: ''),
TextSearchType.filename => filter.value.copyWith(filename: value, context: '', description: '', ocr: ''),
TextSearchType.description => filter.value.copyWith(filename: '', context: '', description: value, ocr: ''),

View file

@ -1,25 +1,23 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/routes.provider.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/domain/models/album/album.model.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
enum AddToMenuItem { album, archive, unarchive, lockedFolder }
@ -37,16 +35,12 @@ class _AddActionButtonState extends ConsumerState<AddActionButton> {
switch (selected) {
case AddToMenuItem.album:
_openAlbumSelector();
break;
case AddToMenuItem.archive:
performArchiveAction(context, ref, source: ActionSource.viewer);
break;
case AddToMenuItem.unarchive:
performUnArchiveAction(context, ref, source: ActionSource.viewer);
break;
case AddToMenuItem.lockedFolder:
performMoveToLockFolderAction(context, ref, source: ActionSource.viewer);
break;
}
}

View file

@ -30,7 +30,7 @@ class DeleteActionButton extends ConsumerWidget {
this.menuItem = false,
});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -7,9 +7,9 @@ import 'package:immich_mobile/domain/utils/event_stream.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
/// This delete action has the following behavior:
/// - Prompt to delete the asset locally
@ -20,7 +20,7 @@ class DeleteLocalActionButton extends ConsumerWidget {
const DeleteLocalActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -28,7 +28,7 @@ class DeletePermanentActionButton extends ConsumerWidget {
this.useShortLabel = false,
});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -18,7 +18,7 @@ class DeleteTrashActionButton extends ConsumerWidget {
const DeleteTrashActionButton({super.key, required this.source});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -1,6 +1,6 @@
import 'package:immich_mobile/constants/enums.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/utils/background_sync.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
@ -14,7 +14,7 @@ class DownloadActionButton extends ConsumerWidget {
final bool menuItem;
const DownloadActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref, BackgroundSyncManager backgroundSyncManager) async {
Future<void> _onTap(BuildContext context, WidgetRef ref, BackgroundSyncManager backgroundSyncManager) async {
if (!context.mounted) {
return;
}

View file

@ -13,7 +13,7 @@ class EditDateTimeActionButton extends ConsumerWidget {
const EditDateTimeActionButton({super.key, required this.source});
_onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -13,7 +13,7 @@ class EditLocationActionButton extends ConsumerWidget {
const EditLocationActionButton({super.key, required this.source});
_onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -17,7 +17,7 @@ class FavoriteActionButton extends ConsumerWidget {
const FavoriteActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -25,7 +25,7 @@ class LikeActivityActionButton extends ConsumerWidget {
final activities = ref.watch(albumActivityProvider((album?.id ?? "", asset?.id)));
onTap(Activity? liked) async {
Future<void> onTap(Activity? liked) async {
if (user == null) {
return;
}

View file

@ -21,20 +21,17 @@ class OpenInBrowserActionButton extends ConsumerWidget {
this.menuItem = false,
});
void _onTap() async {
Future<void> _onTap() async {
final serverEndpoint = Store.get(StoreKey.serverEndpoint).replaceFirst('/api', '');
String originPath = '';
switch (origin) {
case TimelineOrigin.favorite:
originPath = '/favorites';
break;
case TimelineOrigin.trash:
originPath = '/trash';
break;
case TimelineOrigin.archive:
originPath = '/archive';
break;
default:
break;
}

View file

@ -24,7 +24,7 @@ class RemoveFromAlbumActionButton extends ConsumerWidget {
this.menuItem = false,
});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -20,7 +20,7 @@ class RemoveFromLockFolderActionButton extends ConsumerWidget {
this.menuItem = false,
});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -17,7 +17,7 @@ class RestoreActionButton extends ConsumerWidget {
const RestoreActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -12,7 +12,7 @@ class RestoreTrashActionButton extends ConsumerWidget {
const RestoreTrashActionButton({super.key, required this.source});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -22,7 +22,7 @@ class SetAlbumCoverActionButton extends ConsumerWidget {
this.menuItem = false,
});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -93,13 +93,13 @@ class ShareActionButton extends ConsumerWidget {
return switch (source) {
ActionSource.timeline => ref.read(multiSelectProvider).selectedAssets,
ActionSource.viewer => switch (ref.read(assetViewerProvider).currentAsset) {
BaseAsset asset => {asset},
final BaseAsset asset => {asset},
null => const {},
},
};
}
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}
@ -108,7 +108,7 @@ class ShareActionButton extends ConsumerWidget {
await _share(context, ref, fileType);
}
void _onLongPress(BuildContext context, WidgetRef ref) async {
Future<void> _onLongPress(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -12,7 +12,7 @@ class ShareLinkActionButton extends ConsumerWidget {
const ShareLinkActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
_onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -18,7 +18,7 @@ class SimilarPhotosActionButton extends ConsumerWidget {
const SimilarPhotosActionButton({super.key, required this.assetId, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -14,7 +14,7 @@ class StackActionButton extends ConsumerWidget {
const StackActionButton({super.key, required this.source});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -20,7 +20,7 @@ class TrashActionButton extends ConsumerWidget {
const TrashActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -4,13 +4,13 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/events.model.dart';
import 'package:immich_mobile/domain/utils/event_stream.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
import 'package:immich_mobile/providers/infrastructure/action.provider.dart';
import 'package:immich_mobile/providers/timeline/multiselect.provider.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:immich_mobile/domain/models/events.model.dart';
import 'package:immich_mobile/domain/utils/event_stream.dart';
// used to allow performing unarchive action from different sources (without duplicating code)
Future<void> performUnArchiveAction(BuildContext context, WidgetRef ref, {required ActionSource source}) async {

View file

@ -17,7 +17,7 @@ class UnFavoriteActionButton extends ConsumerWidget {
const UnFavoriteActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -15,7 +15,7 @@ class UnStackActionButton extends ConsumerWidget {
const UnStackActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -24,7 +24,7 @@ class UploadActionButton extends ConsumerWidget {
const UploadActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false});
void _onTap(BuildContext context, WidgetRef ref) async {
Future<void> _onTap(BuildContext context, WidgetRef ref) async {
if (!context.mounted) {
return;
}

View file

@ -774,7 +774,7 @@ class AddToAlbumHeader extends ConsumerWidget {
TextButton.icon(
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), // remove internal padding
minimumSize: const Size(0, 0), // allow shrinking
minimumSize: Size.zero, // allow shrinking
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // remove extra height
),
onPressed: onCreateAlbum,
@ -797,7 +797,7 @@ class CreateAlbumButton extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
Future<void> onCreateAlbum() async {
var albumName = await showDialog<String?>(context: context, builder: (context) => const NewAlbumNameModal());
final albumName = await showDialog<String?>(context: context, builder: (context) => const NewAlbumNameModal());
if (albumName == null) {
return;
}
@ -839,7 +839,7 @@ class CreateAlbumButton extends ConsumerWidget {
TextButton.icon(
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
minimumSize: const Size(0, 0),
minimumSize: Size.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
onPressed: onCreateAlbum,

View file

@ -1,4 +1,5 @@
import 'dart:async';
import 'package:auto_route/auto_route.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
@ -8,8 +9,8 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/album/album_tile.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/sheet_tile.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
import 'package:immich_mobile/providers/user.provider.dart';
import 'package:immich_mobile/routing/router.dart';

View file

@ -53,7 +53,7 @@ class _LocationDetailsState extends ConsumerState<LocationDetails> {
}
}
void editLocation() async {
Future<void> editLocation() async {
await ref.read(actionProvider.notifier).editLocation(ActionSource.viewer, context);
}

View file

@ -41,7 +41,7 @@ class RatingDetails extends ConsumerWidget {
unfilledColor: context.themeData.colorScheme.onSurface.withAlpha(100),
itemSize: 40,
onRatingUpdate: (rating) async {
await ref.read(actionProvider.notifier).updateRating(ActionSource.viewer, rating.round());
await ref.read(actionProvider.notifier).updateRating(ActionSource.viewer, rating);
},
onClearRating: () async {
await ref.read(actionProvider.notifier).updateRating(ActionSource.viewer, null);

View file

@ -99,14 +99,14 @@ class TechnicalDetails extends ConsumerWidget {
static String _getFileInfo(BaseAsset asset, ExifInfo? exifInfo) {
final height = asset.height;
final width = asset.width;
final resolution = (width != null && height != null) ? "${width.toInt()} x ${height.toInt()}" : null;
final resolution = (width != null && height != null) ? "$width x $height" : null;
final fileSize = exifInfo?.fileSize != null ? formatBytes(exifInfo!.fileSize!) : null;
return switch ((fileSize, resolution)) {
(null, null) => '',
(String fileSize, null) => fileSize,
(null, String resolution) => resolution,
(String fileSize, String resolution) => '$fileSize$_kSeparator$resolution',
(final String fileSize, null) => fileSize,
(null, final String resolution) => resolution,
(final String fileSize, final String resolution) => '$fileSize$_kSeparator$resolution',
};
}
@ -116,9 +116,9 @@ class TechnicalDetails extends ConsumerWidget {
}
return switch ((exifInfo.make, exifInfo.model)) {
(null, null) => null,
(String make, null) => make,
(null, String model) => model,
(String make, String model) => '$make $model',
(final String make, null) => make,
(null, final String model) => model,
(final String make, final String model) => '$make $model',
};
}

View file

@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
import 'package:immich_mobile/domain/services/timeline.service.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
class AssetStackRow extends ConsumerWidget {
@ -23,7 +23,8 @@ class AssetStackRow extends ConsumerWidget {
}
final showingControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
double opacity = ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity)) * (showingControls ? 1 : 0);
final double opacity =
ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity)) * (showingControls ? 1 : 0);
return IgnorePointer(
ignoring: opacity < 1.0,
@ -75,7 +76,7 @@ class _StackItemState extends ConsumerState<_StackItem> {
Icons.play_circle_outline_rounded,
color: Colors.white,
size: 16,
shadows: [Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset(0.0, 0.0))],
shadows: [Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset.zero)],
),
);
const selectedDecoration = BoxDecoration(

View file

@ -167,7 +167,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
_handleCasting();
}
void _onAssetChanged(int index) async {
Future<void> _onAssetChanged(int index) async {
_currentPage = index;
final asset = await ref.read(timelineServiceProvider).getAssetAsync(index);
@ -222,7 +222,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
_onTimelineReloadEvent();
case ViewerReloadAssetEvent():
_onViewerReloadEvent();
case ViewerStackAssetDeletedEvent event:
case final ViewerStackAssetDeletedEvent event:
_onViewerStackAssetDeletedEvent(event);
default:
}

View file

@ -64,8 +64,8 @@ class _RatingBarState extends State<RatingBar> {
} else if (dx >= totalWidth) {
newRating = widget.itemCount.toDouble();
} else {
double starWithPadding = widget.itemSize + widget.starPadding;
int tappedIndex = (dx / starWithPadding).floor().clamp(0, widget.itemCount - 1);
final double starWithPadding = widget.itemSize + widget.starPadding;
final int tappedIndex = (dx / starWithPadding).floor().clamp(0, widget.itemCount - 1);
newRating = tappedIndex + 1.0;
if (isTap && newRating == _currentRating && _currentRating != 0) {
@ -88,7 +88,7 @@ class _RatingBarState extends State<RatingBar> {
@override
Widget build(BuildContext context) {
final isRTL = Directionality.of(context) == TextDirection.rtl;
final double visualAlignmentOffset = 5.0;
const double visualAlignmentOffset = 5.0;
return Column(
mainAxisSize: MainAxisSize.min,
@ -107,8 +107,8 @@ class _RatingBarState extends State<RatingBar> {
if (i.isOdd) {
return SizedBox(width: widget.starPadding);
}
int index = i ~/ 2;
bool filled = _currentRating > index;
final int index = i ~/ 2;
final bool filled = _currentRating > index;
return widget.itemBuilder ??
Icon(
Icons.star_rounded,

View file

@ -83,7 +83,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) async {
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
switch (state) {
case AppLifecycleState.resumed:
if (_shouldPlayOnForeground) {
@ -198,7 +198,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
return localAsset;
}
void _onPlaybackReady() async {
Future<void> _onPlaybackReady() async {
if (!mounted || !widget.isCurrent) {
return;
}
@ -257,7 +257,7 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
_controller?.onPlaybackEnded.removeListener(_onPlaybackEnded);
}
void _loadVideo() async {
Future<void> _loadVideo() async {
final nc = _controller;
if (nc == null || nc.videoSource != null || !mounted) {
return;

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_bar.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
class ViewerBottomAppBar extends ConsumerWidget {
const ViewerBottomAppBar({super.key});
@ -9,7 +9,8 @@ class ViewerBottomAppBar extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final showingControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
double opacity = ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity)) * (showingControls ? 1 : 0);
final double opacity =
ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity)) * (showingControls ? 1 : 0);
return IgnorePointer(
ignoring: opacity < 1.0,

View file

@ -40,7 +40,8 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
}
final showingControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
double opacity = ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity)) * (showingControls ? 1 : 0);
final double opacity =
ref.watch(assetViewerProvider.select((s) => s.backgroundOpacity)) * (showingControls ? 1 : 0);
final originalTheme = context.themeData;
final assetForAction = [asset];

View file

@ -74,7 +74,7 @@ class _BaseDraggableScrollableSheetState extends ConsumerState<BaseBottomSheet>
color: widget.backgroundColor ?? context.colorScheme.surfaceContainer,
elevation: 3.0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
margin: const EdgeInsets.symmetric(horizontal: 0),
margin: EdgeInsets.zero,
child: Column(
children: [
Expanded(

View file

@ -21,10 +21,10 @@ class MapBottomSheet extends StatelessWidget {
maxChildSize: 0.75,
shouldCloseOnMinExtent: false,
resizeOnScroll: false,
actions: [],
actions: const [],
backgroundColor: context.themeData.colorScheme.surface,
slivers: [
const SliverFillRemaining(hasScrollBody: false, child: SizedBox(height: 0, child: _ScopedMapTimeline())),
slivers: const [
SliverFillRemaining(hasScrollBody: false, child: SizedBox(height: 0, child: _ScopedMapTimeline())),
],
);
}

View file

@ -4,10 +4,10 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:immich_mobile/domain/models/feature_message.model.dart';
import 'package:immich_mobile/presentation/widgets/feature_message/feature_message_placeholder.widget.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/extensions/theme_extensions.dart';
import 'package:immich_mobile/generated/translations.g.dart';
import 'package:immich_mobile/presentation/widgets/feature_message/feature_message_placeholder.widget.dart';
Future<void> showFeatureMessageDialog(BuildContext context) {
return showGeneralDialog<void>(

View file

@ -22,7 +22,7 @@ class FullImage extends StatelessWidget {
Widget build(BuildContext context) {
final provider = getFullImageProvider(asset, size: size);
return OctoImage(
fadeInDuration: const Duration(milliseconds: 0),
fadeInDuration: Duration.zero,
fadeOutDuration: const Duration(milliseconds: 100),
placeholderBuilder: placeholder != null ? (_) => placeholder! : null,
image: provider,

View file

@ -25,7 +25,7 @@ mixin CancellableImageProviderMixin<T extends Object> on CancellableImageProvide
ImageInfo? getInitialImage(CancellableImageProvider provider) {
final completer = CancelableCompleter<ImageInfo?>(onCancel: provider.cancel);
final cachedStream = provider.resolve(const ImageConfiguration());
final cachedStream = provider.resolve(ImageConfiguration.empty);
ImageInfo? cachedImage;
final listener = ImageStreamListener((image, synchronousCall) {
if (synchronousCall) {

View file

@ -285,7 +285,7 @@ class _TileOverlayIcon extends StatelessWidget {
icon,
color: Colors.white,
size: 16,
shadows: [const Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset(0.0, 0.0))],
shadows: const [Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset.zero)],
);
}
}

View file

@ -71,7 +71,7 @@ class MapUtils {
bool silent = false,
}) async {
try {
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
final bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled && !silent) {
unawaited(showDialog(context: context, builder: (context) => _LocationServiceDisabledDialog(context)));
return (null, LocationPermission.deniedForever);
@ -98,7 +98,7 @@ class MapUtils {
return (null, LocationPermission.deniedForever);
}
Position currentUserLocation = await Geolocator.getCurrentPosition(
final Position currentUserLocation = await Geolocator.getCurrentPosition(
locationSettings: const LocationSettings(
accuracy: LocationAccuracy.high,
distanceFilter: 0,

View file

@ -55,7 +55,7 @@ class DriftMemoryCard extends StatelessWidget {
}
if (asset.isImage) {
return FullImage(asset, fit: fit, size: const Size(double.infinity, double.infinity));
return FullImage(asset, fit: fit, size: Size.infinite);
}
return Center(

View file

@ -6,9 +6,9 @@ import 'package:immich_mobile/domain/models/person.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
import 'package:immich_mobile/utils/debug_print.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:scroll_date_picker/scroll_date_picker.dart';
import 'package:immich_mobile/utils/debug_print.dart';
class DriftPersonBirthdayEditForm extends ConsumerStatefulWidget {
final DriftPerson person;
@ -28,7 +28,7 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonBirthdayEdi
_selectedDate = widget.person.birthDate ?? DateTime(DateTime.now().year - 30, 1, 1);
}
void saveBirthday() async {
Future<void> saveBirthday() async {
try {
final result = await ref.read(driftPeopleServiceProvider).updateBrithday(widget.person.id, _selectedDate);

View file

@ -6,8 +6,8 @@ import 'package:immich_mobile/domain/models/person.model.dart';
import 'package:immich_mobile/extensions/build_context_extensions.dart';
import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/providers/infrastructure/people.provider.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
import 'package:immich_mobile/utils/debug_print.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
class DriftPersonNameEditForm extends ConsumerStatefulWidget {
final DriftPerson person;
@ -27,7 +27,7 @@ class _DriftPersonNameEditFormState extends ConsumerState<DriftPersonNameEditFor
_formController = TextEditingController(text: widget.person.name);
}
void onEdit(String personId, String newName) async {
Future<void> onEdit(String personId, String newName) async {
try {
final result = await ref.read(driftPeopleServiceProvider).updateName(personId, newName);
if (result != 0) {

Some files were not shown because too many files have changed in this diff Show more