diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js
index 6f9ff99bcfd99..03a3ec34ab6be 100644
--- a/src/renderer/components/playlist-info/playlist-info.js
+++ b/src/renderer/components/playlist-info/playlist-info.js
@@ -10,6 +10,9 @@ import {
ctrlFHandler,
formatNumber,
showToast,
+ getTodayDateStrLocalTimezone,
+ writeFileFromDialog,
+ showSaveDialog,
} from '../../helpers/utils'
import debounce from 'lodash.debounce'
@@ -262,6 +265,13 @@ export default defineComponent({
return this.selectedUserPlaylist.videos.length - this.userPlaylistUniqueVideoIds.size
},
+ exportPlaylistButtonVisible: function() {
+ // Only online playlists can be shared
+ if (!this.isUserPlaylist) { return false }
+
+ return this.videoCount > 0
+ },
+
deletePlaylistButtonVisible: function() {
if (!this.isUserPlaylist) { return false }
// Cannot delete during edit
@@ -275,7 +285,6 @@ export default defineComponent({
// Only online playlists can be shared
if (this.isUserPlaylist) { return false }
- // Cannot delete protected playlist
return !this.hideSharingActions
},
@@ -412,6 +421,41 @@ export default defineComponent({
showToast(this.playlistDeletionDisabledLabel)
},
+ handlePlaylistExport: async function () {
+ const dateStr = getTodayDateStrLocalTimezone()
+ const title = this.selectedUserPlaylist.playlistName.replaceAll(' ', '_').replaceAll(/["%*/:<>?\\|]/g, '_')
+ const exportFileName = 'freetube-playlist-' + title + '-' + dateStr + '.db'
+
+ const options = {
+ defaultPath: exportFileName,
+ filters: [
+ {
+ name: 'Database File',
+ extensions: ['db']
+ }
+ ]
+ }
+
+ const data = JSON.stringify(this.selectedUserPlaylist) + '\n'
+
+ // See data-settings.js `promptAndWriteToFile`
+ const response = await showSaveDialog(options)
+ if (response.canceled || response.filePath === '') {
+ // User canceled the save dialog
+ return
+ }
+
+ try {
+ await writeFileFromDialog(response, data)
+ } catch (writeErr) {
+ const message = this.$t('Settings.Data Settings.Unable to write file')
+ showToast(`${message}: ${writeErr}`)
+ return
+ }
+
+ showToast(this.$t('User Playlists.The playlist has been successfully exported'))
+ },
+
exitEditMode: function () {
this.editMode = false
diff --git a/src/renderer/components/playlist-info/playlist-info.vue b/src/renderer/components/playlist-info/playlist-info.vue
index 4c8c0cfcf9959..3b594f1606ee8 100644
--- a/src/renderer/components/playlist-info/playlist-info.vue
+++ b/src/renderer/components/playlist-info/playlist-info.vue
@@ -169,6 +169,13 @@
theme="secondary"
@click="toggleCopyVideosPrompt"
/>
+