mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
902889795c
@ -1048,7 +1048,7 @@ private final class WidgetIntentHandler {
|
||||
accountResults.append(accountTransaction(rootPath: rootPath, id: accountId, encryptionParameters: encryptionParameters, isReadOnly: true, useCopy: false, transaction: { postbox, transaction -> [Friend] in
|
||||
var peers: [Peer] = []
|
||||
|
||||
for id in getRecentPeers(transaction: transaction) {
|
||||
for id in _internal_getRecentPeers(transaction: transaction) {
|
||||
if let peer = transaction.getPeer(id), !(peer is TelegramSecretChat), !peer.isDeleted {
|
||||
peers.append(peer)
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public final class ChatListSearchRecentPeersNode: ASDisplayNode {
|
||||
|
||||
let peersDisposable = DisposableSet()
|
||||
|
||||
let recent: Signal<([Peer], [PeerId: (Int32, Bool)], [PeerId : PeerPresence]), NoError> = recentPeers(account: context.account)
|
||||
let recent: Signal<([Peer], [PeerId: (Int32, Bool)], [PeerId : PeerPresence]), NoError> = context.engine.peers.recentPeers()
|
||||
|> filter { value -> Bool in
|
||||
switch value {
|
||||
case .disabled:
|
||||
@ -224,7 +224,7 @@ public final class ChatListSearchRecentPeersNode: ASDisplayNode {
|
||||
}
|
||||
}))
|
||||
if case .actionSheet = mode {
|
||||
peersDisposable.add(managedUpdatedRecentPeers(accountPeerId: context.account.peerId, postbox: context.account.postbox, network: context.account.network).start())
|
||||
peersDisposable.add(context.engine.peers.managedUpdatedRecentPeers().start())
|
||||
}
|
||||
self.disposable.set(peersDisposable)
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
|
||||
switch search {
|
||||
case .recentPeers:
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
let _ = (removeRecentPeer(account: context.account, peerId: peerId)
|
||||
let _ = (context.engine.peers.removeRecentPeer(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
@ -68,7 +68,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
|
||||
items.append(.separator)
|
||||
case .recentSearch:
|
||||
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromRecents, textColor: .destructive, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.contextMenu.destructiveColor) }, action: { _, f in
|
||||
let _ = (removeRecentlySearchedPeer(postbox: context.account.postbox, peerId: peerId)
|
||||
let _ = (context.engine.peers.removeRecentlySearchedPeer(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
f(.default)
|
||||
})
|
||||
|
@ -744,7 +744,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
actionSheet?.dismissAnimated()
|
||||
|
||||
if let strongSelf = self {
|
||||
let _ = removeRecentPeer(account: strongSelf.context.account, peerId: peer.id).start()
|
||||
let _ = strongSelf.context.engine.peers.removeRecentPeer(peerId: peer.id).start()
|
||||
}
|
||||
})
|
||||
]),
|
||||
@ -2004,11 +2004,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
|> delay(0.8, queue: Queue.mainQueue())
|
||||
let progressDisposable = progressSignal.start()
|
||||
|
||||
let signal: Signal<Void, NoError> = strongSelf.context.account.postbox.transaction { transaction -> Void in
|
||||
for peerId in peerIds {
|
||||
removePeerChat(account: context.account, transaction: transaction, mediaBox: context.account.postbox.mediaBox, peerId: peerId, reportChatSpam: false, deleteGloballyIfPossible: peerId.namespace == Namespaces.Peer.SecretChat)
|
||||
}
|
||||
}
|
||||
let signal: Signal<Never, NoError> = strongSelf.context.engine.peers.removePeerChats(peerIds: Array(peerIds))
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
@ -2693,7 +2689,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
if let channel = chatPeer as? TelegramChannel {
|
||||
strongSelf.context.peerChannelMemberCategoriesContextsManager.externallyRemoved(peerId: channel.id, memberId: strongSelf.context.account.peerId)
|
||||
}
|
||||
let _ = removePeerChat(account: strongSelf.context.account, peerId: peerId, reportChatSpam: false, deleteGloballyIfPossible: deleteGloballyIfPossible).start(completed: {
|
||||
let _ = strongSelf.context.engine.peers.removePeerChat(peerId: peerId, reportChatSpam: false, deleteGloballyIfPossible: deleteGloballyIfPossible).start(completed: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = (clearRecentlySearchedPeers(postbox: strongSelf.context.account.postbox)
|
||||
let _ = (strongSelf.context.engine.peers.clearRecentlySearchedPeers()
|
||||
|> deliverOnMainQueue).start()
|
||||
})
|
||||
]), ActionSheetItemGroup(items: [
|
||||
|
@ -1213,7 +1213,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}, peerSelected: { [weak self] peer, _ in
|
||||
interaction.dismissInput()
|
||||
interaction.openPeer(peer, false)
|
||||
let _ = addRecentlySearchedPeer(postbox: context.account.postbox, peerId: peer.id).start()
|
||||
let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).start()
|
||||
self?.listNode.clearHighlightAnimated(true)
|
||||
}, disabledPeerSelected: { _ in
|
||||
}, togglePeerSelected: { _ in
|
||||
@ -1395,7 +1395,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}))
|
||||
|
||||
let previousRecentItems = Atomic<[ChatListRecentEntry]?>(value: nil)
|
||||
let hasRecentPeers = recentPeers(account: context.account)
|
||||
let hasRecentPeers = context.engine.peers.recentPeers()
|
||||
|> map { value -> Bool in
|
||||
switch value {
|
||||
case let .peers(peers):
|
||||
@ -1407,7 +1407,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
|> distinctUntilChanged
|
||||
|
||||
let previousRecentlySearchedPeerOrder = Atomic<[PeerId]>(value: [])
|
||||
let fixedRecentlySearchedPeers = recentlySearchedPeers(postbox: context.account.postbox)
|
||||
let fixedRecentlySearchedPeers = context.engine.peers.recentlySearchedPeers()
|
||||
|> map { peers -> [RecentlySearchedPeer] in
|
||||
var result: [RecentlySearchedPeer] = []
|
||||
let _ = previousRecentlySearchedPeerOrder.modify { current in
|
||||
@ -1465,7 +1465,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}
|
||||
|
||||
if tagMask == nil && !peersFilter.contains(.excludeRecent) {
|
||||
self.updatedRecentPeersDisposable.set(managedUpdatedRecentPeers(accountPeerId: context.account.peerId, postbox: context.account.postbox, network: context.account.network).start())
|
||||
self.updatedRecentPeersDisposable.set(context.engine.peers.managedUpdatedRecentPeers().start())
|
||||
}
|
||||
|
||||
self.recentDisposable.set((combineLatest(queue: .mainQueue(),
|
||||
@ -1479,7 +1479,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
let firstTime = previousEntries == nil
|
||||
let transition = chatListSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries, context: context, presentationData: presentationData, filter: peersFilter, peerSelected: { peer in
|
||||
interaction.openPeer(peer, true)
|
||||
let _ = addRecentlySearchedPeer(postbox: context.account.postbox, peerId: peer.id).start()
|
||||
let _ = context.engine.peers.addRecentlySearchedPeer(peerId: peer.id).start()
|
||||
self?.recentListNode.clearHighlightAnimated(true)
|
||||
}, disabledPeerSelected: { peer in
|
||||
interaction.openDisabledPeer(peer)
|
||||
@ -1492,7 +1492,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}, clearRecentlySearchedPeers: {
|
||||
interaction.clearRecentSearch()
|
||||
}, deletePeer: { peerId in
|
||||
let _ = removeRecentlySearchedPeer(postbox: context.account.postbox, peerId: peerId).start()
|
||||
let _ = context.engine.peers.removeRecentlySearchedPeer(peerId: peerId).start()
|
||||
})
|
||||
strongSelf.enqueueRecentTransition(transition, firstTime: firstTime)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import Foundation
|
||||
import UIKitRuntimeUtils
|
||||
|
||||
public enum Keyboard {
|
||||
public static func applyAutocorrection() {
|
||||
applyKeyboardAutocorrection()
|
||||
public static func applyAutocorrection(textView: UITextView) {
|
||||
applyKeyboardAutocorrection(textView)
|
||||
}
|
||||
}
|
||||
|
@ -117,14 +117,6 @@ private func containedLayoutForWindowLayout(_ layout: WindowLayout, deviceMetric
|
||||
return ContainerViewLayout(size: layout.size, metrics: layout.metrics, deviceMetrics: deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: layout.onScreenNavigationHeight ?? 0.0, right: 0.0), safeInsets: resolvedSafeInsets, additionalInsets: UIEdgeInsets(), statusBarHeight: resolvedStatusBarHeight, inputHeight: updatedInputHeight, inputHeightIsInteractivellyChanging: layout.upperKeyboardInputPositionBound != nil && layout.upperKeyboardInputPositionBound != layout.size.height && layout.inputHeight != nil, inVoiceOver: layout.inVoiceOver)
|
||||
}
|
||||
|
||||
private func encodeText(_ string: String, _ key: Int) -> String {
|
||||
var result = ""
|
||||
for c in string.unicodeScalars {
|
||||
result.append(Character(UnicodeScalar(UInt32(Int(c.value) + key))!))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public func doesViewTreeDisableInteractiveTransitionGestureRecognizer(_ view: UIView, keyboardOnly: Bool = false) -> Bool {
|
||||
if view.disablesInteractiveTransitionGestureRecognizer && !keyboardOnly {
|
||||
return true
|
||||
|
@ -450,7 +450,7 @@ public final class SecretMediaPreviewController: ViewController {
|
||||
self?.didSetReady = true
|
||||
}
|
||||
self._ready.set(ready |> map { true })
|
||||
self.markMessageAsConsumedDisposable.set(markMessageContentAsConsumedInteractively(postbox: self.context.account.postbox, messageId: message.id).start())
|
||||
self.markMessageAsConsumedDisposable.set(self.context.engine.messages.markMessageContentAsConsumedInteractively(messageId: message.id).start())
|
||||
} else {
|
||||
var beginTimeAndTimeout: (Double, Double)?
|
||||
var videoDuration: Int32?
|
||||
|
@ -46,8 +46,6 @@
|
||||
|
||||
- (instancetype)initWithKeyCommandController:(TGKeyCommandController *)keyCommandController;
|
||||
|
||||
+ (void)addTextViewMethods;
|
||||
|
||||
- (void)textViewEnsureSelectionVisible;
|
||||
|
||||
@end
|
||||
|
@ -30,16 +30,9 @@ typedef enum {
|
||||
+ (void)setSecondaryAnimationDurationFactor:(float)factor;
|
||||
+ (void)setForceSystemCurve:(bool)forceSystemCurve;
|
||||
|
||||
+ (CGFloat)applicationStatusBarOffset;
|
||||
+ (void)setApplicationStatusBarOffset:(CGFloat)offset;
|
||||
+ (void)animateApplicationStatusBarStyleTransitionWithDuration:(NSTimeInterval)duration;
|
||||
+ (CGFloat)statusBarHeightForOrientation:(UIInterfaceOrientation)orientation;
|
||||
|
||||
+ (bool)isKeyboardVisible;
|
||||
+ (CGFloat)keyboardHeightForOrientation:(UIInterfaceOrientation)orientation;
|
||||
+ (void)applyCurrentKeyboardAutocorrectionVariant;
|
||||
+ (void)applyCurrentKeyboardAutocorrectionVariant:(UITextView *)textView;
|
||||
+ (UIWindow *)applicationKeyboardWindow;
|
||||
+ (UIView *)applicationKeyboardView;
|
||||
+ (void)setApplicationKeyboardOffset:(CGFloat)offset;
|
||||
|
||||
+ (void)forcePerformWithAnimation:(dispatch_block_t)block;
|
||||
|
@ -63,12 +63,6 @@ NSString *TGMentionBoldAttributeName = @"TGMentionBoldAttributeName";
|
||||
|
||||
- (void)commonInitialiser
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
[HPTextViewInternal addTextViewMethods];
|
||||
});
|
||||
|
||||
CGRect frame = self.frame;
|
||||
frame.origin = CGPointZero;
|
||||
_internalTextView = [[HPTextViewInternal alloc] initWithKeyCommandController:_keyCommandController];
|
||||
|
@ -29,15 +29,6 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (void)addTextViewMethods
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
InjectInstanceMethodFromAnotherClass([HPTextViewInternal class], [HPTextViewInternal class], @selector(textViewAdjustScrollRange:animated:), NSSelectorFromString(TGEncodeText(@"`tdspmmSbohfUpWjtjcmf;bojnbufe;", -1)));
|
||||
});
|
||||
}
|
||||
|
||||
- (void)setText:(NSString *)text
|
||||
{
|
||||
BOOL originalValue = self.scrollEnabled;
|
||||
@ -64,25 +55,6 @@
|
||||
[super setScrollEnabled:isScrollable];
|
||||
}
|
||||
|
||||
- (void)textViewAdjustScrollRange:(NSRange)range animated:(BOOL)animated
|
||||
{
|
||||
static SEL selector = NULL;
|
||||
static void (*impl)(id, SEL, NSRange, BOOL) = NULL;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
Method method = class_getInstanceMethod([UITextView class], selector);
|
||||
if (method != NULL)
|
||||
impl = (void (*)(id, SEL, NSRange, BOOL))method_getImplementation(method);
|
||||
});
|
||||
|
||||
animated = false;
|
||||
|
||||
if (impl != NULL)
|
||||
impl(self, selector, range, animated);
|
||||
}
|
||||
|
||||
- (void)scrollRectToVisible:(CGRect)__unused rect animated:(BOOL)__unused animated
|
||||
{
|
||||
|
||||
|
@ -14,8 +14,6 @@ void TGLegacyLog(NSString *format, ...);
|
||||
int iosMajorVersion();
|
||||
int iosMinorVersion();
|
||||
|
||||
NSString *TGEncodeText(NSString *string, int key);
|
||||
|
||||
void TGDispatchOnMainThread(dispatch_block_t block);
|
||||
void TGDispatchAfter(double delay, dispatch_queue_t queue, dispatch_block_t block);
|
||||
|
||||
|
@ -70,20 +70,6 @@ int iosMinorVersion()
|
||||
return version;
|
||||
}
|
||||
|
||||
NSString *TGEncodeText(NSString *string, int key)
|
||||
{
|
||||
NSMutableString *result = [[NSMutableString alloc] init];
|
||||
|
||||
for (int i = 0; i < (int)[string length]; i++)
|
||||
{
|
||||
unichar c = [string characterAtIndex:i];
|
||||
c += key;
|
||||
[result appendString:[NSString stringWithCharacters:&c length:1]];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int deviceMemorySize()
|
||||
{
|
||||
static int memorySize = 0;
|
||||
|
@ -215,209 +215,6 @@ void InjectInstanceMethodFromAnotherClass(Class toClass, Class fromClass, SEL fr
|
||||
window.alpha = alpha;
|
||||
}
|
||||
|
||||
+ (CGFloat)applicationStatusBarOffset
|
||||
{
|
||||
UIWindow *window = [[LegacyComponentsGlobals provider] applicationStatusBarWindow];
|
||||
return window.bounds.origin.y;
|
||||
}
|
||||
|
||||
+ (void)setApplicationStatusBarOffset:(CGFloat)offset {
|
||||
UIWindow *window = [[LegacyComponentsGlobals provider] applicationStatusBarWindow];
|
||||
CGRect bounds = window.bounds;
|
||||
bounds.origin = CGPointMake(0.0f, -offset);
|
||||
window.bounds = bounds;
|
||||
}
|
||||
|
||||
static UIView *findStatusBarView()
|
||||
{
|
||||
static Class viewClass = nil;
|
||||
static SEL selector = NULL;
|
||||
if (selector == NULL)
|
||||
{
|
||||
NSString *str1 = @"rs`str";
|
||||
NSString *str2 = @"A`qVhmcnv";
|
||||
|
||||
selector = NSSelectorFromString([[NSString alloc] initWithFormat:@"%@%@", TGEncodeText(str1, 1), TGEncodeText(str2, 1)]);
|
||||
|
||||
viewClass = NSClassFromString(TGEncodeText(@"VJTubuvtCbs", -1));
|
||||
}
|
||||
|
||||
UIWindow *window = [[LegacyComponentsGlobals provider] applicationStatusBarWindow];
|
||||
|
||||
for (UIView *subview in window.subviews)
|
||||
{
|
||||
if ([subview isKindOfClass:viewClass])
|
||||
{
|
||||
return subview;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void)animateApplicationStatusBarAppearance:(int)statusBarAnimation duration:(NSTimeInterval)duration completion:(void (^)())completion
|
||||
{
|
||||
[self animateApplicationStatusBarAppearance:statusBarAnimation delay:0.0 duration:duration completion:completion];
|
||||
}
|
||||
|
||||
+ (void)animateApplicationStatusBarAppearance:(int)statusBarAnimation delay:(NSTimeInterval)delay duration:(NSTimeInterval)duration completion:(void (^)())completion
|
||||
{
|
||||
UIView *view = findStatusBarView();
|
||||
|
||||
if (view != nil)
|
||||
{
|
||||
if ((statusBarAnimation & TGStatusBarAppearanceAnimationSlideDown) || (statusBarAnimation & TGStatusBarAppearanceAnimationSlideUp))
|
||||
{
|
||||
CGPoint startPosition = view.layer.position;
|
||||
CGPoint position = view.layer.position;
|
||||
|
||||
CGPoint normalPosition = CGPointMake(CGFloor(view.frame.size.width / 2), CGFloor(view.frame.size.height / 2));
|
||||
|
||||
CGFloat viewHeight = view.frame.size.height;
|
||||
|
||||
if (statusBarAnimation & TGStatusBarAppearanceAnimationSlideDown)
|
||||
{
|
||||
startPosition = CGPointMake(CGFloor(view.frame.size.width / 2), CGFloor(view.frame.size.height / 2) - viewHeight);
|
||||
position = CGPointMake(CGFloor(view.frame.size.width / 2), CGFloor(view.frame.size.height / 2));
|
||||
}
|
||||
else if (statusBarAnimation & TGStatusBarAppearanceAnimationSlideUp)
|
||||
{
|
||||
startPosition = CGPointMake(CGFloor(view.frame.size.width / 2), CGFloor(view.frame.size.height / 2));
|
||||
position = CGPointMake(CGFloor(view.frame.size.width / 2), CGFloor(view.frame.size.height / 2) - viewHeight);
|
||||
}
|
||||
|
||||
CABasicAnimation *animation = [[CABasicAnimation alloc] init];
|
||||
animation.duration = duration;
|
||||
animation.fromValue = [NSValue valueWithCGPoint:startPosition];
|
||||
animation.toValue = [NSValue valueWithCGPoint:position];
|
||||
animation.removedOnCompletion = true;
|
||||
animation.fillMode = kCAFillModeForwards;
|
||||
animation.beginTime = delay;
|
||||
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
||||
|
||||
TGAnimationBlockDelegate *delegate = [[TGAnimationBlockDelegate alloc] initWithLayer:view.layer];
|
||||
delegate.completion = ^(BOOL finished)
|
||||
{
|
||||
if (finished)
|
||||
view.layer.position = normalPosition;
|
||||
if (completion)
|
||||
completion();
|
||||
};
|
||||
animation.delegate = delegate;
|
||||
[view.layer addAnimation:animation forKey:@"position"];
|
||||
|
||||
view.layer.position = position;
|
||||
}
|
||||
else if ((statusBarAnimation & TGStatusBarAppearanceAnimationFadeIn) || (statusBarAnimation & TGStatusBarAppearanceAnimationFadeOut))
|
||||
{
|
||||
float startOpacity = view.layer.opacity;
|
||||
float opacity = view.layer.opacity;
|
||||
|
||||
if (statusBarAnimation & TGStatusBarAppearanceAnimationFadeIn)
|
||||
{
|
||||
startOpacity = 0.0f;
|
||||
opacity = 1.0f;
|
||||
}
|
||||
else if (statusBarAnimation & TGStatusBarAppearanceAnimationFadeOut)
|
||||
{
|
||||
startOpacity = 1.0f;
|
||||
opacity = 0.0f;
|
||||
}
|
||||
|
||||
CABasicAnimation *animation = [[CABasicAnimation alloc] init];
|
||||
animation.duration = duration;
|
||||
animation.fromValue = @(startOpacity);
|
||||
animation.toValue = @(opacity);
|
||||
animation.removedOnCompletion = true;
|
||||
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
||||
TGAnimationBlockDelegate *delegate = [[TGAnimationBlockDelegate alloc] initWithLayer:view.layer];
|
||||
delegate.completion = ^(__unused BOOL finished)
|
||||
{
|
||||
if (completion)
|
||||
completion();
|
||||
};
|
||||
animation.delegate = delegate;
|
||||
|
||||
[view.layer addAnimation:animation forKey:@"opacity"];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (completion)
|
||||
completion();
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)animateApplicationStatusBarStyleTransitionWithDuration:(NSTimeInterval)duration
|
||||
{
|
||||
UIView *view = findStatusBarView();
|
||||
|
||||
if (view != nil)
|
||||
{
|
||||
UIView *snapshotView = [view snapshotViewAfterScreenUpdates:false];
|
||||
[view addSubview:snapshotView];
|
||||
|
||||
[UIView animateWithDuration:duration animations:^
|
||||
{
|
||||
snapshotView.alpha = 0.0f;
|
||||
} completion:^(__unused BOOL finished)
|
||||
{
|
||||
[snapshotView removeFromSuperview];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
+ (CGFloat)statusBarHeightForOrientation:(UIInterfaceOrientation)orientation
|
||||
{
|
||||
UIWindow *window = [[LegacyComponentsGlobals provider] applicationStatusBarWindow];
|
||||
|
||||
Class statusBarClass = NSClassFromString(TGEncodeText(@"VJTubuvtCbs", -1));
|
||||
|
||||
for (UIView *view in window.subviews)
|
||||
{
|
||||
if ([view isKindOfClass:statusBarClass])
|
||||
{
|
||||
SEL selector = NSSelectorFromString(TGEncodeText(@"dvssfouTuzmf", -1));
|
||||
NSMethodSignature *signature = [statusBarClass instanceMethodSignatureForSelector:selector];
|
||||
if (signature == nil)
|
||||
{
|
||||
TGLegacyLog(@"***** Method not found");
|
||||
return 20.0f;
|
||||
}
|
||||
|
||||
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:signature];
|
||||
[inv setSelector:selector];
|
||||
[inv setTarget:view];
|
||||
[inv invoke];
|
||||
|
||||
NSInteger result = 0;
|
||||
[inv getReturnValue:&result];
|
||||
|
||||
SEL selector2 = NSSelectorFromString(TGEncodeText(@"ifjhiuGpsTuzmf;psjfoubujpo;", -1));
|
||||
NSMethodSignature *signature2 = [statusBarClass methodSignatureForSelector:selector2];
|
||||
if (signature2 == nil)
|
||||
{
|
||||
TGLegacyLog(@"***** Method not found");
|
||||
return 20.0f;
|
||||
}
|
||||
NSInvocation *inv2 = [NSInvocation invocationWithMethodSignature:signature2];
|
||||
[inv2 setSelector:selector2];
|
||||
[inv2 setTarget:[view class]];
|
||||
[inv2 setArgument:&result atIndex:2];
|
||||
NSInteger argOrientation = orientation;
|
||||
[inv2 setArgument:&argOrientation atIndex:3];
|
||||
[inv2 invoke];
|
||||
|
||||
CGFloat result2 = 0;
|
||||
[inv2 getReturnValue:&result2];
|
||||
|
||||
return result2;
|
||||
}
|
||||
}
|
||||
|
||||
return 20.0f;
|
||||
}
|
||||
|
||||
+ (bool)isKeyboardVisible
|
||||
{
|
||||
return [self isKeyboardVisibleAlt];
|
||||
@ -445,66 +242,9 @@ static bool keyboardHidden = true;
|
||||
return !keyboardHidden;
|
||||
}
|
||||
|
||||
+ (CGFloat)keyboardHeightForOrientation:(UIInterfaceOrientation)orientation
|
||||
+ (void)applyCurrentKeyboardAutocorrectionVariant:(UITextView *)textView
|
||||
{
|
||||
static NSInvocation *invocation = nil;
|
||||
static Class keyboardClass = NULL;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
keyboardClass = NSClassFromString(TGEncodeText(@"VJLfzcpbse", -1));
|
||||
|
||||
SEL selector = NSSelectorFromString(TGEncodeText(@"tj{fGpsJoufsgbdfPsjfoubujpo;", -1));
|
||||
NSMethodSignature *signature = [keyboardClass methodSignatureForSelector:selector];
|
||||
if (signature == nil)
|
||||
TGLegacyLog(@"***** Method not found");
|
||||
else
|
||||
{
|
||||
invocation = [NSInvocation invocationWithMethodSignature:signature];
|
||||
[invocation setSelector:selector];
|
||||
}
|
||||
});
|
||||
|
||||
if (invocation != nil)
|
||||
{
|
||||
[invocation setTarget:[keyboardClass class]];
|
||||
[invocation setArgument:&orientation atIndex:2];
|
||||
[invocation invoke];
|
||||
|
||||
CGSize result = CGSizeZero;
|
||||
[invocation getReturnValue:&result];
|
||||
|
||||
return MIN(result.width, result.height);
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
+ (void)applyCurrentKeyboardAutocorrectionVariant
|
||||
{
|
||||
static Class keyboardClass = NULL;
|
||||
static SEL currentInstanceSelector = NULL;
|
||||
static SEL applyVariantSelector = NULL;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
keyboardClass = NSClassFromString(TGEncodeText(@"VJLfzcpbse", -1));
|
||||
|
||||
currentInstanceSelector = NSSelectorFromString(TGEncodeText(@"bdujwfLfzcpbse", -1));
|
||||
applyVariantSelector = NSSelectorFromString(TGEncodeText(@"bddfquBvupdpssfdujpo", -1));
|
||||
});
|
||||
|
||||
if ([keyboardClass respondsToSelector:currentInstanceSelector])
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
id currentInstance = [keyboardClass performSelector:currentInstanceSelector];
|
||||
if ([currentInstance respondsToSelector:applyVariantSelector])
|
||||
[currentInstance performSelector:applyVariantSelector];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
[textView unmarkText];
|
||||
}
|
||||
|
||||
+ (UIWindow *)applicationKeyboardWindow
|
||||
@ -518,32 +258,6 @@ static bool keyboardHidden = true;
|
||||
keyboardWindow.frame = CGRectOffset(keyboardWindow.bounds, 0.0f, offset);
|
||||
}
|
||||
|
||||
+ (UIView *)applicationKeyboardView
|
||||
{
|
||||
static Class keyboardViewClass = Nil;
|
||||
static Class keyboardViewContainerClass = Nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
keyboardViewClass = NSClassFromString(TGEncodeText(@"VJJoqvuTfuIptuWjfx", -1));
|
||||
keyboardViewContainerClass = NSClassFromString(TGEncodeText(@"VJJoqvuTfuDpoubjofsWjfx", -1));
|
||||
});
|
||||
|
||||
for (UIView *view in [self applicationKeyboardWindow].subviews)
|
||||
{
|
||||
if ([view isKindOfClass:keyboardViewContainerClass])
|
||||
{
|
||||
for (UIView *subview in view.subviews)
|
||||
{
|
||||
if ([subview isKindOfClass:keyboardViewClass])
|
||||
return subview;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void)setForceMovieAnimatedScaleMode:(bool)force
|
||||
{
|
||||
forceMovieAnimatedScaleMode = force;
|
||||
|
@ -1407,8 +1407,8 @@
|
||||
if (_searchController == nil)
|
||||
return;
|
||||
|
||||
UIView *backArrow = [self _findBackArrow:self.navigationBar];
|
||||
UIView *backButton = [self _findBackButton:self.navigationBar parentView:self.navigationBar];
|
||||
UIView *backArrow = nil;
|
||||
UIView *backButton = nil;
|
||||
|
||||
if ([viewController isKindOfClass:[TGPhotoEditorController class]])
|
||||
{
|
||||
@ -1440,50 +1440,13 @@
|
||||
_searchSnapshotView = nil;
|
||||
_searchController.view.hidden = false;
|
||||
|
||||
UIView *backArrow = [self _findBackArrow:self.navigationBar];
|
||||
UIView *backButton = [self _findBackButton:self.navigationBar parentView:self.navigationBar];
|
||||
UIView *backArrow = nil;
|
||||
UIView *backButton = nil;
|
||||
backArrow.alpha = 1.0f;
|
||||
backButton.alpha = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIView *)_findBackArrow:(UIView *)view
|
||||
{
|
||||
Class backArrowClass = NSClassFromString(TGEncodeText(@"`VJObwjhbujpoCbsCbdlJoejdbupsWjfx", -1));
|
||||
|
||||
if ([view isKindOfClass:backArrowClass])
|
||||
return view;
|
||||
|
||||
for (UIView *subview in view.subviews)
|
||||
{
|
||||
UIView *result = [self _findBackArrow:subview];
|
||||
if (result != nil)
|
||||
return result;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (UIView *)_findBackButton:(UIView *)view parentView:(UIView *)parentView
|
||||
{
|
||||
Class backButtonClass = NSClassFromString(TGEncodeText(@"VJObwjhbujpoJufnCvuupoWjfx", -1));
|
||||
|
||||
if ([view isKindOfClass:backButtonClass])
|
||||
{
|
||||
if (view.center.x < parentView.frame.size.width / 2.0f)
|
||||
return view;
|
||||
}
|
||||
|
||||
for (UIView *subview in view.subviews)
|
||||
{
|
||||
UIView *result = [self _findBackButton:subview parentView:parentView];
|
||||
if (result != nil)
|
||||
return result;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
+ (TGMediaAssetType)assetTypeForIntent:(TGMediaAssetsControllerIntent)intent
|
||||
|
@ -252,7 +252,7 @@ static void setViewFrame(UIView *view, CGRect frame)
|
||||
}
|
||||
|
||||
if (_inputField.internalTextView.isFirstResponder)
|
||||
[TGHacks applyCurrentKeyboardAutocorrectionVariant];
|
||||
[TGHacks applyCurrentKeyboardAutocorrectionVariant:_inputField.internalTextView];
|
||||
|
||||
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithAttributedString:_inputField.text == nil ? [[NSAttributedString alloc] initWithString:@""] : _inputField.attributedText];
|
||||
NSMutableString *usualString = [text.string mutableCopy];
|
||||
|
@ -352,40 +352,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setShowCallStatusBar:(bool)showCallStatusBar
|
||||
{
|
||||
if (_showCallStatusBar == showCallStatusBar)
|
||||
return;
|
||||
|
||||
_showCallStatusBar = showCallStatusBar;
|
||||
|
||||
int screenHeight = (int)TGScreenSize().height;
|
||||
CGFloat statusBarHeight = (screenHeight == 812 || screenHeight == 896) ? 0.0f : 20.0f;
|
||||
|
||||
_currentAdditionalStatusBarHeight = _showCallStatusBar ? statusBarHeight : 0.0f;
|
||||
[(TGNavigationBar *)self.navigationBar setVerticalOffset:_currentAdditionalStatusBarHeight];
|
||||
|
||||
[UIView animateWithDuration:0.25 animations:^
|
||||
{
|
||||
static SEL selector = NULL;
|
||||
static void (*impl)(id, SEL) = NULL;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
selector = NSSelectorFromString(TGEncodeText(@"`vqebufCbstGpsDvssfouJoufsgbdfPsjfoubujpo", -1));
|
||||
Method method = class_getInstanceMethod([UINavigationController class], selector);
|
||||
impl = (void (*)(id, SEL))method_getImplementation(method);
|
||||
});
|
||||
|
||||
if (impl != NULL)
|
||||
impl(self, selector);
|
||||
|
||||
[self updateStatusBarOnControllers];
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
- (void)setupStatusBarOnControllers:(NSArray *)controllers
|
||||
{
|
||||
if ([[self navigationBar] isKindOfClass:[TGNavigationBar class]])
|
||||
@ -416,11 +382,6 @@
|
||||
TGViewController *viewController = (TGViewController *)maybeController;
|
||||
[viewController setAdditionalStatusBarHeight:_currentAdditionalStatusBarHeight];
|
||||
[viewController setNeedsStatusBarAppearanceUpdate];
|
||||
|
||||
if ([viewController.presentedViewController isKindOfClass:[TGNavigationController class]] && viewController.presentedViewController.modalPresentationStyle != UIModalPresentationPopover)
|
||||
{
|
||||
[(TGNavigationController *)viewController.presentedViewController setShowCallStatusBar:_showCallStatusBar];
|
||||
}
|
||||
}
|
||||
else if ([maybeController isKindOfClass:[UITabBarController class]] && [maybeController conformsToProtocol:@protocol(TGNavigationControllerTabsController)])
|
||||
{
|
||||
@ -438,54 +399,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
static UIView *findDimmingView(UIView *view)
|
||||
{
|
||||
static NSString *encodedString = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
encodedString = TGEncodeText(@"VJEjnnjohWjfx", -1);
|
||||
});
|
||||
|
||||
if ([NSStringFromClass(view.class) isEqualToString:encodedString])
|
||||
return view;
|
||||
|
||||
for (UIView *subview in view.subviews)
|
||||
{
|
||||
UIView *result = findDimmingView(subview);
|
||||
if (result != nil)
|
||||
return result;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
if (self.modalPresentationStyle == UIModalPresentationFormSheet)
|
||||
{
|
||||
UIView *dimmingView = findDimmingView(self.view.window);
|
||||
bool tapSetup = false;
|
||||
if (_dimmingTapRecognizer != nil)
|
||||
{
|
||||
for (UIGestureRecognizer *recognizer in dimmingView.gestureRecognizers)
|
||||
{
|
||||
if (recognizer == _dimmingTapRecognizer)
|
||||
{
|
||||
tapSetup = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!tapSetup)
|
||||
{
|
||||
_dimmingTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dimmingViewTapped:)];
|
||||
[dimmingView addGestureRecognizer:_dimmingTapRecognizer];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dimmingViewTapped:(UITapGestureRecognizer *)recognizer
|
||||
@ -931,74 +847,16 @@ TGNavigationController *findNavigationController()
|
||||
|
||||
- (void)updateInteractiveTransition:(CGFloat)percentComplete
|
||||
{
|
||||
TGNavigationController *navigationController = findNavigationController();
|
||||
if (navigationController != nil)
|
||||
{
|
||||
if (!navigationController.disableInteractiveKeyboardTransition && [TGHacks applicationKeyboardWindow] != nil && ![TGHacks applicationKeyboardWindow].hidden)
|
||||
{
|
||||
CGSize screenSize = [TGViewController screenSizeForInterfaceOrientation:navigationController.interfaceOrientation];
|
||||
CGFloat keyboardOffset = MAX(0.0f, percentComplete * screenSize.width);
|
||||
|
||||
UIView *keyboardView = [TGHacks applicationKeyboardView];
|
||||
CGRect keyboardViewFrame = keyboardView.frame;
|
||||
keyboardViewFrame.origin.x = keyboardOffset;
|
||||
|
||||
keyboardView.frame = keyboardViewFrame;
|
||||
}
|
||||
}
|
||||
|
||||
[super updateInteractiveTransition:percentComplete];
|
||||
}
|
||||
|
||||
- (void)finishInteractiveTransition
|
||||
{
|
||||
CGFloat value = self.percentComplete;
|
||||
UIView *keyboardView = [TGHacks applicationKeyboardView];
|
||||
CGRect keyboardViewFrame = keyboardView.frame;
|
||||
|
||||
[super finishInteractiveTransition];
|
||||
|
||||
TGNavigationController *navigationController = findNavigationController();
|
||||
if (navigationController != nil)
|
||||
{
|
||||
if (!navigationController.disableInteractiveKeyboardTransition)
|
||||
{
|
||||
keyboardView.frame = keyboardViewFrame;
|
||||
|
||||
CGSize screenSize = [TGViewController screenSizeForInterfaceOrientation:navigationController.interfaceOrientation];
|
||||
CGFloat keyboardOffset = 1.0f * screenSize.width;
|
||||
|
||||
keyboardViewFrame.origin.x = keyboardOffset;
|
||||
NSTimeInterval duration = (1.0 - value) * [navigationController myNominalTransitionAnimationDuration];
|
||||
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^
|
||||
{
|
||||
keyboardView.frame = keyboardViewFrame;
|
||||
} completion:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancelInteractiveTransition
|
||||
{
|
||||
CGFloat value = self.percentComplete;
|
||||
|
||||
TGNavigationController *navigationController = findNavigationController();
|
||||
if (navigationController != nil)
|
||||
{
|
||||
if (!navigationController.disableInteractiveKeyboardTransition && [TGHacks applicationKeyboardWindow] != nil && ![TGHacks applicationKeyboardWindow].hidden)
|
||||
{
|
||||
UIView *keyboardView = [TGHacks applicationKeyboardView];
|
||||
CGRect keyboardViewFrame = keyboardView.frame;
|
||||
keyboardViewFrame.origin.x = 0.0f;
|
||||
|
||||
NSTimeInterval duration = value * [navigationController myNominalTransitionAnimationDuration];
|
||||
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^
|
||||
{
|
||||
keyboardView.frame = keyboardViewFrame;
|
||||
} completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
[super cancelInteractiveTransition];
|
||||
}
|
||||
|
||||
|
@ -68,28 +68,7 @@
|
||||
}
|
||||
|
||||
- (BOOL)shouldAutorotate
|
||||
{
|
||||
static NSArray *nonRotateableWindowClasses = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^
|
||||
{
|
||||
NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
Class alertClass = NSClassFromString(TGEncodeText(@"`VJBmfsuPwfsmbzXjoepx", -1));
|
||||
if (alertClass != nil)
|
||||
[array addObject:alertClass];
|
||||
|
||||
nonRotateableWindowClasses = array;
|
||||
});
|
||||
|
||||
for (UIWindow *window in [[LegacyComponentsGlobals provider] applicationWindows].reverseObjectEnumerator)
|
||||
{
|
||||
for (Class classInfo in nonRotateableWindowClasses)
|
||||
{
|
||||
if ([window isKindOfClass:classInfo])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
UIViewController *rootController = [[LegacyComponentsGlobals provider] applicationWindows].firstObject.rootViewController;
|
||||
|
||||
if (rootController.presentedViewController != nil)
|
||||
|
@ -695,7 +695,7 @@ static id<LegacyComponentsContext> _defaultContext = nil;
|
||||
{
|
||||
float additionalKeyboardHeight = [self _keyboardAdditionalDeltaHeightWhenRotatingFrom:_viewControllerRotatingFromOrientation toOrientation:toInterfaceOrientation];
|
||||
|
||||
CGFloat statusBarHeight = [TGHacks statusBarHeightForOrientation:toInterfaceOrientation];
|
||||
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
|
||||
[self _updateControllerInsetForOrientation:toInterfaceOrientation statusBarHeight:statusBarHeight keyboardHeight:[self _currentKeyboardHeight:toInterfaceOrientation] + additionalKeyboardHeight force:false notify:true];
|
||||
}
|
||||
|
||||
@ -768,9 +768,6 @@ static id<LegacyComponentsContext> _defaultContext = nil;
|
||||
if ([self isViewLoaded] && !_viewControllerHasEverAppeared && ([self findFirstResponder:self.view] == nil && ![self willCaptureInputShortly]))
|
||||
return 0.0f;
|
||||
|
||||
if ([TGHacks isKeyboardVisible])
|
||||
return [TGHacks keyboardHeightForOrientation:orientation];
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@ -1264,7 +1261,7 @@ static id<LegacyComponentsContext> _defaultContext = nil;
|
||||
if (navigationBarHidden != self.navigationController.navigationBarHidden)
|
||||
{
|
||||
CGFloat barHeight = [self navigationBarHeightForInterfaceOrientation:self.interfaceOrientation];
|
||||
CGFloat statusBarHeight = [TGHacks statusBarHeightForOrientation:self.interfaceOrientation];
|
||||
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
|
||||
if ([self shouldIgnoreStatusBarInOrientation:self.interfaceOrientation])
|
||||
statusBarHeight = 0.0f;
|
||||
|
||||
@ -1435,13 +1432,6 @@ static id<LegacyComponentsContext> _defaultContext = nil;
|
||||
if (TGIsPad() && iosMajorVersion() >= 7)
|
||||
viewControllerToPresent.preferredContentSize = [self.navigationController preferredContentSize];
|
||||
|
||||
if ([viewControllerToPresent isKindOfClass:[TGNavigationController class]])
|
||||
{
|
||||
TGNavigationController *navController = (TGNavigationController *)self.navigationController;
|
||||
if (navController.showCallStatusBar)
|
||||
[(TGNavigationController *)viewControllerToPresent setShowCallStatusBar:true];
|
||||
}
|
||||
|
||||
if (iosMajorVersion() >= 8 && self.presentedViewController != nil && [self.presentedViewController isKindOfClass:[UIAlertController class]])
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
|
@ -67,25 +67,25 @@ private final class LegacyComponentsAccessCheckerImpl: NSObject, LegacyComponent
|
||||
}
|
||||
}
|
||||
|
||||
private func encodeText(_ string: String, _ key: Int) -> String {
|
||||
var result = ""
|
||||
for c in string.unicodeScalars {
|
||||
result.append(Character(UnicodeScalar(UInt32(Int(c.value) + key))!))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private let keyboardWindowClass: AnyClass? = {
|
||||
private func isKeyboardWindow(window: NSObject) -> Bool {
|
||||
let typeName = NSStringFromClass(type(of: window))
|
||||
if #available(iOS 9.0, *) {
|
||||
return NSClassFromString(encodeText("VJSfnpufLfzcpbseXjoepx", -1))
|
||||
if typeName.hasPrefix("UI") && typeName.hasSuffix("RemoteKeyboardWindow") {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return NSClassFromString(encodeText("VJUfyuFggfdutXjoepx", -1))
|
||||
if typeName.hasPrefix("UI") && typeName.hasSuffix("TextEffectsWindow") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}()
|
||||
return false
|
||||
}
|
||||
|
||||
private final class LegacyComponentsGlobalsProviderImpl: NSObject, LegacyComponentsGlobalsProvider {
|
||||
func log(_ string: String!) {
|
||||
print(string)
|
||||
if let string = string {
|
||||
print("\(string)")
|
||||
}
|
||||
}
|
||||
|
||||
public func effectiveLocalization() -> TGLocalization! {
|
||||
@ -101,12 +101,8 @@ private final class LegacyComponentsGlobalsProviderImpl: NSObject, LegacyCompone
|
||||
}
|
||||
|
||||
public func applicationKeyboardWindow() -> UIWindow! {
|
||||
guard let keyboardWindowClass = keyboardWindowClass else {
|
||||
return nil
|
||||
}
|
||||
|
||||
for window in legacyComponentsApplication?.windows ?? [] {
|
||||
if window.isKind(of: keyboardWindowClass) {
|
||||
if isKeyboardWindow(window: window) {
|
||||
return window
|
||||
}
|
||||
}
|
||||
|
@ -24,17 +24,15 @@
|
||||
@interface MTDatacenterAuthPublicKey : NSObject
|
||||
|
||||
@property (nonatomic, strong, readonly) NSString *publicKey;
|
||||
@property (nonatomic, readonly) bool usesModernPaddingScheme;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MTDatacenterAuthPublicKey
|
||||
|
||||
- (instancetype)initWithPublicKey:(NSString *)publicKey usesModernPaddingScheme:(bool)usesModernPaddingScheme {
|
||||
- (instancetype)initWithPublicKey:(NSString *)publicKey {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_publicKey = publicKey;
|
||||
_usesModernPaddingScheme = usesModernPaddingScheme;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -50,78 +48,6 @@ static NSArray<MTDatacenterAuthPublicKey *> *defaultPublicKeys() {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
serverPublicKeys = @[
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAxq7aeLAqJR20tkQQMfRn+ocfrtMlJsQ2Uksfs7Xcoo77jAid0bRt\n"
|
||||
"ksiVmT2HEIJUlRxfABoPBV8wY9zRTUMaMA654pUX41mhyVN+XoerGxFvrs9dF1Ru\n"
|
||||
"vCHbI02dM2ppPvyytvvMoefRoL5BTcpAihFgm5xCaakgsJ/tH5oVl74CdhQw8J5L\n"
|
||||
"xI/K++KJBUyZ26Uba1632cOiq05JBUW0Z2vWIOk4BLysk7+U9z+SxynKiZR3/xdi\n"
|
||||
"XvFKk01R3BHV+GUKM2RYazpS/P8v7eyKhAbKxOdRcFpHLlVwfjyM1VlDQrEZxsMp\n"
|
||||
"NTLYXb6Sce1Uov0YtNx5wEowlREH1WOTlwIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAsQZnSWVZNfClk29RcDTJQ76n8zZaiTGuUsi8sUhW8AS4PSbPKDm+\n"
|
||||
"DyJgdHDWdIF3HBzl7DHeFrILuqTs0vfS7Pa2NW8nUBwiaYQmPtwEa4n7bTmBVGsB\n"
|
||||
"1700/tz8wQWOLUlL2nMv+BPlDhxq4kmJCyJfgrIrHlX8sGPcPA4Y6Rwo0MSqYn3s\n"
|
||||
"g1Pu5gOKlaT9HKmE6wn5Sut6IiBjWozrRQ6n5h2RXNtO7O2qCDqjgB2vBxhV7B+z\n"
|
||||
"hRbLbCmW0tYMDsvPpX5M8fsO05svN+lKtCAuz1leFns8piZpptpSCFn7bWxiA9/f\n"
|
||||
"x5x17D7pfah3Sy2pA+NDXyzSlGcKdaUmwQIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6\n"
|
||||
"lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS\n"
|
||||
"an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw\n"
|
||||
"Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+\n"
|
||||
"8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n\n"
|
||||
"Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAwqjFW0pi4reKGbkc9pK83Eunwj/k0G8ZTioMMPbZmW99GivMibwa\n"
|
||||
"xDM9RDWabEMyUtGoQC2ZcDeLWRK3W8jMP6dnEKAlvLkDLfC4fXYHzFO5KHEqF06i\n"
|
||||
"qAqBdmI1iBGdQv/OQCBcbXIWCGDY2AsiqLhlGQfPOI7/vvKc188rTriocgUtoTUc\n"
|
||||
"/n/sIUzkgwTqRyvWYynWARWzQg0I9olLBBC2q5RQJJlnYXZwyTL3y9tdb7zOHkks\n"
|
||||
"WV9IMQmZmyZh/N7sMbGWQpt4NMchGpPGeJ2e5gHBjDnlIf2p1yZOYeUYrdbwcS0t\n"
|
||||
"UiggS4UeE8TzIuXFQxw7fzEIlmhIaq3FnwIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAruw2yP/BCcsJliRoW5eBVBVle9dtjJw+OYED160Wybum9SXtBBLX\n"
|
||||
"riwt4rROd9csv0t0OHCaTmRqBcQ0J8fxhN6/cpR1GWgOZRUAiQxoMnlt0R93LCX/\n"
|
||||
"j1dnVa/gVbCjdSxpbrfY2g2L4frzjJvdl84Kd9ORYjDEAyFnEA7dD556OptgLQQ2\n"
|
||||
"e2iVNq8NZLYTzLp5YpOdO1doK+ttrltggTCy5SrKeLoCPPbOgGsdxJxyz5KKcZnS\n"
|
||||
"Lj16yE5HvJQn0CNpRdENvRUXe6tBP78O39oJ8BTHp9oIjd6XWXAsp2CvK45Ol8wF\n"
|
||||
"XGF710w9lwCGNbmNxNYhtIkdqfsEcwR5JwIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAvfLHfYH2r9R70w8prHblWt/nDkh+XkgpflqQVcnAfSuTtO05lNPs\n"
|
||||
"pQmL8Y2XjVT4t8cT6xAkdgfmmvnvRPOOKPi0OfJXoRVylFzAQG/j83u5K3kRLbae\n"
|
||||
"7fLccVhKZhY46lvsueI1hQdLgNV9n1cQ3TDS2pQOCtovG4eDl9wacrXOJTG2990V\n"
|
||||
"jgnIKNA0UMoP+KF03qzryqIt3oTvZq03DyWdGK+AZjgBLaDKSnC6qD2cFY81UryR\n"
|
||||
"WOab8zKkWAnhw2kFpcqhI0jdV5QaSCExvnsjVaX0Y1N0870931/5Jb9ICe4nweZ9\n"
|
||||
"kSDF/gip3kWLG0o8XQpChDfyvsqB9OLV/wIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAs/ditzm+mPND6xkhzwFIz6J/968CtkcSE/7Z2qAJiXbmZ3UDJPGr\n"
|
||||
"zqTDHkO30R8VeRM/Kz2f4nR05GIFiITl4bEjvpy7xqRDspJcCFIOcyXm8abVDhF+\n"
|
||||
"th6knSU0yLtNKuQVP6voMrnt9MV1X92LGZQLgdHZbPQz0Z5qIpaKhdyA8DEvWWvS\n"
|
||||
"Uwwc+yi1/gGaybwlzZwqXYoPOhwMebzKUk0xW14htcJrRrq+PXXQbRzTMynseCoP\n"
|
||||
"Ioke0dtCodbA3qQxQovE16q9zz4Otv2k4j63cz53J+mhkVWAeWxVGI0lltJmWtEY\n"
|
||||
"K6er8VqqWot3nqmWMXogrgRLggv/NbbooQIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAvmpxVY7ld/8DAjz6F6q05shjg8/4p6047bn6/m8yPy1RBsvIyvuD\n"
|
||||
"uGnP/RzPEhzXQ9UJ5Ynmh2XJZgHoE9xbnfxL5BXHplJhMtADXKM9bWB11PU1Eioc\n"
|
||||
"3+AXBB8QiNFBn2XI5UkO5hPhbb9mJpjA9Uhw8EdfqJP8QetVsI/xrCEbwEXe0xvi\n"
|
||||
"fRLJbY08/Gp66KpQvy7g8w7VB8wlgePexW3pT13Ap6vuC+mQuJPyiHvSxjEKHgqe\n"
|
||||
"Pji9NP3tJUFQjcECqcm0yV7/2d0t/pbCm+ZH1sadZspQCEPPrtbkQBlvHb4OLiIW\n"
|
||||
"PGHKSMeRFvp3IWcmdJqXahxLCUS1Eh6MAQIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAr4v4wxMDXIaMOh8bayF/NyoYdpcysn5EbjTIOZC0RkgzsRj3SGlu\n"
|
||||
"52QSz+ysO41dQAjpFLgxPVJoOlxXokaOq827IfW0bGCm0doT5hxtedu9UCQKbE8j\n"
|
||||
"lDOk+kWMXHPZFJKWRgKgTu9hcB3y3Vk+JFfLpq3d5ZB48B4bcwrRQnzkx5GhWOFX\n"
|
||||
"x73ZgjO93eoQ2b/lDyXxK4B4IS+hZhjzezPZTI5upTRbs5ljlApsddsHrKk6jJNj\n"
|
||||
"8Ygs/ps8e6ct82jLXbnndC9s8HjEvDvBPH9IPjv5JUlmHMBFZ5vFQIfbpo0u0+1P\n"
|
||||
"n6bkEi5o7/ifoyVv2pAZTRwppTz0EuXD8QIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:false],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEAyMEdY1aR+sCR3ZSJrtztKTKqigvO/vBfqACJLZtS7QMgCGXJ6XIR\n"
|
||||
"yy7mx66W0/sOFa7/1mAZtEoIokDP3ShoqF4fVNb6XeqgQfaUHd8wJpDWHcR2OFwv\n"
|
||||
@ -129,20 +55,23 @@ static NSArray<MTDatacenterAuthPublicKey *> *defaultPublicKeys() {
|
||||
"j25sIWeYPHYeOrFp/eXaqhISP6G+q2IeTaWTXpwZj4LzXq5YOpk4bYEQ6mvRq7D1\n"
|
||||
"aHWfYmlEGepfaYR8Q0YqvvhYtMte3ITnuSJs171+GDqpdKcSwHnd6FudwGO4pcCO\n"
|
||||
"j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----" usesModernPaddingScheme:true]
|
||||
"-----END RSA PUBLIC KEY-----"],
|
||||
[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:@"-----BEGIN RSA PUBLIC KEY-----\n"
|
||||
"MIIBCgKCAQEA6LszBcC1LGzyr992NzE0ieY+BSaOW622Aa9Bd4ZHLl+TuFQ4lo4g\n"
|
||||
"5nKaMBwK/BIb9xUfg0Q29/2mgIR6Zr9krM7HjuIcCzFvDtr+L0GQjae9H0pRB2OO\n"
|
||||
"62cECs5HKhT5DZ98K33vmWiLowc621dQuwKWSQKjWf50XYFw42h21P2KXUGyp2y/\n"
|
||||
"+aEyZ+uVgLLQbRA1dEjSDZ2iGRy12Mk5gpYc397aYp438fsJoHIgJ2lgMv5h7WY9\n"
|
||||
"t6N/byY9Nw9p21Og3AoXSL2q/2IJ1WRUhebgAdGVMlV1fkuOQoEzR7EdpqtQD9Cs\n"
|
||||
"5+bfo3Nhmcyvk5ftB0WkJ9z6bNZ7yxrP8wIDAQAB\n"
|
||||
"-----END RSA PUBLIC KEY-----"]
|
||||
];
|
||||
});
|
||||
return serverPublicKeys;
|
||||
}
|
||||
|
||||
static MTDatacenterAuthPublicKey *selectPublicKey(id<EncryptionProvider> encryptionProvider, NSArray<NSNumber *> *fingerprints, NSArray<MTDatacenterAuthPublicKey *> *publicKeys, bool onlyModernPadding) {
|
||||
static MTDatacenterAuthPublicKey *selectPublicKey(id<EncryptionProvider> encryptionProvider, NSArray<NSNumber *> *fingerprints, NSArray<MTDatacenterAuthPublicKey *> *publicKeys) {
|
||||
for (NSNumber *nFingerprint in fingerprints) {
|
||||
for (MTDatacenterAuthPublicKey *key in publicKeys) {
|
||||
if (onlyModernPadding) {
|
||||
if (!key.usesModernPaddingScheme) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
uint64_t keyFingerprint = [key fingerprintWithEncryptionProvider:encryptionProvider];
|
||||
|
||||
if ([nFingerprint unsignedLongLongValue] == keyFingerprint) {
|
||||
@ -208,7 +137,7 @@ typedef enum {
|
||||
for (NSDictionary *dict in list) {
|
||||
NSString *key = dict[@"key"];
|
||||
if ([key isKindOfClass:[NSString class]]) {
|
||||
[cdnKeys addObject:[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:key usesModernPaddingScheme:false]];
|
||||
[cdnKeys addObject:[[MTDatacenterAuthPublicKey alloc] initWithPublicKey:key]];
|
||||
}
|
||||
}
|
||||
return cdnKeys;
|
||||
@ -434,7 +363,7 @@ static NSData *reversedBytes(NSData *data) {
|
||||
static NSData *encryptRSAModernPadding(id<EncryptionProvider> encryptionProvider, NSData *pqInnerData, NSString *publicKey) {
|
||||
NSMutableData *dataWithPadding = [[NSMutableData alloc] init];
|
||||
[dataWithPadding appendData:pqInnerData];
|
||||
if (dataWithPadding.length > 192) {
|
||||
if (dataWithPadding.length > 144) {
|
||||
return nil;
|
||||
}
|
||||
if (dataWithPadding.length != 192) {
|
||||
@ -538,10 +467,7 @@ static NSData *encryptRSAModernPadding(id<EncryptionProvider> encryptionProvider
|
||||
|
||||
if ([_nonce isEqualToData:resPqMessage.nonce])
|
||||
{
|
||||
MTDatacenterAuthPublicKey *publicKey = selectPublicKey(_encryptionProvider, resPqMessage.serverPublicKeyFingerprints, _publicKeys, true);
|
||||
if (publicKey == nil) {
|
||||
publicKey = selectPublicKey(mtProto.context.encryptionProvider, resPqMessage.serverPublicKeyFingerprints, _publicKeys, false);
|
||||
}
|
||||
MTDatacenterAuthPublicKey *publicKey = selectPublicKey(_encryptionProvider, resPqMessage.serverPublicKeyFingerprints, _publicKeys);
|
||||
|
||||
if (publicKey == nil && mtProto.cdn && resPqMessage.serverPublicKeyFingerprints.count == 1 && _publicKeys.count == 1) {
|
||||
publicKey = _publicKeys[0];
|
||||
@ -618,11 +544,8 @@ static NSData *encryptRSAModernPadding(id<EncryptionProvider> encryptionProvider
|
||||
|
||||
NSData *innerDataBytes = innerDataBuffer.data;
|
||||
NSData *encryptedData = nil;
|
||||
if (publicKey.usesModernPaddingScheme) {
|
||||
encryptedData = encryptRSAModernPadding(_encryptionProvider, innerDataBytes, publicKey.publicKey);
|
||||
} else {
|
||||
encryptedData = encryptRSALegacy(_encryptionProvider, innerDataBytes, publicKey.publicKey);
|
||||
}
|
||||
|
||||
encryptedData = encryptRSAModernPadding(_encryptionProvider, innerDataBytes, publicKey.publicKey);
|
||||
|
||||
if (MTLogEnabled()) {
|
||||
MTLog(@"[MTDatacenterAuthMessageService#%p encryptedData length %d]", self, (int)encryptedData.length);
|
||||
@ -642,11 +565,8 @@ static NSData *encryptRSAModernPadding(id<EncryptionProvider> encryptionProvider
|
||||
NSData *innerDataBytes = innerDataBuffer.data;
|
||||
|
||||
NSData *encryptedData = nil;
|
||||
if (publicKey.usesModernPaddingScheme) {
|
||||
encryptedData = encryptRSAModernPadding(_encryptionProvider, innerDataBytes, publicKey.publicKey);
|
||||
} else {
|
||||
encryptedData = encryptRSALegacy(_encryptionProvider, innerDataBytes, publicKey.publicKey);
|
||||
}
|
||||
|
||||
encryptedData = encryptRSAModernPadding(_encryptionProvider, innerDataBytes, publicKey.publicKey);
|
||||
|
||||
_dhEncryptedData = encryptedData;
|
||||
}
|
||||
|
@ -927,14 +927,14 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
return current.withUpdatedUpdating(true)
|
||||
}
|
||||
if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
updateRightsDisposable.set((removeGroupAdmin(account: context.account, peerId: peerId, adminId: adminId)
|
||||
updateRightsDisposable.set((context.engine.peers.removeGroupAdmin(peerId: peerId, adminId: adminId)
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
}, completed: {
|
||||
updated(nil)
|
||||
dismissImpl?()
|
||||
}))
|
||||
} else {
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: peerId, memberId: adminId, adminRights: nil, rank: nil) |> deliverOnMainQueue).start(error: { _ in
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: nil, rank: nil) |> deliverOnMainQueue).start(error: { _ in
|
||||
|
||||
}, completed: {
|
||||
updated(nil)
|
||||
@ -1041,7 +1041,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
updateState { current in
|
||||
return current.withUpdatedUpdating(true)
|
||||
}
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags ?? []), rank: effectiveRank) |> deliverOnMainQueue).start(error: { error in
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags ?? []), rank: effectiveRank) |> deliverOnMainQueue).start(error: { error in
|
||||
updateState { current in
|
||||
return current.withUpdatedUpdating(false)
|
||||
}
|
||||
@ -1089,7 +1089,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
updateState { current in
|
||||
return current.withUpdatedUpdating(true)
|
||||
}
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: currentFlags), rank: updateRank) |> deliverOnMainQueue).start(error: { _ in
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: currentFlags), rank: updateRank) |> deliverOnMainQueue).start(error: { _ in
|
||||
|
||||
}, completed: {
|
||||
updated(TelegramChatAdminRights(rights: currentFlags))
|
||||
@ -1134,7 +1134,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
updateState { current in
|
||||
return current.withUpdatedUpdating(true)
|
||||
}
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags), rank: updateRank) |> deliverOnMainQueue).start(error: { error in
|
||||
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags), rank: updateRank) |> deliverOnMainQueue).start(error: { error in
|
||||
if case let .addMemberError(addMemberError) = error, let admin = adminView.peers[adminView.peerId] {
|
||||
var text = presentationData.strings.Login_UnknownError
|
||||
switch addMemberError {
|
||||
@ -1201,7 +1201,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
updateState { current in
|
||||
return current.withUpdatedUpdating(true)
|
||||
}
|
||||
updateRightsDisposable.set((addGroupAdmin(account: context.account, peerId: peerId, adminId: adminId)
|
||||
updateRightsDisposable.set((context.engine.peers.addGroupAdmin(peerId: peerId, adminId: adminId)
|
||||
|> deliverOnMainQueue).start(error: { error in
|
||||
if case let .addMemberError(error) = error, case .privacy = error, let admin = adminView.peers[adminView.peerId] {
|
||||
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Privacy_GroupsAndChannels_InviteToGroupError(admin.compactDisplayTitle, admin.compactDisplayTitle).0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
@ -1234,7 +1234,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
guard let upgradedPeerId = upgradedPeerId else {
|
||||
return .fail(.conversionFailed)
|
||||
}
|
||||
return context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: upgradedPeerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags), rank: updateRank)
|
||||
return context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: upgradedPeerId, memberId: adminId, adminRights: TelegramChatAdminRights(rights: updateFlags), rank: updateRank)
|
||||
|> mapError { error -> WrappedUpdateChannelAdminRightsError in
|
||||
return .direct(error)
|
||||
}
|
||||
|
@ -583,14 +583,14 @@ public func channelAdminsController(context: AccountContext, peerId initialPeerI
|
||||
return $0.withUpdatedRemovingPeerId(adminId)
|
||||
}
|
||||
if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
removeAdminDisposable.set((removeGroupAdmin(account: context.account, peerId: peerId, adminId: adminId)
|
||||
removeAdminDisposable.set((context.engine.peers.removeGroupAdmin(peerId: peerId, adminId: adminId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
updateState {
|
||||
return $0.withUpdatedRemovingPeerId(nil)
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
removeAdminDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: peerId, memberId: adminId, adminRights: nil, rank: nil)
|
||||
removeAdminDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: adminId, adminRights: nil, rank: nil)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
updateState {
|
||||
return $0.withUpdatedRemovingPeerId(nil)
|
||||
|
@ -391,7 +391,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
|
||||
let signal = context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: nil)
|
||||
|> ignoreValues
|
||||
|> then(
|
||||
context.peerChannelMemberCategoriesContextsManager.addMember(account: context.account, peerId: peerId, memberId: memberId)
|
||||
context.peerChannelMemberCategoriesContextsManager.addMember(engine: context.engine, peerId: peerId, memberId: memberId)
|
||||
|> map { _ -> Void in
|
||||
return Void()
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) ->
|
||||
contacts = peerIdsValue
|
||||
}
|
||||
|
||||
let signal = context.peerChannelMemberCategoriesContextsManager.addMembers(account: context.account, peerId: peerId, memberIds: contacts.compactMap({ contact -> PeerId? in
|
||||
let signal = context.peerChannelMemberCategoriesContextsManager.addMembers(engine: context.engine, peerId: peerId, memberIds: contacts.compactMap({ contact -> PeerId? in
|
||||
switch contact {
|
||||
case let .peer(contactId):
|
||||
return contactId
|
||||
|
@ -437,7 +437,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
||||
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
if case .searchAdmins = mode {
|
||||
return context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(account: context.account, peerId: peerId, memberId: memberId, adminRights: nil, rank: nil)
|
||||
return context.peerChannelMemberCategoriesContextsManager.updateMemberAdminRights(engine: context.engine, peerId: peerId, memberId: memberId, adminRights: nil, rank: nil)
|
||||
|> `catch` { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
@ -465,7 +465,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|
||||
}
|
||||
|
||||
if case .searchAdmins = mode {
|
||||
return removeGroupAdmin(account: context.account, peerId: peerId, adminId: memberId)
|
||||
return context.engine.peers.removeGroupAdmin(peerId: peerId, adminId: memberId)
|
||||
|> `catch` { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|
@ -1357,7 +1357,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(peerId), keepStack: .never, animated: true))
|
||||
} else {
|
||||
selectionController.displayProgress = true
|
||||
let _ = (addChannelMembers(account: context.account, peerId: peerId, memberIds: filteredPeerIds)
|
||||
let _ = (context.engine.peers.addChannelMembers(peerId: peerId, memberIds: filteredPeerIds)
|
||||
|> deliverOnMainQueue).start(error: { [weak selectionController] _ in
|
||||
guard let selectionController = selectionController, let navigationController = selectionController.navigationController as? NavigationController else {
|
||||
return
|
||||
|
@ -455,21 +455,21 @@ public func oldChannelsController(context: AccountContext, intent: OldChannelsCo
|
||||
let state = stateValue.with { $0 }
|
||||
let _ = (peersPromise.get()
|
||||
|> take(1)
|
||||
|> mapToSignal { peers in
|
||||
|> mapToSignal { peers -> Signal<Never, NoError> in
|
||||
let peers = peers ?? []
|
||||
return context.account.postbox.transaction { transaction -> Void in
|
||||
if let peers = peers {
|
||||
for peer in peers {
|
||||
if state.selectedPeers.contains(peer.peer.id) {
|
||||
if transaction.getPeer(peer.peer.id) == nil {
|
||||
updatePeers(transaction: transaction, peers: [peer.peer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
removePeerChat(account: context.account, transaction: transaction, mediaBox: context.account.postbox.mediaBox, peerId: peer.peer.id, reportChatSpam: false, deleteGloballyIfPossible: false)
|
||||
for peer in peers {
|
||||
if state.selectedPeers.contains(peer.peer.id) {
|
||||
if transaction.getPeer(peer.peer.id) == nil {
|
||||
updatePeers(transaction: transaction, peers: [peer.peer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
|> then(context.engine.peers.removePeerChats(peerIds: Array(peers.map(\.peer.id))))
|
||||
}
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
completed(true)
|
||||
|
@ -453,7 +453,7 @@ public func dataPrivacyController(context: AccountContext) -> ViewController {
|
||||
state.updatedSuggestFrequentContacts = value
|
||||
return state
|
||||
}
|
||||
let _ = updateRecentPeersEnabled(postbox: context.account.postbox, network: context.account.network, enabled: value).start()
|
||||
let _ = context.engine.peers.updateRecentPeersEnabled(enabled: value).start()
|
||||
}
|
||||
if !value {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
@ -503,9 +503,9 @@ public func dataPrivacyController(context: AccountContext) -> ViewController {
|
||||
|
||||
let previousState = Atomic<DataPrivacyControllerState?>(value: nil)
|
||||
|
||||
actionsDisposable.add(managedUpdatedRecentPeers(accountPeerId: context.account.peerId, postbox: context.account.postbox, network: context.account.network).start())
|
||||
actionsDisposable.add(context.engine.peers.managedUpdatedRecentPeers().start())
|
||||
|
||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings]), recentPeers(account: context.account))
|
||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), context.account.postbox.preferencesView(keys: [PreferencesKeys.contactsSettings]), context.engine.peers.recentPeers())
|
||||
|> map { presentationData, state, noticeView, sharedData, preferences, recentPeers -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
let secretChatLinkPreviews = noticeView.value.flatMap({ ApplicationSpecificNotice.getSecretChatLinkPreviews($0) })
|
||||
|
||||
|
@ -851,7 +851,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
||||
pushControllerImpl?(dataPrivacyController(context: context), true)
|
||||
})
|
||||
|
||||
actionsDisposable.add(managedUpdatedRecentPeers(accountPeerId: context.account.peerId, postbox: context.account.postbox, network: context.account.network).start())
|
||||
actionsDisposable.add(context.engine.peers.managedUpdatedRecentPeers().start())
|
||||
|
||||
actionsDisposable.add((privacySettingsPromise.get()
|
||||
|> deliverOnMainQueue).start(next: { settings in
|
||||
@ -865,7 +865,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
|
||||
|
||||
let preferencesKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.appConfiguration]))
|
||||
|
||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), privacySettingsPromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), recentPeers(account: context.account), blockedPeersState.get(), webSessionsContext.state, context.sharedContext.accountManager.accessChallengeData(), combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()), context.account.postbox.combinedView(keys: [preferencesKey]))
|
||||
let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), privacySettingsPromise.get(), context.sharedContext.accountManager.noticeEntry(key: ApplicationSpecificNotice.secretChatLinkPreviewsKey()), context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.contactSynchronizationSettings]), context.engine.peers.recentPeers(), blockedPeersState.get(), webSessionsContext.state, context.sharedContext.accountManager.accessChallengeData(), combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()), context.account.postbox.combinedView(keys: [preferencesKey]))
|
||||
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, preferences -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
var canAutoarchive = false
|
||||
if let view = preferences.views[preferencesKey] as? PreferencesView, let appConfiguration = view.values[PreferencesKeys.appConfiguration] as? AppConfiguration, let data = appConfiguration.data, let hasAutoarchive = data["autoarchive_setting_available"] as? Bool {
|
||||
|
@ -848,7 +848,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode {
|
||||
}
|
||||
|
||||
private func clearRecentSearch() {
|
||||
let _ = (clearRecentlySearchedPeers(postbox: self.context.account.postbox) |> deliverOnMainQueue).start()
|
||||
let _ = (self.context.engine.peers.clearRecentlySearchedPeers() |> deliverOnMainQueue).start()
|
||||
}
|
||||
|
||||
override func scrollToTop() {
|
||||
|
@ -435,7 +435,7 @@ public final class ShareController: ViewController {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = (exportMessageLink(account: strongSelf.currentAccount, peerId: chatPeer.id, messageId: message.id)
|
||||
let _ = (TelegramEngine(account: strongSelf.currentAccount).messages.exportMessageLink(peerId: chatPeer.id, messageId: message.id)
|
||||
|> map { result -> String? in
|
||||
return result
|
||||
}
|
||||
|
@ -743,7 +743,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}, extendedInitialReveal: self.presetText != nil, segmentedValues: self.segmentedValues)
|
||||
self.peersContentNode = peersContentNode
|
||||
peersContentNode.openSearch = { [weak self] in
|
||||
let _ = (recentlySearchedPeers(postbox: context.account.postbox)
|
||||
let _ = (context.engine.peers.recentlySearchedPeers()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { peers in
|
||||
if let strongSelf = self {
|
||||
|
@ -333,7 +333,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode {
|
||||
self?.searchQuery.set(text)
|
||||
}
|
||||
|
||||
let hasRecentPeers = recentPeers(account: context.account)
|
||||
let hasRecentPeers = context.engine.peers.recentPeers()
|
||||
|> map { value -> Bool in
|
||||
switch value {
|
||||
case let .peers(peers):
|
||||
|
@ -901,7 +901,7 @@ public func groupStatsController(context: AccountContext, peerId: PeerId, cached
|
||||
}
|
||||
promotePeerImpl = { [weak controller] participantPeerId in
|
||||
if let navigationController = controller?.navigationController as? NavigationController {
|
||||
let _ = (fetchChannelParticipant(account: context.account, peerId: peerId, participantId: participantPeerId)
|
||||
let _ = (context.engine.peers.fetchChannelParticipant(peerId: peerId, participantId: participantPeerId)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { participant in
|
||||
if let participant = participant, let controller = context.sharedContext.makeChannelAdminController(context: context, peerId: peerId, adminId: participantPeerId, initialParticipant: participant) {
|
||||
|
@ -1286,7 +1286,7 @@ public final class VoiceChatController: ViewController {
|
||||
if let groupPeer = groupPeer as? TelegramChannel {
|
||||
let selfController = strongSelf.controller
|
||||
let inviteDisposable = strongSelf.inviteDisposable
|
||||
var inviteSignal = strongSelf.context.peerChannelMemberCategoriesContextsManager.addMembers(account: strongSelf.context.account, peerId: groupPeer.id, memberIds: [peer.id])
|
||||
var inviteSignal = strongSelf.context.peerChannelMemberCategoriesContextsManager.addMembers(engine: strongSelf.context.engine, peerId: groupPeer.id, memberIds: [peer.id])
|
||||
var cancelImpl: (() -> Void)?
|
||||
let progressSignal = Signal<Never, NoError> { [weak selfController] subscriber in
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: {
|
||||
@ -1358,7 +1358,7 @@ public final class VoiceChatController: ViewController {
|
||||
} else if let groupPeer = groupPeer as? TelegramGroup {
|
||||
let selfController = strongSelf.controller
|
||||
let inviteDisposable = strongSelf.inviteDisposable
|
||||
var inviteSignal = addGroupMember(account: strongSelf.context.account, peerId: groupPeer.id, memberId: peer.id)
|
||||
var inviteSignal = strongSelf.context.engine.peers.addGroupMember(peerId: groupPeer.id, memberId: peer.id)
|
||||
var cancelImpl: (() -> Void)?
|
||||
let progressSignal = Signal<Never, NoError> { [weak selfController] subscriber in
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: {
|
||||
|
@ -1055,7 +1055,7 @@ public class Account {
|
||||
self.managedOperationsDisposable.add(managedSynchronizeRecentlyUsedMediaOperations(postbox: self.postbox, network: self.network, category: .stickers, revalidationContext: self.mediaReferenceRevalidationContext).start())
|
||||
self.managedOperationsDisposable.add(managedSynchronizeSavedGifsOperations(postbox: self.postbox, network: self.network, revalidationContext: self.mediaReferenceRevalidationContext).start())
|
||||
self.managedOperationsDisposable.add(managedSynchronizeSavedStickersOperations(postbox: self.postbox, network: self.network, revalidationContext: self.mediaReferenceRevalidationContext).start())
|
||||
self.managedOperationsDisposable.add(managedRecentlyUsedInlineBots(postbox: self.postbox, network: self.network, accountPeerId: peerId).start())
|
||||
self.managedOperationsDisposable.add(_internal_managedRecentlyUsedInlineBots(postbox: self.postbox, network: self.network, accountPeerId: peerId).start())
|
||||
self.managedOperationsDisposable.add(managedLocalTypingActivities(activities: self.localInputActivityManager.allActivities(), postbox: self.postbox, network: self.network, accountPeerId: self.peerId).start())
|
||||
self.managedOperationsDisposable.add(managedSynchronizeConsumeMessageContentOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||
self.managedOperationsDisposable.add(managedConsumePersonalMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||
|
@ -10,7 +10,7 @@ public enum NotificationTokenType {
|
||||
case voip
|
||||
}
|
||||
|
||||
public func unregisterNotificationToken(account: Account, token: Data, type: NotificationTokenType, otherAccountUserIds: [PeerId.Id]) -> Signal<Never, NoError> {
|
||||
func _internal_unregisterNotificationToken(account: Account, token: Data, type: NotificationTokenType, otherAccountUserIds: [PeerId.Id]) -> Signal<Never, NoError> {
|
||||
let mappedType: Int32
|
||||
switch type {
|
||||
case .aps:
|
||||
@ -23,7 +23,7 @@ public func unregisterNotificationToken(account: Account, token: Data, type: Not
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func registerNotificationToken(account: Account, token: Data, type: NotificationTokenType, sandbox: Bool, otherAccountUserIds: [PeerId.Id], excludeMutedChats: Bool) -> Signal<Never, NoError> {
|
||||
func _internal_registerNotificationToken(account: Account, token: Data, type: NotificationTokenType, sandbox: Bool, otherAccountUserIds: [PeerId.Id], excludeMutedChats: Bool) -> Signal<Never, NoError> {
|
||||
return masterNotificationsKey(account: account, ignoreDisabled: false)
|
||||
|> mapToSignal { masterKey -> Signal<Never, NoError> in
|
||||
let mappedType: Int32
|
@ -1,4 +1,7 @@
|
||||
import Foundation
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import SyncCore
|
||||
|
||||
public extension TelegramEngine {
|
||||
final class AccountData {
|
||||
@ -35,5 +38,13 @@ public extension TelegramEngine {
|
||||
public func updateAbout(about: String?) -> Signal<Void, UpdateAboutError> {
|
||||
return _internal_updateAbout(account: self.account, about: about)
|
||||
}
|
||||
|
||||
public func unregisterNotificationToken(token: Data, type: NotificationTokenType, otherAccountUserIds: [PeerId.Id]) -> Signal<Never, NoError> {
|
||||
return _internal_unregisterNotificationToken(account: self.account, token: token, type: type, otherAccountUserIds: otherAccountUserIds)
|
||||
}
|
||||
|
||||
public func registerNotificationToken(token: Data, type: NotificationTokenType, sandbox: Bool, otherAccountUserIds: [PeerId.Id], excludeMutedChats: Bool) -> Signal<Never, NoError> {
|
||||
return _internal_registerNotificationToken(account: self.account, token: token, type: type, sandbox: sandbox, otherAccountUserIds: otherAccountUserIds, excludeMutedChats: excludeMutedChats)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ public enum EarliestUnseenPersonalMentionMessageResult: Equatable {
|
||||
case result(MessageId?)
|
||||
}
|
||||
|
||||
public func earliestUnseenPersonalMentionMessage(account: Account, peerId: PeerId) -> Signal<EarliestUnseenPersonalMentionMessageResult, NoError> {
|
||||
func _internal_earliestUnseenPersonalMentionMessage(account: Account, peerId: PeerId) -> Signal<EarliestUnseenPersonalMentionMessageResult, NoError> {
|
||||
return account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId), index: .lowerBound, anchorIndex: .lowerBound, count: 4, fixedCombinedReadStates: nil, tagMask: .unseenPersonalMessage, additionalData: [.peerChatState(peerId)])
|
||||
|> mapToSignal { view -> Signal<EarliestUnseenPersonalMentionMessageResult, NoError> in
|
||||
if view.0.isLoading {
|
@ -3,7 +3,7 @@ import Postbox
|
||||
import TelegramApi
|
||||
import SwiftSignalKit
|
||||
|
||||
public func exportMessageLink(account: Account, peerId: PeerId, messageId: MessageId, isThread: Bool = false) -> Signal<String?, NoError> {
|
||||
func _internal_exportMessageLink(account: Account, peerId: PeerId, messageId: MessageId, isThread: Bool = false) -> Signal<String?, NoError> {
|
||||
return account.postbox.transaction { transaction -> (Peer, MessageId)? in
|
||||
var peer: Peer? = transaction.getPeer(messageId.peerId)
|
||||
if let peer = peer {
|
@ -5,7 +5,7 @@ import SwiftSignalKit
|
||||
|
||||
import SyncCore
|
||||
|
||||
public func installInteractiveReadMessagesAction(postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId) -> Disposable {
|
||||
func _internal_installInteractiveReadMessagesAction(postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId) -> Disposable {
|
||||
return postbox.installStoreMessageAction(peerId: peerId, { messages, transaction in
|
||||
var consumeMessageIds: [MessageId] = []
|
||||
|
@ -5,7 +5,7 @@ import SwiftSignalKit
|
||||
|
||||
import SyncCore
|
||||
|
||||
public func markMessageContentAsConsumedInteractively(postbox: Postbox, messageId: MessageId) -> Signal<Void, NoError> {
|
||||
func _internal_markMessageContentAsConsumedInteractively(postbox: Postbox, messageId: MessageId) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if let message = transaction.getMessage(messageId), message.flags.contains(.Incoming) {
|
||||
var updateMessage = false
|
@ -10,7 +10,7 @@ public enum RequestMessageSelectPollOptionError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func requestMessageSelectPollOption(account: Account, messageId: MessageId, opaqueIdentifiers: [Data]) -> Signal<TelegramMediaPoll?, RequestMessageSelectPollOptionError> {
|
||||
func _internal_requestMessageSelectPollOption(account: Account, messageId: MessageId, opaqueIdentifiers: [Data]) -> Signal<TelegramMediaPoll?, RequestMessageSelectPollOptionError> {
|
||||
return account.postbox.loadedPeerWithId(messageId.peerId)
|
||||
|> take(1)
|
||||
|> castError(RequestMessageSelectPollOptionError.self)
|
||||
@ -80,7 +80,7 @@ public func requestMessageSelectPollOption(account: Account, messageId: MessageI
|
||||
}
|
||||
}
|
||||
|
||||
public func requestClosePoll(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId) -> Signal<Void, NoError> {
|
||||
func _internal_requestClosePoll(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> (TelegramMediaPoll, Api.InputPeer)? in
|
||||
guard let inputPeer = transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) else {
|
||||
return nil
|
||||
@ -419,7 +419,7 @@ public final class PollResultsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public init(account: Account, messageId: MessageId, poll: TelegramMediaPoll) {
|
||||
init(account: Account, messageId: MessageId, poll: TelegramMediaPoll) {
|
||||
let queue = self.queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return PollResultsContextImpl(queue: queue, account: account, messageId: messageId, poll: poll)
|
@ -55,7 +55,7 @@ func _internal_requestStartBotInGroup(account: Account, botPeerId: PeerId, group
|
||||
|> mapToSignal { result -> Signal<StartBotInGroupResult, RequestStartBotInGroupError> in
|
||||
account.stateManager.addUpdates(result)
|
||||
if groupPeerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
return fetchChannelParticipant(account: account, peerId: groupPeerId, participantId: botPeerId)
|
||||
return _internal_fetchChannelParticipant(account: account, peerId: groupPeerId, participantId: botPeerId)
|
||||
|> mapError { _ -> RequestStartBotInGroupError in return .generic
|
||||
}
|
||||
|> mapToSignal { participant -> Signal<StartBotInGroupResult, RequestStartBotInGroupError> in
|
||||
|
@ -1,3 +1,4 @@
|
||||
import Foundation
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import SyncCore
|
||||
@ -122,5 +123,33 @@ public extension TelegramEngine {
|
||||
public func getMessagesLoadIfNecessary(_ messageIds: [MessageId], strategy: GetMessagesStrategy = .cloud) -> Signal <[Message], NoError> {
|
||||
return _internal_getMessagesLoadIfNecessary(messageIds, postbox: self.account.postbox, network: self.account.network, accountPeerId: self.account.peerId, strategy: strategy)
|
||||
}
|
||||
|
||||
public func markMessageContentAsConsumedInteractively(messageId: MessageId) -> Signal<Void, NoError> {
|
||||
return _internal_markMessageContentAsConsumedInteractively(postbox: self.account.postbox, messageId: messageId)
|
||||
}
|
||||
|
||||
public func installInteractiveReadMessagesAction(peerId: PeerId) -> Disposable {
|
||||
return _internal_installInteractiveReadMessagesAction(postbox: self.account.postbox, stateManager: self.account.stateManager, peerId: peerId)
|
||||
}
|
||||
|
||||
public func requestMessageSelectPollOption(messageId: MessageId, opaqueIdentifiers: [Data]) -> Signal<TelegramMediaPoll?, RequestMessageSelectPollOptionError> {
|
||||
return _internal_requestMessageSelectPollOption(account: self.account, messageId: messageId, opaqueIdentifiers: opaqueIdentifiers)
|
||||
}
|
||||
|
||||
public func requestClosePoll(messageId: MessageId) -> Signal<Void, NoError> {
|
||||
return _internal_requestClosePoll(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, messageId: messageId)
|
||||
}
|
||||
|
||||
public func pollResults(messageId: MessageId, poll: TelegramMediaPoll) -> PollResultsContext {
|
||||
return PollResultsContext(account: self.account, messageId: messageId, poll: poll)
|
||||
}
|
||||
|
||||
public func earliestUnseenPersonalMentionMessage(peerId: PeerId) -> Signal<EarliestUnseenPersonalMentionMessageResult, NoError> {
|
||||
return _internal_earliestUnseenPersonalMentionMessage(account: self.account, peerId: peerId)
|
||||
}
|
||||
|
||||
public func exportMessageLink(peerId: PeerId, messageId: MessageId, isThread: Bool = false) -> Signal<String?, NoError> {
|
||||
return _internal_exportMessageLink(account: self.account, peerId: peerId, messageId: messageId, isThread: isThread)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ public enum AddGroupMemberError {
|
||||
case tooManyChannels
|
||||
}
|
||||
|
||||
public func addGroupMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<Void, AddGroupMemberError> {
|
||||
func _internal_addGroupMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<Void, AddGroupMemberError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, AddGroupMemberError> in
|
||||
if let peer = transaction.getPeer(peerId), let memberPeer = transaction.getPeer(memberId), let inputUser = apiInputUser(memberPeer) {
|
||||
if let group = peer as? TelegramGroup {
|
||||
@ -79,8 +79,8 @@ public enum AddChannelMemberError {
|
||||
case tooMuchBots
|
||||
}
|
||||
|
||||
public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> {
|
||||
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|
||||
func _internal_addChannelMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> {
|
||||
return _internal_fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|
||||
|> mapError { error -> AddChannelMemberError in
|
||||
}
|
||||
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> in
|
||||
@ -180,7 +180,7 @@ public func addChannelMember(account: Account, peerId: PeerId, memberId: PeerId)
|
||||
}
|
||||
}
|
||||
|
||||
public func addChannelMembers(account: Account, peerId: PeerId, memberIds: [PeerId]) -> Signal<Void, AddChannelMemberError> {
|
||||
func _internal_addChannelMembers(account: Account, peerId: PeerId, memberIds: [PeerId]) -> Signal<Void, AddChannelMemberError> {
|
||||
let signal = account.postbox.transaction { transaction -> Signal<Void, AddChannelMemberError> in
|
||||
var memberPeerIds: [PeerId:Peer] = [:]
|
||||
var inputUsers: [Api.InputUser] = []
|
@ -6,7 +6,7 @@ import MtProtoKit
|
||||
import SyncCore
|
||||
|
||||
func _internal_updateChannelMemberBannedRights(account: Account, peerId: PeerId, memberId: PeerId, rights: TelegramChatBannedRights?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> {
|
||||
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|
||||
return _internal_fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|
||||
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
|
||||
return account.postbox.transaction { transaction -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
|
||||
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer), let _ = transaction.getPeer(account.peerId), let memberPeer = transaction.getPeer(memberId), let inputPeer = apiInputPeer(memberPeer) {
|
||||
|
@ -77,7 +77,7 @@ func _internal_updateChannelOwnership(account: Account, accountStateManager: Acc
|
||||
return .fail(.invalidPassword)
|
||||
}
|
||||
|
||||
return combineLatest(fetchChannelParticipant(account: account, peerId: channelId, participantId: account.peerId), fetchChannelParticipant(account: account, peerId: channelId, participantId: memberId))
|
||||
return combineLatest(_internal_fetchChannelParticipant(account: account, peerId: channelId, participantId: account.peerId), _internal_fetchChannelParticipant(account: account, peerId: channelId, participantId: memberId))
|
||||
|> mapError { error -> ChannelOwnershipTransferError in
|
||||
return .generic
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ public enum RemoveGroupAdminError {
|
||||
case generic
|
||||
}
|
||||
|
||||
public func removeGroupAdmin(account: Account, peerId: PeerId, adminId: PeerId) -> Signal<Void, RemoveGroupAdminError> {
|
||||
func _internal_removeGroupAdmin(account: Account, peerId: PeerId, adminId: PeerId) -> Signal<Void, RemoveGroupAdminError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, RemoveGroupAdminError> in
|
||||
if let peer = transaction.getPeer(peerId), let adminPeer = transaction.getPeer(adminId), let inputUser = apiInputUser(adminPeer) {
|
||||
if let group = peer as? TelegramGroup {
|
||||
@ -58,14 +58,14 @@ public enum AddGroupAdminError {
|
||||
case adminsTooMuch
|
||||
}
|
||||
|
||||
public func addGroupAdmin(account: Account, peerId: PeerId, adminId: PeerId) -> Signal<Void, AddGroupAdminError> {
|
||||
func _internal_addGroupAdmin(account: Account, peerId: PeerId, adminId: PeerId) -> Signal<Void, AddGroupAdminError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, AddGroupAdminError> in
|
||||
if let peer = transaction.getPeer(peerId), let adminPeer = transaction.getPeer(adminId), let inputUser = apiInputUser(adminPeer) {
|
||||
if let group = peer as? TelegramGroup {
|
||||
return account.network.request(Api.functions.messages.editChatAdmin(chatId: group.id.id._internalGetInt32Value(), userId: inputUser, isAdmin: .boolTrue))
|
||||
|> `catch` { error -> Signal<Api.Bool, AddGroupAdminError> in
|
||||
if error.errorDescription == "USER_NOT_PARTICIPANT" {
|
||||
return addGroupMember(account: account, peerId: peerId, memberId: adminId)
|
||||
return _internal_addGroupMember(account: account, peerId: peerId, memberId: adminId)
|
||||
|> mapError { error -> AddGroupAdminError in
|
||||
return .addMemberError(error)
|
||||
}
|
||||
@ -127,7 +127,7 @@ public enum UpdateChannelAdminRightsError {
|
||||
case adminsTooMuch
|
||||
}
|
||||
|
||||
public func fetchChannelParticipant(account: Account, peerId: PeerId, participantId: PeerId) -> Signal<ChannelParticipant?, NoError> {
|
||||
func _internal_fetchChannelParticipant(account: Account, peerId: PeerId, participantId: PeerId) -> Signal<ChannelParticipant?, NoError> {
|
||||
return account.postbox.transaction { transaction -> Signal<ChannelParticipant?, NoError> in
|
||||
if let peer = transaction.getPeer(peerId), let adminPeer = transaction.getPeer(participantId), let inputPeer = apiInputPeer(adminPeer) {
|
||||
if let channel = peer as? TelegramChannel, let inputChannel = apiInputChannel(channel) {
|
||||
@ -150,8 +150,8 @@ public func fetchChannelParticipant(account: Account, peerId: PeerId, participan
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
public func updateChannelAdminRights(account: Account, peerId: PeerId, adminId: PeerId, rights: TelegramChatAdminRights?, rank: String?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), UpdateChannelAdminRightsError> {
|
||||
return fetchChannelParticipant(account: account, peerId: peerId, participantId: adminId)
|
||||
func _internal_updateChannelAdminRights(account: Account, peerId: PeerId, adminId: PeerId, rights: TelegramChatAdminRights?, rank: String?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), UpdateChannelAdminRightsError> {
|
||||
return _internal_fetchChannelParticipant(account: account, peerId: peerId, participantId: adminId)
|
||||
|> mapError { error -> UpdateChannelAdminRightsError in
|
||||
}
|
||||
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant), UpdateChannelAdminRightsError> in
|
||||
@ -188,7 +188,7 @@ public func updateChannelAdminRights(account: Account, peerId: PeerId, adminId:
|
||||
|> map { [$0] }
|
||||
|> `catch` { error -> Signal<[Api.Updates], UpdateChannelAdminRightsError> in
|
||||
if error.errorDescription == "USER_NOT_PARTICIPANT" {
|
||||
return addChannelMember(account: account, peerId: peerId, memberId: adminId)
|
||||
return _internal_addChannelMember(account: account, peerId: peerId, memberId: adminId)
|
||||
|> map { _ -> [Api.Updates] in
|
||||
return []
|
||||
}
|
@ -17,7 +17,7 @@ public struct PeerSpecificStickerPackData {
|
||||
public let canSetup: Bool
|
||||
}
|
||||
|
||||
public func peerSpecificStickerPack(postbox: Postbox, network: Network, peerId: PeerId) -> Signal<PeerSpecificStickerPackData, NoError> {
|
||||
func _internal_peerSpecificStickerPack(postbox: Postbox, network: Network, peerId: PeerId) -> Signal<PeerSpecificStickerPackData, NoError> {
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
let signal: Signal<(WrappedStickerPackCollectionInfo, Bool), NoError> = postbox.combinedView(keys: [.cachedPeerData(peerId: peerId)])
|
||||
|> map { view -> (WrappedStickerPackCollectionInfo, Bool) in
|
@ -16,7 +16,7 @@ private func cachedRecentPeersEntryId() -> ItemCacheEntryId {
|
||||
return ItemCacheEntryId(collectionId: 101, key: CachedRecentPeers.cacheKey())
|
||||
}
|
||||
|
||||
public func recentPeers(account: Account) -> Signal<RecentPeers, NoError> {
|
||||
func _internal_recentPeers(account: Account) -> Signal<RecentPeers, NoError> {
|
||||
let key = PostboxViewKey.cachedItem(cachedRecentPeersEntryId())
|
||||
return account.postbox.combinedView(keys: [key])
|
||||
|> mapToSignal { views -> Signal<RecentPeers, NoError> in
|
||||
@ -41,14 +41,14 @@ public func recentPeers(account: Account) -> Signal<RecentPeers, NoError> {
|
||||
}
|
||||
}
|
||||
|
||||
public func getRecentPeers(transaction: Transaction) -> [PeerId] {
|
||||
public func _internal_getRecentPeers(transaction: Transaction) -> [PeerId] {
|
||||
guard let entry = transaction.retrieveItemCacheEntry(id: cachedRecentPeersEntryId()) as? CachedRecentPeers else {
|
||||
return []
|
||||
}
|
||||
return entry.ids
|
||||
}
|
||||
|
||||
public func managedUpdatedRecentPeers(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
func _internal_managedUpdatedRecentPeers(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
||||
let key = PostboxViewKey.cachedItem(cachedRecentPeersEntryId())
|
||||
let peersEnabled = postbox.combinedView(keys: [key])
|
||||
|> map { views -> Bool in
|
||||
@ -96,7 +96,7 @@ public func managedUpdatedRecentPeers(accountPeerId: PeerId, postbox: Postbox, n
|
||||
}
|
||||
}
|
||||
|
||||
public func removeRecentPeer(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
func _internal_removeRecentPeer(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
guard let entry = transaction.retrieveItemCacheEntry(id: cachedRecentPeersEntryId()) as? CachedRecentPeers else {
|
||||
return .complete()
|
||||
@ -121,7 +121,7 @@ public func removeRecentPeer(account: Account, peerId: PeerId) -> Signal<Void, N
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
public func updateRecentPeersEnabled(postbox: Postbox, network: Network, enabled: Bool) -> Signal<Void, NoError> {
|
||||
func _internal_updateRecentPeersEnabled(postbox: Postbox, network: Network, enabled: Bool) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
var currentValue = true
|
||||
if let entry = transaction.retrieveItemCacheEntry(id: cachedRecentPeersEntryId()) as? CachedRecentPeers {
|
||||
@ -149,7 +149,7 @@ public func updateRecentPeersEnabled(postbox: Postbox, network: Network, enabled
|
||||
} |> switchToLatest
|
||||
}
|
||||
|
||||
public func managedRecentlyUsedInlineBots(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Void, NoError> {
|
||||
func _internal_managedRecentlyUsedInlineBots(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Void, NoError> {
|
||||
let remotePeers = network.request(Api.functions.contacts.getTopPeers(flags: 1 << 2, offset: 0, limit: 16, hash: 0))
|
||||
|> retryRequest
|
||||
|> map { result -> ([Peer], [PeerId: PeerPresence], [(PeerId, Double)])? in
|
||||
@ -207,7 +207,7 @@ public func managedRecentlyUsedInlineBots(postbox: Postbox, network: Network, ac
|
||||
return updatedRemotePeers
|
||||
}
|
||||
|
||||
public func addRecentlyUsedInlineBot(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
func _internal_addRecentlyUsedInlineBot(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
var maxRating = 1.0
|
||||
for entry in transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudRecentInlineBots) {
|
||||
@ -219,7 +219,7 @@ public func addRecentlyUsedInlineBot(postbox: Postbox, peerId: PeerId) -> Signal
|
||||
}
|
||||
}
|
||||
|
||||
public func recentlyUsedInlineBots(postbox: Postbox) -> Signal<[(Peer, Double)], NoError> {
|
||||
func _internal_recentlyUsedInlineBots(postbox: Postbox) -> Signal<[(Peer, Double)], NoError> {
|
||||
return postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.CloudRecentInlineBots)])
|
||||
|> take(1)
|
||||
|> mapToSignal { view -> Signal<[(Peer, Double)], NoError> in
|
||||
@ -238,7 +238,7 @@ public func recentlyUsedInlineBots(postbox: Postbox) -> Signal<[(Peer, Double)],
|
||||
}
|
||||
}
|
||||
|
||||
public func removeRecentlyUsedInlineBot(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
func _internal_removeRecentlyUsedInlineBot(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentInlineBots, itemId: RecentPeerItemId(peerId).rawValue)
|
||||
|
@ -4,19 +4,19 @@ import SwiftSignalKit
|
||||
|
||||
import SyncCore
|
||||
|
||||
public func addRecentlySearchedPeer(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
func _internal_addRecentlySearchedPeer(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, item: OrderedItemListEntry(id: RecentPeerItemId(peerId).rawValue, contents: RecentPeerItem(rating: 0.0)), removeTailIfCountExceeds: 20)
|
||||
}
|
||||
}
|
||||
|
||||
public func removeRecentlySearchedPeer(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
func _internal_removeRecentlySearchedPeer(postbox: Postbox, peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public func clearRecentlySearchedPeers(postbox: Postbox) -> Signal<Void, NoError> {
|
||||
func _internal_clearRecentlySearchedPeers(postbox: Postbox) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
transaction.replaceOrderedItemListItems(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, items: [])
|
||||
}
|
||||
@ -34,7 +34,7 @@ public struct RecentlySearchedPeer: Equatable {
|
||||
public let subpeerSummary: RecentlySearchedPeerSubpeerSummary?
|
||||
}
|
||||
|
||||
public func recentlySearchedPeers(postbox: Postbox) -> Signal<[RecentlySearchedPeer], NoError> {
|
||||
func _internal_recentlySearchedPeers(postbox: Postbox) -> Signal<[RecentlySearchedPeer], NoError> {
|
||||
return postbox.combinedView(keys: [.orderedItemList(id: Namespaces.OrderedItemList.RecentlySearchedPeerIds)])
|
||||
|> mapToSignal { view -> Signal<[RecentlySearchedPeer], NoError> in
|
||||
var peerIds: [PeerId] = []
|
@ -4,13 +4,13 @@ import SwiftSignalKit
|
||||
|
||||
import SyncCore
|
||||
|
||||
public func removePeerChat(account: Account, peerId: PeerId, reportChatSpam: Bool, deleteGloballyIfPossible: Bool = false) -> Signal<Void, NoError> {
|
||||
func _internal_removePeerChat(account: Account, peerId: PeerId, reportChatSpam: Bool, deleteGloballyIfPossible: Bool = false) -> Signal<Void, NoError> {
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
removePeerChat(account: account, transaction: transaction, mediaBox: account.postbox.mediaBox, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible)
|
||||
_internal_removePeerChat(account: account, transaction: transaction, mediaBox: account.postbox.mediaBox, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible)
|
||||
}
|
||||
}
|
||||
|
||||
public func terminateSecretChat(transaction: Transaction, peerId: PeerId, requestRemoteHistoryRemoval: Bool) {
|
||||
func _internal_terminateSecretChat(transaction: Transaction, peerId: PeerId, requestRemoteHistoryRemoval: Bool) {
|
||||
if let state = transaction.getPeerChatState(peerId) as? SecretChatState, state.embeddedState != .terminated {
|
||||
let updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: SecretChatOutgoingOperationContents.terminate(reportSpam: false, requestRemoteHistoryRemoval: requestRemoteHistoryRemoval), state: state).withUpdatedEmbeddedState(.terminated)
|
||||
if updatedState != state {
|
||||
@ -24,7 +24,7 @@ public func terminateSecretChat(transaction: Transaction, peerId: PeerId, reques
|
||||
}
|
||||
}
|
||||
|
||||
public func removePeerChat(account: Account, transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, reportChatSpam: Bool, deleteGloballyIfPossible: Bool) {
|
||||
func _internal_removePeerChat(account: Account, transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, reportChatSpam: Bool, deleteGloballyIfPossible: Bool) {
|
||||
if let _ = transaction.getPeerChatInterfaceState(peerId) {
|
||||
transaction.updatePeerChatInterfaceState(peerId, update: { current in
|
||||
if let current = current {
|
@ -231,5 +231,101 @@ public extension TelegramEngine {
|
||||
public func peerCommands(id: PeerId) -> Signal<PeerCommands, NoError> {
|
||||
return _internal_peerCommands(account: self.account, id: id)
|
||||
}
|
||||
|
||||
public func addGroupAdmin(peerId: PeerId, adminId: PeerId) -> Signal<Void, AddGroupAdminError> {
|
||||
return _internal_addGroupAdmin(account: self.account, peerId: peerId, adminId: adminId)
|
||||
}
|
||||
|
||||
public func removeGroupAdmin(peerId: PeerId, adminId: PeerId) -> Signal<Void, RemoveGroupAdminError> {
|
||||
return _internal_removeGroupAdmin(account: self.account, peerId: peerId, adminId: adminId)
|
||||
}
|
||||
|
||||
public func fetchChannelParticipant(peerId: PeerId, participantId: PeerId) -> Signal<ChannelParticipant?, NoError> {
|
||||
return _internal_fetchChannelParticipant(account: self.account, peerId: peerId, participantId: participantId)
|
||||
}
|
||||
|
||||
public func updateChannelAdminRights(peerId: PeerId, adminId: PeerId, rights: TelegramChatAdminRights?, rank: String?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), UpdateChannelAdminRightsError> {
|
||||
return _internal_updateChannelAdminRights(account: self.account, peerId: peerId, adminId: adminId, rights: rights, rank: rank)
|
||||
}
|
||||
|
||||
public func peerSpecificStickerPack(peerId: PeerId) -> Signal<PeerSpecificStickerPackData, NoError> {
|
||||
return _internal_peerSpecificStickerPack(postbox: self.account.postbox, network: self.account.network, peerId: peerId)
|
||||
}
|
||||
|
||||
public func addRecentlySearchedPeer(peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return _internal_addRecentlySearchedPeer(postbox: self.account.postbox, peerId: peerId)
|
||||
}
|
||||
|
||||
public func removeRecentlySearchedPeer(peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return _internal_removeRecentlySearchedPeer(postbox: self.account.postbox, peerId: peerId)
|
||||
}
|
||||
|
||||
public func clearRecentlySearchedPeers() -> Signal<Void, NoError> {
|
||||
return _internal_clearRecentlySearchedPeers(postbox: self.account.postbox)
|
||||
}
|
||||
|
||||
public func recentlySearchedPeers() -> Signal<[RecentlySearchedPeer], NoError> {
|
||||
return _internal_recentlySearchedPeers(postbox: self.account.postbox)
|
||||
}
|
||||
|
||||
public func removePeerChat(peerId: PeerId, reportChatSpam: Bool, deleteGloballyIfPossible: Bool = false) -> Signal<Void, NoError> {
|
||||
return _internal_removePeerChat(account: self.account, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible)
|
||||
}
|
||||
|
||||
public func removePeerChats(peerIds: [PeerId]) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
for peerId in peerIds {
|
||||
_internal_removePeerChat(account: self.account, transaction: transaction, mediaBox: self.account.postbox.mediaBox, peerId: peerId, reportChatSpam: false, deleteGloballyIfPossible: peerId.namespace == Namespaces.Peer.SecretChat)
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func terminateSecretChat(peerId: PeerId, requestRemoteHistoryRemoval: Bool) -> Signal<Never, NoError> {
|
||||
return self.account.postbox.transaction { transaction -> Void in
|
||||
_internal_terminateSecretChat(transaction: transaction, peerId: peerId, requestRemoteHistoryRemoval: requestRemoteHistoryRemoval)
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func addGroupMember(peerId: PeerId, memberId: PeerId) -> Signal<Void, AddGroupMemberError> {
|
||||
return _internal_addGroupMember(account: self.account, peerId: peerId, memberId: memberId)
|
||||
}
|
||||
|
||||
public func addChannelMember(peerId: PeerId, memberId: PeerId) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), AddChannelMemberError> {
|
||||
return _internal_addChannelMember(account: self.account, peerId: peerId, memberId: memberId)
|
||||
}
|
||||
|
||||
public func addChannelMembers(peerId: PeerId, memberIds: [PeerId]) -> Signal<Void, AddChannelMemberError> {
|
||||
return _internal_addChannelMembers(account: self.account, peerId: peerId, memberIds: memberIds)
|
||||
}
|
||||
|
||||
public func recentPeers() -> Signal<RecentPeers, NoError> {
|
||||
return _internal_recentPeers(account: self.account)
|
||||
}
|
||||
|
||||
public func managedUpdatedRecentPeers() -> Signal<Void, NoError> {
|
||||
return _internal_managedUpdatedRecentPeers(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network)
|
||||
}
|
||||
|
||||
public func removeRecentPeer(peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return _internal_removeRecentPeer(account: self.account, peerId: peerId)
|
||||
}
|
||||
|
||||
public func updateRecentPeersEnabled(enabled: Bool) -> Signal<Void, NoError> {
|
||||
return _internal_updateRecentPeersEnabled(postbox: self.account.postbox, network: self.account.network, enabled: enabled)
|
||||
}
|
||||
|
||||
public func addRecentlyUsedInlineBot(peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return _internal_addRecentlyUsedInlineBot(postbox: self.account.postbox, peerId: peerId)
|
||||
}
|
||||
|
||||
public func recentlyUsedInlineBots() -> Signal<[(Peer, Double)], NoError> {
|
||||
return _internal_recentlyUsedInlineBots(postbox: self.account.postbox)
|
||||
}
|
||||
|
||||
public func removeRecentlyUsedInlineBot(peerId: PeerId) -> Signal<Void, NoError> {
|
||||
return _internal_removeRecentlyUsedInlineBot(account: self.account, peerId: peerId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,24 +45,35 @@ private let handleVoipNotifications = false
|
||||
|
||||
private var testIsLaunched = false
|
||||
|
||||
private func encodeText(_ string: String, _ key: Int) -> String {
|
||||
var result = ""
|
||||
for c in string.unicodeScalars {
|
||||
result.append(Character(UnicodeScalar(UInt32(Int(c.value) + key))!))
|
||||
private func isKeyboardWindow(window: NSObject) -> Bool {
|
||||
let typeName = NSStringFromClass(type(of: window))
|
||||
if #available(iOS 9.0, *) {
|
||||
if typeName.hasPrefix("UI") && typeName.hasSuffix("RemoteKeyboardWindow") {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if typeName.hasPrefix("UI") && typeName.hasSuffix("TextEffectsWindow") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return result
|
||||
return false
|
||||
}
|
||||
|
||||
private let keyboardViewClass: AnyClass? = NSClassFromString(encodeText("VJJoqvuTfuIptuWjfx", -1))!
|
||||
private let keyboardViewContainerClass: AnyClass? = NSClassFromString(encodeText("VJJoqvuTfuDpoubjofsWjfx", -1))!
|
||||
|
||||
private let keyboardWindowClass: AnyClass? = {
|
||||
if #available(iOS 9.0, *) {
|
||||
return NSClassFromString(encodeText("VJSfnpufLfzcpbseXjoepx", -1))
|
||||
} else {
|
||||
return NSClassFromString(encodeText("VJUfyuFggfdutXjoepx", -1))
|
||||
private func isKeyboardView(view: NSObject) -> Bool {
|
||||
let typeName = NSStringFromClass(type(of: view))
|
||||
if typeName.hasPrefix("UI") && typeName.hasSuffix("InputSetHostView") {
|
||||
return true
|
||||
}
|
||||
}()
|
||||
return false
|
||||
}
|
||||
|
||||
private func isKeyboardViewContainer(view: NSObject) -> Bool {
|
||||
let typeName = NSStringFromClass(type(of: view))
|
||||
if typeName.hasPrefix("UI") && typeName.hasSuffix("InputSetContainerView") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private class ApplicationStatusBarHost: StatusBarHost {
|
||||
private let application = UIApplication.shared
|
||||
@ -96,12 +107,8 @@ private class ApplicationStatusBarHost: StatusBarHost {
|
||||
}
|
||||
|
||||
var keyboardWindow: UIWindow? {
|
||||
guard let keyboardWindowClass = keyboardWindowClass else {
|
||||
return nil
|
||||
}
|
||||
|
||||
for window in UIApplication.shared.windows {
|
||||
if window.isKind(of: keyboardWindowClass) {
|
||||
if isKeyboardWindow(window: window) {
|
||||
return window
|
||||
}
|
||||
}
|
||||
@ -109,14 +116,14 @@ private class ApplicationStatusBarHost: StatusBarHost {
|
||||
}
|
||||
|
||||
var keyboardView: UIView? {
|
||||
guard let keyboardWindow = self.keyboardWindow, let keyboardViewContainerClass = keyboardViewContainerClass, let keyboardViewClass = keyboardViewClass else {
|
||||
guard let keyboardWindow = self.keyboardWindow else {
|
||||
return nil
|
||||
}
|
||||
|
||||
for view in keyboardWindow.subviews {
|
||||
if view.isKind(of: keyboardViewContainerClass) {
|
||||
if isKeyboardViewContainer(view: view) {
|
||||
for subview in view.subviews {
|
||||
if subview.isKind(of: keyboardViewClass) {
|
||||
if isKeyboardView(view: subview) {
|
||||
return subview
|
||||
}
|
||||
}
|
||||
|
@ -1902,7 +1902,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation {
|
||||
threadMessageId = replyThreadMessage.messageId
|
||||
}
|
||||
let _ = (exportMessageLink(account: context.account, peerId: message.id.peerId, messageId: message.id, isThread: threadMessageId != nil)
|
||||
let _ = (context.engine.messages.exportMessageLink(peerId: message.id.peerId, messageId: message.id, isThread: threadMessageId != nil)
|
||||
|> map { result -> String? in
|
||||
return result
|
||||
}
|
||||
@ -2281,7 +2281,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
disposables = DisposableDict()
|
||||
strongSelf.selectMessagePollOptionDisposables = disposables
|
||||
}
|
||||
let signal = requestMessageSelectPollOption(account: strongSelf.context.account, messageId: id, opaqueIdentifiers: opaqueIdentifiers)
|
||||
let signal = strongSelf.context.engine.messages.requestMessageSelectPollOption(messageId: id, opaqueIdentifiers: opaqueIdentifiers)
|
||||
disposables.set((signal
|
||||
|> deliverOnMainQueue).start(next: { resultPoll in
|
||||
guard let strongSelf = self, let resultPoll = resultPoll else {
|
||||
@ -4909,7 +4909,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
self.chatDisplayNode.navigateButtons.mentionsPressed = { [weak self] in
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded, case let .peer(peerId) = strongSelf.chatLocation {
|
||||
let signal = earliestUnseenPersonalMentionMessage(account: strongSelf.context.account, peerId: peerId)
|
||||
let signal = strongSelf.context.engine.messages.earliestUnseenPersonalMentionMessage(peerId: peerId)
|
||||
strongSelf.navigationActionDisposable.set((signal |> deliverOnMainQueue).start(next: { result in
|
||||
if let strongSelf = self {
|
||||
switch result {
|
||||
@ -6385,7 +6385,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
let controller = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
let signal = requestMessageSelectPollOption(account: strongSelf.context.account, messageId: id, opaqueIdentifiers: [])
|
||||
let signal = strongSelf.context.engine.messages.requestMessageSelectPollOption(messageId: id, opaqueIdentifiers: [])
|
||||
|> afterDisposed { [weak controller] in
|
||||
Queue.mainQueue().async {
|
||||
controller?.dismiss()
|
||||
@ -6447,7 +6447,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
let controller = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: nil))
|
||||
strongSelf.present(controller, in: .window(.root))
|
||||
let signal = requestClosePoll(postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, stateManager: strongSelf.context.account.stateManager, messageId: id)
|
||||
let signal = strongSelf.context.engine.messages.requestClosePoll(messageId: id)
|
||||
|> afterDisposed { [weak controller] in
|
||||
Queue.mainQueue().async {
|
||||
controller?.dismiss()
|
||||
@ -7056,7 +7056,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
self.chatDisplayNode.loadInputPanels(theme: self.presentationInterfaceState.theme, strings: self.presentationInterfaceState.strings, fontSize: self.presentationInterfaceState.fontSize)
|
||||
|
||||
self.recentlyUsedInlineBotsDisposable = (recentlyUsedInlineBots(postbox: self.context.account.postbox) |> deliverOnMainQueue).start(next: { [weak self] peers in
|
||||
self.recentlyUsedInlineBotsDisposable = (self.context.engine.peers.recentlyUsedInlineBots() |> deliverOnMainQueue).start(next: { [weak self] peers in
|
||||
self?.recentlyUsedInlineBotsValue = peers.filter({ $0.1 >= 0.14 }).map({ $0.0 })
|
||||
})
|
||||
|
||||
@ -11421,12 +11421,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
let _ = strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: true).start()
|
||||
if let _ = chatPeer as? TelegramSecretChat {
|
||||
let _ = (strongSelf.context.account.postbox.transaction { transaction in
|
||||
terminateSecretChat(transaction: transaction, peerId: chatPeer.id, requestRemoteHistoryRemoval: true)
|
||||
}).start()
|
||||
let _ = strongSelf.context.engine.peers.terminateSecretChat(peerId: chatPeer.id, requestRemoteHistoryRemoval: true).start()
|
||||
}
|
||||
if deleteChat {
|
||||
let _ = removePeerChat(account: strongSelf.context.account, peerId: chatPeer.id, reportChatSpam: reportSpam).start()
|
||||
let _ = strongSelf.context.engine.peers.removePeerChat(peerId: chatPeer.id, reportChatSpam: reportSpam).start()
|
||||
strongSelf.effectiveNavigationController?.filterController(strongSelf, animated: true)
|
||||
} else if reportSpam {
|
||||
let _ = strongSelf.context.engine.peers.reportPeer(peerId: peer.id, reason: .spam, message: "").start()
|
||||
@ -11562,7 +11560,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
self.commitPurposefulAction()
|
||||
self.chatDisplayNode.historyNode.disconnect()
|
||||
let _ = removePeerChat(account: self.context.account, peerId: peerId, reportChatSpam: reportChatSpam).start()
|
||||
let _ = self.context.engine.peers.removePeerChat(peerId: peerId, reportChatSpam: reportChatSpam).start()
|
||||
self.effectiveNavigationController?.popToRoot(animated: true)
|
||||
|
||||
let _ = self.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peerId, isBlocked: true).start()
|
||||
@ -11808,7 +11806,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
private func presentBanMessageOptions(accountPeerId: PeerId, author: Peer, messageIds: Set<MessageId>, options: ChatAvailableMessageActionOptions) {
|
||||
let peerId = self.chatLocation.peerId
|
||||
do {
|
||||
self.navigationActionDisposable.set((fetchChannelParticipant(account: self.context.account, peerId: peerId, participantId: author.id)
|
||||
self.navigationActionDisposable.set((self.context.engine.peers.fetchChannelParticipant(peerId: peerId, participantId: author.id)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] participant in
|
||||
if let strongSelf = self {
|
||||
let canBan = participant?.canBeBannedBy(peerId: accountPeerId) ?? true
|
||||
|
@ -2276,8 +2276,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
func sendCurrentMessage(silentPosting: Bool? = nil, scheduleTime: Int32? = nil, completion: @escaping () -> Void = {}) {
|
||||
if let textInputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode {
|
||||
if textInputPanelNode.textInputNode?.isFirstResponder() ?? false {
|
||||
Keyboard.applyAutocorrection()
|
||||
if let textInputNode = textInputPanelNode.textInputNode, textInputNode.isFirstResponder() {
|
||||
Keyboard.applyAutocorrection(textView: textInputNode.textView)
|
||||
}
|
||||
|
||||
var effectivePresentationInterfaceState = self.chatPresentationInterfaceState
|
||||
|
@ -2001,7 +2001,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
} else if self.interactiveReadActionDisposable == nil {
|
||||
if case let .peer(peerId) = self.chatLocation {
|
||||
if !self.context.sharedContext.immediateExperimentalUISettings.skipReadHistory {
|
||||
self.interactiveReadActionDisposable = installInteractiveReadMessagesAction(postbox: self.context.account.postbox, stateManager: self.context.account.stateManager, peerId: peerId)
|
||||
self.interactiveReadActionDisposable = self.context.engine.messages.installInteractiveReadMessagesAction(peerId: peerId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -797,7 +797,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation {
|
||||
threadMessageId = replyThreadMessage.messageId
|
||||
}
|
||||
let _ = (exportMessageLink(account: context.account, peerId: message.id.peerId, messageId: message.id, isThread: threadMessageId != nil)
|
||||
let _ = (context.engine.messages.exportMessageLink(peerId: message.id.peerId, messageId: message.id, isThread: threadMessageId != nil)
|
||||
|> map { result -> String? in
|
||||
return result
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee
|
||||
signal = .single({ _ in return .mentions([]) })
|
||||
}
|
||||
|
||||
let inlineBots: Signal<[(Peer, Double)], NoError> = types.contains(.contextBots) ? recentlyUsedInlineBots(postbox: context.account.postbox) : .single([])
|
||||
let inlineBots: Signal<[(Peer, Double)], NoError> = types.contains(.contextBots) ? context.engine.peers.recentlyUsedInlineBots() : .single([])
|
||||
let participants = combineLatest(inlineBots, searchPeerMembers(context: context, peerId: peer.id, chatLocation: chatLocation, query: query, scope: .mention))
|
||||
|> map { inlineBots, peers -> (ChatPresentationInputQueryResult?) -> ChatPresentationInputQueryResult? in
|
||||
let filteredInlineBots = inlineBots.sorted(by: { $0.1 > $1.1 }).filter { peer, rating in
|
||||
|
@ -772,7 +772,7 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
|
||||
return false
|
||||
})
|
||||
peerSpecificPack = combineLatest(peerSpecificStickerPack(postbox: context.account.postbox, network: context.account.network, peerId: peerId), context.account.postbox.multiplePeersView([peerId]), self.dismissedPeerSpecificStickerPack.get())
|
||||
peerSpecificPack = combineLatest(context.engine.peers.peerSpecificStickerPack(peerId: peerId), context.account.postbox.multiplePeersView([peerId]), self.dismissedPeerSpecificStickerPack.get())
|
||||
|> map { packData, peersView, dismissedPeerSpecificPack -> (PeerSpecificPackData?, CanInstallPeerSpecificPack) in
|
||||
if let peer = peersView.peers[peerId] {
|
||||
var canInstall: CanInstallPeerSpecificPack = .none
|
||||
|
@ -839,7 +839,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
if canBan {
|
||||
actions.append(ContextMenuAction(content: .text(title: self.presentationData.strings.Conversation_ContextMenuBan, accessibilityLabel: self.presentationData.strings.Conversation_ContextMenuBan), action: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.banDisposables.set((fetchChannelParticipant(account: strongSelf.context.account, peerId: strongSelf.peer.id, participantId: author.id)
|
||||
strongSelf.banDisposables.set((strongSelf.context.engine.peers.fetchChannelParticipant(peerId: strongSelf.peer.id, participantId: author.id)
|
||||
|> deliverOnMainQueue).start(next: { participant in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentController(channelBannedMemberController(context: strongSelf.context, peerId: strongSelf.peer.id, memberId: author.id, initialParticipant: participant, updated: { _ in }, upgradedToSupergroup: { _, f in f() }), .window(.root), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
|
||||
|
@ -165,7 +165,7 @@ final class MentionChatInputContextPanelNode: ChatInputContextPanelNode {
|
||||
}
|
||||
}, removeRequested: { [weak self] peerId in
|
||||
if let strongSelf = self {
|
||||
let _ = removeRecentlyUsedInlineBot(account: strongSelf.context.account, peerId: peerId).start()
|
||||
let _ = strongSelf.context.engine.peers.removeRecentlyUsedInlineBot(peerId: peerId).start()
|
||||
|
||||
strongSelf.revealedPeerId = nil
|
||||
strongSelf.currentResults = strongSelf.currentResults.filter { $0.id != peerId }
|
||||
|
@ -67,12 +67,12 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
||||
|
||||
if payload.isEmpty {
|
||||
if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
let _ = (addGroupMember(account: context.account, peerId: peerId, memberId: botPeerId)
|
||||
let _ = (context.engine.peers.addGroupMember(peerId: peerId, memberId: botPeerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
controller?.dismiss()
|
||||
})
|
||||
} else {
|
||||
let _ = (addChannelMember(account: context.account, peerId: peerId, memberId: botPeerId)
|
||||
let _ = (context.engine.peers.addChannelMember(peerId: peerId, memberId: botPeerId)
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
controller?.dismiss()
|
||||
})
|
||||
|
@ -4294,7 +4294,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
|
||||
strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: true).start())
|
||||
if deleteChat {
|
||||
let _ = removePeerChat(account: strongSelf.context.account, peerId: strongSelf.peerId, reportChatSpam: reportSpam).start()
|
||||
let _ = strongSelf.context.engine.peers.removePeerChat(peerId: strongSelf.peerId, reportChatSpam: reportSpam).start()
|
||||
(strongSelf.controller?.navigationController as? NavigationController)?.popToRoot(animated: true)
|
||||
} else if reportSpam {
|
||||
let _ = strongSelf.context.engine.peers.reportPeer(peerId: strongSelf.peerId, reason: .spam, message: "").start()
|
||||
@ -6239,8 +6239,6 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
|
||||
private var canOpenAvatarByDragging = false
|
||||
|
||||
private let velocityKey: String = encodeText("`wfsujdbmWfmpdjuz", -1)
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
if self.ignoreScrolling {
|
||||
return
|
||||
@ -6249,7 +6247,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
if !self.state.isEditing {
|
||||
if self.canAddVelocity {
|
||||
self.previousVelocityM1 = self.previousVelocity
|
||||
if let value = (scrollView.value(forKey: self.velocityKey) as? NSNumber)?.doubleValue {
|
||||
if let value = (scrollView.value(forKey: (["_", "verticalVelocity"] as [String]).joined()) as? NSNumber)?.doubleValue {
|
||||
self.previousVelocity = CGFloat(value)
|
||||
}
|
||||
}
|
||||
@ -7063,14 +7061,6 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
|
||||
}
|
||||
}
|
||||
|
||||
private func encodeText(_ string: String, _ key: Int) -> String {
|
||||
var result = ""
|
||||
for c in string.unicodeScalars {
|
||||
result.append(Character(UnicodeScalar(UInt32(Int(c.value) + key))!))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private final class ContextControllerContentSourceImpl: ContextControllerContentSource {
|
||||
let controller: ViewController
|
||||
weak var sourceNode: ASDisplayNode?
|
||||
@ -7219,14 +7209,14 @@ func presentAddMembers(context: AccountContext, parentController: ViewController
|
||||
if case let .peer(selectedPeer, _, _) = memberPeer {
|
||||
let memberId = selectedPeer.id
|
||||
if groupPeer.id.namespace == Namespaces.Peer.CloudChannel {
|
||||
return context.peerChannelMemberCategoriesContextsManager.addMember(account: context.account, peerId: groupPeer.id, memberId: memberId)
|
||||
return context.peerChannelMemberCategoriesContextsManager.addMember(engine: context.engine, peerId: groupPeer.id, memberId: memberId)
|
||||
|> map { _ -> Void in
|
||||
}
|
||||
|> `catch` { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
} else {
|
||||
return addGroupMember(account: context.account, peerId: groupPeer.id, memberId: memberId)
|
||||
return context.engine.peers.addGroupMember(peerId: groupPeer.id, memberId: memberId)
|
||||
|> deliverOnMainQueue
|
||||
|> `catch` { error -> Signal<Void, NoError> in
|
||||
switch error {
|
||||
@ -7274,7 +7264,7 @@ func presentAddMembers(context: AccountContext, parentController: ViewController
|
||||
guard let upgradedPeerId = upgradedPeerId else {
|
||||
return .single(nil)
|
||||
}
|
||||
return context.peerChannelMemberCategoriesContextsManager.addMember(account: context.account, peerId: upgradedPeerId, memberId: memberId)
|
||||
return context.peerChannelMemberCategoriesContextsManager.addMember(engine: context.engine, peerId: upgradedPeerId, memberId: memberId)
|
||||
|> `catch` { _ -> Signal<Never, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
@ -7310,11 +7300,11 @@ func presentAddMembers(context: AccountContext, parentController: ViewController
|
||||
|> castError(AddChannelMemberError.self)
|
||||
|> mapToSignal { view -> Signal<Void, AddChannelMemberError> in
|
||||
if memberIds.count == 1 {
|
||||
return context.peerChannelMemberCategoriesContextsManager.addMember(account: context.account, peerId: groupPeer.id, memberId: memberIds[0])
|
||||
return context.peerChannelMemberCategoriesContextsManager.addMember(engine: context.engine, peerId: groupPeer.id, memberId: memberIds[0])
|
||||
|> map { _ -> Void in
|
||||
}
|
||||
} else {
|
||||
return context.peerChannelMemberCategoriesContextsManager.addMembers(account: context.account, peerId: groupPeer.id, memberIds: memberIds) |> map { _ in
|
||||
return context.peerChannelMemberCategoriesContextsManager.addMembers(engine: context.engine, peerId: groupPeer.id, memberIds: memberIds) |> map { _ in
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -808,7 +808,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
|
||||
default:
|
||||
break
|
||||
}
|
||||
let _ = markMessageContentAsConsumedInteractively(postbox: self.context.account.postbox, messageId: item.message.id).start()
|
||||
let _ = self.context.engine.messages.markMessageContentAsConsumedInteractively(messageId: item.message.id).start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +323,7 @@ public func pollResultsController(context: AccountContext, messageId: MessageId,
|
||||
|
||||
let actionsDisposable = DisposableSet()
|
||||
|
||||
let resultsContext = PollResultsContext(account: context.account, messageId: messageId, poll: poll)
|
||||
let resultsContext = context.engine.messages.pollResults(messageId: messageId, poll: poll)
|
||||
|
||||
let arguments = PollResultsControllerArguments(context: context,
|
||||
collapseOption: { optionId in
|
||||
|
@ -867,7 +867,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
guard let token = token else {
|
||||
return .complete()
|
||||
}
|
||||
return unregisterNotificationToken(account: account, token: token, type: .aps(encrypt: false), otherAccountUserIds: (account.testingEnvironment ? allTestingUserIds : allProductionUserIds).filter({ $0 != account.peerId.id }))
|
||||
return TelegramEngine(account: account).accountData.unregisterNotificationToken(token: token, type: .aps(encrypt: false), otherAccountUserIds: (account.testingEnvironment ? allTestingUserIds : allProductionUserIds).filter({ $0 != account.peerId.id }))
|
||||
}
|
||||
appliedVoip = self.voipNotificationToken
|
||||
|> distinctUntilChanged(isEqual: { $0 == $1 })
|
||||
@ -875,7 +875,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
guard let token = token else {
|
||||
return .complete()
|
||||
}
|
||||
return unregisterNotificationToken(account: account, token: token, type: .voip, otherAccountUserIds: (account.testingEnvironment ? allTestingUserIds : allProductionUserIds).filter({ $0 != account.peerId.id }))
|
||||
return TelegramEngine(account: account).accountData.unregisterNotificationToken(token: token, type: .voip, otherAccountUserIds: (account.testingEnvironment ? allTestingUserIds : allProductionUserIds).filter({ $0 != account.peerId.id }))
|
||||
}
|
||||
} else {
|
||||
appliedAps = self.apsNotificationToken
|
||||
@ -890,7 +890,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
} else {
|
||||
encrypt = false
|
||||
}
|
||||
return registerNotificationToken(account: account, token: token, type: .aps(encrypt: encrypt), sandbox: sandbox, otherAccountUserIds: (account.testingEnvironment ? activeTestingUserIds : activeProductionUserIds).filter({ $0 != account.peerId.id }), excludeMutedChats: !settings.includeMuted)
|
||||
return TelegramEngine(account: account).accountData.registerNotificationToken(token: token, type: .aps(encrypt: encrypt), sandbox: sandbox, otherAccountUserIds: (account.testingEnvironment ? activeTestingUserIds : activeProductionUserIds).filter({ $0 != account.peerId.id }), excludeMutedChats: !settings.includeMuted)
|
||||
}
|
||||
appliedVoip = self.voipNotificationToken
|
||||
|> distinctUntilChanged(isEqual: { $0 == $1 })
|
||||
@ -898,7 +898,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
guard let token = token else {
|
||||
return .complete()
|
||||
}
|
||||
return registerNotificationToken(account: account, token: token, type: .voip, sandbox: sandbox, otherAccountUserIds: (account.testingEnvironment ? activeTestingUserIds : activeProductionUserIds).filter({ $0 != account.peerId.id }), excludeMutedChats: !settings.includeMuted)
|
||||
return TelegramEngine(account: account).accountData.registerNotificationToken(token: token, type: .voip, sandbox: sandbox, otherAccountUserIds: (account.testingEnvironment ? activeTestingUserIds : activeProductionUserIds).filter({ $0 != account.peerId.id }), excludeMutedChats: !settings.includeMuted)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,8 +378,8 @@ public final class PeerChannelMemberCategoriesContextsManager {
|
||||
}
|
||||
}
|
||||
|
||||
public func updateMemberAdminRights(account: Account, peerId: PeerId, memberId: PeerId, adminRights: TelegramChatAdminRights?, rank: String?) -> Signal<Void, UpdateChannelAdminRightsError> {
|
||||
return updateChannelAdminRights(account: account, peerId: peerId, adminId: memberId, rights: adminRights, rank: rank)
|
||||
public func updateMemberAdminRights(engine: TelegramEngine, peerId: PeerId, memberId: PeerId, adminRights: TelegramChatAdminRights?, rank: String?) -> Signal<Void, UpdateChannelAdminRightsError> {
|
||||
return engine.peers.updateChannelAdminRights(peerId: peerId, adminId: memberId, rights: adminRights, rank: rank)
|
||||
|> map(Optional.init)
|
||||
|> deliverOnMainQueue
|
||||
|> beforeNext { [weak self] result in
|
||||
@ -435,8 +435,8 @@ public final class PeerChannelMemberCategoriesContextsManager {
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func addMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<Never, AddChannelMemberError> {
|
||||
return addChannelMember(account: account, peerId: peerId, memberId: memberId)
|
||||
public func addMember(engine: TelegramEngine, peerId: PeerId, memberId: PeerId) -> Signal<Never, AddChannelMemberError> {
|
||||
return engine.peers.addChannelMember(peerId: peerId, memberId: memberId)
|
||||
|> deliverOnMainQueue
|
||||
|> beforeNext { [weak self] result in
|
||||
if let strongSelf = self {
|
||||
@ -453,9 +453,9 @@ public final class PeerChannelMemberCategoriesContextsManager {
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
public func addMembers(account: Account, peerId: PeerId, memberIds: [PeerId]) -> Signal<Void, AddChannelMemberError> {
|
||||
public func addMembers(engine: TelegramEngine, peerId: PeerId, memberIds: [PeerId]) -> Signal<Void, AddChannelMemberError> {
|
||||
let signals: [Signal<(ChannelParticipant?, RenderedChannelParticipant)?, AddChannelMemberError>] = memberIds.map({ memberId in
|
||||
return addChannelMember(account: account, peerId: peerId, memberId: memberId)
|
||||
return engine.peers.addChannelMember(peerId: peerId, memberId: memberId)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { error -> Signal<(ChannelParticipant?, RenderedChannelParticipant)?, AddChannelMemberError> in
|
||||
return .fail(error)
|
||||
|
@ -84,38 +84,10 @@ CGFloat springAnimationValueAtImpl(CABasicAnimation * _Nonnull animation, CGFloa
|
||||
|
||||
@interface CustomBlurEffect : UIBlurEffect
|
||||
|
||||
/*@property (nonatomic) double blurRadius;
|
||||
@property (nonatomic) double colorBurnTintAlpha;
|
||||
@property (nonatomic) double colorBurnTintLevel;
|
||||
@property (nonatomic, retain) UIColor *colorTint;
|
||||
@property (nonatomic) double colorTintAlpha;
|
||||
@property (nonatomic) bool darkenWithSourceOver;
|
||||
@property (nonatomic) double darkeningTintAlpha;
|
||||
@property (nonatomic) double darkeningTintHue;
|
||||
@property (nonatomic) double darkeningTintSaturation;
|
||||
@property (nonatomic) double grayscaleTintAlpha;
|
||||
@property (nonatomic) double grayscaleTintLevel;
|
||||
@property (nonatomic) bool lightenGrayscaleWithSourceOver;
|
||||
@property (nonatomic) double saturationDeltaFactor;
|
||||
@property (nonatomic) double scale;
|
||||
@property (nonatomic) double zoom;*/
|
||||
|
||||
+ (id)effectWithStyle:(long long)arg1;
|
||||
|
||||
@end
|
||||
|
||||
static NSString *encodeText(NSString *string, int key) {
|
||||
NSMutableString *result = [[NSMutableString alloc] init];
|
||||
|
||||
for (int i = 0; i < (int)[string length]; i++) {
|
||||
unichar c = [string characterAtIndex:i];
|
||||
c += key;
|
||||
[result appendString:[NSString stringWithCharacters:&c length:1]];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void setField(CustomBlurEffect *object, NSString *name, double value) {
|
||||
SEL selector = NSSelectorFromString(name);
|
||||
NSMethodSignature *signature = [[object class] instanceMethodSignatureForSelector:selector];
|
||||
@ -145,7 +117,7 @@ static void setNilField(CustomBlurEffect *object, NSString *name) {
|
||||
[inv invoke];
|
||||
}
|
||||
|
||||
static void setBoolField(CustomBlurEffect *object, NSString *name, BOOL value) {
|
||||
static void setBoolField(NSObject *object, NSString *name, BOOL value) {
|
||||
SEL selector = NSSelectorFromString(name);
|
||||
NSMethodSignature *signature = [[object class] instanceMethodSignatureForSelector:selector];
|
||||
if (signature == nil) {
|
||||
@ -170,18 +142,17 @@ UIBlurEffect *makeCustomZoomBlurEffectImpl(bool isLight) {
|
||||
NSString *string = [@[@"_", @"UI", @"Custom", @"BlurEffect"] componentsJoinedByString:@""];
|
||||
CustomBlurEffect *result = (CustomBlurEffect *)[NSClassFromString(string) effectWithStyle:0];
|
||||
|
||||
setField(result, encodeText(@"tfuCmvsSbejvt;", -1), 10.0);
|
||||
//setField(result, encodeText(@"tfu[ppn;", -1), 0.015);
|
||||
setNilField(result, encodeText(@"tfuDpmpsUjou;", -1));
|
||||
setField(result, encodeText(@"tfuDpmpsUjouBmqib;", -1), 0.0);
|
||||
setField(result, encodeText(@"tfuEbslfojohUjouBmqib;", -1), 0.0);
|
||||
setField(result, encodeText(@"tfuHsbztdbmfUjouBmqib;", -1), 0.0);
|
||||
setField(result, encodeText(@"tfuTbuvsbujpoEfmubGbdups;", -1), 1.0);
|
||||
setField(result, [@[@"set", @"BlurRadius", @":"] componentsJoinedByString:@""], 10.0);
|
||||
setNilField(result, [@[@"set", @"Color", @"Tint", @":"] componentsJoinedByString:@""]);
|
||||
setField(result, [@[@"set", @"Color", @"Tint", @"Alpha", @":"] componentsJoinedByString:@""], 0.0);
|
||||
setField(result, [@[@"set", @"Darkening", @"Tint", @"Alpha", @":"] componentsJoinedByString:@""], 0.0);
|
||||
setField(result, [@[@"set", @"Grayscale", @"Tint", @"Alpha", @":"] componentsJoinedByString:@""], 0.0);
|
||||
setField(result, [@[@"set", @"Saturation", @"Delta", @"Factor", @":"] componentsJoinedByString:@""], 1.0);
|
||||
|
||||
if ([UIScreen mainScreen].scale > 2.5f) {
|
||||
setField(result, encodeText(@"setScale:", 0), 0.3);
|
||||
setField(result, @"setScale:", 0.3);
|
||||
} else {
|
||||
setField(result, encodeText(@"setScale:", 0), 0.5);
|
||||
setField(result, @"setScale:", 0.5);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -191,7 +162,9 @@ UIBlurEffect *makeCustomZoomBlurEffectImpl(bool isLight) {
|
||||
}
|
||||
|
||||
void applySmoothRoundedCornersImpl(CALayer * _Nonnull layer) {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
setBoolField(layer, encodeText(@"tfuDpoujovpvtDpsofst;", -1), true);
|
||||
if (@available(iOS 13.0, *)) {
|
||||
layer.cornerCurve = kCACornerCurveContinuous;
|
||||
} else {
|
||||
setBoolField(layer, [@[@"set", @"Continuous", @"Corners", @":"] componentsJoinedByString:@""], true);
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ typedef NS_OPTIONS(NSUInteger, UIResponderDisableAutomaticKeyboardHandling) {
|
||||
|
||||
@end
|
||||
|
||||
void applyKeyboardAutocorrection();
|
||||
void applyKeyboardAutocorrection(UITextView * _Nonnull textView);
|
||||
|
||||
@interface AboveStatusBarWindow : UIWindow
|
||||
|
||||
|
@ -316,28 +316,15 @@ static NSString *TGEncodeText(NSString *string, int key)
|
||||
return result;
|
||||
}
|
||||
|
||||
void applyKeyboardAutocorrection() {
|
||||
static Class keyboardClass = NULL;
|
||||
static SEL currentInstanceSelector = NULL;
|
||||
static SEL applyVariantSelector = NULL;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
keyboardClass = NSClassFromString(TGEncodeText(@"VJLfzcpbse", -1));
|
||||
|
||||
currentInstanceSelector = NSSelectorFromString(TGEncodeText(@"bdujwfLfzcpbse", -1));
|
||||
applyVariantSelector = NSSelectorFromString(TGEncodeText(@"bddfquBvupdpssfdujpo", -1));
|
||||
});
|
||||
|
||||
if ([keyboardClass respondsToSelector:currentInstanceSelector])
|
||||
{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
id currentInstance = [keyboardClass performSelector:currentInstanceSelector];
|
||||
if ([currentInstance respondsToSelector:applyVariantSelector])
|
||||
[currentInstance performSelector:applyVariantSelector];
|
||||
#pragma clang diagnostic pop
|
||||
void applyKeyboardAutocorrection(UITextView * _Nonnull textView) {
|
||||
NSRange rangeCopy = textView.selectedRange;
|
||||
NSRange fakeRange = rangeCopy;
|
||||
if (fakeRange.location != 0) {
|
||||
fakeRange.location--;
|
||||
}
|
||||
[textView unmarkText];
|
||||
[textView setSelectedRange:fakeRange];
|
||||
[textView setSelectedRange:rangeCopy];
|
||||
}
|
||||
|
||||
@interface AboveStatusBarWindowController : UIViewController
|
||||
|
Loading…
x
Reference in New Issue
Block a user