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

@@ -9,3 +9,5 @@ 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