mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
chore(mobile): Apply stricter linting rules for formatting (#30370)
* chore(mobile): Apply stricter linting rules for formatting * Formatting fixes
This commit is contained in:
parent
0293414abd
commit
d864a90811
208 changed files with 515 additions and 533 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ abstract class ImageRequest {
|
|||
final int requestId = _nextRequestId++;
|
||||
bool _isCancelled = false;
|
||||
|
||||
get isCancelled => _isCancelled;
|
||||
bool get isCancelled => _isCancelled;
|
||||
|
||||
ImageRequest();
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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([
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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((_) {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
|||
}
|
||||
|
||||
@override
|
||||
dispose() {
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
WakelockPlus.disable();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}),
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class PinAuthPage extends HookConsumerWidget {
|
|||
}
|
||||
}
|
||||
|
||||
enableBiometricAuth() {
|
||||
void enableBiometricAuth() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (buildContext) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)],
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class _DriftPersonPageState extends ConsumerState<DriftPersonPage> {
|
|||
late DriftPerson _person;
|
||||
|
||||
@override
|
||||
initState() {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_person = widget.person;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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: ''),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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())),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>(
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue