Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,23 @@ allUserId99Changes.subscribe()
allUserId99Changes.unsubscribe()
allUserId99Changes.off(.all)
```
### Presence

Presence can be used to share state between clients.

* Listen to presence `sync` events:

```swift
let channel = client.channel(.table("channel_id", schema: "someChannel"), options: .init(presenceKey: "user_uuid"))
let presence = Presence(channel: channel)

presence.onSync {
print("presence sync", presence?.state, presence?.list())
}

channel.join()
// ...
```

## Credits

Expand Down
21 changes: 20 additions & 1 deletion Sources/Realtime/Channel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,31 @@ public class Channel {
/// Refs of stateChange hooks
var stateChangeRefs: [String]

/// Initialize a Channel
/// - parameter topic: Topic of the Channel
/// - parameter options: Optional. Options to configure channel broadcast and presence
/// - parameter socket: Socket that the channel is a part of
public convenience init(topic: ChannelTopic, options: ChannelOptions = ChannelOptions(), socket: RealtimeClient) {
let params = [
"config": [
"presence": [
"key": options.presenceKey ?? ""
],
"broadcast": [
"ack": options.broadcastAcknowledge,
"self": options.broadcastSelf
]
]
]
self.init(topic: topic, params: params, socket: socket)
}

/// Initialize a Channel
///
/// - parameter topic: Topic of the Channel
/// - parameter params: Optional. Parameters to send when joining.
/// - parameter socket: Socket that the channel is a part of
init(topic: ChannelTopic, params: [String: Any] = [:], socket: RealtimeClient) {
init(topic: ChannelTopic, params: [String: Any], socket: RealtimeClient) {
state = ChannelState.closed
self.topic = topic
self.params = params
Expand Down
16 changes: 16 additions & 0 deletions Sources/Realtime/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,19 @@ public enum ChannelTopic: RawRepresentable, Equatable {
}
}
}

/// Represents the broadcast and presence options for a channel.
public struct ChannelOptions {
/// Used to track presence payload across clients. Must be unique per client. If `nil`, the server will generate one.
var presenceKey: String?
/// Enables the client to receieve their own`broadcast` messages
var broadcastSelf: Bool
/// Instructs the server to acknoledge the client's `broadcast` messages
var broadcastAcknowledge: Bool

public init(presenceKey: String? = nil, broadcastSelf: Bool = false, broadcastAcknowledge: Bool = false) {
self.presenceKey = presenceKey
self.broadcastSelf = broadcastSelf
self.broadcastAcknowledge = broadcastAcknowledge
}
}
22 changes: 20 additions & 2 deletions Sources/Realtime/RealtimeClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,24 @@ public class RealtimeClient: TransportDelegate {
// ----------------------------------------------------------------------

// MARK: - Channel Initialization

// ----------------------------------------------------------------------
/// Initialize a new Channel
///
/// Example:
///
/// let channel = socket.channel("rooms", options: ChannelOptions(presenceKey: "user123"))
///
/// - parameter topic: Topic of the channel
/// - parameter options: Optional. Options for the channel
/// - return: A new channel
public func channel(
_ topic: ChannelTopic,
options: ChannelOptions = ChannelOptions()
) -> Channel {
let channel = Channel(topic: topic, options: options, socket: self)
channels.append(channel)
return channel
}
// ----------------------------------------------------------------------
/// Initialize a new Channel
///
Expand All @@ -594,9 +611,10 @@ public class RealtimeClient: TransportDelegate {
/// - parameter topic: Topic of the channel
/// - parameter params: Optional. Parameters for the channel
/// - return: A new channel
@available(*, deprecated, renamed: "channel(_:options:)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we really deprecate this?

aren't there other params that can be passed other than ChannelOption? Having this raw [String: Any] I think is still valid.

I'm not sure about this because I'm not used to the realtime feature, what do you think @foodisbeast ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless this package is meant to support Phoenix realtime generally, supabase realtime or realtime-js library only has these options available for initializing a channel (See RealtimeChannelOptions from realtime-js), as well as their documention for realtime only makes mention/use of RealtimeChannelOptions once when talking about Presence Key

import { createClient } from '@supabase/supabase-js'

const channelC = supabase.channel('test', {
  config: {
    presence: {
      key: 'userId-123',
    },
  },
})

public func channel(
_ topic: ChannelTopic,
params: [String: Any] = [:]
params: [String: Any]
) -> Channel {
let channel = Channel(topic: topic, params: params, socket: self)
channels.append(channel)
Expand Down