mirror of
https://github.com/immich-app/immich.git
synced 2025-04-08 03:01:32 -05:00
feat(web): support long-press selection on mobile web (#16906)
* feat(web): max grid row height responsive
* also gallery-viewer
* lint
* feat(web): support long-press selection on mobile web
* use svelte-gestures
* fix test
* Bug fix
* globalThis
* format
* revert generator
* Testing
* bad merge
* Fix typo/tap on thumbnail
* feat: shrink header on small screens (#16909)
* feat(web): shrink header on small screens
* fix test
* test
* Fix test
* Revert user-page-layout chagne
* Restore icons sizes, make consistent, improve logo responsiveness
* remove 4 more pix, lint
* lint
* chore
---------
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
* Revert "Testing"
This reverts commit 442f11c9e1
.
---------
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
parent
a651a4bf0e
commit
4a0045db44
23 changed files with 201 additions and 61 deletions
|
@ -70,6 +70,7 @@
|
|||
font-family: 'Overpass', sans-serif;
|
||||
/* Used by layouts to ensure proper spacing between navbar and content */
|
||||
--navbar-height: calc(theme(spacing.18) + 4px);
|
||||
--navbar-height-md: calc(theme(spacing.18) + 4px - 14px);
|
||||
}
|
||||
|
||||
:root.dark {
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
let { sharedLink, user = undefined }: Props = $props();
|
||||
|
||||
const album = sharedLink.album as AlbumResponseDto;
|
||||
let innerWidth: number = $state(0);
|
||||
|
||||
let { isViewing: showAssetViewer } = assetViewingStore;
|
||||
|
||||
|
@ -56,7 +55,6 @@
|
|||
}
|
||||
},
|
||||
}}
|
||||
bind:innerWidth
|
||||
/>
|
||||
|
||||
<header>
|
||||
|
@ -74,7 +72,7 @@
|
|||
{:else}
|
||||
<ControlAppBar showBackButton={false}>
|
||||
{#snippet leading()}
|
||||
<ImmichLogoSmallLink width={innerWidth} />
|
||||
<ImmichLogoSmallLink />
|
||||
{/snippet}
|
||||
|
||||
{#snippet trailing()}
|
||||
|
@ -100,7 +98,9 @@
|
|||
{/if}
|
||||
</header>
|
||||
|
||||
<main class="relative h-screen overflow-hidden bg-immich-bg px-6 pt-[var(--navbar-height)] dark:bg-immich-dark-bg">
|
||||
<main
|
||||
class="relative h-screen overflow-hidden bg-immich-bg px-6 max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg"
|
||||
>
|
||||
<AssetGrid enableRouting={true} {album} {assetStore} {assetInteraction}>
|
||||
<section class="pt-8 md:pt-24">
|
||||
<!-- ALBUM TITLE -->
|
||||
|
|
|
@ -3,6 +3,23 @@ import Thumbnail from '$lib/components/assets/thumbnail/thumbnail.svelte';
|
|||
import { assetFactory } from '@test-data/factories/asset-factory';
|
||||
import { fireEvent, render, screen } from '@testing-library/svelte';
|
||||
|
||||
vi.hoisted(() => {
|
||||
Object.defineProperty(globalThis, 'matchMedia', {
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
value: vi.fn().mockImplementation((query) => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: vi.fn(), // deprecated
|
||||
removeListener: vi.fn(), // deprecated
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener: vi.fn(),
|
||||
dispatchEvent: vi.fn(),
|
||||
})),
|
||||
});
|
||||
});
|
||||
|
||||
describe('Thumbnail component', () => {
|
||||
beforeAll(() => {
|
||||
vi.stubGlobal('IntersectionObserver', getIntersectionObserverMock());
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { press, tap } from 'svelte-gestures';
|
||||
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { ProjectionType } from '$lib/constants';
|
||||
import { getAssetThumbnailUrl, isSharedLink } from '$lib/utils';
|
||||
|
@ -23,6 +25,7 @@
|
|||
import { currentUrlReplaceAssetId } from '$lib/utils/navigation';
|
||||
import { TUNABLES } from '$lib/utils/tunables';
|
||||
import { thumbhash } from '$lib/actions/thumbhash';
|
||||
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
||||
|
||||
interface Props {
|
||||
asset: AssetResponseDto;
|
||||
|
@ -71,6 +74,7 @@
|
|||
IMAGE_THUMBNAIL: { THUMBHASH_FADE_DURATION },
|
||||
} = TUNABLES;
|
||||
|
||||
let isTouchDevice = $derived(mobileDevice.hoverNone);
|
||||
let focussableElement: HTMLElement | undefined = $state();
|
||||
let mouseOver = $state(false);
|
||||
let loaded = $state(false);
|
||||
|
@ -100,6 +104,9 @@
|
|||
onClick?.($state.snapshot(asset));
|
||||
};
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
if (isTouchDevice) {
|
||||
return;
|
||||
}
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
return;
|
||||
}
|
||||
|
@ -109,6 +116,9 @@
|
|||
};
|
||||
|
||||
const onMouseEnter = () => {
|
||||
if (isTouchDevice) {
|
||||
return;
|
||||
}
|
||||
mouseOver = true;
|
||||
onMouseEvent?.({ isMouseOver: true, selectedGroupIndex: groupIndex });
|
||||
};
|
||||
|
@ -138,6 +148,13 @@
|
|||
|
||||
<!-- svelte queries for all links on afterNavigate, leading to performance problems in asset-grid which updates
|
||||
the navigation url on scroll. Replace this with button for now. -->
|
||||
|
||||
<!-- as of iOS17, there is a preference for long press speed, which is not available for mobile web.
|
||||
The defaults are as follows:
|
||||
fast: 200ms
|
||||
default: 500ms
|
||||
slow: ??ms
|
||||
-->
|
||||
<div
|
||||
class="group"
|
||||
style:width="{width}px"
|
||||
|
@ -146,6 +163,10 @@
|
|||
class:cursor-pointer={!disabled}
|
||||
onmouseenter={onMouseEnter}
|
||||
onmouseleave={onMouseLeave}
|
||||
use:press={() => ({ timeframe: 350, triggerBeforeFinished: true })}
|
||||
use:tap={() => ({ timeframe: 350 })}
|
||||
onpress={(evt) => (evt.detail.pointerType === 'mouse' ? void 0 : onSelect?.($state.snapshot(asset)))}
|
||||
ontap={(evt) => (evt.detail.pointerType === 'mouse' ? void 0 : callClickHandlers())}
|
||||
onkeydown={(evt) => {
|
||||
if (evt.key === 'Enter') {
|
||||
callClickHandlers();
|
||||
|
@ -161,7 +182,7 @@
|
|||
onfocus={handleFocus}
|
||||
data-testid="container-with-tabindex"
|
||||
>
|
||||
{#if mouseOver && !disableMouseOver}
|
||||
{#if !isTouchDevice && mouseOver && !disableMouseOver}
|
||||
<!-- lazy show the url on mouse over-->
|
||||
<a
|
||||
class="absolute z-30 {className} top-[41px]"
|
||||
|
@ -208,11 +229,12 @@
|
|||
class:rounded-xl={selected}
|
||||
>
|
||||
<!-- Gradient overlay on hover -->
|
||||
<div
|
||||
class="absolute z-10 h-full w-full bg-gradient-to-b from-black/25 via-[transparent_25%] opacity-0 transition-opacity group-hover:opacity-100"
|
||||
class:rounded-xl={selected}
|
||||
></div>
|
||||
|
||||
{#if !isTouchDevice}
|
||||
<div
|
||||
class="absolute z-10 h-full w-full bg-gradient-to-b from-black/25 via-[transparent_25%] opacity-0 transition-opacity group-hover:opacity-100"
|
||||
class:rounded-xl={selected}
|
||||
></div>
|
||||
{/if}
|
||||
<!-- Outline on focus -->
|
||||
<div
|
||||
class="absolute size-full group-focus-visible:outline outline-4 -outline-offset-4 outline-immich-primary"
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<section class="bg-immich-bg dark:bg-immich-dark-bg">
|
||||
<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">
|
||||
<ImmichLogo width="55%" />
|
||||
<ImmichLogo class="h-[50px]" />
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
</header>
|
||||
<main
|
||||
tabindex="-1"
|
||||
class="relative grid h-screen grid-cols-[theme(spacing.18)_auto] overflow-hidden bg-immich-bg pt-[var(--navbar-height)] dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
|
||||
class="relative grid h-screen grid-cols-[theme(spacing.18)_auto] overflow-hidden bg-immich-bg max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
|
||||
>
|
||||
{#if sidebar}{@render sidebar()}{:else if admin}
|
||||
<AdminSideBar />
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</script>
|
||||
|
||||
<OnboardingCard>
|
||||
<ImmichLogo noText width="75" />
|
||||
<ImmichLogo noText class="h-[50px]" />
|
||||
<p class="font-medium text-6xl my-6 text-immich-primary dark:text-immich-dark-primary">
|
||||
{$t('onboarding_welcome_user', { values: { user: $user.name } })}
|
||||
</p>
|
||||
|
|
|
@ -136,7 +136,12 @@
|
|||
</div>
|
||||
|
||||
<!-- Image grid -->
|
||||
<div class="relative overflow-clip" style:height={dateGroup.height + 'px'} style:width={dateGroup.width + 'px'}>
|
||||
<div
|
||||
data-image-grid
|
||||
class="relative overflow-clip"
|
||||
style:height={dateGroup.height + 'px'}
|
||||
style:width={dateGroup.width + 'px'}
|
||||
>
|
||||
{#each filterIntersecting(dateGroup.intersetingAssets) as intersectingAsset (intersectingAsset.id)}
|
||||
{@const position = intersectingAsset.position!}
|
||||
{@const asset = intersectingAsset.asset!}
|
||||
|
@ -180,4 +185,7 @@
|
|||
section {
|
||||
contain: layout paint style;
|
||||
}
|
||||
[data-image-grid] {
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
const viewport: Viewport = $state({ width: 0, height: 0 });
|
||||
const assetInteraction = new AssetInteraction();
|
||||
let innerWidth: number = $state(0);
|
||||
|
||||
let assets = $derived(sharedLink.assets);
|
||||
|
||||
|
@ -75,8 +74,6 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth />
|
||||
|
||||
<section class="bg-immich-bg dark:bg-immich-dark-bg">
|
||||
{#if assetInteraction.selectionActive}
|
||||
<AssetSelectControlBar
|
||||
|
@ -94,7 +91,7 @@
|
|||
{:else}
|
||||
<ControlAppBar onClose={() => goto(AppRoute.PHOTOS)} backIcon={mdiArrowLeft} showBackButton={false}>
|
||||
{#snippet leading()}
|
||||
<ImmichLogoSmallLink width={innerWidth} />
|
||||
<ImmichLogoSmallLink />
|
||||
{/snippet}
|
||||
|
||||
{#snippet trailing()}
|
||||
|
|
|
@ -165,7 +165,7 @@
|
|||
transition:fade={{ duration: 250 }}
|
||||
ondragover={onDragOver}
|
||||
>
|
||||
<ImmichLogo noText class="m-16 w-48 animate-bounce" />
|
||||
<ImmichLogo noText class="m-16 h-48 animate-bounce" />
|
||||
<div class="text-2xl">{$t('drop_files_to_upload')}</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
<script lang="ts">
|
||||
import ImmichLogo from '$lib/components/shared-components/immich-logo.svelte';
|
||||
|
||||
interface Props {
|
||||
width: number;
|
||||
}
|
||||
|
||||
let { width }: Props = $props();
|
||||
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
||||
</script>
|
||||
|
||||
<a data-sveltekit-preload-data="hover" class="ml-4" href="/">
|
||||
<ImmichLogo class="h-[24px] w-[24px] max-w-none md:w-auto md:h-10 md:max-w-full" noText={width < 768} />
|
||||
<ImmichLogo class="h-[50px] max-w-none md:w-auto md:max-w-full" noText={mobileDevice.maxMd} />
|
||||
</a>
|
||||
|
|
|
@ -1,27 +1,115 @@
|
|||
<script lang="ts">
|
||||
import { Theme } from '$lib/constants';
|
||||
import { colorTheme } from '$lib/stores/preferences.store';
|
||||
import { immichLogo, immichLogoInlineDark, immichLogoInlineLight, immichLogoJson } from '@immich/ui';
|
||||
import { DateTime } from 'luxon';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { HTMLImgAttributes } from 'svelte/elements';
|
||||
|
||||
interface Props extends HTMLImgAttributes {
|
||||
noText?: boolean;
|
||||
draggable?: boolean;
|
||||
class?: string | undefined;
|
||||
}
|
||||
|
||||
let { noText = false, draggable = false, ...rest }: Props = $props();
|
||||
|
||||
const logoUrl = $derived(
|
||||
noText ? immichLogo : $colorTheme.value == Theme.LIGHT ? immichLogoInlineLight : immichLogoInlineDark,
|
||||
);
|
||||
|
||||
const today = DateTime.now().toLocal();
|
||||
let { noText = false, class: cssClass }: Props = $props();
|
||||
const viewBox = $derived(`0 0 ${noText ? '260' : '792'} 266.25`);
|
||||
</script>
|
||||
|
||||
{#if today.month === 4 && today.day === 1}
|
||||
<img src="data:image/png;base64, {immichLogoJson.content}" alt={$t('immich_logo')} class="h-14" {draggable} />
|
||||
{:else}
|
||||
<img src={logoUrl} alt={$t('immich_logo')} {draggable} {...rest} />
|
||||
{/if}
|
||||
<svg {viewBox} class={cssClass}>
|
||||
<title>{$t('immich_logo')}</title>
|
||||
{#if !noText}
|
||||
<g class="st0 dark:fill-[#accbfa]">
|
||||
<path
|
||||
d="M268.73,63.18c6.34,0,11.52,5.18,11.52,11.35c0,6.34-5.18,11.35-11.52,11.35s-11.69-5.01-11.69-11.35
|
||||
C257.04,68.36,262.39,63.18,268.73,63.18z M258.88,122.45c0-3.01-0.67-7.85-0.67-10.68c0-6.01,4.67-10.68,10.52-10.68
|
||||
c5.84,0,10.52,4.67,10.52,10.68c0,2.84-0.83,7.68-0.83,10.68v38.73c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.67,10.68-10.52,10.68
|
||||
c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68V122.45z"
|
||||
/>
|
||||
<path
|
||||
d="M394.28,171.87c0-2.84,0.83-7.68,0.83-10.68V132.3c0-10.18-5.34-16.86-14.52-16.86c-6.01,0-11.35,3-14.86,8.85
|
||||
c0.33,1.84,0.5,3.67,0.5,5.68v31.22c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.67,10.68-10.68,10.68c-5.51,0-10.35-4.67-10.35-10.68
|
||||
c0-2.84,0.83-7.68,0.83-10.68V131.8c0-3.17-0.5-6.01-1.67-8.51c-2.17-4.84-6.51-7.85-12.52-7.85c-6.18,0-11.19,3.17-14.86,8.85
|
||||
v36.9c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68
|
||||
v-38.57c0-3.01-1.5-8.35-1.5-10.85c0-6.01,4.34-10.68,10.18-10.68c5.51,0,8.68,3.67,9.68,8.51c5.01-6.68,12.02-10.85,21.2-10.85
|
||||
c10.85,0,18.7,5.18,23.54,13.52c5.51-8.68,13.52-13.52,23.54-13.52c16.86,0,29.72,12.19,29.72,31.72v30.72
|
||||
c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.51,10.68-10.52,10.68C399.12,182.55,394.28,177.88,394.28,171.87z"
|
||||
/>
|
||||
<path
|
||||
d="M528.5,171.87c0-2.84,0.83-7.68,0.83-10.68V132.3c0-10.18-5.34-16.86-14.52-16.86c-6.01,0-11.35,3-14.86,8.85
|
||||
c0.33,1.84,0.5,3.67,0.5,5.68v31.22c0,3.01,0.84,7.85,0.84,10.68c0,6.01-4.67,10.68-10.68,10.68c-5.51,0-10.35-4.67-10.35-10.68
|
||||
c0-2.84,0.84-7.68,0.84-10.68V131.8c0-3.17-0.5-6.01-1.67-8.51c-2.17-4.84-6.51-7.85-12.52-7.85c-6.18,0-11.19,3.17-14.86,8.85
|
||||
v36.9c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68c-5.84,0-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68
|
||||
v-38.57c0-3.01-1.5-8.35-1.5-10.85c0-6.01,4.34-10.68,10.18-10.68c5.51,0,8.68,3.67,9.68,8.51c5.01-6.68,12.02-10.85,21.2-10.85
|
||||
c10.85,0,18.7,5.18,23.54,13.52c5.51-8.68,13.52-13.52,23.54-13.52c16.86,0,29.72,12.19,29.72,31.72v30.72
|
||||
c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.51,10.68-10.52,10.68C533.35,182.55,528.5,177.88,528.5,171.87z"
|
||||
/>
|
||||
<path
|
||||
d="M576.92,63.18c6.34,0,11.52,5.18,11.52,11.35c0,6.34-5.18,11.35-11.52,11.35s-11.69-5.01-11.69-11.35
|
||||
C565.23,68.36,570.57,63.18,576.92,63.18z M567.07,122.45c0-3.01-0.67-7.85-0.67-10.68c0-6.01,4.67-10.68,10.52-10.68
|
||||
s10.52,4.67,10.52,10.68c0,2.84-0.84,7.68-0.84,10.68v38.73c0,3.01,0.84,7.85,0.84,10.68c0,6.01-4.67,10.68-10.52,10.68
|
||||
s-10.52-4.67-10.52-10.68c0-2.84,0.67-7.68,0.67-10.68V122.45z"
|
||||
/>
|
||||
<path
|
||||
d="M601.79,141.31c0-23.54,14.69-42.57,39.07-42.57c12.86,0,24.71,5.84,30.05,14.53c2,3.17,2.34,5.01,2.34,6.51
|
||||
c0,5.18-4.01,9.52-9.85,9.52c-3.84,0-7.34-2.17-8.85-6.01c-2.34-5.18-6.85-8.18-13.69-8.18c-12.86,0-20.03,11.52-20.03,26.04
|
||||
c0,14.69,7.51,26.04,20.53,26.04c7.01,0,12.02-2.5,14.36-7.68c1.67-3.51,4.84-6.51,9.18-6.51c6.01,0,9.68,4.17,9.68,9.35
|
||||
c0,2.5-1,5.51-3.17,8.35c-5.51,7.35-15.86,13.19-30.05,13.19C616.32,183.89,601.79,165.19,601.79,141.31z"
|
||||
/>
|
||||
<path
|
||||
d="M737.69,171.87c0-2.84,0.67-7.68,0.67-10.68v-28.55c0-10.18-5.68-17.2-15.36-17.2
|
||||
c-6.68,0-12.35,3.17-16.03,8.35v37.4c0,3.01,0.67,7.85,0.67,10.68c0,6.01-4.67,10.68-10.52,10.68s-10.52-4.67-10.52-10.68
|
||||
c0-2.84,0.84-7.68,0.84-10.68v-80.8c0-3.01-0.84-7.85-0.84-10.68c0-6.01,4.84-10.68,10.52-10.68c5.84,0,10.52,4.67,10.52,10.68
|
||||
c0,2.84-0.67,7.68-0.67,10.68v27.21c5.01-5.51,12.19-8.85,21.37-8.85c17.2,0,29.55,12.86,29.55,31.22v31.22
|
||||
c0,3.01,0.83,7.85,0.83,10.68c0,6.01-4.84,10.68-10.52,10.68C742.36,182.55,737.69,177.88,737.69,171.87z"
|
||||
/>
|
||||
</g>
|
||||
{/if}
|
||||
<g>
|
||||
<path
|
||||
class="st1"
|
||||
d="M114.82,96.21c11.92,10.55,21.52,21.86,27.7,32.52c10.62-18.99,17.71-41.55,17.8-55.92c0-0.1,0-0.19,0-0.28
|
||||
c0-21.26-21.21-29.54-39.48-29.54s-39.48,8.28-39.48,29.54c0,0.29,0,0.68,0,1.15C91.54,78.2,103.61,86.29,114.82,96.21z"
|
||||
/>
|
||||
<path
|
||||
class="st2"
|
||||
d="M49.8,154.19c7.45-8.29,18.88-17.27,31.77-24.86c13.72-8.07,27.44-13.71,39.49-16.3
|
||||
c-14.78-15.96-34.04-29.68-47.68-34.21c-0.1-0.03-0.18-0.06-0.27-0.09c-20.22-6.57-34.65,11.05-40.3,28.42s-4.33,40.11,15.89,46.68
|
||||
C48.99,153.93,49.35,154.05,49.8,154.19z"
|
||||
/>
|
||||
<path
|
||||
class="st3"
|
||||
d="M209.07,106.86c-5.65-17.38-20.07-34.99-40.3-28.42c-0.28,0.09-0.65,0.21-1.09,0.35
|
||||
c-1.16,11.08-5.12,25.07-11.09,38.79c-6.35,14.6-14.14,27.23-22.36,36.39c21.34,4.23,44.99,4,58.68-0.35
|
||||
c0.1-0.03,0.19-0.06,0.27-0.09C213.4,146.97,214.71,124.24,209.07,106.86z"
|
||||
/>
|
||||
<path
|
||||
class="st4"
|
||||
d="M102.8,171.18c-3.44-15.54-4.56-30.34-3.3-42.59c-19.75,9.12-38.75,23.2-47.27,34.78
|
||||
c-0.06,0.08-0.11,0.16-0.16,0.23c-12.5,17.2-0.2,36.37,14.58,47.11s36.81,16.51,49.31-0.69c0.17-0.24,0.4-0.55,0.68-0.93
|
||||
C111.05,199.44,106.04,185.79,102.8,171.18z"
|
||||
/>
|
||||
<path
|
||||
class="st5"
|
||||
d="M189.48,162.49c-10.9,2.33-25.42,2.88-40.32,1.44c-15.84-1.53-30.26-5.03-41.52-10.02
|
||||
c2.57,21.6,10.09,44.02,18.47,55.7c0.06,0.08,0.11,0.16,0.16,0.23c12.5,17.2,34.52,11.43,49.31,0.69
|
||||
c14.78-10.74,27.08-29.9,14.58-47.11C189.99,163.18,189.76,162.86,189.48,162.49z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
<style>
|
||||
.st0 {
|
||||
fill: #4251b0;
|
||||
}
|
||||
.st1 {
|
||||
fill: #fa2921;
|
||||
}
|
||||
.st2 {
|
||||
fill: #ed79b5;
|
||||
}
|
||||
.st3 {
|
||||
fill: #ffb400;
|
||||
}
|
||||
.st4 {
|
||||
fill: #1e83f7;
|
||||
}
|
||||
.st5 {
|
||||
fill: #18c249;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<div class="flex place-items-center justify-between px-5 pb-3">
|
||||
<div class="flex gap-2 place-items-center">
|
||||
{#if showLogo}
|
||||
<ImmichLogo noText={true} width={32} />
|
||||
<ImmichLogo noText={true} class="h-[40px]" />
|
||||
{:else if icon}
|
||||
<Icon path={icon} size={24} ariaHidden={true} class="text-immich-primary dark:text-immich-dark-primary" />
|
||||
{/if}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
import ThemeButton from '../theme-button.svelte';
|
||||
import UserAvatar from '../user-avatar.svelte';
|
||||
import AccountInfoPanel from './account-info-panel.svelte';
|
||||
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
||||
|
||||
interface Props {
|
||||
showUploadButton?: boolean;
|
||||
|
@ -50,13 +51,16 @@
|
|||
<HelpAndFeedbackModal onClose={() => (shouldShowHelpPanel = false)} {info} />
|
||||
{/if}
|
||||
|
||||
<section id="dashboard-navbar" class="fixed z-[900] h-[var(--navbar-height)] w-screen text-sm">
|
||||
<section
|
||||
id="dashboard-navbar"
|
||||
class="fixed z-[900] max-md:h-[var(--navbar-height-md)] h-[var(--navbar-height)] w-screen text-sm"
|
||||
>
|
||||
<SkipLink text={$t('skip_to_content')} />
|
||||
<div
|
||||
class="grid h-full grid-cols-[theme(spacing.18)_auto] items-center border-b bg-immich-bg py-2 dark:border-b-immich-dark-gray dark:bg-immich-dark-bg md:grid-cols-[theme(spacing.64)_auto]"
|
||||
>
|
||||
<a data-sveltekit-preload-data="hover" class="ml-4" href={AppRoute.PHOTOS}>
|
||||
<ImmichLogo width="55%" noText={innerWidth < 768} />
|
||||
<ImmichLogo class="max-md:h-[48px] h-[50px]" noText={mobileDevice.maxMd} />
|
||||
</a>
|
||||
<div class="flex justify-between gap-4 lg:gap-8 pr-6">
|
||||
<div class="hidden w-full max-w-5xl flex-1 tall:pl-0 sm:block">
|
||||
|
@ -71,7 +75,7 @@
|
|||
color="secondary"
|
||||
shape="round"
|
||||
variant="ghost"
|
||||
size="large"
|
||||
size="medium"
|
||||
icon={mdiMagnify}
|
||||
href={AppRoute.SEARCH}
|
||||
id="search-button"
|
||||
|
@ -95,7 +99,7 @@
|
|||
color="secondary"
|
||||
shape="round"
|
||||
variant="ghost"
|
||||
size="large"
|
||||
size="medium"
|
||||
onclick={onUploadClick}
|
||||
title={$t('upload')}
|
||||
aria-label={$t('upload')}
|
||||
|
@ -115,7 +119,7 @@
|
|||
shape="round"
|
||||
color="secondary"
|
||||
variant="ghost"
|
||||
size="large"
|
||||
size="medium"
|
||||
title={$t('support_and_feedback')}
|
||||
icon={mdiHelpCircleOutline}
|
||||
onclick={() => (shouldShowHelpPanel = !shouldShowHelpPanel)}
|
||||
|
|
|
@ -209,7 +209,7 @@
|
|||
type="text"
|
||||
name="q"
|
||||
id="main-search-bar"
|
||||
class="w-full transition-all border-2 px-14 py-4 text-immich-fg/75 dark:text-immich-dark-fg
|
||||
class="w-full transition-all border-2 px-14 py-4 max-md:py-2 text-immich-fg/75 dark:text-immich-dark-fg
|
||||
{grayTheme ? 'dark:bg-immich-dark-gray' : 'dark:bg-immich-dark-bg'}
|
||||
{showSuggestions && isSearchSuggestions ? 'rounded-t-3xl' : 'rounded-3xl bg-gray-200'}
|
||||
{$isSearchEnabled && !showFilter ? 'border-gray-200 dark:border-gray-700 bg-white' : 'border-transparent'}"
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
<div class="flex justify-between w-full place-items-center place-content-center">
|
||||
<div class="flex place-items-center place-content-center gap-1">
|
||||
<div class="h-6 w-6">
|
||||
<ImmichLogo noText />
|
||||
<ImmichLogo noText class="h-[24px]" />
|
||||
</div>
|
||||
<p class="flex text-immich-primary dark:text-immich-dark-primary font-medium">
|
||||
{$t('purchase_button_buy_immich')}
|
||||
|
@ -132,7 +132,7 @@
|
|||
>
|
||||
<div class="flex justify-between place-items-center">
|
||||
<div class="h-10 w-10">
|
||||
<ImmichLogo noText />
|
||||
<ImmichLogo noText class="h-[32px]" />
|
||||
</div>
|
||||
<CircleIconButton
|
||||
icon={mdiClose}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<section
|
||||
id="sidebar"
|
||||
tabindex="-1"
|
||||
class="immich-scrollbar group relative z-10 flex w-18 flex-col gap-1 overflow-y-auto bg-immich-bg pt-8 transition-all duration-200 dark:bg-immich-dark-bg hover:sm:w-64 hover:sm:border-r hover:sm:pr-6 hover:sm:shadow-2xl hover:sm:dark:border-r-immich-dark-gray md:w-64 md:pr-6 hover:md:border-none hover:md:shadow-none"
|
||||
class="immich-scrollbar group relative z-10 flex w-18 flex-col gap-1 overflow-y-auto bg-immich-bg pt-8 max-md:pt-16 transition-all duration-200 dark:bg-immich-dark-bg hover:sm:w-64 hover:sm:border-r hover:sm:pr-6 hover:sm:shadow-2xl hover:sm:dark:border-r-immich-dark-gray md:w-64 md:pr-6 hover:md:border-none hover:md:shadow-none"
|
||||
>
|
||||
{@render children?.()}
|
||||
</section>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
class="flex gap-1 mt-2 place-items-center dark:bg-immich-dark-primary/10 bg-gray-200/50 p-2 rounded-lg bg-clip-padding border border-transparent relative supporter-effect"
|
||||
class:place-content-center={centered}
|
||||
>
|
||||
<ImmichLogo class={logoSize === 'sm' ? 'size-6' : 'size-8'} noText />
|
||||
<ImmichLogo class={logoSize === 'sm' ? 'h-6' : 'h-8'} noText />
|
||||
<p class="dark:text-gray-100">{$t('purchase_account_info')}</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import { MediaQuery } from 'svelte/reactivity';
|
||||
|
||||
const hoverNone = new MediaQuery('hover: none');
|
||||
const maxMd = new MediaQuery('max-width: 767px');
|
||||
|
||||
export const mobileDevice = {
|
||||
get hoverNone() {
|
||||
return hoverNone.current;
|
||||
},
|
||||
get maxMd() {
|
||||
return maxMd.current;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -603,7 +603,9 @@
|
|||
{/if}
|
||||
{/if}
|
||||
|
||||
<main class="relative h-screen overflow-hidden bg-immich-bg px-6 pt-[var(--navbar-height)] dark:bg-immich-dark-bg">
|
||||
<main
|
||||
class="relative h-screen overflow-hidden bg-immich-bg px-6 max-md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg"
|
||||
>
|
||||
<AssetGrid
|
||||
enableRouting={viewMode === AlbumPageViewMode.SELECT_ASSETS ? false : true}
|
||||
{album}
|
||||
|
|
|
@ -486,7 +486,7 @@
|
|||
</header>
|
||||
|
||||
<main
|
||||
class="relative h-screen overflow-hidden bg-immich-bg tall:ml-4 pt-[var(--navbar-height)] dark:bg-immich-dark-bg"
|
||||
class="relative h-screen overflow-hidden bg-immich-bg tall:ml-4 md:pt-[var(--navbar-height-md)] pt-[var(--navbar-height)] dark:bg-immich-dark-bg"
|
||||
use:scrollMemoryClearer={{
|
||||
routeStartsWith: AppRoute.PEOPLE,
|
||||
beforeClear: () => {
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
let { title, description } = $state(meta);
|
||||
let isOwned = $derived($user ? $user.id === sharedLink?.userId : false);
|
||||
let password = $state('');
|
||||
let innerWidth: number = $state(0);
|
||||
|
||||
const handlePasswordSubmit = async () => {
|
||||
try {
|
||||
|
@ -54,8 +53,6 @@
|
|||
};
|
||||
</script>
|
||||
|
||||
<svelte:window bind:innerWidth />
|
||||
|
||||
<svelte:head>
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
|
@ -64,7 +61,7 @@
|
|||
<header>
|
||||
<ControlAppBar showBackButton={false}>
|
||||
{#snippet leading()}
|
||||
<ImmichLogoSmallLink width={innerWidth} />
|
||||
<ImmichLogoSmallLink />
|
||||
{/snippet}
|
||||
|
||||
{#snippet trailing()}
|
||||
|
@ -73,7 +70,7 @@
|
|||
</ControlAppBar>
|
||||
</header>
|
||||
<main
|
||||
class="relative h-screen overflow-hidden bg-immich-bg px-6 pt-[var(--navbar-height)] dark:bg-immich-dark-bg sm:px-12 md:px-24 lg:px-40"
|
||||
class="relative h-screen 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"
|
||||
>
|
||||
<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>
|
||||
|
|
|
@ -50,6 +50,11 @@ export default {
|
|||
},
|
||||
screens: {
|
||||
tall: { raw: '(min-height: 800px)' },
|
||||
'max-2xl': { max: '1535px' },
|
||||
'max-xl': { max: '1279px' },
|
||||
'max-lg': { max: '1023px' },
|
||||
'max-md': { max: '767px' },
|
||||
'max-sm': { max: '639px' },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue