Fix playback, API races, tray, MPRIS, and search UX; add tests

- Correct history/resume next-previous context and list index resync after reload
- Abort stale RadioBrowser requests and suppress error banners when cache satisfies loads
- Reset local search filter on page changes and debounce compact-mode API search
- Move system tray to C++ (QSystemTrayIcon) for reliable Wayland context menus
- Harden MPRIS registration and metadata updates for Plasma media widgets
- Add playback and API race unit tests
- Drop unused KF6 Kirigami, I18n, and CoreAddons build dependencies
- Update packaging docs, CI, and PKGBUILD to match Qt-only requirements
This commit is contained in:
Sebastian Palencsar
2026-06-20 14:06:48 +02:00
parent 4718810d24
commit 1c736b97a6
20 changed files with 1007 additions and 155 deletions

View File

@@ -11,6 +11,7 @@
#include <QDBusMessage>
#include <QDBusObjectPath>
#include <QStandardPaths>
#include <QUrl>
namespace {
void emitPlayerPropertiesChanged(const QStringList &changedProps, const QVariantMap &changedValues)
@@ -109,7 +110,7 @@ MprisPlayerAdaptor::MprisPlayerAdaptor(RadioBackend *backend)
, m_backend(backend)
{
BearPlayer *p = player();
if (!p) {
if (!p || !m_backend) {
return;
}
@@ -139,6 +140,24 @@ MprisPlayerAdaptor::MprisPlayerAdaptor(RadioBackend *backend)
changed.insert(QStringLiteral("Metadata"), metadata());
emitPlayerPropertiesChanged({QStringLiteral("Metadata")}, changed);
});
connect(m_backend, &RadioBackend::currentStationChanged, this, [this]() {
QVariantMap changed;
changed.insert(QStringLiteral("CanGoNext"), canGoNext());
changed.insert(QStringLiteral("CanGoPrevious"), canGoPrevious());
emitPlayerPropertiesChanged({QStringLiteral("CanGoNext"), QStringLiteral("CanGoPrevious")}, changed);
});
}
void MprisPlayerAdaptor::publishState()
{
QVariantMap changed;
changed.insert(QStringLiteral("PlaybackStatus"), playbackStatus());
changed.insert(QStringLiteral("Volume"), volume());
changed.insert(QStringLiteral("Metadata"), metadata());
changed.insert(QStringLiteral("CanGoNext"), canGoNext());
changed.insert(QStringLiteral("CanGoPrevious"), canGoPrevious());
emitPlayerPropertiesChanged({}, changed);
}
BearPlayer *MprisPlayerAdaptor::player() const
@@ -208,6 +227,7 @@ QVariantMap MprisPlayerAdaptor::metadata() const
const QString title = p->currentTrackTitle();
const QString artist = p->currentTrackArtist();
const QString coverUrl = p->currentCoverArtUrl();
const QString streamUrl = m_backend ? m_backend->currentStationUrl() : QString();
map.insert(QStringLiteral("mpris:trackid"), QVariant::fromValue(QDBusObjectPath(QStringLiteral("/org/kde/bearwave/track/0"))));
if (!station.isEmpty()) {
@@ -221,6 +241,9 @@ QVariantMap MprisPlayerAdaptor::metadata() const
if (!artist.isEmpty()) {
map.insert(QStringLiteral("xesam:artist"), QStringList{artist});
}
if (!streamUrl.isEmpty()) {
map.insert(QStringLiteral("xesam:url"), QUrl(streamUrl).toString());
}
QString artUrl = coverUrl;
if (artUrl.isEmpty() && m_backend) {
QObject *stationObj = m_backend->currentStation();