Skip to content

1.0.9

Latest

Choose a tag to compare

@blsage blsage released this 10 Oct 10:36

Swift Chat 1.0.9 fixes the Photos sheet drag-dismissal crash that 1.0.8 did not, and makes typing lighter.

New

  • ChatConversationRow takes isTyping. 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. ChatTypingIndicator gains 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 of onChatSend, 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 isPresented binding from inside its own presentation state's write (PresentationState.base.willset on the stack, under SheetBridge.didBeginInteractiveDismissal), the binding's setter posted the lift at once, and the lift's synchronous layout of the bar ran its hosting view's SheetBridge.preferencesDidChange, which reads that same state (SIGABRT in swift_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.
  • ChatMessagePreview with an empty message still reserves two lines. An empty Text reserved 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 Chat body (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.
  • onChatTypingChanged documents 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; idleAfter is keystrokes, for the indicator another person sees.

Everything in 1.0.8 is unchanged.

Checksum: dae609a3ca3fa4f442ce2c4b7e50540f5560f7119f4d60f7012d205c80fbb644