fix(notifications): bar bell dot = unread since history visit

This commit is contained in:
Ly-sec
2026-05-03 11:05:06 +02:00
parent 4aafcf5a31
commit f83ba97182
8 changed files with 40 additions and 1 deletions
+4
View File
@@ -130,6 +130,10 @@ Application::Application() : m_weatherService(m_configService, m_httpClient) {
const char* origin = (n.origin == NotificationOrigin::Internal) ? "internal" : "external";
kLog.debug("notification {} id={} origin={}", kind, n.id, origin);
if (event == NotificationEvent::Added && m_panelManager.isActivePanelContext("notifications")) {
m_notificationManager.markNotificationHistorySeen();
}
// Keep bar widgets in sync with notification state changes.
m_bar.refresh();
if (shouldRefreshControlCenter()) {
+14
View File
@@ -164,6 +164,7 @@ uint32_t NotificationManager::addOrReplace(uint32_t replaces_id, std::string app
const auto& n = m_notifications.back();
log_notification(n, "added");
upsertHistory(n, true, std::nullopt);
m_unreadSinceHistoryVisit = true;
for (auto& [token, cb] : m_eventCallbacks) {
cb(n, NotificationEvent::Added);
@@ -270,6 +271,7 @@ void NotificationManager::clearHistory() {
m_history.clear();
m_historyIndex.clear();
++m_changeSerial;
markNotificationHistorySeen();
}
std::vector<uint32_t> NotificationManager::expiredIds() const {
@@ -344,3 +346,15 @@ bool NotificationManager::toggleDoNotDisturb() {
void NotificationManager::setStateCallback(StateCallback callback) { m_stateCallback = std::move(callback); }
void NotificationManager::setSoundPlayer(SoundPlayer* soundPlayer) { m_soundPlayer = soundPlayer; }
bool NotificationManager::hasUnreadNotificationHistory() const noexcept { return m_unreadSinceHistoryVisit; }
void NotificationManager::markNotificationHistorySeen() {
if (!m_unreadSinceHistoryVisit) {
return;
}
m_unreadSinceHistoryVisit = false;
if (m_stateCallback) {
m_stateCallback();
}
}
+6
View File
@@ -86,6 +86,11 @@ public:
void setStateCallback(StateCallback callback);
void setSoundPlayer(class SoundPlayer* soundPlayer);
// Bar indicator: true when at least one notification was added since the user last
// viewed the notification history (control center notifications tab).
[[nodiscard]] bool hasUnreadNotificationHistory() const noexcept;
void markNotificationHistorySeen();
private:
void upsertHistory(const Notification& notification, bool active, std::optional<CloseReason> closeReason);
void rebuildHistoryIndex();
@@ -101,5 +106,6 @@ private:
uint32_t m_nextId{1};
std::uint64_t m_changeSerial{0};
bool m_doNotDisturb = false;
bool m_unreadSinceHistoryVisit = false;
class SoundPlayer* m_soundPlayer = nullptr;
};
@@ -78,7 +78,7 @@ void NotificationWidget::doLayout(Renderer& renderer, float /*containerWidth*/,
void NotificationWidget::doUpdate(Renderer& /*renderer*/) { refreshIndicatorState(); }
void NotificationWidget::refreshIndicatorState() {
const bool hasNotifications = (m_manager != nullptr) && !m_manager->all().empty();
const bool hasNotifications = (m_manager != nullptr) && m_manager->hasUnreadNotificationHistory();
const bool dndEnabled = (m_manager != nullptr) && m_manager->doNotDisturb();
if (hasNotifications == m_hasNotifications && dndEnabled == m_dndEnabled) {
return;
@@ -1,6 +1,7 @@
#include "shell/control_center/control_center_panel.h"
#include "i18n/i18n.h"
#include "notification/notification_manager.h"
#include "render/core/renderer.h"
#include "render/scene/input_area.h"
#include "shell/panel/panel_manager.h"
@@ -22,6 +23,7 @@ ControlCenterPanel::ControlCenterPanel(NotificationManager* notifications, PipeW
noctalia::theme::ThemeService* theme, IdleInhibitor* idleInhibitor,
WaylandConnection* wayland, Wallpaper* wallpaper) {
(void)upower;
m_notificationManager = notifications;
m_tabs[tabIndex(TabId::Overview)] =
std::make_unique<OverviewTab>(mpris, weather, audio, powerProfiles, config, network, bluetooth, nightLight, theme,
notifications, idleInhibitor, wayland, wallpaper);
@@ -275,6 +277,9 @@ bool ControlCenterPanel::deferPointerRelayout() const { return deferExternalRefr
void ControlCenterPanel::selectTab(TabId tab) {
m_activeTab = tab;
if (tab == TabId::Notifications && m_notificationManager != nullptr) {
m_notificationManager->markNotificationHistorySeen();
}
for (const auto& meta : kTabs) {
const std::size_t idx = tabIndex(meta.id);
if (m_tabContainers[idx] != nullptr) {
@@ -134,4 +134,5 @@ private:
std::array<Flex*, kTabCount> m_tabContainers{};
std::array<Flex*, kTabCount> m_tabHeaderActions{};
TabId m_activeTab = TabId::Overview;
NotificationManager* m_notificationManager = nullptr;
};
+7
View File
@@ -762,6 +762,13 @@ bool PanelManager::isAttachedOpen() const noexcept { return isOpen() && m_attach
const std::string& PanelManager::activePanelId() const noexcept { return m_activePanelId; }
bool PanelManager::isActivePanelContext(std::string_view context) const noexcept {
if (!isOpen() || m_activePanel == nullptr) {
return false;
}
return m_activePanel->isContextActive(context);
}
void PanelManager::refresh() {
if (!isOpen() || m_renderContext == nullptr || m_activePanel == nullptr || m_surface == nullptr) {
return;
+2
View File
@@ -77,6 +77,8 @@ public:
[[nodiscard]] bool isOpen() const noexcept;
[[nodiscard]] bool isAttachedOpen() const noexcept;
[[nodiscard]] const std::string& activePanelId() const noexcept;
// True when a panel is open and it reports the given context as active (e.g. control-center tab).
[[nodiscard]] bool isActivePanelContext(std::string_view context) const noexcept;
[[nodiscard]] std::optional<LayerPopupParentContext> popupParentContextForSurface(wl_surface* surface) const noexcept;
[[nodiscard]] std::optional<LayerPopupParentContext> fallbackPopupParentContext() const noexcept;