From 4f9d341f692d29e6a19ed8f01d757246eb18dc91 Mon Sep 17 00:00:00 2001 From: advplyr Date: Sat, 17 Jun 2023 12:49:24 -0500 Subject: [PATCH] Update:Delete local item/episode options in context menu #690, android: remove scan options for local server items & remove option --- pages/item/_id/_episode/index.vue | 69 ++++++++++++++++++++++++++----- pages/item/_id/index.vue | 55 ++++++++++++++++++++---- pages/localMedia/item/_id.vue | 45 ++++++++++---------- 3 files changed, 126 insertions(+), 43 deletions(-) diff --git a/pages/item/_id/_episode/index.vue b/pages/item/_id/_episode/index.vue index 75b9fe3f..fbcc0291 100644 --- a/pages/item/_id/_episode/index.vue +++ b/pages/item/_id/_episode/index.vue @@ -288,20 +288,65 @@ export default { value: 'playlist', icon: 'playlist_add' }) + } - if (this.isAdminOrUp) { - items.push({ - text: 'Remove from Server', - value: 'remove_from_server', - icon: 'delete_forever' - }) - } + if (this.localEpisodeId) { + items.push({ + text: 'Delete Local Episode', + value: 'deleteLocal', + icon: 'delete' + }) + } + + if (this.isAdminOrUp && this.serverEpisodeId) { + items.push({ + text: 'Remove from Server', + value: 'remove_from_server', + icon: 'delete_forever' + }) } return items } }, methods: { + async deleteLocalEpisode() { + await this.$hapticsImpact() + + const localEpisodeAudioTrack = this.localEpisode.audioTrack + const localFile = this.localLibraryItem.localFiles.find((lf) => lf.id === localEpisodeAudioTrack.localFileId) + if (!localFile) { + this.$toast.error('Audio track does not have matching local file..') + return + } + + let confirmMessage = `Remove local episode "${localFile.basePath}" from your device?` + if (this.serverLibraryItemId) { + confirmMessage += ' The file on the server will be unaffected.' + } + const { value } = await Dialog.confirm({ + title: 'Confirm', + message: confirmMessage + }) + if (value) { + const res = await AbsFileSystem.deleteTrackFromItem({ id: this.localLibraryItemId, trackLocalFileId: localFile.id, trackContentUrl: localEpisodeAudioTrack.contentUrl }) + if (res?.id) { + this.$toast.success('Deleted episode successfully') + if (this.isLocal) { + // If this is local episode then redirect to server episode when available + if (this.serverEpisodeId) { + this.$router.replace(`/item/${this.serverLibraryItemId}/${this.serverEpisodeId}`) + } else { + this.$router.replace(`/item/${this.localLibraryItemId}`) + } + } else { + // Update local library item and local episode + this.libraryItem.localLibraryItem = res + this.$delete(this.episode, 'localEpisode') + } + } else this.$toast.error('Failed to delete') + } + }, async playClick() { await this.$hapticsImpact() if (this.playerIsPlaying) { @@ -408,8 +453,10 @@ export default { } else if (action === 'playlist' && !this.isLocal) { this.$store.commit('globals/setSelectedPlaylistItems', [{ libraryItem: this.libraryItem, episode: this.episode }]) this.$store.commit('globals/setShowPlaylistsAddCreateModal', true) - } else if (action === 'remove_from_server' && !this.isLocal && this.isAdminOrUp) { + } else if (action === 'remove_from_server' && this.serverEpisodeId && this.isAdminOrUp) { this.deleteEpisodeFromServerClick() + } else if (action === 'deleteLocal') { + this.deleteLocalEpisode() } }, async discardProgress() { @@ -496,13 +543,13 @@ export default { if (value) { this.processing = true this.$axios - .$delete(`/api/podcasts/${this.libraryItemId}/episode/${this.episode.id}?hard=1`) + .$delete(`/api/podcasts/${this.serverLibraryItemId}/episode/${this.serverEpisodeId}?hard=1`) .then(() => { this.$toast.success('Episode deleted from server') - this.$router.replace(`/item/${this.libraryItemId}`) + this.$router.replace(`/item/${this.serverLibraryItemId}`) }) .catch((error) => { - const errorMsg = error.response && error.response.data ? error.response.data : 'Failed to delete episode' + const errorMsg = error.response?.data || 'Failed to delete episode' console.error('Failed to delete episode', error) this.$toast.error(errorMsg) }) diff --git a/pages/item/_id/index.vue b/pages/item/_id/index.vue index b589bb17..24efc1b6 100644 --- a/pages/item/_id/index.vue +++ b/pages/item/_id/index.vue @@ -413,14 +413,6 @@ export default { } } - if (this.localLibraryItemId) { - items.push({ - text: 'Manage Local Files', - value: 'manageLocal', - icon: 'folder' - }) - } - if (!this.isPodcast && this.serverLibraryItemId) { items.push({ text: 'Add to Playlist', @@ -429,6 +421,22 @@ export default { }) } + if (this.localLibraryItemId) { + items.push({ + text: 'Manage Local Files', + value: 'manageLocal', + icon: 'folder' + }) + + if (!this.isPodcast) { + items.push({ + text: 'Delete Local Item', + value: 'deleteLocal', + icon: 'delete' + }) + } + } + items.push({ text: 'More Info', value: 'details', @@ -451,6 +459,35 @@ export default { } }, methods: { + async deleteLocalItem() { + await this.$hapticsImpact() + + let confirmMessage = 'Remove local files of this item from your device?' + if (this.serverLibraryItemId) { + confirmMessage += ' The files on the server and your progress will be unaffected.' + } + const { value } = await Dialog.confirm({ + title: 'Confirm', + message: confirmMessage + }) + if (value) { + const res = await AbsFileSystem.deleteItem(this.localLibraryItem) + if (res?.success) { + this.$toast.success('Deleted successfully') + if (this.isLocal) { + // If local then redirect to server version when available + if (this.serverLibraryItemId) { + this.$router.replace(`/item/${this.serverLibraryItemId}`) + } else { + this.$router.replace('/bookshelf') + } + } else { + // Remove localLibraryItem + this.$delete(this.libraryItem, 'localLibraryItem') + } + } else this.$toast.error('Failed to delete') + } + }, async coverImageLoaded(fullCoverUrl) { if (!fullCoverUrl) return @@ -483,6 +520,8 @@ export default { this.$router.push(`/media/${this.mediaId}/history?title=${this.title}`) } else if (action === 'discardProgress') { this.clearProgressClick() + } else if (action === 'deleteLocal') { + this.deleteLocalItem() } }, moreButtonPress() { diff --git a/pages/localMedia/item/_id.vue b/pages/localMedia/item/_id.vue index f4b3f59e..7e2f931f 100644 --- a/pages/localMedia/item/_id.vue +++ b/pages/localMedia/item/_id.vue @@ -224,18 +224,17 @@ export default { if (this.selectedAudioTrack || this.selectedEpisode) { return [ { - text: 'Remove & Delete Files', + text: 'Delete local file', value: 'track-delete' } ] } else { var options = [] - if (!this.isIos && !this.isInternalStorage) { + if (!this.isIos && !this.isInternalStorage && !this.libraryItemId) { options.push({ text: 'Scan', value: 'scan' }) options.push({ text: 'Force Re-Scan', value: 'rescan' }) - options.push({ text: 'Remove', value: 'remove' }) } - options.push({ text: 'Remove & Delete Files', value: 'delete' }) + options.push({ text: 'Delete local item', value: 'delete' }) return options } } @@ -295,12 +294,11 @@ export default { async dialogAction(action) { console.log('Dialog action', action) await this.$hapticsImpact() + if (action == 'scan') { this.scanItem() } else if (action == 'rescan') { this.scanItem(true) - } else if (action == 'remove') { - this.removeItem() } else if (action == 'delete') { this.deleteItem() } else if (action == 'track-delete') { @@ -319,10 +317,14 @@ export default { this.$toast.error('Audio track does not have matching local file..') return } - var trackPath = localFile ? localFile.basePath : this.selectedEpisode.title + + let confirmMessage = `Remove local audio file "${localFile.basePath}" from your device?` + if (this.libraryItemId) { + confirmMessage += ' The file on the server will be unaffected.' + } const { value } = await Dialog.confirm({ title: 'Confirm', - message: `Warning! This will delete the audio file "${trackPath}" from your file system. Are you sure?` + message: confirmMessage }) if (value) { var res = await AbsFileSystem.deleteTrackFromItem({ id: this.localLibraryItem.id, trackLocalFileId: localFile.id, trackContentUrl: this.selectedEpisode.audioTrack.contentUrl }) @@ -341,10 +343,14 @@ export default { this.$toast.error('Audio track does not have matching local file..') return } - var trackPath = localFile ? localFile.basePath : this.selectedAudioTrack.title + + let confirmMessage = `Remove local audio file "${localFile.basePath}" from your device?` + if (this.libraryItemId) { + confirmMessage += ' The file on the server will be unaffected.' + } const { value } = await Dialog.confirm({ title: 'Confirm', - message: `Warning! This will delete the audio file "${trackPath}" from your file system. Are you sure?` + message: confirmMessage }) if (value) { var res = await AbsFileSystem.deleteTrackFromItem({ id: this.localLibraryItem.id, trackLocalFileId: this.selectedAudioTrack.localFileId, trackContentUrl: this.selectedAudioTrack.contentUrl }) @@ -355,9 +361,13 @@ export default { } }, async deleteItem() { + let confirmMessage = 'Remove local files of this item from your device?' + if (this.libraryItemId) { + confirmMessage += ' The files on the server and your progress will be unaffected.' + } const { value } = await Dialog.confirm({ title: 'Confirm', - message: `Warning! This will delete "${this.media.metadata.title}" and all associated local files. Are you sure?` + message: confirmMessage }) if (value) { var res = await AbsFileSystem.deleteItem(this.localLibraryItem) @@ -367,19 +377,6 @@ export default { } else this.$toast.error('Failed to delete') } }, - async removeItem() { - var deleteMessage = 'Are you sure you want to remove this local library item? (does not delete anything in your file system)' - const { value } = await Dialog.confirm({ - title: 'Confirm', - message: deleteMessage - }) - if (value) { - this.removingItem = true - await AbsFileSystem.removeLocalLibraryItem({ localLibraryItemId: this.localLibraryItemId }) - this.removingItem = false - this.$router.replace(`/localMedia/folders/${this.folderId}`) - } - }, async scanItem(forceAudioProbe = false) { if (this.isScanning) return