// // ChatConversationInfoView.m // linphone // // Created by REIS Benjamin on 23/10/2017. // #import #import "ChatConversationInfoView.h" #import "PhoneMainView.h" #import "UIChatConversationInfoTableViewCell.h" #import "linphone/core.h" @implementation ChatConversationInfoView #pragma mark - UICompositeViewDelegate Functions static UICompositeViewDescription *compositeDescription = nil; + (UICompositeViewDescription *)compositeViewDescription { if (compositeDescription == nil) { compositeDescription = [[UICompositeViewDescription alloc] init:self.class statusBar:StatusBarView.class tabBar:TabBarView.class sideMenu:SideMenuView.class fullscreen:false isLeftFragment:NO fragmentWith:ChatsListView.class]; } return compositeDescription; } - (UICompositeViewDescription *)compositeViewDescription { return self.class.compositeViewDescription; } - (void)viewDidLoad { [super viewDidLoad]; // if we use fragments, remove back button if (IPAD) { _backButton.hidden = YES; } UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboards)]; tap.delegate = self; [self.view addGestureRecognizer:tap]; _nameLabel.delegate = self; _tableView.dataSource = self; _tableView.delegate = self; _admins = [[NSMutableArray alloc] init]; _oldAdmins = [[NSMutableArray alloc] init]; _oldContacts = [[NSMutableArray alloc] init]; _room = NULL; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; _waitView.hidden = YES; _nameLabel.text = _room && linphone_chat_room_get_subject(_room) ? [NSString stringWithUTF8String:linphone_chat_room_get_subject(_room)] : @""; _nextButton.enabled = _nameLabel.text.length > 0 && _contacts.count > 0; LinphoneParticipant *me = _room && (linphone_chat_room_get_state(_room) == LinphoneChatRoomStateCreated) ? linphone_chat_room_get_me(_room) : NULL; _imAdmin = me ? linphone_participant_is_admin(me) : false; _quitButton.hidden = _create || (me == NULL); _nameLabel.enabled = _create || _imAdmin; _addButton.hidden = !_create && !_imAdmin; _nextButton.hidden = !_create && !_imAdmin; CGFloat height = _quitButton.hidden ? self.view.frame.size.height - _tableView.frame.origin.y : _quitButton.frame.origin.y - _tableView.frame.origin.y - 10; [_tableView setFrame:CGRectMake( _tableView.frame.origin.x, _tableView.frame.origin.y, _tableView.frame.size.width, height )]; if (_room) { LinphoneChatRoomCbs *cbs = linphone_chat_room_get_callbacks(_room); linphone_chat_room_cbs_set_state_changed(cbs, chat_room_state_changed); linphone_chat_room_cbs_set_subject_changed(cbs, chat_room_subject_changed); linphone_chat_room_cbs_set_participant_added(cbs, chat_room_participant_added); linphone_chat_room_cbs_set_participant_removed(cbs, chat_room_participant_removed); linphone_chat_room_cbs_set_participant_admin_status_changed(cbs, chat_room_participant_admin_status_changed); linphone_chat_room_cbs_set_user_data(cbs, (__bridge void*)self); } [_tableView reloadData]; } #pragma mark - next functions - (void)onCreate { _waitView.hidden = NO; LinphoneChatRoom *room = linphone_core_create_client_group_chat_room(LC, _nameLabel.text.UTF8String); if(!room) { return; } LinphoneChatRoomCbs *cbs = linphone_chat_room_get_callbacks(room); linphone_chat_room_cbs_set_state_changed(cbs, chat_room_state_changed); linphone_chat_room_cbs_set_user_data(cbs, (__bridge void*)self); bctbx_list_t *addresses = NULL; for(NSString *addr in _contacts) { LinphoneAddress *linphoneAddress = linphone_address_new(addr.UTF8String); if (!linphoneAddress) continue; if (!addresses) { addresses = bctbx_list_new((void *)linphoneAddress); continue; } addresses = bctbx_list_append(addresses, (void *)linphoneAddress); } linphone_chat_room_add_participants(room, addresses); bctbx_list_free_with_data(addresses, (void (*)(void *))linphone_address_unref); } - (void)onValidate { ChatConversationView *view = VIEW(ChatConversationView); // Change subject if necessary if (![_oldSubject isEqualToString:_nameLabel.text]) linphone_chat_room_set_subject(_room, _nameLabel.text.UTF8String); // Add participants if necessary bctbx_list_t *addedPartipants = NULL; for (NSString *uri in _contacts) { if ([_oldContacts containsObject:uri]) continue; LinphoneAddress *addr = linphone_address_new(uri.UTF8String); if (addedPartipants) addedPartipants = bctbx_list_append(addedPartipants, addr); else addedPartipants = bctbx_list_new(addr); } if (addedPartipants) { linphone_chat_room_add_participants(_room, addedPartipants); bctbx_list_free_with_data(addedPartipants, (void (*)(void *))linphone_address_unref); } // Remove participants if necessary bctbx_list_t *removedPartipants = NULL; for (NSString *uri in _oldContacts) { if ([_contacts containsObject:uri]) continue; LinphoneAddress *addr = linphone_address_new(uri.UTF8String); LinphoneParticipant *participant = linphone_participant_ref(linphone_chat_room_find_participant(_room, addr)); if (!participant) continue; if (removedPartipants) removedPartipants = bctbx_list_append(removedPartipants, participant); else removedPartipants = bctbx_list_new(participant); linphone_address_unref(addr); } if (removedPartipants) { linphone_chat_room_remove_participants(_room, removedPartipants); bctbx_list_free_with_data(removedPartipants, (void (*)(void *))linphone_participant_unref); } // add admins if necessary for (NSString *admin in _admins) { if ([_oldAdmins containsObject:admin]) continue; LinphoneAddress *addr = linphone_address_new(admin.UTF8String); LinphoneParticipant *participant = linphone_chat_room_find_participant(_room, addr); if (!participant) continue; linphone_chat_room_set_participant_admin_status(_room, participant, true); linphone_address_unref(addr); } // remove admins if necessary for (NSString *admin in _oldAdmins) { if ([_admins containsObject:admin]) continue; LinphoneAddress *addr = linphone_address_new(admin.UTF8String); LinphoneParticipant *participant = linphone_chat_room_find_participant(_room, addr); if (!participant) continue; linphone_chat_room_set_participant_admin_status(_room, participant, false); linphone_address_unref(addr); } [PhoneMainView.instance changeCurrentView:view.compositeViewDescription]; } #pragma mark - Buttons responders - (IBAction)onNextClick:(id)sender { if(_create) [self onCreate]; else [self onValidate]; } - (IBAction)onBackClick:(id)sender { if(_create) { ChatConversationCreateView *view = VIEW(ChatConversationCreateView); view.tableController.contactsGroup = [_contacts mutableCopy]; view.tableController.notFirstTime = TRUE; view.isForEditing = FALSE; [PhoneMainView.instance popToView:view.compositeViewDescription]; } else { ChatConversationView *view = VIEW(ChatConversationView); [PhoneMainView.instance popToView:view.compositeViewDescription]; } } - (IBAction)onQuitClick:(id)sender { linphone_chat_room_leave(_room); } - (IBAction)onAddClick:(id)sender { ChatConversationCreateView *view = VIEW(ChatConversationCreateView); view.tableController.notFirstTime = TRUE; view.isForEditing = !_create; view.tableController.contactsGroup = [_contacts mutableCopy]; [PhoneMainView.instance popToView:view.compositeViewDescription]; } #pragma mark - TableView - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _contacts.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *kCellId = NSStringFromClass(UIChatConversationInfoTableViewCell.class); UIChatConversationInfoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId]; if (cell == nil) { cell = [[UIChatConversationInfoTableViewCell alloc] initWithIdentifier:kCellId]; } cell.uri = _contacts[indexPath.row]; LinphoneAddress *addr = linphone_address_new(cell.uri.UTF8String); cell.nameLabel.text = [FastAddressBook displayNameForAddress:addr]; [cell.avatarImage setImage:[FastAddressBook imageForAddress:addr] bordered:YES withRoundedRadius:YES]; cell.controllerView = self; if(![_admins containsObject:cell.uri]) { cell.adminLabel.enabled = FALSE; cell.adminImage.image = [UIImage imageNamed:@"check_unselected.png"]; } cell.adminButton.hidden = _create || (!_imAdmin && !cell.adminLabel.enabled); cell.adminButton.userInteractionEnabled = _imAdmin; cell.removeButton.hidden = !_create && !_imAdmin; linphone_address_unref(addr); return cell; } #pragma mark - searchBar delegate - (void)dismissKeyboards { if ([_nameLabel isFirstResponder]) { [_nameLabel resignFirstResponder]; } } #pragma mark - UITextFieldDelegate - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { _nextButton.enabled = (!((string.length == 0 || string == nil || [string isEqual:@""]) && (textField.text.length == 1)) && _contacts.count > 0); return TRUE; } #pragma mark - chat room callbacks - (void)goToChatRoom:(LinphoneChatRoom *)cr { _waitView.hidden = YES; ChatConversationView *view = VIEW(ChatConversationView); view.chatRoom = cr; [PhoneMainView.instance changeCurrentView:view.compositeViewDescription]; } - (void)myAdminStatusChanged:(BOOL)admin { NSString *message = admin ? NSLocalizedString(@"You are now an admin of the chat room", nil) : NSLocalizedString(@"You are no longer an admin of the chat room", nil); static UIAlertController *alertView; // avoid having multiple popups [PhoneMainView.instance dismissViewControllerAnimated:YES completion:nil]; alertView = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"%@", message] message:nil preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {}]; [alertView addAction:defaultAction]; [PhoneMainView.instance presentViewController:alertView animated:YES completion:nil]; } void chat_room_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState) { ChatConversationInfoView *view = (__bridge ChatConversationInfoView *)linphone_chat_room_cbs_get_user_data(linphone_chat_room_get_callbacks(cr)); switch (newState) { case LinphoneChatRoomStateCreated: LOGI(@"Chat room [%p] created on server.", cr); [view goToChatRoom:cr]; break; case LinphoneChatRoomStateCreationFailed: view.waitView.hidden = YES; LOGE(@"Chat room [%p] could not be created on server.", cr); break; case LinphoneChatRoomStateTerminated: LOGI(@"Chat room [%p] has been terminated.", cr); [view goToChatRoom:cr]; break; default: break; } } void chat_room_subject_changed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { ChatConversationInfoView *view = (__bridge ChatConversationInfoView *)linphone_chat_room_cbs_get_user_data(linphone_chat_room_get_callbacks(cr)); view.nameLabel.text = [NSString stringWithUTF8String:linphone_event_log_get_subject(event_log)]; } void chat_room_participant_added(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { ChatConversationInfoView *view = (__bridge ChatConversationInfoView *)linphone_chat_room_cbs_get_user_data(linphone_chat_room_get_callbacks(cr)); NSString *participantAddress = [NSString stringWithUTF8String:linphone_address_as_string(linphone_event_log_get_participant_address(event_log))]; [view.oldContacts addObject:participantAddress]; [view.contacts addObject:participantAddress]; [view.tableView reloadData]; } void chat_room_participant_removed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { ChatConversationInfoView *view = (__bridge ChatConversationInfoView *)linphone_chat_room_cbs_get_user_data(linphone_chat_room_get_callbacks(cr)); NSString *participantAddress = [NSString stringWithUTF8String:linphone_address_as_string(linphone_event_log_get_participant_address(event_log))]; [view.oldContacts removeObject:participantAddress]; [view.contacts removeObject:participantAddress]; [view.tableView reloadData]; } void chat_room_participant_admin_status_changed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { ChatConversationInfoView *view = (__bridge ChatConversationInfoView *)linphone_chat_room_cbs_get_user_data(linphone_chat_room_get_callbacks(cr)); NSString *participantAddress = [NSString stringWithUTF8String:linphone_address_as_string(linphone_event_log_get_participant_address(event_log))]; LinphoneParticipant *me = linphone_chat_room_get_me(cr); if (me && linphone_address_equal(linphone_participant_get_address(me), linphone_event_log_get_participant_address(event_log))) { [view myAdminStatusChanged:(linphone_event_log_get_type(event_log) == LinphoneEventLogTypeConferenceParticipantSetAdmin)]; [view viewWillAppear:TRUE]; return; } if (linphone_event_log_get_type(event_log) == LinphoneEventLogTypeConferenceParticipantSetAdmin) { [view.admins addObject:participantAddress]; [view.oldAdmins addObject:participantAddress]; } else { // linphone_event_log_get_type(event_log) == LinphoneEventLogTypeConferenceParticipantUnsetAdmin [view.admins removeObject:participantAddress]; [view.oldAdmins removeObject:participantAddress]; } [view.tableView reloadData]; } @end