compiling but haven't tested anything
This commit is contained in:
@@ -7,18 +7,16 @@
|
||||
|
||||
import Foundation
|
||||
import AgoraRtcKit
|
||||
import Firebase
|
||||
|
||||
class ConvoViewModel: NSObject, ObservableObject {
|
||||
private var testingUIMode = true
|
||||
|
||||
@Published var selectedConvoId:String? = nil
|
||||
@Published var connectionState: AgoraConnectionStateType? = nil
|
||||
|
||||
let firestoreService = FirestoreService()
|
||||
let agoraService = AgoraService()
|
||||
|
||||
let testConvos: [Convo] = [
|
||||
Convo(id: "testChannel", leaderUserId: "VWVPKCrNmMeZlkEeZxuJ0Wsgq0C3", receiverUserId: "zd6PpD3TmnQUDoy6noS9aZpuPWr1", agoraToken: "006c8dfd65deb5c4741bd564085627139d0IAAqbHMFow9oQ8BN0WCkFrkGBTqFTjlbr6tJmFH5judwbnZXrgMAAAAAEADQ943gC8nOYQEAAQALyc5h", state: .connected)
|
||||
]
|
||||
@Published var relevantConvos: [Convo] = []
|
||||
|
||||
var agoraKit: AgoraRtcEngineKit?
|
||||
|
||||
@@ -26,15 +24,68 @@ class ConvoViewModel: NSObject, ObservableObject {
|
||||
return self.selectedConvoId != nil
|
||||
}
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
||||
var convosListener: ListenerRegistration? = nil
|
||||
|
||||
private var db = Firestore.firestore()
|
||||
|
||||
private var allConvos: [Convo] = []
|
||||
|
||||
private var relevancyAcceptance = 0.6
|
||||
|
||||
func activateDataListener(activeFriendsIds: [String]) {
|
||||
// initiate convo listener to get all relevant convos
|
||||
// any convo that is active
|
||||
// and any of my active friends are in that convo
|
||||
// and any of my active friends or I am in that convo
|
||||
// if am being "called" catch that and join the convo/channel
|
||||
var scopeUserIds: [String] = []
|
||||
scopeUserIds += activeFriendsIds
|
||||
|
||||
// only show convos in which I know a majority of the people inside
|
||||
// I want to get back convos that involve me
|
||||
if let userId = AuthSessionStore.getCurrentUserId() {
|
||||
scopeUserIds.append(userId)
|
||||
}
|
||||
|
||||
print("the scope of users to search for convos is \(scopeUserIds)")
|
||||
|
||||
self.convosListener = db.collection("convos").whereField("state", isEqualTo: ConvoState.active.rawValue).whereField("users", arrayContainsAny: scopeUserIds)
|
||||
.addSnapshotListener { querySnapshot, error in
|
||||
print("convos listener")
|
||||
guard let documents = querySnapshot?.documents else {
|
||||
print("Error fetching convos \(error!)")
|
||||
return
|
||||
}
|
||||
|
||||
self.allConvos.removeAll()
|
||||
self.relevantConvos.removeAll()
|
||||
|
||||
for document in querySnapshot!.documents {
|
||||
let convo:Convo? = try? document.data(as: Convo.self)
|
||||
|
||||
if convo == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
self.allConvos.append(convo!)
|
||||
}
|
||||
|
||||
// only show convos in which I know a majority of the people inside
|
||||
// use relevancyAcceptance value
|
||||
self.relevantConvos = self.allConvos.filter{convo in
|
||||
var relevancyCount = 0
|
||||
// go through all users in this convo
|
||||
for user in convo.users {
|
||||
if scopeUserIds.contains(user) {
|
||||
relevancyCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
if Double(relevancyCount / convo.users.count) > self.relevancyAcceptance {
|
||||
print("this convo counts as relevant!!!")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// initiate agora engine
|
||||
self.initializeAgoraEngine()
|
||||
@@ -42,6 +93,8 @@ class ConvoViewModel: NSObject, ObservableObject {
|
||||
|
||||
deinit {
|
||||
// deinit the firestore listener
|
||||
self.convosListener?.remove()
|
||||
|
||||
// deinit the agora engine
|
||||
print("deiniting and cleaning up convo view model/agora services")
|
||||
|
||||
@@ -54,35 +107,55 @@ class ConvoViewModel: NSObject, ObservableObject {
|
||||
@param: friendId: the second person in the convo...the receiver
|
||||
**/
|
||||
func startConvo(friendId: String) {
|
||||
if testingUIMode {
|
||||
print("testing mode...not doing anything")
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: need to make sure the other user is online or already did in view
|
||||
|
||||
// making sure this user is authenticated
|
||||
if let userId = AuthSessionStore.getCurrentUserId() {
|
||||
let channelName = UUID().uuidString
|
||||
|
||||
// get a new agora token from cloud function
|
||||
self.agoraService.getAgoraTokenCF(channelName: channelName) {[weak self] token in
|
||||
if token == nil {
|
||||
print("error in getting token")
|
||||
}
|
||||
|
||||
let users = [userId] // just one user now, and that's me...but no one has joined yet
|
||||
// only considered joined when I have officially joined the agora channel
|
||||
|
||||
var convo = Convo(id: channelName, leaderUserId: userId, receiverUserId: friendId, agoraToken: token!, state: .initialized, users: [], startedTimestamp: nil, endedTimestamp: nil)
|
||||
|
||||
// create a convo/channel in db to notify the other user with proper attributes
|
||||
self?.firestoreService.createConvo(convo: convo) {[weak self] res in
|
||||
switch res {
|
||||
case .success:
|
||||
// join the convo myself
|
||||
self?.joinConvo(channelName: channelName, agoraToken: token!)
|
||||
case .error(let error):
|
||||
print(error)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func joinConvo(channelName: String, agoraToken: String) {
|
||||
// ensure that this user leaves all other channels
|
||||
if self.isInCall() {
|
||||
self.leaveConvo()
|
||||
}
|
||||
|
||||
// need to make sure the other user is online
|
||||
|
||||
// get a new agora token from cloud function
|
||||
|
||||
// create a convo/channel in db to notify the other user with proper attributes
|
||||
|
||||
// join the convo myself
|
||||
self.agoraKit?.setDefaultAudioRouteToSpeakerphone(true)
|
||||
// finally join channel
|
||||
self.agoraKit?.joinChannel(byToken: agoraToken, channelId: channelName, info: nil, uid: 0, joinSuccess: nil)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Allow user to join an active convo
|
||||
*/
|
||||
func joinConvo() {
|
||||
if testingUIMode {
|
||||
print("testing mode...not doing anything")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ensure the convo is active and includes 2 people in it currently...shouldn't be shown if not anyway
|
||||
|
||||
// ensure that this user leaves all other channels
|
||||
@@ -90,9 +163,7 @@ class ConvoViewModel: NSObject, ObservableObject {
|
||||
self.leaveConvo()
|
||||
}
|
||||
|
||||
self.agoraKit?.setDefaultAudioRouteToSpeakerphone(true)
|
||||
|
||||
let convo = self.testConvos.first {convo in
|
||||
let convo = self.relevantConvos.first {convo in
|
||||
convo.id == self.selectedConvoId
|
||||
}
|
||||
|
||||
@@ -102,25 +173,19 @@ class ConvoViewModel: NSObject, ObservableObject {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// TODO: if the convo has more than 10 people, stop user from joining...that's too expensive...
|
||||
|
||||
|
||||
let convoAgoraToken:String = convo!.agoraToken
|
||||
let channelName:String = convo!.id!
|
||||
|
||||
|
||||
self.agoraKit?.setDefaultAudioRouteToSpeakerphone(true)
|
||||
// finally join channel
|
||||
self.agoraKit?.joinChannel(byToken: convoAgoraToken, channelId: channelName, info: nil, uid: 0, joinSuccess: nil)
|
||||
}
|
||||
|
||||
// anyone can leave at any time
|
||||
func leaveConvo() {
|
||||
if testingUIMode {
|
||||
print("testing mode...not doing anything")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
agoraKit?.leaveChannel(nil)
|
||||
|
||||
// if I am the second person in the room, then end the convo
|
||||
@@ -143,19 +208,87 @@ extension ConvoViewModel: AgoraRtcEngineDelegate {
|
||||
|
||||
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) {
|
||||
print("I did join channel")
|
||||
|
||||
// set my user status to in convo
|
||||
|
||||
// leave channel if it's just me
|
||||
// TODO: play a sound when I join the channel
|
||||
|
||||
// TODO: leave channel if it's just me
|
||||
|
||||
|
||||
var convo = self.relevantConvos.first {convo in
|
||||
convo.id == self.selectedConvoId
|
||||
}
|
||||
if convo == nil {
|
||||
print("no such convo found")
|
||||
return
|
||||
}
|
||||
|
||||
if let userId = AuthSessionStore.getCurrentUserId() {
|
||||
// set my user status to in convo/red
|
||||
self.firestoreService.updateUserStatus(userId: userId, userStatus: .inConvo) {[weak self] res in
|
||||
print(res)
|
||||
|
||||
switch res {
|
||||
case .success:
|
||||
// update convo in database users array to let them know I am there
|
||||
|
||||
convo?.users.append(userId)
|
||||
convo?.state = .active
|
||||
|
||||
self?.firestoreService.updateConvo(convo: convo!) {[weak self] res in
|
||||
print(res)
|
||||
}
|
||||
case .error(let error):
|
||||
print(error)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rtcEngine(_ engine: AgoraRtcEngineKit, didLeaveChannelWith stats: AgoraChannelStats) {
|
||||
// leave channel if I am the only one in it
|
||||
|
||||
print("I did leave channel")
|
||||
|
||||
var convo = self.relevantConvos.first {convo in
|
||||
convo.id == self.selectedConvoId
|
||||
}
|
||||
if convo == nil {
|
||||
print("no such convo found")
|
||||
return
|
||||
}
|
||||
|
||||
self.selectedConvoId = nil
|
||||
if let userId = AuthSessionStore.getCurrentUserId() {
|
||||
// set my user status to online
|
||||
self.firestoreService.updateUserStatus(userId: userId, userStatus: .online) {[weak self] res in
|
||||
print(res)
|
||||
|
||||
switch res {
|
||||
case .success:
|
||||
//update convo in database to show that I left...if I am the last person, also close out the channel
|
||||
|
||||
let updatedUsers: [String] = convo!.users.filter{ arrUserId in
|
||||
return arrUserId != userId
|
||||
}
|
||||
|
||||
convo!.users = updatedUsers
|
||||
|
||||
// if I am the last one in the convo, then end the convo
|
||||
if convo!.users.count == 1 && convo!.users[0] == userId {
|
||||
convo!.state = .complete
|
||||
convo!.endedTimestamp = Date()
|
||||
}
|
||||
|
||||
self?.firestoreService.updateConvo(convo: convo!) {[weak self] res in
|
||||
self?.selectedConvoId = nil
|
||||
print("left convo officially in our db as well")
|
||||
}
|
||||
case .error(let error):
|
||||
print(error)
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
|
||||
|
||||
Reference in New Issue
Block a user