Skip to content

Add peer browser model - #43

Closed
rchatham wants to merge 2 commits into
feature/network-migration-network-configfrom
feature/network-migration-browser-model
Closed

rchatham wants to merge 2 commits into
feature/network-migration-network-configfrom
feature/network-migration-browser-model

Conversation

@rchatham

@rchatham rchatham commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a UIKit-neutral PeerBrowserModel foundation for app-owned Network backend peer selection UI.

Changes

  • Add public PeerBrowserModel in the core PeerConnectivity target.
  • Track discovered peers from manager events:
    • .foundPeer
    • .lostPeer
    • .nearbyPeersChanged
    • .devicesChanged
  • Preserve connection status updates when later nearby-peer snapshots arrive with stale discovery-time status.
  • Deliver peersChanged callbacks on the main queue for UI consumers.
  • Generate a unique listener key by default so multiple models can observe the same manager.
  • Forward approved selections through invitePeer(_:withContext:timeout:); the model does not auto-invite discovered peers.
  • Add tests for found/lost tracking, status updates, invite forwarding, and stop-observing cleanup.
  • Update NetworkBackendGuide.md to show .custom peer selection with PeerBrowserModel.

Verification

  • swift test --filter PeerBrowserModelTests — 4 tests passed
  • swift test — 113 tests passed
  • xcodebuild test -project PeerConnectivity.xcodeproj -scheme PeerConnectivity -destination 'platform=iOS Simulator,name=iPhone 16,OS=18.3.1' -configuration Debug — 113 tests passed
  • GitHub Actions pull_request CI — Swift Package Tests and Xcode Project Tests passed
  • GitHub Actions push CI — Swift Package Tests and Xcode Project Tests passed
  • Correctness reviewer — no merge-blocking findings
  • Security reviewer — no merge-blocking security findings

Notes / limitations

  • This is model/helper foundation only; no SwiftUI/UIKit browser UI is added in this PR.
  • The Network backend remains explicit opt-in and still requires app-owned trust/selection decisions.

Stack context

Stacked on PR #42 (feature/network-migration-network-config). This is the Network browser model foundation slice of the migration stack.

…k-config' into HEAD

# Conflicts:
#	PeerConnectivity.xcodeproj/project.pbxproj

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

Adds a new UIKit-neutral PeerBrowserModel to the core PeerConnectivity target to support app-owned peer selection UI (especially for the Network backend), along with tests and documentation showing intended usage.

Changes:

  • Introduce PeerBrowserModel to track discovered peers via PeerConnectionManager events and forward approved invites.
  • Add PeerBrowserModelTests covering found/lost tracking, status updates, invite forwarding, and stop-observing behavior.
  • Update NetworkBackendGuide.md to demonstrate .custom peer selection using PeerBrowserModel.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
Sources/PeerBrowserModel.swift New public model type for peer discovery state + main-queue UI callbacks + invite forwarding.
PeerConnectivityTests/PeerBrowserModelTests.swift New XCTest coverage validating model behavior using mocked transports.
PeerConnectivity.xcodeproj/project.pbxproj Wires the new source and test files into the Xcode project build.
NetworkBackendGuide.md Updates .custom documentation to recommend PeerBrowserModel for app-owned peer UI.
Suppressed comments (2)

Sources/PeerBrowserModel.swift:152

  • notify dispatches to the main queue even when handler is nil, creating unnecessary async work. Early-return when there is no handler to call.
    fileprivate func notify(_ handler: PeersChangedHandler?, peers: [Peer]) {
        DispatchQueue.main.async {
            handler?(peers)
        }

PeerConnectivityTests/PeerBrowserModelTests.swift:168

  • This test relies on a short RunLoop delay to try to catch post-stopObserving() updates, which can be flaky across environments. Use an inverted XCTest expectation tied to the model's peersChanged callback instead, then wait for a short duration.
    internal func testStopObservingRemovesModelListener() {
        let harness = PeerBrowserModelHarness()
        let manager = makeManager(harness: harness)
        let model = PeerBrowserModel(manager: manager)
        let peer = Peer(identity: PeerIdentity(identifier: "remote", displayName: "Remote"), status: .notConnected)

        model.startObserving()
        manager.startBrowsingOnly()
        model.stopObserving()
        harness.browserObserver?.value = .foundPeer(peer, discoveryInfo: nil)

        RunLoop.current.run(until: Date().addingTimeInterval(0.1))
        XCTAssertTrue(model.discoveredPeers.isEmpty)
    }

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread Sources/PeerBrowserModel.swift
Comment thread PeerConnectivityTests/PeerBrowserModelTests.swift
@rchatham

Copy link
Copy Markdown
Owner Author

Superseded by consolidated PR #48. No commits were discarded; this branch is preserved as a recovery and reference point. Addressed review findings were replied to and resolved before consolidation.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants