Files
zooqueenandHanzo Dev 3d8b2650be review: the remaining minors — honest phases, lean payloads, real probes
The fall-back UTF-8 decoder carries a split multibyte sequence between
chunks instead of reading past the array (utf8() is now the one per-stream
decoder, both faces, with a boundary-sweep test); a chat turn ends its run
as done/stopped/error instead of filing every ending as 'streaming'; a
generated image parks its bytes in a cache file so the 20-run ring never
pins megabytes of base64; the model picker offers Reload only on a service
refusal (permission and credential must not bait a retry); and the iOS
widget module probes the App Group with containerURL — the one call that
actually returns nil when the entitlement is missing — and says so in the
log instead of writing to an unshared bucket forever.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-05 23:00:50 -07:00

33 lines
1.4 KiB
Swift

import ExpoModulesCore
import WidgetKit
// App-side half of the home-screen widget: persist the shared state in the
// App Group and ask WidgetKit to redraw. The JSON shape is owned by
// lib/widget.ts and decoded by targets/widget; this module never interprets
// it, so the two sides cannot drift through here.
public class WidgetModule: Module {
public func definition() -> ModuleDefinition {
Name("Widget")
Function("set") { (stateJson: String) in
// UserDefaults(suiteName:) returns an instance even WITHOUT the App
// Group entitlement — the writes just land in an unshared bucket the
// widget can never read, silently. containerURL is the probe that
// actually answers "is the entitlement on this build": nil means a
// build without plugins/widget-ios.js (or a hand-managed profile
// missing group.ai.hanzo.mobile), and saying so in the log is the
// difference between a five-minute fix and a widget that mysteriously
// reads "Open Hanzo to sync" forever.
guard FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: "group.ai.hanzo.mobile") != nil,
let defaults = UserDefaults(suiteName: "group.ai.hanzo.mobile")
else {
NSLog("[widget] app group entitlement group.ai.hanzo.mobile missing — widget state not shared")
return
}
defaults.set(stateJson, forKey: "widget.state")
WidgetCenter.shared.reloadAllTimelines()
}
}
}