Repository navigation
Swift Chat 1.0.9 fixes the Photos sheet drag-dismissal crash that 1.0.8 did not, and makes typing lighter.
New
ChatConversationRowtakesisTyping. True draws the typing bubble where the last message preview sits, at the size Messages uses in a list, as an overlay on the two reserved preview lines so the row keeps its height.ChatTypingIndicatorgains a public init so a host can draw the bubble itself. Default false; a row without it is unchanged.chatMainThreadWatchdog(_:)logs a main-thread stall longer than a threshold while the input field has the keyboard, with the last thing the chat was doing (a keystroke, a send, or one of the host's callbacks) and emits it as an Instruments signpost. For debug builds; off unless applied. The README's new "Keeping the main thread free" section says what the package does for the keystroke path and what a host must keep out ofonChatSend, the typing callbacks, and view bodies.
Fixed
- Dragging the Photos sheet down no longer aborts the app. 1.0.8 moved the input-bar lift out of the sheet flag's own setter, which cleared the exclusivity conflict on that flag and left the one underneath it: SwiftUI sets the sheet's
isPresentedbinding from inside its own presentation state's write (PresentationState.base.willseton the stack, underSheetBridge.didBeginInteractiveDismissal), the binding's setter posted the lift at once, and the lift's synchronous layout of the bar ran its hosting view'sSheetBridge.preferencesDidChange, which reads that same state (SIGABRT inswift_beginAccess; issue #3, Xcode 27.0, iPhone 17 / iOS 27.0 simulator). When the sheet's binding sets the flag, the flag is written at once and the lift is posted after SwiftUI's update has returned. The plus menu's Photos row and a host's panel binding still post it at once, so the bar still rises as the keyboard leaves. The reporter's UI test from issue #3 (focus, type a draft, open Photos, drag the grabber down, twice) crashes on 1.0.8 and on the source before this change, and passes after it. ChatMessagePreviewwith an empty message still reserves two lines. An emptyTextreserved one, so a blank preview or the typing row shortened the text column and a centred row dropped its name; rows with blank previews are now the same height as the rest.- Typing is lighter. A keystroke re-evaluates the input bar alone instead of the whole
Chatbody (which collected and fingerprinted every message and re-rendered the host's header per letter); the keystroke rescue that measures the bar against the keyboard no longer forces a full layout pass first; the field's height is measured once per edit instead of on every layout proposal; the placeholder is rebuilt only when the field empties or fills. A Time Profiler trace of fast typing in Tally on the simulator went from 7.4 s of main-thread time in a 24 s window to 4.4 s, with the Chat body, the forced layout, and three quarters of the text measurement gone from the keystroke path. - A file picked from the Files row is copied on a background task, not on the main thread in the picker's delegate, and Files takes turns with Camera and Photos the way those take turns with each other: a file picker asked for while the Photos sheet or a host panel is up waits for it to leave, and nothing opens over a file picker.
onChatTypingChangeddocuments what each form means: the plain form is a field with text in it, true until the field is sent or cleared, a draft included;idleAfteris keystrokes, for the indicator another person sees.
Everything in 1.0.8 is unchanged.
Checksum: dae609a3ca3fa4f442ce2c4b7e50540f5560f7119f4d60f7012d205c80fbb644