Skip to content

Commit 56fac78

Browse files
authored
Merge pull request #380 from pusher/subscription-count-support
Handle pusher_internal:subscription_count event
2 parents dd20929 + 24ae563 commit 56fac78

File tree

8 files changed

+108
-37
lines changed

8 files changed

+108
-37
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,19 @@ PusherChannel *myChannel = [pusher subscribeWithChannelName:@"my-channel"];
609609
610610
This returns PusherChannel object, which events can be bound to.
611611
612+
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.
613+
614+
```swift
615+
let onSubscriptionCountChanged = { (count: Int) in
616+
print("\(count) subscriptions")
617+
}
618+
619+
let channel = pusher.subscribe(
620+
channelName: "my-channel",
621+
onSubscriptionCountChanged: onSubscriptionCountChanged
622+
)
623+
```
624+
612625
### Private channels
613626

614627
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:

Sources/Models/Constants.swift

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ enum Constants {
2929
static let memberAdded = "pusher_internal:member_added"
3030
static let memberRemoved = "pusher_internal:member_removed"
3131
static let subscriptionSucceeded = "pusher_internal:subscription_succeeded"
32+
static let subscriptionCount = "pusher_internal:subscription_count"
3233
}
3334
}
3435

@@ -39,21 +40,22 @@ enum Constants {
3940
}
4041

4142
enum JSONKeys {
42-
static let activityTimeout = "activity_timeout"
43-
static let auth = "auth"
44-
static let channel = "channel"
45-
static let channelData = "channel_data"
46-
static let ciphertext = "ciphertext"
47-
static let code = "code"
48-
static let data = "data"
49-
static let event = "event"
50-
static let hash = "hash"
51-
static let message = "message"
52-
static let nonce = "nonce"
53-
static let presence = "presence"
54-
static let socketId = "socket_id"
55-
static let sharedSecret = "shared_secret"
56-
static let userId = "user_id"
57-
static let userInfo = "user_info"
43+
static let activityTimeout = "activity_timeout"
44+
static let auth = "auth"
45+
static let channel = "channel"
46+
static let channelData = "channel_data"
47+
static let ciphertext = "ciphertext"
48+
static let code = "code"
49+
static let data = "data"
50+
static let event = "event"
51+
static let hash = "hash"
52+
static let message = "message"
53+
static let nonce = "nonce"
54+
static let presence = "presence"
55+
static let socketId = "socket_id"
56+
static let sharedSecret = "shared_secret"
57+
static let userId = "user_id"
58+
static let userInfo = "user_info"
59+
static let subscriptionCount = "subscription_count"
5860
}
5961
}

Sources/Models/PusherChannel.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,19 @@ open class PusherChannel: NSObject {
1515
eventHandlersQueue.async(flags: .barrier) { self.eventHandlersInternal = newValue }
1616
}
1717
}
18+
19+
private var _subscriptionCount: Int? = nil
20+
public var subscriptionCount: Int? {
21+
get { return _subscriptionCount }
22+
}
23+
1824
open var subscribed = false
1925
public let name: String
2026
open weak var connection: PusherConnection?
2127
open var unsentEvents = [QueuedClientEvent]()
2228
public let type: PusherChannelType
2329
public var auth: PusherAuth?
30+
open var onSubscriptionCountChanged: ((Int) -> Void)?
2431

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

4653
- returns: A new PusherChannel instance
4754
*/
48-
public init(name: String, connection: PusherConnection, auth: PusherAuth? = nil) {
55+
public init(name: String, connection: PusherConnection, auth: PusherAuth? = nil, onSubscriptionCountChanged: ((Int) -> Void)? = nil) {
4956
self.name = name
5057
self.connection = connection
5158
self.auth = auth
5259
self.type = PusherChannelType(name: name)
60+
self.onSubscriptionCountChanged = onSubscriptionCountChanged
61+
}
62+
63+
internal func updateSubscriptionCount(count: Int) {
64+
self._subscriptionCount = count
65+
self.onSubscriptionCountChanged?(count)
5366
}
5467

5568
/**

Sources/Models/PusherChannels.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ import Foundation
3636
connection: PusherConnection,
3737
auth: PusherAuth? = nil,
3838
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
39-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
39+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
40+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
4041
) -> PusherChannel {
4142
if let channel = self.channels[name] {
4243
return channel
@@ -51,7 +52,10 @@ import Foundation
5152
onMemberRemoved: onMemberRemoved
5253
)
5354
} else {
54-
newChannel = PusherChannel(name: name, connection: connection, auth: auth)
55+
newChannel = PusherChannel(name: name,
56+
connection: connection,
57+
auth: auth,
58+
onSubscriptionCountChanged: onSubscriptionCountChanged)
5559
}
5660
self.channels[name] = newChannel
5761
return newChannel
@@ -78,7 +82,8 @@ import Foundation
7882
connection: PusherConnection,
7983
auth: PusherAuth? = nil,
8084
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
81-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
85+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
86+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
8287
) -> PusherPresenceChannel {
8388
if let channel = self.channels[channelName] as? PusherPresenceChannel {
8489
return channel
@@ -88,7 +93,8 @@ import Foundation
8893
connection: connection,
8994
auth: auth,
9095
onMemberAdded: onMemberAdded,
91-
onMemberRemoved: onMemberRemoved
96+
onMemberRemoved: onMemberRemoved,
97+
onSubscriptionCountChanged: onSubscriptionCountChanged
9298
)
9399
self.channels[channelName] = newChannel
94100
return newChannel

Sources/Models/PusherPresenceChannel.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ public typealias PusherUserInfoObject = [String: AnyObject]
2929
connection: PusherConnection,
3030
auth: PusherAuth? = nil,
3131
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
32-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
32+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
33+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
3334
) {
3435
self.members = []
3536
self.onMemberAdded = onMemberAdded
3637
self.onMemberRemoved = onMemberRemoved
37-
super.init(name: name, connection: connection, auth: auth)
38+
super.init(name: name, connection: connection, auth: auth, onSubscriptionCountChanged: onSubscriptionCountChanged)
3839
}
3940

4041
/**

Sources/ObjC/Pusher+ObjectiveC.swift

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,35 @@ import Foundation
88
func subscribe(
99
channelName: String,
1010
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
11-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
11+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
12+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
1213
) -> PusherChannel {
13-
return self.subscribe(channelName, auth: nil, onMemberAdded: onMemberAdded, onMemberRemoved: onMemberRemoved)
14+
return self.subscribe(channelName,
15+
auth: nil,
16+
onMemberAdded: onMemberAdded,
17+
onMemberRemoved: onMemberRemoved,
18+
onSubscriptionCountChanged: onSubscriptionCountChanged)
1419
}
1520

1621
func subscribeToPresenceChannel(channelName: String) -> PusherPresenceChannel {
1722
return self.subscribeToPresenceChannel(channelName: channelName,
1823
auth: nil,
1924
onMemberAdded: nil,
20-
onMemberRemoved: nil)
25+
onMemberRemoved: nil,
26+
onSubscriptionCountChanged: nil)
2127
}
2228

2329
func subscribeToPresenceChannel(
2430
channelName: String,
2531
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
26-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
32+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
33+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
2734
) -> PusherPresenceChannel {
2835
return self.subscribeToPresenceChannel(channelName: channelName,
2936
auth: nil,
3037
onMemberAdded: onMemberAdded,
31-
onMemberRemoved: onMemberRemoved)
38+
onMemberRemoved: onMemberRemoved,
39+
onSubscriptionCountChanged: onSubscriptionCountChanged)
3240
}
3341

3442
convenience init(withAppKey key: String, options: PusherClientOptions) {

Sources/PusherSwift.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ let CLIENT_NAME = "pusher-websocket-swift"
5151
_ channelName: String,
5252
auth: PusherAuth? = nil,
5353
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
54-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
54+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
55+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
5556
) -> PusherChannel {
5657

5758
let isEncryptedChannel = PusherChannel.isEncrypted(name: channelName)
@@ -64,7 +65,8 @@ let CLIENT_NAME = "pusher-websocket-swift"
6465
channelName: channelName,
6566
auth: auth,
6667
onMemberAdded: onMemberAdded,
67-
onMemberRemoved: onMemberRemoved
68+
onMemberRemoved: onMemberRemoved,
69+
onSubscriptionCountChanged: onSubscriptionCountChanged
6870
)
6971
}
7072

@@ -87,13 +89,15 @@ let CLIENT_NAME = "pusher-websocket-swift"
8789
channelName: String,
8890
auth: PusherAuth? = nil,
8991
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
90-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
92+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
93+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
9194
) -> PusherPresenceChannel {
9295
return self.connection.subscribeToPresenceChannel(
9396
channelName: channelName,
9497
auth: auth,
9598
onMemberAdded: onMemberAdded,
96-
onMemberRemoved: onMemberRemoved
99+
onMemberRemoved: onMemberRemoved,
100+
onSubscriptionCountChanged: onSubscriptionCountChanged
97101
)
98102
}
99103

Sources/Services/PusherConnection.swift

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,16 @@ import NWWebSocket
104104
channelName: String,
105105
auth: PusherAuth? = nil,
106106
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
107-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
107+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
108+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
108109
) -> PusherChannel {
109110
let newChannel = channels.add(
110111
name: channelName,
111112
connection: self,
112113
auth: auth,
113114
onMemberAdded: onMemberAdded,
114-
onMemberRemoved: onMemberRemoved
115+
onMemberRemoved: onMemberRemoved,
116+
onSubscriptionCountChanged: onSubscriptionCountChanged
115117
)
116118

117119
guard self.connectionState == .connected else { return newChannel }
@@ -141,14 +143,16 @@ import NWWebSocket
141143
channelName: String,
142144
auth: PusherAuth? = nil,
143145
onMemberAdded: ((PusherPresenceChannelMember) -> Void)? = nil,
144-
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil
146+
onMemberRemoved: ((PusherPresenceChannelMember) -> Void)? = nil,
147+
onSubscriptionCountChanged: ((Int) -> Void)? = nil
145148
) -> PusherPresenceChannel {
146149
let newChannel = channels.addPresence(
147150
channelName: channelName,
148151
connection: self,
149152
auth: auth,
150153
onMemberAdded: onMemberAdded,
151-
onMemberRemoved: onMemberRemoved
154+
onMemberRemoved: onMemberRemoved,
155+
onSubscriptionCountChanged: onSubscriptionCountChanged
152156
)
153157

154158
guard self.connectionState == .connected else { return newChannel }
@@ -459,7 +463,7 @@ import NWWebSocket
459463
}
460464
}
461465
}
462-
466+
463467
let subscriptionEvent = event.copy(withEventName: Constants.Events.Pusher.subscriptionSucceeded)
464468
callGlobalCallbacks(event: subscriptionEvent)
465469
chan.handleEvent(event: subscriptionEvent)
@@ -549,6 +553,23 @@ import NWWebSocket
549553
Logger.shared.debug(for: .unableToRemoveMemberFromChannel)
550554
}
551555
}
556+
557+
/**
558+
Handle subscription count event
559+
560+
- parameter event: The event to be processed
561+
*/
562+
563+
private func handleSubscriptionCountEvent(event: PusherEvent) {
564+
guard let channelName = event.channelName,
565+
let channel = self.channels.find(name: channelName),
566+
let subscriptionCountData = event.dataToJSONObject() as? [String: Any],
567+
let count = subscriptionCountData[Constants.JSONKeys.subscriptionCount] as? Int else {
568+
return
569+
}
570+
571+
channel.updateSubscriptionCount(count: count)
572+
}
552573

553574
/**
554575
Handles incoming error
@@ -607,6 +628,9 @@ import NWWebSocket
607628

608629
case Constants.Events.PusherInternal.memberRemoved:
609630
handleMemberRemovedEvent(event: event)
631+
632+
case Constants.Events.PusherInternal.subscriptionCount:
633+
handleSubscriptionCountEvent(event: event)
610634

611635
default:
612636
callGlobalCallbacks(event: event)

0 commit comments

Comments
 (0)