// // WebinarViewController.swift // Learn Genie // // Created by Suraj Kumar Mandal on 14/04/22. // import UIKit import JitsiMeetSDK import SideMenu class WebinarViewController: UIViewController { @IBOutlet var navigationBar: UINavigationBar! @IBOutlet var meetingTypeSegmentControl: UISegmentedControl! @IBOutlet var meetingTableView: UITableView! var joiningLinkTF: UITextField? let viewModel = WebinarViewModel() var refreshControl: UIRefreshControl! var meetingType = "Upcoming" fileprivate var jitsiMeetView: JitsiMeetView? var userId = Int() var meetingModel = [MeetingModel]() var groupModel = [GroupModel]() var upcomingArray = [MeetingModel]() var elapsedArray = [MeetingModel]() let userData = UserDefaults.standard.dictionary(forKey: Constant.userData) let userModelDB = DBManager.sharedInstance.database.objects(UserDetailsModel.self) var meetingTime = String() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. viewModel.delegate = self meetingTableView.delegate = self meetingTableView.dataSource = self // Tableview pull to refresh refreshControl = UIRefreshControl() refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh") refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged) meetingTableView.addSubview(refreshControl) if let row = userModelDB.firstIndex(where: {$0.email == self.userData?["email"] as? String}) { userId = userModelDB[row].id } } override func viewWillAppear(_ animated: Bool) { navigationBar.topItem?.title = Helper.translateText(inputText: "Webinar") meetingTypeSegmentControl.setTitle(Helper.translateText(inputText: "Upcoming"), forSegmentAt: 0) meetingTypeSegmentControl.setTitle(Helper.translateText(inputText: "Elapsed"), forSegmentAt: 1) viewModel.meetingModel.removeAll() viewModel.groupModel.removeAll() viewModel.generateCookie() } func setupJitsi(isAdmin:Bool) { let defaultOptions = JitsiMeetConferenceOptions.fromBuilder { (builder) in // for JaaS replace url with https://8x8.vc builder.serverURL = URL(string: "https://meet.jit.si") let userInfo = JitsiMeetUserInfo() userInfo.displayName = (self.userData?["name"] as! String) //userInfo.email = self.userData?["email"] as! String builder.userInfo = userInfo // for JaaS use the obtained Jitsi JWT // builder.token = "SampleJWT" if isAdmin == true { // Set different feature flags builder.setFeatureFlag("add-people.enabled", withBoolean: true) builder.setFeatureFlag("invite.enabled", withBoolean: true) builder.setFeatureFlag("kick-out.enabled", withBoolean: true) builder.setFeatureFlag("live-streaming.enabled", withBoolean: true) builder.setFeatureFlag("server-url-change.enabled", withBoolean: true) builder.setFeatureFlag("video-share.enabled", withBoolean: true) builder.setFeatureFlag("ios.screensharing.enabled", withBoolean: true) builder.setFeatureFlag("recording.enabled", withBoolean: true) builder.setFeatureFlag("security-options.enabled", withBoolean: true) builder.setFeatureFlag("meeting-name.enabled", withBoolean: true) builder.setConfigOverride("disablePolls", withBoolean: false) builder.setConfigOverride("disableRemoteMute", withBoolean: false) } else { builder.setFeatureFlag("add-people.enabled", withBoolean: false) builder.setFeatureFlag("invite.enabled", withBoolean: false) builder.setFeatureFlag("kick-out.enabled", withBoolean: false) builder.setFeatureFlag("live-streaming.enabled", withBoolean: false) builder.setFeatureFlag("server-url-change.enabled", withBoolean: false) builder.setFeatureFlag("video-share.enabled", withBoolean: false) builder.setFeatureFlag("ios.screensharing.enabled", withBoolean: false) builder.setFeatureFlag("recording.enabled", withBoolean: false) builder.setFeatureFlag("security-options.enabled", withBoolean: false) builder.setFeatureFlag("meeting-name.enabled", withBoolean: true) builder.setConfigOverride("disablePolls", withBoolean: true) builder.setConfigOverride("disableRemoteMute", withBoolean: true) } // builder.setFeatureFlag("welcomepage.enabled", withValue: false) // builder.setFeatureFlag("video-share.enabled", withBoolean: false) // builder.setFeatureFlag("resolution", withBoolean: true) // builder.setFeatureFlag("ios.recording.enabled", withBoolean: true) // builder.setFeatureFlag("audio-mute.enabled", withBoolean: true) // builder.setFeatureFlag("chat.enabled", withBoolean: true) // builder.setFeatureFlag("video-mute.enabled", withBoolean: true) // builder.setFeatureFlag("android.audio-focus.disabled", withBoolean: false) // builder.setFeatureFlag("calendar.enabled", withBoolean: true) // builder.setFeatureFlag("call-integration.enabled", withBoolean: true) // builder.setFeatureFlag("close-captions.enabled", withBoolean: true) // builder.setFeatureFlag("conference-timer.enabled", withBoolean: true) // builder.setFeatureFlag("filmstrip.enabled", withBoolean: true) // builder.setFeatureFlag("notifications.enabled", withBoolean: false) // builder.setFeatureFlag("overflow-menu.enabled", withBoolean: false) // builder.setFeatureFlag("pip.enabled", withBoolean: false) // builder.setFeatureFlag("raise-hand.enabled", withBoolean: false) // builder.setFeatureFlag("tile-view.enabled", withBoolean: true) // builder.setFeatureFlag("toolbox.alwaysVisible", withBoolean: true) // builder.setFeatureFlag("toolbox.enabled", withBoolean: true) } JitsiMeet.sharedInstance().defaultConferenceOptions = defaultOptions } func configurationTextField(textField: UITextField!) { if (textField) != nil { self.joiningLinkTF = textField! //Save reference to the UITextField self.joiningLinkTF?.placeholder = "Type joining link here..."; } } @objc func refresh(_ sender: Any) { // your code to reload tableView viewModel.meetingModel.removeAll() viewModel.groupModel.removeAll() viewModel.generateCookie() } func getCurrentDate() -> String { let date = Date() let df = DateFormatter() df.timeZone = TimeZone(identifier: "UTC") df.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" let dateString = df.string(from: date) print(dateString) return dateString } func openJitsi(roomName:String, subject:String) { let room: String = roomName if(room.count < 1) { return } // create and configure jitsimeet view let jitsiMeetView = JitsiMeetView() jitsiMeetView.delegate = self self.jitsiMeetView = jitsiMeetView let options = JitsiMeetConferenceOptions.fromBuilder { (builder) in // for JaaS use / format builder.room = room builder.setSubject(subject) // Settings for audio and video // builder.audioMuted = true; // builder.videoMuted = true; } // setup view controller let vc = UIViewController() vc.modalPresentationStyle = .fullScreen vc.view = jitsiMeetView // join room and display jitsi-call jitsiMeetView.join(options) present(vc, animated: true, completion: nil) } fileprivate func cleanUp() { if(jitsiMeetView != nil) { dismiss(animated: true, completion: nil) jitsiMeetView = nil } } func getMeetingLinks() { self.upcomingArray.removeAll() self.elapsedArray.removeAll() for group in groupModel { let id = group.id for data in group.student { if data.studentId == userId { for meeting in meetingModel { let groupId = meeting.groupId if id == groupId { print(meeting.meetingSubject!) let interval = meeting.duration! * 60 let date1 = meeting.meetingDateTime!.toDate()!.addingTimeInterval(TimeInterval(interval)) let date2 = getCurrentDate().toDate()! if date1.isGreaterThanEqual(date2) { let id = meeting.id let userId = meeting.userId let groupId = meeting.groupId let duration = meeting.duration let meetingDateTime = meeting.meetingDateTime! let sessionID = meeting.sessionID let meetingSubject = meeting.meetingSubject let adminId = meeting.adminId let data = MeetingModel(id: id ?? 0, userId: userId ?? 0, groupId: groupId ?? 0, adminId: adminId ?? 0, duration: duration ?? 0, meetingDateTime: meetingDateTime , sessionID: sessionID ?? "", meetingSubject: meetingSubject ?? "") self.upcomingArray.append(data) } else { let id = meeting.id let userId = meeting.userId let groupId = meeting.groupId let duration = meeting.duration let meetingDateTime = meeting.meetingDateTime let sessionID = meeting.sessionID let meetingSubject = meeting.meetingSubject let adminId = meeting.adminId let data = MeetingModel(id: id ?? 0, userId: userId ?? 0, groupId: groupId ?? 0, adminId: adminId ?? 0, duration: duration ?? 0, meetingDateTime: meetingDateTime ?? "", sessionID: sessionID ?? "", meetingSubject: meetingSubject ?? "") self.elapsedArray.append(data) } } } } } } print("array data: \(upcomingArray.count), \(elapsedArray.count)") meetingTableView.reloadData() } func timeString(time: TimeInterval) -> String { //let hour = Int(time) / 3600 let minute = Int(time) / 60 % 60 let second = Int(time) % 60 // return formated string return String(format: "%02i mins:%02i sec", minute, second) } /* // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Get the new view controller using segue.destination. // Pass the selected object to the new view controller. } */ @IBAction func menuNavAction(_ sender: Any) { let menu = storyboard!.instantiateViewController(withIdentifier: "SideMenuNavigationController") as! SideMenuNavigationController present(menu, animated: true, completion: nil) } @IBAction func segmentedAction(_ sender: Any) { switch meetingTypeSegmentControl.selectedSegmentIndex { case 0: meetingType = "Upcoming" meetingTableView.reloadData() case 1: meetingType = "Elapsed" meetingTableView.reloadData() default: break } } } extension WebinarViewController: WebinarViewProtocol { func startLoader() { ActivityIndicator.start() } func stopLoader() { ActivityIndicator.stop() } func gotGroupList(groupModel: [GroupModel]) { self.groupModel.removeAll() self.groupModel = groupModel print("Group count: \(self.groupModel.count)") if Reachability.isConnectedToNetwork() { viewModel.getMeetingLists(offset: 0) } else { Alert.showInternetFailureAlert(on: self) } } func gotMeetingList(meetingModel: [MeetingModel]) { self.meetingModel.removeAll() self.meetingModel = meetingModel getMeetingLinks() refreshControl.endRefreshing() } } extension WebinarViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if meetingType == "Upcoming" { return upcomingArray.count } else { return elapsedArray.count } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "WebinarTableViewCell", for: indexPath) as? WebinarTableViewCell else { return UITableViewCell() } if meetingType == "Upcoming" { let dateTime = upcomingArray[indexPath.row].meetingDateTime let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" dateFormatter.locale = Locale.current dateFormatter.timeZone = TimeZone.current let date = dateFormatter.date(from:dateTime!) dateFormatter.dateFormat = "dd/MM/yyyy" let finalDate = dateFormatter.string(from: date!) dateFormatter.dateFormat = "h:mm a" let finalTime = dateFormatter.string(from: date!) cell.layer.cornerRadius = 10 cell.meetingNameLabel.text = upcomingArray[indexPath.row].meetingSubject cell.dateLabel.text = "Date: \(finalDate)" cell.timeLabel.text = "Time: \(finalTime)" meetingTime = finalTime } else { let dateTime = elapsedArray.reversed()[indexPath.row].meetingDateTime let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" dateFormatter.locale = Locale.current dateFormatter.timeZone = TimeZone.current let date = dateFormatter.date(from:dateTime!) dateFormatter.dateFormat = "dd/MM/yyyy" let finalDate = dateFormatter.string(from: date!) dateFormatter.dateFormat = "h:mm a" let finalTime = dateFormatter.string(from: date!) cell.layer.cornerRadius = 10 cell.meetingNameLabel.text = elapsedArray.reversed()[indexPath.row].meetingSubject cell.dateLabel.text = "Date: \(finalDate)" cell.timeLabel.text = "Time: \(finalTime)" } return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if meetingType == "Upcoming" { let interval = -10 * 60 let date1 = upcomingArray[indexPath.row].meetingDateTime!.toDate()!.addingTimeInterval(TimeInterval(interval)) let date2 = getCurrentDate().toDate()! if date1.isLessThanEqual(date2) { let room = "\(upcomingArray[indexPath.row].meetingSubject ?? "") - \(upcomingArray[indexPath.row].sessionID ?? "")" let meetingName = upcomingArray[indexPath.row].meetingSubject if Reachability.isConnectedToNetwork() { if userId == upcomingArray[indexPath.row].adminId { // Setup Jitsi setupJitsi(isAdmin: true) openJitsi(roomName: room, subject: meetingName ?? "") } else { // Setup Jitsi setupJitsi(isAdmin: false) openJitsi(roomName: room, subject: meetingName ?? "") } } else { Alert.showInternetFailureAlert(on: self) } } else { let waitTime = upcomingArray[indexPath.row].meetingDateTime?.toDate()?.timeIntervalSinceNow Alert.showAlert(on: self, with: "Meeting is at \(meetingTime)", message: "Meeting will start in \(timeString(time: TimeInterval(waitTime!))), Please join the meeting 10 min prior to meeting time.") } } else { self.view.makeToast("Meeting link expired!") tableView.deselectRow(at: indexPath, animated: true) } } } extension WebinarViewController: JitsiMeetViewDelegate { func ready(toClose data: [AnyHashable : Any]!) { cleanUp() } func participantJoined(_ data: [AnyHashable : Any]!) { print("Joined Participant: \(data)") } func participantLeft(_ data: [AnyHashable : Any]!) { print("Left Participant: \(data)") } }