# 17 — GlobalChat: Messaging UI (iOS + Web) **UI project 4 of 5** · `IOS/TheOne/Main/GlobalChat`, `app/web-platform/app/globalchat` **Stack:** SwiftUI + Combine + Core Data; React/Next.js with a transport/store/runtime split **Scope:** iOS module 75 Swift files ≈ 9,400 lines · web tier with composer, media, search, webrtc, transport, store > **Where this sits.** The client half of > [GlobalChat](02-globalchat-realtime-messaging.md). Two independent > implementations of one realtime protocol — which is exactly the situation > where client/server contract discipline stops being theoretical. --- ## The web tier's structure ``` app/web-platform/app/globalchat/ transport/ wire layer — WebSocket, reconnect, framing store/ client state, ordering, dedupe runtime/ lifecycle and orchestration composer/ message composition, attachments, voice components/ render layer media/ attachment handling search/ message search webrtc/ callController.ts — the media plane ``` Separating **transport / store / runtime / render** is the right decomposition for a realtime client. The transport dies constantly; the store must survive it; the render layer should never know a socket exists. ## The iOS module — and the correction worth reading `docs/GLOBALCHAT-MODULE-WIRING.md` is a wiring record that **opens by retracting three of its own earlier conclusions.** That document is a hiring artifact in its own right: > **"I got these wrong first time and they change the picture materially."** 1. **"The module was never orphaned — it is load-bearing."** `GlobalChatServer.swift` declares 13 publishers typed with `GlobalChatMessage`, `GlobalChatReceiptEvent`, `GlobalChatCallLogEntry` and 14 other types — **every one declared only inside this module.** There is no second copy. The module owns model, persistence and view; `GlobalChatServer` owns transport. 2. **"The module has been attached in production all along."** `TheOneApp.swift:112` applies `.attachGlobalChat(...)` — committed, not added by this work. `GlobalChatStore.attach` had been subscribed to all 13 publishers and mirroring live traffic into Core Data on every install. **The data layer was wired; only the view layer was never rendered.** 3. **"The attach modifier never had a crash."** The earlier claim that nothing injected `GlobalChatServer` was wrong — *"my grep looked for a variable named `server`, and it is named `chat`."* The real gap, once the false ones were cleared, was narrow and specific: the **outbound path**, where `GlobalChatStore` held a `private weak var attachedServer`. > Publicly correcting your own analysis, naming the grep that misled you, and > then landing a smaller and correct fix is the single most senior-coded > behavior in this entire repository. ## Feature surface Attachments (typed), voice messaging, reactions, edits and deletes, view-once media, live location, typing indicators, read receipts, search, call log, and an avatar hexagon treatment migrated across the component set. The dating variant wraps 18 `Dating*` components in a `DatingChatView` facade over the same GlobalChat engine. `WEB_CHAT_RUNBOOK_AND_GAPS.md` carries a **WhatsApp feature-parity comparison** (present / partial / missing), and `WEB_CHAT_FEATURE_IMPLEMENTATION_PLAN.md` turns the gaps into a phased plan with code-verified backend status, exact file/wire/store changes, effort sizing, acceptance criteria, and iOS-parity notes. ## Interview surface this opens - Transport / store / render separation in a realtime client - Message ordering, dedupe, and gap-fill after a reconnect - Local persistence (Core Data) as a mirror of a server log - Two clients, one protocol — and how AsyncAPI keeps them honest - Retracting an analysis in writing when the evidence goes the other way