Skip to content

Commit

Permalink
feat: multi select in potential album and missing location using shif…
Browse files Browse the repository at this point in the history
…t key

Signed-off-by: Varun Raj <varun@skcript.com>
  • Loading branch information
varun-raj committed Jan 11, 2025
1 parent a3e12c8 commit 4820f35
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 19 deletions.
32 changes: 24 additions & 8 deletions src/components/albums/potential-albums/PotentialAlbumsAssets.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import "yet-another-react-lightbox/styles.css";
import { usePotentialAlbumContext } from "@/contexts/PotentialAlbumContext";
import { listPotentialAlbumsAssets } from "@/handlers/api/album.handler";
import { IAsset } from "@/types/asset";
import React, { useEffect, useMemo, useState } from "react";
import type { IAsset } from "@/types/asset";
import React, { type MouseEvent, useEffect, useMemo, useState } from "react";
import { Gallery } from "react-grid-gallery";
import Lightbox, { SlideImage, SlideTypes } from "yet-another-react-lightbox";
import Captions from "yet-another-react-lightbox/plugins/captions";
Expand All @@ -20,6 +20,7 @@ export default function PotentialAlbumsAssets() {
const [errorMessage, setErrorMessage] = useState<string | null>(null);

const [index, setIndex] = useState(-1);
const [lastSelectedIndex, setLastSelectedIndex] = useState(-1);

const fetchAssets = async () => {
setLoading(true);
Expand All @@ -44,14 +45,15 @@ export default function PotentialAlbumsAssets() {
{
title: "Immich Link",
value: (
<a href={exImmichUrl + "/photos/" + p.id} target="_blank">
<a href={`${exImmichUrl}/photos/${p.id}`} target="_blank" rel="noreferrer">
Open in Immich
</a>
),
},
],
}));
}, [assets, selectedIds]);
}, [assets, selectedIds, exImmichUrl]);


const slides = useMemo(
() =>
Expand All @@ -73,17 +75,31 @@ export default function PotentialAlbumsAssets() {
[images]
);

const handleClick = (idx: number) => setIndex(idx);

const handleSelect = (_idx: number, asset: IAsset) => {
const handleSelect = (_idx: number, asset: IAsset, event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
const isPresent = selectedIds.includes(asset.id);
if (isPresent) {
updateContext({
selectedIds: selectedIds.filter((id) => id !== asset.id),
});
} else {
updateContext({ selectedIds: [...selectedIds, asset.id] });
const clickedIndex = images.findIndex((image) => {
return image.id === asset.id
});
if (event.shiftKey) {
const startIndex = Math.min(clickedIndex, lastSelectedIndex);
const endIndex = Math.max(clickedIndex, lastSelectedIndex);
const newSelectedIds = images.slice(startIndex, endIndex + 1).map((image) => image.id);
const allSelectedIds = [...selectedIds, ...newSelectedIds];
const uniqueSelectedIds = [...new Set(allSelectedIds)];
updateContext({ selectedIds: uniqueSelectedIds });
} else {
updateContext({ selectedIds: [...selectedIds, asset.id] });
}
setLastSelectedIndex(clickedIndex);
}

};

useEffect(() => {
Expand Down Expand Up @@ -121,7 +137,7 @@ export default function PotentialAlbumsAssets() {
<div className="w-full overflow-y-auto max-h-[calc(100vh-60px)]">
<Gallery
images={images}
onClick={handleClick}
onClick={setIndex}
enableImageSelection={true}
onSelect={handleSelect}
thumbnailImageComponent={LazyGridImage}
Expand Down
21 changes: 18 additions & 3 deletions src/components/assets/missing-location/MissingLocationAssets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import "yet-another-react-lightbox/styles.css";
import { usePotentialAlbumContext } from "@/contexts/PotentialAlbumContext";
import { listPotentialAlbumsAssets } from "@/handlers/api/album.handler";
import { IAsset } from "@/types/asset";
import React, { useEffect, useMemo, useState } from "react";
import React, { useEffect, useMemo, useState, MouseEvent } from "react";
import { Gallery } from "react-grid-gallery";
import Lightbox from "yet-another-react-lightbox";
import Captions from "yet-another-react-lightbox/plugins/captions";
Expand Down Expand Up @@ -33,6 +33,7 @@ export default function MissingLocationAssets({ groupBy }: IProps) {
const [errorMessage, setErrorMessage] = useState<string | null>(null);

const [index, setIndex] = useState(-1);
const [lastSelectedIndex, setLastSelectedIndex] = useState(-1);

const fetchAssets = async () => {
if (!startDate && !albumId) return;
Expand Down Expand Up @@ -80,14 +81,28 @@ export default function MissingLocationAssets({ groupBy }: IProps) {

const handleClick = (idx: number) => setIndex(idx);

const handleSelect = (_idx: number, asset: IAsset) => {
const handleSelect = (_idx: number, asset: IAsset, event: MouseEvent<HTMLElement>) => {
event.stopPropagation();
const isPresent = selectedIds.includes(asset.id);
if (isPresent) {
updateContext({
selectedIds: selectedIds.filter((id) => id !== asset.id),
});
} else {
updateContext({ selectedIds: [...selectedIds, asset.id] });
const clickedIndex = images.findIndex((image) => {
return image.id === asset.id;
});
if (event.shiftKey) {
const startIndex = Math.min(clickedIndex, lastSelectedIndex);
const endIndex = Math.max(clickedIndex, lastSelectedIndex);
const newSelectedIds = images.slice(startIndex, endIndex + 1).map((image) => image.id);
const allSelectedIds = [...selectedIds, ...newSelectedIds];
const uniqueSelectedIds = [...new Set(allSelectedIds)];
updateContext({ selectedIds: uniqueSelectedIds });
} else {
updateContext({ selectedIds: [...selectedIds, asset.id] });
}
setLastSelectedIndex(clickedIndex);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { IPlace } from "@/types/common";
import React, { useState } from "react";
import TagMissingLocationSearchAndAdd from "./TagMissingLocationSearchAndAdd";
import TagMissingLocationSearchLatLong from "./TagMissingLocationSearchLatLong";
import { MapPinCheck } from "lucide-react";
import dynamic from "next/dynamic";

const LazyMap = dynamic(() => import("./Map"), {
Expand Down Expand Up @@ -46,12 +45,11 @@ export default function TagMissingLocationDialog({
Tagging a location will add the location to the selected assets.
</DialogDescription>
</DialogHeader>
<Tabs defaultValue="search" className="border rounded-lg">
<TabsList className="flex justify-between">
<Tabs defaultValue="search">
<TabsList className="flex justify-center">
<TabsTrigger value="search">Search and Pick</TabsTrigger>
<TabsTrigger value="latlong">
Latitude and Longitude

Lat & Long
</TabsTrigger>
<TabsTrigger value="maps">Map</TabsTrigger>
</TabsList>
Expand All @@ -63,7 +61,7 @@ export default function TagMissingLocationDialog({
onOpenChange={setOpen} location={mapPosition} onLocationChange={setMapPosition} />
</TabsContent>
<TabsContent value="maps">
<div className="py-10 flex flex-col gap-6 items-center ">
<div className="flex flex-col gap-6 items-center ">
<LazyMap location={mapPosition} onLocationChange={setMapPosition} />
</div>
</TabsContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export default function TagMissingLocationSearchLatLong(
return (
<div className="flex flex-col gap-4 py-4 px-2">
<div className="flex items-start gap-2">
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-2 flex-1">
<Label>Latitude</Label>
<Input
placeholder="Latitude"
Expand All @@ -121,7 +121,7 @@ export default function TagMissingLocationSearchLatLong(
onBlur={(e) => handleBlur()}
/>
</div>
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-2 flex-1">
<Label>
Longitude
</Label>
Expand Down

0 comments on commit 4820f35

Please sign in to comment.