diff --git a/web/src/lib/components/elements/icon.svelte b/web/src/lib/components/elements/icon.svelte
index bb22276286..5965928718 100644
--- a/web/src/lib/components/elements/icon.svelte
+++ b/web/src/lib/components/elements/icon.svelte
@@ -16,13 +16,14 @@
   export let ariaLabelledby: string | undefined = undefined;
   export let strokeWidth: number = 0;
   export let strokeColor: string = 'currentColor';
+  export let spin = false;
 </script>
 
 <svg
   width={size}
   height={size}
   {viewBox}
-  class="{className} {flipped ? '-scale-x-100' : ''}"
+  class="{className} {flipped ? '-scale-x-100' : ''} {spin ? 'animate-spin' : ''}"
   {role}
   stroke={strokeColor}
   stroke-width={strokeWidth}
diff --git a/web/src/lib/components/shared-components/upload-asset-preview.svelte b/web/src/lib/components/shared-components/upload-asset-preview.svelte
index d3f12555c7..a7ba3430a0 100644
--- a/web/src/lib/components/shared-components/upload-asset-preview.svelte
+++ b/web/src/lib/components/shared-components/upload-asset-preview.svelte
@@ -1,21 +1,32 @@
 <script lang="ts">
+  import Icon from '$lib/components/elements/icon.svelte';
+  import { AppRoute } from '$lib/constants';
   import type { UploadAsset } from '$lib/models/upload-asset';
   import { UploadState } from '$lib/models/upload-asset';
   import { locale } from '$lib/stores/preferences.store';
-  import { getByteUnitString } from '$lib/utils/byte-units';
-  import { fade } from 'svelte/transition';
-  import ImmichLogo from './immich-logo.svelte';
-  import { getFilenameExtension } from '$lib/utils/asset-utils';
   import { uploadAssetsStore } from '$lib/stores/upload';
-  import Icon from '$lib/components/elements/icon.svelte';
+  import { getByteUnitString } from '$lib/utils/byte-units';
   import { fileUploadHandler } from '$lib/utils/file-uploader';
-  import { mdiRefresh, mdiCancel } from '@mdi/js';
+  import {
+    mdiAlertCircle,
+    mdiCheckCircle,
+    mdiCircleOutline,
+    mdiClose,
+    mdiLoading,
+    mdiOpenInNew,
+    mdiRestart,
+  } from '@mdi/js';
   import { t } from 'svelte-i18n';
+  import { fade } from 'svelte/transition';
 
   export let uploadAsset: UploadAsset;
 
+  const handleDismiss = (uploadAsset: UploadAsset) => {
+    uploadAssetsStore.removeItem(uploadAsset.id);
+  };
+
   const handleRetry = async (uploadAsset: UploadAsset) => {
-    uploadAssetsStore.removeUploadAsset(uploadAsset.id);
+    uploadAssetsStore.removeItem(uploadAsset.id);
     await fileUploadHandler([uploadAsset.file], uploadAsset.albumId);
   };
 </script>
@@ -23,86 +34,69 @@
 <div
   in:fade={{ duration: 250 }}
   out:fade={{ duration: 100 }}
-  class="flex flex-col rounded-lg bg-immich-bg text-xs dark:bg-immich-dark-bg"
+  class="flex flex-col rounded-lg bg-immich-bg text-xs dark:bg-immich-dark-bg p-2 gap-1"
 >
-  <div class="grid grid-cols-[65px_auto_auto] max-h-[70px]">
-    <div class="relative">
-      <div in:fade={{ duration: 250 }}>
-        <ImmichLogo noText class="h-[65px] w-[65px] rounded-bl-lg rounded-tl-lg object-cover p-2" />
-      </div>
-      <div class="absolute bottom-0 left-0 h-[25px] w-full rounded-bl-md bg-immich-primary/30">
-        <p
-          class="absolute bottom-1 right-1 stroke-immich-primary object-right-bottom font-semibold uppercase text-white/95 dark:text-gray-100"
-        >
-          .{getFilenameExtension(uploadAsset.file.name)}
-        </p>
-      </div>
+  <div class="flex items-center gap-2">
+    <div class="flex items-center justify-center">
+      {#if uploadAsset.state === UploadState.PENDING}
+        <Icon path={mdiCircleOutline} size="24" class="text-immich-primary" title={$t('pending')} />
+      {:else if uploadAsset.state === UploadState.STARTED}
+        <Icon path={mdiLoading} size="24" spin class="text-immich-primary" title={$t('asset_skipped')} />
+      {:else if uploadAsset.state === UploadState.ERROR}
+        <Icon path={mdiAlertCircle} size="24" class="text-immich-error" title={$t('error')} />
+      {:else if uploadAsset.state === UploadState.DUPLICATED}
+        <Icon path={mdiAlertCircle} size="24" class="text-immich-warning" title={$t('asset_skipped')} />
+      {:else if uploadAsset.state === UploadState.DONE}
+        <Icon path={mdiCheckCircle} size="24" class="text-immich-success" title={$t('asset_uploaded')} />
+      {/if}
     </div>
-    <div class="flex flex-col justify-between p-2 pr-2">
-      <input
-        disabled
-        class="w-full rounded-md border bg-gray-100 p-1 px-2 text-[10px] dark:border-immich-dark-gray dark:bg-gray-900"
-        value={`[${getByteUnitString(uploadAsset.file.size, $locale)}] ${uploadAsset.file.name}`}
-      />
+    <!-- <span>[{getByteUnitString(uploadAsset.file.size, $locale)}]</span> -->
+    <span class="grow break-all">{uploadAsset.file.name}</span>
 
-      <div
-        class="relative mt-[5px] h-[15px] w-full rounded-md bg-gray-300 text-white dark:bg-immich-dark-gray"
-        class:dark:text-black={uploadAsset.state === UploadState.STARTED}
-      >
-        {#if uploadAsset.state === UploadState.STARTED}
-          <div class="h-[15px] rounded-md bg-immich-primary transition-all" style={`width: ${uploadAsset.progress}%`} />
-          <p class="absolute top-0 h-full w-full text-center text-[10px]">
-            {#if uploadAsset.message}
-              {uploadAsset.message}
-            {:else}
-              {uploadAsset.progress}% - {getByteUnitString(uploadAsset.speed || 0, $locale)}/s - {uploadAsset.eta}s
-            {/if}
-          </p>
-        {:else if uploadAsset.state === UploadState.PENDING}
-          <div class="h-[15px] rounded-md bg-immich-dark-gray transition-all dark:bg-immich-gray" style="width: 100%" />
-          <p class="absolute top-0 h-full w-full text-center text-[10px]">{$t('pending')}</p>
-        {:else if uploadAsset.state === UploadState.ERROR}
-          <div class="h-[15px] rounded-md bg-immich-error transition-all" style="width: 100%" />
-          <p class="absolute top-0 h-full w-full text-center text-[10px]">{$t('error')}</p>
-        {:else if uploadAsset.state === UploadState.DUPLICATED}
-          <div class="h-[15px] rounded-md bg-immich-warning transition-all" style="width: 100%" />
-          <p class="absolute top-0 h-full w-full text-center text-[10px]">
-            {$t('asset_skipped')}
-            {#if uploadAsset.message}
-              ({uploadAsset.message})
-            {/if}
-          </p>
-        {:else if uploadAsset.state === UploadState.DONE}
-          <div class="h-[15px] rounded-md bg-immich-success transition-all" style="width: 100%" />
-          <p class="absolute top-0 h-full w-full text-center text-[10px]">
-            {$t('asset_uploaded')}
-            {#if uploadAsset.message}
-              ({uploadAsset.message})
-            {/if}
-          </p>
-        {/if}
-      </div>
-    </div>
-    {#if uploadAsset.state === UploadState.ERROR}
-      <div class="flex h-full flex-col place-content-evenly place-items-center justify-items-center pr-2">
-        <button type="button" on:click={() => handleRetry(uploadAsset)} title={$t('retry_upload')} class="flex text-sm">
-          <span class="text-immich-dark-gray dark:text-immich-dark-fg"><Icon path={mdiRefresh} size="20" /></span>
-        </button>
-        <button
-          type="button"
-          on:click={() => uploadAssetsStore.removeUploadAsset(uploadAsset.id)}
-          title={$t('dismiss_error')}
-          class="flex text-sm"
+    {#if uploadAsset.state === UploadState.DUPLICATED && uploadAsset.assetId}
+      <div class="flex items-center justify-between gap-1">
+        <a
+          href="{AppRoute.PHOTOS}/{uploadAsset.assetId}"
+          target="_blank"
+          rel="noopener noreferrer"
+          class=""
+          aria-hidden="true"
+          tabindex={-1}
         >
-          <span class="text-immich-error"><Icon path={mdiCancel} size="20" /></span>
+          <Icon path={mdiOpenInNew} size="20" />
+        </a>
+        <button type="button" on:click={() => handleDismiss(uploadAsset)} class="" aria-hidden="true" tabindex={-1}>
+          <Icon path={mdiClose} size="20" />
+        </button>
+      </div>
+    {:else if uploadAsset.state === UploadState.ERROR}
+      <div class="flex items-center justify-between gap-1">
+        <button type="button" on:click={() => handleRetry(uploadAsset)} class="" aria-hidden="true" tabindex={-1}>
+          <Icon path={mdiRestart} size="20" />
+        </button>
+        <button type="button" on:click={() => handleDismiss(uploadAsset)} class="" aria-hidden="true" tabindex={-1}>
+          <Icon path={mdiClose} size="20" />
         </button>
       </div>
     {/if}
   </div>
 
+  {#if uploadAsset.state === UploadState.STARTED}
+    <div class="text-black relative mt-[5px] h-[15px] w-full rounded-md bg-gray-300 dark:bg-immich-dark-gray">
+      <div class="h-[15px] rounded-md bg-immich-primary transition-all" style={`width: ${uploadAsset.progress}%`} />
+      <p class="absolute top-0 h-full w-full text-center text-[10px]">
+        {#if uploadAsset.message}
+          {uploadAsset.message}
+        {:else}
+          {uploadAsset.progress}% - {getByteUnitString(uploadAsset.speed || 0, $locale)}/s - {uploadAsset.eta}s
+        {/if}
+      </p>
+    </div>
+  {/if}
+
   {#if uploadAsset.state === UploadState.ERROR}
     <div class="flex flex-row justify-between">
-      <p class="w-full rounded-md py-1 px-2 text-justify text-[10px] text-immich-error">
+      <p class="w-full rounded-md text-justify text-immich-error">
         {uploadAsset.error}
       </p>
     </div>
diff --git a/web/src/lib/components/shared-components/upload-panel.svelte b/web/src/lib/components/shared-components/upload-panel.svelte
index ee213d7969..d536053286 100644
--- a/web/src/lib/components/shared-components/upload-panel.svelte
+++ b/web/src/lib/components/shared-components/upload-panel.svelte
@@ -15,8 +15,7 @@
   let showOptions = false;
   let concurrency = uploadExecutionQueue.concurrency;
 
-  let { isUploading, hasError, remainingUploads, errorCounter, duplicateCounter, successCounter, totalUploadCounter } =
-    uploadAssetsStore;
+  let { stats, isDismissible, isUploading, remainingUploads } = uploadAssetsStore;
 
   const autoHide = () => {
     if (!$isUploading && showDetail) {
@@ -33,29 +32,29 @@
   }
 </script>
 
-{#if $hasError || $isUploading}
+{#if $isUploading}
   <div
     in:fade={{ duration: 250 }}
     out:fade={{ duration: 250 }}
     on:outroend={() => {
-      if ($errorCounter > 0) {
+      if ($stats.errors > 0) {
         notificationController.show({
-          message: $t('upload_errors', { values: { count: $errorCounter } }),
+          message: $t('upload_errors', { values: { count: $stats.errors } }),
           type: NotificationType.Warning,
         });
-      } else if ($successCounter > 0) {
+      } else if ($stats.success > 0) {
         notificationController.show({
           message: $t('upload_success'),
           type: NotificationType.Info,
         });
       }
-      if ($duplicateCounter > 0) {
+      if ($stats.duplicates > 0) {
         notificationController.show({
-          message: $t('upload_skipped_duplicates', { values: { count: $duplicateCounter } }),
+          message: $t('upload_skipped_duplicates', { values: { count: $stats.duplicates } }),
           type: NotificationType.Warning,
         });
       }
-      uploadAssetsStore.resetStore();
+      uploadAssetsStore.reset();
     }}
     class="fixed bottom-6 right-6 z-[10000]"
   >
@@ -70,20 +69,20 @@
               {$t('upload_progress', {
                 values: {
                   remaining: $remainingUploads,
-                  processed: $successCounter + $errorCounter,
-                  total: $totalUploadCounter,
+                  processed: $stats.total - $remainingUploads,
+                  total: $stats.total,
                 },
               })}
             </p>
             <p class="immich-form-label text-xs">
               {$t('upload_status_uploaded')}
-              <span class="text-immich-success">{$successCounter.toLocaleString($locale)}</span>
+              <span class="text-immich-success">{$stats.success.toLocaleString($locale)}</span>
               -
               {$t('upload_status_errors')}
-              <span class="text-immich-error">{$errorCounter.toLocaleString($locale)}</span>
+              <span class="text-immich-error">{$stats.errors.toLocaleString($locale)}</span>
               -
               {$t('upload_status_duplicates')}
-              <span class="text-immich-warning">{$duplicateCounter.toLocaleString($locale)}</span>
+              <span class="text-immich-warning">{$stats.duplicates.toLocaleString($locale)}</span>
             </p>
           </div>
           <div class="flex flex-col items-end">
@@ -103,7 +102,7 @@
                 on:click={() => (showDetail = false)}
               />
             </div>
-            {#if $hasError}
+            {#if $isDismissible}
               <CircleIconButton
                 title={$t('dismiss_all_errors')}
                 icon={mdiCancel}
@@ -115,7 +114,7 @@
           </div>
         </div>
         {#if showOptions}
-          <div class="immich-scrollbar mb-4 max-h-[400px] overflow-y-auto rounded-lg pr-2">
+          <div class="immich-scrollbar mb-4 max-h-[400px] overflow-y-auto rounded-lg">
             <div class="flex h-[26px] place-items-center gap-1">
               <label class="immich-form-label" for="upload-concurrency">{$t('upload_concurrency')}</label>
             </div>
@@ -133,7 +132,7 @@
             />
           </div>
         {/if}
-        <div class="immich-scrollbar flex max-h-[400px] flex-col gap-2 overflow-y-auto rounded-lg pr-2">
+        <div class="immich-scrollbar flex max-h-[400px] flex-col gap-2 overflow-y-auto rounded-lg">
           {#each $uploadAssetsStore as uploadAsset (uploadAsset.id)}
             <UploadAssetPreview {uploadAsset} />
           {/each}
@@ -149,14 +148,14 @@
         >
           {$remainingUploads.toLocaleString($locale)}
         </button>
-        {#if $hasError}
+        {#if $stats.errors > 0}
           <button
             type="button"
             in:scale={{ duration: 250, easing: quartInOut }}
             on:click={() => (showDetail = true)}
             class="absolute -right-4 -top-4 flex h-10 w-10 place-content-center place-items-center rounded-full bg-immich-error p-5 text-xs text-gray-200"
           >
-            {$errorCounter.toLocaleString($locale)}
+            {$stats.errors.toLocaleString($locale)}
           </button>
         {/if}
         <button
diff --git a/web/src/lib/models/upload-asset.ts b/web/src/lib/models/upload-asset.ts
index c213f77e3e..eb8cb44c5e 100644
--- a/web/src/lib/models/upload-asset.ts
+++ b/web/src/lib/models/upload-asset.ts
@@ -9,8 +9,8 @@ export enum UploadState {
 export type UploadAsset = {
   id: string;
   file: File;
-  albumId?: string;
   assetId?: string;
+  albumId?: string;
   progress?: number;
   state?: UploadState;
   startDate?: number;
diff --git a/web/src/lib/stores/upload.ts b/web/src/lib/stores/upload.ts
index 16f967edb6..4bf597b932 100644
--- a/web/src/lib/stores/upload.ts
+++ b/web/src/lib/stores/upload.ts
@@ -3,32 +3,36 @@ import { UploadState, type UploadAsset } from '../models/upload-asset';
 
 function createUploadStore() {
   const uploadAssets = writable<Array<UploadAsset>>([]);
-
-  const duplicateCounter = writable(0);
-  const successCounter = writable(0);
-  const totalUploadCounter = writable(0);
+  const stats = writable<{ errors: number; duplicates: number; success: number; total: number }>({
+    errors: 0,
+    duplicates: 0,
+    success: 0,
+    total: 0,
+  });
 
   const { subscribe } = uploadAssets;
 
-  const isUploading = derived(uploadAssets, ($uploadAssets) => {
-    return $uploadAssets.length > 0;
-  });
-  const errorsAssets = derived(uploadAssets, (a) => a.filter((e) => e.state === UploadState.ERROR));
-  const errorCounter = derived(errorsAssets, (values) => values.length);
-  const hasError = derived(errorCounter, (values) => values > 0);
+  const isUploading = derived(uploadAssets, (items) => items.length > 0);
+  const isDismissible = derived(uploadAssets, (items) =>
+    items.some((item) => item.state === UploadState.ERROR || item.state === UploadState.DUPLICATED),
+  );
   const remainingUploads = derived(
     uploadAssets,
     (values) => values.filter((a) => a.state === UploadState.PENDING || a.state === UploadState.STARTED).length,
   );
 
-  const addNewUploadAsset = (newAsset: UploadAsset) => {
+  const addItem = (newAsset: UploadAsset) => {
     uploadAssets.update(($assets) => {
       const duplicate = $assets.find((asset) => asset.id === newAsset.id);
       if (duplicate) {
         return $assets.map((asset) => (asset.id === newAsset.id ? newAsset : asset));
       }
 
-      totalUploadCounter.update((c) => c + 1);
+      stats.update((stats) => {
+        stats.total++;
+        return stats;
+      });
+
       $assets.push({
         ...newAsset,
         speed: 0,
@@ -36,6 +40,7 @@ function createUploadStore() {
         progress: 0,
         eta: 0,
       });
+
       return $assets;
     });
   };
@@ -53,7 +58,7 @@ function createUploadStore() {
   };
 
   const markStarted = (id: string) => {
-    updateAsset(id, {
+    updateItem(id, {
       state: UploadState.STARTED,
       startDate: Date.now(),
     });
@@ -70,39 +75,61 @@ function createUploadStore() {
     });
   };
 
-  const updateAsset = (id: string, partialObject: Partial<UploadAsset>) => {
+  const updateItem = (id: string, partialObject: Partial<UploadAsset>) => {
     updateAssetMap(id, (v) => ({ ...v, ...partialObject }));
   };
 
-  const removeUploadAsset = (id: string) => {
+  const removeItem = (id: string) => {
     uploadAssets.update((uploadingAsset) => uploadingAsset.filter((a) => a.id != id));
   };
 
-  const dismissErrors = () => uploadAssets.update((value) => value.filter((e) => e.state !== UploadState.ERROR));
+  const dismissErrors = () =>
+    uploadAssets.update((value) =>
+      value.filter((e) => e.state !== UploadState.ERROR && e.state !== UploadState.DUPLICATED),
+    );
 
-  const resetStore = () => {
+  const reset = () => {
     uploadAssets.set([]);
-    duplicateCounter.set(0);
-    successCounter.set(0);
-    totalUploadCounter.set(0);
+    stats.set({ errors: 0, duplicates: 0, success: 0, total: 0 });
+  };
+
+  const track = (value: 'success' | 'duplicate' | 'error') => {
+    stats.update((stats) => {
+      switch (value) {
+        case 'success': {
+          stats.success++;
+          break;
+        }
+
+        case 'duplicate': {
+          stats.duplicates++;
+          break;
+        }
+
+        case 'error': {
+          stats.errors++;
+          break;
+        }
+      }
+
+      return stats;
+    });
   };
 
   return {
-    subscribe,
-    errorCounter,
-    duplicateCounter,
-    successCounter,
-    totalUploadCounter,
+    stats,
     remainingUploads,
-    hasError,
-    dismissErrors,
+    isDismissible,
     isUploading,
-    resetStore,
-    addNewUploadAsset,
+    track,
+    dismissErrors,
+    reset,
     markStarted,
+    addItem,
+    updateItem,
+    removeItem,
     updateProgress,
-    updateAsset,
-    removeUploadAsset,
+    subscribe,
   };
 }
 
diff --git a/web/src/lib/utils/file-uploader.ts b/web/src/lib/utils/file-uploader.ts
index 2d244e9bea..d7275c8aa3 100644
--- a/web/src/lib/utils/file-uploader.ts
+++ b/web/src/lib/utils/file-uploader.ts
@@ -17,6 +17,25 @@ import { t } from 'svelte-i18n';
 import { get } from 'svelte/store';
 import { getServerErrorMessage, handleError } from './handle-error';
 
+export const addDummyItems = () => {
+  uploadAssetsStore.addItem({ id: 'asset-0', file: { name: 'asset0.jpg', size: 123_456 } as File });
+  uploadAssetsStore.updateItem('asset-0', { state: UploadState.PENDING });
+  uploadAssetsStore.addItem({ id: 'asset-1', file: { name: 'asset1.jpg', size: 123_456 } as File });
+  uploadAssetsStore.updateItem('asset-1', { state: UploadState.STARTED });
+  uploadAssetsStore.updateProgress('asset-1', 75, 100);
+  uploadAssetsStore.addItem({ id: 'asset-2', file: { name: 'asset2.jpg', size: 123_456 } as File });
+  uploadAssetsStore.updateItem('asset-2', { state: UploadState.ERROR, error: new Error('Internal server error') });
+  uploadAssetsStore.addItem({ id: 'asset-3', file: { name: 'asset3.jpg', size: 123_456 } as File });
+  uploadAssetsStore.updateItem('asset-3', { state: UploadState.DUPLICATED, assetId: 'asset-2' });
+  uploadAssetsStore.addItem({ id: 'asset-4', file: { name: 'asset3.jpg', size: 123_456 } as File });
+  uploadAssetsStore.updateItem('asset-4', { state: UploadState.DONE });
+  uploadAssetsStore.track('error');
+  uploadAssetsStore.track('success');
+  uploadAssetsStore.track('duplicate');
+};
+
+// addDummyItems();
+
 let _extensions: string[];
 
 export const uploadExecutionQueue = new ExecutorQueue({ concurrency: 2 });
@@ -68,7 +87,7 @@ export const fileUploadHandler = async (files: File[], albumId?: string, assetId
   for (const file of files) {
     const name = file.name.toLowerCase();
     if (extensions.some((extension) => name.endsWith(extension))) {
-      uploadAssetsStore.addNewUploadAsset({ id: getDeviceAssetId(file), file, albumId, assetId });
+      uploadAssetsStore.addItem({ id: getDeviceAssetId(file), file, albumId });
       promises.push(uploadExecutionQueue.addTask(() => fileUploader(file, albumId, assetId)));
     }
   }
@@ -106,7 +125,7 @@ async function fileUploader(assetFile: File, albumId?: string, replaceAssetId?:
     let responseData: AssetMediaResponseDto | undefined;
     const key = getKey();
     if (crypto?.subtle?.digest && !key) {
-      uploadAssetsStore.updateAsset(deviceAssetId, { message: $t('asset_hashing') });
+      uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_hashing') });
       await tick();
       try {
         const bytes = await assetFile.arrayBuffer();
@@ -127,7 +146,7 @@ async function fileUploader(assetFile: File, albumId?: string, replaceAssetId?:
     }
 
     if (!responseData) {
-      uploadAssetsStore.updateAsset(deviceAssetId, { message: $t('asset_uploading') });
+      uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_uploading') });
       if (replaceAssetId) {
         const response = await uploadRequest<AssetMediaResponseDto>({
           url: getBaseUrl() + getAssetOriginalPath(replaceAssetId) + (key ? `?key=${key}` : ''),
@@ -152,30 +171,34 @@ async function fileUploader(assetFile: File, albumId?: string, replaceAssetId?:
     }
 
     if (responseData.status === AssetMediaStatus.Duplicate) {
-      uploadAssetsStore.duplicateCounter.update((count) => count + 1);
+      uploadAssetsStore.track('duplicate');
     } else {
-      uploadAssetsStore.successCounter.update((c) => c + 1);
+      uploadAssetsStore.track('success');
     }
 
     if (albumId) {
-      uploadAssetsStore.updateAsset(deviceAssetId, { message: $t('asset_adding_to_album') });
+      uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_adding_to_album') });
       await addAssetsToAlbum(albumId, [responseData.id], false);
-      uploadAssetsStore.updateAsset(deviceAssetId, { message: $t('asset_added_to_album') });
+      uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_added_to_album') });
     }
 
-    uploadAssetsStore.updateAsset(deviceAssetId, {
+    uploadAssetsStore.updateItem(deviceAssetId, {
       state: responseData.status === AssetMediaStatus.Duplicate ? UploadState.DUPLICATED : UploadState.DONE,
+      assetId: responseData.id,
     });
 
-    setTimeout(() => {
-      uploadAssetsStore.removeUploadAsset(deviceAssetId);
-    }, 1000);
+    if (responseData.status !== AssetMediaStatus.Duplicate) {
+      setTimeout(() => {
+        uploadAssetsStore.removeItem(deviceAssetId);
+      }, 1000);
+    }
 
     return responseData.id;
   } catch (error) {
     handleError(error, $t('errors.unable_to_upload_file'));
     const reason = getServerErrorMessage(error) || error;
-    uploadAssetsStore.updateAsset(deviceAssetId, { state: UploadState.ERROR, error: reason });
+    uploadAssetsStore.track('error');
+    uploadAssetsStore.updateItem(deviceAssetId, { state: UploadState.ERROR, error: reason });
     return;
   }
 }