mirror of
https://github.com/danog/Telegram.git
synced 2024-12-02 09:27:55 +01:00
1659 lines
68 KiB
Objective-C
1659 lines
68 KiB
Objective-C
/*
|
|
* This is the source code of Telegram for iOS v. 1.1
|
|
* It is licensed under GNU GPL v. 2 or later.
|
|
* You should have received a copy of the license in this archive (see LICENSE).
|
|
*
|
|
* Copyright Peter Iakovlev, 2013.
|
|
*/
|
|
|
|
#import "TGGroupInfoController.h"
|
|
|
|
#import "ActionStage.h"
|
|
#import "SGraphObjectNode.h"
|
|
|
|
#import "TGConversation.h"
|
|
#import "TGDatabase.h"
|
|
|
|
#import "TGHacks.h"
|
|
#import "TGFont.h"
|
|
#import "TGStringUtils.h"
|
|
#import "UIDevice+PlatformInfo.h"
|
|
|
|
#import "TGAppDelegate.h"
|
|
#import "TGTelegraph.h"
|
|
#import "TGTelegramNetworking.h"
|
|
|
|
#import "TGInterfaceManager.h"
|
|
#import "TGNavigationBar.h"
|
|
#import "TGTelegraphDialogListCompanion.h"
|
|
#import "TGConversationChangeTitleRequestActor.h"
|
|
#import "TGConversationChangePhotoActor.h"
|
|
|
|
#import "TGHeaderCollectionItem.h"
|
|
#import "TGSwitchCollectionItem.h"
|
|
#import "TGVariantCollectionItem.h"
|
|
#import "TGButtonCollectionItem.h"
|
|
#import "TGCommentCollectionItem.h"
|
|
#import "TGGroupInfoCollectionItem.h"
|
|
#import "TGGroupInfoUserCollectionItem.h"
|
|
|
|
#import "TGTelegraphUserInfoController.h"
|
|
#import "TGGroupInfoSelectContactController.h"
|
|
#import "TGBotUserInfoController.h"
|
|
#import "TGAlertSoundController.h"
|
|
|
|
#import "TGRemoteImageView.h"
|
|
|
|
#import "TGImageUtils.h"
|
|
|
|
#import "TGAlertView.h"
|
|
#import "TGActionSheet.h"
|
|
|
|
#import "TGModernGalleryController.h"
|
|
#import "TGGroupAvatarGalleryItem.h"
|
|
#import "TGGroupAvatarGalleryModel.h"
|
|
#import "TGOverlayControllerWindow.h"
|
|
|
|
#import "TGSharedMediaController.h"
|
|
|
|
#import "TGTimerTarget.h"
|
|
|
|
#import "TGGroupManagementSignals.h"
|
|
#import "TGProgressWindow.h"
|
|
|
|
#import "TGGroupInfoShareLinkController.h"
|
|
|
|
#import "TGGroupAdminsController.h"
|
|
|
|
#import "TGMediaAvatarMenuMixin.h"
|
|
|
|
@interface TGGroupInfoController () <TGGroupInfoSelectContactControllerDelegate, TGAlertSoundControllerDelegate>
|
|
{
|
|
bool _editing;
|
|
bool _haveEditableUsers;
|
|
|
|
int64_t _conversationId;
|
|
TGConversation *_conversation;
|
|
|
|
TGCollectionMenuSection *_groupInfoSection;
|
|
|
|
TGGroupInfoCollectionItem *_groupInfoItem;
|
|
TGButtonCollectionItem *_setGroupPhotoItem;
|
|
|
|
TGCollectionMenuSection *_notificationsAndMediaSection;
|
|
TGSwitchCollectionItem *_notificationsItem;
|
|
TGVariantCollectionItem *_chatAdminsItem;
|
|
TGVariantCollectionItem *_sharedMediaItem;
|
|
TGVariantCollectionItem *_soundItem;
|
|
|
|
TGCollectionMenuSection *_usersSection;
|
|
TGHeaderCollectionItem *_usersSectionHeader;
|
|
TGCommentCollectionItem *_usersSectionUpgradeNotice1;
|
|
TGCommentCollectionItem *_usersSectionUpgradeNotice2;
|
|
TGButtonCollectionItem *_addParticipantItem;
|
|
|
|
NSMutableDictionary *_groupNotificationSettings;
|
|
NSInteger _sharedMediaCount;
|
|
|
|
NSMutableArray *_soonToBeAddedUserIds;
|
|
NSMutableArray *_soonToBeRemovedUserIds;
|
|
|
|
UILabel *_leftLabel;
|
|
|
|
NSTimer *_muteExpirationTimer;
|
|
|
|
int _upgradeNoticeMemberLimit;
|
|
|
|
bool _ignoreUpdates;
|
|
|
|
TGMediaAvatarMenuMixin *_avatarMixin;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGGroupInfoController
|
|
|
|
- (instancetype)initWithConversationId:(int64_t)conversationId
|
|
{
|
|
self = [super init];
|
|
if (self != nil)
|
|
{
|
|
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Back") style:UIBarButtonItemStylePlain target:self action:@selector(backPressed)];
|
|
|
|
_actionHandle = [[ASHandle alloc] initWithDelegate:self releaseOnMainThread:true];
|
|
|
|
_soonToBeAddedUserIds = [[NSMutableArray alloc] init];
|
|
_soonToBeRemovedUserIds = [[NSMutableArray alloc] init];
|
|
|
|
_conversationId = conversationId;
|
|
_groupNotificationSettings = [[NSMutableDictionary alloc] initWithDictionary:@{@"muteUntil": @(0), @"soundId": @(1)}];
|
|
|
|
[self setTitleText:TGLocalized(@"GroupInfo.Title")];
|
|
[self setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Edit") style:UIBarButtonItemStylePlain target:self action:@selector(editPressed)] animated:false];
|
|
|
|
_groupInfoItem = [[TGGroupInfoCollectionItem alloc] init];
|
|
_groupInfoItem.interfaceHandle = _actionHandle;
|
|
|
|
_setGroupPhotoItem = [[TGButtonCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.SetGroupPhoto") action:@selector(setGroupPhotoPressed)];
|
|
_setGroupPhotoItem.titleColor = TGAccentColor();
|
|
_setGroupPhotoItem.deselectAutomatically = true;
|
|
|
|
_groupInfoSection = [[TGCollectionMenuSection alloc] initWithItems:@[
|
|
_groupInfoItem,
|
|
_setGroupPhotoItem
|
|
]];
|
|
|
|
[self.menuSections addSection:_groupInfoSection];
|
|
|
|
_notificationsItem = [[TGSwitchCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.Notifications") isOn:false];
|
|
__weak TGGroupInfoController *weakSelf = self;
|
|
_notificationsItem.toggled = ^(bool value) {
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf _commitEnableNotifications:value orMuteFor:0];
|
|
}
|
|
};
|
|
_notificationsItem.deselectAutomatically = true;
|
|
_soundItem = [[TGVariantCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.Sound") variant:nil action:@selector(soundPressed)];
|
|
_soundItem.deselectAutomatically = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
|
|
_sharedMediaItem = [[TGVariantCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.SharedMedia") variant:nil action:@selector(sharedMediaPressed)];
|
|
|
|
_chatAdminsItem = [[TGVariantCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.ChatAdmins") action:@selector(chatAdminsPressed)];
|
|
|
|
_notificationsAndMediaSection = [[TGCollectionMenuSection alloc] initWithItems:@[
|
|
_notificationsItem,
|
|
_sharedMediaItem
|
|
]];
|
|
UIEdgeInsets notificationsAndMediaSectionInsets = _notificationsAndMediaSection.insets;
|
|
notificationsAndMediaSectionInsets.bottom = 18.0f;
|
|
_notificationsAndMediaSection.insets = notificationsAndMediaSectionInsets;
|
|
[self.menuSections addSection:_notificationsAndMediaSection];
|
|
|
|
_usersSectionHeader = [[TGHeaderCollectionItem alloc] initWithTitle:@""];
|
|
_addParticipantItem = [[TGButtonCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.AddParticipant") action:@selector(addParticipantPressed)];
|
|
_addParticipantItem.leftInset = 65.0f;
|
|
_addParticipantItem.icon = [UIImage imageNamed:@"GroupInfoIconAddMember.png"];
|
|
_addParticipantItem.titleColor = TGAccentColor();
|
|
_addParticipantItem.deselectAutomatically = true;
|
|
_usersSection = [[TGCollectionMenuSection alloc] initWithItems:@[
|
|
_usersSectionHeader,
|
|
_addParticipantItem
|
|
]];
|
|
[self.menuSections addSection:_usersSection];
|
|
|
|
_usersSectionUpgradeNotice1 = [[TGCommentCollectionItem alloc] initWithFormattedText:TGLocalized(@"Group.UpgradeNoticeText1")];
|
|
_usersSectionUpgradeNotice1.topInset = -2.0f;
|
|
|
|
int channelGroupMemberLimit = 1000;
|
|
NSData *data = [TGDatabaseInstance() customProperty:@"maxChannelGroupMembers"];
|
|
if (data.length >= 4)
|
|
{
|
|
int32_t maxChannelGroupMembers = 0;
|
|
[data getBytes:&maxChannelGroupMembers length:4];
|
|
if (maxChannelGroupMembers != 0) {
|
|
channelGroupMemberLimit = MAX(0, maxChannelGroupMembers);
|
|
}
|
|
}
|
|
|
|
data = [TGDatabaseInstance() customProperty:@"maxChatParticipants"];
|
|
if (data.length >= 4)
|
|
{
|
|
int32_t maxChatParticipants = 0;
|
|
[data getBytes:&maxChatParticipants length:4];
|
|
if (maxChatParticipants == 0) {
|
|
_upgradeNoticeMemberLimit = 99;
|
|
} else {
|
|
_upgradeNoticeMemberLimit = maxChatParticipants - 1;
|
|
}
|
|
}
|
|
|
|
#if TARGET_IPHONE_SIMULATOR
|
|
_upgradeNoticeMemberLimit = 4;
|
|
#endif
|
|
|
|
_usersSectionUpgradeNotice2 = [[TGCommentCollectionItem alloc] initWithFormattedText:[TGLocalized(@"Group.UpgradeNoticeText2") stringByReplacingOccurrencesOfString:@"{supergroup_member_limit}" withString:[[NSString alloc] initWithFormat:@"%d", channelGroupMemberLimit]]];
|
|
_usersSectionUpgradeNotice2.topInset = -5.0f;
|
|
_usersSectionUpgradeNotice2.bottomInset = 5.0f;
|
|
|
|
TGButtonCollectionItem *leaveGroupItem = [[TGButtonCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.DeleteAndExit") action:@selector(leaveGroupPressed)];
|
|
leaveGroupItem.titleColor = TGDestructiveAccentColor();
|
|
leaveGroupItem.alignment = NSTextAlignmentCenter;
|
|
leaveGroupItem.deselectAutomatically = true;
|
|
[self.menuSections addSection:[[TGCollectionMenuSection alloc] initWithItems:@[
|
|
leaveGroupItem
|
|
]]];
|
|
|
|
[self _loadUsersAndUpdateConversation:[TGDatabaseInstance() loadConversationWithIdCached:_conversationId]];
|
|
|
|
[self _updateNotificationItems:false];
|
|
[self _updateSharedMediaCount];
|
|
|
|
[self resetSections];
|
|
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
[ActionStageInstance() watchForPaths:@[
|
|
[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/conversation", _conversationId],
|
|
@"/tg/userdatachanges",
|
|
@"/tg/userpresencechanges",
|
|
@"/as/updateRelativeTimestamps",
|
|
[[NSString alloc] initWithFormat:@"/tg/sharedMediaCount/(%" PRIx64 ")", (int64_t)_conversationId]
|
|
] watcher:self];
|
|
|
|
[ActionStageInstance() watchForPath:[NSString stringWithFormat:@"/tg/peerSettings/(%" PRId64 ")", _conversationId] watcher:self];
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/peerSettings/(%" PRId64 ",cachedOnly)", _conversationId] options:@{@"peerId": @(_conversationId)} watcher:self];
|
|
|
|
NSArray *addActions = [ActionStageInstance() rejoinActionsWithGenericPathNow:@"/tg/conversation/@/addMember/@" prefix:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")", _conversationId] watcher:self];
|
|
NSArray *deleteActions = [ActionStageInstance() rejoinActionsWithGenericPathNow:@"/tg/conversation/@/deleteMember/@" prefix:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")", _conversationId] watcher:self];
|
|
NSArray *changeTitleActions = [ActionStageInstance() rejoinActionsWithGenericPathNow:@"/tg/conversation/@/changeTitle/@" prefix:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")", _conversationId] watcher:self];
|
|
NSArray *changeAvatarActions = [ActionStageInstance() rejoinActionsWithGenericPathNow:@"/tg/conversation/@/updateAvatar/@" prefix:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")", _conversationId] watcher:self];
|
|
|
|
NSString *updatingTitle = nil;
|
|
if (changeTitleActions.count != 0)
|
|
{
|
|
NSString *action = [changeTitleActions lastObject];
|
|
TGConversationChangeTitleRequestActor *actor = (TGConversationChangeTitleRequestActor *)[ActionStageInstance() executingActorWithPath:action];
|
|
if (actor != nil)
|
|
updatingTitle = actor.currentTitle;
|
|
}
|
|
|
|
UIImage *updatingAvatar = nil;
|
|
bool haveUpdatingAvatar = false;
|
|
if (changeAvatarActions.count != 0)
|
|
{
|
|
NSString *action = [changeAvatarActions lastObject];
|
|
TGConversationChangePhotoActor *actor = (TGConversationChangePhotoActor *)[ActionStageInstance() executingActorWithPath:action];
|
|
if (actor != nil)
|
|
{
|
|
updatingAvatar = actor.currentImage;
|
|
haveUpdatingAvatar = true;
|
|
}
|
|
}
|
|
|
|
if (addActions.count != 0 || deleteActions.count != 0 || changeTitleActions.count != 0 || changeAvatarActions.count != 0)
|
|
{
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
for (NSString *path in addActions)
|
|
{
|
|
NSRange range = [path rangeOfString:@"/addMember/("];
|
|
int32_t uid = (int32_t)[[path substringFromIndex:(range.location + range.length)] intValue];
|
|
|
|
[_soonToBeAddedUserIds addObject:@(uid)];
|
|
}
|
|
|
|
for (NSString *path in deleteActions)
|
|
{
|
|
NSRange range = [path rangeOfString:@"/deleteMember/("];
|
|
int32_t uid = (int32_t)[[path substringFromIndex:(range.location + range.length)] intValue];
|
|
|
|
[_soonToBeRemovedUserIds addObject:@(uid)];
|
|
}
|
|
|
|
[_groupInfoItem setUpdatingTitle:updatingTitle];
|
|
|
|
[_groupInfoItem setUpdatingAvatar:updatingAvatar hasUpdatingAvatar:haveUpdatingAvatar];
|
|
[_setGroupPhotoItem setEnabled:!haveUpdatingAvatar];
|
|
|
|
[self _loadUsersAndUpdateConversation:_conversation];
|
|
});
|
|
}
|
|
}];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)resetSections {
|
|
bool reload = false;
|
|
|
|
if (_editing) {
|
|
if (_conversation.isCreator) {
|
|
if ([_notificationsAndMediaSection indexOfItem:_chatAdminsItem] == NSNotFound) {
|
|
[_notificationsAndMediaSection insertItem:_chatAdminsItem atIndex:1];
|
|
reload = true;
|
|
}
|
|
} else {
|
|
if ([_notificationsAndMediaSection indexOfItem:_chatAdminsItem] != NSNotFound) {
|
|
[_notificationsAndMediaSection deleteItem:_chatAdminsItem];
|
|
reload = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool canAddParticipants = _conversation.isCreator || !_conversation.hasAdmins || (_conversation.hasAdmins && _conversation.isAdmin);
|
|
bool canEditGroup = canAddParticipants;
|
|
|
|
if (canAddParticipants) {
|
|
if ([_usersSection indexOfItem:_addParticipantItem] == NSNotFound) {
|
|
[_usersSection insertItem:_addParticipantItem atIndex:1];
|
|
reload = true;
|
|
}
|
|
} else {
|
|
if ([_usersSection deleteItem:_addParticipantItem]) {
|
|
reload = true;
|
|
}
|
|
}
|
|
|
|
if (canEditGroup) {
|
|
if ([_groupInfoSection indexOfItem:_setGroupPhotoItem] == NSNotFound) {
|
|
[_groupInfoSection addItem:_setGroupPhotoItem];
|
|
reload = true;
|
|
}
|
|
} else {
|
|
if ([_groupInfoSection deleteItem:_setGroupPhotoItem]) {
|
|
reload = true;
|
|
}
|
|
}
|
|
|
|
if (reload) {
|
|
[self.collectionView reloadData];
|
|
}
|
|
|
|
if (!canEditGroup && _editing) {
|
|
[self leaveEditingMode:false];
|
|
}
|
|
|
|
if (!(_conversation.kickedFromChat || _conversation.leftChat || _conversation.isDeactivated)) {
|
|
if (canEditGroup) {
|
|
if (self.navigationItem.rightBarButtonItem == nil) {
|
|
[self setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Edit") style:UIBarButtonItemStylePlain target:self action:@selector(editPressed)] animated:false];
|
|
}
|
|
} else {
|
|
if (self.navigationItem.rightBarButtonItem != nil) {
|
|
[self setRightBarButtonItem:nil];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)backPressed
|
|
{
|
|
[self.navigationController popViewControllerAnimated:true];
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[_actionHandle reset];
|
|
[ActionStageInstance() removeWatcher:self];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)_resetCollectionView
|
|
{
|
|
[super _resetCollectionView];
|
|
|
|
[self _updateLeftState];
|
|
|
|
[self.collectionView setAllowEditingCells:_haveEditableUsers animated:false];
|
|
}
|
|
|
|
- (void)viewWillAppear:(BOOL)animated
|
|
{
|
|
[super viewWillAppear:animated];
|
|
|
|
[self _layoutLeftLabel:self.interfaceOrientation];
|
|
}
|
|
|
|
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
|
|
{
|
|
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
|
|
|
|
[self _layoutLeftLabel:toInterfaceOrientation];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)editPressed
|
|
{
|
|
if (!_editing)
|
|
{
|
|
_editing = true;
|
|
|
|
[_groupInfoItem setEditing:true animated:true];
|
|
|
|
NSIndexPath *sharedMediaIndexPath = [self indexPathForItem:_sharedMediaItem];
|
|
if (sharedMediaIndexPath != nil)
|
|
{
|
|
[self.menuSections beginRecordingChanges];
|
|
[self.menuSections replaceItemInSection:sharedMediaIndexPath.section atIndex:sharedMediaIndexPath.item withItem:_soundItem];
|
|
if (_conversation.isCreator) {
|
|
if ([_notificationsAndMediaSection indexOfItem:_chatAdminsItem] == NSNotFound) {
|
|
[self.menuSections insertItem:_chatAdminsItem toSection:[self indexForSection:_notificationsAndMediaSection] atIndex:2];
|
|
}
|
|
}
|
|
[self.menuSections commitRecordedChanges:self.collectionView];
|
|
}
|
|
|
|
[self enterEditingMode:true];
|
|
}
|
|
}
|
|
|
|
- (void)donePressed
|
|
{
|
|
if (_editing)
|
|
{
|
|
_editing = false;
|
|
|
|
if (!TGStringCompare(_conversation.chatTitle, [_groupInfoItem editingTitle]) && [_groupInfoItem editingTitle] != nil)
|
|
[self _commitUpdateTitle:[_groupInfoItem editingTitle]];
|
|
|
|
[_groupInfoItem setEditing:false animated:true];
|
|
}
|
|
|
|
NSIndexPath *soundIndexPath = [self indexPathForItem:_soundItem];
|
|
if (soundIndexPath != nil)
|
|
{
|
|
[self.menuSections beginRecordingChanges];
|
|
[self.menuSections replaceItemInSection:soundIndexPath.section atIndex:soundIndexPath.item withItem:_sharedMediaItem];
|
|
if ([_notificationsAndMediaSection indexOfItem:_chatAdminsItem] != NSNotFound) {
|
|
[self.menuSections deleteItemFromSection:[self indexForSection:_notificationsAndMediaSection] atIndex:[_notificationsAndMediaSection indexOfItem:_chatAdminsItem]];
|
|
}
|
|
[self.menuSections commitRecordedChanges:self.collectionView];
|
|
}
|
|
|
|
[self leaveEditingMode:true];
|
|
}
|
|
|
|
- (void)didEnterEditingMode:(bool)animated
|
|
{
|
|
[super didEnterEditingMode:animated];
|
|
|
|
[self setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Done") style:UIBarButtonItemStyleDone target:self action:@selector(donePressed)] animated:true];
|
|
}
|
|
|
|
- (void)didLeaveEditingMode:(bool)animated
|
|
{
|
|
[super didLeaveEditingMode:animated];
|
|
|
|
[self setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Edit") style:UIBarButtonItemStylePlain target:self action:@selector(editPressed)] animated:animated];
|
|
}
|
|
|
|
- (void)setGroupPhotoPressed
|
|
{
|
|
if ([_groupInfoSection indexOfItem:_setGroupPhotoItem] == NSNotFound)
|
|
return;
|
|
|
|
__weak TGGroupInfoController *weakSelf = self;
|
|
_avatarMixin = [[TGMediaAvatarMenuMixin alloc] initWithParentController:self hasDeleteButton:(_conversation.chatPhotoSmall.length != 0)];
|
|
_avatarMixin.didFinishWithImage = ^(UIImage *image)
|
|
{
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf _updateGroupProfileImage:image];
|
|
strongSelf->_avatarMixin = nil;
|
|
};
|
|
_avatarMixin.didFinishWithDelete = ^
|
|
{
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf _commitDeleteAvatar];
|
|
strongSelf->_avatarMixin = nil;
|
|
};
|
|
_avatarMixin.didDismiss = ^
|
|
{
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
strongSelf->_avatarMixin = nil;
|
|
};
|
|
[_avatarMixin present];
|
|
}
|
|
|
|
- (void)_updateGroupProfileImage:(UIImage *)image
|
|
{
|
|
if (image == nil)
|
|
return;
|
|
|
|
if (MIN(image.size.width, image.size.height) < 160.0f)
|
|
image = TGScaleImageToPixelSize(image, CGSizeMake(160, 160));
|
|
|
|
NSData *imageData = UIImageJPEGRepresentation(image, 0.6f);
|
|
if (imageData == nil)
|
|
return;
|
|
|
|
TGImageProcessor filter = [TGRemoteImageView imageProcessorForName:@"circle:64x64"];
|
|
UIImage *avatarImage = filter(image);
|
|
|
|
[_groupInfoItem setUpdatingAvatar:avatarImage hasUpdatingAvatar:true];
|
|
[_setGroupPhotoItem setEnabled:false];
|
|
|
|
NSMutableDictionary *uploadOptions = [[NSMutableDictionary alloc] init];
|
|
[uploadOptions setObject:imageData forKey:@"imageData"];
|
|
[uploadOptions setObject:[NSNumber numberWithLongLong:_conversation.conversationId] forKey:@"conversationId"];
|
|
[uploadOptions setObject:avatarImage forKey:@"currentImage"];
|
|
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
static int actionId = 0;
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/(updateAvatar%d)", _conversationId, actionId] options:uploadOptions watcher:self];
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/(updateAvatar%d)", _conversationId, actionId++] options:uploadOptions watcher:TGTelegraphInstance];
|
|
}];
|
|
}
|
|
|
|
- (void)_commitDeleteAvatar
|
|
{
|
|
[_groupInfoItem setUpdatingAvatar:nil hasUpdatingAvatar:true];
|
|
[_setGroupPhotoItem setEnabled:false];
|
|
|
|
NSMutableDictionary *uploadOptions = [[NSMutableDictionary alloc] init];
|
|
[uploadOptions setObject:[NSNumber numberWithLongLong:_conversation.conversationId] forKey:@"conversationId"];
|
|
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
static int actionId = 0;
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/(deleteAvatar%d)", _conversationId, actionId] options:uploadOptions watcher:self];
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/(deleteAvatar%d)", _conversationId, actionId++] options:uploadOptions watcher:TGTelegraphInstance];
|
|
}];
|
|
}
|
|
|
|
- (void)_commitCancelAvatarUpdate
|
|
{
|
|
[_groupInfoItem setUpdatingAvatar:nil hasUpdatingAvatar:false];
|
|
[_setGroupPhotoItem setEnabled:true];
|
|
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
NSArray *actors = [ActionStageInstance() executingActorsWithPathPrefix:[NSString stringWithFormat:@"/tg/conversation/(%lld)/updateAvatar/", _conversationId]];
|
|
for (ASActor *actor in actors)
|
|
{
|
|
[ActionStageInstance() removeAllWatchersFromPath:actor.path];
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (void)notificationsPressed
|
|
{
|
|
NSMutableArray *actions = [[NSMutableArray alloc] init];
|
|
[actions addObject:[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"UserInfo.NotificationsEnable") action:@"enable"]];
|
|
|
|
NSArray *muteIntervals = @[
|
|
@(1 * 60 * 60),
|
|
@(8 * 60 * 60),
|
|
@(2 * 24 * 60 * 60),
|
|
];
|
|
|
|
for (NSNumber *nMuteInterval in muteIntervals)
|
|
{
|
|
[actions addObject:[[TGActionSheetAction alloc] initWithTitle:[TGStringUtils stringForMuteInterval:[nMuteInterval intValue]] action:[[NSString alloc] initWithFormat:@"%@", nMuteInterval]]];
|
|
}
|
|
|
|
[actions addObject:[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"UserInfo.NotificationsDisable") action:@"disable"]];
|
|
[actions addObject:[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"Common.Cancel") action:@"cancel" type:TGActionSheetActionTypeCancel]];
|
|
|
|
[[[TGActionSheet alloc] initWithTitle:nil actions:actions actionBlock:^(TGGroupInfoController *controller, NSString *action)
|
|
{
|
|
if ([action isEqualToString:@"enable"])
|
|
[controller _commitEnableNotifications:true orMuteFor:0];
|
|
else if ([action isEqualToString:@"disable"])
|
|
[controller _commitEnableNotifications:false orMuteFor:0];
|
|
else if (![action isEqualToString:@"cancel"])
|
|
{
|
|
[controller _commitEnableNotifications:false orMuteFor:[action intValue]];
|
|
}
|
|
} target:self] showInView:self.view];
|
|
}
|
|
|
|
- (void)_commitEnableNotifications:(bool)enable orMuteFor:(int)muteFor
|
|
{
|
|
int muteUntil = 0;
|
|
if (muteFor == 0)
|
|
{
|
|
if (enable)
|
|
muteUntil = 0;
|
|
else
|
|
muteUntil = INT_MAX;
|
|
}
|
|
else
|
|
{
|
|
muteUntil = (int)([[TGTelegramNetworking instance] approximateRemoteTime] + muteFor);
|
|
}
|
|
|
|
if (muteUntil != [_groupNotificationSettings[@"muteUntil"] intValue])
|
|
{
|
|
_groupNotificationSettings[@"muteUntil"] = @(muteUntil);
|
|
static int actionId = 0;
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/changePeerSettings/(%" PRId64 ")/(userInfoControllerMute%d)", _conversationId, actionId++] options:@{
|
|
@"peerId": @(_conversationId),
|
|
@"muteUntil": @(muteUntil)
|
|
} watcher:TGTelegraphInstance];
|
|
[self _updateNotificationItems:false];
|
|
}
|
|
}
|
|
|
|
- (void)addParticipantPressed
|
|
{
|
|
if ([self showGroupUpgradeNotice]) {
|
|
int64_t conversationId = _conversationId;
|
|
__weak TGGroupInfoController *weakSelf = self;
|
|
[[[TGAlertView alloc] initWithTitle:nil message:TGLocalized(@"Group.UpgradeConfirmation") cancelButtonTitle:TGLocalized(@"Common.Cancel") okButtonTitle:TGLocalized(@"Common.OK") completionBlock:^(bool okButtonPressed) {
|
|
if (okButtonPressed) {
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
strongSelf->_ignoreUpdates = true;
|
|
}
|
|
|
|
TGProgressWindow *progressWindow = [[TGProgressWindow alloc] init];
|
|
[progressWindow show:true];
|
|
|
|
[[[[TGGroupManagementSignals migrateGroup:conversationId] deliverOn:[SQueue mainQueue]] onDispose:^{
|
|
TGDispatchOnMainThread(^{
|
|
[progressWindow dismiss:true];
|
|
});
|
|
}] startWithNext:^(TGConversation *conversation) {
|
|
[[TGInterfaceManager instance] navigateToConversationWithId:conversation.conversationId conversation:conversation];
|
|
} error:^(__unused id error) {
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
strongSelf->_ignoreUpdates = false;
|
|
}
|
|
} completed:nil];
|
|
}
|
|
}] show];
|
|
} else {
|
|
int contactsMode = TGContactsModeRegistered | TGContactsModeManualFirstSection;
|
|
if (_conversation.chatParticipants.chatAdminId == TGTelegraphInstance.clientUserId)
|
|
contactsMode |= TGContactsModeCreateGroupLink;
|
|
contactsMode |= TGContactsModeIgnorePrivateBots;
|
|
TGGroupInfoSelectContactController *selectContactController = [[TGGroupInfoSelectContactController alloc] initWithContactsMode:contactsMode];
|
|
selectContactController.delegate = self;
|
|
|
|
NSMutableArray *disabledUsers = [[NSMutableArray alloc] init];
|
|
[disabledUsers addObjectsFromArray:_conversation.chatParticipants.chatParticipantUids];
|
|
[disabledUsers addObjectsFromArray:_soonToBeAddedUserIds];
|
|
|
|
selectContactController.disabledUsers = disabledUsers;
|
|
|
|
TGNavigationController *navigationController = [TGNavigationController navigationControllerWithControllers:@[selectContactController] navigationBarClass:[TGWhiteNavigationBar class]];
|
|
if ([self inPopover])
|
|
{
|
|
navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
|
|
navigationController.presentationStyle = TGNavigationControllerPresentationStyleChildInPopover;
|
|
}
|
|
|
|
[self presentViewController:navigationController animated:true completion:nil];
|
|
}
|
|
}
|
|
|
|
- (void)selectContactControllerDidSelectUser:(TGUser *)user
|
|
{
|
|
if (user.uid != 0 && ![_conversation.chatParticipants.chatParticipantUids containsObject:@(user.uid)])
|
|
{
|
|
__weak typeof(self) weakSelf = self;
|
|
[[[TGAlertView alloc] initWithTitle:nil message:[[NSString alloc] initWithFormat:TGLocalized(@"GroupInfo.AddParticipantConfirmation"), user.displayFirstName] cancelButtonTitle:TGLocalized(@"Common.Cancel") okButtonTitle:TGLocalized(@"Common.OK") completionBlock:^(bool okButtonPressed)
|
|
{
|
|
if (okButtonPressed)
|
|
{
|
|
TGGroupInfoController *strongSelf = weakSelf;
|
|
[strongSelf _commitAddParticipant:user];
|
|
}
|
|
}] show];
|
|
}
|
|
}
|
|
|
|
- (void)selectContactControllerDidSelectCreateLink
|
|
{
|
|
if ([self.presentedViewController isKindOfClass:[UINavigationController class]])
|
|
{
|
|
TGGroupInfoShareLinkController *controller = [[TGGroupInfoShareLinkController alloc] initWithPeerId:_conversationId accessHash:0 currentLink:_conversation.chatParticipants.exportedChatInviteString];
|
|
[(UINavigationController *)self.presentedViewController pushViewController:controller animated:true];
|
|
}
|
|
}
|
|
|
|
- (void)_commitAddParticipant:(TGUser *)user
|
|
{
|
|
if (![_soonToBeAddedUserIds containsObject:@(user.uid)])
|
|
{
|
|
[_soonToBeAddedUserIds addObject:@(user.uid)];
|
|
[self _loadUsersAndUpdateConversation:_conversation];
|
|
|
|
for (id item in _usersSection.items)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupInfoUserCollectionItem class]])
|
|
{
|
|
if (((TGGroupInfoUserCollectionItem *)item).user.uid == user.uid)
|
|
{
|
|
NSIndexPath *indexPath = [self indexPathForItem:item];
|
|
if (indexPath != nil && [UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPad)
|
|
[self.collectionView selectItemAtIndexPath:indexPath animated:false scrollPosition:UICollectionViewScrollPositionTop];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
NSString *path = [NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/addMember/(%d)", _conversation.conversationId, user.uid];
|
|
NSDictionary *options = @{@"conversationId": @(_conversationId), @"uid": @(user.uid)};
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
[ActionStageInstance() requestActor:path options:options watcher:self];
|
|
[ActionStageInstance() requestActor:path options:options watcher:TGTelegraphInstance];
|
|
}];
|
|
}
|
|
|
|
[self dismissViewControllerAnimated:true completion:nil];
|
|
}
|
|
|
|
- (void)_commitDeleteParticipant:(int32_t)uid
|
|
{
|
|
for (id item in _usersSection.items)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupInfoUserCollectionItem class]] && ((TGGroupInfoUserCollectionItem *)item).user.uid == uid)
|
|
{
|
|
[_soonToBeRemovedUserIds addObject:@(uid)];
|
|
[(TGGroupInfoUserCollectionItem *)item setDisabled:true];
|
|
[(TGGroupInfoUserCollectionItem *)item setCanEdit:false animated:true];
|
|
|
|
NSDictionary *options = @{@"conversationId": @(_conversationId), @"uid": @(uid)};
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/deleteMember/(%d)", _conversationId, uid] options:options watcher:self];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)_commitUpdateTitle:(NSString *)title
|
|
{
|
|
[_groupInfoItem setUpdatingTitle:title];
|
|
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
static int actionId = 0;
|
|
NSString *path = [[NSString alloc] initWithFormat:@"/tg/conversation/(%" PRId64 ")/changeTitle/(groupInfoController%d)", _conversation.conversationId, actionId++];
|
|
NSDictionary *options = @{@"conversationId": @(_conversationId), @"title": title == nil ? @"" : title};
|
|
|
|
[ActionStageInstance() requestActor:path options:options watcher:self];
|
|
[ActionStageInstance() requestActor:path options:options watcher:TGTelegraphInstance];
|
|
}];
|
|
}
|
|
|
|
- (void)leaveGroupPressed
|
|
{
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
[[[TGActionSheet alloc] initWithTitle:TGLocalized(@"GroupInfo.DeleteAndExitConfirmation") actions:@[
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"GroupInfo.DeleteAndExit") action:@"leave" type:TGActionSheetActionTypeDestructive],
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"Common.Cancel") action:@"cancel" type:TGActionSheetActionTypeCancel]
|
|
] actionBlock:^(__unused id target, NSString *action)
|
|
{
|
|
if ([action isEqualToString:@"leave"])
|
|
{
|
|
TGGroupInfoController *strongSelf = weakSelf;
|
|
[strongSelf _commitLeaveGroup];
|
|
}
|
|
} target:self] showInView:self.view];
|
|
}
|
|
|
|
- (void)_commitLeaveGroup
|
|
{
|
|
[TGAppDelegateInstance.rootController.dialogListController.dialogListCompanion deleteItem:[[TGConversation alloc] initWithConversationId:_conversationId unreadCount:0 serviceUnreadCount:0] animated:false];
|
|
|
|
if (self.popoverController != nil)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), ^
|
|
{
|
|
[self.popoverController dismissPopoverAnimated:true];
|
|
});
|
|
}
|
|
else
|
|
[self.navigationController popToRootViewControllerAnimated:true];
|
|
}
|
|
|
|
- (void)_changeNotificationSettings:(bool)enableNotifications
|
|
{
|
|
_groupNotificationSettings[@"muteUntil"] = @(!enableNotifications ? INT_MAX : 0);
|
|
|
|
static int actionId = 0;
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/changePeerSettings/(%" PRId64 ")/(groupInfoController%d)", _conversation.conversationId, actionId++] options:@{@"peerId": @(_conversationId), @"muteUntil": @(!enableNotifications ? INT_MAX : 0)} watcher:TGTelegraphInstance];
|
|
}
|
|
|
|
- (void)soundPressed
|
|
{
|
|
TGAlertSoundController *alertSoundController = [[TGAlertSoundController alloc] initWithTitle:TGLocalized(@"GroupInfo.Sound") soundInfoList:[self _soundInfoListForSelectedSoundId:[_groupNotificationSettings[@"soundId"] intValue]]];
|
|
alertSoundController.delegate = self;
|
|
|
|
TGNavigationController *navigationController = [TGNavigationController navigationControllerWithControllers:@[alertSoundController] navigationBarClass:[TGWhiteNavigationBar class]];
|
|
if ([self inPopover])
|
|
{
|
|
navigationController.modalPresentationStyle = UIModalPresentationCurrentContext;
|
|
navigationController.presentationStyle = TGNavigationControllerPresentationStyleChildInPopover;
|
|
}
|
|
|
|
[self presentViewController:navigationController animated:true completion:nil];
|
|
}
|
|
|
|
- (void)alertSoundController:(TGAlertSoundController *)__unused alertSoundController didFinishPickingWithSoundInfo:(NSDictionary *)soundInfo
|
|
{
|
|
if (soundInfo[@"soundId"] != nil && [soundInfo[@"soundId"] intValue] >= 0 && [soundInfo[@"soundId"] intValue] != [_groupNotificationSettings[@"soundId"] intValue])
|
|
{
|
|
int soundId = [soundInfo[@"soundId"] intValue];
|
|
_groupNotificationSettings[@"soundId"] = @(soundId);
|
|
[self _updateNotificationItems:false];
|
|
|
|
static int actionId = 0;
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/changePeerSettings/(%" PRId64 ")/(groupInfoController%d)", _conversationId, actionId++] options:@{
|
|
@"peerId": @(_conversationId),
|
|
@"soundId": @(soundId)
|
|
} watcher:TGTelegraphInstance];
|
|
}
|
|
}
|
|
|
|
- (NSString *)soundNameFromId:(int)soundId
|
|
{
|
|
if (soundId == 0 || soundId == 1)
|
|
return [TGAppDelegateInstance modernAlertSoundTitles][soundId];
|
|
|
|
if (soundId >= 2 && soundId <= 9)
|
|
return [TGAppDelegateInstance classicAlertSoundTitles][MAX(0, soundId - 2)];
|
|
|
|
if (soundId >= 100 && soundId <= 111)
|
|
return [TGAppDelegateInstance modernAlertSoundTitles][soundId - 100 + 2];
|
|
return @"";
|
|
}
|
|
|
|
- (NSArray *)_soundInfoListForSelectedSoundId:(int)selectedSoundId
|
|
{
|
|
NSMutableArray *infoList = [[NSMutableArray alloc] init];
|
|
|
|
int defaultSoundId = 1;
|
|
[TGDatabaseInstance() loadPeerNotificationSettings:INT_MAX - 2 soundId:&defaultSoundId muteUntil:NULL previewText:NULL messagesMuted:NULL notFound:NULL];
|
|
NSString *defaultSoundTitle = [self soundNameFromId:defaultSoundId];
|
|
|
|
int index = -1;
|
|
for (NSString *soundName in [TGAppDelegateInstance modernAlertSoundTitles])
|
|
{
|
|
index++;
|
|
|
|
int soundId = 0;
|
|
bool isDefault = false;
|
|
|
|
if (index == 1)
|
|
{
|
|
soundId = 1;
|
|
isDefault = true;
|
|
}
|
|
else if (index == 0)
|
|
soundId = 0;
|
|
else
|
|
soundId = index + 100 - 2;
|
|
|
|
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
|
dict[@"title"] = isDefault ? [[NSString alloc] initWithFormat:@"%@ (%@)", soundName, defaultSoundTitle] : soundName;
|
|
dict[@"selected"] = @(selectedSoundId == soundId);
|
|
dict[@"soundName"] = [[NSString alloc] initWithFormat:@"%d", isDefault ? defaultSoundId : soundId];
|
|
dict[@"soundId"] = @(soundId);
|
|
dict[@"groupId"] = @(0);
|
|
[infoList addObject:dict];
|
|
}
|
|
|
|
index = -1;
|
|
for (NSString *soundName in [TGAppDelegateInstance classicAlertSoundTitles])
|
|
{
|
|
index++;
|
|
|
|
int soundId = index + 2;
|
|
|
|
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
|
dict[@"title"] = soundName;
|
|
dict[@"selected"] = @(selectedSoundId == soundId);
|
|
dict[@"soundName"] = [[NSString alloc] initWithFormat:@"%d", soundId];
|
|
dict[@"soundId"] = @(soundId);
|
|
dict[@"groupId"] = @(1);
|
|
[infoList addObject:dict];
|
|
}
|
|
|
|
return infoList;
|
|
}
|
|
|
|
- (void)sharedMediaPressed
|
|
{
|
|
[self.navigationController pushViewController:[[TGSharedMediaController alloc] initWithPeerId:_conversationId accessHash:0 important:true] animated:true];
|
|
//[[TGInterfaceManager instance] navigateToMediaListOfConversation:_conversationId navigationController:self.navigationController];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)_updateNotificationItems:(bool)__unused animated
|
|
{
|
|
[_muteExpirationTimer invalidate];
|
|
_muteExpirationTimer = nil;
|
|
|
|
bool enabled = false;
|
|
int muteUntil = [_groupNotificationSettings[@"muteUntil"] intValue];
|
|
if (muteUntil <= [[TGTelegramNetworking instance] approximateRemoteTime]) {
|
|
enabled = true;
|
|
} else {
|
|
int muteExpiration = muteUntil - (int)[[TGTelegramNetworking instance] approximateRemoteTime];
|
|
if (muteExpiration >= 7 * 24 * 60 * 60) {
|
|
|
|
} else {
|
|
_muteExpirationTimer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(updateMuteExpiration) interval:2.0 repeat:true];
|
|
}
|
|
}
|
|
|
|
_notificationsItem.isOn = enabled;
|
|
|
|
int groupSoundId = [[_groupNotificationSettings objectForKey:@"soundId"] intValue];
|
|
_soundItem.variant = [self soundNameFromId:groupSoundId];
|
|
}
|
|
|
|
- (void)updateMuteExpiration
|
|
{
|
|
bool enabled = false;
|
|
int muteUntil = [_groupNotificationSettings[@"muteUntil"] intValue];
|
|
if (muteUntil <= [[TGTelegramNetworking instance] approximateRemoteTime]) {
|
|
enabled = true;
|
|
}
|
|
|
|
if (_notificationsItem.isOn != enabled) {
|
|
_notificationsItem.isOn = enabled;
|
|
}
|
|
}
|
|
|
|
- (void)_updateSharedMediaCount
|
|
{
|
|
//_sharedMediaItem.variant = _sharedMediaCount == 0 ? TGLocalized(@"GroupInfo.SharedMediaNone") : ( TGIsLocaleArabic() ? [TGStringUtils stringWithLocalizedNumber:_sharedMediaCount] : [[NSString alloc] initWithFormat:@"%d", _sharedMediaCount]);
|
|
_sharedMediaItem.variant = @"";
|
|
}
|
|
|
|
- (void)_loadUsersAndUpdateConversation:(TGConversation *)conversation
|
|
{
|
|
NSMutableArray *participantUsers = [[NSMutableArray alloc] init];
|
|
for (NSNumber *nUid in conversation.chatParticipants.chatParticipantUids)
|
|
{
|
|
TGUser *user = [TGDatabaseInstance() loadUser:[nUid int32Value]];
|
|
if (user != nil)
|
|
[participantUsers addObject:user];
|
|
}
|
|
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
if (_ignoreUpdates) {
|
|
return;
|
|
}
|
|
|
|
for (NSNumber *nUid in _soonToBeAddedUserIds)
|
|
{
|
|
if (![conversation.chatParticipants.chatParticipantUids containsObject:nUid])
|
|
{
|
|
TGUser *user = [TGDatabaseInstance() loadUser:[nUid int32Value]];
|
|
if (user != nil)
|
|
[participantUsers addObject:user];
|
|
}
|
|
}
|
|
|
|
_conversation = conversation;
|
|
[_groupInfoItem setConversation:_conversation];
|
|
|
|
bool forceReload = false;
|
|
|
|
[self _updateLeftState];
|
|
[self _updateConversationWithLoadedUsers:participantUsers forceReload:forceReload];
|
|
|
|
[self resetSections];
|
|
});
|
|
}
|
|
|
|
- (bool)showGroupUpgradeNotice {
|
|
if (_conversation.isCreator) {
|
|
#ifdef INTERNAL_RELEASE
|
|
//return _conversation.chatParticipantCount >= 2;
|
|
#endif
|
|
|
|
if (_upgradeNoticeMemberLimit != 0) {
|
|
return _conversation.chatParticipantCount >= _upgradeNoticeMemberLimit;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
- (void)_updateConversationWithLoadedUsers:(NSArray *)participantUsers forceReload:(bool)forceReload
|
|
{
|
|
NSDictionary *invitedDates = _conversation.chatParticipants.chatInvitedDates;
|
|
|
|
int32_t selfUid = TGTelegraphInstance.clientUserId;
|
|
NSArray *sortedUsers = [participantUsers sortedArrayUsingComparator:^NSComparisonResult(TGUser *user1, TGUser *user2)
|
|
{
|
|
if (user1.botKind != user2.botKind)
|
|
{
|
|
return user1.botKind < user2.botKind ? NSOrderedAscending : NSOrderedDescending;
|
|
}
|
|
|
|
if (user1.kind != user2.kind)
|
|
{
|
|
return user1.kind < user2.kind ? NSOrderedAscending : NSOrderedDescending;
|
|
}
|
|
|
|
if (user1.uid == selfUid)
|
|
return NSOrderedAscending;
|
|
else if (user2.uid == selfUid)
|
|
return NSOrderedDescending;
|
|
|
|
if (user1.presence.online != user2.presence.online)
|
|
return user1.presence.online ? NSOrderedAscending : NSOrderedDescending;
|
|
|
|
if ((user1.presence.lastSeen < 0) != (user2.presence.lastSeen < 0))
|
|
return user1.presence.lastSeen >= 0 ? NSOrderedAscending : NSOrderedDescending;
|
|
|
|
if (user1.presence.online)
|
|
{
|
|
NSNumber *nDate1 = invitedDates[[[NSNumber alloc] initWithInt:user1.uid]];
|
|
NSNumber *nDate2 = invitedDates[[[NSNumber alloc] initWithInt:user2.uid]];
|
|
|
|
if (nDate1 != nil && nDate2 != nil)
|
|
return [nDate1 intValue] < [nDate2 intValue] ? NSOrderedAscending : NSOrderedDescending;
|
|
else if (nDate1 != nil)
|
|
return NSOrderedAscending;
|
|
else if (nDate2 != nil)
|
|
return NSOrderedDescending;
|
|
else
|
|
return user1.uid < user2.uid ? NSOrderedAscending : NSOrderedDescending;
|
|
}
|
|
|
|
if (user1.presence.lastSeen < 0)
|
|
{
|
|
NSNumber *nDate1 = invitedDates[[[NSNumber alloc] initWithInt:user1.uid]];
|
|
NSNumber *nDate2 = invitedDates[[[NSNumber alloc] initWithInt:user2.uid]];
|
|
|
|
if (nDate1 != nil && nDate2 != nil)
|
|
return [nDate1 intValue] < [nDate2 intValue] ? NSOrderedAscending : NSOrderedDescending;
|
|
else
|
|
return user1.uid < user2.uid ? NSOrderedAscending : NSOrderedDescending;
|
|
}
|
|
|
|
return user1.presence.lastSeen > user2.presence.lastSeen ? NSOrderedAscending : NSOrderedDescending;
|
|
}];
|
|
|
|
if ([self showGroupUpgradeNotice]) {
|
|
[_usersSectionHeader setTitle:TGLocalized(@"Group.UpgradeNoticeHeader")];
|
|
|
|
if ([_usersSection indexOfItem:_usersSectionUpgradeNotice1] == NSNotFound) {
|
|
[_usersSection insertItem:_usersSectionUpgradeNotice1 atIndex:1];
|
|
[_usersSection insertItem:_usersSectionUpgradeNotice2 atIndex:2];
|
|
forceReload = true;
|
|
}
|
|
|
|
_addParticipantItem.title = TGLocalized(@"GroupInfo.UpgradeButton");
|
|
_addParticipantItem.icon = [UIImage imageNamed:@"GroupInfoIconUpgrade"];
|
|
|
|
} else {
|
|
_addParticipantItem.title = TGLocalized(@"GroupInfo.AddParticipant");
|
|
_addParticipantItem.icon = [UIImage imageNamed:@"GroupInfoIconAddMember.png"];
|
|
|
|
if ([_usersSection indexOfItem:_usersSectionUpgradeNotice1] != NSNotFound) {
|
|
[_usersSection deleteItem:_usersSectionUpgradeNotice1];
|
|
[_usersSection deleteItem:_usersSectionUpgradeNotice2];
|
|
forceReload = true;
|
|
}
|
|
|
|
NSString *title = @"";
|
|
if (sortedUsers.count == 1)
|
|
title = TGLocalized(@"GroupInfo.ParticipantCount_1");
|
|
else if (sortedUsers.count == 2)
|
|
title = TGLocalized(@"GroupInfo.ParticipantCount_2");
|
|
else if (sortedUsers.count >= 3 && sortedUsers.count <= 10)
|
|
title = [NSString localizedStringWithFormat:TGLocalized(@"GroupInfo.ParticipantCount_3_10"), [TGStringUtils stringWithLocalizedNumber:sortedUsers.count]];
|
|
else
|
|
title = [NSString localizedStringWithFormat:TGLocalized(@"GroupInfo.ParticipantCount_any"), [TGStringUtils stringWithLocalizedNumber:sortedUsers.count]];
|
|
[_usersSectionHeader setTitle:title];
|
|
}
|
|
|
|
NSUInteger sectionIndex = [self indexForSection:_usersSection];
|
|
if (sectionIndex != NSNotFound)
|
|
{
|
|
bool haveChanges = false;
|
|
|
|
NSInteger headButtonCount = 0;
|
|
NSInteger tailButtonCount = 0;
|
|
for (NSInteger i = 0; i < (NSInteger)_usersSection.items.count; i++) {
|
|
if ([_usersSection.items[i] isKindOfClass:[TGGroupInfoUserCollectionItem class]]) {
|
|
break;
|
|
} else {
|
|
headButtonCount++;
|
|
}
|
|
}
|
|
|
|
if (_usersSection.items.count - headButtonCount - tailButtonCount != sortedUsers.count)
|
|
haveChanges = true;
|
|
else
|
|
{
|
|
for (int i = (int)headButtonCount, j = 0; i < (int)_usersSection.items.count - headButtonCount - tailButtonCount; i++, j++)
|
|
{
|
|
TGGroupInfoUserCollectionItem *userItem = _usersSection.items[i];
|
|
TGUser *user = sortedUsers[j];
|
|
if (user.uid != userItem.user.uid)
|
|
{
|
|
haveChanges = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (haveChanges || forceReload)
|
|
{
|
|
int count = (int)(_usersSection.items.count - headButtonCount - tailButtonCount);
|
|
while (count > 0)
|
|
{
|
|
[self.menuSections deleteItemFromSection:sectionIndex atIndex:headButtonCount];
|
|
count--;
|
|
}
|
|
|
|
NSInteger insertIndex = headButtonCount;
|
|
for (TGUser *user in sortedUsers)
|
|
{
|
|
TGGroupInfoUserCollectionItem *userItem = [[TGGroupInfoUserCollectionItem alloc] init];
|
|
userItem.interfaceHandle = _actionHandle;
|
|
|
|
bool disabled = ![_conversation.chatParticipants.chatParticipantUids containsObject:@(user.uid)] || [_soonToBeRemovedUserIds containsObject:@(user.uid)];
|
|
userItem.selectable = user.uid != selfUid && !disabled;
|
|
|
|
bool canEditInPrinciple = false;
|
|
if (user.uid != selfUid) {
|
|
canEditInPrinciple = ((_conversation.chatParticipants.chatAdminId == selfUid || [_conversation.chatParticipants.chatInvitedBy[@(user.uid)] int32Value] == selfUid));
|
|
if (!canEditInPrinciple) {
|
|
if (_conversation.isCreator) {
|
|
canEditInPrinciple = true;
|
|
} else if (_conversation.hasAdmins) {
|
|
canEditInPrinciple = _conversation.isAdmin && ![_conversation.chatParticipants.chatAdminUids containsObject:@(user.uid)] && _conversation.chatParticipants.chatAdminId != user.uid;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool canEdit = userItem.selectable && canEditInPrinciple;
|
|
[userItem setCanEdit:canEdit];
|
|
|
|
[userItem setUser:user];
|
|
[userItem setDisabled:disabled];
|
|
|
|
[self.menuSections insertItem:userItem toSection:sectionIndex atIndex:insertIndex];
|
|
insertIndex++;
|
|
}
|
|
|
|
/*self.collectionLayout.withoutAnimation = true;
|
|
[UIView performWithoutAnimation:^
|
|
{
|
|
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:sectionIndex]];
|
|
}];
|
|
self.collectionLayout.withoutAnimation = false;*/
|
|
|
|
[self.collectionView reloadData];
|
|
|
|
[self _updateAllowCellEditing:false];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)_updateAllowCellEditing:(bool)animated
|
|
{
|
|
bool anyCanEdit = false;
|
|
int32_t selfUid = TGTelegraphInstance.clientUserId;
|
|
|
|
for (id item in _usersSection.items)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupInfoUserCollectionItem class]])
|
|
{
|
|
TGUser *user = ((TGGroupInfoUserCollectionItem *)item).user;
|
|
|
|
bool canEditInPrinciple = false;
|
|
if (user.uid != selfUid) {
|
|
canEditInPrinciple = ((_conversation.chatParticipants.chatAdminId == selfUid || [_conversation.chatParticipants.chatInvitedBy[@(user.uid)] int32Value] == selfUid));
|
|
if (!canEditInPrinciple) {
|
|
if (_conversation.isCreator) {
|
|
canEditInPrinciple = true;
|
|
} else if (_conversation.hasAdmins) {
|
|
canEditInPrinciple = _conversation.isAdmin && ![_conversation.chatParticipants.chatAdminUids containsObject:@(user.uid)] && _conversation.chatParticipants.chatAdminId != user.uid;
|
|
}
|
|
}
|
|
}
|
|
|
|
anyCanEdit |= canEditInPrinciple;
|
|
}
|
|
}
|
|
|
|
_haveEditableUsers = anyCanEdit;
|
|
[self.collectionView setAllowEditingCells:anyCanEdit animated:animated];
|
|
}
|
|
|
|
- (void)_updateRelativeTimestamps
|
|
{
|
|
for (id item in _usersSection.items)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupInfoUserCollectionItem class]])
|
|
{
|
|
[(TGGroupInfoUserCollectionItem *)item updateTimestamp];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)_updateUsers:(NSArray *)users
|
|
{
|
|
bool updatedAnyUser = false;
|
|
|
|
NSMutableDictionary *userIdToUser = [[NSMutableDictionary alloc] init];
|
|
for (TGUser *user in users)
|
|
{
|
|
userIdToUser[@(user.uid)] = user;
|
|
}
|
|
|
|
NSMutableArray *participantUsers = [[NSMutableArray alloc] init];
|
|
|
|
for (id item in _usersSection.items)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupInfoUserCollectionItem class]])
|
|
{
|
|
TGGroupInfoUserCollectionItem *userItem = item;
|
|
|
|
TGUser *user = userIdToUser[@(userItem.user.uid)];
|
|
if (user != nil)
|
|
{
|
|
updatedAnyUser = true;
|
|
[userItem setUser:user];
|
|
}
|
|
|
|
[participantUsers addObject:userItem.user];
|
|
}
|
|
}
|
|
|
|
if (updatedAnyUser)
|
|
{
|
|
[self _updateConversationWithLoadedUsers:participantUsers forceReload:false];
|
|
}
|
|
}
|
|
|
|
- (void)_layoutLeftLabel:(UIInterfaceOrientation)orientation
|
|
{
|
|
if (_leftLabel != nil)
|
|
{
|
|
CGSize screenSize = [TGViewController screenSizeForInterfaceOrientation:orientation];
|
|
CGSize labelSize = [_leftLabel sizeThatFits:CGSizeMake(screenSize.width - 10, screenSize.height)];
|
|
_leftLabel.frame = CGRectMake(CGFloor((screenSize.width - labelSize.width) / 2.0f), CGFloor((screenSize.height - labelSize.height) / 2.0f), labelSize.width, labelSize.height);
|
|
}
|
|
}
|
|
|
|
- (void)_updateLeftState
|
|
{
|
|
if ((_conversation.kickedFromChat || _conversation.leftChat || _conversation.isDeactivated) != (_leftLabel != nil))
|
|
{
|
|
if (_conversation.kickedFromChat || _conversation.leftChat || _conversation.isDeactivated)
|
|
{
|
|
_leftLabel = [[UILabel alloc] init];
|
|
_leftLabel.backgroundColor = [UIColor clearColor];
|
|
_leftLabel.textColor = UIColorRGB(0x999999);
|
|
if (_conversation.isDeactivated) {
|
|
_leftLabel.text = TGLocalized(@"GroupInfo.DeactivatedStatus");
|
|
} else {
|
|
_leftLabel.text = _conversation.kickedFromChat ? TGLocalized(@"GroupInfo.KickedStatus") : TGLocalized(@"GroupInfo.LeftStatus");
|
|
}
|
|
_leftLabel.font = TGSystemFontOfSize(17.0f);
|
|
_leftLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
|
_leftLabel.numberOfLines = 0;
|
|
[self.view addSubview:_leftLabel];
|
|
|
|
[self _layoutLeftLabel:self.interfaceOrientation];
|
|
|
|
[self setRightBarButtonItem:nil];
|
|
}
|
|
else
|
|
{
|
|
[_leftLabel removeFromSuperview];
|
|
_leftLabel = nil;
|
|
|
|
if (_editing)
|
|
{
|
|
[self setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Done") style:UIBarButtonItemStyleDone target:self action:@selector(donePressed)] animated:false];
|
|
}
|
|
else
|
|
{
|
|
[self setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Edit") style:UIBarButtonItemStylePlain target:self action:@selector(editPressed)] animated:false];
|
|
}
|
|
}
|
|
}
|
|
|
|
self.collectionView.hidden = _conversation.kickedFromChat || _conversation.leftChat || _conversation.isDeactivated;
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)actionStageActionRequested:(NSString *)action options:(id)options
|
|
{
|
|
if ([action isEqualToString:@"deleteUser"])
|
|
{
|
|
int32_t uid = [options[@"uid"] int32Value];
|
|
if (uid != 0)
|
|
[self _commitDeleteParticipant:uid];
|
|
}
|
|
else if ([action isEqualToString:@"openUser"])
|
|
{
|
|
int32_t uid = [options[@"uid"] int32Value];
|
|
if (uid != 0)
|
|
{
|
|
TGUser *user = [TGDatabaseInstance() loadUser:uid];
|
|
if (user.kind == TGUserKindBot || user.kind == TGUserKindSmartBot)
|
|
{
|
|
TGBotUserInfoController *userInfoController = [[TGBotUserInfoController alloc] initWithUid:uid sendCommand:nil];
|
|
[self.navigationController pushViewController:userInfoController animated:true];
|
|
}
|
|
else
|
|
{
|
|
TGTelegraphUserInfoController *userInfoController = [[TGTelegraphUserInfoController alloc] initWithUid:uid];
|
|
[self.navigationController pushViewController:userInfoController animated:true];
|
|
}
|
|
}
|
|
}
|
|
else if ([action isEqualToString:@"editedTitleChanged"])
|
|
{
|
|
NSString *title = options[@"title"];
|
|
|
|
if (_editing)
|
|
self.navigationItem.rightBarButtonItem.enabled = title.length != 0;
|
|
}
|
|
else if ([action isEqualToString:@"openAvatar"])
|
|
{
|
|
if (_conversation.chatPhotoSmall.length == 0)
|
|
{
|
|
if (_setGroupPhotoItem.enabled)
|
|
[self setGroupPhotoPressed];
|
|
}
|
|
else
|
|
{
|
|
TGRemoteImageView *avatarView = [_groupInfoItem avatarView];
|
|
|
|
if (avatarView != nil && avatarView.image != nil)
|
|
{
|
|
TGModernGalleryController *modernGallery = [[TGModernGalleryController alloc] init];
|
|
|
|
modernGallery.model = [[TGGroupAvatarGalleryModel alloc] initWithMessageId:0 legacyThumbnailUrl:_conversation.chatPhotoSmall legacyUrl:_conversation.chatPhotoBig imageSize:CGSizeMake(640.0f, 640.0f)];
|
|
|
|
__weak TGGroupInfoController *weakSelf = self;
|
|
|
|
modernGallery.itemFocused = ^(id<TGModernGalleryItem> item)
|
|
{
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupAvatarGalleryItem class]])
|
|
{
|
|
((UIView *)strongSelf->_groupInfoItem.avatarView).hidden = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
modernGallery.beginTransitionIn = ^UIView *(id<TGModernGalleryItem> item, __unused TGModernGalleryItemView *itemView)
|
|
{
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupAvatarGalleryItem class]])
|
|
{
|
|
return strongSelf->_groupInfoItem.avatarView;
|
|
}
|
|
}
|
|
|
|
return nil;
|
|
};
|
|
|
|
modernGallery.beginTransitionOut = ^UIView *(id<TGModernGalleryItem> item, __unused TGModernGalleryItemView *itemView)
|
|
{
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupAvatarGalleryItem class]])
|
|
{
|
|
return strongSelf->_groupInfoItem.avatarView;
|
|
}
|
|
}
|
|
|
|
return nil;
|
|
};
|
|
|
|
modernGallery.completedTransitionOut = ^
|
|
{
|
|
__strong TGGroupInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil)
|
|
{
|
|
((UIView *)strongSelf->_groupInfoItem.avatarView).hidden = false;
|
|
}
|
|
};
|
|
|
|
TGOverlayControllerWindow *controllerWindow = [[TGOverlayControllerWindow alloc] initWithParentController:self contentController:modernGallery];
|
|
controllerWindow.hidden = false;
|
|
}
|
|
}
|
|
}
|
|
else if ([action isEqualToString:@"showUpdatingAvatarOptions"])
|
|
{
|
|
[[[TGActionSheet alloc] initWithTitle:nil actions:@[
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"GroupInfo.SetGroupPhotoStop") action:@"stop" type:TGActionSheetActionTypeDestructive],
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"Common.Cancel") action:@"cancel" type:TGActionSheetActionTypeCancel]
|
|
] actionBlock:^(TGGroupInfoController *controller, NSString *action)
|
|
{
|
|
if ([action isEqualToString:@"stop"])
|
|
[controller _commitCancelAvatarUpdate];
|
|
} target:self] showInView:self.view];
|
|
}
|
|
}
|
|
|
|
- (void)actionStageResourceDispatched:(NSString *)path resource:(id)resource arguments:(id)__unused arguments
|
|
{
|
|
if ([path isEqualToString:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/conversation", _conversationId]])
|
|
{
|
|
TGConversation *conversation = ((SGraphObjectNode *)resource).object;
|
|
|
|
if (conversation != nil)
|
|
[self _loadUsersAndUpdateConversation:conversation];
|
|
}
|
|
else if ([path hasPrefix:@"/tg/peerSettings/"])
|
|
{
|
|
[self actorCompleted:ASStatusSuccess path:path result:resource];
|
|
}
|
|
else if ([path isEqualToString:@"/as/updateRelativeTimestamps"])
|
|
{
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
[self _updateRelativeTimestamps];
|
|
});
|
|
}
|
|
else if ([path isEqualToString:@"/tg/userdatachanges"] || [path isEqualToString:@"/tg/userpresencechanges"])
|
|
{
|
|
NSArray *users = ((SGraphObjectNode *)resource).object;
|
|
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
[self _updateUsers:users];
|
|
});
|
|
}
|
|
else if ([path isEqualToString:[[NSString alloc] initWithFormat:@"/tg/sharedMediaCount/(%" PRIx64 ")", (int64_t)_conversationId]])
|
|
{
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
_sharedMediaCount = [resource intValue];
|
|
[self _updateSharedMediaCount];
|
|
});
|
|
}
|
|
}
|
|
|
|
- (void)actorCompleted:(int)status path:(NSString *)path result:(id)result
|
|
{
|
|
if ([path hasPrefix:@"/tg/peerSettings/"])
|
|
{
|
|
if (status == ASStatusSuccess)
|
|
{
|
|
NSDictionary *notificationSettings = ((SGraphObjectNode *)result).object;
|
|
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
_groupNotificationSettings = [notificationSettings mutableCopy];
|
|
[self _updateNotificationItems:false];
|
|
});
|
|
}
|
|
}
|
|
else if ([path hasPrefix:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/addMember/", _conversation.conversationId]])
|
|
{
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
NSRange range = [path rangeOfString:@"/addMember/("];
|
|
int32_t uid = (int32_t)[[path substringFromIndex:(range.location + range.length)] intValue];
|
|
|
|
[_soonToBeAddedUserIds removeObject:@(uid)];
|
|
|
|
if (status == ASStatusSuccess)
|
|
{
|
|
TGConversation *updatedConversation = [_conversation copy];
|
|
updatedConversation.chatParticipants = [_conversation.chatParticipants copy];
|
|
int32_t currentDate = (int32_t)[[TGTelegramNetworking instance] approximateRemoteTime];
|
|
[updatedConversation.chatParticipants addParticipantWithId:uid invitedBy:TGTelegraphInstance.clientUserId date:currentDate];
|
|
_conversation = updatedConversation;
|
|
|
|
[self _updateLeftState];
|
|
|
|
for (id item in _usersSection.items)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupInfoUserCollectionItem class]] && ((TGGroupInfoUserCollectionItem *)item).user.uid == uid)
|
|
{
|
|
[(TGGroupInfoUserCollectionItem *)item setDisabled:false];
|
|
[(TGGroupInfoUserCollectionItem *)item setCanEdit:true animated:true];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
[self _loadUsersAndUpdateConversation:_conversation];
|
|
|
|
NSString *errorText = TGLocalized(@"ConversationProfile.UnknownAddMemberError");
|
|
if (status == -2)
|
|
{
|
|
TGUser *user = [TGDatabaseInstance() loadUser:uid];
|
|
if (user != nil)
|
|
errorText = [[NSString alloc] initWithFormat:TGLocalized(@"ConversationProfile.UserLeftChatError"), user.displayName];
|
|
}
|
|
else if (status == -3)
|
|
{
|
|
errorText = TGLocalized(@"ConversationProfile.UsersTooMuchError");
|
|
}
|
|
else if (status == -4)
|
|
errorText = TGLocalized(@"GroupInfo.AddUserLeftError");
|
|
else if (status == -5) {
|
|
NSString *format = TGLocalized(@"Privacy.GroupsAndChannels.InviteToGroupError");
|
|
TGUser *user = [TGDatabaseInstance() loadUser:uid];
|
|
errorText = [[NSString alloc] initWithFormat:format, user.displayFirstName, user.displayFirstName];
|
|
}
|
|
|
|
[[[TGAlertView alloc] initWithTitle:nil message:errorText cancelButtonTitle:TGLocalized(@"Common.OK") okButtonTitle:nil completionBlock:nil] show];
|
|
}
|
|
});
|
|
}
|
|
else if ([path hasPrefix:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/deleteMember/", _conversationId]])
|
|
{
|
|
NSRange range = [path rangeOfString:@"/deleteMember/("];
|
|
int32_t uid = (int32_t)[[path substringFromIndex:(range.location + range.length)] intValue];
|
|
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
[_soonToBeRemovedUserIds removeObject:@(uid)];
|
|
|
|
if (status == ASStatusSuccess)
|
|
{
|
|
TGConversation *updatedConversation = [_conversation copy];
|
|
updatedConversation.chatParticipants = [_conversation.chatParticipants copy];
|
|
[updatedConversation.chatParticipants removeParticipantWithId:uid];
|
|
_conversation = updatedConversation;
|
|
|
|
[self _updateLeftState];
|
|
|
|
for (id item in _usersSection.items)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupInfoUserCollectionItem class]] && ((TGGroupInfoUserCollectionItem *)item).user.uid == uid)
|
|
{
|
|
NSIndexPath *indexPath = [self indexPathForItem:item];
|
|
if (indexPath != nil)
|
|
{
|
|
[self.menuSections beginRecordingChanges];
|
|
[self.menuSections deleteItemFromSection:indexPath.section atIndex:indexPath.item];
|
|
[self.menuSections commitRecordedChanges:self.collectionView];
|
|
|
|
[self _updateAllowCellEditing:true];
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (id item in _usersSection.items)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupInfoUserCollectionItem class]] && ((TGGroupInfoUserCollectionItem *)item).user.uid == uid)
|
|
{
|
|
[(TGGroupInfoUserCollectionItem *)item setDisabled:false];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
else if ([path hasPrefix:[[NSString alloc] initWithFormat:@"/tg/conversation/(%" PRId64 ")/changeTitle/", _conversation.conversationId]])
|
|
{
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
[_groupInfoItem setUpdatingTitle:nil];
|
|
|
|
if (status == ASStatusSuccess)
|
|
{
|
|
TGConversation *resultConversation = ((SGraphObjectNode *)result).object;
|
|
|
|
TGConversation *updatedConversation = [_conversation copy];
|
|
updatedConversation.chatTitle = resultConversation.chatTitle;
|
|
_conversation = updatedConversation;
|
|
|
|
[self _updateLeftState];
|
|
|
|
[_groupInfoItem setConversation:_conversation];
|
|
}
|
|
});
|
|
}
|
|
else if ([path hasPrefix:[[NSString alloc] initWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/", _conversation.conversationId]])
|
|
{
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
if (status == ASStatusSuccess)
|
|
{
|
|
TGConversation *resultConversation = ((SGraphObjectNode *)result).object;
|
|
|
|
TGConversation *updatedConversation = [_conversation copy];
|
|
updatedConversation.chatPhotoSmall = resultConversation.chatPhotoSmall;
|
|
updatedConversation.chatPhotoMedium = resultConversation.chatPhotoMedium;
|
|
updatedConversation.chatPhotoBig = resultConversation.chatPhotoBig;
|
|
_conversation = updatedConversation;
|
|
|
|
[self _updateLeftState];
|
|
|
|
[_groupInfoItem copyUpdatingAvatarToCacheWithUri:_conversation.chatPhotoSmall];
|
|
[_groupInfoItem setConversation:_conversation];
|
|
|
|
[_groupInfoItem setUpdatingAvatar:nil hasUpdatingAvatar:false];
|
|
[_setGroupPhotoItem setEnabled:true];
|
|
}
|
|
else
|
|
{
|
|
[_groupInfoItem setUpdatingAvatar:nil hasUpdatingAvatar:false];
|
|
[_setGroupPhotoItem setEnabled:true];
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
- (void)chatAdminsPressed {
|
|
TGGroupAdminsController *controller = [[TGGroupAdminsController alloc] initWithPeerId:_conversationId];
|
|
[self.navigationController pushViewController:controller animated:true];
|
|
}
|
|
|
|
@end
|