gui: add activeSessionPaused property for reactive paused state

The isSessionPaused() Q_INVOKABLE didn't trigger QML binding
re-evaluation on pause/resume. New property with proper signal
makes ChatPane bindings reactive.

- activeSessionPaused property tracks active session's paused state
- Updated on refreshSessions() and switchAgent()
- ChatPane.qml uses property instead of function call
This commit is contained in:
Levi Neely 2026-10-06 15:23:44 +02:00
parent 4be78447fa
commit 91f295dc2d
3 changed files with 22 additions and 4 deletions

View File

@ -95,7 +95,7 @@ Item {
width: 10; height: 10; radius: 5 width: 10; height: 10; radius: 5
color: { color: {
if (!ollie.activeAgentId) return "#9e9e9e" // gray when no agent if (!ollie.activeAgentId) return "#9e9e9e" // gray when no agent
if (ollie.activeSessionId && ollie.isSessionPaused(ollie.activeSessionId)) return "#9e9e9e" // gray when paused if (ollie.activeSessionPaused) return "#9e9e9e" // gray when paused
if (ollie.activeState === "idle") return "#4caf50" if (ollie.activeState === "idle") return "#4caf50"
if (ollie.activeState.startsWith("calling")) return "#ff9800" if (ollie.activeState.startsWith("calling")) return "#ff9800"
return "#2196f3" return "#2196f3"
@ -105,7 +105,7 @@ Item {
Label { Label {
text: { text: {
if (!ollie.activeAgentId) return "" if (!ollie.activeAgentId) return ""
if (ollie.activeSessionId && ollie.isSessionPaused(ollie.activeSessionId)) return "inactive" if (ollie.activeSessionPaused) return "inactive"
return ollie.activeState return ollie.activeState
} }
opacity: 0.7 opacity: 0.7
@ -405,10 +405,10 @@ Item {
if (!ollie.daemonConnected) return "Not connected" if (!ollie.daemonConnected) return "Not connected"
if (!ollie.activeSessionId) return "No session" if (!ollie.activeSessionId) return "No session"
if (!ollie.activeAgentId) return "No agent" if (!ollie.activeAgentId) return "No agent"
if (ollie.isSessionPaused(ollie.activeSessionId)) return "Session paused" if (ollie.activeSessionPaused) return "Session paused"
return "B1=sel B2=exec B3=plumb B1+B2=cut B1+B3=paste" return "B1=sel B2=exec B3=plumb B1+B2=cut B1+B3=paste"
} }
enabled: ollie.daemonConnected && ollie.activeSessionId !== "" && ollie.activeAgentId !== "" && !ollie.isSessionPaused(ollie.activeSessionId) enabled: ollie.daemonConnected && ollie.activeSessionId !== "" && ollie.activeAgentId !== "" && !ollie.activeSessionPaused
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
selectByMouse: true selectByMouse: true
persistentSelection: true persistentSelection: true

View File

@ -368,6 +368,13 @@ void Ollie9pClient::refreshSessions()
emit sessionsChanged(); emit sessionsChanged();
// Update active session paused state
bool wasPaused = m_activeSessionPaused;
m_activeSessionPaused = isSessionPaused(m_activeSessionId);
if (m_activeSessionPaused != wasPaused) {
emit activeSessionPausedChanged();
}
// Handle active session/agent removal // Handle active session/agent removal
if (!m_activeSessionId.isEmpty()) { if (!m_activeSessionId.isEmpty()) {
if (!activeSessionFound) { if (!activeSessionFound) {
@ -581,9 +588,16 @@ void Ollie9pClient::switchAgent(const QString &sessionId, const QString &agentId
// Use cached state from live tracking if available, otherwise default to idle // Use cached state from live tracking if available, otherwise default to idle
m_activeState = m_agentStateValues.value(agentKey(sessionId, agentId), "idle"); m_activeState = m_agentStateValues.value(agentKey(sessionId, agentId), "idle");
// Update paused state
bool wasPaused = m_activeSessionPaused;
m_activeSessionPaused = isSessionPaused(sessionId);
emit activeSessionIdChanged(); emit activeSessionIdChanged();
emit activeAgentIdChanged(); emit activeAgentIdChanged();
emit activeStateChanged(); emit activeStateChanged();
if (m_activeSessionPaused != wasPaused) {
emit activeSessionPausedChanged();
}
startActiveAgentStreams(); startActiveAgentStreams();
} }

View File

@ -23,6 +23,7 @@ class Ollie9pClient : public QObject
Q_PROPERTY(QString activeSessionId READ activeSessionId WRITE setActiveSessionId NOTIFY activeSessionIdChanged) Q_PROPERTY(QString activeSessionId READ activeSessionId WRITE setActiveSessionId NOTIFY activeSessionIdChanged)
Q_PROPERTY(QString activeAgentId READ activeAgentId NOTIFY activeAgentIdChanged) Q_PROPERTY(QString activeAgentId READ activeAgentId NOTIFY activeAgentIdChanged)
Q_PROPERTY(QString activeState READ activeState NOTIFY activeStateChanged) Q_PROPERTY(QString activeState READ activeState NOTIFY activeStateChanged)
Q_PROPERTY(bool activeSessionPaused READ activeSessionPaused NOTIFY activeSessionPausedChanged)
Q_PROPERTY(bool rootBackendsLoaded READ rootBackendsLoaded NOTIFY rootBackendsLoadedChanged) Q_PROPERTY(bool rootBackendsLoaded READ rootBackendsLoaded NOTIFY rootBackendsLoadedChanged)
Q_PROPERTY(QStringList availableBackends READ availableBackends NOTIFY availableBackendsChanged) Q_PROPERTY(QStringList availableBackends READ availableBackends NOTIFY availableBackendsChanged)
Q_PROPERTY(bool rootAgentsLoaded READ rootAgentsLoaded NOTIFY rootAgentsLoadedChanged) Q_PROPERTY(bool rootAgentsLoaded READ rootAgentsLoaded NOTIFY rootAgentsLoadedChanged)
@ -42,6 +43,7 @@ public:
Q_INVOKABLE void setActiveSessionId(const QString &id); Q_INVOKABLE void setActiveSessionId(const QString &id);
QString activeAgentId() const { return m_agentId; } QString activeAgentId() const { return m_agentId; }
QString activeState() const { return m_activeState; } QString activeState() const { return m_activeState; }
bool activeSessionPaused() const { return m_activeSessionPaused; }
bool rootBackendsLoaded() const { return m_rootBackendsLoaded; } bool rootBackendsLoaded() const { return m_rootBackendsLoaded; }
QStringList availableBackends() const { return m_availableBackends; } QStringList availableBackends() const { return m_availableBackends; }
@ -99,6 +101,7 @@ signals:
void activeSessionIdChanged(); void activeSessionIdChanged();
void activeAgentIdChanged(); void activeAgentIdChanged();
void activeStateChanged(); void activeStateChanged();
void activeSessionPausedChanged();
void agentStateChanged(const QString &sessionId, const QString &agentId, const QString &state); void agentStateChanged(const QString &sessionId, const QString &agentId, const QString &state);
void chatReceived(const QString &text); void chatReceived(const QString &text);
void bypassRequested(const QString &sessionId, const QString &agentId, const QString &id, const QString &cmd, const QString &cwd); void bypassRequested(const QString &sessionId, const QString &agentId, const QString &id, const QString &cmd, const QString &cwd);
@ -133,6 +136,7 @@ private:
QString m_activeSessionId; QString m_activeSessionId;
QString m_activeState = "idle"; QString m_activeState = "idle";
QString m_agentId; QString m_agentId;
bool m_activeSessionPaused = false;
// Root data cache // Root data cache
bool m_rootBackendsLoaded = false; bool m_rootBackendsLoaded = false;