mirror of
https://github.com/immich-app/immich.git
synced 2025-12-16 09:13:13 +03:00
Compare commits
4 Commits
chore/asyn
...
qr-code-lo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b192dfff38 | ||
|
|
b3b15e9b61 | ||
|
|
819e56d9ca | ||
|
|
9a98712db7 |
@@ -720,7 +720,6 @@ enum IosBackgroundTask { fetch, processing }
|
|||||||
/// entry point called by Kotlin/Java code; needs to be a top-level function
|
/// entry point called by Kotlin/Java code; needs to be a top-level function
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
void _nativeEntry() {
|
void _nativeEntry() {
|
||||||
HttpOverrides.global = HttpSSLCertOverride();
|
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
DartPluginRegistrant.ensureInitialized();
|
DartPluginRegistrant.ensureInitialized();
|
||||||
BackgroundService backgroundService = BackgroundService();
|
BackgroundService backgroundService = BackgroundService();
|
||||||
|
|||||||
@@ -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 */
|
/** 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) {
|
export function searchAssetBuilder(kysely: Kysely<DB>, options: AssetSearchBuilderOptions) {
|
||||||
options.isArchived ??= options.withArchived ? undefined : false;
|
options.isArchived ??= options.withArchived ? undefined : false;
|
||||||
options.withDeleted ||= !!(options.trashedAfter || options.trashedBefore);
|
options.withDeleted ||= !!(options.trashedAfter || options.trashedBefore || options.isOffline);
|
||||||
return kysely
|
return kysely
|
||||||
.withPlugin(joinDeduplicationPlugin)
|
.withPlugin(joinDeduplicationPlugin)
|
||||||
.selectFrom('assets')
|
.selectFrom('assets')
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export class SyncRepository {
|
|||||||
.select(['id', 'userId'])
|
.select(['id', 'userId'])
|
||||||
.$if(!!ack, (qb) => qb.where('id', '>', ack!.updateId))
|
.$if(!!ack, (qb) => qb.where('id', '>', ack!.updateId))
|
||||||
.where('deletedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
.where('deletedAt', '<', sql.raw<Date>("now() - interval '1 millisecond'"))
|
||||||
.orderBy(['deletedAt asc', 'userId asc'])
|
.orderBy(['id asc'])
|
||||||
.stream();
|
.stream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,14 @@
|
|||||||
import { preferences, user } from '$lib/stores/user.store';
|
import { preferences, user } from '$lib/stores/user.store';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { deleteProfileImage, updateMyPreferences, type UserAvatarColor } from '@immich/sdk';
|
import { deleteProfileImage, updateMyPreferences, type UserAvatarColor } from '@immich/sdk';
|
||||||
import { mdiCog, mdiLogout, mdiPencil, mdiWrench } from '@mdi/js';
|
import { mdiCog, mdiLogout, mdiPencil, mdiQrcode, mdiWrench } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { NotificationType, notificationController } from '../notification/notification';
|
import { NotificationType, notificationController } from '../notification/notification';
|
||||||
import UserAvatar from '../user-avatar.svelte';
|
import UserAvatar from '../user-avatar.svelte';
|
||||||
import AvatarSelector from './avatar-selector.svelte';
|
import AvatarSelector from './avatar-selector.svelte';
|
||||||
|
import { IconButton } from '@immich/ui';
|
||||||
|
import { qrCodeLoginStore } from '$lib/stores/qrcode-login.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onLogout: () => void;
|
onLogout: () => void;
|
||||||
@@ -51,6 +53,14 @@
|
|||||||
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"
|
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
|
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
|
<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"
|
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"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<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}
|
||||||
13
web/src/lib/stores/qrcode-login.svelte.ts
Normal file
13
web/src/lib/stores/qrcode-login.svelte.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
class QRCodeLoginStore {
|
||||||
|
shouldShowForm = $state(false);
|
||||||
|
|
||||||
|
showForm() {
|
||||||
|
this.shouldShowForm = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hideForm() {
|
||||||
|
this.shouldShowForm = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const qrCodeLoginStore = new QRCodeLoginStore();
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
import { setTranslations } from '@immich/ui';
|
import { setTranslations } from '@immich/ui';
|
||||||
import '../app.css';
|
import '../app.css';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
import QRCodeLoginForm from '$lib/components/shared-components/qrcode-login-form.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children?: Snippet;
|
children?: Snippet;
|
||||||
@@ -154,6 +155,7 @@
|
|||||||
<UploadPanel />
|
<UploadPanel />
|
||||||
<NotificationList />
|
<NotificationList />
|
||||||
<DialogWrapper />
|
<DialogWrapper />
|
||||||
|
<QRCodeLoginForm />
|
||||||
|
|
||||||
{#if $user?.isAdmin}
|
{#if $user?.isAdmin}
|
||||||
<VersionAnnouncementBox />
|
<VersionAnnouncementBox />
|
||||||
|
|||||||
Reference in New Issue
Block a user