mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 01:12:58 -04:00
refactor: remove unnecessary bg-color attributes and move to ui lib vars (#18234)
This commit is contained in:
parent
3066c8198c
commit
7544a678ec
@ -103,9 +103,7 @@
|
|||||||
class="block max-h-[320px] w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray dark:text-immich-dark-fg"
|
class="block max-h-[320px] w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray dark:text-immich-dark-fg"
|
||||||
>
|
>
|
||||||
{#each stats.usageByUser as user (user.userId)}
|
{#each stats.usageByUser as user (user.userId)}
|
||||||
<tr
|
<tr class="flex h-[50px] w-full place-items-center text-center even:bg-subtle/20 odd:bg-subtle/80">
|
||||||
class="flex h-[50px] w-full place-items-center text-center odd:bg-subtle even:bg-immich-bg odd:dark:bg-immich-dark-gray/75 even:dark:bg-immich-dark-gray/50"
|
|
||||||
>
|
|
||||||
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.userName}</td>
|
<td class="w-1/4 text-ellipsis px-2 text-sm">{user.userName}</td>
|
||||||
<td class="w-1/4 text-ellipsis px-2 text-sm"
|
<td class="w-1/4 text-ellipsis px-2 text-sm"
|
||||||
>{user.photos.toLocaleString($locale)} ({getByteUnitString(user.usagePhotos, $locale, 0)})</td
|
>{user.photos.toLocaleString($locale)} ({getByteUnitString(user.usagePhotos, $locale, 0)})</td
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { updateAlbumInfo } from '@immich/sdk';
|
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
|
||||||
import { shortcut } from '$lib/actions/shortcut';
|
import { shortcut } from '$lib/actions/shortcut';
|
||||||
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
|
import { updateAlbumInfo } from '@immich/sdk';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -40,7 +40,7 @@
|
|||||||
onblur={handleUpdateName}
|
onblur={handleUpdateName}
|
||||||
class="w-[99%] mb-2 border-b-2 border-transparent text-2xl md:text-4xl lg:text-6xl text-immich-primary outline-none transition-all dark:text-immich-dark-primary {isOwned
|
class="w-[99%] mb-2 border-b-2 border-transparent text-2xl md:text-4xl lg:text-6xl text-immich-primary outline-none transition-all dark:text-immich-dark-primary {isOwned
|
||||||
? 'hover:border-gray-400'
|
? 'hover:border-gray-400'
|
||||||
: 'hover:border-transparent'} bg-immich-bg focus:border-b-2 focus:border-immich-primary focus:outline-none dark:bg-immich-dark-bg dark:focus:border-immich-dark-primary dark:focus:bg-immich-dark-gray"
|
: 'hover:border-transparent'} focus:border-b-2 focus:border-immich-primary focus:outline-none bg-light dark:focus:border-immich-dark-primary dark:focus:bg-immich-dark-gray"
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={newAlbumName}
|
bind:value={newAlbumName}
|
||||||
disabled={!isOwned}
|
disabled={!isOwned}
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { shortcut } from '$lib/actions/shortcut';
|
||||||
|
import AlbumMap from '$lib/components/album-page/album-map.svelte';
|
||||||
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
|
import SelectAllAssets from '$lib/components/photos-page/actions/select-all-assets.svelte';
|
||||||
|
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||||
|
import { AssetStore } from '$lib/stores/assets-store.svelte';
|
||||||
import { dragAndDropFilesStore } from '$lib/stores/drag-and-drop-files.store';
|
import { dragAndDropFilesStore } from '$lib/stores/drag-and-drop-files.store';
|
||||||
|
import { handlePromiseError } from '$lib/utils';
|
||||||
|
import { cancelMultiselect, downloadAlbum } from '$lib/utils/asset-utils';
|
||||||
import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader';
|
import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader';
|
||||||
import type { AlbumResponseDto, SharedLinkResponseDto, UserResponseDto } from '@immich/sdk';
|
import type { AlbumResponseDto, SharedLinkResponseDto, UserResponseDto } from '@immich/sdk';
|
||||||
import { AssetStore } from '$lib/stores/assets-store.svelte';
|
import { mdiFileImagePlusOutline, mdiFolderDownloadOutline } from '@mdi/js';
|
||||||
import { cancelMultiselect, downloadAlbum } from '$lib/utils/asset-utils';
|
import { onDestroy } from 'svelte';
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||||
import DownloadAction from '../photos-page/actions/download-action.svelte';
|
import DownloadAction from '../photos-page/actions/download-action.svelte';
|
||||||
import AssetGrid from '../photos-page/asset-grid.svelte';
|
import AssetGrid from '../photos-page/asset-grid.svelte';
|
||||||
@ -13,14 +20,7 @@
|
|||||||
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
import ControlAppBar from '../shared-components/control-app-bar.svelte';
|
||||||
import ImmichLogoSmallLink from '../shared-components/immich-logo-small-link.svelte';
|
import ImmichLogoSmallLink from '../shared-components/immich-logo-small-link.svelte';
|
||||||
import ThemeButton from '../shared-components/theme-button.svelte';
|
import ThemeButton from '../shared-components/theme-button.svelte';
|
||||||
import { shortcut } from '$lib/actions/shortcut';
|
|
||||||
import { mdiFileImagePlusOutline, mdiFolderDownloadOutline } from '@mdi/js';
|
|
||||||
import { handlePromiseError } from '$lib/utils';
|
|
||||||
import AlbumSummary from './album-summary.svelte';
|
import AlbumSummary from './album-summary.svelte';
|
||||||
import { t } from 'svelte-i18n';
|
|
||||||
import { onDestroy } from 'svelte';
|
|
||||||
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
|
||||||
import AlbumMap from '$lib/components/album-page/album-map.svelte';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
sharedLink: SharedLinkResponseDto;
|
sharedLink: SharedLinkResponseDto;
|
||||||
@ -101,14 +101,12 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main
|
<main class="relative h-dvh overflow-hidden px-2 md:px-6 max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)]">
|
||||||
class="relative h-dvh overflow-hidden bg-immich-bg px-2 md:px-6 max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg"
|
|
||||||
>
|
|
||||||
<AssetGrid enableRouting={true} {album} {assetStore} {assetInteraction}>
|
<AssetGrid enableRouting={true} {album} {assetStore} {assetInteraction}>
|
||||||
<section class="pt-8 md:pt-24 px-2 md:px-0">
|
<section class="pt-8 md:pt-24 px-2 md:px-0">
|
||||||
<!-- ALBUM TITLE -->
|
<!-- ALBUM TITLE -->
|
||||||
<h1
|
<h1
|
||||||
class="bg-immich-bg text-2xl md:text-4xl lg:text-6xl text-immich-primary outline-none transition-all dark:bg-immich-dark-bg dark:text-immich-dark-primary"
|
class="text-2xl md:text-4xl lg:text-6xl text-immich-primary outline-none transition-all dark:text-immich-dark-primary"
|
||||||
>
|
>
|
||||||
{album.albumName}
|
{album.albumName}
|
||||||
</h1>
|
</h1>
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<tr
|
<tr
|
||||||
class="flex h-[50px] w-full place-items-center border-[3px] border-transparent p-2 text-center odd:bg-subtle even:bg-immich-bg hover:cursor-pointer hover:border-immich-primary/75 odd:dark:bg-immich-dark-gray/75 even:dark:bg-immich-dark-gray/50 dark:hover:border-immich-dark-primary/75 md:p-5"
|
class="flex h-[50px] w-full place-items-center border-[3px] border-transparent p-2 text-center even:bg-subtle/20 odd:bg-subtle/80 hover:cursor-pointer hover:border-immich-primary/75 odd:dark:bg-immich-dark-gray/75 even:dark:bg-immich-dark-gray/50 dark:hover:border-immich-dark-primary/75 md:p-5"
|
||||||
onclick={() => goto(`${AppRoute.ALBUMS}/${album.id}`)}
|
onclick={() => goto(`${AppRoute.ALBUMS}/${album.id}`)}
|
||||||
{oncontextmenu}
|
{oncontextmenu}
|
||||||
>
|
>
|
||||||
|
@ -529,7 +529,7 @@
|
|||||||
<div
|
<div
|
||||||
transition:fly={{ duration: 150 }}
|
transition:fly={{ duration: 150 }}
|
||||||
id="detail-panel"
|
id="detail-panel"
|
||||||
class="row-start-1 row-span-4 w-[360px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-s-immich-dark-gray dark:bg-immich-dark-bg"
|
class="row-start-1 row-span-4 w-[360px] overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
|
||||||
translate="yes"
|
translate="yes"
|
||||||
>
|
>
|
||||||
<DetailPanel {asset} currentAlbum={album} albums={appearsInAlbums} onClose={() => ($isShowDetail = false)} />
|
<DetailPanel {asset} currentAlbum={album} albums={appearsInAlbums} onClose={() => ($isShowDetail = false)} />
|
||||||
@ -540,7 +540,7 @@
|
|||||||
<div
|
<div
|
||||||
transition:fly={{ duration: 150 }}
|
transition:fly={{ duration: 150 }}
|
||||||
id="editor-panel"
|
id="editor-panel"
|
||||||
class="row-start-1 row-span-4 w-[400px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-s-immich-dark-gray dark:bg-immich-dark-bg"
|
class="row-start-1 row-span-4 w-[400px] overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
|
||||||
translate="yes"
|
translate="yes"
|
||||||
>
|
>
|
||||||
<EditorPanel {asset} onUpdateSelectedType={handleUpdateSelectedEditType} onClose={closeEditor} />
|
<EditorPanel {asset} onUpdateSelectedType={handleUpdateSelectedEditType} onClose={closeEditor} />
|
||||||
@ -589,7 +589,7 @@
|
|||||||
<div
|
<div
|
||||||
transition:fly={{ duration: 150 }}
|
transition:fly={{ duration: 150 }}
|
||||||
id="activity-panel"
|
id="activity-panel"
|
||||||
class="row-start-1 row-span-5 w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-s-immich-dark-gray dark:bg-immich-dark-bg"
|
class="row-start-1 row-span-5 w-[360px] md:w-[460px] overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
|
||||||
translate="yes"
|
translate="yes"
|
||||||
>
|
>
|
||||||
<ActivityViewer
|
<ActivityViewer
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
{#if downloadManager.isDownloading}
|
{#if downloadManager.isDownloading}
|
||||||
<div
|
<div
|
||||||
transition:fly={{ x: -100, duration: 350 }}
|
transition:fly={{ x: -100, duration: 350 }}
|
||||||
class="fixed bottom-10 start-2 z-[10000] max-h-[270px] w-[315px] rounded-2xl border bg-immich-bg p-4 text-sm shadow-sm"
|
class="fixed bottom-10 start-2 z-[10000] max-h-[270px] w-[315px] rounded-2xl border p-4 text-sm shadow-sm bg-light"
|
||||||
>
|
>
|
||||||
<p class="mb-2 text-xs text-gray-500">{$t('downloading').toUpperCase()}</p>
|
<p class="mb-2 text-xs text-gray-500">{$t('downloading').toUpperCase()}</p>
|
||||||
<div class="my-2 mb-2 flex max-h-[200px] flex-col overflow-y-auto text-sm">
|
<div class="my-2 mb-2 flex max-h-[200px] flex-col overflow-y-auto text-sm">
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||||
|
import SearchPeople from '$lib/components/faces-page/people-search.svelte';
|
||||||
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||||
import { getPersonNameWithHiddenValue } from '$lib/utils/person';
|
import { photoViewerImgElement } from '$lib/stores/assets-store.svelte';
|
||||||
import { getPeopleThumbnailUrl, handlePromiseError } from '$lib/utils';
|
import { getPeopleThumbnailUrl, handlePromiseError } from '$lib/utils';
|
||||||
import { AssetTypeEnum, type AssetFaceResponseDto, type PersonResponseDto, getAllPeople } from '@immich/sdk';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
|
import { zoomImageToBase64 } from '$lib/utils/people-utils';
|
||||||
|
import { getPersonNameWithHiddenValue } from '$lib/utils/person';
|
||||||
|
import { AssetTypeEnum, getAllPeople, type AssetFaceResponseDto, type PersonResponseDto } from '@immich/sdk';
|
||||||
import { mdiArrowLeftThin, mdiClose, mdiMagnify, mdiPlus } from '@mdi/js';
|
import { mdiArrowLeftThin, mdiClose, mdiMagnify, mdiPlus } from '@mdi/js';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
import { linear } from 'svelte/easing';
|
import { linear } from 'svelte/easing';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import { photoViewerImgElement } from '$lib/stores/assets-store.svelte';
|
|
||||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||||
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
|
||||||
import SearchPeople from '$lib/components/faces-page/people-search.svelte';
|
|
||||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
|
||||||
import { zoomImageToBase64 } from '$lib/utils/people-utils';
|
|
||||||
import { t } from 'svelte-i18n';
|
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
editedFace: AssetFaceResponseDto;
|
editedFace: AssetFaceResponseDto;
|
||||||
@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
transition:fly={{ x: 360, duration: 100, easing: linear }}
|
transition:fly={{ x: 360, duration: 100, easing: linear }}
|
||||||
class="absolute top-0 z-[2001] h-full w-[360px] overflow-x-hidden p-2 bg-immich-bg dark:bg-immich-dark-bg dark:text-immich-dark-fg"
|
class="absolute top-0 z-[2001] h-full w-[360px] overflow-x-hidden p-2 dark:text-immich-dark-fg"
|
||||||
>
|
>
|
||||||
<div class="flex place-items-center justify-between gap-2">
|
<div class="flex place-items-center justify-between gap-2">
|
||||||
{#if !searchFaces}
|
{#if !searchFaces}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
notificationController,
|
notificationController,
|
||||||
NotificationType,
|
NotificationType,
|
||||||
} from '$lib/components/shared-components/notification/notification';
|
} from '$lib/components/shared-components/notification/notification';
|
||||||
|
import { ToggleVisibility } from '$lib/constants';
|
||||||
import { locale } from '$lib/stores/preferences.store';
|
import { locale } from '$lib/stores/preferences.store';
|
||||||
import { getPeopleThumbnailUrl } from '$lib/utils';
|
import { getPeopleThumbnailUrl } from '$lib/utils';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
@ -15,7 +16,6 @@
|
|||||||
import { mdiClose, mdiEye, mdiEyeOff, mdiEyeSettings, mdiRestart } from '@mdi/js';
|
import { mdiClose, mdiEye, mdiEyeOff, mdiEyeSettings, mdiRestart } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||||
import { ToggleVisibility } from '$lib/constants';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
people: PersonResponseDto[];
|
people: PersonResponseDto[];
|
||||||
@ -134,7 +134,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-1 bg-immich-bg p-2 pb-8 dark:bg-immich-dark-bg md:px-8 mt-16">
|
<div class="flex flex-wrap gap-1 p-2 pb-8 md:px-8 mt-16">
|
||||||
<PeopleInfiniteScroll {people} hasNextPage={true} {loadNextPage}>
|
<PeopleInfiniteScroll {people} hasNextPage={true} {loadNextPage}>
|
||||||
{#snippet children({ person })}
|
{#snippet children({ person })}
|
||||||
{@const hidden = personIsHidden[person.id]}
|
{@const hidden = personIsHidden[person.id]}
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
|
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||||
import { ActionQueryParameterValue, AppRoute, QueryParameter } from '$lib/constants';
|
import { ActionQueryParameterValue, AppRoute, QueryParameter } from '$lib/constants';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { getAllPeople, getPerson, mergePerson, type PersonResponseDto } from '@immich/sdk';
|
import { getAllPeople, getPerson, mergePerson, type PersonResponseDto } from '@immich/sdk';
|
||||||
import { mdiCallMerge, mdiMerge, mdiSwapHorizontal } from '@mdi/js';
|
import { mdiCallMerge, mdiMerge, mdiSwapHorizontal } from '@mdi/js';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
import { flip } from 'svelte/animate';
|
import { flip } from 'svelte/animate';
|
||||||
import { quintOut } from 'svelte/easing';
|
import { quintOut } from 'svelte/easing';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
@ -16,8 +18,6 @@
|
|||||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||||
import FaceThumbnail from './face-thumbnail.svelte';
|
import FaceThumbnail from './face-thumbnail.svelte';
|
||||||
import PeopleList from './people-list.svelte';
|
import PeopleList from './people-list.svelte';
|
||||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
|
||||||
import { t } from 'svelte-i18n';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
person: PersonResponseDto;
|
person: PersonResponseDto;
|
||||||
@ -99,7 +99,7 @@
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||||
class="absolute start-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
|
class="absolute start-0 top-0 z-[9999] h-full w-full bg-light"
|
||||||
>
|
>
|
||||||
<ControlAppBar onClose={onBack}>
|
<ControlAppBar onClose={onBack}>
|
||||||
{#snippet leading()}
|
{#snippet leading()}
|
||||||
@ -117,7 +117,7 @@
|
|||||||
>
|
>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</ControlAppBar>
|
</ControlAppBar>
|
||||||
<section class="bg-immich-bg px-[70px] pt-[100px] dark:bg-immich-dark-bg">
|
<section class="px-[70px] pt-[100px]">
|
||||||
<section id="merge-face-selector">
|
<section id="merge-face-selector">
|
||||||
<div class="mb-10 h-[200px] place-content-center place-items-center">
|
<div class="mb-10 h-[200px] place-content-center place-items-center">
|
||||||
<p class="mb-4 text-center uppercase dark:text-white">{$t('choose_matching_people_to_merge')}</p>
|
<p class="mb-4 text-center uppercase dark:text-white">{$t('choose_matching_people_to_merge')}</p>
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
searchedPeopleLocal = $bindable(),
|
searchedPeopleLocal = $bindable(),
|
||||||
type,
|
type,
|
||||||
numberPeopleToSearch = maximumLengthSearchPeople,
|
numberPeopleToSearch = maximumLengthSearchPeople,
|
||||||
inputClass = 'w-full gap-2 bg-immich-bg dark:bg-immich-dark-bg',
|
inputClass = 'w-full gap-2',
|
||||||
showLoadingSpinner = $bindable(false),
|
showLoadingSpinner = $bindable(false),
|
||||||
placeholder = $t('name_or_nickname'),
|
placeholder = $t('name_or_nickname'),
|
||||||
onReset = () => {},
|
onReset = () => {},
|
||||||
|
@ -1,34 +1,34 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||||
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
|
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
||||||
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
||||||
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
import { timeBeforeShowLoadingSpinner } from '$lib/constants';
|
||||||
|
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||||
|
import { photoViewerImgElement } from '$lib/stores/assets-store.svelte';
|
||||||
import { boundingBoxesArray } from '$lib/stores/people.store';
|
import { boundingBoxesArray } from '$lib/stores/people.store';
|
||||||
import { websocketEvents } from '$lib/stores/websocket';
|
import { websocketEvents } from '$lib/stores/websocket';
|
||||||
import { getPeopleThumbnailUrl, handlePromiseError } from '$lib/utils';
|
import { getPeopleThumbnailUrl, handlePromiseError } from '$lib/utils';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
|
import { zoomImageToBase64 } from '$lib/utils/people-utils';
|
||||||
import { getPersonNameWithHiddenValue } from '$lib/utils/person';
|
import { getPersonNameWithHiddenValue } from '$lib/utils/person';
|
||||||
import {
|
import {
|
||||||
|
AssetTypeEnum,
|
||||||
createPerson,
|
createPerson,
|
||||||
|
deleteFace,
|
||||||
getFaces,
|
getFaces,
|
||||||
reassignFacesById,
|
reassignFacesById,
|
||||||
AssetTypeEnum,
|
|
||||||
type AssetFaceResponseDto,
|
type AssetFaceResponseDto,
|
||||||
type PersonResponseDto,
|
type PersonResponseDto,
|
||||||
deleteFace,
|
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
|
||||||
import { mdiAccountOff, mdiArrowLeftThin, mdiPencil, mdiRestart, mdiTrashCan } from '@mdi/js';
|
import { mdiAccountOff, mdiArrowLeftThin, mdiPencil, mdiRestart, mdiTrashCan } from '@mdi/js';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
import { linear } from 'svelte/easing';
|
import { linear } from 'svelte/easing';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||||
import AssignFaceSidePanel from './assign-face-side-panel.svelte';
|
import AssignFaceSidePanel from './assign-face-side-panel.svelte';
|
||||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
|
||||||
import { zoomImageToBase64 } from '$lib/utils/people-utils';
|
|
||||||
import { photoViewerImgElement } from '$lib/stores/assets-store.svelte';
|
|
||||||
import { t } from 'svelte-i18n';
|
|
||||||
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
|
|
||||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
assetId: string;
|
assetId: string;
|
||||||
@ -194,7 +194,7 @@
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
transition:fly={{ x: 360, duration: 100, easing: linear }}
|
transition:fly={{ x: 360, duration: 100, easing: linear }}
|
||||||
class="absolute top-0 z-[2000] h-full w-[360px] overflow-x-hidden p-2 bg-immich-bg dark:bg-immich-dark-bg dark:text-immich-dark-fg"
|
class="absolute top-0 z-[2000] h-full w-[360px] overflow-x-hidden p-2 dark:text-immich-dark-fg bg-light"
|
||||||
>
|
>
|
||||||
<div class="flex place-items-center justify-between gap-2">
|
<div class="flex place-items-center justify-between gap-2">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { mdiMerge, mdiPlus } from '@mdi/js';
|
import { mdiMerge, mdiPlus } from '@mdi/js';
|
||||||
import { onMount, type Snippet } from 'svelte';
|
import { onMount, type Snippet } from 'svelte';
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
import { quintOut } from 'svelte/easing';
|
import { quintOut } from 'svelte/easing';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
import Button from '../elements/buttons/button.svelte';
|
import Button from '../elements/buttons/button.svelte';
|
||||||
@ -19,7 +20,6 @@
|
|||||||
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
import { NotificationType, notificationController } from '../shared-components/notification/notification';
|
||||||
import FaceThumbnail from './face-thumbnail.svelte';
|
import FaceThumbnail from './face-thumbnail.svelte';
|
||||||
import PeopleList from './people-list.svelte';
|
import PeopleList from './people-list.svelte';
|
||||||
import { t } from 'svelte-i18n';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
assetIds: string[];
|
assetIds: string[];
|
||||||
@ -120,7 +120,7 @@
|
|||||||
|
|
||||||
<section
|
<section
|
||||||
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||||
class="absolute start-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
|
class="absolute start-0 top-0 z-[9999] h-full w-full bg-light"
|
||||||
>
|
>
|
||||||
<ControlAppBar {onClose}>
|
<ControlAppBar {onClose}>
|
||||||
{#snippet leading()}
|
{#snippet leading()}
|
||||||
@ -161,7 +161,7 @@
|
|||||||
{/snippet}
|
{/snippet}
|
||||||
</ControlAppBar>
|
</ControlAppBar>
|
||||||
{@render merge?.()}
|
{@render merge?.()}
|
||||||
<section class="bg-immich-bg px-[70px] pt-[100px] dark:bg-immich-dark-bg">
|
<section class="px-[70px] pt-[100px]">
|
||||||
<section id="merge-face-selector relative">
|
<section id="merge-face-selector relative">
|
||||||
{#if selectedPerson !== null}
|
{#if selectedPerson !== null}
|
||||||
<div class="mb-10 h-[200px] place-content-center place-items-center">
|
<div class="mb-10 h-[200px] place-content-center place-items-center">
|
||||||
|
@ -177,9 +177,7 @@
|
|||||||
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
||||||
{#each validatedPaths as validatedPath, listIndex (validatedPath.importPath)}
|
{#each validatedPaths as validatedPath, listIndex (validatedPath.importPath)}
|
||||||
<tr
|
<tr
|
||||||
class={`flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg ${
|
class="flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg even:bg-subtle/20 odd:bg-subtle/80"
|
||||||
listIndex % 2 == 0 ? 'bg-subtle' : 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<td class="w-1/8 text-ellipsis ps-8 text-sm">
|
<td class="w-1/8 text-ellipsis ps-8 text-sm">
|
||||||
{#if validatedPath.isValid}
|
{#if validatedPath.isValid}
|
||||||
@ -215,9 +213,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
<tr
|
<tr
|
||||||
class={`flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg ${
|
class="flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg even:bg-subtle/20 odd:bg-subtle/80"
|
||||||
importPaths.length % 2 == 0 ? 'bg-subtle' : 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<td class="w-4/5 text-ellipsis px-4 text-sm">
|
<td class="w-4/5 text-ellipsis px-4 text-sm">
|
||||||
{#if importPaths.length === 0}
|
{#if importPaths.length === 0}
|
||||||
|
@ -127,9 +127,7 @@
|
|||||||
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
||||||
{#each exclusionPatterns as exclusionPattern, listIndex (exclusionPattern)}
|
{#each exclusionPatterns as exclusionPattern, listIndex (exclusionPattern)}
|
||||||
<tr
|
<tr
|
||||||
class={`flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg ${
|
class="flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg even:bg-subtle/20 odd:bg-subtle/80"
|
||||||
listIndex % 2 == 0 ? 'bg-subtle' : 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<td class="w-3/4 text-ellipsis px-4 text-sm">{exclusionPattern}</td>
|
<td class="w-3/4 text-ellipsis px-4 text-sm">{exclusionPattern}</td>
|
||||||
<td class="w-1/4 text-ellipsis flex justify-center">
|
<td class="w-1/4 text-ellipsis flex justify-center">
|
||||||
@ -147,9 +145,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
<tr
|
<tr
|
||||||
class={`flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg ${
|
class="flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg even:bg-subtle/20 odd:bg-subtle/80"
|
||||||
exclusionPatterns.length % 2 == 0 ? 'bg-subtle' : 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<td class="w-3/4 text-ellipsis px-4 text-sm">
|
<td class="w-3/4 text-ellipsis px-4 text-sm">
|
||||||
{#if exclusionPatterns.length === 0}
|
{#if exclusionPatterns.length === 0}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
|
import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
|
||||||
import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte';
|
|
||||||
import { copyToClipboard } from '$lib/utils';
|
import { copyToClipboard } from '$lib/utils';
|
||||||
import { mdiCodeTags, mdiContentCopy, mdiMessage, mdiPartyPopper } from '@mdi/js';
|
import { mdiCodeTags, mdiContentCopy, mdiMessage, mdiPartyPopper } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
@ -22,7 +22,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="h-dvh w-dvw">
|
<div class="h-dvh w-dvw">
|
||||||
<section class="bg-immich-bg dark:bg-immich-dark-bg">
|
<section>
|
||||||
<div class="flex place-items-center border-b px-6 py-4 dark:border-b-immich-dark-gray">
|
<div class="flex place-items-center border-b px-6 py-4 dark:border-b-immich-dark-gray">
|
||||||
<a class="flex place-items-center gap-2 hover:cursor-pointer" href="/photos">
|
<a class="flex place-items-center gap-2 hover:cursor-pointer" href="/photos">
|
||||||
<ImmichLogo class="h-[50px]" />
|
<ImmichLogo class="h-[50px]" />
|
||||||
@ -33,7 +33,7 @@
|
|||||||
<div class="fixed top-0 flex h-full w-full place-content-center place-items-center overflow-hidden bg-black/50">
|
<div class="fixed top-0 flex h-full w-full place-content-center place-items-center overflow-hidden bg-black/50">
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
class="w-[500px] max-w-[95vw] rounded-3xl border shadow-sm dark:border-immich-dark-gray dark:text-immich-dark-fg bg-subtle/80"
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div class="flex items-center justify-between gap-4 px-4 py-4">
|
<div class="flex items-center justify-between gap-4 px-4 py-4">
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
</header>
|
</header>
|
||||||
<div
|
<div
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="relative grid grid-cols-[theme(spacing.0)_auto] overflow-hidden bg-immich-bg dark:bg-immich-dark-bg sidebar:grid-cols-[theme(spacing.64)_auto]
|
class="relative grid grid-cols-[theme(spacing.0)_auto] overflow-hidden sidebar:grid-cols-[theme(spacing.64)_auto]
|
||||||
{hideNavbar ? 'h-dvh' : 'h-[calc(100dvh-var(--navbar-height))]'}
|
{hideNavbar ? 'h-dvh' : 'h-[calc(100dvh-var(--navbar-height))]'}
|
||||||
{hideNavbar ? 'pt-[var(--navbar-height)]' : ''}
|
{hideNavbar ? 'pt-[var(--navbar-height)]' : ''}
|
||||||
{hideNavbar ? 'max-md:pt-[var(--navbar-height-md)]' : ''}"
|
{hideNavbar ? 'max-md:pt-[var(--navbar-height-md)]' : ''}"
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
<div class="flex gap-4 mb-6">
|
<div class="flex gap-4 mb-6">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="w-1/2 aspect-square bg-immich-bg rounded-3xl transition-all shadow-sm hover:shadow-xl border-[3px] border-immich-dark-primary/80 border-immich-primary dark:border dark:border-transparent"
|
class="light w-1/2 aspect-square bg-light rounded-3xl transition-all shadow-sm hover:shadow-xl border-[3px] border-immich-dark-primary/80 border-immich-primary dark:border dark:border-transparent"
|
||||||
onclick={() => themeManager.setTheme(Theme.LIGHT)}
|
onclick={() => themeManager.setTheme(Theme.LIGHT)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -35,7 +35,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="w-1/2 aspect-square bg-immich-dark-bg rounded-3xl dark:border-[3px] dark:border-immich-dark-primary/80 dark:border-immich-dark-primary border border-transparent"
|
class="dark w-1/2 aspect-square bg-light rounded-3xl dark:border-[3px] dark:border-immich-dark-primary/80 dark:border-immich-dark-primary border border-transparent"
|
||||||
onclick={() => themeManager.setTheme(Theme.DARK)}
|
onclick={() => themeManager.setTheme(Theme.DARK)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
|
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
import {
|
import {
|
||||||
type AssetStore,
|
|
||||||
type AssetBucket,
|
type AssetBucket,
|
||||||
assetSnapshot,
|
assetSnapshot,
|
||||||
assetsSnapshot,
|
assetsSnapshot,
|
||||||
|
type AssetStore,
|
||||||
isSelectingAllAssets,
|
isSelectingAllAssets,
|
||||||
} from '$lib/stores/assets-store.svelte';
|
} from '$lib/stores/assets-store.svelte';
|
||||||
import { navigate } from '$lib/utils/navigation';
|
import { navigate } from '$lib/utils/navigation';
|
||||||
import { getDateLocaleString } from '$lib/utils/timeline-util';
|
import { getDateLocaleString } from '$lib/utils/timeline-util';
|
||||||
import type { AssetResponseDto } from '@immich/sdk';
|
import type { AssetResponseDto } from '@immich/sdk';
|
||||||
import { mdiCheckCircle, mdiCircleOutline } from '@mdi/js';
|
import { mdiCheckCircle, mdiCircleOutline } from '@mdi/js';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly, scale } from 'svelte/transition';
|
||||||
import Thumbnail from '../assets/thumbnail/thumbnail.svelte';
|
import Thumbnail from '../assets/thumbnail/thumbnail.svelte';
|
||||||
import type { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
|
||||||
import { scale } from 'svelte/transition';
|
|
||||||
|
|
||||||
import { flip } from 'svelte/animate';
|
import { flip } from 'svelte/animate';
|
||||||
|
|
||||||
@ -128,7 +127,7 @@
|
|||||||
>
|
>
|
||||||
<!-- Date group title -->
|
<!-- Date group title -->
|
||||||
<div
|
<div
|
||||||
class="flex z-[100] pt-7 pb-5 max-md:pt-5 max-md:pb-3 h-6 place-items-center text-xs font-medium text-immich-fg bg-immich-bg dark:bg-immich-dark-bg dark:text-immich-dark-fg md:text-sm"
|
class="flex z-[100] pt-7 pb-5 max-md:pt-5 max-md:pb-3 h-6 place-items-center text-xs font-medium text-immich-fg dark:text-immich-dark-fg md:text-sm"
|
||||||
style:width={dateGroup.width + 'px'}
|
style:width={dateGroup.width + 'px'}
|
||||||
>
|
>
|
||||||
{#if !singleSelect && ((hoveredDateGroup === dateGroup.groupTitle && isMouseOverGroup) || assetInteraction.selectedGroup.has(dateGroup.groupTitle))}
|
{#if !singleSelect && ((hoveredDateGroup === dateGroup.groupTitle && isMouseOverGroup) || assetInteraction.selectedGroup.has(dateGroup.groupTitle))}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<div class="overflow-clip" style:height={height + 'px'}>
|
<div class="overflow-clip" style:height={height + 'px'}>
|
||||||
<div
|
<div
|
||||||
class="flex z-[100] pt-7 pb-5 h-6 place-items-center text-xs font-medium text-immich-fg bg-immich-bg dark:bg-immich-dark-bg dark:text-immich-dark-fg md:text-sm"
|
class="flex z-[100] pt-7 pb-5 h-6 place-items-center text-xs font-medium text-immich-fg bg-light dark:text-immich-dark-fg md:text-sm"
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</div>
|
</div>
|
||||||
|
@ -87,7 +87,7 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="bg-immich-bg dark:bg-immich-dark-bg">
|
<section>
|
||||||
{#if sharedLink?.allowUpload || assets.length > 1}
|
{#if sharedLink?.allowUpload || assets.length > 1}
|
||||||
{#if assetInteraction.selectionActive}
|
{#if assetInteraction.selectionActive}
|
||||||
<AssetSelectControlBar
|
<AssetSelectControlBar
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type AlbumResponseDto, getAllAlbums } from '@immich/sdk';
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import AlbumListItem from '../../asset-viewer/album-list-item.svelte';
|
|
||||||
import NewAlbumListItem from './new-album-list-item.svelte';
|
|
||||||
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
|
||||||
import { initInput } from '$lib/actions/focus';
|
import { initInput } from '$lib/actions/focus';
|
||||||
import { t } from 'svelte-i18n';
|
|
||||||
import { albumViewSettings } from '$lib/stores/preferences.store';
|
|
||||||
import {
|
import {
|
||||||
AlbumModalRowConverter,
|
AlbumModalRowConverter,
|
||||||
AlbumModalRowType,
|
AlbumModalRowType,
|
||||||
isSelectableRowType,
|
isSelectableRowType,
|
||||||
} from '$lib/components/shared-components/album-selection/album-selection-utils';
|
} from '$lib/components/shared-components/album-selection/album-selection-utils';
|
||||||
|
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
|
||||||
|
import { albumViewSettings } from '$lib/stores/preferences.store';
|
||||||
|
import { type AlbumResponseDto, getAllAlbums } from '@immich/sdk';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
|
import AlbumListItem from '../../asset-viewer/album-list-item.svelte';
|
||||||
|
import NewAlbumListItem from './new-album-list-item.svelte';
|
||||||
|
|
||||||
let albums: AlbumResponseDto[] = $state([]);
|
let albums: AlbumResponseDto[] = $state([]);
|
||||||
let recentAlbums: AlbumResponseDto[] = $state([]);
|
let recentAlbums: AlbumResponseDto[] = $state([]);
|
||||||
@ -98,7 +98,7 @@
|
|||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
<input
|
<input
|
||||||
class="border-b-4 border-immich-bg bg-immich-bg px-6 py-2 text-2xl focus:border-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:focus:border-immich-dark-primary"
|
class="border-b-4 border-immich-bg px-6 py-2 text-2xl focus:border-immich-primary dark:border-immich-dark-gray dark:focus:border-immich-dark-primary"
|
||||||
placeholder={$t('search')}
|
placeholder={$t('search')}
|
||||||
{onkeydown}
|
{onkeydown}
|
||||||
bind:value={search}
|
bind:value={search}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
trailing,
|
trailing,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let appBarBorder = $state('bg-immich-bg border border-transparent');
|
let appBarBorder = $state('bg-light border border-transparent');
|
||||||
|
|
||||||
const onScroll = () => {
|
const onScroll = () => {
|
||||||
if (window.scrollY > 80) {
|
if (window.scrollY > 80) {
|
||||||
@ -42,7 +42,7 @@
|
|||||||
appBarBorder = 'border border-gray-600';
|
appBarBorder = 'border border-gray-600';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
appBarBorder = 'bg-immich-bg border border-transparent';
|
appBarBorder = 'bg-light border border-transparent';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
>
|
>
|
||||||
<SkipLink text={$t('skip_to_content')} />
|
<SkipLink text={$t('skip_to_content')} />
|
||||||
<div
|
<div
|
||||||
class="grid h-full grid-cols-[theme(spacing.32)_auto] items-center border-b bg-immich-bg py-2 dark:border-b-immich-dark-gray dark:bg-immich-dark-bg sidebar:grid-cols-[theme(spacing.64)_auto]"
|
class="grid h-full grid-cols-[theme(spacing.32)_auto] items-center border-b py-2 dark:border-b-immich-dark-gray sidebar:grid-cols-[theme(spacing.64)_auto]"
|
||||||
>
|
>
|
||||||
<div class="flex flex-row gap-1 mx-4 items-center">
|
<div class="flex flex-row gap-1 mx-4 items-center">
|
||||||
<IconButton
|
<IconButton
|
||||||
|
@ -446,7 +446,7 @@
|
|||||||
aria-valuemax={toScrollY(1)}
|
aria-valuemax={toScrollY(1)}
|
||||||
aria-valuemin={toScrollY(0)}
|
aria-valuemin={toScrollY(0)}
|
||||||
data-id="immich-scrubbable-scrollbar"
|
data-id="immich-scrubbable-scrollbar"
|
||||||
class="absolute end-0 z-[1] select-none bg-immich-bg hover:cursor-row-resize"
|
class="absolute end-0 z-[1] select-none hover:cursor-row-resize"
|
||||||
style:padding-top={PADDING_TOP + 'px'}
|
style:padding-top={PADDING_TOP + 'px'}
|
||||||
style:padding-bottom={PADDING_BOTTOM + 'px'}
|
style:padding-bottom={PADDING_BOTTOM + 'px'}
|
||||||
style:width
|
style:width
|
||||||
@ -464,7 +464,7 @@
|
|||||||
class={[
|
class={[
|
||||||
{ 'border-b-2': isDragging },
|
{ 'border-b-2': isDragging },
|
||||||
{ 'rounded-bl-md': !isDragging },
|
{ 'rounded-bl-md': !isDragging },
|
||||||
'truncate opacity-85 pointer-events-none absolute end-0 z-[100] min-w-20 max-w-64 w-fit rounded-ss-md border-immich-primary bg-immich-bg py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:bg-immich-dark-gray dark:text-immich-dark-fg',
|
'bg-light truncate opacity-85 pointer-events-none absolute end-0 z-[100] min-w-20 max-w-64 w-fit rounded-ss-md border-immich-primary py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:text-immich-dark-fg',
|
||||||
]}
|
]}
|
||||||
style:top="{hoverY + 2}px"
|
style:top="{hoverY + 2}px"
|
||||||
>
|
>
|
||||||
@ -506,7 +506,7 @@
|
|||||||
{#if assetStore.scrolling && scrollHoverLabel && !isHover}
|
{#if assetStore.scrolling && scrollHoverLabel && !isHover}
|
||||||
<p
|
<p
|
||||||
transition:fade={{ duration: 200 }}
|
transition:fade={{ duration: 200 }}
|
||||||
class="truncate pointer-events-none absolute end-0 bottom-0 z-[100] min-w-20 max-w-64 w-fit rounded-tl-md border-b-2 border-immich-primary bg-immich-bg/80 py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:bg-immich-dark-gray/80 dark:text-immich-dark-fg"
|
class="truncate pointer-events-none absolute end-0 bottom-0 z-[100] min-w-20 max-w-64 w-fit rounded-tl-md border-b-2 border-immich-primary bg-subtle/70 py-1 px-1 text-sm font-medium shadow-[0_0_8px_rgba(0,0,0,0.25)] dark:border-immich-dark-primary dark:text-immich-dark-fg"
|
||||||
>
|
>
|
||||||
{scrollHoverLabel}
|
{scrollHoverLabel}
|
||||||
</p>
|
</p>
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
id="sidebar"
|
id="sidebar"
|
||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
class="immich-scrollbar relative z-auto w-0 sidebar:w-[16rem] overflow-y-auto overflow-x-hidden bg-immich-bg pt-8 transition-all duration-200 dark:bg-immich-dark-bg"
|
class="immich-scrollbar relative z-auto w-0 sidebar:w-[16rem] overflow-y-auto overflow-x-hidden pt-8 transition-all duration-200"
|
||||||
class:shadow-2xl={isExpanded}
|
class:shadow-2xl={isExpanded}
|
||||||
class:dark:border-e-immich-dark-gray={isExpanded}
|
class:dark:border-e-immich-dark-gray={isExpanded}
|
||||||
class:border-r={isExpanded}
|
class:border-r={isExpanded}
|
||||||
|
@ -40,11 +40,7 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div in:fade={{ duration: 250 }} out:fade={{ duration: 100 }} class="flex flex-col rounded-lg text-xs p-2 gap-1">
|
||||||
in:fade={{ duration: 250 }}
|
|
||||||
out:fade={{ duration: 100 }}
|
|
||||||
class="flex flex-col rounded-lg bg-immich-bg text-xs dark:bg-immich-dark-bg p-2 gap-1"
|
|
||||||
>
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
{#if uploadAsset.state === UploadState.PENDING}
|
{#if uploadAsset.state === UploadState.PENDING}
|
||||||
|
@ -125,11 +125,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
||||||
{#each keys as key, index (key.id)}
|
{#each keys as key (key.id)}
|
||||||
<tr
|
<tr
|
||||||
class={`flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg ${
|
class="flex h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg even:bg-subtle/20 odd:bg-subtle/80"
|
||||||
index % 2 == 0 ? 'bg-subtle' : 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<td class="w-1/3 text-ellipsis px-4 text-sm">{key.name}</td>
|
<td class="w-1/3 text-ellipsis px-4 text-sm">{key.name}</td>
|
||||||
<td class="w-1/3 text-ellipsis px-4 text-sm"
|
<td class="w-1/3 text-ellipsis px-4 text-sm"
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
|
|
||||||
{#snippet row(viewName: string, stats: AssetStatsResponseDto)}
|
{#snippet row(viewName: string, stats: AssetStatsResponseDto)}
|
||||||
<tr
|
<tr
|
||||||
class="flex h-14 w-full place-items-center text-center dark:text-immich-dark-fg odd:bg-immich-bg even:bg-subtle odd:dark:bg-immich-dark-gray/50 even:dark:bg-immich-dark-gray/75"
|
class="flex h-14 w-full place-items-center text-center dark:text-immich-dark-fg even:bg-subtle/20 odd:bg-subtle/80"
|
||||||
>
|
>
|
||||||
<td class="w-1/4 px-4 text-sm">{viewName}</td>
|
<td class="w-1/4 px-4 text-sm">{viewName}</td>
|
||||||
<td class="w-1/4 px-4 text-sm">{stats.images.toLocaleString($locale)}</td>
|
<td class="w-1/4 px-4 text-sm">{stats.images.toLocaleString($locale)}</td>
|
||||||
@ -95,7 +95,7 @@
|
|||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="w-full text-start mt-4">
|
<table class="w-full text-start mt-4">
|
||||||
<thead
|
<thead
|
||||||
class="mb-4 flex h-12 w-full rounded-md border bg-gray-50 text-immich-primary dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-primary"
|
class="mb-4 flex h-12 w-full rounded-md border text-immich-primary dark:border-immich-dark-gray bg-subtle dark:text-immich-dark-primary"
|
||||||
>
|
>
|
||||||
<tr class="flex w-full place-items-center text-sm font-medium text-center">
|
<tr class="flex w-full place-items-center text-sm font-medium text-center">
|
||||||
<th class="w-1/2">{$t('owned')}</th>
|
<th class="w-1/2">{$t('owned')}</th>
|
||||||
@ -103,9 +103,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
||||||
<tr
|
<tr class="flex h-14 w-full place-items-center text-center dark:text-immich-dark-fg bg-subtle/20">
|
||||||
class="flex h-14 w-full place-items-center text-center dark:text-immich-dark-fg bg-immich-bg dark:bg-immich-dark-gray/50"
|
|
||||||
>
|
|
||||||
<td class="w-1/2 px-4 text-sm">{albumStats.owned.toLocaleString($locale)}</td>
|
<td class="w-1/2 px-4 text-sm">{albumStats.owned.toLocaleString($locale)}</td>
|
||||||
<td class="w-1/2 px-4 text-sm">{albumStats.shared.toLocaleString($locale)}</td>
|
<td class="w-1/2 px-4 text-sm">{albumStats.shared.toLocaleString($locale)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -588,9 +588,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<main
|
<main class="relative h-dvh overflow-hidden px-6 max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)]">
|
||||||
class="relative h-dvh overflow-hidden bg-immich-bg px-6 max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg"
|
|
||||||
>
|
|
||||||
<AssetGrid
|
<AssetGrid
|
||||||
enableRouting={viewMode === AlbumPageViewMode.SELECT_ASSETS ? false : true}
|
enableRouting={viewMode === AlbumPageViewMode.SELECT_ASSETS ? false : true}
|
||||||
{album}
|
{album}
|
||||||
@ -678,7 +676,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onclick={() => (viewMode = AlbumPageViewMode.SELECT_ASSETS)}
|
onclick={() => (viewMode = AlbumPageViewMode.SELECT_ASSETS)}
|
||||||
class="mt-5 flex w-full place-items-center gap-6 rounded-md border bg-immich-bg px-8 py-8 text-immich-fg transition-all hover:bg-gray-100 hover:text-immich-primary dark:border-none dark:bg-immich-dark-gray dark:text-immich-dark-fg dark:hover:text-immich-dark-primary"
|
class="mt-5 bg-subtle flex w-full place-items-center gap-6 rounded-md border px-8 py-8 text-immich-fg transition-all hover:bg-gray-100 hover:text-immich-primary dark:border-none dark:text-immich-dark-fg dark:hover:text-immich-dark-primary"
|
||||||
>
|
>
|
||||||
<span class="text-text-immich-primary dark:text-immich-dark-primary"
|
<span class="text-text-immich-primary dark:text-immich-dark-primary"
|
||||||
><Icon path={mdiPlus} size="24" />
|
><Icon path={mdiPlus} size="24" />
|
||||||
@ -709,7 +707,7 @@
|
|||||||
<div
|
<div
|
||||||
transition:fly={{ duration: 150 }}
|
transition:fly={{ duration: 150 }}
|
||||||
id="activity-panel"
|
id="activity-panel"
|
||||||
class="z-[2] w-[360px] md:w-[460px] overflow-y-auto bg-immich-bg transition-all dark:border-l dark:border-s-immich-dark-gray dark:bg-immich-dark-bg"
|
class="z-[2] w-[360px] md:w-[460px] overflow-y-auto transition-all dark:border-l dark:border-s-immich-dark-gray"
|
||||||
translate="yes"
|
translate="yes"
|
||||||
>
|
>
|
||||||
<ActivityViewer
|
<ActivityViewer
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main class="grid h-dvh bg-immich-bg pt-18 dark:bg-immich-dark-bg">
|
<main class="grid h-dvh pt-18">
|
||||||
{#if assetInteraction.selectionActive}
|
{#if assetInteraction.selectionActive}
|
||||||
<AssetSelectControlBar
|
<AssetSelectControlBar
|
||||||
assets={assetInteraction.selectedAssets}
|
assets={assetInteraction.selectedAssets}
|
||||||
|
@ -458,7 +458,7 @@
|
|||||||
<dialog
|
<dialog
|
||||||
open
|
open
|
||||||
transition:fly={{ y: innerHeight, duration: 150, easing: quintOut, opacity: 0 }}
|
transition:fly={{ y: innerHeight, duration: 150, easing: quintOut, opacity: 0 }}
|
||||||
class="absolute start-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
|
class="absolute start-0 top-0 z-[9999] h-full w-full bg-light"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="manage-visibility-title"
|
aria-labelledby="manage-visibility-title"
|
||||||
use:focusTrap
|
use:focusTrap
|
||||||
|
@ -487,7 +487,7 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main
|
<main
|
||||||
class="relative h-dvh overflow-hidden bg-immich-bg tall:ms-4 md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg"
|
class="relative h-dvh overflow-hidden tall:ms-4 md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)]"
|
||||||
use:scrollMemoryClearer={{
|
use:scrollMemoryClearer={{
|
||||||
routeStartsWith: AppRoute.PEOPLE,
|
routeStartsWith: AppRoute.PEOPLE,
|
||||||
beforeClear: () => {
|
beforeClear: () => {
|
||||||
|
@ -291,10 +291,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<div class="fixed z-[100] top-0 start-0 w-full">
|
<div class="fixed z-[100] top-0 start-0 w-full">
|
||||||
<ControlAppBar onClose={() => goto(previousRoute)} backIcon={mdiArrowLeft}>
|
<ControlAppBar onClose={() => goto(previousRoute)} backIcon={mdiArrowLeft}>
|
||||||
<div
|
<div class="-z-[1] bg-light" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
|
||||||
class="-z-[1] bg-immich-bg dark:bg-immich-dark-bg"
|
|
||||||
style="position:absolute;top:0;left:0;right:0;bottom:0;"
|
|
||||||
></div>
|
|
||||||
<div class="w-full flex-1 ps-4">
|
<div class="w-full flex-1 ps-4">
|
||||||
<SearchBar grayTheme={false} value={terms?.query ?? ''} searchQuery={terms} />
|
<SearchBar grayTheme={false} value={terms?.query ?? ''} searchQuery={terms} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,17 +4,17 @@
|
|||||||
import IndividualSharedViewer from '$lib/components/share-page/individual-shared-viewer.svelte';
|
import IndividualSharedViewer from '$lib/components/share-page/individual-shared-viewer.svelte';
|
||||||
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
|
||||||
import ImmichLogoSmallLink from '$lib/components/shared-components/immich-logo-small-link.svelte';
|
import ImmichLogoSmallLink from '$lib/components/shared-components/immich-logo-small-link.svelte';
|
||||||
import ThemeButton from '$lib/components/shared-components/theme-button.svelte';
|
|
||||||
import PasswordField from '$lib/components/shared-components/password-field.svelte';
|
import PasswordField from '$lib/components/shared-components/password-field.svelte';
|
||||||
import { user } from '$lib/stores/user.store';
|
import ThemeButton from '$lib/components/shared-components/theme-button.svelte';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
|
||||||
import { getMySharedLink, SharedLinkType } from '@immich/sdk';
|
|
||||||
import type { PageData } from './$types';
|
|
||||||
import { setSharedLink } from '$lib/utils';
|
|
||||||
import { t } from 'svelte-i18n';
|
|
||||||
import { navigate } from '$lib/utils/navigation';
|
|
||||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||||
|
import { user } from '$lib/stores/user.store';
|
||||||
|
import { setSharedLink } from '$lib/utils';
|
||||||
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
|
import { navigate } from '$lib/utils/navigation';
|
||||||
|
import { getMySharedLink, SharedLinkType } from '@immich/sdk';
|
||||||
import { tick } from 'svelte';
|
import { tick } from 'svelte';
|
||||||
|
import { t } from 'svelte-i18n';
|
||||||
|
import type { PageData } from './$types';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
data: PageData;
|
data: PageData;
|
||||||
@ -70,7 +70,7 @@
|
|||||||
</ControlAppBar>
|
</ControlAppBar>
|
||||||
</header>
|
</header>
|
||||||
<main
|
<main
|
||||||
class="relative h-dvh overflow-hidden bg-immich-bg px-6 max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg sm:px-12 md:px-24 lg:px-40"
|
class="relative h-dvh overflow-hidden px-6 max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] sm:px-12 md:px-24 lg:px-40"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col items-center justify-center mt-20">
|
<div class="flex flex-col items-center justify-center mt-20">
|
||||||
<div class="text-2xl font-bold text-immich-primary dark:text-immich-dark-primary">{$t('password_required')}</div>
|
<div class="text-2xl font-bold text-immich-primary dark:text-immich-dark-primary">{$t('password_required')}</div>
|
||||||
|
@ -298,9 +298,7 @@
|
|||||||
<tbody class="block overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
<tbody class="block overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
||||||
{#each libraries as library, index (library.id)}
|
{#each libraries as library, index (library.id)}
|
||||||
<tr
|
<tr
|
||||||
class={`grid grid-cols-6 h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg ${
|
class="grid grid-cols-6 h-[80px] w-full place-items-center text-center dark:text-immich-dark-fg even:bg-subtle/20 odd:bg-subtle/80"
|
||||||
index % 2 == 0 ? 'bg-subtle' : 'bg-immich-bg dark:bg-immich-dark-gray/50'
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<td class="text-ellipsis px-4 text-sm">{library.name}</td>
|
<td class="text-ellipsis px-4 text-sm">{library.name}</td>
|
||||||
<td class="text-ellipsis px-4 text-sm">
|
<td class="text-ellipsis px-4 text-sm">
|
||||||
|
@ -103,13 +103,11 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
<tbody class="block w-full overflow-y-auto rounded-md border dark:border-immich-dark-gray">
|
||||||
{#if allUsers}
|
{#if allUsers}
|
||||||
{#each allUsers as immichUser, index (immichUser.id)}
|
{#each allUsers as immichUser (immichUser.id)}
|
||||||
<tr
|
<tr
|
||||||
class="flex h-[80px] overflow-hidden w-full place-items-center text-center dark:text-immich-dark-fg {immichUser.deletedAt
|
class="flex h-[80px] overflow-hidden w-full place-items-center text-center dark:text-immich-dark-fg {immichUser.deletedAt
|
||||||
? 'bg-red-300 dark:bg-red-900'
|
? 'bg-red-300 dark:bg-red-900'
|
||||||
: index % 2 == 0
|
: 'even:bg-subtle/20 odd:bg-subtle/80'}"
|
||||||
? 'bg-subtle'
|
|
||||||
: 'bg-immich-bg dark:bg-immich-dark-gray/50'}"
|
|
||||||
>
|
>
|
||||||
<td class="w-8/12 sm:w-5/12 lg:w-6/12 xl:w-4/12 2xl:w-5/12 text-ellipsis break-all px-2 text-sm"
|
<td class="w-8/12 sm:w-5/12 lg:w-6/12 xl:w-4/12 2xl:w-5/12 text-ellipsis break-all px-2 text-sm"
|
||||||
><Link href="{AppRoute.ADMIN_USERS}/{immichUser.id}">{immichUser.email}</Link></td
|
><Link href="{AppRoute.ADMIN_USERS}/{immichUser.id}">{immichUser.email}</Link></td
|
||||||
|
Loading…
x
Reference in New Issue
Block a user