Plain-Item overlays get no modal grab, so a MouseArea that swallows presses still lets the wheel scroll the page underneath (the rule and its wording live in DiscoverConfigModal.qml). Every scrim and panel swallow across the modal set now accepts the wheel; the modal Popups (TrackInfo, CastPicker, AlbumInfo, QconnectDev, LocalMediaInfo) already had the Overlay grab, and CoverLightbox — a non-modal Popup — gets its own. cc
212 lines
7.5 KiB
QML
212 lines
7.5 KiB
QML
// App-wide music-link resolver. QbzLink owns state and async resolution;
|
|
// this file is only the modal surface and survives whichever menu/hotkey
|
|
// opened it.
|
|
|
|
import QtQuick
|
|
import com.blitzfc.qbz
|
|
import "../theme"
|
|
|
|
Item {
|
|
id: root
|
|
visible: QbzLink.modalOpen
|
|
|
|
QbzTheme { id: theme }
|
|
|
|
Keys.onEscapePressed: function(event) {
|
|
QbzLink.close()
|
|
event.accepted = true
|
|
}
|
|
|
|
onVisibleChanged: {
|
|
if (visible)
|
|
urlInput.focusField()
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
color: "#bf000000"
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
onClicked: QbzLink.close()
|
|
// Wheel-lock (the DiscoverConfigModal rule).
|
|
onWheel: function (wheel) { wheel.accepted = true }
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: card
|
|
anchors.centerIn: parent
|
|
width: Math.min(parent.width - 80, 520)
|
|
height: panel.implicitHeight + 48
|
|
radius: theme.radiusMd
|
|
color: theme.surfaceCard
|
|
border.width: 1
|
|
border.color: theme.borderSubtle
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
// Wheel-lock (the DiscoverConfigModal rule).
|
|
onWheel: function (wheel) { wheel.accepted = true }
|
|
}
|
|
|
|
Column {
|
|
id: panel
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.margins: 24
|
|
spacing: 16
|
|
|
|
Item {
|
|
width: parent.width
|
|
height: 28
|
|
Text {
|
|
anchors.left: parent.left
|
|
anchors.right: closeButton.left
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: QbzSession.tr("Open Music Link", QbzSession.trRev)
|
|
color: theme.textPrimary
|
|
font.pixelSize: theme.fontHeading
|
|
font.weight: theme.weightSemibold
|
|
elide: Text.ElideRight
|
|
}
|
|
Item {
|
|
id: closeButton
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: 28
|
|
height: 28
|
|
QbzIcon {
|
|
anchors.centerIn: parent
|
|
name: "x"
|
|
width: 17
|
|
height: 17
|
|
tintName: closeArea.containsMouse ? "textPrimary" : "muted"
|
|
}
|
|
MouseArea {
|
|
id: closeArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: QbzLink.close()
|
|
}
|
|
}
|
|
}
|
|
|
|
Row {
|
|
width: parent.width
|
|
height: 40
|
|
spacing: 8
|
|
|
|
Item {
|
|
width: 36
|
|
height: 40
|
|
|
|
Image {
|
|
anchors.centerIn: parent
|
|
width: 24
|
|
height: 24
|
|
fillMode: Image.PreserveAspectFit
|
|
visible: QbzLink.platform === "qobuz"
|
|
|| QbzLink.platform === "spotify"
|
|
|| QbzLink.platform === "apple"
|
|
|| QbzLink.platform === "deezer"
|
|
source: QbzLink.platform === "qobuz"
|
|
? "../assets/brand/qobuz-logo-filled.svg"
|
|
: QbzLink.platform === "spotify"
|
|
? "../assets/brand/spotify-logo.svg"
|
|
: QbzLink.platform === "apple"
|
|
? "../assets/brand/apple-music-logo.svg"
|
|
: "../assets/brand/deezer-logo.svg"
|
|
}
|
|
QbzIcon {
|
|
anchors.centerIn: parent
|
|
width: 24
|
|
height: 24
|
|
visible: QbzLink.platform === "tidal"
|
|
name: "tidal-tidal"
|
|
tintName: "accent"
|
|
}
|
|
QbzIcon {
|
|
anchors.centerIn: parent
|
|
width: 22
|
|
height: 22
|
|
visible: QbzLink.platform !== "qobuz"
|
|
&& QbzLink.platform !== "spotify"
|
|
&& QbzLink.platform !== "apple"
|
|
&& QbzLink.platform !== "deezer"
|
|
&& QbzLink.platform !== "tidal"
|
|
name: "link"
|
|
tintName: "muted"
|
|
}
|
|
}
|
|
|
|
QbzLineEdit {
|
|
id: urlInput
|
|
width: parent.width - 36 - goButton.width - 2 * parent.spacing
|
|
height: 40
|
|
text: QbzLink.url
|
|
placeholder: QbzSession.tr("Paste a Qobuz, Spotify, Apple Music, Tidal, Deezer or song.link URL", QbzSession.trRev)
|
|
enabled: !QbzLink.resolving
|
|
opacity: enabled ? 1.0 : 0.6
|
|
onEdited: function(value) { QbzLink.urlEdited(value) }
|
|
onAccepted: function(value) { QbzLink.submit(value) }
|
|
}
|
|
|
|
QbzPrimaryButton {
|
|
id: goButton
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
label: QbzLink.resolving
|
|
? QbzSession.tr("Resolving…", QbzSession.trRev)
|
|
: QbzSession.tr("Go", QbzSession.trRev)
|
|
btnHeight: 40
|
|
labelSize: theme.fontBody
|
|
btnEnabled: QbzLink.url.trim() !== "" && !QbzLink.resolving
|
|
onClicked: QbzLink.submit(QbzLink.url)
|
|
}
|
|
}
|
|
|
|
Text {
|
|
width: parent.width
|
|
visible: QbzLink.error !== ""
|
|
text: QbzLink.error
|
|
color: theme.danger
|
|
font.pixelSize: theme.fontLegal
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
|
|
Rectangle {
|
|
width: parent.width
|
|
height: playlistColumn.implicitHeight + 24
|
|
visible: QbzLink.playlistDetected
|
|
radius: theme.radiusSm
|
|
color: theme.surfaceElevated
|
|
border.width: 1
|
|
border.color: theme.borderSubtle
|
|
|
|
Column {
|
|
id: playlistColumn
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.margins: 12
|
|
spacing: 10
|
|
Text {
|
|
width: parent.width
|
|
text: QbzSession.tr("This looks like a playlist.", QbzSession.trRev)
|
|
color: theme.textSecondary
|
|
font.pixelSize: theme.fontLegal
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
QbzPrimaryButton {
|
|
label: QbzSession.tr("Open Playlist Importer", QbzSession.trRev)
|
|
btnHeight: 34
|
|
labelSize: theme.fontLegal
|
|
onClicked: QbzLink.openImporter()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|