From 2767387f8ecfdf1e6ccfcfd5e0faf7579d3ba7dc Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sun, 5 Jul 2026 23:36:16 +0200 Subject: [PATCH] phase 7a: desktop notifications on turn completion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Daemon tracks per-session state transitions - Fires freedesktop notification when any session goes non-idle→idle - 5 second auto-dismiss timeout --- daemon/session_manager.cpp | 41 ++++++++++++++++++++++++++++++++++---- daemon/session_manager.h | 8 ++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/daemon/session_manager.cpp b/daemon/session_manager.cpp index 9bb40a4..8607020 100644 --- a/daemon/session_manager.cpp +++ b/daemon/session_manager.cpp @@ -1,6 +1,7 @@ #include "session_manager.h" #include "libollie.h" +#include #include #include @@ -14,10 +15,9 @@ static void onStateChange(const char *session_id, const char *state) if (!g_instance) return; QString sid = QString::fromUtf8(session_id); QString st = QString::fromUtf8(state); - // Marshal to the Qt event loop thread - QMetaObject::invokeMethod(g_instance, [sid, st]() { - emit g_instance->StateChanged(sid, st); - }, Qt::QueuedConnection); + QMetaObject::invokeMethod(g_instance, "handleStateChange", + Qt::QueuedConnection, + Q_ARG(QString, sid), Q_ARG(QString, st)); } static void onChatUpdate(const char *session_id, int64_t offset, const char *text, int len) @@ -103,6 +103,7 @@ bool SessionManager::KillSession(const QString &session_id) QByteArray idUtf8 = session_id.toUtf8(); int rc = ollie_kill_session(const_cast(idUtf8.constData())); if (rc == 0) { + m_sessionStates.remove(session_id); emit SessionKilled(session_id); return true; } @@ -306,3 +307,35 @@ bool SessionManager::PeerSubmit(const QString &session_id, const QString &peer_i const_cast(promptUtf8.constData())); return rc == 0; } + +// --- Notifications --- + +void SessionManager::handleStateChange(const QString &session_id, const QString &new_state) +{ + QString prev = m_sessionStates.value(session_id, "idle"); + m_sessionStates[session_id] = new_state; + + if (new_state == "idle" && prev != "idle") { + sendNotification("Ollie", "Session " + session_id.left(12) + " finished"); + } + + emit StateChanged(session_id, new_state); +} + +void SessionManager::sendNotification(const QString &title, const QString &body) +{ + QDBusInterface notifyIface( + "org.freedesktop.Notifications", + "/org/freedesktop/Notifications", + "org.freedesktop.Notifications", + QDBusConnection::sessionBus()); + notifyIface.call("Notify", + "ollie-kde", // app_name + (uint)0, // replaces_id + "system-run", // app_icon + title, // summary + body, // body + QStringList(), // actions + QVariantMap(), // hints + (int)5000); // timeout ms +} diff --git a/daemon/session_manager.h b/daemon/session_manager.h index ac1721b..4795ce2 100644 --- a/daemon/session_manager.h +++ b/daemon/session_manager.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include // SessionManager is the D-Bus adaptee. The generated SessionManagerAdaptor // (from qt6_add_dbus_adaptor) forwards D-Bus method calls to slots here. @@ -62,6 +64,12 @@ signals: private: void installCallbacks(); + void sendNotification(const QString &title, const QString &body); + + QHash m_sessionStates; + +private slots: + void handleStateChange(const QString &session_id, const QString &new_state); }; #endif // SESSION_MANAGER_H