mirror of
https://github.com/immich-app/immich
synced 2025-06-09 14:05:41 +00:00
refact 1
This commit is contained in:
parent
d7f445b78c
commit
02b62e5183
@ -1,12 +0,0 @@
|
|||||||
enum SortOrder {
|
|
||||||
asc,
|
|
||||||
desc,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TextSearchType {
|
|
||||||
context,
|
|
||||||
filename,
|
|
||||||
description,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AssetVisibilityEnum { timeline, hidden, archive, locked }
|
|
@ -1,12 +1,5 @@
|
|||||||
part of 'base_asset.model.dart';
|
part of 'base_asset.model.dart';
|
||||||
|
|
||||||
enum AssetVisibility {
|
|
||||||
timeline,
|
|
||||||
hidden,
|
|
||||||
archive,
|
|
||||||
locked,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Model for an asset stored in the server
|
// Model for an asset stored in the server
|
||||||
class Asset extends BaseAsset {
|
class Asset extends BaseAsset {
|
||||||
final String id;
|
final String id;
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
part 'asset.model.dart';
|
part 'asset.model.dart';
|
||||||
part 'local_asset.model.dart';
|
part 'local_asset.model.dart';
|
||||||
|
|
||||||
enum AssetType {
|
|
||||||
// do not change this order!
|
|
||||||
other,
|
|
||||||
image,
|
|
||||||
video,
|
|
||||||
audio,
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed class BaseAsset {
|
sealed class BaseAsset {
|
||||||
final String name;
|
final String name;
|
||||||
final String? checksum;
|
final String? checksum;
|
||||||
|
@ -33,7 +33,7 @@ enum StoreKey<T> {
|
|||||||
thumbnailCacheSize<int>._(110),
|
thumbnailCacheSize<int>._(110),
|
||||||
imageCacheSize<int>._(111),
|
imageCacheSize<int>._(111),
|
||||||
albumThumbnailCacheSize<int>._(112),
|
albumThumbnailCacheSize<int>._(112),
|
||||||
selectedAlbumSortOrder<int>._(113),
|
selectedAlbumAssetOrder<int>._(113),
|
||||||
advancedTroubleshooting<bool>._(114),
|
advancedTroubleshooting<bool>._(114),
|
||||||
logLevel<int>._(115),
|
logLevel<int>._(115),
|
||||||
preferRemoteImage<bool>._(116),
|
preferRemoteImage<bool>._(116),
|
||||||
|
@ -12,6 +12,7 @@ import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart';
|
|||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:platform/platform.dart';
|
import 'package:platform/platform.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class LocalSyncService {
|
class LocalSyncService {
|
||||||
final ILocalAlbumRepository _localAlbumRepository;
|
final ILocalAlbumRepository _localAlbumRepository;
|
||||||
@ -365,7 +366,7 @@ extension on Iterable<PlatformAsset> {
|
|||||||
(e) => LocalAsset(
|
(e) => LocalAsset(
|
||||||
id: e.id,
|
id: e.id,
|
||||||
name: e.name,
|
name: e.name,
|
||||||
type: AssetType.values.elementAtOrNull(e.type) ?? AssetType.other,
|
type: AssetType.values.elementAtOrNull(e.type) ?? AssetType.OTHER,
|
||||||
createdAt: e.createdAt == null
|
createdAt: e.createdAt == null
|
||||||
? DateTime.now()
|
? DateTime.now()
|
||||||
: DateTime.fromMillisecondsSinceEpoch(e.createdAt! * 1000),
|
: DateTime.fromMillisecondsSinceEpoch(e.createdAt! * 1000),
|
||||||
|
@ -24,7 +24,7 @@ class Album {
|
|||||||
this.lastModifiedAssetTimestamp,
|
this.lastModifiedAssetTimestamp,
|
||||||
required this.shared,
|
required this.shared,
|
||||||
required this.activityEnabled,
|
required this.activityEnabled,
|
||||||
this.sortOrder = SortOrder.desc,
|
this.sortOrder = AssetOrder.desc,
|
||||||
});
|
});
|
||||||
|
|
||||||
// fields stored in DB
|
// fields stored in DB
|
||||||
@ -42,7 +42,7 @@ class Album {
|
|||||||
bool shared;
|
bool shared;
|
||||||
bool activityEnabled;
|
bool activityEnabled;
|
||||||
@enumerated
|
@enumerated
|
||||||
SortOrder sortOrder;
|
AssetOrder assetOrder;
|
||||||
final IsarLink<User> owner = IsarLink<User>();
|
final IsarLink<User> owner = IsarLink<User>();
|
||||||
final IsarLink<Asset> thumbnail = IsarLink<Asset>();
|
final IsarLink<Asset> thumbnail = IsarLink<Asset>();
|
||||||
final IsarLinks<User> sharedUsers = IsarLinks<User>();
|
final IsarLinks<User> sharedUsers = IsarLinks<User>();
|
||||||
@ -160,7 +160,7 @@ class Album {
|
|||||||
a.owner.value = await db.users.getById(dto.ownerId);
|
a.owner.value = await db.users.getById(dto.ownerId);
|
||||||
if (dto.order != null) {
|
if (dto.order != null) {
|
||||||
a.sortOrder =
|
a.sortOrder =
|
||||||
dto.order == AssetOrder.asc ? SortOrder.asc : SortOrder.desc;
|
dto.order == AssetOrder.asc ? AssetOrder.asc : AssetOrder.desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dto.albumThumbnailAssetId != null) {
|
if (dto.albumThumbnailAssetId != null) {
|
||||||
|
@ -26,7 +26,7 @@ class Asset {
|
|||||||
fileModifiedAt = remote.fileModifiedAt,
|
fileModifiedAt = remote.fileModifiedAt,
|
||||||
updatedAt = remote.updatedAt,
|
updatedAt = remote.updatedAt,
|
||||||
durationInSeconds = remote.duration.toDuration()?.inSeconds ?? 0,
|
durationInSeconds = remote.duration.toDuration()?.inSeconds ?? 0,
|
||||||
type = remote.type.toAssetType(),
|
type = remote.type,
|
||||||
fileName = remote.originalFileName,
|
fileName = remote.originalFileName,
|
||||||
height = remote.exifInfo?.exifImageHeight?.toInt(),
|
height = remote.exifInfo?.exifImageHeight?.toInt(),
|
||||||
width = remote.exifInfo?.exifImageWidth?.toInt(),
|
width = remote.exifInfo?.exifImageWidth?.toInt(),
|
||||||
@ -47,7 +47,7 @@ class Asset {
|
|||||||
stackCount = remote.stack?.assetCount ?? 0,
|
stackCount = remote.stack?.assetCount ?? 0,
|
||||||
stackId = remote.stack?.id,
|
stackId = remote.stack?.id,
|
||||||
thumbhash = remote.thumbhash,
|
thumbhash = remote.thumbhash,
|
||||||
visibility = getVisibility(remote.visibility);
|
visibility = remote.visibility;
|
||||||
|
|
||||||
Asset({
|
Asset({
|
||||||
this.id = Isar.autoIncrement,
|
this.id = Isar.autoIncrement,
|
||||||
@ -73,7 +73,7 @@ class Asset {
|
|||||||
this.stackCount = 0,
|
this.stackCount = 0,
|
||||||
this.isOffline = false,
|
this.isOffline = false,
|
||||||
this.thumbhash,
|
this.thumbhash,
|
||||||
this.visibility = AssetVisibilityEnum.timeline,
|
this.visibility = AssetVisibility.timeline,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ignore
|
@ignore
|
||||||
@ -177,7 +177,7 @@ class Asset {
|
|||||||
int stackCount;
|
int stackCount;
|
||||||
|
|
||||||
@Enumerated(EnumType.ordinal)
|
@Enumerated(EnumType.ordinal)
|
||||||
AssetVisibilityEnum visibility;
|
AssetVisibility visibility;
|
||||||
|
|
||||||
/// Returns null if the asset has no sync access to the exif info
|
/// Returns null if the asset has no sync access to the exif info
|
||||||
@ignore
|
@ignore
|
||||||
@ -210,10 +210,10 @@ class Asset {
|
|||||||
bool get isRemote => remoteId != null;
|
bool get isRemote => remoteId != null;
|
||||||
|
|
||||||
@ignore
|
@ignore
|
||||||
bool get isImage => type == AssetType.image;
|
bool get isImage => type == AssetType.IMAGE;
|
||||||
|
|
||||||
@ignore
|
@ignore
|
||||||
bool get isVideo => type == AssetType.video;
|
bool get isVideo => type == AssetType.VIDEO;
|
||||||
|
|
||||||
@ignore
|
@ignore
|
||||||
bool get isMotionPhoto => livePhotoVideoId != null;
|
bool get isMotionPhoto => livePhotoVideoId != null;
|
||||||
@ -459,7 +459,7 @@ class Asset {
|
|||||||
String? stackPrimaryAssetId,
|
String? stackPrimaryAssetId,
|
||||||
int? stackCount,
|
int? stackCount,
|
||||||
String? thumbhash,
|
String? thumbhash,
|
||||||
AssetVisibilityEnum? visibility,
|
AssetVisibility? visibility,
|
||||||
}) =>
|
}) =>
|
||||||
Asset(
|
Asset(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
@ -553,27 +553,6 @@ class Asset {
|
|||||||
"visibility": "$visibility",
|
"visibility": "$visibility",
|
||||||
}""";
|
}""";
|
||||||
}
|
}
|
||||||
|
|
||||||
static getVisibility(AssetVisibility visibility) {
|
|
||||||
switch (visibility) {
|
|
||||||
case AssetVisibility.timeline:
|
|
||||||
return AssetVisibilityEnum.timeline;
|
|
||||||
case AssetVisibility.archive:
|
|
||||||
return AssetVisibilityEnum.archive;
|
|
||||||
case AssetVisibility.hidden:
|
|
||||||
return AssetVisibilityEnum.hidden;
|
|
||||||
case AssetVisibility.locked:
|
|
||||||
return AssetVisibilityEnum.locked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AssetType {
|
|
||||||
// do not change this order!
|
|
||||||
other,
|
|
||||||
image,
|
|
||||||
video,
|
|
||||||
audio,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes where the information of this asset came from:
|
/// Describes where the information of this asset came from:
|
||||||
|
@ -3,6 +3,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
|||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart';
|
import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart';
|
||||||
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
@TableIndex(
|
@TableIndex(
|
||||||
name: 'UQ_remote_asset_owner_checksum',
|
name: 'UQ_remote_asset_owner_checksum',
|
||||||
|
@ -165,7 +165,7 @@ class DriftSyncStreamRepository extends DriftDatabaseRepository
|
|||||||
for (final asset in data) {
|
for (final asset in data) {
|
||||||
final companion = RemoteAssetEntityCompanion(
|
final companion = RemoteAssetEntityCompanion(
|
||||||
name: Value(asset.originalFileName),
|
name: Value(asset.originalFileName),
|
||||||
type: Value(asset.type.toAssetType()),
|
type: Value(asset.type),
|
||||||
createdAt: Value.absentIfNull(asset.fileCreatedAt),
|
createdAt: Value.absentIfNull(asset.fileCreatedAt),
|
||||||
updatedAt: Value.absentIfNull(asset.fileModifiedAt),
|
updatedAt: Value.absentIfNull(asset.fileModifiedAt),
|
||||||
durationInSeconds: const Value(0),
|
durationInSeconds: const Value(0),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
|
||||||
|
|
||||||
mixin AssetEntityMixin on Table {
|
mixin AssetEntityMixin on Table {
|
||||||
TextColumn get name => text()();
|
TextColumn get name => text()();
|
||||||
IntColumn get type => intEnum<AssetType>()();
|
IntColumn get type => intEnum<AssetType>()();
|
||||||
|
@ -18,7 +18,7 @@ abstract interface class IAlbumApiRepository {
|
|||||||
String? thumbnailAssetId,
|
String? thumbnailAssetId,
|
||||||
String? description,
|
String? description,
|
||||||
bool? activityEnabled,
|
bool? activityEnabled,
|
||||||
SortOrder? sortOrder,
|
AssetOrder? sortOrder,
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<void> delete(String albumId);
|
Future<void> delete(String albumId);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:immich_mobile/constants/enums.dart';
|
import 'package:immich_mobile/constants/enums.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
abstract interface class IAssetApiRepository {
|
abstract interface class IAssetApiRepository {
|
||||||
// Future<Asset> get(String id);
|
// Future<Asset> get(String id);
|
||||||
@ -19,6 +20,6 @@ abstract interface class IAssetApiRepository {
|
|||||||
|
|
||||||
Future<void> updateVisibility(
|
Future<void> updateVisibility(
|
||||||
List<String> list,
|
List<String> list,
|
||||||
AssetVisibilityEnum visibility,
|
AssetVisibility visibility,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ class SearchFilter {
|
|||||||
display.isNotInAlbum == false &&
|
display.isNotInAlbum == false &&
|
||||||
display.isArchive == false &&
|
display.isArchive == false &&
|
||||||
display.isFavorite == false &&
|
display.isFavorite == false &&
|
||||||
mediaType == AssetType.other;
|
mediaType == AssetType.OTHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchFilter copyWith({
|
SearchFilter copyWith({
|
||||||
|
@ -29,7 +29,7 @@ class AlbumsPage extends HookConsumerWidget {
|
|||||||
final albums =
|
final albums =
|
||||||
ref.watch(albumProvider).where((album) => album.isRemote).toList();
|
ref.watch(albumProvider).where((album) => album.isRemote).toList();
|
||||||
final albumSortOption = ref.watch(albumSortByOptionsProvider);
|
final albumSortOption = ref.watch(albumSortByOptionsProvider);
|
||||||
final albumSortIsReverse = ref.watch(albumSortOrderProvider);
|
final albumSortIsReverse = ref.watch(albumAssetOrderProvider);
|
||||||
final sorted = albumSortOption.sortFn(albums, albumSortIsReverse);
|
final sorted = albumSortOption.sortFn(albums, albumSortIsReverse);
|
||||||
final isGrid = useState(false);
|
final isGrid = useState(false);
|
||||||
final searchController = useTextEditingController();
|
final searchController = useTextEditingController();
|
||||||
@ -322,7 +322,7 @@ class SortButton extends ConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final albumSortOption = ref.watch(albumSortByOptionsProvider);
|
final albumSortOption = ref.watch(albumSortByOptionsProvider);
|
||||||
final albumSortIsReverse = ref.watch(albumSortOrderProvider);
|
final albumSortIsReverse = ref.watch(albumAssetOrderProvider);
|
||||||
|
|
||||||
return MenuAnchor(
|
return MenuAnchor(
|
||||||
style: MenuStyle(
|
style: MenuStyle(
|
||||||
@ -360,7 +360,7 @@ class SortButton extends ConsumerWidget {
|
|||||||
// Switch direction
|
// Switch direction
|
||||||
if (selected) {
|
if (selected) {
|
||||||
ref
|
ref
|
||||||
.read(albumSortOrderProvider.notifier)
|
.read(albumAssetOrderProvider.notifier)
|
||||||
.changeSortDirection(!albumSortIsReverse);
|
.changeSortDirection(!albumSortIsReverse);
|
||||||
} else {
|
} else {
|
||||||
ref
|
ref
|
||||||
|
@ -15,6 +15,7 @@ import 'package:immich_mobile/routing/router.dart';
|
|||||||
import 'package:immich_mobile/utils/bytes_units.dart';
|
import 'package:immich_mobile/utils/bytes_units.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/thumbnail_image.dart';
|
import 'package:immich_mobile/widgets/asset_grid/thumbnail_image.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
RecursiveFolder? _findFolderInStructure(
|
RecursiveFolder? _findFolderInStructure(
|
||||||
RootFolder rootFolder,
|
RootFolder rootFolder,
|
||||||
@ -49,7 +50,7 @@ class FolderPage extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final folderState = ref.watch(folderStructureProvider);
|
final folderState = ref.watch(folderStructureProvider);
|
||||||
final currentFolder = useState<RecursiveFolder?>(folder);
|
final currentFolder = useState<RecursiveFolder?>(folder);
|
||||||
final sortOrder = useState<SortOrder>(SortOrder.asc);
|
final sortOrder = useState<AssetOrder>(AssetOrder.asc);
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() {
|
() {
|
||||||
@ -78,9 +79,9 @@ class FolderPage extends HookConsumerWidget {
|
|||||||
[folderState],
|
[folderState],
|
||||||
);
|
);
|
||||||
|
|
||||||
void onToggleSortOrder() {
|
void onToggleAssetOrder() {
|
||||||
final newOrder =
|
final newOrder =
|
||||||
sortOrder.value == SortOrder.asc ? SortOrder.desc : SortOrder.asc;
|
sortOrder.value == AssetOrder.asc ? AssetOrder.desc : AssetOrder.asc;
|
||||||
|
|
||||||
ref.read(folderStructureProvider.notifier).fetchFolders(newOrder);
|
ref.read(folderStructureProvider.notifier).fetchFolders(newOrder);
|
||||||
|
|
||||||
@ -95,7 +96,7 @@ class FolderPage extends HookConsumerWidget {
|
|||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.swap_vert),
|
icon: const Icon(Icons.swap_vert),
|
||||||
onPressed: onToggleSortOrder,
|
onPressed: onToggleAssetOrder,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -134,13 +135,13 @@ class FolderPage extends HookConsumerWidget {
|
|||||||
class FolderContent extends HookConsumerWidget {
|
class FolderContent extends HookConsumerWidget {
|
||||||
final RootFolder? folder;
|
final RootFolder? folder;
|
||||||
final RootFolder root;
|
final RootFolder root;
|
||||||
final SortOrder sortOrder;
|
final AssetOrder sortOrder;
|
||||||
|
|
||||||
const FolderContent({
|
const FolderContent({
|
||||||
super.key,
|
super.key,
|
||||||
this.folder,
|
this.folder,
|
||||||
required this.root,
|
required this.root,
|
||||||
this.sortOrder = SortOrder.asc,
|
this.sortOrder = AssetOrder.asc,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -128,7 +128,7 @@ class PlaceTile extends StatelessWidget {
|
|||||||
isArchive: false,
|
isArchive: false,
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
),
|
),
|
||||||
mediaType: AssetType.other,
|
mediaType: AssetType.OTHER,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,6 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/interfaces/person_api.interface.dart';
|
import 'package:immich_mobile/interfaces/person_api.interface.dart';
|
||||||
@ -23,6 +22,7 @@ import 'package:immich_mobile/widgets/search/search_filter/media_type_picker.dar
|
|||||||
import 'package:immich_mobile/widgets/search/search_filter/people_picker.dart';
|
import 'package:immich_mobile/widgets/search/search_filter/people_picker.dart';
|
||||||
import 'package:immich_mobile/widgets/search/search_filter/search_filter_chip.dart';
|
import 'package:immich_mobile/widgets/search/search_filter/search_filter_chip.dart';
|
||||||
import 'package:immich_mobile/widgets/search/search_filter/search_filter_utils.dart';
|
import 'package:immich_mobile/widgets/search/search_filter/search_filter_utils.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class SearchPage extends HookConsumerWidget {
|
class SearchPage extends HookConsumerWidget {
|
||||||
@ -47,7 +47,7 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
isArchive: false,
|
isArchive: false,
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
),
|
),
|
||||||
mediaType: prefilter?.mediaType ?? AssetType.other,
|
mediaType: prefilter?.mediaType ?? AssetType.OTHER,
|
||||||
language:
|
language:
|
||||||
"${context.locale.languageCode}-${context.locale.countryCode}",
|
"${context.locale.languageCode}-${context.locale.countryCode}",
|
||||||
),
|
),
|
||||||
@ -371,9 +371,9 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
mediaTypeCurrentFilterWidget.value = Text(
|
mediaTypeCurrentFilterWidget.value = Text(
|
||||||
assetType == AssetType.image
|
assetType == AssetType.IMAGE
|
||||||
? 'image'.tr()
|
? 'image'.tr()
|
||||||
: assetType == AssetType.video
|
: assetType == AssetType.VIDEO
|
||||||
? 'video'.tr()
|
? 'video'.tr()
|
||||||
: 'all'.tr(),
|
: 'all'.tr(),
|
||||||
style: context.textTheme.labelLarge,
|
style: context.textTheme.labelLarge,
|
||||||
@ -382,7 +382,7 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
|
|
||||||
handleClear() {
|
handleClear() {
|
||||||
filter.value = filter.value.copyWith(
|
filter.value = filter.value.copyWith(
|
||||||
mediaType: AssetType.other,
|
mediaType: AssetType.OTHER,
|
||||||
);
|
);
|
||||||
|
|
||||||
mediaTypeCurrentFilterWidget.value = null;
|
mediaTypeCurrentFilterWidget.value = null;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
import 'package:immich_mobile/entities/album.entity.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
import 'package:immich_mobile/models/albums/album_search.model.dart';
|
||||||
import 'package:immich_mobile/services/album.service.dart';
|
import 'package:immich_mobile/services/album.service.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
final isRefreshingRemoteAlbumProvider = StateProvider<bool>((ref) => false);
|
final isRefreshingRemoteAlbumProvider = StateProvider<bool>((ref) => false);
|
||||||
|
|
||||||
@ -113,11 +113,11 @@ class AlbumNotifier extends StateNotifier<List<Album>> {
|
|||||||
return albumService.setActivityStatus(album, enabled);
|
return albumService.setActivityStatus(album, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Album?> toggleSortOrder(Album album) {
|
Future<Album?> toggleAssetOrder(Album album) {
|
||||||
final order =
|
final order =
|
||||||
album.sortOrder == SortOrder.asc ? SortOrder.desc : SortOrder.asc;
|
album.sortOrder == AssetOrder.asc ? AssetOrder.desc : AssetOrder.asc;
|
||||||
|
|
||||||
return albumService.updateSortOrder(album, order);
|
return albumService.updateAssetOrder(album, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -106,7 +106,7 @@ class AlbumSortByOptions extends _$AlbumSortByOptions {
|
|||||||
AlbumSortMode build() {
|
AlbumSortMode build() {
|
||||||
final sortOpt = ref
|
final sortOpt = ref
|
||||||
.watch(appSettingsServiceProvider)
|
.watch(appSettingsServiceProvider)
|
||||||
.getSetting(AppSettingsEnum.selectedAlbumSortOrder);
|
.getSetting(AppSettingsEnum.selectedAlbumAssetOrder);
|
||||||
return AlbumSortMode.values.firstWhere(
|
return AlbumSortMode.values.firstWhere(
|
||||||
(e) => e.storeIndex == sortOpt,
|
(e) => e.storeIndex == sortOpt,
|
||||||
orElse: () => AlbumSortMode.title,
|
orElse: () => AlbumSortMode.title,
|
||||||
@ -116,14 +116,14 @@ class AlbumSortByOptions extends _$AlbumSortByOptions {
|
|||||||
void changeSortMode(AlbumSortMode sortOption) {
|
void changeSortMode(AlbumSortMode sortOption) {
|
||||||
state = sortOption;
|
state = sortOption;
|
||||||
ref.watch(appSettingsServiceProvider).setSetting(
|
ref.watch(appSettingsServiceProvider).setSetting(
|
||||||
AppSettingsEnum.selectedAlbumSortOrder,
|
AppSettingsEnum.selectedAlbumAssetOrder,
|
||||||
sortOption.storeIndex,
|
sortOption.storeIndex,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
class AlbumSortOrder extends _$AlbumSortOrder {
|
class AlbumAssetOrder extends _$AlbumAssetOrder {
|
||||||
@override
|
@override
|
||||||
bool build() {
|
bool build() {
|
||||||
return ref
|
return ref
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/domain/services/user.service.dart';
|
import 'package:immich_mobile/domain/services/user.service.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
@ -13,6 +12,7 @@ import 'package:immich_mobile/services/etag.service.dart';
|
|||||||
import 'package:immich_mobile/services/exif.service.dart';
|
import 'package:immich_mobile/services/exif.service.dart';
|
||||||
import 'package:immich_mobile/services/sync.service.dart';
|
import 'package:immich_mobile/services/sync.service.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
final assetProvider = StateNotifierProvider<AssetNotifier, bool>((ref) {
|
final assetProvider = StateNotifierProvider<AssetNotifier, bool>((ref) {
|
||||||
return AssetNotifier(
|
return AssetNotifier(
|
||||||
@ -174,7 +174,7 @@ class AssetNotifier extends StateNotifier<bool> {
|
|||||||
|
|
||||||
Future<void> setLockedView(
|
Future<void> setLockedView(
|
||||||
List<Asset> selection,
|
List<Asset> selection,
|
||||||
AssetVisibilityEnum visibility,
|
AssetVisibility visibility,
|
||||||
) {
|
) {
|
||||||
return _assetService.setVisibility(selection, visibility);
|
return _assetService.setVisibility(selection, visibility);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/models/folder/root_folder.model.dart';
|
import 'package:immich_mobile/models/folder/root_folder.model.dart';
|
||||||
import 'package:immich_mobile/services/folder.service.dart';
|
import 'package:immich_mobile/services/folder.service.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class FolderStructureNotifier extends StateNotifier<AsyncValue<RootFolder>> {
|
class FolderStructureNotifier extends StateNotifier<AsyncValue<RootFolder>> {
|
||||||
final FolderService _folderService;
|
final FolderService _folderService;
|
||||||
@ -11,7 +11,7 @@ class FolderStructureNotifier extends StateNotifier<AsyncValue<RootFolder>> {
|
|||||||
|
|
||||||
FolderStructureNotifier(this._folderService) : super(const AsyncLoading());
|
FolderStructureNotifier(this._folderService) : super(const AsyncLoading());
|
||||||
|
|
||||||
Future<void> fetchFolders(SortOrder order) async {
|
Future<void> fetchFolders(AssetOrder order) async {
|
||||||
try {
|
try {
|
||||||
final folders = await _folderService.getFolderStructure(order);
|
final folders = await _folderService.getFolderStructure(order);
|
||||||
state = AsyncData(folders);
|
state = AsyncData(folders);
|
||||||
@ -38,7 +38,7 @@ class FolderRenderListNotifier extends StateNotifier<AsyncValue<RenderList>> {
|
|||||||
FolderRenderListNotifier(this._folderService, this._folder)
|
FolderRenderListNotifier(this._folderService, this._folder)
|
||||||
: super(const AsyncLoading());
|
: super(const AsyncLoading());
|
||||||
|
|
||||||
Future<void> fetchAssets(SortOrder order) async {
|
Future<void> fetchAssets(AssetOrder order) async {
|
||||||
try {
|
try {
|
||||||
final assets = await _folderService.getFolderAssets(_folder, order);
|
final assets = await _folderService.getFolderAssets(_folder, order);
|
||||||
final renderList =
|
final renderList =
|
||||||
|
@ -9,6 +9,7 @@ import 'package:flutter/painting.dart';
|
|||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:photo_manager/photo_manager.dart' show ThumbnailSize;
|
import 'package:photo_manager/photo_manager.dart' show ThumbnailSize;
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
/// The local image provider for an asset
|
/// The local image provider for an asset
|
||||||
class ImmichLocalImageProvider extends ImageProvider<ImmichLocalImageProvider> {
|
class ImmichLocalImageProvider extends ImageProvider<ImmichLocalImageProvider> {
|
||||||
@ -60,7 +61,7 @@ class ImmichLocalImageProvider extends ImageProvider<ImmichLocalImageProvider> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (asset.type) {
|
switch (asset.type) {
|
||||||
case AssetType.image:
|
case AssetType.IMAGE:
|
||||||
final File? file = await local.originFile;
|
final File? file = await local.originFile;
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
throw StateError("Opening file for asset ${asset.fileName} failed");
|
throw StateError("Opening file for asset ${asset.fileName} failed");
|
||||||
@ -68,7 +69,7 @@ class ImmichLocalImageProvider extends ImageProvider<ImmichLocalImageProvider> {
|
|||||||
final buffer = await ui.ImmutableBuffer.fromFilePath(file.path);
|
final buffer = await ui.ImmutableBuffer.fromFilePath(file.path);
|
||||||
yield await decode(buffer);
|
yield await decode(buffer);
|
||||||
break;
|
break;
|
||||||
case AssetType.video:
|
case AssetType.VIDEO:
|
||||||
final size = ThumbnailSize(width.ceil(), height.ceil());
|
final size = ThumbnailSize(width.ceil(), height.ceil());
|
||||||
final thumbBytes = await local.thumbnailDataWithSize(size);
|
final thumbBytes = await local.thumbnailDataWithSize(size);
|
||||||
if (thumbBytes == null) {
|
if (thumbBytes == null) {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
import 'package:immich_mobile/entities/album.entity.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart'
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart'
|
||||||
@ -59,11 +58,11 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository {
|
|||||||
String? thumbnailAssetId,
|
String? thumbnailAssetId,
|
||||||
String? description,
|
String? description,
|
||||||
bool? activityEnabled,
|
bool? activityEnabled,
|
||||||
SortOrder? sortOrder,
|
AssetOrder? sortOrder,
|
||||||
}) async {
|
}) async {
|
||||||
AssetOrder? order;
|
AssetOrder? order;
|
||||||
if (sortOrder != null) {
|
if (sortOrder != null) {
|
||||||
order = sortOrder == SortOrder.asc ? AssetOrder.asc : AssetOrder.desc;
|
order = sortOrder == AssetOrder.asc ? AssetOrder.asc : AssetOrder.desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
final response = await checkNull(
|
final response = await checkNull(
|
||||||
@ -163,7 +162,7 @@ class AlbumApiRepository extends ApiRepository implements IAlbumApiRepository {
|
|||||||
startDate: dto.startDate,
|
startDate: dto.startDate,
|
||||||
endDate: dto.endDate,
|
endDate: dto.endDate,
|
||||||
activityEnabled: dto.isActivityEnabled,
|
activityEnabled: dto.isActivityEnabled,
|
||||||
sortOrder: dto.order == AssetOrder.asc ? SortOrder.asc : SortOrder.desc,
|
sortOrder: dto.order == AssetOrder.asc ? AssetOrder.asc : AssetOrder.desc,
|
||||||
);
|
);
|
||||||
album.remoteAssetCount = dto.assetCount;
|
album.remoteAssetCount = dto.assetCount;
|
||||||
album.owner.value =
|
album.owner.value =
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
import 'package:immich_mobile/entities/album.entity.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/entities/duplicated_asset.entity.dart';
|
import 'package:immich_mobile/entities/duplicated_asset.entity.dart';
|
||||||
@ -8,6 +7,7 @@ import 'package:immich_mobile/interfaces/asset.interface.dart';
|
|||||||
import 'package:immich_mobile/providers/db.provider.dart';
|
import 'package:immich_mobile/providers/db.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/database.repository.dart';
|
import 'package:immich_mobile/repositories/database.repository.dart';
|
||||||
import 'package:immich_mobile/utils/hash.dart';
|
import 'package:immich_mobile/utils/hash.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
final assetRepositoryProvider =
|
final assetRepositoryProvider =
|
||||||
@ -231,7 +231,7 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository {
|
|||||||
.where()
|
.where()
|
||||||
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
||||||
.filter()
|
.filter()
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.timeline)
|
.visibilityEqualTo(AssetVisibility.timeline)
|
||||||
.sortByFileCreatedAtDesc()
|
.sortByFileCreatedAtDesc()
|
||||||
.findAll();
|
.findAll();
|
||||||
}
|
}
|
||||||
@ -242,7 +242,7 @@ class AssetRepository extends DatabaseRepository implements IAssetRepository {
|
|||||||
.where()
|
.where()
|
||||||
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
||||||
.filter()
|
.filter()
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.timeline)
|
.visibilityEqualTo(AssetVisibility.timeline)
|
||||||
.livePhotoVideoIdIsNotNull()
|
.livePhotoVideoIdIsNotNull()
|
||||||
.findAll();
|
.findAll();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/interfaces/asset_api.interface.dart';
|
import 'package:immich_mobile/interfaces/asset_api.interface.dart';
|
||||||
import 'package:immich_mobile/providers/api.provider.dart';
|
import 'package:immich_mobile/providers/api.provider.dart';
|
||||||
@ -53,23 +52,10 @@ class AssetApiRepository extends ApiRepository implements IAssetApiRepository {
|
|||||||
@override
|
@override
|
||||||
Future<void> updateVisibility(
|
Future<void> updateVisibility(
|
||||||
List<String> ids,
|
List<String> ids,
|
||||||
AssetVisibilityEnum visibility,
|
AssetVisibility visibility,
|
||||||
) async {
|
) async {
|
||||||
return _api.updateAssets(
|
return _api.updateAssets(
|
||||||
AssetBulkUpdateDto(ids: ids, visibility: _mapVisibility(visibility)),
|
AssetBulkUpdateDto(ids: ids, visibility: visibility),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_mapVisibility(AssetVisibilityEnum visibility) {
|
|
||||||
switch (visibility) {
|
|
||||||
case AssetVisibilityEnum.timeline:
|
|
||||||
return AssetVisibility.timeline;
|
|
||||||
case AssetVisibilityEnum.hidden:
|
|
||||||
return AssetVisibility.hidden;
|
|
||||||
case AssetVisibilityEnum.locked:
|
|
||||||
return AssetVisibility.locked;
|
|
||||||
case AssetVisibilityEnum.archive:
|
|
||||||
return AssetVisibility.archive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
|||||||
import 'package:immich_mobile/interfaces/asset_media.interface.dart';
|
import 'package:immich_mobile/interfaces/asset_media.interface.dart';
|
||||||
import 'package:immich_mobile/utils/hash.dart';
|
import 'package:immich_mobile/utils/hash.dart';
|
||||||
import 'package:photo_manager/photo_manager.dart' hide AssetType;
|
import 'package:photo_manager/photo_manager.dart' hide AssetType;
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
final assetMediaRepositoryProvider = Provider((ref) => AssetMediaRepository());
|
final assetMediaRepositoryProvider = Provider((ref) => AssetMediaRepository());
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
import 'package:immich_mobile/entities/album.entity.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
import 'package:immich_mobile/infrastructure/entities/user.entity.dart';
|
||||||
@ -8,6 +7,7 @@ import 'package:immich_mobile/providers/db.provider.dart';
|
|||||||
import 'package:immich_mobile/repositories/database.repository.dart';
|
import 'package:immich_mobile/repositories/database.repository.dart';
|
||||||
import 'package:immich_mobile/utils/hash.dart';
|
import 'package:immich_mobile/utils/hash.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
final timelineRepositoryProvider =
|
final timelineRepositoryProvider =
|
||||||
@ -46,7 +46,7 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
||||||
.filter()
|
.filter()
|
||||||
.isTrashedEqualTo(false)
|
.isTrashedEqualTo(false)
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.archive)
|
.visibilityEqualTo(AssetVisibility.archive)
|
||||||
.sortByFileCreatedAtDesc();
|
.sortByFileCreatedAtDesc();
|
||||||
|
|
||||||
return _watchRenderList(query, GroupAssetsBy.none);
|
return _watchRenderList(query, GroupAssetsBy.none);
|
||||||
@ -60,7 +60,7 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
.filter()
|
.filter()
|
||||||
.isFavoriteEqualTo(true)
|
.isFavoriteEqualTo(true)
|
||||||
.not()
|
.not()
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.locked)
|
.visibilityEqualTo(AssetVisibility.locked)
|
||||||
.isTrashedEqualTo(false)
|
.isTrashedEqualTo(false)
|
||||||
.sortByFileCreatedAtDesc();
|
.sortByFileCreatedAtDesc();
|
||||||
|
|
||||||
@ -76,11 +76,11 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
.filter()
|
.filter()
|
||||||
.isTrashedEqualTo(false)
|
.isTrashedEqualTo(false)
|
||||||
.not()
|
.not()
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.locked);
|
.visibilityEqualTo(AssetVisibility.locked);
|
||||||
|
|
||||||
final withSortedOption = switch (album.sortOrder) {
|
final withSortedOption = switch (album.assetOrder) {
|
||||||
SortOrder.asc => query.sortByFileCreatedAt(),
|
AssetOrder.asc => query.sortByFileCreatedAt(),
|
||||||
SortOrder.desc => query.sortByFileCreatedAtDesc(),
|
AssetOrder.desc => query.sortByFileCreatedAtDesc(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return _watchRenderList(withSortedOption, groupAssetByOption);
|
return _watchRenderList(withSortedOption, groupAssetByOption);
|
||||||
@ -104,8 +104,8 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
||||||
.filter()
|
.filter()
|
||||||
.isTrashedEqualTo(false)
|
.isTrashedEqualTo(false)
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.timeline)
|
.visibilityEqualTo(AssetVisibility.timeline)
|
||||||
.typeEqualTo(AssetType.video)
|
.typeEqualTo(AssetType.VIDEO)
|
||||||
.sortByFileCreatedAtDesc();
|
.sortByFileCreatedAtDesc();
|
||||||
|
|
||||||
return _watchRenderList(query, GroupAssetsBy.none);
|
return _watchRenderList(query, GroupAssetsBy.none);
|
||||||
@ -122,7 +122,7 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
.filter()
|
.filter()
|
||||||
.isTrashedEqualTo(false)
|
.isTrashedEqualTo(false)
|
||||||
.stackPrimaryAssetIdIsNull()
|
.stackPrimaryAssetIdIsNull()
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.timeline)
|
.visibilityEqualTo(AssetVisibility.timeline)
|
||||||
.sortByFileCreatedAtDesc();
|
.sortByFileCreatedAtDesc();
|
||||||
|
|
||||||
return _watchRenderList(query, groupAssetByOption);
|
return _watchRenderList(query, groupAssetByOption);
|
||||||
@ -139,7 +139,7 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
.anyOf(isarUserIds, (qb, id) => qb.ownerIdEqualToAnyChecksum(id))
|
.anyOf(isarUserIds, (qb, id) => qb.ownerIdEqualToAnyChecksum(id))
|
||||||
.filter()
|
.filter()
|
||||||
.isTrashedEqualTo(false)
|
.isTrashedEqualTo(false)
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.timeline)
|
.visibilityEqualTo(AssetVisibility.timeline)
|
||||||
.stackPrimaryAssetIdIsNull()
|
.stackPrimaryAssetIdIsNull()
|
||||||
.sortByFileCreatedAtDesc();
|
.sortByFileCreatedAtDesc();
|
||||||
return _watchRenderList(query, groupAssetByOption);
|
return _watchRenderList(query, groupAssetByOption);
|
||||||
@ -160,7 +160,7 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
.remoteIdIsNotNull()
|
.remoteIdIsNotNull()
|
||||||
.filter()
|
.filter()
|
||||||
.ownerIdEqualTo(fastHash(userId))
|
.ownerIdEqualTo(fastHash(userId))
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.timeline)
|
.visibilityEqualTo(AssetVisibility.timeline)
|
||||||
.isTrashedEqualTo(false)
|
.isTrashedEqualTo(false)
|
||||||
.stackPrimaryAssetIdIsNull()
|
.stackPrimaryAssetIdIsNull()
|
||||||
.sortByFileCreatedAtDesc();
|
.sortByFileCreatedAtDesc();
|
||||||
@ -177,7 +177,7 @@ class TimelineRepository extends DatabaseRepository
|
|||||||
.where()
|
.where()
|
||||||
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
.ownerIdEqualToAnyChecksum(fastHash(userId))
|
||||||
.filter()
|
.filter()
|
||||||
.visibilityEqualTo(AssetVisibilityEnum.locked)
|
.visibilityEqualTo(AssetVisibility.locked)
|
||||||
.isTrashedEqualTo(false)
|
.isTrashedEqualTo(false)
|
||||||
.sortByFileCreatedAtDesc();
|
.sortByFileCreatedAtDesc();
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import 'dart:io';
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
import 'package:immich_mobile/domain/services/user.service.dart';
|
import 'package:immich_mobile/domain/services/user.service.dart';
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
import 'package:immich_mobile/entities/album.entity.dart';
|
||||||
@ -30,6 +29,7 @@ import 'package:immich_mobile/services/entity.service.dart';
|
|||||||
import 'package:immich_mobile/services/sync.service.dart';
|
import 'package:immich_mobile/services/sync.service.dart';
|
||||||
import 'package:immich_mobile/utils/hash.dart';
|
import 'package:immich_mobile/utils/hash.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
final albumServiceProvider = Provider(
|
final albumServiceProvider = Provider(
|
||||||
(ref) => AlbumService(
|
(ref) => AlbumService(
|
||||||
@ -483,7 +483,7 @@ class AlbumService {
|
|||||||
return _albumRepository.search(searchTerm, filterMode);
|
return _albumRepository.search(searchTerm, filterMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Album?> updateSortOrder(Album album, SortOrder order) async {
|
Future<Album?> updateAssetOrder(Album album, AssetOrder order) async {
|
||||||
try {
|
try {
|
||||||
final updateAlbum =
|
final updateAlbum =
|
||||||
await _albumApiRepository.update(album.remoteId!, sortOrder: order);
|
await _albumApiRepository.update(album.remoteId!, sortOrder: order);
|
||||||
|
@ -55,9 +55,9 @@ enum AppSettingsEnum<T> {
|
|||||||
"albumThumbnailCacheSize",
|
"albumThumbnailCacheSize",
|
||||||
200,
|
200,
|
||||||
),
|
),
|
||||||
selectedAlbumSortOrder<int>(
|
selectedAlbumAssetOrder<int>(
|
||||||
StoreKey.selectedAlbumSortOrder,
|
StoreKey.selectedAlbumAssetOrder,
|
||||||
"selectedAlbumSortOrder",
|
"selectedAlbumAssetOrder",
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, null, false),
|
advancedTroubleshooting<bool>(StoreKey.advancedTroubleshooting, null, false),
|
||||||
|
@ -3,7 +3,6 @@ import 'dart:async';
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
|
import 'package:immich_mobile/domain/interfaces/exif.interface.dart';
|
||||||
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
|
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
|
||||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||||
@ -241,8 +240,8 @@ class AssetService {
|
|||||||
for (var element in assets) {
|
for (var element in assets) {
|
||||||
element.isArchived = isArchived;
|
element.isArchived = isArchived;
|
||||||
element.visibility = isArchived
|
element.visibility = isArchived
|
||||||
? AssetVisibilityEnum.archive
|
? AssetVisibility.archive
|
||||||
: AssetVisibilityEnum.timeline;
|
: AssetVisibility.timeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _syncService.upsertAssetsWithExif(assets);
|
await _syncService.upsertAssetsWithExif(assets);
|
||||||
@ -480,7 +479,7 @@ class AssetService {
|
|||||||
.where((asset) => asset.storage == AssetState.merged)
|
.where((asset) => asset.storage == AssetState.merged)
|
||||||
.map((asset) {
|
.map((asset) {
|
||||||
asset.remoteId = null;
|
asset.remoteId = null;
|
||||||
asset.visibility = AssetVisibilityEnum.timeline;
|
asset.visibility = AssetVisibility.timeline;
|
||||||
return asset;
|
return asset;
|
||||||
})
|
})
|
||||||
: assets.where((asset) => asset.isRemote).map((asset) {
|
: assets.where((asset) => asset.isRemote).map((asset) {
|
||||||
@ -538,7 +537,7 @@ class AssetService {
|
|||||||
|
|
||||||
Future<void> setVisibility(
|
Future<void> setVisibility(
|
||||||
List<Asset> assets,
|
List<Asset> assets,
|
||||||
AssetVisibilityEnum visibility,
|
AssetVisibility visibility,
|
||||||
) async {
|
) async {
|
||||||
await _assetApiRepository.updateVisibility(
|
await _assetApiRepository.updateVisibility(
|
||||||
assets.map((asset) => asset.remoteId!).toList(),
|
assets.map((asset) => asset.remoteId!).toList(),
|
||||||
|
@ -520,10 +520,11 @@ class BackupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _getAssetType(AssetType assetType) => switch (assetType) {
|
String _getAssetType(AssetType assetType) => switch (assetType) {
|
||||||
AssetType.audio => "AUDIO",
|
AssetType.AUDIO => "AUDIO",
|
||||||
AssetType.image => "IMAGE",
|
AssetType.IMAGE => "IMAGE",
|
||||||
AssetType.video => "VIDEO",
|
AssetType.VIDEO => "VIDEO",
|
||||||
AssetType.other => "OTHER",
|
AssetType.OTHER => "OTHER",
|
||||||
|
_ => throw Exception('Unknown AssetType value: $this'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ import 'package:immich_mobile/repositories/file_media.repository.dart';
|
|||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:immich_mobile/utils/bootstrap.dart';
|
import 'package:immich_mobile/utils/bootstrap.dart';
|
||||||
import 'package:immich_mobile/utils/diff.dart';
|
import 'package:immich_mobile/utils/diff.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
/// Finds duplicates originating from missing EXIF information
|
/// Finds duplicates originating from missing EXIF information
|
||||||
class BackupVerificationService {
|
class BackupVerificationService {
|
||||||
@ -175,7 +176,7 @@ class BackupVerificationService {
|
|||||||
remote.fileCreatedAt,
|
remote.fileCreatedAt,
|
||||||
local.fileCreatedAt,
|
local.fileCreatedAt,
|
||||||
))) {
|
))) {
|
||||||
if (remote.type == AssetType.video) {
|
if (remote.type == AssetType.VIDEO) {
|
||||||
// it's very unlikely that a video of same length, filesize, name
|
// it's very unlikely that a video of same length, filesize, name
|
||||||
// and date is wrong match. Cannot easily compare videos anyway
|
// and date is wrong match. Cannot easily compare videos anyway
|
||||||
return true;
|
return true;
|
||||||
|
@ -5,6 +5,7 @@ import 'package:immich_mobile/models/folder/recursive_folder.model.dart';
|
|||||||
import 'package:immich_mobile/models/folder/root_folder.model.dart';
|
import 'package:immich_mobile/models/folder/root_folder.model.dart';
|
||||||
import 'package:immich_mobile/repositories/folder_api.repository.dart';
|
import 'package:immich_mobile/repositories/folder_api.repository.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
final folderServiceProvider = Provider(
|
final folderServiceProvider = Provider(
|
||||||
(ref) => FolderService(ref.watch(folderApiRepositoryProvider)),
|
(ref) => FolderService(ref.watch(folderApiRepositoryProvider)),
|
||||||
@ -16,7 +17,7 @@ class FolderService {
|
|||||||
|
|
||||||
FolderService(this._folderApiRepository);
|
FolderService(this._folderApiRepository);
|
||||||
|
|
||||||
Future<RootFolder> getFolderStructure(SortOrder order) async {
|
Future<RootFolder> getFolderStructure(AssetOrder order) async {
|
||||||
final paths = await _folderApiRepository.getAllUniquePaths();
|
final paths = await _folderApiRepository.getAllUniquePaths();
|
||||||
|
|
||||||
// Create folder structure
|
// Create folder structure
|
||||||
@ -54,7 +55,7 @@ class FolderService {
|
|||||||
);
|
);
|
||||||
// Sort folders based on order parameter
|
// Sort folders based on order parameter
|
||||||
folderMap[parentPath]!.sort(
|
folderMap[parentPath]!.sort(
|
||||||
(a, b) => order == SortOrder.desc
|
(a, b) => order == AssetOrder.desc
|
||||||
? b.name.compareTo(a.name)
|
? b.name.compareTo(a.name)
|
||||||
: a.name.compareTo(b.name),
|
: a.name.compareTo(b.name),
|
||||||
);
|
);
|
||||||
@ -71,7 +72,7 @@ class FolderService {
|
|||||||
folder.subfolders.addAll(folderMap[fullPath]!);
|
folder.subfolders.addAll(folderMap[fullPath]!);
|
||||||
// Sort subfolders based on order parameter
|
// Sort subfolders based on order parameter
|
||||||
folder.subfolders.sort(
|
folder.subfolders.sort(
|
||||||
(a, b) => order == SortOrder.desc
|
(a, b) => order == AssetOrder.desc
|
||||||
? b.name.compareTo(a.name)
|
? b.name.compareTo(a.name)
|
||||||
: a.name.compareTo(b.name),
|
: a.name.compareTo(b.name),
|
||||||
);
|
);
|
||||||
@ -84,7 +85,7 @@ class FolderService {
|
|||||||
List<RecursiveFolder> rootSubfolders = folderMap['_root_'] ?? [];
|
List<RecursiveFolder> rootSubfolders = folderMap['_root_'] ?? [];
|
||||||
// Sort root subfolders based on order parameter
|
// Sort root subfolders based on order parameter
|
||||||
rootSubfolders.sort(
|
rootSubfolders.sort(
|
||||||
(a, b) => order == SortOrder.desc
|
(a, b) => order == AssetOrder.desc
|
||||||
? b.name.compareTo(a.name)
|
? b.name.compareTo(a.name)
|
||||||
: a.name.compareTo(b.name),
|
: a.name.compareTo(b.name),
|
||||||
);
|
);
|
||||||
@ -101,7 +102,7 @@ class FolderService {
|
|||||||
|
|
||||||
Future<List<Asset>> getFolderAssets(
|
Future<List<Asset>> getFolderAssets(
|
||||||
RootFolder folder,
|
RootFolder folder,
|
||||||
SortOrder order,
|
AssetOrder order,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
if (folder is RecursiveFolder) {
|
if (folder is RecursiveFolder) {
|
||||||
@ -110,7 +111,7 @@ class FolderService {
|
|||||||
fullPath = fullPath[0] == '/' ? fullPath.substring(1) : fullPath;
|
fullPath = fullPath[0] == '/' ? fullPath.substring(1) : fullPath;
|
||||||
var result = await _folderApiRepository.getAssetsForPath(fullPath);
|
var result = await _folderApiRepository.getAssetsForPath(fullPath);
|
||||||
|
|
||||||
if (order == SortOrder.desc) {
|
if (order == AssetOrder.desc) {
|
||||||
result.sort((a, b) => b.fileCreatedAt.compareTo(a.fileCreatedAt));
|
result.sort((a, b) => b.fileCreatedAt.compareTo(a.fileCreatedAt));
|
||||||
} else {
|
} else {
|
||||||
result.sort((a, b) => a.fileCreatedAt.compareTo(b.fileCreatedAt));
|
result.sort((a, b) => a.fileCreatedAt.compareTo(b.fileCreatedAt));
|
||||||
|
@ -50,9 +50,9 @@ class SearchService {
|
|||||||
try {
|
try {
|
||||||
SearchResponseDto? response;
|
SearchResponseDto? response;
|
||||||
AssetType? type;
|
AssetType? type;
|
||||||
if (filter.mediaType == AssetType.image) {
|
if (filter.mediaType == AssetType.IMAGE) {
|
||||||
type = AssetType.IMAGE;
|
type = AssetType.IMAGE;
|
||||||
} else if (filter.mediaType == AssetType.video) {
|
} else if (filter.mediaType == AssetType.VIDEO) {
|
||||||
type = AssetType.VIDEO;
|
type = AssetType.VIDEO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/extensions/asset_extensions.dart';
|
import 'package:immich_mobile/extensions/asset_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
@ -15,6 +14,7 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
|||||||
import 'package:immich_mobile/widgets/common/location_picker.dart';
|
import 'package:immich_mobile/widgets/common/location_picker.dart';
|
||||||
import 'package:immich_mobile/widgets/common/share_dialog.dart';
|
import 'package:immich_mobile/widgets/common/share_dialog.dart';
|
||||||
import 'package:maplibre_gl/maplibre_gl.dart';
|
import 'package:maplibre_gl/maplibre_gl.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
void handleShareAssets(
|
void handleShareAssets(
|
||||||
WidgetRef ref,
|
WidgetRef ref,
|
||||||
@ -162,7 +162,7 @@ Future<void> handleEditLocation(
|
|||||||
Future<void> handleSetAssetsVisibility(
|
Future<void> handleSetAssetsVisibility(
|
||||||
WidgetRef ref,
|
WidgetRef ref,
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AssetVisibilityEnum visibility,
|
AssetVisibility visibility,
|
||||||
List<Asset> selection, {
|
List<Asset> selection, {
|
||||||
ToastGravity toastGravity = ToastGravity.BOTTOM,
|
ToastGravity toastGravity = ToastGravity.BOTTOM,
|
||||||
}) async {
|
}) async {
|
||||||
@ -172,7 +172,7 @@ Future<void> handleSetAssetsVisibility(
|
|||||||
.setLockedView(selection, visibility);
|
.setLockedView(selection, visibility);
|
||||||
|
|
||||||
final assetOrAssets = selection.length > 1 ? 'assets' : 'asset';
|
final assetOrAssets = selection.length > 1 ? 'assets' : 'asset';
|
||||||
final toastMessage = visibility == AssetVisibilityEnum.locked
|
final toastMessage = visibility == AssetVisibility.locked
|
||||||
? 'Added ${selection.length} $assetOrAssets to locked folder'
|
? 'Added ${selection.length} $assetOrAssets to locked folder'
|
||||||
: 'Removed ${selection.length} $assetOrAssets from locked folder';
|
: 'Removed ${selection.length} $assetOrAssets from locked folder';
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
|
@ -23,7 +23,7 @@ class AddToAlbumSliverList extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final albumSortMode = ref.watch(albumSortByOptionsProvider);
|
final albumSortMode = ref.watch(albumSortByOptionsProvider);
|
||||||
final albumSortIsReverse = ref.watch(albumSortOrderProvider);
|
final albumSortIsReverse = ref.watch(albumAssetOrderProvider);
|
||||||
final sortedAlbums = albumSortMode.sortFn(albums, albumSortIsReverse);
|
final sortedAlbums = albumSortMode.sortFn(albums, albumSortIsReverse);
|
||||||
final sortedSharedAlbums =
|
final sortedSharedAlbums =
|
||||||
albumSortMode.sortFn(sharedAlbums, albumSortIsReverse);
|
albumSortMode.sortFn(sharedAlbums, albumSortIsReverse);
|
||||||
|
@ -148,9 +148,9 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void onSortOrderToggled() async {
|
void onAssetOrderToggled() async {
|
||||||
final updatedAlbum =
|
final updatedAlbum =
|
||||||
await ref.read(albumProvider.notifier).toggleSortOrder(album);
|
await ref.read(albumProvider.notifier).toggleAssetOrder(album);
|
||||||
|
|
||||||
if (updatedAlbum == null) {
|
if (updatedAlbum == null) {
|
||||||
ImmichToast.show(
|
ImmichToast.show(
|
||||||
@ -182,7 +182,7 @@ class AlbumViewerAppbar extends HookConsumerWidget
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.swap_vert_rounded),
|
leading: const Icon(Icons.swap_vert_rounded),
|
||||||
onTap: onSortOrderToggled,
|
onTap: onAssetOrderToggled,
|
||||||
title: const Text(
|
title: const Text(
|
||||||
"change_display_order",
|
"change_display_order",
|
||||||
style: TextStyle(fontWeight: FontWeight.w500),
|
style: TextStyle(fontWeight: FontWeight.w500),
|
||||||
|
@ -7,7 +7,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/constants/enums.dart';
|
|
||||||
import 'package:immich_mobile/entities/album.entity.dart';
|
import 'package:immich_mobile/entities/album.entity.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
import 'package:immich_mobile/extensions/collection_extensions.dart';
|
import 'package:immich_mobile/extensions/collection_extensions.dart';
|
||||||
@ -27,6 +26,7 @@ import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart'
|
|||||||
import 'package:immich_mobile/widgets/asset_grid/control_bottom_app_bar.dart';
|
import 'package:immich_mobile/widgets/asset_grid/control_bottom_app_bar.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart';
|
import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class MultiselectGrid extends HookConsumerWidget {
|
class MultiselectGrid extends HookConsumerWidget {
|
||||||
const MultiselectGrid({
|
const MultiselectGrid({
|
||||||
@ -407,8 +407,8 @@ class MultiselectGrid extends HookConsumerWidget {
|
|||||||
if (remoteAssets.isNotEmpty) {
|
if (remoteAssets.isNotEmpty) {
|
||||||
final isInLockedView = ref.read(inLockedViewProvider);
|
final isInLockedView = ref.read(inLockedViewProvider);
|
||||||
final visibility = isInLockedView
|
final visibility = isInLockedView
|
||||||
? AssetVisibilityEnum.timeline
|
? AssetVisibility.timeline
|
||||||
: AssetVisibilityEnum.locked;
|
: AssetVisibility.locked;
|
||||||
|
|
||||||
await handleSetAssetsVisibility(
|
await handleSetAssetsVisibility(
|
||||||
ref,
|
ref,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/models/search/search_curated_content.model.dart';
|
import 'package:immich_mobile/models/search/search_curated_content.model.dart';
|
||||||
import 'package:immich_mobile/models/search/search_filter.model.dart';
|
import 'package:immich_mobile/models/search/search_filter.model.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/utils/image_url_builder.dart';
|
import 'package:immich_mobile/utils/image_url_builder.dart';
|
||||||
import 'package:immich_mobile/widgets/search/thumbnail_with_info.dart';
|
import 'package:immich_mobile/widgets/search/thumbnail_with_info.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class ExploreGrid extends StatelessWidget {
|
class ExploreGrid extends StatelessWidget {
|
||||||
final List<SearchCuratedContent> curatedContent;
|
final List<SearchCuratedContent> curatedContent;
|
||||||
@ -73,7 +73,7 @@ class ExploreGrid extends StatelessWidget {
|
|||||||
isArchive: false,
|
isArchive: false,
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
),
|
),
|
||||||
mediaType: AssetType.other,
|
mediaType: AssetType.OTHER,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
class MediaTypePicker extends HookWidget {
|
class MediaTypePicker extends HookWidget {
|
||||||
const MediaTypePicker({super.key, required this.onSelect, this.filter});
|
const MediaTypePicker({super.key, required this.onSelect, this.filter});
|
||||||
@ -11,7 +11,7 @@ class MediaTypePicker extends HookWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final selectedMediaType = useState(filter ?? AssetType.other);
|
final selectedMediaType = useState(filter ?? AssetType.OTHER);
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
@ -19,7 +19,7 @@ class MediaTypePicker extends HookWidget {
|
|||||||
RadioListTile(
|
RadioListTile(
|
||||||
key: const Key("all"),
|
key: const Key("all"),
|
||||||
title: const Text("all").tr(),
|
title: const Text("all").tr(),
|
||||||
value: AssetType.other,
|
value: AssetType.OTHER,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
selectedMediaType.value = value!;
|
selectedMediaType.value = value!;
|
||||||
onSelect(value);
|
onSelect(value);
|
||||||
@ -29,7 +29,7 @@ class MediaTypePicker extends HookWidget {
|
|||||||
RadioListTile(
|
RadioListTile(
|
||||||
key: const Key("image"),
|
key: const Key("image"),
|
||||||
title: const Text("image").tr(),
|
title: const Text("image").tr(),
|
||||||
value: AssetType.image,
|
value: AssetType.IMAGE,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
selectedMediaType.value = value!;
|
selectedMediaType.value = value!;
|
||||||
onSelect(value);
|
onSelect(value);
|
||||||
@ -39,7 +39,7 @@ class MediaTypePicker extends HookWidget {
|
|||||||
RadioListTile(
|
RadioListTile(
|
||||||
key: const Key("video"),
|
key: const Key("video"),
|
||||||
title: const Text("video").tr(),
|
title: const Text("video").tr(),
|
||||||
value: AssetType.video,
|
value: AssetType.VIDEO,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
selectedMediaType.value = value!;
|
selectedMediaType.value = value!;
|
||||||
onSelect(value);
|
onSelect(value);
|
||||||
|
7
mobile/test/fixtures/asset.stub.dart
vendored
7
mobile/test/fixtures/asset.stub.dart
vendored
@ -1,5 +1,6 @@
|
|||||||
import 'package:immich_mobile/domain/models/exif.model.dart';
|
import 'package:immich_mobile/domain/models/exif.model.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
final class AssetStub {
|
final class AssetStub {
|
||||||
const AssetStub._();
|
const AssetStub._();
|
||||||
@ -13,7 +14,7 @@ final class AssetStub {
|
|||||||
fileModifiedAt: DateTime(2020),
|
fileModifiedAt: DateTime(2020),
|
||||||
updatedAt: DateTime.now(),
|
updatedAt: DateTime.now(),
|
||||||
durationInSeconds: 0,
|
durationInSeconds: 0,
|
||||||
type: AssetType.image,
|
type: AssetType.IMAGE,
|
||||||
fileName: "image1.jpg",
|
fileName: "image1.jpg",
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
@ -30,7 +31,7 @@ final class AssetStub {
|
|||||||
fileModifiedAt: DateTime(2010),
|
fileModifiedAt: DateTime(2010),
|
||||||
updatedAt: DateTime.now(),
|
updatedAt: DateTime.now(),
|
||||||
durationInSeconds: 60,
|
durationInSeconds: 60,
|
||||||
type: AssetType.video,
|
type: AssetType.VIDEO,
|
||||||
fileName: "image2.jpg",
|
fileName: "image2.jpg",
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
@ -46,7 +47,7 @@ final class AssetStub {
|
|||||||
fileModifiedAt: DateTime(2025),
|
fileModifiedAt: DateTime(2025),
|
||||||
updatedAt: DateTime.now(),
|
updatedAt: DateTime.now(),
|
||||||
durationInSeconds: 60,
|
durationInSeconds: 60,
|
||||||
type: AssetType.image,
|
type: AssetType.IMAGE,
|
||||||
fileName: "image3.jpg",
|
fileName: "image3.jpg",
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
@ -233,7 +233,7 @@ void main() {
|
|||||||
).thenAnswer((_) async => {});
|
).thenAnswer((_) async => {});
|
||||||
when(
|
when(
|
||||||
() => settingsMock.setSetting<int>(
|
() => settingsMock.setSetting<int>(
|
||||||
AppSettingsEnum.selectedAlbumSortOrder,
|
AppSettingsEnum.selectedAlbumAssetOrder,
|
||||||
any(),
|
any(),
|
||||||
),
|
),
|
||||||
).thenAnswer((_) async => {});
|
).thenAnswer((_) async => {});
|
||||||
@ -242,7 +242,7 @@ void main() {
|
|||||||
test('Returns the default sort mode when none set', () {
|
test('Returns the default sort mode when none set', () {
|
||||||
// Returns the default value when nothing is set
|
// Returns the default value when nothing is set
|
||||||
when(
|
when(
|
||||||
() => settingsMock.getSetting(AppSettingsEnum.selectedAlbumSortOrder),
|
() => settingsMock.getSetting(AppSettingsEnum.selectedAlbumAssetOrder),
|
||||||
).thenReturn(0);
|
).thenReturn(0);
|
||||||
|
|
||||||
expect(container.read(albumSortByOptionsProvider), AlbumSortMode.created);
|
expect(container.read(albumSortByOptionsProvider), AlbumSortMode.created);
|
||||||
@ -251,7 +251,7 @@ void main() {
|
|||||||
test('Returns the correct sort mode with index from Store', () {
|
test('Returns the correct sort mode with index from Store', () {
|
||||||
// Returns the default value when nothing is set
|
// Returns the default value when nothing is set
|
||||||
when(
|
when(
|
||||||
() => settingsMock.getSetting(AppSettingsEnum.selectedAlbumSortOrder),
|
() => settingsMock.getSetting(AppSettingsEnum.selectedAlbumAssetOrder),
|
||||||
).thenReturn(3);
|
).thenReturn(3);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@ -267,7 +267,7 @@ void main() {
|
|||||||
|
|
||||||
verify(
|
verify(
|
||||||
() => settingsMock.setSetting(
|
() => settingsMock.setSetting(
|
||||||
AppSettingsEnum.selectedAlbumSortOrder,
|
AppSettingsEnum.selectedAlbumAssetOrder,
|
||||||
AlbumSortMode.mostOldest.storeIndex,
|
AlbumSortMode.mostOldest.storeIndex,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -275,7 +275,7 @@ void main() {
|
|||||||
|
|
||||||
test('Notifies listeners on state change', () {
|
test('Notifies listeners on state change', () {
|
||||||
when(
|
when(
|
||||||
() => settingsMock.getSetting(AppSettingsEnum.selectedAlbumSortOrder),
|
() => settingsMock.getSetting(AppSettingsEnum.selectedAlbumAssetOrder),
|
||||||
).thenReturn(0);
|
).thenReturn(0);
|
||||||
|
|
||||||
final listener = ListenerMock<AlbumSortMode>();
|
final listener = ListenerMock<AlbumSortMode>();
|
||||||
@ -306,7 +306,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/// Verify the sort order provider
|
/// Verify the sort order provider
|
||||||
group('AlbumSortOrder', () {
|
group('AlbumAssetOrder', () {
|
||||||
late AppSettingsService settingsMock;
|
late AppSettingsService settingsMock;
|
||||||
late ProviderContainer container;
|
late ProviderContainer container;
|
||||||
|
|
||||||
@ -327,7 +327,7 @@ void main() {
|
|||||||
).thenAnswer((_) async => {});
|
).thenAnswer((_) async => {});
|
||||||
when(
|
when(
|
||||||
() => settingsMock.setSetting<int>(
|
() => settingsMock.setSetting<int>(
|
||||||
AppSettingsEnum.selectedAlbumSortOrder,
|
AppSettingsEnum.selectedAlbumAssetOrder,
|
||||||
any(),
|
any(),
|
||||||
),
|
),
|
||||||
).thenAnswer((_) async => {});
|
).thenAnswer((_) async => {});
|
||||||
@ -338,11 +338,11 @@ void main() {
|
|||||||
() => settingsMock.getSetting(AppSettingsEnum.selectedAlbumSortReverse),
|
() => settingsMock.getSetting(AppSettingsEnum.selectedAlbumSortReverse),
|
||||||
).thenReturn(false);
|
).thenReturn(false);
|
||||||
|
|
||||||
expect(container.read(albumSortOrderProvider), isFalse);
|
expect(container.read(albumAssetOrderProvider), isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Properly saves the correct order', () {
|
test('Properly saves the correct order', () {
|
||||||
container.read(albumSortOrderProvider.notifier).changeSortDirection(true);
|
container.read(albumAssetOrderProvider.notifier).changeSortDirection(true);
|
||||||
|
|
||||||
verify(
|
verify(
|
||||||
() => settingsMock.setSetting(
|
() => settingsMock.setSetting(
|
||||||
@ -365,11 +365,11 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// false -> true
|
// false -> true
|
||||||
container.read(albumSortOrderProvider.notifier).changeSortDirection(true);
|
container.read(albumAssetOrderProvider.notifier).changeSortDirection(true);
|
||||||
|
|
||||||
// true -> false
|
// true -> false
|
||||||
container
|
container
|
||||||
.read(albumSortOrderProvider.notifier)
|
.read(albumAssetOrderProvider.notifier)
|
||||||
.changeSortDirection(false);
|
.changeSortDirection(false);
|
||||||
|
|
||||||
verifyInOrder([
|
verifyInOrder([
|
||||||
|
@ -4,6 +4,7 @@ import 'package:immich_mobile/entities/asset.entity.dart';
|
|||||||
import 'package:immich_mobile/extensions/asset_extensions.dart';
|
import 'package:immich_mobile/extensions/asset_extensions.dart';
|
||||||
import 'package:timezone/data/latest.dart';
|
import 'package:timezone/data/latest.dart';
|
||||||
import 'package:timezone/timezone.dart';
|
import 'package:timezone/timezone.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
ExifInfo makeExif({
|
ExifInfo makeExif({
|
||||||
DateTime? dateTimeOriginal,
|
DateTime? dateTimeOriginal,
|
||||||
@ -29,7 +30,7 @@ Asset makeAsset({
|
|||||||
fileModifiedAt: DateTime.now(),
|
fileModifiedAt: DateTime.now(),
|
||||||
updatedAt: DateTime.now(),
|
updatedAt: DateTime.now(),
|
||||||
durationInSeconds: 0,
|
durationInSeconds: 0,
|
||||||
type: AssetType.image,
|
type: AssetType.IMAGE,
|
||||||
fileName: id,
|
fileName: id,
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
final List<Asset> testAssets = [];
|
final List<Asset> testAssets = [];
|
||||||
@ -20,7 +21,7 @@ void main() {
|
|||||||
fileModifiedAt: date,
|
fileModifiedAt: date,
|
||||||
updatedAt: date,
|
updatedAt: date,
|
||||||
durationInSeconds: 0,
|
durationInSeconds: 0,
|
||||||
type: AssetType.image,
|
type: AssetType.IMAGE,
|
||||||
fileName: '',
|
fileName: '',
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
@ -14,6 +14,7 @@ import 'package:immich_mobile/interfaces/asset.interface.dart';
|
|||||||
import 'package:immich_mobile/interfaces/partner_api.interface.dart';
|
import 'package:immich_mobile/interfaces/partner_api.interface.dart';
|
||||||
import 'package:immich_mobile/services/sync.service.dart';
|
import 'package:immich_mobile/services/sync.service.dart';
|
||||||
import 'package:mocktail/mocktail.dart';
|
import 'package:mocktail/mocktail.dart';
|
||||||
|
import 'package:openapi/api.dart';
|
||||||
|
|
||||||
import '../../domain/service.mock.dart';
|
import '../../domain/service.mock.dart';
|
||||||
import '../../fixtures/asset.stub.dart';
|
import '../../fixtures/asset.stub.dart';
|
||||||
@ -41,7 +42,7 @@ void main() {
|
|||||||
fileModifiedAt: date,
|
fileModifiedAt: date,
|
||||||
updatedAt: date,
|
updatedAt: date,
|
||||||
durationInSeconds: 0,
|
durationInSeconds: 0,
|
||||||
type: AssetType.image,
|
type: AssetType.IMAGE,
|
||||||
fileName: localId ?? remoteId ?? "",
|
fileName: localId ?? remoteId ?? "",
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
isArchived: false,
|
isArchived: false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user