diff --git a/web/src/app.html b/web/src/app.html index 18a873b525..832b3265ef 100644 --- a/web/src/app.html +++ b/web/src/app.html @@ -107,7 +107,7 @@ To use Immich, you must enable JavaScript or use a JavaScript compatible browser. </noscript> - <body class="bg-immich-bg dark:bg-immich-dark-bg"> + <body class="bg-light text-dark"> <div id="stencil"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 792 792"> <style type="text/css"> diff --git a/web/src/lib/components/shared-components/purchasing/purchase-activation-success.svelte b/web/src/lib/components/shared-components/purchasing/purchase-activation-success.svelte index 00800ab489..1b1a91d163 100644 --- a/web/src/lib/components/shared-components/purchasing/purchase-activation-success.svelte +++ b/web/src/lib/components/shared-components/purchasing/purchase-activation-success.svelte @@ -1,11 +1,11 @@ <script lang="ts"> import Button from '$lib/components/elements/buttons/button.svelte'; import Icon from '$lib/components/elements/icon.svelte'; - import { t } from 'svelte-i18n'; - import { mdiPartyPopper } from '@mdi/js'; import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte'; import { preferences } from '$lib/stores/user.store'; import { setSupportBadgeVisibility } from '$lib/utils/purchase-utils'; + import { mdiPartyPopper } from '@mdi/js'; + import { t } from 'svelte-i18n'; interface Props { onDone: () => void; @@ -14,7 +14,7 @@ let { onDone }: Props = $props(); </script> -<div class="m-auto w-3/4 text-center flex flex-col place-content-center place-items-center dark:text-white my-6"> +<div class="m-auto w-3/4 text-center flex flex-col place-content-center place-items-center my-6"> <Icon path={mdiPartyPopper} class="text-immich-primary dark:text-immich-dark-primary" size="96" /> <p class="text-4xl mt-8 font-bold">{$t('purchase_activated_title')}</p> <p class="text-lg mt-6">{$t('purchase_activated_subtitle')}</p> diff --git a/web/src/lib/components/shared-components/purchasing/purchase-content.svelte b/web/src/lib/components/shared-components/purchasing/purchase-content.svelte index 567fce9281..b46bdcb5e3 100644 --- a/web/src/lib/components/shared-components/purchasing/purchase-content.svelte +++ b/web/src/lib/components/shared-components/purchasing/purchase-content.svelte @@ -1,12 +1,12 @@ <script lang="ts"> - import { handleError } from '$lib/utils/handle-error'; - import ServerPurchaseOptionCard from './server-purchase-option-card.svelte'; - import UserPurchaseOptionCard from './individual-purchase-option-card.svelte'; - import { activateProduct, getActivationKey } from '$lib/utils/license-utils'; import Button from '$lib/components/elements/buttons/button.svelte'; import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte'; import { purchaseStore } from '$lib/stores/purchase.store'; + import { handleError } from '$lib/utils/handle-error'; + import { activateProduct, getActivationKey } from '$lib/utils/license-utils'; import { t } from 'svelte-i18n'; + import UserPurchaseOptionCard from './individual-purchase-option-card.svelte'; + import ServerPurchaseOptionCard from './server-purchase-option-card.svelte'; interface Props { onActivate: () => void; @@ -39,13 +39,13 @@ <section class="p-4"> <div> {#if showTitle} - <h1 class="text-4xl font-bold text-immich-primary dark:text-immich-dark-primary tracking-wider"> + <h1 class="text-4xl font-bold tracking-wider"> {$t('purchase_option_title')} </h1> {/if} {#if showMessage} - <div class="mt-2 dark:text-immich-gray"> + <div class="mt-2"> <p> {$t('purchase_panel_info_1')} </p> diff --git a/web/src/lib/components/shared-components/side-bar/purchase-info.svelte b/web/src/lib/components/shared-components/side-bar/purchase-info.svelte index d94a0c169e..fe48a68009 100644 --- a/web/src/lib/components/shared-components/side-bar/purchase-info.svelte +++ b/web/src/lib/components/shared-components/side-bar/purchase-info.svelte @@ -4,9 +4,10 @@ import Icon from '$lib/components/elements/icon.svelte'; import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte'; import Portal from '$lib/components/shared-components/portal/portal.svelte'; - import LicenseModal from '$lib/components/shared-components/purchasing/purchase-modal.svelte'; import SupporterBadge from '$lib/components/shared-components/side-bar/supporter-badge.svelte'; import { AppRoute } from '$lib/constants'; + import { modalManager } from '$lib/managers/modal-manager.svelte'; + import PurchaseModal from '$lib/modals/PurchaseModal.svelte'; import { purchaseStore } from '$lib/stores/purchase.store'; import { preferences } from '$lib/stores/user.store'; import { getAccountAge } from '$lib/utils/auth'; @@ -19,7 +20,6 @@ import { fade } from 'svelte/transition'; let showMessage = $state(false); - let isOpen = $state(false); let hoverMessage = $state(false); let hoverButton = $state(false); @@ -27,8 +27,8 @@ const { isPurchased } = purchaseStore; - const openPurchaseModal = () => { - isOpen = true; + const openPurchaseModal = async () => { + await modalManager.open(PurchaseModal); showMessage = false; }; @@ -74,10 +74,6 @@ }); </script> -{#if isOpen} - <LicenseModal onClose={() => (isOpen = false)} /> -{/if} - <div class="license-status ps-4 text-sm"> {#if $isPurchased && $preferences.purchase.showSupportBadge} <button diff --git a/web/src/lib/components/shared-components/side-bar/server-status.svelte b/web/src/lib/components/shared-components/side-bar/server-status.svelte index 49006dfe5a..665decc44f 100644 --- a/web/src/lib/components/shared-components/side-bar/server-status.svelte +++ b/web/src/lib/components/shared-components/side-bar/server-status.svelte @@ -1,6 +1,7 @@ <script lang="ts"> import Icon from '$lib/components/elements/icon.svelte'; - import ServerAboutModal from '$lib/components/shared-components/server-about-modal.svelte'; + import { modalManager } from '$lib/managers/modal-manager.svelte'; + import ServerAboutModal from '$lib/modals/ServerAboutModal.svelte'; import { userInteraction } from '$lib/stores/user.svelte'; import { websocketStore } from '$lib/stores/websocket'; import { requestServerInfo } from '$lib/utils/auth'; @@ -16,7 +17,6 @@ const { serverVersion, connected } = websocketStore; - let isOpen = $state(false); let info: ServerAboutResponseDto | undefined = $state(); let versions: ServerVersionHistoryResponseDto[] = $state([]); @@ -37,10 +37,6 @@ ); </script> -{#if isOpen && info} - <ServerAboutModal onClose={() => (isOpen = false)} {info} {versions} /> -{/if} - <div class="text-sm flex md:flex ps-5 pe-1 place-items-center place-content-center justify-between min-w-52 overflow-hidden dark:text-immich-dark-fg" > @@ -58,7 +54,11 @@ <div class="flex justify-between justify-items-center"> {#if $connected && version} - <button type="button" onclick={() => (isOpen = true)} class="dark:text-immich-gray flex gap-1"> + <button + type="button" + onclick={() => info && modalManager.open(ServerAboutModal, { versions, info })} + class="dark:text-immich-gray flex gap-1" + > {#if isMain} <Icon path={mdiAlert} size="1.5em" color="#ffcc4d" /> {info?.sourceRef} {:else} diff --git a/web/src/lib/managers/modal-manager.svelte.ts b/web/src/lib/managers/modal-manager.svelte.ts index 73a3351a7e..055df14502 100644 --- a/web/src/lib/managers/modal-manager.svelte.ts +++ b/web/src/lib/managers/modal-manager.svelte.ts @@ -1,15 +1,15 @@ import ConfirmDialog from '$lib/components/shared-components/dialog/confirm-dialog.svelte'; import { mount, unmount, type Component, type ComponentProps } from 'svelte'; -type OnCloseData<T> = T extends { onClose: (data: infer R) => void } ? R : never; -type OptionalIfEmpty<T extends object> = keyof T extends never ? undefined : T; +type OnCloseData<T> = T extends { onClose: (data: infer R) => void | Promise<void> } ? R : never; class ModalManager { - open<T extends object, K = OnCloseData<T>>( - Component: Component<T>, - props?: OptionalIfEmpty<Omit<T, 'onClose'>> | Record<string, never>, + open<T = { onClose: (data: unknown) => void }, K = OnCloseData<T>>( + Component: Component<{ onClose: T }>, + props?: Record<string, never>, ): Promise<K>; - open<T extends object, K = OnCloseData<T>>(Component: Component<T>, props: OptionalIfEmpty<Omit<T, 'onClose'>>) { + open<T extends object, K = OnCloseData<T>>(Component: Component<T>, props: Omit<T, 'onClose'>): Promise<K>; + open<T extends object, K = OnCloseData<T>>(Component: Component<T>, props?: Omit<T, 'onClose'>) { return new Promise<K>((resolve) => { let modal: object = {}; diff --git a/web/src/lib/components/shared-components/purchasing/purchase-modal.svelte b/web/src/lib/modals/PurchaseModal.svelte similarity index 69% rename from web/src/lib/components/shared-components/purchasing/purchase-modal.svelte rename to web/src/lib/modals/PurchaseModal.svelte index eaf6d14674..f771529ad2 100644 --- a/web/src/lib/components/shared-components/purchasing/purchase-modal.svelte +++ b/web/src/lib/modals/PurchaseModal.svelte @@ -1,9 +1,8 @@ <script lang="ts"> - import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte'; import PurchaseActivationSuccess from '$lib/components/shared-components/purchasing/purchase-activation-success.svelte'; import PurchaseContent from '$lib/components/shared-components/purchasing/purchase-content.svelte'; - import Portal from '$lib/components/shared-components/portal/portal.svelte'; + import { Modal, ModalBody } from '@immich/ui'; interface Props { onClose: () => void; @@ -14,8 +13,8 @@ let showProductActivated = $state(false); </script> -<Portal> - <FullScreenModal showLogo title="" {onClose} width="wide"> +<Modal title="" {onClose} size="large"> + <ModalBody> {#if showProductActivated} <PurchaseActivationSuccess onDone={onClose} /> {:else} @@ -26,5 +25,5 @@ showMessage={false} /> {/if} - </FullScreenModal> -</Portal> + </ModalBody> +</Modal> diff --git a/web/src/lib/components/shared-components/server-about-modal.svelte b/web/src/lib/modals/ServerAboutModal.svelte similarity index 96% rename from web/src/lib/components/shared-components/server-about-modal.svelte rename to web/src/lib/modals/ServerAboutModal.svelte index 1284bb126d..f8f70387e6 100644 --- a/web/src/lib/components/shared-components/server-about-modal.svelte +++ b/web/src/lib/modals/ServerAboutModal.svelte @@ -1,12 +1,11 @@ <script lang="ts"> - import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte'; - import Portal from '$lib/components/shared-components/portal/portal.svelte'; - import { type ServerAboutResponseDto, type ServerVersionHistoryResponseDto } from '@immich/sdk'; - import { DateTime } from 'luxon'; - import { t } from 'svelte-i18n'; - import { mdiAlert } from '@mdi/js'; import Icon from '$lib/components/elements/icon.svelte'; import { locale } from '$lib/stores/preferences.store'; + import { type ServerAboutResponseDto, type ServerVersionHistoryResponseDto } from '@immich/sdk'; + import { Modal, ModalBody } from '@immich/ui'; + import { mdiAlert } from '@mdi/js'; + import { DateTime } from 'luxon'; + import { t } from 'svelte-i18n'; interface Props { onClose: () => void; @@ -17,8 +16,8 @@ let { onClose, info, versions }: Props = $props(); </script> -<Portal> - <FullScreenModal title={$t('about')} {onClose}> +<Modal title={$t('about')} {onClose}> + <ModalBody> <div class="flex flex-col sm:grid sm:grid-cols-2 gap-1 text-immich-primary dark:text-immich-dark-primary"> <div> <label class="font-medium text-immich-primary dark:text-immich-dark-primary text-sm" for="version-desc" @@ -199,5 +198,5 @@ </ul> </div> </div> - </FullScreenModal> -</Portal> + </ModalBody> +</Modal>