feat(gallery): add-to-album submenu on the image right-click menu
Right-clicking an image in the Gallery or Timeline now offers an "Add to Album" submenu listing all albums with their counts — the first use of the new SubMenu primitive. Filing a single image away no longer requires starting a multi-select.
This commit is contained in:
+7
-3
@@ -56,12 +56,16 @@ aims to follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|||||||
from whatever collection you are already browsing. Videos are skipped, controls
|
from whatever collection you are already browsing. Videos are skipped, controls
|
||||||
tuck themselves away after a few seconds, and Settings lets you pick the pace
|
tuck themselves away after a few seconds, and Settings lets you pick the pace
|
||||||
and whether playback follows the current order or goes random.
|
and whether playback follows the current order or goes random.
|
||||||
|
- **Add to album from the right-click menu** — right-click any image in the
|
||||||
|
Gallery or Timeline and file it straight into an album from the new "Add to
|
||||||
|
Album" submenu. One image, one click, zero ceremony.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Consistent right-click menus** — the folder, album, image, and theme menus
|
- **Right-click menus got their act together** — images, folders, albums, and
|
||||||
now share one look and behavior: they stay inside the window instead of
|
the theme switcher now share one menu style with one set of manners: they
|
||||||
spilling off the edge, close on Escape, and support proper submenus.
|
stay on screen instead of wandering off the edge, all close on Escape, and
|
||||||
|
they can do proper submenus now.
|
||||||
- **Neater lightbox details** — image and video metadata now sits in two columns,
|
- **Neater lightbox details** — image and video metadata now sits in two columns,
|
||||||
so the info panel shows more at a glance with less scrolling.
|
so the info panel shows more at a glance with less scrolling.
|
||||||
- **Faster Explore revisits** — returning to a folder's visual clusters should
|
- **Faster Explore revisits** — returning to a folder's visual clusters should
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ImageRecord, useGalleryStore } from "../store";
|
import { ImageRecord, useGalleryStore } from "../store";
|
||||||
import { ContextMenu, MenuItem, MenuLabel, MenuSeparator } from "./menu";
|
import { ContextMenu, MenuItem, MenuLabel, MenuSeparator, SubMenu } from "./menu";
|
||||||
import { Tooltip } from "./Tooltip";
|
import { Tooltip } from "./Tooltip";
|
||||||
|
|
||||||
/** Right-click menu for an image tile. Shared by the Gallery grid and the Timeline. */
|
/** Right-click menu for an image tile. Shared by the Gallery grid and the Timeline. */
|
||||||
@@ -17,6 +17,8 @@ export function ImageContextMenu({
|
|||||||
const openImage = useGalleryStore((state) => state.openImage);
|
const openImage = useGalleryStore((state) => state.openImage);
|
||||||
const updateImageDetails = useGalleryStore((state) => state.updateImageDetails);
|
const updateImageDetails = useGalleryStore((state) => state.updateImageDetails);
|
||||||
const findSimilar = useGalleryStore((state) => state.findSimilar);
|
const findSimilar = useGalleryStore((state) => state.findSimilar);
|
||||||
|
const albums = useGalleryStore((state) => state.albums);
|
||||||
|
const addToAlbum = useGalleryStore((state) => state.addToAlbum);
|
||||||
const canFindSimilar = image.embedding_status === "ready";
|
const canFindSimilar = image.embedding_status === "ready";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -31,6 +33,20 @@ export function ImageContextMenu({
|
|||||||
disabled={!canFindSimilar}
|
disabled={!canFindSimilar}
|
||||||
onSelect={() => findSimilar(image.id, image.folder_id)}
|
onSelect={() => findSimilar(image.id, image.folder_id)}
|
||||||
/>
|
/>
|
||||||
|
<SubMenu label="Add to Album" panelClassName="max-h-64 overflow-y-auto">
|
||||||
|
{albums.length === 0 ? (
|
||||||
|
<MenuItem label="No albums yet" disabled />
|
||||||
|
) : (
|
||||||
|
albums.map((album) => (
|
||||||
|
<MenuItem
|
||||||
|
key={album.id}
|
||||||
|
label={album.name}
|
||||||
|
hint={album.image_count.toLocaleString()}
|
||||||
|
onSelect={() => void addToAlbum(album.id, [image.id])}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</SubMenu>
|
||||||
<MenuSeparator />
|
<MenuSeparator />
|
||||||
<MenuLabel>Rating</MenuLabel>
|
<MenuLabel>Rating</MenuLabel>
|
||||||
<div className="flex items-center gap-0.5 px-2 pb-1.5">
|
<div className="flex items-center gap-0.5 px-2 pb-1.5">
|
||||||
|
|||||||
Reference in New Issue
Block a user