| 1 | import LChatCore |
| 2 | import SwiftUI |
| 3 | import WebKit |
| 4 | |
| 5 | // đŸ¤– A GROUP chat's shared app surface: the selected added app's interface, |
| 6 | // rendered by the shared embed page (FeedWebCache) — seeded with this thread's |
| 7 | // key plus the app to show (app != nil). ONE cached page serves |
| 8 | // all the group's apps; switching apps is a JS call into it |
| 9 | // (WebBridge.setGroupApp), never a reload. NativeChatScreen swaps this in for |
| 10 | // the native feed when the header's view picker chooses an app. |
| 11 | struct GroupAppPane: View { |
| 12 | @ObservedObject private var bridge: WebBridge |
| 13 | let instance: SavedInstance |
| 14 | let thread: ChatThread |
| 15 | let myUserId: String |
| 16 | let instanceKeyB64: String? |
| 17 | let app: String |
| 18 | |
| 19 | @MainActor |
| 20 | init(instance: SavedInstance, thread: ChatThread, myUserId: String, |
| 21 | instanceKeyB64: String?, app: String) { |
| 22 | self.instance = instance |
| 23 | self.thread = thread |
| 24 | self.myUserId = myUserId |
| 25 | self.instanceKeyB64 = instanceKeyB64 |
| 26 | self.app = app |
| 27 | bridge = FeedWebCache.shared.bridge(for: instance, thread: thread, |
| 28 | myUserId: myUserId, |
| 29 | instanceKeyB64: instanceKeyB64, app: app) |
| 30 | } |
| 31 | |
| 32 | var body: some View { |
| 33 | VStack(spacing: 0) { |
| 34 | AppUpdateBar(bridge: bridge) |
| 35 | ZStack { |
| 36 | GroupAppWebView(instance: instance, thread: thread, myUserId: myUserId, |
| 37 | instanceKeyB64: instanceKeyB64, app: app) |
| 38 | if !bridge.pageReady { |
| 39 | WebLoadingVeil().transition(.opacity) |
| 40 | } |
| 41 | } |
| 42 | } |
| 43 | .animation(.easeOut(duration: 0.25), value: bridge.pageReady) |
| 44 | // Re-assert the selection on every appearance/switch. The boot seed |
| 45 | // carries the app chosen at page-creation time; a still-booting page |
| 46 | // ignores the JS no-op, so the ready flip re-asserts once more. |
| 47 | .onAppear { bridge.setGroupApp(app) } |
| 48 | .onChange(of: app) { _, newApp in bridge.setGroupApp(newApp) } |
| 49 | .onChange(of: bridge.pageReady) { _, ready in |
| 50 | if ready { bridge.setGroupApp(app) } |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | private struct GroupAppWebView: UIViewRepresentable { |
| 56 | let instance: SavedInstance |
| 57 | let thread: ChatThread |
| 58 | let myUserId: String |
| 59 | let instanceKeyB64: String? |
| 60 | let app: String |
| 61 | |
| 62 | func makeUIView(context: Context) -> WKWebView { |
| 63 | FeedWebCache.shared.webView(for: instance, thread: thread, myUserId: myUserId, |
| 64 | instanceKeyB64: instanceKeyB64, app: app) |
| 65 | } |
| 66 | |
| 67 | func updateUIView(_ web: WKWebView, context: Context) {} |
| 68 | } |
| 69 | |