diff --git a/README.md b/README.md index 022404d..da2dd01 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,8 @@ BearWave intentionally does not aim to be: BearWave is an early public, source-first desktop project. +BearWave is currently in public beta and is best supported on Arch Linux and KDE Plasma. + It is already usable, but it should currently be treated as software for testers, contributors, and technically comfortable Linux users rather than a polished end-user release. Current priorities: diff --git a/assets/app/bearwave_line.png b/assets/app/bearwave_line.png new file mode 100755 index 0000000..cb4f961 Binary files /dev/null and b/assets/app/bearwave_line.png differ diff --git a/src/qml.qrc b/src/qml.qrc index 799c5fc..396f25a 100644 --- a/src/qml.qrc +++ b/src/qml.qrc @@ -2,6 +2,7 @@ qml/Main.qml ../assets/app/bearwave.png + ../assets/app/bearwave_line.png ../assets/ui/globe.svg ../assets/ui/github.svg ../assets/ui/linkedin.svg diff --git a/src/qml/Main.qml b/src/qml/Main.qml index 1e491e4..cdde6cf 100644 --- a/src/qml/Main.qml +++ b/src/qml/Main.qml @@ -127,24 +127,26 @@ ApplicationWindow { Rectangle { Layout.fillWidth: true - Layout.preferredHeight: compactMode ? 208 : 176 + Layout.preferredHeight: compactMode ? (headerContent.implicitHeight + 20) : 176 radius: 12 color: panel border.color: cardBorder ColumnLayout { + id: headerContent anchors.fill: parent anchors.margins: 10 spacing: 8 RowLayout { + visible: !compactMode Layout.fillWidth: true spacing: 8 Image { - Layout.preferredWidth: compactMode ? 88 : 112 - Layout.preferredHeight: compactMode ? 32 : 40 - source: "qrc:/assets/app/bearwave.png" + Layout.preferredWidth: 112 + Layout.preferredHeight: 40 + source: "qrc:/assets/app/bearwave_line.png" fillMode: Image.PreserveAspectFit smooth: true mipmap: true @@ -222,7 +224,98 @@ ApplicationWindow { } } + ColumnLayout { + visible: compactMode + Layout.fillWidth: true + spacing: 8 + + RowLayout { + Layout.fillWidth: true + spacing: 8 + + Image { + Layout.preferredWidth: 96 + Layout.preferredHeight: 34 + source: "qrc:/assets/app/bearwave_line.png" + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: true + } + + Item { Layout.fillWidth: true } + + Button { + text: "+" + onClicked: addDialog.open() + } + + Button { + text: qsTr("About") + onClicked: aboutDialog.open() + } + + Button { + visible: backend && backend.canResumeLastStation + text: "↺" + onClicked: { + if (backend) { + backend.resumeLastStation() + } + } + } + } + + Flow { + Layout.fillWidth: true + width: parent.width + spacing: 8 + + Button { + text: qsTr("Top") + highlighted: currentPage === "top" + onClicked: { + if (!backend) return + currentPage = "top" + activeQuickFilter = "" + backend.loadTopStations() + } + } + + Button { + text: qsTr("DE") + highlighted: currentPage === "german" + onClicked: { + if (!backend) return + currentPage = "german" + activeQuickFilter = "" + backend.loadGermanStations() + } + } + + Button { + text: qsTr("NL") + highlighted: currentPage === "dutch" + onClicked: { + if (!backend) return + currentPage = "dutch" + activeQuickFilter = "" + backend.loadDutchStations() + } + } + + Button { + text: qsTr("Favorites") + highlighted: currentPage === "favorites" + onClicked: { + currentPage = "favorites" + activeQuickFilter = "" + } + } + } + } + RowLayout { + visible: !compactMode Layout.fillWidth: true spacing: 8 @@ -280,15 +373,93 @@ ApplicationWindow { } } + ColumnLayout { + visible: compactMode + Layout.fillWidth: true + spacing: 8 + + TextField { + id: compactSearchField + Layout.fillWidth: true + placeholderText: qsTr("Search stations (name, genre, country)") + text: searchField.text + onTextChanged: { + if (searchField.text !== text) { + searchField.text = text + } + if (backend) { + backend.filterQuery = text + } + } + onAccepted: { + if (text.length < 2 || !backend) return + currentPage = "search" + backend.searchStations(text) + } + } + + RowLayout { + Layout.fillWidth: true + spacing: 8 + + Item { Layout.fillWidth: true } + + Button { + text: qsTr("Search") + highlighted: true + onClicked: { + if (compactSearchField.text.length < 2 || !backend) return + currentPage = "search" + backend.searchStations(compactSearchField.text) + } + } + } + + Flow { + Layout.fillWidth: true + width: parent.width + spacing: 8 + + Button { + text: "A-Z" + onClicked: { + if (backend && currentPage !== "favorites") { + backend.sortStations("name") + } + } + } + + Button { + text: "kb" + onClicked: { + if (backend && currentPage !== "favorites") { + backend.sortStations("bitrate") + } + } + } + + Button { + text: "❤" + onClicked: { + if (backend && currentPage !== "favorites") { + backend.sortStations("votes") + } + } + } + } + } + Label { Layout.fillWidth: true text: qsTr("Tip: you are not limited to DE/NL. Search worldwide by country, genre, or station name.") color: textMuted font.pixelSize: 11 - elide: Text.ElideRight + wrapMode: compactMode ? Text.WordWrap : Text.NoWrap + elide: compactMode ? Text.ElideNone : Text.ElideRight } RowLayout { + visible: !compactMode Layout.fillWidth: true spacing: 6 @@ -386,6 +557,117 @@ ApplicationWindow { Item { Layout.fillWidth: true } } + ColumnLayout { + visible: compactMode + Layout.fillWidth: true + spacing: 8 + + Flow { + Layout.fillWidth: true + width: parent.width + spacing: 8 + + Label { + text: qsTr("Genre:") + color: textMuted + font.pixelSize: 11 + verticalAlignment: Text.AlignVCenter + padding: 8 + } + + Button { + text: qsTr("Rock") + highlighted: activeQuickFilter === "tag:rock" + onClicked: { + if (!backend) return + currentPage = "genre-rock" + activeQuickFilter = "tag:rock" + backend.loadByTag("rock") + } + } + + Button { + text: qsTr("News") + highlighted: activeQuickFilter === "tag:news" + onClicked: { + if (!backend) return + currentPage = "genre-news" + activeQuickFilter = "tag:news" + backend.loadByTag("news") + } + } + + Button { + text: qsTr("Jazz") + highlighted: activeQuickFilter === "tag:jazz" + onClicked: { + if (!backend) return + currentPage = "genre-jazz" + activeQuickFilter = "tag:jazz" + backend.loadByTag("jazz") + } + } + } + + Flow { + Layout.fillWidth: true + width: parent.width + spacing: 8 + + Label { + text: qsTr("Country:") + color: textMuted + font.pixelSize: 11 + verticalAlignment: Text.AlignVCenter + padding: 8 + } + + Button { + text: qsTr("US") + highlighted: activeQuickFilter === "cc:US" + onClicked: { + if (!backend) return + currentPage = "country-us" + activeQuickFilter = "cc:US" + backend.loadByCountryCode("US") + } + } + + Button { + text: qsTr("UK") + highlighted: activeQuickFilter === "cc:GB" + onClicked: { + if (!backend) return + currentPage = "country-gb" + activeQuickFilter = "cc:GB" + backend.loadByCountryCode("GB") + } + } + + Button { + text: qsTr("FR") + highlighted: activeQuickFilter === "cc:FR" + onClicked: { + if (!backend) return + currentPage = "country-fr" + activeQuickFilter = "cc:FR" + backend.loadByCountryCode("FR") + } + } + + Button { + text: qsTr("WORLD") + highlighted: activeQuickFilter === "world" + onClicked: { + if (!backend) return + currentPage = "world" + activeQuickFilter = "world" + backend.loadWorldStations() + } + } + } + } + Label { Layout.fillWidth: true visible: backend && backend.lastError.length > 0 @@ -782,6 +1064,14 @@ ApplicationWindow { color: textMuted font.pixelSize: 14 } + + Label { + Layout.alignment: Qt.AlignHCenter + text: qsTr("Public beta") + color: accent + font.pixelSize: 12 + font.bold: true + } } // --- CREDITS & LINKS --- @@ -806,12 +1096,19 @@ ApplicationWindow { ToolButton { Layout.preferredWidth: 40 Layout.preferredHeight: 40 - icon.source: "qrc:/assets/ui/globe.svg" - icon.width: 19 - icon.height: 19 onClicked: Qt.openUrlExternally("https://palencsar.pro") ToolTip.visible: hovered ToolTip.text: qsTr("Open website") + contentItem: Item { + Image { + anchors.centerIn: parent + width: 19 + height: 19 + source: "qrc:/assets/ui/globe.svg" + fillMode: Image.PreserveAspectFit + smooth: true + } + } background: Rectangle { radius: 20 color: parent.hovered ? "#274261" : "#1f3147" @@ -823,12 +1120,19 @@ ApplicationWindow { ToolButton { Layout.preferredWidth: 40 Layout.preferredHeight: 40 - icon.source: "qrc:/assets/ui/github.svg" - icon.width: 19 - icon.height: 19 onClicked: Qt.openUrlExternally("https://github.com/spalencsar") ToolTip.visible: hovered ToolTip.text: qsTr("Open GitHub") + contentItem: Item { + Image { + anchors.centerIn: parent + width: 19 + height: 19 + source: "qrc:/assets/ui/github.svg" + fillMode: Image.PreserveAspectFit + smooth: true + } + } background: Rectangle { radius: 20 color: parent.hovered ? "#274261" : "#1f3147" @@ -840,12 +1144,19 @@ ApplicationWindow { ToolButton { Layout.preferredWidth: 40 Layout.preferredHeight: 40 - icon.source: "qrc:/assets/ui/linkedin.svg" - icon.width: 19 - icon.height: 19 onClicked: Qt.openUrlExternally("https://www.linkedin.com/in/spalencsar/") ToolTip.visible: hovered ToolTip.text: qsTr("Open LinkedIn") + contentItem: Item { + Image { + anchors.centerIn: parent + width: 19 + height: 19 + source: "qrc:/assets/ui/linkedin.svg" + fillMode: Image.PreserveAspectFit + smooth: true + } + } background: Rectangle { radius: 20 color: parent.hovered ? "#274261" : "#1f3147"