refactor(qml): extract toast popup and station list panel

Move ScrollView/ListView/empty-state into StationListPanel and toast UI
into ToastPopup with show(). Main.qml is now ~271 lines; stationList
alias preserved for search debounce logic.
This commit is contained in:
Sebastian Palencsar
2026-06-20 14:27:05 +02:00
parent dfc98de077
commit cbd82e5ab1
5 changed files with 113 additions and 62 deletions

View File

@@ -15,6 +15,8 @@
<file>qml/components/AddStationDialog.qml</file> <file>qml/components/AddStationDialog.qml</file>
<file>qml/components/EditStationDialog.qml</file> <file>qml/components/EditStationDialog.qml</file>
<file>qml/components/LoadingOverlay.qml</file> <file>qml/components/LoadingOverlay.qml</file>
<file>qml/components/ToastPopup.qml</file>
<file>qml/components/StationListPanel.qml</file>
<file>qml/utils/FlagUtils.js</file> <file>qml/utils/FlagUtils.js</file>
</qresource> </qresource>
<qresource prefix="/"> <qresource prefix="/">

View File

@@ -31,10 +31,10 @@ ApplicationWindow {
property string selectedWorldType: "" property string selectedWorldType: ""
property string countrySearchText: "" property string countrySearchText: ""
property alias searchField: searchToolbar.searchField property alias searchField: searchToolbar.searchField
property alias stationList: stationPanel.stationList
function toast(message) { function toast(message) {
toastLabel.text = message toastPopup.show(message)
toastPopup.open()
} }
function resetSearchFilter() { function resetSearchFilter() {
@@ -192,27 +192,11 @@ ApplicationWindow {
app: root app: root
} }
ScrollView { StationListPanel {
id: stationScrollView id: stationPanel
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
visible: !(currentPage === "world" && selectedWorldCategory === "") app: root
clip: true
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
ListView {
id: stationList
width: stationScrollView.availableWidth
spacing: 8
model: activeModel()
visible: count > 0
delegate: StationCard {
app: root
compactMode: root.compactMode
listWidth: stationScrollView.availableWidth
}
}
} }
WorldCategories { WorldCategories {
@@ -223,23 +207,6 @@ ApplicationWindow {
compactMode: root.compactMode compactMode: root.compactMode
} }
} }
Column {
anchors.centerIn: parent
spacing: 8
visible: stationList.count === 0 && !(currentPage === "world" && selectedWorldCategory === "")
Label {
text: currentPage === "history" ? qsTr("No playback history") : qsTr("No stations loaded yet")
color: BearTheme.textMain
font.bold: true
}
Label {
text: currentPage === "history" ? qsTr("Play some stations to build history") : qsTr("Load DE/NL stations or use search")
color: BearTheme.textMuted
}
}
} }
PlayerBar { PlayerBar {
@@ -275,30 +242,9 @@ ApplicationWindow {
compactMode: root.compactMode compactMode: root.compactMode
} }
Popup { ToastPopup {
id: toastPopup id: toastPopup
x: (root.width - width) / 2 window: root
y: root.height - height - 20
padding: 10
closePolicy: Popup.NoAutoClose
background: Rectangle {
radius: 10
color: "#24364e"
border.color: BearTheme.accent
}
contentItem: Label {
id: toastLabel
color: BearTheme.textMain
font.pixelSize: 12
}
Timer {
interval: 1400
running: toastPopup.visible
repeat: false
onTriggered: toastPopup.close()
}
} }
Timer { Timer {

View File

@@ -0,0 +1,59 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.15
import QtQuick.Controls 2.15
import theme 1.0
Item {
id: root
required property var app
property alias stationList: stationList
readonly property bool showEmptyState: stationList.count === 0
&& !(app.currentPage === "world" && app.selectedWorldCategory === "")
ScrollView {
id: stationScrollView
anchors.fill: parent
visible: !(app.currentPage === "world" && app.selectedWorldCategory === "")
clip: true
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
ListView {
id: stationList
width: stationScrollView.availableWidth
spacing: 8
model: app.activeModel()
visible: count > 0
delegate: StationCard {
app: root.app
compactMode: root.app.compactMode
listWidth: stationScrollView.availableWidth
}
}
}
Column {
anchors.centerIn: parent
spacing: 8
visible: root.showEmptyState
Label {
text: app.currentPage === "history" ? qsTr("No playback history") : qsTr("No stations loaded yet")
color: BearTheme.textMain
font.bold: true
}
Label {
text: app.currentPage === "history"
? qsTr("Play some stations to build history")
: qsTr("Load DE/NL stations or use search")
color: BearTheme.textMuted
}
}
}

View File

@@ -0,0 +1,42 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.15
import QtQuick.Controls 2.15
import theme 1.0
Popup {
id: root
required property var window
padding: 10
closePolicy: Popup.NoAutoClose
x: (window.width - width) / 2
y: window.height - height - 20
function show(message) {
toastLabel.text = message
open()
}
background: Rectangle {
radius: 10
color: "#24364e"
border.color: BearTheme.accent
}
contentItem: Label {
id: toastLabel
color: BearTheme.textMain
font.pixelSize: 12
}
Timer {
interval: 1400
running: root.visible
repeat: false
onTriggered: root.close()
}
}

View File

@@ -8,4 +8,6 @@ PlayerBar 1.0 PlayerBar.qml
AboutDialog 1.0 AboutDialog.qml AboutDialog 1.0 AboutDialog.qml
AddStationDialog 1.0 AddStationDialog.qml AddStationDialog 1.0 AddStationDialog.qml
EditStationDialog 1.0 EditStationDialog.qml EditStationDialog 1.0 EditStationDialog.qml
LoadingOverlay 1.0 LoadingOverlay.qml LoadingOverlay 1.0 LoadingOverlay.qml
ToastPopup 1.0 ToastPopup.qml
StationListPanel 1.0 StationListPanel.qml