diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index c08c80a08e..c0f290332a 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -4883,6 +4883,6 @@ Any member of this group will be able to see messages in the channel."; "Wallet.Send.SendAnyway" = "Send Anyway"; "Wallet.Receive.CreateInvoice" = "Create Invoice"; -"Wallet.Receive.CreateInvoiceInfo" = "Create Invoice"; +"Wallet.Receive.CreateInvoiceInfo" = "You can specify amount and purpose of the payment to save the sender some time."; "Wallet.CreateInvoice.Title" = "Create Invoice"; diff --git a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+IntentsExtension.xcscheme b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+IntentsExtension.xcscheme index 6d8563cd6c..ce9b325629 100644 --- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+IntentsExtension.xcscheme +++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+IntentsExtension.xcscheme @@ -1 +1,93 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+NotificationContentExtension.xcscheme b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+NotificationContentExtension.xcscheme index 08fc8c1eb4..b37f046d40 100644 --- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+NotificationContentExtension.xcscheme +++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+NotificationContentExtension.xcscheme @@ -1 +1,93 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+NotificationServiceExtension.xcscheme b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+NotificationServiceExtension.xcscheme index c3e465a825..e7ab45d328 100644 --- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+NotificationServiceExtension.xcscheme +++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+NotificationServiceExtension.xcscheme @@ -1 +1,93 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+ShareExtension.xcscheme b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+ShareExtension.xcscheme index 22e9d40515..48813b6770 100644 --- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+ShareExtension.xcscheme +++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+ShareExtension.xcscheme @@ -1 +1,93 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+WidgetExtension.xcscheme b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+WidgetExtension.xcscheme index b53d54939b..3eade82248 100644 --- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+WidgetExtension.xcscheme +++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck+WidgetExtension.xcscheme @@ -1 +1,93 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme index a58b71fc1a..dabec8d94e 100644 --- a/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme +++ b/Telegram_Buck.xcworkspace/xcshareddata/xcschemes/Telegram_Buck.xcscheme @@ -1 +1,2598 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index f8b51417de..b7d538f411 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -421,7 +421,7 @@ public protocol SharedAccountContext: class { func makeDeviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController func makePeersNearbyController(context: AccountContext) -> ViewController func makeComposeController(context: AccountContext) -> ViewController - func makeChatListController(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool, enableDebugActions: Bool) -> ChatListController + func makeChatListController(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool, previewing: Bool, enableDebugActions: Bool) -> ChatListController func makeChatController(context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject?, botStart: ChatControllerInitialBotStart?, mode: ChatControllerPresentationMode) -> ChatController func makeChatMessagePreviewItem(context: AccountContext, message: Message, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder, forcedResourceStatus: FileMediaResourceStatus?) -> ListViewItem func makePeerSharedMediaController(context: AccountContext, peerId: PeerId) -> ViewController? diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 36c1703c0f..8bda67ebdb 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -246,7 +246,7 @@ public enum ChatControllerSubject: Equatable { public enum ChatControllerPresentationMode: Equatable { case standard(previewing: Bool) case overlay - case inline + case inline(NavigationController?) } public final class ChatEmbeddedInterfaceState: PeerChatListEmbeddedInterfaceState { diff --git a/submodules/ChatListSearchItemHeader/Sources/ChatListSearchItemHeader.swift b/submodules/ChatListSearchItemHeader/Sources/ChatListSearchItemHeader.swift index 1316f56876..cb332caf59 100644 --- a/submodules/ChatListSearchItemHeader/Sources/ChatListSearchItemHeader.swift +++ b/submodules/ChatListSearchItemHeader/Sources/ChatListSearchItemHeader.swift @@ -68,7 +68,7 @@ public final class ChatListSearchItemHeaderNode: ListViewItemHeaderNode { case .localPeers: self.sectionHeaderNode.title = strings.DialogList_SearchSectionDialogs.uppercased() case .members: - self.sectionHeaderNode.title = strings.Compose_NewChannel_Members.uppercased() + self.sectionHeaderNode.title = strings.Channel_Info_Members.uppercased() case .contacts: self.sectionHeaderNode.title = strings.Contacts_TopSection.uppercased() case .bots: diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 0d889b6ee3..8d7ef3646a 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -134,7 +134,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, } } - public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool = false, enableDebugActions: Bool) { + public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool = false, previewing: Bool = false, enableDebugActions: Bool) { self.context = context self.controlsHistoryPreload = controlsHistoryPreload self.hideNetworkActivityStatus = hideNetworkActivityStatus @@ -161,36 +161,38 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, self.titleView.title = NetworkStatusTitle(text: title, activity: false, hasProxy: false, connectsViaProxy: false, isPasscodeSet: false, isManuallyLocked: false) self.navigationItem.titleView = self.titleView - if case .root = groupId { - self.tabBarItem.title = self.presentationData.strings.DialogList_Title - - let icon: UIImage? - if (useSpecialTabBarIcons()) { - icon = UIImage(bundleImageName: "Chat List/Tabs/NY/IconChats") + if !previewing { + if case .root = groupId { + self.tabBarItem.title = self.presentationData.strings.DialogList_Title + + let icon: UIImage? + if (useSpecialTabBarIcons()) { + icon = UIImage(bundleImageName: "Chat List/Tabs/NY/IconChats") + } else { + icon = UIImage(bundleImageName: "Chat List/Tabs/IconChats") + } + + self.tabBarItem.image = icon + self.tabBarItem.selectedImage = icon + + let leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed)) + leftBarButtonItem.accessibilityLabel = self.presentationData.strings.Common_Edit + self.navigationItem.leftBarButtonItem = leftBarButtonItem + + let rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationComposeIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.composePressed)) + rightBarButtonItem.accessibilityLabel = self.presentationData.strings.VoiceOver_Navigation_Compose + self.navigationItem.rightBarButtonItem = rightBarButtonItem + let backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.DialogList_Title, style: .plain, target: nil, action: nil) + backBarButtonItem.accessibilityLabel = self.presentationData.strings.Common_Back + self.navigationItem.backBarButtonItem = backBarButtonItem } else { - icon = UIImage(bundleImageName: "Chat List/Tabs/IconChats") + let rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed)) + rightBarButtonItem.accessibilityLabel = self.presentationData.strings.Common_Edit + self.navigationItem.rightBarButtonItem = rightBarButtonItem + let backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) + backBarButtonItem.accessibilityLabel = self.presentationData.strings.Common_Back + self.navigationItem.backBarButtonItem = backBarButtonItem } - - self.tabBarItem.image = icon - self.tabBarItem.selectedImage = icon - - let leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed)) - leftBarButtonItem.accessibilityLabel = self.presentationData.strings.Common_Edit - self.navigationItem.leftBarButtonItem = leftBarButtonItem - - let rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationComposeIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.composePressed)) - rightBarButtonItem.accessibilityLabel = self.presentationData.strings.VoiceOver_Navigation_Compose - self.navigationItem.rightBarButtonItem = rightBarButtonItem - let backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.DialogList_Title, style: .plain, target: nil, action: nil) - backBarButtonItem.accessibilityLabel = self.presentationData.strings.Common_Back - self.navigationItem.backBarButtonItem = backBarButtonItem - } else { - let rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(self.editPressed)) - rightBarButtonItem.accessibilityLabel = self.presentationData.strings.Common_Edit - self.navigationItem.rightBarButtonItem = rightBarButtonItem - let backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) - backBarButtonItem.accessibilityLabel = self.presentationData.strings.Common_Back - self.navigationItem.backBarButtonItem = backBarButtonItem } self.scrollToTop = { [weak self] in @@ -664,7 +666,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, } switch item.content { case let .groupReference(groupReference): - let chatListController = ChatListControllerImpl(context: strongSelf.context, groupId: groupReference.groupId, controlsHistoryPreload: false, enableDebugActions: false) + let chatListController = ChatListControllerImpl(context: strongSelf.context, groupId: groupReference.groupId, controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false) chatListController.navigationPresentation = .master let contextController = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node)), items: archiveContextMenuItems(context: strongSelf.context, groupId: groupReference.groupId, chatListController: strongSelf), reactionItems: [], gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) diff --git a/submodules/ComposePollUI/Sources/CreatePollOptionActionItem.swift b/submodules/ComposePollUI/Sources/CreatePollOptionActionItem.swift index 2d007dba66..0b5cedc856 100644 --- a/submodules/ComposePollUI/Sources/CreatePollOptionActionItem.swift +++ b/submodules/ComposePollUI/Sources/CreatePollOptionActionItem.swift @@ -78,6 +78,7 @@ class CreatePollOptionActionItemNode: ListViewItemNode, ItemListItemNode { private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode + private let maskNode: ASImageNode private let iconNode: ASImageNode private let titleNode: TextNode @@ -98,6 +99,8 @@ class CreatePollOptionActionItemNode: ListViewItemNode, ItemListItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.iconNode = ASImageNode() self.iconNode.isLayerBacked = true self.iconNode.displayWithoutProcessing = true @@ -178,11 +181,19 @@ class CreatePollOptionActionItemNode: ListViewItemNode, ItemListItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { - case .sameSection(false): - strongSelf.topStripeNode.isHidden = true - default: - strongSelf.topStripeNode.isHidden = false + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat @@ -194,8 +205,14 @@ class CreatePollOptionActionItemNode: ListViewItemNode, ItemListItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) diff --git a/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift b/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift index 56b89d8a97..05116a8079 100644 --- a/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift +++ b/submodules/ComposePollUI/Sources/CreatePollOptionItem.swift @@ -86,6 +86,7 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let textClippingNode: ASDisplayNode private let textNode: EditableTextNode @@ -113,6 +114,8 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.editableControlNode = ItemListEditableControlNode() self.reorderControlNode = ItemListEditableReorderControlNode() @@ -335,11 +338,19 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat switch neighbors.bottom { @@ -347,8 +358,14 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode, bottomStripeInset = leftInset default: bottomStripeInset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layout.contentSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - UIScreenPixel), size: CGSize(width: layout.contentSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/Display/Display/UIKitUtils.swift b/submodules/Display/Display/UIKitUtils.swift index a1eeb93118..884fbfc9f9 100644 --- a/submodules/Display/Display/UIKitUtils.swift +++ b/submodules/Display/Display/UIKitUtils.swift @@ -185,6 +185,28 @@ public extension UIColor { return UIColor(red: r, green: g, blue: b, alpha: a) } + + private var colorComponents: (r: Int32, g: Int32, b: Int32) { + var r: CGFloat = 0.0 + var g: CGFloat = 0.0 + var b: CGFloat = 0.0 + if self.getRed(&r, green: &g, blue: &b, alpha: nil) { + return (Int32(max(0.0, r) * 255.0), Int32(max(0.0, g) * 255.0), Int32(max(0.0, b) * 255.0)) + } else if self.getWhite(&r, alpha: nil) { + return (Int32(max(0.0, r) * 255.0), Int32(max(0.0, r) * 255.0), Int32(max(0.0, r) * 255.0)) + } + return (0, 0, 0) + } + + func distance(to other: UIColor) -> Int32 { + let e1 = self.colorComponents + let e2 = other.colorComponents + let rMean = (e1.r + e2.r) / 2 + let r = e1.r - e2.r + let g = e1.g - e2.g + let b = e1.b - e2.b + return ((512 + rMean) * r * r) >> 8 + 4 * g * g + ((767 - rMean) * b * b) >> 8 + } } public extension CGSize { diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index d8d3b41df0..760968bf11 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -94,7 +94,7 @@ public final class HashtagSearchController: TelegramBaseController { } override public func loadDisplayNode() { - self.displayNode = HashtagSearchControllerNode(context: self.context, peer: self.peer, query: self.query, theme: self.presentationData.theme, strings: self.presentationData.strings) + self.displayNode = HashtagSearchControllerNode(context: self.context, peer: self.peer, query: self.query, theme: self.presentationData.theme, strings: self.presentationData.strings, navigationController: self.navigationController as? NavigationController) if let chatController = self.controllerNode.chatController { chatController.parentController = self } diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchControllerNode.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchControllerNode.swift index 5028f77533..e2231e6313 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchControllerNode.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchControllerNode.swift @@ -25,7 +25,7 @@ final class HashtagSearchControllerNode: ASDisplayNode { var navigationBar: NavigationBar? - init(context: AccountContext, peer: Peer?, query: String, theme: PresentationTheme, strings: PresentationStrings) { + init(context: AccountContext, peer: Peer?, query: String, theme: PresentationTheme, strings: PresentationStrings, navigationController: NavigationController?) { self.context = context self.query = query self.listNode = ListView() @@ -48,7 +48,7 @@ final class HashtagSearchControllerNode: ASDisplayNode { self.segmentedControlNode = SegmentedControlNode(theme: SegmentedControlTheme(theme: theme), items: items.map { SegmentedControlItem(title: $0) }, selectedIndex: 0) if let peer = peer { - self.chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(peer.id), subject: nil, botStart: nil, mode: .inline) + self.chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(peer.id), subject: nil, botStart: nil, mode: .inline(navigationController)) } else { self.chatController = nil } @@ -78,7 +78,7 @@ final class HashtagSearchControllerNode: ASDisplayNode { } func enqueueTransition(_ transition: ChatListSearchContainerTransition, firstTime: Bool) { - enqueuedTransitions.append((transition, firstTime)) + self.enqueuedTransitions.append((transition, firstTime)) if self.hasValidLayout { while !self.enqueuedTransitions.isEmpty { diff --git a/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift b/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift index 735bd17b34..05f67e3c74 100644 --- a/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift +++ b/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift @@ -225,6 +225,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo private let highlightedBackgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let avatarNode: AvatarNode private let updatingAvatarOverlay: ASImageNode @@ -276,6 +277,8 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.avatarNode = AvatarNode(font: avatarFont) self.updatingAvatarOverlay = ASImageNode() @@ -464,6 +467,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo let separatorHeight = UIScreenPixel + let hasCorners = params.width > 480 let contentSize: CGSize var insets: UIEdgeInsets let itemBackgroundColor: UIColor @@ -478,7 +482,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor contentSize = CGSize(width: params.width, height: 92.0) - if withTopInset { + if withTopInset || hasCorners { insets = itemListNeighborsGroupedInsets(neighbors) } else { let topInset: CGFloat @@ -575,6 +579,9 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo if strongSelf.bottomStripeNode.supernode != nil { strongSelf.bottomStripeNode.removeFromSupernode() } + if strongSelf.maskNode.supernode != nil { + strongSelf.maskNode.removeFromSupernode() + } case .blocks: avatarOriginY = 13.0 @@ -587,11 +594,18 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat @@ -600,9 +614,14 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo bottomStripeInset = params.leftInset + 16.0 default: bottomStripeInset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: params.width, height: contentSize.height)) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: contentSize.height + UIScreenPixel)) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: layoutSize.height - insets.top - insets.bottom), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/ItemListPeerActionItem/Sources/ItemListPeerActionItem.swift b/submodules/ItemListPeerActionItem/Sources/ItemListPeerActionItem.swift index e5b497cfdd..41d5dd7e15 100644 --- a/submodules/ItemListPeerActionItem/Sources/ItemListPeerActionItem.swift +++ b/submodules/ItemListPeerActionItem/Sources/ItemListPeerActionItem.swift @@ -93,6 +93,7 @@ class ItemListPeerActionItemNode: ListViewItemNode { private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode + private let maskNode: ASImageNode private let iconNode: ASImageNode private let titleNode: TextNode @@ -111,6 +112,8 @@ class ItemListPeerActionItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.iconNode = ASImageNode() self.iconNode.isLayerBacked = true self.iconNode.displayWithoutProcessing = true @@ -208,11 +211,19 @@ class ItemListPeerActionItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat @@ -224,8 +235,14 @@ class ItemListPeerActionItemNode: ListViewItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) diff --git a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift index d20bd104a6..d9d4200884 100644 --- a/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift +++ b/submodules/ItemListPeerItem/Sources/ItemListPeerItem.swift @@ -223,6 +223,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode private var disabledOverlayNode: ASDisplayNode? + private let maskNode: ASImageNode private let containerNode: ContextControllerSourceNode @@ -264,6 +265,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() self.containerNode = ContextControllerSourceNode() @@ -680,11 +682,19 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = !item.hasTopStripe + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners || !item.hasTopStripe } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -695,8 +705,14 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) transition.updateFrame(node: strongSelf.topStripeNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) diff --git a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift index ce5115a171..867383ce1c 100644 --- a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift +++ b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift @@ -146,6 +146,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode private var disabledOverlayNode: ASDisplayNode? + private let maskNode: ASImageNode fileprivate let imageNode: TransformImageNode private var animationNode: AnimatedStickerNode? @@ -195,6 +196,8 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.imageNode = TransformImageNode() self.imageNode.isLayerBacked = !smartInvertColorsEnabled() @@ -535,11 +538,19 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -550,8 +561,14 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) transition.updateFrame(node: strongSelf.topStripeNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) diff --git a/submodules/ItemListUI/Sources/Items/ItemListActionItem.swift b/submodules/ItemListUI/Sources/Items/ItemListActionItem.swift index d85e67ed42..c496bdc0c7 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListActionItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListActionItem.swift @@ -108,7 +108,7 @@ public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode { self.backgroundNode = ASDisplayNode() self.backgroundNode.isLayerBacked = true self.backgroundNode.backgroundColor = .white - self.maskNode = ASImageNode() + self.maskNode = ASImageNode() self.topStripeNode = ASDisplayNode() self.topStripeNode.isLayerBacked = true diff --git a/submodules/ItemListUI/Sources/Items/ItemListCheckboxItem.swift b/submodules/ItemListUI/Sources/Items/ItemListCheckboxItem.swift index baa49f05a4..45ffbf7c6b 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListCheckboxItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListCheckboxItem.swift @@ -84,6 +84,7 @@ public class ItemListCheckboxItemNode: ListViewItemNode { private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode + private let maskNode: ASImageNode private let activateArea: AccessibilityAreaNode @@ -102,6 +103,8 @@ public class ItemListCheckboxItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.iconNode = ASImageNode() self.iconNode.isLayerBacked = true self.iconNode.displayWithoutProcessing = true @@ -214,11 +217,18 @@ public class ItemListCheckboxItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat if item.zeroSeparatorInsets { @@ -229,9 +239,15 @@ public class ItemListCheckboxItemNode: ListViewItemNode { bottomStripeInset = leftInset default: bottomStripeInset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/ItemListUI/Sources/Items/ItemListInfoItem.swift b/submodules/ItemListUI/Sources/Items/ItemListInfoItem.swift index 51e883cfe4..6e2921cee2 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListInfoItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListInfoItem.swift @@ -120,7 +120,8 @@ class InfoItemNode: ListViewItemNode { private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let closeButton: HighlightableButtonNode - + private let maskNode: ASImageNode + private let badgeNode: ASImageNode private let labelNode: TextNode private let titleNode: TextNode @@ -146,6 +147,8 @@ class InfoItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.badgeNode = ASImageNode() self.badgeNode.displayWithoutProcessing = true self.badgeNode.displaysAsynchronously = false @@ -284,12 +287,20 @@ class InfoItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false if let neighbors = neighbors { switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } } let bottomStripeInset: CGFloat @@ -299,6 +310,8 @@ class InfoItemNode: ListViewItemNode { bottomStripeInset = leftInset default: bottomStripeInset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } } else { bottomStripeInset = leftInset @@ -306,7 +319,10 @@ class InfoItemNode: ListViewItemNode { strongSelf.closeButton.isHidden = item.closeAction == nil + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift b/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift index 995865d71c..5d7795f3c8 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListMultilineInputItem.swift @@ -104,6 +104,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let textClippingNode: ASDisplayNode private let textNode: EditableTextNode @@ -129,6 +130,8 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.textClippingNode = ASDisplayNode() self.textClippingNode.clipsToBounds = true @@ -283,11 +286,19 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat switch neighbors.bottom { @@ -295,8 +306,14 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod bottomStripeInset = leftInset default: bottomStripeInset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift b/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift index 3047aad8d3..e806b878e4 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListMultilineTextItem.swift @@ -92,6 +92,8 @@ public class ItemListMultilineTextItemNode: ListViewItemNode { private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode + private let maskNode: ASImageNode + private var linkHighlightingNode: LinkHighlightingNode? private let textNode: TextNode @@ -119,6 +121,8 @@ public class ItemListMultilineTextItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.textNode = TextNode() self.textNode.isUserInteractionEnabled = false self.textNode.contentMode = .left @@ -243,6 +247,9 @@ public class ItemListMultilineTextItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 0) } + if strongSelf.maskNode.supernode != nil { + strongSelf.maskNode.removeFromSupernode() + } strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight)) case .blocks: @@ -255,11 +262,19 @@ public class ItemListMultilineTextItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -270,8 +285,14 @@ public class ItemListMultilineTextItemNode: ListViewItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) } diff --git a/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift b/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift index e83df41e12..8ec14872d5 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift @@ -109,6 +109,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let titleNode: TextNode private let textNode: TextFieldNode @@ -131,6 +132,8 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.titleNode = TextNode() self.textNode = TextFieldNode() @@ -322,11 +325,19 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat switch neighbors.bottom { @@ -334,8 +345,14 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg bottomStripeInset = leftInset default: bottomStripeInset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - UIScreenPixel), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.xcodeproj/xcshareddata/xcschemes/SwiftSignalKit.xcscheme b/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.xcodeproj/xcshareddata/xcschemes/SwiftSignalKit.xcscheme index 6eae9bf611..843e7441be 100644 --- a/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.xcodeproj/xcshareddata/xcschemes/SwiftSignalKit.xcscheme +++ b/submodules/SSignalKit/SwiftSignalKit/SwiftSignalKit.xcodeproj/xcshareddata/xcschemes/SwiftSignalKit.xcscheme @@ -1 +1,58 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + diff --git a/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift b/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift index 3e527f9ef2..14765944f2 100644 --- a/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift +++ b/submodules/SegmentedControlNode/Sources/SegmentedControlNode.swift @@ -105,6 +105,9 @@ public final class SegmentedControlNode: ASDisplayNode, UIGestureRecognizerDeleg self.itemNodes.forEach { $0.removeFromSupernode() } self.itemNodes = self._items.map { item in let itemNode = SegmentedControlItemNode() + itemNode.contentEdgeInsets = UIEdgeInsets(top: 0.0, left: 8.0, bottom: 0.0, right: 8.0) + itemNode.titleNode.maximumNumberOfLines = 1 + itemNode.titleNode.truncationMode = .byTruncatingTail itemNode.setTitle(item.title, with: textFont, with: self.theme.textColor, for: .normal) itemNode.setTitle(item.title, with: selectedTextFont, with: self.theme.textColor, for: .selected) itemNode.setTitle(item.title, with: selectedTextFont, with: self.theme.textColor, for: [.selected, .highlighted]) @@ -153,6 +156,9 @@ public final class SegmentedControlNode: ASDisplayNode, UIGestureRecognizerDeleg self.itemNodes = items.map { item in let itemNode = SegmentedControlItemNode() + itemNode.contentEdgeInsets = UIEdgeInsets(top: 0.0, left: 8.0, bottom: 0.0, right: 8.0) + itemNode.titleNode.maximumNumberOfLines = 1 + itemNode.titleNode.truncationMode = .byTruncatingTail itemNode.setTitle(item.title, with: textFont, with: theme.textColor, for: .normal) itemNode.setTitle(item.title, with: selectedTextFont, with: theme.textColor, for: .selected) itemNode.setTitle(item.title, with: selectedTextFont, with: theme.textColor, for: [.selected, .highlighted]) diff --git a/submodules/SettingsUI/Sources/Data and Storage/AutodownloadDataUsagePickerItem.swift b/submodules/SettingsUI/Sources/Data and Storage/AutodownloadDataUsagePickerItem.swift index cf0031b9f5..a52d32dfdc 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/AutodownloadDataUsagePickerItem.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/AutodownloadDataUsagePickerItem.swift @@ -95,6 +95,7 @@ class AutodownloadDataUsagePickerItemNode: ListViewItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let lowTextNode: TextNode private let mediumTextNode: TextNode @@ -115,6 +116,8 @@ class AutodownloadDataUsagePickerItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.lowTextNode = TextNode() self.lowTextNode.isUserInteractionEnabled = false self.lowTextNode.displaysAsynchronously = false @@ -254,11 +257,19 @@ class AutodownloadDataUsagePickerItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { - case .sameSection(false): - strongSelf.topStripeNode.isHidden = true - default: - strongSelf.topStripeNode.isHidden = false + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -269,8 +280,14 @@ class AutodownloadDataUsagePickerItemNode: ListViewItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/SettingsUI/Sources/Data and Storage/AutodownloadSizeLimitItem.swift b/submodules/SettingsUI/Sources/Data and Storage/AutodownloadSizeLimitItem.swift index 65920b9fdb..8ac64eb0e3 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/AutodownloadSizeLimitItem.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/AutodownloadSizeLimitItem.swift @@ -111,6 +111,7 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let minTextNode: TextNode private let maxTextNode: TextNode @@ -130,6 +131,8 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.textNode = TextNode() self.textNode.isUserInteractionEnabled = false self.textNode.displaysAsynchronously = false @@ -224,11 +227,19 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -239,8 +250,14 @@ class AutodownloadSizeLimitItemNode: ListViewItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/SettingsUI/Sources/Data and Storage/CalculatingCacheSizeItem.swift b/submodules/SettingsUI/Sources/Data and Storage/CalculatingCacheSizeItem.swift index 73251a38da..64cef117ff 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/CalculatingCacheSizeItem.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/CalculatingCacheSizeItem.swift @@ -60,6 +60,7 @@ class CalculatingCacheSizeItemNode: ListViewItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private var activityIndicator: ActivityIndicator? private let titleNode: TextNode @@ -81,6 +82,8 @@ class CalculatingCacheSizeItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.titleNode = TextNode() self.titleNode.isUserInteractionEnabled = false self.titleNode.contentMode = .left @@ -177,11 +180,19 @@ class CalculatingCacheSizeItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { - case .sameSection(false): - strongSelf.topStripeNode.isHidden = true - default: - strongSelf.topStripeNode.isHidden = false + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -192,8 +203,14 @@ class CalculatingCacheSizeItemNode: ListViewItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight)) } diff --git a/submodules/SettingsUI/Sources/Data and Storage/ProxyListSettingsController.swift b/submodules/SettingsUI/Sources/Data and Storage/ProxyListSettingsController.swift index 152fd4b647..27b52d4783 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/ProxyListSettingsController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/ProxyListSettingsController.swift @@ -13,6 +13,7 @@ import MtProtoKitDynamic import ItemListUI import AccountContext import UrlEscaping +import ShareController private final class ProxySettingsControllerArguments { let toggleEnabled: (Bool) -> Void @@ -311,10 +312,11 @@ public enum ProxySettingsControllerMode { public func proxySettingsController(context: AccountContext, mode: ProxySettingsControllerMode = .default) -> ViewController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } - return proxySettingsController(accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, mode: mode, theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: context.sharedContext.presentationData |> map { ($0.theme, $0.strings) }) + return proxySettingsController(accountManager: context.sharedContext.accountManager, context: context, postbox: context.account.postbox, network: context.account.network, mode: mode, theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: context.sharedContext.presentationData |> map { ($0.theme, $0.strings) }) } -public func proxySettingsController(accountManager: AccountManager, postbox: Postbox, network: Network, mode: ProxySettingsControllerMode, theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>) -> ViewController { +public func proxySettingsController(accountManager: AccountManager, context: AccountContext? = nil, postbox: Postbox, network: Network, mode: ProxySettingsControllerMode, theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>) -> ViewController { + var presentControllerImpl: ((ViewController, Any?) -> Void)? var pushControllerImpl: ((ViewController) -> Void)? var dismissImpl: (() -> Void)? let stateValue = Atomic(value: ProxySettingsControllerState()) @@ -439,6 +441,9 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos let controller = ItemListController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, state: signal, tabBarItem: nil) controller.navigationPresentation = .modal + presentControllerImpl = { [weak controller] c, a in + controller?.present(c, in: .window(.root), with: a) + } pushControllerImpl = { [weak controller] c in (controller?.navigationController as? NavigationController)?.pushViewController(c) } @@ -499,7 +504,7 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos } shareProxyListImpl = { [weak controller] in - guard let strongController = controller else { + guard let context = context, let strongController = controller else { return } let _ = (proxySettings.get() @@ -527,13 +532,8 @@ public func proxySettingsController(accountManager: AccountManager, postbox: Pos result += string } - let activityController = UIActivityViewController(activityItems: [result], applicationActivities: nil) - - if let window = strongController.view.window, let rootViewController = window.rootViewController { - activityController.popoverPresentationController?.sourceView = window - activityController.popoverPresentationController?.sourceRect = CGRect(origin: CGPoint(x: window.bounds.width / 2.0, y: window.bounds.size.height - 1.0), size: CGSize(width: 1.0, height: 1.0)) - rootViewController.present(activityController, animated: true, completion: nil) - } + let controller = ShareController(context: context, subject: .text(result), preferredAction: .default, showInChat: nil, externalShare: true, immediateExternalShare: true, switchableAccounts: []) + presentControllerImpl?(controller, nil) }) } diff --git a/submodules/SettingsUI/Sources/Data and Storage/ProxyServerSettingsController.swift b/submodules/SettingsUI/Sources/Data and Storage/ProxyServerSettingsController.swift index 28d152ec18..be49498b21 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/ProxyServerSettingsController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/ProxyServerSettingsController.swift @@ -14,6 +14,7 @@ import ItemListUI import AccountContext import UrlEscaping import UrlHandling +import ShareController private func shareLink(for server: ProxyServerSettings) -> String { var link: String @@ -267,10 +268,10 @@ private func proxyServerSettings(with state: ProxyServerSettingsControllerState) public func proxyServerSettingsController(context: AccountContext, currentSettings: ProxyServerSettings? = nil) -> ViewController { let presentationData = context.sharedContext.currentPresentationData.with { $0 } - return proxyServerSettingsController(theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: context.sharedContext.presentationData |> map { ($0.theme, $0.strings) }, accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, currentSettings: currentSettings) + return proxyServerSettingsController(context: context, theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: context.sharedContext.presentationData |> map { ($0.theme, $0.strings) }, accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, currentSettings: currentSettings) } -func proxyServerSettingsController(theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>, accountManager: AccountManager, postbox: Postbox, network: Network, currentSettings: ProxyServerSettings?) -> ViewController { +func proxyServerSettingsController(context: AccountContext? = nil, theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>, accountManager: AccountManager, postbox: Postbox, network: Network, currentSettings: ProxyServerSettings?) -> ViewController { var currentMode: ProxyServerSettingsControllerMode = .socks5 var currentUsername: String? var currentPassword: String? @@ -303,7 +304,7 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati statePromise.set(stateValue.modify { f($0) }) } - var presentImpl: ((ViewController, Any?) -> Void)? + var presentControllerImpl: ((ViewController, Any?) -> Void)? var dismissImpl: (() -> Void)? var shareImpl: (() -> Void)? @@ -370,7 +371,7 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati let controller = ItemListController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, state: signal, tabBarItem: nil) controller.navigationPresentation = .modal - presentImpl = { [weak controller] c, d in + presentControllerImpl = { [weak controller] c, d in controller?.present(c, in: .window(.root), with: d) } dismissImpl = { [weak controller] in @@ -386,15 +387,10 @@ func proxyServerSettingsController(theme: PresentationTheme, strings: Presentati controller?.view.endEditing(true) if #available(iOSApplicationExtension 9.0, iOS 9.0, *) { let controller = ShareProxyServerActionSheetController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, link: link) - presentImpl?(controller, nil) - } else { - let activityController = UIActivityViewController(activityItems: [link], applicationActivities: nil) - - if let window = strongController.view.window, let rootViewController = window.rootViewController { - activityController.popoverPresentationController?.sourceView = window - activityController.popoverPresentationController?.sourceRect = CGRect(origin: CGPoint(x: window.bounds.width / 2.0, y: window.bounds.size.height - 1.0), size: CGSize(width: 1.0, height: 1.0)) - rootViewController.present(activityController, animated: true, completion: nil) - } + presentControllerImpl?(controller, nil) + } else if let context = context { + let controller = ShareController(context: context, subject: .url(link), preferredAction: .default, showInChat: nil, externalShare: true, immediateExternalShare: true, switchableAccounts: []) + presentControllerImpl?(controller, nil) } } diff --git a/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsActionItem.swift b/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsActionItem.swift index 73bd7b65d8..3869c75bce 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsActionItem.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsActionItem.swift @@ -81,6 +81,7 @@ class ProxySettingsActionItemNode: ListViewItemNode { private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode + private let maskNode: ASImageNode private let iconNode: ASImageNode private let titleNode: TextNode @@ -97,6 +98,8 @@ class ProxySettingsActionItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.iconNode = ASImageNode() self.iconNode.isLayerBacked = true self.iconNode.displayWithoutProcessing = true @@ -181,24 +184,38 @@ class ProxySettingsActionItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { - case .sameSection(false): - strongSelf.topStripeNode.isHidden = true - default: - strongSelf.topStripeNode.isHidden = false + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat switch neighbors.bottom { - case .sameSection(false): - bottomStripeInset = leftInset + editingOffset - bottomStripeOffset = -separatorHeight - default: - bottomStripeInset = 0.0 - bottomStripeOffset = 0.0 + case .sameSection(false): + bottomStripeInset = leftInset + editingOffset + bottomStripeOffset = -separatorHeight + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) diff --git a/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsServerItem.swift b/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsServerItem.swift index aeb5d2e585..98c3c0e7e7 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsServerItem.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsServerItem.swift @@ -104,6 +104,7 @@ class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode { private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode + private let maskNode: ASImageNode private let titleNode: TextNode private let infoIconNode: ASImageNode @@ -137,6 +138,8 @@ class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.infoIconNode = ASImageNode() self.infoIconNode.isLayerBacked = true self.infoIconNode.displayWithoutProcessing = true @@ -363,11 +366,19 @@ class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -378,8 +389,14 @@ class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) transition.updateFrame(node: strongSelf.topStripeNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) diff --git a/submodules/SettingsUI/Sources/Data and Storage/ShareProxyServerActionSheetController.swift b/submodules/SettingsUI/Sources/Data and Storage/ShareProxyServerActionSheetController.swift index bae0c3eaff..661de4500c 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/ShareProxyServerActionSheetController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/ShareProxyServerActionSheetController.swift @@ -8,6 +8,7 @@ import UIKit import SwiftSignalKit import TelegramPresentationData import QrCode +import ShareController public final class ShareProxyServerActionSheetController: ActionSheetController { private var presentationDisposable: Disposable? diff --git a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListRecentSessionItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListRecentSessionItem.swift index 18bf9911a6..dadbb8672c 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListRecentSessionItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListRecentSessionItem.swift @@ -109,6 +109,7 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode { private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode private var disabledOverlayNode: ASDisplayNode? + private let maskNode: ASImageNode private let titleNode: TextNode private let appNode: TextNode @@ -129,6 +130,8 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.titleNode = TextNode() self.titleNode.isUserInteractionEnabled = false self.titleNode.contentMode = .left @@ -338,11 +341,19 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -353,8 +364,14 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) transition.updateFrame(node: strongSelf.topStripeNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListWebsiteItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListWebsiteItem.swift index c9cda1517b..7b4603364b 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListWebsiteItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListWebsiteItem.swift @@ -107,6 +107,7 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode { private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode private var disabledOverlayNode: ASDisplayNode? + private let maskNode: ASImageNode private let avatarNode: AvatarNode private let titleNode: TextNode @@ -128,6 +129,8 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.avatarNode = AvatarNode(font: avatarFont) self.titleNode = TextNode() @@ -338,11 +341,19 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -353,8 +364,14 @@ class ItemListWebsiteItemNode: ItemListRevealOptionsItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) transition.updateFrame(node: strongSelf.topStripeNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))) diff --git a/submodules/SettingsUI/Sources/SettingsController.swift b/submodules/SettingsUI/Sources/SettingsController.swift index cc607669fd..ef41ce122f 100644 --- a/submodules/SettingsUI/Sources/SettingsController.swift +++ b/submodules/SettingsUI/Sources/SettingsController.swift @@ -961,7 +961,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM }) if let selectedAccount = selectedAccount, let sharedContext = sharedContext { let accountContext = sharedContext.makeTempAccountContext(account: selectedAccount) - let chatListController = accountContext.sharedContext.makeChatListController(context: accountContext, groupId: .root, controlsHistoryPreload: false, hideNetworkActivityStatus: true, enableDebugActions: enableDebugActions) + let chatListController = accountContext.sharedContext.makeChatListController(context: accountContext, groupId: .root, controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: enableDebugActions) let presentationData = accountContext.sharedContext.currentPresentationData.with { $0 } @@ -1296,7 +1296,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM return nil } } - |> distinctUntilChanged(isEqual: { $0?.0 === $1?.0 && arePeersEqual($0?.1, $1?.1) }) + |> distinctUntilChanged(isEqual: { $0?.0 === $1?.0 && arePeersEqual($0?.1, $1?.1) && $0?.2 === $1?.2 }) |> mapToSignal { primary -> Signal<(UIImage, UIImage)?, NoError> in if let primary = primary { let size = CGSize(width: 31.0, height: 31.0) @@ -1524,7 +1524,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM }) if let selectedAccount = selectedAccount, let sharedContext = sharedContext { let accountContext = sharedContext.makeTempAccountContext(account: selectedAccount) - let chatListController = accountContext.sharedContext.makeChatListController(context: accountContext, groupId: .root, controlsHistoryPreload: false, hideNetworkActivityStatus: true, enableDebugActions: enableDebugActions) + let chatListController = accountContext.sharedContext.makeChatListController(context: accountContext, groupId: .root, controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: enableDebugActions) return chatListController } } diff --git a/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceControllerNode.swift b/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceControllerNode.swift index f1fd8520b8..bd765219e3 100644 --- a/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceControllerNode.swift +++ b/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceControllerNode.swift @@ -226,7 +226,7 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode { let containerInset: CGFloat = 32.0 let contentInsets = UIEdgeInsets(top: 15.0, left: 15.0 + layout.safeInsets.left, bottom: 15.0, right: 15.0 + layout.safeInsets.right) - let contentSize = self.contentTextNode.updateLayout(CGSize(width: layout.size.width - contentInsets.left, height: CGFloat.greatestFiniteMagnitude)) + let contentSize = self.contentTextNode.updateLayout(CGSize(width: layout.size.width - contentInsets.left - contentInsets.right, height: CGFloat.greatestFiniteMagnitude)) let contentFrame = CGRect(origin: CGPoint(x: 0.0, y: containerInset), size: CGSize(width: layout.size.width, height: contentSize.height + contentInsets.top + contentInsets.bottom)) self.contentTextNode.frame = CGRect(origin: CGPoint(x: contentFrame.minX + contentInsets.left, y: contentFrame.minY + contentInsets.top), size: contentSize) self.contentBackgroundNode.frame = contentFrame diff --git a/submodules/SettingsUI/Sources/Themes/SettingsThemeWallpaperNode.swift b/submodules/SettingsUI/Sources/Themes/SettingsThemeWallpaperNode.swift index 26b84afe35..eb4c0fdb35 100644 --- a/submodules/SettingsUI/Sources/Themes/SettingsThemeWallpaperNode.swift +++ b/submodules/SettingsUI/Sources/Themes/SettingsThemeWallpaperNode.swift @@ -10,12 +10,12 @@ import AccountContext import RadialStatusNode import WallpaperResources -private func whiteColorImage(theme: PresentationTheme) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { +private func whiteColorImage(theme: PresentationTheme, color: UIColor) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { return .single({ arguments in let context = DrawingContext(size: arguments.drawingSize, clear: true) context.withFlippedContext { c in - c.setFillColor(UIColor.white.cgColor) + c.setFillColor(color.cgColor) c.fill(CGRect(origin: CGPoint(), size: arguments.drawingSize)) let lineWidth: CGFloat = 1.0 @@ -85,10 +85,12 @@ final class SettingsThemeWallpaperNode: ASDisplayNode { let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: corners, imageSize: CGSize(), boundingSize: size, intrinsicInsets: UIEdgeInsets())) apply() case let .color(color): - if color == 0x00ffffff { + let theme = context.sharedContext.currentPresentationData.with { $0 }.theme + let uiColor = UIColor(rgb: UInt32(bitPattern: color)) + if uiColor.distance(to: theme.list.itemBlocksBackgroundColor) < 200 { self.imageNode.isHidden = false self.backgroundNode.isHidden = true - self.imageNode.setSignal(whiteColorImage(theme: context.sharedContext.currentPresentationData.with { $0 }.theme)) + self.imageNode.setSignal(whiteColorImage(theme: theme, color: uiColor)) let apply = self.imageNode.asyncLayout()(TransformImageArguments(corners: corners, imageSize: CGSize(), boundingSize: size, intrinsicInsets: UIEdgeInsets())) apply() } else { @@ -96,6 +98,7 @@ final class SettingsThemeWallpaperNode: ASDisplayNode { self.backgroundNode.isHidden = false self.backgroundNode.backgroundColor = UIColor(rgb: UInt32(bitPattern: color)) } + case let .image(representations, _): self.imageNode.isHidden = false self.backgroundNode.isHidden = true diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index cd5c3e6d9a..b2e2ec4d6c 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -21,8 +21,6 @@ final class ThemeAccentColorController: ViewController { return self.displayNode as! ThemeAccentColorControllerNode } - private var didPlayPresentationAnimation = false - private var presentationData: PresentationData init(context: AccountContext, currentTheme: PresentationThemeReference, currentColor: UIColor?) { @@ -55,17 +53,6 @@ final class ThemeAccentColorController: ViewController { fatalError("init(coder:) has not been implemented") } - public override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - if let presentationArguments = self.presentationArguments as? ViewControllerPresentationArguments, !self.didPlayPresentationAnimation { - self.didPlayPresentationAnimation = true - if case .modalSheet = presentationArguments.presentationAnimation { - self.controllerNode.animateIn() - } - } - } - override func loadDisplayNode() { super.loadDisplayNode() @@ -111,13 +98,6 @@ final class ThemeAccentColorController: ViewController { } - override public func dismiss(completion: (() -> Void)? = nil) { - self.controllerNode.animateOut(completion: { [weak self] in - self?.presentingViewController?.dismiss(animated: false, completion: nil) - completion?() - }) - } - override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, transition: transition) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index 7cc5b0bb99..4f0c481db4 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -204,18 +204,6 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate } } - func animateIn(completion: (() -> Void)? = nil) { - self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) - } - - func animateOut(completion: (() -> Void)? = nil) { - self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in - completion?() - }) - } - - - private func updateChatsLayout(layout: ContainerViewLayout, topInset: CGFloat, transition: ContainedViewLayoutTransition) { var items: [ChatListItem] = [] diff --git a/submodules/SettingsUI/Sources/Themes/ThemeNameGenerator.swift b/submodules/SettingsUI/Sources/Themes/ThemeNameGenerator.swift index 4668967035..f2c391e63d 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeNameGenerator.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeNameGenerator.swift @@ -1,4 +1,5 @@ import UIKit +import Display private let colors: [UInt32: String] = [ 0x8e0000: "Berry", @@ -296,30 +297,6 @@ private let subjectives = [ "Zone" ] -private extension UIColor { - var colorComponents: (r: Int32, g: Int32, b: Int32) { - var r: CGFloat = 0.0 - var g: CGFloat = 0.0 - var b: CGFloat = 0.0 - if self.getRed(&r, green: &g, blue: &b, alpha: nil) { - return (Int32(max(0.0, r) * 255.0), Int32(max(0.0, g) * 255.0), Int32(max(0.0, b) * 255.0)) - } else if self.getWhite(&r, alpha: nil) { - return (Int32(max(0.0, r) * 255.0), Int32(max(0.0, r) * 255.0), Int32(max(0.0, r) * 255.0)) - } - return (0, 0, 0) - } - - func distance(to other: UIColor) -> Int32 { - let e1 = self.colorComponents - let e2 = other.colorComponents - let rMean = (e1.r + e2.r) / 2 - let r = e1.r - e2.r - let g = e1.g - e2.g - let b = e1.b - e2.b - return ((512 + rMean) * r * r) >> 8 + 4 * g * g + ((767 - rMean) * b * b) >> 8 - } -} - func generateThemeName(accentColor: UIColor) -> String { var nearest: (color: UInt32, distance: Int32)? for (color, _) in colors { diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift index ffa33fceae..b039aaafff 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAccentColorItem.swift @@ -8,7 +8,7 @@ import TelegramPresentationData import TelegramUIPreferences import ItemListUI -private func generateSwatchImage(color: PresentationThemeAccentColor, selected: Bool) -> UIImage? { +private func generateSwatchImage(theme: PresentationTheme, color: PresentationThemeAccentColor, selected: Bool) -> UIImage? { return generateImage(CGSize(width: 40.0, height: 40.0), rotatedContext: { size, context in let bounds = CGRect(origin: CGPoint(), size: size) context.clear(bounds) @@ -18,6 +18,13 @@ private func generateSwatchImage(color: PresentationThemeAccentColor, selected: if strokeColor == .clear { strokeColor = fillColor } + if strokeColor.distance(to: theme.list.itemBlocksBackgroundColor) < 200 { + if strokeColor.distance(to: UIColor.white) < 200 { + strokeColor = UIColor(rgb: 0x999999) + } else { + strokeColor = theme.list.controlSecondaryColor + } + } context.setFillColor(fillColor.cgColor) context.setStrokeColor(strokeColor.cgColor) @@ -130,8 +137,8 @@ private final class ThemeSettingsAccentColorNode : ASDisplayNode { self.addSubnode(self.iconNode) } - func setup(color: PresentationThemeAccentColor, selected: Bool, action: @escaping () -> Void) { - self.iconNode.image = generateSwatchImage(color: color, selected: selected) + func setup(theme: PresentationTheme, color: PresentationThemeAccentColor, selected: Bool, action: @escaping () -> Void) { + self.iconNode.image = generateSwatchImage(theme: theme, color: color, selected: selected) self.action = { action() } @@ -164,6 +171,7 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let scrollNode: ASScrollNode private var colorNodes: [ThemeSettingsAccentColorNode] = [] @@ -186,6 +194,8 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.scrollNode = ASScrollNode() self.customNode = HighlightableButtonNode() @@ -256,11 +266,19 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -271,8 +289,14 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) @@ -306,7 +330,7 @@ class ThemeSettingsAccentColorItemNode: ListViewItemNode, ItemListItemNode { accentColor = PresentationThemeAccentColor(baseColor: color) } - imageNode.setup(color: accentColor, selected: selected, action: { [weak self, weak imageNode] in + imageNode.setup(theme: item.theme, color: accentColor, selected: selected, action: { [weak self, weak imageNode] in item.updated(accentColor) if let imageNode = imageNode { self?.scrollToNode(imageNode, animated: true) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAppIconItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAppIconItem.swift index 1215142c04..d63445864b 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsAppIconItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsAppIconItem.swift @@ -158,6 +158,7 @@ class ThemeSettingsAppIconItemNode: ListViewItemNode, ItemListItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let scrollNode: ASScrollNode private var nodes: [ThemeSettingsAppIconNode] = [] @@ -179,6 +180,8 @@ class ThemeSettingsAppIconItemNode: ListViewItemNode, ItemListItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.scrollNode = ASScrollNode() super.init(layerBacked: false, dynamicBounce: false) @@ -234,11 +237,19 @@ class ThemeSettingsAppIconItemNode: ListViewItemNode, ItemListItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -249,8 +260,14 @@ class ThemeSettingsAppIconItemNode: ListViewItemNode, ItemListItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsBrightnessItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsBrightnessItem.swift index eca45addbf..5f3204a6cf 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsBrightnessItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsBrightnessItem.swift @@ -69,6 +69,7 @@ class ThemeSettingsBrightnessItemNode: ListViewItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private var sliderView: TGPhotoEditorSliderView? private let leftIconNode: ASImageNode @@ -87,6 +88,8 @@ class ThemeSettingsBrightnessItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.leftIconNode = ASImageNode() self.leftIconNode.displaysAsynchronously = false self.leftIconNode.displayWithoutProcessing = true @@ -169,23 +172,37 @@ class ThemeSettingsBrightnessItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat switch neighbors.bottom { - case .sameSection(false): - bottomStripeInset = params.leftInset + 16.0 - bottomStripeOffset = -separatorHeight - default: - bottomStripeInset = 0.0 - bottomStripeOffset = 0.0 + case .sameSection(false): + bottomStripeInset = params.leftInset + 16.0 + bottomStripeOffset = -separatorHeight + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index 052d07d796..7d49db8fc9 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -94,6 +94,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { private let backgroundNode: ASImageNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let containerNode: ASDisplayNode private var messageNodes: [ListViewItemNode]? @@ -113,6 +114,8 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.containerNode = ASDisplayNode() self.containerNode.subnodeTransform = CATransform3DMakeRotation(CGFloat.pi, 0.0, 0.0, 1.0) @@ -224,11 +227,19 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -239,8 +250,14 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) } diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsFontSizeItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsFontSizeItem.swift index 4114eedb9d..b503e0427d 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsFontSizeItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsFontSizeItem.swift @@ -72,6 +72,7 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private var sliderView: TGPhotoEditorSliderView? private let leftIconNode: ASImageNode @@ -94,6 +95,8 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.leftIconNode = ASImageNode() self.leftIconNode.displaysAsynchronously = false self.leftIconNode.displayWithoutProcessing = true @@ -196,11 +199,19 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { - case .sameSection(false): - strongSelf.topStripeNode.isHidden = true - default: - strongSelf.topStripeNode.isHidden = false + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -211,8 +222,14 @@ class ThemeSettingsFontSizeItemNode: ListViewItemNode, ItemListItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift index 6479f92969..53c45f7a4a 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsThemeItem.swift @@ -265,6 +265,7 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { private let backgroundNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode private let scrollNode: ASScrollNode private var nodes: [ThemeSettingsThemeItemIconNode] = [] @@ -286,6 +287,8 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { self.bottomStripeNode = ASDisplayNode() self.bottomStripeNode.isLayerBacked = true + self.maskNode = ASImageNode() + self.scrollNode = ASScrollNode() super.init(layerBacked: false, dynamicBounce: false) @@ -339,11 +342,19 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { if strongSelf.bottomStripeNode.supernode == nil { strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) } + if strongSelf.maskNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.maskNode, at: 3) + } + + let hasCorners = params.width > 480 + var hasTopCorners = false + var hasBottomCorners = false switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: - strongSelf.topStripeNode.isHidden = false + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -354,8 +365,14 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode { default: bottomStripeInset = 0.0 bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index c7ffe3dde0..086182f34c 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -93,7 +93,7 @@ private struct CollectableExternalShareItem { let mediaReference: AnyMediaReference? } -private func collectExternalShareItems(strings: PresentationStrings, postbox: Postbox, collectableItems: [CollectableExternalShareItem]) -> Signal { +private func collectExternalShareItems(strings: PresentationStrings, postbox: Postbox, collectableItems: [CollectableExternalShareItem], takeOne: Bool = true) -> Signal { var signals: [Signal] = [] for item in collectableItems { if let mediaReference = item.mediaReference, let file = mediaReference.media as? TelegramMediaFile { @@ -166,12 +166,12 @@ private func collectExternalShareItems(strings: PresentationStrings, postbox: Po } if let url = item.url, let parsedUrl = URL(string: url) { - if signals.isEmpty { + if signals.isEmpty || !takeOne { signals.append(.single(.done(.url(parsedUrl)))) } } if !item.text.isEmpty { - if signals.isEmpty { + if signals.isEmpty || !takeOne { signals.append(.single(.done(.text(item.text)))) } } @@ -535,7 +535,7 @@ public final class ShareController: ViewController { selectedMedia = media break loop case let webpage as TelegramMediaWebpage: - if case let .Loaded(content) = webpage.content { + if case let .Loaded(content) = webpage.content, ["photo", "document", "video", "gif"].contains(content.type) { if let file = content.file { selectedMedia = file } else if let image = content.image { @@ -559,7 +559,7 @@ public final class ShareController: ViewController { case .fromExternal: break } - return (collectExternalShareItems(strings: strongSelf.presentationData.strings, postbox: strongSelf.currentAccount.postbox, collectableItems: collectableItems) + return (collectExternalShareItems(strings: strongSelf.presentationData.strings, postbox: strongSelf.currentAccount.postbox, collectableItems: collectableItems, takeOne: !strongSelf.immediateExternalShare) |> deliverOnMainQueue) |> map { state in switch state { diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 4bcb96d378..d434eda2d6 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -259,7 +259,7 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta inputTextColor: .white, inputControlColor: UIColor(rgb: 0x7b7b7b), actionControlFillColor: accentColor, - actionControlForegroundColor: badgeTextColor, + actionControlForegroundColor: secondaryBadgeTextColor, primaryTextColor: .white, secondaryTextColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaRecordingDotColor: destructiveColor, diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index cdd3aab7ed..87ea7f4804 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -25,7 +25,7 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr outgoingCheckColor = .black outgoingControlColor = outgoingPrimaryTextColor outgoingBubbleFillColor = accentColor - if outgoingBubbleFillColor.rgb == 0xffffff { + if outgoingBubbleFillColor.distance(to: UIColor.white) < 200 { outgoingBubbleStrokeColor = UIColor(rgb: 0xc8c7cc) } else { outgoingBubbleStrokeColor = outgoingBubbleFillColor diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 52042de4a5..1f3cf847b7 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -2233,7 +2233,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) self.networkStateDisposable = (context.account.networkState |> deliverOnMainQueue).start(next: { [weak self] state in - if let strongSelf = self { + if let strongSelf = self, case .standard(previewing: false) = strongSelf.presentationInterfaceState.mode { strongSelf.chatTitleView?.networkState = state } }) @@ -2589,19 +2589,22 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.chatDisplayNode.historyNode.contentPositionChanged = { [weak self] offset in if let strongSelf = self { let offsetAlpha: CGFloat - switch offset { - case let .known(offset): - if offset < 40.0 { - offsetAlpha = 0.0 - } else { + if case let .standard(previewing) = strongSelf.presentationInterfaceState.mode, previewing { + offsetAlpha = 0.0 + } else { + switch offset { + case let .known(offset): + if offset < 40.0 { + offsetAlpha = 0.0 + } else { + offsetAlpha = 1.0 + } + case .unknown: offsetAlpha = 1.0 - } - case .unknown: - offsetAlpha = 1.0 - case .none: - offsetAlpha = 0.0 + case .none: + offsetAlpha = 0.0 + } } - strongSelf.chatDisplayNode.navigateButtons.displayDownButton = !offsetAlpha.isZero } } @@ -3162,6 +3165,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { current in return current.updatedSearch(nil) }) + strongSelf.updateItemNodesSearchTextHighlightStates() } }, updateMessageSearch: { [weak self] query in if let strongSelf = self { @@ -3184,7 +3188,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.interfaceInteraction?.navigateMessageSearch(.index(index)) }) strongSelf.chatDisplayNode.dismissInput() - (strongSelf.navigationController as? NavigationController)?.pushViewController(controller) + if case let .inline(navigationController) = strongSelf.presentationInterfaceState.mode { + navigationController?.pushViewController(controller) + } else { + strongSelf.push(controller) + } } }) } @@ -4046,7 +4054,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.chatUnreadMentionCountDisposable = (self.context.account.viewTracker.unseenPersonalMessagesCount(peerId: peerId) |> deliverOnMainQueue).start(next: { [weak self] count in if let strongSelf = self { - strongSelf.chatDisplayNode.navigateButtons.mentionCount = count + if case let .standard(previewing) = strongSelf.presentationInterfaceState.mode, previewing { + strongSelf.chatDisplayNode.navigateButtons.mentionCount = 0 + } else { + strongSelf.chatDisplayNode.navigateButtons.mentionCount = count + } } }) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift index f0a220dd47..1c8046d857 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift @@ -469,9 +469,12 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } } + var edited = false var viewCount: Int? = nil for attribute in item.message.attributes { - if let attribute = attribute as? ViewCountMessageAttribute { + if let _ = attribute as? EditedMessageAttribute, isEmoji { + edited = true + } else if let attribute = attribute as? ViewCountMessageAttribute { viewCount = attribute.count } } @@ -491,7 +494,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .minimal, reactionCount: dateReactionCount) - let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, false, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), dateReactions) + let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), dateReactions) var viaBotApply: (TextNodeLayout, () -> TextNode)? var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)? @@ -534,7 +537,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { let inlineBotNameColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText let nameString = NSAttributedString(string: sourcePeer.displayTitle, font: inlineBotPrefixFont, textColor: inlineBotNameColor) - viaBotApply = viaBotLayout(TextNodeLayoutArguments(attributedString: nameString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0, availableWidth), height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) } } @@ -659,15 +661,43 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { strongSelf.replyBackgroundNode = nil } + if let (viaBotLayout, viaBotApply) = viaBotApply { + let viaBotNode = viaBotApply() + if strongSelf.viaBotNode == nil { + strongSelf.viaBotNode = viaBotNode + strongSelf.addSubnode(viaBotNode) + } + let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 15.0) : (params.width - params.rightInset - viaBotLayout.size.width - layoutConstants.bubble.edgeInset - 14.0)), y: 8.0), size: viaBotLayout.size) + viaBotNode.frame = viaBotFrame + strongSelf.replyBackgroundNode?.frame = CGRect(origin: CGPoint(x: viaBotFrame.minX - 6.0, y: viaBotFrame.minY - 2.0 - UIScreenPixel), size: CGSize(width: viaBotFrame.size.width + 11.0, height: viaBotFrame.size.height + 5.0)) + } else if let viaBotNode = strongSelf.viaBotNode { + viaBotNode.removeFromSupernode() + strongSelf.viaBotNode = nil + } + if let (replyInfoSize, replyInfoApply) = replyInfoApply { let replyInfoNode = replyInfoApply() if strongSelf.replyInfoNode == nil { strongSelf.replyInfoNode = replyInfoNode strongSelf.addSubnode(replyInfoNode) } - let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - replyInfoSize.width - layoutConstants.bubble.edgeInset - 10.0)), y: 8.0), size: replyInfoSize) + var viaBotSize = CGSize() + if let viaBotNode = strongSelf.viaBotNode { + viaBotSize = viaBotNode.frame.size + } + let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - max(replyInfoSize.width, viaBotSize.width) - layoutConstants.bubble.edgeInset - 10.0)), y: 8.0 + viaBotSize.height), size: replyInfoSize) + if let viaBotNode = strongSelf.viaBotNode { + if replyInfoFrame.minX < viaBotNode.frame.minX { + viaBotNode.frame = viaBotNode.frame.offsetBy(dx: replyInfoFrame.minX - viaBotNode.frame.minX, dy: 0.0) + } + } replyInfoNode.frame = replyInfoFrame - strongSelf.replyBackgroundNode?.frame = CGRect(origin: CGPoint(x: replyInfoFrame.minX - 4.0, y: replyInfoFrame.minY - 2.0), size: CGSize(width: replyInfoFrame.size.width + 8.0, height: replyInfoFrame.size.height + 5.0)) + strongSelf.replyBackgroundNode?.frame = CGRect(origin: CGPoint(x: replyInfoFrame.minX - 4.0, y: replyInfoFrame.minY - viaBotSize.height - 2.0), size: CGSize(width: max(replyInfoFrame.size.width, viaBotSize.width) + 8.0, height: replyInfoFrame.size.height + viaBotSize.height + 5.0)) + + if let _ = item.controllerInteraction.selectionState, isEmoji { + replyInfoNode.alpha = 0.0 + strongSelf.replyBackgroundNode?.alpha = 0.0 + } } else if let replyInfoNode = strongSelf.replyInfoNode { replyInfoNode.removeFromSupernode() strongSelf.replyInfoNode = nil diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift index fbf9924573..57d9f13a11 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift @@ -338,7 +338,6 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let inlineBotNameColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText let nameString = NSAttributedString(string: sourcePeer.displayTitle, font: inlineBotPrefixFont, textColor: inlineBotNameColor) - viaBotApply = viaBotLayout(TextNodeLayoutArguments(attributedString: nameString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0, availableWidth), height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) } } @@ -515,7 +514,6 @@ class ChatMessageStickerItemNode: ChatMessageItemView { strongSelf.replyInfoNode = nil } - if isFailed { let deliveryFailedNode: ChatMessageDeliveryFailedNode var isAppearing = false diff --git a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift index 2a4bb452e9..cd180a3506 100644 --- a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift +++ b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift @@ -775,56 +775,57 @@ public class PeerMediaCollectionController: TelegramBaseController { let controller = strongSelf.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: strongSelf.context, filter: [.onlyWriteable, .excludeDisabled])) controller.peerSelected = { [weak controller] peerId in if let strongSelf = self, let _ = controller { - let _ = (strongSelf.context.account.postbox.transaction({ transaction -> Void in - transaction.updatePeerChatInterfaceState(peerId, update: { currentState in - if let currentState = currentState as? ChatInterfaceState { - return currentState.withUpdatedForwardMessageIds(forwardMessageIds) - } else { - return ChatInterfaceState().withUpdatedForwardMessageIds(forwardMessageIds) + if peerId == strongSelf.context.account.peerId { + strongSelf.updateInterfaceState(animated: false, { $0.withoutSelectionState() }) + + let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in + return .forward(source: id, grouping: .auto, attributes: []) + }) + |> deliverOnMainQueue).start(next: { [weak self] messageIds in + if let strongSelf = self { + let signals: [Signal] = messageIds.compactMap({ id -> Signal? in + guard let id = id else { + return nil + } + return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id) + |> mapToSignal { status, _ -> Signal in + if status != nil { + return .never() + } else { + return .single(true) + } + } + |> take(1) + }) + if strongSelf.shareStatusDisposable == nil { + strongSelf.shareStatusDisposable = MetaDisposable() + } + strongSelf.shareStatusDisposable?.set((combineLatest(signals) + |> deliverOnMainQueue).start(completed: { + guard let strongSelf = self else { + return + } + strongSelf.present(OverlayStatusController(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, type: .success), in: .window(.root)) + })) } }) - }) |> deliverOnMainQueue).start(completed: { - if let strongSelf = self { - strongSelf.updateInterfaceState(animated: false, { $0.withoutSelectionState() }) - - if peerId == strongSelf.context.account.peerId { - let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messageIds.map { id -> EnqueueMessage in - return .forward(source: id, grouping: .auto, attributes: []) - }) - |> deliverOnMainQueue).start(next: { [weak self] messageIds in - if let strongSelf = self { - let signals: [Signal] = messageIds.compactMap({ id -> Signal? in - guard let id = id else { - return nil - } - return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id) - |> mapToSignal { status, _ -> Signal in - if status != nil { - return .never() - } else { - return .single(true) - } - } - |> take(1) - }) - if strongSelf.shareStatusDisposable == nil { - strongSelf.shareStatusDisposable = MetaDisposable() - } - strongSelf.shareStatusDisposable?.set((combineLatest(signals) - |> deliverOnMainQueue).start(completed: { - guard let strongSelf = self else { - return - } - strongSelf.present(OverlayStatusController(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, type: .success), in: .window(.root)) - })) - } - }) - if let strongController = controller { - strongController.dismiss() + if let strongController = controller { + strongController.dismiss() + } + } else { + let _ = (strongSelf.context.account.postbox.transaction({ transaction -> Void in + transaction.updatePeerChatInterfaceState(peerId, update: { currentState in + if let currentState = currentState as? ChatInterfaceState { + return currentState.withUpdatedForwardMessageIds(forwardMessageIds) + } else { + return ChatInterfaceState().withUpdatedForwardMessageIds(forwardMessageIds) } - } else { - let ready = ValuePromise() + }) + }) |> deliverOnMainQueue).start(completed: { + if let strongSelf = self { + strongSelf.updateInterfaceState(animated: false, { $0.withoutSelectionState() }) + let ready = ValuePromise() strongSelf.messageContextDisposable.set((ready.get() |> take(1) |> deliverOnMainQueue).start(next: { _ in if let strongController = controller { strongController.dismiss() @@ -833,8 +834,8 @@ public class PeerMediaCollectionController: TelegramBaseController { (strongSelf.navigationController as? NavigationController)?.replaceTopController(ChatControllerImpl(context: strongSelf.context, chatLocation: .peer(peerId)), animated: false, ready: ready) } - } - }) + }) + } } } (strongSelf.navigationController as? NavigationController)?.pushViewController(controller) diff --git a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift index 8414b342a2..087e67bb69 100644 --- a/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift +++ b/submodules/TelegramUI/TelegramUI/SharedAccountContext.swift @@ -1008,8 +1008,8 @@ public final class SharedAccountContextImpl: SharedAccountContext { return createGroupControllerImpl(context: context, peerIds: peerIds, initialTitle: initialTitle, mode: mode, completion: completion) } - public func makeChatListController(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool, enableDebugActions: Bool) -> ChatListController { - return ChatListControllerImpl(context: context, groupId: groupId, controlsHistoryPreload: controlsHistoryPreload, hideNetworkActivityStatus: hideNetworkActivityStatus, enableDebugActions: enableDebugActions) + public func makeChatListController(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool, previewing: Bool, enableDebugActions: Bool) -> ChatListController { + return ChatListControllerImpl(context: context, groupId: groupId, controlsHistoryPreload: controlsHistoryPreload, hideNetworkActivityStatus: hideNetworkActivityStatus, previewing: previewing, enableDebugActions: enableDebugActions) } public func makePeerSelectionController(_ params: PeerSelectionControllerParams) -> PeerSelectionController { diff --git a/submodules/TelegramUI/TelegramUI/TelegramRootController.swift b/submodules/TelegramUI/TelegramUI/TelegramRootController.swift index c0de067a68..20b8de99e5 100644 --- a/submodules/TelegramUI/TelegramUI/TelegramRootController.swift +++ b/submodules/TelegramUI/TelegramUI/TelegramRootController.swift @@ -80,7 +80,7 @@ public final class TelegramRootController: NavigationController { public func addRootControllers(showCallsTab: Bool) { let tabBarController = TabBarController(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData), theme: TabBarControllerTheme(rootControllerTheme: self.presentationData.theme)) tabBarController.navigationPresentation = .master - let chatListController = self.context.sharedContext.makeChatListController(context: self.context, groupId: .root, controlsHistoryPreload: true, hideNetworkActivityStatus: false, enableDebugActions: !GlobalExperimentalSettings.isAppStoreBuild) + let chatListController = self.context.sharedContext.makeChatListController(context: self.context, groupId: .root, controlsHistoryPreload: true, hideNetworkActivityStatus: false, previewing: false, enableDebugActions: !GlobalExperimentalSettings.isAppStoreBuild) if let sharedContext = self.context.sharedContext as? SharedAccountContextImpl { chatListController.tabBarItem.badgeValue = sharedContext.switchingData.chatListBadge } diff --git a/submodules/TelegramUIPreferences/Sources/CallListSettings.swift b/submodules/TelegramUIPreferences/Sources/CallListSettings.swift index 239f6a554c..ff81d69b1a 100644 --- a/submodules/TelegramUIPreferences/Sources/CallListSettings.swift +++ b/submodules/TelegramUIPreferences/Sources/CallListSettings.swift @@ -6,7 +6,7 @@ public struct CallListSettings: PreferencesEntry, Equatable { public var showTab: Bool public static var defaultSettings: CallListSettings { - return CallListSettings(showTab: true) + return CallListSettings(showTab: false) } public init(showTab: Bool) { diff --git a/submodules/TextFormat/Sources/GenerateTextEntities.swift b/submodules/TextFormat/Sources/GenerateTextEntities.swift index 0fb56fbb4b..b28f98aa21 100644 --- a/submodules/TextFormat/Sources/GenerateTextEntities.swift +++ b/submodules/TextFormat/Sources/GenerateTextEntities.swift @@ -20,11 +20,13 @@ private let validIdentifierSet: CharacterSet = { private let identifierDelimiterSet: CharacterSet = { var set = CharacterSet.punctuationCharacters set.formUnion(CharacterSet.whitespacesAndNewlines) + set.insert("|") return set }() private let externalIdentifierDelimiterSet: CharacterSet = { var set = CharacterSet.punctuationCharacters set.formUnion(CharacterSet.whitespacesAndNewlines) + set.insert("|") set.remove(".") return set }()