Skip to content

Commit

Permalink
Merge pull request #380 from pusher/subscription-count-support
Browse files Browse the repository at this point in the history
Handle pusher_internal:subscription_count event
  • Loading branch information
fbenevides authored Jul 15, 2022
2 parents dd20929 + 24ae563 commit 56fac78
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 37 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,19 @@ PusherChannel *myChannel = [pusher subscribeWithChannelName:@"my-channel"];
This returns PusherChannel object, which events can be bound to.
For non-presence channels, you can also provide a function that will be called when a client either subscribes or unsubscribes to a channel with the number of subscribers as a parameter. Also, this function is available as a parameter to `subscribe` function.
```swift
let onSubscriptionCountChanged = { (count: Int) in
print("\(count) subscriptions")
}
let channel = pusher.subscribe(
channelName: "my-channel",
onSubscriptionCountChanged: onSubscriptionCountChanged
)
```

### Private channels

Private channels are created in exactly the same way as public channels, except that they reside in the 'private-' namespace. This means prefixing the channel name:
Expand Down
34 changes: 18 additions & 16 deletions Sources/Models/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum Constants {
static let memberAdded = "pusher_internal:member_added"
static let memberRemoved = "pusher_internal:member_removed"
static let subscriptionSucceeded = "pusher_internal:subscription_succeeded"
static let subscriptionCount = "pusher_internal:subscription_count"
}
}

Expand All @@ -39,21 +40,22 @@ enum Constants {
}

enum JSONKeys {
static let activityTimeout = "activity_timeout"
static let auth = "auth"
static let channel = "channel"
static let channelData = "channel_data"
static let ciphertext = "ciphertext"
static let code = "code"
static let data = "data"
static let event = "event"
static let hash = "hash"
static let message = "message"
static let nonce = "nonce"
static let presence = "presence"
static let socketId = "socket_id"
static let sharedSecret = "shared_secret"
static let userId = "user_id"
static let userInfo = "user_info"
static let activityTimeout = "activity_timeout"
static let auth = "auth"
static let channel = "channel"
static let channelData = "channel_data"
static let ciphertext = "ciphertext"
static let code = "code"
static let data = "data"
static let event = "event"
static let hash = "hash"
static let message = "message"
static let nonce = "nonce"
static let presence = "presence"
static let socketId = "socket_id"
static let sharedSecret = "shared_secret"
static let userId = "user_id"
static let userInfo = "user_info"
static let subscriptionCount = "subscription_count"
}
}
15 changes: 14 additions & 1 deletion Sources/Models/PusherChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ open class PusherChannel: NSObject {
eventHandlersQueue.async(flags: .barrier) { self.eventHandlersInternal = newValue }
}
}

private var _subscriptionCount: Int? = nil
public var subscriptionCount: Int? {
get { return _subscriptionCount }
}

open var subscribed = false
public let name: String
open weak var connection: PusherConnection?
open var unsentEvents = [QueuedClientEvent]()
public let type: PusherChannelType
public var auth: PusherAuth?
open var onSubscriptionCountChanged: ((Int) -> Void)?

// Wrap accesses to the decryption key in a serial queue because it will be accessed from multiple threads
@nonobjc private var decryptionKeyQueue = DispatchQueue(label: "com.pusher.pusherswift-channel-decryption-key-\(UUID().uuidString)",
Expand All @@ -45,11 +52,17 @@ open class PusherChannel: NSObject {

- returns: A new PusherChannel instance
*/
public init(name: String, connection: PusherConnection, auth: PusherAuth? = nil) {
public init(name: String, connection: PusherConnection, auth: PusherAuth? = nil, onSubscriptionCountChanged: ((Int) -> Void)? = nil) {
self.name = name
self.connection = connection
self.auth = auth
self.type = PusherChannelType(name: name)
self.onSubscriptionCountChanged = onSubscriptionCountChanged
}

internal func updateSubscriptionCount(count: Int) {
self._subscriptionCount = count
self.onSubscriptionCountChanged?(count)
}

/**
Expand Down
14 changes: 10 additions & 4 deletions Sources/Models/PusherChannels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ import Foundation
connection: PusherConnection,
auth: PusherAuth? = nil,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) -> PusherChannel {
if let channel = self.channels[name] {
return channel
Expand All @@ -51,7 +52,10 @@ import Foundation
onMemberRemoved: onMemberRemoved
)
} else {
newChannel = PusherChannel(name: name, connection: connection, auth: auth)
newChannel = PusherChannel(name: name,
connection: connection,
auth: auth,
onSubscriptionCountChanged: onSubscriptionCountChanged)
}
self.channels[name] = newChannel
return newChannel
Expand All @@ -78,7 +82,8 @@ import Foundation
connection: PusherConnection,
auth: PusherAuth? = nil,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) -> PusherPresenceChannel {
if let channel = self.channels[channelName] as? PusherPresenceChannel {
return channel
Expand All @@ -88,7 +93,8 @@ import Foundation
connection: connection,
auth: auth,
onMemberAdded: onMemberAdded,
onMemberRemoved: onMemberRemoved
onMemberRemoved: onMemberRemoved,
onSubscriptionCountChanged: onSubscriptionCountChanged
)
self.channels[channelName] = newChannel
return newChannel
Expand Down
5 changes: 3 additions & 2 deletions Sources/Models/PusherPresenceChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@ public typealias PusherUserInfoObject = [String: AnyObject]
connection: PusherConnection,
auth: PusherAuth? = nil,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) {
self.members = []
self.onMemberAdded = onMemberAdded
self.onMemberRemoved = onMemberRemoved
super.init(name: name, connection: connection, auth: auth)
super.init(name: name, connection: connection, auth: auth, onSubscriptionCountChanged: onSubscriptionCountChanged)
}

/**
Expand Down
18 changes: 13 additions & 5 deletions Sources/ObjC/Pusher+ObjectiveC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,35 @@ import Foundation
func subscribe(
channelName: String,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) -> PusherChannel {
return self.subscribe(channelName, auth: nil, onMemberAdded: onMemberAdded, onMemberRemoved: onMemberRemoved)
return self.subscribe(channelName,
auth: nil,
onMemberAdded: onMemberAdded,
onMemberRemoved: onMemberRemoved,
onSubscriptionCountChanged: onSubscriptionCountChanged)
}

func subscribeToPresenceChannel(channelName: String) -> PusherPresenceChannel {
return self.subscribeToPresenceChannel(channelName: channelName,
auth: nil,
onMemberAdded: nil,
onMemberRemoved: nil)
onMemberRemoved: nil,
onSubscriptionCountChanged: nil)
}

func subscribeToPresenceChannel(
channelName: String,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) -> PusherPresenceChannel {
return self.subscribeToPresenceChannel(channelName: channelName,
auth: nil,
onMemberAdded: onMemberAdded,
onMemberRemoved: onMemberRemoved)
onMemberRemoved: onMemberRemoved,
onSubscriptionCountChanged: onSubscriptionCountChanged)
}

convenience init(withAppKey key: String, options: PusherClientOptions) {
Expand Down
12 changes: 8 additions & 4 deletions Sources/PusherSwift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ let CLIENT_NAME = "pusher-websocket-swift"
_ channelName: String,
auth: PusherAuth? = nil,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) -> PusherChannel {

let isEncryptedChannel = PusherChannel.isEncrypted(name: channelName)
Expand All @@ -64,7 +65,8 @@ let CLIENT_NAME = "pusher-websocket-swift"
channelName: channelName,
auth: auth,
onMemberAdded: onMemberAdded,
onMemberRemoved: onMemberRemoved
onMemberRemoved: onMemberRemoved,
onSubscriptionCountChanged: onSubscriptionCountChanged
)
}

Expand All @@ -87,13 +89,15 @@ let CLIENT_NAME = "pusher-websocket-swift"
channelName: String,
auth: PusherAuth? = nil,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) -> PusherPresenceChannel {
return self.connection.subscribeToPresenceChannel(
channelName: channelName,
auth: auth,
onMemberAdded: onMemberAdded,
onMemberRemoved: onMemberRemoved
onMemberRemoved: onMemberRemoved,
onSubscriptionCountChanged: onSubscriptionCountChanged
)
}

Expand Down
34 changes: 29 additions & 5 deletions Sources/Services/PusherConnection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,16 @@ import NWWebSocket
channelName: String,
auth: PusherAuth? = nil,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) -> PusherChannel {
let newChannel = channels.add(
name: channelName,
connection: self,
auth: auth,
onMemberAdded: onMemberAdded,
onMemberRemoved: onMemberRemoved
onMemberRemoved: onMemberRemoved,
onSubscriptionCountChanged: onSubscriptionCountChanged
)

guard self.connectionState == .connected else { return newChannel }
Expand Down Expand Up @@ -141,14 +143,16 @@ import NWWebSocket
channelName: String,
auth: PusherAuth? = nil,
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
onSubscriptionCountChanged: ((Int) -> Void)? = nil
) -> PusherPresenceChannel {
let newChannel = channels.addPresence(
channelName: channelName,
connection: self,
auth: auth,
onMemberAdded: onMemberAdded,
onMemberRemoved: onMemberRemoved
onMemberRemoved: onMemberRemoved,
onSubscriptionCountChanged: onSubscriptionCountChanged
)

guard self.connectionState == .connected else { return newChannel }
Expand Down Expand Up @@ -459,7 +463,7 @@ import NWWebSocket
}
}
}

let subscriptionEvent = event.copy(withEventName: Constants.Events.Pusher.subscriptionSucceeded)
callGlobalCallbacks(event: subscriptionEvent)
chan.handleEvent(event: subscriptionEvent)
Expand Down Expand Up @@ -549,6 +553,23 @@ import NWWebSocket
Logger.shared.debug(for: .unableToRemoveMemberFromChannel)
}
}

/**
Handle subscription count event

- parameter event: The event to be processed
*/

private func handleSubscriptionCountEvent(event: PusherEvent) {
guard let channelName = event.channelName,
let channel = self.channels.find(name: channelName),
let subscriptionCountData = event.dataToJSONObject() as? [String: Any],
let count = subscriptionCountData[Constants.JSONKeys.subscriptionCount] as? Int else {
return
}

channel.updateSubscriptionCount(count: count)
}

/**
Handles incoming error
Expand Down Expand Up @@ -607,6 +628,9 @@ import NWWebSocket

case Constants.Events.PusherInternal.memberRemoved:
handleMemberRemovedEvent(event: event)

case Constants.Events.PusherInternal.subscriptionCount:
handleSubscriptionCountEvent(event: event)

default:
callGlobalCallbacks(event: event)
Expand Down

0 comments on commit 56fac78

Please sign in to comment.