mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:39:37 -05:00 
			
		
		
		
	feat(web): select all duplicates (#10189)
* feat(web): select all duplicates Allows users to select or deselect all duplicate photos when removing duplicates * styling * chore(web): add more translations to duplicates page * color --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com> Co-authored-by: Zack Pollard <zackpollard@ymail.com>
This commit is contained in:
		
							parent
							
								
									ae095baad3
								
							
						
					
					
						commit
						52170423be
					
				@ -39,6 +39,16 @@
 | 
				
			|||||||
    selectedAssetIds = selectedAssetIds;
 | 
					    selectedAssetIds = selectedAssetIds;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const onSelectNone = () => {
 | 
				
			||||||
 | 
					    selectedAssetIds.clear();
 | 
				
			||||||
 | 
					    selectedAssetIds = selectedAssetIds;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const onSelectAll = () => {
 | 
				
			||||||
 | 
					    selectedAssetIds = new Set(duplicate.assets.map((asset) => asset.id));
 | 
				
			||||||
 | 
					    selectedAssetIds = selectedAssetIds;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleResolve = () => {
 | 
					  const handleResolve = () => {
 | 
				
			||||||
    const trashIds = duplicate.assets.map((asset) => asset.id).filter((id) => !selectedAssetIds.has(id));
 | 
					    const trashIds = duplicate.assets.map((asset) => asset.id).filter((id) => !selectedAssetIds.has(id));
 | 
				
			||||||
    const duplicateAssetIds = duplicate.assets.map((asset) => asset.id);
 | 
					    const duplicateAssetIds = duplicate.assets.map((asset) => asset.id);
 | 
				
			||||||
@ -76,7 +86,7 @@
 | 
				
			|||||||
            <div
 | 
					            <div
 | 
				
			||||||
              class="absolute top-2 right-3 bg-immich-primary/90 px-4 py-1 rounded-xl text-xs font-semibold text-white"
 | 
					              class="absolute top-2 right-3 bg-immich-primary/90 px-4 py-1 rounded-xl text-xs font-semibold text-white"
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              External
 | 
					              {$t('external')}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          {/if}
 | 
					          {/if}
 | 
				
			||||||
        </button>
 | 
					        </button>
 | 
				
			||||||
@ -117,18 +127,34 @@
 | 
				
			|||||||
    {/each}
 | 
					    {/each}
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <!-- CONFIRM BUTTONS -->
 | 
					  <div class="flex mt-10 mb-4 px-6 w-full place-content-end justify-between h-[45px]">
 | 
				
			||||||
  <div class="flex gap-4 my-4 border-transparent w-full justify-end p-4 h-[85px]">
 | 
					    <!-- MARK ALL BUTTONS -->
 | 
				
			||||||
    {#if trashCount === 0}
 | 
					    <div class="flex text-xs text-black">
 | 
				
			||||||
      <Button size="sm" color="primary" class="flex place-items-center gap-2" on:click={handleResolve}
 | 
					      <button
 | 
				
			||||||
        ><Icon path={mdiCheck} size="20" />Keep All
 | 
					        type="button"
 | 
				
			||||||
      </Button>
 | 
					        class="px-4 flex place-items-center gap-2 rounded-tl-full rounded-bl-full dark:bg-immich-dark-primary hover:dark:bg-immich-dark-primary/90 bg-immich-primary/25 hover:bg-immich-primary/50"
 | 
				
			||||||
    {:else}
 | 
					        on:click={onSelectAll}><Icon path={mdiCheck} size="20" />{$t('select_keep_all')}</button
 | 
				
			||||||
      <Button size="sm" color="red" class="flex place-items-center gap-2" on:click={handleResolve}
 | 
					      >
 | 
				
			||||||
        ><Icon path={mdiTrashCanOutline} size="20" />{trashCount === duplicate.assets.length
 | 
					      <button
 | 
				
			||||||
          ? $t('trash_all')
 | 
					        type="button"
 | 
				
			||||||
          : `Trash ${trashCount}`}
 | 
					        class="px-4 flex place-items-center gap-2 rounded-tr-full rounded-br-full dark:bg-immich-dark-primary/50 hover:dark:bg-immich-dark-primary/70 bg-immich-primary hover:bg-immich-primary/80 text-white"
 | 
				
			||||||
      </Button>
 | 
					        on:click={onSelectNone}><Icon path={mdiTrashCanOutline} size="20" />{$t('select_trash_all')}</button
 | 
				
			||||||
    {/if}
 | 
					      >
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- CONFIRM BUTTONS -->
 | 
				
			||||||
 | 
					    <div class="flex gap-4">
 | 
				
			||||||
 | 
					      {#if trashCount === 0}
 | 
				
			||||||
 | 
					        <Button size="sm" color="primary" class="flex place-items-center gap-2" on:click={handleResolve}
 | 
				
			||||||
 | 
					          ><Icon path={mdiCheck} size="20" />Keep All
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					      {:else}
 | 
				
			||||||
 | 
					        <Button size="sm" color="red" class="flex place-items-center gap-2" on:click={handleResolve}
 | 
				
			||||||
 | 
					          ><Icon path={mdiTrashCanOutline} size="20" />{trashCount === duplicate.assets.length
 | 
				
			||||||
 | 
					            ? $t('trash_all')
 | 
				
			||||||
 | 
					            : `${$t('trash')} ${trashCount}`}
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					      {/if}
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -514,6 +514,7 @@
 | 
				
			|||||||
  "export": "Export",
 | 
					  "export": "Export",
 | 
				
			||||||
  "export_as_json": "Export as JSON",
 | 
					  "export_as_json": "Export as JSON",
 | 
				
			||||||
  "extension": "Extension",
 | 
					  "extension": "Extension",
 | 
				
			||||||
 | 
					  "external": "External",
 | 
				
			||||||
  "external_libraries": "External Libraries",
 | 
					  "external_libraries": "External Libraries",
 | 
				
			||||||
  "failed_to_get_people": "Failed to get people",
 | 
					  "failed_to_get_people": "Failed to get people",
 | 
				
			||||||
  "favorite": "Favorite",
 | 
					  "favorite": "Favorite",
 | 
				
			||||||
@ -752,9 +753,11 @@
 | 
				
			|||||||
  "select_avatar_color": "Select avatar color",
 | 
					  "select_avatar_color": "Select avatar color",
 | 
				
			||||||
  "select_face": "Select face",
 | 
					  "select_face": "Select face",
 | 
				
			||||||
  "select_featured_photo": "Select featured photo",
 | 
					  "select_featured_photo": "Select featured photo",
 | 
				
			||||||
 | 
					  "select_keep_all": "Select keep all",
 | 
				
			||||||
  "select_library_owner": "Select library owner",
 | 
					  "select_library_owner": "Select library owner",
 | 
				
			||||||
  "select_new_face": "Select new face",
 | 
					  "select_new_face": "Select new face",
 | 
				
			||||||
  "select_photos": "Select photos",
 | 
					  "select_photos": "Select photos",
 | 
				
			||||||
 | 
					  "select_trash_all": "Select trash all",
 | 
				
			||||||
  "selected": "Selected",
 | 
					  "selected": "Selected",
 | 
				
			||||||
  "send_message": "Send message",
 | 
					  "send_message": "Send message",
 | 
				
			||||||
  "server": "Server",
 | 
					  "server": "Server",
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user