Files
qbz/crates/qbz-qt/qml/controls/LinkResolverModal.qml
T
vicrodh 69e5066d07 fix(qt): wheel-lock sweep across plain-Item modal overlays
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
2026-08-31 11:50:32 -06:00

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()
}
}
}
}
}
}