mirror of
https://github.com/immich-app/immich.git
synced 2026-02-04 08:49:01 +03:00
refactor: album page (#25140)
This commit is contained in:
@@ -463,7 +463,7 @@ test.describe('Timeline', () => {
|
|||||||
});
|
});
|
||||||
changes.albumAdditions.push(...requestJson.ids);
|
changes.albumAdditions.push(...requestJson.ids);
|
||||||
});
|
});
|
||||||
await page.getByText('Done').click();
|
await page.getByText('Add assets').click();
|
||||||
await expect(put).resolves.toEqual({
|
await expect(put).resolves.toEqual({
|
||||||
ids: [
|
ids: [
|
||||||
'c077ea7b-cfa1-45e4-8554-f86c00ee5658',
|
'c077ea7b-cfa1-45e4-8554-f86c00ee5658',
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"add_a_title": "Add a title",
|
"add_a_title": "Add a title",
|
||||||
"add_action": "Add action",
|
"add_action": "Add action",
|
||||||
"add_action_description": "Click to add an action to perform",
|
"add_action_description": "Click to add an action to perform",
|
||||||
|
"add_assets": "Add assets",
|
||||||
"add_birthday": "Add a birthday",
|
"add_birthday": "Add a birthday",
|
||||||
"add_endpoint": "Add endpoint",
|
"add_endpoint": "Add endpoint",
|
||||||
"add_exclusion_pattern": "Add exclusion pattern",
|
"add_exclusion_pattern": "Add exclusion pattern",
|
||||||
@@ -478,6 +479,7 @@
|
|||||||
"album_summary": "Album summary",
|
"album_summary": "Album summary",
|
||||||
"album_updated": "Album updated",
|
"album_updated": "Album updated",
|
||||||
"album_updated_setting_description": "Receive an email notification when a shared album has new assets",
|
"album_updated_setting_description": "Receive an email notification when a shared album has new assets",
|
||||||
|
"album_upload_assets": "Upload assets from your computer and add to album",
|
||||||
"album_user_left": "Left {album}",
|
"album_user_left": "Left {album}",
|
||||||
"album_user_removed": "Removed {user}",
|
"album_user_removed": "Removed {user}",
|
||||||
"album_viewer_appbar_delete_confirm": "Are you sure you want to delete this album from your account?",
|
"album_viewer_appbar_delete_confirm": "Are you sure you want to delete this album from your account?",
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
import RightClickContextMenu from '$lib/components/shared-components/context-menu/right-click-context-menu.svelte';
|
import RightClickContextMenu from '$lib/components/shared-components/context-menu/right-click-context-menu.svelte';
|
||||||
import AlbumEditModal from '$lib/modals/AlbumEditModal.svelte';
|
import AlbumEditModal from '$lib/modals/AlbumEditModal.svelte';
|
||||||
import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte';
|
import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte';
|
||||||
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
|
|
||||||
import { handleDeleteAlbum, handleDownloadAlbum } from '$lib/services/album.service';
|
import { handleDeleteAlbum, handleDownloadAlbum } from '$lib/services/album.service';
|
||||||
import {
|
import {
|
||||||
AlbumFilter,
|
AlbumFilter,
|
||||||
@@ -21,14 +20,8 @@
|
|||||||
import { userInteraction } from '$lib/stores/user.svelte';
|
import { userInteraction } from '$lib/stores/user.svelte';
|
||||||
import { getSelectedAlbumGroupOption, sortAlbums, stringToSortOrder, type AlbumGroup } from '$lib/utils/album-utils';
|
import { getSelectedAlbumGroupOption, sortAlbums, stringToSortOrder, type AlbumGroup } from '$lib/utils/album-utils';
|
||||||
import type { ContextMenuPosition } from '$lib/utils/context-menu';
|
import type { ContextMenuPosition } from '$lib/utils/context-menu';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
|
||||||
import { normalizeSearchString } from '$lib/utils/string-utils';
|
import { normalizeSearchString } from '$lib/utils/string-utils';
|
||||||
import {
|
import { type AlbumResponseDto, type SharedLinkResponseDto } from '@immich/sdk';
|
||||||
addUsersToAlbum,
|
|
||||||
type AlbumResponseDto,
|
|
||||||
type AlbumUserAddDto,
|
|
||||||
type SharedLinkResponseDto,
|
|
||||||
} from '@immich/sdk';
|
|
||||||
import { modalManager } from '@immich/ui';
|
import { modalManager } from '@immich/ui';
|
||||||
import { mdiDeleteOutline, mdiDownload, mdiRenameOutline, mdiShareVariantOutline } from '@mdi/js';
|
import { mdiDeleteOutline, mdiDownload, mdiRenameOutline, mdiShareVariantOutline } from '@mdi/js';
|
||||||
import { groupBy } from 'lodash-es';
|
import { groupBy } from 'lodash-es';
|
||||||
@@ -205,18 +198,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'share': {
|
case 'share': {
|
||||||
const result = await modalManager.show(AlbumShareModal, { album: selectedAlbum });
|
await modalManager.show(AlbumShareModal, { album: selectedAlbum });
|
||||||
switch (result?.action) {
|
|
||||||
case 'sharedUsers': {
|
|
||||||
await handleAddUsers(selectedAlbum, result.data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'sharedLink': {
|
|
||||||
await modalManager.show(SharedLinkCreateModal, { albumId: selectedAlbum.id });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,20 +233,6 @@
|
|||||||
sharedAlbums = findAndUpdate(sharedAlbums, album);
|
sharedAlbums = findAndUpdate(sharedAlbums, album);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddUsers = async (album: AlbumResponseDto, albumUsers: AlbumUserAddDto[]) => {
|
|
||||||
try {
|
|
||||||
const updatedAlbum = await addUsersToAlbum({
|
|
||||||
id: album.id,
|
|
||||||
addUsersDto: {
|
|
||||||
albumUsers,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
onUpdate(updatedAlbum);
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error, $t('errors.unable_to_add_album_users'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onAlbumUpdate = (album: AlbumResponseDto) => {
|
const onAlbumUpdate = (album: AlbumResponseDto) => {
|
||||||
onUpdate(album);
|
onUpdate(album);
|
||||||
userInteraction.recentAlbums = findAndUpdate(userInteraction.recentAlbums || [], album);
|
userInteraction.recentAlbums = findAndUpdate(userInteraction.recentAlbums || [], album);
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ export type Events = {
|
|||||||
AssetUpdate: [AssetResponseDto];
|
AssetUpdate: [AssetResponseDto];
|
||||||
AssetReplace: [{ oldAssetId: string; newAssetId: string }];
|
AssetReplace: [{ oldAssetId: string; newAssetId: string }];
|
||||||
|
|
||||||
|
AlbumAddAssets: [];
|
||||||
AlbumUpdate: [AlbumResponseDto];
|
AlbumUpdate: [AlbumResponseDto];
|
||||||
AlbumDelete: [AlbumResponseDto];
|
AlbumDelete: [AlbumResponseDto];
|
||||||
|
AlbumShare: [];
|
||||||
|
|
||||||
PersonUpdate: [PersonResponseDto];
|
PersonUpdate: [PersonResponseDto];
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,17 @@
|
|||||||
import AlbumSharedLink from '$lib/components/album-page/album-shared-link.svelte';
|
import AlbumSharedLink from '$lib/components/album-page/album-shared-link.svelte';
|
||||||
import { AppRoute } from '$lib/constants';
|
import { AppRoute } from '$lib/constants';
|
||||||
import Dropdown from '$lib/elements/Dropdown.svelte';
|
import Dropdown from '$lib/elements/Dropdown.svelte';
|
||||||
|
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
|
||||||
|
import { handleAddUsersToAlbum } from '$lib/services/album.service';
|
||||||
import {
|
import {
|
||||||
AlbumUserRole,
|
AlbumUserRole,
|
||||||
getAllSharedLinks,
|
getAllSharedLinks,
|
||||||
searchUsers,
|
searchUsers,
|
||||||
type AlbumResponseDto,
|
type AlbumResponseDto,
|
||||||
type AlbumUserAddDto,
|
|
||||||
type SharedLinkResponseDto,
|
type SharedLinkResponseDto,
|
||||||
type UserResponseDto,
|
type UserResponseDto,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { Button, Icon, Link, Modal, ModalBody, Stack, Text } from '@immich/ui';
|
import { Button, Icon, Link, Modal, ModalBody, modalManager, Stack, Text } from '@immich/ui';
|
||||||
import { mdiCheck, mdiEye, mdiLink, mdiPencil } from '@mdi/js';
|
import { mdiCheck, mdiEye, mdiLink, mdiPencil } from '@mdi/js';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
@@ -19,7 +20,7 @@
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
album: AlbumResponseDto;
|
album: AlbumResponseDto;
|
||||||
onClose: (result?: { action: 'sharedLink' } | { action: 'sharedUsers'; data: AlbumUserAddDto[] }) => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { album, onClose }: Props = $props();
|
let { album, onClose }: Props = $props();
|
||||||
@@ -62,6 +63,21 @@
|
|||||||
selectedUsers[user.id].role = role;
|
selectedUsers[user.id].role = role;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onShareUser = async () => {
|
||||||
|
const success = await handleAddUsersToAlbum(
|
||||||
|
album,
|
||||||
|
Object.values(selectedUsers).map(({ user, ...rest }) => ({ userId: user.id, ...rest })),
|
||||||
|
);
|
||||||
|
if (success) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onShareLink = () => {
|
||||||
|
void modalManager.show(SharedLinkCreateModal, { albumId: album.id });
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal size="small" title={$t('share')} {onClose}>
|
<Modal size="small" title={$t('share')} {onClose}>
|
||||||
@@ -145,12 +161,10 @@
|
|||||||
fullWidth
|
fullWidth
|
||||||
shape="round"
|
shape="round"
|
||||||
disabled={Object.keys(selectedUsers).length === 0}
|
disabled={Object.keys(selectedUsers).length === 0}
|
||||||
onclick={() =>
|
onclick={onShareUser}
|
||||||
onClose({
|
|
||||||
action: 'sharedUsers',
|
|
||||||
data: Object.values(selectedUsers).map(({ user, ...rest }) => ({ userId: user.id, ...rest })),
|
|
||||||
})}>{$t('add')}</Button
|
|
||||||
>
|
>
|
||||||
|
{$t('add')}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -170,13 +184,9 @@
|
|||||||
</Stack>
|
</Stack>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<Button
|
<Button leadingIcon={mdiLink} size="small" shape="round" fullWidth onclick={onShareLink}>
|
||||||
leadingIcon={mdiLink}
|
{$t('create_link')}
|
||||||
size="small"
|
</Button>
|
||||||
shape="round"
|
|
||||||
fullWidth
|
|
||||||
onclick={() => onClose({ action: 'sharedLink' })}>{$t('create_link')}</Button
|
|
||||||
>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -2,11 +2,89 @@ import { goto } from '$app/navigation';
|
|||||||
import ToastAction from '$lib/components/ToastAction.svelte';
|
import ToastAction from '$lib/components/ToastAction.svelte';
|
||||||
import { AppRoute } from '$lib/constants';
|
import { AppRoute } from '$lib/constants';
|
||||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||||
|
import type { TimelineAsset } from '$lib/managers/timeline-manager/types';
|
||||||
|
import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte';
|
||||||
|
import { user } from '$lib/stores/user.store';
|
||||||
import { downloadArchive } from '$lib/utils/asset-utils';
|
import { downloadArchive } from '$lib/utils/asset-utils';
|
||||||
|
import { openFileUploadDialog } from '$lib/utils/file-uploader';
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { getFormatter } from '$lib/utils/i18n';
|
import { getFormatter } from '$lib/utils/i18n';
|
||||||
import { deleteAlbum, updateAlbumInfo, type AlbumResponseDto, type UpdateAlbumDto } from '@immich/sdk';
|
import {
|
||||||
import { modalManager, toastManager } from '@immich/ui';
|
addAssetsToAlbum,
|
||||||
|
addUsersToAlbum,
|
||||||
|
deleteAlbum,
|
||||||
|
updateAlbumInfo,
|
||||||
|
type AlbumResponseDto,
|
||||||
|
type AlbumUserAddDto,
|
||||||
|
type UpdateAlbumDto,
|
||||||
|
} from '@immich/sdk';
|
||||||
|
import { modalManager, toastManager, type ActionItem } from '@immich/ui';
|
||||||
|
import { mdiPlusBoxOutline, mdiShareVariantOutline, mdiUpload } from '@mdi/js';
|
||||||
|
import { type MessageFormatter } from 'svelte-i18n';
|
||||||
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
|
export const getAlbumActions = ($t: MessageFormatter, album: AlbumResponseDto) => {
|
||||||
|
const isOwned = get(user).id === album.ownerId;
|
||||||
|
|
||||||
|
const Share: ActionItem = {
|
||||||
|
title: $t('share'),
|
||||||
|
type: $t('command'),
|
||||||
|
icon: mdiShareVariantOutline,
|
||||||
|
$if: () => isOwned,
|
||||||
|
onAction: () => modalManager.show(AlbumShareModal, { album }),
|
||||||
|
};
|
||||||
|
|
||||||
|
return { Share };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAlbumAssetsActions = ($t: MessageFormatter, album: AlbumResponseDto, assets: TimelineAsset[]) => {
|
||||||
|
const AddAssets: ActionItem = {
|
||||||
|
title: $t('add_assets'),
|
||||||
|
type: $t('command'),
|
||||||
|
icon: mdiPlusBoxOutline,
|
||||||
|
$if: () => assets.length > 0,
|
||||||
|
onAction: () => addAssets(album, assets),
|
||||||
|
};
|
||||||
|
|
||||||
|
const Upload: ActionItem = {
|
||||||
|
title: $t('select_from_computer'),
|
||||||
|
description: $t('album_upload_assets'),
|
||||||
|
type: $t('command'),
|
||||||
|
icon: mdiUpload,
|
||||||
|
onAction: () => void openFileUploadDialog({ albumId: album.id }),
|
||||||
|
};
|
||||||
|
|
||||||
|
return { AddAssets, Upload };
|
||||||
|
};
|
||||||
|
|
||||||
|
const addAssets = async (album: AlbumResponseDto, assets: TimelineAsset[]) => {
|
||||||
|
const $t = await getFormatter();
|
||||||
|
const assetIds = assets.map(({ id }) => id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const results = await addAssetsToAlbum({ id: album.id, bulkIdsDto: { ids: assetIds } });
|
||||||
|
|
||||||
|
const count = results.filter(({ success }) => success).length;
|
||||||
|
toastManager.success($t('assets_added_count', { values: { count } }));
|
||||||
|
eventManager.emit('AlbumAddAssets');
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, $t('errors.error_adding_assets_to_album'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const handleAddUsersToAlbum = async (album: AlbumResponseDto, albumUsers: AlbumUserAddDto[]) => {
|
||||||
|
const $t = await getFormatter();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await addUsersToAlbum({ id: album.id, addUsersDto: { albumUsers } });
|
||||||
|
eventManager.emit('AlbumShare');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, $t('errors.error_adding_users_to_album'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
export const handleUpdateAlbum = async ({ id }: { id: string }, dto: UpdateAlbumDto) => {
|
export const handleUpdateAlbum = async ({ id }: { id: string }, dto: UpdateAlbumDto) => {
|
||||||
const $t = await getFormatter();
|
const $t = await getFormatter();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
import AlbumTitle from '$lib/components/album-page/album-title.svelte';
|
import AlbumTitle from '$lib/components/album-page/album-title.svelte';
|
||||||
import ActivityStatus from '$lib/components/asset-viewer/activity-status.svelte';
|
import ActivityStatus from '$lib/components/asset-viewer/activity-status.svelte';
|
||||||
import ActivityViewer from '$lib/components/asset-viewer/activity-viewer.svelte';
|
import ActivityViewer from '$lib/components/asset-viewer/activity-viewer.svelte';
|
||||||
|
import HeaderActionButton from '$lib/components/HeaderActionButton.svelte';
|
||||||
import OnEvents from '$lib/components/OnEvents.svelte';
|
import OnEvents from '$lib/components/OnEvents.svelte';
|
||||||
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';
|
||||||
@@ -38,7 +39,12 @@
|
|||||||
import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte';
|
import AlbumShareModal from '$lib/modals/AlbumShareModal.svelte';
|
||||||
import AlbumUsersModal from '$lib/modals/AlbumUsersModal.svelte';
|
import AlbumUsersModal from '$lib/modals/AlbumUsersModal.svelte';
|
||||||
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
|
import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte';
|
||||||
import { handleDeleteAlbum, handleDownloadAlbum } from '$lib/services/album.service';
|
import {
|
||||||
|
getAlbumActions,
|
||||||
|
getAlbumAssetsActions,
|
||||||
|
handleDeleteAlbum,
|
||||||
|
handleDownloadAlbum,
|
||||||
|
} from '$lib/services/album.service';
|
||||||
import { getGlobalActions } from '$lib/services/app.service';
|
import { getGlobalActions } from '$lib/services/app.service';
|
||||||
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
import { AssetInteraction } from '$lib/stores/asset-interaction.svelte';
|
||||||
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
|
||||||
@@ -46,7 +52,6 @@
|
|||||||
import { preferences, user } from '$lib/stores/user.store';
|
import { preferences, user } from '$lib/stores/user.store';
|
||||||
import { handlePromiseError } from '$lib/utils';
|
import { handlePromiseError } from '$lib/utils';
|
||||||
import { cancelMultiselect } from '$lib/utils/asset-utils';
|
import { cancelMultiselect } from '$lib/utils/asset-utils';
|
||||||
import { openFileUploadDialog } from '$lib/utils/file-uploader';
|
|
||||||
import { handleError } from '$lib/utils/handle-error';
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import {
|
import {
|
||||||
isAlbumsRoute,
|
isAlbumsRoute,
|
||||||
@@ -59,14 +64,11 @@
|
|||||||
AlbumUserRole,
|
AlbumUserRole,
|
||||||
AssetOrder,
|
AssetOrder,
|
||||||
AssetVisibility,
|
AssetVisibility,
|
||||||
addAssetsToAlbum,
|
|
||||||
addUsersToAlbum,
|
|
||||||
getAlbumInfo,
|
getAlbumInfo,
|
||||||
updateAlbumInfo,
|
updateAlbumInfo,
|
||||||
type AlbumResponseDto,
|
type AlbumResponseDto,
|
||||||
type AlbumUserAddDto,
|
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { Button, Icon, IconButton, modalManager, toastManager } from '@immich/ui';
|
import { CommandPaletteDefaultProvider, Icon, IconButton, modalManager, toastManager } from '@immich/ui';
|
||||||
import {
|
import {
|
||||||
mdiAccountEye,
|
mdiAccountEye,
|
||||||
mdiAccountEyeOutline,
|
mdiAccountEyeOutline,
|
||||||
@@ -80,8 +82,6 @@
|
|||||||
mdiLink,
|
mdiLink,
|
||||||
mdiPlus,
|
mdiPlus,
|
||||||
mdiPresentationPlay,
|
mdiPresentationPlay,
|
||||||
mdiShareVariantOutline,
|
|
||||||
mdiUpload,
|
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
import { onDestroy } from 'svelte';
|
import { onDestroy } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
@@ -101,7 +101,6 @@
|
|||||||
|
|
||||||
let backUrl: string = $state(AppRoute.ALBUMS);
|
let backUrl: string = $state(AppRoute.ALBUMS);
|
||||||
let viewMode: AlbumPageViewMode = $state(AlbumPageViewMode.VIEW);
|
let viewMode: AlbumPageViewMode = $state(AlbumPageViewMode.VIEW);
|
||||||
let isCreatingSharedAlbum = $state(false);
|
|
||||||
let albumOrder: AssetOrder | undefined = $state(data.album.order);
|
let albumOrder: AssetOrder | undefined = $state(data.album.order);
|
||||||
|
|
||||||
let timelineManager = $state<TimelineManager>() as TimelineManager;
|
let timelineManager = $state<TimelineManager>() as TimelineManager;
|
||||||
@@ -124,9 +123,7 @@
|
|||||||
|
|
||||||
backUrl = url || AppRoute.ALBUMS;
|
backUrl = url || AppRoute.ALBUMS;
|
||||||
|
|
||||||
if (backUrl === AppRoute.SHARING && album.albumUsers.length === 0 && !album.hasSharedLink) {
|
if (backUrl === AppRoute.SHARED_LINKS) {
|
||||||
isCreatingSharedAlbum = true;
|
|
||||||
} else if (backUrl === AppRoute.SHARED_LINKS) {
|
|
||||||
backUrl = history.state?.backUrl || AppRoute.ALBUMS;
|
backUrl = history.state?.backUrl || AppRoute.ALBUMS;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -177,26 +174,6 @@
|
|||||||
const refreshAlbum = async () => {
|
const refreshAlbum = async () => {
|
||||||
album = await getAlbumInfo({ id: album.id, withoutAssets: true });
|
album = await getAlbumInfo({ id: album.id, withoutAssets: true });
|
||||||
};
|
};
|
||||||
const handleAddAssets = async () => {
|
|
||||||
const assetIds = timelineInteraction.selectedAssets.map((asset) => asset.id);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const results = await addAssetsToAlbum({
|
|
||||||
id: album.id,
|
|
||||||
bulkIdsDto: { ids: assetIds },
|
|
||||||
});
|
|
||||||
|
|
||||||
const count = results.filter(({ success }) => success).length;
|
|
||||||
toastManager.success($t('assets_added_count', { values: { count } }));
|
|
||||||
|
|
||||||
await refreshAlbum();
|
|
||||||
|
|
||||||
timelineInteraction.clearMultiselect();
|
|
||||||
await setModeToView();
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error, $t('errors.error_adding_assets_to_album'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const setModeToView = async () => {
|
const setModeToView = async () => {
|
||||||
timelineManager.suspendTransitions = true;
|
timelineManager.suspendTransitions = true;
|
||||||
@@ -213,28 +190,6 @@
|
|||||||
await setModeToView();
|
await setModeToView();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectFromComputer = async () => {
|
|
||||||
await openFileUploadDialog({ albumId: album.id });
|
|
||||||
timelineInteraction.clearMultiselect();
|
|
||||||
await setModeToView();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleAddUsers = async (albumUsers: AlbumUserAddDto[]) => {
|
|
||||||
try {
|
|
||||||
await addUsersToAlbum({
|
|
||||||
id: album.id,
|
|
||||||
addUsersDto: {
|
|
||||||
albumUsers,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await refreshAlbum();
|
|
||||||
|
|
||||||
viewMode = AlbumPageViewMode.VIEW;
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error, $t('errors.error_adding_users_to_album'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSetVisibility = (assetIds: string[]) => {
|
const handleSetVisibility = (assetIds: string[]) => {
|
||||||
timelineManager.removeAssets(assetIds);
|
timelineManager.removeAssets(assetIds);
|
||||||
assetInteraction.clearMultiselect();
|
assetInteraction.clearMultiselect();
|
||||||
@@ -353,22 +308,6 @@
|
|||||||
viewMode === AlbumPageViewMode.SELECT_ASSETS ? timelineInteraction : assetInteraction,
|
viewMode === AlbumPageViewMode.SELECT_ASSETS ? timelineInteraction : assetInteraction,
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleShare = async () => {
|
|
||||||
const result = await modalManager.show(AlbumShareModal, { album });
|
|
||||||
|
|
||||||
switch (result?.action) {
|
|
||||||
case 'sharedLink': {
|
|
||||||
await handleShareLink();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'sharedUsers': {
|
|
||||||
await handleAddUsers(result.data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSharedLinkCreate = async () => {
|
const onSharedLinkCreate = async () => {
|
||||||
await refreshAlbum();
|
await refreshAlbum();
|
||||||
};
|
};
|
||||||
@@ -380,10 +319,6 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleShareLink = async () => {
|
|
||||||
await modalManager.show(SharedLinkCreateModal, { albumId: album.id });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleEditUsers = async () => {
|
const handleEditUsers = async () => {
|
||||||
const changed = await modalManager.show(AlbumUsersModal, { album });
|
const changed = await modalManager.show(AlbumUsersModal, { album });
|
||||||
|
|
||||||
@@ -405,7 +340,7 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'shareUser': {
|
case 'shareUser': {
|
||||||
await handleShare();
|
await modalManager.show(AlbumShareModal, { album });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'refreshAlbum': {
|
case 'refreshAlbum': {
|
||||||
@@ -415,10 +350,24 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onAlbumAddAssets = async () => {
|
||||||
|
await refreshAlbum();
|
||||||
|
timelineInteraction.clearMultiselect();
|
||||||
|
await setModeToView();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onAlbumShare = async () => {
|
||||||
|
await refreshAlbum();
|
||||||
|
await setModeToView();
|
||||||
|
};
|
||||||
|
|
||||||
const { Cast } = $derived(getGlobalActions($t));
|
const { Cast } = $derived(getGlobalActions($t));
|
||||||
|
const { Share } = $derived(getAlbumActions($t, album));
|
||||||
|
const { AddAssets, Upload } = $derived(getAlbumAssetsActions($t, album, timelineInteraction.selectedAssets));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<OnEvents {onSharedLinkCreate} {onAlbumDelete} />
|
<OnEvents {onSharedLinkCreate} {onAlbumDelete} {onAlbumAddAssets} {onAlbumShare} />
|
||||||
|
<CommandPaletteDefaultProvider name={$t('album')} actions={[AddAssets, Upload]} />
|
||||||
|
|
||||||
<div class="flex overflow-hidden" use:scrollMemoryClearer={{ routeStartsWith: AppRoute.ALBUMS }}>
|
<div class="flex overflow-hidden" use:scrollMemoryClearer={{ routeStartsWith: AppRoute.ALBUMS }}>
|
||||||
<div class="relative w-full shrink">
|
<div class="relative w-full shrink">
|
||||||
@@ -463,7 +412,7 @@
|
|||||||
size="medium"
|
size="medium"
|
||||||
shape="round"
|
shape="round"
|
||||||
icon={mdiLink}
|
icon={mdiLink}
|
||||||
onclick={handleShareLink}
|
onclick={() => modalManager.show(SharedLinkCreateModal, { albumId: album.id })}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -491,16 +440,7 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if isOwned}
|
<ActionButton action={Share} />
|
||||||
<IconButton
|
|
||||||
shape="round"
|
|
||||||
color="secondary"
|
|
||||||
size="medium"
|
|
||||||
icon={mdiPlus}
|
|
||||||
onclick={handleShare}
|
|
||||||
aria-label={$t('add_more_users')}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<!-- ALBUM DESCRIPTION -->
|
<!-- ALBUM DESCRIPTION -->
|
||||||
@@ -616,16 +556,7 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if isOwned}
|
<ActionButton action={Share} />
|
||||||
<IconButton
|
|
||||||
shape="round"
|
|
||||||
variant="ghost"
|
|
||||||
color="secondary"
|
|
||||||
aria-label={$t('share')}
|
|
||||||
onclick={handleShare}
|
|
||||||
icon={mdiShareVariantOutline}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if featureFlagsManager.value.map}
|
{#if featureFlagsManager.value.map}
|
||||||
<AlbumMap {album} />
|
<AlbumMap {album} />
|
||||||
@@ -682,12 +613,6 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</ButtonContextMenu>
|
</ButtonContextMenu>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if isCreatingSharedAlbum && album.albumUsers.length === 0}
|
|
||||||
<Button size="small" disabled={album.assetCount === 0} onclick={handleShare}>
|
|
||||||
{$t('share')}
|
|
||||||
</Button>
|
|
||||||
{/if}
|
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</ControlAppBar>
|
</ControlAppBar>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -705,10 +630,8 @@
|
|||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
{#snippet trailing()}
|
{#snippet trailing()}
|
||||||
<Button variant="ghost" leadingIcon={mdiUpload} onclick={handleSelectFromComputer}
|
<HeaderActionButton action={Upload} />
|
||||||
>{$t('select_from_computer')}</Button
|
<HeaderActionButton action={AddAssets} />
|
||||||
>
|
|
||||||
<Button disabled={!timelineInteraction.selectionActive} onclick={handleAddAssets}>{$t('done')}</Button>
|
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</ControlAppBar>
|
</ControlAppBar>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user