1
0
mirror of https://github.com/immich-app/immich.git synced 2025-01-01 11:37:06 +02:00

fix(web): selecting shared link expiration (#10437)

This commit is contained in:
Michel Heusschen 2024-06-17 17:31:11 +02:00 committed by GitHub
parent 8e373cee8d
commit a6e767e46d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 42 additions and 81 deletions

View File

@ -8,13 +8,14 @@
import { SharedLinkType, createSharedLink, updateSharedLink, type SharedLinkResponseDto } from '@immich/sdk'; import { SharedLinkType, createSharedLink, updateSharedLink, type SharedLinkResponseDto } from '@immich/sdk';
import { mdiContentCopy, mdiLink } from '@mdi/js'; import { mdiContentCopy, mdiLink } from '@mdi/js';
import { createEventDispatcher } from 'svelte'; import { createEventDispatcher } from 'svelte';
import type { ImmichDropDownOption } from '../dropdown-button.svelte'; import DropdownButton, { type DropDownOption } from '../dropdown-button.svelte';
import DropdownButton from '../dropdown-button.svelte';
import { NotificationType, notificationController } from '../notification/notification'; import { NotificationType, notificationController } from '../notification/notification';
import SettingInputField, { SettingInputFieldType } from '../settings/setting-input-field.svelte'; import SettingInputField, { SettingInputFieldType } from '../settings/setting-input-field.svelte';
import SettingSwitch from '../settings/setting-switch.svelte'; import SettingSwitch from '../settings/setting-switch.svelte';
import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte'; import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
import { t } from 'svelte-i18n'; import { t } from 'svelte-i18n';
import { locale } from '$lib/stores/preferences.store';
import { DateTime, Duration } from 'luxon';
export let onClose: () => void; export let onClose: () => void;
export let albumId: string | undefined = undefined; export let albumId: string | undefined = undefined;
@ -26,7 +27,7 @@
let allowDownload = true; let allowDownload = true;
let allowUpload = false; let allowUpload = false;
let showMetadata = true; let showMetadata = true;
let expirationTime = ''; let expirationOption: DropDownOption<number> | undefined;
let password = ''; let password = '';
let shouldChangeExpirationTime = false; let shouldChangeExpirationTime = false;
let enablePassword = false; let enablePassword = false;
@ -35,20 +36,27 @@
created: void; created: void;
}>(); }>();
const expiredDateOption: ImmichDropDownOption = { const expirationOptions: [number, Intl.RelativeTimeFormatUnit][] = [
default: $t('never'), [30, 'minutes'],
options: [ [1, 'hour'],
$t('never'), [6, 'hours'],
$t('durations.minutes', { values: { minutes: 30 } }), [1, 'day'],
$t('durations.hours', { values: { hours: 1 } }), [7, 'days'],
$t('durations.hours', { values: { hours: 6 } }), [30, 'days'],
$t('durations.days', { values: { days: 1 } }), [3, 'months'],
$t('durations.days', { values: { days: 7 } }), [1, 'year'],
$t('durations.days', { values: { days: 30 } }), ];
$t('durations.months', { values: { months: 3 } }),
$t('durations.years', { values: { years: 1 } }), $: relativeTime = new Intl.RelativeTimeFormat($locale);
], $: expiredDateOption = [
}; { label: $t('never'), value: 0 },
...expirationOptions.map(
([value, unit]): DropDownOption<number> => ({
label: relativeTime.format(value, unit),
value: Duration.fromObject({ [unit]: value }).toMillis(),
}),
),
];
$: shareType = albumId ? SharedLinkType.Album : SharedLinkType.Individual; $: shareType = albumId ? SharedLinkType.Album : SharedLinkType.Individual;
$: { $: {
@ -74,9 +82,8 @@
} }
const handleCreateSharedLink = async () => { const handleCreateSharedLink = async () => {
const expirationTime = getExpirationTimeInMillisecond(); const expirationDate =
const currentTime = Date.now(); expirationOption && expirationOption.value > 0 ? DateTime.now().plus(expirationOption.value).toISO() : undefined;
const expirationDate = expirationTime ? new Date(currentTime + expirationTime).toISOString() : undefined;
try { try {
const data = await createSharedLink({ const data = await createSharedLink({
@ -99,49 +106,14 @@
} }
}; };
const getExpirationTimeInMillisecond = () => {
switch (expirationTime) {
case '30 minutes': {
return 30 * 60 * 1000;
}
case '1 hour': {
return 60 * 60 * 1000;
}
case '6 hours': {
return 6 * 60 * 60 * 1000;
}
case '1 day': {
return 24 * 60 * 60 * 1000;
}
case '7 days': {
return 7 * 24 * 60 * 60 * 1000;
}
case '30 days': {
return 30 * 24 * 60 * 60 * 1000;
}
case '3 months': {
return 30 * 24 * 60 * 60 * 3 * 1000;
}
case '1 year': {
return 30 * 24 * 60 * 60 * 12 * 1000;
}
default: {
return 0;
}
}
};
const handleEditLink = async () => { const handleEditLink = async () => {
if (!editingLink) { if (!editingLink) {
return; return;
} }
try { try {
const expirationTime = getExpirationTimeInMillisecond(); const expirationDate =
const currentTime = Date.now(); expirationOption && expirationOption.value > 0 ? DateTime.now().plus(expirationOption.value).toISO() : null;
const expirationDate: string | null = expirationTime
? new Date(currentTime + expirationTime).toISOString()
: null;
await updateSharedLink({ await updateSharedLink({
id: editingLink.id, id: editingLink.id,
@ -252,7 +224,7 @@
<DropdownButton <DropdownButton
options={expiredDateOption} options={expiredDateOption}
bind:selected={expirationTime} bind:selected={expirationOption}
disabled={editingLink && !shouldChangeExpirationTime} disabled={editingLink && !shouldChangeExpirationTime}
/> />
</div> </div>

View File

@ -1,21 +1,15 @@
<script lang="ts" context="module"> <script lang="ts" context="module">
export type ImmichDropDownOption = { export type DropDownOption<T = unknown> = {
default: string; label: string;
options: string[]; value: T;
}; };
</script> </script>
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; export let options: DropDownOption[];
export let selected = options.at(0);
export let options: ImmichDropDownOption;
export let selected: string;
export let disabled = false; export let disabled = false;
onMount(() => {
selected = options.default;
});
export let isOpen = false; export let isOpen = false;
const toggle = () => (isOpen = !isOpen); const toggle = () => (isOpen = !isOpen);
</script> </script>
@ -28,9 +22,11 @@
aria-expanded={isOpen} aria-expanded={isOpen}
class="flex w-full place-items-center justify-between rounded-lg bg-gray-200 p-2 disabled:cursor-not-allowed disabled:bg-gray-600 dark:bg-gray-600 dark:disabled:bg-gray-300" class="flex w-full place-items-center justify-between rounded-lg bg-gray-200 p-2 disabled:cursor-not-allowed disabled:bg-gray-600 dark:bg-gray-600 dark:disabled:bg-gray-300"
> >
<div> {#if selected}
{selected} <div>
</div> {selected.label}
</div>
{/if}
<div> <div>
<svg <svg
@ -51,7 +47,7 @@
{#if isOpen} {#if isOpen}
<div class="absolute mt-2 flex w-full flex-col"> <div class="absolute mt-2 flex w-full flex-col">
{#each options.options as option} {#each options as option}
<button <button
type="button" type="button"
on:click={() => { on:click={() => {
@ -60,7 +56,7 @@
}} }}
class="flex w-full bg-gray-200 p-2 transition-all hover:bg-gray-300 dark:bg-gray-500 dark:hover:bg-gray-700" class="flex w-full bg-gray-200 p-2 transition-all hover:bg-gray-300 dark:bg-gray-500 dark:hover:bg-gray-700"
> >
{option} {option.label}
</button> </button>
{/each} {/each}
</div> </div>

View File

@ -424,13 +424,6 @@
"duplicates": "Duplicates", "duplicates": "Duplicates",
"duplicates_description": "Resolve each group by indicating which, if any, are duplicates", "duplicates_description": "Resolve each group by indicating which, if any, are duplicates",
"duration": "Duration", "duration": "Duration",
"durations": {
"days": "{days, plural, one {day} other {{days, number} days}}",
"hours": "{hours, plural, one {hour} other {{hours, number} hours}}",
"minutes": "{minutes, plural, one {minute} other {{minutes, number} minutes}}",
"months": "{months, plural, one {month} other {{months, number} months}}",
"years": "{years, plural, one {year} other {{years, number} years}}"
},
"edit_album": "Edit album", "edit_album": "Edit album",
"edit_avatar": "Edit avatar", "edit_avatar": "Edit avatar",
"edit_date": "Edit date", "edit_date": "Edit date",