refactor(qml): extract dialogs and loading overlay from Main.qml

Add AddStationDialog, EditStationDialog, and LoadingOverlay components.
Main.qml shrinks to ~325 lines; dialog IDs and app.editDialog API unchanged.
This commit is contained in:
Sebastian Palencsar
2026-06-20 14:24:25 +02:00
parent 44597ec089
commit dfc98de077
6 changed files with 150 additions and 98 deletions

View File

@@ -12,6 +12,9 @@
<file>qml/components/WorldCategories.qml</file> <file>qml/components/WorldCategories.qml</file>
<file>qml/components/PlayerBar.qml</file> <file>qml/components/PlayerBar.qml</file>
<file>qml/components/AboutDialog.qml</file> <file>qml/components/AboutDialog.qml</file>
<file>qml/components/AddStationDialog.qml</file>
<file>qml/components/EditStationDialog.qml</file>
<file>qml/components/LoadingOverlay.qml</file>
<file>qml/utils/FlagUtils.js</file> <file>qml/utils/FlagUtils.js</file>
</qresource> </qresource>
<qresource prefix="/"> <qresource prefix="/">

View File

@@ -248,38 +248,8 @@ ApplicationWindow {
} }
} }
Rectangle { LoadingOverlay {
visible: backend && backend.loading app: root
anchors.fill: parent
color: "#7f0b121a"
z: 20
Rectangle {
anchors.centerIn: parent
width: 210
height: 110
radius: 12
color: BearTheme.panel
border.color: BearTheme.cardBorder
Column {
anchors.centerIn: parent
spacing: 10
BusyIndicator {
running: true
width: 36
height: 36
anchors.horizontalCenter: parent.horizontalCenter
}
Label {
text: qsTr("Loading stations...")
color: BearTheme.textMain
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
} }
Component.onCompleted: { Component.onCompleted: {
@@ -288,75 +258,16 @@ ApplicationWindow {
} }
} }
Dialog { AddStationDialog {
id: addDialog id: addDialog
title: qsTr("Add station manually") app: root
modal: true compactMode: root.compactMode
anchors.centerIn: parent
width: compactMode ? 320 : 420
standardButtons: Dialog.Ok | Dialog.Cancel
contentItem: ColumnLayout {
spacing: 8
TextField { id: manualName; Layout.fillWidth: true; placeholderText: qsTr("Name") }
TextField { id: manualUrl; Layout.fillWidth: true; placeholderText: qsTr("Stream URL (http/https)") }
TextField { id: manualCountry; Layout.fillWidth: true; placeholderText: qsTr("Country (optional)") }
}
onAccepted: {
if (backend) {
backend.addManualStation(manualName.text, manualUrl.text, manualCountry.text)
toast(qsTr("Station added"))
}
manualName.text = ""
manualUrl.text = ""
manualCountry.text = ""
}
} }
Dialog { EditStationDialog {
id: editDialog id: editDialog
title: qsTr("Edit station") app: root
modal: true compactMode: root.compactMode
anchors.centerIn: parent
width: compactMode ? 320 : 420
standardButtons: Dialog.Ok | Dialog.Cancel
property var stationObject: null
contentItem: ColumnLayout {
spacing: 8
TextField { id: editName; Layout.fillWidth: true; placeholderText: qsTr("Name") }
TextField { id: editUrl; Layout.fillWidth: true; placeholderText: qsTr("Stream URL (http/https)") }
TextField { id: editCountry; Layout.fillWidth: true; placeholderText: qsTr("Country (optional)") }
}
function setupAndOpen() {
if (stationObject) {
editName.text = stationObject.name || ""
editUrl.text = stationObject.url || ""
editCountry.text = (stationObject.country === qsTr("Manual") ? "" : (stationObject.country || ""))
open()
}
}
onAccepted: {
if (backend && stationObject) {
backend.editManualStation(stationObject, editName.text, editUrl.text, editCountry.text)
toast(qsTr("Station updated"))
}
stationObject = null
editName.text = ""
editUrl.text = ""
editCountry.text = ""
}
onRejected: {
stationObject = null
editName.text = ""
editUrl.text = ""
editCountry.text = ""
}
} }
AboutDialog { AboutDialog {

View File

@@ -0,0 +1,36 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Dialog {
id: root
required property var app
required property bool compactMode
title: qsTr("Add station manually")
modal: true
anchors.centerIn: parent
width: compactMode ? 320 : 420
standardButtons: Dialog.Ok | Dialog.Cancel
contentItem: ColumnLayout {
spacing: 8
TextField { id: manualName; Layout.fillWidth: true; placeholderText: qsTr("Name") }
TextField { id: manualUrl; Layout.fillWidth: true; placeholderText: qsTr("Stream URL (http/https)") }
TextField { id: manualCountry; Layout.fillWidth: true; placeholderText: qsTr("Country (optional)") }
}
onAccepted: {
if (app.backend) {
app.backend.addManualStation(manualName.text, manualUrl.text, manualCountry.text)
app.toast(qsTr("Station added"))
}
manualName.text = ""
manualUrl.text = ""
manualCountry.text = ""
}
}

View File

@@ -0,0 +1,54 @@
// Copyright (c) 2026 Sebastian Palencsar
// SPDX-License-Identifier: GPL-3.0-or-later
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Dialog {
id: root
required property var app
required property bool compactMode
property var stationObject: null
title: qsTr("Edit station")
modal: true
anchors.centerIn: parent
width: compactMode ? 320 : 420
standardButtons: Dialog.Ok | Dialog.Cancel
contentItem: ColumnLayout {
spacing: 8
TextField { id: editName; Layout.fillWidth: true; placeholderText: qsTr("Name") }
TextField { id: editUrl; Layout.fillWidth: true; placeholderText: qsTr("Stream URL (http/https)") }
TextField { id: editCountry; Layout.fillWidth: true; placeholderText: qsTr("Country (optional)") }
}
function setupAndOpen() {
if (stationObject) {
editName.text = stationObject.name || ""
editUrl.text = stationObject.url || ""
editCountry.text = (stationObject.country === qsTr("Manual") ? "" : (stationObject.country || ""))
open()
}
}
function clearFields() {
stationObject = null
editName.text = ""
editUrl.text = ""
editCountry.text = ""
}
onAccepted: {
if (app.backend && stationObject) {
app.backend.editManualStation(stationObject, editName.text, editUrl.text, editCountry.text)
app.toast(qsTr("Station updated"))
}
clearFields()
}
onRejected: clearFields()
}

View File

@@ -0,0 +1,45 @@
// 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
Rectangle {
id: root
required property var app
visible: app.backend && app.backend.loading
anchors.fill: parent
color: "#7f0b121a"
z: 20
Rectangle {
anchors.centerIn: parent
width: 210
height: 110
radius: 12
color: BearTheme.panel
border.color: BearTheme.cardBorder
Column {
anchors.centerIn: parent
spacing: 10
BusyIndicator {
running: true
width: 36
height: 36
anchors.horizontalCenter: parent.horizontalCenter
}
Label {
text: qsTr("Loading stations...")
color: BearTheme.textMain
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}

View File

@@ -5,4 +5,7 @@ StationCard 1.0 StationCard.qml
WorldCategoryHeader 1.0 WorldCategoryHeader.qml WorldCategoryHeader 1.0 WorldCategoryHeader.qml
WorldCategories 1.0 WorldCategories.qml WorldCategories 1.0 WorldCategories.qml
PlayerBar 1.0 PlayerBar.qml PlayerBar 1.0 PlayerBar.qml
AboutDialog 1.0 AboutDialog.qml AboutDialog 1.0 AboutDialog.qml
AddStationDialog 1.0 AddStationDialog.qml
EditStationDialog 1.0 EditStationDialog.qml
LoadingOverlay 1.0 LoadingOverlay.qml