feat(qt): move a playlist to a folder from its editor, delete one from any context menu

The editor gains a Folder row — the same folders the sidebar and the
manager file playlists into, "No folder" for the root — seeded from the
playlist's current folder and applied on Save through the manager's own
move verb, so an existing playlist no longer needs the sidebar's row menu
to be filed (#785). "Delete playlist" joins the sidebar row menu (own and
local playlists; sidebar entries now carry isOwner) and the playlist card
menu (own playlists), behind a shell-level "Delete playlist?" confirmation
that runs the same delete the editor's button runs and leaves the detail
page only when it was the deleted one (#776). Eight catalogs updated.

cc
This commit is contained in:
vicrodh committed 2026-09-13 14:47:12 -06:00
1 parent 83c12c62c5
commit 1ba578a1d8
17 files changed
+445 -35

No files matched your search

+7
View File
@@ -950,6 +950,13 @@ Rectangle {
PlaylistEditModal {
anchors.fill: parent
}
// PlaylistDeleteConfirm — the "Delete playlist?" confirmation the sidebar
// row menu and the playlist cards summon (QbzPlaylistEdit.askDelete).
// Self-gates on QbzPlaylistEdit.deleteJson; invisible and inert while
// closed. Out here for the same reason as FolderModals above.
PlaylistDeleteConfirm {
anchors.fill: parent
}
// PlaylistCreateModal — "New playlist" (name · description · folder ·
// public · offline-only), raised by the sidebar's "+" and, like its
// neighbour, self-gating on its own document (QbzPlaylistEdit.createJson).
@@ -89,6 +89,10 @@ QbzContextMenu {
readonly property bool isFolder: root.entry !== null && root.entry.kind === "folder"
readonly property bool isLocal: root.entry !== null && root.entry.isLocal === true
/// The signed-in user owns the Qobuz playlist (sidebar_qt stamps it);
/// a local playlist is always the user's own.
readonly property bool isOwner: root.entry !== null
&& (root.entry.isLocal === true || root.entry.isOwner === true)
readonly property string entryId: root.entry !== null ? String(root.entry.id) : ""
readonly property string entryFolderId:
(root.entry !== null && root.entry.folderId) ? String(root.entry.folderId) : ""
@@ -261,6 +265,19 @@ QbzContextMenu {
}
}
// Divider before the move-to-folder section — Qobuz only.
// Delete (2026-09-13): the fast path the editor's danger button already
// offers, one click from the row, behind the shell-level confirmation
// (PlaylistDeleteConfirm.qml). Owned Qobuz playlists and local ones only;
// a followed playlist keeps its Unfollow elsewhere.
MenuRow {
visible: !root.isFolder && root.isOwner
icon: "trash-2"
label: QbzSession.tr("Delete playlist", QbzSession.trRev)
onActivated: {
root.close()
QbzPlaylistEdit.askDelete(root.entryId, String(root.entry.name))
}
}
Item {
visible: !root.isFolder && !root.isLocal
width: parent ? parent.width : 0