#import "TGGroupInfoController.h" #import "TGStringUtils.h" #import "TGBridgeContext.h" #import "TGBridgeConversationSignals.h" #import "TGBridgePeerSettingsSignals.h" #import "TGBridgeChat.h" #import "TGBridgeUser.h" #import "WKInterfaceTable+TGDataDrivenTable.h" #import "TGTableDeltaUpdater.h" #import "TGInterfaceMenu.h" #import "TGGroupInfoHeaderController.h" #import "TGGroupInfoFooterController.h" #import "TGUserRowController.h" #import "TGInputController.h" #import "TGUserInfoController.h" #import "TGContactsController.h" #import "TGProfilePhotoController.h" NSString *const TGGroupInfoControllerIdentifier = @"TGGroupInfoController"; @implementation TGGroupInfoControllerContext - (instancetype)initWithGroupChat:(TGBridgeChat *)groupChat { self = [super init]; if (self != nil) { _groupChat = groupChat; } return self; } @end @interface TGGroupInfoController () { SMetaDisposable *_chatDisposable; SMetaDisposable *_peerSettingsDisposable; SMetaDisposable *_updateSettingsDisposable; TGInterfaceMenu *_menu; TGGroupInfoControllerContext *_context; TGBridgeChat *_chatModel; NSDictionary *_userModels; NSArray *_participantsModels; NSArray *_currentParticipantsModels; bool _muted; NSDictionary *_preferredParticipantsOrder; } @end @implementation TGGroupInfoController - (instancetype)init { self = [super init]; if (self != nil) { _chatDisposable = [[SMetaDisposable alloc] init]; _peerSettingsDisposable = [[SMetaDisposable alloc] init]; _updateSettingsDisposable = [[SMetaDisposable alloc] init]; [self.table _setInitialHidden:true]; self.table.tableDataSource = self; } return self; } - (void)dealloc { [_chatDisposable dispose]; [_peerSettingsDisposable dispose]; [_updateSettingsDisposable dispose]; } - (void)configureWithContext:(TGGroupInfoControllerContext *)context { _context = context; self.title = TGLocalized(@"Watch.GroupInfo.Title"); __weak TGGroupInfoController *weakSelf = self; [_chatDisposable setDisposable:[[[TGBridgeConversationSignals conversationWithPeerId:_context.groupChat.identifier] deliverOn:[SQueue mainQueue]] startWithNext:^(NSDictionary *models) { __strong TGGroupInfoController *strongSelf = weakSelf; if (strongSelf == nil) return; strongSelf->_chatModel = models[TGBridgeChatKey]; strongSelf->_userModels = models[TGBridgeUsersDictionaryKey]; NSMutableArray *participantsModels = [[NSMutableArray alloc] init]; for (NSNumber *uid in strongSelf->_chatModel.participants) { TGBridgeUser *user = strongSelf->_userModels[uid]; if (user != nil) [participantsModels addObject:user]; } participantsModels = [TGGroupInfoController sortedParticipantsList:participantsModels preferredOrder:strongSelf->_preferredParticipantsOrder ownUid:strongSelf->_context.context.userId]; strongSelf->_preferredParticipantsOrder = [TGGroupInfoController participantsOrderForList:participantsModels]; strongSelf->_participantsModels = participantsModels; [strongSelf performInterfaceUpdate:^(bool animated) { strongSelf.activityIndicator.hidden = true; strongSelf.table.hidden = false; NSArray *currentParticipantsModels = strongSelf->_currentParticipantsModels; bool initial = (currentParticipantsModels == 0); strongSelf->_currentParticipantsModels = strongSelf->_participantsModels; if (animated && !initial) { [TGTableDeltaUpdater updateTable:strongSelf.table oldData:currentParticipantsModels newData:strongSelf->_currentParticipantsModels controllerClassForIndexPath:^Class(TGIndexPath *indexPath) { return [strongSelf table:strongSelf->_table rowControllerClassAtIndexPath:indexPath]; }]; [strongSelf.table reloadHeader]; [strongSelf.table reloadFooter]; } else { [strongSelf.table reloadData]; } }]; } error:^(id error) { } completed:^ { }]]; [_peerSettingsDisposable setDisposable:[[TGBridgePeerSettingsSignals peerSettingsWithPeerId:_context.groupChat.identifier] startWithNext:^(NSDictionary *next) { __strong TGGroupInfoController *strongSelf = weakSelf; if (strongSelf == nil) return; TGBridgePeerNotificationSettings *settings = next[@"notifications"]; bool muted = (settings.muteFor > 0); if (strongSelf->_menu == nil || muted != strongSelf->_muted) { strongSelf->_muted = muted; [strongSelf performInterfaceUpdate:^(bool animated) { [strongSelf updateMenuItemsMuted:strongSelf->_muted]; }]; } }]]; } - (void)willActivate { [super willActivate]; [self.table notifyVisiblityChange]; } - (void)didDeactivate { [super didDeactivate]; } #pragma mark - - (void)updateMenuItemsMuted:(bool)muted { [_menu clearItems]; if (_menu == nil) _menu = [[TGInterfaceMenu alloc] initForInterfaceController:self]; __weak TGGroupInfoController *weakSelf = self; NSMutableArray *menuItems = [[NSMutableArray alloc] init]; bool muteForever = true; int32_t muteFor = muteForever ? INT_MAX : 1; NSString *muteTitle = muteForever ? TGLocalized(@"Watch.UserInfo.Mute") : [NSString stringWithFormat:TGLocalized([TGStringUtils integerValueFormat:@"Watch.UserInfo.Mute_" value:muteFor]), muteFor]; TGInterfaceMenuItem *muteItem = [[TGInterfaceMenuItem alloc] initWithItemIcon:muted ? WKMenuItemIconSpeaker : WKMenuItemIconMute title:muted ? TGLocalized(@"Watch.UserInfo.Unmute") : muteTitle actionBlock:^(TGInterfaceController *controller, TGInterfaceMenuItem *sender) { __strong TGGroupInfoController *strongSelf = weakSelf; if (strongSelf == nil) return; TGBridgePeerNotificationSettings *settings = [[TGBridgePeerNotificationSettings alloc] init]; settings.muteFor = muted ? 0 : (muteFor == INT_MAX ? INT_MAX : muteFor * 60 * 60); [strongSelf->_updateSettingsDisposable setDisposable:[[TGBridgePeerSettingsSignals updateNotificationSettingsWithPeerId:strongSelf->_context.groupChat.identifier settings:settings] startWithNext:nil completed:^ { __strong TGGroupInfoController *strongSelf = weakSelf; if (strongSelf == nil) return; strongSelf->_muted = !muted; [strongSelf updateMenuItemsMuted:strongSelf->_muted]; }]]; }]; [menuItems addObject:muteItem]; [_menu addItems:menuItems]; } #pragma mark - - (Class)headerControllerClassForTable:(WKInterfaceTable *)table { return [TGGroupInfoHeaderController class]; } - (void)table:(WKInterfaceTable *)table updateHeaderController:(TGGroupInfoHeaderController *)controller { __weak TGGroupInfoController *weakSelf = self; controller.isVisible = ^bool { __strong TGGroupInfoController *strongSelf = weakSelf; if (strongSelf == nil) return false; return strongSelf.isVisible; }; controller.avatarPressed = ^ { __strong TGGroupInfoController *strongSelf = weakSelf; if (strongSelf == nil) return; TGProfilePhotoControllerContext *context = [[TGProfilePhotoControllerContext alloc] initWithImageUrl:strongSelf->_chatModel.groupPhotoSmall]; [strongSelf pushControllerWithClass:[TGProfilePhotoController class] context:context]; }; [controller updateWithGroupChat:_chatModel users:_userModels context:_context.context]; } - (void)table:(WKInterfaceTable *)table updateFooterController:(TGGroupInfoFooterController *)controller { } - (Class)table:(WKInterfaceTable *)table rowControllerClassAtIndexPath:(NSIndexPath *)indexPath { return [TGUserRowController class]; } - (NSUInteger)numberOfRowsInTable:(WKInterfaceTable *)table section:(NSUInteger)section { return _currentParticipantsModels.count; } - (void)table:(WKInterfaceTable *)table updateRowController:(TGUserRowController *)controller forIndexPath:(TGIndexPath *)indexPath { __weak TGGroupInfoController *weakSelf = self; controller.isVisible = ^bool { __strong TGGroupInfoController *strongSelf = weakSelf; if (strongSelf == nil) return false; return strongSelf.isVisible; }; [controller updateWithUser:_currentParticipantsModels[indexPath.row] context:_context.context]; } - (id)contextForSegueWithIdentifer:(NSString *)segueIdentifier table:(WKInterfaceTable *)table indexPath:(TGIndexPath *)indexPath { return [[TGUserInfoControllerContext alloc] initWithUser:_currentParticipantsModels[indexPath.row]]; } + (NSMutableArray *)sortedParticipantsList:(NSMutableArray *)list preferredOrder:(NSDictionary *)preferredOrder ownUid:(int32_t)ownUid { NSMutableArray *resultList = [list mutableCopy]; [resultList sortUsingComparator:^NSComparisonResult(TGBridgeUser *user1, TGBridgeUser *user2) { if (user1.identifier == ownUid) return NSOrderedAscending; else if (user2.identifier == ownUid) return NSOrderedDescending; NSNumber *order1 = preferredOrder[@(user1.identifier)]; NSNumber *order2 = preferredOrder[@(user2.identifier)]; if (order1 != nil && order2 != nil) return order1.integerValue < order2.integerValue ? NSOrderedAscending : NSOrderedDescending; if (user1.isOnline != user2.isOnline) return user1.isOnline ? NSOrderedAscending : NSOrderedDescending; if ((user1.lastSeen < 0) != (user2.lastSeen < 0)) return user1.lastSeen >= 0 ? NSOrderedAscending : NSOrderedDescending; if (user1.isOnline || user1.lastSeen < 0) return user1.identifier < user2.identifier ? NSOrderedAscending : NSOrderedDescending; return user1.lastSeen > user2.lastSeen ? NSOrderedAscending : NSOrderedDescending; }]; return resultList; } + (NSDictionary *)participantsOrderForList:(NSArray *)list { NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; NSInteger i = 0; for (TGBridgeUser *user in list) { dictionary[@(user.identifier)] = @(i); i++; } return dictionary; } #pragma mark - + (NSString *)identifier { return TGGroupInfoControllerIdentifier; } @end