diff --git a/swift/ChatRoomTutorial/ChatRoomTutorial/ChatRoomExample.swift b/swift/ChatRoomTutorial/ChatRoomTutorial/ChatRoomExample.swift index 7cc0d20..1fb8e31 100644 --- a/swift/ChatRoomTutorial/ChatRoomTutorial/ChatRoomExample.swift +++ b/swift/ChatRoomTutorial/ChatRoomTutorial/ChatRoomExample.swift @@ -15,8 +15,13 @@ enum ChatroomExampleState } -class ChatRoomExampleContext : ObservableObject -{ +struct DisplayableUser : Identifiable { + var id = UUID() + var name : String + +} + +class ChatRoomExampleContext : ObservableObject { var mCore: Core! // We need a Core for... anything, basically @Published var coreVersion: String = Core.getVersion @@ -25,9 +30,9 @@ class ChatRoomExampleContext : ObservableObject /*-------- Chatroom tutorial related variables ---------------*/ - @Published var dest : String = "sip:chatdest@sip.linphone.org" - @Published var id : String = "sip:thisphone@sip.linphone.org" - @Published var passwd : String = "thispassword" + @Published var dest : String = "sip:arguillq@sip.linphone.org" + @Published var id : String = "sip:quentindev@sip.linphone.org" + @Published var passwd : String = "dev" @Published var loggedIn: Bool = false let mFactoryUri = "sip:conference-factory@sip.linphone.org" @@ -42,14 +47,18 @@ class ChatRoomExampleContext : ObservableObject @Published var encryptionEnabled : Bool = false @Published var groupChatEnabled : Bool = true @Published var chatroomState = ChatroomExampleState.Unstarted - @Published var textToSend: String = "msg to send" + @Published var textToSend: String = "Hello" @Published var sReceivedMessages : String = "" @Published var isDownloading : Bool = false + + @Published var displayableUsers = [DisplayableUser]() + + @Published var newUser : String = "sip:newuser@sip.linphone.org" var fileFolderUrl : URL? var fileUrl : URL? - init() - { + init() { + mChatRoomDelegate.tutorialContext = self mLinphoneCoreDelegate.tutorialContext = self mChatMessageDelegate.tutorialContext = self @@ -79,8 +88,7 @@ class ChatRoomExampleContext : ObservableObject } - func createProxyConfigAndRegister() - { + func createProxyConfigAndRegister() { do { mProxyConfig = try createAndInitializeProxyConfig(core : mCore, identity: id, password: passwd) mProxyConfig.conferenceFactoryUri = mFactoryUri @@ -94,8 +102,7 @@ class ChatRoomExampleContext : ObservableObject } } - func createChatRoom() - { + func createChatRoom() { // proxy configuration must first be initialized and registered if (!loggedIn || mChatRoom != nil) { return } @@ -113,6 +120,7 @@ class ChatRoomExampleContext : ObservableObject mChatRoom = try mCore.createChatRoom(params: chatParams, localAddr: mProxyConfig.contact!, participants: chatDest) // Flexisip chatroom requires a setup time. The delegate will set the state to started when it is ready. chatroomState = ChatroomExampleState.Starting + //displayableUsers.list.append(DisplayableUser(participant: mChatRoom!.participants[0])) } else { chatParams.backend = ChatRoomBackend.Basic @@ -147,10 +155,10 @@ class ChatRoomExampleContext : ObservableObject mChatRoom = nil; } chatroomState = ChatroomExampleState.Unstarted + displayableUsers = [] } - func send(room : ChatRoom, msg : String) - { + func send(room : ChatRoom, msg : String) { do { self.mChatMessage = try room.createMessageFromUtf8(message: msg) @@ -161,15 +169,13 @@ class ChatRoomExampleContext : ObservableObject } } - func sendMsg() - { + func sendMsg() { if let chatRoom = mChatRoom { send(room: chatRoom, msg: textToSend) } } - func sendExampleFile() - { + func sendExampleFile() { do { let content = try mCore.createContent() content.filePath = fileUrl!.path @@ -200,7 +206,37 @@ class ChatRoomExampleContext : ObservableObject } } } - mLastFileMessageReceived = nil + } + + func addParticipant() { + if let chatroom = mChatRoom { + do { + chatroom.addParticipant(addr: try Factory.Instance.createAddress(addr: newUser)) + displayableUsers.append(DisplayableUser(name: newUser)) + } catch let error as NSError { + print("Unable to create directory",error) + } + } + } + + func removeParticipant(user : DisplayableUser) { + + if let userAddr = try? Factory.Instance.createAddress(addr: user.name) { + for part in mChatRoom!.participants { + if (part.address!.equal(address2: userAddr)) + { + mChatRoom!.removeParticipant(participant: part) + } + } + } + + for i in 0...displayableUsers.count { + if (displayableUsers[i].id == user.id) { + displayableUsers.remove(at: i) + break + } + } + } } @@ -241,6 +277,10 @@ class LinphoneChatRoomStateTracker: ChatRoomDelegate { func onConferenceJoined(chatRoom: ChatRoom, eventLog: EventLog) { print("ChatRoomTrace - Chatroom ready to start") + tutorialContext.displayableUsers = [] + for part in chatRoom.participants { + tutorialContext.displayableUsers.append(DisplayableUser(name: part.address!.asString())) + } tutorialContext.chatroomState = ChatroomExampleState.Started } } diff --git a/swift/ChatRoomTutorial/ChatRoomTutorial/ContentView.swift b/swift/ChatRoomTutorial/ChatRoomTutorial/ContentView.swift index b478281..a618cf9 100644 --- a/swift/ChatRoomTutorial/ChatRoomTutorial/ContentView.swift +++ b/swift/ChatRoomTutorial/ChatRoomTutorial/ContentView.swift @@ -31,142 +31,184 @@ struct ActivityIndicator: UIViewRepresentable { } struct ContentView: View { - + @ObservedObject var tutorialContext : ChatRoomExampleContext var body: some View { - - VStack(alignment: .leading) { - Group { - HStack { - Text("Identity :") - .font(.subheadline) - TextField("", text : $tutorialContext.id) - .textFieldStyle(RoundedBorderTextFieldStyle()) + NavigationView { + VStack(alignment: .leading) { + Group { + HStack { + Text("Identity :") + .font(.subheadline) + TextField("", text : $tutorialContext.id) + .textFieldStyle(RoundedBorderTextFieldStyle()) + } + HStack { + Text("Password :") + .font(.subheadline) + TextField("", text : $tutorialContext.passwd) + .textFieldStyle(RoundedBorderTextFieldStyle()) + } + HStack { + Button(action: tutorialContext.createProxyConfigAndRegister) + { + Text("Login") + .font(.largeTitle) + .foregroundColor(Color.white) + .frame(width: 90.0, height: 42.0) + .background(Color.gray) + }.disabled(tutorialContext.loggedIn) + Text("Login State : ") + .font(.footnote) + Text(tutorialContext.loggedIn ? "Logged in" : "Unregistered") + .font(.footnote) + .foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black) + } } HStack { - Text("Password :") - .font(.subheadline) - TextField("", text : $tutorialContext.passwd) + Text("Chat destination :") + TextField("", text : $tutorialContext.dest) .textFieldStyle(RoundedBorderTextFieldStyle()) - } + }.disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted) + .padding(.top, 5) HStack { - Button(action: tutorialContext.createProxyConfigAndRegister) + VStack { + Toggle(isOn: $tutorialContext.groupChatEnabled) { + Text("Group ChatRoom") + }.frame(width: 210) + .padding(.top) + .disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted) + Toggle(isOn: $tutorialContext.encryptionEnabled) { + VStack { + Text("Lime Encryption") + Text("(group chat only)").italic().font(.footnote) + } + }.frame(width: 210) + .disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted) + HStack { + Text("Chatroom state: ") + .font(.footnote) + Text(getStateAsString(chatroomState: tutorialContext.chatroomState)) + .font(.footnote) + .foregroundColor((tutorialContext.chatroomState == ChatroomExampleState.Started) ? Color.green : Color .black) + if (tutorialContext.chatroomState == ChatroomExampleState.Starting) { + ActivityIndicator() + } + } + } + Button(action: { + if (self.tutorialContext.chatroomState == ChatroomExampleState.Started) { + self.tutorialContext.reset() + } else { + self.tutorialContext.createChatRoom() + } + }) { - Text("Login") - .font(.largeTitle) - .foregroundColor(Color.white) - .frame(width: 90.0, height: 42.0) - .background(Color.gray) - }.disabled(tutorialContext.loggedIn) - Text("Login State : ") - .font(.footnote) - Text(tutorialContext.loggedIn ? "Logged in" : "Unregistered") - .font(.footnote) - .foregroundColor(tutorialContext.loggedIn ? Color.green : Color.black) - } - } - HStack { - Text("Chat destination :") - TextField("", text : $tutorialContext.dest) - .textFieldStyle(RoundedBorderTextFieldStyle()) - }.disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted) - .padding(.top, 5) - HStack { - VStack { - Toggle(isOn: $tutorialContext.groupChatEnabled) { - Text("Group ChatRoom") - }.frame(width: 210) - .padding(.top) - .disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted) - Toggle(isOn: $tutorialContext.encryptionEnabled) { - VStack { - Text("Lime Encryption") - Text("(group chat only)").italic().font(.footnote) - } - }.frame(width: 210) - .disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted) - HStack { - Text("Chatroom state: ") - .font(.footnote) - Text(getStateAsString(chatroomState: tutorialContext.chatroomState)) - .font(.footnote) - .foregroundColor((tutorialContext.chatroomState == ChatroomExampleState.Started) ? Color.green : Color .black) - if (tutorialContext.chatroomState == ChatroomExampleState.Starting) { - ActivityIndicator() - } + Text((tutorialContext.chatroomState == ChatroomExampleState.Started) ? "Reset" : "Start\nChat") + .font(.largeTitle) + .foregroundColor(Color.white) + .frame(width: 140.0, height: 100.0) + .background(Color.gray) + .padding() } } - Button(action: { - if (self.tutorialContext.chatroomState == ChatroomExampleState.Started) { - self.tutorialContext.reset() - } else { - self.tutorialContext.createChatRoom() - } - }) + Spacer() + if (tutorialContext.chatroomState == ChatroomExampleState.Started) { - Text((tutorialContext.chatroomState == ChatroomExampleState.Started) ? "Reset" : "Start\nChat") - .font(.largeTitle) - .foregroundColor(Color.white) - .frame(width: 140.0, height: 100.0) - .background(Color.gray) - .padding() - } - } - HStack { - VStack { - Text("Chat received").bold() - ScrollView { - Text(tutorialContext.sReceivedMessages) - .font(.footnote) - .frame(width : 160) - }.border(Color.gray) - HStack { - TextField("Sent text", text : $tutorialContext.textToSend) - .textFieldStyle(RoundedBorderTextFieldStyle()) - Button(action: tutorialContext.sendMsg) - { - Text("Send") - .font(.callout) - .foregroundColor(Color.white) - .frame(width: 50.0, height: 30.0) - .background(Color.gray) - }.disabled(tutorialContext.chatroomState != ChatroomExampleState.Started) - } - HStack { - Button(action: tutorialContext.sendExampleFile) - { - Text("Send example \n file") - .foregroundColor(Color.white) - .multilineTextAlignment(.center) - .frame(width: 120.0, height: 50.0) - .background(Color.gray) - }.disabled(tutorialContext.chatroomState != ChatroomExampleState.Started) - Button(action: tutorialContext.downloadLastFileMessage) - { - Text("Download last files \n received") - .foregroundColor(Color.white) - .multilineTextAlignment(.center) - .frame(width: 150.0, height: 50.0) - .background(Color.gray) - }.disabled(tutorialContext.mLastFileMessageReceived == nil) - if (tutorialContext.isDownloading) { - ActivityIndicator() + NavigationLink(destination: Group{ + VStack { + if (tutorialContext.mChatRoom!.canHandleParticipants()) { + Text("Chat participants").bold() + ScrollView { + ForEach(tutorialContext.displayableUsers) { user in + HStack { + Text(user.name) + Spacer() + Button(action: { tutorialContext.removeParticipant(user: user) }) + { + Text("Remove") + .font(.callout) + .foregroundColor(Color.white) + .frame(width: 70.0, height: 35.0) + .background(Color.gray) + } + }.padding(.horizontal).border(Color.gray) + }.frame(height: 200) + }.border(Color.gray) + HStack { + TextField("Add participant", text : $tutorialContext.newUser) + .textFieldStyle(RoundedBorderTextFieldStyle()) + Button(action: tutorialContext.addParticipant) + { + Text("Add") + .font(.callout) + .foregroundColor(Color.white) + .frame(width: 50.0, height: 30.0) + .background(Color.gray) + } + }.padding() + } + Text("Chat received").bold() + ScrollView { + Text(tutorialContext.sReceivedMessages) + .font(.footnote) + .frame(width: 330, height: 400) + }.border(Color.gray) + HStack { + TextField("Sent text", text : $tutorialContext.textToSend) + .textFieldStyle(RoundedBorderTextFieldStyle()) + Button(action: tutorialContext.sendMsg) + { + Text("Send") + .font(.callout) + .foregroundColor(Color.white) + .frame(width: 50.0, height: 30.0) + .background(Color.gray) + }.disabled(tutorialContext.chatroomState != ChatroomExampleState.Started) + } + HStack { + Button(action: tutorialContext.sendExampleFile) + { + Text("Send example \n file") + .foregroundColor(Color.white) + .multilineTextAlignment(.center) + .frame(width: 120.0, height: 50.0) + .background(Color.gray) + }.disabled(tutorialContext.chatroomState != ChatroomExampleState.Started) + Button(action: tutorialContext.downloadLastFileMessage) + { + Text("Download last files \n received") + .foregroundColor(Color.white) + .multilineTextAlignment(.center) + .frame(width: 150.0, height: 50.0) + .background(Color.gray) + }.disabled(tutorialContext.mLastFileMessageReceived == nil) + if (tutorialContext.isDownloading) { + ActivityIndicator() + } + } + } + }) + { + HStack() { + Spacer() + Text("Go to chat view").multilineTextAlignment(.center).frame(width: 200, height: 100).foregroundColor(Color.white).background(Color.gray) + Spacer() } } + Group { + Spacer() + Toggle(isOn: $tutorialContext.loggingUnit.logsEnabled.value) { + Text("Logs collection") + .font(.body) + .multilineTextAlignment(.trailing) + } + Text("Core Version is \(tutorialContext.coreVersion)") + } } - Spacer() - }.padding(.top) - Group { - Spacer() - Toggle(isOn: $tutorialContext.loggingUnit.logsEnabled.value) { - Text("Logs collection") - .font(.body) - .multilineTextAlignment(.trailing) - } - Text("Core Version is \(tutorialContext.coreVersion)") - } - }.padding() + }.padding() + } } }