From ec0f8028aafc860c0bc906c09586314ef93178e9 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 18 Oct 2023 03:34:47 +0400 Subject: [PATCH] Various improvements --- .../Sources/AccountContext.swift | 4 +- .../ContactMultiselectionController.swift | 1 + .../Sources/AnimatedAvatarSetNode.swift | 4 +- .../AvatarNode/Sources/PeerAvatar.swift | 10 ++- .../Sources/ContactListNode.swift | 64 +++++++++++++------ .../Sources/ContactsSearchContainerNode.swift | 27 ++++++++ .../Sources/CreateGiveawayController.swift | 33 +++++++--- .../Sources/PremiumGiftCodeScreen.swift | 28 ++++---- .../Sources/State/ChannelBoost.swift | 2 +- .../State/UserLimitsConfiguration.swift | 5 ++ .../Data/ConfigurationData.swift | 4 ++ .../Sources/TelegramIntents.swift | 2 +- .../CameraScreen/Sources/CameraScreen.swift | 1 + .../ChatMessagePollBubbleContentNode.swift | 10 +-- .../Sources/ItemListDatePickerItem.swift | 16 ++++- .../PeerNameColorChatPreviewItem.swift | 15 ++++- .../Sources/PeerNameColorItem.swift | 2 + .../Sources/PeerNameColorScreen.swift | 1 + .../TelegramUI/Sources/ChatController.swift | 8 +-- .../ChatInterfaceStateContextMenus.swift | 22 ++++--- .../Sources/ContactSelectionController.swift | 4 +- .../ContactSelectionControllerNode.swift | 13 +++- .../Sources/PeerInfo/PeerInfoScreen.swift | 2 +- 23 files changed, 199 insertions(+), 79 deletions(-) diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index d3babbae12..92ea81b2b9 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -663,9 +663,10 @@ public final class ContactSelectionControllerParams { public let displayDeviceContacts: Bool public let displayCallIcons: Bool public let multipleSelection: Bool + public let requirePhoneNumbers: Bool public let confirmation: (ContactListPeer) -> Signal - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, autoDismiss: Bool = true, title: @escaping (PresentationStrings) -> String, options: [ContactListAdditionalOption] = [], displayDeviceContacts: Bool = false, displayCallIcons: Bool = false, multipleSelection: Bool = false, confirmation: @escaping (ContactListPeer) -> Signal = { _ in .single(true) }) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, autoDismiss: Bool = true, title: @escaping (PresentationStrings) -> String, options: [ContactListAdditionalOption] = [], displayDeviceContacts: Bool = false, displayCallIcons: Bool = false, multipleSelection: Bool = false, requirePhoneNumbers: Bool = false, confirmation: @escaping (ContactListPeer) -> Signal = { _ in .single(true) }) { self.context = context self.updatedPresentationData = updatedPresentationData self.autoDismiss = autoDismiss @@ -674,6 +675,7 @@ public final class ContactSelectionControllerParams { self.displayDeviceContacts = displayDeviceContacts self.displayCallIcons = displayCallIcons self.multipleSelection = multipleSelection + self.requirePhoneNumbers = requirePhoneNumbers self.confirmation = confirmation } } diff --git a/submodules/AccountContext/Sources/ContactMultiselectionController.swift b/submodules/AccountContext/Sources/ContactMultiselectionController.swift index 11cd6c8fca..f1bb36cc4e 100644 --- a/submodules/AccountContext/Sources/ContactMultiselectionController.swift +++ b/submodules/AccountContext/Sources/ContactMultiselectionController.swift @@ -72,6 +72,7 @@ public enum ContactMultiselectionControllerMode { } public enum ContactListFilter { + case excludeWithoutPhoneNumbers case excludeSelf case exclude([EnginePeer.Id]) case disable([EnginePeer.Id]) diff --git a/submodules/AnimatedAvatarSetNode/Sources/AnimatedAvatarSetNode.swift b/submodules/AnimatedAvatarSetNode/Sources/AnimatedAvatarSetNode.swift index a4e45e33d7..cb7ce1554a 100644 --- a/submodules/AnimatedAvatarSetNode/Sources/AnimatedAvatarSetNode.swift +++ b/submodules/AnimatedAvatarSetNode/Sources/AnimatedAvatarSetNode.swift @@ -113,7 +113,7 @@ private final class ContentNode: ASDisplayNode { } else { let image = generateImage(size, rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - drawPeerAvatarLetters(context: context, size: size, font: avatarFont, letters: peer.displayLetters, peerId: peer.id) + drawPeerAvatarLetters(context: context, size: size, font: avatarFont, letters: peer.displayLetters, peerId: peer.id, nameColor: peer.nameColor) })! self.updateImage(image: image, size: size, spacing: spacing) } @@ -346,7 +346,7 @@ public final class AnimatedAvatarSetView: UIView { } else { let image = generateImage(size, rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - drawPeerAvatarLetters(context: context, size: size, font: avatarFont, letters: peer.displayLetters, peerId: peer.id) + drawPeerAvatarLetters(context: context, size: size, font: avatarFont, letters: peer.displayLetters, peerId: peer.id, nameColor: peer.nameColor) })! self.updateImage(image: image, size: size, spacing: spacing) } diff --git a/submodules/AvatarNode/Sources/PeerAvatar.swift b/submodules/AvatarNode/Sources/PeerAvatar.swift index 618a8a20a3..1474e15460 100644 --- a/submodules/AvatarNode/Sources/PeerAvatar.swift +++ b/submodules/AvatarNode/Sources/PeerAvatar.swift @@ -156,7 +156,7 @@ public func peerAvatarCompleteImage(postbox: Postbox, network: Network, peer: En iconSignal = Signal { subscriber in let image = generateImage(size, rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - drawPeerAvatarLetters(context: context, size: CGSize(width: size.width, height: size.height), round: round, font: font, letters: displayLetters, peerId: peerId) + drawPeerAvatarLetters(context: context, size: CGSize(width: size.width, height: size.height), round: round, font: font, letters: displayLetters, peerId: peerId, nameColor: peer.nameColor) if blurred { context.setFillColor(UIColor(rgb: 0x000000, alpha: 0.5).cgColor) context.fill(CGRect(origin: CGPoint(), size: size)) @@ -346,7 +346,7 @@ public func peerAvatarImage(postbox: Postbox, network: Network, peerReference: P } } -public func drawPeerAvatarLetters(context: CGContext, size: CGSize, round: Bool = true, font: UIFont, letters: [String], peerId: EnginePeer.Id) { +public func drawPeerAvatarLetters(context: CGContext, size: CGSize, round: Bool = true, font: UIFont, letters: [String], peerId: EnginePeer.Id, nameColor: PeerNameColor?) { if round { context.beginPath() context.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: @@ -365,7 +365,11 @@ public func drawPeerAvatarLetters(context: CGContext, size: CGSize, round: Bool if colorIndex == -1 { colorsArray = AvatarNode.grayscaleColors.map(\.cgColor) as NSArray } else { - colorsArray = AvatarNode.gradientColors[colorIndex % AvatarNode.gradientColors.count].map(\.cgColor) as NSArray + var index = colorIndex % AvatarNode.gradientColors.count + if let nameColor { + index = Int(nameColor.rawValue) % AvatarNode.gradientColors.count + } + colorsArray = AvatarNode.gradientColors[index].map(\.cgColor) as NSArray } var locations: [CGFloat] = [1.0, 0.0] diff --git a/submodules/ContactListUI/Sources/ContactListNode.swift b/submodules/ContactListUI/Sources/ContactListNode.swift index 9bc2728322..d1cbb233b5 100644 --- a/submodules/ContactListUI/Sources/ContactListNode.swift +++ b/submodules/ContactListUI/Sources/ContactListNode.swift @@ -1085,15 +1085,18 @@ public final class ContactListNode: ASDisplayNode { var existingNormalizedPhoneNumbers = Set() var excludeSelf = false + var requirePhoneNumbers = false for filter in filters { switch filter { - case .excludeSelf: - excludeSelf = true - existingPeerIds.insert(context.account.peerId) - case let .exclude(peerIds): - existingPeerIds = existingPeerIds.union(peerIds) - case let .disable(peerIds): - disabledPeerIds = disabledPeerIds.union(peerIds) + case .excludeSelf: + excludeSelf = true + existingPeerIds.insert(context.account.peerId) + case let .exclude(peerIds): + existingPeerIds = existingPeerIds.union(peerIds) + case let .disable(peerIds): + disabledPeerIds = disabledPeerIds.union(peerIds) + case .excludeWithoutPhoneNumbers: + requirePhoneNumbers = true } } @@ -1127,8 +1130,13 @@ public final class ContactListNode: ASDisplayNode { } for peer in remotePeers.0 { let matches: Bool - if peer.peer is TelegramUser { - matches = true + if let user = peer.peer as? TelegramUser { + let phone = user.phone ?? "" + if requirePhoneNumbers && phone.isEmpty { + matches = false + } else { + matches = true + } } else if searchGroups || searchChannels { if peer.peer is TelegramGroup && searchGroups { matches = true @@ -1157,8 +1165,13 @@ public final class ContactListNode: ASDisplayNode { } for peer in remotePeers.1 { let matches: Bool - if peer.peer is TelegramUser { - matches = true + if let user = peer.peer as? TelegramUser { + let phone = user.phone ?? "" + if requirePhoneNumbers && phone.isEmpty { + matches = false + } else { + matches = true + } } else if searchGroups || searchChannels { if peer.peer is TelegramGroup { matches = searchGroups @@ -1270,23 +1283,32 @@ public final class ContactListNode: ASDisplayNode { } var existingPeerIds = Set() var disabledPeerIds = Set() + var requirePhoneNumbers = false for filter in filters { switch filter { - case .excludeSelf: - existingPeerIds.insert(context.account.peerId) - case let .exclude(peerIds): - existingPeerIds = existingPeerIds.union(peerIds) - case let .disable(peerIds): - disabledPeerIds = disabledPeerIds.union(peerIds) + case .excludeSelf: + existingPeerIds.insert(context.account.peerId) + case let .exclude(peerIds): + existingPeerIds = existingPeerIds.union(peerIds) + case let .disable(peerIds): + disabledPeerIds = disabledPeerIds.union(peerIds) + case .excludeWithoutPhoneNumbers: + requirePhoneNumbers = true } } peers = peers.filter { contact in switch contact { - case let .peer(peer, _, _): - return !existingPeerIds.contains(peer.id) - default: - return true + case let .peer(peer, _, _): + if requirePhoneNumbers, let user = peer as? TelegramUser { + let phone = user.phone ?? "" + if phone.isEmpty { + return false + } + } + return !existingPeerIds.contains(peer.id) + default: + return true } } diff --git a/submodules/ContactListUI/Sources/ContactsSearchContainerNode.swift b/submodules/ContactListUI/Sources/ContactsSearchContainerNode.swift index 3333f44ac5..90972a156b 100644 --- a/submodules/ContactListUI/Sources/ContactsSearchContainerNode.swift +++ b/submodules/ContactListUI/Sources/ContactsSearchContainerNode.swift @@ -322,6 +322,7 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo var entries: [ContactListSearchEntry] = [] var existingPeerIds = Set() var disabledPeerIds = Set() + var requirePhoneNumbers = false for filter in filters { switch filter { case .excludeSelf: @@ -330,6 +331,8 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo existingPeerIds = existingPeerIds.union(peerIds) case let .disable(peerIds): disabledPeerIds = disabledPeerIds.union(peerIds) + case .excludeWithoutPhoneNumbers: + requirePhoneNumbers = true } } var existingNormalizedPhoneNumbers = Set() @@ -338,6 +341,14 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo if existingPeerIds.contains(peer.id) { continue } + + if case let .user(user) = peer, requirePhoneNumbers { + let phone = user.phone ?? "" + if phone.isEmpty { + continue + } + } + existingPeerIds.insert(peer.id) var enabled = true if onlyWriteable { @@ -354,6 +365,14 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo if !(peer.peer is TelegramUser) { continue } + + if let user = peer.peer as? TelegramUser, requirePhoneNumbers { + let phone = user.phone ?? "" + if phone.isEmpty { + continue + } + } + if !existingPeerIds.contains(peer.peer.id) { existingPeerIds.insert(peer.peer.id) @@ -373,6 +392,14 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo if !(peer.peer is TelegramUser) { continue } + + if let user = peer.peer as? TelegramUser, requirePhoneNumbers { + let phone = user.phone ?? "" + if phone.isEmpty { + continue + } + } + if !existingPeerIds.contains(peer.peer.id) { existingPeerIds.insert(peer.peer.id) diff --git a/submodules/PremiumUI/Sources/CreateGiveawayController.swift b/submodules/PremiumUI/Sources/CreateGiveawayController.swift index 8c824cd475..99ac2390aa 100644 --- a/submodules/PremiumUI/Sources/CreateGiveawayController.swift +++ b/submodules/PremiumUI/Sources/CreateGiveawayController.swift @@ -94,7 +94,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry { case timeHeader(PresentationTheme, String) case timeExpiryDate(PresentationTheme, PresentationDateTimeFormat, Int32?, Bool) - case timeCustomPicker(PresentationTheme, PresentationDateTimeFormat, Int32?) + case timeCustomPicker(PresentationTheme, PresentationDateTimeFormat, Int32?, Int32?, Int32?) case timeInfo(PresentationTheme, String) case durationHeader(PresentationTheme, String) @@ -282,8 +282,8 @@ private enum CreateGiveawayEntry: ItemListNodeEntry { } else { return false } - case let .timeCustomPicker(lhsTheme, lhsDateTimeFormat, lhsDate): - if case let .timeCustomPicker(rhsTheme, rhsDateTimeFormat, rhsDate) = rhs, lhsTheme === rhsTheme, lhsDateTimeFormat == rhsDateTimeFormat, lhsDate == rhsDate { + case let .timeCustomPicker(lhsTheme, lhsDateTimeFormat, lhsDate, lhsMinDate, lhsMaxDate): + if case let .timeCustomPicker(rhsTheme, rhsDateTimeFormat, rhsDate, rhsMinDate, rhsMaxDate) = rhs, lhsTheme === rhsTheme, lhsDateTimeFormat == rhsDateTimeFormat, lhsDate == rhsDate, lhsMinDate == rhsMinDate, lhsMaxDate == rhsMaxDate { return true } else { return false @@ -450,8 +450,8 @@ private enum CreateGiveawayEntry: ItemListNodeEntry { } } }) - case let .timeCustomPicker(_, dateTimeFormat, date): - return ItemListDatePickerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, date: date, sectionId: self.section, style: .blocks, updated: { date in + case let .timeCustomPicker(_, dateTimeFormat, date, minDate, maxDate): + return ItemListDatePickerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, date: date, minDate: minDate, maxDate: maxDate, sectionId: self.section, style: .blocks, updated: { date in arguments.updateState({ state in var updatedState = state updatedState.time = date @@ -499,7 +499,18 @@ private struct PremiumGiftProduct: Equatable { } } -private func createGiveawayControllerEntries(peerId: EnginePeer.Id, subject: CreateGiveawaySubject, state: CreateGiveawayControllerState, presentationData: PresentationData, locale: Locale, peers: [EnginePeer.Id: EnginePeer], products: [PremiumGiftProduct], defaultPrice: (Int64, NSDecimalNumber)) -> [CreateGiveawayEntry] { +private func createGiveawayControllerEntries( + peerId: EnginePeer.Id, + subject: CreateGiveawaySubject, + state: CreateGiveawayControllerState, + presentationData: PresentationData, + locale: Locale, + peers: [EnginePeer.Id: EnginePeer], + products: [PremiumGiftProduct], + defaultPrice: (Int64, NSDecimalNumber), + minDate: Int32, + maxDate: Int32 +) -> [CreateGiveawayEntry] { var entries: [CreateGiveawayEntry] = [] switch subject { @@ -568,7 +579,7 @@ private func createGiveawayControllerEntries(peerId: EnginePeer.Id, subject: Cre entries.append(.timeHeader(presentationData.theme, "DATE WHEN GIVEAWAY ENDS".uppercased())) entries.append(.timeExpiryDate(presentationData.theme, presentationData.dateTimeFormat, state.time, state.pickingTimeLimit)) if state.pickingTimeLimit { - entries.append(.timeCustomPicker(presentationData.theme, presentationData.dateTimeFormat, state.time)) + entries.append(.timeCustomPicker(presentationData.theme, presentationData.dateTimeFormat, state.time, minDate, maxDate)) } entries.append(.timeInfo(presentationData.theme, "Choose when \(state.subscriptions) subscribers of your channel will be randomly selected to receive Telegram Premium.")) } @@ -657,7 +668,11 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio initialSubscriptions = 5 } - let expiryTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) + 86400 * 5 + let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) + let expiryTime = currentTime + 86400 * 3 + let minDate = currentTime + 60 * 10 + let maxDate = currentTime + context.userLimits.maxGiveawayPeriodSeconds + let initialState: CreateGiveawayControllerState = CreateGiveawayControllerState(mode: .giveaway, subscriptions: initialSubscriptions, channels: [], peers: [], countries: [], onlyNewEligible: false, time: expiryTime) let statePromise = ValuePromise(initialState, ignoreRepeated: true) @@ -801,7 +816,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(""), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: createGiveawayControllerEntries(peerId: peerId, subject: subject, state: state, presentationData: presentationData, locale: locale, peers: peers, products: products, defaultPrice: defaultPrice), style: .blocks, emptyStateItem: nil, headerItem: headerItem, footerItem: footerItem, crossfadeState: false, animateChanges: animateChanges) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: createGiveawayControllerEntries(peerId: peerId, subject: subject, state: state, presentationData: presentationData, locale: locale, peers: peers, products: products, defaultPrice: defaultPrice, minDate: minDate, maxDate: maxDate), style: .blocks, emptyStateItem: nil, headerItem: headerItem, footerItem: footerItem, crossfadeState: false, animateChanges: animateChanges) return (controllerState, (listState, arguments)) } diff --git a/submodules/PremiumUI/Sources/PremiumGiftCodeScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftCodeScreen.swift index bf12f9b14c..d8d847df35 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftCodeScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftCodeScreen.swift @@ -27,7 +27,7 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent { let context: AccountContext let giftCode: PremiumGiftCodeInfo let action: () -> Void - let cancel: () -> Void + let cancel: (Bool) -> Void let openPeer: (EnginePeer) -> Void let openMessage: (EngineMessage.Id) -> Void let copyLink: (String) -> Void @@ -37,7 +37,7 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent { context: AccountContext, giftCode: PremiumGiftCodeInfo, action: @escaping () -> Void, - cancel: @escaping () -> Void, + cancel: @escaping (Bool) -> Void, openPeer: @escaping (EnginePeer) -> Void, openMessage: @escaping (EngineMessage.Id) -> Void, copyLink: @escaping (String) -> Void, @@ -149,7 +149,7 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent { component: Button( content: AnyComponent(Image(image: closeImage)), action: { [weak component] in - component?.cancel() + component?.cancel(true) } ), availableSize: CGSize(width: 30.0, height: 30.0), @@ -240,8 +240,10 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent { content: AnyComponent(PeerCellComponent(context: context.component.context, textColor: tableLinkColor, peer: fromPeer)), action: { if let peer = fromPeer { - component.cancel() component.openPeer(peer) + Queue.mainQueue().after(1.0, { + component.cancel(false) + }) } } ) @@ -257,8 +259,10 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent { content: AnyComponent(PeerCellComponent(context: context.component.context, textColor: tableLinkColor, peer: toPeer)), action: { if let peer = toPeer { - component.cancel() component.openPeer(peer) + Queue.mainQueue().after(1.0, { + component.cancel(false) + }) } } ) @@ -301,10 +305,12 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent { content: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: giftReason, font: tableFont, textColor: giftCode.messageId != nil ? tableLinkColor : tableTextColor)))), isEnabled: true, action: { - component.cancel() if let messageId = giftCode.messageId { component.openMessage(messageId) } + Queue.mainQueue().after(1.0) { + component.cancel(true) + } } ) ) @@ -362,7 +368,7 @@ private final class PremiumGiftCodeSheetContent: CombinedComponent { iconPosition: .left, action: { if giftCode.isUsed { - component.cancel() + component.cancel(true) } else { component.action() } @@ -425,7 +431,6 @@ private final class PremiumGiftCodeSheetComponent: CombinedComponent { let context: AccountContext let giftCode: PremiumGiftCodeInfo let action: () -> Void - let cancel: () -> Void let openPeer: (EnginePeer) -> Void let openMessage: (EngineMessage.Id) -> Void let copyLink: (String) -> Void @@ -435,7 +440,6 @@ private final class PremiumGiftCodeSheetComponent: CombinedComponent { context: AccountContext, giftCode: PremiumGiftCodeInfo, action: @escaping () -> Void, - cancel: @escaping () -> Void, openPeer: @escaping (EnginePeer) -> Void, openMessage: @escaping (EngineMessage.Id) -> Void, copyLink: @escaping (String) -> Void, @@ -444,7 +448,6 @@ private final class PremiumGiftCodeSheetComponent: CombinedComponent { self.context = context self.giftCode = giftCode self.action = action - self.cancel = cancel self.openPeer = openPeer self.openMessage = openMessage self.copyLink = copyLink @@ -475,7 +478,7 @@ private final class PremiumGiftCodeSheetComponent: CombinedComponent { context: context.component.context, giftCode: context.component.giftCode, action: context.component.action, - cancel: { + cancel: { animate in animateOut.invoke(Action { _ in if let controller = controller() { controller.dismiss(completion: nil) @@ -535,7 +538,6 @@ public class PremiumGiftCodeScreen: ViewControllerComponentContainer { context: AccountContext, giftCode: PremiumGiftCodeInfo, forceDark: Bool = false, - cancel: @escaping () -> Void = {}, action: @escaping () -> Void, openPeer: @escaping (EnginePeer) -> Void = { _ in }, openMessage: @escaping (EngineMessage.Id) -> Void = { _ in }, @@ -544,7 +546,7 @@ public class PremiumGiftCodeScreen: ViewControllerComponentContainer { self.context = context var copyLinkImpl: ((String) -> Void)? - super.init(context: context, component: PremiumGiftCodeSheetComponent(context: context, giftCode: giftCode, action: action, cancel: cancel, openPeer: openPeer, openMessage: openMessage, copyLink: { link in + super.init(context: context, component: PremiumGiftCodeSheetComponent(context: context, giftCode: giftCode, action: action, openPeer: openPeer, openMessage: openMessage, copyLink: { link in copyLinkImpl?(link) }, shareLink: shareLink), navigationBarAppearance: .none, statusBarStyle: .ignore, theme: forceDark ? .dark : .default) diff --git a/submodules/TelegramCore/Sources/State/ChannelBoost.swift b/submodules/TelegramCore/Sources/State/ChannelBoost.swift index 571bbfbda7..85bf8efd56 100644 --- a/submodules/TelegramCore/Sources/State/ChannelBoost.swift +++ b/submodules/TelegramCore/Sources/State/ChannelBoost.swift @@ -49,7 +49,7 @@ public final class ChannelBoostStatus: Equatable { } func _internal_getChannelBoostStatus(account: Account, peerId: PeerId) -> Signal { - return .single(nil) + return .single(ChannelBoostStatus(level: 0, boosts: 0, currentLevelBoosts: 0, nextLevelBoosts: nil, premiumAudience: nil, url: "", prepaidGiveaways: [])) // return account.postbox.transaction { transaction -> Api.InputPeer? in // return transaction.getPeer(peerId).flatMap(apiInputPeer) // } diff --git a/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift b/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift index 5e694b3288..b5f99b7392 100644 --- a/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift +++ b/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift @@ -24,6 +24,7 @@ public struct UserLimitsConfiguration: Equatable { public let maxStoriesSuggestedReactions: Int32 public let maxGiveawayChannelsCount: Int32 public let maxGiveawayCountriesCount: Int32 + public let maxGiveawayPeriodSeconds: Int32 public let minChannelNameColorLevel: Int32 public static var defaultValue: UserLimitsConfiguration { @@ -50,6 +51,7 @@ public struct UserLimitsConfiguration: Equatable { maxStoriesSuggestedReactions: 1, maxGiveawayChannelsCount: 10, maxGiveawayCountriesCount: 10, + maxGiveawayPeriodSeconds: 86400 * 7, minChannelNameColorLevel: 10 ) } @@ -77,6 +79,7 @@ public struct UserLimitsConfiguration: Equatable { maxStoriesSuggestedReactions: Int32, maxGiveawayChannelsCount: Int32, maxGiveawayCountriesCount: Int32, + maxGiveawayPeriodSeconds: Int32, minChannelNameColorLevel: Int32 ) { self.maxPinnedChatCount = maxPinnedChatCount @@ -101,6 +104,7 @@ public struct UserLimitsConfiguration: Equatable { self.maxStoriesSuggestedReactions = maxStoriesSuggestedReactions self.maxGiveawayChannelsCount = maxGiveawayChannelsCount self.maxGiveawayCountriesCount = maxGiveawayCountriesCount + self.maxGiveawayPeriodSeconds = maxGiveawayPeriodSeconds self.minChannelNameColorLevel = minChannelNameColorLevel } } @@ -148,6 +152,7 @@ extension UserLimitsConfiguration { self.maxStoriesSuggestedReactions = getValue("stories_suggested_reactions_limit", orElse: defaultValue.maxStoriesMonthlyCount) self.maxGiveawayChannelsCount = getGeneralValue("giveaway_add_peers_max", orElse: defaultValue.maxGiveawayChannelsCount) self.maxGiveawayCountriesCount = getGeneralValue("giveaway_countries_max", orElse: defaultValue.maxGiveawayCountriesCount) + self.maxGiveawayPeriodSeconds = getGeneralValue("giveaway_period_max", orElse: defaultValue.maxGiveawayPeriodSeconds) self.minChannelNameColorLevel = getGeneralValue("channel_color_level_min", orElse: defaultValue.minChannelNameColorLevel) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift index 28fbfa9f38..ca16e2f12b 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift @@ -58,6 +58,7 @@ public enum EngineConfiguration { public let maxStoriesSuggestedReactions: Int32 public let maxGiveawayChannelsCount: Int32 public let maxGiveawayCountriesCount: Int32 + public let maxGiveawayPeriodSeconds: Int32 public let minChannelNameColorLevel: Int32 public static var defaultValue: UserLimits { @@ -87,6 +88,7 @@ public enum EngineConfiguration { maxStoriesSuggestedReactions: Int32, maxGiveawayChannelsCount: Int32, maxGiveawayCountriesCount: Int32, + maxGiveawayPeriodSeconds: Int32, minChannelNameColorLevel: Int32 ) { self.maxPinnedChatCount = maxPinnedChatCount @@ -111,6 +113,7 @@ public enum EngineConfiguration { self.maxStoriesSuggestedReactions = maxStoriesSuggestedReactions self.maxGiveawayChannelsCount = maxGiveawayChannelsCount self.maxGiveawayCountriesCount = maxGiveawayCountriesCount + self.maxGiveawayPeriodSeconds = maxGiveawayPeriodSeconds self.minChannelNameColorLevel = minChannelNameColorLevel } } @@ -171,6 +174,7 @@ public extension EngineConfiguration.UserLimits { maxStoriesSuggestedReactions: userLimitsConfiguration.maxStoriesSuggestedReactions, maxGiveawayChannelsCount: userLimitsConfiguration.maxGiveawayChannelsCount, maxGiveawayCountriesCount: userLimitsConfiguration.maxGiveawayCountriesCount, + maxGiveawayPeriodSeconds: userLimitsConfiguration.maxGiveawayPeriodSeconds, minChannelNameColorLevel: userLimitsConfiguration.minChannelNameColorLevel ) } diff --git a/submodules/TelegramIntents/Sources/TelegramIntents.swift b/submodules/TelegramIntents/Sources/TelegramIntents.swift index fb11b19cb6..f6a782d87c 100644 --- a/submodules/TelegramIntents/Sources/TelegramIntents.swift +++ b/submodules/TelegramIntents/Sources/TelegramIntents.swift @@ -151,7 +151,7 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou if let image = generateImage(size, rotatedContext: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - drawPeerAvatarLetters(context: context, size: CGSize(width: size.width, height: size.height), font: avatarFont, letters: peer.displayLetters, peerId: peer.id) + drawPeerAvatarLetters(context: context, size: CGSize(width: size.width, height: size.height), font: avatarFont, letters: peer.displayLetters, peerId: peer.id, nameColor: peer.nameColor) })?.withRenderingMode(.alwaysOriginal) { avatarImage = image } diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index eb0145a1d2..6df09dea53 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -771,6 +771,7 @@ private final class CameraScreenComponent: CombinedComponent { ) context.add(frontFlash .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0)) + .scale(1.5 - component.cameraState.flashTintSize * 0.5) .appear(.default(alpha: true)) .disappear(.default(alpha: true)) ) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessagePollBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessagePollBubbleContentNode.swift index bc4b21fc69..1588ba7d24 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessagePollBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessagePollBubbleContentNode.swift @@ -1708,12 +1708,12 @@ public class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { } private enum PeerAvatarReference: Equatable { - case letters(PeerId, [String]) + case letters(PeerId, PeerNameColor?, [String]) case image(PeerReference, TelegramMediaImageRepresentation) var peerId: PeerId { switch self { - case let .letters(value, _): + case let .letters(value, _, _): return value case let .image(value, _): return value.id @@ -1726,7 +1726,7 @@ private extension PeerAvatarReference { if let photo = peer.smallProfileImage, let peerReference = PeerReference(peer) { self = .image(peerReference, photo) } else { - self = .letters(peer.id, peer.displayLetters) + self = .letters(peer.id, peer.nameColor, peer.displayLetters) } } } @@ -1885,9 +1885,9 @@ public final class MergedAvatarsNode: ASDisplayNode { context.saveGState() switch parameters.peers[i] { - case let .letters(peerId, letters): + case let .letters(peerId, nameColor, letters): context.translateBy(x: currentX, y: 0.0) - drawPeerAvatarLetters(context: context, size: CGSize(width: mergedImageSize, height: mergedImageSize), font: avatarFont, letters: letters, peerId: peerId) + drawPeerAvatarLetters(context: context, size: CGSize(width: mergedImageSize, height: mergedImageSize), font: avatarFont, letters: letters, peerId: peerId, nameColor: nameColor) context.translateBy(x: -currentX, y: 0.0) case .image: if let image = parameters.images[parameters.peers[i].peerId] { diff --git a/submodules/TelegramUI/Components/ItemListDatePickerItem/Sources/ItemListDatePickerItem.swift b/submodules/TelegramUI/Components/ItemListDatePickerItem/Sources/ItemListDatePickerItem.swift index dec343cce6..4ea1972758 100644 --- a/submodules/TelegramUI/Components/ItemListDatePickerItem/Sources/ItemListDatePickerItem.swift +++ b/submodules/TelegramUI/Components/ItemListDatePickerItem/Sources/ItemListDatePickerItem.swift @@ -11,6 +11,8 @@ public class ItemListDatePickerItem: ListViewItem, ItemListItem { let presentationData: ItemListPresentationData let dateTimeFormat: PresentationDateTimeFormat let date: Int32? + let minDate: Int32? + let maxDate: Int32? public let sectionId: ItemListSectionId let style: ItemListStyle let updated: ((Int32) -> Void)? @@ -20,6 +22,8 @@ public class ItemListDatePickerItem: ListViewItem, ItemListItem { presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, date: Int32?, + minDate: Int32? = nil, + maxDate: Int32? = nil, sectionId: ItemListSectionId, style: ItemListStyle, updated: ((Int32) -> Void)?, @@ -28,6 +32,8 @@ public class ItemListDatePickerItem: ListViewItem, ItemListItem { self.presentationData = presentationData self.dateTimeFormat = dateTimeFormat self.date = date + self.minDate = minDate + self.maxDate = maxDate self.sectionId = sectionId self.style = style self.updated = updated @@ -223,7 +229,15 @@ public class ItemListDatePickerItemNode: ListViewItemNode, ItemListItemNode { strongSelf.item?.updated?(Int32(date.timeIntervalSince1970)) } - datePickerNode.minimumDate = Date() + if let minDate = item.minDate { + datePickerNode.minimumDate = Date(timeIntervalSince1970: TimeInterval(minDate)) + } else { + datePickerNode.minimumDate = Date() + } + if let maxDate = item.maxDate { + datePickerNode.maximumDate = Date(timeIntervalSince1970: TimeInterval(maxDate)) + } + datePickerNode.date = item.date.flatMap { Date(timeIntervalSince1970: TimeInterval($0)) } let datePickerSize = CGSize(width: width, height: contentSize.height) diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift index 3766da300f..6def45b01a 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorChatPreviewItem.swift @@ -164,6 +164,8 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { var currentBackgroundNode = self.backgroundNode + let currentItem = self.item + return { item, params, neighbors in if currentBackgroundNode == nil { currentBackgroundNode = createWallpaperBackgroundNode(context: item.context, forChatDisplay: false) @@ -214,7 +216,9 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { itemNode.frame = nodeFrame itemNode.isUserInteractionEnabled = false - apply(ListViewItemApply(isOnScreen: true)) + Queue.mainQueue().after(0.01) { + apply(ListViewItemApply(isOnScreen: true)) + } }) } } else { @@ -249,6 +253,15 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode { strongSelf.containerNode.frame = CGRect(origin: CGPoint(), size: contentSize) + if let currentItem, currentItem.messageItems.first?.nameColor != item.messageItems.first?.nameColor { + if let snapshot = strongSelf.view.snapshotView(afterScreenUpdates: false) { + strongSelf.view.addSubview(snapshot) + snapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in + snapshot.removeFromSuperview() + }) + } + } + strongSelf.messageNodes = nodes var topOffset: CGFloat = 4.0 for node in nodes { diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorItem.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorItem.swift index 6c4357b347..fbf7f17659 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorItem.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorItem.swift @@ -184,8 +184,10 @@ private final class PeerNameColorIconItemNode : ListViewItemNode { let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .easeInOut) : .immediate if selected { transition.updateTransformScale(node: self.fillNode, scale: 0.8) + transition.updateTransformScale(node: self.ringNode, scale: 1.0) } else { transition.updateTransformScale(node: self.fillNode, scale: 1.0) + transition.updateTransformScale(node: self.ringNode, scale: 0.99) } } diff --git a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreen.swift b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreen.swift index c004085599..5f10c6c242 100644 --- a/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreen.swift +++ b/submodules/TelegramUI/Components/Settings/PeerNameColorScreen/Sources/PeerNameColorScreen.swift @@ -336,6 +336,7 @@ public func PeerNameColorScreen( } dismissImpl?() } else { + HapticFeedback().error() let controller = UndoOverlayController( presentationData: presentationData, content: .premiumPaywall( diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index dbad588d76..6640cd546f 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -10958,7 +10958,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else { return } - strongSelf.presentAttachmentPremiumGift() + strongSelf.presentAttachmentMenu(subject: .gift) Queue.mainQueue().after(0.5) { let _ = ApplicationSpecificNotice.incrementDismissedPremiumGiftSuggestion(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peerId).startStandalone() } @@ -13389,10 +13389,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } - func presentAttachmentPremiumGift() { - self.presentAttachmentMenu(subject: .gift) - } - enum AttachMenuSubject { case `default` case edit(mediaOptions: MessageMediaEditingOptions, mediaReference: AnyMediaReference) @@ -13720,7 +13716,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let _ = currentLocationController.swap(controller) }) case .contact: - let contactsController = ContactSelectionControllerImpl(ContactSelectionControllerParams(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: { $0.Contacts_Title }, displayDeviceContacts: true, multipleSelection: true)) + let contactsController = ContactSelectionControllerImpl(ContactSelectionControllerParams(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: { $0.Contacts_Title }, displayDeviceContacts: true, multipleSelection: true, requirePhoneNumbers: true)) contactsController.presentScheduleTimePicker = { [weak self] completion in if let strongSelf = self { strongSelf.presentScheduleTimePicker(completion: completion) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index 6a4f1d8db8..a35a747c9f 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -1177,17 +1177,19 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState } } - for media in message.media { - if let file = media as? TelegramMediaFile { - if file.isMusic { - actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_SaveToFiles, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor) - }, action: { _, f in - controllerInteraction.saveMediaToFiles(message.id) - f(.default) - }))) + if !isCopyProtected { + for media in message.media { + if let file = media as? TelegramMediaFile { + if file.isMusic { + actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_SaveToFiles, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor) + }, action: { _, f in + controllerInteraction.saveMediaToFiles(message.id) + f(.default) + }))) + } + break } - break } } diff --git a/submodules/TelegramUI/Sources/ContactSelectionController.swift b/submodules/TelegramUI/Sources/ContactSelectionController.swift index 6acddae341..8fee5a2f58 100644 --- a/submodules/TelegramUI/Sources/ContactSelectionController.swift +++ b/submodules/TelegramUI/Sources/ContactSelectionController.swift @@ -37,6 +37,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController private let displayDeviceContacts: Bool private let displayCallIcons: Bool private let multipleSelection: Bool + private let requirePhoneNumbers: Bool private var _ready = Promise() override var ready: Promise { @@ -91,6 +92,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController self.displayCallIcons = params.displayCallIcons self.confirmation = params.confirmation self.multipleSelection = params.multipleSelection + self.requirePhoneNumbers = params.requirePhoneNumbers self.presentationData = params.updatedPresentationData?.initial ?? params.context.sharedContext.currentPresentationData.with { $0 } @@ -178,7 +180,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController } override func loadDisplayNode() { - self.displayNode = ContactSelectionControllerNode(context: self.context, presentationData: self.presentationData, options: self.options, displayDeviceContacts: self.displayDeviceContacts, displayCallIcons: self.displayCallIcons, multipleSelection: self.multipleSelection) + self.displayNode = ContactSelectionControllerNode(context: self.context, presentationData: self.presentationData, options: self.options, displayDeviceContacts: self.displayDeviceContacts, displayCallIcons: self.displayCallIcons, multipleSelection: self.multipleSelection, requirePhoneNumbers: self.requirePhoneNumbers) self._ready.set(self.contactsNode.contactListNode.ready) self.contactsNode.navigationBar = self.navigationBar diff --git a/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift b/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift index 3358677668..ad60e31dd4 100644 --- a/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/ContactSelectionControllerNode.swift @@ -23,6 +23,7 @@ final class ContactSelectionControllerNode: ASDisplayNode { private let displayDeviceContacts: Bool private let displayCallIcons: Bool + private let filters: [ContactListFilter] let contactListNode: ContactListNode private let dimNode: ASDisplayNode @@ -53,14 +54,20 @@ final class ContactSelectionControllerNode: ASDisplayNode { var searchContainerNode: ContactsSearchContainerNode? - init(context: AccountContext, presentationData: PresentationData, options: [ContactListAdditionalOption], displayDeviceContacts: Bool, displayCallIcons: Bool, multipleSelection: Bool) { + init(context: AccountContext, presentationData: PresentationData, options: [ContactListAdditionalOption], displayDeviceContacts: Bool, displayCallIcons: Bool, multipleSelection: Bool, requirePhoneNumbers: Bool) { self.context = context self.presentationData = presentationData self.displayDeviceContacts = displayDeviceContacts self.displayCallIcons = displayCallIcons + var filters: [ContactListFilter] = [.excludeSelf] + if requirePhoneNumbers { + filters.append(.excludeWithoutPhoneNumbers) + } + self.filters = filters + var contextActionImpl: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? - self.contactListNode = ContactListNode(context: context, updatedPresentationData: (presentationData, self.presentationDataPromise.get()), presentation: .single(.natural(options: options, includeChatList: false)), displayCallIcons: displayCallIcons, contextAction: multipleSelection ? { peer, node, gesture, _, _ in + self.contactListNode = ContactListNode(context: context, updatedPresentationData: (presentationData, self.presentationDataPromise.get()), presentation: .single(.natural(options: options, includeChatList: false)), filters: filters, displayCallIcons: displayCallIcons, contextAction: multipleSelection ? { peer, node, gesture, _, _ in contextActionImpl?(peer, node, gesture, nil) } : nil, multipleSelection: multipleSelection) @@ -186,7 +193,7 @@ final class ContactSelectionControllerNode: ASDisplayNode { categories.insert(.global) } - let searchContainerNode = ContactsSearchContainerNode(context: self.context, updatedPresentationData: (self.presentationData, self.presentationDataPromise.get()), onlyWriteable: false, categories: categories, addContact: nil, openPeer: { [weak self] peer in + let searchContainerNode = ContactsSearchContainerNode(context: self.context, updatedPresentationData: (self.presentationData, self.presentationDataPromise.get()), onlyWriteable: false, categories: categories, filters: self.filters, addContact: nil, openPeer: { [weak self] peer in if let strongSelf = self { var updated = false strongSelf.contactListNode.updateSelectionState { state -> ContactListNodeGroupSelectionState? in diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 61160180c1..f6b56f7676 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -10304,7 +10304,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc context.clear(CGRect(origin: CGPoint(), size: size)) context.translateBy(x: inset, y: inset) - drawPeerAvatarLetters(context: context, size: CGSize(width: size.width - inset * 2.0, height: size.height - inset * 2.0), font: avatarFont, letters: displayLetters, peerId: primary.1.id) + drawPeerAvatarLetters(context: context, size: CGSize(width: size.width - inset * 2.0, height: size.height - inset * 2.0), font: avatarFont, letters: displayLetters, peerId: primary.1.id, nameColor: primary.1.nameColor) })?.withRenderingMode(.alwaysOriginal) if let image = image { subscriber.putNext((image, image))