Skip to content

fix: historical messages rendering, question tools and todos on client#24

Merged
sirily11 merged 3 commits into
mainfrom
client-fix
May 20, 2026
Merged

fix: historical messages rendering, question tools and todos on client#24
sirily11 merged 3 commits into
mainfrom
client-fix

Conversation

@sirily11

Copy link
Copy Markdown
Contributor

No description provided.

sirily11 and others added 3 commits May 20, 2026 11:48
Deliver chat history to mobile in ~30-message windows with backward
paging as users scroll up, and mirror the desktop AskUserQuestion flow
on mobile.

- Add loadMoreMessages/moreMessages and questionQueue/questionAnswer
  sync payloads, plus an activeSessionHasMore flag on the snapshot
- Desktop AppState broadcasts the question queue and handles answers
  and pagination requests from paired mobile devices
- MobileAppState tracks paged history and pending questions
- New MobileQuestionSheet mirrors the desktop QuestionSheetView
  (single/multi-select and free-form "Other" answers)
- MobileChatView shows a question queue banner above the input field

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ed history

- Add byte-budget paging for mobile message snapshots so a sync frame
  stays under the relay's 10 MiB cap; older messages page in on demand
- Wire best-effort APNs fan-out into broadcastNotification so finished
  threads surface a banner on backgrounded/offline devices
- Preserve carried history when a session redirect lands after live
  messages already accumulated under the new session id
- Make the mobile navigation title fully tappable to open the todo +
  summary sheet even when the thread has no todos

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 20, 2026 04:39
@vercel

vercel Bot commented May 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rxcode Ready Ready Preview, Comment May 20, 2026 4:39am

Request Review

@sirily11 sirily11 changed the title fix: historical messages rendering, question tools and todos fix: historical messages rendering, question tools and todos on client May 20, 2026
@sirily11 sirily11 enabled auto-merge (squash) May 20, 2026 04:39
@autopilot-project-manager autopilot-project-manager Bot added the bug Something isn't working label May 20, 2026
@sirily11 sirily11 merged commit 985f3e7 into main May 20, 2026
8 checks passed
@sirily11 sirily11 deleted the client-fix branch May 20, 2026 04:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades the mobile + desktop sync and UI to better handle large thread histories, mirror desktop tool-driven interactions (AskUserQuestion + todos), and improve notification delivery.

Changes:

  • Add message paging (“load older”) to avoid sending/rendering full histories in one snapshot and improve scroll stability when prepending pages.
  • Add mobile support for AskUserQuestion (queue mirroring + question sheet) and surface thread todos/summary in the chat title UI.
  • Add APNs fan-out on the desktop relay path and extend the sync protocol with new payloads/fields (thinking state, unread completion indicator, model sections, etc.).

Reviewed changes

Copilot reviewed 21 out of 23 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
RxCodeMobile/Views/SessionsList.swift Adds incremental list paging and a leading status dot for unread completions.
RxCodeMobile/Views/RootView.swift Adjusts navigation to avoid double-push and adds a close callback for chat.
RxCodeMobile/Views/NewThreadSheet.swift Uses structured modelSections (with fallback to flat models) for the model picker.
RxCodeMobile/Views/MobileQuestionSheet.swift New mobile question sheet UI mirroring the desktop AskUserQuestion flow.
RxCodeMobile/Views/MobileChatView.swift Adds message paging, question queue banner/sheet, todos + summary sheet, and thread actions (rename/archive/delete).
RxCodeMobile/Views/MobileBriefingView.swift Adds briefing filters (project + branch) and improved empty state.
RxCodeMobile/State/MobileAppState.swift Implements thinking state sync, message paging state, question queue sync, and thread lifecycle actions.
RxCode/Services/MobileSyncService.swift Adds APNs push fan-out and new inbound event routing for new payload types.
RxCode/App/AppState.swift Implements desktop handlers for thread actions, paging requests, question answers, and snapshot changes (paging + unread completion).
RxCode.xcodeproj/.../Package.resolved Updates Xcode project SwiftPM resolution with new dependencies.
Packages/Sources/RxCodeSync/Transport/RelayClient.swift Raises WebSocket frame size limit for sync payloads.
Packages/Sources/RxCodeSync/Protocol/Payload.swift Extends wire protocol with new payloads/fields (paging, thread actions, questions, model sections, thinking, unread completion).
Packages/Sources/RxCodeCore/Models/AgentModel.swift Adds AgentModelSection for structured model picker grouping.
Packages/Sources/RxCodeChatKit/ToolResultView.swift Fixes layout alignment for tool result rows.
Packages/Sources/RxCodeChatKit/MessageBubble.swift Removes an extra frame modifier to avoid layout side effects.
Packages/Sources/RxCodeChatKit/MarkdownView.swift Replaces custom markdown rendering with Textual-based renderer + preprocessing.
Packages/Sources/RxCodeChatKit/ChatTextContentView.swift Simplifies chat text rendering and ensures link tinting.
Packages/Sources/RxCodeChatKit/ChatMessageBubble.swift Switches assistant markdown rendering to MarkdownContentView.
Packages/Package.swift Adds Textual dependency for RxCodeChatKit.
Packages/Package.resolved Records new SwiftPM dependency graph for Packages workspace.
icon.icon/icon.json Updates icon fill + layer metadata.
Comments suppressed due to low confidence (1)

RxCodeMobile/State/MobileAppState.swift:820

  • updateSessionStreamingFlag reconstructs SessionSummary without hasUncheckedCompletion, so it will default to false and can clear the unread-completion state whenever a session_update arrives without a full summary (e.g. message diffs carrying isStreaming). Preserve current.hasUncheckedCompletion when rebuilding the summary to avoid losing the green indicator due to delivery ordering.
    private func updateSessionStreamingFlag(sessionID: String, isStreaming: Bool) {
        guard let index = sessions.firstIndex(where: { $0.id == sessionID }) else { return }
        let current = sessions[index]
        sessions[index] = SessionSummary(
            id: current.id,
            projectId: current.projectId,
            title: current.title,
            updatedAt: current.updatedAt,
            isPinned: current.isPinned,
            isArchived: current.isArchived,
            isStreaming: isStreaming,
            attention: current.attention,
            progress: current.progress,
            queuedMessages: current.queuedMessages
        )

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}
if loadingMoreSessions.remove(previous) != nil {
loadingMoreSessions.insert(update.sessionID)
}
Comment on lines +318 to +333
func renameThread(sessionID: String, title: String) async {
let trimmed = title.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return }
replaceSession(sessionID: sessionID) { current in
SessionSummary(
id: current.id,
projectId: current.projectId,
title: trimmed,
updatedAt: current.updatedAt,
isPinned: current.isPinned,
isArchived: current.isArchived,
isStreaming: current.isStreaming,
attention: current.attention,
progress: current.progress,
queuedMessages: current.queuedMessages
)
Comment on lines +171 to +181
Section("Branches") {
Button {
showAllBranches = false
} label: {
Label("Current branch", systemImage: showAllBranches ? "" : "checkmark")
}
Button {
showAllBranches = true
} label: {
Label("All branches", systemImage: showAllBranches ? "checkmark" : "")
}
Comment on lines +501 to +526
var submitEnabled: Bool {
guard !isSubmitting else { return false }
if isLastQuestion || allAnswered { return allAnswered }
return currentAnswerProvided
}

var mainButtonLabel: String {
(isLastQuestion || allAnswered) ? "Submit" : "Next"
}

var mainButtonIcon: String {
(isLastQuestion || allAnswered) ? "paperplane.fill" : "arrow.right"
}

func submit() {
guard allAnswered, !isSubmitting else { return }
isSubmitting = true
UIImpactFeedbackGenerator(style: .light).impactOccurred()
var resolved: [Int: AskUserQuestion.Answer] = [:]
for (index, question) in questions.enumerated() {
guard let local = answers[index] else { continue }
resolved[index] = convert(local: local, multiSelect: question.multiSelect)
}
onSubmit(resolved)
dismiss()
}
Comment on lines 89 to 116
public struct SnapshotPayload: Codable, Sendable {
public let projects: [Project]
public let sessions: [SessionSummary]
public let branchBriefings: [MobileBranchBriefing]?
public let threadSummaries: [MobileThreadSummary]?
public let settings: MobileSettingsSnapshot?
public let activeSessionID: String?
public let activeSessionMessages: [ChatMessage]?
/// Whether the active thread has messages older than the window in
/// `activeSessionMessages`. Mobile uses this to decide whether to offer
/// "load more" as the user scrolls up. `nil`/`false` means the window is
/// the whole thread (or the desktop predates message paging).
public let activeSessionHasMore: Bool?
/// Current git branch resolved per project on the desktop. Mobile uses this
/// to surface "you're about to create a thread on branch X" when starting
/// a new thread. Missing entries mean the project isn't a git repo or the
/// branch couldn't be resolved.
public let projectBranches: [ProjectBranchInfo]?
public init(
projects: [Project],
sessions: [SessionSummary],
branchBriefings: [MobileBranchBriefing]? = nil,
threadSummaries: [MobileThreadSummary]? = nil,
settings: MobileSettingsSnapshot? = nil,
activeSessionID: String? = nil,
activeSessionMessages: [ChatMessage]? = nil,
activeSessionHasMore: Bool? = nil,
projectBranches: [ProjectBranchInfo]? = nil
@sirily11

Copy link
Copy Markdown
Contributor Author

🎉 This PR is included in version 1.6.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants