From f95cfbdc42bee2b4ee92750ca2bda0e85d68e942 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 6 Dec 2021 16:25:41 +0400 Subject: [PATCH 1/9] Trigger build --- Random.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Random.txt b/Random.txt index fee1ef59cf..1b28f7d5d0 100644 --- a/Random.txt +++ b/Random.txt @@ -1 +1 @@ -da31f706ff299a64eb70ef55d5ac985b +689ecb2a0d0d76ad50bc8eec22be2951 From 50848269a95306b711414f01b2d99ec351751d45 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 8 Dec 2021 18:41:35 +0400 Subject: [PATCH 2/9] Cheery-pick some fixes --- submodules/Display/Source/NavigationBarBadge.swift | 4 ++-- .../LegacyComponents/TGPhotoEditorController.h | 2 +- .../LegacyComponents/Sources/TGClipboardGalleryModel.m | 2 +- .../LegacyComponents/Sources/TGPhotoEditorController.m | 6 +++--- submodules/PhotoResources/Sources/PhotoResources.swift | 2 +- .../Language Selection/LocalizationListControllerNode.swift | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/submodules/Display/Source/NavigationBarBadge.swift b/submodules/Display/Source/NavigationBarBadge.swift index 2c998d3a57..f1236dccc3 100644 --- a/submodules/Display/Source/NavigationBarBadge.swift +++ b/submodules/Display/Source/NavigationBarBadge.swift @@ -31,7 +31,7 @@ public final class NavigationBarBadgeNode: ASDisplayNode { self.backgroundNode = ASImageNode() self.backgroundNode.isLayerBacked = true self.backgroundNode.displaysAsynchronously = false - self.backgroundNode.image = generateStretchableFilledCircleImage(radius: 18.0, color: fillColor, backgroundColor: nil) + self.backgroundNode.image = generateStretchableFilledCircleImage(radius: 9.0, color: fillColor, backgroundColor: nil) super.init() @@ -43,7 +43,7 @@ public final class NavigationBarBadgeNode: ASDisplayNode { self.fillColor = fillColor self.strokeColor = strokeColor self.textColor = textColor - self.backgroundNode.image = generateStretchableFilledCircleImage(radius: 18.0, color: fillColor, backgroundColor: nil) + self.backgroundNode.image = generateStretchableFilledCircleImage(radius: 9.0, color: fillColor, backgroundColor: nil) self.textNode.attributedText = NSAttributedString(string: self.text, font: self.font, textColor: self.textColor) self.textNode.redrawIfPossible() } diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorController.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorController.h index 3235543022..62135820a5 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorController.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorController.h @@ -64,7 +64,7 @@ typedef enum { @property (nonatomic, strong) TGPhotoEntitiesContainerView *entitiesView; -- (instancetype)initWithContext:(id)context item:(id)item intent:(TGPhotoEditorControllerIntent)intent adjustments:(id)adjustments caption:(NSString *)caption screenImage:(UIImage *)screenImage availableTabs:(TGPhotoEditorTab)availableTabs selectedTab:(TGPhotoEditorTab)selectedTab; +- (instancetype)initWithContext:(id)context item:(id)item intent:(TGPhotoEditorControllerIntent)intent adjustments:(id)adjustments caption:(NSAttributedString *)caption screenImage:(UIImage *)screenImage availableTabs:(TGPhotoEditorTab)availableTabs selectedTab:(TGPhotoEditorTab)selectedTab; - (void)dismissEditor; - (void)applyEditor; diff --git a/submodules/LegacyComponents/Sources/TGClipboardGalleryModel.m b/submodules/LegacyComponents/Sources/TGClipboardGalleryModel.m index a66273db3a..ca5c567869 100644 --- a/submodules/LegacyComponents/Sources/TGClipboardGalleryModel.m +++ b/submodules/LegacyComponents/Sources/TGClipboardGalleryModel.m @@ -305,7 +305,7 @@ PGPhotoEditorValues *editorValues = (PGPhotoEditorValues *)[item.editingContext adjustmentsForItem:item.editableMediaItem]; - NSString *caption = [item.editingContext captionForItem:item.editableMediaItem]; + NSAttributedString *caption = [item.editingContext captionForItem:item.editableMediaItem]; CGRect refFrame = CGRectZero; UIView *editorReferenceView = [self referenceViewForItem:item frame:&refFrame]; diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorController.m b/submodules/LegacyComponents/Sources/TGPhotoEditorController.m index cda57e13a9..1bba112b04 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorController.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorController.m @@ -94,7 +94,7 @@ bool _scheduledVideoPlayback; id _initialAdjustments; - NSString *_caption; + NSAttributedString *_caption; bool _viewFillingWholeScreen; bool _forceStatusBarVisible; @@ -139,7 +139,7 @@ @synthesize actionHandle = _actionHandle; -- (instancetype)initWithContext:(id)context item:(id)item intent:(TGPhotoEditorControllerIntent)intent adjustments:(id)adjustments caption:(NSString *)caption screenImage:(UIImage *)screenImage availableTabs:(TGPhotoEditorTab)availableTabs selectedTab:(TGPhotoEditorTab)selectedTab +- (instancetype)initWithContext:(id)context item:(id)item intent:(TGPhotoEditorControllerIntent)intent adjustments:(id)adjustments caption:(NSAttributedString *)caption screenImage:(UIImage *)screenImage availableTabs:(TGPhotoEditorTab)availableTabs selectedTab:(TGPhotoEditorTab)selectedTab { self = [super initWithContext:context]; if (self != nil) @@ -2292,7 +2292,7 @@ _documentController.delegate = self; [_documentController setUTI:@"com.instagram.exclusivegram"]; if (_caption.length > 0) - [_documentController setAnnotation:@{@"InstagramCaption" : _caption}]; + [_documentController setAnnotation:@{@"InstagramCaption" : _caption.string}]; [_documentController presentOpenInMenuFromRect:self.view.frame inView:self.view animated:true]; }]; } diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index 35af7162d1..4691b9c1ef 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -2536,7 +2536,7 @@ public func albumArtThumbnailData(engine: TelegramEngine, thumbnail: ExternalMus private func albumArtFullSizeDatas(engine: TelegramEngine, thumbnail: ExternalMusicAlbumArtResource, fullSize: ExternalMusicAlbumArtResource, autoFetchFullSize: Bool = true) -> Signal, NoError> { return engine.resources.custom( - id: thumbnail.id.stringRepresentation, + id: fullSize.id.stringRepresentation, fetch: nil, attemptSynchronously: false ) diff --git a/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift b/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift index decd4d028a..909cb6c91b 100644 --- a/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift +++ b/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift @@ -444,7 +444,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { self.presentationData = presentationData self.presentationDataValue.set(.single(presentationData)) self.backgroundColor = presentationData.theme.list.blocksBackgroundColor - self.listNode.keepTopItemOverscrollBackground = ListViewKeepTopItemOverscrollBackground(color: presentationData.theme.chatList.backgroundColor, direction: true) + self.listNode.keepTopItemOverscrollBackground = ListViewKeepTopItemOverscrollBackground(color: presentationData.theme.list.blocksBackgroundColor, direction: true) self.searchDisplayController?.updatePresentationData(presentationData) self.leftOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor self.rightOverlayNode.backgroundColor = presentationData.theme.list.blocksBackgroundColor From 4f325b354f8a648103c2c2f7df95f0d3393a15cc Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 9 Dec 2021 18:58:28 +0400 Subject: [PATCH 3/9] Cherry-pick more fixes --- submodules/Display/Source/NavigationBar.swift | 1 + .../Sources/GalleryControllerNode.swift | 4 +- .../Sources/AvatarGalleryController.swift | 5 +- .../Sources/PeerAvatarImageGalleryItem.swift | 2 +- .../Sources/ChannelInfoController.swift | 1153 ----------------- .../Sources/ChannelVisibilityController.swift | 25 +- .../Sources/SparseItemGrid.swift | 3 + .../Sources/PresentationCall.swift | 2 +- .../State/AccountStateManagementUtils.swift | 46 +- .../Message/BotLink.imageset/BotLink@2x.png | Bin 1111 -> 0 bytes .../Message/BotLink.imageset/BotLink@3x.png | Bin 322 -> 0 bytes .../Message/BotLink.imageset/Contents.json | 20 +- .../Chat/Message/BotLink.imageset/botlink.pdf | 82 ++ .../BotLocation.imageset/BotLocation@2x.png | Bin 1198 -> 0 bytes .../BotLocation.imageset/BotLocation@3x.png | Bin 555 -> 0 bytes .../BotLocation.imageset/Contents.json | 20 +- .../BotLocation.imageset/botlocation.pdf | 77 ++ .../BotMessage.imageset/BotMessage@2x.png | Bin 1068 -> 0 bytes .../BotMessage.imageset/BotMessage@3x.png | Bin 1934 -> 0 bytes .../Message/BotMessage.imageset/Contents.json | 20 +- .../BotMessage.imageset/botmessage.pdf | 146 +++ .../Message/BotPayment.imageset/Contents.json | 2 +- .../BotPayment.imageset/botcreditcard.pdf | 87 ++ .../Chat/Message/BotPayment.imageset/card.pdf | Bin 3781 -> 0 bytes .../Message/BotPhone.imageset/BotPhone@2x.png | Bin 1226 -> 0 bytes .../Message/BotPhone.imageset/BotPhone@3x.png | Bin 1894 -> 0 bytes .../Message/BotPhone.imageset/Contents.json | 20 +- .../Message/BotPhone.imageset/botsimcard.pdf | 105 ++ .../BotProfile.imageset/BotMessage@3x.png | Bin 1934 -> 0 bytes .../Message/BotProfile.imageset/Contents.json | 13 +- .../BotProfile.imageset/botprofile (1).pdf | 87 ++ .../Message/BotShare.imageset/BotShare@2x.png | Bin 1230 -> 0 bytes .../Message/BotShare.imageset/BotShare@3x.png | Bin 1964 -> 0 bytes .../Message/BotShare.imageset/Contents.json | 20 +- .../Message/BotShare.imageset/botshare.pdf | 154 +++ .../TelegramUI/Sources/AppDelegate.swift | 2 +- .../PeerInfoScreenLabeledValueItem.swift | 2 +- .../Panes/PeerInfoVisualMediaPaneNode.swift | 190 ++- .../PeerInfo/PeerInfoPaneContainerNode.swift | 9 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 2 +- .../Sources/PeerInfoGifPaneNode.swift | 7 +- 41 files changed, 984 insertions(+), 1322 deletions(-) delete mode 100644 submodules/PeerInfoUI/Sources/ChannelInfoController.swift delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/BotLink@2x.png delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/BotLink@3x.png create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/botlink.pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/BotLocation@2x.png delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/BotLocation@3x.png create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/botlocation.pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/BotMessage@2x.png delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/BotMessage@3x.png create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/botmessage.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/botcreditcard.pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/card.pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotPhone.imageset/BotPhone@2x.png delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotPhone.imageset/BotPhone@3x.png create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotPhone.imageset/botsimcard.pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/BotMessage@3x.png create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/botprofile (1).pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotShare.imageset/BotShare@2x.png delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotShare.imageset/BotShare@3x.png create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Message/BotShare.imageset/botshare.pdf diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index ede32ea4d5..d632297de8 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -1236,6 +1236,7 @@ open class NavigationBar: ASDisplayNode { public func makeTransitionBackButtonNode(accentColor: UIColor) -> NavigationButtonNode? { if self.backButtonNode.supernode != nil { let node = NavigationButtonNode() + node.manualAlpha = self.backButtonNode.manualAlpha node.updateManualText(self.backButtonNode.manualText) node.color = accentColor if let validLayout = self.validLayout { diff --git a/submodules/GalleryUI/Sources/GalleryControllerNode.swift b/submodules/GalleryUI/Sources/GalleryControllerNode.swift index ea6054ff1a..5ddb6a240c 100644 --- a/submodules/GalleryUI/Sources/GalleryControllerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryControllerNode.swift @@ -35,6 +35,8 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture public var areControlsHidden = false public var controlsVisibilityChanged: ((Bool) -> Void)? + public var animateAlpha = true + public var updateOrientation: ((UIInterfaceOrientation) -> Void)? public var isBackgroundExtendedOverNavigationBar = true { @@ -397,7 +399,7 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture contentAnimationCompleted = true intermediateCompletion() }) - } else { + } else if self.animateAlpha { self.scrollView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in contentAnimationCompleted = true intermediateCompletion() diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index cbbbff9191..bd02f1fc61 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -332,7 +332,7 @@ public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account public class AvatarGalleryController: ViewController, StandalonePresentableController { public enum SourceCorners { case none - case round(Bool) + case round case roundRect(CGFloat) } @@ -382,7 +382,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr private let editDisposable = MetaDisposable () - public init(context: AccountContext, peer: Peer, sourceCorners: SourceCorners = .round(true), remoteEntries: Promise<[AvatarGalleryEntry]>? = nil, skipInitial: Bool = false, centralEntryIndex: Int? = nil, replaceRootController: @escaping (ViewController, Promise?) -> Void, synchronousLoad: Bool = false) { + public init(context: AccountContext, peer: Peer, sourceCorners: SourceCorners = .round, remoteEntries: Promise<[AvatarGalleryEntry]>? = nil, skipInitial: Bool = false, centralEntryIndex: Int? = nil, replaceRootController: @escaping (ViewController, Promise?) -> Void, synchronousLoad: Bool = false) { self.context = context self.peer = peer self.sourceCorners = sourceCorners @@ -579,6 +579,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr self.galleryNode.pager.updateOnReplacement = true self.galleryNode.statusBar = self.statusBar self.galleryNode.navigationBar = self.navigationBar + self.galleryNode.animateAlpha = false self.galleryNode.transitionDataForCentralItem = { [weak self] in if let strongSelf = self { diff --git a/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift b/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift index c4a392a311..22b1fc8111 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift @@ -439,7 +439,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode { self.contentNode.layer.animate(from: NSValue(caTransform3D: transform), to: NSValue(caTransform3D: self.contentNode.layer.transform), keyPath: "transform", timingFunction: kCAMediaTimingFunctionSpring, duration: 0.25) self.contentNode.clipsToBounds = true - if case .round(true) = self.sourceCorners { + if case .round = self.sourceCorners { self.contentNode.layer.animate(from: (self.contentNode.frame.width / 2.0) as NSNumber, to: 0.0 as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.default.rawValue, duration: 0.18, removeOnCompletion: false, completion: { [weak self] value in if value { self?.contentNode.clipsToBounds = false diff --git a/submodules/PeerInfoUI/Sources/ChannelInfoController.swift b/submodules/PeerInfoUI/Sources/ChannelInfoController.swift deleted file mode 100644 index 1ec3c93b88..0000000000 --- a/submodules/PeerInfoUI/Sources/ChannelInfoController.swift +++ /dev/null @@ -1,1153 +0,0 @@ -import Foundation -import UIKit -import AsyncDisplayKit -import Display -import SwiftSignalKit -import Postbox -import TelegramCore -import LegacyComponents -import TelegramPresentationData -import ItemListUI -import PresentationDataUtils -import AccountContext -import TextFormat -import OverlayStatusController -import TelegramStringFormatting -import ShareController -import AlertUI -import PresentationDataUtils -import GalleryUI -import LegacyUI -import LegacyMediaPickerUI -import ItemListAvatarAndNameInfoItem -import WebSearchUI -import PeerAvatarGalleryUI -import NotificationMuteSettingsUI -import MapResourceToAvatarSizes -import NotificationSoundSelectionUI -import Markdown - -private final class ChannelInfoControllerArguments { - let context: AccountContext - let avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext - let tapAvatarAction: () -> Void - let changeProfilePhoto: () -> Void - let updateEditingName: (ItemListAvatarAndNameInfoItemName) -> Void - let updateEditingDescriptionText: (String) -> Void - let openChannelTypeSetup: () -> Void - let openDiscussionGroupSetup: () -> Void - let changeNotificationMuteSettings: () -> Void - let openSharedMedia: () -> Void - let openStats: () -> Void - let openAdmins: () -> Void - let openMembers: () -> Void - let openBanned: () -> Void - let reportChannel: () -> Void - let leaveChannel: () -> Void - let deleteChannel: () -> Void - let displayAddressNameContextMenu: (String) -> Void - let displayContextMenu: (ChannelInfoEntryTag, String) -> Void - let aboutLinkAction: (TextLinkItemActionType, TextLinkItem) -> Void - let toggleSignatures: (Bool) -> Void - - init(context: AccountContext, avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext, tapAvatarAction: @escaping () -> Void, changeProfilePhoto: @escaping () -> Void, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updateEditingDescriptionText: @escaping (String) -> Void, openChannelTypeSetup: @escaping () -> Void, openDiscussionGroupSetup: @escaping () -> Void, changeNotificationMuteSettings: @escaping () -> Void, openSharedMedia: @escaping () -> Void, openStats: @escaping () -> Void, openAdmins: @escaping () -> Void, openMembers: @escaping () -> Void, openBanned: @escaping () -> Void, reportChannel: @escaping () -> Void, leaveChannel: @escaping () -> Void, deleteChannel: @escaping () -> Void, displayAddressNameContextMenu: @escaping (String) -> Void, displayContextMenu: @escaping (ChannelInfoEntryTag, String) -> Void, aboutLinkAction: @escaping (TextLinkItemActionType, TextLinkItem) -> Void, toggleSignatures: @escaping(Bool)->Void) { - self.context = context - self.avatarAndNameInfoContext = avatarAndNameInfoContext - self.tapAvatarAction = tapAvatarAction - self.changeProfilePhoto = changeProfilePhoto - self.updateEditingName = updateEditingName - self.updateEditingDescriptionText = updateEditingDescriptionText - self.openChannelTypeSetup = openChannelTypeSetup - self.openDiscussionGroupSetup = openDiscussionGroupSetup - self.changeNotificationMuteSettings = changeNotificationMuteSettings - self.openSharedMedia = openSharedMedia - self.openStats = openStats - self.openAdmins = openAdmins - self.openMembers = openMembers - self.openBanned = openBanned - self.reportChannel = reportChannel - self.leaveChannel = leaveChannel - self.deleteChannel = deleteChannel - self.displayAddressNameContextMenu = displayAddressNameContextMenu - self.displayContextMenu = displayContextMenu - self.aboutLinkAction = aboutLinkAction - self.toggleSignatures = toggleSignatures - } -} - -private enum ChannelInfoSection: ItemListSectionId { - case info - case discriptionAndType - case sharedMediaAndNotifications - case sign - case members - case reportOrLeave -} - -private enum ChannelInfoEntryTag { - case about - case link -} - -private enum ChannelInfoEntry: ItemListNodeEntry { - case info(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, peer: Peer?, cachedData: CachedPeerData?, state: ItemListAvatarAndNameInfoItemState, updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar?) - case about(theme: PresentationTheme, text: String, value: String) - case addressName(theme: PresentationTheme, text: String, value: String) - case channelPhotoSetup(theme: PresentationTheme, text: String) - case channelTypeSetup(theme: PresentationTheme, text: String, value: String) - case discussionGroupSetup(theme: PresentationTheme, text: String, value: String) - case discussionGroupSetupInfo(theme: PresentationTheme, text: String) - case channelDescriptionSetup(theme: PresentationTheme, placeholder: String, value: String) - case admins(theme: PresentationTheme, text: String, value: String) - case members(theme: PresentationTheme, text: String, value: String) - case banned(theme: PresentationTheme, text: String, value: String) - case notifications(theme: PresentationTheme, text: String, value: String) - case sharedMedia(theme: PresentationTheme, text: String) - case stats(theme: PresentationTheme, text: String) - case signMessages(theme: PresentationTheme, text: String, value: Bool) - case signInfo(theme: PresentationTheme, text: String) - case report(theme: PresentationTheme, text: String) - case leave(theme: PresentationTheme, text: String) - case deleteChannel(theme: PresentationTheme, text: String) - - var section: ItemListSectionId { - switch self { - case .info, .about, .addressName, .channelPhotoSetup, .channelDescriptionSetup: - return ChannelInfoSection.info.rawValue - case .channelTypeSetup, .discussionGroupSetup, .discussionGroupSetupInfo: - return ChannelInfoSection.discriptionAndType.rawValue - case .signMessages, .signInfo: - return ChannelInfoSection.sign.rawValue - case .admins, .members, .banned: - return ChannelInfoSection.members.rawValue - case .sharedMedia, .notifications, .stats: - return ChannelInfoSection.sharedMediaAndNotifications.rawValue - case .report, .leave, .deleteChannel: - return ChannelInfoSection.reportOrLeave.rawValue - } - } - - var stableId: Int32 { - switch self { - case .info: - return 0 - case .channelPhotoSetup: - return 1 - case .addressName: - return 2 - case .about: - return 3 - case .channelDescriptionSetup: - return 4 - case .channelTypeSetup: - return 5 - case .discussionGroupSetup: - return 6 - case .discussionGroupSetupInfo: - return 7 - case .signMessages: - return 8 - case .signInfo: - return 9 - case .admins: - return 10 - case .members: - return 11 - case .banned: - return 12 - case .notifications: - return 13 - case .sharedMedia: - return 14 - case .stats: - return 15 - case .report: - return 16 - case .leave: - return 17 - case .deleteChannel: - return 18 - } - } - - static func ==(lhs: ChannelInfoEntry, rhs: ChannelInfoEntry) -> Bool { - switch lhs { - case let .info(lhsTheme, lhsStrings, lhsDateTimeFormat, lhsPeer, lhsCachedData, lhsState, lhsUpdatingAvatar): - if case let .info(rhsTheme, rhsStrings, rhsDateTimeFormat, rhsPeer, rhsCachedData, rhsState, rhsUpdatingAvatar) = rhs { - if lhsTheme !== rhsTheme { - return false - } - if lhsStrings !== rhsStrings { - return false - } - if lhsDateTimeFormat != rhsDateTimeFormat { - return false - } - if let lhsPeer = lhsPeer, let rhsPeer = rhsPeer { - if !lhsPeer.isEqual(rhsPeer) { - return false - } - } else if (lhsPeer == nil) != (rhsPeer != nil) { - return false - } - if let lhsCachedData = lhsCachedData, let rhsCachedData = rhsCachedData { - if !lhsCachedData.isEqual(to: rhsCachedData) { - return false - } - } else if (lhsCachedData != nil) != (rhsCachedData != nil) { - return false - } - if lhsState != rhsState { - return false - } - if lhsUpdatingAvatar != rhsUpdatingAvatar { - return false - } - return true - } else { - return false - } - case let .about(lhsTheme, lhsText, lhsValue): - if case let .about(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - - case let .addressName(lhsTheme, lhsText, lhsValue): - if case let .addressName(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .channelPhotoSetup(lhsTheme, lhsText): - if case let .channelPhotoSetup(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .channelTypeSetup(lhsTheme, lhsText, lhsValue): - if case let .channelTypeSetup(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .discussionGroupSetup(lhsTheme, lhsText, lhsValue): - if case let .discussionGroupSetup(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .discussionGroupSetupInfo(lhsTheme, lhsText): - if case let .discussionGroupSetupInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .channelDescriptionSetup(lhsTheme, lhsPlaceholder, lhsValue): - if case let .channelDescriptionSetup(rhsTheme, rhsPlaceholder, rhsValue) = rhs, lhsTheme === rhsTheme, lhsPlaceholder == rhsPlaceholder, lhsValue == rhsValue { - return true - } else { - return false - } - case let .admins(lhsTheme, lhsText, lhsValue): - if case let .admins(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .members(lhsTheme, lhsText, lhsValue): - if case let .members(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .banned(lhsTheme, lhsText, lhsValue): - if case let .banned(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .signMessages(lhsTheme, lhsText, lhsValue): - if case let .signMessages(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - case let .signInfo(lhsTheme, lhsText): - if case let .signInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .sharedMedia(lhsTheme, lhsText): - if case let .sharedMedia(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .stats(lhsTheme, lhsText): - if case let .stats(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .report(lhsTheme, lhsText): - if case let .report(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .leave(lhsTheme, lhsText): - if case let .leave(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .deleteChannel(lhsTheme, lhsText): - if case let .deleteChannel(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { - return true - } else { - return false - } - case let .notifications(lhsTheme, lhsText, lhsValue): - if case let .notifications(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } - } - } - - static func <(lhs: ChannelInfoEntry, rhs: ChannelInfoEntry) -> Bool { - return lhs.stableId < rhs.stableId - } - - func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { - let arguments = arguments as! ChannelInfoControllerArguments - switch self { - case let .info(_, _, dateTimeFormat, peer, cachedData, state, updatingAvatar): - return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer.flatMap(EnginePeer.init), presence: nil, memberCount: (cachedData as? CachedChannelData)?.participantsSummary.memberCount.flatMap(Int.init), state: state, sectionId: self.section, style: .plain, editingNameUpdated: { editingName in - arguments.updateEditingName(editingName) - }, avatarTapped: { - arguments.tapAvatarAction() - }, context: arguments.avatarAndNameInfoContext, updatingImage: updatingAvatar) - case let .about(_, text, value): - return ItemListTextWithLabelItem(presentationData: presentationData, label: text, text: foldMultipleLineBreaks(value), enabledEntityTypes: [.allUrl, .mention, .hashtag], multiline: true, sectionId: self.section, action: nil, longTapAction: { - arguments.displayContextMenu(ChannelInfoEntryTag.about, value) - }, linkItemAction: { action, itemLink in - arguments.aboutLinkAction(action, itemLink) - }, tag: ChannelInfoEntryTag.about) - case let .addressName(_, text, value): - return ItemListTextWithLabelItem(presentationData: presentationData, label: text, text: "https://t.me/\(value)", textColor: .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: { - arguments.displayAddressNameContextMenu("https://t.me/\(value)") - }, longTapAction: { - arguments.displayContextMenu(ChannelInfoEntryTag.link, "https://t.me/\(value)") - }, tag: ChannelInfoEntryTag.link) - case let .channelPhotoSetup(_, text): - return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: { - arguments.changeProfilePhoto() - }) - case let .channelTypeSetup(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: { - arguments.openChannelTypeSetup() - }) - case let .discussionGroupSetup(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: { - arguments.openDiscussionGroupSetup() - }) - case let .discussionGroupSetupInfo(_, text): - return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) - case let .channelDescriptionSetup(_, placeholder, value): - return ItemListMultilineInputItem(presentationData: presentationData, text: value, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .plain, textUpdated: { updatedText in - arguments.updateEditingDescriptionText(updatedText) - }) - case let .admins(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: { - arguments.openAdmins() - }) - case let .members(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: { - arguments.openMembers() - }) - case let .banned(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: { - arguments.openBanned() - }) - case let .signMessages(_, text, value): - return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .plain, updated: { updated in - arguments.toggleSignatures(updated) - }) - case let .signInfo(_, text): - return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section, style: .plain) - case let .sharedMedia(_, text): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .plain, action: { - arguments.openSharedMedia() - }) - case let .stats(_, text): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .plain, action: { - arguments.openStats() - }) - case let .notifications(_, text, value): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: { - arguments.changeNotificationMuteSettings() - }) - case let .report(_, text): - return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: { - arguments.reportChannel() - }) - case let .leave(_, text): - return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .plain, action: { - arguments.leaveChannel() - }) - case let .deleteChannel(_, text): - return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .plain, action: { - arguments.deleteChannel() - }) - } - } -} - -private struct ChannelInfoState: Equatable { - let updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar? - let editingState: ChannelInfoEditingState? - let savingData: Bool - - init(updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar?, editingState: ChannelInfoEditingState?, savingData: Bool) { - self.updatingAvatar = updatingAvatar - self.editingState = editingState - self.savingData = savingData - } - - init() { - self.updatingAvatar = nil - self.editingState = nil - self.savingData = false - } - - static func ==(lhs: ChannelInfoState, rhs: ChannelInfoState) -> Bool { - if lhs.updatingAvatar != rhs.updatingAvatar { - return false - } - if lhs.editingState != rhs.editingState { - return false - } - if lhs.savingData != rhs.savingData { - return false - } - return true - } - - func withUpdatedUpdatingAvatar(_ updatingAvatar: ItemListAvatarAndNameInfoItemUpdatingAvatar?) -> ChannelInfoState { - return ChannelInfoState(updatingAvatar: updatingAvatar, editingState: self.editingState, savingData: self.savingData) - } - - func withUpdatedEditingState(_ editingState: ChannelInfoEditingState?) -> ChannelInfoState { - return ChannelInfoState(updatingAvatar: self.updatingAvatar, editingState: editingState, savingData: self.savingData) - } - - func withUpdatedSavingData(_ savingData: Bool) -> ChannelInfoState { - return ChannelInfoState(updatingAvatar: self.updatingAvatar, editingState: self.editingState, savingData: savingData) - } -} - -private struct ChannelInfoEditingState: Equatable { - let editingName: ItemListAvatarAndNameInfoItemName? - let editingDescriptionText: String - - func withUpdatedEditingDescriptionText(_ editingDescriptionText: String) -> ChannelInfoEditingState { - return ChannelInfoEditingState(editingName: self.editingName, editingDescriptionText: editingDescriptionText) - } - - static func ==(lhs: ChannelInfoEditingState, rhs: ChannelInfoEditingState) -> Bool { - if lhs.editingName != rhs.editingName { - return false - } - if lhs.editingDescriptionText != rhs.editingDescriptionText { - return false - } - return true - } -} - -private func channelInfoEntries(account: Account, presentationData: PresentationData, view: PeerView, globalNotificationSettings: GlobalNotificationSettings, state: ChannelInfoState) -> [ChannelInfoEntry] { - var entries: [ChannelInfoEntry] = [] - - if let peer = view.peers[view.peerId] as? TelegramChannel { - let canEditChannel = peer.hasPermission(.changeInfo) - let canEditMembers = peer.hasPermission(.banMembers) - - let infoState = ItemListAvatarAndNameInfoItemState(editingName: canEditChannel ? state.editingState?.editingName : nil, updatingName: nil) - entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer, cachedData: view.cachedData, state: infoState, updatingAvatar: state.updatingAvatar)) - - if let editingState = state.editingState, canEditChannel { - entries.append(.channelPhotoSetup(theme: presentationData.theme, text: presentationData.strings.Channel_UpdatePhotoItem)) - entries.append(.channelDescriptionSetup(theme: presentationData.theme, placeholder: presentationData.strings.Channel_About_Placeholder, value: editingState.editingDescriptionText)) - } - - if let _ = state.editingState, peer.flags.contains(.isCreator) { - let linkText: String - if let username = peer.username { - linkText = "@\(username)" - } else { - linkText = presentationData.strings.Channel_Setup_TypePrivate - } - entries.append(.channelTypeSetup(theme: presentationData.theme, text: presentationData.strings.Channel_TypeSetup_Title, value: linkText)) - - let discussionGroupTitle: String - if let cachedData = view.cachedData as? CachedChannelData { - if case let .known(maybeLinkedDiscussionPeerId) = cachedData.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = view.peers[linkedDiscussionPeerId] { - if let addressName = peer.addressName, !addressName.isEmpty { - discussionGroupTitle = "@\(addressName)" - } else { - discussionGroupTitle = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - } - } else { - discussionGroupTitle = presentationData.strings.Channel_DiscussionGroupAdd - } - } else { - discussionGroupTitle = "..." - } - entries.append(.discussionGroupSetup(theme: presentationData.theme, text: presentationData.strings.Channel_DiscussionGroup, value: discussionGroupTitle)) - entries.append(.discussionGroupSetupInfo(theme: presentationData.theme, text: presentationData.strings.Channel_DiscussionGroupInfo)) - - let messagesShouldHaveSignatures:Bool - switch peer.info { - case let .broadcast(info): - messagesShouldHaveSignatures = info.flags.contains(.messagesShouldHaveSignatures) - default: - messagesShouldHaveSignatures = false - } - - entries.append(.signMessages(theme: presentationData.theme, text: presentationData.strings.Channel_SignMessages, value: messagesShouldHaveSignatures)) - entries.append(.signInfo(theme: presentationData.theme, text: presentationData.strings.Channel_SignMessages_Help)) - } else { - if state.editingState == nil || !peer.flags.contains(.isCreator) { - if let username = peer.username, !username.isEmpty, state.editingState == nil { - entries.append(.addressName(theme: presentationData.theme, text: presentationData.strings.Channel_LinkItem, value: username)) - } - } - - if let _ = state.editingState, let _ = peer.adminRights { - let discussionGroupTitle: String? - if let cachedData = view.cachedData as? CachedChannelData { - if case let .known(maybeLinkedDiscussionPeerId) = cachedData.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = view.peers[linkedDiscussionPeerId] { - if let addressName = peer.addressName, !addressName.isEmpty { - discussionGroupTitle = "@\(addressName)" - } else { - discussionGroupTitle = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - } - } else if canEditChannel { - discussionGroupTitle = presentationData.strings.Channel_DiscussionGroupAdd - } else { - discussionGroupTitle = nil - } - } else if canEditChannel { - discussionGroupTitle = "..." - } else { - discussionGroupTitle = nil - } - - if let discussionGroupTitle = discussionGroupTitle { - entries.append(.discussionGroupSetup(theme: presentationData.theme, text: presentationData.strings.Channel_DiscussionGroup, value: discussionGroupTitle)) - if canEditChannel { - entries.append(.discussionGroupSetupInfo(theme: presentationData.theme, text: presentationData.strings.Channel_DiscussionGroupInfo)) - } - } - } - } - - if let _ = state.editingState { - } else { - if peer.isScam { - entries.append(.about(theme: presentationData.theme, text: presentationData.strings.Channel_AboutItem, value: presentationData.strings.ChannelInfo_ScamChannelWarning)) - } else if let cachedChannelData = view.cachedData as? CachedChannelData, let about = cachedChannelData.about, !about.isEmpty { - entries.append(.about(theme: presentationData.theme, text: presentationData.strings.Channel_AboutItem, value: about)) - } - } - - if let cachedChannelData = view.cachedData as? CachedChannelData { - if canEditMembers { - if peer.adminRights != nil || peer.flags.contains(.isCreator) { - let adminCount = cachedChannelData.participantsSummary.adminCount ?? 0 - entries.append(.admins(theme: presentationData.theme, text: presentationData.strings.GroupInfo_Administrators, value: "\(adminCount == 0 ? "" : "\(presentationStringsFormattedNumber(adminCount, presentationData.dateTimeFormat.groupingSeparator))")")) - - let memberCount = cachedChannelData.participantsSummary.memberCount ?? 0 - entries.append(.members(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Subscribers, value: "\(memberCount == 0 ? "" : "\(presentationStringsFormattedNumber(memberCount, presentationData.dateTimeFormat.groupingSeparator))")")) - - let bannedCount = cachedChannelData.participantsSummary.kickedCount ?? 0 - entries.append(.banned(theme: presentationData.theme, text: presentationData.strings.GroupRemoved_Title, value: "\(bannedCount == 0 ? "" : "\(presentationStringsFormattedNumber(bannedCount, presentationData.dateTimeFormat.groupingSeparator))")")) - } - } - } - - if state.editingState == nil, let notificationSettings = view.notificationSettings as? TelegramPeerNotificationSettings { - let notificationsText: String - if case let .muted(until) = notificationSettings.muteState, until >= Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) { - if until < Int32.max - 1 { - notificationsText = stringForRemainingMuteInterval(strings: presentationData.strings, muteInterval: until) - } else { - notificationsText = presentationData.strings.UserInfo_NotificationsDisabled - } - } else if case .default = notificationSettings.messageSound { - notificationsText = presentationData.strings.UserInfo_NotificationsEnabled - } else { - notificationsText = localizedPeerNotificationSoundString(strings: presentationData.strings, sound: notificationSettings.messageSound, default: globalNotificationSettings.effective.channels.sound) - } - entries.append(ChannelInfoEntry.notifications(theme: presentationData.theme, text: presentationData.strings.GroupInfo_Notifications, value: notificationsText)) - } - if state.editingState == nil { - entries.append(ChannelInfoEntry.sharedMedia(theme: presentationData.theme, text: presentationData.strings.GroupInfo_SharedMedia)) - if let cachedChannelData = view.cachedData as? CachedChannelData, cachedChannelData.flags.contains(.canViewStats) { - entries.append(ChannelInfoEntry.stats(theme: presentationData.theme, text: presentationData.strings.ChannelInfo_Stats)) - } - } - - if peer.flags.contains(.isCreator) { - //if state.editingState != nil { - entries.append(ChannelInfoEntry.deleteChannel(theme: presentationData.theme, text: presentationData.strings.ChannelInfo_DeleteChannel)) - //} - } else if state.editingState == nil { - entries.append(ChannelInfoEntry.report(theme: presentationData.theme, text: presentationData.strings.ReportPeer_Report)) - if peer.participationStatus == .member { - entries.append(ChannelInfoEntry.leave(theme: presentationData.theme, text: presentationData.strings.Channel_LeaveChannel)) - } - } - } - - return entries -} - -private func valuesRequiringUpdate(state: ChannelInfoState, view: PeerView) -> (title: String?, description: String?) { - if let peer = view.peers[view.peerId] as? TelegramChannel { - var titleValue: String? - var descriptionValue: String? - if let editingState = state.editingState { - if let title = editingState.editingName?.composedTitle, title != peer.title { - titleValue = title - } - if let cachedData = view.cachedData as? CachedChannelData { - if let about = cachedData.about { - if about != editingState.editingDescriptionText { - descriptionValue = editingState.editingDescriptionText - } - } else if !editingState.editingDescriptionText.isEmpty { - descriptionValue = editingState.editingDescriptionText - } - } - } - - return (titleValue, descriptionValue) - } else { - return (nil, nil) - } -} - -public func channelInfoController(context: AccountContext, peerId: PeerId) -> ViewController { - let statePromise = ValuePromise(ChannelInfoState(), ignoreRepeated: true) - let stateValue = Atomic(value: ChannelInfoState()) - let updateState: ((ChannelInfoState) -> ChannelInfoState) -> Void = { f in - statePromise.set(stateValue.modify { f($0) }) - } - - var pushControllerImpl: ((ViewController) -> Void)? - var presentControllerImpl: ((ViewController, Any?) -> Void)? - var removePeerChatImpl: ((Peer, Bool) -> Void)? - var endEditingImpl: (() -> Void)? - var errorImpl: (() -> Void)? - - let actionsDisposable = DisposableSet() - - let updatePeerNameDisposable = MetaDisposable() - actionsDisposable.add(updatePeerNameDisposable) - - let updatePeerDescriptionDisposable = MetaDisposable() - actionsDisposable.add(updatePeerDescriptionDisposable) - - let changeMuteSettingsDisposable = MetaDisposable() - actionsDisposable.add(changeMuteSettingsDisposable) - - let hiddenAvatarRepresentationDisposable = MetaDisposable() - actionsDisposable.add(hiddenAvatarRepresentationDisposable) - - let updateAvatarDisposable = MetaDisposable() - actionsDisposable.add(updateAvatarDisposable) - let currentAvatarMixin = Atomic(value: nil) - - let navigateDisposable = MetaDisposable() - actionsDisposable.add(navigateDisposable) - - let statsUrlDisposable = MetaDisposable() - actionsDisposable.add(statsUrlDisposable) - - var avatarGalleryTransitionArguments: ((AvatarGalleryEntry) -> GalleryTransitionArguments?)? - let avatarAndNameInfoContext = ItemListAvatarAndNameInfoItemContext() - var updateHiddenAvatarImpl: (() -> Void)? - - var displayContextMenuImpl: ((ChannelInfoEntryTag, String) -> Void)? - var aboutLinkActionImpl: ((TextLinkItemActionType, TextLinkItem) -> Void)? - - let arguments = ChannelInfoControllerArguments(context: context, avatarAndNameInfoContext: avatarAndNameInfoContext, tapAvatarAction: { - let _ = (context.account.postbox.loadedPeerWithId(peerId) |> take(1) |> deliverOnMainQueue).start(next: { peer in - if peer.profileImageRepresentations.isEmpty { - return - } - - let galleryController = AvatarGalleryController(context: context, peer: peer, replaceRootController: { controller, ready in - - }) - hiddenAvatarRepresentationDisposable.set((galleryController.hiddenMedia |> deliverOnMainQueue).start(next: { entry in - avatarAndNameInfoContext.hiddenAvatarRepresentation = entry?.representations.first?.representation - updateHiddenAvatarImpl?() - })) - presentControllerImpl?(galleryController, AvatarGalleryControllerPresentationArguments(transitionArguments: { entry in - return avatarGalleryTransitionArguments?(entry) - })) - }) - }, changeProfilePhoto: { - endEditingImpl?() - - let _ = (context.account.postbox.transaction { transaction -> (Peer?, SearchBotsConfiguration) in - return (transaction.getPeer(peerId), currentSearchBotsConfiguration(transaction: transaction)) - } |> deliverOnMainQueue).start(next: { peer, searchBotsConfiguration in - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - - let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme) - legacyController.statusBar.statusBarStyle = .Ignore - - let emptyController = LegacyEmptyController(context: legacyController.context)! - let navigationController = makeLegacyNavigationController(rootController: emptyController) - navigationController.setNavigationBarHidden(true, animated: false) - navigationController.navigationBar.transform = CGAffineTransform(translationX: -1000.0, y: 0.0) - - legacyController.bind(controller: navigationController) - - presentControllerImpl?(legacyController, nil) - - var hasPhotos = false - if let peer = peer, !peer.profileImageRepresentations.isEmpty { - hasPhotos = true - } - - let completedImpl: (UIImage) -> Void = { image in - if let data = image.jpegData(compressionQuality: 0.6) { - let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max)) - context.account.postbox.mediaBox.storeResourceData(resource.id, data: data) - let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource, progressiveSizes: [], immediateThumbnailData: nil) - updateState { - $0.withUpdatedUpdatingAvatar(.image(representation, true)) - } - updateAvatarDisposable.set((context.engine.peers.updatePeerPhoto(peerId: peerId, photo: context.engine.peers.uploadedPeerPhoto(resource: resource), mapResourceToAvatarSizes: { resource, representations in - return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) - }) - |> deliverOnMainQueue).start(next: { result in - switch result { - case .complete: - updateState { - $0.withUpdatedUpdatingAvatar(nil) - } - case .progress: - break - } - })) - } - } - - let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: hasPhotos, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: true)! - let _ = currentAvatarMixin.swap(mixin) - mixin.requestSearchController = { assetsController in - let controller = WebSearchController(context: context, peer: peer.flatMap(EnginePeer.init), chatLocation: nil, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: peer.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), completion: { result in - assetsController?.dismiss() - completedImpl(result) - })) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - } - mixin.didFinishWithImage = { image in - if let image = image { - completedImpl(image) - } - } - mixin.didFinishWithDelete = { - let _ = currentAvatarMixin.swap(nil) - updateState { - if let profileImage = peer?.smallProfileImage { - return $0.withUpdatedUpdatingAvatar(.image(profileImage, false)) - } else { - return $0.withUpdatedUpdatingAvatar(ItemListAvatarAndNameInfoItemUpdatingAvatar.none) - } - } - updateAvatarDisposable.set((context.engine.peers.updatePeerPhoto(peerId: peerId, photo: nil, mapResourceToAvatarSizes: { resource, representations in - return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations) - }) |> deliverOnMainQueue).start(next: { result in - switch result { - case .complete: - updateState { - $0.withUpdatedUpdatingAvatar(nil) - } - case .progress: - break - } - })) - } - mixin.didDismiss = { [weak legacyController] in - let _ = currentAvatarMixin.swap(nil) - legacyController?.dismiss() - } - let menuController = mixin.present() - if let menuController = menuController { - menuController.customRemoveFromParentViewController = { [weak legacyController] in - legacyController?.dismiss() - } - } - }) - }, updateEditingName: { editingName in - updateState { state in - if let editingState = state.editingState { - return state.withUpdatedEditingState(ChannelInfoEditingState(editingName: editingName, editingDescriptionText: editingState.editingDescriptionText)) - } else { - return state - } - } - }, updateEditingDescriptionText: { text in - updateState { state in - if let editingState = state.editingState { - return state.withUpdatedEditingState(editingState.withUpdatedEditingDescriptionText(text)) - } - return state - } - }, openChannelTypeSetup: { - presentControllerImpl?(channelVisibilityController(context: context, peerId: peerId, mode: .generic, upgradedToSupergroup: { _, f in f() }), ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet)) - }, openDiscussionGroupSetup: { - pushControllerImpl?(channelDiscussionGroupSetupController(context: context, peerId: peerId)) - }, changeNotificationMuteSettings: { - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let _ = (context.account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in - let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings) ?? TelegramPeerNotificationSettings.defaultSettings - let globalSettings: GlobalNotificationSettings = transaction.getPreferencesEntry(key: PreferencesKeys.globalNotifications)?.get(GlobalNotificationSettings.self) ?? GlobalNotificationSettings.defaultSettings - return (peerSettings, globalSettings) - } - |> deliverOnMainQueue).start(next: { peerSettings, globalSettings in - let soundSettings: NotificationSoundSettings? - if case .default = peerSettings.messageSound { - soundSettings = NotificationSoundSettings(value: nil) - } else { - soundSettings = NotificationSoundSettings(value: peerSettings.messageSound) - } - let controller = notificationMuteSettingsController(presentationData: presentationData, notificationSettings: globalSettings.effective.groupChats, soundSettings: soundSettings, openSoundSettings: { - let controller = notificationSoundSelectionController(context: context, isModal: true, currentSound: peerSettings.messageSound, defaultSound: globalSettings.effective.groupChats.sound, completion: { sound in - let _ = context.engine.peers.updatePeerNotificationSoundInteractive(peerId: peerId, sound: sound).start() - }) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }, updateSettings: { value in - changeMuteSettingsDisposable.set(context.engine.peers.updatePeerMuteSetting(peerId: peerId, muteInterval: value).start()) - }) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }) - }, openSharedMedia: { - if let controller = context.sharedContext.makePeerSharedMediaController(context: context, peerId: peerId) { - pushControllerImpl?(controller) - } - }, openStats: { - }, openAdmins: { - pushControllerImpl?(channelAdminsController(context: context, peerId: peerId)) - }, openMembers: { - pushControllerImpl?(channelMembersController(context: context, peerId: peerId)) - }, openBanned: { - pushControllerImpl?(channelBlacklistController(context: context, peerId: peerId)) - }, reportChannel: { - presentControllerImpl?(peerReportOptionsController(context: context, subject: .peer(peerId), passthrough: false, present: { c, a in - presentControllerImpl?(c, a) - }, push: { c in - pushControllerImpl?(c) - }, completion: { _, _ in }), nil) - }, leaveChannel: { - let _ = (context.account.postbox.transaction { transaction -> Peer? in - return transaction.getPeer(peerId) - } - |> deliverOnMainQueue).start(next: { peer in - guard let peer = peer else { - return - } - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let controller = ActionSheetController(presentationData: presentationData) - let dismissAction: () -> Void = { [weak controller] in - controller?.dismissAnimated() - } - controller.setItemGroups([ - ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: presentationData.strings.Channel_LeaveChannel, color: .destructive, action: { - dismissAction() - removePeerChatImpl?(peer, false) - }), - ]), - ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) - ]) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }) - }, deleteChannel: { - let _ = (context.account.postbox.transaction { transaction -> Peer? in - return transaction.getPeer(peerId) - } - |> deliverOnMainQueue).start(next: { peer in - guard let peer = peer else { - return - } - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let controller = ActionSheetController(presentationData: presentationData) - let dismissAction: () -> Void = { [weak controller] in - controller?.dismissAnimated() - } - controller.setItemGroups([ - ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: presentationData.strings.ChannelInfo_DeleteChannelConfirmation), - ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteChannel, color: .destructive, action: { - dismissAction() - removePeerChatImpl?(peer, true) - }), - ]), - ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) - ]) - presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) - }) - }, displayAddressNameContextMenu: { text in - let shareController = ShareController(context: context, subject: .url(text)) - presentControllerImpl?(shareController, nil) - }, displayContextMenu: { tag, text in - displayContextMenuImpl?(tag, text) - }, aboutLinkAction: { action, itemLink in - aboutLinkActionImpl?(action, itemLink) - }, toggleSignatures: { enabled in - actionsDisposable.add(context.engine.peers.toggleShouldChannelMessagesSignatures(peerId: peerId, enabled: enabled).start()) - }) - - var wasEditing: Bool? - - let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) - let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, statePromise.get(), context.account.viewTracker.peerView(peerId, updateData: true), context.account.postbox.combinedView(keys: [globalNotificationsKey])) - |> map { presentationData, state, view, combinedView -> (ItemListControllerState, (ItemListNodeState, Any)) in - let peer = peerViewMainPeer(view) - - var globalNotificationSettings: GlobalNotificationSettings = GlobalNotificationSettings.defaultSettings - if let preferencesView = combinedView.views[globalNotificationsKey] as? PreferencesView { - if let settings = preferencesView.values[PreferencesKeys.globalNotifications]?.get(GlobalNotificationSettings.self) { - globalNotificationSettings = settings - } - } - - var canEditChannel = false - var hasSomethingToEdit = false - if let peer = view.peers[view.peerId] as? TelegramChannel { - canEditChannel = peer.hasPermission(.changeInfo) - if canEditChannel { - hasSomethingToEdit = true - } else if let _ = peer.adminRights { - if let cachedData = view.cachedData as? CachedChannelData, case let .known(maybeLinkedDiscussionPeerId) = cachedData.linkedDiscussionPeerId, let _ = maybeLinkedDiscussionPeerId { - hasSomethingToEdit = true - } - } - } - - var leftNavigationButton: ItemListNavigationButton? - var rightNavigationButton: ItemListNavigationButton? - if let editingState = state.editingState { - leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { - updateState { - $0.withUpdatedEditingState(nil) - } - }) - - var doneEnabled = true - if let editingName = editingState.editingName, editingName.isEmpty { - doneEnabled = false - } - if peer is TelegramChannel { - if (view.cachedData as? CachedChannelData) == nil { - doneEnabled = false - } - } - - if state.savingData { - rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: doneEnabled, action: {}) - } else { - rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: doneEnabled, action: { - var updateValues: (title: String?, description: String?) = (nil, nil) - var failed = false - updateState { state in - updateValues = valuesRequiringUpdate(state: state, view: view) - if updateValues.0 != nil || updateValues.1 != nil { - if (updateValues.description?.count ?? 0) > 255 { - failed = true - return state - } - return state.withUpdatedSavingData(true) - } else { - return state.withUpdatedEditingState(nil) - } - } - - guard !failed else { - errorImpl?() - return - } - - let updateTitle: Signal - if let titleValue = updateValues.title { - updateTitle = context.engine.peers.updatePeerTitle(peerId: peerId, title: titleValue) - |> mapError { _ in return Void() } - } else { - updateTitle = .complete() - } - - let updateDescription: Signal - if let descriptionValue = updateValues.description { - updateDescription = context.engine.peers.updatePeerDescription(peerId: peerId, description: descriptionValue.isEmpty ? nil : descriptionValue) - |> mapError { _ in return Void() } - } else { - updateDescription = .complete() - } - - let signal = combineLatest(updateTitle, updateDescription) - - updatePeerNameDisposable.set((signal |> deliverOnMainQueue).start(error: { _ in - updateState { state in - return state.withUpdatedSavingData(false) - } - }, completed: { - updateState { state in - return state.withUpdatedSavingData(false).withUpdatedEditingState(nil) - } - })) - }) - } - } else if hasSomethingToEdit { - rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: { - if let channel = peer as? TelegramChannel, case .broadcast = channel.info { - var text = "" - if let cachedData = view.cachedData as? CachedChannelData, let about = cachedData.about { - text = about - } - updateState { state in - return state.withUpdatedEditingState(ChannelInfoEditingState(editingName: ItemListAvatarAndNameInfoItemName(EnginePeer(channel)), editingDescriptionText: text)) - } - } - }) - } - - let wasEditingValue = wasEditing - wasEditing = state.editingState != nil - - var crossfadeState = false - if let wasEditingValue = wasEditingValue, wasEditingValue != (state.editingState != nil) { - crossfadeState = true - } - - let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.UserInfo_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelInfoEntries(account: context.account, presentationData: presentationData, view: view, globalNotificationSettings: globalNotificationSettings, state: state), style: .plain, crossfadeState: crossfadeState, animateChanges: false) - - return (controllerState, (listState, arguments)) - } |> afterDisposed { - actionsDisposable.dispose() - } - - let controller = ItemListController(context: context, state: signal) - - pushControllerImpl = { [weak controller] value in - (controller?.navigationController as? NavigationController)?.pushViewController(value) - } - presentControllerImpl = { [weak controller] value, presentationArguments in - controller?.present(value, in: .window(.root), with: presentationArguments, blockInteraction: true) - } - removePeerChatImpl = { [weak controller] peer, deleteGloballyIfPossible in - guard let controller = controller, let navigationController = controller.navigationController as? NavigationController else { - return - } - guard let tabController = navigationController.viewControllers.first as? TabBarController else { - return - } - for childController in tabController.controllers { - if let chatListController = childController as? ChatListController { - chatListController.maybeAskForPeerChatRemoval(peer: RenderedPeer(peer: peer), joined: false, deleteGloballyIfPossible: deleteGloballyIfPossible, completion: { [weak navigationController] removed in - if removed { - navigationController?.popToRoot(animated: true) - } - }, removed: { - }) - break - } - } - } - avatarGalleryTransitionArguments = { [weak controller] entry in - if let controller = controller { - var result: ((ASDisplayNode, CGRect, () -> (UIView?, UIView?)), CGRect)? - controller.forEachItemNode { itemNode in - if let itemNode = itemNode as? ItemListAvatarAndNameInfoItemNode { - result = itemNode.avatarTransitionNode() - } - } - if let (node, _) = result { - return GalleryTransitionArguments(transitionNode: node, addToTransitionSurface: { _ in - }) - } - } - return nil - } - updateHiddenAvatarImpl = { [weak controller] in - if let controller = controller { - controller.forEachItemNode { itemNode in - if let itemNode = itemNode as? ItemListAvatarAndNameInfoItemNode { - itemNode.updateAvatarHidden() - } - } - } - } - displayContextMenuImpl = { [weak controller] tag, text in - if let strongController = controller { - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - var resultItemNode: ListViewItemNode? - let _ = strongController.frameForItemNode({ itemNode in - if let itemNode = itemNode as? ItemListTextWithLabelItemNode { - if let itemTag = itemNode.tag as? ChannelInfoEntryTag { - if itemTag == tag { - resultItemNode = itemNode - return true - } - } - } - return false - }) - if let resultItemNode = resultItemNode { - let contextMenuController = ContextMenuController(actions: [ContextMenuAction(content: .text(title: presentationData.strings.Conversation_ContextMenuCopy, accessibilityLabel: presentationData.strings.Conversation_ContextMenuCopy), action: { - UIPasteboard.general.string = text - })]) - strongController.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak resultItemNode] in - if let strongController = controller, let resultItemNode = resultItemNode { - return (resultItemNode, resultItemNode.contentBounds.insetBy(dx: 0.0, dy: -2.0), strongController.displayNode, strongController.view.bounds) - } else { - return nil - } - })) - - } - } - } - aboutLinkActionImpl = { [weak context, weak controller] action, itemLink in - if let controller = controller, let context = context { - context.sharedContext.handleTextLinkAction(context: context, peerId: peerId, navigateDisposable: navigateDisposable, controller: controller, action: action, itemLink: itemLink) - } - } - endEditingImpl = { - [weak controller] in - controller?.view.endEditing(true) - } - - let hapticFeedback = HapticFeedback() - errorImpl = { [weak controller] in - hapticFeedback.error() - controller?.forEachItemNode { itemNode in - if let itemNode = itemNode as? ItemListMultilineInputItemNode { - itemNode.animateError() - } - } - } - return controller -} diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index e5d81f45fb..9f6820aa73 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -94,7 +94,6 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { case existingLinkPeerItem(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, Peer, ItemListPeerItemEditing, Bool) case forwardingHeader(PresentationTheme, String) - case forwardingEnabled(PresentationTheme, String, Bool) case forwardingDisabled(PresentationTheme, String, Bool) case forwardingInfo(PresentationTheme, String) @@ -108,7 +107,7 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { return ChannelVisibilitySection.linkActions.rawValue case .existingLinksInfo, .existingLinkPeerItem: return ChannelVisibilitySection.link.rawValue - case .forwardingHeader, .forwardingEnabled, .forwardingDisabled, .forwardingInfo: + case .forwardingHeader, .forwardingDisabled, .forwardingInfo: return ChannelVisibilitySection.forwarding.rawValue } } @@ -149,12 +148,10 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { return 1001 case .forwardingHeader: return 1002 - case .forwardingEnabled: - return 1003 case .forwardingDisabled: - return 1004 + return 1003 case .forwardingInfo: - return 1005 + return 1004 } } @@ -286,12 +283,6 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { } else { return false } - case let .forwardingEnabled(lhsTheme, lhsText, lhsValue): - if case let .forwardingEnabled(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { - return true - } else { - return false - } case let .forwardingDisabled(lhsTheme, lhsText, lhsValue): if case let .forwardingDisabled(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { return true @@ -403,13 +394,9 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { }) case let .forwardingHeader(_, title): return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section) - case let .forwardingEnabled(_, text, selected): - return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: { - arguments.toggleForwarding(true) - }) case let .forwardingDisabled(_, text, selected): - return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: { - arguments.toggleForwarding(false) + return ItemListSwitchItem(presentationData: presentationData, title: text, value: selected, sectionId: self.section, style: .blocks, updated: { value in + arguments.toggleForwarding(!value) }) case let .forwardingInfo(_, text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) @@ -710,7 +697,6 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa } entries.append(.forwardingHeader(presentationData.theme, isGroup ? presentationData.strings.Group_Setup_ForwardingGroupTitle.uppercased() : presentationData.strings.Group_Setup_ForwardingChannelTitle.uppercased())) - entries.append(.forwardingEnabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingEnabled, forwardingEnabled)) entries.append(.forwardingDisabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingDisabled, !forwardingEnabled)) entries.append(.forwardingInfo(presentationData.theme, forwardingEnabled ? (isGroup ? presentationData.strings.Group_Setup_ForwardingGroupInfo : presentationData.strings.Group_Setup_ForwardingChannelInfo) : (isGroup ? presentationData.strings.Group_Setup_ForwardingGroupInfoDisabled : presentationData.strings.Group_Setup_ForwardingChannelInfoDisabled))) @@ -842,7 +828,6 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa } entries.append(.forwardingHeader(presentationData.theme, presentationData.strings.Group_Setup_ForwardingGroupTitle.uppercased())) - entries.append(.forwardingEnabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingEnabled, forwardingEnabled)) entries.append(.forwardingDisabled(presentationData.theme, presentationData.strings.Group_Setup_ForwardingDisabled, !forwardingEnabled)) entries.append(.forwardingInfo(presentationData.theme, forwardingEnabled ? presentationData.strings.Group_Setup_ForwardingGroupInfo : presentationData.strings.Group_Setup_ForwardingGroupInfoDisabled)) } diff --git a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift index 058002ee5b..a5ec2b5ddc 100644 --- a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift +++ b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift @@ -15,6 +15,9 @@ private let nullAction = NullActionClass() public protocol SparseItemGridLayer: CALayer { func update(size: CGSize) func needsShimmer() -> Bool + + func getContents() -> Any? + func setContents(_ contents: Any?) } public protocol SparseItemGridView: UIView { diff --git a/submodules/TelegramCallsUI/Sources/PresentationCall.swift b/submodules/TelegramCallsUI/Sources/PresentationCall.swift index 56cfa62c67..74f2c80a7c 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCall.swift @@ -613,7 +613,7 @@ public final class PresentationCallImpl: PresentationCall { self.callKitIntegration?.reportIncomingCall( uuid: self.internalId, stableId: stableId, - handle: "\(self.peerId.id)", + handle: "\(self.peerId.id._internalGetInt64Value())", isVideo: sessionState.type == .video, displayTitle: self.peer?.debugDisplayTitle ?? "Unknown", completion: { [weak self] error in diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 4eaf554904..f9db8bda93 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -2576,35 +2576,39 @@ func replayFinalState( } if !message.flags.contains(.Incoming), message.forwardInfo == nil { - inner: for media in message.media { - if let file = media as? TelegramMediaFile { - for attribute in file.attributes { - switch attribute { - case let .Sticker(_, packReference, _): - if let index = message.index, packReference != nil { - if let (currentIndex, _) = recentlyUsedStickers[file.fileId] { - if currentIndex < index { + if [Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel].contains(message.id.peerId.namespace), let peer = transaction.getPeer(message.id.peerId), peer.isCopyProtectionEnabled { + + } else { + inner: for media in message.media { + if let file = media as? TelegramMediaFile { + for attribute in file.attributes { + switch attribute { + case let .Sticker(_, packReference, _): + if let index = message.index, packReference != nil { + if let (currentIndex, _) = recentlyUsedStickers[file.fileId] { + if currentIndex < index { + recentlyUsedStickers[file.fileId] = (index, file) + } + } else { recentlyUsedStickers[file.fileId] = (index, file) } - } else { - recentlyUsedStickers[file.fileId] = (index, file) } - } - case .Animated: - if let index = message.index { - if let (currentIndex, _) = recentlyUsedGifs[file.fileId] { - if currentIndex < index { + case .Animated: + if let index = message.index { + if let (currentIndex, _) = recentlyUsedGifs[file.fileId] { + if currentIndex < index { + recentlyUsedGifs[file.fileId] = (index, file) + } + } else { recentlyUsedGifs[file.fileId] = (index, file) } - } else { - recentlyUsedGifs[file.fileId] = (index, file) } - } - default: - break + default: + break + } } + break inner } - break inner } } } diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/BotLink@2x.png b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/BotLink@2x.png deleted file mode 100644 index 269f80a0c67caa6438616c01cc50dc2d66dd1f36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1111 zcmaJ=O=#0l9M85ghcc-311E@Yal%BKyi~iTakaKdw-uH#YH>YGU7EbEq05KKo6UyE zHW3s=@TBe_9(NMG`EeMEiprRS34-jRc<>;2@t`Q^OI@c2YvASm-{b%L{l9+i($HXE z>&BfMDT->%^h;T?hy2yjO#a80t_+i{4X5+?m{r6T#X(e3vkC}g3}p;uk)lnWet~)@ zs;N`Y<#Apf5LC-x6yJyO44a@Sswd&uidse(6wsJ%#_7)w7igesae6o^L)jKlN$;O> z(6On(oH|ujV;Y?}0(v}w5Euw6z%#~8SMcI=l~*9Pf6daM>VnI0`gc-!c?gJ>gFuw& z3ai{92)bho*98wnxdR{qxo#FlS=beZoB(+t!hyAqCea+NC}gGHwOHg7r%M>y0?Sq^ z6{d2Kv79lMi^XCrjIfbNn0SQUNfRqx*mU>Q7$oGXj&5V!GJ(&i6s!pxr%9&2OEBzp zTGL%?6KNRhDK^V7&@ZXxD9itMHH>v{7iZC*eE&)8<|b{#W|3=6I4T)jagQI$7DNXr z*m81~HD2rDP|3oUTe55*ihkF4&?zgbZu*z|swi0&GNy|aQ$-mmP7@wR*EKUQBhTYFNoqCk$lb8dm#*P1VKvf-r0nSwfC}25G&HWq@ko zf?hutzAoPyR;!;&tS*)%$*}%-{~CAgifG6;*TqW?>+(k?(Y!;%{p049W%4kdW~5}! zdt1;(N1q4YZwJL9*uAI(LO~pKdtPbhj~BY2Xrbt9@DH zB=uzB)}xuriC}pe26y+Z{J4-ie{be1oNM1S!{69?{?7dmFt;?9_YMBF9cPx#{7FPXR7efA)=dh+Fc1ac=vojj(3OX9>5cS$Ucf_0L8!a#Tud7K_80_DzvLNOguiL?UP`F>0v2CB Uh)8)C4FCWD07*qoM6N<$f>n8lvH$=8 diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/Contents.json index 09bcb1c4da..4f334b1a65 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/Contents.json @@ -1,22 +1,12 @@ { "images" : [ { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "BotLink@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "BotLink@3x.png", - "scale" : "3x" + "filename" : "botlink.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/botlink.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/botlink.pdf new file mode 100644 index 0000000000..d5a2a7dc55 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLink.imageset/botlink.pdf @@ -0,0 +1,82 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 1.000000 1.258984 cm +0.000000 0.000000 0.000000 scn +7.000000 7.571017 m +1.000000 7.571017 l +0.541604 7.571017 0.170000 7.199414 0.170000 6.741017 c +0.170000 6.282621 0.541604 5.911017 1.000000 5.911017 c +4.996202 5.911017 l +0.413101 1.327916 l +0.088966 1.003781 0.088966 0.478254 0.413101 0.154119 c +0.737236 -0.170016 1.262764 -0.170016 1.586899 0.154119 c +6.170000 4.737220 l +6.170000 0.741017 l +6.170000 0.282621 6.541604 -0.088983 7.000000 -0.088983 c +7.458396 -0.088983 7.830000 0.282621 7.830000 0.741017 c +7.830000 6.741017 l +7.830000 6.953433 7.748966 7.165848 7.586899 7.327916 c +7.507321 7.407494 7.415605 7.467534 7.317710 7.508038 c +7.219848 7.548619 7.112540 7.571017 7.000000 7.571017 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 777 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 10.000000 10.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000000867 00000 n +0000000889 00000 n +0000001062 00000 n +0000001136 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1195 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/BotLocation@2x.png b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/BotLocation@2x.png deleted file mode 100644 index db0521f331aa145b50f34c9b1add64e99cec4847..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1198 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9W!3HGH#-DKnQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07??FOLn2Bde0{8v^K*7iAWdWaj57fJ{tG z$}cUkRRX#c;)UD-xUqS~&|m@vn0`fKfxe-h0mw@*g}%P{mFDKcRTq~8r6Sym)!^cg z%7Rq=pw#00(xPNw#HA^NtSYc_E=o--$uA1Y&(DE{Vn9ZINq%ugeu09sGbq$76f}Gj zlQZ)`f|_7mzP?tTdBr7(dC94sF1AWQbM!JZQ>@IKOx#=z&D;!(3``9TU4da`WZ~rK z=wxVVXyNQ+?gZ28lAm0fo0?Yw)0+a4XwQ{9y2`Cyw3GXs{8rd z7k?f8wq0q5%0a#*y#CYI?|t%~>x870ctAkCm7*QLtNV7f1DY*Qj% zU?d`!p7PAu=(9!k`y&SrDMfC0tgUHa=5cI~xJB*;)!gWhss|W&f9yN$v5z$pRDyWA L`njxgN@xNACZL%= diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/BotLocation@3x.png b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/BotLocation@3x.png deleted file mode 100644 index 951df08900cf7a4756c80e469dc3b7262773141f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 555 zcmV+`0@VG9P)Px$1XL7=pN0Z@BqX>1EmSlhM8z$jp}-~QK%9UAAqrX= zpaVpgG$>6vgo1>C`79?&HoGrg+Zk!H*?se7Vtehlk&MTjB)j6CxGt`Ui(*Io5MRY> z@mBm4OJQDJ7vh)rSAgiy(-(z(srltaLR<}f^p8bDigWQ-bWLLB^y6a!L5%4*Z7`5S zuX;poIDR9il#5#S8o2@P9N(c$!!B|~?)+JrBay8?n~%&{ceU;u{|wwm*7p8UJr!p} zA6QRCbZ$s*jz2lcfgwViibar0)HC;uwu>VqY8=tIbImQ}Ux{yLr@c#xCfPM@J&)LXCeY{b8h zV}0wHPGZErk7<2-7bg*fFaAR~)NB%A_>O@0k0-ItK>YCaVpFT%VjY3_;Ai4Q)jGoP z84GUod$CF&{rD8Zf>du}nLzsJkHVVN{0GGZqNlGEHq=!#5FPqTSXK9nXdNMSbhUt& t%q!6s$okMrXf25{*%5EVPCha(jDN^S*42`c#IFDV002ovPDHLkV1g|c{^0-s diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/Contents.json index 817688347d..673d13bfcf 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/Contents.json @@ -1,22 +1,12 @@ { "images" : [ { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "BotLocation@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "BotLocation@3x.png", - "scale" : "3x" + "filename" : "botlocation.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/botlocation.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/botlocation.pdf new file mode 100644 index 0000000000..b2b739cadd --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotLocation.imageset/botlocation.pdf @@ -0,0 +1,77 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 1.000000 0.000000 cm +0.000000 0.000000 0.000000 scn +4.000000 0.000000 m +4.209139 0.000000 8.000000 2.790861 8.000000 6.000000 c +8.000000 8.209139 6.209139 10.000000 4.000000 10.000000 c +1.790861 10.000000 0.000000 8.209139 0.000000 6.000000 c +0.000000 2.790861 3.790861 0.000000 4.000000 0.000000 c +h +4.000000 4.500000 m +4.828427 4.500000 5.500000 5.171573 5.500000 6.000000 c +5.500000 6.828427 4.828427 7.500000 4.000000 7.500000 c +3.171573 7.500000 2.500000 6.828427 2.500000 6.000000 c +2.500000 5.171573 3.171573 4.500000 4.000000 4.500000 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 621 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 10.000000 10.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000000711 00000 n +0000000733 00000 n +0000000906 00000 n +0000000980 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1039 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/BotMessage@2x.png b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/BotMessage@2x.png deleted file mode 100644 index 11ab949e1168de68c1f94f21f2d21711abb7855a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1068 zcmaJ=O-K|`93K@eZLJK9^5SbYLc!hnaChAu96xr)kA-HDbs;e-XJ?-7s55VzdA6&U zOb9HxcIjeSfrkjJLxw~q5^2YvLm1Sdvt9yE*_+kX4s8Q(-g|%kzu*7s_wM#3daA4H zswj%8j`vDQvY&I;@e1<)o)ve=b{=;P;C?iWvx*I=P7S3Yh#SfXOhQGQn%ID?6jj!s zrv~tVd|6PD;a6NAf6lN7nxb0UbC#lxK@8GxL^nlxd*vMsbWNnM1Z7sXVlbokPTR15 zI+0SR$JB^Mx3_`ToInT+h!v1C#!W}aiFBS-)E$3%KRsR6kU#E=a^&>!-t zTz~~F5kD7V13|6{@GRHDutA0m`B+Y1!vfENgO4WBY;9ObO5F#s$W5d(7+V6vWV2a+ zw%L#D5r&IIA`HtjJnthOK4;3rO3r6G-U5RJ9o5z?tRoY+j7l0!Vv#19?w4R#hqR`1 z&?eF_CZ|{o=V#rL3XZb;e^$)a{qJi!%uBDmf z*&xStkzVoPXlG}Xi*Vssv?W@=N=ThFpot4u?Fbtvigg8HSR}FpZT%+Hx@}~DeBpv# zJQuDg-vL%Do(o?T%aCLkcf5a%yI>+3a*v1NC6`0_Lz8IUCgQ%h_30jY7!Tu8XDatK zJv215>{;K_XPCXcz4_ZUn~y80!PSrJ9V$EeezE+?+53YXPs?v)w9wX82K<(OF4Sq) z1J9Q$N@~HEo|kWr&DHKKn`chfuX%6P%x%v!t(GT#Ok5Kyf0ZQOoCtdudTH&##;k`Q z4J`QPF1^}ZZ_J(=-KhsBpFK)^XngINn=f7R-g(eg=54#WSVEP0sNHYqb8vfQ!F|8+ Lu7va=IyCzS(05nV diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/BotMessage@3x.png b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/BotMessage@3x.png deleted file mode 100644 index a896a845d698471ddd957a7377a3bc6fcdc51315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1934 zcmbVMeQXnD9KLR}+q!Nt9I^Y*+zu8upuLZ_>v~y%(Qd9_M^mbde@L%)*Y2{mSMF}K zT{Kb{9~B|RL4r7O3CWN|aOFb@GZ_SChLP}(iY^+2Akh#u{0JdItnYPQ1%qESx!!y4 z`@GNZ_x!$+uFeV8mzhmBd}LS zRY;Xqe{1t+WWDK>rcP0 zSHc^MQabk>sWN3Py3o0O#JuS%$K1OWBL`A&0KTtE9Ze1HDK>8TsVH@Hpnu`P-50h^ zmKJ=Ye`{Q6N$yiCKGArJ>W|E?hbJv#L&qBo)boTGxrYzh7n+wk;-%%#plHNK$ z>|eQx_TD==m`Ir4OtjuBaIKa$97tCzyc-+TYP+T%WHRe^B@(X^h3Bu90KWCVW-?dD zmtTr%wdFSy&@%<>^iy-5{SL&rB+{`?grL%=7}P?LvWoL`NnOqtNtzGoDTep4 z`dBCe&=AzJEEb{Y9#(>VY=8?}k?GMf1m+kkvex9poDmz_&2{t%?3%t#58c;8TNq^7 zQn)2X0)h}LQE)6242xvUie!07u$H$`1kOUF9xKu+8-%-@F4)EkENs#@>1f=D!Dfpd zZ^Dcwd59Xp{}IAvP?D0E_3bk#1h%#cuv@sPo5<7yzMlI`cLj z>q{t=F$6==3?BXDzptR_O*1eTI`!Nc>x*+jW!U50Ho zIWf&}gOj4Uu&kr;p=AfB7X$}?&Y-NH zPABOIixL&4S%=+x(5+52{$ z?v)E*_CE7J@2?g((129%iFxF5Qup4r#AO~lQg`{Y?39JY$XP;$| z+&1^b5tyNkcC&!=9|~dyCh~qMN(pRh07UD*RUHZxpmNX7h(Z6VGkf+>f6v0f(2$q; zX$3y=^NtOJAt!)o7IOqngGqSCVQ=+xoxgphu6zYPxBr?2Qf-Z&qte|i2Y;cecW-XL zj+Lo21@kTtWt9oVjsmz^0=E*dT&PgoWm zR+8ze%3%dL(zy5K(#aDgm1_$p)A-)C>dE63)$h+aN!g5(9}UePJ#MNQx;F2Ja!mu# TSff3R%LCof)@eVs!n^qoS(}Q- diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/Contents.json index 29b49981e8..a5a134f3f9 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/Contents.json @@ -1,22 +1,12 @@ { "images" : [ { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "BotMessage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "BotMessage@3x.png", - "scale" : "3x" + "filename" : "botmessage.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/botmessage.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/botmessage.pdf new file mode 100644 index 0000000000..0b87021746 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotMessage.imageset/botmessage.pdf @@ -0,0 +1,146 @@ +%PDF-1.7 + +1 0 obj + << /Type /XObject + /Length 2 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 10.000000 10.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.000000 -0.067810 cm +0.000000 0.000000 0.000000 scn +5.000000 10.067810 m +7.761424 10.067810 10.000000 8.032742 10.000000 5.522356 c +10.000000 3.011971 7.761424 0.976902 5.000000 0.976902 c +4.576631 0.976902 4.165551 1.024737 3.772944 1.114788 c +3.608864 1.152423 3.395684 0.726701 2.633157 0.299067 c +2.099883 0.000000 1.361029 0.025946 1.235985 0.078396 c +1.033161 0.163471 1.437598 0.390721 1.761992 0.887999 c +2.086386 1.385276 1.952343 1.977291 1.806809 2.083839 c +1.600757 2.234695 1.410087 2.396711 1.235985 2.569399 c +0.448528 3.350461 0.000000 4.349841 0.000000 5.522356 c +0.000000 8.032742 2.238576 10.067810 5.000000 10.067810 c +h +f +n +Q + +endstream +endobj + +2 0 obj + 715 +endobj + +3 0 obj + << /Type /XObject + /Length 4 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 10.000000 10.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm +0.000000 0.000000 0.000000 scn +0.000000 10.000000 m +10.000000 10.000000 l +10.000000 0.000000 l +0.000000 0.000000 l +0.000000 10.000000 l +h +f +n +Q + +endstream +endobj + +4 0 obj + 232 +endobj + +5 0 obj + << /XObject << /X1 1 0 R >> + /ExtGState << /E1 << /SMask << /Type /Mask + /G 3 0 R + /S /Alpha + >> + /Type /ExtGState + >> >> + >> +endobj + +6 0 obj + << /Length 7 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +/E1 gs +/X1 Do +Q + +endstream +endobj + +7 0 obj + 46 +endobj + +8 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 10.000000 10.000000 ] + /Resources 5 0 R + /Contents 6 0 R + /Parent 9 0 R + >> +endobj + +9 0 obj + << /Kids [ 8 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +10 0 obj + << /Pages 9 0 R + /Type /Catalog + >> +endobj + +xref +0 11 +0000000000 65535 f +0000000010 00000 n +0000000973 00000 n +0000000995 00000 n +0000001475 00000 n +0000001497 00000 n +0000001795 00000 n +0000001897 00000 n +0000001918 00000 n +0000002091 00000 n +0000002165 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 10 0 R + /Size 11 +>> +startxref +2225 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/Contents.json index 8d74185285..a9391ca38f 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "card.pdf", + "filename" : "botcreditcard.pdf", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/botcreditcard.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/botcreditcard.pdf new file mode 100644 index 0000000000..9636a435f8 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/botcreditcard.pdf @@ -0,0 +1,87 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.000000 1.000000 cm +0.000000 0.000000 0.000000 scn +0.163490 7.180986 m +0.000000 6.860118 0.000000 6.440079 0.000000 5.600000 c +0.000000 4.000000 l +10.000000 4.000000 l +10.000000 5.600000 l +10.000000 6.440079 10.000000 6.860118 9.836510 7.180986 c +9.692699 7.463229 9.463229 7.692700 9.180985 7.836510 c +8.860118 8.000000 8.440079 8.000000 7.600000 8.000000 c +2.400000 8.000000 l +1.559921 8.000000 1.139882 8.000000 0.819014 7.836510 c +0.536771 7.692700 0.307300 7.463229 0.163490 7.180986 c +h +9.999153 2.000000 m +0.000847 2.000000 l +0.004894 1.417536 0.028288 1.084363 0.163490 0.819014 c +0.307300 0.536771 0.536771 0.307300 0.819014 0.163490 c +1.139882 0.000000 1.559921 0.000000 2.400000 0.000000 c +7.600000 0.000000 l +8.440079 0.000000 8.860118 0.000000 9.180985 0.163490 c +9.463229 0.307300 9.692699 0.536771 9.836510 0.819014 c +9.971712 1.084363 9.995106 1.417536 9.999153 2.000000 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 966 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 10.000000 10.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001056 00000 n +0000001078 00000 n +0000001251 00000 n +0000001325 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1384 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/card.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPayment.imageset/card.pdf deleted file mode 100644 index 3e219e9e059200a44a55c319c490c29d4e7c5571..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3781 zcmai%c|4ST_s1<$7?R2osjg&3$}*d&DZ613Wot3kX2xJ_Q)BGOk|m7n4GKw-T~UdK z?8IZpmI{d>At|>t`Hk+o=kEF4&+qlSUf1iozOVB==Um@&KGz@b12M%KD8p5dU`Qk9 zD`z_I+nuh)W-tR zkh6nEH({&9%wM%eOcUuUdZ`FwY*?3};B=15^@JU(?gmg~yKzAC(2-1a@CvcyM!mwu z<@=*D0@P27hkq`NMJ65$sP`W9hke?tP=iPwP*bu=<=KhO5wAvD&xc^z|0}$l&DDfkCIaz=0|r)9<06db%ZVFe=+p z{PT33&CXrzjZ1vH#dt+6d0&h=I)ZS^SiauxERD3Z2Pd1$7eA{6J5;|_sx^gr_HP6w z$Q{*_-^v5l??bC!g-UVwk}b-cq!AmSmkTM1hzK}BGF#|wk=$5gsoP@S#F6T@R3>yh zTL#}L{T!9as5Tu=hm7VhK-o5_koQhGR|LqcvxezBoTWoOJb4d8=D{%WG23@l?2P)#i*Analw^U$^j74B!5?FT%|(vGIe5f^f{tjGHHK zmaEE zlFk_kbF1Uq881M;14f0Y!1$CdZj%j0Ug94Hc*25Dit*p%S2@W?(FQ%z(R|GV)`7p~ z^}gnEiKjQjzYBCG6n$x{4d}v)ZI^^af^pj5h&m$}?{El3F!YO<#9f_&c*%R)({%gA z_E-t}>FJmr6X$Qzi;5RZ)L!X=KG=QuT0yp+sm8)Vx=fXz?X}fA0$l)V>pE{>*p5`b z9>TWQJWqlL%TCA&;_BPqV|^uV3rM|qJ9?^8Qd9J4z0~NQFFZ=&_Vr1E+O2~8-3FF| zd*-pa@s{$uI}W%e$lc@1*H4cZy|?FC?8$`7NmES=`#-W4gvb!GHRljVmLtO{e`&t89(HjV zX)b-Ak;JHG#C=0eJY$cs-=a$?b{o$XQ&tXp9KMnwm*SYhn-W)Ge2&^D-j`9}USQG- zbAh@LTn1g%`cw*I*?DZAOm>DnYGeF+XlX?#kONtdaSk(N0p!$dW! zNvC_Hx21E^Cs8dG&Q`*YK~@~A$;WoEl(f$sXB{EsF_`S)lG!}vZq0i`g&M`A2j!Md zIcLf{ciASYSRd7SYV*{>N7uwi)l${I)NC$W(=4kv>s~Fc);j3ri!R{J#TcDibq}(m zvug>Ngq%^*!GeUs?!!4&IVYNrk)B+Rp4S|+hL%NT7$zFVww<;$??0jazt1o#xf>Da!Ar%X;#TXd0J^dUJ<{=(!JtS z*=oa^#&lO(QeaDj%NVJ=Gk0j>adE!#h8*}do9ri@uluXdash@JFqbZ;DbtueS>xpri`(e?yfOiOZJ(xePq*zP*B z^g_ag(x-__#5tF_Jk8^pQJS%uyK1~^3IkP_3G008-m6332EI(L4y>7gj)97VK7#Lo z3_#}vG=&jDJGXd&8tQoKszdjyzOt9M>6PTu{jTR7t}dh|Vk@!gxm!gERRo>!t32m> z)z=54Ow`BfHCCUDYkk#D3W1`p@iWWpNY=n_g;_ezlMzG zC&wq}C?fN_^Z!K&t5~k+(S;DA%Z}J0H56E?4X7NLUe!xV-{*6??rL`@7$5S)J65OO z_+k9VNrwC_$Thrhxyz$rCmcEJrCG<0iG}g>agX-BZQt6~uBthz`FJ_ic>jp_UZ?ii zRkS#~zr^P4vok)nbycH()J(^@1MVjWzqA{)$CCGqctj8Pn%yxgtGVc0J~z><`%Kqt zl%?EhE$Y_fCgC#jsh{{l)uhKJUE+ zeclaCReiHeBjW7_yGq{M7IQkj-u?Qt`oc`jd4l!ji`yx24sjKT2ai~%N?mY$d7tim z3XzFRpJ06ocsiT$rseHG?TC9&4{t1glYr(vaoOiVtxKk^#X9aygmt| zg6xB^vnS^h*tl@q{g(PTuf7w#14kbmO-9$pCN@7DyWB!ufB%PGz^=k6Q)JGwWzew$ znE4Ma%lqdtMbroVq5})26xOpApLAJ8TV?mZ>yLVJ4^0U$4j7pV?#bBOxmQ{1*2a|u z#$sA}`Aa7wc0#Ab?OT{EpQ~SWo5Sa0qNE~^U!ZGNRgAyNC@Cu$ZVzFW+RZdpb?))bN8E%xeFl`=rCi@g5(_Ty9?UaAA$sV#s>-8fl>= zVQR)?*(4<^R?Fv#(D$#tPgnkcJjo8gCaanQw!iRq zlb3(t@83A>38Gagho{NFBrAJLaab_Bx!3>fzB3qY%>A=Lm!;Fk@7=C*0`0z7`%kZ?7w z0RL%&!4TYz|1TR7^%z) zcRHd{>AEP)ETKh`xyd_8U}fi7AzZCsS=07?>+ELn2Bde0{8v^K*7iAWdWaj57fJ{tG z$}cUkRRX#c;)UD-UthSvdBxCx0tT6WMPh-zp`L+$ZZ61QVAaJXL8%C5U{zflQdy9y zACy|0Us{w5jE^*Bm}X$u;kO8+5a=2!|DsG_q$K9J@Y~ zl1!3Q(~@*k%nZ|XO-zkbbS=%25_OZ3jFZh0EzDDs%`IT&VAJpH;%wn)VQFk&WMFD& z=n4!yBMT=-M<+u|Lknjob0?Ty&%EN2#JuEGnBAE`yP1T{es1@X5_YEfocYKmJ?ey##Iq^&ZsxPrJ4 zfap&lHw5*8j?xDu7o_9^69T455EGsmfE;*sO3ef2p(0>r(bCh424=Juo-U3d6}Og5 z-pF;xK%gyHuq(vX>W9MJx5gcd^PfFi(yZ{VPw5BCzQ*ommesK?kL!h0kExiQJ!o!n zr*`KTp<@!S8#OH$^AZ__(mE{#L~k^1^E{x<)v&rw=?o=zySCUPXH)sjZ x<>NDz6T153i`cdVrZ&0nP4^CTWzA>eVR*N4+Swy(cZz~a7f)9|mvv4FO#pkKoRt6o diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPhone.imageset/BotPhone@3x.png b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotPhone.imageset/BotPhone@3x.png deleted file mode 100644 index b2eb8fa8f15ebd74f9fa0c239107dd91c108c4a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1894 zcmbVMeQXnD9KNn}A6@wWD=G6KW|5{7_)O87$!N=zUsiwVJDvJe!pzSngX41Uq%dhfmO z^FF`d^ZV)vwmduDILnA2$asIVF9hEf_*9e@!~Ziy9eWW(_dM_Q27SCD#hEl3v?EB( zWi}EC`D<$~Fia$J;nKW0MmZVk?%ooLyn119!p4)PsL9xK@tk3sPPbrDwTYZnM%u`i zPZVP_E!LasKc}mm$Na}u4PJ@vzx~zgANt<0+}0o3`Q>*UdcUN5`Hu3}maJ>qk9_m# zjcNnBrlc1SjZ>%gdP>f=Y(DH-_qBi09rNKmy=WVHuekSMZ{M4xjtxJT^d8)?v1;G8 zvzxA#7kz8pea_(S*=5vyVhWd3ADC8+UUi@9KT>1&yyrV@wk$bd+?T%CMH`!nHw~Fg z{p98ket)ub!qTPzd+ET?J(KD9y=*pn>WPY>WAA2|%HT6sS~kAD$)MkWy7Xsy_8NK` zdmMp;I0#$4kStwoPDY4x)B=um;T_+8PL=UQq_9(^`kKl!HWF zZYxzsI-FE3Y9lEZK{^St4ksy^tfy@hn*U+Yn#{%Mkgq9k3x0X9c2$*Vf=DKl)}-Ak z%54PYcDo7EM%ZjPMBqwVP?;1iD3xOjKA^BNFR8pJpc*3+6+2ZA20a~>kdO+rf|3st z3>cAOB!aS%nxq_%V+%N`Q;z41b1VVkAOQqbfmo`5mD)vBRNBSAp)MRhWB`UX5GdGq zq%Vm?!GxkVu7NW00eK`^38y7Mgn%M;$}DJH1Kq6D)JU{f28=4oVNr~aB`P@PGV1ke ziK$0x0u0LwnvOXS+yXvE1s+U8;FJxwxx!REO}c1@a~|oSNpch#5IH`UeiW3l(Kh=- zP*^t{qcZ;r=2$u=$_WOl<`YaCAS9s;LkqE_y<%LHp<(Eq{lR@doISD_6I`g;rxhlaK+ zOe^?Nn0G*cLr#X%Z1JR0Gn|Cm{l129^Z8qEeO5MzPV(VrpT0HtQtj#OC;9Rz-o>Sv zAAjBLtBs&3b5B>*uDm^0x3cK? zxOiE&dRq?+=^XtKay^d~|5WZ|kQSMrLnaFzwokFBa8Kw6~m}ER5X6 n&BL?(H-A~Rc6xG`zW<00*|GM> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 1.000000 0.000000 cm +0.000000 0.000000 0.000000 scn +5.600000 0.000000 m +2.400000 0.000000 l +1.559921 0.000000 1.139882 0.000000 0.819014 0.163490 c +0.536771 0.307301 0.307300 0.536771 0.163490 0.819015 c +0.000000 1.139882 0.000000 1.559921 0.000000 2.400000 c +0.000000 7.600000 l +0.000000 8.440079 0.000000 8.860118 0.163490 9.180985 c +0.307300 9.463229 0.536771 9.692699 0.819014 9.836510 c +1.139882 10.000000 1.559921 10.000000 2.400000 10.000000 c +3.174517 10.000000 l +3.663698 10.000000 3.908288 10.000000 4.138463 9.944740 c +4.342536 9.895746 4.537625 9.814938 4.716570 9.705280 c +4.918403 9.581596 5.091355 9.408646 5.437258 9.062742 c +7.062742 7.437258 l +7.408645 7.091355 7.581597 6.918403 7.705280 6.716570 c +7.814938 6.537625 7.895746 6.342536 7.944740 6.138464 c +8.000000 5.908288 8.000000 5.663698 8.000000 5.174517 c +8.000000 2.400000 l +8.000000 1.559921 8.000000 1.139882 7.836510 0.819015 c +7.692700 0.536771 7.463229 0.307301 7.180986 0.163490 c +6.860118 0.000000 6.440079 0.000000 5.600000 0.000000 c +h +1.608990 4.953990 m +1.499996 4.740078 1.499996 4.460052 1.499996 3.900000 c +1.499996 3.099999 l +1.499996 2.539947 1.499996 2.259921 1.608990 2.046009 c +1.704863 1.857847 1.857844 1.704866 2.046006 1.608993 c +2.259917 1.500000 2.539944 1.500000 3.099996 1.500000 c +4.899996 1.500000 l +5.460049 1.500000 5.740075 1.500000 5.953987 1.608993 c +6.142149 1.704866 6.295129 1.857847 6.391003 2.046009 c +6.499996 2.259921 6.499996 2.539947 6.499996 3.099999 c +6.499996 3.900000 l +6.499996 4.460052 6.499996 4.740078 6.391003 4.953990 c +6.295129 5.142152 6.142149 5.295133 5.953987 5.391006 c +5.740075 5.500000 5.460049 5.500000 4.899996 5.500000 c +3.099996 5.500000 l +2.539944 5.500000 2.259917 5.500000 2.046006 5.391006 c +1.857844 5.295133 1.704863 5.142152 1.608990 4.953990 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1868 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 10.000000 10.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001958 00000 n +0000001981 00000 n +0000002154 00000 n +0000002228 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2287 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/BotMessage@3x.png b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/BotMessage@3x.png deleted file mode 100644 index a896a845d698471ddd957a7377a3bc6fcdc51315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1934 zcmbVMeQXnD9KLR}+q!Nt9I^Y*+zu8upuLZ_>v~y%(Qd9_M^mbde@L%)*Y2{mSMF}K zT{Kb{9~B|RL4r7O3CWN|aOFb@GZ_SChLP}(iY^+2Akh#u{0JdItnYPQ1%qESx!!y4 z`@GNZ_x!$+uFeV8mzhmBd}LS zRY;Xqe{1t+WWDK>rcP0 zSHc^MQabk>sWN3Py3o0O#JuS%$K1OWBL`A&0KTtE9Ze1HDK>8TsVH@Hpnu`P-50h^ zmKJ=Ye`{Q6N$yiCKGArJ>W|E?hbJv#L&qBo)boTGxrYzh7n+wk;-%%#plHNK$ z>|eQx_TD==m`Ir4OtjuBaIKa$97tCzyc-+TYP+T%WHRe^B@(X^h3Bu90KWCVW-?dD zmtTr%wdFSy&@%<>^iy-5{SL&rB+{`?grL%=7}P?LvWoL`NnOqtNtzGoDTep4 z`dBCe&=AzJEEb{Y9#(>VY=8?}k?GMf1m+kkvex9poDmz_&2{t%?3%t#58c;8TNq^7 zQn)2X0)h}LQE)6242xvUie!07u$H$`1kOUF9xKu+8-%-@F4)EkENs#@>1f=D!Dfpd zZ^Dcwd59Xp{}IAvP?D0E_3bk#1h%#cuv@sPo5<7yzMlI`cLj z>q{t=F$6==3?BXDzptR_O*1eTI`!Nc>x*+jW!U50Ho zIWf&}gOj4Uu&kr;p=AfB7X$}?&Y-NH zPABOIixL&4S%=+x(5+52{$ z?v)E*_CE7J@2?g((129%iFxF5Qup4r#AO~lQg`{Y?39JY$XP;$| z+&1^b5tyNkcC&!=9|~dyCh~qMN(pRh07UD*RUHZxpmNX7h(Z6VGkf+>f6v0f(2$q; zX$3y=^NtOJAt!)o7IOqngGqSCVQ=+xoxgphu6zYPxBr?2Qf-Z&qte|i2Y;cecW-XL zj+Lo21@kTtWt9oVjsmz^0=E*dT&PgoWm zR+8ze%3%dL(zy5K(#aDgm1_$p)A-)C>dE63)$h+aN!g5(9}UePJ#MNQx;F2Ja!mu# TSff3R%LCof)@eVs!n^qoS(}Q- diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/Contents.json index cd6ffbe035..82ca30b22b 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/Contents.json @@ -1,17 +1,8 @@ { "images" : [ { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "BotMessage@3x.png", - "idiom" : "universal", - "scale" : "3x" + "filename" : "botprofile (1).pdf", + "idiom" : "universal" } ], "info" : { diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/botprofile (1).pdf b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/botprofile (1).pdf new file mode 100644 index 0000000000..20a92a0f27 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotProfile.imageset/botprofile (1).pdf @@ -0,0 +1,87 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm +0.000000 0.000000 0.000000 scn +10.000000 5.000000 m +10.000000 2.238576 7.761424 0.000000 5.000000 0.000000 c +2.238576 0.000000 0.000000 2.238576 0.000000 5.000000 c +0.000000 7.761424 2.238576 10.000000 5.000000 10.000000 c +7.761424 10.000000 10.000000 7.761424 10.000000 5.000000 c +h +7.693560 2.871713 m +7.055479 3.417237 6.157626 3.689999 4.999999 3.689999 c +3.843426 3.689999 2.946154 3.417733 2.307761 2.873090 c +2.298760 2.865411 2.289426 2.857153 2.279822 2.848403 c +2.019047 2.610812 2.037121 2.187978 2.309236 1.963464 c +3.040504 1.360117 3.977927 0.997691 4.999999 0.997691 c +6.022901 0.997691 6.961017 1.360706 7.692426 1.965061 c +7.963211 2.188808 7.981247 2.609582 7.721957 2.846554 c +7.712191 2.855480 7.702703 2.863896 7.693560 2.871713 c +h +6.538462 6.153847 m +6.538462 7.003516 5.849669 7.692309 5.000000 7.692309 c +4.150331 7.692309 3.461539 7.003516 3.461539 6.153847 c +3.461539 5.304178 4.150331 4.615386 5.000000 4.615386 c +5.849669 4.615386 6.538462 5.304178 6.538462 6.153847 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1095 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 10.000000 10.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001185 00000 n +0000001208 00000 n +0000001381 00000 n +0000001455 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1514 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Message/BotShare.imageset/BotShare@2x.png b/submodules/TelegramUI/Images.xcassets/Chat/Message/BotShare.imageset/BotShare@2x.png deleted file mode 100644 index 4feb51ca846f3fc33dd2063539b20c74617e36e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1230 zcmbVMU1%It6dtopHceAp($H>d(d$GoE6&bOcXoG%Y&W|zNxN+~4cpZQEHrm!?j}Pr zKb^VhPC^i?K{lx9TOswKg;WZH*n$t$f{8*)AF6$nJ_!0G)Y7J)L=PSu#V4H_u0sz|1;f!0 zC|PhERS-00&fY=&6cq`~>L?y9AD4Be$*ZCX%~uY0D8O~(eI zMW{K`I7gF6H&U?Na(TQU=$f(dueb`&a-Xyg-~Ns0oeR7an-kc~@fjwUxr!!+cBf|Nm7F~ih^G-OgxPcvC9 z1sOd}gd{>u68WZ`?eL1KWD8j-!wHUm13sY#FlIyLt95p-zM?B ziA_HfD=Qv?*zu~4Gu7;ZkqHMo{)FQKMG32(1$||xn|64Z2n)55w~9RT95RMH#{%n2 z%jPyw{5J+R@W%gTkR?H}VY~dReVRw4C&T5|Fp$mGI3b(NkVl4PALq4_LHoU=7OKI0 zZ4A5^L{{Ghd*P+7_UC?mIxyGLxN$b2(JRYONA4eJWGMdmD{XXSANcvbyH}RtS3kIQ z`$6UO^3KL7YW3LF3)kRH*b&)3aC6VcFaH)~4qdnvSgE$xUdbjSZ}U7TNjr}gOVv4u}x9hi$Y@-3@T@Mcuol@h`C zE$7!>xqfNq;z!ZTKO8>Mwz78m{m$#3bpP>7>Eg=Tcbz>`^RF!)1=pf`ydE#%MH)BS vkfojf*S+*$^>K1B8tX;)o<7LX0Gn5fhDoB4P&AcU@P(AW<%P_ujqt zz3=z`cQJeI^SQFwG6;flt<@F>n4botAUg}Z8}F3mLy%|%Z8qC2G#B&{5!kMSprTo% z%jK{ti$(~-(Y%?z0ifz>In{#8sj^7C^66e?D^WwZ?#IqufYcKiP$@mSY^yL*9&`> z){w4SA9qHhhBu-Ww=(R@_@<8j{P{P-oeD+W)jNsAs_oI}dad}xr5wPw=0+lMX}Eke zq)<%1EP|fQpsudm(ar%s=LD-)fqB{tVThoPP6Y%>X3)+$zRvanPBMNq;bGjAI_wVu zGz2Xw3kM0Zk>X)DRZj;@$koB42uyoS$cuU#W(%6B2D-Y1rIxqUI?0ws(&$0T7Q>6e zI3Vy-JOPLOz5s`ZO-Pa#2Ww#)Mc^caZ!{qlfErtZ0N2`VX&DdH z#qUpx;P}e5z>Jhb9*E|gksyUSD2{1nNvd)!P;;JOO%OM;6u~pBlVN;QfwE7j44chD zU`pX48$r?m!Hxy@+@dT5Pni$_q0(qoT7y$liem;`SGo`@#xZOXYGXXKH}W8;Mt2_$ zB#npQiH9RSB<^KcKLPBe{X{*51_Sj7oc1DaW_%0_L;}5Z_wHLk*I^ki?E?pYcb}w& zHXCjYa6AzpDXYbV0H>&F+Joz~MgvukYY5<*o>kR_^8cQK(NOTc8*6K zkj+Bqr|x_H=lx|Y4N8yjJu;6_kV4Mj)iej98A+AQa;hn{^3iZIO>lw~(%*!TLfk12 zlG>&p*#ncbp#}<&J|q<;VI1S-Lj+4z)B|t*w|ql^1*lN1lg6O`v@>~jPi0TRLAwx^ z={^NM(w&Y9fcD0MKK5Ir0Q{7o@2!>!XLT;=>Ynp6G$v~mL5ZGEiEd@@;CMoM`qzY* z`ZEz7xLx*zvOdFI1OJjaR*um?OJ-6qOsL7PK0Y0&0KxN1ntC_jF zdSHBR`R(?tdmg7E#d(RI=m%J5Y}D}*e7DA2)4y5?4LwHt7JSp)RhGA>?`-Lsrf2$w z#l*hM-1Y5-iOWBn4NLkiNZVF)=froe-aTYhcATj=^u%airBT_@E7Iup7i3&-==ki% zb2lo^3>NhKu6kwmtAF%#bcy?6)7~T4_Tx7KU!l^m%of8*(R;ls> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 10.000000 10.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.000000 1.697514 cm +0.000000 0.000000 0.000000 scn +5.152984 5.102487 m +5.152984 5.968138 l +5.152984 6.547595 5.152984 6.837323 5.269190 6.976490 c +5.370099 7.097338 5.522033 7.163600 5.679254 7.155328 c +5.860308 7.145803 6.072636 6.948676 6.497293 6.554421 c +9.368506 3.888769 l +9.587912 3.685072 9.697614 3.583224 9.738306 3.464036 c +9.774062 3.359304 9.774062 3.245669 9.738306 3.140937 c +9.697614 3.021749 9.587911 2.919900 9.368506 2.716203 c +6.497293 0.050551 l +6.072636 -0.343703 5.860308 -0.540830 5.679254 -0.550356 c +5.522033 -0.558627 5.370099 -0.492365 5.269190 -0.371517 c +5.152984 -0.232350 5.152984 0.057378 5.152984 0.636834 c +5.152984 1.502486 l +2.908304 1.502486 1.549372 0.625330 0.795713 -0.129066 c +0.460085 -0.465023 0.292271 -0.633001 0.213952 -0.636048 c +0.141017 -0.638886 0.084704 -0.611050 0.042670 -0.551378 c +-0.002468 -0.487302 0.025289 -0.280314 0.080801 0.133661 c +0.328706 1.982362 1.315535 5.102487 5.152984 5.102487 c +h +f* +n +Q + +endstream +endobj + +2 0 obj + 1029 +endobj + +3 0 obj + << /Type /XObject + /Length 4 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 10.000000 10.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm +0.000000 0.000000 0.000000 scn +0.000000 10.000000 m +10.000000 10.000000 l +10.000000 0.000000 l +0.000000 0.000000 l +0.000000 10.000000 l +h +f +n +Q + +endstream +endobj + +4 0 obj + 232 +endobj + +5 0 obj + << /XObject << /X1 1 0 R >> + /ExtGState << /E1 << /SMask << /Type /Mask + /G 3 0 R + /S /Alpha + >> + /Type /ExtGState + >> >> + >> +endobj + +6 0 obj + << /Length 7 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +/E1 gs +/X1 Do +Q + +endstream +endobj + +7 0 obj + 46 +endobj + +8 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 10.000000 10.000000 ] + /Resources 5 0 R + /Contents 6 0 R + /Parent 9 0 R + >> +endobj + +9 0 obj + << /Kids [ 8 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +10 0 obj + << /Pages 9 0 R + /Type /Catalog + >> +endobj + +xref +0 11 +0000000000 65535 f +0000000010 00000 n +0000001287 00000 n +0000001310 00000 n +0000001790 00000 n +0000001812 00000 n +0000002110 00000 n +0000002212 00000 n +0000002233 00000 n +0000002406 00000 n +0000002480 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 10 0 R + /Size 11 +>> +startxref +2540 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index 1d31cf59a8..58ce4b2f49 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -1544,7 +1544,7 @@ private func extractAccountManagerState(records: AccountRecordsView Any? { + return self.contents + } + + func setContents(_ contents: Any?) { + if let image = contents as? UIImage { + self.contents = image.cgImage + } + } override func action(forKey event: String) -> CAAction? { return nullAction @@ -865,6 +892,117 @@ private final class ItemLayer: CALayer, SparseItemGridLayer { } } +private final class CaptureProtectedItemLayer: AVSampleBufferDisplayLayer, ItemLayer { + var item: VisualMediaItem? + var durationLayer: DurationLayer? + var minFactor: CGFloat = 1.0 + var selectionLayer: GridMessageSelectionLayer? + var disposable: Disposable? + + var hasContents: Bool = false + + override init() { + super.init() + + self.contentsGravity = .resize + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + self.disposable?.dispose() + } + + override func action(forKey event: String) -> CAAction? { + return nullAction + } + + private var layerContents: Any? + func getContents() -> Any? { + return self.layerContents + } + + func setContents(_ contents: Any?) { + self.layerContents = contents + + if let image = contents as? UIImage { + self.layerContents = image.cgImage + if let cmSampleBuffer = image.cmSampleBuffer { + self.enqueue(cmSampleBuffer) + } + } + } + + func bind(item: VisualMediaItem) { + self.item = item + } + + func updateDuration(duration: Int32?, isMin: Bool, minFactor: CGFloat) { + self.minFactor = minFactor + + if let duration = duration { + if let durationLayer = self.durationLayer { + durationLayer.update(duration: duration, isMin: isMin) + } else { + let durationLayer = DurationLayer() + durationLayer.update(duration: duration, isMin: isMin) + self.addSublayer(durationLayer) + durationLayer.frame = CGRect(origin: CGPoint(x: self.bounds.width - 3.0, y: self.bounds.height - 3.0), size: CGSize()) + durationLayer.transform = CATransform3DMakeScale(minFactor, minFactor, 1.0) + self.durationLayer = durationLayer + } + } else if let durationLayer = self.durationLayer { + self.durationLayer = nil + durationLayer.removeFromSuperlayer() + } + } + + func updateSelection(theme: CheckNodeTheme, isSelected: Bool?, animated: Bool) { + if let isSelected = isSelected { + if let selectionLayer = self.selectionLayer { + selectionLayer.updateSelected(isSelected, animated: animated) + } else { + let selectionLayer = GridMessageSelectionLayer(theme: theme) + selectionLayer.updateSelected(isSelected, animated: false) + self.selectionLayer = selectionLayer + self.addSublayer(selectionLayer) + if !self.bounds.isEmpty { + selectionLayer.frame = CGRect(origin: CGPoint(), size: self.bounds.size) + selectionLayer.updateLayout(size: self.bounds.size) + if animated { + selectionLayer.animateIn() + } + } + } + } else if let selectionLayer = self.selectionLayer { + self.selectionLayer = nil + if animated { + selectionLayer.animateOut { [weak selectionLayer] in + selectionLayer?.removeFromSuperlayer() + } + } else { + selectionLayer.removeFromSuperlayer() + } + } + } + + func unbind() { + self.item = nil + } + + func needsShimmer() -> Bool { + return !self.hasContents + } + + func update(size: CGSize) { + /*if let durationLayer = self.durationLayer { + durationLayer.frame = CGRect(origin: CGPoint(x: size.width - 3.0, y: size.height - 3.0), size: CGSize()) + }*/ + } +} + private final class ItemView: UIView, SparseItemGridView { var item: VisualMediaItem? var disposable: Disposable? @@ -1037,6 +1175,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme let context: AccountContext let chatLocation: ChatLocation let directMediaImageCache: DirectMediaImageCache + let captureProtected: Bool var strings: PresentationStrings let useListItems: Bool let listItemInteraction: ListMessageItemInteraction @@ -1055,13 +1194,14 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme private var shimmerImages: [CGFloat: UIImage] = [:] - init(context: AccountContext, chatLocation: ChatLocation, useListItems: Bool, listItemInteraction: ListMessageItemInteraction, chatControllerInteraction: ChatControllerInteraction, directMediaImageCache: DirectMediaImageCache) { + init(context: AccountContext, chatLocation: ChatLocation, useListItems: Bool, listItemInteraction: ListMessageItemInteraction, chatControllerInteraction: ChatControllerInteraction, directMediaImageCache: DirectMediaImageCache, captureProtected: Bool) { self.context = context self.chatLocation = chatLocation self.useListItems = useListItems self.listItemInteraction = listItemInteraction self.chatControllerInteraction = chatControllerInteraction self.directMediaImageCache = directMediaImageCache + self.captureProtected = captureProtected let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } self.strings = presentationData.strings @@ -1174,7 +1314,11 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme if self.useListItems { return nil } - return ItemLayer() + if self.captureProtected { + return CaptureProtectedItemLayer() + } else { + return GenericItemLayer() + } } func createView() -> SparseItemGridView? { @@ -1256,7 +1400,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme if let selectedMedia = selectedMedia { if let result = directMediaImageCache.getImage(message: message, media: selectedMedia, width: imageWidthSpec, possibleWidths: SparseItemGridBindingImpl.widthSpecs.1, synchronous: synchronous == .full) { if let image = result.image { - layer.contents = image.cgImage + layer.setContents(image) switch synchronous { case .none: layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, completion: { [weak self, weak layer, weak displayItem] _ in @@ -1286,9 +1430,9 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme synchronousValue = deltaTime < 0.1 } - if layer.contents != nil && !synchronousValue { - let copyLayer = ItemLayer() - copyLayer.contents = layer.contents + if let contents = layer.getContents(), !synchronousValue { + let copyLayer = GenericItemLayer() + copyLayer.contents = contents copyLayer.contentsRect = layer.contentsRect copyLayer.frame = layer.bounds if let durationLayer = layer.durationLayer { @@ -1300,14 +1444,13 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme copyLayer?.removeFromSuperlayer() }) - layer.contents = image?.cgImage - + layer.setContents(image) layer.hasContents = true if let displayItem = displayItem { self?.updateShimmerLayersImpl?(displayItem) } } else { - layer.contents = image?.cgImage + layer.setContents(image) if !synchronousValue { layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, completion: { [weak layer] _ in @@ -1510,7 +1653,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro private var presentationData: PresentationData private var presentationDataDisposable: Disposable? - init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId, contentType: ContentType) { + init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId, contentType: ContentType, captureProtected: Bool) { self.context = context self.peerId = peerId self.chatControllerInteraction = chatControllerInteraction @@ -1562,7 +1705,8 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro useListItems: useListItems, listItemInteraction: listItemInteraction, chatControllerInteraction: chatControllerInteraction, - directMediaImageCache: self.directMediaImageCache + directMediaImageCache: self.directMediaImageCache, + captureProtected: captureProtected ) self.listSource = self.context.engine.messages.sparseMessageList(peerId: self.peerId, tag: tagMaskForType(self.contentType)) @@ -1787,20 +1931,6 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro } let rect = strongSelf.itemGrid.frameForItem(layer: itemLayer) - /*let proxyNode = ASDisplayNode() - proxyNode.frame = rect - proxyNode.contents = itemLayer.contents - proxyNode.isHidden = true - strongSelf.addSubnode(proxyNode) - - let escapeNotification = EscapeNotification { - proxyNode.removeFromSupernode() - } - - Queue.mainQueue().after(1.0, { - escapeNotification.keep() - })*/ - strongSelf.chatControllerInteraction.openMessageContextActions(message, strongSelf, rect, gesture) strongSelf.itemGrid.cancelGestures() @@ -2209,7 +2339,13 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro let itemFrame = self.view.convert(self.itemGrid.frameForItem(layer: itemLayer), from: self.itemGrid.view) let proxyNode = ASDisplayNode() proxyNode.frame = itemFrame - proxyNode.contents = itemLayer.contents + if let contents = itemLayer.getContents() { + if let image = contents as? UIImage { + proxyNode.contents = image.cgImage + } else { + proxyNode.contents = contents + } + } proxyNode.isHidden = true self.addSubnode(proxyNode) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift index f3b66bd805..8d889b81d6 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift @@ -392,10 +392,11 @@ private final class PeerInfoPendingPane { openMediaCalendar: @escaping () -> Void, paneDidScroll: @escaping () -> Void ) { + let captureProtected = data.peer?.isCopyProtectionEnabled ?? false let paneNode: PeerInfoPaneNode switch key { case .media: - let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, contentType: .photoOrVideo) + let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, contentType: .photoOrVideo, captureProtected: captureProtected) paneNode = visualPaneNode visualPaneNode.openCurrentDate = { openMediaCalendar() @@ -404,17 +405,17 @@ private final class PeerInfoPendingPane { paneDidScroll() } case .files: - let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, contentType: .files) + let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, contentType: .files, captureProtected: captureProtected) paneNode = visualPaneNode //paneNode = PeerInfoListPaneNode(context: context, updatedPresentationData: updatedPresentationData, chatControllerInteraction: chatControllerInteraction, peerId: peerId, tagMask: .file) case .links: paneNode = PeerInfoListPaneNode(context: context, updatedPresentationData: updatedPresentationData, chatControllerInteraction: chatControllerInteraction, peerId: peerId, tagMask: .webPage) case .voice: - let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, contentType: .voiceAndVideoMessages) + let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, contentType: .voiceAndVideoMessages, captureProtected: captureProtected) paneNode = visualPaneNode //paneNode = PeerInfoListPaneNode(context: context, updatedPresentationData: updatedPresentationData, chatControllerInteraction: chatControllerInteraction, peerId: peerId, tagMask: .voiceOrInstantVideo) case .music: - let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, contentType: .music) + let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, contentType: .music, captureProtected: captureProtected) paneNode = visualPaneNode //paneNode = PeerInfoListPaneNode(context: context, updatedPresentationData: updatedPresentationData, chatControllerInteraction: chatControllerInteraction, peerId: peerId, tagMask: .music) case .gifs: diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index a04619a5ea..2b76086919 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -2345,7 +2345,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } let entriesPromise = Promise<[AvatarGalleryEntry]>(entries) - let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, sourceCorners: .round(!strongSelf.headerNode.isAvatarExpanded), remoteEntries: entriesPromise, skipInitial: true, centralEntryIndex: centralEntry.flatMap { entries.firstIndex(of: $0) }, replaceRootController: { controller, ready in + let galleryController = AvatarGalleryController(context: strongSelf.context, peer: peer, sourceCorners: .round, remoteEntries: entriesPromise, skipInitial: true, centralEntryIndex: centralEntry.flatMap { entries.firstIndex(of: $0) }, replaceRootController: { controller, ready in }) galleryController.openAvatarSetup = { [weak self] completion in self?.openAvatarForEditing(fromGallery: true, completion: completion) diff --git a/submodules/TelegramUI/Sources/PeerInfoGifPaneNode.swift b/submodules/TelegramUI/Sources/PeerInfoGifPaneNode.swift index 0552a6691a..d16b75a67f 100644 --- a/submodules/TelegramUI/Sources/PeerInfoGifPaneNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfoGifPaneNode.swift @@ -875,8 +875,11 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDe animationTimer.start() self.statusPromise.set(context.account.postbox.combinedView(keys: [PostboxViewKey.historyTagSummaryView(tag: tagMaskForType(self.contentType), peerId: peerId, namespace: Namespaces.Message.Cloud)]) - |> map { views -> PeerInfoStatusData? in - let count: Int32 = (views.views[PostboxViewKey.historyTagSummaryView(tag: tagMaskForType(self.contentType), peerId: peerId, namespace: Namespaces.Message.Cloud)] as? MessageHistoryTagSummaryView)?.count ?? 0 + |> map { [weak self] views -> PeerInfoStatusData? in + guard let strongSelf = self else { + return nil + } + let count: Int32 = (views.views[PostboxViewKey.historyTagSummaryView(tag: tagMaskForType(strongSelf.contentType), peerId: peerId, namespace: Namespaces.Message.Cloud)] as? MessageHistoryTagSummaryView)?.count ?? 0 if count == 0 { return nil } From 5d97a0c65c1e9b45fb4609801a06aa0e13c94194 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 10 Dec 2021 18:42:29 +0400 Subject: [PATCH 4/9] Cherry-pick more fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/ChatListSearchContainerNode.swift | 18 ++- .../Sources/Items/ChatImageGalleryItem.swift | 6 +- .../Sources/ImageContentAnalysis.swift | 8 +- .../SearchBarNode/Sources/SearchBarNode.swift | 13 ++- .../Sources/SearchDisplayController.swift | 5 +- .../Themes/ThemeGridSearchContentNode.swift | 2 +- .../Search/Archive.imageset/Contents.json | 12 ++ .../Search/Archive.imageset/archive_18.pdf | 109 ++++++++++++++++++ .../TelegramUI/Sources/ChatController.swift | 3 + .../ChatMessageSelectionInputPanelNode.swift | 6 + .../ChatSearchNavigationContentNode.swift | 2 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 4 +- .../Sources/PeerMessagesMediaPlaylist.swift | 2 +- .../StickerPaneTrendingListGridItem.swift | 2 +- 15 files changed, 176 insertions(+), 18 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat List/Search/Archive.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat List/Search/Archive.imageset/archive_18.pdf diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index ff955dabf5..869636a7da 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7131,3 +7131,5 @@ Sorry for the inconvenience."; "Conversation.LargeEmojiDisabledInfo" = "You have disabled large emoji, so they appear small and have no effects in chat."; "Conversation.LargeEmojiEnable" = "Enable Large Emoji"; "Conversation.LargeEmojiEnabled" = "Large emoji enabled."; + +"ChatList.Archive" = "Archive"; diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index b66f3235ef..4da7046071 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -31,6 +31,7 @@ import UndoUI import TextFormat private enum ChatListTokenId: Int32 { + case archive case filter case peer case date @@ -457,13 +458,17 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo private func updateSearchOptions(_ options: ChatListSearchOptions?, clearQuery: Bool = false) { var options = options + var tokens: [SearchBarToken] = [] + if self.groupId == .archive { + tokens.append(SearchBarToken(id: ChatListTokenId.archive.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Archive"), title: self.presentationData.strings.ChatList_Archive, permanent: true)) + } + if options?.isEmpty ?? true { options = nil } self.searchOptionsValue = options self.searchOptions.set(.single(options)) - var tokens: [SearchBarToken] = [] if let (peerId, isGroup, peerName) = options?.peer { let image: UIImage? if isGroup { @@ -473,11 +478,11 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } else { image = UIImage(bundleImageName: "Chat List/Search/User") } - tokens.append(SearchBarToken(id: ChatListTokenId.peer.rawValue, icon:image, title: peerName)) + tokens.append(SearchBarToken(id: ChatListTokenId.peer.rawValue, icon: image, title: peerName, permanent: false)) } if let (_, _, dateTitle) = options?.date { - tokens.append(SearchBarToken(id: ChatListTokenId.date.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Calendar"), title: dateTitle)) + tokens.append(SearchBarToken(id: ChatListTokenId.date.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Calendar"), title: dateTitle, permanent: false)) self.suggestedDates.set(.single([])) } @@ -524,7 +529,12 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo self.paneContainerNode.requestSelectPane(key) self.updateSearchOptions(nil) self.searchTextUpdated(text: query ?? "") - self.setQuery?(nil, [], query ?? "") + + var tokens: [SearchBarToken] = [] + if self.groupId == .archive { + tokens.append(SearchBarToken(id: ChatListTokenId.archive.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Archive"), title: self.presentationData.strings.ChatList_Archive, permanent: true)) + } + self.setQuery?(nil, tokens, query ?? "") } override public func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { diff --git a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift index 2ec9e63f32..2cb36c9ae2 100644 --- a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift @@ -322,8 +322,10 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { strongSelf.recognizedContentNode?.removeFromSupernode() if !results.isEmpty { let size = strongSelf.imageNode.bounds.size - let recognizedContentNode = RecognizedContentContainer(size: size, recognitions: results, presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, present: { c, a in - strongSelf.galleryController()?.presentInGlobalOverlay(c, with: a) + let recognizedContentNode = RecognizedContentContainer(size: size, recognitions: results, presentationData: strongSelf.context.sharedContext.currentPresentationData.with { $0 }, present: { [weak self] c, a in + if let strongSelf = self { + strongSelf.galleryController()?.presentInGlobalOverlay(c, with: a) + } }, performAction: { [weak self] string, action in guard let strongSelf = self else { return diff --git a/submodules/ImageContentAnalysis/Sources/ImageContentAnalysis.swift b/submodules/ImageContentAnalysis/Sources/ImageContentAnalysis.swift index 13b5e5ca05..eb0bf757a8 100644 --- a/submodules/ImageContentAnalysis/Sources/ImageContentAnalysis.swift +++ b/submodules/ImageContentAnalysis/Sources/ImageContentAnalysis.swift @@ -302,6 +302,7 @@ private func recognizeContent(in image: UIImage) -> Signal<[RecognizedContent], let _ = barcodeResult.swap(mappedResults) completion() } + barcodeRequest.preferBackgroundProcessing = true requests.append(barcodeRequest) if #available(iOS 13.0, *) { @@ -310,6 +311,7 @@ private func recognizeContent(in image: UIImage) -> Signal<[RecognizedContent], let _ = textResult.swap(mappedResults) completion() } + textRequest.preferBackgroundProcessing = true textRequest.usesLanguageCorrection = true requests.append(textRequest) } else { @@ -320,7 +322,11 @@ private func recognizeContent(in image: UIImage) -> Signal<[RecognizedContent], try? handler.perform(requests) return ActionDisposable { - + if #available(iOS 13.0, *) { + for request in requests { + request.cancel() + } + } } } } else { diff --git a/submodules/SearchBarNode/Sources/SearchBarNode.swift b/submodules/SearchBarNode/Sources/SearchBarNode.swift index 2756d839c7..9dec26f70d 100644 --- a/submodules/SearchBarNode/Sources/SearchBarNode.swift +++ b/submodules/SearchBarNode/Sources/SearchBarNode.swift @@ -43,12 +43,14 @@ public struct SearchBarToken { public let icon: UIImage? public let title: String public let style: Style? + public let permanent: Bool - public init(id: AnyHashable, icon: UIImage?, title: String, style: Style? = nil) { + public init(id: AnyHashable, icon: UIImage?, title: String, style: Style? = nil, permanent: Bool) { self.id = id self.icon = icon self.title = title self.style = style + self.permanent = permanent } } @@ -106,6 +108,7 @@ private final class TokenNode: ASDisplayNode { } @objc private func tapGesture() { + self.tapped?() } @@ -264,7 +267,7 @@ private class SearchBarTextField: UITextField, UIScrollViewDelegate { if i < self.tokens.count - 1 && isSelected { hasSelected = true } - let isCollapsed = !isSelected && (i < self.tokens.count - 1 || hasSelected) + let isCollapsed = !isSelected && (token.permanent || (i < self.tokens.count - 1 || hasSelected)) tokenNode.update(theme: self.theme, token: token, isSelected: isSelected, isCollapsed: isCollapsed) } var removeKeys: [AnyHashable] = [] @@ -863,8 +866,10 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate { return false } if let index = strongSelf.textField.selectedTokenIndex { - strongSelf.tokens.remove(at: index) - strongSelf.tokensUpdated?(strongSelf.tokens) + if !strongSelf.tokens[index].permanent { + strongSelf.tokens.remove(at: index) + strongSelf.tokensUpdated?(strongSelf.tokens) + } return true } else if strongSelf.text.isEmpty { strongSelf.clearPressed() diff --git a/submodules/SearchUI/Sources/SearchDisplayController.swift b/submodules/SearchUI/Sources/SearchDisplayController.swift index 341bebff44..ed4dc6974f 100644 --- a/submodules/SearchUI/Sources/SearchDisplayController.swift +++ b/submodules/SearchUI/Sources/SearchDisplayController.swift @@ -70,15 +70,18 @@ public final class SearchDisplayController { self.contentNode.dismissInput = { [weak self] in self?.searchBar.deactivate(clear: false) } + + var isFirstTime = true self.contentNode.setQuery = { [weak self] prefix, tokens, query in if let strongSelf = self { strongSelf.searchBar.prefixString = prefix let previousTokens = strongSelf.searchBar.tokens strongSelf.searchBar.tokens = tokens strongSelf.searchBar.text = query - if previousTokens.count < tokens.count { + if previousTokens.count < tokens.count && !isFirstTime { strongSelf.searchBar.selectLastToken() } + isFirstTime = false } } if let placeholder = placeholder { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift index bbdd356531..540ec13610 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeGridSearchContentNode.swift @@ -681,7 +681,7 @@ final class ThemeGridSearchContentNode: SearchDisplayControllerContentNode { foregroundColor = .white strokeColor = color.displayColor } - tokens = [SearchBarToken(id: 0, icon: UIImage(bundleImageName: "Settings/WallpaperSearchColorIcon"), title: color.localizedString(strings: self.presentationData.strings), style: SearchBarToken.Style(backgroundColor: backgroundColor, foregroundColor: foregroundColor, strokeColor: strokeColor))] + tokens = [SearchBarToken(id: 0, icon: UIImage(bundleImageName: "Settings/WallpaperSearchColorIcon"), title: color.localizedString(strings: self.presentationData.strings), style: SearchBarToken.Style(backgroundColor: backgroundColor, foregroundColor: foregroundColor, strokeColor: strokeColor), permanent: false)] text = query placeholder = self.presentationData.strings.Wallpaper_SearchShort } diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/Search/Archive.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Archive.imageset/Contents.json new file mode 100644 index 0000000000..b5c9067a42 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Archive.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "archive_18.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/Search/Archive.imageset/archive_18.pdf b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Archive.imageset/archive_18.pdf new file mode 100644 index 0000000000..ef7c2a13f2 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Archive.imageset/archive_18.pdf @@ -0,0 +1,109 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 3.000000 11.625000 cm +0.000000 0.000000 0.000000 scn +0.000000 1.500000 m +0.000000 1.848739 -0.000000 2.023109 0.038333 2.166172 c +0.142359 2.554400 0.445600 2.857641 0.833829 2.961667 c +0.976891 3.000000 1.151261 3.000000 1.500000 3.000000 c +10.500000 3.000000 l +10.848740 3.000000 11.023109 3.000000 11.166171 2.961667 c +11.554400 2.857641 11.857641 2.554400 11.961666 2.166172 c +12.000000 2.023109 12.000000 1.848739 12.000000 1.500000 c +12.000000 1.500000 l +12.000000 1.151261 12.000000 0.976891 11.961666 0.833829 c +11.857641 0.445600 11.554400 0.142359 11.166171 0.038333 c +11.023109 0.000000 10.848740 0.000000 10.500000 0.000000 c +1.500000 0.000000 l +1.151261 0.000000 0.976891 0.000000 0.833829 0.038333 c +0.445600 0.142359 0.142359 0.445600 0.038333 0.833829 c +-0.000000 0.976891 0.000000 1.151261 0.000000 1.500000 c +0.000000 1.500000 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 3.750000 3.375000 cm +0.000000 0.000000 0.000000 scn +0.000000 3.200033 m +0.000000 7.625000 l +10.500000 7.625000 l +10.500000 3.200035 l +10.500000 2.079930 10.500000 1.519877 10.282013 1.092054 c +10.090266 0.715730 9.784306 0.409769 9.407981 0.218022 c +8.980158 0.000035 8.420105 0.000035 7.300000 0.000035 c +3.200000 0.000035 l +2.079895 0.000035 1.519843 0.000035 1.092019 0.218022 c +0.715695 0.409769 0.409734 0.715730 0.217987 1.092054 c +0.000000 1.519877 0.000000 2.079929 0.000000 3.200033 c +h +3.000000 6.500000 m +2.723858 6.500000 2.500000 6.276142 2.500000 6.000000 c +2.500000 5.723858 2.723858 5.500000 3.000000 5.500000 c +7.500000 5.500000 l +7.776143 5.500000 8.000000 5.723858 8.000000 6.000000 c +8.000000 6.276142 7.776143 6.500000 7.500000 6.500000 c +3.000000 6.500000 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1750 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 18.000000 18.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001840 00000 n +0000001863 00000 n +0000002036 00000 n +0000002110 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2169 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 1f516390b6..732143bd41 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -4859,6 +4859,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G allPeers?.insert(currentAccountPeer, at: 0) } } + if allPeers?.count == 1 { + allPeers = nil + } strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { return $0.updatedSendAsPeers(allPeers) }) diff --git a/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift index e01f11d8c1..4d04335615 100644 --- a/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageSelectionInputPanelNode.swift @@ -132,6 +132,9 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { } @objc func forwardButtonPressed() { + if let _ = self.presentationInterfaceState?.renderedPeer?.peer as? TelegramSecretChat { + return + } if let actions = self.actions, actions.isCopyProtected { self.interfaceInteraction?.displayCopyProtectionTip(self.forwardButton, false) } else { @@ -140,6 +143,9 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode { } @objc func shareButtonPressed() { + if let _ = self.presentationInterfaceState?.renderedPeer?.peer as? TelegramSecretChat { + return + } if let actions = self.actions, actions.isCopyProtected { self.interfaceInteraction?.displayCopyProtectionTip(self.shareButton, true) } else { diff --git a/submodules/TelegramUI/Sources/ChatSearchNavigationContentNode.swift b/submodules/TelegramUI/Sources/ChatSearchNavigationContentNode.swift index f2dce4fdbf..4c2aaf455e 100644 --- a/submodules/TelegramUI/Sources/ChatSearchNavigationContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchNavigationContentNode.swift @@ -112,7 +112,7 @@ final class ChatSearchNavigationContentNode: NavigationBarContentNode { self.searchBar.prefixString = NSAttributedString(string: strings.Conversation_SearchByName_Prefix, font: searchBarFont, textColor: theme.rootController.navigationSearchBar.inputTextColor) self.searchBar.placeholderString = nil case let .member(peer): - self.searchBar.tokens = [SearchBarToken(id: peer.id, icon: UIImage(bundleImageName: "Chat List/Search/User"), title: EnginePeer(peer).compactDisplayTitle)] + self.searchBar.tokens = [SearchBarToken(id: peer.id, icon: UIImage(bundleImageName: "Chat List/Search/User"), title: EnginePeer(peer).compactDisplayTitle, permanent: false)] self.searchBar.prefixString = nil self.searchBar.placeholderString = nil } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 2b76086919..6c0a042b41 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -6424,7 +6424,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } strongSelf.deleteMessages(messageIds: nil) }, shareMessages: { [weak self] in - guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty else { + guard let strongSelf = self, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty, strongSelf.peerId.namespace != Namespaces.Peer.SecretChat else { return } let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in @@ -6448,7 +6448,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } }) }, forwardMessages: { [weak self] in - guard let strongSelf = self else { + guard let strongSelf = self, strongSelf.peerId.namespace != Namespaces.Peer.SecretChat else { return } strongSelf.forwardMessages(messageIds: nil) diff --git a/submodules/TelegramUI/Sources/PeerMessagesMediaPlaylist.swift b/submodules/TelegramUI/Sources/PeerMessagesMediaPlaylist.swift index 44839c6c05..996269fd3a 100644 --- a/submodules/TelegramUI/Sources/PeerMessagesMediaPlaylist.swift +++ b/submodules/TelegramUI/Sources/PeerMessagesMediaPlaylist.swift @@ -114,7 +114,7 @@ final class MessageMediaPlaylistItem: SharedMediaPlaylistItem { albumArt = SharedMediaPlaybackAlbumArt(thumbnailResource: ExternalMusicAlbumArtResource(title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: true), fullSizeResource: ExternalMusicAlbumArtResource(title: updatedTitle ?? "", performer: updatedPerformer ?? "", isThumbnail: false)) } - return SharedMediaPlaybackDisplayData.music(title: updatedTitle, performer: updatedPerformer, albumArt: albumArt, long: duration > 60 * 20) + return SharedMediaPlaybackDisplayData.music(title: updatedTitle, performer: updatedPerformer, albumArt: albumArt, long: CGFloat(duration) > 10.0 * 60.0) } case let .Video(_, _, flags): if flags.contains(.instantRoundVideo) { diff --git a/submodules/TelegramUI/Sources/StickerPaneTrendingListGridItem.swift b/submodules/TelegramUI/Sources/StickerPaneTrendingListGridItem.swift index f023e78890..a6616e5e59 100644 --- a/submodules/TelegramUI/Sources/StickerPaneTrendingListGridItem.swift +++ b/submodules/TelegramUI/Sources/StickerPaneTrendingListGridItem.swift @@ -528,7 +528,7 @@ class StickerPaneTrendingListGridItemNode: GridItemNode { let titleFrame = CGRect(origin: CGPoint(x: params.leftInset + leftInset, y: topOffset), size: titleLayout.size) let dismissButtonSize = CGSize(width: 12.0, height: 12.0) - self.dismissButtonNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - rightInset - dismissButtonSize.width, y: topOffset - 1.0), size: dismissButtonSize) + self.dismissButtonNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - rightInset - dismissButtonSize.width + 1.0, y: topOffset - 1.0), size: dismissButtonSize) self.dismissButtonNode.isHidden = item.dismiss == nil self.titleNode.frame = titleFrame } From 7a6264a269db8140c9f9c6db6370c7aa4bc234df Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 10 Dec 2021 19:50:32 +0400 Subject: [PATCH 5/9] Bump version --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index 9c82469a48..f4351a4b04 100644 --- a/versions.json +++ b/versions.json @@ -1,5 +1,5 @@ { - "app": "8.3", + "app": "8.3.1", "bazel": "4.0.0", "xcode": "13.1" } From daa9aa2587dab7e445e0f5bc3b01297d7e3eac43 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 10 Dec 2021 19:54:55 +0400 Subject: [PATCH 6/9] Update locked message logic --- .../Sources/NotificationService.swift | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/Telegram/NotificationService/Sources/NotificationService.swift b/Telegram/NotificationService/Sources/NotificationService.swift index e76cb277f2..3e50ecf6e1 100644 --- a/Telegram/NotificationService/Sources/NotificationService.swift +++ b/Telegram/NotificationService/Sources/NotificationService.swift @@ -488,19 +488,22 @@ private struct NotificationContent: CustomStringConvertible { func generate() -> UNNotificationContent { var content = UNMutableNotificationContent() - if let isLockedMessage = self.isLockedMessage { - content.body = isLockedMessage - } else { - if let title = self.title { - content.title = title - } - if let subtitle = self.subtitle { - content.subtitle = subtitle - } - if let body = self.body { - content.body = body + if let title = self.title { + content.title = title + } + if let subtitle = self.subtitle { + content.subtitle = subtitle + } + if let body = self.body { + content.body = body + } + + if !content.title.isEmpty || !content.subtitle.isEmpty || !content.body.isEmpty { + if let isLockedMessage = self.isLockedMessage { + content.body = isLockedMessage } } + if let threadId = self.threadId { content.threadIdentifier = threadId } @@ -688,7 +691,7 @@ private final class NotificationServiceHandler { guard let strongSelf = self, let recordId = recordId else { Logger.shared.log("NotificationService \(episode)", "Couldn't find a matching decryption key") - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) completed() @@ -710,7 +713,7 @@ private final class NotificationServiceHandler { guard let stateManager = stateManager else { Logger.shared.log("NotificationService \(episode)", "Didn't receive stateManager") - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) completed() return @@ -720,7 +723,7 @@ private final class NotificationServiceHandler { strongSelf.notificationKeyDisposable.set((existingMasterNotificationsKey(postbox: stateManager.postbox) |> deliverOn(strongSelf.queue)).start(next: { notificationsKey in guard let strongSelf = self else { - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) completed() @@ -729,7 +732,7 @@ private final class NotificationServiceHandler { guard let notificationsKey = notificationsKey else { Logger.shared.log("NotificationService \(episode)", "Didn't receive decryption key") - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) completed() @@ -738,7 +741,7 @@ private final class NotificationServiceHandler { guard let decryptedPayload = decryptedNotificationPayload(key: notificationsKey, data: payloadData) else { Logger.shared.log("NotificationService \(episode)", "Couldn't decrypt payload") - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) completed() @@ -747,7 +750,7 @@ private final class NotificationServiceHandler { guard let payloadJson = try? JSONSerialization.jsonObject(with: decryptedPayload, options: []) as? [String: Any] else { Logger.shared.log("NotificationService \(episode)", "Couldn't process payload as JSON") - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) completed() @@ -840,7 +843,7 @@ private final class NotificationServiceHandler { action = .logout case "MESSAGE_MUTED": if let peerId = peerId { - action = .poll(peerId: peerId, content: NotificationContent(isLockedMessage: isLockedMessage)) + action = .poll(peerId: peerId, content: NotificationContent(isLockedMessage: nil)) } case "MESSAGE_DELETED": if let peerId = peerId { @@ -970,7 +973,7 @@ private final class NotificationServiceHandler { if #available(iOS 14.5, *), voiceCallSettings.enableSystemIntegration { Logger.shared.log("NotificationService \(episode)", "Will report voip notification") - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) CXProvider.reportNewIncomingVoIPPushPayload(voipPayload, completion: { error in @@ -993,7 +996,7 @@ private final class NotificationServiceHandler { case .logout: Logger.shared.log("NotificationService \(episode)", "Will logout") - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) completed() case let .poll(peerId, initialContent): @@ -1249,7 +1252,7 @@ private final class NotificationServiceHandler { postbox: stateManager.postbox ) |> deliverOn(strongSelf.queue)).start(next: { value in - var content = NotificationContent(isLockedMessage: isLockedMessage) + var content = NotificationContent(isLockedMessage: nil) if isCurrentAccount { content.badge = Int(value.0) } @@ -1298,7 +1301,7 @@ private final class NotificationServiceHandler { postbox: stateManager.postbox ) |> deliverOn(strongSelf.queue)).start(next: { value in - var content = NotificationContent(isLockedMessage: isLockedMessage) + var content = NotificationContent(isLockedMessage: nil) if isCurrentAccount { content.badge = Int(value.0) } @@ -1325,7 +1328,7 @@ private final class NotificationServiceHandler { }) } } else { - let content = NotificationContent(isLockedMessage: isLockedMessage) + let content = NotificationContent(isLockedMessage: nil) updateCurrentContent(content) completed() From f3eaa9fecdc6f1107dafc13a092782cabb066582 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 10 Dec 2021 20:41:23 +0400 Subject: [PATCH 7/9] Don't resend code automatically --- .../Telegram-iOS/en.lproj/Localizable.strings | 1 + .../Sources/AuthorizationOptionText.swift | 13 +++-- .../CodeInputView/Sources/CodeInputView.swift | 14 +++-- ...ationSequenceCodeEntryControllerNode.swift | 53 +++++++++++-------- 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 869636a7da..3ae20ff1c7 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7121,6 +7121,7 @@ Sorry for the inconvenience."; "ForcedPasswordSetup.Intro.DismissActionCancel" = "No, let me set a password"; "ForcedPasswordSetup.Intro.DismissActionOK" = "Yes, I’m sure"; +"Login.ShortCallTitle" = "Within a few seconds you should\nreceive a short call from:"; "Login.CodePhonePatternInfoText" = "Please enter the last digits\nof the missed call number."; "Login.EnterMissingDigits" = "Enter the missing digits"; diff --git a/submodules/AuthorizationUI/Sources/AuthorizationOptionText.swift b/submodules/AuthorizationUI/Sources/AuthorizationOptionText.swift index fe71055aef..78251b1c14 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationOptionText.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationOptionText.swift @@ -17,14 +17,14 @@ public func authorizationCurrentOptionText(_ type: SentAuthorizationCodeType, st case .missedCall: let body = MarkdownAttributeSet(font: Font.regular(16.0), textColor: primaryColor) let bold = MarkdownAttributeSet(font: Font.semibold(16.0), textColor: primaryColor) - return parseMarkdownIntoAttributedString("Within a few seconds you should\nreceive a short call from:", attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center) + return parseMarkdownIntoAttributedString(strings.Login_ShortCallTitle, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center) case .call, .flashCall: return NSAttributedString(string: strings.ChangePhoneNumberCode_Called, font: Font.regular(16.0), textColor: primaryColor, paragraphAlignment: .center) } } public func authorizationNextOptionText(currentType: SentAuthorizationCodeType, nextType: AuthorizationCodeNextType?, timeout: Int32?, strings: PresentationStrings, primaryColor: UIColor, accentColor: UIColor) -> (NSAttributedString, Bool) { - if let nextType = nextType, let timeout = timeout { + if let nextType = nextType, let timeout = timeout, timeout > 0 { let minutes = timeout / 60 let seconds = timeout % 60 switch nextType { @@ -54,7 +54,14 @@ public func authorizationNextOptionText(currentType: SentAuthorizationCodeType, return (NSAttributedString(string: strings.Login_HaveNotReceivedCodeInternal, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) } default: - return (NSAttributedString(string: strings.Login_HaveNotReceivedCodeInternal, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) + switch nextType { + case .sms: + return (NSAttributedString(string: strings.Login_SendCodeViaSms, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) + case .call, .flashCall, .missedCall: + return (NSAttributedString(string: strings.Login_SendCodeViaCall, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) + case .none: + return (NSAttributedString(string: strings.Login_HaveNotReceivedCodeInternal, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) + } } } } diff --git a/submodules/CodeInputView/Sources/CodeInputView.swift b/submodules/CodeInputView/Sources/CodeInputView.swift index e8fe0e5571..6228e08a7f 100644 --- a/submodules/CodeInputView/Sources/CodeInputView.swift +++ b/submodules/CodeInputView/Sources/CodeInputView.swift @@ -75,7 +75,9 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate { } } - self.textNode.attributedText = NSAttributedString(string: text, font: Font.monospace(21.0), textColor: UIColor(argb: textColor)) + let fontSize: CGFloat = floor(21.0 * size.height / 28.0) + + self.textNode.attributedText = NSAttributedString(string: text, font: Font.monospace(fontSize), textColor: UIColor(argb: textColor)) let textSize = self.textNode.updateLayout(size) self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize) @@ -224,12 +226,18 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate { self.textField.keyboardAppearance = .light } - let height: CGFloat = 28.0 + let height: CGFloat + if prefix.isEmpty { + height = 40.0 + } else { + height = 28.0 + } + self.prefixLabel.attributedText = NSAttributedString(string: prefix, font: Font.monospace(21.0), textColor: UIColor(argb: theme.foreground)) let prefixSize = self.prefixLabel.updateLayout(CGSize(width: width, height: 100.0)) let prefixSpacing: CGFloat = prefix.isEmpty ? 0.0 : 8.0 - let itemSize = CGSize(width: 25.0, height: height) + let itemSize = CGSize(width: floor(25.0 * height / 28.0), height: height) let itemSpacing: CGFloat = 5.0 let itemsWidth: CGFloat = itemSize.width * CGFloat(count) + itemSpacing * CGFloat(count - 1) diff --git a/submodules/TelegramUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift b/submodules/TelegramUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift index 698aa9262f..e283434ba3 100644 --- a/submodules/TelegramUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift +++ b/submodules/TelegramUI/Sources/AuthorizationSequenceCodeEntryControllerNode.swift @@ -18,11 +18,10 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF private let titleIconNode: ASImageNode private let currentOptionNode: ASTextNode private let currentOptionInfoNode: ASTextNode - private let nextOptionNode: HighlightableButtonNode + private let nextOptionTitleNode: ImmediateTextNode + private let nextOptionButtonNode: HighlightableButtonNode private let codeInputView: CodeInputView - //private let codeField: TextFieldNode - //private let codeSeparatorNode: ASDisplayNode private var codeType: SentAuthorizationCodeType? @@ -81,11 +80,14 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF self.currentOptionInfoNode.isUserInteractionEnabled = false self.currentOptionInfoNode.displaysAsynchronously = false - self.nextOptionNode = HighlightableButtonNode() - self.nextOptionNode.displaysAsynchronously = false + self.nextOptionTitleNode = ImmediateTextNode() + + self.nextOptionButtonNode = HighlightableButtonNode() + self.nextOptionButtonNode.displaysAsynchronously = false let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: .sms(length: 5), nextType: .call, timeout: 60, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor) - self.nextOptionNode.setAttributedTitle(nextOptionText, for: []) - self.nextOptionNode.isUserInteractionEnabled = nextOptionActive + self.nextOptionTitleNode.attributedText = nextOptionText + self.nextOptionButtonNode.isUserInteractionEnabled = nextOptionActive + self.nextOptionButtonNode.addSubnode(self.nextOptionTitleNode) /*self.codeSeparatorNode = ASDisplayNode() self.codeSeparatorNode.isLayerBacked = true @@ -125,7 +127,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF self.addSubnode(self.titleIconNode) self.addSubnode(self.currentOptionNode) self.addSubnode(self.currentOptionInfoNode) - self.addSubnode(self.nextOptionNode) + self.addSubnode(self.nextOptionButtonNode) self.codeInputView.updated = { [weak self] in guard let strongSelf = self else { @@ -139,7 +141,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF //self.codeField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_Code, font: Font.regular(24.0), textColor: self.theme.list.itemPlaceholderTextColor) - self.nextOptionNode.addTarget(self, action: #selector(self.nextOptionNodePressed), forControlEvents: .touchUpInside) + self.nextOptionButtonNode.addTarget(self, action: #selector(self.nextOptionNodePressed), forControlEvents: .touchUpInside) } deinit { @@ -182,21 +184,24 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF self.currentOptionInfoNode.attributedText = NSAttributedString(string: "", font: Font.regular(15.0), textColor: self.theme.list.itemPrimaryTextColor) } if let timeout = timeout { + #if DEBUG + let timeout = min(timeout, 5) + #endif self.currentTimeoutTime = timeout let disposable = ((Signal.single(1) |> delay(1.0, queue: Queue.mainQueue())) |> restart).start(next: { [weak self] _ in if let strongSelf = self { if let currentTimeoutTime = strongSelf.currentTimeoutTime, currentTimeoutTime > 0 { strongSelf.currentTimeoutTime = currentTimeoutTime - 1 - let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: codeType, nextType: nextType, timeout:strongSelf.currentTimeoutTime, strings: strongSelf.strings, primaryColor: strongSelf.theme.list.itemPrimaryTextColor, accentColor: strongSelf.theme.list.itemAccentColor) - strongSelf.nextOptionNode.setAttributedTitle(nextOptionText, for: []) - strongSelf.nextOptionNode.isUserInteractionEnabled = nextOptionActive + let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: codeType, nextType: nextType, timeout: strongSelf.currentTimeoutTime, strings: strongSelf.strings, primaryColor: strongSelf.theme.list.itemPrimaryTextColor, accentColor: strongSelf.theme.list.itemAccentColor) + strongSelf.nextOptionTitleNode.attributedText = nextOptionText + strongSelf.nextOptionButtonNode.isUserInteractionEnabled = nextOptionActive if let layoutArguments = strongSelf.layoutArguments { strongSelf.containerLayoutUpdated(layoutArguments.0, navigationBarHeight: layoutArguments.1, transition: .immediate) } - if currentTimeoutTime == 1 { + /*if currentTimeoutTime == 1 { strongSelf.requestNextOption?() - } + }*/ } } }) @@ -206,8 +211,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF self.countdownDisposable.set(nil) } let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: codeType, nextType: nextType, timeout: self.currentTimeoutTime, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor) - self.nextOptionNode.setAttributedTitle(nextOptionText, for: []) - self.nextOptionNode.isUserInteractionEnabled = nextOptionActive + self.nextOptionTitleNode.attributedText = nextOptionText + self.nextOptionButtonNode.isUserInteractionEnabled = nextOptionActive + + if let layoutArguments = self.layoutArguments { + self.containerLayoutUpdated(layoutArguments.0, navigationBarHeight: layoutArguments.1, transition: .immediate) + } } func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { @@ -264,7 +273,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF let currentOptionSize = self.currentOptionNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude)) let currentOptionInfoSize = self.currentOptionInfoNode.measure(CGSize(width: layout.size.width - 28.0, height: CGFloat.greatestFiniteMagnitude)) - let nextOptionSize = self.nextOptionNode.measure(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude)) + let nextOptionSize = self.nextOptionTitleNode.updateLayout(CGSize(width: layout.size.width, height: CGFloat.greatestFiniteMagnitude)) let codeLength: Int var codePrefix: String = "" @@ -341,7 +350,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF //items.append(AuthorizationLayoutItem(node: self.codeField, size: CGSize(width: layout.size.width - 88.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) //items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 88.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) - items.append(AuthorizationLayoutItem(node: self.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) + items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) case .missedCall: self.titleIconNode.isHidden = false @@ -369,7 +378,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF items.append(AuthorizationLayoutItem(node: self.currentOptionInfoNode, size: currentOptionInfoSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 60.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) - items.append(AuthorizationLayoutItem(node: self.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) + items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) default: self.titleIconNode.isHidden = true items.append(AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) @@ -379,7 +388,7 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF /*items.append(AuthorizationLayoutItem(node: self.codeField, size: CGSize(width: layout.size.width - 88.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 88.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))*/ - items.append(AuthorizationLayoutItem(node: self.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) + items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) } } else { self.titleIconNode.isHidden = true @@ -390,10 +399,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF /*items.append(AuthorizationLayoutItem(node: self.codeField, size: CGSize(width: layout.size.width - 88.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 100.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) items.append(AuthorizationLayoutItem(node: self.codeSeparatorNode, size: CGSize(width: layout.size.width - 88.0, height: UIScreenPixel), spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)))*/ - items.append(AuthorizationLayoutItem(node: self.nextOptionNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) + items.append(AuthorizationLayoutItem(node: self.nextOptionButtonNode, size: nextOptionSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 50.0, maxValue: 120.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0))) } let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - 20.0)), items: items, transition: transition, failIfDoesNotFit: false) + + self.nextOptionTitleNode.frame = self.nextOptionButtonNode.bounds } func activateInput() { From af9a41779816249362b0d0662538e18afba82817 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 10 Dec 2021 20:52:53 +0400 Subject: [PATCH 8/9] Don't dismiss payment controller with Apple Pay --- submodules/AppLock/Sources/AppLock.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/submodules/AppLock/Sources/AppLock.swift b/submodules/AppLock/Sources/AppLock.swift index 94e973538b..2f8d668b27 100644 --- a/submodules/AppLock/Sources/AppLock.swift +++ b/submodules/AppLock/Sources/AppLock.swift @@ -11,6 +11,7 @@ import TelegramUIPreferences import ImageBlur import FastBlur import AppLockState +import PassKit private func isLocked(passcodeSettings: PresentationPasscodeSettings, state: LockState, isApplicationActive: Bool) -> Bool { if state.isManuallyLocked { @@ -204,6 +205,7 @@ public final class AppLockContextImpl: AppLockContext { strongSelf.passcodeController = passcodeController if let rootViewController = strongSelf.rootController { if let _ = rootViewController.presentedViewController as? UIActivityViewController { + } else if let _ = rootViewController.presentedViewController as? PKPaymentAuthorizationViewController { } else { rootViewController.dismiss(animated: false, completion: nil) } @@ -228,6 +230,7 @@ public final class AppLockContextImpl: AppLockContext { if let rootViewController = strongSelf.rootController { if let _ = rootViewController.presentedViewController as? UIActivityViewController { + } else if let _ = rootViewController.presentedViewController as? PKPaymentAuthorizationViewController { } else { rootViewController.dismiss(animated: false, completion: nil) } From aa1b009cea6b9163dd025b36506704292ac0e814 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 10 Dec 2021 22:03:35 +0400 Subject: [PATCH 9/9] Update localization --- Telegram/Telegram-iOS/en.lproj/Localizable.strings | 9 +++++---- .../Sources/AuthorizationOptionText.swift | 8 ++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 3ae20ff1c7..179fb30bd3 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -364,7 +364,7 @@ "Login.HaveNotReceivedCodeInternal" = "Haven't received the code?"; "Login.CodeSentSms" = "We have sent you an SMS with the code"; "Login.Code" = "Code"; -"Login.WillCallYou" = "Telegram will call you in %@"; +"Login.WillCallYou" = "You can request a voice call in %@"; "Login.CallRequestState2" = "Requesting a call from Telegram..."; "Login.CallRequestState3" = "Telegram dialed your number\n[Didn't get the code?]"; "Login.EmailNotConfiguredError" = "Please set up an email account."; @@ -2073,7 +2073,7 @@ "Login.CodeSentCall" = "We are calling your phone to dictate a code."; -"Login.WillSendSms" = "Telegram will send you an SMS in %@"; +"Login.WillSendSms" = "You can request an SMS in %@"; "Login.SmsRequestState2" = "Requesting an SMS from Telegram..."; "Login.SmsRequestState3" = "Telegram sent you an SMS\n[Didn't get the code?]"; @@ -3764,8 +3764,9 @@ Unused sets are archived when you add more."; "AuthCode.Alert" = "Your login code is %@. Enter it in the Telegram app where you are trying to log in.\n\nDo not give this code to anyone."; "Login.CheckOtherSessionMessages" = "Check your Telegram messages"; -"Login.SendCodeViaSms" = "Send the code as an SMS"; -"Login.SendCodeViaCall" = "Get code on my phone"; +"Login.SendCodeViaSms" = "Get the code via SMS"; +"Login.SendCodeViaCall" = "Call me to dictate the code"; +"Login.SendCodeViaFlashCall" = "Get the code via phone call"; "Login.CancelPhoneVerification" = "Do you want to stop the phone number verification process?"; "Login.CancelPhoneVerificationStop" = "Stop"; "Login.CancelPhoneVerificationContinue" = "Continue"; diff --git a/submodules/AuthorizationUI/Sources/AuthorizationOptionText.swift b/submodules/AuthorizationUI/Sources/AuthorizationOptionText.swift index 78251b1c14..da9faf84d3 100644 --- a/submodules/AuthorizationUI/Sources/AuthorizationOptionText.swift +++ b/submodules/AuthorizationUI/Sources/AuthorizationOptionText.swift @@ -48,8 +48,10 @@ public func authorizationNextOptionText(currentType: SentAuthorizationCodeType, switch nextType { case .sms: return (NSAttributedString(string: strings.Login_SendCodeViaSms, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) - case .call, .flashCall, .missedCall: + case .call: return (NSAttributedString(string: strings.Login_SendCodeViaCall, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) + case .flashCall, .missedCall: + return (NSAttributedString(string: strings.Login_SendCodeViaFlashCall, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) case .none: return (NSAttributedString(string: strings.Login_HaveNotReceivedCodeInternal, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) } @@ -57,8 +59,10 @@ public func authorizationNextOptionText(currentType: SentAuthorizationCodeType, switch nextType { case .sms: return (NSAttributedString(string: strings.Login_SendCodeViaSms, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) - case .call, .flashCall, .missedCall: + case .call: return (NSAttributedString(string: strings.Login_SendCodeViaCall, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) + case .flashCall, .missedCall: + return (NSAttributedString(string: strings.Login_SendCodeViaFlashCall, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) case .none: return (NSAttributedString(string: strings.Login_HaveNotReceivedCodeInternal, font: Font.regular(16.0), textColor: accentColor, paragraphAlignment: .center), true) }