Parcourir la source

feat(web): Allow showing hidden people in image asset details view (#5420)

* Allow showing hidden people in image asset details view

This makes it possible to easily find people/faces that have accidentally been hidden.
Unhiding them still requires clicking on the person to go to their page to unhide them.

* Update web/src/lib/components/asset-viewer/detail-panel.svelte

Co-authored-by: martin <74269598+martabal@users.noreply.github.com>

---------

Co-authored-by: brokeh <git@brocky.net>
Co-authored-by: martin <74269598+martabal@users.noreply.github.com>
Andrew Brock il y a 1 an
Parent
commit
a02e91169d

+ 1 - 1
server/src/domain/asset/response-dto/asset-response.dto.ts

@@ -98,7 +98,7 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
     tags: entity.tags?.map(mapTag),
     people: entity.faces
       ?.map(mapFace)
-      .filter((person): person is PersonResponseDto => person !== null && !person.isHidden)
+      .filter((person): person is PersonResponseDto => person !== null)
       .reduce((people, person) => {
         const existingPerson = people.find((p) => p.id === person.id);
         if (!existingPerson) {

+ 30 - 13
web/src/lib/components/asset-viewer/detail-panel.svelte

@@ -19,8 +19,11 @@
     mdiImageOutline,
     mdiMapMarkerOutline,
     mdiInformationOutline,
+    mdiEye,
+    mdiEyeOff,
   } from '@mdi/js';
   import Icon from '$lib/components/elements/icon.svelte';
+  import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
   import Map from '../shared-components/map/map.svelte';
   import { websocketStore } from '$lib/stores/websocket';
   import { AppRoute } from '$lib/constants';
@@ -57,6 +60,7 @@
   })();
 
   $: people = asset.people || [];
+  $: showingHiddenPeople = false;
 
   const unsubscribe = websocketStore.onAssetUpdate.subscribe((assetUpdate) => {
     if (assetUpdate && assetUpdate.id === asset.id) {
@@ -177,25 +181,38 @@
 
   {#if !api.isSharedLink && people.length > 0}
     <section class="px-4 py-4 text-sm">
-      <h2>PEOPLE</h2>
+      <div class="flex h-10 w-full items-center justify-between">
+        <h2>PEOPLE</h2>
+        {#if people.some((person) => person.isHidden)}
+          <CircleIconButton
+            title="Show hidden people"
+            icon={showingHiddenPeople ? mdiEyeOff : mdiEye}
+            padding="1"
+            on:click={() => (showingHiddenPeople = !showingHiddenPeople)}
+          />
+        {/if}
+      </div>
 
-      <div class="mt-4 flex flex-wrap gap-2">
+      <div class="mt-2 flex flex-wrap gap-2">
         {#each people as person (person.id)}
           <a
             href="/people/{person.id}?previousRoute={albumId ? `${AppRoute.ALBUMS}/${albumId}` : AppRoute.PHOTOS}"
-            class="w-[90px]"
+            class="w-[90px] {!showingHiddenPeople && person.isHidden ? 'hidden' : ''}"
             on:click={() => dispatch('close-viewer')}
           >
-            <ImageThumbnail
-              curve
-              shadow
-              url={api.getPeopleThumbnailUrl(person.id)}
-              altText={person.name}
-              title={person.name}
-              widthStyle="90px"
-              heightStyle="90px"
-              thumbhash={null}
-            />
+            <div class="relative">
+              <ImageThumbnail
+                curve
+                shadow
+                url={api.getPeopleThumbnailUrl(person.id)}
+                altText={person.name}
+                title={person.name}
+                widthStyle="90px"
+                heightStyle="90px"
+                thumbhash={null}
+                hidden={person.isHidden}
+              />
+            </div>
             <p class="mt-1 truncate font-medium" title={person.name}>{person.name}</p>
             {#if person.birthDate}
               {@const personBirthDate = DateTime.fromISO(person.birthDate)}