mirror of
https://github.com/immich-app/immich.git
synced 2026-02-15 13:28:24 +03:00
Compare commits
4 Commits
fix/timeli
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff7dca35f5 | ||
|
|
49ba833e4c | ||
|
|
9ab887d5d2 | ||
|
|
d264e78d3f |
@@ -14,7 +14,7 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.8.0",
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@immich/sdk": "workspace:*",
|
||||
"@types/byte-size": "^8.1.0",
|
||||
"@types/cli-progress": "^3.11.0",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.8.0",
|
||||
"@faker-js/faker": "^10.1.0",
|
||||
"@immich/cli": "file:../cli",
|
||||
"@immich/e2e-auth-server": "file:../e2e-auth-server",
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@immich/cli": "workspace:*",
|
||||
"@immich/e2e-auth-server": "workspace:*",
|
||||
"@immich/sdk": "workspace:*",
|
||||
"@playwright/test": "^1.44.1",
|
||||
"@socket.io/component-emitter": "^3.1.2",
|
||||
"@types/luxon": "^3.4.2",
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -45,7 +45,7 @@ importers:
|
||||
specifier: ^9.8.0
|
||||
version: 9.39.2
|
||||
'@immich/sdk':
|
||||
specifier: file:../open-api/typescript-sdk
|
||||
specifier: workspace:*
|
||||
version: link:../open-api/typescript-sdk
|
||||
'@types/byte-size':
|
||||
specifier: ^8.1.0
|
||||
@@ -202,13 +202,13 @@ importers:
|
||||
specifier: ^10.1.0
|
||||
version: 10.3.0
|
||||
'@immich/cli':
|
||||
specifier: file:../cli
|
||||
specifier: workspace:*
|
||||
version: link:../cli
|
||||
'@immich/e2e-auth-server':
|
||||
specifier: file:../e2e-auth-server
|
||||
specifier: workspace:*
|
||||
version: link:../e2e-auth-server
|
||||
'@immich/sdk':
|
||||
specifier: file:../open-api/typescript-sdk
|
||||
specifier: workspace:*
|
||||
version: link:../open-api/typescript-sdk
|
||||
'@playwright/test':
|
||||
specifier: ^1.44.1
|
||||
@@ -738,7 +738,7 @@ importers:
|
||||
specifier: ^0.4.3
|
||||
version: 0.4.3
|
||||
'@immich/sdk':
|
||||
specifier: file:../open-api/typescript-sdk
|
||||
specifier: workspace:*
|
||||
version: link:../open-api/typescript-sdk
|
||||
'@immich/ui':
|
||||
specifier: ^0.62.1
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "^3.0.0",
|
||||
"@immich/justified-layout-wasm": "^0.4.3",
|
||||
"@immich/sdk": "file:../open-api/typescript-sdk",
|
||||
"@immich/sdk": "workspace:*",
|
||||
"@immich/ui": "^0.62.1",
|
||||
"@mapbox/mapbox-gl-rtl-text": "0.2.3",
|
||||
"@mdi/js": "^7.4.47",
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
alt={$getAltText(toTimelineAsset(asset))}
|
||||
class="h-full w-full {$slideshowState === SlideshowState.None
|
||||
? 'object-contain'
|
||||
: slideshowLookCssMapping[$slideshowLook]} checkerboard"
|
||||
: slideshowLookCssMapping[$slideshowLook]}"
|
||||
draggable="false"
|
||||
/>
|
||||
<!-- eslint-disable-next-line svelte/require-each-key -->
|
||||
@@ -259,8 +259,4 @@
|
||||
visibility: hidden;
|
||||
animation: 0s linear 0.4s forwards delayedVisibility;
|
||||
}
|
||||
.checkerboard {
|
||||
background-image: conic-gradient(#808080 25%, #b0b0b0 25% 50%, #808080 50% 75%, #b0b0b0 75%);
|
||||
background-size: 20px 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -102,25 +102,21 @@ export class DayGroup {
|
||||
}
|
||||
|
||||
runAssetCallback(ids: Set<string>, callback: (asset: TimelineAsset) => void | { remove?: boolean }) {
|
||||
if (ids.size === 0) {
|
||||
return {
|
||||
moveAssets: [] as MoveAsset[],
|
||||
processedIds: new SvelteSet<string>(),
|
||||
unprocessedIds: ids,
|
||||
changedGeometry: false,
|
||||
};
|
||||
}
|
||||
const unprocessedIds = new SvelteSet<string>(ids);
|
||||
const processedIds = new SvelteSet<string>();
|
||||
const moveAssets: MoveAsset[] = [];
|
||||
let changedGeometry = false;
|
||||
for (const assetId of unprocessedIds) {
|
||||
const index = this.viewerAssets.findIndex((viewAsset) => viewAsset.id == assetId);
|
||||
if (index === -1) {
|
||||
|
||||
if (ids.size === 0) {
|
||||
return { moveAssets, processedIds, unprocessedIds, changedGeometry };
|
||||
}
|
||||
|
||||
for (let index = this.viewerAssets.length - 1; index >= 0; index--) {
|
||||
const { id: assetId, asset } = this.viewerAssets[index];
|
||||
if (!ids.has(assetId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const asset = this.viewerAssets[index].asset!;
|
||||
const oldTime = { ...asset.localDateTime };
|
||||
const callbackResult = callback(asset);
|
||||
let remove = (callbackResult as { remove?: boolean } | undefined)?.remove ?? false;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||
import { user } from '$lib/stores/user.store';
|
||||
import { AssetVisibility, type UserAdminResponseDto } from '@immich/sdk';
|
||||
import { SvelteSet } from 'svelte/reactivity';
|
||||
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
||||
import { fromStore } from 'svelte/store';
|
||||
|
||||
export class AssetInteraction {
|
||||
selectedAssets = $state<TimelineAsset[]>([]);
|
||||
private selectedAssetsMap = new SvelteMap<string, TimelineAsset>();
|
||||
selectedAssets = $derived(Array.from(this.selectedAssetsMap.values()));
|
||||
selectAll = $state(false);
|
||||
hasSelectedAsset(assetId: string) {
|
||||
return this.selectedAssets.some((asset) => asset.id === assetId);
|
||||
return this.selectedAssetsMap.has(assetId);
|
||||
}
|
||||
selectedGroup = new SvelteSet<string>();
|
||||
assetSelectionCandidates = $state<TimelineAsset[]>([]);
|
||||
@@ -16,7 +17,7 @@ export class AssetInteraction {
|
||||
return this.assetSelectionCandidates.some((asset) => asset.id === assetId);
|
||||
}
|
||||
assetSelectionStart = $state<TimelineAsset | null>(null);
|
||||
selectionActive = $derived(this.selectedAssets.length > 0);
|
||||
selectionActive = $derived(this.selectedAssetsMap.size > 0);
|
||||
|
||||
private user = fromStore<UserAdminResponseDto | undefined>(user);
|
||||
private userId = $derived(this.user.current?.id);
|
||||
@@ -27,9 +28,7 @@ export class AssetInteraction {
|
||||
isAllUserOwned = $derived(this.selectedAssets.every((asset) => asset.ownerId === this.userId));
|
||||
|
||||
selectAsset(asset: TimelineAsset) {
|
||||
if (!this.hasSelectedAsset(asset.id)) {
|
||||
this.selectedAssets.push(asset);
|
||||
}
|
||||
this.selectedAssetsMap.set(asset.id, asset);
|
||||
}
|
||||
|
||||
selectAssets(assets: TimelineAsset[]) {
|
||||
@@ -39,10 +38,7 @@ export class AssetInteraction {
|
||||
}
|
||||
|
||||
removeAssetFromMultiselectGroup(assetId: string) {
|
||||
const index = this.selectedAssets.findIndex((a) => a.id == assetId);
|
||||
if (index !== -1) {
|
||||
this.selectedAssets.splice(index, 1);
|
||||
}
|
||||
this.selectedAssetsMap.delete(assetId);
|
||||
}
|
||||
|
||||
addGroupToMultiselectGroup(group: string) {
|
||||
@@ -69,7 +65,7 @@ export class AssetInteraction {
|
||||
this.selectAll = false;
|
||||
|
||||
// Multi-selection
|
||||
this.selectedAssets = [];
|
||||
this.selectedAssetsMap.clear();
|
||||
this.selectedGroup.clear();
|
||||
|
||||
// Range selection
|
||||
|
||||
@@ -4,7 +4,6 @@ import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||
import { downloadManager } from '$lib/managers/download-manager.svelte';
|
||||
import { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
|
||||
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||
import { assetsSnapshot } from '$lib/managers/timeline-manager/utils.svelte';
|
||||
import { Route } from '$lib/route';
|
||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
@@ -443,13 +442,15 @@ export const selectAllAssets = async (timelineManager: TimelineManager, assetInt
|
||||
|
||||
try {
|
||||
for (const monthGroup of timelineManager.months) {
|
||||
await timelineManager.loadMonthGroup(monthGroup.yearMonth);
|
||||
if (!monthGroup.isLoaded) {
|
||||
await timelineManager.loadMonthGroup(monthGroup.yearMonth);
|
||||
}
|
||||
|
||||
if (!assetInteraction.selectAll) {
|
||||
assetInteraction.clearMultiselect();
|
||||
break; // Cancelled
|
||||
}
|
||||
assetInteraction.selectAssets(assetsSnapshot([...monthGroup.assetsIterator()]));
|
||||
assetInteraction.selectAssets([...monthGroup.assetsIterator()]);
|
||||
|
||||
for (const dateGroup of monthGroup.dayGroups) {
|
||||
assetInteraction.addGroupToMultiselectGroup(dateGroup.groupTitle);
|
||||
|
||||
Reference in New Issue
Block a user