From 66b3d8b8747a6e529aea838d28499c47ad02811d Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Wed, 22 Nov 2023 01:05:47 +0400 Subject: [PATCH] [WIP] Colored profiles --- .../Sources/AccountContext.swift | 116 ++++++- .../Sources/ChatListSearchListPaneNode.swift | 2 +- .../Sources/ChatListShimmerNode.swift | 2 +- .../InviteContactsControllerNode.swift | 2 +- .../Sources/ContextSourceContainer.swift | 1 + submodules/Display/Source/NavigationBar.swift | 11 + .../Display/Source/NavigationButtonNode.swift | 8 + .../Display/Source/Nodes/ASImageNode.swift | 4 + .../Display/Source/ViewController.swift | 2 +- .../Sources/InstantPageControllerNode.swift | 2 +- .../Sources/InviteLinkViewController.swift | 4 +- submodules/ItemListUI/BUILD | 2 + ...ItemListControllerSegmentedTitleView.swift | 86 ++++- .../Sources/MediaPickerSelectedListNode.swift | 2 +- .../Sources/DeviceContactInfoController.swift | 2 +- .../BubbleSettingsController.swift | 4 +- .../ForwardPrivacyChatPreviewItem.swift | 2 +- .../Reactions/ReactionChatPreviewItem.swift | 2 +- .../TextSizeSelectionController.swift | 20 +- .../ThemeAccentColorControllerNode.swift | 16 +- .../Themes/ThemePreviewControllerNode.swift | 22 +- .../Themes/ThemeSettingsChatPreviewItem.swift | 4 +- .../Sources/Themes/WallpaperGalleryItem.swift | 4 +- .../Sources/ApiUtils/ApiGroupOrChannel.swift | 8 +- .../Sources/ApiUtils/TelegramUser.swift | 8 +- .../State/AccountStateManagementUtils.swift | 2 +- .../SyncCore/SyncCore_TelegramChannel.swift | 50 ++- .../SyncCore/SyncCore_TelegramUser.swift | 56 ++- .../TelegramEngineAccountData.swift | 4 +- .../AccountData/UpdateAccountPeerName.swift | 4 +- .../TelegramEngine/Messages/AdMessages.swift | 8 +- .../Sources/TelegramEngine/Peers/Peer.swift | 8 + .../Peers/TelegramEnginePeers.swift | 4 +- .../TelegramEngine/Peers/UpdatePeerInfo.swift | 2 +- .../Sources/Utils/PeerUtils.swift | 22 ++ .../PresentationResourcesRootController.swift | 2 +- .../Sources/ChatMessageBubbleItemNode.swift | 4 +- .../Sources/ChatMessageItemImpl.swift | 2 +- .../ChatRecentActionsHistoryTransition.swift | 2 +- .../DustEffect/Sources/DustEffectLayer.swift | 2 +- .../Sources/EmojiPagerContentComponent.swift | 53 ++- .../Sources/EmojiSearchContent.swift | 3 +- .../Sources/EntityKeyboard.swift | 4 +- .../EntityKeyboardTopPanelComponent.swift | 4 +- .../Sources/MultiScaleTextNode.swift | 6 + .../NotificationExceptionsScreen.swift | 2 +- .../Sources/PeerInfoCoverComponent.swift | 46 ++- .../Components/PeerInfo/PeerInfoScreen/BUILD | 1 + ...PeerInfoAvatarTransformContainerNode.swift | 18 +- .../PeerInfoScreen/Sources/PeerInfoData.swift | 9 +- .../Sources/PeerInfoHeaderButtonNode.swift | 161 +++++---- .../PeerInfoHeaderNavigationButton.swift | 191 +++++----- ...oHeaderNavigationButtonContainerNode.swift | 50 +-- .../Sources/PeerInfoHeaderNode.swift | 314 ++++++++++++----- .../Sources/PeerInfoScreen.swift | 61 ++-- .../Settings/PeerNameColorScreen/BUILD | 2 + .../Sources/EmojiPickerItem.swift | 29 +- .../PeerNameColorChatPreviewItem.swift | 4 +- .../Sources/PeerNameColorItem.swift | 36 +- .../PeerNameColorProfilePreviewItem.swift | 274 +++++++++++++++ .../Sources/PeerNameColorScreen.swift | 327 ++++++++++++++---- .../PeerNameColorScreenComponent.swift | 13 + .../Sources/TabSelectorComponent.swift | 8 +- .../BackArrow.imageset/BackArrow.svg | 3 + .../BackArrow.imageset/Contents.json | 12 + .../Images.xcassets/Navigation/Contents.json | 9 + .../TelegramUI/Sources/AppDelegate.swift | 1 + .../Sources/ChatControllerNode.swift | 4 +- .../Sources/PollResultsController.swift | 2 +- 69 files changed, 1626 insertions(+), 529 deletions(-) create mode 100644 submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorProfilePreviewItem.swift create mode 100644 submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreenComponent.swift create mode 100644 submodules/TelegramUI/Images.xcassets/Navigation/BackArrow.imageset/BackArrow.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Navigation/BackArrow.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Navigation/Contents.json diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 6d450b7d0d..71006adaca 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -1271,7 +1271,10 @@ public class PeerNameColors: Equatable { return PeerNameColors( colors: defaultSingleColors, darkColors: [:], - displayOrder: [5, 3, 1, 0, 2, 4, 6] + displayOrder: [5, 3, 1, 0, 2, 4, 6], + profileColors: [:], + profileDarkColors: [:], + profileDisplayOrder: [] ) } @@ -1279,6 +1282,10 @@ public class PeerNameColors: Equatable { public let darkColors: [Int32: Colors] public let displayOrder: [Int32] + public let profileColors: [Int32: Colors] + public let profileDarkColors: [Int32: Colors] + public let profileDisplayOrder: [Int32] + public func get(_ color: PeerNameColor, dark: Bool = false) -> Colors { if dark, let colors = self.darkColors[color.rawValue] { return colors @@ -1289,10 +1296,30 @@ public class PeerNameColors: Equatable { } } - fileprivate init(colors: [Int32: Colors], darkColors: [Int32: Colors], displayOrder: [Int32]) { + public func getProfile(_ color: PeerNameColor, dark: Bool = false) -> Colors { + if dark, let colors = self.profileDarkColors[color.rawValue] { + return colors + } else if let colors = self.profileColors[color.rawValue] { + return colors + } else { + return Colors(main: UIColor(rgb: 0xcc5049)) + } + } + + fileprivate init( + colors: [Int32: Colors], + darkColors: [Int32: Colors], + displayOrder: [Int32], + profileColors: [Int32: Colors], + profileDarkColors: [Int32: Colors], + profileDisplayOrder: [Int32] + ) { self.colors = colors self.darkColors = darkColors self.displayOrder = displayOrder + self.profileColors = profileColors + self.profileDarkColors = profileDarkColors + self.profileDisplayOrder = profileDisplayOrder } public static func with(appConfiguration: AppConfiguration) -> PeerNameColors { @@ -1330,10 +1357,84 @@ public class PeerNameColors: Equatable { displayOrder = PeerNameColors.defaultValue.displayOrder } + var profileColors = PeerNameColors.defaultSingleColors + var profileDarkColors: [Int32: Colors] = [:] + + if let peerColors = data["profile_colors"] as? [String: [String]] { + for (key, values) in peerColors { + if let index = Int32(key) { + let colorsArray = values.compactMap { UIColor(hexString: $0) } + if let colorValues = Colors(colors: colorsArray) { + profileColors[index] = colorValues + } + } + } + } else { + profileColors = [ + 0: Colors(main: UIColor(rgb: 0x5A8FBB), secondary: nil, tertiary: nil), + 1: Colors(main: UIColor(rgb: 0x49A355), secondary: nil, tertiary: nil), + 2: Colors(main: UIColor(rgb: 0xC27C3E), secondary: nil, tertiary: nil), + 3: Colors(main: UIColor(rgb: 0xBA5650), secondary: nil, tertiary: nil), + 4: Colors(main: UIColor(rgb: 0x956AC8), secondary: nil, tertiary: nil), + 5: Colors(main: UIColor(rgb: 0x3E97AD), secondary: nil, tertiary: nil), + 6: Colors(main: UIColor(rgb: 0xB85378), secondary: nil, tertiary: nil), + 7: Colors(main: UIColor(rgb: 0x7F8B95), secondary: nil, tertiary: nil), + 8: Colors(main: UIColor(rgb: 0x538BC2), secondary: UIColor(rgb: 0x4DA8BD), tertiary: nil), + 9: Colors(main: UIColor(rgb: 0x3D9755), secondary: UIColor(rgb: 0x89A650), tertiary: nil), + 10: Colors(main: UIColor(rgb: 0xCF7244), secondary: UIColor(rgb: 0xCC9433), tertiary: nil), + 11: Colors(main: UIColor(rgb: 0xC9565D), secondary: UIColor(rgb: 0xD97C57), tertiary: nil), + 12: Colors(main: UIColor(rgb: 0x9662D4), secondary: UIColor(rgb: 0xB966B6), tertiary: nil), + 13: Colors(main: UIColor(rgb: 0x3D95BA), secondary: UIColor(rgb: 0x50AD98), tertiary: nil), + 14: Colors(main: UIColor(rgb: 0xB04F74), secondary: UIColor(rgb: 0xD1666D), tertiary: nil), + 15: Colors(main: UIColor(rgb: 0x637482), secondary: UIColor(rgb: 0x7B8A97), tertiary: nil), + ] + } + + if let darkPeerColors = data["dark_profile_colors"] as? [String: [String]] { + for (key, values) in darkPeerColors { + if let index = Int32(key) { + let colorsArray = values.compactMap { UIColor(hexString: $0) } + if let colorValues = Colors(colors: colorsArray) { + profileDarkColors[index] = colorValues + } + } + } + } else { + profileDarkColors = [ + 0: Colors(main: UIColor(rgb: 0x477194), secondary: nil, tertiary: nil), + 1: Colors(main: UIColor(rgb: 0x33713B), secondary: nil, tertiary: nil), + 2: Colors(main: UIColor(rgb: 0x945E2C), secondary: nil, tertiary: nil), + 3: Colors(main: UIColor(rgb: 0x9C4540), secondary: nil, tertiary: nil), + 4: Colors(main: UIColor(rgb: 0x715099), secondary: nil, tertiary: nil), + 5: Colors(main: UIColor(rgb: 0x387E87), secondary: nil, tertiary: nil), + 6: Colors(main: UIColor(rgb: 0x944763), secondary: nil, tertiary: nil), + 7: Colors(main: UIColor(rgb: 0x435261), secondary: nil, tertiary: nil), + 8: Colors(main: UIColor(rgb: 0x38618C), secondary: UIColor(rgb: 0x458BA1), tertiary: nil), + 9: Colors(main: UIColor(rgb: 0x296A43), secondary: UIColor(rgb: 0x5F8F44), tertiary: nil), + 10: Colors(main: UIColor(rgb: 0x8F552F), secondary: UIColor(rgb: 0xA17232), tertiary: nil), + 11: Colors(main: UIColor(rgb: 0x994343), secondary: UIColor(rgb: 0xAC583E), tertiary: nil), + 12: Colors(main: UIColor(rgb: 0x634691), secondary: UIColor(rgb: 0x9250A2), tertiary: nil), + 13: Colors(main: UIColor(rgb: 0x306C7C), secondary: UIColor(rgb: 0x3E987E), tertiary: nil), + 14: Colors(main: UIColor(rgb: 0x884160), secondary: UIColor(rgb: 0xA65259), tertiary: nil), + 15: Colors(main: UIColor(rgb: 0x384654), secondary: UIColor(rgb: 0x99ACC3), tertiary: nil), + ] + } + + var profileDisplayOrder: [Int32] = [] + if let order = data["profile_colors_available"] as? [Double] { + profileDisplayOrder = order.map { Int32($0) } + } + if profileDisplayOrder.isEmpty { + profileDisplayOrder = Array((0 ..< profileColors.count).map { i in Int32(i) }) + } + return PeerNameColors( colors: colors, darkColors: darkColors, - displayOrder: displayOrder + displayOrder: displayOrder, + profileColors: profileColors, + profileDarkColors: profileDarkColors, + profileDisplayOrder: profileDisplayOrder ) } else { return .defaultValue @@ -1350,6 +1451,15 @@ public class PeerNameColors: Equatable { if lhs.displayOrder != rhs.displayOrder { return false } + if lhs.profileColors != rhs.profileColors { + return false + } + if lhs.profileDarkColors != rhs.profileDarkColors { + return false + } + if lhs.profileDisplayOrder != rhs.profileDisplayOrder { + return false + } return true } } diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index d6c0d7db81..ef04a62b29 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -3531,7 +3531,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode { let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) - let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) let timestamp1: Int32 = 100000 var peers: [EnginePeer.Id: EnginePeer] = [:] peers[peer1.id] = peer1 diff --git a/submodules/ChatListUI/Sources/ChatListShimmerNode.swift b/submodules/ChatListUI/Sources/ChatListShimmerNode.swift index 14526c30c6..5db4d9194e 100644 --- a/submodules/ChatListUI/Sources/ChatListShimmerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListShimmerNode.swift @@ -150,7 +150,7 @@ final class ChatListShimmerNode: ASDisplayNode { let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) - let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: Namespaces.Peer.CloudUser, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "FirstName", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) let timestamp1: Int32 = 100000 let peers: [EnginePeer.Id: EnginePeer] = [:] let interaction = ChatListNodeInteraction(context: context, animationCache: animationCache, animationRenderer: animationRenderer, activateSearch: {}, peerSelected: { _, _, _, _ in }, disabledPeerSelected: { _, _ in }, togglePeerSelected: { _, _ in }, togglePeersSelection: { _, _ in }, additionalCategorySelected: { _ in diff --git a/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift b/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift index 579c98cf80..3786a03d23 100644 --- a/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift +++ b/submodules/ContactListUI/Sources/InviteContactsControllerNode.swift @@ -56,7 +56,7 @@ private enum InviteContactsEntry: Comparable, Identifiable { } else { status = .none } - let peer: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: contact.firstName, lastName: contact.lastName, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) + let peer: EnginePeer = .user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: contact.firstName, lastName: contact.lastName, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: status, enabled: true, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: ChatListSearchItemHeader(type: .contacts, theme: theme, strings: strings, actionTitle: nil, action: nil), action: { _ in interaction.toggleContact(id) }) diff --git a/submodules/ContextUI/Sources/ContextSourceContainer.swift b/submodules/ContextUI/Sources/ContextSourceContainer.swift index a12b0cd501..dc620965b8 100644 --- a/submodules/ContextUI/Sources/ContextSourceContainer.swift +++ b/submodules/ContextUI/Sources/ContextSourceContainer.swift @@ -610,6 +610,7 @@ final class ContextSourceContainer: ASDisplayNode { selection: presentationData.theme.contextMenu.primaryColor.withMultipliedAlpha(0.1) ), customLayout: TabSelectorComponent.CustomLayout( + font: Font.medium(14.0), spacing: 9.0 ), items: mappedItems, diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 489396a9ff..1ddb6767cf 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -476,6 +476,8 @@ open class NavigationBar: ASDisplayNode { } } } + + public static let thinBackArrowImage = generateTintedImage(image: UIImage(bundleImageName: "Navigation/BackArrow"), color: .white)?.withRenderingMode(.alwaysTemplate) public static let titleFont = Font.with(size: 17.0, design: .regular, weight: .semibold, traits: [.monospacedNumbers]) @@ -729,11 +731,20 @@ open class NavigationBar: ASDisplayNode { self.updateAccessibilityElements() } + public var enableAutomaticBackButton: Bool = true + var _previousItem: NavigationPreviousAction? public internal(set) var previousItem: NavigationPreviousAction? { get { + if !self.enableAutomaticBackButton { + return nil + } return self._previousItem } set(value) { + if !self.enableAutomaticBackButton { + self._previousItem = nil + return + } if self._previousItem != value { if let previousValue = self._previousItem, case let .item(itemValue) = previousValue { if let previousItemListenerKey = self.previousItemListenerKey { diff --git a/submodules/Display/Source/NavigationButtonNode.swift b/submodules/Display/Source/NavigationButtonNode.swift index 46a5ad84cc..fe281a6211 100644 --- a/submodules/Display/Source/NavigationButtonNode.swift +++ b/submodules/Display/Source/NavigationButtonNode.swift @@ -338,6 +338,10 @@ public final class NavigationButtonNode: ContextControllerSourceNode { return nil } + public var mainContentNode: ASDisplayNode? { + return self.nodes.first + } + public var pressed: (Int) -> () = { _ in } public var highlightChanged: (Int, Bool) -> () = { _, _ in } @@ -397,6 +401,8 @@ public final class NavigationButtonNode: ContextControllerSourceNode { } } + public var contentsColor: UIColor? + public func updateManualAlpha(alpha: CGFloat, transition: ContainedViewLayoutTransition) { for node in self.nodes { transition.updateAlpha(node: node, alpha: alpha) @@ -411,6 +417,7 @@ public final class NavigationButtonNode: ContextControllerSourceNode { node = NavigationButtonItemNode() node.color = self.color node.rippleColor = self.rippleColor + node.layer.layerTintColor = self.contentsColor?.cgColor node.highlightChanged = { [weak node, weak self] value in if let strongSelf = self, let node = node { if let index = strongSelf.nodes.firstIndex(where: { $0 === node }) { @@ -454,6 +461,7 @@ public final class NavigationButtonNode: ContextControllerSourceNode { node = NavigationButtonItemNode() node.color = self.color node.rippleColor = self.rippleColor + node.layer.layerTintColor = self.contentsColor?.cgColor node.highlightChanged = { [weak node, weak self] value in if let strongSelf = self, let node = node { if let index = strongSelf.nodes.firstIndex(where: { $0 === node }) { diff --git a/submodules/Display/Source/Nodes/ASImageNode.swift b/submodules/Display/Source/Nodes/ASImageNode.swift index 2ebf0e9987..f4b8406aaa 100644 --- a/submodules/Display/Source/Nodes/ASImageNode.swift +++ b/submodules/Display/Source/Nodes/ASImageNode.swift @@ -47,4 +47,8 @@ open class ASImageNode: ASDisplayNode { override public func calculateSizeThatFits(_ contrainedSize: CGSize) -> CGSize { return self.image?.size ?? CGSize() } + + public var asdf: Int { + return 1234 + } } diff --git a/submodules/Display/Source/ViewController.swift b/submodules/Display/Source/ViewController.swift index ea8372fc72..8e7f0feded 100644 --- a/submodules/Display/Source/ViewController.swift +++ b/submodules/Display/Source/ViewController.swift @@ -155,7 +155,7 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject { return self.prefersOnScreenNavigationHidden } - public internal(set) var previousItem: NavigationPreviousAction? + open var previousItem: NavigationPreviousAction? open var navigationPresentation: ViewControllerNavigationPresentation = .default open var _presentedInModal: Bool = false diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index c2e3048b8a..795b118c2f 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1412,7 +1412,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { }, openUrl: { _ in }, openPeer: { _ in }, showAll: false) - let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) let controller = LocationViewController(context: self.context, subject: EngineMessage(message), params: controllerParams) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index 0146ab8af0..ba8fe938f5 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -726,7 +726,7 @@ public final class InviteLinkViewController: ViewController { if requestsState.importers.isEmpty && requestsState.isLoadingMore { count = min(4, state.count) loading = true - let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) for i in 0 ..< count { entries.append(.request(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, true)) } @@ -760,7 +760,7 @@ public final class InviteLinkViewController: ViewController { if state.importers.isEmpty && state.isLoadingMore { count = min(4, state.count) loading = true - let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + let fakeUser = TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) for i in 0 ..< count { entries.append(.importer(Int32(i), presentationData.theme, presentationData.dateTimeFormat, EnginePeer.user(fakeUser), 0, false, true)) } diff --git a/submodules/ItemListUI/BUILD b/submodules/ItemListUI/BUILD index 59b5c92032..1791a5db3c 100644 --- a/submodules/ItemListUI/BUILD +++ b/submodules/ItemListUI/BUILD @@ -29,6 +29,8 @@ swift_library( "//submodules/ManagedAnimationNode:ManagedAnimationNode", "//submodules/AvatarNode", "//submodules/TelegramCore", + "//submodules/ComponentFlow", + "//submodules/TelegramUI/Components/TabSelectorComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/ItemListUI/Sources/ItemListControllerSegmentedTitleView.swift b/submodules/ItemListUI/Sources/ItemListControllerSegmentedTitleView.swift index e98741580d..7da5bebbdd 100644 --- a/submodules/ItemListUI/Sources/ItemListControllerSegmentedTitleView.swift +++ b/submodules/ItemListUI/Sources/ItemListControllerSegmentedTitleView.swift @@ -2,48 +2,48 @@ import Foundation import UIKit import SegmentedControlNode import TelegramPresentationData +import ComponentFlow +import TabSelectorComponent +import Display public final class ItemListControllerSegmentedTitleView: UIView { - private let segmentedControlNode: SegmentedControlNode + private let tabSelector = ComponentView() public var theme: PresentationTheme { didSet { - self.segmentedControlNode.updateTheme(SegmentedControlTheme(theme: self.theme)) + if self.theme !== oldValue { + self.setNeedsLayout() + } } } public var segments: [String] { didSet { if self.segments != oldValue { - self.segmentedControlNode.items = self.segments.map { SegmentedControlItem(title: $0) } self.setNeedsLayout() } } } public var index: Int { - get { - return self.segmentedControlNode.selectedIndex - } - set { - self.segmentedControlNode.selectedIndex = newValue + didSet { + if self.index != oldValue { + self.animateLayout = true + self.setNeedsLayout() + } } } + private var validLayout: CGSize? + private var animateLayout: Bool = false + public var indexUpdated: ((Int) -> Void)? public init(theme: PresentationTheme, segments: [String], selectedIndex: Int) { self.theme = theme self.segments = segments - - self.segmentedControlNode = SegmentedControlNode(theme: SegmentedControlTheme(theme: theme), items: segments.map { SegmentedControlItem(title: $0) }, selectedIndex: selectedIndex) + self.index = selectedIndex super.init(frame: CGRect()) - - self.segmentedControlNode.selectedIndexChanged = { [weak self] index in - self?.indexUpdated?(index) - } - - self.addSubnode(self.segmentedControlNode) } required public init?(coder aDecoder: NSCoder) { @@ -54,7 +54,57 @@ public final class ItemListControllerSegmentedTitleView: UIView { super.layoutSubviews() let size = self.bounds.size - let controlSize = self.segmentedControlNode.updateLayout(.sizeToFit(maximumWidth: size.width, minimumWidth: 160.0, height: 32.0), transition: .immediate) - self.segmentedControlNode.frame = CGRect(origin: CGPoint(x: floor((size.width - controlSize.width) / 2.0), y: floor((size.height - controlSize.height) / 2.0)), size: controlSize) + self.validLayout = size + self.update(transition: .immediate) + } + + private func update(transition: Transition) { + guard let size = self.validLayout else { + return + } + + let mappedItems = zip(0 ..< self.segments.count, self.segments).map { index, segment in + return TabSelectorComponent.Item( + id: AnyHashable(index), + title: segment + ) + } + + var transition = transition + if self.animateLayout { + transition = .spring(duration: 0.4) + self.animateLayout = false + } + + let tabSelectorSize = self.tabSelector.update( + transition: transition, + component: AnyComponent(TabSelectorComponent( + colors: TabSelectorComponent.Colors( + foreground: self.theme.list.itemPrimaryTextColor.withMultipliedAlpha(0.8), + selection: self.theme.list.itemPrimaryTextColor.withMultipliedAlpha(0.05) + ), + customLayout: TabSelectorComponent.CustomLayout( + font: Font.medium(15.0), + spacing: 8.0 + ), + items: mappedItems, + selectedId: AnyHashable(self.index), + setSelectedId: { [weak self] id in + guard let self, let index = id.base as? Int else { + return + } + self.indexUpdated?(index) + } + )), + environment: {}, + containerSize: CGSize(width: size.width, height: 44.0) + ) + let tabSelectorFrame = CGRect(origin: CGPoint(x: floor((size.width - tabSelectorSize.width) / 2.0), y: floor((size.height - tabSelectorSize.height) / 2.0)), size: tabSelectorSize) + if let tabSelectorView = self.tabSelector.view { + if tabSelectorView.superview == nil { + self.addSubview(tabSelectorView) + } + transition.setFrame(view: tabSelectorView, frame: tabSelectorFrame) + } } } diff --git a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift index cdcafeffc9..3b727bc835 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift @@ -854,7 +854,7 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)) var peers = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) let previewText = groupLayouts.count > 1 ? presentationData.strings.Attachment_MessagesPreview : presentationData.strings.Attachment_MessagePreview diff --git a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift index b2382f72d2..777edd846f 100644 --- a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift +++ b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift @@ -663,7 +663,7 @@ private func deviceContactInfoEntries(account: Account, engine: TelegramEngine, firstName = presentationData.strings.Message_Contact } - entries.append(.info(entries.count, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer ?? EnginePeer.user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: firstName, lastName: isOrganization ? nil : personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary, isPlain: !isShare, hiddenAvatar: hiddenAvatar)) + entries.append(.info(entries.count, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer: peer ?? EnginePeer.user(TelegramUser(id: EnginePeer.Id(namespace: .max, id: EnginePeer.Id.Id._internalFromInt64Value(0)), accessHash: nil, firstName: firstName, lastName: isOrganization ? nil : personName.1, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)), state: ItemListAvatarAndNameInfoItemState(editingName: editingName, updatingName: nil), job: isOrganization ? nil : jobSummary, isPlain: !isShare, hiddenAvatar: hiddenAvatar)) if !selecting { if let _ = peer { diff --git a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift index b549d3d41e..a34be8551b 100644 --- a/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift +++ b/submodules/SettingsUI/Sources/BubbleSettings/BubbleSettingsController.swift @@ -163,8 +163,8 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) diff --git a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift index 22ab048ed3..70d6e57038 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/ForwardPrivacyChatPreviewItem.swift @@ -145,7 +145,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() let messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: item.peerName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: item.peerName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName, psaType: nil, flags: []) diff --git a/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift b/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift index 33ffc6a2fc..287ca363bd 100644 --- a/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Reactions/ReactionChatPreviewItem.swift @@ -274,7 +274,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() let messages = SimpleDictionary() - peers[userPeerId] = TelegramUser(id: userPeerId, accessHash: nil, firstName: item.strings.Settings_QuickReactionSetup_DemoMessageAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) + peers[userPeerId] = TelegramUser(id: userPeerId, accessHash: nil, firstName: item.strings.Settings_QuickReactionSetup_DemoMessageAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) let messageText = item.strings.Settings_QuickReactionSetup_DemoMessageText diff --git a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift index ca37f1a9d8..cbdf0b3716 100644 --- a/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift +++ b/submodules/SettingsUI/Sources/Text Size/TextSizeSelectionController.swift @@ -304,14 +304,14 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView ) } - let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) + let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) let timestamp = self.referenceTimestamp @@ -427,8 +427,8 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift index e472c5a796..397424587a 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorControllerNode.swift @@ -937,12 +937,12 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate ) } - let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) + let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) let timestamp = self.referenceTimestamp @@ -1030,8 +1030,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) var sampleMessages: [Message] = [] diff --git a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift index 9f57e20b78..bf9d14106b 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemePreviewControllerNode.swift @@ -452,15 +452,15 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { let chatListPresentationData = ChatListPresentationData(theme: self.previewTheme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true) - let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) - let peer7: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(6)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)) + let selfPeer: EnginePeer = .user(TelegramUser(id: self.context.account.peerId, accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer1: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_1_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer2: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_2_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer3: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(3)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer3Author: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_3_AuthorName, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer4: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(4)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_4_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer5: EnginePeer = .channel(TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, title: self.presentationData.strings.Appearance_ThemePreview_ChatList_5_Name, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .broadcast(.init(flags: [])), flags: [], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer6: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.SecretChat, id: PeerId.Id._internalFromInt64Value(5)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_6_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) + let peer7: EnginePeer = .user(TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(6)), accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_ChatList_7_Name, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)) let timestamp = self.referenceTimestamp @@ -581,8 +581,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate { let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) var sampleMessages: [Message] = [] diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift index fc90663f4d..299a9a8095 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsChatPreviewItem.swift @@ -163,11 +163,11 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) if let (author, text) = messageItem.reply { - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: author, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: messageItem.nameColor, backgroundEmojiId: messageItem.backgroundEmojiId) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: author, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: messageItem.nameColor, backgroundEmojiId: messageItem.backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil) messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) } - let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) + let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:]) items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false)) } diff --git a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift index c6783d8d30..10aae76e22 100644 --- a/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift +++ b/submodules/SettingsUI/Sources/Themes/WallpaperGalleryItem.swift @@ -1491,8 +1491,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode { let otherPeerId = self.context.account.peerId var peers = SimpleDictionary() let messages = SimpleDictionary() - peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) - peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil) + peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) + peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) var topMessageText = "" var bottomMessageText = "" diff --git a/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift b/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift index bc0ab4d048..1a39dc54af 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift @@ -153,7 +153,7 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? { } } - return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: date, version: 0, participationStatus: participationStatus, info: info, flags: channelFlags, restrictionInfo: restrictionInfo, adminRights: adminRights.flatMap(TelegramChatAdminRights.init), bannedRights: bannedRights.flatMap(TelegramChatBannedRights.init), defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColor.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId) + return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: date, version: 0, participationStatus: participationStatus, info: info, flags: channelFlags, restrictionInfo: restrictionInfo, adminRights: adminRights.flatMap(TelegramChatAdminRights.init), bannedRights: bannedRights.flatMap(TelegramChatBannedRights.init), defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColor.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil) case let .channelForbidden(flags, id, accessHash, title, untilDate): let info: TelegramChannelInfo if (flags & Int32(1 << 8)) != 0 { @@ -162,7 +162,7 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? { info = .broadcast(TelegramChannelBroadcastInfo(flags: [])) } - return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: .personal(accessHash), title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, info: info, flags: TelegramChannelFlags(), restrictionInfo: nil, adminRights: nil, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: untilDate ?? Int32.max), defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + return TelegramChannel(id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id)), accessHash: .personal(accessHash), title: title, username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .kicked, info: info, flags: TelegramChannelFlags(), restrictionInfo: nil, adminRights: nil, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: untilDate ?? Int32.max), defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) } } @@ -212,7 +212,7 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? { } } - return TelegramChannel(id: lhs.id, accessHash: lhs.accessHash, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: lhs.creationDate, version: lhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: lhs.restrictionInfo, adminRights: lhs.adminRights, bannedRights: lhs.bannedRights, defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColor.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId) + return TelegramChannel(id: lhs.id, accessHash: lhs.accessHash, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: lhs.creationDate, version: lhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: lhs.restrictionInfo, adminRights: lhs.adminRights, bannedRights: lhs.bannedRights, defaultBannedRights: defaultBannedRights.flatMap(TelegramChatBannedRights.init), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColor.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil) } else { return parseTelegramGroupOrChannel(chat: rhs) } @@ -266,6 +266,6 @@ func mergeChannel(lhs: TelegramChannel?, rhs: TelegramChannel) -> TelegramChanne let storiesHidden: Bool? = rhs.storiesHidden ?? lhs.storiesHidden - return TelegramChannel(id: lhs.id, accessHash: accessHash, title: rhs.title, username: rhs.username, photo: rhs.photo, creationDate: rhs.creationDate, version: rhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: rhs.restrictionInfo, adminRights: rhs.adminRights, bannedRights: rhs.bannedRights, defaultBannedRights: rhs.defaultBannedRights, usernames: rhs.usernames, storiesHidden: storiesHidden, nameColor: rhs.nameColor, backgroundEmojiId: rhs.backgroundEmojiId) + return TelegramChannel(id: lhs.id, accessHash: accessHash, title: rhs.title, username: rhs.username, photo: rhs.photo, creationDate: rhs.creationDate, version: rhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: rhs.restrictionInfo, adminRights: rhs.adminRights, bannedRights: rhs.bannedRights, defaultBannedRights: rhs.defaultBannedRights, usernames: rhs.usernames, storiesHidden: storiesHidden, nameColor: rhs.nameColor, backgroundEmojiId: rhs.backgroundEmojiId, profileColor: rhs.profileColor, profileBackgroundEmojiId: rhs.profileBackgroundEmojiId) } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift index ebc1d017af..23b633e323 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift @@ -96,9 +96,9 @@ extension TelegramUser { let restrictionInfo: PeerAccessRestrictionInfo? = restrictionReason.flatMap(PeerAccessRestrictionInfo.init(apiReasons:)) - self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColor.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId) + self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: accessHashValue, firstName: firstName, lastName: lastName, username: username, phone: phone, photo: representations, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: usernames?.map(TelegramPeerUsername.init(apiUsername:)) ?? [], storiesHidden: storiesHidden, nameColor: nameColor.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil) case let .userEmpty(id): - self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + self.init(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(id)), accessHash: nil, firstName: nil, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) } } @@ -180,7 +180,7 @@ extension TelegramUser { accessHash = lhs.accessHash ?? rhsAccessHashValue } - return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: lhs.username, phone: lhs.phone, photo: telegramPhoto, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: lhs.usernames, storiesHidden: lhs.storiesHidden, nameColor: nameColor.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId) + return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: lhs.username, phone: lhs.phone, photo: telegramPhoto, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus.flatMap(PeerEmojiStatus.init(apiStatus:)), usernames: lhs.usernames, storiesHidden: lhs.storiesHidden, nameColor: nameColor.flatMap { PeerNameColor(rawValue: $0) }, backgroundEmojiId: backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil) } else { return TelegramUser(user: rhs) } @@ -241,7 +241,7 @@ extension TelegramUser { storiesHidden = lhs.storiesHidden } - return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: lhs.username, phone: lhs.phone, photo: photo, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus, usernames: lhs.usernames, storiesHidden: storiesHidden, nameColor: rhs.nameColor, backgroundEmojiId: rhs.backgroundEmojiId) + return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: lhs.username, phone: lhs.phone, photo: photo, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus, usernames: lhs.usernames, storiesHidden: storiesHidden, nameColor: rhs.nameColor, backgroundEmojiId: rhs.backgroundEmojiId, profileColor: rhs.profileColor, profileBackgroundEmojiId: rhs.profileBackgroundEmojiId) } } } diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 7334d848d9..b3c17d8344 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1121,7 +1121,7 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox: if updatedState.peers[peerId] == nil { updatedState.updatePeer(peerId, { peer in if peer == nil { - return TelegramUser(id: peerId, accessHash: nil, firstName: "Telegram Notifications", lastName: nil, username: nil, phone: nil, photo: [], botInfo: BotUserInfo(flags: [], inlinePlaceholder: nil), restrictionInfo: nil, flags: [.isVerified], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + return TelegramUser(id: peerId, accessHash: nil, firstName: "Telegram Notifications", lastName: nil, username: nil, phone: nil, photo: [], botInfo: BotUserInfo(flags: [], inlinePlaceholder: nil), restrictionInfo: nil, flags: [.isVerified], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) } else { return peer } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift index ba725bccd0..08abf2fdab 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift @@ -169,6 +169,8 @@ public final class TelegramChannel: Peer, Equatable { public let storiesHidden: Bool? public let nameColor: PeerNameColor? public let backgroundEmojiId: Int64? + public let profileColor: PeerNameColor? + public let profileBackgroundEmojiId: Int64? public var indexName: PeerIndexNameRepresentation { var addressNames = self.usernames.map { $0.username } @@ -209,7 +211,9 @@ public final class TelegramChannel: Peer, Equatable { usernames: [TelegramPeerUsername], storiesHidden: Bool?, nameColor: PeerNameColor?, - backgroundEmojiId: Int64? + backgroundEmojiId: Int64?, + profileColor: PeerNameColor?, + profileBackgroundEmojiId: Int64? ) { self.id = id self.accessHash = accessHash @@ -229,6 +233,8 @@ public final class TelegramChannel: Peer, Equatable { self.storiesHidden = storiesHidden self.nameColor = nameColor self.backgroundEmojiId = backgroundEmojiId + self.profileColor = profileColor + self.profileBackgroundEmojiId = profileBackgroundEmojiId } public init(decoder: PostboxDecoder) { @@ -260,6 +266,8 @@ public final class TelegramChannel: Peer, Equatable { self.storiesHidden = decoder.decodeOptionalBoolForKey("sth") self.nameColor = decoder.decodeOptionalInt32ForKey("nclr").flatMap { PeerNameColor(rawValue: $0) } self.backgroundEmojiId = decoder.decodeOptionalInt64ForKey("bgem") + self.profileColor = decoder.decodeOptionalInt32ForKey("pclr").flatMap { PeerNameColor(rawValue: $0) } + self.profileBackgroundEmojiId = decoder.decodeOptionalInt64ForKey("pgem") } public func encode(_ encoder: PostboxEncoder) { @@ -327,6 +335,18 @@ public final class TelegramChannel: Peer, Equatable { } else { encoder.encodeNil(forKey: "bgem") } + + if let profileColor = self.profileColor { + encoder.encodeInt32(profileColor.rawValue, forKey: "pclr") + } else { + encoder.encodeNil(forKey: "pclr") + } + + if let profileBackgroundEmojiId = self.profileBackgroundEmojiId { + encoder.encodeInt64(profileBackgroundEmojiId, forKey: "pgem") + } else { + encoder.encodeNil(forKey: "pgem") + } } public func isEqual(_ other: Peer) -> Bool { @@ -373,35 +393,49 @@ public final class TelegramChannel: Peer, Equatable { if lhs.backgroundEmojiId != rhs.backgroundEmojiId { return false } + if lhs.profileColor != rhs.profileColor { + return false + } + if lhs.profileBackgroundEmojiId != rhs.profileBackgroundEmojiId { + return false + } return true } public func withUpdatedAddressName(_ addressName: String?) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: addressName, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: addressName, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedAddressNames(_ addressNames: [TelegramPeerUsername]) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: addressNames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: addressNames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedDefaultBannedRights(_ defaultBannedRights: TelegramChatBannedRights?) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedFlags(_ flags: TelegramChannelFlags) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedStoriesHidden(_ storiesHidden: Bool?) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedNameColor(_ nameColor: PeerNameColor?) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedBackgroundEmojiId(_ backgroundEmojiId: Int64?) -> TelegramChannel { - return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: backgroundEmojiId) + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + } + + public func withUpdatedProfileColor(_ profileColor: PeerNameColor?) -> TelegramChannel { + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + } + + public func withUpdatedProfileBackgroundEmojiId(_ profileBackgroundEmojiId: Int64?) -> TelegramChannel { + return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift index 714303790c..81d610ef09 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift @@ -112,6 +112,8 @@ public final class TelegramUser: Peer, Equatable { public let storiesHidden: Bool? public let nameColor: PeerNameColor? public let backgroundEmojiId: Int64? + public let profileColor: PeerNameColor? + public let profileBackgroundEmojiId: Int64? public var nameOrPhone: String { if let firstName = self.firstName { @@ -198,7 +200,9 @@ public final class TelegramUser: Peer, Equatable { usernames: [TelegramPeerUsername], storiesHidden: Bool?, nameColor: PeerNameColor?, - backgroundEmojiId: Int64? + backgroundEmojiId: Int64?, + profileColor: PeerNameColor?, + profileBackgroundEmojiId: Int64? ) { self.id = id self.accessHash = accessHash @@ -215,6 +219,8 @@ public final class TelegramUser: Peer, Equatable { self.storiesHidden = storiesHidden self.nameColor = nameColor self.backgroundEmojiId = backgroundEmojiId + self.profileColor = profileColor + self.profileBackgroundEmojiId = profileBackgroundEmojiId } public init(decoder: PostboxDecoder) { @@ -257,6 +263,8 @@ public final class TelegramUser: Peer, Equatable { self.nameColor = decoder.decodeOptionalInt32ForKey("nclr").flatMap { PeerNameColor(rawValue: $0) } self.backgroundEmojiId = decoder.decodeOptionalInt64ForKey("bgem") + self.profileColor = decoder.decodeOptionalInt32ForKey("pclr").flatMap { PeerNameColor(rawValue: $0) } + self.profileBackgroundEmojiId = decoder.decodeOptionalInt64ForKey("pgem") } public func encode(_ encoder: PostboxEncoder) { @@ -328,6 +336,18 @@ public final class TelegramUser: Peer, Equatable { } else { encoder.encodeNil(forKey: "bgem") } + + if let profileColor = self.profileColor { + encoder.encodeInt32(profileColor.rawValue, forKey: "pclr") + } else { + encoder.encodeNil(forKey: "pclr") + } + + if let profileBackgroundEmojiId = self.profileBackgroundEmojiId { + encoder.encodeInt64(profileBackgroundEmojiId, forKey: "pgem") + } else { + encoder.encodeNil(forKey: "pgem") + } } public func isEqual(_ other: Peer) -> Bool { @@ -389,47 +409,61 @@ public final class TelegramUser: Peer, Equatable { if lhs.backgroundEmojiId != rhs.backgroundEmojiId { return false } + if lhs.profileColor != rhs.profileColor { + return false + } + if lhs.profileBackgroundEmojiId != rhs.profileBackgroundEmojiId { + return false + } return true } public func withUpdatedUsername(_ username: String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedUsernames(_ usernames: [TelegramPeerUsername]) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedNames(firstName: String?, lastName: String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: firstName, lastName: lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: firstName, lastName: lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedPhone(_ phone: String?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedPhoto(_ representations: [TelegramMediaImageRepresentation]) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: representations, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: representations, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedEmojiStatus(_ emojiStatus: PeerEmojiStatus?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedFlags(_ flags: UserInfoFlags) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedStoriesHidden(_ storiesHidden: Bool?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedNameColor(_ nameColor: PeerNameColor) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: nameColor, backgroundEmojiId: self.backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) } public func withUpdatedBackgroundEmojiId(_ backgroundEmojiId: Int64?) -> TelegramUser { - return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: backgroundEmojiId) + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + } + + public func withUpdatedProfileColor(_ profileColor: PeerNameColor?) -> TelegramUser { + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: self.profileBackgroundEmojiId) + } + + public func withUpdatedProfileBackgroundEmojiId(_ profileBackgroundEmojiId: Int64?) -> TelegramUser { + return TelegramUser(id: self.id, accessHash: self.accessHash, firstName: self.firstName, lastName: self.lastName, username: self.username, phone: self.phone, photo: self.photo, botInfo: self.botInfo, restrictionInfo: self.restrictionInfo, flags: self.flags, emojiStatus: self.emojiStatus, usernames: self.usernames, storiesHidden: self.storiesHidden, nameColor: self.nameColor, backgroundEmojiId: self.backgroundEmojiId, profileColor: self.profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift index b4aebf2428..de3568e123 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/TelegramEngineAccountData.swift @@ -35,8 +35,8 @@ public extension TelegramEngine { return _internal_updateAbout(account: self.account, about: about) } - public func updateNameColorAndEmoji(nameColor: PeerNameColor, backgroundEmojiId: Int64?) -> Signal { - return _internal_updateNameColorAndEmoji(account: self.account, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId) + public func updateNameColorAndEmoji(nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal { + return _internal_updateNameColorAndEmoji(account: self.account, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId) } public func unregisterNotificationToken(token: Data, type: NotificationTokenType, otherAccountUserIds: [PeerId.Id]) -> Signal { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/UpdateAccountPeerName.swift b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/UpdateAccountPeerName.swift index 13d45fb782..8693267acb 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/AccountData/UpdateAccountPeerName.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/AccountData/UpdateAccountPeerName.swift @@ -51,13 +51,13 @@ public enum UpdateNameColorAndEmojiError { case generic } -func _internal_updateNameColorAndEmoji(account: Account, nameColor: PeerNameColor, backgroundEmojiId: Int64?) -> Signal { +func _internal_updateNameColorAndEmoji(account: Account, nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal { let flags: Int32 = (1 << 0) return account.postbox.transaction { transaction -> Signal in guard let peer = transaction.getPeer(account.peerId) as? TelegramUser else { return .complete() } - updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedNameColor(nameColor).withUpdatedBackgroundEmojiId(backgroundEmojiId)], update: { _, updated in + updatePeersCustom(transaction: transaction, peers: [peer.withUpdatedNameColor(nameColor).withUpdatedBackgroundEmojiId(backgroundEmojiId).withUpdatedProfileColor(profileColor).withUpdatedProfileBackgroundEmojiId(profileBackgroundEmojiId)], update: { _, updated in return updated }) return .single(peer) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift index f32426c7b3..493c924e6c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift @@ -313,7 +313,9 @@ private class AdMessagesHistoryContextImpl { usernames: [], storiesHidden: nil, nameColor: invite.nameColor, - backgroundEmojiId: nil + backgroundEmojiId: nil, + profileColor: nil, + profileBackgroundEmojiId: nil ) case let .webPage(webPage): author = TelegramChannel( @@ -334,7 +336,9 @@ private class AdMessagesHistoryContextImpl { usernames: [], storiesHidden: nil, nameColor: .blue, - backgroundEmojiId: nil + backgroundEmojiId: nil, + profileColor: nil, + profileBackgroundEmojiId: nil ) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift index 64deebf284..8f6fca61b8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift @@ -510,9 +510,17 @@ public extension EnginePeer { return self._asPeer().nameColor } + var profileColor: PeerNameColor? { + return self._asPeer().profileColor + } + var backgroundEmojiId: Int64? { return self._asPeer().backgroundEmojiId } + + var profileBackgroundEmojiId: Int64? { + return self._asPeer().profileBackgroundEmojiId + } } public extension EnginePeer { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index b6d80075ee..24fc76215a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -715,8 +715,8 @@ public extension TelegramEngine { return _internal_updateBotAbout(account: self.account, peerId: peerId, about: about) } - public func updatePeerNameColorAndEmoji(peerId: EnginePeer.Id, nameColor: PeerNameColor, backgroundEmojiId: Int64?) -> Signal { - return _internal_updatePeerNameColorAndEmoji(account: self.account, peerId: peerId, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId) + public func updatePeerNameColorAndEmoji(peerId: EnginePeer.Id, nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal { + return _internal_updatePeerNameColorAndEmoji(account: self.account, peerId: peerId, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId) } public func getChatListPeers(filterPredicate: ChatListFilterPredicate) -> Signal<[EnginePeer], NoError> { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdatePeerInfo.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdatePeerInfo.swift index f91d9d3fce..69de747224 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdatePeerInfo.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdatePeerInfo.swift @@ -94,7 +94,7 @@ public enum UpdatePeerNameColorAndEmojiError { case channelBoostRequired } -func _internal_updatePeerNameColorAndEmoji(account: Account, peerId: EnginePeer.Id, nameColor: PeerNameColor, backgroundEmojiId: Int64?) -> Signal { +func _internal_updatePeerNameColorAndEmoji(account: Account, peerId: EnginePeer.Id, nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId) { if let peer = peer as? TelegramChannel, let inputChannel = apiInputChannel(peer) { diff --git a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift index 11d20ef720..53aaa0e3bb 100644 --- a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift @@ -236,6 +236,17 @@ public extension Peer { } } + var profileColor: PeerNameColor? { + switch self { + case let user as TelegramUser: + return user.profileColor + case let channel as TelegramChannel: + return channel.profileColor + default: + return nil + } + } + var hasCustomNameColor: Bool { let defaultNameColor = PeerNameColor(rawValue: Int32(self.id.id._internalGetInt64Value() % 7)) if self.nameColor != defaultNameColor { @@ -254,6 +265,17 @@ public extension Peer { return nil } } + + var profileBackgroundEmojiId: Int64? { + switch self { + case let user as TelegramUser: + return user.profileBackgroundEmojiId + case let channel as TelegramChannel: + return channel.profileBackgroundEmojiId + default: + return nil + } + } } public extension TelegramPeerUsername { diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesRootController.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesRootController.swift index 51c5ae79c9..f54b1559e9 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesRootController.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesRootController.swift @@ -101,7 +101,7 @@ public struct PresentationResourcesRootController { public static func navigationQrCodeIcon(_ theme: PresentationTheme) -> UIImage? { return theme.image(PresentationResourceKey.navigationQrCodeIcon.rawValue, { theme in - generateTintedImage(image: UIImage(bundleImageName: "Settings/QrIcon"), color: theme.rootController.navigationBar.accentTextColor) + generateTintedImage(image: UIImage(bundleImageName: "Settings/QrIcon"), color: .white) }) } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift index b1911602fb..17a7bfac59 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift @@ -1355,7 +1355,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI ignoreForward = true effectiveAuthor = forwardInfo.author if effectiveAuthor == nil, let authorSignature = forwardInfo.authorSignature { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) } } displayAuthorInfo = !mergedTop.merged && incoming && effectiveAuthor != nil @@ -1371,7 +1371,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI displayAuthorInfo = !mergedTop.merged && incoming } else if let forwardInfo = item.content.firstMessage.forwardInfo, forwardInfo.flags.contains(.isImported), let authorSignature = forwardInfo.authorSignature { ignoreForward = true - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) displayAuthorInfo = !mergedTop.merged && incoming } else if let adAttribute = item.content.firstMessage.adAttribute, let author = item.content.firstMessage.author { ignoreForward = true diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift index b13877ff43..e77784a7c6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemImpl/Sources/ChatMessageItemImpl.swift @@ -254,7 +254,7 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible if let forwardInfo = content.firstMessage.forwardInfo { effectiveAuthor = forwardInfo.author if effectiveAuthor == nil, let authorSignature = forwardInfo.authorSignature { - effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil) + effectiveAuthor = TelegramUser(id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(Int64(authorSignature.persistentHashValue % 32))), accessHash: nil, firstName: authorSignature, lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil) } } displayAuthorInfo = incoming && effectiveAuthor != nil diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsHistoryTransition.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsHistoryTransition.swift index 5e722ef69f..bb3d266454 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsHistoryTransition.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsHistoryTransition.swift @@ -69,7 +69,7 @@ private func filterOriginalMessageFlags(_ message: Message) -> Message { private func filterMessageChannelPeer(_ peer: Peer) -> Peer { if let peer = peer as? TelegramChannel { - return TelegramChannel(id: peer.id, accessHash: peer.accessHash, title: peer.title, username: peer.username, photo: peer.photo, creationDate: peer.creationDate, version: peer.version, participationStatus: peer.participationStatus, info: .group(TelegramChannelGroupInfo(flags: [])), flags: peer.flags, restrictionInfo: peer.restrictionInfo, adminRights: peer.adminRights, bannedRights: peer.bannedRights, defaultBannedRights: peer.defaultBannedRights, usernames: peer.usernames, storiesHidden: peer.storiesHidden, nameColor: peer.nameColor, backgroundEmojiId: peer.backgroundEmojiId) + return TelegramChannel(id: peer.id, accessHash: peer.accessHash, title: peer.title, username: peer.username, photo: peer.photo, creationDate: peer.creationDate, version: peer.version, participationStatus: peer.participationStatus, info: .group(TelegramChannelGroupInfo(flags: [])), flags: peer.flags, restrictionInfo: peer.restrictionInfo, adminRights: peer.adminRights, bannedRights: peer.bannedRights, defaultBannedRights: peer.defaultBannedRights, usernames: peer.usernames, storiesHidden: peer.storiesHidden, nameColor: peer.nameColor, backgroundEmojiId: peer.backgroundEmojiId, profileColor: peer.profileColor, profileBackgroundEmojiId: peer.profileBackgroundEmojiId) } return peer } diff --git a/submodules/TelegramUI/Components/DustEffect/Sources/DustEffectLayer.swift b/submodules/TelegramUI/Components/DustEffect/Sources/DustEffectLayer.swift index 9b5dd04fac..c907e93c69 100644 --- a/submodules/TelegramUI/Components/DustEffect/Sources/DustEffectLayer.swift +++ b/submodules/TelegramUI/Components/DustEffect/Sources/DustEffectLayer.swift @@ -181,7 +181,7 @@ public final class DustEffectLayer: MetalEngineSubjectLayer, MetalEngineSubject private func updateNeedsAnimation() { if !self.items.isEmpty && self.isInHierarchy { if self.updateLink == nil { - self.updateLink = SharedDisplayLinkDriver.shared.add(framesPerSecond: .fps(60), { [weak self] deltaTime in + self.updateLink = SharedDisplayLinkDriver.shared.add(framesPerSecond: .max, { [weak self] deltaTime in guard let self else { return } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index c1f26f0c68..f05f506e9d 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -2694,6 +2694,7 @@ public final class EmojiPagerContentComponent: Component { public let emptySearchResults: EmptySearchResults? public let enableLongPress: Bool public let selectedItems: Set + public let customTintColor: UIColor? public init( id: AnyHashable, @@ -2716,7 +2717,8 @@ public final class EmojiPagerContentComponent: Component { searchIsPlaceholderOnly: Bool, emptySearchResults: EmptySearchResults?, enableLongPress: Bool, - selectedItems: Set + selectedItems: Set, + customTintColor: UIColor? ) { self.id = id self.context = context @@ -2739,6 +2741,7 @@ public final class EmojiPagerContentComponent: Component { self.emptySearchResults = emptySearchResults self.enableLongPress = enableLongPress self.selectedItems = selectedItems + self.customTintColor = customTintColor } public func withUpdatedItemGroups(panelItemGroups: [ItemGroup], contentItemGroups: [ItemGroup], itemContentUniqueId: ContentId?, emptySearchResults: EmptySearchResults?, searchState: SearchState) -> EmojiPagerContentComponent { @@ -2763,7 +2766,8 @@ public final class EmojiPagerContentComponent: Component { searchIsPlaceholderOnly: self.searchIsPlaceholderOnly, emptySearchResults: emptySearchResults, enableLongPress: self.enableLongPress, - selectedItems: self.selectedItems + selectedItems: self.selectedItems, + customTintColor: self.customTintColor ) } @@ -2789,7 +2793,35 @@ public final class EmojiPagerContentComponent: Component { searchIsPlaceholderOnly: self.searchIsPlaceholderOnly, emptySearchResults: emptySearchResults, enableLongPress: self.enableLongPress, - selectedItems: selectedItems + selectedItems: selectedItems, + customTintColor: self.customTintColor + ) + } + + public func withCustomTintColor(_ customTintColor: UIColor?) -> EmojiPagerContentComponent { + return EmojiPagerContentComponent( + id: self.id, + context: self.context, + avatarPeer: self.avatarPeer, + animationCache: self.animationCache, + animationRenderer: self.animationRenderer, + inputInteractionHolder: self.inputInteractionHolder, + panelItemGroups: panelItemGroups, + contentItemGroups: contentItemGroups, + itemLayoutType: self.itemLayoutType, + itemContentUniqueId: itemContentUniqueId, + searchState: searchState, + warpContentsOnEdges: self.warpContentsOnEdges, + hideBackground: self.hideBackground, + displaySearchWithPlaceholder: self.displaySearchWithPlaceholder, + searchCategories: self.searchCategories, + searchInitiallyHidden: self.searchInitiallyHidden, + searchAlwaysActive: self.searchAlwaysActive, + searchIsPlaceholderOnly: self.searchIsPlaceholderOnly, + emptySearchResults: emptySearchResults, + enableLongPress: self.enableLongPress, + selectedItems: self.selectedItems, + customTintColor: customTintColor ) } @@ -2860,6 +2892,9 @@ public final class EmojiPagerContentComponent: Component { if lhs.selectedItems != rhs.selectedItems { return false } + if lhs.customTintColor != rhs.customTintColor { + return false + } return true } @@ -5882,7 +5917,7 @@ public final class EmojiPagerContentComponent: Component { case let .custom(color): itemLayer.layerTintColor = color.cgColor case .accent: - itemLayer.layerTintColor = keyboardChildEnvironment.theme.list.itemAccentColor.cgColor + itemLayer.layerTintColor = component.customTintColor?.cgColor ?? keyboardChildEnvironment.theme.list.itemAccentColor.cgColor case .primary: itemLayer.layerTintColor = keyboardChildEnvironment.theme.list.itemPrimaryTextColor.cgColor case .none: @@ -5928,7 +5963,7 @@ public final class EmojiPagerContentComponent: Component { itemSelectionLayer.backgroundColor = color.withMultipliedAlpha(0.1).cgColor itemSelectionLayer.tintContainerLayer.backgroundColor = UIColor.clear.cgColor } else if case .accent = item.tintMode { - itemSelectionLayer.backgroundColor = keyboardChildEnvironment.theme.list.itemAccentColor.withMultipliedAlpha(0.1).cgColor + itemSelectionLayer.backgroundColor = component.customTintColor?.withMultipliedAlpha(0.1).cgColor ?? keyboardChildEnvironment.theme.list.itemAccentColor.withMultipliedAlpha(0.1).cgColor itemSelectionLayer.tintContainerLayer.backgroundColor = UIColor.clear.cgColor } else { if useOpaqueTheme { @@ -7940,7 +7975,7 @@ public final class EmojiPagerContentComponent: Component { itemFile: nil, subgroupId: nil, icon: .none, - tintMode: backgroundIconColor.flatMap { .custom($0) } ?? .accent + tintMode: .accent ) let groupId = "recent" @@ -8329,7 +8364,8 @@ public final class EmojiPagerContentComponent: Component { searchIsPlaceholderOnly: false, emptySearchResults: nil, enableLongPress: enableLongPress, - selectedItems: selectedItems + selectedItems: selectedItems, + customTintColor: backgroundIconColor ) } return emojiItems @@ -8810,7 +8846,8 @@ public final class EmojiPagerContentComponent: Component { searchIsPlaceholderOnly: searchIsPlaceholderOnly, emptySearchResults: nil, enableLongPress: false, - selectedItems: Set() + selectedItems: Set(), + customTintColor: nil ) } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiSearchContent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiSearchContent.swift index 9763f7dba3..cc21a8caa1 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiSearchContent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiSearchContent.swift @@ -468,7 +468,8 @@ public final class EmojiSearchContent: ASDisplayNode, EntitySearchContainerNode searchIsPlaceholderOnly: false, emptySearchResults: nil, enableLongPress: false, - selectedItems: Set() + selectedItems: Set(), + customTintColor: nil ) if let emojiSearchResult = self.immediateEmojiSearchState.result { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 0b247cf527..fd938c10b1 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -370,6 +370,7 @@ public final class EntityKeyboardComponent: Component { animationRenderer: maskContent.animationRenderer, theme: component.theme, title: itemGroup.title ?? "", + customTintColor: component.customTintColor, pressed: { [weak self] in self?.scrollToItemGroup(contentId: "masks", groupId: itemGroup.supergroupId, subgroupId: nil) } @@ -509,6 +510,7 @@ public final class EntityKeyboardComponent: Component { animationRenderer: stickerContent.animationRenderer, theme: component.theme, title: itemGroup.title ?? "", + customTintColor: component.customTintColor, pressed: { [weak self] in self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.supergroupId, subgroupId: nil) } @@ -625,7 +627,7 @@ public final class EntityKeyboardComponent: Component { animationRenderer: emojiContent.animationRenderer, theme: component.theme, title: itemGroup.title ?? "", - customTintColor: itemGroup.customTintColor, + customTintColor: component.customTintColor ?? itemGroup.customTintColor, pressed: { [weak self] in self?.scrollToItemGroup(contentId: "emoji", groupId: itemGroup.supergroupId, subgroupId: nil) } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 9f7f317f53..eea256000d 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -169,9 +169,9 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { case .none: break case .primary: - itemLayer.layerTintColor = component.theme.list.itemPrimaryTextColor.cgColor + itemLayer.layerTintColor = component.customTintColor?.cgColor ?? component.theme.list.itemPrimaryTextColor.cgColor case .accent: - itemLayer.layerTintColor = component.theme.list.itemAccentColor.cgColor + itemLayer.layerTintColor = component.customTintColor?.cgColor ?? component.theme.list.itemAccentColor.cgColor case let .custom(color): itemLayer.layerTintColor = component.customTintColor?.cgColor ?? color.cgColor } diff --git a/submodules/TelegramUI/Components/MultiScaleTextNode/Sources/MultiScaleTextNode.swift b/submodules/TelegramUI/Components/MultiScaleTextNode/Sources/MultiScaleTextNode.swift index d8e18729b4..ab4b31c4fb 100644 --- a/submodules/TelegramUI/Components/MultiScaleTextNode/Sources/MultiScaleTextNode.swift +++ b/submodules/TelegramUI/Components/MultiScaleTextNode/Sources/MultiScaleTextNode.swift @@ -63,6 +63,12 @@ public final class MultiScaleTextNode: ASDisplayNode { return self.stateNodes[key]?.textNode } + public func updateTintColor(color: UIColor, transition: ContainedViewLayoutTransition) { + for (_, node) in self.stateNodes { + transition.updateTintColor(layer: node.textNode.layer, color: color) + } + } + public func updateLayout(text: String, states: [AnyHashable: MultiScaleTextState], mainState: AnyHashable) -> [AnyHashable: MultiScaleTextLayout] { assert(Set(states.keys) == Set(self.stateNodes.keys)) assert(states[mainState] != nil) diff --git a/submodules/TelegramUI/Components/NotificationExceptionsScreen/Sources/NotificationExceptionsScreen.swift b/submodules/TelegramUI/Components/NotificationExceptionsScreen/Sources/NotificationExceptionsScreen.swift index 5bb42be0b1..3f7c37cfd7 100644 --- a/submodules/TelegramUI/Components/NotificationExceptionsScreen/Sources/NotificationExceptionsScreen.swift +++ b/submodules/TelegramUI/Components/NotificationExceptionsScreen/Sources/NotificationExceptionsScreen.swift @@ -332,7 +332,7 @@ private func notificationsPeerCategoryEntries(peerId: EnginePeer.Id, notificatio } } existingThreadIds.insert(value.threadId) - entries.append(.exception(Int32(index), presentationData.dateTimeFormat, presentationData.nameDisplayOrder, .channel(TelegramChannel(id: peerId, accessHash: nil, title: "", username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(TelegramChannelGroupInfo(flags: [])), flags: [.isForum], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil)), value.threadId, value.info, title, value.notificationSettings._asNotificationSettings(), state.editing, state.revealedThreadId == value.threadId)) + entries.append(.exception(Int32(index), presentationData.dateTimeFormat, presentationData.nameDisplayOrder, .channel(TelegramChannel(id: peerId, accessHash: nil, title: "", username: nil, photo: [], creationDate: 0, version: 0, participationStatus: .member, info: .group(TelegramChannelGroupInfo(flags: [])), flags: [.isForum], restrictionInfo: nil, adminRights: nil, bannedRights: nil, defaultBannedRights: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)), value.threadId, value.info, title, value.notificationSettings._asNotificationSettings(), state.editing, state.revealedThreadId == value.threadId)) index += 1 } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent/Sources/PeerInfoCoverComponent.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent/Sources/PeerInfoCoverComponent.swift index e02b42c0e9..3dc98d27e9 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent/Sources/PeerInfoCoverComponent.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent/Sources/PeerInfoCoverComponent.swift @@ -60,6 +60,7 @@ private func patternScaleValueAt(fraction: CGFloat, t: CGFloat, reverse: Bool) - public final class PeerInfoCoverComponent: Component { public let context: AccountContext public let peer: EnginePeer? + public let isDark: Bool public let avatarCenter: CGPoint public let avatarScale: CGFloat public let avatarTransitionFraction: CGFloat @@ -68,6 +69,7 @@ public final class PeerInfoCoverComponent: Component { public init( context: AccountContext, peer: EnginePeer?, + isDark: Bool, avatarCenter: CGPoint, avatarScale: CGFloat, avatarTransitionFraction: CGFloat, @@ -75,6 +77,7 @@ public final class PeerInfoCoverComponent: Component { ) { self.context = context self.peer = peer + self.isDark = isDark self.avatarCenter = avatarCenter self.avatarScale = avatarScale self.avatarTransitionFraction = avatarTransitionFraction @@ -88,6 +91,9 @@ public final class PeerInfoCoverComponent: Component { if lhs.peer != rhs.peer { return false } + if lhs.isDark != rhs.isDark { + return false + } if lhs.avatarCenter != rhs.avatarCenter { return false } @@ -105,6 +111,7 @@ public final class PeerInfoCoverComponent: Component { public final class View: UIView { private let backgroundView: UIView + private let backgroundGradientLayer: SimpleGradientLayer private let avatarBackgroundPatternContainer: UIView private let avatarBackgroundGradientLayer: SimpleGradientLayer private let avatarBackgroundPatternView: UIView @@ -122,6 +129,7 @@ public final class PeerInfoCoverComponent: Component { override public init(frame: CGRect) { self.backgroundView = UIView() + self.backgroundGradientLayer = SimpleGradientLayer() self.avatarBackgroundPatternContainer = UIView() self.avatarBackgroundGradientLayer = SimpleGradientLayer() self.avatarBackgroundPatternView = UIView() @@ -130,6 +138,7 @@ public final class PeerInfoCoverComponent: Component { super.init(frame: frame) self.addSubview(self.backgroundView) + self.layer.addSublayer(self.backgroundGradientLayer) self.addSubview(self.avatarBackgroundPatternContainer) self.avatarBackgroundPatternContainer.layer.addSublayer(self.avatarBackgroundGradientLayer) self.avatarBackgroundPatternContainer.addSubview(self.avatarBackgroundPatternView) @@ -186,8 +195,8 @@ public final class PeerInfoCoverComponent: Component { } func update(component: PeerInfoCoverComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { - if self.component?.peer?.backgroundEmojiId != component.peer?.backgroundEmojiId { - if let backgroundEmojiId = component.peer?.backgroundEmojiId, backgroundEmojiId != 0 { + if self.component?.peer?.profileBackgroundEmojiId != component.peer?.profileBackgroundEmojiId { + if let profileBackgroundEmojiId = component.peer?.profileBackgroundEmojiId, profileBackgroundEmojiId != 0 { if self.patternContentsTarget == nil { self.patternContentsTarget = PatternContentsTarget(imageUpdated: { [weak self] in guard let self else { @@ -202,7 +211,7 @@ public final class PeerInfoCoverComponent: Component { self.patternFileDisposable = nil self.patternImageDisposable?.dispose() - let fileId = backgroundEmojiId + let fileId = profileBackgroundEmojiId self.patternFileDisposable = (component.context.engine.stickers.resolveInlineStickers(fileIds: [fileId]) |> deliverOnMainQueue).startStrict(next: { [weak self] files in guard let self else { @@ -218,6 +227,7 @@ public final class PeerInfoCoverComponent: Component { self.patternFileDisposable?.dispose() self.patternFileDisposable = nil self.patternFile = nil + self.updatePatternLayerImages() } } @@ -225,25 +235,45 @@ public final class PeerInfoCoverComponent: Component { self.state = state let backgroundColor: UIColor + var secondaryBackgroundColor: UIColor let patternColor: UIColor - if let peer = component.peer, let colors = peer._asPeer().nameColor.flatMap({ component.context.peerNameColors.get($0) }) { - backgroundColor = colors.main.withMultiplied(hue: 1.0, saturation: 0.9, brightness: 0.9) + if let peer = component.peer, let colors = peer._asPeer().profileColor.flatMap({ component.context.peerNameColors.getProfile($0, dark: component.isDark) }) { + backgroundColor = colors.main + secondaryBackgroundColor = colors.secondary ?? colors.main patternColor = colors.main.withMultiplied(hue: 1.0, saturation: 1.0, brightness: 0.8).withMultipliedAlpha(0.8) } else { backgroundColor = .clear + secondaryBackgroundColor = .clear patternColor = .clear } - self.backgroundView.backgroundColor = backgroundColor + self.backgroundView.backgroundColor = secondaryBackgroundColor + + self.backgroundGradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0) + self.backgroundGradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0) + self.backgroundGradientLayer.type = .axial + self.backgroundGradientLayer.colors = [backgroundColor.cgColor, secondaryBackgroundColor.cgColor] + //self.backgroundGradientLayer.colors = [UIColor.green.cgColor, UIColor.blue.cgColor] + self.backgroundGradientLayer.anchorPoint = CGPoint(x: 0.0, y: 1.0) + + let backgroundGradientFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - 350.0), size: CGSize(width: availableSize.width, height: 350.0)) + if !transition.animation.isImmediate { + let previousPosition = self.backgroundGradientLayer.position + let updatedPosition = CGPoint(x: backgroundGradientFrame.minX, y: backgroundGradientFrame.maxY) + self.backgroundGradientLayer.bounds = CGRect(origin: CGPoint(), size: backgroundGradientFrame.size) + self.backgroundGradientLayer.position = updatedPosition + transition.containedViewLayoutTransition.animatePositionAdditive(layer: self.backgroundGradientLayer, offset: CGPoint(x: previousPosition.x - updatedPosition.x, y: previousPosition.y - updatedPosition.y)) + } else { + self.backgroundGradientLayer.frame = backgroundGradientFrame + } + let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -1000.0 + availableSize.height), size: CGSize(width: availableSize.width, height: 1000.0)) transition.containedViewLayoutTransition.updateFrameAdditive(view: self.backgroundView, frame: backgroundFrame) let avatarBackgroundPatternContainerFrame = CGSize(width: 0.0, height: 0.0).centered(around: component.avatarCenter) transition.containedViewLayoutTransition.updateFrameAdditive(view: self.avatarBackgroundPatternContainer, frame: avatarBackgroundPatternContainerFrame) transition.containedViewLayoutTransition.updateSublayerTransformScaleAdditive(layer: self.avatarBackgroundPatternContainer.layer, scale: component.avatarScale) - //transition.containedViewLayoutTransition.updateAlpha(layer: self.avatarBackgroundPatternContainer.layer, alpha: 1.0 - component.avatarTransitionFraction) - //self.avatarBackgroundPatternView.backgroundColor = .yellow transition.setFrame(view: self.avatarBackgroundPatternView, frame: CGSize(width: 200.0, height: 200.0).centered(around: CGPoint())) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/BUILD b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/BUILD index 63f6ad30ec..7c81fabf2f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/BUILD +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/BUILD @@ -129,6 +129,7 @@ swift_library( "//submodules/TelegramUI/Components/Chat/ChatMessageSelectionInputPanelNode", "//submodules/TelegramUI/Components/Chat/ChatHistorySearchContainerNode", "//submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent", + "//submodules/TelegramUI/Components/LottieComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoAvatarTransformContainerNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoAvatarTransformContainerNode.swift index a14769f9df..41fab89171 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoAvatarTransformContainerNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoAvatarTransformContainerNode.swift @@ -84,12 +84,22 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { self.playbackStartDisposable.dispose() } - func updateStoryView(transition: ContainedViewLayoutTransition, theme: PresentationTheme) { + func updateStoryView(transition: ContainedViewLayoutTransition, theme: PresentationTheme, peer: Peer?) { var colors = AvatarNode.Colors(theme: theme) + + let regularNavigationContentsSecondaryColor: UIColor + if let profileColor = peer?.profileColor { + let backgroundColor = self.context.peerNameColors.getProfile(profileColor).main + regularNavigationContentsSecondaryColor = UIColor(white: 1.0, alpha: 0.6).blitOver(backgroundColor.withMultiplied(hue: 1.0, saturation: 2.2, brightness: 1.5), alpha: 1.0) + } else { + regularNavigationContentsSecondaryColor = theme.list.controlSecondaryColor + } + colors.seenColors = [ - theme.list.controlSecondaryColor, - theme.list.controlSecondaryColor + regularNavigationContentsSecondaryColor, + regularNavigationContentsSecondaryColor ] + var storyStats: AvatarNode.StoryStats? if let storyData = self.storyData { storyStats = AvatarNode.StoryStats( @@ -410,6 +420,6 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode { } } - self.updateStoryView(transition: .immediate, theme: theme) + self.updateStoryView(transition: .immediate, theme: theme, peer: peer) } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift index f704ea3ae8..52b6ecf38b 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoData.swift @@ -819,8 +819,15 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen availablePanes = nil } + var peer: Peer? + peer = peerView.peers[userPeerId] + + if let user = peer as? TelegramUser, let profileColor = user.nameColor { + peer = user.withUpdatedProfileColor(PeerNameColor(rawValue: profileColor.rawValue)).withUpdatedProfileBackgroundEmojiId(user.backgroundEmojiId) + } + return PeerInfoScreenData( - peer: peerView.peers[userPeerId], + peer: peer, chatPeer: peerView.peers[peerId], cachedData: peerView.cachedData, status: status, diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderButtonNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderButtonNode.swift index defeeb8645..f27a2281a0 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderButtonNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderButtonNode.swift @@ -5,6 +5,8 @@ import ContextUI import AnimationUI import Display import TelegramPresentationData +import ComponentFlow +import LottieComponent enum PeerInfoHeaderButtonKey: Hashable { case message @@ -43,7 +45,7 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode { private let backgroundNode: NavigationBackgroundNode private let iconNode: ASImageNode private let textNode: ImmediateTextNode - private var animationNode: AnimationNode? + private var animatedIcon: ComponentView? private var theme: PresentationTheme? private var icon: PeerInfoHeaderButtonIcon? @@ -102,15 +104,17 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode { @objc private func buttonPressed() { switch self.icon { - case .voiceChat, .more, .leave: - self.animationNode?.playOnce() - default: - break + case .voiceChat, .more, .leave: + if let animatedIconView = self.animatedIcon?.view as? LottieComponent.View { + animatedIconView.playOnce() + } + default: + break } self.action(self, nil) } - func update(size: CGSize, text: String, icon: PeerInfoHeaderButtonIcon, isActive: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) { + func update(size: CGSize, text: String, icon: PeerInfoHeaderButtonIcon, isActive: Bool, presentationData: PresentationData, backgroundColor: UIColor, foregroundColor: UIColor, transition: ContainedViewLayoutTransition) { let previousIcon = self.icon let themeUpdated = self.theme != presentationData.theme let iconUpdated = self.icon != icon @@ -128,78 +132,8 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode { isGestureEnabled = true } self.containerNode.isGestureEnabled = isGestureEnabled - - let animationName: String? - var colors: [String: UIColor] = [:] - var playOnce = false - var seekToEnd = false + let iconColor = UIColor.white - switch icon { - case .voiceChat: - animationName = "anim_profilevc" - colors = ["Line 3.Group 1.Stroke 1": iconColor, - "Line 1.Group 1.Stroke 1": iconColor, - "Line 2.Group 1.Stroke 1": iconColor] - case .mute: - animationName = "anim_profileunmute" - colors = ["Middle.Group 1.Fill 1": iconColor, - "Top.Group 1.Fill 1": iconColor, - "Bottom.Group 1.Fill 1": iconColor, - "EXAMPLE.Group 1.Fill 1": iconColor, - "Line.Group 1.Stroke 1": iconColor] - if previousIcon == .unmute { - playOnce = true - } else { - seekToEnd = true - } - case .unmute: - animationName = "anim_profilemute" - colors = ["Middle.Group 1.Fill 1": iconColor, - "Top.Group 1.Fill 1": iconColor, - "Bottom.Group 1.Fill 1": iconColor, - "EXAMPLE.Group 1.Fill 1": iconColor, - "Line.Group 1.Stroke 1": iconColor] - if previousIcon == .mute { - playOnce = true - } else { - seekToEnd = true - } - case .more: - animationName = "anim_profilemore" - colors = ["Point 2.Group 1.Fill 1": iconColor, - "Point 3.Group 1.Fill 1": iconColor, - "Point 1.Group 1.Fill 1": iconColor] - case .leave: - animationName = "anim_profileleave" - colors = ["Arrow.Group 2.Stroke 1": iconColor, - "Door.Group 1.Stroke 1": iconColor, - "Arrow.Group 1.Stroke 1": iconColor] - default: - animationName = nil - } - - if let animationName = animationName { - let animationNode: AnimationNode - if let current = self.animationNode { - animationNode = current - animationNode.setAnimation(name: animationName, colors: colors) - } else { - animationNode = AnimationNode(animation: animationName, colors: colors, scale: 1.0) - self.referenceNode.addSubnode(animationNode) - self.animationNode = animationNode - } - } else if let animationNode = self.animationNode { - self.animationNode = nil - animationNode.removeFromSupernode() - } - - if playOnce { - self.animationNode?.play() - } else if seekToEnd { - self.animationNode?.seekToEnd() - } - - //self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor self.iconNode.image = generateImage(iconSize, contextGenerator: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) context.setBlendMode(.normal) @@ -237,11 +171,75 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode { }) } + let animationName: String? + var playOnce = false + var seekToEnd = false + switch icon { + case .voiceChat: + animationName = "anim_profilevc" + case .mute: + animationName = "anim_profileunmute" + if previousIcon == .unmute { + playOnce = true + } else { + seekToEnd = true + } + case .unmute: + animationName = "anim_profilemute" + if previousIcon == .mute { + playOnce = true + } else { + seekToEnd = true + } + case .more: + animationName = "anim_profilemore" + case .leave: + animationName = "anim_profileleave" + default: + animationName = nil + } + + if let animationName = animationName { + let animatedIcon: ComponentView + if let current = self.animatedIcon { + animatedIcon = current + } else { + animatedIcon = ComponentView() + self.animatedIcon = animatedIcon + } + let _ = animatedIcon.update( + transition: .immediate, + component: AnyComponent(LottieComponent( + content: LottieComponent.AppBundleContent(name: animationName), + color: foregroundColor, + startingPosition: seekToEnd ? .end : .begin + )), + environment: {}, + containerSize: iconSize + ) + } else if let animatedIcon = self.animatedIcon { + self.animatedIcon = nil + animatedIcon.view?.removeFromSuperview() + } + + if let animatedIconView = self.animatedIcon?.view as? LottieComponent.View { + if animatedIconView.superview == nil { + self.referenceNode.view.addSubview(animatedIconView) + } + if playOnce { + animatedIconView.playOnce() + } + } + + transition.updateTintColor(layer: self.iconNode.layer, color: foregroundColor) + transition.updateTintColor(layer: self.titleNode.layer, color: foregroundColor) + transition.updateTintColor(layer: self.textNode.layer, color: foregroundColor) + if isActiveUpdated { let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut) alphaTransition.updateAlpha(node: self.iconNode, alpha: isActive ? 1.0 : 0.3) - if let animationNode = self.animationNode { - alphaTransition.updateAlpha(node: animationNode, alpha: isActive ? 1.0 : 0.3) + if let animatedIconView = self.animatedIcon?.view { + alphaTransition.updateAlpha(layer: animatedIconView.layer, alpha: isActive ? 1.0 : 0.3) } alphaTransition.updateAlpha(node: self.textNode, alpha: isActive ? 1.0 : 0.3) } @@ -253,9 +251,10 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode { transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: size)) transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size)) self.backgroundNode.update(size: size, cornerRadius: 11.0, transition: transition) + self.backgroundNode.updateColor(color: backgroundColor, transition: transition) transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: 1.0), size: iconSize)) - if let animationNode = self.animationNode { - transition.updateFrame(node: animationNode, frame: CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: 1.0), size: iconSize)) + if let animatedIconView = self.animatedIcon?.view { + transition.updateFrame(view: animatedIconView, frame: CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: 1.0), size: iconSize)) } transition.updateFrameAdditiveToCenter(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: size.height - titleSize.height - 9.0), size: titleSize)) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButton.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButton.swift index 5881239d6d..a3a0913996 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButton.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButton.swift @@ -95,30 +95,14 @@ private final class MoreIconNode: ManagedAnimationNode { final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { let containerNode: ContextControllerSourceNode let contextSourceNode: ContextReferenceContentNode - private let regularTextNode: ImmediateTextNode - private let whiteTextNode: ImmediateTextNode + private let textNode: ImmediateTextNode private let iconNode: ASImageNode private var animationNode: MoreIconNode? + private let backgroundNode: NavigationBackgroundNode private var key: PeerInfoHeaderNavigationButtonKey? - private var theme: PresentationTheme? - var isWhite: Bool = false { - didSet { - if self.isWhite != oldValue { - if case .qrCode = self.key, let theme = self.theme { - self.iconNode.image = self.isWhite ? generateTintedImage(image: PresentationResourcesRootController.navigationQrCodeIcon(theme), color: .white) : PresentationResourcesRootController.navigationQrCodeIcon(theme) - } else if case .postStory = self.key, let theme = self.theme { - self.iconNode.image = self.isWhite ? generateTintedImage(image: PresentationResourcesRootController.navigationPostStoryIcon(theme), color: .white) : PresentationResourcesRootController.navigationPostStoryIcon(theme) - } - - self.regularTextNode.isHidden = self.isWhite - self.whiteTextNode.isHidden = !self.isWhite - self.animationNode?.view.tintColor = self.isWhite ? .white : self.theme?.list.itemAccentColor - self.animationNode?.imageNode.layer.layerTintColor = self.isWhite ? UIColor.white.cgColor : self.theme?.list.itemAccentColor.cgColor - } - } - } + private var contentsColor: UIColor = .white var action: ((ASDisplayNode, ContextGesture?) -> Void)? @@ -127,22 +111,22 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { self.containerNode = ContextControllerSourceNode() self.containerNode.animateScale = false - self.regularTextNode = ImmediateTextNode() - self.whiteTextNode = ImmediateTextNode() - self.whiteTextNode.isHidden = true + self.textNode = ImmediateTextNode() self.iconNode = ASImageNode() self.iconNode.displaysAsynchronously = false self.iconNode.displayWithoutProcessing = true + self.backgroundNode = NavigationBackgroundNode(color: .clear, enableBlur: true) + super.init(pointerStyle: .insetRectangle(-8.0, 2.0)) self.isAccessibilityElement = true self.accessibilityTraits = .button self.containerNode.addSubnode(self.contextSourceNode) - self.contextSourceNode.addSubnode(self.regularTextNode) - self.contextSourceNode.addSubnode(self.whiteTextNode) + self.contextSourceNode.addSubnode(self.backgroundNode) + self.contextSourceNode.addSubnode(self.textNode) self.contextSourceNode.addSubnode(self.iconNode) self.addSubnode(self.containerNode) @@ -162,12 +146,34 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { self.action?(self.contextSourceNode, nil) } + func updateContentsColor(backgroundColor: UIColor, contentsColor: UIColor, transition: ContainedViewLayoutTransition) { + self.contentsColor = contentsColor + + self.backgroundNode.updateColor(color: backgroundColor, transition: transition) + + transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor) + transition.updateTintColor(layer: self.iconNode.layer, color: self.contentsColor) + + if let animationNode = self.animationNode { + transition.updateTintColor(layer: animationNode.imageNode.layer, color: self.contentsColor) + } + } + func update(key: PeerInfoHeaderNavigationButtonKey, presentationData: PresentationData, height: CGFloat) -> CGSize { + let transition: ContainedViewLayoutTransition = .immediate + + var iconOffset = CGPoint() + switch key { + case .back: + iconOffset = CGPoint(x: -1.0, y: 0.0) + default: + break + } + let textSize: CGSize let isFirstTime = self.key == nil - if self.key != key || self.theme !== presentationData.theme { + if self.key != key { self.key = key - self.theme = presentationData.theme let text: String var accessibilityText: String @@ -177,55 +183,64 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { var isAnimation = false var animationState: MoreIconNodeState = .more switch key { - case .edit: - text = presentationData.strings.Common_Edit - accessibilityText = text - case .done, .cancel, .selectionDone: - text = presentationData.strings.Common_Done - accessibilityText = text - isBold = true - case .select: - text = presentationData.strings.Common_Select - accessibilityText = text - case .search: - text = "" - accessibilityText = presentationData.strings.Common_Search - icon = nil// PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme) - isAnimation = true - animationState = .search - case .editPhoto: - text = presentationData.strings.Settings_EditPhoto - accessibilityText = text - case .editVideo: - text = presentationData.strings.Settings_EditVideo - accessibilityText = text - case .more: - text = "" - accessibilityText = presentationData.strings.Common_More - icon = nil// PresentationResourcesRootController.navigationMoreCircledIcon(presentationData.theme) - isGestureEnabled = true - isAnimation = true - animationState = .more - case .qrCode: - text = "" - accessibilityText = presentationData.strings.PeerInfo_QRCode_Title - icon = PresentationResourcesRootController.navigationQrCodeIcon(presentationData.theme) - case .moreToSearch: - text = "" - accessibilityText = "" - case .postStory: - text = "" - accessibilityText = presentationData.strings.Story_Privacy_PostStory - icon = PresentationResourcesRootController.navigationPostStoryIcon(presentationData.theme) + case .back: + text = "" + accessibilityText = presentationData.strings.Common_Back + icon = NavigationBar.thinBackArrowImage + case .edit: + text = presentationData.strings.Common_Edit + accessibilityText = text + case .cancel: + text = presentationData.strings.Common_Cancel + accessibilityText = text + isBold = false + case .done, .selectionDone: + text = presentationData.strings.Common_Done + accessibilityText = text + isBold = true + case .select: + text = presentationData.strings.Common_Select + accessibilityText = text + case .search: + text = "" + accessibilityText = presentationData.strings.Common_Search + icon = nil// PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme) + isAnimation = true + animationState = .search + case .editPhoto: + text = presentationData.strings.Settings_EditPhoto + accessibilityText = text + case .editVideo: + text = presentationData.strings.Settings_EditVideo + accessibilityText = text + case .more: + text = "" + accessibilityText = presentationData.strings.Common_More + icon = nil// PresentationResourcesRootController.navigationMoreCircledIcon(presentationData.theme) + isGestureEnabled = true + isAnimation = true + animationState = .more + case .qrCode: + text = "" + accessibilityText = presentationData.strings.PeerInfo_QRCode_Title + icon = PresentationResourcesRootController.navigationQrCodeIcon(presentationData.theme) + case .moreToSearch: + text = "" + accessibilityText = "" + case .postStory: + text = "" + accessibilityText = presentationData.strings.Story_Privacy_PostStory + icon = PresentationResourcesRootController.navigationPostStoryIcon(presentationData.theme) } self.accessibilityLabel = accessibilityText self.containerNode.isGestureEnabled = isGestureEnabled let font: UIFont = isBold ? Font.semibold(17.0) : Font.regular(17.0) - self.regularTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: presentationData.theme.rootController.navigationBar.accentTextColor) - self.whiteTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white) + self.textNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white) + transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor) self.iconNode.image = icon + transition.updateTintColor(layer: self.iconNode.layer, color: self.contentsColor) if isAnimation { self.iconNode.isHidden = true @@ -236,9 +251,10 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { animationNode = MoreIconNode() self.animationNode = animationNode self.contextSourceNode.addSubnode(animationNode) + animationNode.imageNode.layer.layerTintColor = self.contentsColor.cgColor + animationNode.customColor = .white } - animationNode.customColor = .white - animationNode.imageNode.layer.layerTintColor = self.isWhite ? UIColor.white.cgColor : presentationData.theme.rootController.navigationBar.accentTextColor.cgColor + transition.updateTintColor(layer: animationNode.imageNode.layer, color: self.contentsColor) animationNode.enqueueState(animationState, animated: !isFirstTime) } else { self.iconNode.isHidden = false @@ -248,39 +264,54 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { } } - textSize = self.regularTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) - let _ = self.whiteTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) + textSize = self.textNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) } else { - textSize = self.regularTextNode.bounds.size + textSize = self.textNode.bounds.size } let inset: CGFloat = 0.0 + let resultSize: CGSize + let textFrame = CGRect(origin: CGPoint(x: inset, y: floor((height - textSize.height) / 2.0)), size: textSize) - self.regularTextNode.frame = textFrame - self.whiteTextNode.frame = textFrame + self.textNode.frame = textFrame if let animationNode = self.animationNode { let animationSize = CGSize(width: 30.0, height: 30.0) - animationNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - animationSize.height) / 2.0)), size: animationSize) + animationNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - animationSize.height) / 2.0)), size: animationSize).offsetBy(dx: iconOffset.x, dy: iconOffset.y) let size = CGSize(width: animationSize.width + inset * 2.0, height: height) self.containerNode.frame = CGRect(origin: CGPoint(), size: size) self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size) - return size + resultSize = size } else if let image = self.iconNode.image { - self.iconNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - image.size.height) / 2.0)), size: image.size) + self.iconNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - image.size.height) / 2.0)), size: image.size).offsetBy(dx: iconOffset.x, dy: iconOffset.y) let size = CGSize(width: image.size.width + inset * 2.0, height: height) self.containerNode.frame = CGRect(origin: CGPoint(), size: size) self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size) - return size + resultSize = size } else { let size = CGSize(width: textSize.width + inset * 2.0, height: height) self.containerNode.frame = CGRect(origin: CGPoint(), size: size) self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size) - return size + resultSize = size } + + let diameter: CGFloat = 32.0 + let backgroundWidth: CGFloat + if self.iconNode.image != nil || self.animationNode != nil { + backgroundWidth = diameter + } else { + backgroundWidth = max(diameter, resultSize.width + 12.0 * 2.0) + } + let backgroundFrame = CGRect(origin: CGPoint(x: floor((resultSize.width - backgroundWidth) * 0.5), y: floor((resultSize.height - diameter) * 0.5)), size: CGSize(width: backgroundWidth, height: diameter)) + transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame) + self.backgroundNode.update(size: backgroundFrame.size, cornerRadius: diameter * 0.5, transition: transition) + + self.hitTestSlop = UIEdgeInsets(top: -2.0, left: -12.0, bottom: -2.0, right: -12.0) + + return resultSize } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButtonContainerNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButtonContainerNode.swift index ae063d16b4..feeb405fe9 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButtonContainerNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNavigationButtonContainerNode.swift @@ -6,6 +6,7 @@ import TelegramPresentationData import Display enum PeerInfoHeaderNavigationButtonKey { + case back case edit case done case cancel @@ -33,30 +34,34 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { private var currentLeftButtons: [PeerInfoHeaderNavigationButtonSpec] = [] private var currentRightButtons: [PeerInfoHeaderNavigationButtonSpec] = [] - var isWhite: Bool = false { - didSet { - if self.isWhite != oldValue { - for (_, buttonNode) in self.leftButtonNodes { - buttonNode.isWhite = self.isWhite - } - for (_, buttonNode) in self.rightButtonNodes { - buttonNode.isWhite = self.isWhite - } - } - } - } + private var backgroundContentColor: UIColor = .clear + private var contentsColor: UIColor = .white var performAction: ((PeerInfoHeaderNavigationButtonKey, ContextReferenceContentNode?, ContextGesture?) -> Void)? + func updateContentsColor(backgroundContentColor: UIColor, contentsColor: UIColor, transition: ContainedViewLayoutTransition) { + self.backgroundContentColor = backgroundContentColor + self.contentsColor = contentsColor + + for (_, button) in self.leftButtonNodes { + button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, transition: transition) + } + for (_, button) in self.rightButtonNodes { + button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, transition: transition) + } + } + func update(size: CGSize, presentationData: PresentationData, leftButtons: [PeerInfoHeaderNavigationButtonSpec], rightButtons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, transition: ContainedViewLayoutTransition) { + let sideInset: CGFloat = 24.0 + let maximumExpandOffset: CGFloat = 14.0 let expandOffset: CGFloat = -expandFraction * maximumExpandOffset if self.currentLeftButtons != leftButtons || presentationData.strings !== self.presentationData?.strings { self.currentLeftButtons = leftButtons - var nextRegularButtonOrigin = 16.0 - var nextExpandedButtonOrigin = 16.0 + var nextRegularButtonOrigin = sideInset + var nextExpandedButtonOrigin = sideInset for spec in leftButtons.reversed() { let buttonNode: PeerInfoHeaderNavigationButton var wasAdded = false @@ -88,8 +93,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { buttonNode.frame = buttonFrame buttonNode.alpha = 0.0 transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) - - buttonNode.isWhite = self.isWhite + buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, transition: .immediate) } else { transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame) transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) @@ -107,8 +111,8 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { } } } else { - var nextRegularButtonOrigin = 16.0 - var nextExpandedButtonOrigin = 16.0 + var nextRegularButtonOrigin = sideInset + var nextExpandedButtonOrigin = sideInset for spec in leftButtons.reversed() { if let buttonNode = self.leftButtonNodes[spec.key] { let buttonSize = buttonNode.bounds.size @@ -135,8 +139,8 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { if self.currentRightButtons != rightButtons || presentationData.strings !== self.presentationData?.strings { self.currentRightButtons = rightButtons - var nextRegularButtonOrigin = size.width - 16.0 - var nextExpandedButtonOrigin = size.width - 16.0 + var nextRegularButtonOrigin = size.width - sideInset + var nextExpandedButtonOrigin = size.width - sideInset for spec in rightButtons.reversed() { let buttonNode: PeerInfoHeaderNavigationButton var wasAdded = false @@ -174,7 +178,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { } let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) if wasAdded { - buttonNode.isWhite = self.isWhite + buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, transition: .immediate) if key == .moreToSearch { buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2) @@ -211,8 +215,8 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode { } } } else { - var nextRegularButtonOrigin = size.width - 16.0 - var nextExpandedButtonOrigin = size.width - 16.0 + var nextRegularButtonOrigin = size.width - sideInset + var nextExpandedButtonOrigin = size.width - sideInset for spec in rightButtons.reversed() { var key = spec.key diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift index 3eed39518e..59041273f7 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift @@ -76,6 +76,7 @@ private let TitleNodeStateExpanded = 1 final class PeerInfoHeaderNode: ASDisplayNode { private var context: AccountContext + private weak var controller: PeerInfoScreenImpl? private var presentationData: PresentationData? private var state: PeerInfoState? private var peer: Peer? @@ -159,8 +160,9 @@ final class PeerInfoHeaderNode: ASDisplayNode { private var validLayout: (width: CGFloat, deviceMetrics: DeviceMetrics)? - init(context: AccountContext, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isMediaOnly: Bool, isSettings: Bool, forumTopicThreadId: Int64?, chatLocation: ChatLocation) { + init(context: AccountContext, controller: PeerInfoScreenImpl, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isMediaOnly: Bool, isSettings: Bool, forumTopicThreadId: Int64?, chatLocation: ChatLocation) { self.context = context + self.controller = controller self.isAvatarExpanded = avatarInitiallyExpanded self.isOpenedFromChat = isOpenedFromChat self.isSettings = isSettings @@ -481,7 +483,168 @@ final class PeerInfoHeaderNode: ASDisplayNode { isForum = true } - if themeUpdated || self.currentCredibilityIcon != credibilityIcon { + self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0 + self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0 + + let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, isModalOverlay: isModalOverlay, peer: state.isEditing ? peer : nil, threadData: threadData, chatLocation: self.chatLocation, cachedData: cachedData, isContact: isContact, isSettings: isSettings, presentationData: presentationData, transition: transition) + transition.updateFrame(node: self.editingContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -contentOffset), size: CGSize(width: width, height: editingContentHeight))) + + let avatarOverlayFarme = self.editingContentNode.convert(self.editingContentNode.avatarNode.frame, to: self) + transition.updateFrame(node: self.avatarOverlayNode, frame: avatarOverlayFarme) + + var transitionSourceHeight: CGFloat = 0.0 + var transitionFraction: CGFloat = 0.0 + var transitionSourceAvatarFrame: CGRect? + var transitionSourceTitleFrame = CGRect() + var transitionSourceSubtitleFrame = CGRect() + + let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 22.0), size: CGSize(width: avatarSize, height: avatarSize)) + + self.backgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate) + + let headerBackgroundColor: UIColor = presentationData.theme.list.blocksBackgroundColor + + let regularNavigationContentsAccentColor: UIColor = peer?.profileColor != nil ? .white : presentationData.theme.list.itemAccentColor + let collapsedHeaderNavigationContentsAccentColor = presentationData.theme.list.itemAccentColor + let expandedAvatarNavigationContentsAccentColor: UIColor = .white + + let regularNavigationContentsPrimaryColor: UIColor = peer?.profileColor != nil ? .white : presentationData.theme.list.itemPrimaryTextColor + let collapsedHeaderNavigationContentsPrimaryColor = presentationData.theme.list.itemPrimaryTextColor + let expandedAvatarNavigationContentsPrimaryColor: UIColor = .white + + let regularContentButtonBackgroundColor: UIColor + let collapsedHeaderContentButtonBackgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + let expandedAvatarContentButtonBackgroundColor: UIColor = UIColor(white: 1.0, alpha: 0.3) + + let regularHeaderButtonBackgroundColor: UIColor + let collapsedHeaderButtonBackgroundColor: UIColor = .clear + let expandedAvatarHeaderButtonBackgroundColor: UIColor = UIColor(white: 1.0, alpha: 0.3) + + let regularContentButtonForegroundColor: UIColor = peer?.profileColor != nil ? UIColor.white : presentationData.theme.list.itemAccentColor + let collapsedHeaderContentButtonForegroundColor = presentationData.theme.list.itemAccentColor + let expandedAvatarContentButtonForegroundColor: UIColor = .white + + let regularNavigationContentsSecondaryColor: UIColor + if let profileColor = peer?.profileColor { + let backgroundColor = self.context.peerNameColors.getProfile(profileColor).main + regularNavigationContentsSecondaryColor = UIColor(white: 1.0, alpha: 0.6).blitOver(backgroundColor.withMultiplied(hue: 1.0, saturation: 2.2, brightness: 1.5), alpha: 1.0) + + if presentationData.theme.overallDarkAppearance { + let baseButtonBackgroundColor: UIColor = UIColor(white: 0.0, alpha: 0.4) + regularContentButtonBackgroundColor = baseButtonBackgroundColor.blitOver(backgroundColor.withMultiplied(hue: 1.0, saturation: 2.2, brightness: 0.7), alpha: 1.0) + } else { + let baseButtonBackgroundColor: UIColor = UIColor(white: 1.0, alpha: 0.3) + regularContentButtonBackgroundColor = baseButtonBackgroundColor.blitOver(backgroundColor.withMultiplied(hue: 1.0, saturation: 0.8, brightness: 1.0), alpha: 1.0) + } + regularHeaderButtonBackgroundColor = regularContentButtonBackgroundColor + } else { + regularNavigationContentsSecondaryColor = presentationData.theme.list.itemSecondaryTextColor + regularContentButtonBackgroundColor = presentationData.theme.list.itemBlocksBackgroundColor + regularHeaderButtonBackgroundColor = .clear + } + let collapsedHeaderNavigationContentsSecondaryColor = presentationData.theme.list.itemSecondaryTextColor + let expandedAvatarNavigationContentsSecondaryColor: UIColor = .white + + let navigationContentsAccentColor: UIColor + let navigationContentsPrimaryColor: UIColor + let navigationContentsSecondaryColor: UIColor + + let contentButtonBackgroundColor: UIColor + let contentButtonForegroundColor: UIColor + + let headerButtonBackgroundColor: UIColor + + var effectiveSeparatorAlpha: CGFloat + if let navigationTransition = self.navigationTransition { + transitionSourceHeight = navigationTransition.sourceNavigationBar.backgroundNode.bounds.height + transitionFraction = navigationTransition.fraction + + if let avatarNavigationNode = navigationTransition.sourceNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode { + if let statusView = avatarNavigationNode.statusView.view { + transitionSourceAvatarFrame = statusView.convert(statusView.bounds, to: navigationTransition.sourceNavigationBar.view) + } else { + transitionSourceAvatarFrame = avatarNavigationNode.avatarNode.view.convert(avatarNavigationNode.avatarNode.view.bounds, to: navigationTransition.sourceNavigationBar.view) + } + transition.updateAlpha(node: self.avatarListNode.avatarContainerNode.avatarNode, alpha: 1.0 - transitionFraction) + } else { + if deviceMetrics.hasDynamicIsland && !isLandscape { + transitionSourceAvatarFrame = CGRect(origin: CGPoint(x: avatarFrame.minX, y: -20.0), size: avatarFrame.size).insetBy(dx: avatarSize * 0.4, dy: avatarSize * 0.4) + } else { + transitionSourceAvatarFrame = avatarFrame.offsetBy(dx: 0.0, dy: -avatarFrame.maxY).insetBy(dx: avatarSize * 0.4, dy: avatarSize * 0.4) + } + } + transitionSourceTitleFrame = navigationTransition.sourceTitleFrame + transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame + + transition.updateAlpha(layer: self.backgroundBannerView.layer, alpha: 1.0 - transitionFraction) + + self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor.mixedWith(headerBackgroundColor, alpha: 1.0 - transitionFraction), forceKeepBlur: true, transition: transition) + effectiveSeparatorAlpha = transitionFraction + + if self.isAvatarExpanded { + navigationContentsAccentColor = expandedAvatarNavigationContentsAccentColor + navigationContentsPrimaryColor = expandedAvatarNavigationContentsPrimaryColor + navigationContentsSecondaryColor = expandedAvatarNavigationContentsSecondaryColor + + contentButtonBackgroundColor = expandedAvatarContentButtonBackgroundColor + contentButtonForegroundColor = expandedAvatarContentButtonForegroundColor + + headerButtonBackgroundColor = expandedAvatarHeaderButtonBackgroundColor + } else { + navigationContentsAccentColor = regularNavigationContentsAccentColor + navigationContentsPrimaryColor = regularNavigationContentsPrimaryColor + navigationContentsSecondaryColor = regularNavigationContentsSecondaryColor + + contentButtonBackgroundColor = regularContentButtonBackgroundColor + contentButtonForegroundColor = regularContentButtonForegroundColor + + headerButtonBackgroundColor = regularHeaderButtonBackgroundColor + } + + if self.isAvatarExpanded, case .animated = transition, transitionFraction == 1.0 { + self.avatarListNode.animateAvatarCollapse(transition: transition) + } + self.avatarClippingNode.clipsToBounds = false + } else { + let contentOffset = max(0.0, contentOffset - 140.0) + let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / 30.0)) + self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.opaqueBackgroundColor.mixedWith(headerBackgroundColor, alpha: 1.0 - backgroundTransitionFraction), forceKeepBlur: true, transition: transition) + + transition.updateAlpha(layer: self.backgroundBannerView.layer, alpha: state.isEditing ? 0.0 : (1.0 - backgroundTransitionFraction)) + + if state.isEditing { + navigationContentsAccentColor = collapsedHeaderNavigationContentsAccentColor + navigationContentsPrimaryColor = collapsedHeaderNavigationContentsPrimaryColor + navigationContentsSecondaryColor = collapsedHeaderNavigationContentsSecondaryColor + contentButtonBackgroundColor = collapsedHeaderContentButtonBackgroundColor + contentButtonForegroundColor = collapsedHeaderContentButtonForegroundColor + + headerButtonBackgroundColor = collapsedHeaderButtonBackgroundColor + } else if self.isAvatarExpanded { + navigationContentsAccentColor = expandedAvatarNavigationContentsAccentColor + navigationContentsPrimaryColor = expandedAvatarNavigationContentsPrimaryColor + navigationContentsSecondaryColor = expandedAvatarNavigationContentsSecondaryColor + contentButtonBackgroundColor = expandedAvatarContentButtonBackgroundColor + contentButtonForegroundColor = expandedAvatarContentButtonForegroundColor + + headerButtonBackgroundColor = expandedAvatarHeaderButtonBackgroundColor + } else { + navigationContentsAccentColor = regularNavigationContentsAccentColor.mixedWith(collapsedHeaderNavigationContentsAccentColor, alpha: backgroundTransitionFraction) + navigationContentsPrimaryColor = regularNavigationContentsPrimaryColor.mixedWith(collapsedHeaderNavigationContentsPrimaryColor, alpha: backgroundTransitionFraction) + navigationContentsSecondaryColor = regularNavigationContentsSecondaryColor.mixedWith(collapsedHeaderNavigationContentsSecondaryColor, alpha: backgroundTransitionFraction) + + contentButtonBackgroundColor = regularContentButtonBackgroundColor.mixedWith(collapsedHeaderContentButtonBackgroundColor, alpha: backgroundTransitionFraction) + contentButtonForegroundColor = regularContentButtonForegroundColor.mixedWith(collapsedHeaderContentButtonForegroundColor, alpha: backgroundTransitionFraction) + + headerButtonBackgroundColor = regularHeaderButtonBackgroundColor.mixedWith(collapsedHeaderButtonBackgroundColor, alpha: backgroundTransitionFraction) + } + + effectiveSeparatorAlpha = backgroundTransitionFraction + + self.avatarClippingNode.clipsToBounds = true + } + + do { self.currentCredibilityIcon = credibilityIcon var currentEmojiStatus: PeerEmojiStatus? @@ -492,11 +655,11 @@ final class PeerInfoHeaderNode: ASDisplayNode { emojiRegularStatusContent = .none emojiExpandedStatusContent = .none case .premium: - emojiRegularStatusContent = .premium(color: UIColor.white) - emojiExpandedStatusContent = .premium(color: UIColor(rgb: 0xffffff, alpha: 0.75)) + emojiRegularStatusContent = .premium(color: navigationContentsAccentColor) + emojiExpandedStatusContent = .premium(color: navigationContentsAccentColor) case .verified: emojiRegularStatusContent = .verified(fillColor: presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .large) - emojiExpandedStatusContent = .verified(fillColor: UIColor(rgb: 0xffffff, alpha: 0.75), foregroundColor: .clear, sizeType: .large) + emojiExpandedStatusContent = .verified(fillColor: navigationContentsAccentColor, foregroundColor: .clear, sizeType: .large) case .fake: emojiRegularStatusContent = .text(color: presentationData.theme.chat.message.incoming.scamColor, string: presentationData.strings.Message_FakeAccount.uppercased()) emojiExpandedStatusContent = emojiRegularStatusContent @@ -505,14 +668,14 @@ final class PeerInfoHeaderNode: ASDisplayNode { emojiExpandedStatusContent = emojiRegularStatusContent case let .emojiStatus(emojiStatus): currentEmojiStatus = emojiStatus - emojiRegularStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 80.0, height: 80.0), placeholderColor: presentationData.theme.list.mediaPlaceholderColor, themeColor: UIColor.white, loopMode: .forever) - emojiExpandedStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 80.0, height: 80.0), placeholderColor: UIColor(rgb: 0xffffff, alpha: 0.15), themeColor: UIColor.white, loopMode: .forever) + emojiRegularStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 80.0, height: 80.0), placeholderColor: presentationData.theme.list.mediaPlaceholderColor, themeColor: navigationContentsAccentColor, loopMode: .forever) + emojiExpandedStatusContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 80.0, height: 80.0), placeholderColor: navigationContentsAccentColor, themeColor: navigationContentsAccentColor, loopMode: .forever) } - let animateStatusIcon = !self.titleCredibilityIconView.bounds.isEmpty + //let animateStatusIcon = !self.titleCredibilityIconView.bounds.isEmpty let iconSize = self.titleCredibilityIconView.update( - transition: animateStatusIcon ? Transition(animation: .curve(duration: 0.3, curve: .easeInOut)) : .immediate, + transition: Transition(transition), component: AnyComponent(EmojiStatusComponent( context: self.context, animationCache: self.animationCache, @@ -568,7 +731,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { containerSize: CGSize(width: 34.0, height: 34.0) ) let expandedIconSize = self.titleExpandedCredibilityIconView.update( - transition: animateStatusIcon ? Transition(animation: .curve(duration: 0.3, curve: .easeInOut)) : .immediate, + transition: Transition(transition), component: AnyComponent(EmojiStatusComponent( context: self.context, animationCache: self.animationCache, @@ -591,76 +754,37 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.titleExpandedCredibilityIconSize = expandedIconSize } - self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0 - self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0 + self.navigationButtonContainer.updateContentsColor(backgroundContentColor: headerButtonBackgroundColor, contentsColor: navigationContentsAccentColor, transition: transition) - let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, isModalOverlay: isModalOverlay, peer: state.isEditing ? peer : nil, threadData: threadData, chatLocation: self.chatLocation, cachedData: cachedData, isContact: isContact, isSettings: isSettings, presentationData: presentationData, transition: transition) - transition.updateFrame(node: self.editingContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -contentOffset), size: CGSize(width: width, height: editingContentHeight))) - - let avatarOverlayFarme = self.editingContentNode.convert(self.editingContentNode.avatarNode.frame, to: self) - transition.updateFrame(node: self.avatarOverlayNode, frame: avatarOverlayFarme) - - var transitionSourceHeight: CGFloat = 0.0 - var transitionFraction: CGFloat = 0.0 - var transitionSourceAvatarFrame: CGRect? - var transitionSourceTitleFrame = CGRect() - var transitionSourceSubtitleFrame = CGRect() - - let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 22.0), size: CGSize(width: avatarSize, height: avatarSize)) - - self.backgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate) - - let headerBackgroundColor: UIColor = presentationData.theme.list.blocksBackgroundColor - let _ = headerBackgroundColor - - var effectiveSeparatorAlpha: CGFloat - if let navigationTransition = self.navigationTransition { - transitionSourceHeight = navigationTransition.sourceNavigationBar.backgroundNode.bounds.height - transitionFraction = navigationTransition.fraction - - if let avatarNavigationNode = navigationTransition.sourceNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode { - if let statusView = avatarNavigationNode.statusView.view { - transitionSourceAvatarFrame = statusView.convert(statusView.bounds, to: navigationTransition.sourceNavigationBar.view) - } else { - transitionSourceAvatarFrame = avatarNavigationNode.avatarNode.view.convert(avatarNavigationNode.avatarNode.view.bounds, to: navigationTransition.sourceNavigationBar.view) - } - transition.updateAlpha(node: self.avatarListNode.avatarContainerNode.avatarNode, alpha: 1.0 - transitionFraction) - } else { - if deviceMetrics.hasDynamicIsland && !isLandscape { - transitionSourceAvatarFrame = CGRect(origin: CGPoint(x: avatarFrame.minX, y: -20.0), size: avatarFrame.size).insetBy(dx: avatarSize * 0.4, dy: avatarSize * 0.4) - } else { - transitionSourceAvatarFrame = avatarFrame.offsetBy(dx: 0.0, dy: -avatarFrame.maxY).insetBy(dx: avatarSize * 0.4, dy: avatarSize * 0.4) - } + self.titleNode.updateTintColor(color: navigationContentsPrimaryColor, transition: transition) + self.subtitleNode.updateTintColor(color: navigationContentsSecondaryColor, transition: transition) + self.panelSubtitleNode.updateTintColor(color: navigationContentsSecondaryColor, transition: transition) + self.nextPanelSubtitleNode.updateTintColor(color: navigationContentsSecondaryColor, transition: transition) + if let navigationBar = self.controller?.navigationBar { + if let mainContentNode = navigationBar.backButtonNode.mainContentNode { + transition.updateTintColor(layer: mainContentNode.layer, color: navigationContentsAccentColor) } - transitionSourceTitleFrame = navigationTransition.sourceTitleFrame - transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame - - transition.updateAlpha(layer: self.backgroundBannerView.layer, alpha: 1.0 - transitionFraction) + transition.updateTintColor(layer: navigationBar.backButtonArrow.layer, color: navigationContentsAccentColor) - self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor.mixedWith(headerBackgroundColor, alpha: 1.0 - transitionFraction), forceKeepBlur: true, transition: transition) - effectiveSeparatorAlpha = transitionFraction - - if self.isAvatarExpanded, case .animated = transition, transitionFraction == 1.0 { - self.avatarListNode.animateAvatarCollapse(transition: transition) + if let mainContentNode = navigationBar.leftButtonNode.mainContentNode { + transition.updateTintColor(layer: mainContentNode.layer, color: navigationContentsAccentColor) } - self.avatarClippingNode.clipsToBounds = false - } else { - let contentOffset = max(0.0, contentOffset - 140.0) - let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / 30.0)) - self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.opaqueBackgroundColor.mixedWith(headerBackgroundColor, alpha: 1.0 - backgroundTransitionFraction), forceKeepBlur: true, transition: transition) - transition.updateAlpha(layer: self.backgroundBannerView.layer, alpha: state.isEditing ? 0.0 : 1.0) - effectiveSeparatorAlpha = backgroundTransitionFraction - - self.avatarClippingNode.clipsToBounds = true + navigationBar.rightButtonNode.contentsColor = navigationContentsAccentColor + navigationBar.leftButtonNode.contentsColor = navigationContentsAccentColor + navigationBar.backButtonNode.contentsColor = navigationContentsAccentColor } + var titleBrightness: CGFloat = 0.0 + navigationContentsPrimaryColor.getHue(nil, saturation: nil, brightness: &titleBrightness, alpha: nil) + self.controller?.setStatusBarStyle(titleBrightness > 0.5 ? .White : .Black, animated: !isFirstTime) + self.avatarListNode.avatarContainerNode.updateTransitionFraction(transitionFraction, transition: transition) self.avatarListNode.listContainerNode.currentItemNode?.updateTransitionFraction(transitionFraction, transition: transition) self.avatarOverlayNode.updateTransitionFraction(transitionFraction, transition: transition) if self.navigationTitle != presentationData.strings.EditProfile_Title || themeUpdated { - self.navigationTitleNode.attributedText = NSAttributedString(string: presentationData.strings.EditProfile_Title, font: Font.semibold(17.0), textColor: UIColor.white) + self.navigationTitleNode.attributedText = NSAttributedString(string: presentationData.strings.EditProfile_Title, font: Font.semibold(17.0), textColor: .white) } let navigationTitleSize = self.navigationTitleNode.updateLayout(CGSize(width: width, height: navigationHeight)) @@ -727,7 +851,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { } titleStringText = title - titleAttributes = MultiScaleTextState.Attributes(font: Font.medium(28.0), color: UIColor.white) + titleAttributes = MultiScaleTextState.Attributes(font: Font.medium(28.0), color: .white) smallTitleAttributes = MultiScaleTextState.Attributes(font: Font.medium(28.0), color: .white) if self.isSettings, let user = peer as? TelegramUser { @@ -737,10 +861,10 @@ final class PeerInfoHeaderNode: ASDisplayNode { subtitle = "\(subtitle) • @\(mainUsername)" } subtitleStringText = subtitle - subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(17.0), color: UIColor.white.withMultipliedAlpha(0.7)) - smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor(white: 1.0, alpha: 0.7)) + subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(17.0), color: .white) + smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white) - usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7))) + usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white)) } else if let _ = threadData { let subtitleColor: UIColor subtitleColor = UIColor.white @@ -750,9 +874,9 @@ final class PeerInfoHeaderNode: ASDisplayNode { subtitleStringText = statusText subtitleAttributes = MultiScaleTextState.Attributes(font: Font.semibold(16.0), color: subtitleColor) - smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor(white: 1.0, alpha: 0.7)) + smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white) - usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7))) + usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white)) subtitleIsButton = true @@ -762,26 +886,26 @@ final class PeerInfoHeaderNode: ASDisplayNode { if panelStatusData.isActivity { subtitleColor = UIColor.white } else { - subtitleColor = UIColor.white.withAlphaComponent(0.7) + subtitleColor = UIColor.white } panelSubtitleString = (panelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: subtitleColor)) } if let nextPanelStatusData = maybeNextPanelStatusData { - nextPanelSubtitleString = (nextPanelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: UIColor.white.withMultipliedAlpha(0.7))) + nextPanelSubtitleString = (nextPanelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: .white)) } } else if let statusData = statusData { let subtitleColor: UIColor if statusData.isActivity { subtitleColor = UIColor.white } else { - subtitleColor = UIColor.white.withMultipliedAlpha(0.7) + subtitleColor = UIColor.white } subtitleStringText = statusData.text subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(17.0), color: subtitleColor) - smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor(white: 1.0, alpha: 0.7)) + smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white) - usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7))) + usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white)) let (maybePanelStatusData, maybeNextPanelStatusData, _) = panelStatusData if let panelStatusData = maybePanelStatusData { @@ -789,30 +913,30 @@ final class PeerInfoHeaderNode: ASDisplayNode { if panelStatusData.isActivity { subtitleColor = UIColor.white } else { - subtitleColor = UIColor.white.withMultipliedAlpha(0.7) + subtitleColor = UIColor.white } panelSubtitleString = (panelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: subtitleColor)) } if let nextPanelStatusData = maybeNextPanelStatusData { - nextPanelSubtitleString = (nextPanelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: UIColor.white.withMultipliedAlpha(0.7))) + nextPanelSubtitleString = (nextPanelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: .white)) } } else { subtitleStringText = " " - subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7)) - smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7)) + subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white) + smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white) - usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7))) + usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white)) } } else { titleStringText = " " - titleAttributes = MultiScaleTextState.Attributes(font: Font.regular(24.0), color: UIColor.white) + titleAttributes = MultiScaleTextState.Attributes(font: Font.regular(24.0), color: .white) smallTitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(24.0), color: .white) subtitleStringText = " " - subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7)) - smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7)) + subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white) + smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white) - usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: UIColor.white.withMultipliedAlpha(0.7))) + usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(16.0), color: .white)) } let textSideInset: CGFloat = 36.0 @@ -868,16 +992,16 @@ final class PeerInfoHeaderNode: ASDisplayNode { if let current = self.subtitleArrowNode { subtitleArrowNode = current if themeUpdated { - subtitleArrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Item List/DisclosureArrow"), color: UIColor.white.withMultipliedAlpha(0.5)) + subtitleArrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Item List/DisclosureArrow"), color: .white)?.withRenderingMode(.alwaysTemplate) } } else { subtitleArrowNode = ASImageNode() self.subtitleArrowNode = subtitleArrowNode self.subtitleNode.insertSubnode(subtitleArrowNode, at: 1) - subtitleArrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Item List/DisclosureArrow"), color: UIColor.white.withMultipliedAlpha(0.5)) + subtitleArrowNode.image = generateTintedImage(image: UIImage(bundleImageName: "Item List/DisclosureArrow"), color: .white)?.withRenderingMode(.alwaysTemplate) } - subtitleBackgroundNode.backgroundColor = UIColor.white.withMultipliedAlpha(0.1) + subtitleBackgroundNode.backgroundColor = .white.withMultipliedAlpha(0.1) let subtitleSize = subtitleNodeLayout[TitleNodeStateRegular]!.size var subtitleBackgroundFrame = CGRect(origin: CGPoint(), size: subtitleSize).offsetBy(dx: -subtitleSize.width * 0.5, dy: -subtitleSize.height * 0.5).insetBy(dx: -6.0, dy: -4.0) subtitleBackgroundFrame.size.width += 12.0 @@ -965,7 +1089,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { collapsedTransitionOffset = -10.0 * navigationTransition.fraction } - transition.updateFrame(view: self.titleCredibilityIconView, frame: CGRect(origin: CGPoint(x: titleSize.width + 4.0 + collapsedTransitionOffset, y: floor((titleSize.height - credibilityIconSize.height) / 2.0) + 2.0), size: credibilityIconSize)) + transition.updateFrame(view: self.titleCredibilityIconView, frame: CGRect(origin: CGPoint(x: titleSize.width + 4.0 + collapsedTransitionOffset, y: floor((titleSize.height - credibilityIconSize.height) / 2.0)), size: credibilityIconSize)) transition.updateFrame(view: self.titleExpandedCredibilityIconView, frame: CGRect(origin: CGPoint(x: titleExpandedSize.width + 4.0, y: floor((titleExpandedSize.height - titleExpandedCredibilityIconSize.height) / 2.0) + 1.0), size: titleExpandedCredibilityIconSize)) } @@ -1097,6 +1221,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { } avatarOffset = 0.0 } else { + // avatarScale = 1.0 * (1.0 - titleCollapseFraction) + avatarMinScale * titleCollapseFraction avatarOffset = apparentTitleLockOffset + 0.0 * (1.0 - titleCollapseFraction) + 10.0 * titleCollapseFraction } @@ -1190,7 +1315,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { } } else { var trueAvatarSize = avatarFrame.size - if let storyStats = self.avatarListNode.avatarContainerNode.avatarNode.storyStats, storyStats.unseenCount != 0 { + if let storyStats = self.avatarListNode.avatarContainerNode.avatarNode.storyStats, storyStats.totalCount != 0 { trueAvatarSize.width -= 3.0 * 4.0 trueAvatarSize.height -= 3.0 * 4.0 } @@ -1551,7 +1676,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { isActive = buttonKey == highlightedButton } - buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isActive: isActive, presentationData: presentationData, transition: buttonTransition) + buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isActive: isActive, presentationData: presentationData, backgroundColor: contentButtonBackgroundColor, foregroundColor: contentButtonForegroundColor, transition: buttonTransition) if wasAdded { buttonNode.alpha = 0.0 @@ -1621,6 +1746,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { component: AnyComponent(PeerInfoCoverComponent( context: self.context, peer: peer.flatMap(EnginePeer.init), + isDark: presentationData.theme.overallDarkAppearance, avatarCenter: apparentAvatarFrame.center, avatarScale: avatarScale, avatarTransitionFraction: max(0.0, min(1.0, titleCollapseFraction + transitionFraction * 2.0)), diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index e346aed08d..a7dbb2e339 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -2255,7 +2255,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro if case let .replyThread(message) = chatLocation { forumTopicThreadId = Int64(message.messageId.id) } - self.headerNode = PeerInfoHeaderNode(context: context, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, isMediaOnly: self.isMediaOnly, isSettings: isSettings, forumTopicThreadId: forumTopicThreadId, chatLocation: self.chatLocation) + self.headerNode = PeerInfoHeaderNode(context: context, controller: controller, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, isMediaOnly: self.isMediaOnly, isSettings: isSettings, forumTopicThreadId: forumTopicThreadId, chatLocation: self.chatLocation) self.paneContainerNode = PeerInfoPaneContainerNode(context: context, updatedPresentationData: controller.updatedPresentationData, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, isMediaOnly: self.isMediaOnly) super.init() @@ -3281,6 +3281,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro return } switch key { + case .back: + strongSelf.controller?.dismiss() case .edit: if case let .replyThread(message) = strongSelf.chatLocation { let threadId = Int64(message.messageId.id) @@ -3333,7 +3335,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } } }) - strongSelf.controller?.navigationItem.setLeftBarButton(UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, style: .plain, target: strongSelf, action: #selector(strongSelf.editingCancelPressed)), animated: true) } case .done, .cancel: strongSelf.view.endEditing(true) @@ -3649,7 +3650,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } UIView.transition(with: strongSelf.view, duration: 0.3, options: [.transitionCrossDissolve], animations: { }, completion: nil) - strongSelf.controller?.navigationItem.setLeftBarButton(nil, animated: true) } (strongSelf.controller?.parent as? TabBarController)?.updateIsTabBarHidden(false, transition: .animated(duration: 0.3, curve: .linear)) case .select: @@ -3993,11 +3993,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro self.storiesReady.set(false) let expiringStoryList = PeerExpiringStoryListContext(account: context.account, peerId: peerId) self.expiringStoryList = expiringStoryList - self.storyUploadProgressDisposable = (context.engine.messages.allStoriesUploadProgress() - |> map { value -> Float? in - return value[peerId] - } - |> distinctUntilChanged).startStrict(next: { [weak self] value in + self.storyUploadProgressDisposable = ( + combineLatest(context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + |> distinctUntilChanged, + context.engine.messages.allStoriesUploadProgress() + |> map { value -> Float? in + return value[peerId] + } + |> distinctUntilChanged + )).startStrict(next: { [weak self] peer, value in guard let self else { return } @@ -4008,7 +4012,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro if self.headerNode.avatarListNode.avatarContainerNode.storyProgress != mappedValue { self.headerNode.avatarListNode.avatarContainerNode.storyProgress = mappedValue - self.headerNode.avatarListNode.avatarContainerNode.updateStoryView(transition: .immediate, theme: self.presentationData.theme) + self.headerNode.avatarListNode.avatarContainerNode.updateStoryView(transition: .immediate, theme: self.presentationData.theme, peer: peer?._asPeer()) } }) self.expiringStoryListDisposable = (combineLatest(queue: .mainQueue(), @@ -9959,11 +9963,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition) transition.updateFrame(node: self.headerNode.navigationButtonContainer, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight))) - self.headerNode.navigationButtonContainer.isWhite = true//self.headerNode.isAvatarExpanded + var leftNavigationButtons: [PeerInfoHeaderNavigationButtonSpec] = [] var rightNavigationButtons: [PeerInfoHeaderNavigationButtonSpec] = [] if self.state.isEditing { + leftNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .cancel, isForExpandedView: false)) rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .done, isForExpandedView: false)) } else { if self.isSettings { @@ -9999,6 +10004,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .selectionDone, isForExpandedView: true)) } } + if leftNavigationButtons.isEmpty, let controller = self.controller, let previousItem = controller.previousItem { + switch previousItem { + case .close, .item: + leftNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .back, isForExpandedView: false)) + } + } self.headerNode.navigationButtonContainer.update(size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight), presentationData: self.presentationData, leftButtons: leftNavigationButtons, rightButtons: rightNavigationButtons, expandFraction: effectiveAreaExpansionFraction, transition: transition) } } @@ -10102,9 +10113,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } private func updateNavigationExpansionPresentation(isExpanded: Bool, animated: Bool) { - if let controller = self.controller { - controller.setStatusBarStyle(.White, animated: animated) - + /*if let controller = self.controller { if animated { UIView.transition(with: controller.controllerNode.headerNode.navigationButtonContainer.view, duration: 0.3, options: [.transitionCrossDissolve], animations: { }, completion: nil) @@ -10125,7 +10134,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro ), strings: baseNavigationBarPresentationData.strings) controller.setNavigationBarPresentationData(navigationBarPresentationData, animated: animated) - } + }*/ } func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { @@ -10255,6 +10264,16 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc } } + override public var previousItem: NavigationPreviousAction? { + didSet { + if self.isNodeLoaded { + if let (layout, navigationHeight) = self.validLayout { + self.controllerNode.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate) + } + } + } + } + private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)? public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool = false, hintGroupInCommon: PeerId? = nil, requestsContext: PeerInvitationImportersContext? = nil, forumTopicThread: ChatReplyThreadMessage? = nil) { @@ -10282,8 +10301,8 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc super.init(navigationBarPresentationData: NavigationBarPresentationData( theme: NavigationBarTheme( buttonColor: .white, - disabledButtonColor: baseNavigationBarPresentationData.theme.disabledButtonColor, - primaryTextColor: baseNavigationBarPresentationData.theme.primaryTextColor, + disabledButtonColor: .white, + primaryTextColor: .white, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, @@ -10291,6 +10310,8 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc badgeStrokeColor: baseNavigationBarPresentationData.theme.badgeStrokeColor, badgeTextColor: baseNavigationBarPresentationData.theme.badgeTextColor ), strings: baseNavigationBarPresentationData.strings)) + + self.navigationBar?.enableAutomaticBackButton = false if isSettings { let activeSessionsContextAndCountSignal = deferred { () -> Signal<(ActiveSessionsContext, Int, WebSessionsContext)?, NoError> in @@ -10502,8 +10523,6 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc } } - self.setStatusBarStyle(.White, animated: false) - self.scrollToTop = { [weak self] in self?.controllerNode.scrollToTop() } @@ -11001,7 +11020,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig if let currentBackButtonArrow = topNavigationBar.makeTransitionBackArrowNode(accentColor: .white) { self.currentBackButtonArrow = currentBackButtonArrow - self.addSubnode(currentBackButtonArrow) + //self.addSubnode(currentBackButtonArrow) } if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View { @@ -11015,7 +11034,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig if let currentBackButton = topNavigationBar.makeTransitionBackButtonNode(accentColor: .white) { self.currentBackButton = currentBackButton - self.addSubnode(currentBackButton) + //self.addSubnode(currentBackButton) } if let headerView = bottomNavigationBar.customHeaderContentView as? ChatListHeaderComponent.View { @@ -11087,10 +11106,12 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig if let backArrowView = headerView.backArrowView { let previousBackButtonArrowFrame = backArrowView.convert(backArrowView.bounds, to: bottomNavigationBar.view) previousBackButtonArrow.frame = previousBackButtonArrowFrame + transition.updateAlpha(layer: previousBackButtonArrow.layer, alpha: fraction) } } else { let previousBackButtonArrowFrame = bottomNavigationBar.backButtonArrow.view.convert(bottomNavigationBar.backButtonArrow.view.bounds, to: bottomNavigationBar.view) previousBackButtonArrow.frame = previousBackButtonArrowFrame + transition.updateAlpha(layer: previousBackButtonArrow.layer, alpha: fraction) } } diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/BUILD b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/BUILD index 2dc1c20ba1..dd8d1627db 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/BUILD +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/BUILD @@ -26,6 +26,8 @@ swift_library( "//submodules/SolidRoundedButtonNode", "//submodules/AppBundle", "//submodules/PremiumUI", + "//submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent", + "//submodules/AvatarNode", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/EmojiPickerItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/EmojiPickerItem.swift index 7c8f6f686b..c858d11c1a 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/EmojiPickerItem.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/EmojiPickerItem.swift @@ -16,6 +16,8 @@ final class EmojiPickerItem: ListViewItem, ItemListItem { let strings: PresentationStrings let emojiContent: EmojiPagerContentComponent let backgroundIconColor: UIColor + let isProfileColor: Bool + let hasRemoveButton: Bool let sectionId: ItemListSectionId init( @@ -24,6 +26,8 @@ final class EmojiPickerItem: ListViewItem, ItemListItem { strings: PresentationStrings, emojiContent: EmojiPagerContentComponent, backgroundIconColor: UIColor, + isProfileColor: Bool, + hasRemoveButton: Bool, sectionId: ItemListSectionId ) { self.context = context @@ -31,6 +35,8 @@ final class EmojiPickerItem: ListViewItem, ItemListItem { self.strings = strings self.emojiContent = emojiContent self.backgroundIconColor = backgroundIconColor + self.isProfileColor = isProfileColor + self.hasRemoveButton = hasRemoveButton self.sectionId = sectionId } @@ -103,13 +109,20 @@ final class EmojiPickerItemNode: ListViewItemNode { } func asyncLayout() -> (_ item: EmojiPickerItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { - let currentItem = self.item - return { item, params, neighbors in let insets: UIEdgeInsets let separatorHeight = UIScreenPixel - var contentSize = CGSize(width: params.width, height: params.availableHeight - 452.0) + var contentHeight: CGFloat + if item.isProfileColor { + contentHeight = params.availableHeight - 352.0 - 10.0 + if item.hasRemoveButton { + contentHeight -= 44.0 + } + } else { + contentHeight = params.availableHeight - 452.0 + } + var contentSize = CGSize(width: params.width, height: contentHeight) if params.width <= 320.0 { contentSize.height += 77.0 } @@ -121,16 +134,6 @@ final class EmojiPickerItemNode: ListViewItemNode { return (layout, { [weak self] in if let strongSelf = self { strongSelf.item = item - - if let currentItem, currentItem.backgroundIconColor != item.backgroundIconColor { - if let snapshot = strongSelf.view.snapshotView(afterScreenUpdates: false) { - snapshot.frame = CGRect(origin: CGPoint(x: 0.0, y: -insets.top), size: snapshot.frame.size) - strongSelf.view.addSubview(snapshot) - snapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, delay: 0.25, removeOnCompletion: false, completion: { _ in - snapshot.removeFromSuperview() - }) - } - } strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift index 54e1c3e99a..3fe87c1620 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift @@ -184,7 +184,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { var peers = SimpleDictionary() var messages = SimpleDictionary() - peers[authorPeerId] = TelegramUser(id: authorPeerId, accessHash: nil, firstName: messageItem.author, lastName: "", username: nil, phone: nil, photo: messageItem.photo, botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: messageItem.nameColor, backgroundEmojiId: messageItem.backgroundEmojiId) + peers[authorPeerId] = TelegramUser(id: authorPeerId, accessHash: nil, firstName: messageItem.author, lastName: "", username: nil, phone: nil, photo: messageItem.photo, botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: messageItem.nameColor, backgroundEmojiId: messageItem.backgroundEmojiId, profileColor: nil, profileBackgroundEmojiId: nil) let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3) if let (_, text) = messageItem.reply { @@ -296,7 +296,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { headerNode.updateLayoutInternal(size: headerFrame.size, leftInset: leftInset, rightInset: rightInset) headerNode.updateStickDistanceFactor(stickLocationDistanceFactor, transition: .immediate) } else { - headerNode = header.node(synchronousLoad: false) + headerNode = header.node(synchronousLoad: true) if headerNode.item !== header { header.updateNode(headerNode, previous: nil, next: nil) headerNode.item = header diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorItem.swift index c628bc1895..7e7863506a 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorItem.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorItem.swift @@ -287,13 +287,15 @@ final class PeerNameColorItem: ListViewItem, ItemListItem { let theme: PresentationTheme let colors: PeerNameColors - let currentColor: PeerNameColor + let isProfile: Bool + let currentColor: PeerNameColor? let updated: (PeerNameColor) -> Void let tag: ItemListItemTag? - init(theme: PresentationTheme, colors: PeerNameColors, currentColor: PeerNameColor, updated: @escaping (PeerNameColor) -> Void, tag: ItemListItemTag? = nil, sectionId: ItemListSectionId) { + init(theme: PresentationTheme, colors: PeerNameColors, isProfile: Bool, currentColor: PeerNameColor?, updated: @escaping (PeerNameColor) -> Void, tag: ItemListItemTag? = nil, sectionId: ItemListSectionId) { self.theme = theme self.colors = colors + self.isProfile = isProfile self.currentColor = currentColor self.updated = updated self.tag = tag @@ -436,7 +438,13 @@ final class PeerNameColorItemNode: ListViewItemNode, ItemListItemNode { let options = ListViewDeleteAndInsertOptions() var scrollToItem: ListViewScrollToItem? if !self.initialized || transition.updatePosition || !self.tapping { - if let index = item.colors.displayOrder.firstIndex(where: { $0 == item.currentColor.rawValue }) { + let displayOrder: [Int32] + if item.isProfile { + displayOrder = item.colors.profileDisplayOrder + } else { + displayOrder = item.colors.displayOrder + } + if let index = displayOrder.firstIndex(where: { $0 == item.currentColor?.rawValue }) { scrollToItem = ListViewScrollToItem(index: index, position: .bottom(-70.0), animated: false, curve: .Default(duration: 0.0), directionHint: .Down) self.initialized = true } @@ -492,12 +500,17 @@ final class PeerNameColorItemNode: ListViewItemNode, ItemListItemNode { let hasCorners = itemListHasRoundedBlockLayout(params) var hasTopCorners = false var hasBottomCorners = false - switch neighbors.top { + if item.currentColor != nil { + switch neighbors.top { case .sameSection(false): strongSelf.topStripeNode.isHidden = true default: hasTopCorners = true strongSelf.topStripeNode.isHidden = hasCorners + } + } else { + strongSelf.topStripeNode.isHidden = true + hasTopCorners = true } let bottomStripeInset: CGFloat let bottomStripeOffset: CGFloat @@ -531,10 +544,21 @@ final class PeerNameColorItemNode: ListViewItemNode, ItemListItemNode { var entries: [PeerNameColorEntry] = [] + let displayOrder: [Int32] + if item.isProfile { + displayOrder = item.colors.profileDisplayOrder + } else { + displayOrder = item.colors.displayOrder + } var i: Int = 0 - for index in item.colors.displayOrder { + for index in displayOrder { let color = PeerNameColor(rawValue: index) - let colors = item.colors.get(color, dark: item.theme.overallDarkAppearance) + let colors: PeerNameColors.Colors + if item.isProfile { + colors = item.colors.getProfile(color, dark: item.theme.overallDarkAppearance) + } else { + colors = item.colors.get(color, dark: item.theme.overallDarkAppearance) + } entries.append(.color(i, color, colors, item.theme.overallDarkAppearance, color == item.currentColor)) i += 1 diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorProfilePreviewItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorProfilePreviewItem.swift new file mode 100644 index 0000000000..746de029ae --- /dev/null +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorProfilePreviewItem.swift @@ -0,0 +1,274 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import SwiftSignalKit +import TelegramCore +import Postbox +import TelegramPresentationData +import TelegramUIPreferences +import ItemListUI +import PresentationDataUtils +import AccountContext +import ComponentFlow +import PeerInfoCoverComponent +import AvatarNode +import EmojiStatusComponent + +final class PeerNameColorProfilePreviewItem: ListViewItem, ItemListItem { + let context: AccountContext + let theme: PresentationTheme + let componentTheme: PresentationTheme + let strings: PresentationStrings + let sectionId: ItemListSectionId + let peer: EnginePeer? + let nameDisplayOrder: PresentationPersonNameOrder + + init(context: AccountContext, theme: PresentationTheme, componentTheme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, peer: EnginePeer?, nameDisplayOrder: PresentationPersonNameOrder) { + self.context = context + self.theme = theme + self.componentTheme = componentTheme + self.strings = strings + self.sectionId = sectionId + self.peer = peer + self.nameDisplayOrder = nameDisplayOrder + } + + func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { + async { + let node = PeerNameColorProfilePreviewItemNode() + let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + + node.contentSize = layout.contentSize + node.insets = layout.insets + + Queue.mainQueue().async { + completion(node, { + return (nil, { _ in apply() }) + }) + } + } + } + + func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) { + Queue.mainQueue().async { + if let nodeValue = node() as? PeerNameColorProfilePreviewItemNode { + let makeLayout = nodeValue.asyncLayout() + + async { + let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + Queue.mainQueue().async { + completion(layout, { _ in + apply() + }) + } + } + } + } + } +} + +final class PeerNameColorProfilePreviewItemNode: ListViewItemNode { + private let background = ComponentView() + private let avatarNode: AvatarNode + private let title = ComponentView() + private let subtitle = ComponentView() + private var icon: ComponentView? + + private let topStripeNode: ASDisplayNode + private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode + + private var item: PeerNameColorProfilePreviewItem? + + init() { + self.topStripeNode = ASDisplayNode() + self.topStripeNode.isLayerBacked = true + + self.bottomStripeNode = ASDisplayNode() + self.bottomStripeNode.isLayerBacked = true + + self.maskNode = ASImageNode() + + let avatarFont = avatarPlaceholderFont(size: floor(100.0 * 16.0 / 37.0)) + self.avatarNode = AvatarNode(font: avatarFont) + + super.init(layerBacked: false, dynamicBounce: false) + + self.clipsToBounds = true + self.isUserInteractionEnabled = false + } + + deinit { + } + + func asyncLayout() -> (_ item: PeerNameColorProfilePreviewItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { + return { [weak self] item, params, neighbors in + let separatorHeight = UIScreenPixel + + let contentSize = CGSize(width: params.width, height: 210.0) + var insets = itemListNeighborsGroupedInsets(neighbors, params) + if params.width <= 320.0 { + insets.top = 0.0 + } + + let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) + let layoutSize = layout.size + + return (layout, { [weak self] in + guard let self else { + return + } + self.item = item + + self.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor + self.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor + + if self.topStripeNode.supernode == nil { + self.addSubnode(self.topStripeNode) + } + if self.bottomStripeNode.supernode == nil { + self.addSubnode(self.bottomStripeNode) + } + if self.maskNode.supernode == nil { + self.addSubnode(self.maskNode) + } + + let hasCorners = itemListHasRoundedBlockLayout(params) + var hasTopCorners = false + var hasBottomCorners = false + switch neighbors.top { + case .sameSection(false): + self.topStripeNode.isHidden = true + default: + hasTopCorners = true + self.topStripeNode.isHidden = hasCorners + } + let bottomStripeInset: CGFloat + let bottomStripeOffset: CGFloat + switch neighbors.bottom { + case .sameSection(false): + bottomStripeInset = 0.0 + bottomStripeOffset = -separatorHeight + self.bottomStripeNode.isHidden = item.peer?.profileColor == nil + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 + hasBottomCorners = true + self.bottomStripeNode.isHidden = hasCorners + } + + self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.componentTheme, top: hasTopCorners, bottom: hasBottomCorners) : nil + + let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + + let coverFrame = backgroundFrame.insetBy(dx: params.leftInset, dy: 0.0) + + let avatarSize: CGFloat = 104.0 + let avatarFrame = CGRect(origin: CGPoint(x: floor((coverFrame.width - avatarSize) * 0.5), y: coverFrame.minY + 24.0), size: CGSize(width: avatarSize, height: avatarSize)) + + let _ = self.background.update( + transition: .immediate, + component: AnyComponent(PeerInfoCoverComponent( + context: item.context, + peer: item.peer, + isDark: item.theme.overallDarkAppearance, + avatarCenter: avatarFrame.center, + avatarScale: 1.0, + avatarTransitionFraction: 0.0, + patternTransitionFraction: 0.0 + )), + environment: {}, + containerSize: coverFrame.size + ) + if let backgroundView = self.background.view { + if backgroundView.superview == nil { + backgroundView.clipsToBounds = true + self.view.insertSubview(backgroundView, at: 0) + } + backgroundView.frame = coverFrame + } + + let clipStyle: AvatarNodeClipStyle + switch item.peer { + case let .channel(channel) where channel.isForum: + clipStyle = .roundedRect + default: + clipStyle = .round + } + self.avatarNode.setPeer( + context: item.context, + theme: item.theme, + peer: item.peer, + clipStyle: clipStyle, + synchronousLoad: true, + displayDimensions: avatarFrame.size + ) + if self.avatarNode.supernode == nil { + self.addSubnode(self.avatarNode) + } + self.avatarNode.frame = avatarFrame.offsetBy(dx: coverFrame.minX, dy: coverFrame.minY) + + let backgroundColor: UIColor + let titleColor: UIColor + let subtitleColor: UIColor + if let peer = item.peer, let profileColor = peer.profileColor { + titleColor = .white + backgroundColor = item.context.peerNameColors.getProfile(profileColor).main + subtitleColor = UIColor(white: 1.0, alpha: 0.6).blitOver(backgroundColor.withMultiplied(hue: 1.0, saturation: 2.2, brightness: 1.5), alpha: 1.0) + } else { + titleColor = item.theme.list.itemPrimaryTextColor + subtitleColor = item.theme.list.itemSecondaryTextColor + backgroundColor = .clear + } + + let titleString: String = item.peer?.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) ?? " " + let titleSize = self.title.update( + transition: .immediate, + component: AnyComponent(Text( + text: titleString, font: Font.semibold(28.0), color: titleColor + )), + environment: {}, + containerSize: CGSize(width: coverFrame.width - 16.0, height: 100.0) + ) + let titleFrame = CGRect(origin: CGPoint(x: coverFrame.minX + floor((coverFrame.width - titleSize.width) * 0.5), y: avatarFrame.maxY + 10.0), size: titleSize) + if let titleView = self.title.view { + if titleView.superview == nil { + self.view.addSubview(titleView) + } + titleView.frame = titleFrame + } + + //TODO:localize + let subtitleString: String = "last seen just now" + let subtitleSize = self.subtitle.update( + transition: .immediate, + component: AnyComponent(Text( + text: subtitleString, font: Font.regular(18.0), color: subtitleColor + )), + environment: {}, + containerSize: CGSize(width: coverFrame.width - 16.0, height: 100.0) + ) + let subtitleFrame = CGRect(origin: CGPoint(x: coverFrame.minX + floor((coverFrame.width - subtitleSize.width) * 0.5), y: titleFrame.maxY + 3.0), size: subtitleSize) + if let subtitleView = self.subtitle.view { + if subtitleView.superview == nil { + self.view.addSubview(subtitleView) + } + subtitleView.frame = subtitleFrame + } + + self.maskNode.frame = backgroundFrame.insetBy(dx: params.leftInset, dy: 0.0) + self.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) + self.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) + }) + } + } + + override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4) + } + + override func animateRemoved(_ currentTimestamp: Double, duration: Double) { + self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) + } +} diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreen.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreen.swift index 70e291a38e..247a552885 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreen.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreen.swift @@ -16,12 +16,12 @@ import PremiumUI private final class PeerNameColorScreenArguments { let context: AccountContext - let updateNameColor: (PeerNameColor) -> Void + let updateNameColor: (PeerNameColor?) -> Void let updateBackgroundEmojiId: (Int64?) -> Void init( context: AccountContext, - updateNameColor: @escaping (PeerNameColor) -> Void, + updateNameColor: @escaping (PeerNameColor?) -> Void, updateBackgroundEmojiId: @escaping (Int64?) -> Void ) { self.context = context @@ -39,7 +39,9 @@ private enum PeerNameColorScreenEntry: ItemListNodeEntry { enum StableId: Hashable { case colorHeader case colorMessage + case colorProfile case colorPicker + case removeColor case colorDescription case backgroundEmojiHeader case backgroundEmoji @@ -47,14 +49,16 @@ private enum PeerNameColorScreenEntry: ItemListNodeEntry { case colorHeader(String) case colorMessage(wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, items: [PeerNameColorChatPreviewItem.MessageItem]) - case colorPicker(colors: PeerNameColors, currentColor: PeerNameColor) + case colorProfile(peer: EnginePeer?, nameDisplayOrder: PresentationPersonNameOrder) + case colorPicker(colors: PeerNameColors, currentColor: PeerNameColor?, isProfile: Bool) + case removeColor case colorDescription(String) case backgroundEmojiHeader(String, String?) - case backgroundEmoji(EmojiPagerContentComponent, UIColor) + case backgroundEmoji(EmojiPagerContentComponent, UIColor, Bool, Bool) var section: ItemListSectionId { switch self { - case .colorHeader, .colorMessage, .colorPicker, .colorDescription: + case .colorHeader, .colorMessage, .colorProfile, .colorPicker, .removeColor, .colorDescription: return PeerNameColorScreenSection.nameColor.rawValue case .backgroundEmojiHeader, .backgroundEmoji: return PeerNameColorScreenSection.backgroundEmoji.rawValue @@ -67,8 +71,12 @@ private enum PeerNameColorScreenEntry: ItemListNodeEntry { return .colorHeader case .colorMessage: return .colorMessage + case .colorProfile: + return .colorProfile case .colorPicker: return .colorPicker + case .removeColor: + return.removeColor case .colorDescription: return .colorDescription case .backgroundEmojiHeader: @@ -84,14 +92,18 @@ private enum PeerNameColorScreenEntry: ItemListNodeEntry { return 0 case .colorMessage: return 1 - case .colorPicker: + case .colorProfile: return 2 - case .colorDescription: + case .colorPicker: return 3 - case .backgroundEmojiHeader: + case .removeColor: return 4 - case .backgroundEmoji: + case .colorDescription: return 5 + case .backgroundEmojiHeader: + return 6 + case .backgroundEmoji: + return 7 } } @@ -109,8 +121,26 @@ private enum PeerNameColorScreenEntry: ItemListNodeEntry { } else { return false } - case let .colorPicker(lhsColors, lhsCurrentColor): - if case let .colorPicker(rhsColors, rhsCurrentColor) = rhs, lhsColors == rhsColors, lhsCurrentColor == rhsCurrentColor { + case let .colorProfile(lhsPeer, lhsNameDisplayOrder): + if case let .colorProfile(rhsPeer, rhsNameDisplayOrder) = rhs { + if lhsPeer != rhsPeer { + return false + } + if lhsNameDisplayOrder != rhsNameDisplayOrder { + return false + } + return true + } else { + return false + } + case let .colorPicker(lhsColors, lhsCurrentColor, lhsIsProfile): + if case let .colorPicker(rhsColors, rhsCurrentColor, rhsIsProfile) = rhs, lhsColors == rhsColors, lhsCurrentColor == rhsCurrentColor, lhsIsProfile == rhsIsProfile { + return true + } else { + return false + } + case .removeColor: + if case .removeColor = rhs { return true } else { return false @@ -127,8 +157,8 @@ private enum PeerNameColorScreenEntry: ItemListNodeEntry { } else { return false } - case let .backgroundEmoji(lhsEmojiContent, lhsBackgroundIconColor): - if case let .backgroundEmoji(rhsEmojiContent, rhsBackgroundIconColor) = rhs, lhsEmojiContent == rhsEmojiContent, lhsBackgroundIconColor == rhsBackgroundIconColor { + case let .backgroundEmoji(lhsEmojiContent, lhsBackgroundIconColor, lhsIsProfile, lhsHasRemoveButton): + if case let .backgroundEmoji(rhsEmojiContent, rhsBackgroundIconColor, rhsIsProfile, rhsHasRemoveButton) = rhs, lhsEmojiContent == rhsEmojiContent, lhsBackgroundIconColor == rhsBackgroundIconColor, lhsIsProfile == rhsIsProfile, lhsHasRemoveButton == rhsHasRemoveButton { return true } else { return false @@ -157,25 +187,42 @@ private enum PeerNameColorScreenEntry: ItemListNodeEntry { wallpaper: wallpaper, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, - messageItems: items) - case let .colorPicker(colors, currentColor): + messageItems: items + ) + case let .colorProfile(peer, nameDisplayOrder): + return PeerNameColorProfilePreviewItem( + context: arguments.context, + theme: presentationData.theme, + componentTheme: presentationData.theme, + strings: presentationData.strings, + sectionId: self.section, + peer: peer, + nameDisplayOrder: nameDisplayOrder + ) + case let .colorPicker(colors, currentColor, isProfile): return PeerNameColorItem( theme: presentationData.theme, colors: colors, + isProfile: isProfile, currentColor: currentColor, updated: { color in arguments.updateNameColor(color) }, sectionId: self.section ) + case .removeColor: + //TODO:localize + return ItemListActionItem(presentationData: presentationData, title: "Reset Profile Color", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { + arguments.updateNameColor(nil) + }) case let .colorDescription(text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) case let .backgroundEmojiHeader(text, action): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, actionText: action, action: action != nil ? { arguments.updateBackgroundEmojiId(0) } : nil, sectionId: self.section) - case let .backgroundEmoji(emojiContent, backgroundIconColor): - return EmojiPickerItem(context: arguments.context, theme: presentationData.theme, strings: presentationData.strings, emojiContent: emojiContent, backgroundIconColor: backgroundIconColor, sectionId: self.section) + case let .backgroundEmoji(emojiContent, backgroundIconColor, isProfileColor, hasRemoveButton): + return EmojiPickerItem(context: arguments.context, theme: presentationData.theme, strings: presentationData.strings, emojiContent: emojiContent, backgroundIconColor: backgroundIconColor, isProfileColor: isProfileColor, hasRemoveButton: hasRemoveButton, sectionId: self.section) } } } @@ -185,6 +232,13 @@ private struct PeerNameColorScreenState: Equatable { var updatedBackgroundEmojiId: Int64? var inProgress: Bool = false var needsBoosts: Bool = false + + var updatedProfileColor: PeerNameColor? + var hasUpdatedProfileColor: Bool = false + var updatedProfileBackgroundEmojiId: Int64? + var hasUpdatedProfileBackgroundEmojiId: Bool = false + + var selectedTabIndex: Int = 0 } private func peerNameColorScreenEntries( @@ -222,6 +276,20 @@ private func peerNameColorScreenEntries( backgroundEmojiId = nil } + let profileColor: PeerNameColor? + if state.hasUpdatedProfileColor { + profileColor = state.updatedProfileColor + } else { + profileColor = peer.profileColor + } + var selectedProfileEmojiId: Int64? + if state.hasUpdatedProfileBackgroundEmojiId { + selectedProfileEmojiId = state.updatedProfileBackgroundEmojiId + } else { + selectedProfileEmojiId = peer.profileBackgroundEmojiId + } + let profileColors = profileColor.flatMap { profileColor in nameColors.getProfile(profileColor, dark: presentationData.theme.overallDarkAppearance) } + let replyText: String let messageText: String if case .channel = peer { @@ -242,27 +310,83 @@ private func peerNameColorScreenEntries( linkPreview: (presentationData.strings.NameColor_ChatPreview_LinkSite, presentationData.strings.NameColor_ChatPreview_LinkTitle, presentationData.strings.NameColor_ChatPreview_LinkText), text: messageText ) - entries.append(.colorMessage( - wallpaper: presentationData.chatWallpaper, - fontSize: presentationData.chatFontSize, - bubbleCorners: presentationData.chatBubbleCorners, - dateTimeFormat: presentationData.dateTimeFormat, - nameDisplayOrder: presentationData.nameDisplayOrder, - items: [messageItem] - )) - entries.append(.colorPicker( - colors: nameColors, - currentColor: nameColor - )) - if case .channel = peer { - entries.append(.colorDescription(presentationData.strings.NameColor_ChatPreview_Description_Channel)) + if state.selectedTabIndex == 0 { + entries.append(.colorMessage( + wallpaper: presentationData.chatWallpaper, + fontSize: presentationData.chatFontSize, + bubbleCorners: presentationData.chatBubbleCorners, + dateTimeFormat: presentationData.dateTimeFormat, + nameDisplayOrder: presentationData.nameDisplayOrder, + items: [messageItem] + )) } else { - entries.append(.colorDescription(presentationData.strings.NameColor_ChatPreview_Description_Account)) + var updatedPeer = peer + switch updatedPeer { + case let .user(user): + updatedPeer = .user(user.withUpdatedNameColor(nameColor).withUpdatedBackgroundEmojiId(backgroundEmojiId).withUpdatedProfileColor(profileColor).withUpdatedProfileBackgroundEmojiId(selectedProfileEmojiId)) + case let .channel(channel): + updatedPeer = .channel(channel.withUpdatedNameColor(nameColor).withUpdatedBackgroundEmojiId(backgroundEmojiId).withUpdatedProfileColor(profileColor).withUpdatedProfileBackgroundEmojiId(selectedProfileEmojiId)) + default: + break + } + entries.append(.colorProfile( + peer: updatedPeer, + nameDisplayOrder: presentationData.nameDisplayOrder + )) + } + if state.selectedTabIndex == 0 { + entries.append(.colorPicker( + colors: nameColors, + currentColor: nameColor, + isProfile: false + )) + } else { + entries.append(.colorPicker( + colors: nameColors, + currentColor: profileColor, + isProfile: true + )) + } + if state.selectedTabIndex == 1 && profileColor != nil { + entries.append(.removeColor) } - if let emojiContent { - entries.append(.backgroundEmojiHeader(presentationData.strings.NameColor_BackgroundEmoji_Title, backgroundEmojiId != nil ? presentationData.strings.NameColor_BackgroundEmoji_Remove : nil)) - entries.append(.backgroundEmoji(emojiContent, colors.main)) + if state.selectedTabIndex == 0 { + if case .channel = peer { + entries.append(.colorDescription(presentationData.strings.NameColor_ChatPreview_Description_Channel)) + } else { + entries.append(.colorDescription(presentationData.strings.NameColor_ChatPreview_Description_Account)) + } + + if let emojiContent { + var selectedItems = Set() + if let backgroundEmojiId { + selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: backgroundEmojiId)) + } + let emojiContent = emojiContent.withSelectedItems(selectedItems).withCustomTintColor(colors.main) + + entries.append(.backgroundEmojiHeader(presentationData.strings.NameColor_BackgroundEmoji_Title, (backgroundEmojiId != nil && backgroundEmojiId != 0) ? presentationData.strings.NameColor_BackgroundEmoji_Remove : nil)) + entries.append(.backgroundEmoji(emojiContent, colors.main, false, false)) + } + } else { + if let emojiContent, profileColors != nil { + var selectedItems = Set() + if let selectedProfileEmojiId { + selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: selectedProfileEmojiId)) + } + let emojiContent = emojiContent.withSelectedItems(selectedItems).withCustomTintColor(profileColors?.main) + + //TODO:localize + entries.append(.backgroundEmojiHeader("ADD ICON TO PROFILE", (selectedProfileEmojiId != nil && selectedProfileEmojiId != 0) ? presentationData.strings.NameColor_BackgroundEmoji_Remove : nil)) + entries.append(.backgroundEmoji(emojiContent, profileColors?.main ?? presentationData.theme.list.itemSecondaryTextColor, true, profileColor != nil)) + } else { + //TODO:localize + if case .channel = peer { + entries.append(.colorDescription("Choose a color for channel's profile")) + } else { + entries.append(.colorDescription("Choose a color for your profile")) + } + } } } @@ -300,14 +424,27 @@ public func PeerNameColorScreen( updateNameColor: { color in updateState { state in var updatedState = state - updatedState.updatedNameColor = color + + if state.selectedTabIndex == 0 { + if let color { + updatedState.updatedNameColor = color + } + } else { + updatedState.updatedProfileColor = color + updatedState.hasUpdatedProfileColor = true + } return updatedState } }, updateBackgroundEmojiId: { emojiId in updateState { state in var updatedState = state - updatedState.updatedBackgroundEmojiId = emojiId + if state.selectedTabIndex == 0 { + updatedState.updatedBackgroundEmojiId = emojiId + } else { + updatedState.hasUpdatedProfileBackgroundEmojiId = true + updatedState.updatedProfileBackgroundEmojiId = emojiId + } return updatedState } } @@ -321,12 +458,24 @@ public func PeerNameColorScreen( peerId = channelId } - let emojiContent = combineLatest( - context.sharedContext.presentationData, - statePromise.get(), - context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + let emojiContent = EmojiPagerContentComponent.emojiInputData( + context: context, + animationCache: context.animationCache, + animationRenderer: context.animationRenderer, + isStandalone: false, + subject: .backgroundIcon, + hasTrending: false, + topReactionItems: [], + areUnicodeEmojiEnabled: false, + areCustomEmojiEnabled: true, + chatPeerId: context.account.peerId, + selectedItems: Set(), + backgroundIconColor: nil ) - |> mapToSignal { presentationData, state, peer -> Signal in + /*let emojiContent: Signal = combineLatest( + context.sharedContext.presentationData + ) + |> mapToSignal { presentationData, state, peer -> Signal<(EmojiPagerContentComponent, EmojiPagerContentComponent), NoError> in var selectedEmojiId: Int64? if let updatedBackgroundEmojiId = state.updatedBackgroundEmojiId { selectedEmojiId = updatedBackgroundEmojiId @@ -339,7 +488,22 @@ public func PeerNameColorScreen( } else { nameColor = (peer?.nameColor ?? .blue) } + + var selectedProfileEmojiId: Int64? + if state.hasUpdatedProfileBackgroundEmojiId { + selectedProfileEmojiId = state.updatedProfileBackgroundEmojiId + } else { + selectedProfileEmojiId = peer?.profileBackgroundEmojiId + } + let profileColor: PeerNameColor? + if state.hasUpdatedProfileColor { + profileColor = state.updatedProfileColor + } else { + profileColor = peer?.profileColor + } + let color = context.peerNameColors.get(nameColor, dark: presentationData.theme.overallDarkAppearance) + let profileColorValue: UIColor? = profileColor.flatMap { profileColor in context.peerNameColors.getProfile(profileColor, dark: presentationData.theme.overallDarkAppearance).main } let selectedItems: [EngineMedia.Id] if let selectedEmojiId, selectedEmojiId != 0 { @@ -348,21 +512,13 @@ public func PeerNameColorScreen( selectedItems = [] } - return EmojiPagerContentComponent.emojiInputData( - context: context, - animationCache: context.animationCache, - animationRenderer: context.animationRenderer, - isStandalone: false, - subject: .backgroundIcon, - hasTrending: false, - topReactionItems: [], - areUnicodeEmojiEnabled: false, - areCustomEmojiEnabled: true, - chatPeerId: context.account.peerId, - selectedItems: Set(selectedItems), - backgroundIconColor: color.main - ) - } + let selectedProfileItems: [EngineMedia.Id] + if let selectedProfileEmojiId, selectedProfileEmojiId != 0 { + selectedProfileItems = [EngineMedia.Id(namespace: Namespaces.Media.CloudFile, id: selectedProfileEmojiId)] + } else { + selectedProfileItems = [] + } + }*/ let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData let signal = combineLatest(queue: .mainQueue(), @@ -375,17 +531,15 @@ public func PeerNameColorScreen( |> deliverOnMainQueue |> map { presentationData, state, availableReactions, peer, emojiContent -> (ItemListControllerState, (ItemListNodeState, Any)) in let isPremium = peer?.isPremium ?? false - let title: String let buttonTitle: String let isLocked: Bool switch subject { case .account: - title = presentationData.strings.NameColor_Title_Account isLocked = !isPremium case .channel: - title = presentationData.strings.NameColor_Title_Channel isLocked = false } + let _ = isLocked let backgroundEmojiId: Int64 if let updatedBackgroundEmojiId = state.updatedBackgroundEmojiId { @@ -400,8 +554,9 @@ public func PeerNameColorScreen( } else { buttonTitle = presentationData.strings.NameColor_ApplyColor } + let _ = buttonTitle - let footerItem = ApplyColorFooterItem( + /*let footerItem = ApplyColorFooterItem( theme: presentationData.theme, title: buttonTitle, locked: isLocked, @@ -432,7 +587,7 @@ public func PeerNameColorScreen( presentImpl?(controller) } } - ) + )*/ emojiContent.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction( performItemAction: { _, item, _, _, _, _ in @@ -512,11 +667,37 @@ public func PeerNameColorScreen( emojiContent: emojiContent ) + //TODO:localize let controllerState = ItemListControllerState( presentationData: ItemListPresentationData(presentationData), - title: .text(title), + title: .sectionControl(["Name", "Profile"], state.selectedTabIndex), leftNavigationButton: nil, - rightNavigationButton: nil, + rightNavigationButton: ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: { + if !isLocked { + applyChangesImpl?() + } else { + HapticFeedback().impact(.light) + let controller = UndoOverlayController( + presentationData: presentationData, + content: .premiumPaywall( + title: nil, + text: presentationData.strings.NameColor_TooltipPremium_Account, + customUndoText: nil, + timeout: nil, + linkAction: nil + ), + elevatedLayout: false, + action: { action in + if case .info = action { + let controller = context.sharedContext.makePremiumIntroController(context: context, source: .nameColor, forceDark: false, dismissed: nil) + pushImpl?(controller) + } + return true + } + ) + presentImpl?(controller) + } + }), backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false ) @@ -524,7 +705,7 @@ public func PeerNameColorScreen( presentationData: ItemListPresentationData(presentationData), entries: entries, style: .blocks, - footerItem: footerItem, + footerItem: nil, animateChanges: false ) @@ -536,6 +717,13 @@ public func PeerNameColorScreen( let controller = ItemListController(context: context, state: signal) controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) + controller.titleControlValueChanged = { value in + updateState { state in + var state = state + state.selectedTabIndex = value + return state + } + } presentImpl = { [weak controller] c in guard let controller else { return @@ -596,7 +784,7 @@ public func PeerNameColorScreen( return } let state = stateValue.with { $0 } - if state.updatedNameColor == nil && state.updatedBackgroundEmojiId == nil { + if state.updatedNameColor == nil && state.updatedBackgroundEmojiId == nil && !state.hasUpdatedProfileColor && !state.hasUpdatedProfileBackgroundEmojiId { dismissImpl?() return } @@ -607,9 +795,12 @@ public func PeerNameColorScreen( let backgroundEmojiId = state.updatedBackgroundEmojiId ?? peer.backgroundEmojiId let colors = context.peerNameColors.get(nameColor ?? .blue, dark: presentationData.theme.overallDarkAppearance) + let profileColor = state.hasUpdatedProfileColor ? state.updatedProfileColor : peer.profileColor + let profileBackgroundEmojiId = state.hasUpdatedProfileBackgroundEmojiId ? state.updatedProfileBackgroundEmojiId : peer.profileBackgroundEmojiId + switch subject { case .account: - let _ = context.engine.accountData.updateNameColorAndEmoji(nameColor: nameColor ?? .blue, backgroundEmojiId: backgroundEmojiId ?? 0).startStandalone() + let _ = context.engine.accountData.updateNameColorAndEmoji(nameColor: nameColor ?? .blue, backgroundEmojiId: backgroundEmojiId ?? 0, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId ?? 0).startStandalone() if let navigationController = controller?.navigationController as? NavigationController { Queue.mainQueue().after(0.25) { @@ -627,7 +818,7 @@ public func PeerNameColorScreen( updatedState.inProgress = true return updatedState } - let _ = (context.engine.peers.updatePeerNameColorAndEmoji(peerId: peerId, nameColor: nameColor ?? .blue, backgroundEmojiId: backgroundEmojiId ?? 0) + let _ = (context.engine.peers.updatePeerNameColorAndEmoji(peerId: peerId, nameColor: nameColor ?? .blue, backgroundEmojiId: backgroundEmojiId ?? 0, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId ?? 0) |> deliverOnMainQueue).startStandalone(next: { }, error: { error in if case .channelBoostRequired = error { diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreenComponent.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreenComponent.swift new file mode 100644 index 0000000000..997b96aaa8 --- /dev/null +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreenComponent.swift @@ -0,0 +1,13 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import SwiftSignalKit +import Postbox +import TelegramCore +import TelegramPresentationData +import TelegramUIPreferences +import PresentationDataUtils +import AccountContext +import UndoUI + diff --git a/submodules/TelegramUI/Components/TabSelectorComponent/Sources/TabSelectorComponent.swift b/submodules/TelegramUI/Components/TabSelectorComponent/Sources/TabSelectorComponent.swift index c6fa45b0f2..d8d5e02e03 100644 --- a/submodules/TelegramUI/Components/TabSelectorComponent/Sources/TabSelectorComponent.swift +++ b/submodules/TelegramUI/Components/TabSelectorComponent/Sources/TabSelectorComponent.swift @@ -19,9 +19,11 @@ public final class TabSelectorComponent: Component { } public struct CustomLayout: Equatable { + public var font: UIFont public var spacing: CGFloat - public init(spacing: CGFloat) { + public init(font: UIFont, spacing: CGFloat) { + self.font = font self.spacing = spacing } } @@ -113,8 +115,8 @@ public final class TabSelectorComponent: Component { let spacing: CGFloat = component.customLayout?.spacing ?? 2.0 let itemFont: UIFont - if component.customLayout != nil { - itemFont = Font.medium(14.0) + if let customLayout = component.customLayout { + itemFont = customLayout.font } else { itemFont = Font.semibold(14.0) } diff --git a/submodules/TelegramUI/Images.xcassets/Navigation/BackArrow.imageset/BackArrow.svg b/submodules/TelegramUI/Images.xcassets/Navigation/BackArrow.imageset/BackArrow.svg new file mode 100644 index 0000000000..46caf41fd7 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Navigation/BackArrow.imageset/BackArrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/submodules/TelegramUI/Images.xcassets/Navigation/BackArrow.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Navigation/BackArrow.imageset/Contents.json new file mode 100644 index 0000000000..000c70dfaf --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Navigation/BackArrow.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "BackArrow.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Navigation/Contents.json b/submodules/TelegramUI/Images.xcassets/Navigation/Contents.json new file mode 100644 index 0000000000..6e965652df --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Navigation/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index 75737a2d13..03b5f310a5 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -348,6 +348,7 @@ private func extractAccountManagerState(records: AccountRecordsView