@@ -55,21 +55,32 @@ public function subscribe(ConnectionInterface $connection, stdClass $payload)
55
55
]));
56
56
});
57
57
58
- $ memberAddedPayload = [
59
- 'event ' => 'pusher_internal:member_added ' ,
60
- 'channel ' => $ this ->getName (),
61
- 'data ' => $ payload ->channel_data ,
62
- ];
63
-
64
- $ this ->broadcastToEveryoneExcept (
65
- (object ) $ memberAddedPayload , $ connection ->socketId ,
66
- $ connection ->app ->id
67
- );
58
+ // The `pusher_internal:member_added` event is triggered when a user joins a channel.
59
+ // It's quite possible that a user can have multiple connections to the same channel
60
+ // (for example by having multiple browser tabs open)
61
+ // and in this case the events will only be triggered when the first tab is opened.
62
+ $ this ->channelManager
63
+ ->getMemberSockets ($ user ->user_id , $ connection ->app ->id , $ this ->getName ())
64
+ ->then (function ($ sockets ) use ($ payload , $ connection ) {
65
+ if (count ($ sockets ) === 1 ) {
66
+ $ memberAddedPayload = [
67
+ 'event ' => 'pusher_internal:member_added ' ,
68
+ 'channel ' => $ this ->getName (),
69
+ 'data ' => $ payload ->channel_data ,
70
+ ];
71
+
72
+ $ this ->broadcastToEveryoneExcept (
73
+ (object ) $ memberAddedPayload , $ connection ->socketId ,
74
+ $ connection ->app ->id
75
+ );
76
+ }
68
77
69
- DashboardLogger::log ($ connection ->app ->id , DashboardLogger::TYPE_SUBSCRIBED , [
70
- 'socketId ' => $ connection ->socketId ,
71
- 'channel ' => $ this ->getName (),
72
- ]);
78
+ DashboardLogger::log ($ connection ->app ->id , DashboardLogger::TYPE_SUBSCRIBED , [
79
+ 'socketId ' => $ connection ->socketId ,
80
+ 'channel ' => $ this ->getName (),
81
+ 'duplicate-connection ' => count ($ sockets ) > 1 ,
82
+ ]);
83
+ });
73
84
}
74
85
75
86
/**
@@ -95,18 +106,28 @@ public function unsubscribe(ConnectionInterface $connection)
95
106
$ connection , $ user , $ this ->getName ()
96
107
);
97
108
98
- $ memberRemovedPayload = [
99
- 'event ' => 'pusher_internal:member_removed ' ,
100
- 'channel ' => $ this ->getName (),
101
- 'data ' => json_encode ([
102
- 'user_id ' => $ user ->user_id ,
103
- ]),
104
- ];
105
-
106
- $ this ->broadcastToEveryoneExcept (
107
- (object ) $ memberRemovedPayload , $ connection ->socketId ,
108
- $ connection ->app ->id
109
- );
109
+ // The `pusher_internal:member_removed` is triggered when a user leaves a channel.
110
+ // It's quite possible that a user can have multiple connections to the same channel
111
+ // (for example by having multiple browser tabs open)
112
+ // and in this case the events will only be triggered when the last one is closed.
113
+ $ this ->channelManager
114
+ ->getMemberSockets ($ user ->user_id , $ connection ->app ->id , $ this ->getName ())
115
+ ->then (function ($ sockets ) use ($ connection , $ user ) {
116
+ if (count ($ sockets ) === 0 ) {
117
+ $ memberRemovedPayload = [
118
+ 'event ' => 'pusher_internal:member_removed ' ,
119
+ 'channel ' => $ this ->getName (),
120
+ 'data ' => json_encode ([
121
+ 'user_id ' => $ user ->user_id ,
122
+ ]),
123
+ ];
124
+
125
+ $ this ->broadcastToEveryoneExcept (
126
+ (object ) $ memberRemovedPayload , $ connection ->socketId ,
127
+ $ connection ->app ->id
128
+ );
129
+ }
130
+ });
110
131
});
111
132
}
112
133
}
0 commit comments