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)) {