refactor(qt): extract search_bridge.rs from the QbzBridge god-object

QbzBridge carried five domains (Settings, Search, Playlist, Genre filter,
Discover config); its own boot() comment called the split "TEMP (phase 23)".
TRACK-RULES section 2 requires one cxx-qt bridge per domain. This moves the
Search domain out verbatim, ahead of the cortinilla parity work, so the
refactor and the behaviour change stay separately reviewable.

QbzSearch (search_bridge.rs) takes 7 properties and 11 invokables. Two
deliberate changes ride the move:

  - selected_index -> cortinilla_selected_index. It is cortinilla-only
    state and the bare name on an app-wide singleton is a collision hazard.
  - cortinilla_scroll_y f32 -> f64, unifying with the immersive twin in
    immersive_bridge.rs, which was already f64.

cortinilla_query is declared here but not yet wired; C2 wires it, which is
what makes Enter carry the text the user actually typed instead of the last
successfully loaded payload's query.

Every Rust writer of a moving property was re-pointed BY HAND, never by
regex over the multi-line ui() closures: the seven crate::ui( sites in
search_qt.rs plus two that live outside it and that the QML-only xref audit
cannot see - settings_qt.rs (the live Settings > Appearance path) and
main.rs toggle_intelligent_search. All 48 QML consumer sites across
Cortinilla.qml, HeaderBar.qml and SearchView.qml were updated, including the
one Connections block, whose onSelectedIndexChanged handler was renamed with
its property.

A stale 6.0 base in flat_index_content_y is left in place and annotated: it
mirrors a Flickable viewport margin rather than content space, so every row
reports 6px low. C4 corrects it with its unit test; this commit is a move.

Contract: qbz-nix-docs/qt-frontend/2026-08-03-cortinilla-parity, commit C0.

Gate: build clean (no new warnings), 256/256 tests, qml_resolution_audit
214 files, qml_singleton_xref 28 bridges with QbzSearch resolving, offscreen
smoke 0 complaints + home published.

cc
This commit is contained in:
vicrodh committed 2026-08-03 15:24:25 -06:00
1 parent 07b0ba818e
commit fa433d465b
11 files changed
+309 -172

No files matched your search

+15 -15
View File
@@ -1,5 +1,5 @@
// Search results view — the QML port of search/SearchResultsView.slint
// (phase 15). One JSON document (QbzBridge.searchJson, search_qt.rs
// (phase 15). One JSON document (QbzSearch.searchJson, search_qt.rs
// SearchPageDoc: query/tab/loading/filterIndex + the four category lists,
// totals, the most-popular hero, the carousel-only artists list).
//
@@ -65,7 +65,7 @@ Rectangle {
readonly property var doc: parseDoc()
function parseDoc() {
try {
return JSON.parse(QbzBridge.searchJson)
return JSON.parse(QbzSearch.searchJson)
} catch (e) {
return ({})
}
@@ -190,7 +190,7 @@ Rectangle {
root.fadeTab = t
root.fadeFrom = root.moreFrom
moreSettle.restart()
QbzBridge.searchLoadMore(t)
QbzSearch.searchLoadMore(t)
}
// `morePending` clears only when the tab's array GROWS — and search_qt::
// load_more never republishes on a failed fetch (main.rs just logs), nor
@@ -404,11 +404,11 @@ Rectangle {
anchors.rightMargin: 32
anchors.verticalCenter: parent.verticalCenter
spacing: 16
FilterRadio { label: QbzSession.tr("Main Artist", QbzSession.trRev); selected: root.filterIndex === 1; onPicked: QbzBridge.searchFilterChanged(1) }
FilterRadio { label: QbzSession.tr("Performer", QbzSession.trRev); selected: root.filterIndex === 2; onPicked: QbzBridge.searchFilterChanged(2) }
FilterRadio { label: QbzSession.tr("Composer", QbzSession.trRev); selected: root.filterIndex === 3; onPicked: QbzBridge.searchFilterChanged(3) }
FilterRadio { label: QbzSession.tr("Label", QbzSession.trRev); selected: root.filterIndex === 4; onPicked: QbzBridge.searchFilterChanged(4) }
FilterRadio { label: QbzSession.tr("Release Name", QbzSession.trRev); selected: root.filterIndex === 5; onPicked: QbzBridge.searchFilterChanged(5) }
FilterRadio { label: QbzSession.tr("Main Artist", QbzSession.trRev); selected: root.filterIndex === 1; onPicked: QbzSearch.searchFilterChanged(1) }
FilterRadio { label: QbzSession.tr("Performer", QbzSession.trRev); selected: root.filterIndex === 2; onPicked: QbzSearch.searchFilterChanged(2) }
FilterRadio { label: QbzSession.tr("Composer", QbzSession.trRev); selected: root.filterIndex === 3; onPicked: QbzSearch.searchFilterChanged(3) }
FilterRadio { label: QbzSession.tr("Label", QbzSession.trRev); selected: root.filterIndex === 4; onPicked: QbzSearch.searchFilterChanged(4) }
FilterRadio { label: QbzSession.tr("Release Name", QbzSession.trRev); selected: root.filterIndex === 5; onPicked: QbzSearch.searchFilterChanged(5) }
Rectangle {
visible: root.filterIndex !== 0
width: 24
@@ -422,7 +422,7 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: QbzBridge.searchFilterChanged(0)
onClicked: QbzSearch.searchFilterChanged(0)
}
}
}
@@ -460,7 +460,7 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: QbzBridge.searchTabChanged(modelData.t)
onClicked: QbzSearch.searchTabChanged(modelData.t)
}
}
Rectangle {
@@ -583,7 +583,7 @@ Rectangle {
showViewAll: true
viewAllAccent: true
showChevrons: false
onViewAllClicked: QbzBridge.searchTabChanged(3)
onViewAllClicked: QbzSearch.searchTabChanged(3)
}
ListView {
width: parent.width
@@ -612,7 +612,7 @@ Rectangle {
showViewAll: true
viewAllAccent: true
showChevrons: false
onViewAllClicked: QbzBridge.searchTabChanged(3)
onViewAllClicked: QbzSearch.searchTabChanged(3)
}
ListView {
width: parent.width
@@ -641,7 +641,7 @@ Rectangle {
showViewAll: true
viewAllAccent: true
showChevrons: false
onViewAllClicked: QbzBridge.searchTabChanged(1)
onViewAllClicked: QbzSearch.searchTabChanged(1)
}
ListView {
width: parent.width
@@ -772,7 +772,7 @@ Rectangle {
showViewAll: root.tab === 0 && (root.doc.tracksTotal || 0) > root.previewCap
viewAllAccent: true
showChevrons: false
onViewAllClicked: QbzBridge.searchTabChanged(2)
onViewAllClicked: QbzSearch.searchTabChanged(2)
}
Repeater {
model: root.tab === 2 ? root.tracks : root.tracks.slice(0, root.previewCap)
@@ -911,7 +911,7 @@ Rectangle {
showViewAll: true
viewAllAccent: true
showChevrons: false
onViewAllClicked: QbzBridge.searchTabChanged(4)
onViewAllClicked: QbzSearch.searchTabChanged(4)
}
ListView {
width: parent.width