mirror of
https://github.com/immich-app/immich.git
synced 2026-07-18 13:44:33 +03:00
Compare commits
1 Commits
main
...
renovate/n
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46a35db7e0 |
@@ -32,7 +32,7 @@
|
||||
"@playwright/test": "^1.44.1",
|
||||
"@socket.io/component-emitter": "^3.1.2",
|
||||
"@types/luxon": "^3.4.2",
|
||||
"@types/node": "^24.13.3",
|
||||
"@types/node": "^24.13.2",
|
||||
"@types/pg": "^8.15.1",
|
||||
"@types/pngjs": "^6.0.4",
|
||||
"@types/supertest": "^7.0.0",
|
||||
|
||||
30
mise.lock
30
mise.lock
@@ -212,36 +212,36 @@ checksum = "sha256:b6c17e747ae78cdd6de4d7532b3164b277daee97c007d3eaa2b39cca99882
|
||||
url = "https://download.java.net/java/GA/jdk21.0.2/f2283984656d49d69e91c558476027ac/13/GPL/openjdk-21.0.2_windows-x64_bin.zip"
|
||||
|
||||
[[tools.node]]
|
||||
version = "24.15.0"
|
||||
version = "24.18.0"
|
||||
backend = "core:node"
|
||||
|
||||
[tools.node."platforms.linux-arm64"]
|
||||
checksum = "sha256:73afc234d558c24919875f51c2d1ea002a2ada4ea6f83601a383869fefa64eed"
|
||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-linux-arm64.tar.gz"
|
||||
checksum = "sha256:6b4484c2190274175df9aa8f28e2d758a819cb1c1fe6ab481e2f95b463ab8508"
|
||||
url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-linux-arm64.tar.gz"
|
||||
|
||||
[tools.node."platforms.linux-arm64-musl"]
|
||||
checksum = "sha256:31e98aa960a067da91edffd5d93bc46657b5d2a8029612c359f5f2ac0060152a"
|
||||
url = "https://unofficial-builds.nodejs.org/download/release/v24.15.0/node-v24.15.0-linux-arm64-musl.tar.gz"
|
||||
checksum = "sha256:b1c6c2dc31b46dd8fb2322f4fe75b07e775c5120bc37251deeea28f529d4567b"
|
||||
url = "https://unofficial-builds.nodejs.org/download/release/v24.18.0/node-v24.18.0-linux-arm64-musl.tar.gz"
|
||||
|
||||
[tools.node."platforms.linux-x64"]
|
||||
checksum = "sha256:44836872d9aec49f1e6b52a9a922872db9a2b02d235a616a5681b6a85fec8d89"
|
||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-linux-x64.tar.gz"
|
||||
checksum = "sha256:783130984963db7ba9cbd01089eaf2c2efb055c7c1693c943174b967b3050cb8"
|
||||
url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-linux-x64.tar.gz"
|
||||
|
||||
[tools.node."platforms.linux-x64-musl"]
|
||||
checksum = "sha256:f55af5bd489c5347b113ca6594cae00a54b30ba57ac5875324311bfc6f4762e3"
|
||||
url = "https://unofficial-builds.nodejs.org/download/release/v24.15.0/node-v24.15.0-linux-x64-musl.tar.gz"
|
||||
checksum = "sha256:ea58409911e141ec6b19d9178efa2d9185a13295005b1cbf5521b3157eed1d95"
|
||||
url = "https://unofficial-builds.nodejs.org/download/release/v24.18.0/node-v24.18.0-linux-x64-musl.tar.gz"
|
||||
|
||||
[tools.node."platforms.macos-arm64"]
|
||||
checksum = "sha256:372331b969779ab5d15b949884fc6eaf88d5afe87bde8ba881d6400b9100ffc4"
|
||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-darwin-arm64.tar.gz"
|
||||
checksum = "sha256:e1a97e14c99c803e96c7339403282ea05a499c32f8d83defe9ef5ec66f979ed1"
|
||||
url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-darwin-arm64.tar.gz"
|
||||
|
||||
[tools.node."platforms.macos-x64"]
|
||||
checksum = "sha256:ffd5ee293467927f3ee731a553eb88fd1f48cf74eebc2d74a6babe4af228673b"
|
||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-darwin-x64.tar.gz"
|
||||
checksum = "sha256:dfd0dbd3e721503434df7b7205e719f61b3a3a31b2bcf9729b8b91fea240f080"
|
||||
url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-darwin-x64.tar.gz"
|
||||
|
||||
[tools.node."platforms.windows-x64"]
|
||||
checksum = "sha256:cc5149eabd53779ce1e7bdc5401643622d0c7e6800ade18928a767e940bb0e62"
|
||||
url = "https://nodejs.org/dist/v24.15.0/node-v24.15.0-win-x64.zip"
|
||||
checksum = "sha256:0ae68406b42d7725661da979b1403ec9926da205c6770827f33aac9d8f26e821"
|
||||
url = "https://nodejs.org/dist/v24.18.0/node-v24.18.0-win-x64.zip"
|
||||
|
||||
[[tools."npm:oazapfts"]]
|
||||
version = "7.5.0"
|
||||
|
||||
@@ -15,7 +15,7 @@ config_roots = [
|
||||
]
|
||||
|
||||
[tools]
|
||||
node = "24.15.0"
|
||||
node = "24.18.0"
|
||||
pnpm = "11.11.0"
|
||||
terragrunt = "1.0.3"
|
||||
opentofu = "1.11.6"
|
||||
|
||||
@@ -70,10 +70,6 @@ class RemoteAsset extends BaseAsset {
|
||||
|
||||
bool get isTrashed => deletedAt != null;
|
||||
|
||||
bool get isStacked => stackId != null;
|
||||
|
||||
bool get isArchived => visibility == .archive;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '''Asset {
|
||||
|
||||
@@ -3,23 +3,25 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/presentation/actions/action.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||
import 'package:immich_mobile/utils/asset_filter.dart';
|
||||
import 'package:immich_ui/immich_ui.dart';
|
||||
|
||||
class FavoriteAction extends AssetAction<RemoteAsset> {
|
||||
final bool favorite;
|
||||
final bool shouldFavorite;
|
||||
|
||||
FavoriteAction({required super.assets}) : favorite = assets.any((asset) => !asset.isFavorite);
|
||||
FavoriteAction({required super.assets}) : shouldFavorite = assets.any((asset) => !asset.isFavorite);
|
||||
|
||||
@override
|
||||
IconData get icon => favorite ? Icons.favorite_border_rounded : Icons.favorite_rounded;
|
||||
IconData get icon => shouldFavorite ? Icons.favorite_border_rounded : Icons.favorite_rounded;
|
||||
|
||||
@override
|
||||
String label(ActionScope scope) => favorite ? scope.context.t.favorite : scope.context.t.unfavorite;
|
||||
String label(ActionScope scope) => shouldFavorite ? scope.context.t.favorite : scope.context.t.unfavorite;
|
||||
|
||||
@override
|
||||
Iterable<RemoteAsset> filter(ActionScope scope) =>
|
||||
AssetFilter(assets).owned(scope.authUser.id).favorite(isFavorite: !favorite);
|
||||
Iterable<RemoteAsset> filter(ActionScope scope) => assets
|
||||
.where(
|
||||
(asset) => asset is RemoteAsset && asset.ownerId == scope.authUser.id && asset.isFavorite == !shouldFavorite,
|
||||
)
|
||||
.cast<RemoteAsset>();
|
||||
|
||||
@override
|
||||
bool isVisible(ActionScope scope) => filter(scope).isNotEmpty;
|
||||
@@ -29,8 +31,8 @@ class FavoriteAction extends AssetAction<RemoteAsset> {
|
||||
final ActionScope(:ref) = scope;
|
||||
final assets = filter(scope).map((asset) => asset.id).toList(growable: false);
|
||||
|
||||
await ref.read(assetServiceProvider).updateFavorite(assets, favorite);
|
||||
final message = favorite
|
||||
await ref.read(assetServiceProvider).updateFavorite(assets, shouldFavorite);
|
||||
final message = shouldFavorite
|
||||
? StaticTranslations.instance.favorite_action_prompt(count: assets.length)
|
||||
: StaticTranslations.instance.unfavorite_action_prompt(count: assets.length);
|
||||
snackbar.success(message);
|
||||
|
||||
@@ -745,15 +745,10 @@ class AddToAlbumHeader extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
Future<void> onCreateAlbum() async {
|
||||
final albumName = await showDialog<String?>(context: context, builder: (context) => const NewAlbumNameModal());
|
||||
if (albumName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final selectedAssets = ref.read(multiSelectProvider).selectedAssets;
|
||||
final newAlbum = await ref
|
||||
.read(remoteAlbumProvider.notifier)
|
||||
.createAlbumWithAssets(title: albumName, assets: selectedAssets);
|
||||
.createAlbumWithAssets(title: "Untitled Album", assets: selectedAssets);
|
||||
|
||||
if (newAlbum == null) {
|
||||
ImmichToast.show(context: context, toastType: ToastType.error, msg: 'errors.failed_to_create_album'.tr());
|
||||
|
||||
@@ -63,7 +63,7 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||
|
||||
ActionIconButtonWidget(action: FavoriteAction(assets: assetForAction)),
|
||||
|
||||
ImmichColorOverride(color: null, child: ViewerKebabMenu(originalTheme: originalTheme)),
|
||||
ViewerKebabMenu(originalTheme: originalTheme),
|
||||
];
|
||||
|
||||
final lockedViewActions = <Widget>[ViewerKebabMenu(originalTheme: originalTheme)];
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
|
||||
extension type const AssetFilter<T extends BaseAsset>(Iterable<T> assets) implements Iterable<T> {
|
||||
AssetFilter<T> where(bool Function(T asset) test) => AssetFilter(assets.where(test));
|
||||
AssetFilter<T> whereNot(bool Function(T asset) test) => AssetFilter(assets.where((asset) => !test(asset)));
|
||||
|
||||
AssetFilter<T> type(AssetType type) => where((asset) => asset.type == type);
|
||||
AssetFilter<T> favorite({bool isFavorite = true}) => where((asset) => asset.isFavorite == isFavorite);
|
||||
|
||||
AssetFilter<RemoteAsset> remote() => AssetFilter(assets.whereType<RemoteAsset>());
|
||||
AssetFilter<RemoteAsset> owned(String ownerId) => remote().where((asset) => asset.ownerId == ownerId);
|
||||
AssetFilter<RemoteAsset> visibility(AssetVisibility visibility) =>
|
||||
remote().where((asset) => asset.visibility == visibility);
|
||||
AssetFilter<RemoteAsset> notVisibility(AssetVisibility visibility) =>
|
||||
remote().where((asset) => asset.visibility != visibility);
|
||||
AssetFilter<RemoteAsset> archived({bool isArchived = true}) =>
|
||||
remote().where((asset) => asset.isArchived == isArchived);
|
||||
AssetFilter<RemoteAsset> stacked({bool isStacked = true}) => remote().where((asset) => asset.isStacked == isStacked);
|
||||
|
||||
AssetFilter<LocalAsset> local() => AssetFilter(assets.whereType<LocalAsset>());
|
||||
AssetFilter<LocalAsset> backedUp() => local().where((asset) => asset.remoteAssetId != null);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import 'package:flutter/widgets.dart';
|
||||
class ImmichColorOverride extends InheritedWidget {
|
||||
const ImmichColorOverride({super.key, required this.color, required super.child});
|
||||
|
||||
final Color? color;
|
||||
final Color color;
|
||||
|
||||
static Color? maybeOf(BuildContext context) =>
|
||||
context.dependOnInheritedWidgetOfExactType<ImmichColorOverride>()?.color;
|
||||
|
||||
@@ -5,14 +5,7 @@ import '../../utils.dart';
|
||||
class RemoteAssetFactory {
|
||||
const RemoteAssetFactory();
|
||||
|
||||
static RemoteAsset create({
|
||||
String? id,
|
||||
String? name,
|
||||
String? ownerId,
|
||||
bool isFavorite = false,
|
||||
AssetVisibility visibility = AssetVisibility.timeline,
|
||||
String? stackId,
|
||||
}) {
|
||||
static RemoteAsset create({String? id, String? name, String? ownerId, bool isFavorite = false}) {
|
||||
id = TestUtils.uuid(id);
|
||||
|
||||
return RemoteAsset(
|
||||
@@ -24,8 +17,6 @@ class RemoteAssetFactory {
|
||||
createdAt: TestUtils.yesterday(),
|
||||
updatedAt: TestUtils.now(),
|
||||
isFavorite: isFavorite,
|
||||
visibility: visibility,
|
||||
stackId: stackId,
|
||||
isEdited: false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/utils/asset_filter.dart';
|
||||
|
||||
import '../factories/local_asset_factory.dart';
|
||||
import '../factories/remote_asset_factory.dart';
|
||||
|
||||
void main() {
|
||||
group('AssetFilter', () {
|
||||
group('type promotion', () {
|
||||
test('a bare filter retains every BaseAsset', () {
|
||||
final remoteAsset = RemoteAssetFactory.create();
|
||||
final localAsset = LocalAssetFactory.create();
|
||||
|
||||
final AssetFilter<BaseAsset> filter = AssetFilter(<BaseAsset>[remoteAsset, localAsset]);
|
||||
|
||||
expect(filter.toList(), [remoteAsset, localAsset]);
|
||||
});
|
||||
|
||||
test('remote keeps only remote assets', () {
|
||||
final remoteAsset = RemoteAssetFactory.create();
|
||||
final localAsset = LocalAssetFactory.create();
|
||||
|
||||
final AssetFilter<RemoteAsset> remoteOnly = AssetFilter(<BaseAsset>[remoteAsset, localAsset]).remote();
|
||||
|
||||
expect(remoteOnly.toList(), [remoteAsset]);
|
||||
});
|
||||
|
||||
test('local keeps only local assets', () {
|
||||
final remoteAsset = RemoteAssetFactory.create();
|
||||
final localAsset = LocalAssetFactory.create();
|
||||
|
||||
final AssetFilter<LocalAsset> localOnly = AssetFilter(<BaseAsset>[remoteAsset, localAsset]).local();
|
||||
|
||||
expect(localOnly.toList(), [localAsset]);
|
||||
});
|
||||
|
||||
test('owned promotes to RemoteAsset and drops local assets', () {
|
||||
final remoteAsset = RemoteAssetFactory.create();
|
||||
final localAsset = LocalAssetFactory.create();
|
||||
|
||||
final AssetFilter<RemoteAsset> remoteOnly = AssetFilter(<BaseAsset>[
|
||||
remoteAsset,
|
||||
localAsset,
|
||||
]).owned(remoteAsset.ownerId);
|
||||
|
||||
expect(remoteOnly.toList(), [remoteAsset]);
|
||||
});
|
||||
|
||||
test('backedUp promotes to LocalAsset and drops remote assets', () {
|
||||
final syncedPhoto = LocalAssetFactory.create().copyWith(remoteId: 'remote');
|
||||
final offlinePhoto = LocalAssetFactory.create();
|
||||
final remotePhoto = RemoteAssetFactory.create();
|
||||
|
||||
final AssetFilter<LocalAsset> syncedPhotos = AssetFilter(<BaseAsset>[
|
||||
syncedPhoto,
|
||||
offlinePhoto,
|
||||
remotePhoto,
|
||||
]).backedUp();
|
||||
|
||||
expect(syncedPhotos.toList(), [syncedPhoto]);
|
||||
});
|
||||
});
|
||||
|
||||
group('named filters', () {
|
||||
test('owned keeps only assets of the given owner', () {
|
||||
final asset1 = RemoteAssetFactory.create();
|
||||
final asset2 = RemoteAssetFactory.create();
|
||||
|
||||
final alexPhotos = AssetFilter([asset1, asset2]).owned(asset1.ownerId);
|
||||
|
||||
expect(alexPhotos.toList(), [asset1]);
|
||||
});
|
||||
|
||||
test('favorites keeps only favorite assets', () {
|
||||
final asset1 = RemoteAssetFactory.create(isFavorite: true);
|
||||
final asset2 = RemoteAssetFactory.create(ownerId: asset1.ownerId);
|
||||
|
||||
final favorites = AssetFilter([asset1, asset2]).favorite();
|
||||
|
||||
expect(favorites.toList(), [asset1]);
|
||||
});
|
||||
|
||||
test('type keeps only assets of the given type', () {
|
||||
final image = RemoteAssetFactory.create();
|
||||
final video = RemoteAssetFactory.create(ownerId: image.ownerId).copyWith(type: .video);
|
||||
|
||||
final videos = AssetFilter([image, video]).type(.video);
|
||||
|
||||
expect(videos.toList(), [video]);
|
||||
});
|
||||
|
||||
test('visibility keeps only assets with the given visibility', () {
|
||||
final locked = RemoteAssetFactory.create(visibility: AssetVisibility.locked);
|
||||
final onTimeline = RemoteAssetFactory.create(ownerId: locked.ownerId);
|
||||
|
||||
final lockedPhotos = AssetFilter([locked, onTimeline]).visibility(.locked);
|
||||
|
||||
expect(lockedPhotos.toList(), [locked]);
|
||||
});
|
||||
|
||||
test('archived keeps only archived assets', () {
|
||||
final archived = RemoteAssetFactory.create(visibility: AssetVisibility.archive);
|
||||
final onTimeline = RemoteAssetFactory.create(ownerId: archived.ownerId);
|
||||
|
||||
final archivedPhotos = AssetFilter([archived, onTimeline]).archived();
|
||||
|
||||
expect(archivedPhotos.toList(), [archived]);
|
||||
});
|
||||
|
||||
test('stacked keeps only assets belonging to a stack', () {
|
||||
final stacked = RemoteAssetFactory.create(stackId: 'stack');
|
||||
final loose = RemoteAssetFactory.create(ownerId: stacked.ownerId);
|
||||
|
||||
final stackedPhotos = AssetFilter([stacked, loose]).stacked();
|
||||
|
||||
expect(stackedPhotos.toList(), [stacked]);
|
||||
});
|
||||
});
|
||||
|
||||
group('inversion', () {
|
||||
test('notArchived keeps every non-archived visibility', () {
|
||||
final archived = RemoteAssetFactory.create(visibility: AssetVisibility.archive);
|
||||
final onTimeline = RemoteAssetFactory.create(ownerId: archived.ownerId, visibility: AssetVisibility.timeline);
|
||||
final hidden = RemoteAssetFactory.create(ownerId: archived.ownerId, visibility: AssetVisibility.hidden);
|
||||
final locked = RemoteAssetFactory.create(ownerId: archived.ownerId, visibility: AssetVisibility.locked);
|
||||
|
||||
final visiblePhotos = AssetFilter([archived, onTimeline, hidden, locked]).archived(isArchived: false);
|
||||
|
||||
expect(visiblePhotos.toSet(), {onTimeline, hidden, locked});
|
||||
});
|
||||
|
||||
test('notVisibility keeps every asset not at the target visibility', () {
|
||||
final archived = RemoteAssetFactory.create(visibility: AssetVisibility.archive);
|
||||
final onTimeline = RemoteAssetFactory.create(ownerId: archived.ownerId, visibility: AssetVisibility.timeline);
|
||||
final locked = RemoteAssetFactory.create(ownerId: archived.ownerId, visibility: AssetVisibility.locked);
|
||||
|
||||
final toArchive = AssetFilter([archived, onTimeline, locked]).notVisibility(.archive);
|
||||
|
||||
expect(toArchive.toSet(), {onTimeline, locked});
|
||||
});
|
||||
|
||||
test('notStacked keeps only assets without a stack', () {
|
||||
final stacked = RemoteAssetFactory.create(stackId: 'stack');
|
||||
final loose = RemoteAssetFactory.create(ownerId: stacked.ownerId);
|
||||
|
||||
final loosePhotos = AssetFilter([stacked, loose]).stacked(isStacked: false);
|
||||
|
||||
expect(loosePhotos.toList(), [loose]);
|
||||
});
|
||||
|
||||
test('whereNot inverts an arbitrary predicate', () {
|
||||
final favorite = RemoteAssetFactory.create(isFavorite: true);
|
||||
final regular = RemoteAssetFactory.create(ownerId: favorite.ownerId);
|
||||
|
||||
final nonFavorites = AssetFilter([favorite, regular]).whereNot((asset) => asset.isFavorite);
|
||||
|
||||
expect(nonFavorites.toList(), [regular]);
|
||||
});
|
||||
|
||||
test('notFavorites keeps only non-favorite assets', () {
|
||||
final favorite = RemoteAssetFactory.create(isFavorite: true);
|
||||
final regular = RemoteAssetFactory.create(ownerId: favorite.ownerId);
|
||||
|
||||
final nonFavorites = AssetFilter([favorite, regular]).favorite(isFavorite: false);
|
||||
|
||||
expect(nonFavorites.toList(), [regular]);
|
||||
});
|
||||
});
|
||||
|
||||
group('chaining', () {
|
||||
test('combines predicates across owner, visibility and stack', () {
|
||||
final asset = RemoteAssetFactory.create();
|
||||
final wrongOwner = RemoteAssetFactory.create();
|
||||
final archived = RemoteAssetFactory.create(ownerId: asset.ownerId, visibility: AssetVisibility.archive);
|
||||
final stacked = RemoteAssetFactory.create(ownerId: asset.ownerId, stackId: 'stack-1');
|
||||
final localPhoto = LocalAssetFactory.create();
|
||||
|
||||
final result = AssetFilter(<BaseAsset>[
|
||||
asset,
|
||||
wrongOwner,
|
||||
archived,
|
||||
stacked,
|
||||
localPhoto,
|
||||
]).owned(asset.ownerId).archived(isArchived: false).stacked(isStacked: false);
|
||||
|
||||
expect(result.toList(), [asset]);
|
||||
});
|
||||
|
||||
test('a base filter after a promotion retains the promoted type', () {
|
||||
final favorite = RemoteAssetFactory.create(isFavorite: true);
|
||||
final regular = RemoteAssetFactory.create(ownerId: favorite.ownerId);
|
||||
|
||||
final AssetFilter<RemoteAsset> result = AssetFilter([favorite, regular]).owned(favorite.ownerId).favorite();
|
||||
|
||||
expect(result.toList(), [favorite]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/micromatch": "^4.0.9",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/node": "^24.13.3",
|
||||
"@types/node": "^24.13.2",
|
||||
"@vitest/coverage-v8": "^4.0.0",
|
||||
"byte-size": "^9.0.0",
|
||||
"cli-progress": "^3.12.0",
|
||||
|
||||
@@ -103,12 +103,6 @@
|
||||
"default": false,
|
||||
"title": "Case sensitive",
|
||||
"description": "Whether matching should be case-sensitive"
|
||||
},
|
||||
"usePath": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"title": "Use path",
|
||||
"description": "Match the full path on the server instead of the original filename"
|
||||
}
|
||||
},
|
||||
"required": ["pattern"]
|
||||
|
||||
@@ -54,11 +54,11 @@ const methods = wrapper<Manifest>({
|
||||
},
|
||||
|
||||
assetFileFilter: ({ data, config }) => {
|
||||
const { pattern, matchType = 'contains', caseSensitive = false, usePath = false } = config;
|
||||
const { pattern, matchType = 'contains', caseSensitive = false } = config;
|
||||
|
||||
const { asset } = data;
|
||||
|
||||
const fileName = usePath ? asset.originalPath : asset.originalFileName;
|
||||
const fileName = asset.originalFileName || '';
|
||||
const searchName = caseSensitive ? fileName : fileName.toLowerCase();
|
||||
const searchPattern = caseSensitive ? pattern : pattern.toLowerCase();
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"devDependencies": {
|
||||
"@extism/js-pdk": "^1.1.1",
|
||||
"@immich/sdk": "workspace:*",
|
||||
"@types/node": "^24.13.3",
|
||||
"@types/node": "^24.13.2",
|
||||
"esbuild": "^0.28.0",
|
||||
"tsc-alias": "^1.8.16",
|
||||
"typescript": "^6.0.0"
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"semver": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.13.3",
|
||||
"@types/node": "^24.13.2",
|
||||
"@types/semver": "^7.7.1",
|
||||
"vite": "^8.0.16",
|
||||
"vitest": "^4.1.8"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"@oazapfts/runtime": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^24.13.3",
|
||||
"@types/node": "^24.13.2",
|
||||
"typescript": "^6.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -127,7 +127,7 @@ importers:
|
||||
specifier: ^3.4.2
|
||||
version: 3.7.2
|
||||
'@types/node':
|
||||
specifier: ^24.13.3
|
||||
specifier: ^24.13.2
|
||||
version: 24.13.3
|
||||
'@types/pg':
|
||||
specifier: ^8.15.1
|
||||
@@ -236,7 +236,7 @@ importers:
|
||||
specifier: ^4.13.1
|
||||
version: 4.13.4
|
||||
'@types/node':
|
||||
specifier: ^24.13.3
|
||||
specifier: ^24.13.2
|
||||
version: 24.13.3
|
||||
'@vitest/coverage-v8':
|
||||
specifier: ^4.0.0
|
||||
@@ -339,7 +339,7 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../sdk
|
||||
'@types/node':
|
||||
specifier: ^24.13.3
|
||||
specifier: ^24.13.2
|
||||
version: 24.13.3
|
||||
esbuild:
|
||||
specifier: ^0.28.0
|
||||
@@ -361,7 +361,7 @@ importers:
|
||||
version: 7.8.5
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^24.13.3
|
||||
specifier: ^24.13.2
|
||||
version: 24.13.3
|
||||
'@types/semver':
|
||||
specifier: ^7.7.1
|
||||
@@ -380,7 +380,7 @@ importers:
|
||||
version: 1.2.0
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^24.13.3
|
||||
specifier: ^24.13.2
|
||||
version: 24.13.3
|
||||
typescript:
|
||||
specifier: ^6.0.0
|
||||
@@ -690,7 +690,7 @@ importers:
|
||||
specifier: ^2.0.0
|
||||
version: 2.2.0
|
||||
'@types/node':
|
||||
specifier: ^24.13.3
|
||||
specifier: ^24.13.2
|
||||
version: 24.13.3
|
||||
'@types/nodemailer':
|
||||
specifier: ^8.0.0
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
"@types/luxon": "^3.6.2",
|
||||
"@types/mock-fs": "^4.13.1",
|
||||
"@types/multer": "^2.0.0",
|
||||
"@types/node": "^24.13.3",
|
||||
"@types/node": "^24.13.2",
|
||||
"@types/nodemailer": "^8.0.0",
|
||||
"@types/picomatch": "^4.0.0",
|
||||
"@types/pngjs": "^6.0.5",
|
||||
|
||||
@@ -25,8 +25,6 @@ select
|
||||
inner join "plugin" on "plugin"."id" = "plugin_method"."pluginId"
|
||||
where
|
||||
"workflow"."id" = "workflow_step"."workflowId"
|
||||
order by
|
||||
"workflow_step"."order" asc
|
||||
) as agg
|
||||
) as "steps"
|
||||
from
|
||||
@@ -59,8 +57,6 @@ select
|
||||
inner join "plugin" on "plugin"."id" = "plugin_method"."pluginId"
|
||||
where
|
||||
"workflow"."id" = "workflow_step"."workflowId"
|
||||
order by
|
||||
"workflow_step"."order" asc
|
||||
) as agg
|
||||
) as "steps"
|
||||
from
|
||||
|
||||
@@ -39,8 +39,7 @@ export class WorkflowRepository {
|
||||
'plugin_method.name as methodName',
|
||||
'workflow_step.config',
|
||||
'workflow_step.enabled',
|
||||
])
|
||||
.orderBy('workflow_step.order', 'asc'),
|
||||
]),
|
||||
).as('steps'),
|
||||
]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user