mirror of
https://github.com/immich-app/immich.git
synced 2026-07-15 21:32:32 +03:00
fix(web): URI encode slug and reduce confusion for users (#29796)
Co-authored-by: bwees <brandonwees@gmail.com>
This commit is contained in:
@@ -814,7 +814,6 @@
|
|||||||
"custom_date": "Custom date",
|
"custom_date": "Custom date",
|
||||||
"custom_locale": "Custom locale",
|
"custom_locale": "Custom locale",
|
||||||
"custom_locale_description": "Format dates, times, and numbers based on the selected language and region",
|
"custom_locale_description": "Format dates, times, and numbers based on the selected language and region",
|
||||||
"custom_url": "Custom URL",
|
|
||||||
"cutoff_date_description": "Keep photos from the last…",
|
"cutoff_date_description": "Keep photos from the last…",
|
||||||
"cutoff_day": "{count, plural, one {day} other {days}}",
|
"cutoff_day": "{count, plural, one {day} other {days}}",
|
||||||
"cutoff_year": "{count, plural, one {year} other {years}}",
|
"cutoff_year": "{count, plural, one {year} other {years}}",
|
||||||
@@ -1948,7 +1947,9 @@
|
|||||||
"shared_link_app_bar_title": "Shared Links",
|
"shared_link_app_bar_title": "Shared Links",
|
||||||
"shared_link_clipboard_copied_massage": "Copied to clipboard",
|
"shared_link_clipboard_copied_massage": "Copied to clipboard",
|
||||||
"shared_link_create_error": "Error while creating shared link",
|
"shared_link_create_error": "Error while creating shared link",
|
||||||
"shared_link_custom_url_description": "Access this shared link with a custom URL",
|
"shared_link_custom_url_description": "Access this shared link with a custom URL name",
|
||||||
|
"shared_link_custom_url_title": "Custom URL",
|
||||||
|
"shared_link_custom_url_warning": "Warning: a custom URL name with a forward slash may not behave as you expect.",
|
||||||
"shared_link_edit_description_hint": "Enter the share description",
|
"shared_link_edit_description_hint": "Enter the share description",
|
||||||
"shared_link_edit_expire_after_option_day": "1 day",
|
"shared_link_edit_expire_after_option_day": "1 day",
|
||||||
"shared_link_edit_expire_after_option_days": "{count} days",
|
"shared_link_edit_expire_after_option_days": "{count} days",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import SharedLinkExpiration from '$lib/components/SharedLinkExpiration.svelte';
|
import SharedLinkExpiration from '$lib/components/SharedLinkExpiration.svelte';
|
||||||
import { Field, Input, PasswordInput, Switch, Text } from '@immich/ui';
|
import { Field, HelperText, Input, PasswordInput, Switch, Text } from '@immich/ui';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -32,8 +32,11 @@
|
|||||||
|
|
||||||
<div class="mt-4 flex flex-col gap-4">
|
<div class="mt-4 flex flex-col gap-4">
|
||||||
<div>
|
<div>
|
||||||
<Field label={$t('custom_url')} description={$t('shared_link_custom_url_description')}>
|
<Field label={$t('shared_link_custom_url_title')} description={$t('shared_link_custom_url_description')}>
|
||||||
<Input bind:value={slug} autocomplete="off" />
|
<Input bind:value={slug} autocomplete="off" />
|
||||||
|
{#if slug.includes('/')}
|
||||||
|
<HelperText class="text-warning">{$t('shared_link_custom_url_warning')}</HelperText>
|
||||||
|
{/if}
|
||||||
</Field>
|
</Field>
|
||||||
{#if slug}
|
{#if slug}
|
||||||
<Text size="tiny" color="muted" class="pt-2 break-all">/s/{encodeURIComponent(slug)}</Text>
|
<Text size="tiny" color="muted" class="pt-2 break-all">/s/{encodeURIComponent(slug)}</Text>
|
||||||
|
|||||||
@@ -24,6 +24,20 @@ describe('Route', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe(Route.viewSharedLink.name, () => {
|
||||||
|
it('should work with key', () => {
|
||||||
|
expect(Route.viewSharedLink({ key: 'uuid-key' })).toBe('/share/uuid-key');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work with key and slug', () => {
|
||||||
|
expect(Route.viewSharedLink({ key: 'uuid-key', slug: 'custom-slug' })).toBe('/s/custom-slug');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should URI encode slug', () => {
|
||||||
|
expect(Route.viewSharedLink({ key: 'uuid-key', slug: 'albums/the-moon?' })).toBe('/s/albums%2Fthe-moon%3F');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe(Route.tags.name, () => {
|
describe(Route.tags.name, () => {
|
||||||
it('should work', () => {
|
it('should work', () => {
|
||||||
expect(Route.tags()).toBe('/tags');
|
expect(Route.tags()).toBe('/tags');
|
||||||
|
|||||||
@@ -120,7 +120,8 @@ export const Route = {
|
|||||||
// shared links
|
// shared links
|
||||||
sharedLinks: (params?: { filter?: SharedLinkTab }) => '/shared-links' + asQueryString(params),
|
sharedLinks: (params?: { filter?: SharedLinkTab }) => '/shared-links' + asQueryString(params),
|
||||||
editSharedLink: ({ id }: { id: string }) => `/shared-links/${id}/edit`,
|
editSharedLink: ({ id }: { id: string }) => `/shared-links/${id}/edit`,
|
||||||
viewSharedLink: ({ slug, key }: { slug?: string | null; key: string }) => (slug ? `/s/${slug}` : `/share/${key}`),
|
viewSharedLink: ({ slug, key }: { slug?: string | null; key: string }) =>
|
||||||
|
slug ? `/s/${encodeURIComponent(slug)}` : `/share/${key}`,
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
userSettings: (params?: { isOpen?: OpenQueryParam }) => '/user-settings' + asQueryString(params),
|
userSettings: (params?: { isOpen?: OpenQueryParam }) => '/user-settings' + asQueryString(params),
|
||||||
|
|||||||
@@ -60,9 +60,7 @@ export const getSharedLinkActions = ($t: MessageFormatter, sharedLink: SharedLin
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const asUrl = (sharedLink: SharedLinkResponseDto) => {
|
export const asUrl = (sharedLink: SharedLinkResponseDto) => {
|
||||||
const path = sharedLink.slug
|
const path = Route.viewSharedLink(sharedLink);
|
||||||
? `s/${encodeURIComponent(sharedLink.slug)}`
|
|
||||||
: `share/${encodeURIComponent(sharedLink.key)}`;
|
|
||||||
return new URL(path, serverConfigManager.value.externalDomain || globalThis.location.origin).href;
|
return new URL(path, serverConfigManager.value.externalDomain || globalThis.location.origin).href;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -56,8 +56,10 @@
|
|||||||
|
|
||||||
{#if shareType === SharedLinkType.Individual}
|
{#if shareType === SharedLinkType.Individual}
|
||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
{$t('individual_share')} |
|
{$t('individual_share')}
|
||||||
<span class="text-primary">{sharedLink.description || ''}</span>
|
{#if description !== ''}
|
||||||
|
| <span class="text-primary">{description}</span>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user