mirror of
https://github.com/danog/Telegram.git
synced 2024-12-02 09:27:55 +01:00
1007 lines
47 KiB
Objective-C
1007 lines
47 KiB
Objective-C
#import "TGChannelConversationCompanion.h"
|
|
|
|
#import "TGAppDelegate.h"
|
|
#import "ActionStage.h"
|
|
#import "TGDatabase.h"
|
|
#import "TGTelegraph.h"
|
|
#import "TGAppDelegate.h"
|
|
#import "TGDialogListCompanion.h"
|
|
|
|
#import "TGChannelManagementSignals.h"
|
|
#import "TGChannelStateSignals.h"
|
|
|
|
#import "TGModernConversationController.h"
|
|
#import "TGMessageModernConversationItem.h"
|
|
|
|
#import "TGModernConversationGroupTitlePanel.h"
|
|
#import "TGUpdateStateRequestBuilder.h"
|
|
|
|
#import "TGChannelInfoController.h"
|
|
#import "TGNavigationController.h"
|
|
#import "TGPopoverController.h"
|
|
#import "TGNavigationBar.h"
|
|
|
|
#import "TGModernViewContext.h"
|
|
|
|
#import "TGModernConversationActionInputPanel.h"
|
|
|
|
#import "TGTelegramNetworking.h"
|
|
|
|
#import "TGStringUtils.h"
|
|
|
|
#import "TGAlertView.h"
|
|
|
|
#import <libkern/OSAtomic.h>
|
|
|
|
@interface TGChannelConversationCompanion () {
|
|
TGConversation *_conversation;
|
|
int32_t _displayVariant;
|
|
int32_t _kind;
|
|
TGChannelRole _role;
|
|
bool _isReadOnly;
|
|
bool _postAsChannel;
|
|
bool _isMuted;
|
|
bool _isForbidden;
|
|
|
|
int32_t _memberCount;
|
|
|
|
bool _enableVisibleMessagesProcessing;
|
|
|
|
SMetaDisposable *_requestingHoleDisposable;
|
|
SMetaDisposable *_managedState;
|
|
SMetaDisposable *_extendedDataDisposable;
|
|
SMetaDisposable *_cachedDataDisposable;
|
|
|
|
TGVisibleMessageHole *_requestingHole;
|
|
bool _loadingHistoryAbove;
|
|
bool _loadingHistoryBelow;
|
|
|
|
bool _historyAbove;
|
|
bool _historyBelow;
|
|
|
|
NSArray *_visibleHoles;
|
|
|
|
TGModernConversationActionInputPanel *_joinChannelPanel; // Main Thread
|
|
TGModernConversationActionInputPanel *_mutePanel; // Main Thread
|
|
TGModernConversationActionInputPanel *_deletePanel; // Main Thread
|
|
SMetaDisposable *_joinChannelDisposable;
|
|
|
|
TGMessageGroup *_lastExpandedGroup;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation TGChannelConversationCompanion
|
|
|
|
- (instancetype)initWithPeerId:(int64_t)peerId conversation:(TGConversation *)conversation {
|
|
self = [super initWithConversationId:peerId mayHaveUnreadMessages:false];
|
|
if (self != nil) {
|
|
_conversation = conversation;
|
|
_accessHash = conversation.accessHash;
|
|
_displayVariant = conversation.displayVariant;
|
|
_kind = conversation.kind;
|
|
_role = conversation.channelRole;
|
|
_isReadOnly = conversation.channelIsReadOnly;
|
|
_postAsChannel = conversation.postAsChannel && (conversation.channelRole == TGChannelRoleCreator || conversation.channelRole == TGChannelRolePublisher);
|
|
if (_isReadOnly && (conversation.channelRole == TGChannelRoleCreator || conversation.channelRole == TGChannelRolePublisher)) {
|
|
_postAsChannel = true;
|
|
}
|
|
_displayVariant = conversation.displayExpanded ? TGChannelDisplayVariantAll : TGChannelDisplayVariantImportant;
|
|
_isForbidden = conversation.kickedFromChat;
|
|
|
|
__weak TGChannelConversationCompanion *weakSelf = self;
|
|
_cachedDataDisposable = [[[TGDatabaseInstance() channelCachedData:_conversationId] deliverOn:[SQueue mainQueue]] startWithNext:^(TGCachedConversationData *data) {
|
|
__strong TGChannelConversationCompanion *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
[strongSelf setMemberCount:data.memberCount];
|
|
}
|
|
}];
|
|
|
|
_manualMessageManagement = true;
|
|
_everyMessageNeedsAuthor = true;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[_requestingHoleDisposable dispose];
|
|
[_managedState dispose];
|
|
[_extendedDataDisposable dispose];
|
|
}
|
|
|
|
- (void)setMemberCount:(int32_t)memberCount {
|
|
if (_memberCount != memberCount) {
|
|
_memberCount = memberCount;
|
|
|
|
[self updateStatus];
|
|
}
|
|
}
|
|
|
|
- (void)_controllerDidAppear:(bool)firstTime {
|
|
[super _controllerDidAppear:firstTime];
|
|
|
|
if (firstTime) {
|
|
_managedState = [[TGChannelStateSignals updatedChannel:_conversationId] startWithNext:nil];
|
|
|
|
_enableVisibleMessagesProcessing = true;
|
|
[self _updateVisibleHoles];
|
|
|
|
_extendedDataDisposable = [[TGChannelManagementSignals updateChannelExtendedInfo:_conversationId accessHash:_accessHash updateUnread:false] startWithNext:nil];
|
|
|
|
if (_isForbidden) {
|
|
[[[TGAlertView alloc] initWithTitle:nil message:TGLocalized(@"ChannelInfo.ChannelForbidden") cancelButtonTitle:TGLocalized(@"Common.OK") okButtonTitle:nil completionBlock:nil] show];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)_controllerAvatarPressed
|
|
{
|
|
TGModernConversationController *controller = self.controller;
|
|
if (controller.currentSizeClass == UIUserInterfaceSizeClassCompact) {
|
|
TGChannelInfoController *groupInfoController = [[TGChannelInfoController alloc] initWithPeerId:_conversationId];
|
|
|
|
[controller.navigationController pushViewController:groupInfoController animated:true];
|
|
}
|
|
else
|
|
{
|
|
if (controller != nil)
|
|
{
|
|
TGChannelInfoController *groupInfoController = [[TGChannelInfoController alloc] initWithPeerId:_conversationId];
|
|
|
|
TGNavigationController *navigationController = [TGNavigationController navigationControllerWithControllers:@[groupInfoController] navigationBarClass:[TGWhiteNavigationBar class]];
|
|
navigationController.presentationStyle = TGNavigationControllerPresentationStyleRootInPopover;
|
|
TGPopoverController *popoverController = [[TGPopoverController alloc] initWithContentViewController:navigationController];
|
|
navigationController.parentPopoverController = popoverController;
|
|
navigationController.detachFromPresentingControllerInCompactMode = true;
|
|
[popoverController setContentSize:CGSizeMake(320.0f, 528.0f)];
|
|
|
|
controller.associatedPopoverController = popoverController;
|
|
[popoverController presentPopoverFromBarButtonItem:controller.navigationItem.rightBarButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:true];
|
|
groupInfoController.collectionView.contentOffset = CGPointMake(0.0f, -groupInfoController.collectionView.contentInset.top);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)_createOrUpdatePrimaryTitlePanel:(bool)__unused createIfNeeded
|
|
{
|
|
/*if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
|
|
{
|
|
TGModernConversationController *controller = self.controller;
|
|
|
|
TGModernConversationGroupTitlePanel *groupTitlePanel = nil;
|
|
if ([[controller primaryTitlePanel] isKindOfClass:[TGModernConversationGroupTitlePanel class]])
|
|
groupTitlePanel = (TGModernConversationGroupTitlePanel *)[controller primaryTitlePanel];
|
|
else
|
|
{
|
|
if (createIfNeeded)
|
|
{
|
|
groupTitlePanel = [[TGModernConversationGroupTitlePanel alloc] init];
|
|
groupTitlePanel.companionHandle = self.actionHandle;
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
|
|
NSMutableArray *actions = [[NSMutableArray alloc] init];
|
|
[actions addObject:@{@"title": @"Switch Mode", @"action": @"switchMode"}];
|
|
[actions addObject:@{@"title": @"Copy Link", @"action": @"copyLink"}];
|
|
|
|
[groupTitlePanel setButtonsWithTitlesAndActions:actions];
|
|
|
|
[controller setPrimaryTitlePanel:groupTitlePanel];
|
|
}*/
|
|
}
|
|
|
|
- (void)_loadControllerPrimaryTitlePanel {
|
|
[self _createOrUpdatePrimaryTitlePanel:true];
|
|
}
|
|
|
|
|
|
- (TGModernConversationInputPanel *)_conversationGenericInputPanel {
|
|
if (_isForbidden) {
|
|
if (_deletePanel == nil) {
|
|
TGModernConversationController *controller = self.controller;
|
|
_deletePanel = [[TGModernConversationActionInputPanel alloc] init];
|
|
[_deletePanel setActionWithTitle:TGLocalized(@"DialogList.DeleteConversationConfirmation") action:@"delete" color:TGAccentColor() icon:TGModernConversationActionInputPanelIconNone];
|
|
_deletePanel.companionHandle = self.actionHandle;
|
|
_deletePanel.delegate = controller;
|
|
}
|
|
return _deletePanel;
|
|
} else if (_kind != TGConversationKindPersistentChannel)
|
|
{
|
|
if (_joinChannelPanel == nil)
|
|
{
|
|
TGModernConversationController *controller = self.controller;
|
|
_joinChannelPanel = [[TGModernConversationActionInputPanel alloc] init];
|
|
[_joinChannelPanel setActionWithTitle:TGLocalized(@"Channel.JoinChannel") action:@"joinchannel" color:TGAccentColor() icon:TGModernConversationActionInputPanelIconJoin];
|
|
_joinChannelPanel.companionHandle = self.actionHandle;
|
|
_joinChannelPanel.delegate = controller;
|
|
}
|
|
return _joinChannelPanel;
|
|
} else if (![self canPostMessages]) {
|
|
if (_mutePanel == nil) {
|
|
TGModernConversationController *controller = self.controller;
|
|
_mutePanel = [[TGModernConversationActionInputPanel alloc] init];
|
|
[_mutePanel setActionWithTitle:!_isMuted ? TGLocalized(@"Conversation.Mute") : TGLocalized(@"Conversation.Unmute") action:@"toggleMute" color:TGAccentColor() icon:TGModernConversationActionInputPanelIconNone];
|
|
_mutePanel.companionHandle = self.actionHandle;
|
|
_mutePanel.delegate = controller;
|
|
}
|
|
return _mutePanel;
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
- (bool)canPostMessages {
|
|
return _role == TGChannelRoleCreator || _role == TGChannelRolePublisher;
|
|
}
|
|
|
|
- (void)_updateJoinPanel {
|
|
TGModernConversationController *controller = self.controller;
|
|
[controller setCustomInputPanel:[self _conversationGenericInputPanel]];
|
|
}
|
|
|
|
- (void)actionStageActionRequested:(NSString *)action options:(id)options {
|
|
if ([action isEqualToString:@"titlePanelAction"]) {
|
|
NSString *panelAction = options[@"action"];
|
|
|
|
if ([panelAction isEqualToString:@"switchMode"]) {
|
|
[self _toggleTitleMode];
|
|
}
|
|
} else if ([action isEqualToString:@"openMessageGroup"]) {
|
|
TGModernConversationController *controller = self.controller;
|
|
if ([controller isEditing]) {
|
|
return;
|
|
}
|
|
|
|
TGMessageGroup *group = options[@"group"];
|
|
_lastExpandedGroup = group;
|
|
|
|
__weak TGChannelConversationCompanion *weakSelf = self;
|
|
int64_t conversationId = _conversationId;
|
|
|
|
TGMessageTransparentSortKey sortKey = TGMessageTransparentSortKeyMake(_conversationId, group.maxTimestamp, group.maxId, 0);
|
|
|
|
[[TGChannelManagementSignals preloadedHistoryForPeerId:_conversationId accessHash:_accessHash aroundMessageId:group.minId] startWithNext:^(NSDictionary *dict) {
|
|
NSArray *removedImportantHoles = nil;
|
|
NSArray *removedUnimportantHoles = nil;
|
|
|
|
removedImportantHoles = dict[@"hole"] == nil ? nil : @[dict[@"hole"]];
|
|
removedUnimportantHoles = dict[@"hole"] == nil ? nil : @[dict[@"hole"]];
|
|
|
|
[TGDatabaseInstance() addMessagesToChannel:conversationId messages:dict[@"messages"] deleteMessages:nil unimportantGroups:dict[@"unimportantGroups"] addedHoles:nil removedHoles:removedImportantHoles removedUnimportantHoles:removedUnimportantHoles updatedMessageSortKeys:nil returnGroups:false changedMessages:^(__unused NSArray *addedMessages, __unused NSArray *removedMessages, __unused NSDictionary *updatedMessages, __unused NSArray *addedUnimportantHoles, __unused NSArray *removedUnimportantHoles) {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
__strong TGChannelConversationCompanion *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
strongSelf->_displayVariant = TGChannelDisplayVariantAll;
|
|
[TGDatabaseInstance() updateChannelDisplayExpanded:strongSelf->_conversationId displayExpanded:true];
|
|
[strongSelf reloadVariantAtSortKey:sortKey group:group jump:false];
|
|
}
|
|
}];
|
|
}];
|
|
}];
|
|
} else if ([action isEqualToString:@"actionPanelAction"]) {
|
|
NSString *panelAction = options[@"action"];
|
|
if ([panelAction isEqualToString:@"joinchannel"]) {
|
|
[self requestJoinChannel];
|
|
} else if ([panelAction isEqualToString:@"toggleMute"]) {
|
|
[self _commitEnableNotifications:_isMuted];
|
|
} else if ([panelAction isEqualToString:@"delete"]) {
|
|
TGModernConversationController *controller = self.controller;
|
|
|
|
[TGAppDelegateInstance.rootController.dialogListController.dialogListCompanion deleteItem:[[TGConversation alloc] initWithConversationId:_conversationId unreadCount:0 serviceUnreadCount:0] animated:false];
|
|
|
|
if (controller.popoverController != nil) {
|
|
dispatch_async(dispatch_get_main_queue(), ^ {
|
|
[controller.popoverController dismissPopoverAnimated:true];
|
|
});
|
|
}
|
|
else {
|
|
[controller.navigationController popToRootViewControllerAnimated:true];
|
|
}
|
|
}
|
|
}
|
|
|
|
[super actionStageActionRequested:action options:options];
|
|
}
|
|
|
|
- (void)_commitEnableNotifications:(bool)enable
|
|
{
|
|
_isMuted = !enable;
|
|
|
|
[_mutePanel setActionWithTitle:!_isMuted ? TGLocalized(@"Conversation.Mute") : TGLocalized(@"Conversation.Unmute") action:@"toggleMute" color:TGAccentColor() icon:TGModernConversationActionInputPanelIconNone];
|
|
|
|
int muteUntil = enable ? 0 : INT32_MAX;
|
|
|
|
static int actionId = 0;
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/changePeerSettings/(%" PRId64 ")/(channelControllerMute%d)", _conversationId, actionId++] options:@{@"peerId": @(_conversationId), @"accessHash": @(_accessHash), @"muteUntil": @(muteUntil)} watcher:TGTelegraphInstance];
|
|
}
|
|
|
|
- (void)loadInitialState {
|
|
[super loadInitialState:false];
|
|
|
|
TGModernConversationController *controller = self.controller;
|
|
[controller setIsChannel:true];
|
|
|
|
if (_isReadOnly) {
|
|
[controller setCanBroadcast:false];
|
|
[controller setIsBroadcasting:false];
|
|
[controller setIsAlwaysBroadcasting:_role == TGChannelRoleCreator || _role == TGChannelRolePublisher];
|
|
[controller setInputDisabled:!(_role == TGChannelRoleCreator || _role == TGChannelRolePublisher)];
|
|
} else {
|
|
[controller setIsAlwaysBroadcasting:false];
|
|
[controller setCanBroadcast:_role == TGChannelRoleCreator || _role == TGChannelRolePublisher];
|
|
if (!(_role == TGChannelRoleCreator || _role == TGChannelRolePublisher)) {
|
|
[controller setIsBroadcasting:false];
|
|
} else {
|
|
[controller setIsBroadcasting:_postAsChannel];
|
|
}
|
|
[controller setInputDisabled:false];
|
|
}
|
|
|
|
self.viewContext.conversation = _conversation;
|
|
|
|
__block NSArray *topMessages = nil;
|
|
[TGDatabaseInstance() dispatchOnDatabaseThread:^{
|
|
__block TGMessageTransparentSortKey maxSortKey = TGMessageTransparentSortKeyUpperBound(_conversationId);
|
|
|
|
if (_preferredInitialPositionedMessageId != 0) {
|
|
[TGDatabaseInstance() channelMessageExists:_conversationId messageId:_preferredInitialPositionedMessageId completion:^(bool exists, TGMessageSortKey key) {
|
|
if (exists) {
|
|
if (TGMessageSortKeySpace(key) == TGMessageSpaceUnimportant) {
|
|
_displayVariant = TGChannelDisplayVariantAll;
|
|
}
|
|
maxSortKey = TGMessageTransparentSortKeyMake(_conversationId, TGMessageSortKeyTimestamp(key), TGMessageSortKeyMid(key), TGMessageSortKeySpace(key));
|
|
[self setInitialMessagePositioning:TGMessageSortKeyMid(key) position:TGInitialScrollPositionCenter];
|
|
}
|
|
}];
|
|
} else if (_conversation.kind == TGConversationKindPersistentChannel && (_conversation.unreadCount != 0 || (_displayVariant == TGChannelDisplayVariantAll && _conversation.serviceUnreadCount != 0))) {
|
|
[TGDatabaseInstance() channelMessageExists:_conversationId messageId:_conversation.maxReadMessageId + 1 completion:^(bool exists, TGMessageSortKey key) {
|
|
if (exists) {
|
|
maxSortKey = TGMessageTransparentSortKeyMake(_conversationId, TGMessageSortKeyTimestamp(key), TGMessageSortKeyMid(key), TGMessageSortKeySpace(key));
|
|
[self setInitialMessagePositioning:TGMessageSortKeyMid(key) position:TGInitialScrollPositionTop];
|
|
|
|
TGMessageRange unreadRange = TGMessageRangeEmpty();
|
|
|
|
unreadRange.firstDate = TGMessageSortKeyTimestamp(key);
|
|
unreadRange.lastDate = INT32_MAX;
|
|
unreadRange.firstMessageId = TGMessageSortKeyMid(key);
|
|
unreadRange.lastMessageId = INT32_MAX;
|
|
|
|
self.unreadMessageRange = unreadRange;
|
|
}
|
|
}];
|
|
}
|
|
|
|
[TGDatabaseInstance() channelMessages:_conversationId maxTransparentSortKey:maxSortKey count:35 important:_displayVariant == TGChannelDisplayVariantImportant mode:TGChannelHistoryRequestAround completion:^(NSArray *messages, bool hasLater) {
|
|
topMessages = messages;
|
|
_historyBelow = hasLater;
|
|
}];
|
|
} synchronous:true];
|
|
_historyAbove = topMessages.count != 0;
|
|
|
|
[self _replaceMessages:topMessages];
|
|
|
|
[self _setTitle:[self titleForConversation:_conversation] andStatus:TGLocalized(@"Channel.Status") accentColored:false allowAnimatioon:false toggleMode:[self currentToggleMode]];
|
|
[self _setAvatarConversationId:_conversationId title:_conversation.chatTitle icon:nil];
|
|
[self _setAvatarUrl:_conversation.chatPhotoSmall];
|
|
}
|
|
|
|
- (TGModernConversationControllerTitleToggle)currentToggleMode {
|
|
if (_displayVariant == TGChannelDisplayVariantAll) {
|
|
return TGModernConversationControllerTitleToggleHideDiscussion;
|
|
} else if (!_isReadOnly) {
|
|
return TGModernConversationControllerTitleToggleNone;
|
|
} else {
|
|
return TGModernConversationControllerTitleToggleNone;
|
|
}
|
|
}
|
|
|
|
- (void)updateStatus {
|
|
NSString *text = TGLocalized(@"Channel.Status");
|
|
if (_memberCount != 0 && !_isForbidden) {
|
|
text = [self stringForMemberCount:_memberCount];
|
|
}
|
|
[self _setStatus:text accentColored:false allowAnimation:false toggleMode:[self currentToggleMode]];
|
|
}
|
|
|
|
- (NSString *)stringForMemberCount:(int)memberCount
|
|
{
|
|
if (memberCount == 1)
|
|
return TGLocalizedStatic(@"Conversation.StatusMembers_1");
|
|
else if (memberCount == 2)
|
|
return TGLocalizedStatic(@"Conversation.StatusMembers_2");
|
|
else if (memberCount >= 3 && memberCount <= 10)
|
|
return [[NSString alloc] initWithFormat:TGLocalizedStatic(@"Conversation.StatusMembers_3_10"), [TGStringUtils stringWithLocalizedNumber:memberCount]];
|
|
else
|
|
return [[NSString alloc] initWithFormat:TGLocalizedStatic(@"Conversation.StatusMembers_any"), [TGStringUtils stringWithLocalizedNumber:memberCount]];
|
|
}
|
|
|
|
- (void)reloadVariantAtSortKey:(TGMessageTransparentSortKey)sortKey group:(TGMessageGroup *)group jump:(bool)jump {
|
|
TGDispatchOnMainThread(^{
|
|
[self updateStatus];
|
|
});
|
|
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
_enableVisibleMessagesProcessing = true;
|
|
_visibleHoles = nil;
|
|
[_requestingHoleDisposable setDisposable:nil];
|
|
_requestingHole = nil;
|
|
_loadingHistoryAbove = false;
|
|
_historyAbove = false;
|
|
_loadingHistoryBelow = false;
|
|
_historyBelow = false;
|
|
|
|
[self _updateControllerHistoryRequestsFlags];
|
|
|
|
[TGDatabaseInstance() dispatchOnDatabaseThread:^{
|
|
__block TGMessageTransparentSortKey updatedSortKey = sortKey;
|
|
|
|
if (group != nil) {
|
|
[TGDatabaseInstance() channelEarlierMessage:_conversationId messageId:group.maxId timestamp:group.maxTimestamp important:true completion:^(bool exists, TGMessageSortKey key) {
|
|
if (exists) {
|
|
updatedSortKey = TGMessageTransparentSortKeyMake(_conversationId, TGMessageSortKeyTimestamp(key), TGMessageSortKeyMid(key), TGMessageSortKeySpace(key));
|
|
}
|
|
}];
|
|
} else if (_displayVariant == TGChannelDisplayVariantImportant && TGMessageTransparentSortKeySpace(sortKey) == TGMessageSpaceUnimportant) {
|
|
[TGDatabaseInstance() channelEarlierMessage:_conversationId messageId:TGMessageTransparentSortKeyMid(sortKey) timestamp:TGMessageTransparentSortKeyTimestamp(sortKey) important:true completion:^(bool exists, TGMessageSortKey key) {
|
|
if (exists) {
|
|
updatedSortKey = TGMessageTransparentSortKeyMake(_conversationId, TGMessageSortKeyTimestamp(key), TGMessageSortKeyMid(key), TGMessageSortKeySpace(key));
|
|
}
|
|
}];
|
|
} else {
|
|
|
|
}
|
|
|
|
[TGDatabaseInstance() channelMessages:_conversationId maxTransparentSortKey:updatedSortKey count:60 important:_displayVariant == TGChannelDisplayVariantImportant mode:TGChannelHistoryRequestAround completion:^(NSArray *messages, bool hasLater) {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
_historyAbove = messages.count != 0;
|
|
_historyBelow = hasLater;
|
|
|
|
int32_t atMessageId = 0;
|
|
for (TGMessage *message in messages) {
|
|
if (TGMessageTransparentSortKeyCompare(message.transparentSortKey, updatedSortKey) <= 0) {
|
|
atMessageId = message.mid;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (atMessageId != 0) {
|
|
TGLog(@"Reloading at %d", atMessageId);
|
|
}
|
|
|
|
[self _replaceMessages:messages atMessageId:atMessageId expandFrom:-group.maxId jump:jump];
|
|
|
|
[self _updateControllerHistoryRequestsFlags];
|
|
}];
|
|
}];
|
|
} synchronous:false];
|
|
}];
|
|
}
|
|
|
|
- (bool)imageDownloadsShouldAutosavePhotos
|
|
{
|
|
return TGAppDelegateInstance.autosavePhotos;
|
|
}
|
|
|
|
- (bool)shouldAutomaticallyDownloadPhotos
|
|
{
|
|
return TGAppDelegateInstance.autoDownloadPhotosInGroups;
|
|
}
|
|
|
|
- (bool)shouldAutomaticallyDownloadAudios
|
|
{
|
|
return TGAppDelegateInstance.autoDownloadAudioInGroups;
|
|
}
|
|
|
|
- (NSString *)_sendMessagePathForMessageId:(int32_t)mid {
|
|
return [[NSString alloc] initWithFormat:@"/tg/sendCommonMessage/(%@)/(%d)", [self _conversationIdPathComponent], mid];
|
|
}
|
|
|
|
- (NSString *)_sendMessagePathPrefix {
|
|
return [[NSString alloc] initWithFormat:@"/tg/sendCommonMessage/(%@)/", [self _conversationIdPathComponent]];
|
|
}
|
|
|
|
- (NSDictionary *)_optionsForMessageActions {
|
|
bool postAsChannel = [self messageAuthorPeerId] == _conversationId;
|
|
return @{@"conversationId": @(_conversationId), @"accessHash": @(_accessHash), @"asChannel": @(postAsChannel)};
|
|
}
|
|
|
|
- (void)_setupOutgoingMessage:(TGMessage *)message {
|
|
[super _setupOutgoingMessage:message];
|
|
|
|
if ((_role == TGChannelRoleCreator || _role == TGChannelRolePublisher) && _postAsChannel) {
|
|
if (message.viewCount == nil) {
|
|
message.viewCount = [[TGMessageViewCountContentProperty alloc] initWithViewCount:1];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)subscribeToUpdates
|
|
{
|
|
[ActionStageInstance() watchForPaths:@[
|
|
[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/typing", _conversationId],
|
|
[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/conversation", _conversationId],
|
|
[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/importantMessages", _conversationId],
|
|
[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/unimportantMessages", _conversationId],
|
|
[[NSString alloc] initWithFormat:@"/tg/peerSettings/(%" PRId64 ")", _conversationId]
|
|
] watcher:self];
|
|
|
|
[ActionStageInstance() requestActor:[NSString stringWithFormat:@"/tg/peerSettings/(%" PRId64 ",cachedOnly)", _conversationId] options:@{@"peerId": @(_conversationId), @"accessHash": @(_accessHash)} watcher:self];
|
|
|
|
[super subscribeToUpdates];
|
|
}
|
|
|
|
- (void)_controllerDidUpdateVisibleHoles:(NSArray *)holes {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
_visibleHoles = holes;
|
|
|
|
[self _updateVisibleHoles];
|
|
}];
|
|
}
|
|
|
|
- (void)_updateVisibleHoles {
|
|
if (_enableVisibleMessagesProcessing && _visibleHoles.count != 0 && _requestingHole == nil) {
|
|
TGVisibleMessageHole *maxHole = _visibleHoles[0];
|
|
|
|
[self _requestHole:maxHole];
|
|
}
|
|
}
|
|
|
|
- (void)loadMoreMessagesAbove {
|
|
int count = 100;
|
|
|
|
TGModernConversationController *controller = self.controller;
|
|
[controller setEnableAboveHistoryRequests:false];
|
|
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
if (!_loadingHistoryAbove) {
|
|
if (_historyAbove) {
|
|
TGMessageTransparentSortKey maxKey = TGMessageTransparentSortKeyUpperBound(_conversationId);
|
|
for (TGMessageModernConversationItem *item in _items) {
|
|
TGMessageTransparentSortKey itemKey = item->_message.transparentSortKey;
|
|
itemKey = TGMessageTransparentSortKeyMake(TGMessageTransparentSortKeyPeerId(itemKey), TGMessageTransparentSortKeyTimestamp(itemKey), TGMessageTransparentSortKeyMid(itemKey) - 1, TGMessageTransparentSortKeySpace(itemKey));
|
|
if (TGMessageTransparentSortKeyCompare(maxKey, itemKey) > 0) {
|
|
maxKey = itemKey;
|
|
}
|
|
}
|
|
|
|
__weak TGChannelConversationCompanion *weakSelf = self;
|
|
_loadingHistoryAbove = true;
|
|
[TGDatabaseInstance() channelMessages:_conversationId maxTransparentSortKey:maxKey count:count important:_displayVariant == TGChannelDisplayVariantImportant mode:TGChannelHistoryRequestEarlier completion:^(NSArray *messages, __unused bool hasLater) {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
__strong TGChannelConversationCompanion *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
strongSelf->_loadingHistoryAbove = false;
|
|
if (messages.count == 0) {
|
|
strongSelf->_historyAbove = false;
|
|
} else {
|
|
strongSelf->_historyAbove = true;
|
|
}
|
|
if (messages.count != 0) {
|
|
[strongSelf _addMessages:messages animated:false intent:TGModernConversationAddMessageIntentLoadMoreMessagesAbove];
|
|
}
|
|
[strongSelf _updateControllerHistoryRequestsFlags];
|
|
}
|
|
}];
|
|
}];
|
|
}
|
|
} else {
|
|
[self _updateControllerHistoryRequestsFlags];
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (void)loadMoreMessagesBelow {
|
|
int count = 100;
|
|
#ifdef DEBUG
|
|
count = 10;
|
|
#endif
|
|
|
|
TGModernConversationController *controller = self.controller;
|
|
[controller setEnableBelowHistoryRequests:false];
|
|
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
if (!_loadingHistoryBelow) {
|
|
if (_historyBelow) {
|
|
TGMessageTransparentSortKey minKey = TGMessageTransparentSortKeyLowerBound(_conversationId);
|
|
for (TGMessageModernConversationItem *item in _items) {
|
|
TGMessageTransparentSortKey itemKey = item->_message.transparentSortKey;
|
|
if (TGMessageTransparentSortKeyCompare(minKey, itemKey) < 0) {
|
|
minKey = itemKey;
|
|
}
|
|
}
|
|
|
|
__weak TGChannelConversationCompanion *weakSelf = self;
|
|
_loadingHistoryBelow = true;
|
|
[TGDatabaseInstance() channelMessages:_conversationId maxTransparentSortKey:minKey count:count important:_displayVariant == TGChannelDisplayVariantImportant mode:TGChannelHistoryRequestLater completion:^(NSArray *messages, __unused bool hasLater) {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
__strong TGChannelConversationCompanion *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
strongSelf->_loadingHistoryBelow = false;
|
|
if (messages.count == 0) {
|
|
strongSelf->_historyBelow = false;
|
|
} else {
|
|
strongSelf->_historyBelow = true;
|
|
}
|
|
if (messages.count != 0) {
|
|
[strongSelf _addMessages:messages animated:false intent:TGModernConversationAddMessageIntentLoadMoreMessagesBelow];
|
|
}
|
|
[strongSelf _updateControllerHistoryRequestsFlags];
|
|
}
|
|
}];
|
|
}];
|
|
}
|
|
} else {
|
|
[self _updateControllerHistoryRequestsFlags];
|
|
}
|
|
}];
|
|
}
|
|
|
|
- (void)_requestHole:(TGVisibleMessageHole *)hole {
|
|
_requestingHole = hole;
|
|
if (_requestingHoleDisposable == nil) {
|
|
_requestingHoleDisposable = [[SMetaDisposable alloc] init];
|
|
}
|
|
|
|
int64_t conversationId = _conversationId;
|
|
int32_t displayVariant = _displayVariant;
|
|
|
|
TGLog(@"request hole %d ... %d, %s", hole.hole.minId, hole.hole.maxId, hole.direction == TGVisibleMessageHoleDirectionEarlier ? "earlier" : "later");
|
|
|
|
__weak TGChannelConversationCompanion *weakSelf = self;
|
|
[_requestingHoleDisposable setDisposable:[[TGChannelManagementSignals channelMessageHoleForPeerId:_conversationId accessHash:_accessHash hole:hole.hole direction:hole.direction == TGVisibleMessageHoleDirectionEarlier ? TGChannelHistoryHoleDirectionEarlier : TGChannelHistoryHoleDirectionLater important:_displayVariant == TGChannelDisplayVariantImportant] startWithNext:^(NSDictionary *dict) {
|
|
|
|
NSArray *removedImportantHoles = nil;
|
|
NSArray *removedUnimportantHoles = nil;
|
|
|
|
removedImportantHoles = dict[@"hole"] == nil ? nil : @[dict[@"hole"]];
|
|
removedUnimportantHoles = dict[@"hole"] == nil ? nil : @[dict[@"hole"]];
|
|
|
|
[TGDatabaseInstance() addMessagesToChannel:conversationId messages:dict[@"messages"] deleteMessages:nil unimportantGroups:dict[@"unimportantGroups"] addedHoles:nil removedHoles:removedImportantHoles removedUnimportantHoles:removedUnimportantHoles updatedMessageSortKeys:nil returnGroups:displayVariant == TGChannelDisplayVariantImportant changedMessages:^(NSArray *addedMessages, NSArray *removedMessages, NSDictionary *updatedMessages, NSArray *addedUnimportantHoles, NSArray *removedUnimportantHoles) {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
__strong TGChannelConversationCompanion *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
|
|
NSMutableArray *resultRemovedMessages = [[NSMutableArray alloc] init];
|
|
[resultRemovedMessages addObjectsFromArray:removedMessages];
|
|
if (strongSelf->_displayVariant == TGChannelDisplayVariantAll) {
|
|
[resultRemovedMessages addObjectsFromArray:removedUnimportantHoles];
|
|
}
|
|
|
|
NSMutableArray *resultAddedMessages = [[NSMutableArray alloc] init];
|
|
[resultAddedMessages addObjectsFromArray:addedMessages];
|
|
if (strongSelf->_displayVariant == TGChannelDisplayVariantAll) {
|
|
[resultAddedMessages addObjectsFromArray:addedUnimportantHoles];
|
|
}
|
|
|
|
[strongSelf _addMessages:resultAddedMessages animated:false intent:hole.direction == TGVisibleMessageHoleDirectionEarlier ? TGModernConversationAddMessageIntentLoadMoreMessagesAbove : TGModernConversationAddMessageIntentLoadMoreMessagesBelow deletedMessageIds:resultRemovedMessages];
|
|
|
|
[strongSelf _updateMessages:updatedMessages];
|
|
|
|
strongSelf->_requestingHole = nil;
|
|
[strongSelf _updateControllerHistoryRequestsFlags];
|
|
}
|
|
}];
|
|
}];
|
|
} error:^(__unused id error) {
|
|
|
|
} completed:nil]];
|
|
}
|
|
|
|
- (void)_updateControllerHistoryRequestsFlags {
|
|
NSAssert([TGModernConversationCompanion isMessageQueue], @"[TGModernConversationCompanion isMessageQueue]");
|
|
|
|
bool enableAboveRequests = _historyAbove;
|
|
if (_loadingHistoryAbove) {
|
|
enableAboveRequests = false;
|
|
}
|
|
|
|
bool enableBelowRequests = _historyBelow;
|
|
if (_loadingHistoryBelow) {
|
|
enableBelowRequests = false;
|
|
}
|
|
|
|
TGDispatchOnMainThread(^{
|
|
TGModernConversationController *controller = self.controller;
|
|
[controller setEnableAboveHistoryRequests:enableAboveRequests];
|
|
[controller setEnableBelowHistoryRequests:enableBelowRequests];
|
|
});
|
|
}
|
|
|
|
- (NSString *)titleForConversation:(TGConversation *)conversation {
|
|
return conversation.chatTitle;
|
|
}
|
|
|
|
- (void)actorCompleted:(int)status path:(NSString *)path result:(id)result {
|
|
if ([path hasPrefix:@"/tg/peerSettings/"])
|
|
{
|
|
if (status == ASStatusSuccess)
|
|
{
|
|
NSDictionary *notificationSettings = ((SGraphObjectNode *)result).object;
|
|
|
|
TGDispatchOnMainThread(^{
|
|
int muteUntil = [notificationSettings[@"muteUntil"] intValue];
|
|
if (muteUntil <= [[TGTelegramNetworking instance] approximateRemoteTime]) {
|
|
_isMuted = false;
|
|
} else {
|
|
_isMuted = true;
|
|
}
|
|
|
|
[_mutePanel setActionWithTitle:!_isMuted ? TGLocalized(@"Conversation.Mute") : TGLocalized(@"Conversation.Unmute") action:@"toggleMute" color:TGAccentColor() icon:TGModernConversationActionInputPanelIconNone];
|
|
});
|
|
}
|
|
}
|
|
|
|
[super actorCompleted:status path:path result:result];
|
|
}
|
|
|
|
- (void)actionStageResourceDispatched:(NSString *)path resource:(id)resource arguments:(id)arguments {
|
|
if ([path isEqualToString:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/conversation", _conversationId]]) {
|
|
TGConversation *conversation = ((SGraphObjectNode *)resource).object;
|
|
_conversation = conversation;
|
|
|
|
TGDispatchOnMainThread(^{
|
|
bool importantFlagsUpdated = _role != conversation.channelRole || _isReadOnly != conversation.channelIsReadOnly || _kind != conversation.kind || _isForbidden != conversation.kickedFromChat;
|
|
|
|
_kind = conversation.kind;
|
|
_role = conversation.channelRole;
|
|
_isReadOnly = conversation.channelIsReadOnly;
|
|
|
|
if (_isForbidden != conversation.kickedFromChat && conversation.kickedFromChat) {
|
|
[[[TGAlertView alloc] initWithTitle:nil message:TGLocalized(@"ChannelInfo.ChannelForbidden") cancelButtonTitle:TGLocalized(@"Common.OK") okButtonTitle:nil completionBlock:nil] show];
|
|
}
|
|
|
|
_isForbidden = conversation.kickedFromChat;
|
|
|
|
TGModernConversationController *controller = self.controller;
|
|
if (_isReadOnly) {
|
|
[controller setCanBroadcast:false];
|
|
[controller setIsBroadcasting:false];
|
|
[controller setIsAlwaysBroadcasting:_role == TGChannelRoleCreator || _role == TGChannelRolePublisher];
|
|
[controller setInputDisabled:!(_role == TGChannelRoleCreator || _role == TGChannelRolePublisher)];
|
|
} else {
|
|
[controller setIsAlwaysBroadcasting:false];
|
|
[controller setCanBroadcast:_role == TGChannelRoleCreator || _role == TGChannelRolePublisher];
|
|
if (!(_role == TGChannelRoleCreator || _role == TGChannelRolePublisher)) {
|
|
[controller setIsBroadcasting:false];
|
|
} else {
|
|
[controller setIsBroadcasting:_postAsChannel];
|
|
}
|
|
[controller setInputDisabled:false];
|
|
}
|
|
|
|
if (importantFlagsUpdated) {
|
|
[self _updateJoinPanel];
|
|
}
|
|
|
|
[self _setTitle:[self titleForConversation:conversation] andStatus:TGLocalized(@"Channel.Status") accentColored:false allowAnimatioon:false toggleMode:[self currentToggleMode]];
|
|
[self updateStatus];
|
|
[self _setAvatarConversationId:_conversationId title:conversation.chatTitle icon:nil];
|
|
[self _setAvatarUrl:conversation.chatPhotoSmall];
|
|
});
|
|
} else if ([path isEqualToString:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/importantMessages", _conversationId]]) {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
if (_displayVariant == TGChannelDisplayVariantImportant) {
|
|
if (((NSArray *)resource[@"removed"]).count != 0) {
|
|
[self _deleteMessages:resource[@"removed"] animated:true];
|
|
}
|
|
if (((NSArray *)resource[@"added"]).count != 0) {
|
|
[super actionStageResourceDispatched:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messages", _conversationId] resource:[[SGraphObjectNode alloc] initWithObject:resource[@"added"]] arguments:@{@"treatIncomingAsUnread": @true}];
|
|
}
|
|
if (((NSDictionary *)resource[@"updated"]).count != 0) {
|
|
[self _updateMessages:resource[@"updated"]];
|
|
__block bool hadGroups = false;
|
|
[(NSDictionary *)resource[@"updated"] enumerateKeysAndObjectsUsingBlock:^(__unused id key, TGMessage *message, BOOL *stop) {
|
|
if (message.group != nil) {
|
|
if (stop) {
|
|
hadGroups = true;
|
|
*stop = true;
|
|
}
|
|
}
|
|
}];
|
|
|
|
if (hadGroups) {
|
|
[self scheduleReadHistory];
|
|
}
|
|
}
|
|
}
|
|
}];
|
|
} else if ([path isEqualToString:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/unimportantMessages", _conversationId]]) {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
if (_displayVariant == TGChannelDisplayVariantAll) {
|
|
if (((NSArray *)resource[@"removed"]).count != 0) {
|
|
[self _deleteMessages:resource[@"removed"] animated:true];
|
|
}
|
|
if (((NSArray *)resource[@"added"]).count != 0) {
|
|
[super actionStageResourceDispatched:[[NSString alloc] initWithFormat:@"/tg/conversation/(%lld)/messages", _conversationId] resource:[[SGraphObjectNode alloc] initWithObject:resource[@"added"]] arguments:@{@"treatIncomingAsUnread": @true}];
|
|
}
|
|
if (((NSDictionary *)resource[@"updated"]).count != 0) {
|
|
[self _updateMessages:resource[@"updated"]];
|
|
}
|
|
}
|
|
}];
|
|
} else if ([path hasPrefix:@"/tg/peerSettings/"]) {
|
|
[self actorCompleted:ASStatusSuccess path:path result:resource];
|
|
}
|
|
|
|
[super actionStageResourceDispatched:path resource:resource arguments:arguments];
|
|
}
|
|
|
|
- (void)requestJoinChannel {
|
|
if (_joinChannelDisposable == nil) {
|
|
_joinChannelDisposable = [[SMetaDisposable alloc] init];
|
|
}
|
|
|
|
[_joinChannelPanel setActivity:true];
|
|
|
|
[_joinChannelDisposable setDisposable:[[TGChannelManagementSignals joinTemporaryChannel:_conversationId] startWithNext:nil]];
|
|
}
|
|
|
|
- (bool)allowReplies {
|
|
return (_role == TGChannelRoleCreator || _role == TGChannelRolePublisher) || !_isReadOnly;
|
|
}
|
|
|
|
- (int64_t)messageAuthorPeerId {
|
|
if (_isReadOnly) {
|
|
return (_role == TGChannelRoleCreator || _role == TGChannelRolePublisher) ? _conversationId : TGTelegraphInstance.clientUserId;
|
|
} else {
|
|
return ((_role == TGChannelRoleCreator || _role == TGChannelRolePublisher) && _postAsChannel) ? _conversationId : TGTelegraphInstance.clientUserId;
|
|
}
|
|
}
|
|
|
|
- (bool)canDeleteMessage:(TGMessage *)message {
|
|
if (message.fromUid == _conversationId) {
|
|
return (_role == TGChannelRoleCreator || _role == TGChannelRolePublisher);
|
|
} else {
|
|
if (message.outgoing || (_role == TGChannelRoleCreator || _role == TGChannelRolePublisher || _role == TGChannelRoleModerator)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
- (bool)canDeleteMessages {
|
|
return _role == TGChannelRoleCreator || _role == TGChannelRolePublisher || _role == TGChannelRoleModerator;
|
|
}
|
|
|
|
- (bool)canDeleteAllMessages {
|
|
return false;
|
|
}
|
|
|
|
- (NSString *)_controllerInfoButtonText {
|
|
return TGLocalized(@"Conversation.InfoChannel");
|
|
}
|
|
|
|
- (int64_t)requestPeerId {
|
|
return _conversationId;
|
|
}
|
|
|
|
- (int64_t)requestAccessHash {
|
|
return _accessHash;
|
|
}
|
|
|
|
- (void)_toggleBroadcastMode {
|
|
if (_role == TGChannelRoleCreator || _role == TGChannelRolePublisher) {
|
|
_postAsChannel = !_postAsChannel;
|
|
[TGDatabaseInstance() updateChannelPostAsChannel:_conversationId postAsChannel:_postAsChannel];
|
|
TGModernConversationController *controller = self.controller;
|
|
[controller setIsBroadcasting:_postAsChannel];
|
|
} else {
|
|
_postAsChannel = false;
|
|
TGModernConversationController *controller = self.controller;
|
|
[controller setIsBroadcasting:_postAsChannel];
|
|
}
|
|
}
|
|
|
|
- (void)_toggleTitleMode {
|
|
TGMessageTransparentSortKey sortKey = TGMessageTransparentSortKeyUpperBound(_conversationId);
|
|
TGModernConversationController *controller = self.controller;
|
|
TGMessage *maxMessage = [controller latestVisibleMessage];
|
|
if (maxMessage != nil) {
|
|
sortKey = maxMessage.transparentSortKey;
|
|
}
|
|
|
|
if (_displayVariant == TGChannelDisplayVariantAll) {
|
|
_displayVariant = TGChannelDisplayVariantImportant;
|
|
[TGDatabaseInstance() updateChannelDisplayExpanded:_conversationId displayExpanded:false];
|
|
|
|
if (_lastExpandedGroup != nil) {
|
|
for (NSNumber *nMessageId in [controller visibleMessageIds]) {
|
|
int32_t mid = [nMessageId intValue];
|
|
if (mid >= _lastExpandedGroup.minId && mid <= _lastExpandedGroup.maxId) {
|
|
sortKey = TGMessageTransparentSortKeyMake(_conversationId, _lastExpandedGroup.maxTimestamp, _lastExpandedGroup.maxId, TGMessageSpaceUnimportant);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
_displayVariant = TGChannelDisplayVariantAll;
|
|
[TGDatabaseInstance() updateChannelDisplayExpanded:_conversationId displayExpanded:true];
|
|
}
|
|
_lastExpandedGroup = nil;
|
|
|
|
if (_displayVariant != _conversation.displayVariant && _displayVariant == TGChannelDisplayVariantImportant) {
|
|
_conversation = [_conversation copy];
|
|
_conversation.displayVariant = _displayVariant;
|
|
[TGDatabaseInstance() updateChannelDisplayVariant:_conversationId displayVariant:_displayVariant];
|
|
}
|
|
|
|
[self reloadVariantAtSortKey:sortKey group:nil jump:false];
|
|
}
|
|
|
|
- (void)navigateToMessageId:(int32_t)messageId scrollBackMessageId:(int32_t)scrollBackMessageId animated:(bool)animated
|
|
{
|
|
__weak TGChannelConversationCompanion *weakSelf = self;
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^
|
|
{
|
|
bool found = false;
|
|
for (TGMessageModernConversationItem *item in _items)
|
|
{
|
|
if (item->_message.mid == messageId)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int32_t sourceMid = scrollBackMessageId;
|
|
|
|
if (found)
|
|
{
|
|
TGDispatchOnMainThread(^
|
|
{
|
|
TGModernConversationController *controller = self.controller;
|
|
[controller scrollToMessage:messageId sourceMessageId:sourceMid animated:animated];
|
|
});
|
|
}
|
|
else
|
|
{
|
|
int64_t conversationId = _conversationId;
|
|
[[TGChannelManagementSignals preloadedHistoryForPeerId:_conversationId accessHash:_accessHash aroundMessageId:messageId] startWithNext:^(NSDictionary *dict) {
|
|
NSArray *removedImportantHoles = nil;
|
|
NSArray *removedUnimportantHoles = nil;
|
|
|
|
removedImportantHoles = dict[@"hole"] == nil ? nil : @[dict[@"hole"]];
|
|
removedUnimportantHoles = dict[@"hole"] == nil ? nil : @[dict[@"hole"]];
|
|
|
|
__block TGMessageTransparentSortKey sortKey = TGMessageTransparentSortKeyUpperBound(conversationId);
|
|
__block bool keyExists = false;
|
|
|
|
[TGDatabaseInstance() dispatchOnDatabaseThread:^{
|
|
[TGDatabaseInstance() channelMessageExists:conversationId messageId:messageId completion:^(bool exists, TGMessageSortKey key) {
|
|
if (exists) {
|
|
keyExists = true;
|
|
sortKey = TGMessageTransparentSortKeyMake(conversationId, TGMessageSortKeyTimestamp(key), TGMessageSortKeyMid(key), TGMessageSortKeySpace(key));
|
|
}
|
|
}];
|
|
} synchronous:true];
|
|
|
|
if (!keyExists) {
|
|
for (TGMessage *message in dict[@"messages"]) {
|
|
if (message.mid == messageId) {
|
|
sortKey = message.transparentSortKey;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
[TGDatabaseInstance() addMessagesToChannel:conversationId messages:dict[@"messages"] deleteMessages:nil unimportantGroups:dict[@"unimportantGroups"] addedHoles:nil removedHoles:removedImportantHoles removedUnimportantHoles:removedUnimportantHoles updatedMessageSortKeys:nil returnGroups:false changedMessages:^(__unused NSArray *addedMessages, __unused NSArray *removedMessages, __unused NSDictionary *updatedMessages, __unused NSArray *addedUnimportantHoles, __unused NSArray *removedUnimportantHoles) {
|
|
[TGModernConversationCompanion dispatchOnMessageQueue:^{
|
|
__strong TGChannelConversationCompanion *strongSelf = weakSelf;
|
|
if (strongSelf != nil) {
|
|
if (TGMessageTransparentSortKeySpace(sortKey) == TGMessageSpaceUnimportant && strongSelf->_displayVariant != TGChannelDisplayVariantAll) {
|
|
strongSelf->_displayVariant = TGChannelDisplayVariantAll;
|
|
[TGDatabaseInstance() updateChannelDisplayExpanded:strongSelf->_conversationId displayExpanded:true];
|
|
}
|
|
[strongSelf reloadVariantAtSortKey:sortKey group:nil jump:true];
|
|
}
|
|
}];
|
|
}];
|
|
}];
|
|
}
|
|
}];
|
|
}
|
|
|
|
@end
|