Skip to content

Commit

Permalink
fix(web): previous/next asset navigation (#3107)
Browse files Browse the repository at this point in the history
* fix(web): previous/next asset navigation

* Apply suggestions from code review

Co-authored-by: Thomas <[email protected]>

* Call setViewingAsset once

* Make code more readable

* Avoid recursive call

* Simplify return statement

* Set position of the bucket to Unknown

---------

Co-authored-by: Thomas <[email protected]>
Co-authored-by: Alex Tran <[email protected]>
  • Loading branch information
3 people authored and pull[bot] committed Mar 12, 2024
1 parent d25826a commit a224086
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 20 deletions.
5 changes: 5 additions & 0 deletions web/src/lib/models/asset-grid-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ export class AssetGridState {
*/
assets: AssetResponseDto[] = [];

/**
* Total assets that have been loaded along with additional data
*/
loadedAssets: Record<string, number> = {};

/**
* User that owns assets
*/
Expand Down
72 changes: 52 additions & 20 deletions web/src/lib/stores/asset-interaction.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,30 +66,62 @@ function createAssetInteractionStore() {
isViewingAssetStoreState.set(isViewing);
};

const getNextAsset = async (currentBucketIndex: number, assetId: string): Promise<AssetResponseDto | null> => {
const currentBucket = _assetGridState.buckets[currentBucketIndex];
const assetIndex = currentBucket.assets.findIndex(({ id }) => id == assetId);
if (assetIndex === -1) {
return null;
}

if (assetIndex + 1 < currentBucket.assets.length) {
return currentBucket.assets[assetIndex + 1];
}

const nextBucketIndex = currentBucketIndex + 1;
if (nextBucketIndex >= _assetGridState.buckets.length) {
return null;
}

const nextBucket = _assetGridState.buckets[nextBucketIndex];
await assetStore.getAssetsByBucket(nextBucket.bucketDate, BucketPosition.Unknown);

return nextBucket.assets[0] ?? null;
};

const getPrevAsset = async (currentBucketIndex: number, assetId: string): Promise<AssetResponseDto | null> => {
const currentBucket = _assetGridState.buckets[currentBucketIndex];
const assetIndex = currentBucket.assets.findIndex(({ id }) => id == assetId);
if (assetIndex === -1) {
return null;
}

if (assetIndex > 0) {
return currentBucket.assets[assetIndex - 1];
}

const prevBucketIndex = currentBucketIndex - 1;
if (prevBucketIndex < 0) {
return null;
}

const prevBucket = _assetGridState.buckets[prevBucketIndex];
await assetStore.getAssetsByBucket(prevBucket.bucketDate, BucketPosition.Unknown);

return prevBucket.assets[prevBucket.assets.length - 1] ?? null;
};

const navigateAsset = async (direction: 'next' | 'previous') => {
let index = _assetGridState.assets.findIndex(({ id }) => id === _viewingAssetStoreState.id);

index = direction === 'next' ? index + 1 : index - 1;

const needMoreAbove = index < 0;
const needMoreBelow = index >= _assetGridState.assets.length;

// Try to load more assets if we're at the end.
if (needMoreAbove || needMoreBelow) {
for (const bucket of _assetGridState.buckets) {
if (bucket.assets.length === 0) {
await assetStore.getAssetsByBucket(
bucket.bucketDate,
needMoreAbove ? BucketPosition.Above : BucketPosition.Below,
);
navigateAsset(direction);
break;
}
}
const currentAssetId = _viewingAssetStoreState.id;
const currentBucketIndex = _assetGridState.loadedAssets[currentAssetId];
if (currentBucketIndex < 0 || currentBucketIndex >= _assetGridState.buckets.length) {
return;
}

const asset = _assetGridState.assets[index];
const asset =
direction === 'next'
? await getNextAsset(currentBucketIndex, currentAssetId)
: await getPrevAsset(currentBucketIndex, currentAssetId);

if (asset) {
setViewingAsset(asset);
}
Expand Down
14 changes: 14 additions & 0 deletions web/src/lib/stores/assets.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ function createAssetStore() {
return height;
};

const refreshLoadedAssets = (state: AssetGridState): void => {
state.loadedAssets = {};
state.buckets.forEach((bucket, bucketIndex) =>
bucket.assets.map((asset) => {
state.loadedAssets[asset.id] = bucketIndex;
}),
);
};

/**
* Set initial state
* @param viewportHeight
Expand All @@ -54,6 +63,7 @@ function createAssetStore() {
position: BucketPosition.Unknown,
})),
assets: [],
loadedAssets: {},
userId,
});

Expand Down Expand Up @@ -101,6 +111,7 @@ function createAssetStore() {
state.buckets[bucketIndex].assets = assets;
state.buckets[bucketIndex].position = position;
state.assets = state.buckets.flatMap((b) => b.assets);
refreshLoadedAssets(state);
return state;
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -123,6 +134,7 @@ function createAssetStore() {
_removeBucket(state.buckets[bucketIndex].bucketDate);
}
state.assets = state.buckets.flatMap((b) => b.assets);
refreshLoadedAssets(state);
return state;
});
};
Expand All @@ -132,6 +144,7 @@ function createAssetStore() {
const bucketIndex = state.buckets.findIndex((b) => b.bucketDate === bucketDate);
state.buckets.splice(bucketIndex, 1);
state.assets = state.buckets.flatMap((b) => b.assets);
refreshLoadedAssets(state);
return state;
});
};
Expand Down Expand Up @@ -180,6 +193,7 @@ function createAssetStore() {
state.buckets[bucketIndex].assets[assetIndex].isFavorite = isFavorite;

state.assets = state.buckets.flatMap((b) => b.assets);
refreshLoadedAssets(state);
return state;
});
};
Expand Down

0 comments on commit a224086

Please sign in to comment.