Skip to content

Commit aa5ba6e

Browse files
committed
wip
1 parent 0c6c495 commit aa5ba6e

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

Examples/SlackClone/Supabase.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ let decoder: JSONDecoder = {
2121
}()
2222

2323
let supabase = SupabaseClient(
24-
supabaseURL: URL(string: "http://localhost:54321")!,
25-
supabaseKey: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0",
24+
supabaseURL: URL(string: "https://rkehabxkxxpcbpzsammm.supabase.red")!,
25+
supabaseKey: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InJrZWhhYnhreHhwY2JwenNhbW1tIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Mjk3NTgzODgsImV4cCI6MjA0NTMzNDM4OH0.rTpPEGk9fMjHXXR49drfyF6IkrNYeL_-yGGDa1JaXTY",
2626
options: SupabaseClientOptions(
2727
db: .init(encoder: encoder, decoder: decoder),
2828
auth: .init(redirectToURL: URL(string: "com.supabase.slack-clone://login-callback")),

Sources/Realtime/V2/RealtimeClientV2.swift

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,13 @@ public final class RealtimeClientV2: Sendable {
2020
var accessToken: String?
2121
var ref = 0
2222
var pendingHeartbeatRef: Int?
23+
24+
/// Long-running task that keeps sending heartbeat messages.
2325
var heartbeatTask: Task<Void, Never>?
26+
27+
/// Long-running task for listening for incoming messages from WebSocket.
2428
var messageTask: Task<Void, Never>?
29+
2530
var connectionTask: Task<Void, Never>?
2631
var channels: [String: RealtimeChannelV2] = [:]
2732
var sendBuffer: [@Sendable () async -> Void] = []
@@ -34,13 +39,14 @@ public final class RealtimeClientV2: Sendable {
3439
let http: any HTTPClientType
3540
let apikey: String?
3641

42+
/// All managed channels indexed by their topics.
3743
public var channels: [String: RealtimeChannelV2] {
3844
mutableState.channels
3945
}
4046

4147
private let statusEventEmitter = EventEmitter<RealtimeClientStatus>(initialEvent: .disconnected)
4248

43-
/// AsyncStream that emits when connection status change.
49+
/// Listen for connection status changes.
4450
///
4551
/// You can also use ``onStatusChange(_:)`` for a closure based method.
4652
public var statusChange: AsyncStream<RealtimeClientStatus> {
@@ -198,6 +204,13 @@ public final class RealtimeClientV2: Sendable {
198204
await connect(reconnect: true)
199205
}
200206

207+
/// Creates a new channel and bind it to this client.
208+
/// - Parameters:
209+
/// - topic: Channel's topic.
210+
/// - options: Configuration options for the channel.
211+
/// - Returns: Channel instance.
212+
///
213+
/// - Note: This method doesn't subscribe to the channel, call ``RealtimeChannelV2/subscribe()`` on the returned channel instance.
201214
public func channel(
202215
_ topic: String,
203216
options: @Sendable (inout RealtimeChannelConfig) -> Void = { _ in }
@@ -223,6 +236,9 @@ public final class RealtimeClientV2: Sendable {
223236
}
224237
}
225238

239+
/// Unsubscribe and removes channel.
240+
///
241+
/// If there is no channel left, client is disconnected.
226242
public func removeChannel(_ channel: RealtimeChannelV2) async {
227243
if channel.status == .subscribed {
228244
await channel.unsubscribe()
@@ -238,6 +254,7 @@ public final class RealtimeClientV2: Sendable {
238254
}
239255
}
240256

257+
/// Unsubscribes and removes all channels.
241258
public func removeAllChannels() async {
242259
await withTaskGroup(of: Void.self) { group in
243260
for channel in channels.values {
@@ -327,6 +344,7 @@ public final class RealtimeClientV2: Sendable {
327344
}
328345
}
329346

347+
/// Disconnects client.
330348
public func disconnect() {
331349
options.logger?.debug("Closing WebSocket connection")
332350
mutableState.withValue {
@@ -388,13 +406,14 @@ public final class RealtimeClientV2: Sendable {
388406
try Task.checkCancellation()
389407
try await self?.ws.send(message)
390408
} catch {
391-
self?.options.logger?.error("""
392-
Failed to send message:
393-
\(message)
394-
395-
Error:
396-
\(error)
397-
""")
409+
self?.options.logger?.error(
410+
"""
411+
Failed to send message:
412+
\(message)
413+
414+
Error:
415+
\(error)
416+
""")
398417
}
399418
}
400419

@@ -470,3 +489,31 @@ public final class RealtimeClientV2: Sendable {
470489
url.appendingPathComponent("api/broadcast")
471490
}
472491
}
492+
493+
import Network
494+
495+
final class NetworkMonitor: @unchecked Sendable {
496+
static let shared = NetworkMonitor()
497+
498+
private let monitor: NWPathMonitor
499+
private let queue = DispatchQueue(label: "NetworkMonitor")
500+
501+
private(set) var isConnected: Bool = false
502+
503+
private init() {
504+
monitor = NWPathMonitor()
505+
}
506+
507+
func start(_ onChange: (@Sendable () -> Void)? = nil) {
508+
monitor.pathUpdateHandler = { [weak self] path in
509+
self?.isConnected = path.status != .unsatisfied
510+
onChange?()
511+
}
512+
513+
monitor.start(queue: queue)
514+
}
515+
516+
func stop() {
517+
monitor.cancel()
518+
}
519+
}

0 commit comments

Comments
 (0)