mirror of
https://github.com/immich-app/immich.git
synced 2025-01-07 00:50:23 -05:00
feat: zooming and virtual keyboard working for iPadOS/Safari
This commit is contained in:
parent
fdd0729c4a
commit
cac29bac0d
1 changed files with 25 additions and 14 deletions
|
@ -21,7 +21,7 @@
|
|||
import { fly } from 'svelte/transition';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { mdiMagnify, mdiUnfoldMoreHorizontal, mdiClose } from '@mdi/js';
|
||||
import { createEventDispatcher, onDestroy, onMount, tick } from 'svelte';
|
||||
import { createEventDispatcher, onMount, tick } from 'svelte';
|
||||
import type { FormEventHandler } from 'svelte/elements';
|
||||
import { shortcuts } from '$lib/actions/shortcut';
|
||||
import { focusOutside } from '$lib/actions/focus-outside';
|
||||
|
@ -52,6 +52,7 @@
|
|||
let selectedIndex: number | undefined;
|
||||
let optionRefs: HTMLElement[] = [];
|
||||
let input: HTMLInputElement;
|
||||
let dropdown: HTMLUListElement;
|
||||
let bounds: DOMRect | undefined;
|
||||
let scrollableAncestor: Element | null;
|
||||
let dropdownDirection: 'bottom' | 'top' = 'bottom';
|
||||
|
@ -81,11 +82,15 @@
|
|||
observer.observe(input);
|
||||
scrollableAncestor = input.closest('.overflow-y-auto, .overflow-y-scroll');
|
||||
scrollableAncestor?.addEventListener('scroll', onPositionChange);
|
||||
});
|
||||
window.visualViewport?.addEventListener('resize', onPositionChange);
|
||||
window.visualViewport?.addEventListener('scroll', onPositionChange);
|
||||
|
||||
onDestroy(() => {
|
||||
scrollableAncestor?.removeEventListener('scroll', onPositionChange);
|
||||
observer.disconnect();
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
scrollableAncestor?.removeEventListener('scroll', onPositionChange);
|
||||
window.visualViewport?.removeEventListener('resize', onPositionChange);
|
||||
window.visualViewport?.removeEventListener('scroll', onPositionChange);
|
||||
};
|
||||
});
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
|
@ -155,21 +160,28 @@
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const viewportHeight = window.innerHeight;
|
||||
const vv = window.visualViewport;
|
||||
const viewportHeight = vv?.height || 0;
|
||||
const left = boundary.left + (vv?.offsetLeft || 0);
|
||||
const offsetTop = vv?.offsetTop || 0;
|
||||
|
||||
if (dropdownDirection === 'top') {
|
||||
const dropdownHeight = dropdown?.clientHeight || 0;
|
||||
const availableHeight = boundary.top - dropdownOffset;
|
||||
const adjustTop = Math.max(availableHeight - dropdownHeight, 0);
|
||||
return {
|
||||
bottom: `${viewportHeight - boundary.top}px`,
|
||||
left: `${boundary.left}px`,
|
||||
top: `${dropdownOffset + offsetTop + adjustTop}px`,
|
||||
left: `${left}px`,
|
||||
width: `${boundary.width}px`,
|
||||
maxHeight: maxHeight(boundary.top - dropdownOffset),
|
||||
maxHeight: maxHeight(availableHeight),
|
||||
};
|
||||
}
|
||||
|
||||
const top = boundary.bottom + offsetTop;
|
||||
const availableHeight = viewportHeight - boundary.bottom;
|
||||
return {
|
||||
top: `${boundary.bottom}px`,
|
||||
left: `${boundary.left}px`,
|
||||
top: `${top}px`,
|
||||
left: `${left}px`,
|
||||
width: `${boundary.width}px`,
|
||||
maxHeight: maxHeight(availableHeight - dropdownOffset),
|
||||
};
|
||||
|
@ -191,7 +203,7 @@
|
|||
return 'bottom';
|
||||
}
|
||||
|
||||
const viewportHeight = window.innerHeight;
|
||||
const viewportHeight = window.visualViewport?.height || 0;
|
||||
const heightBelow = viewportHeight - boundary.bottom;
|
||||
const heightAbove = boundary.top;
|
||||
|
||||
|
@ -201,7 +213,6 @@
|
|||
const getInputPosition = () => input?.getBoundingClientRect();
|
||||
</script>
|
||||
|
||||
<svelte:window on:resize={onPositionChange} />
|
||||
<label class="immich-form-label" class:sr-only={hideLabel} for={inputId}>{label}</label>
|
||||
<div
|
||||
class="relative w-full dark:text-gray-300 text-gray-700 text-base"
|
||||
|
@ -308,11 +319,11 @@
|
|||
class:shadow={dropdownDirection === 'bottom'}
|
||||
class:border={isOpen}
|
||||
style:top={position?.top}
|
||||
style:bottom={position?.bottom}
|
||||
style:left={position?.left}
|
||||
style:width={position?.width}
|
||||
style:max-height={position?.maxHeight}
|
||||
tabindex="-1"
|
||||
bind:this={dropdown}
|
||||
>
|
||||
{#if isOpen}
|
||||
{#if filteredOptions.length === 0}
|
||||
|
|
Loading…
Reference in a new issue