basic call works with swiftui architecture
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
8904DEC8277055E90071E6CA /* OnboardingOneView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8904DEC7277055E90071E6CA /* OnboardingOneView.swift */; };
|
8904DEC8277055E90071E6CA /* OnboardingOneView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8904DEC7277055E90071E6CA /* OnboardingOneView.swift */; };
|
||||||
|
89091993277D958D0025F4BB /* ConvoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89091992277D958D0025F4BB /* ConvoViewModel.swift */; };
|
||||||
890C245D277BF628009B4A30 /* AgoraRtcKit in Frameworks */ = {isa = PBXBuildFile; productRef = 890C245C277BF628009B4A30 /* AgoraRtcKit */; };
|
890C245D277BF628009B4A30 /* AgoraRtcKit in Frameworks */ = {isa = PBXBuildFile; productRef = 890C245C277BF628009B4A30 /* AgoraRtcKit */; };
|
||||||
890C2460277BF896009B4A30 /* AgoraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890C245F277BF896009B4A30 /* AgoraViewController.swift */; };
|
890C2460277BF896009B4A30 /* AgoraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890C245F277BF896009B4A30 /* AgoraViewController.swift */; };
|
||||||
890C2462277BF935009B4A30 /* CallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890C2461277BF935009B4A30 /* CallView.swift */; };
|
890C2462277BF935009B4A30 /* CallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890C2461277BF935009B4A30 /* CallView.swift */; };
|
||||||
@@ -92,6 +93,7 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
8904DEC7277055E90071E6CA /* OnboardingOneView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingOneView.swift; sourceTree = "<group>"; };
|
8904DEC7277055E90071E6CA /* OnboardingOneView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingOneView.swift; sourceTree = "<group>"; };
|
||||||
|
89091992277D958D0025F4BB /* ConvoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConvoViewModel.swift; sourceTree = "<group>"; };
|
||||||
890C245F277BF896009B4A30 /* AgoraViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgoraViewController.swift; sourceTree = "<group>"; };
|
890C245F277BF896009B4A30 /* AgoraViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgoraViewController.swift; sourceTree = "<group>"; };
|
||||||
890C2461277BF935009B4A30 /* CallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallView.swift; sourceTree = "<group>"; };
|
890C2461277BF935009B4A30 /* CallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallView.swift; sourceTree = "<group>"; };
|
||||||
890C2463277BFA97009B4A30 /* AgroRep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgroRep.swift; sourceTree = "<group>"; };
|
890C2463277BFA97009B4A30 /* AgroRep.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AgroRep.swift; sourceTree = "<group>"; };
|
||||||
@@ -373,6 +375,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
89814682277D83F300DA46CD /* ConvosView.swift */,
|
89814682277D83F300DA46CD /* ConvosView.swift */,
|
||||||
|
89091992277D958D0025F4BB /* ConvoViewModel.swift */,
|
||||||
);
|
);
|
||||||
path = Convos;
|
path = Convos;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -640,6 +643,7 @@
|
|||||||
89BCABE5276B3D58009E9B10 /* InnerCircleView.swift in Sources */,
|
89BCABE5276B3D58009E9B10 /* InnerCircleView.swift in Sources */,
|
||||||
894E80C1276EFD0500624B72 /* AudioPlayerView.swift in Sources */,
|
894E80C1276EFD0500624B72 /* AudioPlayerView.swift in Sources */,
|
||||||
89F18AF5276ECF2A00115B1E /* AddBasicInfoView.swift in Sources */,
|
89F18AF5276ECF2A00115B1E /* AddBasicInfoView.swift in Sources */,
|
||||||
|
89091993277D958D0025F4BB /* ConvoViewModel.swift in Sources */,
|
||||||
89BCABF0276D53C4009E9B10 /* PhoneVerificationViewModel.swift in Sources */,
|
89BCABF0276D53C4009E9B10 /* PhoneVerificationViewModel.swift in Sources */,
|
||||||
89BDCDE72769616600577829 /* UIImage+Extension.swift in Sources */,
|
89BDCDE72769616600577829 /* UIImage+Extension.swift in Sources */,
|
||||||
890C2464277BFA97009B4A30 /* AgroRep.swift in Sources */,
|
890C2464277BFA97009B4A30 /* AgroRep.swift in Sources */,
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
//
|
||||||
|
// ConvoViewModel.swift
|
||||||
|
// nirvana-ios
|
||||||
|
//
|
||||||
|
// Created by Arjun Patel on 12/29/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import AgoraRtcKit
|
||||||
|
|
||||||
|
|
||||||
|
class ConvoViewModel: ObservableObject {
|
||||||
|
let firestoreService = FirestoreService()
|
||||||
|
|
||||||
|
var agoraKit: AgoraRtcEngineKit?
|
||||||
|
var agoraDelegate: AgoraRtcEngineDelegate?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
// initiate convo listener to get all relevant convos
|
||||||
|
// any convo that is active
|
||||||
|
// and any of my active friends are in that convo
|
||||||
|
// if am being "called" catch that and join the convo/channel
|
||||||
|
|
||||||
|
// only show convos in which I know a majority of the people inside
|
||||||
|
|
||||||
|
// initiate agora engine
|
||||||
|
self.initializeAgoraEngine()
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
// deinit the firestore listener
|
||||||
|
// deinit the agora engine
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@param: friendId: the second person in the convo...the receiver
|
||||||
|
**/
|
||||||
|
func startConvo(friendId: String) {
|
||||||
|
if let userId = AuthSessionStore.getCurrentUserId() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allow user to join an active convo
|
||||||
|
*/
|
||||||
|
func joinConvo(convoId: String, convoAgoraToken: String) {
|
||||||
|
// 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
|
||||||
|
self.leaveConvo()
|
||||||
|
|
||||||
|
// finally join channel
|
||||||
|
agoraKit?.joinChannel(byToken: convoAgoraToken, channelId: "testChannel", info: nil, uid: 0, joinSuccess: {(channel, uid, elapsed) in
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// anyone can leave at any time
|
||||||
|
private func leaveConvo() {
|
||||||
|
agoraKit?.leaveChannel(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if you are the second to last person in the convo and you leave, you end the convo
|
||||||
|
private func endConvo() {
|
||||||
|
AgoraRtcEngineKit.destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ConvoViewModel {
|
||||||
|
func initializeAgoraEngine() {
|
||||||
|
// TODO: put app id in environment variables
|
||||||
|
agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: "c8dfd65deb5c4741bd564085627139d0", delegate: agoraDelegate)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,20 +9,21 @@ import SwiftUI
|
|||||||
|
|
||||||
// test convos
|
// test convos
|
||||||
let testConvos: [Convo] = [
|
let testConvos: [Convo] = [
|
||||||
Convo(leaderUserId: "VWVPKCrNmMeZlkEeZxuJ0Wsgq0C3", receiverUserId: "zd6PpD3TmnQUDoy6noS9aZpuPWr1", agoraToken: "006c8dfd65deb5c4741bd564085627139d0IAAIlYcWj21zCp4jq/WS2BMaiMYlKSax7ohIjzBx1BtpWAx+f9gAAAAAEADQ943gX6LOYQEAAQBfos5h", state: .connected)
|
Convo(id: "testChannel", leaderUserId: "VWVPKCrNmMeZlkEeZxuJ0Wsgq0C3", receiverUserId: "zd6PpD3TmnQUDoy6noS9aZpuPWr1", agoraToken: "006c8dfd65deb5c4741bd564085627139d0IAAqbHMFow9oQ8BN0WCkFrkGBTqFTjlbr6tJmFH5judwbnZXrgMAAAAAEADQ943gC8nOYQEAAQALyc5h", state: .connected)
|
||||||
]
|
]
|
||||||
|
|
||||||
struct ConvosView: View {
|
struct ConvosView: View {
|
||||||
|
@ObservedObject var vm = ConvoViewModel()
|
||||||
|
@State var animate = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ScrollView([.horizontal]) {
|
ScrollView([.horizontal]) {
|
||||||
HStack {
|
HStack {
|
||||||
ForEach(0..<testConvos.count, id: \.self) {index in
|
ForEach(0..<testConvos.count, id: \.self) {index in
|
||||||
|
|
||||||
|
|
||||||
ZStack(alignment: .topTrailing) {
|
ZStack(alignment: .topTrailing) {
|
||||||
Circle()
|
Circle()
|
||||||
.foregroundColor(NirvanaColor.dimTeal.opacity(0.4))
|
.foregroundColor(NirvanaColor.dimTeal.opacity(0.4))
|
||||||
|
|
||||||
ZStack {
|
ZStack {
|
||||||
Color.clear
|
Color.clear
|
||||||
ProfilePictureOverlap()
|
ProfilePictureOverlap()
|
||||||
@@ -35,11 +36,28 @@ struct ConvosView: View {
|
|||||||
.foregroundColor(Color.white)
|
.foregroundColor(Color.white)
|
||||||
.background(NirvanaColor.dimTeal)
|
.background(NirvanaColor.dimTeal)
|
||||||
.cornerRadius(100)
|
.cornerRadius(100)
|
||||||
|
|
||||||
|
// ZStack(alignment: .bottom) {
|
||||||
|
// Color.clear
|
||||||
|
//
|
||||||
|
// Text("kev, sarth...")
|
||||||
|
// .foregroundColor(NirvanaColor.teal)
|
||||||
|
// .font(.caption)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
.frame(width: 100, height: 100)
|
.frame(width: 100, height: 100)
|
||||||
|
.scaleEffect(self.animate ? 1 : 0.85)
|
||||||
|
.animation(animate ? Animation.easeInOut(duration: 4).repeatForever(autoreverses: true) : .default)
|
||||||
|
.onTapGesture {
|
||||||
|
self.vm.joinConvo(convoId: testConvos[index].id!, convoAgoraToken: testConvos[index].agoraToken)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onAppear {
|
||||||
|
self.animate = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.padding()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +85,6 @@ struct ProfilePictureOverlap: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ struct CircleGridView: View {
|
|||||||
@State var queuePlayer = AVQueuePlayer()
|
@State var queuePlayer = AVQueuePlayer()
|
||||||
@State var timeObserverToken: Any?
|
@State var timeObserverToken: Any?
|
||||||
|
|
||||||
@State private var showCall: Bool = false
|
|
||||||
|
|
||||||
@GestureState var dragState = DragState.inactive
|
@GestureState var dragState = DragState.inactive
|
||||||
|
|
||||||
let universalSize = UIScreen.main.bounds
|
let universalSize = UIScreen.main.bounds
|
||||||
@@ -268,9 +266,6 @@ struct CircleGridView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // scrollview reader
|
} // scrollview reader
|
||||||
.fullScreenCover(isPresented: $showCall, content: {
|
|
||||||
CallView()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -382,17 +377,12 @@ extension CircleGridView {
|
|||||||
extension CircleGridView {
|
extension CircleGridView {
|
||||||
// listening to messages
|
// listening to messages
|
||||||
private func handleTap(gridItemIndex: Int, friendId: String) {
|
private func handleTap(gridItemIndex: Int, friendId: String) {
|
||||||
// TODO: if there is a message, then listen to it
|
|
||||||
// then after that, check if friend is online, and if so, then connect with him/her if they are free/not in another call
|
|
||||||
// TESTING CALL
|
|
||||||
let testingCall = false
|
|
||||||
if testingCall {
|
|
||||||
self.showCall.toggle()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
print("tap gesture activated")
|
print("tap gesture activated")
|
||||||
|
|
||||||
|
// if friend is online, start call immediately
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// clearing the player to make room for this friend's convo or to deselect this user
|
// clearing the player to make room for this friend's convo or to deselect this user
|
||||||
self.queuePlayer.removeAllItems()
|
self.queuePlayer.removeAllItems()
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ struct InnerCircleView: View {
|
|||||||
// background
|
// background
|
||||||
WavesGlassBackgroundView(isRecording: self.innerCircleVM.isRecording)
|
WavesGlassBackgroundView(isRecording: self.innerCircleVM.isRecording)
|
||||||
|
|
||||||
// stale states
|
// stale state: create profile
|
||||||
if self.authSessionStore.user?.nickname == nil || self.authSessionStore.user?.avatar == nil {
|
if self.authSessionStore.user?.nickname == nil || self.authSessionStore.user?.avatar == nil {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
Image("undraw_fall_is_coming_yl-0-x")
|
Image("undraw_fall_is_coming_yl-0-x")
|
||||||
@@ -55,7 +55,7 @@ struct InnerCircleView: View {
|
|||||||
|
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
} // add friend: stale state
|
||||||
else if self.authSessionStore.friendsArr.count == 0 && self.authSessionStore.inboxUsersArr.count == 0 {
|
else if self.authSessionStore.friendsArr.count == 0 && self.authSessionStore.inboxUsersArr.count == 0 {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
Image("undraw_fall_is_coming_yl-0-x")
|
Image("undraw_fall_is_coming_yl-0-x")
|
||||||
@@ -84,10 +84,18 @@ struct InnerCircleView: View {
|
|||||||
|
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
} else {
|
} else {
|
||||||
// content
|
VStack(alignment: .leading) {
|
||||||
CircleGridView(selectedFriendIndex: self.$selectedFriendIndex)
|
// convos
|
||||||
.environmentObject(innerCircleVM)
|
ConvosView()
|
||||||
|
.padding(.top, 50)
|
||||||
|
|
||||||
|
// inner circle grid
|
||||||
|
CircleGridView(selectedFriendIndex: self.$selectedFriendIndex)
|
||||||
|
.environmentObject(innerCircleVM)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// header
|
// header
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ extension InnerCircleViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// everything related to calls and such
|
||||||
extension InnerCircleViewModel {
|
extension InnerCircleViewModel {
|
||||||
func getAgoraToken() {
|
func getAgoraToken() {
|
||||||
if let uid = AuthSessionStore.getCurrentUserId() {
|
if let uid = AuthSessionStore.getCurrentUserId() {
|
||||||
@@ -149,5 +150,5 @@ extension InnerCircleViewModel {
|
|||||||
else {
|
else {
|
||||||
print("no user authenticated to get an agora token")
|
print("no user authenticated to get an agora token")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user