Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2023-11-22 03:24:44 +04:00
commit ac7d53ea52
68 changed files with 1624 additions and 527 deletions

View file

@ -1296,7 +1296,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: []
)
}
@ -1304,6 +1307,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
@ -1314,10 +1321,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 {
@ -1355,10 +1382,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
@ -1375,6 +1476,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
}
}

View file

@ -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

View file

@ -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

View file

@ -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)
})

View file

@ -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,

View file

@ -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 {

View file

@ -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 }) {

View file

@ -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
}
}

View file

@ -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

View file

@ -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)

View file

@ -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))
}

View file

@ -29,6 +29,8 @@ swift_library(
"//submodules/ManagedAnimationNode:ManagedAnimationNode",
"//submodules/AvatarNode",
"//submodules/TelegramCore",
"//submodules/ComponentFlow",
"//submodules/TelegramUI/Components/TabSelectorComponent",
],
visibility = [
"//visibility:public",

View file

@ -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<Empty>()
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)
}
}
}

View file

@ -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<PeerId, Peer>()
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

View file

@ -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 {

View file

@ -163,8 +163,8 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel
let otherPeerId = self.context.account.peerId
var peers = SimpleDictionary<PeerId, Peer>()
var messages = SimpleDictionary<MessageId, Message>()
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: [:])

View file

@ -145,7 +145,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode {
var peers = SimpleDictionary<PeerId, Peer>()
let messages = SimpleDictionary<MessageId, Message>()
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: [])

View file

@ -274,7 +274,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode {
var peers = SimpleDictionary<PeerId, Peer>()
let messages = SimpleDictionary<MessageId, Message>()
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

View file

@ -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<PeerId, Peer>()
var messages = SimpleDictionary<MessageId, Message>()
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: [:])

View file

@ -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<PeerId, Peer>()
var messages = SimpleDictionary<MessageId, Message>()
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] = []

View file

@ -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<PeerId, Peer>()
var messages = SimpleDictionary<MessageId, Message>()
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] = []

View file

@ -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))
}

View file

@ -1491,8 +1491,8 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
let otherPeerId = self.context.account.peerId
var peers = SimpleDictionary<PeerId, Peer>()
let messages = SimpleDictionary<MessageId, Message>()
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 = ""

View file

@ -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)
}

View file

@ -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)
}
}
}

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -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)
}
}

View file

@ -35,8 +35,8 @@ public extension TelegramEngine {
return _internal_updateAbout(account: self.account, about: about)
}
public func updateNameColorAndEmoji(nameColor: PeerNameColor, backgroundEmojiId: Int64?) -> Signal<Void, UpdateNameColorAndEmojiError> {
return _internal_updateNameColorAndEmoji(account: self.account, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId)
public func updateNameColorAndEmoji(nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal<Void, UpdateNameColorAndEmojiError> {
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<Never, NoError> {

View file

@ -51,13 +51,13 @@ public enum UpdateNameColorAndEmojiError {
case generic
}
func _internal_updateNameColorAndEmoji(account: Account, nameColor: PeerNameColor, backgroundEmojiId: Int64?) -> Signal<Void, UpdateNameColorAndEmojiError> {
func _internal_updateNameColorAndEmoji(account: Account, nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal<Void, UpdateNameColorAndEmojiError> {
let flags: Int32 = (1 << 0)
return account.postbox.transaction { transaction -> Signal<Peer, NoError> 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)

View file

@ -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
)
}

View file

@ -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 {

View file

@ -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<Void, UpdatePeerNameColorAndEmojiError> {
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<Void, UpdatePeerNameColorAndEmojiError> {
return _internal_updatePeerNameColorAndEmoji(account: self.account, peerId: peerId, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId)
}
public func getChatListPeers(filterPredicate: ChatListFilterPredicate) -> Signal<[EnginePeer], NoError> {

View file

@ -94,7 +94,7 @@ public enum UpdatePeerNameColorAndEmojiError {
case channelBoostRequired
}
func _internal_updatePeerNameColorAndEmoji(account: Account, peerId: EnginePeer.Id, nameColor: PeerNameColor, backgroundEmojiId: Int64?) -> Signal<Void, UpdatePeerNameColorAndEmojiError> {
func _internal_updatePeerNameColorAndEmoji(account: Account, peerId: EnginePeer.Id, nameColor: PeerNameColor, backgroundEmojiId: Int64?, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal<Void, UpdatePeerNameColorAndEmojiError> {
return account.postbox.transaction { transaction -> Signal<Void, UpdatePeerNameColorAndEmojiError> in
if let peer = transaction.getPeer(peerId) {
if let peer = peer as? TelegramChannel, let inputChannel = apiInputChannel(peer) {

View file

@ -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 {

View file

@ -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)
})
}

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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
}

View file

@ -2694,6 +2694,7 @@ public final class EmojiPagerContentComponent: Component {
public let emptySearchResults: EmptySearchResults?
public let enableLongPress: Bool
public let selectedItems: Set<MediaId>
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<MediaId>
selectedItems: Set<MediaId>,
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
)
}
}

View file

@ -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 {

View file

@ -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)
}

View file

@ -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
}

View file

@ -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)

View file

@ -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
}

View file

@ -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<Empty>, 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()))

View file

@ -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",

View file

@ -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)
}
}

View file

@ -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,

View file

@ -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<Empty>?
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<Empty>
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))

View file

@ -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
}
}

View file

@ -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

View file

@ -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)),

View file

@ -2256,7 +2256,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()
@ -3301,6 +3301,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)
@ -3353,7 +3355,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)
@ -3669,7 +3670,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:
@ -4015,11 +4015,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
}
@ -4030,7 +4034,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(),
@ -9977,11 +9981,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 {
@ -10017,6 +10022,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)
}
}
@ -10120,9 +10131,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)
@ -10143,7 +10152,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
), strings: baseNavigationBarPresentationData.strings)
controller.setNavigationBarPresentationData(navigationBarPresentationData, animated: animated)
}
}*/
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
@ -10310,6 +10319,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<PresentationData, NoError>)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool = false, hintGroupInCommon: PeerId? = nil, requestsContext: PeerInvitationImportersContext? = nil, forumTopicThread: ChatReplyThreadMessage? = nil) {
@ -10337,8 +10356,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,
@ -10346,6 +10365,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
@ -10557,8 +10578,6 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
}
}
self.setStatusBarStyle(.White, animated: false)
self.scrollToTop = { [weak self] in
self?.controllerNode.scrollToTop()
}
@ -11056,7 +11075,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 {
@ -11070,7 +11089,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 {
@ -11142,10 +11161,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)
}
}

View file

@ -26,6 +26,8 @@ swift_library(
"//submodules/SolidRoundedButtonNode",
"//submodules/AppBundle",
"//submodules/PremiumUI",
"//submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent",
"//submodules/AvatarNode",
],
visibility = [
"//visibility:public",

View file

@ -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

View file

@ -184,7 +184,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode {
var peers = SimpleDictionary<PeerId, Peer>()
var messages = SimpleDictionary<MessageId, Message>()
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

View file

@ -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

View file

@ -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<Void, NoError>?, (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<Empty>()
private let avatarNode: AvatarNode
private let title = ComponentView<Empty>()
private let subtitle = ComponentView<Empty>()
private var icon: ComponentView<Empty>?
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)
}
}

View file

@ -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<MediaId>()
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<MediaId>()
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<EmojiPagerContentComponent, NoError> in
/*let emojiContent: Signal<EmojiPagerContentComponent, NoError> = 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 {

View file

@ -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

View file

@ -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)
}

View file

@ -0,0 +1,3 @@
<svg width="9" height="16" viewBox="0 0 9 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 1L1 8L8 15" stroke="black" stroke-width="1.66" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 209 B

View file

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "BackArrow.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View file

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"provides-namespace" : true
}
}

View file

@ -348,6 +348,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
UIDevice.current.isBatteryMonitoringEnabled = true
}
let clearNotificationsManager = ClearNotificationsManager(getNotificationIds: { completion in
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().getDeliveredNotifications(completionHandler: { notifications in

View file

@ -251,7 +251,7 @@ private func pollResultsControllerEntries(presentationData: PresentationData, po
displayCount = Int(voterCount)
}
for peerIndex in 0 ..< displayCount {
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)
let peer = EngineRenderedPeer(peer: EnginePeer(fakeUser))
entries.append(.optionPeer(optionId: i, index: peerIndex, peer: peer, optionText: optionTextHeader, optionAdditionalText: optionAdditionalTextHeader, optionCount: voterCount, optionExpanded: false, opaqueIdentifier: option.opaqueIdentifier, shimmeringAlternation: peerIndex % 2, isFirstInOption: peerIndex == 0))
}