diff --git a/src/components/viewer/Viewer.vue b/src/components/viewer/Viewer.vue
index 7c4fd79b..c6043479 100644
--- a/src/components/viewer/Viewer.vue
+++ b/src/components/viewer/Viewer.vue
@@ -22,159 +22,15 @@
- {{ t('memories', 'Share') }}
-
-
-
- {{ t('memories', 'Delete') }}
-
-
-
- {{ t('memories', 'Remove from album') }}
-
-
-
- {{ t('memories', 'Play Live Photo') }}
+ {{ action.name }}
-
-
-
-
- {{ t('memories', 'Favorite') }}
-
-
-
-
-
-
- {{ t('memories', 'Info') }}
-
-
-
-
-
- {{ t('memories', 'Edit') }}
-
-
-
-
-
- {{ t('memories', 'Download') }}
-
-
-
-
-
- {{ t('memories', 'Download Video') }}
-
-
-
-
-
- {{ t('memories', 'Download {ext}', { ext: raw.extension }) }}
-
-
-
-
-
- {{ t('memories', 'View in folder') }}
-
-
-
-
-
- {{ t('memories', 'Slideshow') }}
-
-
-
-
-
- {{ t('memories', 'Edit metadata') }}
-
-
-
-
-
- {{ t('memories', 'Rotate / Flip') }}
-
-
-
-
-
- {{ t('memories', 'Add to album') }}
-
-
+
@@ -234,6 +90,21 @@ import AlbumRemoveIcon from 'vue-material-design-icons/BookRemove.vue';
import AlbumIcon from 'vue-material-design-icons/ImageAlbum.vue';
import RotateLeftIcon from 'vue-material-design-icons/RotateLeft.vue';
+type IViewerAction = {
+ /** Identifier (optional) */
+ id: string;
+ /** Display text */
+ name: string;
+ /** Icon component */
+ icon: any;
+ /** Props on icon component */
+ iconArgs?: any;
+ /** Action to perform */
+ callback: () => void;
+ /** Condition to check for including */
+ if: boolean;
+};
+
const SLIDESHOW_MS = 5000;
const SIDEBAR_DEBOUNCE_MS = 350;
const BODY_HAS_VIEWER = 'has-viewer';
@@ -246,20 +117,6 @@ export default defineComponent({
NcActions,
NcActionButton,
ImageEditor,
- LivePhotoIcon,
- ShareIcon,
- DeleteIcon,
- StarIcon,
- StarOutlineIcon,
- DownloadIcon,
- InfoIcon,
- OpenInNewIcon,
- TuneIcon,
- SlideshowIcon,
- EditFileIcon,
- AlbumRemoveIcon,
- AlbumIcon,
- RotateLeftIcon,
},
mixins: [UserConfig],
@@ -371,6 +228,126 @@ export default defineComponent({
return this.list[idx];
},
+ /** Get all actions to show */
+ actions(): IViewerAction[] {
+ return [
+ {
+ id: 'share',
+ name: this.t('memories', 'Share'),
+ icon: ShareIcon,
+ callback: this.shareCurrent,
+ if: this.canShare,
+ },
+ {
+ id: 'delete',
+ name: this.t('memories', 'Delete'),
+ icon: DeleteIcon,
+ callback: this.deleteCurrent,
+ if: !this.routeIsAlbums && this.canDelete,
+ },
+ {
+ id: 'remove-from-album',
+ name: this.t('memories', 'Remove from album'),
+ icon: AlbumRemoveIcon,
+ callback: this.deleteCurrent,
+ if: this.routeIsAlbums,
+ },
+ {
+ id: 'play-live-photo',
+ name: this.t('memories', 'Play Live Photo'),
+ icon: LivePhotoIcon,
+ iconArgs: {
+ playing: this.liveState.playing,
+ spin: this.liveState.waiting,
+ },
+ callback: this.playLivePhoto,
+ if: this.isLivePhoto,
+ },
+ {
+ id: 'favorite',
+ name: this.t('memories', 'Favorite'),
+ icon: this.isFavorite ? StarIcon : StarOutlineIcon,
+ callback: this.favoriteCurrent,
+ if: !this.routeIsPublic && !this.isLocal,
+ },
+ {
+ id: 'info',
+ name: this.t('memories', 'Info'),
+ icon: InfoIcon,
+ callback: this.toggleSidebar,
+ if: true,
+ },
+ {
+ id: 'edit',
+ name: this.t('memories', 'Edit'),
+ icon: TuneIcon,
+ callback: this.openEditor,
+ if: this.canEdit && !this.isVideo,
+ },
+ {
+ id: 'download',
+ name: this.t('memories', 'Download'),
+ icon: DownloadIcon,
+ callback: this.downloadCurrent,
+ if: !this.initstate.noDownload && !this.isLocal,
+ },
+ {
+ id: 'download-video',
+ name: this.t('memories', 'Download Video'),
+ icon: DownloadIcon,
+ callback: this.downloadCurrentLiveVideo,
+ if: !this.initstate.noDownload && !!this.currentPhoto?.liveid,
+ },
+ ...this.stackedRaw.map((raw) => ({
+ id: `download-raw-${raw.fileid}`,
+ name: this.t('memories', 'Download {ext}', { ext: raw.extension }),
+ icon: DownloadIcon,
+ callback: () => this.downloadByFileId(raw.fileid),
+ if: true,
+ })),
+ {
+ id: 'view-in-folder',
+ name: this.t('memories', 'View in folder'),
+ icon: OpenInNewIcon,
+ callback: this.viewInFolder,
+ if: !this.routeIsPublic && !this.routeIsAlbums && !this.isLocal,
+ },
+ {
+ id: 'slideshow',
+ name: this.t('memories', 'Slideshow'),
+ icon: SlideshowIcon,
+ callback: this.startSlideshow,
+ if: this.globalCount > 1,
+ },
+ {
+ id: 'edit-metadata',
+ name: this.t('memories', 'Edit metadata'),
+ icon: EditFileIcon,
+ callback: () => this.editMetadata(),
+ if: this.canEdit,
+ },
+ {
+ id: 'rotate-flip',
+ name: this.t('memories', 'Rotate / Flip'),
+ icon: RotateLeftIcon,
+ callback: () => this.editMetadata([5]),
+ if: this.canEdit && !this.isVideo,
+ },
+ {
+ id: 'add-to-album',
+ name: this.t('memories', 'Add to album'),
+ icon: AlbumIcon,
+ callback: this.updateAlbums,
+ if:
+ this.config.albums_enabled &&
+ !this.isLocal &&
+ !this.routeIsPublic &&
+ this.canShare &&
+ !!this.currentPhoto?.imageInfo?.filename,
+ },
+ ].filter((action) => action.if);
+ },
+
/** Is the current slide a video */
isVideo(): boolean {
return Boolean((this.currentPhoto?.flag ?? 0) & this.c.FLAG_IS_VIDEO);
@@ -386,6 +363,13 @@ export default defineComponent({
return utils.isLocalPhoto(this.currentPhoto!);
},
+ /** Is the current photo a favorite */
+ isFavorite() {
+ const p = this.currentPhoto;
+ if (!p) return false;
+ return Boolean(p.flag & this.c.FLAG_IS_FAVORITE);
+ },
+
/** Show bottom bar info such as date taken */
showBottomBar(): boolean {
return !this.isVideo && this.fullyOpened && Boolean(this.currentPhoto?.imageInfo);
@@ -1062,17 +1046,10 @@ export default defineComponent({
this.psLivePhoto?.play(this.photoswipe!.currSlide!.content as PsContent);
},
- /** Is the current photo a favorite */
- isFavorite() {
- const p = this.currentPhoto;
- if (!p) return false;
- return Boolean(p.flag & this.c.FLAG_IS_FAVORITE);
- },
-
/** Favorite the current photo */
async favoriteCurrent() {
const photo = this.currentPhoto!;
- const val = !this.isFavorite();
+ const val = !this.isFavorite;
try {
this.updateLoading(1);
for await (const p of dav.favoritePhotos([photo], val)) {