Compare commits

..

1 Commits

Author SHA1 Message Date
mertalev
9771c8aec1 async hash extracted video 2025-02-28 10:48:53 +03:00
9 changed files with 12 additions and 67 deletions

View File

@@ -720,6 +720,7 @@ enum IosBackgroundTask { fetch, processing }
/// entry point called by Kotlin/Java code; needs to be a top-level function
@pragma('vm:entry-point')
void _nativeEntry() {
HttpOverrides.global = HttpSSLCertOverride();
WidgetsFlutterBinding.ensureInitialized();
DartPluginRegistrant.ensureInitialized();
BackgroundService backgroundService = BackgroundService();

View File

@@ -352,7 +352,7 @@ const joinDeduplicationPlugin = new DeduplicateJoinsPlugin();
/** TODO: This should only be used for search-related queries, not as a general purpose query builder */
export function searchAssetBuilder(kysely: Kysely<DB>, options: AssetSearchBuilderOptions) {
options.isArchived ??= options.withArchived ? undefined : false;
options.withDeleted ||= !!(options.trashedAfter || options.trashedBefore || options.isOffline);
options.withDeleted ||= !!(options.trashedAfter || options.trashedBefore);
return kysely
.withPlugin(joinDeduplicationPlugin)
.selectFrom('assets')

View File

@@ -53,7 +53,7 @@ export class SyncRepository {
.select(['id', 'userId'])
.$if(!!ack, (qb) => qb.where('id', '>', ack!.updateId))
.where('deletedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
.orderBy(['id asc'])
.orderBy(['deletedAt asc', 'userId asc'])
.stream();
}
}

View File

@@ -579,7 +579,7 @@ describe(MetadataService.name, () => {
EmbeddedVideoFile: new BinaryField(0, ''),
EmbeddedVideoType: 'MotionPhoto_Data',
});
mocks.crypto.hashSha1.mockReturnValue(randomBytes(512));
mocks.crypto.hashFile.mockResolvedValue(randomBytes(512));
mocks.asset.create.mockResolvedValue(assetStub.livePhotoMotionAsset);
mocks.crypto.randomUUID.mockReturnValue(fileStub.livePhotoMotion.uuid);
const video = randomBytes(512);
@@ -623,7 +623,7 @@ describe(MetadataService.name, () => {
EmbeddedVideoFile: new BinaryField(0, ''),
EmbeddedVideoType: 'MotionPhoto_Data',
});
mocks.crypto.hashSha1.mockReturnValue(randomBytes(512));
mocks.crypto.hashFile.mockResolvedValue(randomBytes(512));
mocks.asset.create.mockResolvedValue(assetStub.livePhotoMotionAsset);
mocks.crypto.randomUUID.mockReturnValue(fileStub.livePhotoMotion.uuid);
const video = randomBytes(512);
@@ -668,7 +668,7 @@ describe(MetadataService.name, () => {
MicroVideo: 1,
MicroVideoOffset: 1,
});
mocks.crypto.hashSha1.mockReturnValue(randomBytes(512));
mocks.crypto.hashFile.mockResolvedValue(randomBytes(512));
mocks.asset.create.mockResolvedValue(assetStub.livePhotoMotionAsset);
mocks.crypto.randomUUID.mockReturnValue(fileStub.livePhotoMotion.uuid);
const video = randomBytes(512);
@@ -713,7 +713,7 @@ describe(MetadataService.name, () => {
MicroVideo: 1,
MicroVideoOffset: 1,
});
mocks.crypto.hashSha1.mockReturnValue(randomBytes(512));
mocks.crypto.hashFile.mockResolvedValue(randomBytes(512));
mocks.asset.create.mockImplementation(
(asset) => Promise.resolve({ ...assetStub.livePhotoMotionAsset, ...asset }) as Promise<AssetEntity>,
);
@@ -739,7 +739,7 @@ describe(MetadataService.name, () => {
MicroVideo: 1,
MicroVideoOffset: 1,
});
mocks.crypto.hashSha1.mockReturnValue(randomBytes(512));
mocks.crypto.hashFile.mockResolvedValue(randomBytes(512));
mocks.asset.getByChecksum.mockResolvedValue(assetStub.livePhotoMotionAsset);
const video = randomBytes(512);
mocks.storage.readFile.mockResolvedValue(video);
@@ -761,7 +761,7 @@ describe(MetadataService.name, () => {
MicroVideo: 1,
MicroVideoOffset: 1,
});
mocks.crypto.hashSha1.mockReturnValue(randomBytes(512));
mocks.crypto.hashFile.mockResolvedValue(randomBytes(512));
mocks.asset.getByChecksum.mockResolvedValue({ ...assetStub.livePhotoMotionAsset, isVisible: true });
const video = randomBytes(512);
mocks.storage.readFile.mockResolvedValue(video);
@@ -787,7 +787,7 @@ describe(MetadataService.name, () => {
MicroVideo: 1,
MicroVideoOffset: 1,
});
mocks.crypto.hashSha1.mockReturnValue(randomBytes(512));
mocks.crypto.hashFile.mockResolvedValue(randomBytes(512));
mocks.asset.create.mockResolvedValue(assetStub.livePhotoMotionAsset);
const video = randomBytes(512);
mocks.storage.readFile.mockResolvedValue(video);

View File

@@ -458,7 +458,7 @@ export class MetadataService extends BaseService {
length,
});
}
const checksum = this.cryptoRepository.hashSha1(video);
const checksum = await this.cryptoRepository.hashFile(video);
let motionAsset = await this.assetRepository.getByChecksum({
ownerId: asset.ownerId,

View File

@@ -8,14 +8,12 @@
import { preferences, user } from '$lib/stores/user.store';
import { handleError } from '$lib/utils/handle-error';
import { deleteProfileImage, updateMyPreferences, type UserAvatarColor } from '@immich/sdk';
import { mdiCog, mdiLogout, mdiPencil, mdiQrcode, mdiWrench } from '@mdi/js';
import { mdiCog, mdiLogout, mdiPencil, mdiWrench } from '@mdi/js';
import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition';
import { NotificationType, notificationController } from '../notification/notification';
import UserAvatar from '../user-avatar.svelte';
import AvatarSelector from './avatar-selector.svelte';
import { IconButton } from '@immich/ui';
import { qrCodeLoginStore } from '$lib/stores/qrcode-login.svelte';
interface Props {
onLogout: () => void;
@@ -53,14 +51,6 @@
class="absolute right-[25px] top-[75px] z-[100] w-[min(360px,100vw-50px)] rounded-3xl bg-gray-200 shadow-lg dark:border dark:border-immich-dark-gray dark:bg-immich-dark-gray"
use:focusTrap
>
<div class="absolute right-8 top-8">
<IconButton
icon={mdiQrcode}
shape="round"
aria-label="Signin With QR Code"
onclick={() => qrCodeLoginStore.showForm()}
/>
</div>
<div
class="mx-4 mt-4 flex flex-col items-center justify-center gap-4 rounded-3xl bg-white p-4 dark:bg-immich-dark-primary/10"
>

View File

@@ -1,31 +0,0 @@
<script lang="ts">
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
import { qrCodeLoginStore } from '$lib/stores/qrcode-login.svelte';
import { Button, Input } from '@immich/ui';
let password = $state('');
const submitPassword = (event: Event) => {
event.preventDefault();
console.log('Password submitted:', password);
};
</script>
{#if qrCodeLoginStore.shouldShowForm}
<div id="instance-qr-login">
<FullScreenModal title={'Login QR Code'} onClose={() => {}}>
<p class="text-xs">Enter your password to show the QR code</p>
<div class="mt-4">
<form onsubmit={submitPassword}>
<Input size="small" placeholder="Password" type="password" bind:value={password} required />
<div class="mt-6">
<Button type="submit" size="small" shape="round" fullWidth>Confirm</Button>
</div>
</form>
</div>
</FullScreenModal>
</div>
{/if}

View File

@@ -1,13 +0,0 @@
class QRCodeLoginStore {
shouldShowForm = $state(false);
showForm() {
this.shouldShowForm = true;
}
hideForm() {
this.shouldShowForm = false;
}
}
export const qrCodeLoginStore = new QRCodeLoginStore();

View File

@@ -22,7 +22,6 @@
import { setTranslations } from '@immich/ui';
import '../app.css';
import { t } from 'svelte-i18n';
import QRCodeLoginForm from '$lib/components/shared-components/qrcode-login-form.svelte';
interface Props {
children?: Snippet;
@@ -155,7 +154,6 @@
<UploadPanel />
<NotificationList />
<DialogWrapper />
<QRCodeLoginForm />
{#if $user?.isAdmin}
<VersionAnnouncementBox />