mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:27:09 -05:00 
			
		
		
		
	fix(web): properly update activityManager when browsing assets (#18909)
This commit is contained in:
		
							parent
							
								
									94e9adf625
								
							
						
					
					
						commit
						0322a8b1d9
					
				@ -138,16 +138,6 @@
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const updateComments = async () => {
 | 
			
		||||
    if (album) {
 | 
			
		||||
      try {
 | 
			
		||||
        await activityManager.refreshActivities(album.id, asset.id);
 | 
			
		||||
      } catch (error) {
 | 
			
		||||
        handleError(error, $t('errors.unable_to_get_comments_number'));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const onAssetUpdate = ({ asset: assetUpdate }: { event: 'upload' | 'update'; asset: AssetResponseDto }) => {
 | 
			
		||||
    if (assetUpdate.id === asset.id) {
 | 
			
		||||
      asset = assetUpdate;
 | 
			
		||||
@ -180,10 +170,6 @@
 | 
			
		||||
    if (!sharedLink) {
 | 
			
		||||
      await handleGetAllAlbums();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (album) {
 | 
			
		||||
      activityManager.init(album.id, asset.id);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  onDestroy(() => {
 | 
			
		||||
@ -370,8 +356,8 @@
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  $effect(() => {
 | 
			
		||||
    if (isShared && asset.id) {
 | 
			
		||||
      handlePromiseError(updateComments());
 | 
			
		||||
    if (album && isShared && asset.id) {
 | 
			
		||||
      handlePromiseError(activityManager.init(album.id, asset.id));
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  $effect(() => {
 | 
			
		||||
@ -510,7 +496,7 @@
 | 
			
		||||
            onVideoStarted={handleVideoStarted}
 | 
			
		||||
          />
 | 
			
		||||
        {/if}
 | 
			
		||||
        {#if $slideshowState === SlideshowState.None && isShared && ((album && album.isActivityEnabled) || activityManager.commentCount > 0)}
 | 
			
		||||
        {#if $slideshowState === SlideshowState.None && isShared && ((album && album.isActivityEnabled) || activityManager.commentCount > 0) && !activityManager.isLoading}
 | 
			
		||||
          <div class="absolute bottom-0 end-0 mb-20 me-8">
 | 
			
		||||
            <ActivityStatus
 | 
			
		||||
              disabled={!album?.isActivityEnabled}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
import { user } from '$lib/stores/user.store';
 | 
			
		||||
import { handlePromiseError } from '$lib/utils';
 | 
			
		||||
import { handleError } from '$lib/utils/handle-error';
 | 
			
		||||
import {
 | 
			
		||||
  createActivity,
 | 
			
		||||
  deleteActivity,
 | 
			
		||||
@ -10,8 +11,17 @@ import {
 | 
			
		||||
  type ActivityCreateDto,
 | 
			
		||||
  type ActivityResponseDto,
 | 
			
		||||
} from '@immich/sdk';
 | 
			
		||||
import { t } from 'svelte-i18n';
 | 
			
		||||
import { get } from 'svelte/store';
 | 
			
		||||
 | 
			
		||||
type CacheKey = string;
 | 
			
		||||
type ActivityCache = {
 | 
			
		||||
  activities: ActivityResponseDto[];
 | 
			
		||||
  commentCount: number;
 | 
			
		||||
  likeCount: number;
 | 
			
		||||
  isLiked: ActivityResponseDto | null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ActivityManager {
 | 
			
		||||
  #albumId = $state<string | undefined>();
 | 
			
		||||
  #assetId = $state<string | undefined>();
 | 
			
		||||
@ -20,6 +30,14 @@ class ActivityManager {
 | 
			
		||||
  #likeCount = $state(0);
 | 
			
		||||
  #isLiked = $state<ActivityResponseDto | null>(null);
 | 
			
		||||
 | 
			
		||||
  #cache = new Map<CacheKey, ActivityCache>();
 | 
			
		||||
 | 
			
		||||
  isLoading = $state(false);
 | 
			
		||||
 | 
			
		||||
  get assetId() {
 | 
			
		||||
    return this.#assetId;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get activities() {
 | 
			
		||||
    return this.#activities;
 | 
			
		||||
  }
 | 
			
		||||
@ -36,9 +54,27 @@ class ActivityManager {
 | 
			
		||||
    return this.#isLiked;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  init(albumId: string, assetId?: string) {
 | 
			
		||||
  #getCacheKey(albumId: string, assetId?: string) {
 | 
			
		||||
    return `${albumId}:${assetId ?? ''}`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async init(albumId: string, assetId?: string) {
 | 
			
		||||
    if (assetId && assetId === this.#assetId) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.#albumId = albumId;
 | 
			
		||||
    this.#assetId = assetId;
 | 
			
		||||
    try {
 | 
			
		||||
      await activityManager.refreshActivities(albumId, assetId);
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      handleError(error, get(t)('errors.unable_to_get_comments_number'));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #invalidateCache(albumId: string, assetId?: string) {
 | 
			
		||||
    this.#cache.delete(this.#getCacheKey(albumId));
 | 
			
		||||
    this.#cache.delete(this.#getCacheKey(albumId, assetId));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async addActivity(dto: ActivityCreateDto) {
 | 
			
		||||
@ -57,6 +93,7 @@ class ActivityManager {
 | 
			
		||||
      this.#likeCount++;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.#invalidateCache(this.#albumId, this.#assetId);
 | 
			
		||||
    handlePromiseError(this.refreshActivities(this.#albumId, this.#assetId));
 | 
			
		||||
    return activity;
 | 
			
		||||
  }
 | 
			
		||||
@ -79,6 +116,7 @@ class ActivityManager {
 | 
			
		||||
      : this.#activities.filter(({ id }) => id !== activity.id);
 | 
			
		||||
 | 
			
		||||
    await deleteActivity({ id: activity.id });
 | 
			
		||||
    this.#invalidateCache(this.#albumId, this.#assetId);
 | 
			
		||||
    handlePromiseError(this.refreshActivities(this.#albumId, this.#assetId));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -100,6 +138,20 @@ class ActivityManager {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async refreshActivities(albumId: string, assetId?: string) {
 | 
			
		||||
    this.isLoading = true;
 | 
			
		||||
 | 
			
		||||
    const cacheKey = this.#getCacheKey(albumId, assetId);
 | 
			
		||||
 | 
			
		||||
    if (this.#cache.has(cacheKey)) {
 | 
			
		||||
      const cached = this.#cache.get(cacheKey)!;
 | 
			
		||||
      this.#activities = cached.activities;
 | 
			
		||||
      this.#commentCount = cached.commentCount;
 | 
			
		||||
      this.#likeCount = cached.likeCount;
 | 
			
		||||
      this.#isLiked = cached.isLiked ?? null;
 | 
			
		||||
      this.isLoading = false;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.#activities = await getActivities({ albumId, assetId });
 | 
			
		||||
 | 
			
		||||
    const [liked] = await getActivities({
 | 
			
		||||
@ -114,6 +166,15 @@ class ActivityManager {
 | 
			
		||||
    const { comments, likes } = await getActivityStatistics({ albumId, assetId });
 | 
			
		||||
    this.#commentCount = comments;
 | 
			
		||||
    this.#likeCount = likes;
 | 
			
		||||
 | 
			
		||||
    this.#cache.set(cacheKey, {
 | 
			
		||||
      activities: this.#activities,
 | 
			
		||||
      commentCount: this.#commentCount,
 | 
			
		||||
      likeCount: this.#likeCount,
 | 
			
		||||
      isLiked: this.#isLiked,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    this.isLoading = false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  reset() {
 | 
			
		||||
 | 
			
		||||
@ -159,14 +159,6 @@
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const updateComments = async () => {
 | 
			
		||||
    try {
 | 
			
		||||
      await activityManager.refreshActivities(album.id);
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      handleError(error, $t('errors.cant_get_number_of_comments'));
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const handleOpenAndCloseActivityTab = () => {
 | 
			
		||||
    isShowActivity = !isShowActivity;
 | 
			
		||||
  };
 | 
			
		||||
@ -388,9 +380,14 @@
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const isShared = $derived(viewMode === AlbumPageViewMode.SELECT_ASSETS ? false : album.albumUsers.length > 0);
 | 
			
		||||
 | 
			
		||||
  $effect(() => {
 | 
			
		||||
    activityManager.reset();
 | 
			
		||||
    activityManager.init(album.id);
 | 
			
		||||
    if ($showAssetViewer || !isShared) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handlePromiseError(activityManager.init(album.id));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  onDestroy(() => {
 | 
			
		||||
@ -409,12 +406,6 @@
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  let albumHasViewers = $derived(album.albumUsers.some(({ role }) => role === AlbumUserRole.Viewer));
 | 
			
		||||
  $effect(() => {
 | 
			
		||||
    if (album.albumUsers.length > 0) {
 | 
			
		||||
      handlePromiseError(updateComments());
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  const isShared = $derived(viewMode === AlbumPageViewMode.SELECT_ASSETS ? false : album.albumUsers.length > 0);
 | 
			
		||||
  const isSelectionMode = $derived(
 | 
			
		||||
    viewMode === AlbumPageViewMode.SELECT_ASSETS ? true : viewMode === AlbumPageViewMode.SELECT_THUMBNAIL,
 | 
			
		||||
  );
 | 
			
		||||
@ -570,7 +561,7 @@
 | 
			
		||||
        {/if}
 | 
			
		||||
      </AssetGrid>
 | 
			
		||||
 | 
			
		||||
      {#if showActivityStatus}
 | 
			
		||||
      {#if showActivityStatus && !activityManager.isLoading}
 | 
			
		||||
        <div class="absolute z-2 bottom-0 end-0 mb-6 me-6 justify-self-end">
 | 
			
		||||
          <ActivityStatus
 | 
			
		||||
            disabled={!album.isActivityEnabled}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user