-
Notifications
You must be signed in to change notification settings - Fork 0
/
VirtualGiftingViewModel.swift
179 lines (145 loc) · 6.41 KB
/
VirtualGiftingViewModel.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
//
// VirtualGiftingViewModel.swift
// APIExample_RTM2x
//
// Created by BBC on 2024/8/8.
//
import Foundation
import SwiftUI
import AgoraRtmKit
class VirtualGiftingViewModel: NSObject, ObservableObject {
var agoraRtmKit: AgoraRtmClientKit? = nil
@AppStorage("userID") var userID: String = ""
@Published var token: String = ""
@Published var isLoggedIn: Bool = false
@Published var connectionState: AgoraRtmClientConnectionState = .disconnected
@Published var users: [AgoraRtmUserState] = []
@Published var gifts: [Gift] = []
let customGiftType = "giftMessage"
@MainActor
func loginRTM() async throws {
do {
if userID.isEmpty {
throw customError.emptyUIDLoginError
}
// Initialize RTM instance
if agoraRtmKit == nil {
let config = AgoraRtmClientConfig(appId: Configurations.agora_AppID , userId: userID)
agoraRtmKit = try AgoraRtmClientKit(config, delegate: self)
}
// Login to RTM server
// Use AppID to login if app certificate is NOT enabled for project
if let (response, error) = await agoraRtmKit?.login(token.isEmpty ? Configurations.agora_AppID : token) {
if error == nil{
isLoggedIn = true
}else{
print("Bac's code loginRTM login result = \(String(describing: response?.description)) | error \(String(describing: error))")
await agoraRtmKit?.logout()
throw error ?? customError.loginRTMError
}
} else {
// Handle any cases where login fails or error is present
print("Bac's code loginRTM login result = \(userID)")
}
}catch {
print("Bac's Some other error occurred: \(error.localizedDescription)")
throw error
}
}
// Logout RTM server
func logoutRTM(){
agoraRtmKit?.logout()
agoraRtmKit?.destroy()
isLoggedIn = false
}
//MARK: MESSAGE CHANNEL METHODS
// Subscribe to channel in 'MessageChannel'
@MainActor
func subscribeChannel(channelName: String) async -> Bool {
let subOptions: AgoraRtmSubscribeOptions = AgoraRtmSubscribeOptions()
subOptions.features = [.message, .presence]
if let (_, error) = await agoraRtmKit?.subscribe(channelName: channelName, option: subOptions){
if error == nil {
return true
}
return false
}
return false
}
// Publish to channel in 'MessageChannel'
@MainActor
func publishToChannel(channelName: String, messageString: String) async -> Bool{
let pubOptions = AgoraRtmPublishOptions()
pubOptions.customType = customGiftType
pubOptions.channelType = .message
if let (_, error) = await agoraRtmKit?.publish(channelName: channelName, message: messageString, option: pubOptions){
if error == nil {
let userGift = Gift(userID: userID, gift: messageString, timestamp: Date())
withAnimation {
gifts.append(userGift)
}
return true
}else{
print("Bac's sendMessageToChannel error \(String(describing: error))")
return false
}
}
return false
}
}
extension VirtualGiftingViewModel: AgoraRtmClientDelegate {
// Receive message event notifications in subscribed message channels and subscribed topics.
func rtmKit(_ rtmKit: AgoraRtmClientKit, didReceiveMessageEvent event: AgoraRtmMessageEvent) {
print("Bac's didReceiveMessageEvent msg = \(event.message.stringData ?? "Empty") from \(event.publisher) type \(String(describing: event.customType))")
switch event.channelType {
case .message:
if event.customType == customGiftType {
Task {
await MainActor.run {
let userGift = Gift(userID: event.publisher, gift: event.message.stringData ?? "", timestamp: Date())
withAnimation {
gifts.append(userGift)
}
}
}
}
break
case .stream:
break
case .user:
break
case .none:
break
@unknown default:
print("Bac's didReceiveMessageEvent channelType is unknown")
}
}
// Receive presence event notifications in subscribed message channels and joined stream channels.
func rtmKit(_ rtmKit: AgoraRtmClientKit, didReceivePresenceEvent event: AgoraRtmPresenceEvent) {
print("Bac's didReceivePresenceEvent channelType \(event.channelType) publisher \(String(describing: event.publisher)) channel \(event.channelName) type \(event.type) ")
if event.type == .remoteLeaveChannel || event.type == .remoteConnectionTimeout {
// Remove user from list
if let userIndex = users.firstIndex(where: {$0.userId == event.publisher}) {
users.remove(at: userIndex)
}
}else if event.type == .remoteJoinChannel && event.publisher != nil {
// Add user to list if it doesn't exist
if !users.contains(where: {$0.userId == event.publisher}) && event.publisher != nil {
let userState = AgoraRtmUserState()
userState.userId = event.publisher!
userState.states = event.states
users.append(userState)
}
}else if event.type == .snapshot {
print("Bac's didReceivePresenceEvent snapshot")
users = event.snapshot
}else if event.type == .remoteStateChanged {
print("Bac's didReceivePresenceEvent remoteStateChanged")
}
}
// Triggers when connection changes
func rtmKit(_ kit: AgoraRtmClientKit, channel channelName: String, connectionChangedToState state: AgoraRtmClientConnectionState, reason: AgoraRtmClientConnectionChangeReason) {
print("Bac's connectionChangedToState \(state) reason \(reason.rawValue)")
connectionState = connectionState
}
}