mirror of
https://github.com/danog/Telegram.git
synced 2024-12-03 09:57:46 +01:00
1419 lines
62 KiB
Objective-C
1419 lines
62 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 "TGChannelInfoController.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 "TGInterfaceAssets.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 "TGUserInfoVariantCollectionItem.h"
|
|
#import "TGUserInfoTextCollectionItem.h"
|
|
#import "TGUserInfoUsernameCollectionItem.h"
|
|
#import "TGUserInfoButtonCollectionItem.h"
|
|
|
|
#import "TGSharedMediaController.h"
|
|
|
|
#import "TGTimerTarget.h"
|
|
|
|
#import "TGGroupManagementSignals.h"
|
|
#import "TGProgressWindow.h"
|
|
|
|
#import "TGGroupInfoShareLinkController.h"
|
|
|
|
#import "TGChannelLinkSetupController.h"
|
|
#import "TGChannelAboutSetupController.h"
|
|
|
|
#import "TGChannelManagementSignals.h"
|
|
|
|
#import "TGChannelMembersController.h"
|
|
|
|
#import "TGAccountSignals.h"
|
|
|
|
#import "TGReportPeerOtherTextController.h"
|
|
|
|
#import "TGMediaAvatarMenuMixin.h"
|
|
|
|
#import "TGCollectionMultilineInputItem.h"
|
|
|
|
#import "TGHashtagSearchController.h"
|
|
|
|
@interface TGChannelInfoController () <TGGroupInfoSelectContactControllerDelegate, TGAlertSoundControllerDelegate, ASWatcher>
|
|
{
|
|
bool _editing;
|
|
|
|
int64_t _peerId;
|
|
TGConversation *_conversation;
|
|
|
|
TGCollectionMenuSection *_groupInfoSection;
|
|
|
|
TGGroupInfoCollectionItem *_groupInfoItem;
|
|
TGButtonCollectionItem *_setGroupPhotoItem;
|
|
|
|
TGCollectionMenuSection *_infoSection;
|
|
TGUserInfoTextCollectionItem *_aboutItem;
|
|
TGUserInfoUsernameCollectionItem *_linkItem;
|
|
|
|
TGCollectionMenuSection *_leaveSection;
|
|
TGUserInfoButtonCollectionItem *_leaveItem;
|
|
|
|
TGCollectionMenuSection *_adminInfoSection;
|
|
TGUserInfoVariantCollectionItem *_infoManagementItem;
|
|
TGUserInfoVariantCollectionItem *_infoBlacklistItem;
|
|
TGUserInfoVariantCollectionItem *_infoMembersItem;
|
|
|
|
TGCollectionMenuSection *_editingInfoSection;
|
|
TGCollectionMultilineInputItem *_channelAboutItem;
|
|
TGVariantCollectionItem *_channelLinkItem;
|
|
TGSwitchCollectionItem *_channelCommentsItem;
|
|
|
|
TGCollectionMenuSection *_editingSignMessagesSection;
|
|
TGSwitchCollectionItem *_signMessagesItem;
|
|
|
|
TGCollectionMenuSection *_deleteChannelSection;
|
|
|
|
TGCollectionMenuSection *_notificationsAndMediaSection;
|
|
TGUserInfoVariantCollectionItem *_notificationsItem;
|
|
TGUserInfoVariantCollectionItem *_soundItem;
|
|
|
|
NSMutableDictionary *_groupNotificationSettings;
|
|
NSInteger _sharedMediaCount;
|
|
|
|
NSTimer *_muteExpirationTimer;
|
|
|
|
id<SDisposable> _completeInfoDisposable;
|
|
id<SDisposable> _cachedDataDisposable;
|
|
SDisposableSet *_genericDisposables;
|
|
|
|
NSString *_privateLink;
|
|
|
|
TGMediaAvatarMenuMixin *_avatarMixin;
|
|
}
|
|
|
|
@property (nonatomic, strong) ASHandle *actionHandle;
|
|
|
|
@end
|
|
|
|
@implementation TGChannelInfoController
|
|
|
|
- (instancetype)initWithPeerId:(int64_t)peerId
|
|
{
|
|
self = [super init];
|
|
if (self != nil)
|
|
{
|
|
__weak TGChannelInfoController *weakSelf = self;
|
|
|
|
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Back") style:UIBarButtonItemStylePlain target:self action:@selector(backPressed)];
|
|
|
|
_actionHandle = [[ASHandle alloc] initWithDelegate:self releaseOnMainThread:true];
|
|
|
|
_peerId = peerId;
|
|
_groupNotificationSettings = [[NSMutableDictionary alloc] initWithDictionary:@{@"muteUntil": @(0), @"soundId": @(1)}];
|
|
|
|
TGConversation *conversation = [TGDatabaseInstance() loadConversationWithId:_peerId];
|
|
|
|
if (conversation.chatIsAdmin) {
|
|
[self setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:TGLocalized(@"Common.Edit") style:UIBarButtonItemStylePlain target:self action:@selector(editPressed)] animated:false];
|
|
} else {
|
|
}
|
|
|
|
[self setTitleText:TGLocalized(@"Channel.TitleInfo")];
|
|
|
|
_groupInfoItem = [[TGGroupInfoCollectionItem alloc] init];
|
|
_groupInfoItem.interfaceHandle = _actionHandle;
|
|
_groupInfoItem.transparent = true;
|
|
_groupInfoItem.isChannel = true;
|
|
|
|
_setGroupPhotoItem = [[TGButtonCollectionItem alloc] initWithTitle:TGLocalized(@"Channel.UpdatePhotoItem") action:@selector(setGroupPhotoPressed)];
|
|
_setGroupPhotoItem.titleColor = TGAccentColor();
|
|
_setGroupPhotoItem.deselectAutomatically = true;
|
|
|
|
NSMutableArray *infoSectionItems = [[NSMutableArray alloc] init];
|
|
[infoSectionItems addObject:_groupInfoItem];
|
|
|
|
_groupInfoSection = [[TGCollectionMenuSection alloc] initWithItems:infoSectionItems];
|
|
_groupInfoSection.insets = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
NSString *linkText = _conversation.username.length == 0 ? @"" : [@"https://telegram.me/" stringByAppendingString:_conversation.username];
|
|
_aboutItem = [[TGUserInfoTextCollectionItem alloc] init];
|
|
_aboutItem.title = TGLocalized(@"Channel.Info.Description");
|
|
_aboutItem.text = _conversation.about;
|
|
_aboutItem.followLink = ^(NSString *link) {
|
|
TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf followLink:link];
|
|
}
|
|
};
|
|
_linkItem = [[TGUserInfoUsernameCollectionItem alloc] initWithLabel:TGLocalized(@"Channel.LinkItem") username:linkText];
|
|
_linkItem.action = @selector(sharePressed);
|
|
_infoSection = [[TGCollectionMenuSection alloc] initWithItems:@[_aboutItem, _linkItem]];
|
|
_infoSection.insets = UIEdgeInsetsMake(1.0f, 0.0f, 22.0f, 0.0f);
|
|
|
|
TGUserInfoButtonCollectionItem *reportChannelItem = [[TGUserInfoButtonCollectionItem alloc] initWithTitle:TGLocalized(@"ReportPeer.Report") action:@selector(reportChannelPressed)];
|
|
reportChannelItem.deselectAutomatically = true;
|
|
|
|
_leaveItem = [[TGUserInfoButtonCollectionItem alloc] initWithTitle:TGLocalized(@"Channel.LeaveChannel") action:@selector(leavePressed)];
|
|
_leaveItem.titleColor = TGDestructiveAccentColor();
|
|
_leaveItem.deselectAutomatically = true;
|
|
_leaveSection = [[TGCollectionMenuSection alloc] initWithItems:@[reportChannelItem, _leaveItem]];
|
|
|
|
TGButtonCollectionItem *deleteChannelItem = [[TGButtonCollectionItem alloc] initWithTitle:TGLocalized(@"ChannelInfo.DeleteChannel") action:@selector(deleteChannelPressed)];
|
|
deleteChannelItem.titleColor = TGDestructiveAccentColor();
|
|
deleteChannelItem.deselectAutomatically = true;
|
|
_deleteChannelSection = [[TGCollectionMenuSection alloc] initWithItems:@[deleteChannelItem]];
|
|
|
|
_infoManagementItem = [[TGUserInfoVariantCollectionItem alloc] initWithTitle:TGLocalized(@"Channel.Info.Management") variant:@"" action:@selector(infoManagementPressed)];
|
|
_infoBlacklistItem = [[TGUserInfoVariantCollectionItem alloc] initWithTitle:TGLocalized(@"Channel.Info.BlackList") variant:@"" action:@selector(infoBlacklistPressed)];
|
|
_infoMembersItem = [[TGUserInfoVariantCollectionItem alloc] initWithTitle:TGLocalized(@"Channel.Info.Members") variant:@"" action:@selector(infoMembersPressed)];
|
|
_adminInfoSection = [[TGCollectionMenuSection alloc] initWithItems:@[_infoManagementItem, _infoMembersItem]];
|
|
|
|
_channelAboutItem = [[TGCollectionMultilineInputItem alloc] init];
|
|
_channelAboutItem.placeholder = TGLocalized(@"Channel.About.Placeholder");
|
|
_channelAboutItem.text = _conversation.about;
|
|
_channelAboutItem.textChanged = ^(__unused NSString *text) {
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf.collectionLayout invalidateLayout];
|
|
[strongSelf.collectionView layoutSubviews];
|
|
}
|
|
};
|
|
_channelAboutItem.maxLength = 200;
|
|
|
|
_channelLinkItem = [[TGVariantCollectionItem alloc] initWithTitle:TGLocalized(@"Channel.Edit.LinkItem") action:@selector(linkPressed)];
|
|
_channelLinkItem.variant = _conversation.username.length == 0 ? @"" : [@"/" stringByAppendingString:_conversation.username];
|
|
|
|
_channelCommentsItem = [[TGSwitchCollectionItem alloc] initWithTitle:TGLocalized(@"Channel.Edit.EnableComments") isOn:!_conversation.channelIsReadOnly];
|
|
_channelCommentsItem.toggled = ^(bool value){
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf toggleCommentsEnabled:value];
|
|
}
|
|
};
|
|
__unused TGCommentCollectionItem *commentsHelp = [[TGCommentCollectionItem alloc] initWithFormattedText:TGLocalized(@"Channel.Username.CreateCommentsHelp")];
|
|
_editingInfoSection = [[TGCollectionMenuSection alloc] initWithItems:@[_channelLinkItem, _channelAboutItem, [[TGCommentCollectionItem alloc] initWithFormattedText:TGLocalized(@"Channel.About.Help")]]];
|
|
|
|
_signMessagesItem = [[TGSwitchCollectionItem alloc] initWithTitle:TGLocalized(@"Channel.SignMessages") isOn:false];
|
|
_signMessagesItem.toggled = ^(bool value) {
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf updateSignMessages:value];
|
|
}
|
|
};
|
|
_editingSignMessagesSection = [[TGCollectionMenuSection alloc] initWithItems:@[_signMessagesItem, [[TGCommentCollectionItem alloc] initWithFormattedText:TGLocalized(@"Channel.SignMessages.Help")]]];
|
|
|
|
_notificationsItem = [[TGUserInfoVariantCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.Notifications") variant:nil action:@selector(notificationsPressed)];
|
|
_notificationsItem.deselectAutomatically = true;
|
|
_soundItem = [[TGUserInfoVariantCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.Sound") variant:nil action:@selector(soundPressed)];
|
|
_soundItem.deselectAutomatically = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
|
|
|
|
TGUserInfoVariantCollectionItem *_sharedMediaItem = [[TGUserInfoVariantCollectionItem alloc] initWithTitle:TGLocalized(@"GroupInfo.SharedMedia") variant:@"" action:@selector(sharedMediaPressed)];
|
|
|
|
_notificationsAndMediaSection = [[TGCollectionMenuSection alloc] initWithItems:@[_notificationsItem, _sharedMediaItem]];
|
|
UIEdgeInsets notificationsAndMediaSectionInsets = _notificationsAndMediaSection.insets;
|
|
notificationsAndMediaSectionInsets.bottom = 22.0f;
|
|
_notificationsAndMediaSection.insets = notificationsAndMediaSectionInsets;
|
|
|
|
[self _loadUsersAndUpdateConversation:conversation];
|
|
|
|
[self _updateNotificationItems:false];
|
|
[self _updateSharedMediaCount];
|
|
|
|
int64_t accessHash = _conversation.accessHash;
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
[ActionStageInstance() watchForPaths:@[
|
|
[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/conversation", _peerId],
|
|
//@"/tg/userdatachanges",
|
|
//@"/tg/userpresencechanges",
|
|
//@"/as/updateRelativeTimestamps",
|
|
//[[NSString alloc] initWithFormat:@"/tg/sharedMediaCount/(%" PRIx64 ")", (int64_t)_conversationId]
|
|
] watcher:self];
|
|
|
|
[ActionStageInstance() watchForPath:[NSString stringWithFormat:@"/tg/peerSettings/(%" PRId64 ")", _peerId] watcher:self];
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/peerSettings/(%" PRId64 ",cachedOnly)", _peerId] options:@{@"peerId": @(_peerId), @"accessHash": @(accessHash)} watcher:self];
|
|
|
|
NSArray *changeTitleActions = [ActionStageInstance() rejoinActionsWithGenericPathNow:@"/tg/conversation/@/changeTitle/@" prefix:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")", _peerId] watcher:self];
|
|
NSArray *changeAvatarActions = [ActionStageInstance() rejoinActionsWithGenericPathNow:@"/tg/conversation/@/updateAvatar/@" prefix:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")", _peerId] 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 (changeTitleActions.count != 0 || changeAvatarActions.count != 0)
|
|
{
|
|
TGDispatchOnMainThread(^ {
|
|
[_groupInfoItem setUpdatingTitle:updatingTitle];
|
|
|
|
[_groupInfoItem setUpdatingAvatar:updatingAvatar hasUpdatingAvatar:haveUpdatingAvatar];
|
|
[_setGroupPhotoItem setEnabled:!haveUpdatingAvatar];
|
|
|
|
[self _loadUsersAndUpdateConversation:_conversation];
|
|
});
|
|
}
|
|
}];
|
|
|
|
_completeInfoDisposable = [[TGChannelManagementSignals updateChannelExtendedInfo:_conversation.conversationId accessHash:_conversation.accessHash updateUnread:true] startWithNext:nil];
|
|
|
|
_cachedDataDisposable = [[[TGDatabaseInstance() channelCachedData:_conversation.conversationId] deliverOn:[SQueue mainQueue]] startWithNext:^(TGCachedConversationData *cachedData) {
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil && cachedData != nil) {
|
|
[strongSelf->_infoManagementItem setVariant:[[NSString alloc] initWithFormat:@"%d", cachedData.managementCount]];
|
|
[strongSelf->_infoBlacklistItem setVariant:[[NSString alloc] initWithFormat:@"%d", cachedData.blacklistCount]];
|
|
[strongSelf->_infoMembersItem setVariant:[[NSString alloc] initWithFormat:@"%d", cachedData.memberCount]];
|
|
strongSelf->_privateLink = cachedData.privateLink;
|
|
}
|
|
}];
|
|
|
|
_genericDisposables = [[SDisposableSet alloc] init];
|
|
|
|
[self _setupSections:false];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)_setupSections:(bool)editing {
|
|
while (self.menuSections.sections.count != 0) {
|
|
[self.menuSections deleteSection:0];
|
|
}
|
|
|
|
if (editing) {
|
|
_groupInfoItem.transparent = false;
|
|
if ([_groupInfoSection indexOfItem:_setGroupPhotoItem] == NSNotFound) {
|
|
[_groupInfoSection insertItem:_setGroupPhotoItem atIndex:1];
|
|
}
|
|
_groupInfoSection.insets = UIEdgeInsetsMake(0.0f, 0.0f, 35.0f, 0.0f);
|
|
|
|
[self.menuSections addSection:_groupInfoSection];
|
|
[self.menuSections addSection:_editingInfoSection];
|
|
|
|
if (_conversation.channelRole == TGChannelRoleCreator) {
|
|
[self.menuSections addSection:_editingSignMessagesSection];
|
|
}
|
|
|
|
if (_conversation.channelRole == TGChannelRoleCreator) {
|
|
[self.menuSections addSection:_deleteChannelSection];
|
|
}
|
|
|
|
self.collectionView.backgroundColor = [TGInterfaceAssets listsBackgroundColor];
|
|
} else {
|
|
_groupInfoItem.transparent = true;
|
|
[_groupInfoSection deleteItem:_setGroupPhotoItem];
|
|
_groupInfoSection.insets = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
[self.menuSections addSection:_groupInfoSection];
|
|
[self.menuSections addSection:_infoSection];
|
|
if (_conversation.channelRole == TGChannelRoleCreator || _conversation.channelRole == TGChannelRoleModerator || _conversation.channelRole == TGChannelRolePublisher) {
|
|
[self.menuSections addSection:_adminInfoSection];
|
|
}
|
|
[self.menuSections addSection:_notificationsAndMediaSection];
|
|
if (_conversation.kind == TGConversationKindPersistentChannel && _conversation.channelRole != TGChannelRoleCreator) {
|
|
[self.menuSections addSection:_leaveSection];
|
|
}
|
|
self.collectionView.backgroundColor = [UIColor whiteColor];
|
|
}
|
|
|
|
[self.collectionView reloadData];
|
|
}
|
|
|
|
- (void)backPressed
|
|
{
|
|
[self.navigationController popViewControllerAnimated:true];
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[_actionHandle reset];
|
|
[ActionStageInstance() removeWatcher:self];
|
|
|
|
[_completeInfoDisposable dispose];
|
|
[_cachedDataDisposable dispose];
|
|
[_genericDisposables dispose];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)_resetCollectionView
|
|
{
|
|
[super _resetCollectionView];
|
|
|
|
self.view.backgroundColor = [UIColor whiteColor];
|
|
self.collectionView.backgroundColor = [UIColor whiteColor];
|
|
[self.collectionView setAllowEditingCells:false animated:false];
|
|
}
|
|
|
|
- (void)viewWillAppear:(BOOL)animated
|
|
{
|
|
[super viewWillAppear:animated];
|
|
}
|
|
|
|
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
|
|
{
|
|
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)editPressed
|
|
{
|
|
if (!_editing)
|
|
{
|
|
_editing = true;
|
|
|
|
[_groupInfoItem setEditing:true animated:false];
|
|
[self _setupSections:true];
|
|
[self enterEditingMode:true];
|
|
|
|
[self animateCollectionCrossfade];
|
|
}
|
|
}
|
|
|
|
- (void)donePressed
|
|
{
|
|
if (_editing)
|
|
{
|
|
__weak TGChannelInfoController *weakSelf = self;
|
|
void (^block)() = ^{
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
strongSelf->_editing = false;
|
|
|
|
if (!TGStringCompare(strongSelf->_conversation.chatTitle, [strongSelf->_groupInfoItem editingTitle]) && [strongSelf->_groupInfoItem editingTitle] != nil)
|
|
[strongSelf _commitUpdateTitle:[strongSelf->_groupInfoItem editingTitle]];
|
|
|
|
[strongSelf->_groupInfoItem setEditing:false animated:false];
|
|
[strongSelf _setupSections:false];
|
|
[strongSelf leaveEditingMode:true];
|
|
|
|
[strongSelf animateCollectionCrossfade];
|
|
}
|
|
};
|
|
|
|
if (!TGStringCompare(_channelAboutItem.text, _conversation.about)) {
|
|
TGProgressWindow *progressWindow = [[TGProgressWindow alloc] init];
|
|
[progressWindow showWithDelay:0.2];
|
|
|
|
[[[[TGChannelManagementSignals updateChannelAbout:_conversation.conversationId accessHash:_conversation.accessHash about:_channelAboutItem.text] deliverOn:[SQueue mainQueue]] onDispose:^{
|
|
TGDispatchOnMainThread(^{
|
|
[progressWindow dismiss:true];
|
|
});
|
|
}] startWithNext:nil error:^(__unused id error) {
|
|
[[[TGAlertView alloc] initWithTitle:nil message:TGLocalized(@"Channel.About.Error") cancelButtonTitle:TGLocalized(@"Common.OK") okButtonTitle:nil completionBlock:nil] show];
|
|
} completed:^{
|
|
block();
|
|
}];
|
|
} else {
|
|
block();
|
|
}
|
|
}
|
|
|
|
[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 (!_conversation.chatIsAdmin)
|
|
return;
|
|
|
|
__weak TGChannelInfoController *weakSelf = self;
|
|
_avatarMixin = [[TGMediaAvatarMenuMixin alloc] initWithParentController:self hasDeleteButton:(_conversation.chatPhotoSmall.length != 0)];
|
|
_avatarMixin.didFinishWithImage = ^(UIImage *image)
|
|
{
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf _updateGroupProfileImage:image];
|
|
strongSelf->_avatarMixin = nil;
|
|
};
|
|
_avatarMixin.didFinishWithDelete = ^
|
|
{
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf == nil)
|
|
return;
|
|
|
|
[strongSelf _commitDeleteAvatar];
|
|
strongSelf->_avatarMixin = nil;
|
|
};
|
|
_avatarMixin.didDismiss = ^
|
|
{
|
|
__strong TGChannelInfoController *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"];
|
|
uploadOptions[@"accessHash"] = @(_conversation.accessHash);
|
|
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
static int actionId = 0;
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/(updateAvatar%d)", _peerId, actionId] options:uploadOptions watcher:self];
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/(updateAvatar%d)", _peerId, 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"];
|
|
uploadOptions[@"accessHash"] = @(_conversation.accessHash);
|
|
|
|
[ActionStageInstance() dispatchOnStageQueue:^
|
|
{
|
|
static int actionId = 0;
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/(deleteAvatar%d)", _peerId, actionId] options:uploadOptions watcher:self];
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/conversation/(%" PRId64 ")/updateAvatar/(deleteAvatar%d)", _peerId, 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/", _peerId]];
|
|
for (ASActor *actor in actors)
|
|
{
|
|
[ActionStageInstance() removeAllWatchersFromPath:actor.path];
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (void)legacyCameraControllerCompletedWithNoResult
|
|
{
|
|
[self dismissViewControllerAnimated:true completion:nil];
|
|
}
|
|
|
|
- (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:^(TGChannelInfoController *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)", _peerId, actionId++] options:@{@"peerId": @(_peerId), @"accessHash": @(_conversation.accessHash), @"muteUntil": @(muteUntil)} watcher:TGTelegraphInstance];
|
|
[self _updateNotificationItems:false];
|
|
}
|
|
}
|
|
- (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++];
|
|
NSMutableDictionary *options = [[NSMutableDictionary alloc] initWithDictionary:@{@"conversationId": @(_peerId), @"title": title == nil ? @"" : title}];
|
|
options[@"accessHash"] = @(_conversation.accessHash);
|
|
|
|
[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"])
|
|
{
|
|
TGChannelInfoController *strongSelf = weakSelf;
|
|
[strongSelf _commitLeaveGroup];
|
|
}
|
|
} target:self] showInView:self.view];
|
|
}
|
|
|
|
- (void)_commitLeaveGroup
|
|
{
|
|
[TGAppDelegateInstance.rootController.dialogListController.dialogListCompanion deleteItem:[[TGConversation alloc] initWithConversationId:_peerId 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": @(_peerId), @"accessHash": @(_conversation.accessHash), @"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)", _peerId, actionId++] options:@{@"peerId": @(_peerId), @"accessHash": @(_conversation.accessHash), @"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;
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)_updateNotificationItems:(bool)__unused animated
|
|
{
|
|
[_muteExpirationTimer invalidate];
|
|
_muteExpirationTimer = nil;
|
|
|
|
NSString *variant = TGLocalized(@"UserInfo.NotificationsEnabled");
|
|
int muteUntil = [_groupNotificationSettings[@"muteUntil"] intValue];
|
|
if (muteUntil <= [[TGTelegramNetworking instance] approximateRemoteTime])
|
|
{
|
|
variant = TGLocalized(@"UserInfo.NotificationsEnabled");
|
|
}
|
|
else
|
|
{
|
|
int muteExpiration = muteUntil - (int)[[TGTelegramNetworking instance] approximateRemoteTime];
|
|
if (muteExpiration >= 7 * 24 * 60 * 60)
|
|
variant = TGLocalized(@"UserInfo.NotificationsDisabled");
|
|
else
|
|
{
|
|
variant = [TGStringUtils stringForRemainingMuteInterval:muteExpiration];
|
|
|
|
_muteExpirationTimer = [TGTimerTarget scheduledMainThreadTimerWithTarget:self action:@selector(updateMuteExpiration) interval:2.0 repeat:true];
|
|
}
|
|
}
|
|
|
|
[_notificationsItem setVariant:variant];
|
|
|
|
int groupSoundId = [[_groupNotificationSettings objectForKey:@"soundId"] intValue];
|
|
_soundItem.variant = [self soundNameFromId:groupSoundId];
|
|
}
|
|
|
|
- (void)updateMuteExpiration
|
|
{
|
|
NSString *variant = TGLocalized(@"UserInfo.NotificationsEnabled");
|
|
int muteUntil = [_groupNotificationSettings[@"muteUntil"] intValue];
|
|
if (muteUntil <= [[TGTelegramNetworking instance] approximateRemoteTime])
|
|
{
|
|
variant = TGLocalized(@"UserInfo.NotificationsEnabled");
|
|
}
|
|
else
|
|
{
|
|
int muteExpiration = muteUntil - (int)[[TGTelegramNetworking instance] approximateRemoteTime];
|
|
variant = [TGStringUtils stringForRemainingMuteInterval:muteExpiration];
|
|
}
|
|
|
|
if (!TGStringCompare(_notificationsItem.variant, variant))
|
|
{
|
|
[_notificationsItem setVariant:variant];
|
|
}
|
|
}
|
|
|
|
- (void)_updateSharedMediaCount
|
|
{
|
|
}
|
|
|
|
- (void)_loadUsersAndUpdateConversation:(TGConversation *)conversation
|
|
{
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
bool reloadData = false;
|
|
|
|
if (_conversation.channelRole != conversation.channelRole) {
|
|
reloadData = true;
|
|
}
|
|
|
|
_conversation = conversation;
|
|
[_groupInfoItem setConversation:_conversation];
|
|
|
|
NSString *linkText = _conversation.username.length == 0 ? @"" : [@"https://telegram.me/" stringByAppendingString:_conversation.username];
|
|
|
|
if (!TGStringCompare(_aboutItem.text, _conversation.about)) {
|
|
reloadData = true;
|
|
}
|
|
|
|
_aboutItem.text = _conversation.about;
|
|
_linkItem.username = linkText;
|
|
|
|
if (_aboutItem.text.length == 0) {
|
|
if ([_infoSection deleteItem:_aboutItem]) {
|
|
reloadData = true;
|
|
}
|
|
} else {
|
|
NSUInteger aboutIndex = [_infoSection indexOfItem:_aboutItem];
|
|
if (aboutIndex == NSNotFound) {
|
|
reloadData = true;
|
|
[_infoSection insertItem:_aboutItem atIndex:0];
|
|
}
|
|
}
|
|
|
|
if (_linkItem.username.length == 0) {
|
|
if ([_infoSection deleteItem:_linkItem]) {
|
|
reloadData = true;
|
|
}
|
|
} else {
|
|
NSUInteger linkIndex = [_infoSection indexOfItem:_linkItem];
|
|
if (linkIndex == NSNotFound) {
|
|
reloadData = true;
|
|
[_infoSection addItem:_linkItem];
|
|
}
|
|
}
|
|
|
|
if (_channelCommentsItem.isOn != !conversation.channelIsReadOnly) {
|
|
[_channelCommentsItem setIsOn:!conversation.channelIsReadOnly animated:true];
|
|
}
|
|
|
|
if (!_editing) {
|
|
_channelAboutItem.text = conversation.about;
|
|
}
|
|
_channelLinkItem.variant = conversation.username.length == 0 ? @"" : [@"/" stringByAppendingString:conversation.username];
|
|
|
|
bool forceReload = false;
|
|
|
|
if (_signMessagesItem.isOn != _conversation.signaturesEnabled) {
|
|
_signMessagesItem.isOn = _conversation.signaturesEnabled;
|
|
}
|
|
|
|
[self _updateConversationWithLoadedUsers:nil forceReload:forceReload];
|
|
|
|
if (reloadData) {
|
|
[self _setupSections:_editing];
|
|
}
|
|
});
|
|
}
|
|
|
|
- (void)_updateConversationWithLoadedUsers:(NSArray *)__unused participantUsers forceReload:(bool)__unused forceReload
|
|
{
|
|
}
|
|
|
|
- (void)_updateRelativeTimestamps
|
|
{
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)actionStageActionRequested:(NSString *)action options:(id)options
|
|
{
|
|
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 TGChannelInfoController *weakSelf = self;
|
|
|
|
modernGallery.itemFocused = ^(id<TGModernGalleryItem> item)
|
|
{
|
|
__strong TGChannelInfoController *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 TGChannelInfoController *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 TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil)
|
|
{
|
|
if ([item isKindOfClass:[TGGroupAvatarGalleryItem class]])
|
|
{
|
|
return strongSelf->_groupInfoItem.avatarView;
|
|
}
|
|
}
|
|
|
|
return nil;
|
|
};
|
|
|
|
modernGallery.completedTransitionOut = ^
|
|
{
|
|
__strong TGChannelInfoController *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:^(TGChannelInfoController *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", _peerId]])
|
|
{
|
|
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)_peerId]])
|
|
{
|
|
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 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;
|
|
|
|
[_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;
|
|
|
|
[_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)aboutPressed {
|
|
TGChannelAboutSetupController *aboutController = [[TGChannelAboutSetupController alloc] initWithConversation:_conversation];
|
|
TGNavigationController *navigationController = [TGNavigationController navigationControllerWithControllers:@[aboutController]];
|
|
[self presentViewController:navigationController animated:true completion:nil];
|
|
}
|
|
|
|
- (void)linkPressed {
|
|
TGChannelLinkSetupController *linkController = [[TGChannelLinkSetupController alloc] initWithConversation:_conversation];
|
|
TGNavigationController *navigationController = [TGNavigationController navigationControllerWithControllers:@[linkController]];
|
|
[self presentViewController:navigationController animated:true completion:nil];
|
|
}
|
|
|
|
- (void)sharePressed {
|
|
if (_conversation.username.length != 0) {
|
|
NSString *aboutText = _conversation.about;
|
|
if (aboutText == nil) {
|
|
aboutText = @"";
|
|
}
|
|
if (aboutText.length > 200) {
|
|
aboutText = [[aboutText substringToIndex:200] stringByAppendingString:@"..."];
|
|
}
|
|
NSString *linkText = [[NSString alloc] initWithFormat:@"https://telegram.me/%@%@%@", _conversation.username, aboutText.length == 0 ? @"" : @"\n", aboutText];
|
|
|
|
NSArray *dataToShare = @[linkText];
|
|
|
|
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:nil];
|
|
[self presentViewController:activityViewController animated:YES completion:nil];
|
|
} else {
|
|
__weak TGChannelInfoController *weakSelf = self;
|
|
[[[TGAlertView alloc] initWithTitle:TGLocalized(@"Channel.ShareNoLink") message:nil cancelButtonTitle:TGLocalized(@"Common.OK") okButtonTitle:nil completionBlock:^(__unused bool okButtonPressed) {
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf linkPressed];
|
|
}
|
|
}] show];
|
|
}
|
|
}
|
|
|
|
- (void)leavePressed {
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
[[[TGActionSheet alloc] initWithTitle:nil actions:@[
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"ChannelInfo.ConfirmLeave") action:@"leave" type:TGActionSheetActionTypeDestructive],
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"Common.Cancel") action:@"cancel" type:TGActionSheetActionTypeCancel]
|
|
] actionBlock:^(__unused id target, NSString *action)
|
|
{
|
|
if ([action isEqualToString:@"leave"])
|
|
{
|
|
TGChannelInfoController *strongSelf = weakSelf;
|
|
[strongSelf _commitLeaveChannel];
|
|
}
|
|
} target:self] showInView:self.view];
|
|
}
|
|
|
|
- (void)_commitLeaveChannel
|
|
{
|
|
[TGAppDelegateInstance.rootController.dialogListController.dialogListCompanion deleteItem:[[TGConversation alloc] initWithConversationId:_peerId 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)_commitDeleteChannel
|
|
{
|
|
TGProgressWindow *progressWindow = [[TGProgressWindow alloc] init];
|
|
[progressWindow show:true];
|
|
|
|
[[[[TGChannelManagementSignals deleteChannel:_conversation.conversationId accessHash:_conversation.accessHash] deliverOn:[SQueue mainQueue]] onDispose:^{
|
|
TGDispatchOnMainThread(^{
|
|
[progressWindow dismiss:true];
|
|
});
|
|
}] startWithNext:nil completed:^{
|
|
[TGAppDelegateInstance.rootController.dialogListController.dialogListCompanion deleteItem:[[TGConversation alloc] initWithConversationId:_peerId 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)toggleCommentsEnabled:(bool)value {
|
|
TGProgressWindow *progressWindow = [[TGProgressWindow alloc] init];
|
|
[progressWindow show:true];
|
|
|
|
__weak TGChannelInfoController *weakSelf = self;
|
|
[[[[TGChannelManagementSignals toggleChannelCommentsEnabled:_conversation.conversationId accessHash:_conversation.accessHash enabled:value] deliverOn:[SQueue mainQueue]] onDispose:^{
|
|
TGDispatchOnMainThread(^{
|
|
[progressWindow dismiss:true];
|
|
});
|
|
}] startWithNext:nil error:^(__unused id error) {
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf->_channelCommentsItem setIsOn:!value animated:true];
|
|
}
|
|
} completed:^{
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf->_channelCommentsItem setIsOn:value animated:true];
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (void)infoManagementPressed {
|
|
[self.navigationController pushViewController:[[TGChannelMembersController alloc] initWithConversation:_conversation mode:TGChannelMembersModeAdmins] animated:true];
|
|
}
|
|
|
|
- (void)infoBlacklistPressed {
|
|
[self.navigationController pushViewController:[[TGChannelMembersController alloc] initWithConversation:_conversation mode:TGChannelMembersModeBlacklist] animated:true];
|
|
}
|
|
|
|
- (void)infoMembersPressed {
|
|
[self.navigationController pushViewController:[[TGChannelMembersController alloc] initWithConversation:_conversation mode:TGChannelMembersModeMembers] animated:true];
|
|
}
|
|
|
|
- (void)sharedMediaPressed {
|
|
TGSharedMediaController *controller = [[TGSharedMediaController alloc] initWithPeerId:_peerId accessHash:_conversation.accessHash important:true];
|
|
controller.channelAllowDelete = _conversation.channelRole == TGChannelRoleCreator;
|
|
[self.navigationController pushViewController:controller animated:true];
|
|
}
|
|
|
|
- (void)deleteChannelPressed {
|
|
__weak typeof(self) weakSelf = self;
|
|
|
|
[[[TGActionSheet alloc] initWithTitle:TGLocalized(@"ChannelInfo.DeleteChannelConfirmation") actions:@[
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"ChannelInfo.DeleteChannel") action:@"leave" type:TGActionSheetActionTypeDestructive],
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"Common.Cancel") action:@"cancel" type:TGActionSheetActionTypeCancel]
|
|
] actionBlock:^(__unused id target, NSString *action)
|
|
{
|
|
if ([action isEqualToString:@"leave"])
|
|
{
|
|
TGChannelInfoController *strongSelf = weakSelf;
|
|
[strongSelf _commitDeleteChannel];
|
|
}
|
|
} target:self] showInView:self.view];
|
|
}
|
|
|
|
- (void)reportChannelPressed {
|
|
__weak TGChannelInfoController *weakSelf = self;
|
|
[[[TGActionSheet alloc] initWithTitle:nil actions:@[
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"ReportPeer.ReasonSpam") action:@"spam"],
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"ReportPeer.ReasonViolence") action:@"violence"],
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"ReportPeer.ReasonPornography") action:@"pornography"],
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"ReportPeer.ReasonOther") action:@"other"],
|
|
[[TGActionSheetAction alloc] initWithTitle:TGLocalized(@"Common.Cancel") action:@"cancel" type:TGActionSheetActionTypeCancel]] actionBlock:^(__unused id target, NSString *action) {
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
if (![action isEqualToString:@"cancel"]) {
|
|
TGReportPeerReason reason = TGReportPeerReasonSpam;
|
|
if ([action isEqualToString:@"spam"]) {
|
|
reason = TGReportPeerReasonSpam;
|
|
} else if ([action isEqualToString:@"violence"]) {
|
|
reason = TGReportPeerReasonViolence;
|
|
} else if ([action isEqualToString:@"pornography"]) {
|
|
reason = TGReportPeerReasonPornography;
|
|
} else if ([action isEqualToString:@"other"]) {
|
|
reason = TGReportPeerReasonOther;
|
|
}
|
|
|
|
void (^reportBlock)(NSString *) = ^(NSString *otherText) {
|
|
TGProgressWindow *progressWindow = [[TGProgressWindow alloc] init];
|
|
[progressWindow showWithDelay:0.1];
|
|
|
|
[[[[TGAccountSignals reportPeer:strongSelf->_conversation.conversationId accessHash:strongSelf->_conversation.accessHash reason:reason otherText:otherText] deliverOn:[SQueue mainQueue]] onDispose:^{
|
|
TGDispatchOnMainThread(^{
|
|
[progressWindow dismiss:true];
|
|
});
|
|
}] startWithNext:nil error:^(__unused id error) {
|
|
if (NSClassFromString(@"UIAlertController") != nil) {
|
|
|
|
} else {
|
|
[[[TGAlertView alloc] initWithTitle:nil message:TGLocalized(@"TwoStepAuth.GenericError") cancelButtonTitle:TGLocalized(@"Common.OK") okButtonTitle:nil completionBlock:nil] show];
|
|
}
|
|
} completed:^{
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf dismissViewControllerAnimated:true completion:nil];
|
|
}
|
|
|
|
if (NSClassFromString(@"UIAlertController") != nil) {
|
|
UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:nil message:TGLocalized(@"ReportPeer.AlertSuccess") preferredStyle:UIAlertControllerStyleAlert];
|
|
|
|
UIAlertAction *doneAction = [UIAlertAction actionWithTitle:TGLocalized(@"Common.OK") style:UIAlertActionStyleDefault handler:nil];
|
|
[alertVC addAction:doneAction];
|
|
|
|
[strongSelf presentViewController:alertVC animated:true completion:nil];
|
|
} else {
|
|
[[[TGAlertView alloc] initWithTitle:nil message:TGLocalized(@"ReportPeer.AlertSuccess") cancelButtonTitle:TGLocalized(@"Common.OK") okButtonTitle:nil completionBlock:nil] show];
|
|
}
|
|
}];
|
|
};
|
|
|
|
if (reason == TGReportPeerReasonOther) {
|
|
TGReportPeerOtherTextController *controller = [[TGReportPeerOtherTextController alloc] initWithCompletion:^(NSString *text) {
|
|
if (text.length != 0) {
|
|
reportBlock(text);
|
|
}
|
|
}];
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf presentViewController:[TGNavigationController navigationControllerWithControllers:@[controller]] animated:true completion:nil];
|
|
}
|
|
} else {
|
|
reportBlock(nil);
|
|
}
|
|
}
|
|
}
|
|
} target:self] showInView:self.view];
|
|
}
|
|
|
|
- (void)updateSignMessages:(bool)value {
|
|
TGProgressWindow *progressWindow = [[TGProgressWindow alloc] init];
|
|
[progressWindow showWithDelay:0.2];
|
|
|
|
[[[[TGChannelManagementSignals updateChannelSignaturesEnabled:_conversation.conversationId accessHash:_conversation.accessHash enabled:value] deliverOn:[SQueue mainQueue]] onDispose:^{
|
|
TGDispatchOnMainThread(^{
|
|
[progressWindow dismiss:true];
|
|
});
|
|
}] startWithNext:nil];
|
|
}
|
|
|
|
- (void)followLink:(NSString *)link {
|
|
if ([link hasPrefix:@"mention://"])
|
|
{
|
|
NSString *domain = [link substringFromIndex:@"mention://".length];
|
|
[ActionStageInstance() requestActor:[[NSString alloc] initWithFormat:@"/resolveDomain/(%@,profile)", domain] options:@{@"domain": domain, @"profile": @true} flags:0 watcher:TGTelegraphInstance];
|
|
}
|
|
else if ([link hasPrefix:@"hashtag://"])
|
|
{
|
|
NSString *hashtag = [link substringFromIndex:@"hashtag://".length];
|
|
|
|
TGHashtagSearchController *hashtagController = [[TGHashtagSearchController alloc] initWithQuery:[@"#" stringByAppendingString:hashtag] peerId:0 accessHash:0];
|
|
//__weak TGChannelInfoController *weakSelf = self;
|
|
/*hashtagController.customResultBlock = ^(int32_t messageId) {
|
|
__strong TGChannelInfoController *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf navigateToMessageId:messageId scrollBackMessageId:0 animated:true];
|
|
TGModernConversationController *controller = strongSelf.controller;
|
|
[controller.navigationController popToViewController:controller animated:true];
|
|
}
|
|
};*/
|
|
|
|
[self.navigationController pushViewController:hashtagController animated:true];
|
|
} else {
|
|
@try {
|
|
NSURL *url = [NSURL URLWithString:link];
|
|
if (url != nil) {
|
|
[[UIApplication sharedApplication] openURL:url];
|
|
}
|
|
} @catch (NSException *e) {
|
|
}
|
|
}
|
|
}
|
|
|
|
@end
|