@@ -200,16 +200,18 @@ struct ContentView: View {
200200 do {
201201 let room = try await room ( )
202202
203+ printConnectionStatusChange ( duration: 30 ) // stops printing after 30 seconds
204+ subscribeToReactions ( room: room)
205+ subscribeToRoomStatus ( room: room)
206+ subscribeToTypingEvents ( room: room)
207+ subscribeToOccupancy ( room: room)
208+ subscribeToPresence ( room: room)
209+
203210 try await room. attach ( )
211+ try await showOccupancy ( room: room)
204212 try await room. presence. enter ( data: [ " status " : " 📱 Online " ] )
205213
206214 try await showMessages ( room: room)
207- showReactions ( room: room)
208- showPresence ( room: room)
209- try await showOccupancy ( room: room)
210- showTypings ( room: room)
211- showRoomStatus ( room: room)
212- printConnectionStatusChange ( )
213215 } catch {
214216 print ( " Failed to initialize room: \( error) " ) // TODO: replace with logger (+ message to the user?)
215217 }
@@ -234,136 +236,110 @@ struct ContentView: View {
234236 }
235237
236238 func showMessages( room: Room ) async throws {
237- let messagesSubscription = try await room. messages. subscribe ( )
238- let previousMessages = try await messagesSubscription. getPreviousMessages ( params: . init( ) )
239-
240- for message in previousMessages. items {
239+ let subscription = try await room. messages. subscribe { message in
241240 switch message. action {
242- case . create, . update , . delete :
241+ case . create:
243242 withAnimation {
244- listItems. append ( . message( . init( message: message, isSender: message. clientID == chatClient. realtime. clientId) ) )
245- }
246- }
247- }
248-
249- // Continue listening for messages on a background task so this function can return
250- Task {
251- for await message in messagesSubscription {
252- switch message. action {
253- case . create:
254- withAnimation {
255- listItems. insert (
256- . message(
257- . init(
258- message: message,
259- isSender: message. clientID == chatClient. realtime. clientId
260- )
261- ) ,
262- at: 0
263- )
264- }
265- case . update, . delete:
266- if let index = listItems. firstIndex ( where: { $0. id == message. id } ) {
267- listItems [ index] = . message(
243+ listItems. insert (
244+ . message(
268245 . init(
269246 message: message,
270247 isSender: message. clientID == chatClient. realtime. clientId
271248 )
249+ ) ,
250+ at: 0
251+ )
252+ }
253+ case . update, . delete:
254+ if let index = listItems. firstIndex ( where: { $0. id == message. id } ) {
255+ listItems [ index] = . message(
256+ . init(
257+ message: message,
258+ isSender: message. clientID == chatClient. realtime. clientId
272259 )
273- }
260+ )
274261 }
275262 }
276263 }
277- }
278-
279- func showReactions( room: Room ) {
280- let reactionSubscription = room. reactions. subscribe ( )
264+ let previousMessages = try await subscription. historyBeforeSubscribe ( )
281265
282- // Continue listening for reactions on a background task so this function can return
283- Task {
284- for await reaction in reactionSubscription {
266+ for message in previousMessages . items {
267+ switch message . action {
268+ case . create , . update , . delete :
285269 withAnimation {
286- showReaction ( reaction . displayedText )
270+ listItems . append ( . message ( . init ( message : message , isSender : message . clientID == chatClient . realtime . clientId ) ) )
287271 }
288272 }
289273 }
290274 }
291275
292- func showPresence( room: Room ) {
293- // Continue listening for new presence events on a background task so this function can return
294- Task {
295- for await event in room. presence. subscribe ( events: [ . enter, . leave, . update] ) {
296- withAnimation {
297- listItems. insert (
298- . presence(
299- . init(
300- presence: event
301- )
302- ) ,
303- at: 0
304- )
305- }
276+ func subscribeToReactions( room: Room ) {
277+ room. reactions. subscribe { reaction in
278+ withAnimation {
279+ showReaction ( reaction. displayedText)
306280 }
307281 }
308282 }
309283
310- func showTypings ( room: Room ) {
311- let typingSubscription = room. typing . subscribe ( )
312- // Continue listening for typing events on a background task so this function can return
313- Task {
314- for await typing in typingSubscription {
315- withAnimation {
316- // Set the typing info to the list of users currently typing
317- typingInfo = typing . currentlyTyping . isEmpty ?
318- " " :
319- " Typing: \( typing . currentlyTyping . joined ( separator : " , " ) ) ... "
320- }
284+ func subscribeToPresence ( room: Room ) {
285+ room. presence . subscribe ( events : [ . enter , . leave , . update ] ) { event in
286+ withAnimation {
287+ listItems . insert (
288+ . presence (
289+ . init (
290+ presence : event
291+ )
292+ ) ,
293+ at : 0
294+ )
321295 }
322296 }
323297 }
324298
325- func showOccupancy( room: Room ) async throws {
326- // Continue listening for occupancy events on a background task so this function can return
327- let currentOccupancy = try await room. occupancy. get ( )
328- withAnimation {
329- occupancyInfo = " Connections: \( currentOccupancy. presenceMembers) ( \( currentOccupancy. connections) ) "
330- }
331-
332- Task {
333- for await event in room. occupancy. subscribe ( ) {
334- withAnimation {
335- occupancyInfo = " Connections: \( event. presenceMembers) ( \( event. connections) ) "
336- }
299+ func subscribeToTypingEvents( room: Room ) {
300+ room. typing. subscribe { typing in
301+ withAnimation {
302+ // Set the typing info to the list of users currently typing
303+ let reset = typing. currentlyTyping. isEmpty || typing. currentlyTyping. count == 1 && typing. change. type == . stopped
304+ typingInfo = reset ? " " : " Typing: \( typing. currentlyTyping. joined ( separator: " , " ) ) ... "
337305 }
338306 }
339307 }
340308
341- func printConnectionStatusChange( ) {
342- let connectionSubsciption = chatClient. connection. onStatusChange ( )
309+ func showOccupancy( room: Room ) async throws {
310+ let occupancy = try await room. occupancy. get ( )
311+ occupancyInfo = " Connections: \( occupancy. presenceMembers) ( \( occupancy. connections) ) "
312+ }
343313
344- // Continue listening for connection status change on a background task so this function can return
345- Task {
346- for await status in connectionSubsciption {
347- print ( " Connection status changed to : \( status . current ) " )
314+ func subscribeToOccupancy ( room : Room ) {
315+ room . occupancy . subscribe { occupancy in
316+ withAnimation {
317+ occupancyInfo = " Connections : \( occupancy . presenceMembers ) ( \( occupancy . connections ) ) "
348318 }
349319 }
350320 }
351321
352- func showRoomStatus( room: Room ) {
353- // Continue listening for status change events on a background task so this function can return
354- Task {
355- for await status in room. onStatusChange ( ) {
356- withAnimation {
357- if status. current. isAttaching {
358- statusInfo = " \( status. current) ... " . capitalized
359- } else {
360- statusInfo = " \( status. current) " . capitalized
361- if status. current. isAttached {
362- Task {
363- try ? await Task . sleep ( nanoseconds: 1 * 1_000_000_000 )
364- withAnimation {
365- statusInfo = " "
366- }
322+ func printConnectionStatusChange( duration: TimeInterval ) {
323+ let subscription = chatClient. connection. onStatusChange { status in
324+ print ( " Connection status changed to: ` \( status. current) ` from ` \( status. previous) ` " )
325+ }
326+ after ( duration) {
327+ subscription. off ( )
328+ print ( " Unsubscribed from connection status changes. " )
329+ }
330+ }
331+
332+ func subscribeToRoomStatus( room: Room ) {
333+ room. onStatusChange { status in
334+ withAnimation {
335+ if status. current. isAttaching {
336+ statusInfo = " \( status. current) ... " . capitalized
337+ } else {
338+ statusInfo = " \( status. current) " . capitalized
339+ if status. current. isAttached {
340+ after ( 1 ) {
341+ withAnimation {
342+ statusInfo = " "
367343 }
368344 }
369345 }
0 commit comments