Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions src/components/panel/Filmstrip.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useRef } from 'react';
import { Image as ImageIcon, Star } from 'lucide-react';
import { Image as ImageIcon, Star, Pencil } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';

const COLOR_LABELS = [
Expand All @@ -10,10 +10,10 @@ const COLOR_LABELS = [
{ name: 'purple', color: '#a78bfa' },
];

export default function Filmstrip({
imageList,
selectedImage,
onImageSelect,
export default function Filmstrip({
imageList,
selectedImage,
onImageSelect,
onContextMenu,
thumbnails,
multiSelectedPaths,
Expand Down Expand Up @@ -57,15 +57,15 @@ export default function Filmstrip({
block: 'nearest',
inline: 'center',
});
}, 320);
}, 320);
}
}
}
}, [selectedImage, imageList]);

return (
<div
ref={filmstripRef}
<div
ref={filmstripRef}
className="h-full overflow-x-auto overflow-y-hidden p-1"
onClick={onClearSelection}
>
Expand All @@ -74,17 +74,18 @@ export default function Filmstrip({
{imageList.map((imageFile) => {
const path = imageFile.path;
const isActive = selectedImage?.path === path;
const isEdited = imageFile.is_edited;
const isSelected = multiSelectedPaths.includes(path);
const thumbData = thumbnails[path];
const rating = imageRatings?.[path] || 0;
const colorTag = imageFile.tags?.find(t => t.startsWith('color:'))?.substring(6);
const colorLabel = COLOR_LABELS.find(c => c.name === colorTag);

const ringClass = isActive
? 'ring-2 ring-accent'
: isSelected
? 'ring-2 ring-gray-400'
: 'hover:ring-2 hover:ring-hover-color';
? 'ring-2 ring-gray-400'
: 'hover:ring-2 hover:ring-hover-color';

return (
<motion.div
Expand All @@ -111,11 +112,11 @@ export default function Filmstrip({
<ImageIcon size={24} className="text-text-secondary animate-pulse" />
</div>
)}
{(colorLabel || rating > 0) && (

{(colorLabel || rating > 0 || isEdited) && (
<div className="absolute top-1 right-1 bg-primary rounded-full px-1.5 py-0.5 text-xs text-white flex items-center gap-1 backdrop-blur-sm">
{colorLabel && (
<div
<div
className="w-3 h-3 rounded-full ring-1 ring-black/20"
style={{ backgroundColor: colorLabel.color }}
title={`Color: ${colorLabel.name}`}
Expand All @@ -127,6 +128,9 @@ export default function Filmstrip({
<Star size={10} className="fill-white text-white" />
</>
)}
{isEdited && (<div className="fill-white text-white">
<Pencil size={12} />
</div>)}
</div>
)}
</motion.div>
Expand All @@ -136,4 +140,4 @@ export default function Filmstrip({
</motion.div>
</div>
);
}
}
35 changes: 21 additions & 14 deletions src/components/panel/MainLibrary.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Loader2,
AlertTriangle,
FolderInput,
Pencil,
} from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { FixedSizeGrid as Grid } from 'react-window';
Expand Down Expand Up @@ -286,9 +287,9 @@ function ViewOptionsDropdown({
sortCriteria,
setSortCriteria,
}) {
const isFilterActive = filterCriteria.rating > 0 ||
(filterCriteria.rawStatus && filterCriteria.rawStatus !== 'all') ||
(filterCriteria.colors && filterCriteria.colors.length > 0);
const isFilterActive = filterCriteria.rating > 0 ||
(filterCriteria.rawStatus && filterCriteria.rawStatus !== 'all') ||
(filterCriteria.colors && filterCriteria.colors.length > 0);

return (
<DropdownMenu
Expand Down Expand Up @@ -316,7 +317,7 @@ function ViewOptionsDropdown({
);
}

function Thumbnail({ path, data, onImageClick, onImageDoubleClick, isSelected, isActive, rating, onContextMenu, tags }) {
function Thumbnail({ isEdited, path, data, onImageClick, onImageDoubleClick, isSelected, isActive, rating, onContextMenu, tags }) {
const [isLoaded, setIsLoaded] = useState(false);

useEffect(() => {
Expand All @@ -342,11 +343,11 @@ function Thumbnail({ path, data, onImageClick, onImageDoubleClick, isSelected, i
<ImageIcon className="text-text-secondary animate-pulse" />
</div>
)}
{(colorLabel || rating > 0) && (

{(colorLabel || rating > 0 || isEdited) && (
<div className="absolute top-1.5 right-1.5 bg-bg-primary/50 rounded-full px-1.5 py-0.5 text-xs text-text-primary flex items-center gap-1 backdrop-blur-sm">
{colorLabel && (
<div
<div
className="w-3 h-3 rounded-full ring-1 ring-black/20"
style={{ backgroundColor: colorLabel.color }}
title={`Color: ${colorLabel.name}`}
Expand All @@ -358,6 +359,11 @@ function Thumbnail({ path, data, onImageClick, onImageDoubleClick, isSelected, i
<StarIcon size={12} className="text-accent fill-accent" />
</>
)}
{isEdited && (
<>
<Pencil className="text-accent" size={12} />
</>
)}
</div>
)}

Expand All @@ -384,6 +390,7 @@ const Cell = ({ columnIndex, rowIndex, style, data }) => {
className="p-2 h-full"
>
<Thumbnail
isEdited={imageFile.is_edited}
path={imageFile.path}
data={thumbnails[imageFile.path]}
rating={imageRatings?.[imageFile.path] || 0}
Expand Down Expand Up @@ -527,12 +534,12 @@ export default function MainLibrary({
<div className="flex-1 flex flex-col items-center justify-center text-text-secondary" onContextMenu={onEmptyAreaContextMenu}>
<Loader2 className="h-12 w-12 text-secondary animate-spin mb-4" />
<p className="text-lg font-semibold">
{aiModelDownloadStatus ? `Downloading ${aiModelDownloadStatus}...`
: (isIndexing && indexingProgress.total > 0)
? `Indexing images... (${indexingProgress.current}/${indexingProgress.total})`
: (importState.status === 'importing' && importState.progress.total > 0)
? `Importing images... (${importState.progress.current}/${importState.progress.total})`
: "Processing images..."
{aiModelDownloadStatus ? `Downloading ${aiModelDownloadStatus}...`
: (isIndexing && indexingProgress.total > 0)
? `Indexing images... (${indexingProgress.current}/${indexingProgress.total})`
: (importState.status === 'importing' && importState.progress.total > 0)
? `Importing images... (${importState.progress.current}/${importState.progress.total})`
: "Processing images..."
}
</p>
<p className="text-sm mt-2">This may take a moment.</p>
Expand Down Expand Up @@ -578,4 +585,4 @@ export default function MainLibrary({
)}
</div>
);
}
}
Loading