aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/photos-app.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/photos-app.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/photos-app.js31
1 files changed, 23 insertions, 8 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/photos-app.js b/packages/meshbay-hub/src/meshbay_hub/static/photos-app.js
index 00bc288..afc815a 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/photos-app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/photos-app.js
@@ -10,6 +10,8 @@ import { transfers } from './transfers.js';
import { MediaThumb, LazyTile } from './media-tiles.js';
import { SourceTag } from './group-name.js';
import { CastButton, castSession, useCastDevice, showPhoto } from './cast-session.js';
+import { Menu, useMenu } from './menu.js';
+import { copyLink } from './copy-link.js';
// ── Photos ───────────────────────────────────────────────────────────────────
//
@@ -118,11 +120,11 @@ function AlbumLanding({ albums, transportRef, gekRef, onOpen }) {
// ── open album: grid of its own photos ──────────────────────────────────────
-function PhotoTile({ entry, transportRef, gekRef, onOpen }) {
+function PhotoTile({ entry, transportRef, gekRef, onOpen, onMenu }) {
const tRef = entry._tRef || transportRef;
const gRef = entry._gRef || gekRef;
return html`
- <div class="photo-tile" onClick=${onOpen}>
+ <div class="photo-tile" onClick=${onOpen} onContextMenu=${onMenu}>
<${MediaThumb} thumbHash=${entry.thumb_hash} alt=${entry.name}
cls="photo-tile-thumb" transportRef=${tRef} gekRef=${gRef}
emptyIcon="image" />
@@ -153,7 +155,7 @@ const ZOOM_MAX = 400;
// a slow node must not skip a photo nobody saw.
const SLIDESHOW_MS = 5000;
-function Lightbox({ photos, index, transportRef, gekRef, onClose, onNav }) {
+function Lightbox({ photos, index, transportRef, gekRef, onClose, onNav, linkFor }) {
const entry = photos[index];
const tRef = entry._tRef || transportRef;
const gRef = entry._gRef || gekRef;
@@ -284,6 +286,10 @@ function Lightbox({ photos, index, transportRef, gekRef, onClose, onNav }) {
aria-pressed=${slideshow ? 'true' : 'false'}>
<${Icon} name=${slideshow ? 'pause' : 'play'} /></button>
<${CastButton} variant="overlay" cls="video-close" />
+ ${linkFor && linkFor(entry) && html`
+ <button class="video-close" onClick=${() => copyLink(linkFor(entry))}
+ title=${t('link.copy')} aria-label=${t('link.copy')}>
+ <${Icon} name="link" /></button>`}
<button class="video-close" onClick=${onClose} title=${t('video.close')}>
<${Icon} name="close" /></button>
</div>
@@ -311,8 +317,16 @@ function Lightbox({ photos, index, transportRef, gekRef, onClose, onNav }) {
`;
}
-function AlbumView({ album, entries, transportRef, gekRef, setError, onBack, readOnly }) {
+function AlbumView({ album, entries, transportRef, gekRef, setError, onBack, readOnly, linkFor }) {
const [lightboxIndex, setLightboxIndex] = useState(null);
+ // Right-click a photo for its link. A tile has no dots to press, so on a
+ // touchscreen the link is in the lightbox's bar instead.
+ const { menu, openAt, close: closeMenu } = useMenu();
+ const onTileMenu = (e, entry) => {
+ const link = linkFor ? linkFor(entry) : null;
+ if (!link) return;
+ openAt(e, [{ label: t('link.copy'), icon: 'link', onSelect: () => copyLink(link) }]);
+ };
const zip = useCallback(async () => {
const transport = transportRef.current;
@@ -352,15 +366,16 @@ function AlbumView({ album, entries, transportRef, gekRef, setError, onBack, rea
${album.photos.map((e, i) => html`
<${LazyTile} key=${e.id} cls="photo-tile-slot">
<${PhotoTile} entry=${e} transportRef=${transportRef} gekRef=${gekRef}
- onOpen=${() => setLightboxIndex(i)} />
+ onOpen=${() => setLightboxIndex(i)} onMenu=${(ev) => onTileMenu(ev, e)} />
</${LazyTile}>
`)}
</div>
${lightboxIndex !== null && html`
<${Lightbox} photos=${album.photos} index=${lightboxIndex}
transportRef=${transportRef} gekRef=${gekRef}
- onClose=${() => setLightboxIndex(null)} onNav=${navigate} />
+ onClose=${() => setLightboxIndex(null)} onNav=${navigate} linkFor=${linkFor} />
`}
+ ${menu && html`<${Menu} ...${menu} onClose=${closeMenu} />`}
`;
}
@@ -369,7 +384,7 @@ function AlbumView({ album, entries, transportRef, gekRef, setError, onBack, rea
function PhotosApp({
groupId, transportRef, gekRef, status, entries, availableEntries,
photoDirectories, setError,
- hideFilter, readOnly,
+ hideFilter, readOnly, linkFor,
}) {
const [openDir, setOpenDir] = useState(null);
const [filter, setFilter] = useState('');
@@ -423,7 +438,7 @@ function PhotosApp({
${status === 'connected' && openAlbum && html`
<${AlbumView} album=${openAlbum} entries=${entries}
transportRef=${transportRef} gekRef=${gekRef} setError=${setError}
- onBack=${() => setOpenDir(null)} readOnly=${readOnly} />
+ onBack=${() => setOpenDir(null)} readOnly=${readOnly} linkFor=${linkFor} />
`}
`;
}