mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
fix(web): timeline and asset viewer RTL support (#26513)
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
|
import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte';
|
||||||
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
|
||||||
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte';
|
||||||
|
import { languageManager } from '$lib/managers/language-manager.svelte';
|
||||||
import { Route } from '$lib/route';
|
import { Route } from '$lib/route';
|
||||||
import { getGlobalActions } from '$lib/services/app.service';
|
import { getGlobalActions } from '$lib/services/app.service';
|
||||||
import { getAssetActions, handleReplaceAsset } from '$lib/services/asset.service';
|
import { getAssetActions, handleReplaceAsset } from '$lib/services/asset.service';
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
import { ActionButton, CommandPaletteDefaultProvider, type ActionItem } from '@immich/ui';
|
import { ActionButton, CommandPaletteDefaultProvider, type ActionItem } from '@immich/ui';
|
||||||
import {
|
import {
|
||||||
mdiArrowLeft,
|
mdiArrowLeft,
|
||||||
|
mdiArrowRight,
|
||||||
mdiCompare,
|
mdiCompare,
|
||||||
mdiDotsVertical,
|
mdiDotsVertical,
|
||||||
mdiImageSearch,
|
mdiImageSearch,
|
||||||
@@ -84,7 +86,7 @@
|
|||||||
const Close: ActionItem = $derived({
|
const Close: ActionItem = $derived({
|
||||||
title: $t('go_back'),
|
title: $t('go_back'),
|
||||||
type: $t('assets'),
|
type: $t('assets'),
|
||||||
icon: mdiArrowLeft,
|
icon: languageManager.rtl ? mdiArrowRight : mdiArrowLeft,
|
||||||
$if: () => !!onClose,
|
$if: () => !!onClose,
|
||||||
onAction: () => onClose?.(),
|
onAction: () => onClose?.(),
|
||||||
shortcuts: [{ key: 'Escape' }],
|
shortcuts: [{ key: 'Escape' }],
|
||||||
|
|||||||
@@ -134,7 +134,7 @@
|
|||||||
></div>
|
></div>
|
||||||
{/if}
|
{/if}
|
||||||
</Button>
|
</Button>
|
||||||
<span class="text-sm text-white text-left">{ratio.label}</span>
|
<span class="text-sm text-white">{ratio.label}</span>
|
||||||
</HStack>
|
</HStack>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { shortcuts, type ShortcutOptions } from '$lib/actions/shortcut';
|
import { shortcuts, type ShortcutOptions } from '$lib/actions/shortcut';
|
||||||
import ProgressBar from '$lib/components/shared-components/progress-bar/progress-bar.svelte';
|
import ProgressBar from '$lib/components/shared-components/progress-bar/progress-bar.svelte';
|
||||||
import { ProgressBarStatus } from '$lib/constants';
|
import { ProgressBarStatus } from '$lib/constants';
|
||||||
|
import { languageManager } from '$lib/managers/language-manager.svelte';
|
||||||
import SlideshowSettingsModal from '$lib/modals/SlideshowSettingsModal.svelte';
|
import SlideshowSettingsModal from '$lib/modals/SlideshowSettingsModal.svelte';
|
||||||
import { SlideshowNavigation, slideshowStore } from '$lib/stores/slideshow.store';
|
import { SlideshowNavigation, slideshowStore } from '$lib/stores/slideshow.store';
|
||||||
import { AssetTypeEnum } from '@immich/sdk';
|
import { AssetTypeEnum } from '@immich/sdk';
|
||||||
@@ -199,7 +200,7 @@
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
shape="round"
|
shape="round"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
icon={mdiChevronLeft}
|
icon={languageManager.rtl ? mdiChevronRight : mdiChevronLeft}
|
||||||
onclick={onPrevious}
|
onclick={onPrevious}
|
||||||
aria-label={$t('previous')}
|
aria-label={$t('previous')}
|
||||||
/>
|
/>
|
||||||
@@ -207,7 +208,7 @@
|
|||||||
variant="ghost"
|
variant="ghost"
|
||||||
shape="round"
|
shape="round"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
icon={mdiChevronRight}
|
icon={languageManager.rtl ? mdiChevronLeft : mdiChevronRight}
|
||||||
onclick={onNext}
|
onclick={onNext}
|
||||||
aria-label={$t('next')}
|
aria-label={$t('next')}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
data-asset-id={asset.id}
|
data-asset-id={asset.id}
|
||||||
class="absolute"
|
class="absolute"
|
||||||
style:top={position.top + 'px'}
|
style:top={position.top + 'px'}
|
||||||
style:left={position.left + 'px'}
|
style:inset-inline-start={position.left + 'px'}
|
||||||
style:width={position.width + 'px'}
|
style:width={position.width + 'px'}
|
||||||
style:height={position.height + 'px'}
|
style:height={position.height + 'px'}
|
||||||
out:scale|global={{ start: 0.1, duration: scaleDuration }}
|
out:scale|global={{ start: 0.1, duration: scaleDuration }}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#each filterIntersecting(monthGroup.dayGroups) as dayGroup, groupIndex (dayGroup.day)}
|
{#each filterIntersecting(monthGroup.dayGroups) as dayGroup, groupIndex (dayGroup.day)}
|
||||||
{@const absoluteWidth = dayGroup.left}
|
|
||||||
{@const isDayGroupSelected = assetInteraction.selectedGroup.has(dayGroup.groupTitle)}
|
{@const isDayGroupSelected = assetInteraction.selectedGroup.has(dayGroup.groupTitle)}
|
||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<section
|
<section
|
||||||
@@ -64,7 +63,8 @@
|
|||||||
]}
|
]}
|
||||||
data-group
|
data-group
|
||||||
style:position="absolute"
|
style:position="absolute"
|
||||||
style:transform={`translate3d(${absoluteWidth}px,${dayGroup.top}px,0)`}
|
style:inset-inline-start={dayGroup.start + 'px'}
|
||||||
|
style:top={dayGroup.top + 'px'}
|
||||||
onmouseenter={() => (hoveredDayGroup = dayGroup.groupTitle)}
|
onmouseenter={() => (hoveredDayGroup = dayGroup.groupTitle)}
|
||||||
onmouseleave={() => (hoveredDayGroup = null)}
|
onmouseleave={() => (hoveredDayGroup = null)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -617,7 +617,7 @@
|
|||||||
<section
|
<section
|
||||||
id="asset-grid"
|
id="asset-grid"
|
||||||
class={['scrollbar-hidden h-full overflow-y-auto outline-none', { 'm-0': isEmpty }, { 'ms-0': !isEmpty }]}
|
class={['scrollbar-hidden h-full overflow-y-auto outline-none', { 'm-0': isEmpty }, { 'ms-0': !isEmpty }]}
|
||||||
style:margin-right={(usingMobileDevice ? 0 : scrubberWidth) + 'px'}
|
style:margin-inline-end={(usingMobileDevice ? 0 : scrubberWidth) + 'px'}
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
bind:clientHeight={timelineManager.viewportHeight}
|
bind:clientHeight={timelineManager.viewportHeight}
|
||||||
bind:clientWidth={timelineManager.viewportWidth}
|
bind:clientWidth={timelineManager.viewportWidth}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class DayGroup {
|
|||||||
intersecting = $derived.by(() => this.viewerAssets.some((viewAsset) => viewAsset.intersecting));
|
intersecting = $derived.by(() => this.viewerAssets.some((viewAsset) => viewAsset.intersecting));
|
||||||
|
|
||||||
#top: number = $state(0);
|
#top: number = $state(0);
|
||||||
#left: number = $state(0);
|
#start: number = $state(0);
|
||||||
#row = $state(0);
|
#row = $state(0);
|
||||||
#col = $state(0);
|
#col = $state(0);
|
||||||
#deferredLayout = false;
|
#deferredLayout = false;
|
||||||
@@ -41,12 +41,12 @@ export class DayGroup {
|
|||||||
this.#top = value;
|
this.#top = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get left() {
|
get start() {
|
||||||
return this.#left;
|
return this.#start;
|
||||||
}
|
}
|
||||||
|
|
||||||
set left(value: number) {
|
set start(value: number) {
|
||||||
this.#left = value;
|
this.#start = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get row() {
|
get row() {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export function layoutMonthGroup(timelineManager: TimelineManager, month: MonthG
|
|||||||
if (fitsInCurrentRow) {
|
if (fitsInCurrentRow) {
|
||||||
dayGroup.row = dayGroupRow;
|
dayGroup.row = dayGroupRow;
|
||||||
dayGroup.col = dayGroupCol++;
|
dayGroup.col = dayGroupCol++;
|
||||||
dayGroup.left = cumulativeWidth;
|
dayGroup.start = cumulativeWidth;
|
||||||
dayGroup.top = cumulativeHeight;
|
dayGroup.top = cumulativeHeight;
|
||||||
|
|
||||||
cumulativeWidth += dayGroup.width + timelineManager.gap;
|
cumulativeWidth += dayGroup.width + timelineManager.gap;
|
||||||
@@ -53,7 +53,7 @@ export function layoutMonthGroup(timelineManager: TimelineManager, month: MonthG
|
|||||||
// Position at start of new row
|
// Position at start of new row
|
||||||
dayGroup.row = dayGroupRow;
|
dayGroup.row = dayGroupRow;
|
||||||
dayGroup.col = dayGroupCol;
|
dayGroup.col = dayGroupCol;
|
||||||
dayGroup.left = 0;
|
dayGroup.start = 0;
|
||||||
dayGroup.top = cumulativeHeight;
|
dayGroup.top = cumulativeHeight;
|
||||||
|
|
||||||
dayGroupCol++;
|
dayGroupCol++;
|
||||||
|
|||||||
Reference in New Issue
Block a user