feat(web): Shared album owner labels (#21171)

* - pass available album users along to the thumbnail through the asset-date-group
- show a small user-avatar in bottom right of thumbnail

* - change owner to their name in white text instead of the avatar

* cleanup

* - cleanup albumUsers creation
- use font-light for the user's name

* fix lint

* format

* - add toggle to show/hide asset owner names

* update new Timeline with albumUsers

* add @idubnori suggestion for the name font

* Don't show 'view owners' button if the album doesn't have editors

* add missing import

* format

* fix(web): #21171 (#24298)

fix: Bind timelineManager to Timeline component

---------

Co-authored-by: idubnori <i.dub.nori@gmail.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Chris Peckover
2025-11-30 13:56:03 -05:00
committed by GitHub
parent e3ab16a5bd
commit 922282b2b4
3 changed files with 36 additions and 2 deletions
@@ -66,6 +66,7 @@
} from '@immich/sdk';
import { Button, Icon, IconButton, modalManager, toastManager } from '@immich/ui';
import {
mdiAccountEyeOutline,
mdiArrowLeft,
mdiCogOutline,
mdiDeleteOutline,
@@ -100,6 +101,7 @@
let isCreatingSharedAlbum = $state(false);
let isShowActivity = $state(false);
let albumOrder: AssetOrder | undefined = $state(data.album.order);
let showAlbumUsers = $state(false);
const assetInteraction = new AssetInteraction();
const timelineInteraction = new AssetInteraction();
@@ -290,6 +292,11 @@
let album = $derived(data.album);
let albumId = $derived(album.id);
const containsEditors = $derived(album?.shared && album.albumUsers.some(({ role }) => role === AlbumUserRole.Editor));
const albumUsers = $derived(
showAlbumUsers && containsEditors ? [album.owner, ...album.albumUsers.map(({ user }) => user)] : [],
);
$effect(() => {
if (!album.isActivityEnabled && activityManager.commentCount === 0) {
isShowActivity = false;
@@ -418,6 +425,7 @@
<Timeline
enableRouting={viewMode === AlbumPageViewMode.SELECT_ASSETS ? false : true}
{album}
{albumUsers}
bind:timelineManager
{options}
assetInteraction={currentAssetIntersection}
@@ -597,6 +605,17 @@
{#snippet trailing()}
<CastButton />
{#if containsEditors}
<IconButton
variant="ghost"
shape="round"
color="secondary"
aria-label="view asset owners"
icon={mdiAccountEyeOutline}
onclick={() => (showAlbumUsers = !showAlbumUsers)}
/>
{/if}
{#if isEditor}
<IconButton
variant="ghost"