diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index f183c2c7a4..d24e4b3073 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -11884,3 +11884,11 @@ Sorry for the inconvenience."; "BusinessLink.ErrorExpired" = "Link Expired"; "WebApp.AlertBiometryAccessText" = "Do you want to allow %@ to use Face ID?"; + +"StoryList.SubtitleArchived_1" = "1 archived post"; +"StoryList.SubtitleArchived_any" = "%d archived posts"; + +"Business.AdsTitle" = "ADS IN CHANNELS"; +"Business.DontHideAds" = "Do Not Hide Ads"; +"Business.AdsInfo" = "As a Premium subscriber, you don't see any ads on Telegram, but you can turn them on, for example, to view your own ads that you launched on the [Telegram Ad Platform >]()"; +"Business.AdsInfo_URL" = "https://promote.telegram.org"; diff --git a/build-system/bazel-rules/apple_support b/build-system/bazel-rules/apple_support index d97e2e3dd4..cf271a330b 160000 --- a/build-system/bazel-rules/apple_support +++ b/build-system/bazel-rules/apple_support @@ -1 +1 @@ -Subproject commit d97e2e3dd45bd73080d1e76474062fd8bca55e65 +Subproject commit cf271a330b08a3bbd8ad61241d03787683d5a1c5 diff --git a/build-system/bazel-rules/rules_apple b/build-system/bazel-rules/rules_apple index 3430ddfcb1..345b71fc22 160000 --- a/build-system/bazel-rules/rules_apple +++ b/build-system/bazel-rules/rules_apple @@ -1 +1 @@ -Subproject commit 3430ddfcb11842e3e220837e6475d2be522dccf1 +Subproject commit 345b71fc226d79abfe180b27b7f8d711aa398bbd diff --git a/build-system/bazel-rules/rules_swift b/build-system/bazel-rules/rules_swift index f8a04280c1..72347ab6cb 160000 --- a/build-system/bazel-rules/rules_swift +++ b/build-system/bazel-rules/rules_swift @@ -1 +1 @@ -Subproject commit f8a04280c1119b40563cba81a304f16c8ca0c8b1 +Subproject commit 72347ab6cb613b36039d43a071ac67f63f4de248 diff --git a/build-system/bazel-rules/rules_xcodeproj b/build-system/bazel-rules/rules_xcodeproj index 48c3af2361..77e00ae3fd 160000 --- a/build-system/bazel-rules/rules_xcodeproj +++ b/build-system/bazel-rules/rules_xcodeproj @@ -1 +1 @@ -Subproject commit 48c3af236127cc0ba78b2664fa9b868f2471ca2c +Subproject commit 77e00ae3fd2d7f6fae3790420bc95c8f7abb6f7b diff --git a/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode.h b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode.h index f74e585372..3119c01976 100644 --- a/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode.h +++ b/submodules/AsyncDisplayKit/Source/PublicHeaders/AsyncDisplayKit/ASDisplayNode.h @@ -995,4 +995,71 @@ typedef NS_ENUM(NSInteger, ASLayoutEngineType) { @property (nullable, weak) ASDisplayNode *asyncdisplaykit_node; @end +@protocol ASGestureRecognizerDelegate + +@optional +// called when a gesture recognizer attempts to transition out of UIGestureRecognizerStatePossible. returning NO causes it to transition to UIGestureRecognizerStateFailed +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer; + +// called when the recognition of one of gestureRecognizer or otherGestureRecognizer would be blocked by the other +// return YES to allow both to recognize simultaneously. the default implementation returns NO (by default no two gestures can be recognized simultaneously) +// +// note: returning YES is guaranteed to allow simultaneous recognition. returning NO is not guaranteed to prevent simultaneous recognition, as the other gesture's delegate may return YES +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer; + +// called once per attempt to recognize, so failure requirements can be determined lazily and may be set up between recognizers across view hierarchies +// return YES to set up a dynamic failure requirement between gestureRecognizer and otherGestureRecognizer +// +// note: returning YES is guaranteed to set up the failure requirement. returning NO does not guarantee that there will not be a failure requirement as the other gesture's counterpart delegate or subclass methods may return YES +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer API_AVAILABLE(ios(7.0)); +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer API_AVAILABLE(ios(7.0)); + +// called before touchesBegan:withEvent: is called on the gesture recognizer for a new touch. return NO to prevent the gesture recognizer from seeing this touch +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch; + +// called before pressesBegan:withEvent: is called on the gesture recognizer for a new press. return NO to prevent the gesture recognizer from seeing this press +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceivePress:(UIPress *)press; + +// called once before either -gestureRecognizer:shouldReceiveTouch: or -gestureRecognizer:shouldReceivePress: +// return NO to prevent the gesture recognizer from seeing this event +- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveEvent:(UIEvent *)event API_AVAILABLE(ios(13.4), tvos(13.4)) API_UNAVAILABLE(watchos); + +@end + +@protocol ASScrollViewDelegate +@optional + +- (void)scrollViewDidScroll:(UIScrollView *)scrollView; // any offset changes +- (void)scrollViewDidZoom:(UIScrollView *)scrollView API_AVAILABLE(ios(3.2)); // any zoom scale changes + +// called on start of dragging (may require some time and or distance to move) +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView; +// called on finger up if the user dragged. velocity is in points/millisecond. targetContentOffset may be changed to adjust where the scroll view comes to rest +- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset API_AVAILABLE(ios(5.0)); +// called on finger up if the user dragged. decelerate is true if it will continue moving afterwards +- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate; + +- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView; // called on finger up as we are moving +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; // called when scroll view grinds to a halt + +- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView; // called when setContentOffset/scrollRectVisible:animated: finishes. not called if not animating + +- (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView; // return a view that will be scaled. if delegate returns nil, nothing happens +- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view API_AVAILABLE(ios(3.2)); // called before the scroll view begins zooming its content +- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale; // scale between minimum and maximum. called after any 'bounce' animations + +- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView; // return a yes if you want to scroll to the top. if not defined, assumes YES +- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView; // called when scrolling animation finished. may be called immediately if already at top + +/* Also see -[UIScrollView adjustedContentInsetDidChange] + */ +- (void)scrollViewDidChangeAdjustedContentInset:(UIScrollView *)scrollView API_AVAILABLE(ios(11.0), tvos(11.0)); + +- (nullable NSString *)accessibilityScrollStatusForScrollView:(UIScrollView *)scrollView; + +// If an object adopting this protocol responds to this method, the system will try sending it before sending its non-attributed version. +- (nullable NSAttributedString *)accessibilityAttributedScrollStatusForScrollView:(UIScrollView *)scrollView API_AVAILABLE(ios(11.0), tvos(11.0)); + +@end + NS_ASSUME_NONNULL_END diff --git a/submodules/AttachmentUI/Sources/AttachmentContainer.swift b/submodules/AttachmentUI/Sources/AttachmentContainer.swift index 7b934c28b3..9f2c472512 100644 --- a/submodules/AttachmentUI/Sources/AttachmentContainer.swift +++ b/submodules/AttachmentUI/Sources/AttachmentContainer.swift @@ -25,7 +25,7 @@ public func attachmentDefaultTopInset(layout: ContainerViewLayout?) -> CGFloat { } } -final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { +final class AttachmentContainer: ASDisplayNode, ASGestureRecognizerDelegate { let wrappingNode: ASDisplayNode let clipNode: ASDisplayNode let container: NavigationContainer @@ -112,7 +112,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { super.didLoad() let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.panGestureRecognizer = panRecognizer diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index 255e9c3e53..092ea90dba 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -680,7 +680,7 @@ private final class MainButtonNode: HighlightTrackingButtonNode { } } -final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { +final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate { private let context: AccountContext private let isScheduledMessages: Bool private var presentationData: PresentationData @@ -1026,7 +1026,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { self.containerNode.layer.cornerCurve = .continuous } - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.showsVerticalScrollIndicator = false diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutInfoControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutInfoControllerNode.swift index 2ae9a23786..353b1adfbf 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutInfoControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutInfoControllerNode.swift @@ -92,7 +92,7 @@ enum BotCheckoutInfoControllerStatus { case verifying } -final class BotCheckoutInfoControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class BotCheckoutInfoControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private weak var navigationBar: NavigationBar? private let invoice: BotPaymentInvoice @@ -244,7 +244,7 @@ final class BotCheckoutInfoControllerNode: ViewControllerTracingNode, UIScrollVi self.scrollNode.view.alwaysBounceVertical = true self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.showsHorizontalScrollIndicator = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.scrollNode) diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutNativeCardEntryControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutNativeCardEntryControllerNode.swift index 9f497c90b9..e50e9d8d2a 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutNativeCardEntryControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutNativeCardEntryControllerNode.swift @@ -41,7 +41,7 @@ private final class BotCheckoutNativeCardEntryScrollerNode: ASDisplayNode { } } -final class BotCheckoutNativeCardEntryControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class BotCheckoutNativeCardEntryControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private weak var navigationBar: NavigationBar? private let provider: BotCheckoutNativeCardEntryController.Provider @@ -183,7 +183,7 @@ final class BotCheckoutNativeCardEntryControllerNode: ViewControllerTracingNode, self.scrollNode.view.alwaysBounceVertical = true self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.showsHorizontalScrollIndicator = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.scrollNode) diff --git a/submodules/BrowserUI/Sources/BrowserStackContainerNode.swift b/submodules/BrowserUI/Sources/BrowserStackContainerNode.swift index 2e5c58f3ee..17b244e331 100644 --- a/submodules/BrowserUI/Sources/BrowserStackContainerNode.swift +++ b/submodules/BrowserUI/Sources/BrowserStackContainerNode.swift @@ -191,7 +191,7 @@ class StackItemContainerNode: ASDisplayNode { } } -public class StackContainerNode: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +public class StackContainerNode: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private let scrollNode: ASScrollNode private var nodes: [StackItemContainerNode] @@ -222,11 +222,11 @@ public class StackContainerNode: ASDisplayNode, UIScrollViewDelegate, UIGestureR self.scrollNode.view.contentInsetAdjustmentBehavior = .never } - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.alwaysBounceVertical = true let deleteGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPanToDelete(gestureRecognizer:))) - deleteGestureRecognizer.delegate = self + deleteGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate deleteGestureRecognizer.delaysTouchesBegan = true self.scrollNode.view.addGestureRecognizer(deleteGestureRecognizer) self.deleteGestureRecognizer = deleteGestureRecognizer diff --git a/submodules/CalendarMessageScreen/Sources/CalendarMessageScreen.swift b/submodules/CalendarMessageScreen/Sources/CalendarMessageScreen.swift index 58f1bc1884..078503777c 100644 --- a/submodules/CalendarMessageScreen/Sources/CalendarMessageScreen.swift +++ b/submodules/CalendarMessageScreen/Sources/CalendarMessageScreen.swift @@ -975,7 +975,7 @@ private func monthMetadata(calendar: Calendar, for baseDate: Date, currentYear: } public final class CalendarMessageScreen: ViewController { - private final class Node: ViewControllerTracingNode, UIScrollViewDelegate { + private final class Node: ViewControllerTracingNode, ASScrollViewDelegate { struct SelectionState { var dayRange: ClosedRange? } @@ -1173,7 +1173,7 @@ public final class CalendarMessageScreen: ViewController { self.backgroundColor = self.presentationData.theme.list.plainBackgroundColor - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.contextGestureContainerNode) self.contextGestureContainerNode.view.addSubview(self.scrollView) diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 7ab58a8099..b1b1ab0bc1 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -44,7 +44,7 @@ public enum ChatListContainerNodeFilter: Equatable { } } -public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { +public final class ChatListContainerNode: ASDisplayNode, ASGestureRecognizerDelegate { private let context: AccountContext private weak var controller: ChatListControllerImpl? let location: ChatListControllerLocation @@ -481,7 +481,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele return [.rightEdge] } }, edgeWidth: .widthMultiplier(factor: 1.0 / 6.0, min: 22.0, max: 80.0)) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.panRecognizer = panRecognizer @@ -1009,7 +1009,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele } } -final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate { +final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate { private let context: AccountContext private let location: ChatListControllerLocation private var presentationData: PresentationData @@ -1199,7 +1199,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate { let directions: InteractiveTransitionGestureRecognizerDirections = [.rightCenter] return directions }, edgeWidth: .widthMultiplier(factor: 1.0 / 6.0, min: 22.0, max: 80.0)) - inlineContentPanRecognizer.delegate = self + inlineContentPanRecognizer.delegate = self.wrappedGestureRecognizerDelegate inlineContentPanRecognizer.delaysTouchesBegan = false inlineContentPanRecognizer.cancelsTouchesInView = true self.inlineContentPanRecognizer = inlineContentPanRecognizer diff --git a/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift b/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift index 89a88281c9..7c02fe7f39 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchMediaNode.swift @@ -594,7 +594,7 @@ private enum ItemsLayout { } } -final class ChatListSearchMediaNode: ASDisplayNode, UIScrollViewDelegate { +final class ChatListSearchMediaNode: ASDisplayNode, ASScrollViewDelegate { enum ContentType { case photoOrVideo case gifs @@ -664,7 +664,7 @@ final class ChatListSearchMediaNode: ASDisplayNode, UIScrollViewDelegate { self.scrollNode.view.contentInsetAdjustmentBehavior = .never } self.scrollNode.view.scrollsToTop = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.scrollNode) self.addSubnode(self.floatingHeaderNode) diff --git a/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift index f3747fb993..831898d52d 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift @@ -142,7 +142,7 @@ private final class ChatListSearchPendingPane { } } -final class ChatListSearchPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { +final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegate { private let context: AccountContext private let animationCache: AnimationCache private let animationRenderer: MultiAnimationRenderer @@ -234,7 +234,7 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, UIGestureRecognizerD } return [.left, .right] }) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.view.addGestureRecognizer(panRecognizer) diff --git a/submodules/ChatListUI/Sources/Node/ChatListArchiveInfoItem.swift b/submodules/ChatListUI/Sources/Node/ChatListArchiveInfoItem.swift index 0582c8859b..4dda5fe57c 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListArchiveInfoItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListArchiveInfoItem.swift @@ -156,7 +156,7 @@ private final class InfoPageNode: ASDisplayNode { } } -class ChatListArchiveInfoItemNode: ListViewItemNode, UIScrollViewDelegate { +class ChatListArchiveInfoItemNode: ListViewItemNode, ASScrollViewDelegate { private var item: ChatListArchiveInfoItem? private let scrollNode: ASScrollNode @@ -187,7 +187,7 @@ class ChatListArchiveInfoItemNode: ListViewItemNode, UIScrollViewDelegate { self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.isPagingEnabled = true - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.pageControlNode.setPage(0.0) } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index eaa684efb9..0da52b7977 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -1808,11 +1808,8 @@ public final class ChatListNode: ListView { self.present?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.ChatList_BirthdayInSettingsInfo, timeout: 5.0, customUndoText: nil), elevatedLayout: false, action: { _ in return true })) - case let .birthdayPremiumGift(peers, _): - let peerIds = peers.sorted { lhs, rhs in - return lhs.id < rhs.id - } - let _ = ApplicationSpecificNotice.setDismissedBirthdayPremiumGifts(accountManager: self.context.sharedContext.accountManager, values: peerIds.map { $0.id.toInt64() }).start() + case .birthdayPremiumGift: + let _ = self.context.engine.notices.dismissServerProvidedSuggestion(suggestion: .todayBirthdays).startStandalone() self.present?(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.ChatList_PremiumGiftInSettingsInfo, timeout: 5.0, customUndoText: nil), elevatedLayout: false, action: { _ in return true })) @@ -1909,13 +1906,13 @@ public final class ChatListNode: ListView { let suggestedChatListNoticeSignal: Signal = combineLatest( context.engine.notices.getServerProvidedSuggestions(), + context.engine.notices.getServerDismissedSuggestions(), twoStepData, newSessionReviews(postbox: context.account.postbox), context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Birthday(id: context.account.peerId)), - context.account.stateManager.contactBirthdays, - ApplicationSpecificNotice.dismissedBirthdayPremiumGifts(accountManager: context.sharedContext.accountManager) + context.account.stateManager.contactBirthdays ) - |> mapToSignal { suggestions, configuration, newSessionReviews, birthday, birthdays, dismissedBirthdayPeerIds -> Signal in + |> mapToSignal { suggestions, dismissedSuggestions, configuration, newSessionReviews, birthday, birthdays -> Signal in if let newSessionReview = newSessionReviews.first { return .single(.reviewLogin(newSessionReview: newSessionReview, totalCount: newSessionReviews.count)) } @@ -1945,6 +1942,10 @@ public final class ChatListNode: ListView { return lhs < rhs } + if dismissedSuggestions.contains(.todayBirthdays) { + todayBirthdayPeerIds = [] + } + if suggestions.contains(.setupBirthday) && birthday == nil { return .single(.setupBirthday) } else if suggestions.contains(.xmasPremiumGift) { @@ -1989,7 +1990,7 @@ public final class ChatListNode: ListView { return nil } } - } else if !todayBirthdayPeerIds.isEmpty && todayBirthdayPeerIds.map({ $0.toInt64() }) != dismissedBirthdayPeerIds { + } else if !todayBirthdayPeerIds.isEmpty { return context.engine.data.get( EngineDataMap(todayBirthdayPeerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:))) ) diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift index 93563c76f3..397c6657fd 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -155,7 +155,7 @@ private final class ActionSheetItemNode: ASDisplayNode { } } -final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private let sourceSendButton: ASDisplayNode @@ -382,7 +382,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.delaysContentTouches = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.alwaysBounceVertical = true if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { self.scrollNode.view.contentInsetAdjustmentBehavior = .never diff --git a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift index 1b70a3a8b6..d623afc580 100644 --- a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift +++ b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift @@ -387,7 +387,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent private static let readIconImage: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/MenuReadIcon"), color: .white)?.withRenderingMode(.alwaysTemplate) private static let reactionIconImage: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/MenuReactionIcon"), color: .white)?.withRenderingMode(.alwaysTemplate) - private final class ReactionsTabNode: ASDisplayNode, UIScrollViewDelegate { + private final class ReactionsTabNode: ASDisplayNode, ASScrollViewDelegate { private final class ItemNode: HighlightTrackingButtonNode { let context: AccountContext let displayReadTimestamps: Bool @@ -868,7 +868,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent super.init() self.addSubnode(self.scrollNode) - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.clipsToBounds = true @@ -1101,7 +1101,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent } } - final class ItemsNode: ASDisplayNode, ContextControllerItemsNode, UIGestureRecognizerDelegate { + final class ItemsNode: ASDisplayNode, ContextControllerItemsNode, ASGestureRecognizerDelegate { private let context: AccountContext private let displayReadTimestamps: Bool private let availableReactions: AvailableReactions? @@ -1266,7 +1266,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent } return [.left, .right] }) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(panRecognizer) } diff --git a/submodules/ContactListUI/Sources/ContactsControllerNode.swift b/submodules/ContactListUI/Sources/ContactsControllerNode.swift index b72c8501fb..a56ad6c048 100644 --- a/submodules/ContactListUI/Sources/ContactsControllerNode.swift +++ b/submodules/ContactListUI/Sources/ContactsControllerNode.swift @@ -44,7 +44,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent } } -final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate { +final class ContactsControllerNode: ASDisplayNode, ASGestureRecognizerDelegate { let contactListNode: ContactListNode private let context: AccountContext diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index ba800ab20b..6917289507 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -247,7 +247,7 @@ func convertFrame(_ frame: CGRect, from fromView: UIView, to toView: UIView) -> return targetWindowFrame } -final class ContextControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class ContextControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private weak var controller: ContextController? private var presentationData: PresentationData @@ -408,7 +408,7 @@ final class ContextControllerNode: ViewControllerTracingNode, UIScrollViewDelega self?.updateLayout() } - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate if blurBackground { self.view.addSubview(self.effectView) diff --git a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift index 2e6c0cece5..ea8a437b13 100644 --- a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift @@ -1101,7 +1101,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode { case additional } - final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { + final class NavigationContainer: ASDisplayNode, ASGestureRecognizerDelegate { let backgroundNode: NavigationBackgroundNode let parentShadowNode: ASImageNode @@ -1136,7 +1136,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode { let _ = strongSelf return [.right] }) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(panRecognizer) self.panRecognizer = panRecognizer } diff --git a/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift b/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift index ef5b52afd9..20539c1359 100644 --- a/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift @@ -110,7 +110,7 @@ private extension ContextControllerTakeViewInfo.ContainingItem { } } -final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextControllerPresentationNode, UIScrollViewDelegate { +final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextControllerPresentationNode, ASScrollViewDelegate { enum ContentSource { case location(ContextLocationContentSource) case reference(ContextReferenceContentSource) @@ -339,7 +339,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo //self.addSubnode(self.contentRectDebugNode) #endif - self.scroller.delegate = self + self.scroller.delegate = self.wrappedScrollViewDelegate self.dismissTapNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dismissTapGesture(_:)))) diff --git a/submodules/ContextUI/Sources/PinchController.swift b/submodules/ContextUI/Sources/PinchController.swift index 9543ec328e..17082739c1 100644 --- a/submodules/ContextUI/Sources/PinchController.swift +++ b/submodules/ContextUI/Sources/PinchController.swift @@ -133,7 +133,7 @@ private func cancelContextGestures(view: UIView) { } } -public final class PinchSourceContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { +public final class PinchSourceContainerNode: ASDisplayNode, ASGestureRecognizerDelegate { public let contentNode: ASDisplayNode public var contentRect: CGRect = CGRect() private(set) var naturalContentFrame: CGRect? diff --git a/submodules/Display/Source/ActionSheetControllerNode.swift b/submodules/Display/Source/ActionSheetControllerNode.swift index 80d94f3ddd..c27cc399f8 100644 --- a/submodules/Display/Source/ActionSheetControllerNode.swift +++ b/submodules/Display/Source/ActionSheetControllerNode.swift @@ -4,7 +4,7 @@ import SwiftSignalKit private let containerInsets = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0) -final class ActionSheetControllerNode: ASDisplayNode, UIScrollViewDelegate { +final class ActionSheetControllerNode: ASDisplayNode, ASScrollViewDelegate { var theme: ActionSheetControllerTheme { didSet { self.itemGroupsContainerNode.theme = self.theme @@ -64,7 +64,7 @@ final class ActionSheetControllerNode: ASDisplayNode, UIScrollViewDelegate { super.init() - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.scrollNode) diff --git a/submodules/Display/Source/ActionSheetItemGroupNode.swift b/submodules/Display/Source/ActionSheetItemGroupNode.swift index 46a8f81fc7..cee228963b 100644 --- a/submodules/Display/Source/ActionSheetItemGroupNode.swift +++ b/submodules/Display/Source/ActionSheetItemGroupNode.swift @@ -1,7 +1,7 @@ import UIKit import AsyncDisplayKit -final class ActionSheetItemGroupNode: ASDisplayNode, UIScrollViewDelegate { +final class ActionSheetItemGroupNode: ASDisplayNode, ASScrollViewDelegate { private let theme: ActionSheetControllerTheme private let centerDimView: UIImageView @@ -60,7 +60,7 @@ final class ActionSheetItemGroupNode: ASDisplayNode, UIScrollViewDelegate { self.view.addSubview(self.bottomDimView) self.view.addSubview(self.trailingDimView) - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.clippingNode.view.addSubview(self.backgroundEffectView) self.clippingNode.addSubnode(self.scrollNode) diff --git a/submodules/Display/Source/GestureRecognizerDelegate.swift b/submodules/Display/Source/GestureRecognizerDelegate.swift new file mode 100644 index 0000000000..93505d1711 --- /dev/null +++ b/submodules/Display/Source/GestureRecognizerDelegate.swift @@ -0,0 +1,213 @@ +import Foundation +import UIKit +import ObjectiveC +import AsyncDisplayKit + +private var ASGestureRecognizerDelegateKey: Int? +private var ASScrollViewDelegateKey: Int? + +private final class WrappedGestureRecognizerDelegate: NSObject, UIGestureRecognizerDelegate { + private weak var target: ASGestureRecognizerDelegate? + + init(target: ASGestureRecognizerDelegate) { + self.target = target + + super.init() + } + + func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + guard let target = self.target else { + return true + } + return target.gestureRecognizerShouldBegin?(gestureRecognizer) ?? true + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + guard let target = self.target else { + return false + } + return target.gestureRecognizer?(gestureRecognizer, shouldRecognizeSimultaneouslyWith: otherGestureRecognizer) ?? false + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool { + guard let target = self.target else { + return false + } + return target.gestureRecognizer?(gestureRecognizer, shouldRequireFailureOf: otherGestureRecognizer) ?? false + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { + guard let target = self.target else { + return false + } + return target.gestureRecognizer?(gestureRecognizer, shouldBeRequiredToFailBy: otherGestureRecognizer) ?? false + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { + guard let target = self.target else { + return true + } + return target.gestureRecognizer?(gestureRecognizer, shouldReceive: touch) ?? true + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive press: UIPress) -> Bool { + guard let target = self.target else { + return true + } + return target.gestureRecognizer?(gestureRecognizer, shouldReceive: press) ?? true + } + + @available(iOS 13.4, *) + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive event: UIEvent) -> Bool { + guard let target = self.target else { + return true + } + return target.gestureRecognizer?(gestureRecognizer, shouldReceive: event) ?? true + } +} + +public extension ASGestureRecognizerDelegate { + var wrappedGestureRecognizerDelegate: UIGestureRecognizerDelegate { + if let delegate = objc_getAssociatedObject(self, &ASGestureRecognizerDelegateKey) as? WrappedGestureRecognizerDelegate { + return delegate + } else { + let delegate = WrappedGestureRecognizerDelegate(target: self) + objc_setAssociatedObject(self, &ASGestureRecognizerDelegateKey, delegate, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + return delegate + } + } +} + +private final class WrappedScrollViewDelegate: NSObject, UIScrollViewDelegate, UIScrollViewAccessibilityDelegate { + private weak var target: ASScrollViewDelegate? + + init(target: ASScrollViewDelegate) { + self.target = target + + super.init() + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + guard let target = self.target else { + return + } + target.scrollViewDidScroll?(scrollView) + } + + func scrollViewDidZoom(_ scrollView: UIScrollView) { + guard let target = self.target else { + return + } + target.scrollViewDidZoom?(scrollView) + } + + func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + guard let target = self.target else { + return + } + target.scrollViewWillBeginDragging?(scrollView) + } + + func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { + guard let target = self.target else { + return + } + target.scrollViewWillEndDragging?(scrollView, withVelocity: velocity, targetContentOffset: targetContentOffset) + } + + func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + guard let target = self.target else { + return + } + target.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate) + } + + func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) { + guard let target = self.target else { + return + } + target.scrollViewWillBeginDecelerating?(scrollView) + } + + func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + guard let target = self.target else { + return + } + target.scrollViewDidEndDecelerating?(scrollView) + } + + func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { + guard let target = self.target else { + return + } + target.scrollViewDidEndScrollingAnimation?(scrollView) + } + + func viewForZooming(in scrollView: UIScrollView) -> UIView? { + guard let target = self.target else { + return nil + } + return target.viewForZooming?(in: scrollView) + } + + func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) { + guard let target = self.target else { + return + } + target.scrollViewWillBeginZooming?(scrollView, with: view) + } + + func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) { + guard let target = self.target else { + return + } + target.scrollViewDidEndZooming?(scrollView, with: view, atScale: scale) + } + + func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { + guard let target = self.target else { + return true + } + return target.scrollViewShouldScroll?(toTop: scrollView) ?? true + } + + func scrollViewDidScrollToTop(_ scrollView: UIScrollView) { + guard let target = self.target else { + return + } + target.scrollViewDidScroll?(toTop: scrollView) + } + + func scrollViewDidChangeAdjustedContentInset(_ scrollView: UIScrollView) { + guard let target = self.target else { + return + } + target.scrollViewDidChangeAdjustedContentInset?(scrollView) + } + + func accessibilityScrollStatus(for scrollView: UIScrollView) -> String? { + guard let target = self.target else { + return nil + } + return target.accessibilityScrollStatus?(for: scrollView) + } + + func accessibilityAttributedScrollStatus(for scrollView: UIScrollView) -> NSAttributedString? { + guard let target = self.target else { + return nil + } + return target.accessibilityAttributedScrollStatus?(for: scrollView) + } +} + +public extension ASScrollViewDelegate { + var wrappedScrollViewDelegate: UIScrollViewDelegate & UIScrollViewAccessibilityDelegate { + if let delegate = objc_getAssociatedObject(self, &ASScrollViewDelegateKey) as? WrappedScrollViewDelegate { + return delegate + } else { + let delegate = WrappedScrollViewDelegate(target: self) + objc_setAssociatedObject(self, &ASScrollViewDelegateKey, delegate, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + return delegate + } + } +} diff --git a/submodules/Display/Source/GridNode.swift b/submodules/Display/Source/GridNode.swift index 6235e8d5b1..568bfb5257 100644 --- a/submodules/Display/Source/GridNode.swift +++ b/submodules/Display/Source/GridNode.swift @@ -207,7 +207,7 @@ private struct WrappedGridItemNode: Hashable { } } -open class GridNode: GridNodeScroller, UIScrollViewDelegate { +open class GridNode: GridNodeScroller, ASScrollViewDelegate { public private(set) var gridLayout = GridNodeLayout(size: CGSize(), insets: UIEdgeInsets(), preloadSize: 0.0, type: .fixed(itemSize: CGSize(), fillWidth: nil, lineSpacing: 0.0, itemSpacing: nil)) private var firstIndexInSectionOffset: Int = 0 public private(set) var items: [GridItem] = [] @@ -257,7 +257,7 @@ open class GridNode: GridNodeScroller, UIScrollViewDelegate { self.scrollView.showsVerticalScrollIndicator = false self.scrollView.showsHorizontalScrollIndicator = false self.scrollView.scrollsToTop = false - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate } required public init?(coder aDecoder: NSCoder) { diff --git a/submodules/Display/Source/GridNodeScroller.swift b/submodules/Display/Source/GridNodeScroller.swift index dc884cf79c..de5496720a 100644 --- a/submodules/Display/Source/GridNodeScroller.swift +++ b/submodules/Display/Source/GridNodeScroller.swift @@ -32,7 +32,7 @@ public class GridNodeScrollerView: UIScrollView { } } -open class GridNodeScroller: ASDisplayNode, UIGestureRecognizerDelegate { +open class GridNodeScroller: ASDisplayNode, ASGestureRecognizerDelegate { public var scrollView: UIScrollView { return self.view as! UIScrollView } diff --git a/submodules/Display/Source/ListView.swift b/submodules/Display/Source/ListView.swift index 515e7966d1..facaad0685 100644 --- a/submodules/Display/Source/ListView.swift +++ b/submodules/Display/Source/ListView.swift @@ -149,7 +149,7 @@ private func cancelContextGestures(view: UIView) { } } -open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGestureRecognizerDelegate { +open class ListView: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { public struct ScrollingIndicatorState { public struct Item { public var index: Int @@ -494,13 +494,13 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture self.scroller.alwaysBounceVertical = true self.scroller.contentSize = CGSize(width: 0.0, height: infiniteScrollSize * 2.0) self.scroller.isHidden = true - self.scroller.delegate = self + self.scroller.delegate = self.wrappedScrollViewDelegate self.view.addSubview(self.scroller) self.scroller.panGestureRecognizer.cancelsTouchesInView = true self.view.addGestureRecognizer(self.scroller.panGestureRecognizer) let trackingRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.trackingGesture(_:))) - trackingRecognizer.delegate = self + trackingRecognizer.delegate = self.wrappedGestureRecognizerDelegate trackingRecognizer.cancelsTouchesInView = false self.view.addGestureRecognizer(trackingRecognizer) @@ -534,7 +534,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))) tapGestureRecognizer.isEnabled = false - tapGestureRecognizer.delegate = self + tapGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(tapGestureRecognizer) self.tapGestureRecognizer = tapGestureRecognizer diff --git a/submodules/Display/Source/Navigation/NavigationContainer.swift b/submodules/Display/Source/Navigation/NavigationContainer.swift index 516639626d..c07d352f34 100644 --- a/submodules/Display/Source/Navigation/NavigationContainer.swift +++ b/submodules/Display/Source/Navigation/NavigationContainer.swift @@ -3,7 +3,7 @@ import UIKit import AsyncDisplayKit import SwiftSignalKit -public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelegate { +public final class NavigationContainer: ASDisplayNode, ASGestureRecognizerDelegate { private final class Child { let value: ViewController var layout: ContainerViewLayout @@ -151,7 +151,7 @@ public final class NavigationContainer: ASDisplayNode, UIGestureRecognizerDelega if #available(iOS 13.4, *) { panRecognizer.allowedScrollTypesMask = .continuous } - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.panRecognizer = panRecognizer diff --git a/submodules/Display/Source/Navigation/NavigationModalContainer.swift b/submodules/Display/Source/Navigation/NavigationModalContainer.swift index 59be617288..1e7603dcbf 100644 --- a/submodules/Display/Source/Navigation/NavigationModalContainer.swift +++ b/submodules/Display/Source/Navigation/NavigationModalContainer.swift @@ -4,7 +4,7 @@ import AsyncDisplayKit import SwiftSignalKit import UIKitRuntimeUtils -final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +final class NavigationModalContainer: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private var theme: NavigationControllerTheme let isFlat: Bool @@ -89,7 +89,7 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes } self.scrollNode.view.delaysContentTouches = false self.scrollNode.view.clipsToBounds = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate let panRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: #selector(self.panGesture(_:)), allowedDirections: { [weak self] _ in guard let strongSelf = self, !strongSelf.isDismissed else { @@ -109,7 +109,7 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes panRecognizer.isEnabled = false } } - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true if !self.isFlat { @@ -312,7 +312,7 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { } - func scrollViewShouldScrollToTop(_ scrollView: UIScrollView) -> Bool { + func scrollViewShouldScroll(toTop scrollView: UIScrollView) -> Bool { return false } diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 5b625117ac..fbd9c66ac3 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -123,7 +123,7 @@ class CaptionScrollWrapperNode: ASDisplayNode { -final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScrollViewDelegate { +final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private var theme: PresentationTheme @@ -638,7 +638,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll override func didLoad() { super.didLoad() - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.showsVerticalScrollIndicator = false let backwardLongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.seekBackwardLongPress(_:))) diff --git a/submodules/GalleryUI/Sources/GalleryControllerNode.swift b/submodules/GalleryUI/Sources/GalleryControllerNode.swift index e943566b24..48ca1b5f83 100644 --- a/submodules/GalleryUI/Sources/GalleryControllerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryControllerNode.swift @@ -6,7 +6,7 @@ import Postbox import SwipeToDismissGesture import AccountContext -open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { public var statusBar: StatusBar? public var navigationBar: NavigationBar? { didSet { @@ -143,7 +143,7 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture self.scrollView.alwaysBounceHorizontal = false self.scrollView.alwaysBounceVertical = false self.scrollView.clipsToBounds = false - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.scrollView.scrollsToTop = false self.view.addSubview(self.scrollView) diff --git a/submodules/GalleryUI/Sources/GalleryPagerNode.swift b/submodules/GalleryUI/Sources/GalleryPagerNode.swift index aafe2f0409..1ee1b3af55 100644 --- a/submodules/GalleryUI/Sources/GalleryPagerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryPagerNode.swift @@ -76,7 +76,7 @@ public struct GalleryPagerTransaction { } } -public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +public final class GalleryPagerNode: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private let pageGap: CGFloat private let disableTapNavigation: Bool @@ -142,7 +142,7 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest self.scrollView.alwaysBounceHorizontal = !pageGap.isZero self.scrollView.bounces = !pageGap.isZero self.scrollView.isPagingEnabled = true - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.scrollView.clipsToBounds = false self.scrollView.scrollsToTop = false self.scrollView.delaysContentTouches = false @@ -167,7 +167,7 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest super.didLoad() let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:))) - recognizer.delegate = self + recognizer.delegate = self.wrappedGestureRecognizerDelegate self.tapRecognizer = recognizer recognizer.tapActionAtPoint = { [weak self] point in guard let strongSelf = self, strongSelf.pagingEnabled else { diff --git a/submodules/GalleryUI/Sources/GalleryThumbnailContainerNode.swift b/submodules/GalleryUI/Sources/GalleryThumbnailContainerNode.swift index a381a3c3a5..fa8806d70b 100644 --- a/submodules/GalleryUI/Sources/GalleryThumbnailContainerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryThumbnailContainerNode.swift @@ -48,7 +48,7 @@ private final class GalleryThumbnailItemNode: ASDisplayNode { } } -public final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDelegate { +public final class GalleryThumbnailContainerNode: ASDisplayNode, ASScrollViewDelegate { public let groupId: Int64 private let scrollNode: ASScrollNode @@ -69,7 +69,7 @@ public final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDel super.init() - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.showsVerticalScrollIndicator = false diff --git a/submodules/GalleryUI/Sources/ZoomableContentGalleryItemNode.swift b/submodules/GalleryUI/Sources/ZoomableContentGalleryItemNode.swift index 7d42ddcf65..fbcf016de4 100644 --- a/submodules/GalleryUI/Sources/ZoomableContentGalleryItemNode.swift +++ b/submodules/GalleryUI/Sources/ZoomableContentGalleryItemNode.swift @@ -3,7 +3,7 @@ import UIKit import Display import AsyncDisplayKit -open class ZoomableContentGalleryItemNode: GalleryItemNode, UIScrollViewDelegate { +open class ZoomableContentGalleryItemNode: GalleryItemNode, ASScrollViewDelegate { public let scrollNode: ASScrollNode private var containerLayout: ContainerViewLayout? @@ -34,7 +34,7 @@ open class ZoomableContentGalleryItemNode: GalleryItemNode, UIScrollViewDelegate super.init() - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.clipsToBounds = false diff --git a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift index 2e0fb376bd..0d5d6c1957 100644 --- a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift +++ b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift @@ -48,7 +48,7 @@ private struct StickerPackPreviewGridTransaction { } } -final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class ImportStickerPackControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private var stickerPack: ImportStickerPack? @@ -194,7 +194,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.cancelButtonNode) diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index 407c45656f..f27a0b7f07 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -18,7 +18,7 @@ import UndoUI import ContextUI import TranslateUI -final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { +final class InstantPageControllerNode: ASDisplayNode, ASScrollViewDelegate { private weak var controller: InstantPageController? private let context: AccountContext private var settings: InstantPagePresentationSettings? @@ -137,7 +137,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { self.scrollNode.addSubnode(self.scrollNodeFooter) self.addSubnode(self.navigationBar) self.scrollNode.view.delaysContentTouches = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.navigationBar.back = navigateBack self.navigationBar.share = { [weak self] in diff --git a/submodules/InstantPageUI/Sources/InstantPageReferenceControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageReferenceControllerNode.swift index 4f284bfcd5..9ef8a460f5 100644 --- a/submodules/InstantPageUI/Sources/InstantPageReferenceControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageReferenceControllerNode.swift @@ -10,7 +10,7 @@ import ShareController import OpenInExternalAppUI import TelegramUIPreferences -class InstantPageReferenceControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +class InstantPageReferenceControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private let sourceLocation: InstantPageSourceLocation private let theme: InstantPageTheme @@ -84,7 +84,7 @@ class InstantPageReferenceControllerNode: ViewControllerTracingNode, UIScrollVie self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.contentBackgroundNode) diff --git a/submodules/InstantPageUI/Sources/InstantPageSlideshowItemNode.swift b/submodules/InstantPageUI/Sources/InstantPageSlideshowItemNode.swift index b584d5b1b6..5551d7343b 100644 --- a/submodules/InstantPageUI/Sources/InstantPageSlideshowItemNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageSlideshowItemNode.swift @@ -63,7 +63,7 @@ private final class InstantPageSlideshowItemNode: ASDisplayNode { } } -private final class InstantPageSlideshowPagerNode: ASDisplayNode, UIScrollViewDelegate { +private final class InstantPageSlideshowPagerNode: ASDisplayNode, ASScrollViewDelegate { private let context: AccountContext private let sourceLocation: InstantPageSourceLocation private let theme: InstantPageTheme @@ -123,7 +123,7 @@ private final class InstantPageSlideshowPagerNode: ASDisplayNode, UIScrollViewDe self.scrollView.alwaysBounceHorizontal = !pageGap.isZero self.scrollView.bounces = !pageGap.isZero self.scrollView.isPagingEnabled = true - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.scrollView.clipsToBounds = false self.scrollView.scrollsToTop = false self.view.addSubview(self.scrollView) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift b/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift index 0f3c3b8d08..9c5b0ae132 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift @@ -247,7 +247,7 @@ public final class InviteLinkInviteController: ViewController { self.controllerNode.containerLayoutUpdated(layout, transition: transition) } - class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: InviteLinkInviteController? private let context: AccountContext @@ -574,7 +574,7 @@ public final class InviteLinkInviteController: ViewController { self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) let panRecognizer = DirectionalPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.view.addGestureRecognizer(panRecognizer) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index dcbe0ca9dc..f69aaf3115 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -380,7 +380,7 @@ public final class InviteLinkViewController: ViewController { self.controllerNode.containerLayoutUpdated(layout, transition: transition) } - class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: InviteLinkViewController? private let context: AccountContext @@ -855,7 +855,7 @@ public final class InviteLinkViewController: ViewController { self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) let panRecognizer = DirectionalPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.view.addGestureRecognizer(panRecognizer) diff --git a/submodules/ItemListUI/Sources/Items/ItemListEditableItem.swift b/submodules/ItemListUI/Sources/Items/ItemListEditableItem.swift index f0811c1e3c..3ba05e2b4c 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListEditableItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListEditableItem.swift @@ -58,7 +58,7 @@ public final class ItemListRevealOptionsGestureRecognizer: UIPanGestureRecognize } } -open class ItemListRevealOptionsItemNode: ListViewItemNode, UIGestureRecognizerDelegate { +open class ItemListRevealOptionsItemNode: ListViewItemNode, ASGestureRecognizerDelegate { private var validLayout: (CGSize, CGFloat, CGFloat)? private var leftRevealNode: ItemListRevealOptionsNode? @@ -96,13 +96,13 @@ open class ItemListRevealOptionsItemNode: ListViewItemNode, UIGestureRecognizerD let recognizer = ItemListRevealOptionsGestureRecognizer(target: self, action: #selector(self.revealGesture(_:))) self.recognizer = recognizer - recognizer.delegate = self + recognizer.delegate = self.wrappedGestureRecognizerDelegate recognizer.allowAnyDirection = self.allowAnyDirection self.view.addGestureRecognizer(recognizer) let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.revealTapGesture(_:))) self.tapRecognizer = tapRecognizer - tapRecognizer.delegate = self + tapRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(tapRecognizer) self.view.disablesInteractiveTransitionGestureRecognizer = self.allowAnyDirection diff --git a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewControllerNode.swift b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewControllerNode.swift index ab465684b6..072a48a65d 100644 --- a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewControllerNode.swift +++ b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewControllerNode.swift @@ -34,7 +34,7 @@ struct JoinLinkPreviewData { let isJoined: Bool } -final class JoinLinkPreviewControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class JoinLinkPreviewControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData @@ -110,7 +110,7 @@ final class JoinLinkPreviewControllerNode: ViewControllerTracingNode, UIScrollVi self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside) diff --git a/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewControllerNode.swift b/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewControllerNode.swift index eabbb8e37a..95fd3d3982 100644 --- a/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewControllerNode.swift +++ b/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewControllerNode.swift @@ -9,7 +9,7 @@ import ActivityIndicator import AccountContext import ShareController -final class LanguageLinkPreviewControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class LanguageLinkPreviewControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData @@ -121,7 +121,7 @@ final class LanguageLinkPreviewControllerNode: ViewControllerTracingNode, UIScro self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.cancelButtonNode.setTitle(self.presentationData.strings.Common_Cancel, with: Font.medium(20.0), with: self.presentationData.theme.actionSheet.standardActionTextColor, for: .normal) diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorSliderView.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorSliderView.h index 859a57eb52..415c0b7f4b 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorSliderView.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorSliderView.h @@ -19,6 +19,7 @@ @property (nonatomic, assign) bool displayEdges; @property (nonatomic, assign) bool useLinesForPositions; +@property (nonatomic, assign) bool markPositions; @property (nonatomic, readonly) bool knobStartedDragging; diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorSliderView.m b/submodules/LegacyComponents/Sources/TGPhotoEditorSliderView.m index 5a2e49f5c9..5988d1e908 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorSliderView.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorSliderView.m @@ -42,6 +42,7 @@ const CGFloat TGPhotoEditorSliderViewInternalMargin = 7.0f; _value = _startValue; _dotSize = 10.5f; _minimumUndottedValue = -1; + _markPositions = true; _lineSize = TGPhotoEditorSliderViewLineSize; _knobPadding = TGPhotoEditorSliderViewInternalMargin; @@ -214,6 +215,12 @@ const CGFloat TGPhotoEditorSliderViewInternalMargin = 7.0f; { for (NSInteger i = 0; i < self.positionsCount; i++) { + if (!self.markPositions) { + if (i != 0 && i != self.positionsCount - 1) { + continue; + } + } + if (self.useLinesForPositions) { CGSize lineSize = CGSizeMake(4.0, 12.0); CGRect lineRect = CGRectMake(margin - lineSize.width / 2.0f + totalLength / (self.positionsCount - 1) * i, (sideLength - lineSize.height) / 2, lineSize.width, lineSize.height); diff --git a/submodules/LocationUI/Sources/LocationDistancePickerScreen.swift b/submodules/LocationUI/Sources/LocationDistancePickerScreen.swift index 6403ddf26b..29dac3d2cb 100644 --- a/submodules/LocationUI/Sources/LocationDistancePickerScreen.swift +++ b/submodules/LocationUI/Sources/LocationDistancePickerScreen.swift @@ -169,7 +169,7 @@ private var smallUnitValues: [Int32] = { return values }() -class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPickerViewDataSource, UIPickerViewDelegate { +class LocationDistancePickerScreenNode: ViewControllerTracingNode, ASScrollViewDelegate, UIPickerViewDataSource, UIPickerViewDelegate { private let context: AccountContext private let controllerStyle: LocationDistancePickerScreenStyle private var presentationData: PresentationData @@ -277,7 +277,7 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.backgroundNode) diff --git a/submodules/MediaPickerUI/Sources/MediaGroupsContextMenuContent.swift b/submodules/MediaPickerUI/Sources/MediaGroupsContextMenuContent.swift index 25838debc9..741427fc78 100644 --- a/submodules/MediaPickerUI/Sources/MediaGroupsContextMenuContent.swift +++ b/submodules/MediaPickerUI/Sources/MediaGroupsContextMenuContent.swift @@ -14,7 +14,7 @@ struct MediaGroupItem { } final class MediaGroupsContextMenuContent: ContextControllerItemsContent { - private final class GroupsListNode: ASDisplayNode, UIScrollViewDelegate { + private final class GroupsListNode: ASDisplayNode, ASScrollViewDelegate { private final class ItemNode: HighlightTrackingButtonNode { let context: AccountContext let highlightBackgroundNode: ASDisplayNode @@ -170,7 +170,7 @@ final class MediaGroupsContextMenuContent: ContextControllerItemsContent { super.init() self.addSubnode(self.scrollNode) - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.clipsToBounds = true } diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index fe07fa0fc0..76a89b99b0 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -210,7 +210,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { var dismissAll: () -> Void = { } - private class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + private class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { enum DisplayMode { case all case selected @@ -440,7 +440,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } else { let selectionGesture = MediaPickerGridSelectionGesture() - selectionGesture.delegate = self + selectionGesture.delegate = self.wrappedGestureRecognizerDelegate selectionGesture.began = { [weak self] in self?.controller?.cancelPanGesture() } diff --git a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift index a1c87d391d..1353609243 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift @@ -496,7 +496,7 @@ private class MessageBackgroundNode: ASDisplayNode { } } -final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +final class MediaPickerSelectedListNode: ASDisplayNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private let context: AccountContext private let persistentItems: Bool @@ -539,7 +539,7 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI self.scrollNode.view.contentInsetAdjustmentBehavior = .never } - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.panGestureRecognizer.cancelsTouchesInView = true self.scrollNode.view.showsVerticalScrollIndicator = false diff --git a/submodules/MediaPlayer/Sources/MediaPlayerScrubbingNode.swift b/submodules/MediaPlayer/Sources/MediaPlayerScrubbingNode.swift index 025c093993..ff460a79ff 100644 --- a/submodules/MediaPlayer/Sources/MediaPlayerScrubbingNode.swift +++ b/submodules/MediaPlayer/Sources/MediaPlayerScrubbingNode.swift @@ -63,7 +63,7 @@ public func parseMediaPlayerChapters(_ string: NSAttributedString) -> [MediaPlay return chapters } -private final class MediaPlayerScrubbingNodeButton: ASDisplayNode, UIGestureRecognizerDelegate { +private final class MediaPlayerScrubbingNodeButton: ASDisplayNode, ASGestureRecognizerDelegate { var beginScrubbing: (() -> Void)? var endScrubbing: ((Bool) -> Void)? var updateScrubbing: ((CGFloat, Double) -> Void)? @@ -83,7 +83,7 @@ private final class MediaPlayerScrubbingNodeButton: ASDisplayNode, UIGestureReco self.view.disablesInteractiveTransitionGestureRecognizer = true let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - gestureRecognizer.delegate = self + gestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(gestureRecognizer) } diff --git a/submodules/PassportUI/Sources/Form/FormControllerNode.swift b/submodules/PassportUI/Sources/Form/FormControllerNode.swift index cd76c108eb..d1d991c909 100644 --- a/submodules/PassportUI/Sources/Form/FormControllerNode.swift +++ b/submodules/PassportUI/Sources/Form/FormControllerNode.swift @@ -105,7 +105,7 @@ private enum FilteredItemNeighbor { case item(FormControllerItem) } -public class FormControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +public class FormControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private typealias InternalState = FormControllerInternalState typealias State = FormControllerState typealias Entry = InnerState.Entry @@ -142,7 +142,7 @@ public class FormControllerNode: ASDisplayNode, FormControllerItemNode, FormBlockItemNodeProto, UIGestureRecognizerDelegate { +class FormEditableBlockItemNode: ASDisplayNode, FormControllerItemNode, FormBlockItemNodeProto, ASGestureRecognizerDelegate { private let topSeparatorInset: FormBlockItemInset private let highlightedBackgroundNode: ASDisplayNode diff --git a/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift b/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift index 9ace2cac26..9dbb573c81 100644 --- a/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift +++ b/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift @@ -1268,7 +1268,7 @@ private final class TwoFactorDataInputTextNode: ASDisplayNode, UITextFieldDelega } } -private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { +private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, ASScrollViewDelegate { private var presentationData: PresentationData private let mode: TwoFactorDataInputMode private let action: () -> Void @@ -1818,7 +1818,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, UIS if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { self.scrollNode.view.contentInsetAdjustmentBehavior = .never } - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate } func scrollViewDidScroll(_ scrollView: UIScrollView) { diff --git a/submodules/PremiumUI/Sources/CreateGiveawayController.swift b/submodules/PremiumUI/Sources/CreateGiveawayController.swift index 846d11ad8f..9976989cf2 100644 --- a/submodules/PremiumUI/Sources/CreateGiveawayController.swift +++ b/submodules/PremiumUI/Sources/CreateGiveawayController.swift @@ -854,7 +854,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio let expiryDate = calendar.date(byAdding: .day, value: 3, to: calendar.date(from: components)!)! let expiryTime = Int32(expiryDate.timeIntervalSince1970) - let minDate = currentTime + 60 * 30 + let minDate = currentTime + 60 * 1 let maxDate = currentTime + context.userLimits.maxGiveawayPeriodSeconds let initialState: CreateGiveawayControllerState = CreateGiveawayControllerState(mode: .giveaway, subscriptions: initialSubscriptions, time: expiryTime) @@ -1099,7 +1099,9 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio let quantity: Int32 switch state.mode { case .giveaway: - purpose = .giveaway(boostPeer: peerId, additionalPeerIds: state.channels.filter { $0 != peerId }, countries: state.countries, onlyNewSubscribers: state.onlyNewEligible, showWinners: state.showWinners, prizeDescription: state.prizeDescription.isEmpty ? nil : state.prizeDescription, randomId: Int64.random(in: .min ..< .max), untilDate: state.time, currency: currency, amount: amount) + let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) + let untilDate = max(state.time, currentTime + 60) + purpose = .giveaway(boostPeer: peerId, additionalPeerIds: state.channels.filter { $0 != peerId }, countries: state.countries, onlyNewSubscribers: state.onlyNewEligible, showWinners: state.showWinners, prizeDescription: state.prizeDescription.isEmpty ? nil : state.prizeDescription, randomId: Int64.random(in: .min ..< .max), untilDate: untilDate, currency: currency, amount: amount) quantity = selectedProduct.giftOption.storeQuantity case .gift: purpose = .giftCode(peerIds: state.peers, boostPeer: peerId, currency: currency, amount: amount) diff --git a/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift b/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift index fa6b73cd81..f41ee7c974 100644 --- a/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumBoostLevelsScreen.swift @@ -1596,7 +1596,7 @@ public class PremiumBoostLevelsScreen: ViewController { case features } - final class Node: ViewControllerTracingNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { + final class Node: ViewControllerTracingNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private var presentationData: PresentationData private weak var controller: PremiumBoostLevelsScreen? @@ -1727,7 +1727,7 @@ public class PremiumBoostLevelsScreen: ViewController { super.didLoad() let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.panGestureRecognizer = panRecognizer diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 585c40707a..a91c7c5621 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -1463,6 +1463,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { var isPremium: Bool? var peer: EnginePeer? + var adsEnabled = false private var disposable: Disposable? private(set) var configuration = PremiumIntroConfiguration.defaultValue @@ -1470,6 +1471,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { private var stickersDisposable: Disposable? private var newPerksDisposable: Disposable? private var preloadDisposableSet = DisposableSet() + private var adsEnabledDisposable: Disposable? var price: String? { return self.products?.first(where: { $0.id == self.selectedProductId })?.price @@ -1491,6 +1493,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { } } + var cachedChevronImage: (UIImage, PresentationTheme)? + init( context: AccountContext, source: PremiumSource, @@ -1581,6 +1585,15 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { self.newPerks = newPerks self.updated() }) + + self.adsEnabledDisposable = (context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.AdsEnabled(id: context.account.peerId)) + |> deliverOnMainQueue).start(next: { [weak self] adsEnabled in + guard let self else { + return + } + self.adsEnabled = adsEnabled + self.updated() + }) } deinit { @@ -1588,6 +1601,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { self.preloadDisposableSet.dispose() self.stickersDisposable?.dispose() self.newPerksDisposable?.dispose() + self.adsEnabledDisposable?.dispose() } private var updatedPeerStatus: PeerEmojiStatus? @@ -1653,6 +1667,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { let optionsSection = Child(SectionGroupComponent.self) let businessSection = Child(ListSectionComponent.self) let moreBusinessSection = Child(ListSectionComponent.self) + let adsSettingsSection = Child(ListSectionComponent.self) let perksSection = Child(ListSectionComponent.self) let infoBackground = Child(RoundedRectangle.self) let infoTitle = Child(MultilineTextComponent.self) @@ -2464,6 +2479,94 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { size.height += 23.0 } + let termsFont = Font.regular(13.0) + let boldTermsFont = Font.semibold(13.0) + let italicTermsFont = Font.italic(13.0) + let boldItalicTermsFont = Font.semiboldItalic(13.0) + let monospaceTermsFont = Font.monospace(13.0) + let termsTextColor = environment.theme.list.freeTextColor + let termsMarkdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), bold: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), link: MarkdownAttributeSet(font: termsFont, textColor: environment.theme.list.itemAccentColor), linkAttribute: { contents in + return (TelegramTextAttributes.URL, contents) + }) + + let layoutAdsSettings = { + size.height += 8.0 + + var adsSettingsItems: [AnyComponentWithIdentity] = [] + adsSettingsItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent( + theme: environment.theme, + title: AnyComponent(VStack([ + AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString( + string: environment.strings.Business_DontHideAds, + font: Font.regular(presentationData.listsFontSize.baseDisplaySize), + textColor: environment.theme.list.itemPrimaryTextColor + )), + maximumNumberOfLines: 1 + ))), + ], alignment: .left, spacing: 2.0)), + accessory: .toggle(ListActionItemComponent.Toggle(style: .regular, isOn: state.adsEnabled, action: { [weak state] value in + let _ = accountContext.engine.accountData.updateAdMessagesEnabled(enabled: value).startStandalone() + state?.updated(transition: .immediate) + })), + action: nil + )))) + + let adsInfoString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Business_AdsInfo, attributes: termsMarkdownAttributes, textAlignment: .natural + )) + if state.cachedChevronImage == nil || state.cachedChevronImage?.1 !== theme { + state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Contact List/SubtitleArrow"), color: environment.theme.list.itemAccentColor)!, theme) + } + if let range = adsInfoString.string.range(of: ">"), let chevronImage = state.cachedChevronImage?.0 { + adsInfoString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: adsInfoString.string)) + } + let controller = environment.controller + let adsInfoTapActionImpl: ([NSAttributedString.Key: Any]) -> Void = { _ in + if let controller = controller() as? PremiumIntroScreen { + controller.context.sharedContext.openExternalUrl(context: controller.context, urlContext: .generic, url: environment.strings.Business_AdsInfo_URL, forceExternal: true, presentationData: controller.context.sharedContext.currentPresentationData.with({$0}), navigationController: nil, dismissInput: {}) + } + } + let adsSettingsSection = adsSettingsSection.update( + component: ListSectionComponent( + theme: environment.theme, + header: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString( + string: strings.Business_AdsTitle.uppercased(), + font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize), + textColor: environment.theme.list.freeTextColor + )), + maximumNumberOfLines: 0 + )), + footer: AnyComponent(MultilineTextComponent( + text: .plain(adsInfoString), + maximumNumberOfLines: 0, + highlightColor: environment.theme.list.itemAccentColor.withAlphaComponent(0.2), + highlightAction: { attributes in + if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] { + return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL) + } else { + return nil + } + }, + tapAction: { attributes, _ in + adsInfoTapActionImpl(attributes) + } + )), + items: adsSettingsItems + ), + environment: {}, + availableSize: CGSize(width: availableWidth - sideInsets, height: .greatestFiniteMagnitude), + transition: context.transition + ) + context.add(adsSettingsSection + .position(CGPoint(x: availableWidth / 2.0, y: size.height + adsSettingsSection.size.height / 2.0)) + .clipsToBounds(true) + .cornerRadius(10.0) + ) + size.height += adsSettingsSection.size.height + size.height += 23.0 + } + let copyLink = context.component.copyLink if case .emojiStatus = context.component.source { layoutPerks() @@ -2499,6 +2602,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { layoutBusinessPerks() if context.component.isPremium == true { layoutMoreBusinessPerks() + layoutAdsSettings() } } else { layoutPerks() @@ -2556,17 +2660,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { ) size.height += infoBackground.size.height size.height += 6.0 - - let termsFont = Font.regular(13.0) - let boldTermsFont = Font.semibold(13.0) - let italicTermsFont = Font.italic(13.0) - let boldItalicTermsFont = Font.semiboldItalic(13.0) - let monospaceTermsFont = Font.monospace(13.0) - let termsTextColor = environment.theme.list.freeTextColor - let termsMarkdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), bold: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), link: MarkdownAttributeSet(font: termsFont, textColor: environment.theme.list.itemAccentColor), linkAttribute: { contents in - return (TelegramTextAttributes.URL, contents) - }) - + var isGiftView = false if case let .gift(fromId, _, _, _) = context.component.source { if fromId == context.component.context.account.peerId { diff --git a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift index fda838bf36..3c5ae8f075 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift @@ -18,7 +18,7 @@ import SolidRoundedButtonNode import BlurredBackgroundComponent public class PremiumLimitsListScreen: ViewController { - final class Node: ViewControllerTracingNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { + final class Node: ViewControllerTracingNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private var presentationData: PresentationData private weak var controller: PremiumLimitsListScreen? @@ -188,7 +188,7 @@ public class PremiumLimitsListScreen: ViewController { super.didLoad() let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.panGestureRecognizer = panRecognizer diff --git a/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift b/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift index 3f596f9ca9..fdf4c6fb87 100644 --- a/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift +++ b/submodules/PremiumUI/Sources/ReplaceBoostScreen.swift @@ -294,7 +294,7 @@ private final class ReplaceBoostScreenComponent: CombinedComponent { } public class ReplaceBoostScreen: ViewController { - final class Node: ViewControllerTracingNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { + final class Node: ViewControllerTracingNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private var presentationData: PresentationData private weak var controller: ReplaceBoostScreen? @@ -345,7 +345,7 @@ public class ReplaceBoostScreen: ViewController { super.init() - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.scrollView.showsVerticalScrollIndicator = false self.containerView.clipsToBounds = true @@ -373,7 +373,7 @@ public class ReplaceBoostScreen: ViewController { super.didLoad() let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.panGestureRecognizer = panRecognizer diff --git a/submodules/PremiumUI/Sources/StickersCarouselComponent.swift b/submodules/PremiumUI/Sources/StickersCarouselComponent.swift index bedd056e90..45dfae0797 100644 --- a/submodules/PremiumUI/Sources/StickersCarouselComponent.swift +++ b/submodules/PremiumUI/Sources/StickersCarouselComponent.swift @@ -279,7 +279,7 @@ private class StickerNode: ASDisplayNode { } } -private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate { +private class StickersCarouselNode: ASDisplayNode, ASScrollViewDelegate { private let context: AccountContext private let stickers: [TelegramMediaFile] private let tapAction: () -> Void @@ -331,7 +331,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate { override func didLoad() { super.didLoad() - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.canCancelContentTouches = true diff --git a/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift b/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift index 2df200944e..124ad220c3 100644 --- a/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift +++ b/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift @@ -387,7 +387,7 @@ private final class FrameNode: ASDisplayNode { } } -private final class QrCodeScanScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { +private final class QrCodeScanScreenNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private weak var controller: QrCodeScanScreen? diff --git a/submodules/QrCodeUI/Sources/QrCodeScreen.swift b/submodules/QrCodeUI/Sources/QrCodeScreen.swift index ef4567a4a5..d4568f4d8b 100644 --- a/submodules/QrCodeUI/Sources/QrCodeScreen.swift +++ b/submodules/QrCodeUI/Sources/QrCodeScreen.swift @@ -182,7 +182,7 @@ public final class QrCodeScreen: ViewController { self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition) } - class Node: ViewControllerTracingNode, UIScrollViewDelegate { + class Node: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private let subject: QrCodeScreen.Subject private var presentationData: PresentationData @@ -279,7 +279,7 @@ public final class QrCodeScreen: ViewController { self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.backgroundNode) diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index 8fe2c49ac1..f58c6ef9b8 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -241,7 +241,7 @@ private final class TitleLabelView: UIView { } } -public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { +public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { private struct ItemLayout { var itemSize: CGFloat var visibleItemCount: Int @@ -590,7 +590,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { self.addSubnode(self.backgroundNode) - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.contentContainer) self.addSubnode(self.previewingItemContainer) diff --git a/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift b/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift index bf42171425..646addf3a6 100644 --- a/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift +++ b/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift @@ -83,7 +83,7 @@ private class SegmentedControlItemNode: HighlightTrackingButtonNode { } } -public final class SegmentedControlNode: ASDisplayNode, UIGestureRecognizerDelegate { +public final class SegmentedControlNode: ASDisplayNode, ASGestureRecognizerDelegate { private var theme: SegmentedControlTheme private var _items: [SegmentedControlItem] private var _selectedIndex: Int = 0 @@ -224,7 +224,7 @@ public final class SegmentedControlNode: ASDisplayNode, UIGestureRecognizerDeleg self.view.disablesInteractiveTransitionGestureRecognizer = true let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - gestureRecognizer.delegate = self + gestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(gestureRecognizer) self.gestureRecognizer = gestureRecognizer } diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index 6c2a35621b..5a19bd9b4a 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -29,7 +29,7 @@ private func generateMaskImage(color: UIColor) -> UIImage? { }) } -private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDelegate { +private final class BubbleSettingsControllerNode: ASDisplayNode, ASScrollViewDelegate { private let context: AccountContext private var presentationThemeSettings: PresentationThemeSettings private var presentationData: PresentationData @@ -132,7 +132,7 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.isPagingEnabled = true - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.alwaysBounceHorizontal = false } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/RecentSessionScreen.swift b/submodules/SettingsUI/Sources/Privacy and Security/RecentSessionScreen.swift index 53754a8eac..81a65b4cea 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/RecentSessionScreen.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/RecentSessionScreen.swift @@ -153,7 +153,7 @@ final class RecentSessionScreen: ViewController { } } -private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { +private class RecentSessionScreenNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private weak var controller: RecentSessionScreen? @@ -459,7 +459,7 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.backgroundNode) diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index 3d74e47806..c324b45db0 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -31,7 +31,7 @@ private func generateMaskImage(color: UIColor) -> UIImage? { }) } -private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollViewDelegate { +private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollViewDelegate { private let context: AccountContext private var presentationThemeSettings: PresentationThemeSettings private var presentationData: PresentationData @@ -173,7 +173,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.isPagingEnabled = true - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.pageControlNode.setPage(0.0) } diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index 63976f42a8..7469514140 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -31,7 +31,7 @@ private func generateMaskImage(color: UIColor) -> UIImage? { }) } -final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { +final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate { private let context: AccountContext private var previewTheme: PresentationTheme private var presentationData: PresentationData @@ -318,7 +318,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.isPagingEnabled = true - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.pageControlNode.setPage(0.0) } diff --git a/submodules/ShareController/Sources/ShareControllerNode.swift b/submodules/ShareController/Sources/ShareControllerNode.swift index c0d555f11a..693baadba3 100644 --- a/submodules/ShareController/Sources/ShareControllerNode.swift +++ b/submodules/ShareController/Sources/ShareControllerNode.swift @@ -296,7 +296,7 @@ private final class ShareContentInfoView: UIView { } } -final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private weak var controller: ShareController? private let environment: ShareControllerEnvironment private var context: ShareControllerAccountContext? @@ -624,7 +624,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.cancelButtonNode.setTitle(self.presentationData.strings.Common_Cancel, with: Font.medium(20.0), with: self.presentationData.theme.actionSheet.standardActionTextColor, for: .normal) diff --git a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift index ef208b69f4..ca308f94ff 100644 --- a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift +++ b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift @@ -338,7 +338,7 @@ public final class SparseItemGrid: ASDisplayNode { } } - private final class Viewport: ASDisplayNode, UIScrollViewDelegate { + private final class Viewport: ASDisplayNode, ASScrollViewDelegate { final class VisibleItem: SparseItemGridDisplayItem { let layer: SparseItemGridLayer? let view: SparseItemGridView? @@ -527,7 +527,7 @@ public final class SparseItemGrid: ASDisplayNode { self.anchorPoint = CGPoint() - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.view.addSubview(self.scrollView) } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift index 2771c40622..f9f5a76427 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -46,7 +46,7 @@ private struct StickerPackPreviewGridTransaction { } } -final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +final class StickerPackPreviewControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private let openShare: (() -> Void)? private var presentationData: PresentationData @@ -152,7 +152,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.cancelButtonNode) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPreviewControllerNode.swift index 66850c8f93..ff1ee5e255 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPreviewControllerNode.swift @@ -9,7 +9,7 @@ import TelegramPresentationData import AccountContext import StickerResources -final class StickerPreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { +final class StickerPreviewControllerNode: ASDisplayNode, ASScrollViewDelegate { private let context: AccountContext private let presentationData: PresentationData diff --git a/submodules/TabBarUI/Sources/TabBarNode.swift b/submodules/TabBarUI/Sources/TabBarNode.swift index 473a7f42aa..b5d14b5460 100644 --- a/submodules/TabBarUI/Sources/TabBarNode.swift +++ b/submodules/TabBarUI/Sources/TabBarNode.swift @@ -316,7 +316,7 @@ final class TabBarNodeItem { } } -class TabBarNode: ASDisplayNode, UIGestureRecognizerDelegate { +class TabBarNode: ASDisplayNode, ASGestureRecognizerDelegate { var tabBarItems: [TabBarNodeItem] = [] { didSet { self.reloadTabBarItems() @@ -389,7 +389,7 @@ class TabBarNode: ASDisplayNode, UIGestureRecognizerDelegate { super.didLoad() let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:))) - recognizer.delegate = self + recognizer.delegate = self.wrappedGestureRecognizerDelegate recognizer.tapActionAtPoint = { _ in return .keepWithSingleTap } diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 6cabdb6467..9d326df42c 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -198,8 +198,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1605510357] = { return Api.ChatAdminRights.parse_chatAdminRights($0) } dict[-219353309] = { return Api.ChatAdminWithInvites.parse_chatAdminWithInvites($0) } dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) } - dict[1153455271] = { return Api.ChatFull.parse_channelFull($0) } - dict[-908914376] = { return Api.ChatFull.parse_chatFull($0) } + dict[-1146407795] = { return Api.ChatFull.parse_channelFull($0) } + dict[640893467] = { return Api.ChatFull.parse_chatFull($0) } dict[-840897472] = { return Api.ChatInvite.parse_chatInvite($0) } dict[1516793212] = { return Api.ChatInvite.parse_chatInviteAlready($0) } dict[1634294960] = { return Api.ChatInvite.parse_chatInvitePeek($0) } @@ -857,9 +857,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1239335713] = { return Api.ShippingOption.parse_shippingOption($0) } dict[-2010155333] = { return Api.SimpleWebViewResult.parse_simpleWebViewResultUrl($0) } dict[-425595208] = { return Api.SmsJob.parse_smsJob($0) } - dict[-313293833] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) } + dict[-1611532106] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) } dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) } - dict[1035529315] = { return Api.SponsoredWebPage.parse_sponsoredWebPage($0) } dict[-884757282] = { return Api.StatsAbsValueAndPrev.parse_statsAbsValueAndPrev($0) } dict[-1237848657] = { return Api.StatsDateRangeDays.parse_statsDateRangeDays($0) } dict[-1901828938] = { return Api.StatsGraph.parse_statsGraph($0) } @@ -1932,8 +1931,6 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.SponsoredMessageReportOption: _1.serialize(buffer, boxed) - case let _1 as Api.SponsoredWebPage: - _1.serialize(buffer, boxed) case let _1 as Api.StatsAbsValueAndPrev: _1.serialize(buffer, boxed) case let _1 as Api.StatsDateRangeDays: diff --git a/submodules/TelegramApi/Sources/Api22.swift b/submodules/TelegramApi/Sources/Api22.swift index f36982ea3e..c028e604e9 100644 --- a/submodules/TelegramApi/Sources/Api22.swift +++ b/submodules/TelegramApi/Sources/Api22.swift @@ -477,31 +477,27 @@ public extension Api { } } public extension Api { - indirect enum SponsoredMessage: TypeConstructorDescription { - case sponsoredMessage(flags: Int32, randomId: Buffer, fromId: Api.Peer?, chatInvite: Api.ChatInvite?, chatInviteHash: String?, channelPost: Int32?, startParam: String?, webpage: Api.SponsoredWebPage?, app: Api.BotApp?, message: String, entities: [Api.MessageEntity]?, buttonText: String?, sponsorInfo: String?, additionalInfo: String?) + enum SponsoredMessage: TypeConstructorDescription { + case sponsoredMessage(flags: Int32, randomId: Buffer, url: String, title: String, message: String, entities: [Api.MessageEntity]?, photo: Api.Photo?, buttonText: String, sponsorInfo: String?, additionalInfo: String?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .sponsoredMessage(let flags, let randomId, let fromId, let chatInvite, let chatInviteHash, let channelPost, let startParam, let webpage, let app, let message, let entities, let buttonText, let sponsorInfo, let additionalInfo): + case .sponsoredMessage(let flags, let randomId, let url, let title, let message, let entities, let photo, let buttonText, let sponsorInfo, let additionalInfo): if boxed { - buffer.appendInt32(-313293833) + buffer.appendInt32(-1611532106) } serializeInt32(flags, buffer: buffer, boxed: false) serializeBytes(randomId, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 3) != 0 {fromId!.serialize(buffer, true)} - if Int(flags) & Int(1 << 4) != 0 {chatInvite!.serialize(buffer, true)} - if Int(flags) & Int(1 << 4) != 0 {serializeString(chatInviteHash!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 2) != 0 {serializeInt32(channelPost!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 9) != 0 {webpage!.serialize(buffer, true)} - if Int(flags) & Int(1 << 10) != 0 {app!.serialize(buffer, true)} + serializeString(url, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) serializeString(message, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) buffer.appendInt32(Int32(entities!.count)) for item in entities! { item.serialize(buffer, true) }} - if Int(flags) & Int(1 << 11) != 0 {serializeString(buttonText!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 6) != 0 {photo!.serialize(buffer, true)} + serializeString(buttonText, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 7) != 0 {serializeString(sponsorInfo!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 8) != 0 {serializeString(additionalInfo!, buffer: buffer, boxed: false)} break @@ -510,8 +506,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .sponsoredMessage(let flags, let randomId, let fromId, let chatInvite, let chatInviteHash, let channelPost, let startParam, let webpage, let app, let message, let entities, let buttonText, let sponsorInfo, let additionalInfo): - return ("sponsoredMessage", [("flags", flags as Any), ("randomId", randomId as Any), ("fromId", fromId as Any), ("chatInvite", chatInvite as Any), ("chatInviteHash", chatInviteHash as Any), ("channelPost", channelPost as Any), ("startParam", startParam as Any), ("webpage", webpage as Any), ("app", app as Any), ("message", message as Any), ("entities", entities as Any), ("buttonText", buttonText as Any), ("sponsorInfo", sponsorInfo as Any), ("additionalInfo", additionalInfo as Any)]) + case .sponsoredMessage(let flags, let randomId, let url, let title, let message, let entities, let photo, let buttonText, let sponsorInfo, let additionalInfo): + return ("sponsoredMessage", [("flags", flags as Any), ("randomId", randomId as Any), ("url", url as Any), ("title", title as Any), ("message", message as Any), ("entities", entities as Any), ("photo", photo as Any), ("buttonText", buttonText as Any), ("sponsorInfo", sponsorInfo as Any), ("additionalInfo", additionalInfo as Any)]) } } @@ -520,56 +516,38 @@ public extension Api { _1 = reader.readInt32() var _2: Buffer? _2 = parseBytes(reader) - var _3: Api.Peer? - if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer - } } - var _4: Api.ChatInvite? - if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.ChatInvite - } } + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) var _5: String? - if Int(_1!) & Int(1 << 4) != 0 {_5 = parseString(reader) } - var _6: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_6 = reader.readInt32() } - var _7: String? - if Int(_1!) & Int(1 << 0) != 0 {_7 = parseString(reader) } - var _8: Api.SponsoredWebPage? - if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { - _8 = Api.parse(reader, signature: signature) as? Api.SponsoredWebPage - } } - var _9: Api.BotApp? - if Int(_1!) & Int(1 << 10) != 0 {if let signature = reader.readInt32() { - _9 = Api.parse(reader, signature: signature) as? Api.BotApp - } } - var _10: String? - _10 = parseString(reader) - var _11: [Api.MessageEntity]? + _5 = parseString(reader) + var _6: [Api.MessageEntity]? if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) } } - var _12: String? - if Int(_1!) & Int(1 << 11) != 0 {_12 = parseString(reader) } - var _13: String? - if Int(_1!) & Int(1 << 7) != 0 {_13 = parseString(reader) } - var _14: String? - if Int(_1!) & Int(1 << 8) != 0 {_14 = parseString(reader) } + var _7: Api.Photo? + if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.Photo + } } + var _8: String? + _8 = parseString(reader) + var _9: String? + if Int(_1!) & Int(1 << 7) != 0 {_9 = parseString(reader) } + var _10: String? + if Int(_1!) & Int(1 << 8) != 0 {_10 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 3) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 9) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 10) == 0) || _9 != nil - let _c10 = _10 != nil - let _c11 = (Int(_1!) & Int(1 << 1) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 11) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 7) == 0) || _13 != nil - let _c14 = (Int(_1!) & Int(1 << 8) == 0) || _14 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 { - return Api.SponsoredMessage.sponsoredMessage(flags: _1!, randomId: _2!, fromId: _3, chatInvite: _4, chatInviteHash: _5, channelPost: _6, startParam: _7, webpage: _8, app: _9, message: _10!, entities: _11, buttonText: _12, sponsorInfo: _13, additionalInfo: _14) + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil + let _c8 = _8 != nil + let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 8) == 0) || _10 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { + return Api.SponsoredMessage.sponsoredMessage(flags: _1!, randomId: _2!, url: _3!, title: _4!, message: _5!, entities: _6, photo: _7, buttonText: _8!, sponsorInfo: _9, additionalInfo: _10) } else { return nil @@ -618,56 +596,6 @@ public extension Api { } } -public extension Api { - enum SponsoredWebPage: TypeConstructorDescription { - case sponsoredWebPage(flags: Int32, url: String, siteName: String, photo: Api.Photo?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .sponsoredWebPage(let flags, let url, let siteName, let photo): - if boxed { - buffer.appendInt32(1035529315) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(url, buffer: buffer, boxed: false) - serializeString(siteName, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .sponsoredWebPage(let flags, let url, let siteName, let photo): - return ("sponsoredWebPage", [("flags", flags as Any), ("url", url as Any), ("siteName", siteName as Any), ("photo", photo as Any)]) - } - } - - public static func parse_sponsoredWebPage(_ reader: BufferReader) -> SponsoredWebPage? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: Api.Photo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.Photo - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.SponsoredWebPage.sponsoredWebPage(flags: _1!, url: _2!, siteName: _3!, photo: _4) - } - else { - return nil - } - } - - } -} public extension Api { enum StatsAbsValueAndPrev: TypeConstructorDescription { case statsAbsValueAndPrev(current: Double, previous: Double) @@ -922,3 +850,47 @@ public extension Api { } } +public extension Api { + enum StatsGroupTopPoster: TypeConstructorDescription { + case statsGroupTopPoster(userId: Int64, messages: Int32, avgChars: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .statsGroupTopPoster(let userId, let messages, let avgChars): + if boxed { + buffer.appendInt32(-1660637285) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt32(messages, buffer: buffer, boxed: false) + serializeInt32(avgChars, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .statsGroupTopPoster(let userId, let messages, let avgChars): + return ("statsGroupTopPoster", [("userId", userId as Any), ("messages", messages as Any), ("avgChars", avgChars as Any)]) + } + } + + public static func parse_statsGroupTopPoster(_ reader: BufferReader) -> StatsGroupTopPoster? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int32? + _3 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.StatsGroupTopPoster.statsGroupTopPoster(userId: _1!, messages: _2!, avgChars: _3!) + } + else { + return nil + } + } + + } +} diff --git a/submodules/TelegramApi/Sources/Api23.swift b/submodules/TelegramApi/Sources/Api23.swift index e9dfea2cd9..330e0e1d87 100644 --- a/submodules/TelegramApi/Sources/Api23.swift +++ b/submodules/TelegramApi/Sources/Api23.swift @@ -1,47 +1,3 @@ -public extension Api { - enum StatsGroupTopPoster: TypeConstructorDescription { - case statsGroupTopPoster(userId: Int64, messages: Int32, avgChars: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .statsGroupTopPoster(let userId, let messages, let avgChars): - if boxed { - buffer.appendInt32(-1660637285) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt32(messages, buffer: buffer, boxed: false) - serializeInt32(avgChars, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .statsGroupTopPoster(let userId, let messages, let avgChars): - return ("statsGroupTopPoster", [("userId", userId as Any), ("messages", messages as Any), ("avgChars", avgChars as Any)]) - } - } - - public static func parse_statsGroupTopPoster(_ reader: BufferReader) -> StatsGroupTopPoster? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.StatsGroupTopPoster.statsGroupTopPoster(userId: _1!, messages: _2!, avgChars: _3!) - } - else { - return nil - } - } - - } -} public extension Api { enum StatsPercentValue: TypeConstructorDescription { case statsPercentValue(part: Double, total: Double) diff --git a/submodules/TelegramApi/Sources/Api35.swift b/submodules/TelegramApi/Sources/Api35.swift index 92d6afb124..3a62f61962 100644 --- a/submodules/TelegramApi/Sources/Api35.swift +++ b/submodules/TelegramApi/Sources/Api35.swift @@ -1361,6 +1361,21 @@ public extension Api.functions.account { }) } } +public extension Api.functions.account { + static func toggleSponsoredMessages(enabled: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1176919155) + enabled.serialize(buffer, true) + return (FunctionDescription(name: "account.toggleSponsoredMessages", parameters: [("enabled", String(describing: enabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } +} public extension Api.functions.account { static func toggleUsername(username: String, active: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -2770,11 +2785,12 @@ public extension Api.functions.channels { } } public extension Api.functions.channels { - static func getChannelRecommendations(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func getChannelRecommendations(flags: Int32, channel: Api.InputChannel?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-2085155433) - channel.serialize(buffer, true) - return (FunctionDescription(name: "channels.getChannelRecommendations", parameters: [("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in + buffer.appendInt32(631707458) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {channel!.serialize(buffer, true)} + return (FunctionDescription(name: "channels.getChannelRecommendations", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Chats? in let reader = BufferReader(buffer) var result: Api.messages.Chats? if let signature = reader.readInt32() { @@ -7816,12 +7832,14 @@ public extension Api.functions.messages { } } public extension Api.functions.messages { - static func setChatAvailableReactions(peer: Api.InputPeer, availableReactions: Api.ChatReactions) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func setChatAvailableReactions(flags: Int32, peer: Api.InputPeer, availableReactions: Api.ChatReactions, reactionsLimit: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-21928079) + buffer.appendInt32(1511328724) + serializeInt32(flags, buffer: buffer, boxed: false) peer.serialize(buffer, true) availableReactions.serialize(buffer, true) - return (FunctionDescription(name: "messages.setChatAvailableReactions", parameters: [("peer", String(describing: peer)), ("availableReactions", String(describing: availableReactions))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(reactionsLimit!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "messages.setChatAvailableReactions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("availableReactions", String(describing: availableReactions)), ("reactionsLimit", String(describing: reactionsLimit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in let reader = BufferReader(buffer) var result: Api.Updates? if let signature = reader.readInt32() { diff --git a/submodules/TelegramApi/Sources/Api4.swift b/submodules/TelegramApi/Sources/Api4.swift index 1548b8695b..09f23bb178 100644 --- a/submodules/TelegramApi/Sources/Api4.swift +++ b/submodules/TelegramApi/Sources/Api4.swift @@ -920,14 +920,14 @@ public extension Api { } public extension Api { enum ChatFull: TypeConstructorDescription { - case channelFull(flags: Int32, flags2: Int32, id: Int64, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int64?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int64?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?, ttlPeriod: Int32?, pendingSuggestions: [String]?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, defaultSendAs: Api.Peer?, availableReactions: Api.ChatReactions?, stories: Api.PeerStories?, wallpaper: Api.WallPaper?, boostsApplied: Int32?, boostsUnrestrict: Int32?, emojiset: Api.StickerSet?) - case chatFull(flags: Int32, id: Int64, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?, ttlPeriod: Int32?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, availableReactions: Api.ChatReactions?) + case channelFull(flags: Int32, flags2: Int32, id: Int64, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int64?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int64?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?, ttlPeriod: Int32?, pendingSuggestions: [String]?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, defaultSendAs: Api.Peer?, availableReactions: Api.ChatReactions?, reactionsLimit: Int32?, stories: Api.PeerStories?, wallpaper: Api.WallPaper?, boostsApplied: Int32?, boostsUnrestrict: Int32?, emojiset: Api.StickerSet?) + case chatFull(flags: Int32, id: Int64, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?, ttlPeriod: Int32?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, availableReactions: Api.ChatReactions?, reactionsLimit: Int32?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .channelFull(let flags, let flags2, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let defaultSendAs, let availableReactions, let stories, let wallpaper, let boostsApplied, let boostsUnrestrict, let emojiset): + case .channelFull(let flags, let flags2, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let defaultSendAs, let availableReactions, let reactionsLimit, let stories, let wallpaper, let boostsApplied, let boostsUnrestrict, let emojiset): if boxed { - buffer.appendInt32(1153455271) + buffer.appendInt32(-1146407795) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(flags2, buffer: buffer, boxed: false) @@ -978,15 +978,16 @@ public extension Api { }} if Int(flags) & Int(1 << 29) != 0 {defaultSendAs!.serialize(buffer, true)} if Int(flags) & Int(1 << 30) != 0 {availableReactions!.serialize(buffer, true)} + if Int(flags2) & Int(1 << 13) != 0 {serializeInt32(reactionsLimit!, buffer: buffer, boxed: false)} if Int(flags2) & Int(1 << 4) != 0 {stories!.serialize(buffer, true)} if Int(flags2) & Int(1 << 7) != 0 {wallpaper!.serialize(buffer, true)} if Int(flags2) & Int(1 << 8) != 0 {serializeInt32(boostsApplied!, buffer: buffer, boxed: false)} if Int(flags2) & Int(1 << 9) != 0 {serializeInt32(boostsUnrestrict!, buffer: buffer, boxed: false)} if Int(flags2) & Int(1 << 10) != 0 {emojiset!.serialize(buffer, true)} break - case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let availableReactions): + case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let availableReactions, let reactionsLimit): if boxed { - buffer.appendInt32(-908914376) + buffer.appendInt32(640893467) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt64(id, buffer: buffer, boxed: false) @@ -1013,16 +1014,17 @@ public extension Api { serializeInt64(item, buffer: buffer, boxed: false) }} if Int(flags) & Int(1 << 18) != 0 {availableReactions!.serialize(buffer, true)} + if Int(flags) & Int(1 << 20) != 0 {serializeInt32(reactionsLimit!, buffer: buffer, boxed: false)} break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .channelFull(let flags, let flags2, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let defaultSendAs, let availableReactions, let stories, let wallpaper, let boostsApplied, let boostsUnrestrict, let emojiset): - return ("channelFull", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("about", about as Any), ("participantsCount", participantsCount as Any), ("adminsCount", adminsCount as Any), ("kickedCount", kickedCount as Any), ("bannedCount", bannedCount as Any), ("onlineCount", onlineCount as Any), ("readInboxMaxId", readInboxMaxId as Any), ("readOutboxMaxId", readOutboxMaxId as Any), ("unreadCount", unreadCount as Any), ("chatPhoto", chatPhoto as Any), ("notifySettings", notifySettings as Any), ("exportedInvite", exportedInvite as Any), ("botInfo", botInfo as Any), ("migratedFromChatId", migratedFromChatId as Any), ("migratedFromMaxId", migratedFromMaxId as Any), ("pinnedMsgId", pinnedMsgId as Any), ("stickerset", stickerset as Any), ("availableMinId", availableMinId as Any), ("folderId", folderId as Any), ("linkedChatId", linkedChatId as Any), ("location", location as Any), ("slowmodeSeconds", slowmodeSeconds as Any), ("slowmodeNextSendDate", slowmodeNextSendDate as Any), ("statsDc", statsDc as Any), ("pts", pts as Any), ("call", call as Any), ("ttlPeriod", ttlPeriod as Any), ("pendingSuggestions", pendingSuggestions as Any), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs as Any), ("themeEmoticon", themeEmoticon as Any), ("requestsPending", requestsPending as Any), ("recentRequesters", recentRequesters as Any), ("defaultSendAs", defaultSendAs as Any), ("availableReactions", availableReactions as Any), ("stories", stories as Any), ("wallpaper", wallpaper as Any), ("boostsApplied", boostsApplied as Any), ("boostsUnrestrict", boostsUnrestrict as Any), ("emojiset", emojiset as Any)]) - case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let availableReactions): - return ("chatFull", [("flags", flags as Any), ("id", id as Any), ("about", about as Any), ("participants", participants as Any), ("chatPhoto", chatPhoto as Any), ("notifySettings", notifySettings as Any), ("exportedInvite", exportedInvite as Any), ("botInfo", botInfo as Any), ("pinnedMsgId", pinnedMsgId as Any), ("folderId", folderId as Any), ("call", call as Any), ("ttlPeriod", ttlPeriod as Any), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs as Any), ("themeEmoticon", themeEmoticon as Any), ("requestsPending", requestsPending as Any), ("recentRequesters", recentRequesters as Any), ("availableReactions", availableReactions as Any)]) + case .channelFull(let flags, let flags2, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call, let ttlPeriod, let pendingSuggestions, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let defaultSendAs, let availableReactions, let reactionsLimit, let stories, let wallpaper, let boostsApplied, let boostsUnrestrict, let emojiset): + return ("channelFull", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("about", about as Any), ("participantsCount", participantsCount as Any), ("adminsCount", adminsCount as Any), ("kickedCount", kickedCount as Any), ("bannedCount", bannedCount as Any), ("onlineCount", onlineCount as Any), ("readInboxMaxId", readInboxMaxId as Any), ("readOutboxMaxId", readOutboxMaxId as Any), ("unreadCount", unreadCount as Any), ("chatPhoto", chatPhoto as Any), ("notifySettings", notifySettings as Any), ("exportedInvite", exportedInvite as Any), ("botInfo", botInfo as Any), ("migratedFromChatId", migratedFromChatId as Any), ("migratedFromMaxId", migratedFromMaxId as Any), ("pinnedMsgId", pinnedMsgId as Any), ("stickerset", stickerset as Any), ("availableMinId", availableMinId as Any), ("folderId", folderId as Any), ("linkedChatId", linkedChatId as Any), ("location", location as Any), ("slowmodeSeconds", slowmodeSeconds as Any), ("slowmodeNextSendDate", slowmodeNextSendDate as Any), ("statsDc", statsDc as Any), ("pts", pts as Any), ("call", call as Any), ("ttlPeriod", ttlPeriod as Any), ("pendingSuggestions", pendingSuggestions as Any), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs as Any), ("themeEmoticon", themeEmoticon as Any), ("requestsPending", requestsPending as Any), ("recentRequesters", recentRequesters as Any), ("defaultSendAs", defaultSendAs as Any), ("availableReactions", availableReactions as Any), ("reactionsLimit", reactionsLimit as Any), ("stories", stories as Any), ("wallpaper", wallpaper as Any), ("boostsApplied", boostsApplied as Any), ("boostsUnrestrict", boostsUnrestrict as Any), ("emojiset", emojiset as Any)]) + case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call, let ttlPeriod, let groupcallDefaultJoinAs, let themeEmoticon, let requestsPending, let recentRequesters, let availableReactions, let reactionsLimit): + return ("chatFull", [("flags", flags as Any), ("id", id as Any), ("about", about as Any), ("participants", participants as Any), ("chatPhoto", chatPhoto as Any), ("notifySettings", notifySettings as Any), ("exportedInvite", exportedInvite as Any), ("botInfo", botInfo as Any), ("pinnedMsgId", pinnedMsgId as Any), ("folderId", folderId as Any), ("call", call as Any), ("ttlPeriod", ttlPeriod as Any), ("groupcallDefaultJoinAs", groupcallDefaultJoinAs as Any), ("themeEmoticon", themeEmoticon as Any), ("requestsPending", requestsPending as Any), ("recentRequesters", recentRequesters as Any), ("availableReactions", availableReactions as Any), ("reactionsLimit", reactionsLimit as Any)]) } } @@ -1125,21 +1127,23 @@ public extension Api { if Int(_1!) & Int(1 << 30) != 0 {if let signature = reader.readInt32() { _37 = Api.parse(reader, signature: signature) as? Api.ChatReactions } } - var _38: Api.PeerStories? + var _38: Int32? + if Int(_2!) & Int(1 << 13) != 0 {_38 = reader.readInt32() } + var _39: Api.PeerStories? if Int(_2!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { - _38 = Api.parse(reader, signature: signature) as? Api.PeerStories + _39 = Api.parse(reader, signature: signature) as? Api.PeerStories } } - var _39: Api.WallPaper? + var _40: Api.WallPaper? if Int(_2!) & Int(1 << 7) != 0 {if let signature = reader.readInt32() { - _39 = Api.parse(reader, signature: signature) as? Api.WallPaper + _40 = Api.parse(reader, signature: signature) as? Api.WallPaper } } - var _40: Int32? - if Int(_2!) & Int(1 << 8) != 0 {_40 = reader.readInt32() } var _41: Int32? - if Int(_2!) & Int(1 << 9) != 0 {_41 = reader.readInt32() } - var _42: Api.StickerSet? + if Int(_2!) & Int(1 << 8) != 0 {_41 = reader.readInt32() } + var _42: Int32? + if Int(_2!) & Int(1 << 9) != 0 {_42 = reader.readInt32() } + var _43: Api.StickerSet? if Int(_2!) & Int(1 << 10) != 0 {if let signature = reader.readInt32() { - _42 = Api.parse(reader, signature: signature) as? Api.StickerSet + _43 = Api.parse(reader, signature: signature) as? Api.StickerSet } } let _c1 = _1 != nil let _c2 = _2 != nil @@ -1178,13 +1182,14 @@ public extension Api { let _c35 = (Int(_1!) & Int(1 << 28) == 0) || _35 != nil let _c36 = (Int(_1!) & Int(1 << 29) == 0) || _36 != nil let _c37 = (Int(_1!) & Int(1 << 30) == 0) || _37 != nil - let _c38 = (Int(_2!) & Int(1 << 4) == 0) || _38 != nil - let _c39 = (Int(_2!) & Int(1 << 7) == 0) || _39 != nil - let _c40 = (Int(_2!) & Int(1 << 8) == 0) || _40 != nil - let _c41 = (Int(_2!) & Int(1 << 9) == 0) || _41 != nil - let _c42 = (Int(_2!) & Int(1 << 10) == 0) || _42 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 && _c35 && _c36 && _c37 && _c38 && _c39 && _c40 && _c41 && _c42 { - return Api.ChatFull.channelFull(flags: _1!, flags2: _2!, id: _3!, about: _4!, participantsCount: _5, adminsCount: _6, kickedCount: _7, bannedCount: _8, onlineCount: _9, readInboxMaxId: _10!, readOutboxMaxId: _11!, unreadCount: _12!, chatPhoto: _13!, notifySettings: _14!, exportedInvite: _15, botInfo: _16!, migratedFromChatId: _17, migratedFromMaxId: _18, pinnedMsgId: _19, stickerset: _20, availableMinId: _21, folderId: _22, linkedChatId: _23, location: _24, slowmodeSeconds: _25, slowmodeNextSendDate: _26, statsDc: _27, pts: _28!, call: _29, ttlPeriod: _30, pendingSuggestions: _31, groupcallDefaultJoinAs: _32, themeEmoticon: _33, requestsPending: _34, recentRequesters: _35, defaultSendAs: _36, availableReactions: _37, stories: _38, wallpaper: _39, boostsApplied: _40, boostsUnrestrict: _41, emojiset: _42) + let _c38 = (Int(_2!) & Int(1 << 13) == 0) || _38 != nil + let _c39 = (Int(_2!) & Int(1 << 4) == 0) || _39 != nil + let _c40 = (Int(_2!) & Int(1 << 7) == 0) || _40 != nil + let _c41 = (Int(_2!) & Int(1 << 8) == 0) || _41 != nil + let _c42 = (Int(_2!) & Int(1 << 9) == 0) || _42 != nil + let _c43 = (Int(_2!) & Int(1 << 10) == 0) || _43 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 && _c35 && _c36 && _c37 && _c38 && _c39 && _c40 && _c41 && _c42 && _c43 { + return Api.ChatFull.channelFull(flags: _1!, flags2: _2!, id: _3!, about: _4!, participantsCount: _5, adminsCount: _6, kickedCount: _7, bannedCount: _8, onlineCount: _9, readInboxMaxId: _10!, readOutboxMaxId: _11!, unreadCount: _12!, chatPhoto: _13!, notifySettings: _14!, exportedInvite: _15, botInfo: _16!, migratedFromChatId: _17, migratedFromMaxId: _18, pinnedMsgId: _19, stickerset: _20, availableMinId: _21, folderId: _22, linkedChatId: _23, location: _24, slowmodeSeconds: _25, slowmodeNextSendDate: _26, statsDc: _27, pts: _28!, call: _29, ttlPeriod: _30, pendingSuggestions: _31, groupcallDefaultJoinAs: _32, themeEmoticon: _33, requestsPending: _34, recentRequesters: _35, defaultSendAs: _36, availableReactions: _37, reactionsLimit: _38, stories: _39, wallpaper: _40, boostsApplied: _41, boostsUnrestrict: _42, emojiset: _43) } else { return nil @@ -1243,6 +1248,8 @@ public extension Api { if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() { _17 = Api.parse(reader, signature: signature) as? Api.ChatReactions } } + var _18: Int32? + if Int(_1!) & Int(1 << 20) != 0 {_18 = reader.readInt32() } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil @@ -1260,8 +1267,9 @@ public extension Api { let _c15 = (Int(_1!) & Int(1 << 17) == 0) || _15 != nil let _c16 = (Int(_1!) & Int(1 << 17) == 0) || _16 != nil let _c17 = (Int(_1!) & Int(1 << 18) == 0) || _17 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 { - return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11, ttlPeriod: _12, groupcallDefaultJoinAs: _13, themeEmoticon: _14, requestsPending: _15, recentRequesters: _16, availableReactions: _17) + let _c18 = (Int(_1!) & Int(1 << 20) == 0) || _18 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 { + return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11, ttlPeriod: _12, groupcallDefaultJoinAs: _13, themeEmoticon: _14, requestsPending: _15, recentRequesters: _16, availableReactions: _17, reactionsLimit: _18) } else { return nil diff --git a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryContainerNode.swift b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryContainerNode.swift index 4db832cc97..2ac69b494d 100644 --- a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryContainerNode.swift +++ b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryContainerNode.swift @@ -6,7 +6,7 @@ import TelegramCore import TelegramPresentationData import AccountContext -public final class MediaNavigationAccessoryContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { +public final class MediaNavigationAccessoryContainerNode: ASDisplayNode, ASGestureRecognizerDelegate { private let displayBackground: Bool public let backgroundNode: ASDisplayNode diff --git a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift index 5052903899..fc1b19ed9d 100644 --- a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift +++ b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift @@ -140,7 +140,7 @@ private func generateMaskImage(color: UIColor) -> UIImage? { }) } -public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollViewDelegate { +public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, ASScrollViewDelegate { public static let minimizedHeight: CGFloat = 37.0 private let context: AccountContext @@ -345,7 +345,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi self.view.disablesInteractiveTransitionGestureRecognizer = true self.scrollNode.view.alwaysBounceHorizontal = true - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.isPagingEnabled = true self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.showsVerticalScrollIndicator = false diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatCameraPreviewController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatCameraPreviewController.swift index bdbf531757..959bf6cc82 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatCameraPreviewController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatCameraPreviewController.swift @@ -112,7 +112,7 @@ final class VoiceChatCameraPreviewController: ViewController { } } -private class VoiceChatCameraPreviewControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +private class VoiceChatCameraPreviewControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private weak var controller: VoiceChatCameraPreviewController? private let sharedContext: SharedAccountContext private var presentationData: PresentationData @@ -223,7 +223,7 @@ private class VoiceChatCameraPreviewControllerNode: ViewControllerTracingNode, U self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.backgroundNode) @@ -510,7 +510,7 @@ private class VoiceChatCameraPreviewControllerNode: ViewControllerTracingNode, U private let textFont = Font.with(size: 14.0, design: .camera, weight: .regular) private let selectedTextFont = Font.with(size: 14.0, design: .camera, weight: .semibold) -private class WheelControlNode: ASDisplayNode, UIGestureRecognizerDelegate { +private class WheelControlNode: ASDisplayNode, ASGestureRecognizerDelegate { struct Item: Equatable { public let title: String diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index 298f3d103f..49ef374575 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -254,7 +254,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController case fullscreen(controlsHidden: Bool) } - fileprivate final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + fileprivate final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private struct ListTransition { let deletions: [ListViewDeleteItem] let insertions: [ListViewInsertItem] @@ -3022,11 +3022,11 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController let longTapRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.actionButtonPressGesture(_:))) longTapRecognizer.minimumPressDuration = 0.001 - longTapRecognizer.delegate = self + longTapRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.actionButton.view.addGestureRecognizer(longTapRecognizer) let panRecognizer = DirectionalPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.view.addGestureRecognizer(panRecognizer) @@ -6747,7 +6747,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController self.updateDecorationsLayout(transition: transition) } } - if false, let (peerId, _) = minimalVisiblePeerid { + if !"".isEmpty, let (peerId, _) = minimalVisiblePeerid { var index = 0 for item in self.currentEntries { if case let .peer(entry, _) = item, entry.peer.id == peerId { diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift b/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift index 186d35e138..25280946e0 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift @@ -176,7 +176,7 @@ public final class VoiceChatJoinScreen: ViewController { self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationLayout(layout: layout).navigationFrame.maxY, transition: transition) } - class Node: ViewControllerTracingNode, UIScrollViewDelegate { + class Node: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private let asSpeaker: Bool @@ -285,7 +285,7 @@ public final class VoiceChatJoinScreen: ViewController { self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.cancelButtonNode.setTitle(self.presentationData.strings.Common_Cancel, with: Font.medium(20.0), with: self.presentationData.theme.actionSheet.standardActionTextColor, for: .normal) diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatOverlayController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatOverlayController.swift index 7e724bd582..0f1b2e5ed4 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatOverlayController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatOverlayController.swift @@ -17,7 +17,7 @@ import TooltipUI private let slideOffset: CGFloat = 80.0 + 44.0 public final class VoiceChatOverlayController: ViewController { - private final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + private final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: VoiceChatOverlayController? private var validLayout: ContainerViewLayout? diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatRecordingSetupController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatRecordingSetupController.swift index f03d96ef09..40c399006a 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatRecordingSetupController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatRecordingSetupController.swift @@ -90,7 +90,7 @@ final class VoiceChatRecordingSetupController: ViewController { } } -private class VoiceChatRecordingSetupControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +private class VoiceChatRecordingSetupControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { enum MediaMode { case videoAndAudio case audioOnly @@ -263,7 +263,7 @@ private class VoiceChatRecordingSetupControllerNode: ViewControllerTracingNode, self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.backgroundNode) diff --git a/submodules/TelegramCore/Sources/Account/Account.swift b/submodules/TelegramCore/Sources/Account/Account.swift index cae367b7cd..6ec6e2c81a 100644 --- a/submodules/TelegramCore/Sources/Account/Account.swift +++ b/submodules/TelegramCore/Sources/Account/Account.swift @@ -1278,6 +1278,7 @@ public class Account { self.stateManager.updateConfigRequested = { [weak self] in self?.restartConfigurationUpdates() + self?.taskManager?.reloadAppConfiguration() } self.restartConfigurationUpdates() diff --git a/submodules/TelegramCore/Sources/ApiUtils/AdMessageAttribute.swift b/submodules/TelegramCore/Sources/ApiUtils/AdMessageAttribute.swift index 913cefbac1..3f57b53351 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/AdMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/AdMessageAttribute.swift @@ -7,27 +7,18 @@ public final class AdMessageAttribute: MessageAttribute { case recommended } - public enum MessageTarget { - case peer(id: EnginePeer.Id, message: EngineMessage.Id?, startParam: String?) - case join(title: String, joinHash: String, peer: EnginePeer?) - case webPage(title: String, url: String) - case botApp(peerId: EnginePeer.Id, app: BotApp, startParam: String?) - } - public let opaqueId: Data public let messageType: MessageType - public let displayAvatar: Bool - public let target: MessageTarget - public let buttonText: String? + public let url: String + public let buttonText: String public let sponsorInfo: String? public let additionalInfo: String? public let canReport: Bool - public init(opaqueId: Data, messageType: MessageType, displayAvatar: Bool, target: MessageTarget, buttonText: String?, sponsorInfo: String?, additionalInfo: String?, canReport: Bool) { + public init(opaqueId: Data, messageType: MessageType, url: String, buttonText: String, sponsorInfo: String?, additionalInfo: String?, canReport: Bool) { self.opaqueId = opaqueId self.messageType = messageType - self.displayAvatar = displayAvatar - self.target = target + self.url = url self.buttonText = buttonText self.sponsorInfo = sponsorInfo self.additionalInfo = additionalInfo diff --git a/submodules/TelegramCore/Sources/State/AccountTaskManager.swift b/submodules/TelegramCore/Sources/State/AccountTaskManager.swift index 10e22a56fb..186090cc6c 100644 --- a/submodules/TelegramCore/Sources/State/AccountTaskManager.swift +++ b/submodules/TelegramCore/Sources/State/AccountTaskManager.swift @@ -18,6 +18,7 @@ final class AccountTaskManager { private var stateDisposable: Disposable? private let tasksDisposable = MetaDisposable() + private let configurationDisposable = MetaDisposable() private let managedTopReactionsDisposable = MetaDisposable() @@ -118,7 +119,7 @@ final class AccountTaskManager { self.managedTopReactionsDisposable.set(managedTopReactions(postbox: self.stateManager.postbox, network: self.stateManager.network).start()) //tasks.add(managedVoipConfigurationUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start()) - tasks.add(managedAppConfigurationUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start()) + self.reloadAppConfiguration() tasks.add(managedPremiumPromoConfigurationUpdates(accountPeerId: self.accountPeerId, postbox: self.stateManager.postbox, network: self.stateManager.network).start()) tasks.add(managedAutodownloadSettingsUpdates(accountManager: self.accountManager, network: self.stateManager.network).start()) tasks.add(managedTermsOfServiceUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start()) @@ -143,8 +144,13 @@ final class AccountTaskManager { deinit { self.stateDisposable?.dispose() self.tasksDisposable.dispose() + self.configurationDisposable.dispose() self.managedTopReactionsDisposable.dispose() } + + func reloadAppConfiguration() { + self.configurationDisposable.set(managedAppConfigurationUpdates(postbox: self.stateManager.postbox, network: self.stateManager.network).start()) + } } private let queue: Queue @@ -158,4 +164,10 @@ final class AccountTaskManager { return Impl(queue: queue, accountPeerId: stateManager.accountPeerId, stateManager: stateManager, accountManager: accountManager, networkArguments: networkArguments, viewTracker: viewTracker, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, isMainApp: isMainApp, testingEnvironment: testingEnvironment) }) } + + func reloadAppConfiguration() { + self.impl.with { impl in + impl.reloadAppConfiguration() + } + } } diff --git a/submodules/TelegramCore/Sources/State/MessageReactions.swift b/submodules/TelegramCore/Sources/State/MessageReactions.swift index 372f736d97..cd7ea7e216 100644 --- a/submodules/TelegramCore/Sources/State/MessageReactions.swift +++ b/submodules/TelegramCore/Sources/State/MessageReactions.swift @@ -674,7 +674,7 @@ func _internal_updatePeerAllowedReactions(account: Account, peerId: PeerId, allo mappedReactions = .chatReactionsNone } - return account.network.request(Api.functions.messages.setChatAvailableReactions(peer: inputPeer, availableReactions: mappedReactions)) + return account.network.request(Api.functions.messages.setChatAvailableReactions(flags: 0, peer: inputPeer, availableReactions: mappedReactions, reactionsLimit: nil)) |> map(Optional.init) |> `catch` { error -> Signal in if error.errorDescription == "CHAT_NOT_MODIFIED" { diff --git a/submodules/TelegramCore/Sources/State/Serialization.swift b/submodules/TelegramCore/Sources/State/Serialization.swift index 03166bd199..de13906cf0 100644 --- a/submodules/TelegramCore/Sources/State/Serialization.swift +++ b/submodules/TelegramCore/Sources/State/Serialization.swift @@ -210,7 +210,7 @@ public class BoxedMessage: NSObject { public class Serialization: NSObject, MTSerialization { public func currentLayer() -> UInt { - return 177 + return 178 } public func parseMessage(_ data: Data!) -> Any! { diff --git a/submodules/TelegramCore/Sources/Suggestions.swift b/submodules/TelegramCore/Sources/Suggestions.swift index 4aaaf830e4..d06828ba16 100644 --- a/submodules/TelegramCore/Sources/Suggestions.swift +++ b/submodules/TelegramCore/Sources/Suggestions.swift @@ -14,6 +14,7 @@ public enum ServerProvidedSuggestion: String { case restorePremium = "PREMIUM_RESTORE" case xmasPremiumGift = "PREMIUM_CHRISTMAS" case setupBirthday = "BIRTHDAY_SETUP" + case todayBirthdays = "BIRTHDAY_CONTACTS_TODAY" } private var dismissedSuggestionsPromise = ValuePromise<[AccountRecordId: Set]>([:]) @@ -45,6 +46,30 @@ func _internal_getServerProvidedSuggestions(account: Account) -> Signal<[ServerP |> distinctUntilChanged } +func _internal_getServerDismissedSuggestions(account: Account) -> Signal<[ServerProvidedSuggestion], NoError> { + let key: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.appConfiguration])) + return combineLatest(account.postbox.combinedView(keys: [key]), dismissedSuggestionsPromise.get()) + |> map { views, dismissedSuggestionsValue -> [ServerProvidedSuggestion] in + let dismissedSuggestions = dismissedSuggestionsValue[account.id] ?? Set() + guard let view = views.views[key] as? PreferencesView else { + return [] + } + guard let appConfiguration = view.values[PreferencesKeys.appConfiguration]?.get(AppConfiguration.self) else { + return [] + } + guard let data = appConfiguration.data, let listItems = data["hidden_suggestions"] as? [String] else { + return [] + } + + var items = listItems.compactMap { item -> ServerProvidedSuggestion? in + return ServerProvidedSuggestion(rawValue: item) + } + items.append(contentsOf: dismissedSuggestions) + return items + } + |> distinctUntilChanged +} + func _internal_dismissServerProvidedSuggestion(account: Account, suggestion: ServerProvidedSuggestion) -> Signal { if let _ = dismissedSuggestions[account.id] { dismissedSuggestions[account.id]?.insert(suggestion) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index 7d4a3c8207..ea394efd5d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift @@ -297,6 +297,7 @@ public struct CachedUserFlags: OptionSet { public static let isBlockedFromStories = CachedUserFlags(rawValue: 1 << 1) public static let readDatesPrivate = CachedUserFlags(rawValue: 1 << 2) public static let premiumRequired = CachedUserFlags(rawValue: 1 << 3) + public static let adsEnabled = CachedUserFlags(rawValue: 1 << 4) } public final class EditableBotInfo: PostboxCoding, Equatable { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift index 94b48fbc84..9f48fc7460 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift @@ -233,5 +233,9 @@ public extension TelegramEngine { public func updatePersonalChannel(personalChannel: TelegramPersonalChannel?) -> Signal { return _internal_updatePersonalChannel(account: self.account, personalChannel: personalChannel) } + + public func updateAdMessagesEnabled(enabled: Bool) -> Signal { + return _internal_updateAdMessagesEnabled(account: self.account, enabled: enabled) + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift index cd5066f20f..44b40c3e3a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift @@ -1896,5 +1896,33 @@ public extension TelegramEngine.EngineData.Item { } } } + + public struct AdsEnabled: TelegramEngineDataItem, TelegramEngineMapKeyDataItem, PostboxViewDataItem { + public typealias Result = Bool + + fileprivate var id: EnginePeer.Id + public var mapKey: EnginePeer.Id { + return self.id + } + + public init(id: EnginePeer.Id) { + self.id = id + } + + var key: PostboxViewKey { + return .cachedPeerData(peerId: self.id) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? CachedPeerDataView else { + preconditionFailure() + } + if let cachedData = view.cachedPeerData as? CachedUserData { + return cachedData.flags.contains(.adsEnabled) + } else { + return false + } + } + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift index 83ad6be77b..faaed76cf0 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift @@ -8,13 +8,11 @@ private class AdMessagesHistoryContextImpl { enum CodingKeys: String, CodingKey { case opaqueId case messageType - case displayAvatar + case title case text case textEntities case media - case target - case messageId - case startParam + case url case buttonText case sponsorInfo case additionalInfo @@ -26,147 +24,14 @@ private class AdMessagesHistoryContextImpl { case recommended = 1 } - enum Target: Equatable, Codable { - enum DecodingError: Error { - case generic - } - - enum CodingKeys: String, CodingKey { - case peer - case invite - case webPage - case botApp - } - - struct Invite: Equatable, Codable { - enum CodingKeys: String, CodingKey { - case title - case joinHash - case nameColor - case image - case peer - } - - var title: String - var joinHash: String - var nameColor: PeerNameColor? - var image: TelegramMediaImage? - var peer: Peer? - - init(title: String, joinHash: String, nameColor: PeerNameColor?, image: TelegramMediaImage?, peer: Peer?) { - self.title = title - self.joinHash = joinHash - self.nameColor = nameColor - self.image = image - self.peer = peer - } - - static func ==(lhs: Invite, rhs: Invite) -> Bool { - if lhs.title != rhs.title { - return false - } - if lhs.joinHash != rhs.joinHash { - return false - } - if lhs.nameColor != rhs.nameColor { - return false - } - if lhs.image != rhs.image { - return false - } - if !arePeersEqual(lhs.peer, rhs.peer) { - return false - } - return true - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - self.title = try container.decode(String.self, forKey: .title) - self.joinHash = try container.decode(String.self, forKey: .joinHash) - self.nameColor = try container.decodeIfPresent(Int32.self, forKey: .nameColor).flatMap { PeerNameColor(rawValue: $0) } - self.image = (try container.decodeIfPresent(Data.self, forKey: .image)).flatMap { data in - return TelegramMediaImage(decoder: PostboxDecoder(buffer: MemoryBuffer(data: data))) - } - self.peer = (try container.decodeIfPresent(Data.self, forKey: .peer)).flatMap { data in - return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Peer - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - - try container.encode(self.title, forKey: .title) - try container.encode(self.joinHash, forKey: .joinHash) - try container.encodeIfPresent(self.nameColor?.rawValue, forKey: .nameColor) - try container.encodeIfPresent(self.image.flatMap { image in - let encoder = PostboxEncoder() - image.encode(encoder) - return encoder.makeData() - }, forKey: .image) - try container.encodeIfPresent(self.peer.flatMap { peer in - let encoder = PostboxEncoder() - encoder.encodeRootObject(peer) - return encoder.makeData() - }, forKey: .peer) - } - } - - struct WebPage: Equatable, Codable { - var title: String - var url: String - var photo: TelegramMediaImage? - } - - case peer(PeerId) - case invite(Invite) - case webPage(WebPage) - case botApp(PeerId, BotApp) - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - if let botApp = try container.decodeIfPresent(BotApp.self, forKey: .botApp), let peer = try container.decodeIfPresent(Int64.self, forKey: .peer) { - self = .botApp(PeerId(peer), botApp) - } else if let peer = try container.decodeIfPresent(Int64.self, forKey: .peer) { - self = .peer(PeerId(peer)) - } else if let invite = try container.decodeIfPresent(Invite.self, forKey: .invite) { - self = .invite(invite) - } else if let webPage = try container.decodeIfPresent(WebPage.self, forKey: .webPage) { - self = .webPage(webPage) - } else { - throw DecodingError.generic - } - } - - func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - - switch self { - case let .peer(peerId): - try container.encode(peerId.toInt64(), forKey: .peer) - case let .invite(invite): - try container.encode(invite, forKey: .invite) - case let .webPage(webPage): - try container.encode(webPage, forKey: .webPage) - case let .botApp(peerId, botApp): - try container.encode(peerId.toInt64(), forKey: .peer) - try container.encode(botApp, forKey: .botApp) - } - } - } - public let opaqueId: Data public let messageType: MessageType - public let displayAvatar: Bool + public let title: String public let text: String public let textEntities: [MessageTextEntity] public let media: [Media] - public let target: Target - public let messageId: MessageId? - public let startParam: String? - public let buttonText: String? + public let url: String + public let buttonText: String public let sponsorInfo: String? public let additionalInfo: String? public let canReport: Bool @@ -174,27 +39,23 @@ private class AdMessagesHistoryContextImpl { public init( opaqueId: Data, messageType: MessageType, - displayAvatar: Bool, + title: String, text: String, textEntities: [MessageTextEntity], media: [Media], - target: Target, - messageId: MessageId?, - startParam: String?, - buttonText: String?, + url: String, + buttonText: String, sponsorInfo: String?, additionalInfo: String?, canReport: Bool ) { self.opaqueId = opaqueId self.messageType = messageType - self.displayAvatar = displayAvatar + self.title = title self.text = text self.textEntities = textEntities self.media = media - self.target = target - self.messageId = messageId - self.startParam = startParam + self.url = url self.buttonText = buttonText self.sponsorInfo = sponsorInfo self.additionalInfo = additionalInfo @@ -212,8 +73,7 @@ private class AdMessagesHistoryContextImpl { self.messageType = .sponsored } - self.displayAvatar = try container.decodeIfPresent(Bool.self, forKey: .displayAvatar) ?? false - + self.title = try container.decode(String.self, forKey: .title) self.text = try container.decode(String.self, forKey: .text) self.textEntities = try container.decode([MessageTextEntity].self, forKey: .textEntities) @@ -222,15 +82,13 @@ private class AdMessagesHistoryContextImpl { return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Media } - self.target = try container.decode(Target.self, forKey: .target) - self.messageId = try container.decodeIfPresent(MessageId.self, forKey: .messageId) - self.startParam = try container.decodeIfPresent(String.self, forKey: .startParam) - self.buttonText = try container.decodeIfPresent(String.self, forKey: .buttonText) + self.url = try container.decode(String.self, forKey: .url) + self.buttonText = try container.decode(String.self, forKey: .buttonText) self.sponsorInfo = try container.decodeIfPresent(String.self, forKey: .sponsorInfo) self.additionalInfo = try container.decodeIfPresent(String.self, forKey: .additionalInfo) - self.canReport = try container.decodeIfPresent(Bool.self, forKey: .displayAvatar) ?? false + self.canReport = try container.decodeIfPresent(Bool.self, forKey: .canReport) ?? false } public func encode(to encoder: Encoder) throws { @@ -238,7 +96,7 @@ private class AdMessagesHistoryContextImpl { try container.encode(self.opaqueId, forKey: .opaqueId) try container.encode(self.messageType.rawValue, forKey: .messageType) - try container.encode(self.displayAvatar, forKey: .displayAvatar) + try container.encode(self.title, forKey: .title) try container.encode(self.text, forKey: .text) try container.encode(self.textEntities, forKey: .textEntities) @@ -249,10 +107,8 @@ private class AdMessagesHistoryContextImpl { } try container.encode(mediaData, forKey: .media) - try container.encode(self.target, forKey: .target) - try container.encodeIfPresent(self.messageId, forKey: .messageId) - try container.encodeIfPresent(self.startParam, forKey: .startParam) - try container.encodeIfPresent(self.buttonText, forKey: .buttonText) + try container.encode(self.url, forKey: .url) + try container.encode(self.buttonText, forKey: .buttonText) try container.encodeIfPresent(self.sponsorInfo, forKey: .sponsorInfo) try container.encodeIfPresent(self.additionalInfo, forKey: .additionalInfo) @@ -267,6 +123,9 @@ private class AdMessagesHistoryContextImpl { if lhs.messageType != rhs.messageType { return false } + if lhs.title != rhs.title { + return false + } if lhs.text != rhs.text { return false } @@ -281,13 +140,7 @@ private class AdMessagesHistoryContextImpl { return false } } - if lhs.target != rhs.target { - return false - } - if lhs.messageId != rhs.messageId { - return false - } - if lhs.startParam != rhs.startParam { + if lhs.url != rhs.url { return false } if lhs.buttonText != rhs.buttonText { @@ -308,17 +161,6 @@ private class AdMessagesHistoryContextImpl { func toMessage(peerId: PeerId, transaction: Transaction) -> Message? { var attributes: [MessageAttribute] = [] - let target: AdMessageAttribute.MessageTarget - switch self.target { - case let .peer(peerId): - target = .peer(id: peerId, message: self.messageId, startParam: self.startParam) - case let .invite(invite): - target = .join(title: invite.title, joinHash: invite.joinHash, peer: invite.peer.flatMap(EnginePeer.init)) - case let .webPage(webPage): - target = .webPage(title: webPage.title, url: webPage.url) - case let .botApp(peerId, botApp): - target = .botApp(peerId: peerId, app: botApp, startParam: self.startParam) - } let mappedMessageType: AdMessageAttribute.MessageType switch self.messageType { case .sponsored: @@ -326,7 +168,7 @@ private class AdMessagesHistoryContextImpl { case .recommended: mappedMessageType = .recommended } - attributes.append(AdMessageAttribute(opaqueId: self.opaqueId, messageType: mappedMessageType, displayAvatar: self.displayAvatar && !self.canReport, target: target, buttonText: self.buttonText, sponsorInfo: self.sponsorInfo, additionalInfo: self.additionalInfo, canReport: self.canReport)) + attributes.append(AdMessageAttribute(opaqueId: self.opaqueId, messageType: mappedMessageType, url: self.url, buttonText: self.buttonText, sponsorInfo: self.sponsorInfo, additionalInfo: self.additionalInfo, canReport: self.canReport)) if !self.textEntities.isEmpty { let attribute = TextEntitiesMessageAttribute(entities: self.textEntities) attributes.append(attribute) @@ -338,81 +180,35 @@ private class AdMessagesHistoryContextImpl { messagePeers[peer.id] = peer } - let author: Peer - switch self.target { - case let .peer(peerId), let .botApp(peerId, _): - if let peer = transaction.getPeer(peerId) { - author = peer - } else { - return nil - } - case let .invite(invite): - author = TelegramChannel( - id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)), - accessHash: nil, - title: invite.title, - username: nil, - photo: [], - creationDate: 0, - version: 0, - participationStatus: .left, - info: .broadcast(TelegramChannelBroadcastInfo(flags: [])), - flags: [], - restrictionInfo: nil, - adminRights: nil, - bannedRights: nil, - defaultBannedRights: nil, - usernames: [], - storiesHidden: nil, - nameColor: invite.nameColor, - backgroundEmojiId: nil, - profileColor: nil, - profileBackgroundEmojiId: nil, - emojiStatus: nil, - approximateBoostLevel: nil - ) - case let .webPage(webPage): - author = TelegramChannel( - id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)), - accessHash: nil, - title: webPage.title, - username: nil, - photo: webPage.photo?.representations ?? [], - creationDate: 0, - version: 0, - participationStatus: .left, - info: .broadcast(TelegramChannelBroadcastInfo(flags: [])), - flags: [], - restrictionInfo: nil, - adminRights: nil, - bannedRights: nil, - defaultBannedRights: nil, - usernames: [], - storiesHidden: nil, - nameColor: .blue, - backgroundEmojiId: nil, - profileColor: nil, - profileBackgroundEmojiId: nil, - emojiStatus: nil, - approximateBoostLevel: nil - ) - } - + let author: Peer = TelegramChannel( + id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)), + accessHash: nil, + title: self.title, + username: nil, + photo: [], + creationDate: 0, + version: 0, + participationStatus: .left, + info: .broadcast(TelegramChannelBroadcastInfo(flags: [])), + flags: [], + restrictionInfo: nil, + adminRights: nil, + bannedRights: nil, + defaultBannedRights: nil, + usernames: [], + storiesHidden: nil, + nameColor: .blue, + backgroundEmojiId: nil, + profileColor: nil, + profileBackgroundEmojiId: nil, + emojiStatus: nil, + approximateBoostLevel: nil + ) messagePeers[author.id] = author let messageHash = (self.text.hashValue &+ 31 &* peerId.hashValue) &* 31 &+ author.id.hashValue let messageStableVersion = UInt32(bitPattern: Int32(truncatingIfNeeded: messageHash)) - var media: [Media] = self.media - if media.isEmpty { - if case let .invite(invite) = self.target, let image = invite.image { - media.append(image) - } else if self.displayAvatar && self.canReport, let profileImage = author.smallProfileImage { - media.append(TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: [profileImage], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])) - } - } - - return Message( stableId: 0, stableVersion: messageStableVersion, @@ -431,7 +227,7 @@ private class AdMessagesHistoryContextImpl { author: author, text: self.text, attributes: attributes, - media: media, + media: self.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], @@ -612,100 +408,30 @@ private class AdMessagesHistoryContextImpl { for message in messages { switch message { - case let .sponsoredMessage(flags, randomId, fromId, chatInvite, chatInviteHash, channelPost, startParam, webPage, botApp, message, entities, buttonText, sponsorInfo, additionalInfo): + case let .sponsoredMessage(flags, randomId, url, title, message, entities, photo, buttonText, sponsorInfo, additionalInfo): var parsedEntities: [MessageTextEntity] = [] if let entities = entities { parsedEntities = messageTextEntitiesFromApiEntities(entities) } let isRecommended = (flags & (1 << 5)) != 0 - var displayAvatar = (flags & (1 << 6)) != 0 let canReport = (flags & (1 << 12)) != 0 - var target: CachedMessage.Target? - if let fromId = fromId { - if let botApp = botApp, let app = BotApp(apiBotApp: botApp) { - target = .botApp(fromId.peerId, app) - } else { - target = .peer(fromId.peerId) - } - } else if let webPage = webPage { - switch webPage { - case let .sponsoredWebPage(_, url, siteName, photo): - let photo = photo.flatMap { telegramMediaImageFromApiPhoto($0) } - target = .webPage(CachedMessage.Target.WebPage(title: siteName, url: url, photo: photo)) - } - } else if let chatInvite = chatInvite, let chatInviteHash = chatInviteHash { - switch chatInvite { - case let .chatInvite(flags, title, _, photo, participantsCount, participants, nameColor): - let image = telegramMediaImageFromApiPhoto(photo) - let flags: ExternalJoiningChatState.Invite.Flags = .init(isChannel: (flags & (1 << 0)) != 0, isBroadcast: (flags & (1 << 1)) != 0, isPublic: (flags & (1 << 2)) != 0, isMegagroup: (flags & (1 << 3)) != 0, requestNeeded: (flags & (1 << 6)) != 0, isVerified: (flags & (1 << 7)) != 0, isScam: (flags & (1 << 8)) != 0, isFake: (flags & (1 << 9)) != 0) - - let _ = flags - let _ = participantsCount - let _ = participants - - target = .invite(CachedMessage.Target.Invite( - title: title, - joinHash: chatInviteHash, - nameColor: PeerNameColor(rawValue: nameColor), - image: displayAvatar ? image : nil, - peer: nil - )) - - displayAvatar = false - case let .chatInvitePeek(chat, _): - if let peer = parseTelegramGroupOrChannel(chat: chat) { - target = .invite(CachedMessage.Target.Invite( - title: peer.debugDisplayTitle, - joinHash: chatInviteHash, - nameColor: peer.nameColor, - image: nil, - peer: displayAvatar ? peer : nil - )) - } - - displayAvatar = false - case let .chatInviteAlready(chat): - if let peer = parseTelegramGroupOrChannel(chat: chat) { - target = .invite(CachedMessage.Target.Invite( - title: peer.debugDisplayTitle, - joinHash: chatInviteHash, - nameColor: peer.nameColor, - image: nil, - peer: displayAvatar ? peer : nil - )) - } - - displayAvatar = false - } - } -// else if let botApp = app.flatMap({ BotApp(apiBotApp: $0) }) { -// target = .botApp(botApp) -// } - - var messageId: MessageId? - if let fromId = fromId, let channelPost = channelPost { - messageId = MessageId(peerId: fromId.peerId, namespace: Namespaces.Message.Cloud, id: channelPost) - } + let photo = photo.flatMap { telegramMediaImageFromApiPhoto($0) } - if let target = target { - parsedMessages.append(CachedMessage( - opaqueId: randomId.makeData(), - messageType: isRecommended ? .recommended : .sponsored, - displayAvatar: displayAvatar, - text: message, - textEntities: parsedEntities, - media: [], - target: target, - messageId: messageId, - startParam: startParam, - buttonText: buttonText, - sponsorInfo: sponsorInfo, - additionalInfo: additionalInfo, - canReport: canReport - )) - } + parsedMessages.append(CachedMessage( + opaqueId: randomId.makeData(), + messageType: isRecommended ? .recommended : .sponsored, + title: title, + text: message, + textEntities: parsedEntities, + media: photo.flatMap { [$0] } ?? [], + url: url, + buttonText: buttonText, + sponsorInfo: sponsorInfo, + additionalInfo: additionalInfo, + canReport: canReport + )) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Notices/TelegramEngineNotices.swift b/submodules/TelegramCore/Sources/TelegramEngine/Notices/TelegramEngineNotices.swift index 7771fa30c8..b61fab28f6 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Notices/TelegramEngineNotices.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Notices/TelegramEngineNotices.swift @@ -25,6 +25,10 @@ public extension TelegramEngine { return _internal_getServerProvidedSuggestions(account: self.account) } + public func getServerDismissedSuggestions() -> Signal<[ServerProvidedSuggestion], NoError> { + return _internal_getServerDismissedSuggestions(account: self.account) + } + public func dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion) -> Signal { return _internal_dismissServerProvidedSuggestion(account: self.account, suggestion: suggestion) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelAds.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelAds.swift index 32d9775811..44ccb4fa82 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelAds.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelAds.swift @@ -45,3 +45,36 @@ func _internal_updateChannelRestrictAdMessages(account: Account, peerId: PeerId, } } + +public enum AdMessagesEnableError { + case generic +} + +func _internal_updateAdMessagesEnabled(account: Account, enabled: Bool) -> Signal { + return account.network.request(Api.functions.account.toggleSponsoredMessages(enabled: enabled ? .boolTrue : .boolFalse)) + |> `catch` { error -> Signal in + return .fail(.generic) + } + |> mapToSignal { result -> Signal in + guard case .boolTrue = result else { + return .fail(.generic) + } + return account.postbox.transaction { transaction -> Void in + transaction.updatePeerCachedData(peerIds: [account.peerId], update: { peerId, currentData in + if let currentData = currentData as? CachedUserData { + var flags = currentData.flags + if enabled { + flags.insert(.adsEnabled) + } else { + flags.remove(.adsEnabled) + } + return currentData.withUpdatedFlags(flags) + } else { + return currentData + } + }) + } + |> castError(AdMessagesEnableError.self) + |> ignoreValues + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift index b66146f16d..7bc65e514b 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift @@ -53,7 +53,8 @@ func _internal_requestRecommendedChannels(account: Account, peerId: EnginePeer.I guard let inputChannel = channel.flatMap(apiInputChannel) else { return .complete() } - return account.network.request(Api.functions.channels.getChannelRecommendations(channel: inputChannel)) + let flags: Int32 = (1 << 0) + return account.network.request(Api.functions.channels.getChannelRecommendations(flags: flags, channel: inputChannel)) |> retryRequest |> mapToSignal { result -> Signal in return account.postbox.transaction { transaction -> [EnginePeer] in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 22125d98f9..155672cef8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -258,7 +258,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee previous = CachedUserData() } switch fullUser { - case let .userFull(userFullFlags, _, _, userFullAbout, userFullSettings, personalPhoto, profilePhoto, fallbackPhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _, userPremiumGiftOptions, userWallpaper, stories, businessWorkHours, businessLocation, greetingMessage, awayMessage, businessIntro, birthday, personalChannelId, personalChannelMessage): + case let .userFull(userFullFlags, userFullFlags2, _, userFullAbout, userFullSettings, personalPhoto, profilePhoto, fallbackPhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _, userPremiumGiftOptions, userWallpaper, stories, businessWorkHours, businessLocation, greetingMessage, awayMessage, businessIntro, birthday, personalChannelId, personalChannelMessage): let _ = stories let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:)) let isBlocked = (userFullFlags & (1 << 0)) != 0 @@ -268,6 +268,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee let readDatesPrivate = (userFullFlags & (1 << 30)) != 0 let premiumRequired = (userFullFlags & (1 << 29)) != 0 let translationsDisabled = (userFullFlags & (1 << 23)) != 0 + let adsEnabled = (userFullFlags2 & (1 << 7)) != 0 var flags: CachedUserFlags = previous.flags if premiumRequired { @@ -285,6 +286,11 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee } else { flags.remove(.translationHidden) } + if adsEnabled { + flags.insert(.adsEnabled) + } else { + flags.remove(.adsEnabled) + } let callsPrivate = (userFullFlags & (1 << 5)) != 0 let canPinMessages = (userFullFlags & (1 << 7)) != 0 @@ -409,14 +415,14 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee switch result { case let .chatFull(fullChat, chats, users): switch fullChat { - case let .chatFull(_, _, _, _, _, notifySettings, _, _, _, _, _, _, _, _, _, _, _): + case let .chatFull(_, _, _, _, _, notifySettings, _, _, _, _, _, _, _, _, _, _, _, _): transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)]) case .channelFull: break } switch fullChat { - case let .chatFull(chatFullFlags, _, chatFullAbout, chatFullParticipants, chatFullChatPhoto, _, chatFullExportedInvite, chatFullBotInfo, chatFullPinnedMsgId, _, chatFullCall, chatTtlPeriod, chatFullGroupcallDefaultJoinAs, chatFullThemeEmoticon, chatFullRequestsPending, _, allowedReactions): + case let .chatFull(chatFullFlags, _, chatFullAbout, chatFullParticipants, chatFullChatPhoto, _, chatFullExportedInvite, chatFullBotInfo, chatFullPinnedMsgId, _, chatFullCall, chatTtlPeriod, chatFullGroupcallDefaultJoinAs, chatFullThemeEmoticon, chatFullRequestsPending, _, allowedReactions, reactionsLimit): var botInfos: [CachedPeerBotInfo] = [] for botInfo in chatFullBotInfo ?? [] { switch botInfo { @@ -495,6 +501,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee mappedAllowedReactions = .empty } + let _ = reactionsLimit + return previous.withUpdatedParticipants(participants) .withUpdatedExportedInvitation(exportedInvitation) .withUpdatedBotInfos(botInfos) @@ -540,14 +548,14 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee switch result { case let .chatFull(fullChat, chats, users): switch fullChat { - case let .channelFull(_, _, _, _, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ ): + case let .channelFull(_, _, _, _, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)]) case .chatFull: break } switch fullChat { - case let .channelFull(flags, flags2, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, _, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, _, inputCall, ttl, pendingSuggestions, groupcallDefaultJoinAs, themeEmoticon, requestsPending, _, defaultSendAs, allowedReactions, _, wallpaper, appliedBoosts, boostsUnrestrict, emojiSet): + case let .channelFull(flags, flags2, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, chatPhoto, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, _, linkedChatId, location, slowmodeSeconds, slowmodeNextSendDate, statsDc, _, inputCall, ttl, pendingSuggestions, groupcallDefaultJoinAs, themeEmoticon, requestsPending, _, defaultSendAs, allowedReactions, reactionsLimit, _, wallpaper, appliedBoosts, boostsUnrestrict, emojiSet): var channelFlags = CachedChannelFlags() if (flags & (1 << 3)) != 0 { channelFlags.insert(.canDisplayParticipants) @@ -734,6 +742,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee mappedAllowedReactions = .empty } + let _ = reactionsLimit + let membersHidden = (flags2 & (1 << 2)) != 0 let forumViewAsMessages = (flags2 & (1 << 6)) != 0 diff --git a/submodules/TelegramNotices/Sources/Notices.swift b/submodules/TelegramNotices/Sources/Notices.swift index 2f0d403fc7..1ac2425e16 100644 --- a/submodules/TelegramNotices/Sources/Notices.swift +++ b/submodules/TelegramNotices/Sources/Notices.swift @@ -194,7 +194,6 @@ private enum ApplicationSpecificGlobalNotice: Int32 { case outgoingVideoMessagePlayOnceTip = 63 case savedMessageTagLabelSuggestion = 65 case dismissedBusinessBadge = 68 - case dismissedBirthdayPremiumGifts = 69 case monetizationIntroDismissed = 70 case businessBotMessageTooltip = 71 case dismissedBusinessIntroBadge = 72 @@ -511,11 +510,7 @@ private struct ApplicationSpecificNoticeKeys { static func dismissedBusinessBadge() -> NoticeEntryKey { return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.dismissedBusinessBadge.key) } - - static func dismissedBirthdayPremiumGifts() -> NoticeEntryKey { - return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.dismissedBirthdayPremiumGifts.key) - } - + static func dismissedBirthdayPremiumGiftTip(peerId: PeerId) -> NoticeEntryKey { return NoticeEntryKey(namespace: noticeNamespace(namespace: dismissedBirthdayPremiumGiftTipNamespace), key: noticeKey(peerId: peerId, key: 0)) } @@ -2121,25 +2116,6 @@ public struct ApplicationSpecificNotice { |> take(1) } - public static func dismissedBirthdayPremiumGifts(accountManager: AccountManager) -> Signal<[Int64]?, NoError> { - return accountManager.noticeEntry(key: ApplicationSpecificNoticeKeys.dismissedBirthdayPremiumGifts()) - |> map { view -> [Int64]? in - if let value = view.value?.get(ApplicationSpecificInt64ArrayNotice.self) { - return value.values - } else { - return nil - } - } - } - - public static func setDismissedBirthdayPremiumGifts(accountManager: AccountManager, values: [Int64]) -> Signal { - return accountManager.transaction { transaction -> Void in - if let entry = CodableEntry(ApplicationSpecificInt64ArrayNotice(values: values)) { - transaction.setNotice(ApplicationSpecificNoticeKeys.dismissedBirthdayPremiumGifts(), entry) - } - } - } - public static func dismissedBirthdayPremiumGiftTip(accountManager: AccountManager, peerId: PeerId) -> Signal { return accountManager.noticeEntry(key: ApplicationSpecificNoticeKeys.dismissedBirthdayPremiumGiftTip(peerId: peerId)) |> map { view -> Int32? in diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift index 28fbbb4021..4ca6bf6921 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift @@ -73,6 +73,7 @@ public struct PresentationResourcesSettings { public static let stories = renderIcon(name: "Settings/Menu/Stories") public static let premiumGift = renderIcon(name: "Settings/Menu/Gift") public static let business = renderIcon(name: "Settings/Menu/Business", backgroundColors: [UIColor(rgb: 0xA95CE3), UIColor(rgb: 0xF16B80)]) + public static let myProfile = renderIcon(name: "Settings/Menu/Profile") public static let premium = generateImage(CGSize(width: 29.0, height: 29.0), contextGenerator: { size, context in let bounds = CGRect(origin: CGPoint(), size: size) diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index 529f22e001..d94ec661bf 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -1389,7 +1389,7 @@ public class CameraScreen: ViewController { } } - fileprivate final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + fileprivate final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: CameraScreen? private let context: AccountContext fileprivate var camera: Camera? @@ -1700,7 +1700,7 @@ public class CameraScreen: ViewController { self.previewContainerView.addGestureRecognizer(pinchGestureRecognizer) let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(_:))) - panGestureRecognizer.delegate = self + panGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate panGestureRecognizer.maximumNumberOfTouches = 1 self.panGestureRecognizer = panGestureRecognizer self.previewContainerView.addGestureRecognizer(panGestureRecognizer) @@ -1713,7 +1713,7 @@ public class CameraScreen: ViewController { self.previewContainerView.addGestureRecognizer(doubleGestureRecognizer) let pipPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePipPan(_:))) - pipPanGestureRecognizer.delegate = self + pipPanGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.previewContainerView.addGestureRecognizer(pipPanGestureRecognizer) self.pipPanGestureRecognizer = pipPanGestureRecognizer } diff --git a/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift index 8b42ed869f..218ca14ac6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatEmptyNode/Sources/ChatEmptyNode.swift @@ -86,7 +86,7 @@ public protocol ChatEmptyNodeStickerContentNode: ASDisplayNode { var stickerNode: ChatMediaInputStickerGridItemNode { get } } -public final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNodeStickerContentNode, ChatEmptyNodeContent, UIGestureRecognizerDelegate { +public final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNodeStickerContentNode, ChatEmptyNodeContent, ASGestureRecognizerDelegate { private let context: AccountContext private let interaction: ChatPanelInterfaceInteraction? @@ -134,7 +134,7 @@ public final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNod super.didLoad() let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.stickerTapGesture(_:))) - tapRecognizer.delegate = self + tapRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.stickerNode.view.addGestureRecognizer(tapRecognizer) } @@ -295,7 +295,7 @@ public final class ChatEmptyNodeGreetingChatContent: ASDisplayNode, ChatEmptyNod } } -public final class ChatEmptyNodeNearbyChatContent: ASDisplayNode, ChatEmptyNodeStickerContentNode, ChatEmptyNodeContent, UIGestureRecognizerDelegate { +public final class ChatEmptyNodeNearbyChatContent: ASDisplayNode, ChatEmptyNodeStickerContentNode, ChatEmptyNodeContent, ASGestureRecognizerDelegate { private let context: AccountContext private let interaction: ChatPanelInterfaceInteraction? @@ -342,7 +342,7 @@ public final class ChatEmptyNodeNearbyChatContent: ASDisplayNode, ChatEmptyNodeS super.didLoad() let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.stickerTapGesture(_:))) - tapRecognizer.delegate = self + tapRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.stickerNode.view.addGestureRecognizer(tapRecognizer) } @@ -1082,7 +1082,7 @@ private final class ChatEmptyNodeCloudChatContent: ASDisplayNode, ChatEmptyNodeC } } -public final class ChatEmptyNodeTopicChatContent: ASDisplayNode, ChatEmptyNodeContent, UIGestureRecognizerDelegate { +public final class ChatEmptyNodeTopicChatContent: ASDisplayNode, ChatEmptyNodeContent, ASGestureRecognizerDelegate { private let context: AccountContext private let titleNode: ImmediateTextNode diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift index 8df70d4273..0039683647 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentNode/Sources/ChatMessageAttachedContentNode.swift @@ -314,9 +314,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { contentMediaAspectFilled = flags.contains(.preferMediaAspectFilled) } var contentMediaInline = false - - var contentMediaImagePeer: EnginePeer? - + if let (media, flags) = mediaAndFlags { contentMediaInline = flags.contains(.preferMediaInline) @@ -362,9 +360,6 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { } else if let _ = media as? TelegramMediaStory { contentMediaValue = media } - } else if let adAttribute = message.adAttribute, case let .join(_, _, peer) = adAttribute.target, let peer, peer.largeProfileImage != nil { - contentMediaInline = true - contentMediaImagePeer = peer } var maxWidth: CGFloat = .greatestFiniteMagnitude @@ -408,9 +403,6 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode { inlineMediaAndSize = nil } - } else if let contentMediaImagePeer { - contentMediaContinueLayout = nil - inlineMediaAndSize = (.peerAvatar(contentMediaImagePeer), CGSize(width: 54.0, height: 54.0)) } else { contentMediaContinueLayout = nil inlineMediaAndSize = nil diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift index 3411fd8b67..97cad329f7 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift @@ -1411,11 +1411,10 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI ignoreForward = true effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) displayAuthorInfo = !mergedTop.merged && incoming - } else if let adAttribute = item.content.firstMessage.adAttribute, let author = item.content.firstMessage.author { + } else if let _ = item.content.firstMessage.adAttribute, let author = item.content.firstMessage.author { ignoreForward = true effectiveAuthor = author displayAuthorInfo = !mergedTop.merged && incoming - hasAvatar = adAttribute.displayAvatar } else { effectiveAuthor = firstMessage.author diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift index aa150aa342..2951dc6069 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode/Sources/ChatMessageGiveawayBubbleContentNode.swift @@ -24,7 +24,7 @@ private let titleFont = Font.medium(15.0) private let textFont = Font.regular(13.0) private let boldTextFont = Font.semibold(13.0) -public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode, UIGestureRecognizerDelegate { +public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode, ASGestureRecognizerDelegate { private let dateAndStatusNode: ChatMessageDateAndStatusNode private let placeholderNode: StickerShimmerEffectNode @@ -170,7 +170,7 @@ public class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode, super.didLoad() let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.bubbleTap(_:))) - tapRecognizer.delegate = self + tapRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(tapRecognizer) } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift index e982d5f985..6874321c3c 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInstantVideoItemNode/Sources/ChatMessageInstantVideoItemNode.swift @@ -34,7 +34,7 @@ private let nameFont = Font.medium(14.0) private let inlineBotPrefixFont = Font.regular(14.0) private let inlineBotNameFont = nameFont -public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerDelegate { +public class ChatMessageInstantVideoItemNode: ChatMessageItemView, ASGestureRecognizerDelegate { public let contextSourceNode: ContextExtractedContentContainingNode public let containerNode: ContextControllerSourceNode public let interactiveVideoNode: ChatMessageInteractiveInstantVideoNode diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift index daf37c91fc..77819bbc07 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift @@ -340,12 +340,6 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible hasAvatar = true } - if let adAttribute = message.adAttribute { - if adAttribute.displayAvatar { - hasAvatar = adAttribute.displayAvatar - } - } - if hasAvatar { if let effectiveAuthor = effectiveAuthor { var storyStats: PeerStoryStats? diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift index 39318cae99..fc6b107e92 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift @@ -510,38 +510,12 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent break } } - if adAttribute.displayAvatar && adAttribute.canReport, let profileImage = item.message.author?.smallProfileImage { - mediaAndFlags = (TelegramMediaImage(imageId: MediaId(namespace: 0, id: 0), representations: [profileImage], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: []), [.preferMediaInline]) - } if adAttribute.canReport { titleBadge = item.presentationData.strings.Message_AdWhatIsThis } - if let buttonText = adAttribute.buttonText { - actionTitle = buttonText.uppercased() - } else if let author = item.message.author as? TelegramUser, author.botInfo != nil { - if case .botApp = adAttribute.target { - actionTitle = item.presentationData.strings.Conversation_LaunchApp - } else { - actionTitle = item.presentationData.strings.Conversation_ViewBot - } - } else if let author = item.message.author as? TelegramChannel, case .group = author.info { - if case let .peer(_, messageId, _) = adAttribute.target, messageId != nil { - actionTitle = item.presentationData.strings.Conversation_ViewPost - } else { - actionTitle = item.presentationData.strings.Conversation_ViewGroup - } - } else { - if case .webPage = adAttribute.target { - actionTitle = item.presentationData.strings.Conversation_OpenLink - actionIcon = .link - } else if case let .peer(_, messageId, _) = adAttribute.target, messageId != nil { - actionTitle = item.presentationData.strings.Conversation_ViewMessage - } else { - actionTitle = item.presentationData.strings.Conversation_ViewChannel - } - } + actionTitle = adAttribute.buttonText.uppercased() displayLine = true } diff --git a/submodules/TelegramUI/Components/Chat/ChatQrCodeScreen/Sources/ChatQrCodeScreen.swift b/submodules/TelegramUI/Components/Chat/ChatQrCodeScreen/Sources/ChatQrCodeScreen.swift index deba00c493..0ce5e17bc6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatQrCodeScreen/Sources/ChatQrCodeScreen.swift +++ b/submodules/TelegramUI/Components/Chat/ChatQrCodeScreen/Sources/ChatQrCodeScreen.swift @@ -751,7 +751,7 @@ private func generateShadowImage() -> UIImage? { })?.stretchableImage(withLeftCapWidth: 20, topCapHeight: 0) } -private class ChatQrCodeScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { +private class ChatQrCodeScreenNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private weak var controller: ChatQrCodeScreen? @@ -1285,7 +1285,7 @@ private class ChatQrCodeScreenNode: ViewControllerTracingNode, UIScrollViewDeleg override public func didLoad() { super.didLoad() - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { self.wrappingScrollNode.view.contentInsetAdjustmentBehavior = .never } diff --git a/submodules/TelegramUI/Components/Chat/InstantVideoRadialStatusNode/Sources/InstantVideoRadialStatusNode.swift b/submodules/TelegramUI/Components/Chat/InstantVideoRadialStatusNode/Sources/InstantVideoRadialStatusNode.swift index bd7e982c5d..b81129edf4 100644 --- a/submodules/TelegramUI/Components/Chat/InstantVideoRadialStatusNode/Sources/InstantVideoRadialStatusNode.swift +++ b/submodules/TelegramUI/Components/Chat/InstantVideoRadialStatusNode/Sources/InstantVideoRadialStatusNode.swift @@ -62,7 +62,7 @@ private extension CGPoint { } } -public final class InstantVideoRadialStatusNode: ASDisplayNode, UIGestureRecognizerDelegate { +public final class InstantVideoRadialStatusNode: ASDisplayNode, ASGestureRecognizerDelegate { private let color: UIColor private let hasSeek: Bool private let sparks: Bool @@ -177,11 +177,11 @@ public final class InstantVideoRadialStatusNode: ASDisplayNode, UIGestureRecogni } let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))) - tapGestureRecognizer.delegate = self + tapGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(tapGestureRecognizer) let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panGestureRecognizer.delegate = self + panGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(panGestureRecognizer) } diff --git a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeControllerNode.swift b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeControllerNode.swift index 0a7936716d..3ddddcd8ba 100644 --- a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeControllerNode.swift +++ b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeControllerNode.swift @@ -11,7 +11,7 @@ import SolidRoundedButtonNode import PresentationDataUtils import UIKitRuntimeUtils -class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +class ChatScheduleTimeControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private let mode: ChatScheduleTimeControllerMode private let controllerStyle: ChatScheduleTimeControllerStyle @@ -128,7 +128,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.backgroundNode) diff --git a/submodules/TelegramUI/Components/ChatTimerScreen/Sources/ChatTimerScreen.swift b/submodules/TelegramUI/Components/ChatTimerScreen/Sources/ChatTimerScreen.swift index dfebbb77ff..94cc90f6ff 100644 --- a/submodules/TelegramUI/Components/ChatTimerScreen/Sources/ChatTimerScreen.swift +++ b/submodules/TelegramUI/Components/ChatTimerScreen/Sources/ChatTimerScreen.swift @@ -259,7 +259,7 @@ private var timerValues: [Int32] = { return values }() -class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPickerViewDataSource, UIPickerViewDelegate { +class ChatTimerScreenNode: ViewControllerTracingNode, ASScrollViewDelegate, UIPickerViewDataSource, UIPickerViewDelegate { private let context: AccountContext private let controllerStyle: ChatTimerScreenStyle private var presentationData: PresentationData @@ -400,7 +400,7 @@ class ChatTimerScreenNode: ViewControllerTracingNode, UIScrollViewDelegate, UIPi self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.backgroundNode) diff --git a/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift index 01ac92dbe0..11a58b0a01 100644 --- a/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift +++ b/submodules/TelegramUI/Components/EmptyStateIndicatorComponent/Sources/EmptyStateIndicatorComponent.swift @@ -15,6 +15,7 @@ public final class EmptyStateIndicatorComponent: Component { public let title: String public let text: String public let actionTitle: String? + public let fitToHeight: Bool public let action: () -> Void public let additionalActionTitle: String? public let additionalAction: () -> Void @@ -22,6 +23,7 @@ public final class EmptyStateIndicatorComponent: Component { public init( context: AccountContext, theme: PresentationTheme, + fitToHeight: Bool, animationName: String, title: String, text: String, @@ -32,6 +34,7 @@ public final class EmptyStateIndicatorComponent: Component { ) { self.context = context self.theme = theme + self.fitToHeight = fitToHeight self.animationName = animationName self.title = title self.text = text @@ -48,6 +51,9 @@ public final class EmptyStateIndicatorComponent: Component { if lhs.theme !== rhs.theme { return false } + if lhs.fitToHeight != rhs.fitToHeight { + return false + } if lhs.animationName != rhs.animationName { return false } @@ -205,7 +211,12 @@ public final class EmptyStateIndicatorComponent: Component { totalHeight += buttonSpacing + additionalButtonSize.height } - var contentY = floor((availableSize.height - totalHeight) * 0.5) + var contentY: CGFloat + if component.fitToHeight { + contentY = 0.0 + } else { + contentY = floor((availableSize.height - totalHeight) * 0.5) + } if let animationView = self.animation.view { if animationView.superview == nil { @@ -243,7 +254,11 @@ public final class EmptyStateIndicatorComponent: Component { contentY += additionalButtonSize.height } - return availableSize + if component.fitToHeight { + return CGSize(width: availableSize.width, height: totalHeight) + } else { + return availableSize + } } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift index 351b10e121..5068066d1c 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift @@ -48,7 +48,7 @@ public final class EntitySearchContainerController: ViewController { self.node.containerLayoutUpdated(layout, transition: transition) } - private class Node: ViewControllerTracingNode, UIScrollViewDelegate { + private class Node: ViewControllerTracingNode, ASScrollViewDelegate { private weak var controller: EntitySearchContainerController? private let containerNode: EntitySearchContainerNode diff --git a/submodules/TelegramUI/Components/ListItemSliderSelectorComponent/Sources/ListItemSliderSelectorComponent.swift b/submodules/TelegramUI/Components/ListItemSliderSelectorComponent/Sources/ListItemSliderSelectorComponent.swift index 80b67d862a..0d7e103007 100644 --- a/submodules/TelegramUI/Components/ListItemSliderSelectorComponent/Sources/ListItemSliderSelectorComponent.swift +++ b/submodules/TelegramUI/Components/ListItemSliderSelectorComponent/Sources/ListItemSliderSelectorComponent.swift @@ -11,18 +11,24 @@ import SliderComponent public final class ListItemSliderSelectorComponent: Component { public let theme: PresentationTheme public let values: [String] + public let markPositions: Bool public let selectedIndex: Int + public let title: String? public let selectedIndexUpdated: (Int) -> Void public init( theme: PresentationTheme, values: [String], + markPositions: Bool, selectedIndex: Int, + title: String?, selectedIndexUpdated: @escaping (Int) -> Void ) { self.theme = theme self.values = values + self.markPositions = markPositions self.selectedIndex = selectedIndex + self.title = title self.selectedIndexUpdated = selectedIndexUpdated } @@ -33,14 +39,21 @@ public final class ListItemSliderSelectorComponent: Component { if lhs.values != rhs.values { return false } + if lhs.markPositions != rhs.markPositions { + return false + } if lhs.selectedIndex != rhs.selectedIndex { return false } + if lhs.title != rhs.title { + return false + } return true } public final class View: UIView, ListSectionComponent.ChildView { - private var titles: [ComponentView] = [] + private var titles: [Int: ComponentView] = [:] + private var mainTitle: ComponentView? private var slider = ComponentView() private var component: ListItemSliderSelectorComponent? @@ -67,15 +80,24 @@ public final class ListItemSliderSelectorComponent: Component { let titleAreaWidth: CGFloat = availableSize.width - titleSideInset * 2.0 + var validIds: [Int] = [] for i in 0 ..< component.values.count { + if component.title != nil { + if i != 0 && i != component.values.count - 1 { + continue + } + } + + validIds.append(i) + var titleTransition = transition let title: ComponentView - if self.titles.count > i { - title = self.titles[i] + if let current = self.titles[i] { + title = current } else { titleTransition = titleTransition.withAnimation(.none) title = ComponentView() - self.titles.append(title) + self.titles[i] = title } let titleSize = title.update( transition: .immediate, @@ -103,11 +125,48 @@ public final class ListItemSliderSelectorComponent: Component { titleTransition.setPosition(view: titleView, position: titleFrame.center) } } - if self.titles.count > component.values.count { - for i in component.values.count ..< self.titles.count { - self.titles[i].view?.removeFromSuperview() + var removeIds: [Int] = [] + for (id, title) in self.titles { + if !validIds.contains(id) { + removeIds.append(id) + title.view?.removeFromSuperview() + } + } + for id in removeIds { + self.titles.removeValue(forKey: id) + } + + if let title = component.title { + let mainTitle: ComponentView + var mainTitleTransition = transition + if let current = self.mainTitle { + mainTitle = current + } else { + mainTitleTransition = mainTitleTransition.withAnimation(.none) + mainTitle = ComponentView() + self.mainTitle = mainTitle + } + let mainTitleSize = mainTitle.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: title, font: Font.regular(16.0), textColor: component.theme.list.itemPrimaryTextColor)) + )), + environment: {}, + containerSize: CGSize(width: 100.0, height: 100.0) + ) + let mainTitleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - mainTitleSize.width) * 0.5), y: 10.0), size: mainTitleSize) + if let mainTitleView = mainTitle.view { + if mainTitleView.superview == nil { + self.addSubview(mainTitleView) + } + mainTitleView.bounds = CGRect(origin: CGPoint(), size: mainTitleFrame.size) + mainTitleTransition.setPosition(view: mainTitleView, position: mainTitleFrame.center) + } + } else { + if let mainTitle = self.mainTitle { + self.mainTitle = nil + mainTitle.view?.removeFromSuperview() } - self.titles.removeLast(self.titles.count - component.values.count) } let sliderSize = self.slider.update( @@ -115,6 +174,7 @@ public final class ListItemSliderSelectorComponent: Component { component: AnyComponent(SliderComponent( valueCount: component.values.count, value: component.selectedIndex, + markPositions: component.markPositions, trackBackgroundColor: component.theme.list.controlSecondaryColor, trackForegroundColor: component.theme.list.itemAccentColor, valueUpdated: { [weak self] value in diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaCutoutScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaCutoutScreen.swift index ef3a279155..fe959363d5 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaCutoutScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaCutoutScreen.swift @@ -288,7 +288,7 @@ private final class MediaCutoutScreenComponent: Component { } public final class MediaCutoutScreen: ViewController { - fileprivate final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + fileprivate final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: MediaCutoutScreen? private let context: AccountContext diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 20088635e5..01cf56c725 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -2121,7 +2121,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate } } - final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: MediaEditorScreen? private let context: AccountContext fileprivate var interaction: DrawingToolsInteraction? @@ -2750,28 +2750,28 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate self.view.disablesInteractiveKeyboardGestureRecognizer = true let dismissPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handleDismissPan(_:))) - dismissPanGestureRecognizer.delegate = self + dismissPanGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate dismissPanGestureRecognizer.maximumNumberOfTouches = 1 self.previewContainerView.addGestureRecognizer(dismissPanGestureRecognizer) self.dismissPanGestureRecognizer = dismissPanGestureRecognizer let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.handlePan(_:))) - panGestureRecognizer.delegate = self + panGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate panGestureRecognizer.minimumNumberOfTouches = 1 panGestureRecognizer.maximumNumberOfTouches = 2 self.view.addGestureRecognizer(panGestureRecognizer) self.panGestureRecognizer = panGestureRecognizer let pinchGestureRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(self.handlePinch(_:))) - pinchGestureRecognizer.delegate = self + pinchGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.previewContainerView.addGestureRecognizer(pinchGestureRecognizer) let rotateGestureRecognizer = UIRotationGestureRecognizer(target: self, action: #selector(self.handleRotate(_:))) - rotateGestureRecognizer.delegate = self + rotateGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.previewContainerView.addGestureRecognizer(rotateGestureRecognizer) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))) - tapGestureRecognizer.delegate = self + tapGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.previewContainerView.addGestureRecognizer(tapGestureRecognizer) self.interaction = DrawingToolsInteraction( diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaToolsScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaToolsScreen.swift index 4401869e98..2336fce88b 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaToolsScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaToolsScreen.swift @@ -954,7 +954,7 @@ private final class MediaToolsScreenComponent: Component { } public final class MediaToolsScreen: ViewController { - fileprivate final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + fileprivate final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: MediaToolsScreen? private let context: AccountContext diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/SaveProgressScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/SaveProgressScreen.swift index d16c858c64..123591de92 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/SaveProgressScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/SaveProgressScreen.swift @@ -384,7 +384,7 @@ public final class SaveProgressScreenComponent: Component { } public final class SaveProgressScreen: ViewController { - fileprivate final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + fileprivate final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: SaveProgressScreen? private let context: AccountContext diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerPackListContextItem.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerPackListContextItem.swift index 7b01557735..05f167e9f5 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerPackListContextItem.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/StickerPackListContextItem.swift @@ -26,7 +26,7 @@ final class StickerPackListContextItem: ContextMenuCustomItem { } } -private final class StickerPackListContextItemNode: ASDisplayNode, ContextMenuCustomNode, ContextActionNodeProtocol, UIScrollViewDelegate { +private final class StickerPackListContextItemNode: ASDisplayNode, ContextMenuCustomNode, ContextActionNodeProtocol, ASScrollViewDelegate { private let item: StickerPackListContextItem private let presentationData: PresentationData private let getController: () -> ContextControllerProtocol? @@ -105,7 +105,7 @@ private final class StickerPackListContextItemNode: ASDisplayNode, ContextMenuCu override func didLoad() { super.didLoad() - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.alwaysBounceVertical = false self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.scrollIndicatorInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 5.0, right: 0.0) diff --git a/submodules/TelegramUI/Components/MultiplexedVideoNode/Sources/MultiplexedVideoNode.swift b/submodules/TelegramUI/Components/MultiplexedVideoNode/Sources/MultiplexedVideoNode.swift index aec600797c..6e58886501 100644 --- a/submodules/TelegramUI/Components/MultiplexedVideoNode/Sources/MultiplexedVideoNode.swift +++ b/submodules/TelegramUI/Components/MultiplexedVideoNode/Sources/MultiplexedVideoNode.swift @@ -100,7 +100,7 @@ public final class MultiplexedVideoNodeFiles { } } -public final class MultiplexedVideoNode: ASDisplayNode, UIScrollViewDelegate { +public final class MultiplexedVideoNode: ASDisplayNode, ASScrollViewDelegate { private let account: Account private var theme: PresentationTheme private var strings: PresentationStrings @@ -236,7 +236,7 @@ public final class MultiplexedVideoNode: ASDisplayNode, UIScrollViewDelegate { } } - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate let recognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))) self.view.addGestureRecognizer(recognizer) diff --git a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/BUILD b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/BUILD index da94a4fdb1..99f9217acf 100644 --- a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/BUILD +++ b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/BUILD @@ -33,6 +33,8 @@ swift_library( "//submodules/UndoUI", "//submodules/TextFormat", "//submodules/Components/HierarchyTrackingLayer", + "//submodules/TelegramUI/Components/ListSectionComponent", + "//submodules/TelegramUI/Components/ListItemSliderSelectorComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift index a5e5ee87a0..fdedcdbb92 100644 --- a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift +++ b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift @@ -21,6 +21,8 @@ import AnimatedTextComponent import TextFormat import AudioToolbox import PremiumLockButtonSubtitleComponent +import ListSectionComponent +import ListItemSliderSelectorComponent final class PeerAllowedReactionsScreenComponent: Component { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -57,6 +59,7 @@ final class PeerAllowedReactionsScreenComponent: Component { private var reactionsTitleText: ComponentView? private var reactionsInfoText: ComponentView? private var reactionInput: ComponentView? + private var reactionCountSection: ComponentView? private let actionButton = ComponentView() private var reactionSelectionControl: ComponentView? @@ -82,6 +85,8 @@ final class PeerAllowedReactionsScreenComponent: Component { private var displayInput: Bool = false private var recenterOnCaret: Bool = false + private var allowedReactionCount: Int = 11 + private var isApplyingSettings: Bool = false private var applyDisposable: Disposable? @@ -775,6 +780,86 @@ final class PeerAllowedReactionsScreenComponent: Component { } contentHeight += reactionsInfoTextSize.height contentHeight += 6.0 + + contentHeight += 32.0 + + let reactionCountSection: ComponentView + if let current = self.reactionCountSection { + reactionCountSection = current + } else { + reactionCountSection = ComponentView() + self.reactionCountSection = reactionCountSection + } + + let reactionCountValueList = (1 ... 11).map { i -> String in + return "\(i)" + } + //TODO:localize + let sliderTitle: String + if self.allowedReactionCount == 1 { + sliderTitle = "1 reaction" + } else { + sliderTitle = "\(self.allowedReactionCount) reactions" + } + let reactionCountSectionSize = reactionCountSection.update( + transition: transition, + component: AnyComponent(ListSectionComponent( + theme: environment.theme, + header: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString( + string: "MAXIMUM REACTIONS PER POST", + font: Font.regular(13.0), + textColor: environment.theme.list.freeTextColor + )), + maximumNumberOfLines: 0 + )), + footer: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString( + string: "Limit the number of different reactions that can be added to a post, including already published posts.", + font: Font.regular(13.0), + textColor: environment.theme.list.freeTextColor + )), + maximumNumberOfLines: 0 + )), + items: [ + AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemSliderSelectorComponent( + theme: environment.theme, + values: reactionCountValueList.map { item in + return item + }, + markPositions: false, + selectedIndex: max(0, min(reactionCountValueList.count - 1, self.allowedReactionCount - 1)), + title: sliderTitle, + selectedIndexUpdated: { [weak self] index in + guard let self else { + return + } + let index = max(1, min(reactionCountValueList.count, index + 1)) + self.allowedReactionCount = index + self.state?.updated(transition: .immediate) + } + ))) + ], + displaySeparators: false + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 10000.0) + ) + let reactionCountSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: reactionCountSectionSize) + if let reactionCountSectionView = reactionCountSection.view { + if reactionCountSectionView.superview == nil { + self.scrollView.addSubview(reactionCountSectionView) + } + if animateIn { + reactionCountSectionView.frame = reactionCountSectionFrame + if !transition.animation.isImmediate { + reactionCountSectionView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + } + } else { + transition.setFrame(view: reactionCountSectionView, frame: reactionCountSectionFrame) + } + } + contentHeight += reactionCountSectionSize.height } else { if let reactionsTitleText = self.reactionsTitleText { self.reactionsTitleText = nil @@ -814,6 +899,19 @@ final class PeerAllowedReactionsScreenComponent: Component { } } } + + if let reactionCountSection = self.reactionCountSection { + self.reactionCountSection = nil + if let reactionCountSectionView = reactionCountSection.view { + if !transition.animation.isImmediate { + reactionCountSectionView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak reactionCountSectionView] _ in + reactionCountSectionView?.removeFromSuperview() + }) + } else { + reactionCountSectionView.removeFromSuperview() + } + } + } } var buttonContents: [AnyComponentWithIdentity] = [] diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode/Sources/PeerInfoChatListPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode/Sources/PeerInfoChatListPaneNode.swift index a830414f1b..0c44d4b0d3 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode/Sources/PeerInfoChatListPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode/Sources/PeerInfoChatListPaneNode.swift @@ -94,7 +94,7 @@ private final class SearchNavigationContentNode: ASDisplayNode, PeerInfoPanelNod } } -public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private let context: AccountContext private let navigationController: () -> NavigationController? diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode/Sources/PeerInfoChatPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode/Sources/PeerInfoChatPaneNode.swift index 2acf7e0072..c8d05f4e09 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode/Sources/PeerInfoChatPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode/Sources/PeerInfoChatPaneNode.swift @@ -89,7 +89,7 @@ private final class SearchNavigationContentNode: ASDisplayNode, PeerInfoPanelNod } } -public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private let context: AccountContext private let peerId: EnginePeer.Id private let navigationController: () -> NavigationController? diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/Sources/PeerInfoPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/Sources/PeerInfoPaneNode.swift index 328d0612e5..5b8d3acff0 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/Sources/PeerInfoPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode/Sources/PeerInfoPaneNode.swift @@ -8,6 +8,7 @@ import TelegramPresentationData public enum PeerInfoPaneKey: Int32 { case members case stories + case storyArchive case media case savedMessagesChats case savedMessages diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGifPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGifPaneNode.swift index 054cfeba82..a360848d8a 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGifPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/Panes/PeerInfoGifPaneNode.swift @@ -761,7 +761,7 @@ private enum ItemsLayout { } } -final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate { +final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDelegate { enum ContentType { case photoOrVideo case gifs @@ -853,7 +853,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDe self.scrollNode.view.contentInsetAdjustmentBehavior = .never } self.scrollNode.view.scrollsToTop = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.scrollNode) self.addSubnode(self.floatingHeaderNode) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift index d6a15bfd57..1d65c49eaf 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift @@ -305,6 +305,7 @@ final class PeerInfoScreenData { let linkedDiscussionPeer: Peer? let members: PeerInfoMembersData? let storyListContext: PeerStoryListContext? + let storyArchiveListContext: PeerStoryListContext? let encryptionKeyFingerprint: SecretChatKeyFingerprint? let globalSettings: TelegramGlobalSettings? let invitations: PeerExportedInvitationsState? @@ -344,6 +345,7 @@ final class PeerInfoScreenData { linkedDiscussionPeer: Peer?, members: PeerInfoMembersData?, storyListContext: PeerStoryListContext?, + storyArchiveListContext: PeerStoryListContext?, encryptionKeyFingerprint: SecretChatKeyFingerprint?, globalSettings: TelegramGlobalSettings?, invitations: PeerExportedInvitationsState?, @@ -371,6 +373,7 @@ final class PeerInfoScreenData { self.linkedDiscussionPeer = linkedDiscussionPeer self.members = members self.storyListContext = storyListContext + self.storyArchiveListContext = storyArchiveListContext self.encryptionKeyFingerprint = encryptionKeyFingerprint self.globalSettings = globalSettings self.invitations = invitations @@ -403,7 +406,7 @@ private enum PeerInfoScreenInputData: Equatable { public func hasAvailablePeerInfoMediaPanes(context: AccountContext, peerId: PeerId) -> Signal { let chatLocationContextHolder = Atomic(value: nil) - let mediaPanes = peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: .peer(id: peerId), chatLocationContextHolder: chatLocationContextHolder) + let mediaPanes = peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: .peer(id: peerId), isMyProfile: false, chatLocationContextHolder: chatLocationContextHolder) |> map { panes -> Bool in if let panes { return !panes.isEmpty @@ -426,15 +429,19 @@ public func hasAvailablePeerInfoMediaPanes(context: AccountContext, peerId: Peer } } -private func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation, chatLocationContextHolder: Atomic) -> Signal<[PeerInfoPaneKey]?, NoError> { - let tags: [(MessageTags, PeerInfoPaneKey)] = [ - (.photoOrVideo, .media), - (.file, .files), - (.music, .music), - (.voiceOrInstantVideo, .voice), - (.webPage, .links), - (.gif, .gifs) - ] +private func peerInfoAvailableMediaPanes(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation, isMyProfile: Bool, chatLocationContextHolder: Atomic) -> Signal<[PeerInfoPaneKey]?, NoError> { + var tags: [(MessageTags, PeerInfoPaneKey)] = [] + + if !isMyProfile { + tags = [ + (.photoOrVideo, .media), + (.file, .files), + (.music, .music), + (.voiceOrInstantVideo, .voice), + (.webPage, .links), + (.gif, .gifs) + ] + } enum PaneState { case loading case empty @@ -545,7 +552,7 @@ public func keepPeerInfoScreenDataHot(context: AccountContext, peerId: PeerId, c case .user, .channel, .group: var signals: [Signal] = [] - signals.append(context.peerChannelMemberCategoriesContextsManager.profileData(postbox: context.account.postbox, network: context.account.network, peerId: peerId, customData: peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder) |> ignoreValues) |> ignoreValues) + signals.append(context.peerChannelMemberCategoriesContextsManager.profileData(postbox: context.account.postbox, network: context.account.network, peerId: peerId, customData: peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, isMyProfile: false, chatLocationContextHolder: chatLocationContextHolder) |> ignoreValues) |> ignoreValues) signals.append(context.peerChannelMemberCategoriesContextsManager.profilePhotos(postbox: context.account.postbox, network: context.account.network, peerId: peerId, fetch: peerInfoProfilePhotos(context: context, peerId: peerId)) |> ignoreValues) if case .user = inputData { @@ -843,6 +850,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id, linkedDiscussionPeer: nil, members: nil, storyListContext: hasStories == true ? storyListContext : nil, + storyArchiveListContext: nil, encryptionKeyFingerprint: nil, globalSettings: globalSettings, invitations: nil, @@ -859,7 +867,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id, } } -func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, isSettings: Bool, hintGroupInCommon: PeerId?, existingRequestsContext: PeerInvitationImportersContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic) -> Signal { +func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, isSettings: Bool, isMyProfile: Bool, hintGroupInCommon: PeerId?, existingRequestsContext: PeerInvitationImportersContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic) -> Signal { return peerInfoScreenInputData(context: context, peerId: peerId, isSettings: isSettings) |> mapToSignal { inputData -> Signal in let wasUpgradedGroup = Atomic(value: nil) @@ -881,6 +889,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen linkedDiscussionPeer: nil, members: nil, storyListContext: nil, + storyArchiveListContext: nil, encryptionKeyFingerprint: nil, globalSettings: nil, invitations: nil, @@ -896,7 +905,9 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen )) case let .user(userPeerId, secretChatId, kind): let groupsInCommon: GroupsInCommonContext? - if [.user, .bot].contains(kind) { + if isMyProfile { + groupsInCommon = nil + } else if [.user, .bot].contains(kind) { groupsInCommon = GroupsInCommonContext(account: context.account, peerId: userPeerId, hintGroupInCommon: hintGroupInCommon) } else { groupsInCommon = nil @@ -1008,6 +1019,23 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen } |> distinctUntilChanged + let hasStoryArchive: Signal + var storyArchiveListContext: PeerStoryListContext? + if isMyProfile { + let storyArchiveListContextValue = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: true) + storyArchiveListContext = storyArchiveListContextValue + hasStoryArchive = storyArchiveListContextValue.state + |> map { state -> Bool? in + if !state.hasCache { + return nil + } + return !state.items.isEmpty + } + |> distinctUntilChanged + } else { + hasStoryArchive = .single(false) + } + let accountIsPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) |> map { peer -> Bool in return peer?.isPremium ?? false @@ -1092,11 +1120,12 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen return combineLatest( context.account.viewTracker.peerView(peerId, updateData: true), - peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder), + peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, isMyProfile: isMyProfile, chatLocationContextHolder: chatLocationContextHolder), context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()), secretChatKeyFingerprint, status, hasStories, + hasStoryArchive, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, @@ -1104,10 +1133,15 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen hasSavedMessageTags, peerInfoPersonalChannel(context: context, peerId: peerId, isSettings: false) ) - |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, personalChannel -> PeerInfoScreenData in + |> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, personalChannel -> PeerInfoScreenData in var availablePanes = availablePanes - if let hasStories { + if isMyProfile { + availablePanes?.insert(.stories, at: 0) + if let hasStoryArchive, hasStoryArchive { + availablePanes?.insert(.storyArchive, at: 1) + } + } else if let hasStories { if hasStories, peerView.peers[peerView.peerId] is TelegramUser, peerView.peerId != context.account.peerId { availablePanes?.insert(.stories, at: 0) } @@ -1155,6 +1189,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen linkedDiscussionPeer: nil, members: nil, storyListContext: storyListContext, + storyArchiveListContext: storyArchiveListContext, encryptionKeyFingerprint: encryptionKeyFingerprint, globalSettings: nil, invitations: nil, @@ -1244,7 +1279,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen return combineLatest( context.account.viewTracker.peerView(peerId, updateData: true), - peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder), + peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, isMyProfile: false, chatLocationContextHolder: chatLocationContextHolder), context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()), status, invitationsContextPromise.get(), @@ -1325,6 +1360,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen linkedDiscussionPeer: discussionPeer, members: nil, storyListContext: storyListContext, + storyArchiveListContext: nil, encryptionKeyFingerprint: nil, globalSettings: nil, invitations: invitations, @@ -1517,7 +1553,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen return combineLatest(queue: .mainQueue(), context.account.viewTracker.peerView(groupId, updateData: true), - peerInfoAvailableMediaPanes(context: context, peerId: groupId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder), + peerInfoAvailableMediaPanes(context: context, peerId: groupId, chatLocation: chatLocation, isMyProfile: false, chatLocationContextHolder: chatLocationContextHolder), context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()), status, membersData, @@ -1618,6 +1654,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen linkedDiscussionPeer: discussionPeer, members: membersData, storyListContext: storyListContext, + storyArchiveListContext: nil, encryptionKeyFingerprint: nil, globalSettings: nil, invitations: invitations, diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift index 7e87eaba58..6c83253053 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift @@ -88,6 +88,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { private let isOpenedFromChat: Bool private let isSettings: Bool + private let isMyProfile: Bool private let videoCallsEnabled: Bool private let forumTopicThreadId: Int64? private let chatLocation: ChatLocation @@ -179,12 +180,13 @@ final class PeerInfoHeaderNode: ASDisplayNode { private var validLayout: (width: CGFloat, deviceMetrics: DeviceMetrics)? - init(context: AccountContext, controller: PeerInfoScreenImpl, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isMediaOnly: Bool, isSettings: Bool, forumTopicThreadId: Int64?, chatLocation: ChatLocation) { + init(context: AccountContext, controller: PeerInfoScreenImpl, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isMediaOnly: Bool, isSettings: Bool, isMyProfile: Bool, forumTopicThreadId: Int64?, chatLocation: ChatLocation) { self.context = context self.controller = controller self.isAvatarExpanded = avatarInitiallyExpanded self.isOpenedFromChat = isOpenedFromChat self.isSettings = isSettings + self.isMyProfile = isMyProfile self.videoCallsEnabled = true self.forumTopicThreadId = forumTopicThreadId self.chatLocation = chatLocation @@ -522,7 +524,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { let credibilityIcon: CredibilityIcon var verifiedIcon: CredibilityIcon = .none if let peer = peer { - if peer.id == self.context.account.peerId && !self.isSettings { + if peer.id == self.context.account.peerId && !self.isSettings && !self.isMyProfile { credibilityIcon = .none } else if peer.isFake { credibilityIcon = .fake @@ -535,7 +537,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { credibilityIcon = .emojiStatus(emojiStatus) } else if peer.isVerified { credibilityIcon = .verified - } else if peer.isPremium && !premiumConfiguration.isPremiumDisabled && (peer.id != self.context.account.peerId || self.isSettings) { + } else if peer.isPremium && !premiumConfiguration.isPremiumDisabled && (peer.id != self.context.account.peerId || self.isSettings || self.isMyProfile) { credibilityIcon = .premium } else { credibilityIcon = .none @@ -554,7 +556,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0 - let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, isModalOverlay: isModalOverlay, peer: state.isEditing ? peer : nil, threadData: threadData, chatLocation: self.chatLocation, cachedData: cachedData, isContact: isContact, isSettings: isSettings, presentationData: presentationData, transition: transition) + let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, isModalOverlay: isModalOverlay, peer: state.isEditing ? peer : nil, threadData: threadData, chatLocation: self.chatLocation, cachedData: cachedData, isContact: isContact, isSettings: isSettings || isMyProfile, presentationData: presentationData, transition: transition) transition.updateFrame(node: self.editingContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -contentOffset), size: CGSize(width: width, height: editingContentHeight))) let avatarOverlayFarme = self.editingContentNode.convert(self.editingContentNode.avatarNode.frame, to: self) @@ -694,7 +696,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { } else { let backgroundTransitionStepDistance: CGFloat = 50.0 var backgroundTransitionDistance: CGFloat = navigationHeight + panelWithAvatarHeight - backgroundTransitionStepDistance - if self.isSettings { + if self.isSettings || self.isMyProfile { backgroundTransitionDistance -= 100.0 } if isMediaOnly { @@ -978,15 +980,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.navigationBackgroundBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.opaqueBackgroundColor self.navigationSeparatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor - let navigationSeparatorAlpha: CGFloat - if isMediaOnly { - navigationSeparatorAlpha = 0.0 - } else if state.isEditing && self.isSettings { - //navigationSeparatorAlpha = min(1.0, contentOffset / (navigationHeight * 0.5)) - navigationSeparatorAlpha = 0.0 - } else { - navigationSeparatorAlpha = 0.0 - } + let navigationSeparatorAlpha: CGFloat = 0.0 transition.updateAlpha(node: self.navigationBackgroundBackgroundNode, alpha: 1.0 - navigationSeparatorAlpha) transition.updateAlpha(node: self.navigationSeparatorNode, alpha: navigationSeparatorAlpha) @@ -994,7 +988,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { let expandedAvatarControlsHeight: CGFloat = 61.0 var expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight) - if self.isSettings { + if self.isSettings || self.isMyProfile { expandedAvatarListHeight = expandedAvatarListHeight + 60.0 } else { expandedAvatarListHeight = expandedAvatarListHeight + 98.0 @@ -1002,8 +996,8 @@ final class PeerInfoHeaderNode: ASDisplayNode { let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight) - let actionButtonKeys: [PeerInfoHeaderButtonKey] = self.isSettings ? [] : peerInfoHeaderActionButtons(peer: peer, isSecretChat: isSecretChat, isContact: isContact) - let buttonKeys: [PeerInfoHeaderButtonKey] = self.isSettings ? [] : peerInfoHeaderButtons(peer: peer, cachedData: cachedData, isOpenedFromChat: self.isOpenedFromChat, isExpanded: true, videoCallsEnabled: width > 320.0 && self.videoCallsEnabled, isSecretChat: isSecretChat, isContact: isContact, threadInfo: threadData?.info) + let actionButtonKeys: [PeerInfoHeaderButtonKey] = (self.isSettings || self.isMyProfile) ? [] : peerInfoHeaderActionButtons(peer: peer, isSecretChat: isSecretChat, isContact: isContact) + let buttonKeys: [PeerInfoHeaderButtonKey] = (self.isSettings || self.isMyProfile) ? [] : peerInfoHeaderButtons(peer: peer, cachedData: cachedData, isOpenedFromChat: self.isOpenedFromChat, isExpanded: true, videoCallsEnabled: width > 320.0 && self.videoCallsEnabled, isSecretChat: isSecretChat, isContact: isContact, threadInfo: threadData?.info) var isPremium = false var isVerified = false @@ -1029,7 +1023,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { if let peer = peer { var title: String - if peer.id == self.context.account.peerId && !self.isSettings { + if peer.id == self.context.account.peerId && !self.isSettings && !self.isMyProfile { if case .replyThread = self.chatLocation { title = presentationData.strings.Conversation_MyNotes } else { @@ -1069,6 +1063,26 @@ final class PeerInfoHeaderNode: ASDisplayNode { smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white, shadowColor: titleShadowColor) usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white)) + } else if self.isMyProfile { + let subtitleColor: UIColor + subtitleColor = .white + + subtitleStringText = presentationData.strings.Presence_online + subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(17.0), color: subtitleColor) + smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white, shadowColor: titleShadowColor) + + usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white)) + + let (maybePanelStatusData, _, _) = panelStatusData + if let panelStatusData = maybePanelStatusData { + let subtitleColor: UIColor + if panelStatusData.isActivity { + subtitleColor = UIColor.white + } else { + subtitleColor = UIColor.white + } + panelSubtitleString = (panelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: subtitleColor)) + } } else if let _ = threadData { let subtitleColor: UIColor subtitleColor = UIColor.white @@ -1341,14 +1355,14 @@ final class PeerInfoHeaderNode: ASDisplayNode { let expandedTitleScale: CGFloat = 0.8 var bottomShadowHeight: CGFloat = 88.0 - if !self.isSettings { + if !self.isSettings && !self.isMyProfile { bottomShadowHeight += 100.0 } let bottomShadowFrame = CGRect(origin: CGPoint(x: 0.0, y: expandedAvatarHeight - bottomShadowHeight), size: CGSize(width: width, height: bottomShadowHeight)) transition.updateFrame(node: self.avatarListNode.listContainerNode.bottomShadowNode, frame: bottomShadowFrame, beginWithCurrentState: true) self.avatarListNode.listContainerNode.bottomShadowNode.update(size: bottomShadowFrame.size, transition: transition) - let singleTitleLockOffset: CGFloat = (peer?.id == self.context.account.peerId || subtitleSize.height.isZero) ? 8.0 : 0.0 + let singleTitleLockOffset: CGFloat = ((peer?.id == self.context.account.peerId && !self.isMyProfile) || subtitleSize.height.isZero) ? 8.0 : 0.0 let titleLockOffset: CGFloat = 7.0 + singleTitleLockOffset let titleMaxLockOffset: CGFloat = 7.0 @@ -1358,14 +1372,14 @@ final class PeerInfoHeaderNode: ASDisplayNode { if self.isAvatarExpanded { let minTitleSize = CGSize(width: titleSize.width * expandedTitleScale, height: titleSize.height * expandedTitleScale) var minTitleFrame = CGRect(origin: CGPoint(x: 16.0, y: expandedAvatarHeight - 58.0 - UIScreenPixel + (subtitleSize.height.isZero ? 10.0 : 0.0)), size: minTitleSize) - if !self.isSettings { + if !self.isSettings && !self.isMyProfile { minTitleFrame.origin.y -= 83.0 } titleFrame = CGRect(origin: CGPoint(x: minTitleFrame.midX - titleSize.width / 2.0, y: minTitleFrame.midY - titleSize.height / 2.0), size: titleSize) var titleCollapseOffset = titleFrame.midY - statusBarHeight - titleLockOffset - if case .regular = metrics.widthClass, !isSettings { + if case .regular = metrics.widthClass, !isSettings, !isMyProfile { titleCollapseOffset -= 7.0 } titleOffset = -min(titleCollapseOffset, contentOffset) @@ -1377,7 +1391,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { titleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 9.0 + (subtitleSize.height.isZero ? 11.0 : 0.0)), size: titleSize) var titleCollapseOffset = titleFrame.midY - statusBarHeight - titleLockOffset - if case .regular = metrics.widthClass, !isSettings { + if case .regular = metrics.widthClass, !isSettings, !isMyProfile { titleCollapseOffset -= 7.0 } titleOffset = -min(titleCollapseOffset, contentOffset) @@ -1408,7 +1422,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { let effectiveAreaExpansionFraction: CGFloat if state.isEditing { effectiveAreaExpansionFraction = 0.0 - } else if isSettings { + } else if isSettings || isMyProfile { var paneAreaExpansionDelta = (self.frame.maxY - navigationHeight) - contentOffset paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance @@ -1716,12 +1730,12 @@ final class PeerInfoHeaderNode: ASDisplayNode { } else { rawHeight = navigationHeight + panelWithAvatarHeight var expandablePart: CGFloat = panelWithAvatarHeight - contentOffset - if self.isSettings { + if self.isSettings || self.isMyProfile { expandablePart += 20.0 } else { if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId { expandablePart = 0.0 - } else if peer?.id == self.context.account.peerId { + } else if peer?.id == self.context.account.peerId && !self.isMyProfile { expandablePart = 0.0 } else { expandablePart += 99.0 @@ -2140,7 +2154,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { } if !state.isEditing { - if !isSettings { + if !isSettings && !isMyProfile { if self.isAvatarExpanded { resolvedHeight -= 21.0 } else { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift index ce1c371908..173d3f0824 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift @@ -365,6 +365,7 @@ private final class PeerInfoPendingPane { hasBecomeReady: @escaping (PeerInfoPaneKey) -> Void, parentController: ViewController?, openMediaCalendar: @escaping () -> Void, + openAddStory: @escaping () -> Void, paneDidScroll: @escaping () -> Void, ensureRectVisible: @escaping (UIView, CGRect) -> Void, externalDataUpdated: @escaping (ContainedViewLayoutTransition) -> Void @@ -372,8 +373,8 @@ private final class PeerInfoPendingPane { let captureProtected = data.peer?.isCopyProtectionEnabled ?? false let paneNode: PeerInfoPaneNode switch key { - case .stories: - let visualPaneNode = PeerInfoStoryPaneNode(context: context, peerId: peerId, chatLocation: chatLocation, contentType: .photoOrVideo, captureProtected: captureProtected, isSaved: false, isArchive: false, navigationController: chatControllerInteraction.navigationController, listContext: data.storyListContext) + case .stories, .storyArchive: + let visualPaneNode = PeerInfoStoryPaneNode(context: context, peerId: peerId, chatLocation: chatLocation, contentType: .photoOrVideo, captureProtected: captureProtected, isSaved: false, isArchive: key == .storyArchive, isProfileEmbedded: true, navigationController: chatControllerInteraction.navigationController, listContext: key == .storyArchive ? data.storyArchiveListContext : data.storyListContext) paneNode = visualPaneNode visualPaneNode.openCurrentDate = { openMediaCalendar() @@ -384,6 +385,9 @@ private final class PeerInfoPendingPane { visualPaneNode.ensureRectVisible = { sourceView, rect in ensureRectVisible(sourceView, rect) } + visualPaneNode.emptyAction = { + openAddStory() + } case .media: let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .photoOrVideo, captureProtected: captureProtected) paneNode = visualPaneNode @@ -442,7 +446,7 @@ private final class PeerInfoPendingPane { } } -final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { +final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegate { private let context: AccountContext private let peerId: PeerId private let chatLocation: ChatLocation @@ -500,6 +504,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat var requestUpdate: ((ContainedViewLayoutTransition) -> Void)? var openMediaCalendar: (() -> Void)? + var openAddStory: (() -> Void)? var paneDidScroll: (() -> Void)? var ensurePaneRectVisible: ((UIView, CGRect) -> Void)? @@ -597,7 +602,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat } return [.left, .right] }) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.view.addGestureRecognizer(panRecognizer) @@ -848,6 +853,9 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat openMediaCalendar: { [weak self] in self?.openMediaCalendar?() }, + openAddStory: { [weak self] in + self?.openAddStory?() + }, paneDidScroll: { [weak self] in self?.paneDidScroll?() }, @@ -1010,6 +1018,9 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat switch key { case .stories: title = presentationData.strings.PeerInfo_PaneStories + case .storyArchive: + //TODO:localize + title = "Archived Posts" case .media: title = presentationData.strings.PeerInfo_PaneMedia case .files: diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 4256d39642..69a9adc75c 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -518,6 +518,7 @@ private enum PeerInfoSettingsSection { case emojiStatus case powerSaving case businessSetup + case profile } private enum PeerInfoReportType { @@ -725,6 +726,7 @@ private enum SettingsSection: Int, CaseIterable { case edit case phone case accounts + case myProfile case proxy case apps case shortcuts @@ -850,6 +852,11 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p })) } + //TODO:localize + items[.myProfile]!.append(PeerInfoScreenDisclosureItem(id: 0, text: "My Profile", icon: PresentationResourcesSettings.myProfile, action: { + interaction.openSettings(.profile) + })) + if !settings.proxySettings.servers.isEmpty { let proxyType: String if settings.proxySettings.enabled, let activeServer = settings.proxySettings.activeServer { @@ -892,10 +899,6 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p } } - items[.apps]!.append(PeerInfoScreenDisclosureItem(id: 0, text: presentationData.strings.Settings_MyStories, icon: PresentationResourcesSettings.stories, action: { - interaction.openSettings(.stories) - })) - items[.shortcuts]!.append(PeerInfoScreenDisclosureItem(id: 1, text: presentationData.strings.Settings_SavedMessages, icon: PresentationResourcesSettings.savedMessages, action: { interaction.openSettings(.savedMessages) })) @@ -994,7 +997,7 @@ private func settingsItems(data: PeerInfoScreenData?, context: AccountContext, p return result } -private func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, context: AccountContext, presentationData: PresentationData, interaction: PeerInfoInteraction) -> [(AnyHashable, [PeerInfoScreenItem])] { +private func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, context: AccountContext, presentationData: PresentationData, interaction: PeerInfoInteraction, isMyProfile: Bool) -> [(AnyHashable, [PeerInfoScreenItem])] { guard let data = data else { return [] } @@ -1028,7 +1031,9 @@ private func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoStat let ItemBirthdayHelp = 12 let ItemPeerPersonalChannel = 13 - items[.help]!.append(PeerInfoScreenCommentItem(id: ItemNameHelp, text: presentationData.strings.EditProfile_NameAndPhotoOrVideoHelp)) + if !isMyProfile { + items[.help]!.append(PeerInfoScreenCommentItem(id: ItemNameHelp, text: presentationData.strings.EditProfile_NameAndPhotoOrVideoHelp)) + } if let cachedData = data.cachedData as? CachedUserData { items[.bio]!.append(PeerInfoScreenMultilineInputItem(id: ItemBio, text: state.updatingBio ?? (cachedData.about ?? ""), placeholder: presentationData.strings.UserInfo_About_Placeholder, textUpdated: { updatedText in @@ -1056,28 +1061,31 @@ private func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoStat birthDateString = presentationData.strings.Settings_Birthday_Add } - let isEditingBirthDate = state.isEditingBirthDate - items[.birthday]!.append(PeerInfoScreenDisclosureItem(id: ItemBirthday, label: .coloredText(birthDateString, isEditingBirthDate ? .accent : .generic), text: presentationData.strings.Settings_Birthday, icon: nil, hasArrow: false, action: { - interaction.updateIsEditingBirthdate(!isEditingBirthDate) - })) - if isEditingBirthDate, let birthday { - items[.birthday]!.append(PeerInfoScreenBirthdatePickerItem(id: ItemBirthdayPicker, value: birthday, valueUpdated: { value in - interaction.updateBirthdate(value) + if !isMyProfile { + let isEditingBirthDate = state.isEditingBirthDate + items[.birthday]!.append(PeerInfoScreenDisclosureItem(id: ItemBirthday, label: .coloredText(birthDateString, isEditingBirthDate ? .accent : .generic), text: presentationData.strings.Settings_Birthday, icon: nil, hasArrow: false, action: { + interaction.updateIsEditingBirthdate(!isEditingBirthDate) })) - items[.birthday]!.append(PeerInfoScreenActionItem(id: ItemBirthdayRemove, text: presentationData.strings.Settings_Birthday_Remove, alignment: .natural, action: { - interaction.updateBirthdate(.some(nil)) - interaction.updateIsEditingBirthdate(false) + if isEditingBirthDate, let birthday { + items[.birthday]!.append(PeerInfoScreenBirthdatePickerItem(id: ItemBirthdayPicker, value: birthday, valueUpdated: { value in + interaction.updateBirthdate(value) + })) + items[.birthday]!.append(PeerInfoScreenActionItem(id: ItemBirthdayRemove, text: presentationData.strings.Settings_Birthday_Remove, alignment: .natural, action: { + interaction.updateBirthdate(.some(nil)) + interaction.updateIsEditingBirthdate(false) + })) + } + + + var birthdayIsForContactsOnly = false + if let birthdayPrivacy = data.globalSettings?.privacySettings?.birthday, case .enableContacts = birthdayPrivacy { + birthdayIsForContactsOnly = true + } + items[.birthday]!.append(PeerInfoScreenCommentItem(id: ItemBirthdayHelp, text: birthdayIsForContactsOnly ? presentationData.strings.Settings_Birthday_ContactsHelp : presentationData.strings.Settings_Birthday_Help, linkAction: { _ in + interaction.openBirthdatePrivacy() })) } - var birthdayIsForContactsOnly = false - if let birthdayPrivacy = data.globalSettings?.privacySettings?.birthday, case .enableContacts = birthdayPrivacy { - birthdayIsForContactsOnly = true - } - items[.birthday]!.append(PeerInfoScreenCommentItem(id: ItemBirthdayHelp, text: birthdayIsForContactsOnly ? presentationData.strings.Settings_Birthday_ContactsHelp : presentationData.strings.Settings_Birthday_Help, linkAction: { _ in - interaction.openBirthdatePrivacy() - })) - if let user = data.peer as? TelegramUser { items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPhoneNumber, label: .text(user.phone.flatMap({ formatPhoneNumber(context: context, number: $0) }) ?? ""), text: presentationData.strings.Settings_PhoneNumber, action: { interaction.openSettings(.phoneNumber) @@ -1091,7 +1099,7 @@ private func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoStat interaction.openSettings(.username) })) - if let peer = data.peer as? TelegramUser { + if !isMyProfile, let peer = data.peer as? TelegramUser { var colors: [PeerNameColors.Colors] = [] if let nameColor = peer.nameColor.flatMap({ context.peerNameColors.get($0, dark: presentationData.theme.overallDarkAppearance) }) { colors.append(nameColor) @@ -1123,9 +1131,11 @@ private func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoStat } } - items[.account]!.append(PeerInfoScreenActionItem(id: ItemAddAccount, text: presentationData.strings.Settings_AddAnotherAccount, alignment: .center, action: { - interaction.openSettings(.addAccount) - })) + if !isMyProfile { + items[.account]!.append(PeerInfoScreenActionItem(id: ItemAddAccount, text: presentationData.strings.Settings_AddAnotherAccount, alignment: .center, action: { + interaction.openSettings(.addAccount) + })) + } var hasPremiumAccounts = false if data.peer?.isPremium == true && !context.account.testingEnvironment { @@ -1142,11 +1152,13 @@ private func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoStat } } - items[.account]!.append(PeerInfoScreenCommentItem(id: ItemAddAccountHelp, text: hasPremiumAccounts ? presentationData.strings.Settings_AddAnotherAccount_PremiumHelp : presentationData.strings.Settings_AddAnotherAccount_Help)) - - items[.logout]!.append(PeerInfoScreenActionItem(id: ItemLogout, text: presentationData.strings.Settings_Logout, color: .destructive, alignment: .center, action: { - interaction.openSettings(.logout) - })) + if !isMyProfile { + items[.account]!.append(PeerInfoScreenCommentItem(id: ItemAddAccountHelp, text: hasPremiumAccounts ? presentationData.strings.Settings_AddAnotherAccount_PremiumHelp : presentationData.strings.Settings_AddAnotherAccount_Help)) + + items[.logout]!.append(PeerInfoScreenActionItem(id: ItemLogout, text: presentationData.strings.Settings_Logout, color: .destructive, alignment: .center, action: { + interaction.openSettings(.logout) + })) + } var result: [(AnyHashable, [PeerInfoScreenItem])] = [] for section in Section.allCases { @@ -2359,7 +2371,7 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL return result } -final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodeProtocol, UIScrollViewDelegate { +final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodeProtocol, ASScrollViewDelegate { private weak var controller: PeerInfoScreenImpl? private let context: AccountContext @@ -2371,6 +2383,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro private let chatLocationContextHolder: Atomic let isSettings: Bool + let isMyProfile: Bool private let isMediaOnly: Bool let initialExpandPanes: Bool @@ -2488,7 +2501,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } private var didSetReady = false - init(controller: PeerInfoScreenImpl, context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool, hintGroupInCommon: PeerId?, requestsContext: PeerInvitationImportersContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, initialPaneKey: PeerInfoPaneKey?) { + init(controller: PeerInfoScreenImpl, context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool, isMyProfile: Bool, hintGroupInCommon: PeerId?, requestsContext: PeerInvitationImportersContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, initialPaneKey: PeerInfoPaneKey?) { self.controller = controller self.context = context self.peerId = peerId @@ -2499,9 +2512,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro self.reactionSourceMessageId = reactionSourceMessageId self.callMessages = callMessages self.isSettings = isSettings + self.isMyProfile = isMyProfile self.chatLocation = chatLocation self.chatLocationContextHolder = chatLocationContextHolder - self.isMediaOnly = context.account.peerId == peerId && !isSettings + self.isMediaOnly = context.account.peerId == peerId && !isSettings && !isMyProfile self.initialExpandPanes = initialPaneKey != nil self.scrollNode = ASScrollNode() @@ -2512,7 +2526,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro if case let .replyThread(message) = chatLocation { forumTopicThreadId = message.threadId } - self.headerNode = PeerInfoHeaderNode(context: context, controller: controller, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, isMediaOnly: self.isMediaOnly, isSettings: isSettings, forumTopicThreadId: forumTopicThreadId, chatLocation: self.chatLocation) + self.headerNode = PeerInfoHeaderNode(context: context, controller: controller, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, isMediaOnly: self.isMediaOnly, isSettings: isSettings, isMyProfile: isMyProfile, forumTopicThreadId: forumTopicThreadId, chatLocation: self.chatLocation) self.paneContainerNode = PeerInfoPaneContainerNode(context: context, updatedPresentationData: controller.updatedPresentationData, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, isMediaOnly: self.isMediaOnly, initialPaneKey: initialPaneKey) super.init() @@ -3297,7 +3311,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } self.scrollNode.view.alwaysBounceVertical = true self.scrollNode.view.scrollsToTop = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.scrollNode) self.scrollNode.addSubnode(self.paneContainerNode) @@ -3436,6 +3450,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } strongSelf.openMediaCalendar() } + + self.paneContainerNode.openAddStory = { [weak self] in + guard let self else { + return + } + self.headerNode.navigationButtonContainer.performAction?(.postStory, nil, nil) + } self.paneContainerNode.paneDidScroll = { [weak self] in guard let strongSelf = self else { @@ -4180,7 +4201,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro strongSelf.controller?.present(emojiStatusSelectionController, in: .window(.root)) } } else { - screenData = peerInfoScreenData(context: context, peerId: peerId, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, isSettings: self.isSettings, hintGroupInCommon: hintGroupInCommon, existingRequestsContext: requestsContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder) + screenData = peerInfoScreenData(context: context, peerId: peerId, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, isSettings: self.isSettings, isMyProfile: self.isMyProfile, hintGroupInCommon: hintGroupInCommon, existingRequestsContext: requestsContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder) var previousTimestamp: Double? self.headerNode.displayPremiumIntro = { [weak self] sourceView, peerStatus, emojiStatusFileAndPack, white in @@ -9186,6 +9207,18 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro self.headerNode.navigationButtonContainer.performAction?(.edit, nil, nil) case .proxy: self.controller?.push(proxySettingsController(context: self.context)) + case .profile: + self.controller?.push(PeerInfoScreenImpl( + context: self.context, + updatedPresentationData: self.controller?.updatedPresentationData, + peerId: self.context.account.peerId, + avatarInitiallyExpanded: false, + isOpenedFromChat: false, + nearbyPeerDistance: nil, + reactionSourceMessageId: nil, + callMessages: [], + isMyProfile: true + )) case .stories: push(PeerInfoStoryGridScreen(context: self.context, peerId: self.context.account.peerId, scope: .saved)) case .savedMessages: @@ -10503,7 +10536,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } var validEditingSections: [AnyHashable] = [] - let editItems = self.isSettings ? settingsEditingItems(data: self.data, state: self.state, context: self.context, presentationData: self.presentationData, interaction: self.interaction) : editingItems(data: self.data, state: self.state, chatLocation: self.chatLocation, context: self.context, presentationData: self.presentationData, interaction: self.interaction) + let editItems = (self.isSettings || self.isMyProfile) ? settingsEditingItems(data: self.data, state: self.state, context: self.context, presentationData: self.presentationData, interaction: self.interaction, isMyProfile: self.isMyProfile) : editingItems(data: self.data, state: self.state, chatLocation: self.chatLocation, context: self.context, presentationData: self.presentationData, interaction: self.interaction) for (sectionId, sectionItems) in editItems { var insets = UIEdgeInsets() @@ -10827,7 +10860,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } else if peerInfoCanEdit(peer: self.data?.peer, chatLocation: self.chatLocation, threadData: self.data?.threadData, cachedData: self.data?.cachedData, isContact: self.data?.isContact) { rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false)) } - if let data = self.data, !data.isPremiumRequiredForStoryPosting || data.accountIsPremium, let channel = data.peer as? TelegramChannel, channel.hasPermission(.postStories) { + if let data = self.data, !data.isPremiumRequiredForStoryPosting || data.accountIsPremium, let channel = data.peer as? TelegramChannel, channel.hasPermission(.postStories) { + rightNavigationButtons.insert(PeerInfoHeaderNavigationButtonSpec(key: .postStory, isForExpandedView: false), at: 0) + } else if self.isMyProfile { rightNavigationButtons.insert(PeerInfoHeaderNavigationButtonSpec(key: .postStory, isForExpandedView: false), at: 0) } @@ -11182,6 +11217,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc private let reactionSourceMessageId: MessageId? private let callMessages: [Message] private let isSettings: Bool + private let isMyProfile: Bool private let hintGroupInCommon: PeerId? private weak var requestsContext: PeerInvitationImportersContext? private let switchToRecommendedChannels: Bool @@ -11241,7 +11277,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)? - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool = false, hintGroupInCommon: PeerId? = nil, requestsContext: PeerInvitationImportersContext? = nil, forumTopicThread: ChatReplyThreadMessage? = nil, switchToRecommendedChannels: Bool = false) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool = false, isMyProfile: Bool = false, hintGroupInCommon: PeerId? = nil, requestsContext: PeerInvitationImportersContext? = nil, forumTopicThread: ChatReplyThreadMessage? = nil, switchToRecommendedChannels: Bool = false) { self.context = context self.updatedPresentationData = updatedPresentationData self.peerId = peerId @@ -11251,6 +11287,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc self.reactionSourceMessageId = reactionSourceMessageId self.callMessages = callMessages self.isSettings = isSettings + self.isMyProfile = isMyProfile self.hintGroupInCommon = hintGroupInCommon self.requestsContext = requestsContext self.switchToRecommendedChannels = switchToRecommendedChannels @@ -11587,7 +11624,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc } override public func loadDisplayNode() { - self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId, avatarInitiallyExpanded: self.avatarInitiallyExpanded, isOpenedFromChat: self.isOpenedFromChat, nearbyPeerDistance: self.nearbyPeerDistance, reactionSourceMessageId: self.reactionSourceMessageId, callMessages: self.callMessages, isSettings: self.isSettings, hintGroupInCommon: self.hintGroupInCommon, requestsContext: self.requestsContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, initialPaneKey: self.switchToRecommendedChannels ? .recommended : nil) + self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId, avatarInitiallyExpanded: self.avatarInitiallyExpanded, isOpenedFromChat: self.isOpenedFromChat, nearbyPeerDistance: self.nearbyPeerDistance, reactionSourceMessageId: self.reactionSourceMessageId, callMessages: self.callMessages, isSettings: self.isSettings, isMyProfile: self.isMyProfile, hintGroupInCommon: self.hintGroupInCommon, requestsContext: self.requestsContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, initialPaneKey: self.switchToRecommendedChannels ? .recommended : nil) self.controllerNode.accountsAndPeers.set(self.accountsAndPeers.get() |> map { $0.1 }) self.controllerNode.activeSessionsContextAndCount.set(self.activeSessionsContextAndCount.get()) self.cachedDataPromise.set(self.controllerNode.cachedDataPromise.get()) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift index 1ae74c8100..1e877ef2cc 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen/Sources/PeerInfoStoryGridScreen.swift @@ -461,6 +461,7 @@ final class PeerInfoStoryGridScreenComponent: Component { captureProtected: false, isSaved: true, isArchive: component.scope == .archive, + isProfileEmbedded: false, navigationController: { [weak self] in guard let self else { return nil diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift index 99d64be443..bb434fed1a 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoStoryPaneNode.swift @@ -189,6 +189,62 @@ private let viewCountImage: UIImage = { return image! }() +private let privacyTypeImageScaleFactor: CGFloat = { + return 0.9 +}() + +private let privacyTypeEveryoneImage: UIImage = { + let baseImage = UIImage(bundleImageName: "Stories/PrivacyEveryone")! + let imageSize = CGSize(width: floor(baseImage.size.width * privacyTypeImageScaleFactor), height: floor(baseImage.size.width * privacyTypeImageScaleFactor)) + let image = generateImage(imageSize, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + UIGraphicsPushContext(context) + baseImage.draw(in: CGRect(origin: CGPoint(), size: size)) + UIGraphicsPopContext() + }) + return image! +}() + +private let privacyTypeContactsImage: UIImage = { + let baseImage = UIImage(bundleImageName: "Stories/PrivacyContacts")! + let imageSize = CGSize(width: floor(baseImage.size.width * privacyTypeImageScaleFactor), height: floor(baseImage.size.width * privacyTypeImageScaleFactor)) + let image = generateImage(imageSize, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + UIGraphicsPushContext(context) + baseImage.draw(in: CGRect(origin: CGPoint(), size: size)) + UIGraphicsPopContext() + }) + return image! +}() + +private let privacyTypeCloseFriendsImage: UIImage = { + let baseImage = UIImage(bundleImageName: "Stories/PrivacyCloseFriends")! + let imageSize = CGSize(width: floor(baseImage.size.width * privacyTypeImageScaleFactor), height: floor(baseImage.size.width * privacyTypeImageScaleFactor)) + let image = generateImage(imageSize, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + UIGraphicsPushContext(context) + baseImage.draw(in: CGRect(origin: CGPoint(), size: size)) + UIGraphicsPopContext() + }) + return image! +}() + +private let privacyTypeSelectedImage: UIImage = { + let baseImage = UIImage(bundleImageName: "Stories/PrivacySelectedContacts")! + let imageSize = CGSize(width: floor(baseImage.size.width * privacyTypeImageScaleFactor), height: floor(baseImage.size.width * privacyTypeImageScaleFactor)) + let image = generateImage(imageSize, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + UIGraphicsPushContext(context) + baseImage.draw(in: CGRect(origin: CGPoint(), size: size)) + UIGraphicsPopContext() + }) + return image! +}() + private final class DurationLayer: CALayer { override init() { super.init() @@ -264,6 +320,41 @@ private final class DurationLayer: CALayer { self.contents = image?.cgImage } } + + func update(privacyType: Stories.Item.Privacy.Base, isMin: Bool) { + if isMin { + self.contents = nil + } else { + let iconImage: UIImage + switch privacyType { + case .everyone: + iconImage = privacyTypeEveryoneImage + case .contacts: + iconImage = privacyTypeContactsImage + case .closeFriends: + iconImage = privacyTypeCloseFriendsImage + case .nobody: + iconImage = privacyTypeSelectedImage + } + + let sideInset: CGFloat = 0.0 + let verticalInset: CGFloat = 0.0 + let image = generateImage(CGSize(width: iconImage.size.width + sideInset * 2.0, height: iconImage.size.height + verticalInset * 2.0), rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + context.setBlendMode(.normal) + + context.setShadow(offset: CGSize(width: 0.0, height: 0.0), blur: 2.5, color: UIColor(rgb: 0x000000, alpha: 0.22).cgColor) + + UIGraphicsPushContext(context) + + iconImage.draw(in: CGRect(origin: CGPoint(x: (size.width - iconImage.size.width) * 0.5, y: (size.height - iconImage.size.height) * 0.5), size: iconImage.size)) + + UIGraphicsPopContext() + }) + self.contents = image?.cgImage + } + } } private protocol ItemLayer: SparseItemGridLayer { @@ -276,7 +367,7 @@ private protocol ItemLayer: SparseItemGridLayer { var hasContents: Bool { get set } func setSpoilerContents(_ contents: Any?) - func updateDuration(viewCount: Int32?, duration: Int32?, isMin: Bool, minFactor: CGFloat) + func updateDuration(viewCount: Int32?, duration: Int32?, privacy: Stories.Item.Privacy.Base?, isMin: Bool, minFactor: CGFloat) func updateSelection(theme: CheckNodeTheme, isSelected: Bool?, animated: Bool) func updateHasSpoiler(hasSpoiler: Bool) @@ -288,8 +379,10 @@ private final class GenericItemLayer: CALayer, ItemLayer { var item: VisualMediaItem? var viewCountLayer: DurationLayer? var durationLayer: DurationLayer? + var privacyTypeLayer: DurationLayer? var leftShadowLayer: SimpleLayer? var rightShadowLayer: SimpleLayer? + var topRightShadowLayer: SimpleLayer? var minFactor: CGFloat = 1.0 var selectionLayer: GridMessageSelectionLayer? var dustLayer: MediaDustLayer? @@ -335,7 +428,7 @@ private final class GenericItemLayer: CALayer, ItemLayer { self.item = item } - func updateDuration(viewCount: Int32?, duration: Int32?, isMin: Bool, minFactor: CGFloat) { + func updateDuration(viewCount: Int32?, duration: Int32?, privacy: Stories.Item.Privacy.Base?, isMin: Bool, minFactor: CGFloat) { self.minFactor = minFactor if let viewCount { @@ -371,6 +464,23 @@ private final class GenericItemLayer: CALayer, ItemLayer { durationLayer.removeFromSuperlayer() } + if let privacy { + if let privacyTypeLayer = self.privacyTypeLayer { + privacyTypeLayer.update(privacyType: privacy, isMin: isMin) + } else { + let privacyTypeLayer = DurationLayer() + privacyTypeLayer.contentsGravity = .bottomRight + privacyTypeLayer.update(privacyType: privacy, isMin: isMin) + self.addSublayer(privacyTypeLayer) + privacyTypeLayer.frame = CGRect(origin: CGPoint(x: self.bounds.width - 2.0, y: 3.0), size: CGSize()) + privacyTypeLayer.transform = CATransform3DMakeScale(minFactor, minFactor, 1.0) + self.privacyTypeLayer = privacyTypeLayer + } + } else if let privacyTypeLayer = self.privacyTypeLayer { + self.privacyTypeLayer = nil + privacyTypeLayer.removeFromSuperlayer() + } + let size = self.bounds.size if self.viewCountLayer != nil { @@ -404,6 +514,22 @@ private final class GenericItemLayer: CALayer, ItemLayer { rightShadowLayer.removeFromSuperlayer() } } + + if self.privacyTypeLayer != nil { + if self.topRightShadowLayer == nil { + let topRightShadowLayer = SimpleLayer() + self.topRightShadowLayer = topRightShadowLayer + self.insertSublayer(topRightShadowLayer, at: 0) + topRightShadowLayer.contents = rightShadowImage.cgImage + let shadowSize = CGSize(width: min(size.width, rightShadowImage.size.width), height: min(size.height, rightShadowImage.size.height)) + topRightShadowLayer.frame = CGRect(origin: CGPoint(x: size.width - shadowSize.width, y: size.height - shadowSize.height), size: shadowSize) + } + } else { + if let topRightShadowLayer = self.topRightShadowLayer { + self.topRightShadowLayer = nil + topRightShadowLayer.removeFromSuperlayer() + } + } } func updateSelection(theme: CheckNodeTheme, isSelected: Bool?, animated: Bool) { @@ -468,6 +594,9 @@ private final class GenericItemLayer: CALayer, ItemLayer { if let durationLayer = self.durationLayer { durationLayer.frame = CGRect(origin: CGPoint(x: size.width - 3.0, y: size.height - 4.0), size: CGSize()) } + if let privacyTypeLayer = self.privacyTypeLayer { + privacyTypeLayer.frame = CGRect(origin: CGPoint(x: size.width - 2.0, y: 3.0), size: CGSize()) + } if let leftShadowLayer = self.leftShadowLayer { let shadowSize = CGSize(width: min(size.width, leftShadowImage.size.width), height: min(size.height, leftShadowImage.size.height)) @@ -479,6 +608,11 @@ private final class GenericItemLayer: CALayer, ItemLayer { rightShadowLayer.frame = CGRect(origin: CGPoint(x: size.width - shadowSize.width, y: size.height - shadowSize.height), size: shadowSize) } + if let topRightShadowLayer = self.topRightShadowLayer { + let shadowSize = CGSize(width: min(size.width, rightShadowImage.size.width), height: min(size.height, rightShadowImage.size.height)) + topRightShadowLayer.frame = CGRect(origin: CGPoint(x: size.width - shadowSize.width, y: 0.0), size: shadowSize) + } + if let binding = binding as? SparseItemGridBindingImpl, let item = item as? VisualMediaItem, let previousItem = self.item, previousItem.story.media.id != item.story.media.id { binding.bindLayers(items: [item], layers: [displayItem], size: size, insets: insets, synchronous: .none) } @@ -489,11 +623,14 @@ private final class ItemTransitionView: UIView { private weak var itemLayer: CALayer? private var copyDurationLayer: SimpleLayer? private var copyViewCountLayer: SimpleLayer? + private var copyPrivacyTypeLayer: SimpleLayer? private var copyLeftShadowLayer: SimpleLayer? private var copyRightShadowLayer: SimpleLayer? + private var copyTopRightShadowLayer: SimpleLayer? private var viewCountLayerBottomLeftPosition: CGPoint? private var durationLayerBottomLeftPosition: CGPoint? + private var privacyTypeLayerTopRightPosition: CGPoint? init(itemLayer: CALayer?) { self.itemLayer = itemLayer @@ -505,13 +642,17 @@ private final class ItemTransitionView: UIView { var viewCountLayer: CALayer? var durationLayer: CALayer? + var privacyTypeLayer: CALayer? var leftShadowLayer: CALayer? var rightShadowLayer: CALayer? + var topRightShadowLayer: CALayer? if let itemLayer = itemLayer as? GenericItemLayer { viewCountLayer = itemLayer.viewCountLayer durationLayer = itemLayer.durationLayer + privacyTypeLayer = itemLayer.privacyTypeLayer leftShadowLayer = itemLayer.leftShadowLayer rightShadowLayer = itemLayer.rightShadowLayer + topRightShadowLayer = itemLayer.topRightShadowLayer self.layer.contents = itemLayer.contents } @@ -537,6 +678,17 @@ private final class ItemTransitionView: UIView { self.copyRightShadowLayer = copyLayer } + if let topRightShadowLayer { + let copyLayer = SimpleLayer() + copyLayer.contents = topRightShadowLayer.contents + copyLayer.contentsRect = topRightShadowLayer.contentsRect + copyLayer.contentsGravity = topRightShadowLayer.contentsGravity + copyLayer.contentsScale = topRightShadowLayer.contentsScale + copyLayer.frame = topRightShadowLayer.frame + self.layer.addSublayer(copyLayer) + self.copyTopRightShadowLayer = copyLayer + } + if let viewCountLayer { let copyViewCountLayer = SimpleLayer() copyViewCountLayer.contents = viewCountLayer.contents @@ -550,6 +702,19 @@ private final class ItemTransitionView: UIView { self.viewCountLayerBottomLeftPosition = CGPoint(x: viewCountLayer.frame.minX, y: itemLayer.bounds.height - viewCountLayer.frame.maxY) } + if let privacyTypeLayer { + let copyPrivacyTypeLayer = SimpleLayer() + copyPrivacyTypeLayer.contents = privacyTypeLayer.contents + copyPrivacyTypeLayer.contentsRect = privacyTypeLayer.contentsRect + copyPrivacyTypeLayer.contentsGravity = privacyTypeLayer.contentsGravity + copyPrivacyTypeLayer.contentsScale = privacyTypeLayer.contentsScale + copyPrivacyTypeLayer.frame = privacyTypeLayer.frame + self.layer.addSublayer(copyPrivacyTypeLayer) + self.copyPrivacyTypeLayer = copyPrivacyTypeLayer + + self.privacyTypeLayerTopRightPosition = CGPoint(x: itemLayer.bounds.width - privacyTypeLayer.frame.maxX, y: privacyTypeLayer.frame.minY) + } + if let durationLayer { let copyDurationLayer = SimpleLayer() copyDurationLayer.contents = durationLayer.contents @@ -576,8 +741,12 @@ private final class ItemTransitionView: UIView { transition.setFrame(layer: copyDurationLayer, frame: CGRect(origin: CGPoint(x: size.width - durationLayerBottomLeftPosition.x - copyDurationLayer.bounds.width, y: size.height - durationLayerBottomLeftPosition.y - copyDurationLayer.bounds.height), size: copyDurationLayer.bounds.size)) } - if let copyViewCountLayer = self.copyViewCountLayer, let viewcountLayerBottomLeftPosition = self.viewCountLayerBottomLeftPosition { - transition.setFrame(layer: copyViewCountLayer, frame: CGRect(origin: CGPoint(x: viewcountLayerBottomLeftPosition.x, y: size.height - viewcountLayerBottomLeftPosition.y - copyViewCountLayer.bounds.height), size: copyViewCountLayer.bounds.size)) + if let copyViewCountLayer = self.copyViewCountLayer, let viewCountLayerBottomLeftPosition = self.viewCountLayerBottomLeftPosition { + transition.setFrame(layer: copyViewCountLayer, frame: CGRect(origin: CGPoint(x: viewCountLayerBottomLeftPosition.x, y: size.height - viewCountLayerBottomLeftPosition.y - copyViewCountLayer.bounds.height), size: copyViewCountLayer.bounds.size)) + } + + if let privacyTypeLayer = self.copyPrivacyTypeLayer, let privacyTypeLayerTopRightPosition = self.privacyTypeLayerTopRightPosition { + transition.setFrame(layer: privacyTypeLayer, frame: CGRect(origin: CGPoint(x: size.width - privacyTypeLayerTopRightPosition.x, y: privacyTypeLayerTopRightPosition.y), size: privacyTypeLayer.bounds.size)) } if let copyLeftShadowLayer = self.copyLeftShadowLayer { @@ -587,6 +756,10 @@ private final class ItemTransitionView: UIView { if let copyRightShadowLayer = self.copyRightShadowLayer { transition.setFrame(layer: copyRightShadowLayer, frame: CGRect(origin: CGPoint(x: size.width - copyRightShadowLayer.bounds.width, y: size.height - copyRightShadowLayer.bounds.height), size: copyRightShadowLayer.bounds.size)) } + + if let copyTopRightShadowLayer = self.copyTopRightShadowLayer { + transition.setFrame(layer: copyTopRightShadowLayer, frame: CGRect(origin: CGPoint(x: size.width - copyTopRightShadowLayer.bounds.width, y: 0.0), size: copyTopRightShadowLayer.bounds.size)) + } } } @@ -595,6 +768,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding { let chatLocation: ChatLocation let directMediaImageCache: DirectMediaImageCache let captureProtected: Bool + let displayPrivacy: Bool var strings: PresentationStrings var chatPresentationData: ChatPresentationData var checkNodeTheme: CheckNodeTheme @@ -613,11 +787,12 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding { private var shimmerImages: [CGFloat: UIImage] = [:] - init(context: AccountContext, chatLocation: ChatLocation, directMediaImageCache: DirectMediaImageCache, captureProtected: Bool) { + init(context: AccountContext, chatLocation: ChatLocation, directMediaImageCache: DirectMediaImageCache, captureProtected: Bool, displayPrivacy: Bool) { self.context = context self.chatLocation = chatLocation self.directMediaImageCache = directMediaImageCache self.captureProtected = false + self.displayPrivacy = displayPrivacy let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } self.strings = presentationData.strings @@ -794,6 +969,11 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding { viewCount = Int32(value) } + var privacyType: EngineStoryPrivacy.Base? + if self.displayPrivacy, let value = story.privacy { + privacyType = value.base + } + var duration: Int32? var isMin: Bool = false if let file = selectedMedia as? TelegramMediaFile, !file.isAnimated { @@ -802,7 +982,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding { } isMin = layer.bounds.width < 80.0 } - layer.updateDuration(viewCount: viewCount, duration: duration, isMin: isMin, minFactor: min(1.0, layer.bounds.height / 74.0)) + layer.updateDuration(viewCount: viewCount, duration: duration, privacy: privacyType, isMin: isMin, minFactor: min(1.0, layer.bounds.height / 74.0)) } var isSelected: Bool? @@ -867,7 +1047,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding { } } -public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { public enum ContentType { case photoOrVideo case photo @@ -895,6 +1075,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr private let chatLocation: ChatLocation private let isSaved: Bool private let isArchive: Bool + private let isProfileEmbedded: Bool public private(set) var contentType: ContentType private var contentTypePromise: ValuePromise @@ -1002,7 +1183,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr private var emptyStateView: ComponentView? - public init(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation, contentType: ContentType, captureProtected: Bool, isSaved: Bool, isArchive: Bool, navigationController: @escaping () -> NavigationController?, listContext: PeerStoryListContext?) { + public init(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation, contentType: ContentType, captureProtected: Bool, isSaved: Bool, isArchive: Bool, isProfileEmbedded: Bool, navigationController: @escaping () -> NavigationController?, listContext: PeerStoryListContext?) { self.context = context self.peerId = peerId self.chatLocation = chatLocation @@ -1011,6 +1192,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr self.navigationController = navigationController self.isSaved = isSaved self.isArchive = isArchive + self.isProfileEmbedded = isProfileEmbedded self.isSelectionModeActive = isArchive @@ -1024,7 +1206,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr context: context, chatLocation: .peer(id: peerId), directMediaImageCache: self.directMediaImageCache, - captureProtected: captureProtected + captureProtected: captureProtected, + displayPrivacy: isProfileEmbedded && !self.isArchive ) self.listSource = listContext ?? PeerStoryListContext(account: context.account, peerId: peerId, isArchived: self.isArchive) @@ -1421,7 +1604,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr strongSelf.itemGrid.cancelGestures() } - self.statusPromise.set(.single(PeerInfoStatusData(text: "", isActivity: false, key: .stories))) + self.statusPromise.set(.single(PeerInfoStatusData(text: "", isActivity: false, key: self.isArchive ? .storyArchive : .stories))) /*self.storedStateDisposable = (visualMediaStoredState(engine: context.engine, peerId: peerId, messageTag: self.stateTag) |> deliverOnMainQueue).start(next: { [weak self] value in @@ -1671,11 +1854,13 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr } else { if self.isSaved { title = self.presentationData.strings.StoryList_SubtitleSaved(Int32(state.totalCount)) + } else if self.isArchive { + title = self.presentationData.strings.StoryList_SubtitleArchived(Int32(state.totalCount)) } else { title = self.presentationData.strings.StoryList_SubtitleCount(Int32(state.totalCount)) } } - self.statusPromise.set(.single(PeerInfoStatusData(text: title, isActivity: false, key: .stories))) + self.statusPromise.set(.single(PeerInfoStatusData(text: title, isActivity: false, key: self.isArchive ? .storyArchive : .stories))) let timezoneOffset = Int32(TimeZone.current.secondsFromGMT()) @@ -1952,12 +2137,19 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr itemLayer.updateSelection(theme: self.itemGridBinding.checkNodeTheme, isSelected: self.itemInteraction.selectedIds?.contains(item.story.id), animated: animated) } - let isSelecting = self._itemInteraction?.selectedIds != nil + var isSelecting = false + if let selectedIds = self._itemInteraction?.selectedIds, !selectedIds.isEmpty { + isSelecting = true + } self.itemGrid.pinchEnabled = !isSelecting var enableDismissGesture = true - if let items = self.items, items.items.isEmpty { - } else if isSelecting { + if self.isProfileEmbedded { + enableDismissGesture = true + } else if let items = self.items, items.items.isEmpty { + } + + if isSelecting { enableDismissGesture = false } self.view.disablesInteractiveTransitionGestureRecognizer = !enableDismissGesture @@ -1965,7 +2157,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr if isSelecting { if self.gridSelectionGesture == nil { let selectionGesture = MediaPickerGridSelectionGesture() - selectionGesture.delegate = self + selectionGesture.delegate = self.wrappedGestureRecognizerDelegate selectionGesture.sideInset = 44.0 selectionGesture.updateIsScrollEnabled = { [weak self] isEnabled in self?.itemGrid.isScrollEnabled = isEnabled @@ -2030,6 +2222,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr component: AnyComponent(EmptyStateIndicatorComponent( context: self.context, theme: presentationData.theme, + fitToHeight: self.isProfileEmbedded, animationName: "StoryListEmpty", title: self.isArchive ? presentationData.strings.StoryList_ArchivedEmptyState_Title : presentationData.strings.StoryList_SavedEmptyPosts_Title, text: self.isArchive ? presentationData.strings.StoryList_ArchivedEmptyState_Text : presentationData.strings.StoryList_SavedEmptyPosts_Text, @@ -2040,7 +2233,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr } self.emptyAction?() }, - additionalActionTitle: self.isArchive ? nil : presentationData.strings.StoryList_SavedEmptyAction, + additionalActionTitle: (self.isArchive || self.isProfileEmbedded) ? nil : presentationData.strings.StoryList_SavedEmptyAction, additionalAction: { [weak self] in guard let self else { return @@ -2051,6 +2244,14 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr environment: {}, containerSize: CGSize(width: size.width, height: size.height - topInset - bottomInset) ) + + let emptyStateFrame: CGRect + if self.isProfileEmbedded { + emptyStateFrame = CGRect(origin: CGPoint(x: floor((size.width - emptyStateSize.width) * 0.5), y: max(topInset, floor((visibleHeight - topInset - bottomInset - emptyStateSize.height) * 0.5))), size: emptyStateSize) + } else { + emptyStateFrame = CGRect(origin: CGPoint(x: floor((size.width - emptyStateSize.width) * 0.5), y: topInset), size: emptyStateSize) + } + if let emptyStateComponentView = emptyStateView.view { if emptyStateComponentView.superview == nil { self.view.addSubview(emptyStateComponentView) @@ -2058,12 +2259,20 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr emptyStateComponentView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } } - emptyStateTransition.setFrame(view: emptyStateComponentView, frame: CGRect(origin: CGPoint(x: floor((size.width - emptyStateSize.width) * 0.5), y: topInset), size: emptyStateSize)) + emptyStateTransition.setFrame(view: emptyStateComponentView, frame: emptyStateFrame) } - if self.didUpdateItemsOnce { - Transition(animation: .curve(duration: 0.2, curve: .easeInOut)).setBackgroundColor(view: self.view, color: presentationData.theme.list.blocksBackgroundColor) + + let backgroundColor: UIColor + if self.isProfileEmbedded { + backgroundColor = presentationData.theme.list.plainBackgroundColor } else { - self.view.backgroundColor = presentationData.theme.list.blocksBackgroundColor + backgroundColor = presentationData.theme.list.blocksBackgroundColor + } + + if self.didUpdateItemsOnce { + Transition(animation: .curve(duration: 0.2, curve: .easeInOut)).setBackgroundColor(view: self.view, color: backgroundColor) + } else { + self.view.backgroundColor = backgroundColor } } else { if let emptyStateView = self.emptyStateView { @@ -2076,7 +2285,11 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr }) } - subTransition.setBackgroundColor(view: self.view, color: presentationData.theme.list.blocksBackgroundColor) + if self.isProfileEmbedded { + subTransition.setBackgroundColor(view: self.view, color: presentationData.theme.list.plainBackgroundColor) + } else { + subTransition.setBackgroundColor(view: self.view, color: presentationData.theme.list.blocksBackgroundColor) + } } else { self.view.backgroundColor = .clear } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoVisualMediaPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoVisualMediaPaneNode.swift index 5de4a34aaa..a9be603144 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoVisualMediaPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoVisualMediaPaneNode.swift @@ -1051,7 +1051,7 @@ public protocol PeerInfoScreenNodeProtocol: AnyObject { func displaySharedMediaFastScrollingTooltip() } -public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { +public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { public enum ContentType { case photoOrVideo case photo @@ -2067,7 +2067,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, if isSelecting { if self.gridSelectionGesture == nil { let selectionGesture = MediaPickerGridSelectionGesture() - selectionGesture.delegate = self + selectionGesture.delegate = self.wrappedGestureRecognizerDelegate selectionGesture.sideInset = 44.0 selectionGesture.updateIsScrollEnabled = { [weak self] isEnabled in self?.itemGrid.isScrollEnabled = isEnabled diff --git a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageSetupScreen.swift b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageSetupScreen.swift index c8c3624129..c7eda3161a 100644 --- a/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageSetupScreen.swift +++ b/submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen/Sources/AutomaticBusinessMessageSetupScreen.swift @@ -1463,7 +1463,9 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component { values: valueList.map { item in return environment.strings.MessageTimer_Days(Int32(item)) }, + markPositions: true, selectedIndex: selectedInactivityIndex, + title: nil, selectedIndexUpdated: { [weak self] index in guard let self else { return diff --git a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift index 4d5ee92144..21a8986798 100644 --- a/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift +++ b/submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen/Sources/ThemeAccentColorControllerNode.swift @@ -149,7 +149,7 @@ private func calcPatternColors(for state: ThemeColorState) -> [UIColor] { } } -final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate { +final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate { private let context: AccountContext private var theme: PresentationTheme private let mode: ThemeAccentColorControllerMode @@ -625,7 +625,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate self.scrollNode.view.disablesInteractiveTransitionGestureRecognizer = true self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.isPagingEnabled = true - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.pageControlNode.setPage(0.0) self.colorPanelNode.view.disablesInteractiveTransitionGestureRecognizer = true self.patternPanelNode.view.disablesInteractiveTransitionGestureRecognizer = true diff --git a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperCropNode.swift b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperCropNode.swift index 00dbe5b327..ca30053e7f 100644 --- a/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperCropNode.swift +++ b/submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen/Sources/WallpaperCropNode.swift @@ -3,7 +3,7 @@ import UIKit import Display import AsyncDisplayKit -final class WallpaperCropNode: ASDisplayNode, UIScrollViewDelegate { +final class WallpaperCropNode: ASDisplayNode, ASScrollViewDelegate { let scrollNode: ASScrollNode private var ignoreZoom = false @@ -34,7 +34,7 @@ final class WallpaperCropNode: ASDisplayNode, UIScrollViewDelegate { super.init() - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.clipsToBounds = false diff --git a/submodules/TelegramUI/Components/SliderComponent/Sources/SliderComponent.swift b/submodules/TelegramUI/Components/SliderComponent/Sources/SliderComponent.swift index 2494d74a76..52abc1f328 100644 --- a/submodules/TelegramUI/Components/SliderComponent/Sources/SliderComponent.swift +++ b/submodules/TelegramUI/Components/SliderComponent/Sources/SliderComponent.swift @@ -9,6 +9,7 @@ import ComponentFlow public final class SliderComponent: Component { public let valueCount: Int public let value: Int + public let markPositions: Bool public let trackBackgroundColor: UIColor public let trackForegroundColor: UIColor public let valueUpdated: (Int) -> Void @@ -17,6 +18,7 @@ public final class SliderComponent: Component { public init( valueCount: Int, value: Int, + markPositions: Bool, trackBackgroundColor: UIColor, trackForegroundColor: UIColor, valueUpdated: @escaping (Int) -> Void, @@ -24,6 +26,7 @@ public final class SliderComponent: Component { ) { self.valueCount = valueCount self.value = value + self.markPositions = markPositions self.trackBackgroundColor = trackBackgroundColor self.trackForegroundColor = trackForegroundColor self.valueUpdated = valueUpdated @@ -37,6 +40,9 @@ public final class SliderComponent: Component { if lhs.value != rhs.value { return false } + if lhs.markPositions != rhs.markPositions { + return false + } if lhs.trackBackgroundColor != rhs.trackBackgroundColor { return false } @@ -97,6 +103,7 @@ public final class SliderComponent: Component { sliderView.maximumValue = CGFloat(component.valueCount - 1) sliderView.positionsCount = component.valueCount sliderView.useLinesForPositions = true + sliderView.markPositions = component.markPositions sliderView.backgroundColor = nil sliderView.isOpaque = false diff --git a/submodules/TelegramUI/Components/SliderContextItem/Sources/SliderContextItem.swift b/submodules/TelegramUI/Components/SliderContextItem/Sources/SliderContextItem.swift index 5272830366..a96132f715 100644 --- a/submodules/TelegramUI/Components/SliderContextItem/Sources/SliderContextItem.swift +++ b/submodules/TelegramUI/Components/SliderContextItem/Sources/SliderContextItem.swift @@ -27,7 +27,7 @@ public final class SliderContextItem: ContextMenuCustomItem { private let textFont = Font.with(size: 17.0, design: .regular, traits: .monospacedNumbers) -private final class SliderContextItemNode: ASDisplayNode, ContextMenuCustomNode, UIGestureRecognizerDelegate { +private final class SliderContextItemNode: ASDisplayNode, ContextMenuCustomNode, ASGestureRecognizerDelegate { private var presentationData: PresentationData private(set) var vibrancyEffectView: UIVisualEffectView? @@ -134,7 +134,7 @@ private final class SliderContextItemNode: ASDisplayNode, ContextMenuCustomNode, } let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panGestureRecognizer.delegate = self + panGestureRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(panGestureRecognizer) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))) diff --git a/submodules/TelegramUI/Components/StickerPickerScreen/Sources/StickerPickerScreen.swift b/submodules/TelegramUI/Components/StickerPickerScreen/Sources/StickerPickerScreen.swift index d5446679df..c5828da772 100644 --- a/submodules/TelegramUI/Components/StickerPickerScreen/Sources/StickerPickerScreen.swift +++ b/submodules/TelegramUI/Components/StickerPickerScreen/Sources/StickerPickerScreen.swift @@ -430,7 +430,7 @@ private final class StickerSelectionComponent: Component { } public class StickerPickerScreen: ViewController { - final class Node: ViewControllerTracingNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { + final class Node: ViewControllerTracingNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private var presentationData: PresentationData private weak var controller: StickerPickerScreen? private let theme: PresentationTheme @@ -1549,7 +1549,7 @@ public class StickerPickerScreen: ViewController { super.didLoad() let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.panGestureRecognizer = panRecognizer diff --git a/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift b/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift index 79f6fd787b..70892cf4c4 100644 --- a/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift +++ b/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift @@ -539,7 +539,7 @@ public class VideoMessageCameraScreen: ViewController { case video(Video) } - fileprivate final class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { + fileprivate final class Node: ViewControllerTracingNode, ASGestureRecognizerDelegate { private weak var controller: VideoMessageCameraScreen? private let context: AccountContext fileprivate var camera: Camera? diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/Profile.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/Menu/Profile.imageset/Contents.json new file mode 100644 index 0000000000..0e9b66a206 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/Profile.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "profile.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/Profile.imageset/profile.pdf b/submodules/TelegramUI/Images.xcassets/Settings/Menu/Profile.imageset/profile.pdf new file mode 100644 index 0000000000..6e061c89a8 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/Profile.imageset/profile.pdf @@ -0,0 +1,231 @@ +%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 30.000000 30.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm +1.000000 0.176471 0.333333 scn +0.000000 18.799999 m +0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c +1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c +5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c +18.799999 30.000000 l +22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c +27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c +30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c +30.000000 11.200001 l +30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c +28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c +24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c +11.200000 0.000000 l +7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c +2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c +0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c +0.000000 18.799999 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 5.000000 5.000000 cm +1.000000 1.000000 1.000000 scn +17.165209 3.024336 m +18.919451 4.825943 20.000000 7.286784 20.000000 10.000000 c +20.000000 15.522848 15.522847 20.000000 10.000000 20.000000 c +4.477152 20.000000 0.000000 15.522848 0.000000 10.000000 c +0.000000 7.286821 1.080519 4.826013 2.834717 3.024412 c +2.877964 3.183798 2.941688 3.345104 3.027704 3.506973 c +3.983309 5.305289 5.950467 7.156250 9.999956 7.156250 c +14.049442 7.156250 16.016598 5.305290 16.972202 3.506973 c +17.058231 3.345078 17.121962 3.183746 17.165209 3.024336 c +h +11.770506 0.156250 m +8.229494 0.156250 l +8.804153 0.053581 9.395820 0.000000 10.000000 0.000000 c +10.604180 0.000000 11.195847 0.053581 11.770506 0.156250 c +h +13.499953 12.843750 m +13.499953 10.910753 11.932950 9.343750 9.999953 9.343750 c +8.066957 9.343750 6.499953 10.910753 6.499953 12.843750 c +6.499953 14.776747 8.066957 16.343750 9.999953 16.343750 c +11.932950 16.343750 13.499953 14.776747 13.499953 12.843750 c +h +f* +n +Q +q +25.000000 15.000000 m +25.000000 9.477154 20.522846 5.000000 15.000000 5.000000 c +9.477152 5.000000 5.000000 9.477154 5.000000 15.000000 c +5.000000 20.522848 9.477152 25.000000 15.000000 25.000000 c +20.522846 25.000000 25.000000 20.522848 25.000000 15.000000 c +h +W* +n +q +1.000000 0.000000 -0.000000 1.000000 5.000000 5.000000 cm +1.000000 1.000000 1.000000 scn +18.670000 10.000000 m +18.670000 5.211691 14.788309 1.330000 10.000000 1.330000 c +10.000000 -1.330000 l +16.257387 -1.330000 21.330000 3.742613 21.330000 10.000000 c +18.670000 10.000000 l +h +10.000000 1.330000 m +5.211691 1.330000 1.330000 5.211691 1.330000 10.000000 c +-1.330000 10.000000 l +-1.330000 3.742613 3.742614 -1.330000 10.000000 -1.330000 c +10.000000 1.330000 l +h +1.330000 10.000000 m +1.330000 14.788309 5.211691 18.670000 10.000000 18.670000 c +10.000000 21.330000 l +3.742614 21.330000 -1.330000 16.257385 -1.330000 10.000000 c +1.330000 10.000000 l +h +10.000000 18.670000 m +14.788309 18.670000 18.670000 14.788309 18.670000 10.000000 c +21.330000 10.000000 l +21.330000 16.257385 16.257387 21.330000 10.000000 21.330000 c +10.000000 18.670000 l +h +f +n +Q +Q + +endstream +endobj + +2 0 obj + 3071 +endobj + +3 0 obj + << /Type /XObject + /Length 4 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 30.000000 30.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 18.799999 m +0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c +1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c +5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c +18.799999 30.000000 l +22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c +27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c +30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c +30.000000 11.200001 l +30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c +28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c +24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c +11.200000 0.000000 l +7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c +2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c +0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c +0.000000 18.799999 l +h +f +n +Q + +endstream +endobj + +4 0 obj + 944 +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 30.000000 30.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 +0000003329 00000 n +0000003352 00000 n +0000004544 00000 n +0000004566 00000 n +0000004864 00000 n +0000004966 00000 n +0000004987 00000 n +0000005160 00000 n +0000005234 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 10 0 R + /Size 11 +>> +startxref +5294 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 0c5f28a39a..c026ce77c7 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -4080,45 +4080,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let self, let message = self.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId), let adAttribute = message.adAttribute else { return } - self.chatDisplayNode.historyNode.adMessagesContext?.markAction(opaqueId: adAttribute.opaqueId) - - switch adAttribute.target { - case let .peer(id, messageId, startParam): - if case let .peer(currentPeerId) = self.chatLocation, currentPeerId == id { - if let messageId { - self.navigateToMessage(from: nil, to: .id(messageId, NavigateToMessageParams(timestamp: nil, quote: nil)), rememberInStack: false) - } - } else { - let navigationData: ChatControllerInteractionNavigateToPeer - if let bot = message.author as? TelegramUser, bot.botInfo != nil, let startParam = startParam { - navigationData = .withBotStartPayload(ChatControllerInitialBotStart(payload: startParam, behavior: .interactive)) - } else { - var subject: ChatControllerSubject? - if let messageId = messageId { - subject = .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil) - } - navigationData = .chat(textInputState: nil, subject: subject, peekData: nil) - } - let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: id)) - |> deliverOnMainQueue).startStandalone(next: { [weak self] peer in - if let self, let peer = peer { - self.openPeer(peer: peer, navigation: navigationData, fromMessage: nil) - } - }) - } - case let .join(_, joinHash, _): - self.controllerInteraction?.openJoinLink(joinHash) - case let .webPage(_, url): - self.controllerInteraction?.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: false, external: true)) - case let .botApp(peerId, botApp, startParam): - let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) - |> deliverOnMainQueue).startStandalone(next: { [weak self] peer in - if let self, let peer { - self.presentBotApp(botApp: botApp, botPeer: peer, payload: startParam) - } - }) - } + self.controllerInteraction?.openUrl(ChatControllerInteraction.OpenUrl(url: adAttribute.url, concealed: false, external: true)) }, openRequestedPeerSelection: { [weak self] messageId, peerType, buttonId, maxQuantity in guard let self else { return diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index dd932f2c61..95c149e8c9 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -106,7 +106,7 @@ class HistoryNodeContainer: ASDisplayNode { } } -class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { +class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { let context: AccountContext let chatLocation: ChatLocation let controllerInteraction: ChatControllerInteraction @@ -1163,7 +1163,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if self.scrollContainerNode == nil { let scrollContainerNode = ScrollContainerNode() scrollContainerNode.view.delaysContentTouches = false - scrollContainerNode.view.delegate = self + scrollContainerNode.view.delegate = self.wrappedScrollViewDelegate scrollContainerNode.view.alwaysBounceVertical = true if #available(iOSApplicationExtension 11.0, iOS 11.0, *) { scrollContainerNode.view.contentInsetAdjustmentBehavior = .never diff --git a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift index 709a548cf5..aaab82ea21 100644 --- a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift @@ -148,7 +148,7 @@ private func chatListSearchContainerPreparedTransition(from fromEntries: [ChatLi return ChatListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates) } -class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { +class ChatSearchResultsControllerNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private let animationCache: AnimationCache diff --git a/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift index dde6928282..acbcf0c576 100644 --- a/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift @@ -26,7 +26,7 @@ private let backgroundTagImage: UIImage? = { } }() -final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, ChatControllerCustomNavigationPanelNode, UIScrollViewDelegate { +final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, ChatControllerCustomNavigationPanelNode, ASScrollViewDelegate { private struct Params: Equatable { var width: CGFloat var leftInset: CGFloat @@ -466,7 +466,7 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, Chat self.scrollView.alwaysBounceHorizontal = false self.scrollView.alwaysBounceVertical = false self.scrollView.scrollsToTop = false - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.view.addSubview(self.scrollView) diff --git a/submodules/TelegramUI/Sources/ChatSendAsPeerListContextItem.swift b/submodules/TelegramUI/Sources/ChatSendAsPeerListContextItem.swift index ba3e4481ad..0dc33acc28 100644 --- a/submodules/TelegramUI/Sources/ChatSendAsPeerListContextItem.swift +++ b/submodules/TelegramUI/Sources/ChatSendAsPeerListContextItem.swift @@ -35,7 +35,7 @@ final class ChatSendAsPeerListContextItem: ContextMenuCustomItem { } } -private final class ChatSendAsPeerListContextItemNode: ASDisplayNode, ContextMenuCustomNode, ContextActionNodeProtocol, UIScrollViewDelegate { +private final class ChatSendAsPeerListContextItemNode: ASDisplayNode, ContextMenuCustomNode, ContextActionNodeProtocol, ASScrollViewDelegate { private let item: ChatSendAsPeerListContextItem private let presentationData: PresentationData private let getController: () -> ContextControllerProtocol? @@ -146,7 +146,7 @@ private final class ChatSendAsPeerListContextItemNode: ASDisplayNode, ContextMen override func didLoad() { super.didLoad() - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.scrollNode.view.alwaysBounceVertical = false self.scrollNode.view.showsHorizontalScrollIndicator = false self.scrollNode.view.scrollIndicatorInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 5.0, right: 0.0) diff --git a/submodules/TelegramUI/Sources/ChatThemeScreen.swift b/submodules/TelegramUI/Sources/ChatThemeScreen.swift index 8b2e570ad4..454a84050f 100644 --- a/submodules/TelegramUI/Sources/ChatThemeScreen.swift +++ b/submodules/TelegramUI/Sources/ChatThemeScreen.swift @@ -711,7 +711,7 @@ private func interpolateColors(from: [String: UIColor], to: [String: UIColor], f return colors } -private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelegate { +private class ChatThemeScreenNode: ViewControllerTracingNode, ASScrollViewDelegate { private let context: AccountContext private var presentationData: PresentationData private weak var controller: ChatThemeScreen? @@ -842,7 +842,7 @@ private class ChatThemeScreenNode: ViewControllerTracingNode, UIScrollViewDelega self.addSubnode(self.dimNode) - self.wrappingScrollNode.view.delegate = self + self.wrappingScrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.wrappingScrollNode) self.wrappingScrollNode.addSubnode(self.backgroundNode) diff --git a/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift b/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift index c6ac0b2fe6..5ca9802b74 100644 --- a/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift @@ -452,7 +452,7 @@ private final class TranslationLanguagesContextMenuContent: ContextControllerIte } } - private final class LanguagesListNode: ASDisplayNode, UIScrollViewDelegate { + private final class LanguagesListNode: ASDisplayNode, ASScrollViewDelegate { private final class ItemNode: HighlightTrackingButtonNode { let context: AccountContext let highlightBackgroundNode: ASDisplayNode @@ -586,7 +586,7 @@ private final class TranslationLanguagesContextMenuContent: ContextControllerIte super.init() self.addSubnode(self.scrollNode) - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.clipsToBounds = true } diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index 4ace9c8922..8ca90a5755 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -17,7 +17,7 @@ import UndoUI import ChatControllerInteraction import ChatInputContextPanelNode -private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollViewDelegate { +private final class InlineReactionSearchStickersNode: ASDisplayNode, ASScrollViewDelegate { private final class DisplayItem { let file: TelegramMediaFile let frame: CGRect @@ -78,7 +78,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie self.scrollNode.view.alwaysBounceVertical = true self.scrollNode.view.showsVerticalScrollIndicator = false self.scrollNode.view.showsHorizontalScrollIndicator = false - self.scrollNode.view.delegate = self + self.scrollNode.view.delegate = self.wrappedScrollViewDelegate self.addSubnode(self.scrollNode) } diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 4335325b8a..b6382e7396 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -12,7 +12,7 @@ import DirectionalPanGesture import ChatPresentationInterfaceState import ChatControllerInteraction -final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestureRecognizerDelegate { +final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestureRecognizerDelegate { let ready = Promise() private let context: AccountContext @@ -336,7 +336,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimTapGesture(_:)))) let panRecognizer = DirectionalPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true panRecognizer.shouldBegin = { [weak self] point in diff --git a/submodules/TelegramUI/Sources/OverlayMediaControllerNode.swift b/submodules/TelegramUI/Sources/OverlayMediaControllerNode.swift index dc9ae6a5a8..0e2cc2d901 100644 --- a/submodules/TelegramUI/Sources/OverlayMediaControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayMediaControllerNode.swift @@ -30,7 +30,7 @@ private final class OverlayMediaVideoNodeData { -final class OverlayMediaControllerNode: ASDisplayNode, UIGestureRecognizerDelegate { +final class OverlayMediaControllerNode: ASDisplayNode, ASGestureRecognizerDelegate { private let updatePossibleEmbeddingItem: (OverlayMediaControllerEmbeddingItem?) -> Void private let embedPossibleEmbeddingItem: (OverlayMediaControllerEmbeddingItem) -> Bool @@ -61,12 +61,12 @@ final class OverlayMediaControllerNode: ASDisplayNode, UIGestureRecognizerDelega let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) panRecognizer.cancelsTouchesInView = false - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(panRecognizer) let pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(self.pinchGesture(_:))) pinchRecognizer.cancelsTouchesInView = false - pinchRecognizer.delegate = self + pinchRecognizer.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(pinchRecognizer) } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 71422234dd..b828eba274 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -2205,18 +2205,8 @@ public final class SharedAccountContextImpl: SharedAccountContext { filterImpl?() completion?() - if let currentBirthdays { - let today = Calendar(identifier: .gregorian).component(.day, from: Date()) - var todayBirthdayPeerIds: [EnginePeer.Id] = [] - for (peerId, birthday) in currentBirthdays { - if birthday.day == today { - todayBirthdayPeerIds.append(peerId) - } - } - let peerIds = todayBirthdayPeerIds.sorted { lhs, rhs in - return lhs < rhs - } - let _ = ApplicationSpecificNotice.setDismissedBirthdayPremiumGifts(accountManager: context.sharedContext.accountManager, values: peerIds.map { $0.toInt64() }).start() + if case .chatList = source, let _ = currentBirthdays { + let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .todayBirthdays).startStandalone() } }) pushImpl = { [weak giftController] c in diff --git a/submodules/TranslateUI/Sources/TranslateScreen.swift b/submodules/TranslateUI/Sources/TranslateScreen.swift index 94f61b42ae..477f9d4014 100644 --- a/submodules/TranslateUI/Sources/TranslateScreen.swift +++ b/submodules/TranslateUI/Sources/TranslateScreen.swift @@ -506,7 +506,7 @@ private final class TranslateScreenComponent: CombinedComponent { } public class TranslateScreen: ViewController { - final class Node: ViewControllerTracingNode, UIScrollViewDelegate, UIGestureRecognizerDelegate { + final class Node: ViewControllerTracingNode, ASScrollViewDelegate, ASGestureRecognizerDelegate { private var presentationData: PresentationData private weak var controller: TranslateScreen? @@ -549,7 +549,7 @@ public class TranslateScreen: ViewController { super.init() - self.scrollView.delegate = self + self.scrollView.delegate = self.wrappedScrollViewDelegate self.scrollView.showsVerticalScrollIndicator = false self.containerView.clipsToBounds = true @@ -567,7 +567,7 @@ public class TranslateScreen: ViewController { super.didLoad() let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) - panRecognizer.delegate = self + panRecognizer.delegate = self.wrappedGestureRecognizerDelegate panRecognizer.delaysTouchesBegan = false panRecognizer.cancelsTouchesInView = true self.panGestureRecognizer = panRecognizer diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index e44c6412ab..24b963a7ba 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -263,7 +263,7 @@ public final class WebAppController: ViewController, AttachmentContainable { public var isContainerPanning: () -> Bool = { return false } public var isContainerExpanded: () -> Bool = { return false } - fileprivate class Node: ViewControllerTracingNode, WKNavigationDelegate, WKUIDelegate, UIScrollViewDelegate { + fileprivate class Node: ViewControllerTracingNode, WKNavigationDelegate, WKUIDelegate, ASScrollViewDelegate { private weak var controller: WebAppController? private let backgroundNode: ASDisplayNode @@ -321,7 +321,7 @@ public final class WebAppController: ViewController, AttachmentContainable { webView.alpha = 0.0 webView.navigationDelegate = self webView.uiDelegate = self - webView.scrollView.delegate = self + webView.scrollView.delegate = self.wrappedScrollViewDelegate webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: [], context: nil) webView.tintColor = self.presentationData.theme.rootController.tabBar.iconColor webView.handleScriptMessage = { [weak self] message in diff --git a/submodules/WebUI/Sources/WebAppTermsAlertController.swift b/submodules/WebUI/Sources/WebAppTermsAlertController.swift index 2151785cc6..88f3a71776 100644 --- a/submodules/WebUI/Sources/WebAppTermsAlertController.swift +++ b/submodules/WebUI/Sources/WebAppTermsAlertController.swift @@ -21,7 +21,7 @@ private func formattedText(_ text: String, fontSize: CGFloat, color: UIColor, li return parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: Font.regular(fontSize), textColor: color), bold: MarkdownAttributeSet(font: Font.semibold(fontSize), textColor: color), link: MarkdownAttributeSet(font: Font.regular(fontSize), textColor: linkColor), linkAttribute: { _ in return (TelegramTextAttributes.URL, "") }), textAlignment: textAlignment) } -private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureRecognizerDelegate { +private final class WebAppTermsAlertContentNode: AlertContentNode, ASGestureRecognizerDelegate { private let strings: PresentationStrings private let title: String private let text: String @@ -144,7 +144,7 @@ private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureReco super.didLoad() let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.acceptTap(_:))) - tapGesture.delegate = self + tapGesture.delegate = self.wrappedGestureRecognizerDelegate self.view.addGestureRecognizer(tapGesture) if let firstAction = self.actionNodes.first { diff --git a/versions.json b/versions.json index a1bd5122fb..91e354dc69 100644 --- a/versions.json +++ b/versions.json @@ -1,7 +1,6 @@ { - "app": "10.9.2", - "app": "10.10", - "bazel": "7.0.2", + "app": "10.10.1", "xcode": "15.2", + "bazel": "7.1.1", "macos": "13.0" }