From 3faa077bd1e1424fcf9f026d90a19cdead03a7f8 Mon Sep 17 00:00:00 2001 From: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com> Date: Mon, 22 Jun 2026 10:47:17 +0000 Subject: [PATCH] ios: add head-to-head subs query + app-state transition tracing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the number of device test cycles by capturing everything in one reproduction: - ServersSummaryView.getServersSummary: log the subs the detail view actually shows (allUsersSMP/currentUserSMP smpTotals), and additionally run getAgentSubsTotal() here UNGATED. The detail view fetches on .onAppear regardless of AppChatState (unlike the indicator, whose every poll tick is gated on == .active), so opening "servers info" once now shows both core queries head-to-head at the same moment/user — proving whether they disagree or whether only the gate differs. - AppChatState: log the initial persisted value at process start and every set() transition. The indicator polls only when value == .active, so this shows whether/when the app reaches .active on cold launch vs returning from background. --- apps/ios/Shared/Model/SuspendChat.swift | 10 ++++++++++ .../Views/ChatList/ServersSummaryView.swift | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/apps/ios/Shared/Model/SuspendChat.swift b/apps/ios/Shared/Model/SuspendChat.swift index 92bcdcac53..dd205cd0de 100644 --- a/apps/ios/Shared/Model/SuspendChat.swift +++ b/apps/ios/Shared/Model/SuspendChat.swift @@ -191,11 +191,21 @@ class AppChatState { static let shared = AppChatState() private var value_ = appStateGroupDefault.get() + init() { + // SUBS_TRACE: the state this process starts at, read from the persisted group default. + // On cold launch this is whatever was saved when the app last backgrounded (often .suspended). + logger.debug("SUBS_TRACE appstate init: initial persisted value=\(value_.rawValue)") + } + var value: AppState { value_ } func set(_ state: AppState) { + // SUBS_TRACE: log every app-state transition. The chat-list subs indicator only polls when + // value == .active, so this shows whether/when the app actually reaches (or leaves) .active, + // e.g. on cold launch vs returning from background. + logger.debug("SUBS_TRACE appstate set: \(value_.rawValue) -> \(state.rawValue)") appStateGroupDefault.set(state) sendAppState(state) value_ = state diff --git a/apps/ios/Shared/Views/ChatList/ServersSummaryView.swift b/apps/ios/Shared/Views/ChatList/ServersSummaryView.swift index ee7605dbd2..14aaaf2056 100644 --- a/apps/ios/Shared/Views/ChatList/ServersSummaryView.swift +++ b/apps/ios/Shared/Views/ChatList/ServersSummaryView.swift @@ -68,9 +68,27 @@ struct ServersSummaryView: View { private func getServersSummary() { do { serversSummary = try getAgentServersSummary() + if let summ = serversSummary { + // SUBS_TRACE: this detail view shows the real %. Log the subs it actually has, + // so they can be compared with what the chat-list indicator's getAgentSubsTotal returns. + let allS = summ.allUsersSMP.smpTotals + let curS = summ.currentUserSMP.smpTotals + logger.debug("SUBS_TRACE detail getAgentServersSummary: appState=\(AppChatState.shared.value.rawValue) allUsersSMP subs ssActive=\(allS.subs.ssActive) ssPending=\(allS.subs.ssPending) total=\(allS.subs.total) sessHasSess=\(allS.sessions.hasSess); currentUserSMP subs ssActive=\(curS.subs.ssActive) ssPending=\(curS.subs.ssPending) total=\(curS.subs.total) sessHasSess=\(curS.sessions.hasSess)") + } } catch let error { logger.error("getAgentServersSummary error: \(responseError(error))") } + // SUBS_TRACE: run the chat-list indicator's own query (getAgentSubsTotal) here too, UNGATED, + // so a single open of this view shows both core queries head-to-head at the same moment / user, + // regardless of whether AppChatState gates the indicator's poll. Raw payload is logged in API.sendSimpleXCmd. + Task { + do { + let (subs, hasSess) = try await getAgentSubsTotal() + logger.debug("SUBS_TRACE detail getAgentSubsTotal (same query the indicator uses): ssActive=\(subs.ssActive) ssPending=\(subs.ssPending) total=\(subs.total) hasSess=\(hasSess)") + } catch let error { + logger.error("SUBS_TRACE detail getAgentSubsTotal error: \(responseError(error))") + } + } } private func stopTimer() {