diff --git a/web/src/lib/components/asset-viewer/activity-status.svelte b/web/src/lib/components/asset-viewer/activity-status.svelte new file mode 100644 index 0000000000..23fdb7a9d4 --- /dev/null +++ b/web/src/lib/components/asset-viewer/activity-status.svelte @@ -0,0 +1,33 @@ + + +
+ + +
diff --git a/web/src/lib/components/asset-viewer/activity-viewer.svelte b/web/src/lib/components/asset-viewer/activity-viewer.svelte index 234f708f74..efc53db9c1 100644 --- a/web/src/lib/components/asset-viewer/activity-viewer.svelte +++ b/web/src/lib/components/asset-viewer/activity-viewer.svelte @@ -1,9 +1,9 @@ diff --git a/web/src/lib/components/shared-components/control-app-bar.svelte b/web/src/lib/components/shared-components/control-app-bar.svelte index a7c7da6bad..f8d5627fa6 100644 --- a/web/src/lib/components/shared-components/control-app-bar.svelte +++ b/web/src/lib/components/shared-components/control-app-bar.svelte @@ -40,7 +40,7 @@ }); -
+
height}
(undefined); + +export const setNumberOfComments = (number: number) => { + numberOfComments.set(number); +}; + +export const updateNumberOfComments = (addOrRemove: 1 | -1) => { + numberOfComments.update((n) => (n ? n + addOrRemove : undefined)); +}; diff --git a/web/src/routes/(user)/albums/[albumId]/+page.svelte b/web/src/routes/(user)/albums/[albumId]/+page.svelte index 1697af5221..3d0c97510c 100644 --- a/web/src/routes/(user)/albums/[albumId]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId]/+page.svelte @@ -35,7 +35,7 @@ import { downloadArchive } from '$lib/utils/asset-utils'; import { openFileUploadDialog } from '$lib/utils/file-uploader'; import { handleError } from '$lib/utils/handle-error'; - import { UserResponseDto, api } from '@api'; + import { ActivityResponseDto, ReactionType, UserResponseDto, api } from '@api'; import Icon from '$lib/components/elements/icon.svelte'; import type { PageData } from './$types'; import { clickOutside } from '$lib/utils/click-outside'; @@ -45,11 +45,16 @@ mdiDotsVertical, mdiArrowLeft, mdiFileImagePlusOutline, - mdiShareVariantOutline, - mdiDeleteOutline, mdiFolderDownloadOutline, mdiLink, + mdiShareVariantOutline, + mdiDeleteOutline, } from '@mdi/js'; + import { onMount } from 'svelte'; + import { fly } from 'svelte/transition'; + import ActivityViewer from '$lib/components/asset-viewer/activity-viewer.svelte'; + import ActivityStatus from '$lib/components/asset-viewer/activity-status.svelte'; + import { numberOfComments, setNumberOfComments, updateNumberOfComments } from '$lib/stores/activity.store'; export let data: PageData; @@ -77,6 +82,12 @@ let isCreatingSharedAlbum = false; let currentAlbumName = ''; let contextMenuPosition: { x: number; y: number } = { x: 0, y: 0 }; + let isShowActivity = false; + let isLiked: ActivityResponseDto | null = null; + let reactions: ActivityResponseDto[] = []; + let user = data.user; + let globalWidth: number; + let assetGridWidth: number; const assetStore = new AssetStore({ albumId: album.id }); const assetInteractionStore = createAssetInteractionStore(); @@ -89,6 +100,13 @@ $: isOwned = data.user.id == album.ownerId; $: isAllUserOwned = Array.from($selectedAssets).every((asset) => asset.ownerId === data.user.id); $: isAllFavorite = Array.from($selectedAssets).every((asset) => asset.isFavorite); + $: { + if (isShowActivity) { + assetGridWidth = globalWidth - (globalWidth < 768 ? 360 : 460); + } else { + assetGridWidth = globalWidth; + } + } afterNavigate(({ from }) => { assetViewingStore.showAssetViewer(false); @@ -110,6 +128,63 @@ } }); + const handleFavorite = async () => { + try { + if (isLiked) { + const activityId = isLiked.id; + await api.activityApi.deleteActivity({ id: activityId }); + reactions = reactions.filter((reaction) => reaction.id !== activityId); + isLiked = null; + } else { + const { data } = await api.activityApi.createActivity({ + activityCreateDto: { albumId: album.id, type: ReactionType.Like }, + }); + + isLiked = data; + reactions = [...reactions, isLiked]; + } + } catch (error) { + handleError(error, "Can't change favorite for asset"); + } + }; + + const getFavorite = async () => { + if (user) { + try { + const { data } = await api.activityApi.getActivities({ + userId: user.id, + albumId: album.id, + type: ReactionType.Like, + }); + if (data.length > 0) { + isLiked = data[0]; + } + } catch (error) { + handleError(error, "Can't get Favorite"); + } + } + }; + + const getNumberOfComments = async () => { + try { + const { data } = await api.activityApi.getActivityStatistics({ albumId: album.id }); + setNumberOfComments(data.comments); + } catch (error) { + handleError(error, "Can't get number of comments"); + } + }; + + const handleOpenAndCloseActivityTab = () => { + isShowActivity = !isShowActivity; + }; + + onMount(async () => { + if (album.sharedUsers.length > 0) { + getFavorite(); + getNumberOfComments(); + } + }); + const handleStartSlideshow = async () => { const asset = $slideshowShuffle ? await assetStore.getRandomAsset() : assetStore.assets[0]; if (asset) { @@ -321,239 +396,275 @@ }; -
- {#if $isMultiSelectState} - assetInteractionStore.clearMultiselect()}> - - - - - - - - {#if isAllUserOwned} - - {/if} - - - {#if isOwned || isAllUserOwned} - handleRemoveAssets(assetIds)} /> - {/if} - {#if isAllUserOwned} - assetStore.removeAsset(assetId)} /> - {/if} - - - {:else} - {#if viewMode === ViewMode.VIEW || viewMode === ViewMode.ALBUM_OPTIONS} - goto(backUrl)}> - - (viewMode = ViewMode.SELECT_ASSETS)} - icon={mdiFileImagePlusOutline} - /> - - {#if isOwned} - (viewMode = ViewMode.SELECT_USERS)} - icon={mdiShareVariantOutline} - /> - (viewMode = ViewMode.CONFIRM_DELETE)} - icon={mdiDeleteOutline} - /> +
+
+ {#if $isMultiSelectState} + assetInteractionStore.clearMultiselect()}> + + + + + + + + {#if isAllUserOwned} + {/if} - - {#if album.assetCount > 0} - + + + {#if isOwned || isAllUserOwned} + handleRemoveAssets(assetIds)} /> + {/if} + {#if isAllUserOwned} + assetStore.removeAsset(assetId)} /> + {/if} + + + {:else} + {#if viewMode === ViewMode.VIEW || viewMode === ViewMode.ALBUM_OPTIONS} + goto(backUrl)}> + + (viewMode = ViewMode.SELECT_ASSETS)} + icon={mdiFileImagePlusOutline} + /> {#if isOwned} -
(viewMode = ViewMode.VIEW)}> - - {#if viewMode === ViewMode.ALBUM_OPTIONS} - - {#if album.assetCount !== 0} - - {/if} - (viewMode = ViewMode.SELECT_THUMBNAIL)} text="Set album cover" /> - - {/if} - -
+ (viewMode = ViewMode.SELECT_USERS)} + icon={mdiShareVariantOutline} + /> + (viewMode = ViewMode.CONFIRM_DELETE)} + icon={mdiDeleteOutline} + /> {/if} - {/if} - {#if isCreatingSharedAlbum && album.sharedUsers.length === 0} - - {/if} -
-
- {/if} - - {#if viewMode === ViewMode.SELECT_ASSETS} - - -

- {#if $timelineSelected.size == 0} - Add to album - {:else} - {$timelineSelected.size.toLocaleString($locale)} selected - {/if} -

-
- - - - - -
- {/if} - - {#if viewMode === ViewMode.SELECT_THUMBNAIL} - (viewMode = ViewMode.VIEW)}> - Select Album Cover - - {/if} - {/if} -
- -
- {#if viewMode === ViewMode.SELECT_ASSETS} - - {:else} - 0} - isSelectionMode={viewMode === ViewMode.SELECT_THUMBNAIL} - singleSelect={viewMode === ViewMode.SELECT_THUMBNAIL} - on:select={({ detail: asset }) => handleUpdateThumbnail(asset.id)} - on:escape={handleEscape} - > - {#if viewMode !== ViewMode.SELECT_THUMBNAIL} - -
- e.key == 'Enter' && titleInput.blur()} - on:blur={handleUpdateName} - class="w-[99%] border-b-2 border-transparent text-6xl text-immich-primary outline-none transition-all dark:text-immich-dark-primary {isOwned - ? 'hover:border-gray-400' - : 'hover:border-transparent'} bg-immich-bg focus:border-b-2 focus:border-immich-primary focus:outline-none dark:bg-immich-dark-bg dark:focus:border-immich-dark-primary dark:focus:bg-immich-dark-gray" - type="text" - bind:value={album.albumName} - disabled={!isOwned} - bind:this={titleInput} - title="Edit Title" - /> - - - {#if album.assetCount > 0} - -

{getDateRange()}

-

·

-

{album.assetCount} items

-
- {/if} - - - {#if album.sharedUsers.length > 0 || (album.hasSharedLink && isOwned)} -
- - {#if album.hasSharedLink && isOwned} - (viewMode = ViewMode.LINK_SHARING)} - /> - {/if} - - - - - - {#each album.sharedUsers as user (user.id)} - - {/each} + {#if album.assetCount > 0} + {#if isOwned} - (viewMode = ViewMode.SELECT_USERS)} - title="Add more users" - /> +
(viewMode = ViewMode.VIEW)}> + + {#if viewMode === ViewMode.ALBUM_OPTIONS} + + {#if album.assetCount !== 0} + + {/if} + (viewMode = ViewMode.SELECT_THUMBNAIL)} text="Set album cover" /> + + {/if} + +
{/if} -
- {/if} + {/if} - - {#if isOwned || album.description} - - {/if} -
+ {#if isCreatingSharedAlbum && album.sharedUsers.length === 0} + + {/if} + + {/if} - {#if album.assetCount === 0} -
-
-

ADD PHOTOS

+ {#if viewMode === ViewMode.SELECT_ASSETS} + + +

+ {#if $timelineSelected.size === 0} + Add to album + {:else} + {$timelineSelected.size.toLocaleString($locale)} selected + {/if} +

+
+ + -
-
+ + + {/if} -
+ + {#if viewMode === ViewMode.SELECT_THUMBNAIL} + (viewMode = ViewMode.VIEW)}> + Select Album Cover + + {/if} + {/if} + +
+ {#if viewMode === ViewMode.SELECT_ASSETS} + + {:else} + 0} + isSelectionMode={viewMode === ViewMode.SELECT_THUMBNAIL} + singleSelect={viewMode === ViewMode.SELECT_THUMBNAIL} + on:select={({ detail: asset }) => handleUpdateThumbnail(asset.id)} + on:escape={handleEscape} + > + {#if viewMode !== ViewMode.SELECT_THUMBNAIL} + +
+ e.key === 'Enter' && titleInput.blur()} + on:blur={handleUpdateName} + class="w-[99%] border-b-2 border-transparent text-6xl text-immich-primary outline-none transition-all dark:text-immich-dark-primary {isOwned + ? 'hover:border-gray-400' + : 'hover:border-transparent'} bg-immich-bg focus:border-b-2 focus:border-immich-primary focus:outline-none dark:bg-immich-dark-bg dark:focus:border-immich-dark-primary dark:focus:bg-immich-dark-gray" + type="text" + bind:value={album.albumName} + disabled={!isOwned} + bind:this={titleInput} + title="Edit Title" + /> + + + {#if album.assetCount > 0} + +

{getDateRange()}

+

·

+

{album.assetCount} items

+
+ {/if} + + + {#if album.sharedUsers.length > 0 || (album.hasSharedLink && isOwned)} +
+ + {#if album.hasSharedLink && isOwned} + (viewMode = ViewMode.LINK_SHARING)} + /> + {/if} + + + + + + {#each album.sharedUsers as user (user.id)} + + {/each} + + {#if isOwned} + (viewMode = ViewMode.SELECT_USERS)} + title="Add more users" + /> + {/if} +
+ {/if} + + + {#if isOwned || album.description} + + {/if} +
+ {/if} + + {#if album.assetCount === 0} +
+
+

ADD PHOTOS

+ +
+
+ {/if} +
+ {/if} + + {#if album.sharedUsers.length > 0 && !$showAssetViewer} +
+ +
+ {/if} +
+
+ {#if album.sharedUsers.length > 0 && album && isShowActivity && user && !$showAssetViewer} +
+
+ updateNumberOfComments(1)} + on:deleteComment={() => updateNumberOfComments(-1)} + on:deleteLike={() => (isLiked = null)} + on:close={handleOpenAndCloseActivityTab} + /> +
+
{/if} - - +
{#if viewMode === ViewMode.SELECT_USERS}