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

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