Skip to content

Commit d9afe26

Browse files
next iteration of the client upgrade
1 parent d42f48f commit d9afe26

File tree

3 files changed

+76
-130
lines changed

3 files changed

+76
-130
lines changed

Sources/LiveViewNative/Coordinators/LiveSessionCoordinator.swift

Lines changed: 29 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ public class LiveSessionCoordinator<R: RootRegistry>: ObservableObject {
5858
private var liveviewClient: LiveViewClient?
5959
private var builder: LiveViewClientBuilder
6060

61-
private var liveReloadChannel: LiveViewNativeCore.LiveChannel?
6261
private var liveReloadListenerLoop: Task<(), any Error>?
6362

6463
private var cancellables = Set<AnyCancellable>()
@@ -69,16 +68,10 @@ public class LiveSessionCoordinator<R: RootRegistry>: ObservableObject {
6968

7069
deinit {
7170
let client = liveviewClient
72-
let channel = liveReloadChannel
7371
Task { @MainActor in
7472
if let client {
7573
client.shutdown()
7674
}
77-
if let channel {
78-
do {
79-
try await channel.shutdownParentSocket()
80-
}
81-
}
8275
}
8376
}
8477

@@ -103,12 +96,8 @@ public class LiveSessionCoordinator<R: RootRegistry>: ObservableObject {
10396
self.init(host.url, config: config, customRegistryType: customRegistryType)
10497
}
10598

106-
public func clientChannel() -> LiveViewClientChannel? {
107-
self.liveviewClient?.channel()
108-
}
109-
110-
public func status() -> SocketStatus {
111-
(try? self.liveviewClient?.status()) ?? .disconnected
99+
public func status() -> LiveViewClientStatus {
100+
(try? self.liveviewClient?.status()) ?? .connecting
112101
}
113102

114103
/// Creates a new coordinator with a custom registry.
@@ -141,8 +130,27 @@ public class LiveSessionCoordinator<R: RootRegistry>: ObservableObject {
141130
.sink { [weak self] newView in
142131
guard let self else { return }
143132
guard let last = self.navigationPath.last else { return }
144-
if let client = self.liveviewClient {
145-
last.coordinator.join(client, self.eventHandler, self.patchHandler)
133+
switch newView {
134+
case .disconnected:
135+
self.state = .disconnected
136+
case .connecting:
137+
self.state = .connecting
138+
case .reconnecting:
139+
self.state = .reconnecting
140+
case .connected(channelStatus: let channelStatus):
141+
switch channelStatus {
142+
case .connected(let doc):
143+
self.state = .connected
144+
case .reconnecting:
145+
self.state = .reconnecting
146+
}
147+
case .error(error: let error):
148+
self.state = .connectionFailed(error)
149+
}
150+
if stylesheet != nil && rootLayout != nil {
151+
if let client = self.liveviewClient {
152+
last.coordinator.join(client, newView, self.patchHandler)
153+
}
146154
}
147155
}.store(in: &cancellables)
148156

@@ -252,10 +260,8 @@ public class LiveSessionCoordinator<R: RootRegistry>: ObservableObject {
252260
try await client.reconnect(originalURL.absoluteString, opts)
253261
} else {
254262
self.liveviewClient = try await self.builder.connect(originalURL.absoluteString, opts)
255-
self.navigationPath.last!.coordinator.join(self.liveviewClient!, self.eventHandler, self.patchHandler)
256263
}
257-
258-
264+
259265
self.rootLayout = try self.liveviewClient!.deadRender()
260266
let styleURLs = try self.liveviewClient!.styleUrls()
261267

@@ -281,49 +287,15 @@ public class LiveSessionCoordinator<R: RootRegistry>: ObservableObject {
281287
}
282288
}
283289

284-
self.state = .connected
285-
290+
self.navigationPath.last!.coordinator.join(self.liveviewClient!, self.liveviewClient!.status(), self.patchHandler)
291+
286292
} catch {
293+
self.rootLayout = nil
294+
self.stylesheet = nil
287295
self.state = .connectionFailed(error)
288296
}
289297
}
290-
291-
// TODO: move this error handlign into core
292-
func overrideLiveReloadChannel(channel: LiveChannel) async throws {
293-
if let liveReloadChannel {
294-
try await liveReloadChannel.shutdownParentSocket()
295-
self.liveReloadChannel = nil
296-
}
297-
298-
self.liveReloadChannel = channel
299-
self.bindLiveReloadListener()
300-
}
301298

302-
func bindLiveReloadListener() {
303-
let eventListener = self.liveReloadChannel!.channel().events()
304-
self.liveReloadListenerLoop = Task { @MainActor [weak self] in
305-
while !Task.isCancelled {
306-
let event = try await eventListener.event()
307-
guard let self else { return }
308-
let currentTime = Date()
309-
310-
guard currentTime.timeIntervalSince(lastReloadTime) >= debounceTime else {
311-
continue
312-
}
313-
314-
if case .user(user: "assets_change") = event.event {
315-
Task { @MainActor in
316-
await self.disconnect()
317-
self.navigationPath = [.init(url: self.url, coordinator: .init(session: self, url: self.url), navigationTransition: nil, pendingView: nil)]
318-
await self.connect()
319-
self.lastReloadTime = Date()
320-
}
321-
return
322-
}
323-
}
324-
325-
}
326-
}
327299

328300
private func disconnect(preserveNavigationPath: Bool = false) async {
329301
do {
@@ -342,15 +314,12 @@ public class LiveSessionCoordinator<R: RootRegistry>: ObservableObject {
342314
self.navigationPath = [self.navigationPath.first!]
343315
}
344316

345-
if self.liveReloadChannel?.channel().status() == .joined {
346-
try await self.liveReloadChannel?.shutdownParentSocket()
347-
}
317+
348318

349319
if let liveReloadListenerLoop {
350320
liveReloadListenerLoop.cancel()
351321
}
352322

353-
self.liveReloadChannel = nil
354323

355324
if let client = self.liveviewClient {
356325
try await client.disconnect()

Sources/LiveViewNative/Coordinators/LiveViewCoordinator.swift

Lines changed: 47 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {
3434
@_spi(LiveForm) public private(set) weak var session: LiveSessionCoordinator<R>!
3535

3636
private weak var liveviewClient: LiveViewClient?
37-
private var channel: LiveViewClientChannel?
3837

3938
var url: URL
4039

@@ -113,7 +112,7 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {
113112
throw LiveSocketError.DisconnectionError
114113
}
115114

116-
if let replyPayload = try await channel?.call(event, payload) {
115+
if let replyPayload = try await liveviewClient?.call(event, payload) {
117116
return try await handleEventReplyPayload(replyPayload)
118117
} else {
119118
return nil
@@ -126,7 +125,7 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {
126125
throw LiveSocketError.DisconnectionError
127126
}
128127

129-
if let replyPayload = try await channel?.call(event, payload) {
128+
if let replyPayload = try await liveviewClient?.call(event, payload) {
130129
return replyPayload
131130
} else {
132131
return nil
@@ -245,9 +244,10 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {
245244
}
246245

247246

248-
func bindDocumentListener() {
249-
let handler = SimplePatchHandler()
250-
patchHandlerCancellable = handler.patchEventSubject.sink { [weak self] patch in
247+
func bindDocumentListener(_ handler: SimplePatchHandler) {
248+
patchHandlerCancellable = handler.patchEventSubject
249+
.receive(on: DispatchQueue.main)
250+
.sink { [weak self] patch in
251251
switch patch.data {
252252
case .root:
253253
// when the root changes, update the `NavStackEntry` itself.
@@ -278,70 +278,57 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {
278278
}
279279
}
280280
}
281-
self.document?.setEventHandler(handler)
282281
}
283282

284283
func join(_ client: LiveViewNativeCore.LiveViewClient,
285-
_ eventListener: SimpleEventHandler,
284+
_ initial_status: LiveViewClientStatus,
286285
_ docHandler: SimplePatchHandler
287286
) {
288287
self.liveviewClient = client
289-
self.channel = client.channel()
290-
self.document = try! client.document()
291-
292-
eventListener.channelStatusSubject
293-
.receive(on: DispatchQueue.main)
294-
.sink { event in
295-
self.internalState = switch event.status {
296-
case .joined:
297-
.connected
298-
case .joining, .waitingForSocketToConnect, .waitingToJoin:
299-
.connecting
300-
case .waitingToRejoin:
301-
.reconnecting
302-
case .leaving, .left, .shuttingDown, .shutDown:
303-
.disconnected
304-
}
305-
}.store(in: &eventHandlers)
306-
307-
308-
docHandler.patchEventSubject
309-
.receive(on: DispatchQueue.main)
310-
.sink { event in
311-
switch event.data {
312-
case .root:
313-
// when the root changes, update the `NavStackEntry` itself.
314-
self.objectWillChange.send()
315-
case .leaf:
316-
// text nodes don't have their own views, changes to them need to be handled by the parent Text view
317-
// note: aren't these branches the same?
318-
if event.parent != nil {
319-
self.elementChanged(event.node).send()
320-
} else {
321-
self.elementChanged(event.node).send()
288+
handleViewReloadStatus(initial_status)
289+
self.bindDocumentListener(docHandler)
290+
}
291+
292+
293+
func handleViewReloadStatus(_ status: LiveViewClientStatus) {
294+
switch status {
295+
case .disconnected:
296+
self.internalState = .disconnected
297+
case .connecting:
298+
self.internalState = .connecting
299+
case .error(error: let error):
300+
self.internalState = .connectionFailed(error)
301+
case .reconnecting:
302+
self.internalState = .setup
303+
case .connected(channelStatus: let channelStatus):
304+
switch channelStatus {
305+
case .connected(let document):
306+
self.document = document
307+
do {
308+
if case let .jsonPayload(.object(payload)) = try self.liveviewClient?.joinPayload() {
309+
self.handleEvents(payload["rendered"]!)
310+
}
311+
self.internalState = .connected
312+
} catch {
313+
self.internalState = .connectionFailed(error)
314+
}
315+
case .reconnecting:
316+
do {
317+
guard let document = try self.liveviewClient?.document() else {
318+
self.internalState = .connecting
319+
return
320+
}
321+
self.document = document
322+
self.internalState = .reconnecting
323+
} catch {
324+
self.internalState = .connecting
325+
}
322326
}
323-
case .nodeElement:
324-
// when a single element changes, send an update only to that element.
325-
self.elementChanged(event.node).send()
326-
}
327-
}.store(in: &eventHandlers)
328-
329-
330-
331-
332-
switch try! client.joinPayload() {
333-
case let .jsonPayload(.object(payload)):
334-
self.handleEvents(payload["rendered"]!)
335-
default:
336-
fatalError()
337327
}
338-
339-
self.internalState = .connected
340328
}
341-
329+
342330
func disconnect() {
343-
self.liveviewClient = nil
344-
self.channel = nil
345331
self.internalState = .setup
332+
self.liveviewClient = nil
346333
}
347334
}

Sources/LiveViewNative/Live/LiveView.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -207,16 +207,6 @@ public struct LiveView<
207207
case .connecting:
208208
return .connecting
209209
case let .connectionFailed(error):
210-
211-
if let error = error as? LiveViewNativeCore.LiveSocketError,
212-
case let .ConnectionError(connectionError) = error {
213-
if let channel = connectionError.livereloadChannel {
214-
Task { @MainActor [weak session] in
215-
try await session?.overrideLiveReloadChannel(channel: channel)
216-
}
217-
}
218-
}
219-
220210
return .error(error)
221211
case .setup:
222212
return .connecting

0 commit comments

Comments
 (0)