mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
46e203137a
commit
6730f7d2fb
@ -10773,3 +10773,26 @@ Sorry for the inconvenience.";
|
||||
"ChatList.PremiumXmasGiftText" = "Gift Telegram Premium for Christmas.";
|
||||
|
||||
"ReassignBoost.DescriptionWithLink" = "To boost **%1$@**, reassign a previous boost or [gift Telegram Premium]() to a friend to get **%2$@** additional boosts.";
|
||||
|
||||
"Channel.AdminLog.ChannelChangedNameColorAndIcon" = "%1$@ changed the channel name color and icon to %2$@ %3$@";
|
||||
"Channel.AdminLog.ChannelChangedNameColor" = "%1$@ changed the channel name color to %2$@";
|
||||
"Channel.AdminLog.ChannelChangedNameIcon" = "%1$@ changed the channel name icon to %2$@";
|
||||
|
||||
"Channel.AdminLog.ChannelChangedProfileColorAndIcon" = "%1$@ changed the channel profile color and icon to %2$@ %3$@";
|
||||
"Channel.AdminLog.ChannelChangedProfileColor" = "%1$@ changed the channel profile color to %2$@";
|
||||
"Channel.AdminLog.ChannelChangedProfileIcon" = "%1$@ changed the channel profile icon to %2$@";
|
||||
"Channel.AdminLog.ChannelRemovedProfileColorAndIcon" = "%1$@ changed the removed profile color and icon";
|
||||
"Channel.AdminLog.ChannelRemovedProfileColor" = "%1$@ removed profile color";
|
||||
"Channel.AdminLog.ChannelRemovedProfileIcon" = "%1$@ removed profile icon";
|
||||
|
||||
"Channel.AdminLog.ChannelUpdatedStatus" = "%1$@ changed the channel status to %2$@";
|
||||
"Channel.AdminLog.ChannelRemovedStatus" = "%1$@ removed the channel status";
|
||||
|
||||
"Channel.AdminLog.ChannelRemovedWallpaper" = "%1$@ removed wallpaper";
|
||||
|
||||
"Channel.AdminLog.ChannelChangedWallpaper" = "%1$@ set a new wallpaper";
|
||||
|
||||
"Channel.Appearance.UnsavedChangesAlertTitle" = "Unsaved Changes";
|
||||
"Channel.Appearance.UnsavedChangesAlertText" = "You have changed the channel appearance settings. Apply changes?";
|
||||
"Channel.Appearance.UnsavedChangesAlertDiscard" = "Discard";
|
||||
"Channel.Appearance.UnsavedChangesAlertApply" = "Apply";
|
||||
|
@ -1335,19 +1335,19 @@ public class PeerNameColors: Equatable {
|
||||
public let secondary: UIColor?
|
||||
public let tertiary: UIColor?
|
||||
|
||||
init(main: UIColor, secondary: UIColor?, tertiary: UIColor?) {
|
||||
public init(main: UIColor, secondary: UIColor?, tertiary: UIColor?) {
|
||||
self.main = main
|
||||
self.secondary = secondary
|
||||
self.tertiary = tertiary
|
||||
}
|
||||
|
||||
init(main: UIColor) {
|
||||
public init(main: UIColor) {
|
||||
self.main = main
|
||||
self.secondary = nil
|
||||
self.tertiary = nil
|
||||
}
|
||||
|
||||
init?(colors: [UIColor]) {
|
||||
public init?(colors: [UIColor]) {
|
||||
guard let first = colors.first else {
|
||||
return nil
|
||||
}
|
||||
|
@ -969,6 +969,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var avatarTimerBadge: AvatarBadgeView?
|
||||
let pinnedIconNode: ASImageNode
|
||||
var secretIconNode: ASImageNode?
|
||||
var verifiedIconView: ComponentHostView<Empty>?
|
||||
var verifiedIconComponent: EmojiStatusComponent?
|
||||
var credibilityIconView: ComponentHostView<Empty>?
|
||||
var credibilityIconComponent: EmojiStatusComponent?
|
||||
let mutedIconNode: ASImageNode
|
||||
@ -1152,6 +1154,14 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
self.textNode.visibilityRect = self.visibilityStatus ? CGRect.infinite : nil
|
||||
|
||||
if let verifiedIconView = self.verifiedIconView, let verifiedIconComponent = self.verifiedIconComponent {
|
||||
let _ = verifiedIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(verifiedIconComponent.withVisibleForAnimations(self.visibilityStatus)),
|
||||
environment: {},
|
||||
containerSize: verifiedIconView.bounds.size
|
||||
)
|
||||
}
|
||||
if let credibilityIconView = self.credibilityIconView, let credibilityIconComponent = self.credibilityIconComponent {
|
||||
let _ = credibilityIconView.update(
|
||||
transition: .immediate,
|
||||
@ -1761,6 +1771,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var currentPinnedIconImage: UIImage?
|
||||
var currentMutedIconImage: UIImage?
|
||||
var currentCredibilityIconContent: EmojiStatusComponent.Content?
|
||||
var currentVerifiedIconContent: EmojiStatusComponent.Content?
|
||||
var currentSecretIconImage: UIImage?
|
||||
var currentForwardedIcon: UIImage?
|
||||
var currentStoryIcon: UIImage?
|
||||
@ -2478,6 +2489,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
} else if peer.isFake {
|
||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
||||
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
||||
if case .channel = peer, peer.isVerified {
|
||||
currentVerifiedIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||
}
|
||||
|
||||
currentCredibilityIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
} else if peer.isVerified {
|
||||
currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||
@ -2494,6 +2509,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
} else if peer.isFake {
|
||||
currentCredibilityIconContent = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
||||
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
||||
if case .channel = peer, peer.isVerified {
|
||||
currentVerifiedIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||
}
|
||||
|
||||
currentCredibilityIconContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
} else if peer.isVerified {
|
||||
currentCredibilityIconContent = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||
@ -2505,7 +2524,24 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
if let currentSecretIconImage = currentSecretIconImage {
|
||||
titleIconsWidth += currentSecretIconImage.size.width + 2.0
|
||||
}
|
||||
if let currentCredibilityIconContent = currentCredibilityIconContent {
|
||||
|
||||
if let currentVerifiedIconContent {
|
||||
if titleIconsWidth.isZero {
|
||||
titleIconsWidth += 4.0
|
||||
} else {
|
||||
titleIconsWidth += 2.0
|
||||
}
|
||||
switch currentVerifiedIconContent {
|
||||
case let .text(_, string):
|
||||
let textString = NSAttributedString(string: string, font: Font.bold(10.0), textColor: .black, paragraphAlignment: .center)
|
||||
let stringRect = textString.boundingRect(with: CGSize(width: 100.0, height: 16.0), options: .usesLineFragmentOrigin, context: nil)
|
||||
titleIconsWidth += floor(stringRect.width) + 11.0
|
||||
default:
|
||||
titleIconsWidth += 8.0
|
||||
}
|
||||
}
|
||||
|
||||
if let currentCredibilityIconContent {
|
||||
if titleIconsWidth.isZero {
|
||||
titleIconsWidth += 4.0
|
||||
} else {
|
||||
@ -3556,7 +3592,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
lastLineRect = CGRect(origin: CGPoint(), size: titleLayout.size)
|
||||
}
|
||||
|
||||
if let currentCredibilityIconContent = currentCredibilityIconContent {
|
||||
if let currentCredibilityIconContent {
|
||||
let credibilityIconView: ComponentHostView<Empty>
|
||||
if let current = strongSelf.credibilityIconView {
|
||||
credibilityIconView = current
|
||||
@ -3589,6 +3625,39 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
credibilityIconView.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let currentVerifiedIconContent {
|
||||
let verifiedIconView: ComponentHostView<Empty>
|
||||
if let current = strongSelf.verifiedIconView {
|
||||
verifiedIconView = current
|
||||
} else {
|
||||
verifiedIconView = ComponentHostView<Empty>()
|
||||
strongSelf.verifiedIconView = verifiedIconView
|
||||
strongSelf.mainContentContainerNode.view.addSubview(verifiedIconView)
|
||||
}
|
||||
|
||||
let verifiedIconComponent = EmojiStatusComponent(
|
||||
context: item.context,
|
||||
animationCache: item.interaction.animationCache,
|
||||
animationRenderer: item.interaction.animationRenderer,
|
||||
content: currentVerifiedIconContent,
|
||||
isVisibleForAnimations: strongSelf.visibilityStatus && item.context.sharedContext.energyUsageSettings.loopEmoji,
|
||||
action: nil
|
||||
)
|
||||
strongSelf.verifiedIconComponent = verifiedIconComponent
|
||||
|
||||
let iconSize = verifiedIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(verifiedIconComponent),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 20.0, height: 20.0)
|
||||
)
|
||||
transition.updateFrame(view: verifiedIconView, frame: CGRect(origin: CGPoint(x: nextTitleIconOrigin, y: floorToScreenPixels(titleFrame.maxY - lastLineRect.height * 0.5 - iconSize.height / 2.0) - UIScreenPixel), size: iconSize))
|
||||
nextTitleIconOrigin += verifiedIconView.bounds.width + 4.0
|
||||
} else if let verifiedIconView = strongSelf.verifiedIconView {
|
||||
strongSelf.verifiedIconView = nil
|
||||
verifiedIconView.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let currentMutedIconImage = currentMutedIconImage {
|
||||
strongSelf.mutedIconNode.image = currentMutedIconImage
|
||||
strongSelf.mutedIconNode.isHidden = false
|
||||
|
@ -404,6 +404,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
private let titleNode: TextNode
|
||||
private var credibilityIconView: ComponentHostView<Empty>?
|
||||
private var credibilityIconComponent: EmojiStatusComponent?
|
||||
private var verifiedIconView: ComponentHostView<Empty>?
|
||||
private var verifiedIconComponent: EmojiStatusComponent?
|
||||
private let statusNode: TextNode
|
||||
private var statusIconNode: ASImageNode?
|
||||
private var badgeBackgroundNode: ASImageNode?
|
||||
@ -464,6 +466,14 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
containerSize: credibilityIconView.bounds.size
|
||||
)
|
||||
}
|
||||
if let verifiedIconView = self.verifiedIconView, let verifiedIconComponent = self.verifiedIconComponent {
|
||||
let _ = verifiedIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(verifiedIconComponent.withVisibleForAnimations(self.visibilityStatus)),
|
||||
environment: {},
|
||||
containerSize: verifiedIconView.bounds.size
|
||||
)
|
||||
}
|
||||
if let avatarIconView = self.avatarIconView, let avatarIconComponent = self.avatarIconComponent {
|
||||
let _ = avatarIconView.update(
|
||||
transition: .immediate,
|
||||
@ -692,6 +702,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||
|
||||
var credibilityIcon: EmojiStatusComponent.Content?
|
||||
var verifiedIcon: EmojiStatusComponent.Content?
|
||||
switch item.peer {
|
||||
case let .peer(peer, _):
|
||||
if let peer = peer, peer.id != item.context.account.peerId {
|
||||
@ -700,6 +711,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
} else if peer.isFake {
|
||||
credibilityIcon = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
||||
} else if let emojiStatus = peer.emojiStatus {
|
||||
if case .channel = peer, peer.isVerified {
|
||||
verifiedIcon = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||
}
|
||||
credibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
} else if peer.isVerified {
|
||||
credibilityIcon = .verified(fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||
@ -879,7 +893,18 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
var additionalTitleInset: CGFloat = 0.0
|
||||
if let credibilityIcon = credibilityIcon {
|
||||
if let verifiedIcon {
|
||||
additionalTitleInset += 3.0
|
||||
switch verifiedIcon {
|
||||
case let .text(_, string):
|
||||
let textString = NSAttributedString(string: string, font: Font.bold(10.0), textColor: .black, paragraphAlignment: .center)
|
||||
let stringRect = textString.boundingRect(with: CGSize(width: 100.0, height: 16.0), options: .usesLineFragmentOrigin, context: nil)
|
||||
additionalTitleInset += floor(stringRect.width) + 11.0
|
||||
default:
|
||||
additionalTitleInset += 16.0
|
||||
}
|
||||
}
|
||||
if let credibilityIcon {
|
||||
additionalTitleInset += 3.0
|
||||
switch credibilityIcon {
|
||||
case let .text(_, string):
|
||||
@ -1193,7 +1218,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
if let credibilityIcon = credibilityIcon {
|
||||
var nextIconX: CGFloat = titleFrame.maxX
|
||||
if let credibilityIcon {
|
||||
let animationCache = item.context.animationCache
|
||||
let animationRenderer = item.context.animationRenderer
|
||||
|
||||
@ -1224,12 +1250,53 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
containerSize: CGSize(width: 20.0, height: 20.0)
|
||||
)
|
||||
|
||||
transition.updateFrame(view: credibilityIconView, frame: CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: floorToScreenPixels(titleFrame.midY - iconSize.height / 2.0)), size: iconSize))
|
||||
nextIconX += 4.0
|
||||
transition.updateFrame(view: credibilityIconView, frame: CGRect(origin: CGPoint(x: nextIconX, y: floorToScreenPixels(titleFrame.midY - iconSize.height / 2.0)), size: iconSize))
|
||||
nextIconX += iconSize.width
|
||||
} else if let credibilityIconView = strongSelf.credibilityIconView {
|
||||
strongSelf.credibilityIconView = nil
|
||||
credibilityIconView.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let verifiedIcon {
|
||||
let animationCache = item.context.animationCache
|
||||
let animationRenderer = item.context.animationRenderer
|
||||
|
||||
let verifiedIconView: ComponentHostView<Empty>
|
||||
if let current = strongSelf.verifiedIconView {
|
||||
verifiedIconView = current
|
||||
} else {
|
||||
verifiedIconView = ComponentHostView<Empty>()
|
||||
strongSelf.offsetContainerNode.view.addSubview(verifiedIconView)
|
||||
strongSelf.verifiedIconView = verifiedIconView
|
||||
}
|
||||
|
||||
let verifiedIconComponent = EmojiStatusComponent(
|
||||
context: item.context,
|
||||
animationCache: animationCache,
|
||||
animationRenderer: animationRenderer,
|
||||
content: verifiedIcon,
|
||||
isVisibleForAnimations: strongSelf.visibilityStatus,
|
||||
action: nil,
|
||||
emojiFileUpdated: nil
|
||||
)
|
||||
strongSelf.verifiedIconComponent = verifiedIconComponent
|
||||
|
||||
let iconSize = verifiedIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(verifiedIconComponent),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 20.0, height: 20.0)
|
||||
)
|
||||
|
||||
nextIconX += 4.0
|
||||
transition.updateFrame(view: verifiedIconView, frame: CGRect(origin: CGPoint(x: nextIconX, y: floorToScreenPixels(titleFrame.midY - iconSize.height / 2.0)), size: iconSize))
|
||||
nextIconX += iconSize.width
|
||||
} else if let verifiedIconView = strongSelf.verifiedIconView {
|
||||
strongSelf.verifiedIconView = nil
|
||||
verifiedIconView.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let actionButtons = actionButtons {
|
||||
if strongSelf.actionButtonNodes == nil {
|
||||
var actionButtonNodes: [HighlightableButtonNode] = []
|
||||
@ -1430,11 +1497,19 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
self.statusNode.frame = statusFrame
|
||||
transition.animatePositionAdditive(node: self.statusNode, offset: CGPoint(x: previousStatusFrame.minX - statusFrame.minX, y: 0))
|
||||
|
||||
var nextIconX = titleFrame.maxX
|
||||
if let credibilityIconView = self.credibilityIconView {
|
||||
var iconFrame = credibilityIconView.frame
|
||||
iconFrame.origin.x = titleFrame.maxX + 4.0
|
||||
iconFrame.origin.x = nextIconX + 4.0
|
||||
nextIconX += 4.0 + iconFrame.width
|
||||
transition.updateFrame(view: credibilityIconView, frame: iconFrame)
|
||||
}
|
||||
if let verifiedIconView = self.verifiedIconView {
|
||||
var iconFrame = verifiedIconView.frame
|
||||
iconFrame.origin.x = nextIconX + 4.0
|
||||
nextIconX += 4.0 + iconFrame.width
|
||||
transition.updateFrame(view: verifiedIconView, frame: iconFrame)
|
||||
}
|
||||
|
||||
if let badgeBackgroundNode = self.badgeBackgroundNode, let badgeTextNode = self.badgeTextNode {
|
||||
var badgeBackgroundFrame = badgeBackgroundNode.frame
|
||||
|
@ -858,10 +858,10 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI
|
||||
|
||||
let previewText = groupLayouts.count > 1 ? presentationData.strings.Attachment_MessagesPreview : presentationData.strings.Attachment_MessagePreview
|
||||
|
||||
let previewMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: previewText, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let previewMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: previewText, entities: [], additionalAttributes: nil))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let previewItem = self.context.sharedContext.makeChatMessagePreviewItem(context: context, messages: [previewMessage], theme: theme, strings: presentationData.strings, wallpaper: wallpaper, fontSize: presentationData.chatFontSize, chatBubbleCorners: bubbleCorners, dateTimeFormat: presentationData.dateTimeFormat, nameOrder: presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.wallpaperBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: true)
|
||||
|
||||
let dragMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: presentationData.strings.Attachment_DragToReorder, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let dragMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: presentationData.strings.Attachment_DragToReorder, entities: [], additionalAttributes: nil))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let dragItem = self.context.sharedContext.makeChatMessagePreviewItem(context: context, messages: [dragMessage], theme: theme, strings: presentationData.strings, wallpaper: wallpaper, fontSize: presentationData.chatFontSize, chatBubbleCorners: bubbleCorners, dateTimeFormat: presentationData.dateTimeFormat, nameOrder: presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.wallpaperBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: true)
|
||||
|
||||
let headerItems: [ListViewItem] = [previewItem, dragItem]
|
||||
|
@ -1534,9 +1534,25 @@ final class HistoryViewLoadedState {
|
||||
author = updatedAuthor
|
||||
rebuild = true
|
||||
}
|
||||
var associatedMessages = message.associatedMessages
|
||||
for (id, associatedMessage) in message.associatedMessages {
|
||||
var peers = associatedMessage.peers
|
||||
var author = associatedMessage.author
|
||||
for (peerId, _) in associatedMessage.peers {
|
||||
if let updatedPeer = updatedPeers[peerId] {
|
||||
peers[peerId] = updatedPeer
|
||||
rebuild = true
|
||||
}
|
||||
}
|
||||
if let authorValue = author, let updatedAuthor = updatedPeers[authorValue.id] {
|
||||
author = updatedAuthor
|
||||
rebuild = true
|
||||
}
|
||||
associatedMessages[id] = associatedMessage.withUpdatedPeers(peers).withUpdatedAuthor(author)
|
||||
}
|
||||
|
||||
if rebuild {
|
||||
let updatedMessage = message.withUpdatedPeers(peers).withUpdatedAuthor(author)
|
||||
let updatedMessage = message.withUpdatedPeers(peers).withUpdatedAuthor(author).withUpdatedAssociatedMessages(associatedMessages)
|
||||
return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes), reloadAssociatedMessages: reloadAssociatedMessages, reloadPeers: reloadPeers)
|
||||
}
|
||||
case .IntermediateMessageEntry:
|
||||
|
@ -49,7 +49,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
||||
case .messageActionScreenshotTaken:
|
||||
return TelegramMediaAction(action: .historyScreenshot)
|
||||
case let .messageActionCustomAction(message):
|
||||
return TelegramMediaAction(action: .customText(text: message, entities: []))
|
||||
return TelegramMediaAction(action: .customText(text: message, entities: [], additionalAttributes: nil))
|
||||
case let .messageActionBotAllowed(flags, domain, app):
|
||||
if let domain = domain {
|
||||
return TelegramMediaAction(action: .botDomainAccessGranted(domain: domain))
|
||||
|
@ -1,4 +1,5 @@
|
||||
import Postbox
|
||||
import Foundation
|
||||
|
||||
public enum PhoneCallDiscardReason: Int32 {
|
||||
case missed = 0
|
||||
@ -73,6 +74,18 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct CustomTextAttributes: Equatable {
|
||||
public var attributes: [(NSRange, NSAttributedString.Key, Any)]
|
||||
|
||||
public init(attributes: [(NSRange, NSAttributedString.Key, Any)]) {
|
||||
self.attributes = attributes
|
||||
}
|
||||
|
||||
public static func ==(lhs: CustomTextAttributes, rhs: CustomTextAttributes) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case unknown
|
||||
case groupCreated(title: String)
|
||||
case addedMembers(peerIds: [PeerId])
|
||||
@ -89,7 +102,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
case gameScore(gameId: Int64, score: Int32)
|
||||
case phoneCall(callId: Int64, discardReason: PhoneCallDiscardReason?, duration: Int32?, isVideo: Bool)
|
||||
case paymentSent(currency: String, totalAmount: Int64, invoiceSlug: String?, isRecurringInit: Bool, isRecurringUsed: Bool)
|
||||
case customText(text: String, entities: [MessageTextEntity])
|
||||
case customText(text: String, entities: [MessageTextEntity], additionalAttributes: CustomTextAttributes?)
|
||||
case botDomainAccessGranted(domain: String)
|
||||
case botAppAccessGranted(appName: String?, type: BotSendMessageAccessGrantedType?)
|
||||
case botSentSecureValues(types: [SentSecureValueType])
|
||||
@ -152,7 +165,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
case 15:
|
||||
self = .paymentSent(currency: decoder.decodeStringForKey("currency", orElse: ""), totalAmount: decoder.decodeInt64ForKey("ta", orElse: 0), invoiceSlug: decoder.decodeOptionalStringForKey("invoiceSlug"), isRecurringInit: decoder.decodeBoolForKey("isRecurringInit", orElse: false), isRecurringUsed: decoder.decodeBoolForKey("isRecurringUsed", orElse: false))
|
||||
case 16:
|
||||
self = .customText(text: decoder.decodeStringForKey("text", orElse: ""), entities: decoder.decodeObjectArrayWithDecoderForKey("ent"))
|
||||
self = .customText(text: decoder.decodeStringForKey("text", orElse: ""), entities: decoder.decodeObjectArrayWithDecoderForKey("ent"), additionalAttributes: nil)
|
||||
case 17:
|
||||
self = .botDomainAccessGranted(domain: decoder.decodeStringForKey("do", orElse: ""))
|
||||
case 18:
|
||||
@ -298,7 +311,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
||||
encoder.encodeNil(forKey: "d")
|
||||
}
|
||||
encoder.encodeInt32(isVideo ? 1 : 0, forKey: "vc")
|
||||
case let .customText(text, entities):
|
||||
case let .customText(text, entities, _):
|
||||
encoder.encodeInt32(16, forKey: "_rawValue")
|
||||
encoder.encodeString(text, forKey: "text")
|
||||
encoder.encodeObjectArray(entities, forKey: "ent")
|
||||
|
@ -87,7 +87,10 @@ public enum AdminLogEventAction {
|
||||
case pinTopic(prevInfo: EngineMessageHistoryThread.Info?, newInfo: EngineMessageHistoryThread.Info?)
|
||||
case toggleForum(isForum: Bool)
|
||||
case toggleAntiSpam(isEnabled: Bool)
|
||||
case changeNameColor(prev: PeerNameColor, new: PeerNameColor)
|
||||
case changeNameColor(prevColor: PeerNameColor, prevIcon: Int64?, newColor: PeerNameColor, newIcon: Int64?)
|
||||
case changeProfileColor(prevColor: PeerNameColor?, prevIcon: Int64?, newColor: PeerNameColor?, newIcon: Int64?)
|
||||
case changeWallpaper(prev: TelegramWallpaper?, new: TelegramWallpaper?)
|
||||
case changeStatus(prev: PeerEmojiStatus?, new: PeerEmojiStatus?)
|
||||
}
|
||||
|
||||
public enum ChannelAdminLogEventError {
|
||||
@ -348,22 +351,69 @@ func channelAdminLogEvents(accountPeerId: PeerId, postbox: Postbox, network: Net
|
||||
case let .channelAdminLogEventActionToggleAntiSpam(newValue):
|
||||
action = .toggleAntiSpam(isEnabled: newValue == .boolTrue)
|
||||
case let .channelAdminLogEventActionChangePeerColor(prevValue, newValue):
|
||||
let _ = prevValue
|
||||
let _ = newValue
|
||||
action = nil
|
||||
// action = .changeNameColor(prev: PeerNameColor(rawValue: prevValue), new: PeerNameColor(rawValue: newValue))
|
||||
var prevColorIndex: Int32
|
||||
var prevEmojiId: Int64?
|
||||
switch prevValue {
|
||||
case let .peerColor(_, color, backgroundEmojiIdValue):
|
||||
prevColorIndex = color ?? 0
|
||||
prevEmojiId = backgroundEmojiIdValue
|
||||
}
|
||||
|
||||
var newColorIndex: Int32
|
||||
var newEmojiId: Int64?
|
||||
switch newValue {
|
||||
case let .peerColor(_, color, backgroundEmojiIdValue):
|
||||
newColorIndex = color ?? 0
|
||||
newEmojiId = backgroundEmojiIdValue
|
||||
}
|
||||
|
||||
action = .changeNameColor(prevColor: PeerNameColor(rawValue: prevColorIndex), prevIcon: prevEmojiId, newColor: PeerNameColor(rawValue: newColorIndex), newIcon: newEmojiId)
|
||||
case let .channelAdminLogEventActionChangeProfilePeerColor(prevValue, newValue):
|
||||
let _ = prevValue
|
||||
let _ = newValue
|
||||
action = nil
|
||||
var prevColorIndex: Int32?
|
||||
var prevEmojiId: Int64?
|
||||
switch prevValue {
|
||||
case let .peerColor(_, color, backgroundEmojiIdValue):
|
||||
prevColorIndex = color
|
||||
prevEmojiId = backgroundEmojiIdValue
|
||||
}
|
||||
|
||||
var newColorIndex: Int32?
|
||||
var newEmojiId: Int64?
|
||||
switch newValue {
|
||||
case let .peerColor(_, color, backgroundEmojiIdValue):
|
||||
newColorIndex = color
|
||||
newEmojiId = backgroundEmojiIdValue
|
||||
}
|
||||
|
||||
action = .changeProfileColor(prevColor: prevColorIndex.flatMap(PeerNameColor.init(rawValue:)), prevIcon: prevEmojiId, newColor: newColorIndex.flatMap(PeerNameColor.init(rawValue:)), newIcon: newEmojiId)
|
||||
case let .channelAdminLogEventActionChangeWallpaper(prevValue, newValue):
|
||||
let _ = prevValue
|
||||
let _ = newValue
|
||||
action = nil
|
||||
let prev: TelegramWallpaper?
|
||||
if case let .wallPaperNoFile(_, _, settings) = prevValue {
|
||||
if settings == nil {
|
||||
prev = nil
|
||||
} else if case let .wallPaperSettings(flags, _, _, _, _, _, _, _) = settings, flags == 0 {
|
||||
prev = nil
|
||||
} else {
|
||||
prev = TelegramWallpaper(apiWallpaper: prevValue)
|
||||
}
|
||||
} else {
|
||||
prev = TelegramWallpaper(apiWallpaper: prevValue)
|
||||
}
|
||||
let new: TelegramWallpaper?
|
||||
if case let .wallPaperNoFile(_, _, settings) = newValue {
|
||||
if settings == nil {
|
||||
new = nil
|
||||
} else if case let .wallPaperSettings(flags, _, _, _, _, _, _, _) = settings, flags == 0 {
|
||||
new = nil
|
||||
} else {
|
||||
new = TelegramWallpaper(apiWallpaper: newValue)
|
||||
}
|
||||
} else {
|
||||
new = TelegramWallpaper(apiWallpaper: newValue)
|
||||
}
|
||||
action = .changeWallpaper(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeEmojiStatus(prevValue, newValue):
|
||||
let _ = prevValue
|
||||
let _ = newValue
|
||||
action = nil
|
||||
action = .changeStatus(prev: PeerEmojiStatus(apiStatus: prevValue), new: PeerEmojiStatus(apiStatus: newValue))
|
||||
}
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
|
||||
if let action = action {
|
||||
|
@ -718,6 +718,14 @@ public extension TelegramEngine {
|
||||
return _internal_updatePeerNameColorAndEmoji(account: self.account, peerId: peerId, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId)
|
||||
}
|
||||
|
||||
public func updatePeerNameColor(peerId: EnginePeer.Id, nameColor: PeerNameColor, backgroundEmojiId: Int64?) -> Signal<Void, UpdatePeerNameColorAndEmojiError> {
|
||||
return _internal_updatePeerNameColor(account: self.account, peerId: peerId, nameColor: nameColor, backgroundEmojiId: backgroundEmojiId)
|
||||
}
|
||||
|
||||
public func updatePeerProfileColor(peerId: EnginePeer.Id, profileColor: PeerNameColor?, profileBackgroundEmojiId: Int64?) -> Signal<Void, UpdatePeerNameColorAndEmojiError> {
|
||||
return _internal_updatePeerProfileColor(account: self.account, peerId: peerId, profileColor: profileColor, profileBackgroundEmojiId: profileBackgroundEmojiId)
|
||||
}
|
||||
|
||||
public func updatePeerEmojiStatus(peerId: EnginePeer.Id, fileId: Int64?, expirationDate: Int32?) -> Signal<Never, UpdatePeerEmojiStatusError> {
|
||||
return _internal_updatePeerEmojiStatus(account: self.account, peerId: peerId, fileId: fileId, expirationDate: expirationDate)
|
||||
}
|
||||
|
@ -98,15 +98,21 @@ func _internal_updatePeerNameColorAndEmoji(account: Account, peerId: EnginePeer.
|
||||
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) {
|
||||
let flagsReplies: Int32 = (1 << 0) | (1 << 2)
|
||||
var flagsReplies: Int32 = (1 << 2)
|
||||
if backgroundEmojiId != nil {
|
||||
flagsReplies |= 1 << 0
|
||||
}
|
||||
|
||||
var flagsProfile: Int32 = (1 << 0) | (1 << 1)
|
||||
var flagsProfile: Int32 = (1 << 1)
|
||||
if profileBackgroundEmojiId != nil {
|
||||
flagsProfile |= 1 << 0
|
||||
}
|
||||
if profileColor != nil {
|
||||
flagsProfile |= (1 << 2)
|
||||
}
|
||||
|
||||
return combineLatest(
|
||||
account.network.request(Api.functions.channels.updateColor(flags: flagsReplies, channel: inputChannel, color: nameColor.rawValue, backgroundEmojiId: backgroundEmojiId ?? 0))
|
||||
account.network.request(Api.functions.channels.updateColor(flags: flagsReplies, channel: inputChannel, color: nameColor.rawValue, backgroundEmojiId: backgroundEmojiId))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { error -> Signal<Api.Updates?, MTRpcError> in
|
||||
if error.errorDescription.hasPrefix("CHAT_NOT_MODIFIED") {
|
||||
@ -115,7 +121,7 @@ func _internal_updatePeerNameColorAndEmoji(account: Account, peerId: EnginePeer.
|
||||
return .fail(error)
|
||||
}
|
||||
},
|
||||
account.network.request(Api.functions.channels.updateColor(flags: flagsProfile, channel: inputChannel, color: profileColor?.rawValue, backgroundEmojiId: profileBackgroundEmojiId ?? 0))
|
||||
account.network.request(Api.functions.channels.updateColor(flags: flagsProfile, channel: inputChannel, color: profileColor?.rawValue, backgroundEmojiId: profileBackgroundEmojiId))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { error -> Signal<Api.Updates?, MTRpcError> in
|
||||
if error.errorDescription.hasPrefix("CHAT_NOT_MODIFIED") {
|
||||
@ -162,6 +168,105 @@ func _internal_updatePeerNameColorAndEmoji(account: Account, peerId: EnginePeer.
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
func _internal_updatePeerNameColor(account: Account, peerId: EnginePeer.Id, nameColor: PeerNameColor, backgroundEmojiId: 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) {
|
||||
var flagsReplies: Int32 = (1 << 2)
|
||||
if backgroundEmojiId != nil {
|
||||
flagsReplies |= 1 << 0
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.channels.updateColor(flags: flagsReplies, channel: inputChannel, color: nameColor.rawValue, backgroundEmojiId: backgroundEmojiId))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { error -> Signal<Api.Updates?, MTRpcError> in
|
||||
if error.errorDescription.hasPrefix("CHAT_NOT_MODIFIED") {
|
||||
return .single(nil)
|
||||
} else {
|
||||
return .fail(error)
|
||||
}
|
||||
}
|
||||
|> mapError { error -> UpdatePeerNameColorAndEmojiError in
|
||||
if error.errorDescription.hasPrefix("BOOSTS_REQUIRED") {
|
||||
return .channelBoostRequired
|
||||
}
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { repliesResult -> Signal<Void, UpdatePeerNameColorAndEmojiError> in
|
||||
if let repliesResult = repliesResult {
|
||||
account.stateManager.addUpdates(repliesResult)
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let repliesResult = repliesResult, let apiChat = apiUpdatesGroups(repliesResult).first {
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [apiChat], users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
|> mapError { _ -> UpdatePeerNameColorAndEmojiError in }
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
|> castError(UpdatePeerNameColorAndEmojiError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
func _internal_updatePeerProfileColor(account: Account, peerId: EnginePeer.Id, 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) {
|
||||
var flagsProfile: Int32 = (1 << 1)
|
||||
if profileBackgroundEmojiId != nil {
|
||||
flagsProfile |= 1 << 0
|
||||
}
|
||||
if profileColor != nil {
|
||||
flagsProfile |= (1 << 2)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.channels.updateColor(flags: flagsProfile, channel: inputChannel, color: profileColor?.rawValue, backgroundEmojiId: profileBackgroundEmojiId))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { error -> Signal<Api.Updates?, MTRpcError> in
|
||||
if error.errorDescription.hasPrefix("CHAT_NOT_MODIFIED") {
|
||||
return .single(nil)
|
||||
} else {
|
||||
return .fail(error)
|
||||
}
|
||||
}
|
||||
|> mapError { error -> UpdatePeerNameColorAndEmojiError in
|
||||
if error.errorDescription.hasPrefix("BOOSTS_REQUIRED") {
|
||||
return .channelBoostRequired
|
||||
}
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { profileResult -> Signal<Void, UpdatePeerNameColorAndEmojiError> in
|
||||
if let profileResult = profileResult {
|
||||
account.stateManager.addUpdates(profileResult)
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let profileResult = profileResult, let apiChat = apiUpdatesGroups(profileResult).first {
|
||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: [apiChat], users: [])
|
||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: parsedPeers)
|
||||
}
|
||||
}
|
||||
|> mapError { _ -> UpdatePeerNameColorAndEmojiError in }
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
} else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
|> castError(UpdatePeerNameColorAndEmojiError.self)
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
public enum UpdatePeerEmojiStatusError {
|
||||
case generic
|
||||
}
|
||||
|
@ -625,8 +625,14 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
attributedString = addAttributesToStringWithRanges(titleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds))
|
||||
}
|
||||
}
|
||||
case let .customText(text, entities):
|
||||
attributedString = stringWithAppliedEntities(text, entities: entities, baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false, message: message._asMessage())
|
||||
case let .customText(text, entities, additionalAttributes):
|
||||
let mutableAttributedString = NSMutableAttributedString(attributedString: stringWithAppliedEntities(text, entities: entities, baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false, message: message._asMessage()))
|
||||
if let additionalAttributes {
|
||||
for (range, key, value) in additionalAttributes.attributes {
|
||||
mutableAttributedString.addAttribute(key, value: value, range: range)
|
||||
}
|
||||
}
|
||||
attributedString = mutableAttributedString
|
||||
case let .botDomainAccessGranted(domain):
|
||||
attributedString = NSAttributedString(string: strings.AuthSessions_Message(domain).string, font: titleFont, textColor: primaryTextColor)
|
||||
case let .botAppAccessGranted(appName, type):
|
||||
@ -733,7 +739,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
case let .topicCreated(title, iconColor, iconFileId):
|
||||
if forForumOverview {
|
||||
let maybeFileId = iconFileId ?? 0
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicCreated(".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, topicInfo: maybeFileId == 0 ? (message.threadId ?? 0, EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicCreated(".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, custom: maybeFileId == 0 ? .topic(id: message.threadId ?? 0, info: EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
} else {
|
||||
attributedString = NSAttributedString(string: strings.Notification_ForumTopicCreated, font: titleFont, textColor: primaryTextColor)
|
||||
}
|
||||
@ -757,9 +763,9 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
maybeFileId = info.icon ?? 0
|
||||
}
|
||||
if isHidden {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicHidden(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, topicInfo: maybeFileId == 0 ? (message.threadId ?? 0, EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicHidden(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, custom: maybeFileId == 0 ? .topic(id: message.threadId ?? 0, info: EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
} else {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicUnhidden(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, topicInfo: maybeFileId == 0 ? (message.threadId ?? 0, EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicUnhidden(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, custom: maybeFileId == 0 ? .topic(id: message.threadId ?? 0, info: EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
}
|
||||
} else {
|
||||
if isHidden {
|
||||
@ -794,9 +800,9 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
maybeFileId = info.icon ?? 0
|
||||
}
|
||||
if isClosed {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicClosed(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, topicInfo: maybeFileId == 0 ? (message.threadId ?? 0, EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicClosed(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, custom: maybeFileId == 0 ? .topic(id: message.threadId ?? 0, info: EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
} else {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicReopened(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, topicInfo: maybeFileId == 0 ? (message.threadId ?? 0, EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_OverviewTopicReopened(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, custom: maybeFileId == 0 ? .topic(id: message.threadId ?? 0, info: EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
}
|
||||
} else {
|
||||
if isClosed {
|
||||
@ -834,7 +840,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
}
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ForumTopicRenamedIconChangedAuthor(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".", title)._tuple, body: bodyAttributes, argumentAttributes: [
|
||||
0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id),
|
||||
1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, topicInfo: maybeFileId == 0 ? (message.threadId ?? 0, EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])
|
||||
1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, custom: maybeFileId == 0 ? .topic(id: message.threadId ?? 0, info: EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])
|
||||
])
|
||||
} else {
|
||||
attributedString = NSAttributedString(string: strings.Notification_ForumTopicRenamed(title).string, font: titleFont, textColor: primaryTextColor)
|
||||
@ -867,9 +873,9 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
||||
title = info.title
|
||||
}
|
||||
if case let .user(user) = message.author {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ForumTopicIconChangedAuthor(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".")._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, topicInfo: maybeFileId == 0 ? (message.threadId ?? 0, EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ForumTopicIconChangedAuthor(EnginePeer.user(user).displayTitle(strings: strings, displayOrder: nameDisplayOrder), ".")._tuple, body: bodyAttributes, argumentAttributes: [0: peerMentionAttributes(primaryTextColor: primaryTextColor, peerId: user.id), 1: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, custom: maybeFileId == 0 ? .topic(id: message.threadId ?? 0, info: EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
} else {
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ForumTopicIconChanged(".")._tuple, body: bodyAttributes, argumentAttributes: [0: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, topicInfo: maybeFileId == 0 ? (message.threadId ?? 0, EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_ForumTopicIconChanged(".")._tuple, body: bodyAttributes, argumentAttributes: [0: MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [ChatTextInputAttributes.customEmoji.rawValue: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: maybeFileId, file: nil, custom: maybeFileId == 0 ? .topic(id: message.threadId ?? 0, info: EngineMessageHistoryThread.Info(title: title, icon: nil, iconColor: iconColor)) : nil)])])
|
||||
}
|
||||
}
|
||||
case let .suggestedProfilePhoto(image):
|
||||
|
@ -282,7 +282,10 @@ public class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if item.message.id.peerId.isGroupOrChannel {
|
||||
if item.associatedData.isRecentActions {
|
||||
let authorName = item.message.author.flatMap { EnginePeer($0).compactDisplayTitle } ?? ""
|
||||
text = item.presentationData.strings.Channel_AdminLog_ChannelChangedWallpaper(authorName).string
|
||||
} else if item.message.id.peerId.isGroupOrChannel {
|
||||
text = item.presentationData.strings.Notification_ChannelChangedWallpaper
|
||||
} else {
|
||||
text = item.presentationData.strings.Notification_ChangedWallpaper(peerName).string
|
||||
|
@ -47,6 +47,7 @@ swift_library(
|
||||
"//submodules/TemporaryCachedPeerDataManager",
|
||||
"//submodules/UndoUI",
|
||||
"//submodules/WallpaperBackgroundNode",
|
||||
"//submodules/TextFormat",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -9,6 +9,7 @@ import AccountContext
|
||||
import ChatControllerInteraction
|
||||
import ChatHistoryEntry
|
||||
import ChatMessageItemImpl
|
||||
import TextFormat
|
||||
|
||||
enum ChatRecentActionsEntryContentIndex: Int32 {
|
||||
case header = 0
|
||||
@ -56,6 +57,22 @@ private func appendAttributedText(text: PresentationStrings.FormattedString, gen
|
||||
string.append(text.string)
|
||||
}
|
||||
|
||||
private func appendAttributedText(text: PresentationStrings.FormattedString, additionalAttributes: inout [(NSRange, NSAttributedString.Key, Any)], generateEntities: (Int) -> ([MessageTextEntityType], [NSAttributedString.Key: Any]), to string: inout String, entities: inout [MessageTextEntity]) {
|
||||
let nsString = string as NSString
|
||||
for rangeItem in text.ranges {
|
||||
let (types, additionalValues) = generateEntities(rangeItem.index)
|
||||
for type in types {
|
||||
entities.append(MessageTextEntity(range: (nsString.length + rangeItem.range.lowerBound) ..< (nsString.length + rangeItem.range.upperBound), type: type))
|
||||
}
|
||||
let lowerBound = nsString.length + rangeItem.range.lowerBound
|
||||
let range = NSRange(location: lowerBound, length: nsString.length + rangeItem.range.upperBound - lowerBound)
|
||||
for (key, value) in additionalValues {
|
||||
additionalAttributes.append((range, key, value))
|
||||
}
|
||||
}
|
||||
string.append(text.string)
|
||||
}
|
||||
|
||||
private func appendAttributedText(text: String, withEntities: [MessageTextEntityType], to string: inout String, entities: inout [MessageTextEntity]) {
|
||||
for type in withEntities {
|
||||
entities.append(MessageTextEntity(range: string.count ..< (string.count + text.count), type: type))
|
||||
@ -146,7 +163,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case .content:
|
||||
@ -184,7 +201,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case .content:
|
||||
@ -234,7 +251,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case .content:
|
||||
@ -318,7 +335,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .toggleSignatures(value):
|
||||
@ -345,7 +362,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .updatePinned(message):
|
||||
@ -376,7 +393,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case .content:
|
||||
@ -415,7 +432,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -460,7 +477,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -503,7 +520,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -962,7 +979,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -992,7 +1009,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1079,7 +1096,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1152,7 +1169,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
}
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1179,7 +1196,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: [], media: [mediaMap], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
} else {
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1210,7 +1227,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1247,7 +1264,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1281,7 +1298,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1310,7 +1327,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1341,7 +1358,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1367,7 +1384,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1393,7 +1410,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1419,7 +1436,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1450,7 +1467,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1481,7 +1498,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1552,7 +1569,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1583,7 +1600,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1623,7 +1640,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
@ -1651,7 +1668,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .sendMessage(message):
|
||||
@ -1676,7 +1693,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case .content:
|
||||
@ -1713,7 +1730,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
}
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .deleteTopic(info):
|
||||
@ -1734,7 +1751,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .editTopic(prevInfo, newInfo):
|
||||
@ -1807,7 +1824,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .pinTopic(prevInfo, newInfo):
|
||||
@ -1845,7 +1862,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .toggleForum(isForum):
|
||||
@ -1866,7 +1883,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .toggleAntiSpam(isEnabled):
|
||||
@ -1887,73 +1904,220 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
|
||||
case let .changeNameColor(_, updatedValue):
|
||||
var peers = SimpleDictionary<PeerId, Peer>()
|
||||
var author: Peer?
|
||||
if let peer = self.entry.peers[self.entry.event.peerId] {
|
||||
author = peer
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
case let .changeNameColor(_, _, updatedColor, updatedIcon):
|
||||
var peers = SimpleDictionary<PeerId, Peer>()
|
||||
var author: Peer?
|
||||
if let peer = self.entry.peers[self.entry.event.peerId] {
|
||||
author = peer
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
let authorTitle = author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? ""
|
||||
|
||||
var text: String = ""
|
||||
var entities: [MessageTextEntity] = []
|
||||
|
||||
let _ = updatedValue
|
||||
var text: String = ""
|
||||
var entities: [MessageTextEntity] = []
|
||||
var additionalAttributes: [(NSRange, NSAttributedString.Key, Any)] = []
|
||||
|
||||
let rawText = self.presentationData.strings.Channel_AdminLog_MessageChangedNameColorSet(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", "●")
|
||||
if let updatedIcon {
|
||||
let rawText = self.presentationData.strings.Channel_AdminLog_ChannelChangedNameColorAndIcon(authorTitle, ".", ".")
|
||||
|
||||
appendAttributedText(text: rawText, generateEntities: { index in
|
||||
let colors = context.peerNameColors.get(updatedColor)
|
||||
var colorList: [UInt32] = []
|
||||
colorList.append(colors.main.argb)
|
||||
if let secondary = colors.secondary {
|
||||
colorList.append(secondary.argb)
|
||||
}
|
||||
if let tertiary = colors.tertiary {
|
||||
colorList.append(tertiary.argb)
|
||||
}
|
||||
|
||||
appendAttributedText(text: rawText, additionalAttributes: &additionalAttributes, generateEntities: { index in
|
||||
if index == 0, let author = author {
|
||||
return ([.TextMention(peerId: author.id)], [:])
|
||||
} else if index == 1 {
|
||||
return ([], [
|
||||
ChatTextInputAttributes.customEmoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .nameColors(colorList))
|
||||
])
|
||||
} else if index == 2 {
|
||||
return ([.CustomEmoji(stickerPack: nil, fileId: updatedIcon)], [:])
|
||||
} else {
|
||||
return ([], [:])
|
||||
}
|
||||
}, to: &text, entities: &entities)
|
||||
} else {
|
||||
let rawText = self.presentationData.strings.Channel_AdminLog_ChannelChangedNameColor(authorTitle, ".")
|
||||
|
||||
let colors = context.peerNameColors.get(updatedColor)
|
||||
var colorList: [UInt32] = []
|
||||
colorList.append(colors.main.argb)
|
||||
if let secondary = colors.secondary {
|
||||
colorList.append(secondary.argb)
|
||||
}
|
||||
if let tertiary = colors.tertiary {
|
||||
colorList.append(tertiary.argb)
|
||||
}
|
||||
|
||||
appendAttributedText(text: rawText, additionalAttributes: &additionalAttributes, generateEntities: { index in
|
||||
if index == 0, let author = author {
|
||||
return ([.TextMention(peerId: author.id)], [:])
|
||||
} else if index == 1 {
|
||||
return ([], [
|
||||
ChatTextInputAttributes.customEmoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .nameColors(colorList))
|
||||
])
|
||||
} else {
|
||||
return ([], [:])
|
||||
}
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: TelegramMediaActionType.CustomTextAttributes(attributes: additionalAttributes))
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .changeProfileColor(_, _, updatedColor, updatedIcon):
|
||||
var peers = SimpleDictionary<PeerId, Peer>()
|
||||
var author: Peer?
|
||||
if let peer = self.entry.peers[self.entry.event.peerId] {
|
||||
author = peer
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
let authorTitle = author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? ""
|
||||
|
||||
var text: String = ""
|
||||
var entities: [MessageTextEntity] = []
|
||||
var additionalAttributes: [(NSRange, NSAttributedString.Key, Any)] = []
|
||||
|
||||
if let updatedColor, let updatedIcon {
|
||||
let rawText = self.presentationData.strings.Channel_AdminLog_ChannelChangedProfileColorAndIcon(authorTitle, ".", ".")
|
||||
|
||||
let colors = context.peerNameColors.get(updatedColor)
|
||||
var colorList: [UInt32] = []
|
||||
colorList.append(colors.main.argb)
|
||||
if let secondary = colors.secondary {
|
||||
colorList.append(secondary.argb)
|
||||
}
|
||||
if let tertiary = colors.tertiary {
|
||||
colorList.append(tertiary.argb)
|
||||
}
|
||||
|
||||
appendAttributedText(text: rawText, additionalAttributes: &additionalAttributes, generateEntities: { index in
|
||||
if index == 0, let author = author {
|
||||
return ([.TextMention(peerId: author.id)], [:])
|
||||
} else if index == 1 {
|
||||
return ([], [
|
||||
ChatTextInputAttributes.customEmoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .nameColors(colorList))
|
||||
])
|
||||
} else if index == 2 {
|
||||
return ([.CustomEmoji(stickerPack: nil, fileId: updatedIcon)], [:])
|
||||
} else {
|
||||
return ([], [:])
|
||||
}
|
||||
}, to: &text, entities: &entities)
|
||||
} else if let updatedColor {
|
||||
let rawText = self.presentationData.strings.Channel_AdminLog_ChannelChangedProfileColor(authorTitle, ".")
|
||||
|
||||
let colors = context.peerNameColors.get(updatedColor)
|
||||
var colorList: [UInt32] = []
|
||||
colorList.append(colors.main.argb)
|
||||
if let secondary = colors.secondary {
|
||||
colorList.append(secondary.argb)
|
||||
}
|
||||
if let tertiary = colors.tertiary {
|
||||
colorList.append(tertiary.argb)
|
||||
}
|
||||
|
||||
appendAttributedText(text: rawText, additionalAttributes: &additionalAttributes, generateEntities: { index in
|
||||
if index == 0, let author = author {
|
||||
return ([.TextMention(peerId: author.id)], [:])
|
||||
} else if index == 1 {
|
||||
return ([], [
|
||||
ChatTextInputAttributes.customEmoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .nameColors(colorList))
|
||||
])
|
||||
} else {
|
||||
return ([], [:])
|
||||
}
|
||||
}, to: &text, entities: &entities)
|
||||
} else {
|
||||
let rawText = self.presentationData.strings.Channel_AdminLog_ChannelRemovedProfileColorAndIcon(authorTitle)
|
||||
|
||||
appendAttributedText(text: rawText, additionalAttributes: &additionalAttributes, generateEntities: { index in
|
||||
if index == 0, let author = author {
|
||||
return ([.TextMention(peerId: author.id)], [:])
|
||||
} else {
|
||||
return ([], [:])
|
||||
}
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: TelegramMediaActionType.CustomTextAttributes(attributes: additionalAttributes))
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .changeStatus(_, status):
|
||||
var peers = SimpleDictionary<PeerId, Peer>()
|
||||
var author: Peer?
|
||||
if let peer = self.entry.peers[self.entry.event.peerId] {
|
||||
author = peer
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
|
||||
let authorTitle: String = author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? ""
|
||||
|
||||
var text: String = ""
|
||||
var entities: [MessageTextEntity] = []
|
||||
|
||||
if let status {
|
||||
appendAttributedText(text: self.presentationData.strings.Channel_AdminLog_ChannelUpdatedStatus(authorTitle, "."), generateEntities: { index in
|
||||
if index == 0, let author = author {
|
||||
return [.TextMention(peerId: author.id)]
|
||||
} else if index == 1 {
|
||||
return [.Bold]
|
||||
return [.CustomEmoji(stickerPack: nil, fileId: status.fileId)]
|
||||
}
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
// case let .changeBackgroundEmojiId(_, updatedValue):
|
||||
// var peers = SimpleDictionary<PeerId, Peer>()
|
||||
// var author: Peer?
|
||||
// if let peer = self.entry.peers[self.entry.event.peerId] {
|
||||
// author = peer
|
||||
// peers[peer.id] = peer
|
||||
// }
|
||||
//
|
||||
// var text: String = ""
|
||||
// var entities: [MessageTextEntity] = []
|
||||
//
|
||||
// if let updatedValue, updatedValue != 0 {
|
||||
// appendAttributedText(text: self.presentationData.strings.Channel_AdminLog_MessageChangedBackgroundEmojiSet(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "", "."), generateEntities: { index in
|
||||
// if index == 0, let author = author {
|
||||
// return [.TextMention(peerId: author.id)]
|
||||
// } else if index == 1 {
|
||||
// return [.CustomEmoji(stickerPack: nil, fileId: updatedValue)]
|
||||
// }
|
||||
// return []
|
||||
// }, to: &text, entities: &entities)
|
||||
// } else {
|
||||
// let rawText = self.presentationData.strings.Channel_AdminLog_MessageChangedBackgroundEmojiRemoved(author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? "")
|
||||
//
|
||||
// appendAttributedText(text: rawText, generateEntities: { index in
|
||||
// if index == 0, let author = author {
|
||||
// return [.TextMention(peerId: author.id)]
|
||||
// }
|
||||
// return []
|
||||
// }, to: &text, entities: &entities)
|
||||
// }
|
||||
//
|
||||
// let action = TelegramMediaActionType.customText(text: text, entities: entities)
|
||||
//
|
||||
// let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
// return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
} else {
|
||||
appendAttributedText(text: self.presentationData.strings.Channel_AdminLog_ChannelRemovedStatus(authorTitle), generateEntities: { index in
|
||||
if index == 0, let author = author {
|
||||
return [.TextMention(peerId: author.id)]
|
||||
}
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
}
|
||||
|
||||
let action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
case let .changeWallpaper(_, wallpaper):
|
||||
var peers = SimpleDictionary<PeerId, Peer>()
|
||||
var author: Peer?
|
||||
if let peer = self.entry.peers[self.entry.event.peerId] {
|
||||
author = peer
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
|
||||
let authorTitle: String = author.flatMap(EnginePeer.init)?.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder) ?? ""
|
||||
|
||||
var text: String = ""
|
||||
var entities: [MessageTextEntity] = []
|
||||
|
||||
let action: TelegramMediaActionType
|
||||
if let wallpaper {
|
||||
action = TelegramMediaActionType.setChatWallpaper(wallpaper: wallpaper, forBoth: false)
|
||||
} else {
|
||||
appendAttributedText(text: self.presentationData.strings.Channel_AdminLog_ChannelRemovedWallpaper(authorTitle), generateEntities: { index in
|
||||
if index == 0, let author = author {
|
||||
return [.TextMention(peerId: author.id)]
|
||||
}
|
||||
return []
|
||||
}, to: &text, entities: &entities)
|
||||
action = TelegramMediaActionType.customText(text: text, entities: entities, additionalAttributes: nil)
|
||||
}
|
||||
|
||||
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
return ChatMessageItemImpl(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,6 +166,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
public let titleLeftIconNode: ASImageNode
|
||||
public let titleRightIconNode: ASImageNode
|
||||
public let titleCredibilityIconView: ComponentHostView<Empty>
|
||||
public let titleVerifiedIconView: ComponentHostView<Empty>
|
||||
public let activityNode: ChatTitleActivityNode
|
||||
|
||||
private let button: HighlightTrackingButtonNode
|
||||
@ -178,6 +179,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
private var titleLeftIcon: ChatTitleIcon = .none
|
||||
private var titleRightIcon: ChatTitleIcon = .none
|
||||
private var titleCredibilityIcon: ChatTitleCredibilityIcon = .none
|
||||
private var titleVerifiedIcon: ChatTitleCredibilityIcon = .none
|
||||
|
||||
private var presenceManager: PeerPresenceStatusManager?
|
||||
|
||||
@ -224,6 +226,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
var titleLeftIcon: ChatTitleIcon = .none
|
||||
var titleRightIcon: ChatTitleIcon = .none
|
||||
var titleCredibilityIcon: ChatTitleCredibilityIcon = .none
|
||||
var titleVerifiedIcon: ChatTitleCredibilityIcon = .none
|
||||
var isEnabled = true
|
||||
switch titleContent {
|
||||
case let .peer(peerView, customTitle, _, isScheduledMessages, isMuted, _, isEnabledValue):
|
||||
@ -258,6 +261,9 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
} else if peer.isScam {
|
||||
titleCredibilityIcon = .scam
|
||||
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
||||
if peer is TelegramChannel, peer.isVerified {
|
||||
titleVerifiedIcon = .verified
|
||||
}
|
||||
titleCredibilityIcon = .emojiStatus(emojiStatus)
|
||||
} else if peer.isVerified {
|
||||
titleCredibilityIcon = .verified
|
||||
@ -381,18 +387,11 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
|
||||
if titleCredibilityIcon != self.titleCredibilityIcon {
|
||||
self.titleCredibilityIcon = titleCredibilityIcon
|
||||
/*switch titleCredibilityIcon {
|
||||
case .none:
|
||||
self.titleCredibilityIconNode.image = nil
|
||||
case .fake:
|
||||
self.titleCredibilityIconNode.image = PresentationResourcesChatList.fakeIcon(titleTheme, strings: self.strings, type: .regular)
|
||||
case .scam:
|
||||
self.titleCredibilityIconNode.image = PresentationResourcesChatList.scamIcon(titleTheme, strings: self.strings, type: .regular)
|
||||
case .verified:
|
||||
self.titleCredibilityIconNode.image = PresentationResourcesChatList.verifiedIcon(titleTheme)
|
||||
case .premium:
|
||||
self.titleCredibilityIconNode.image = PresentationResourcesChatList.premiumIcon(titleTheme)
|
||||
}*/
|
||||
updated = true
|
||||
}
|
||||
|
||||
if titleVerifiedIcon != self.titleVerifiedIcon {
|
||||
self.titleVerifiedIcon = titleVerifiedIcon
|
||||
updated = true
|
||||
}
|
||||
|
||||
@ -696,6 +695,9 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
self.titleCredibilityIconView = ComponentHostView()
|
||||
self.titleCredibilityIconView.isUserInteractionEnabled = false
|
||||
|
||||
self.titleVerifiedIconView = ComponentHostView()
|
||||
self.titleVerifiedIconView.isUserInteractionEnabled = false
|
||||
|
||||
self.activityNode = ChatTitleActivityNode()
|
||||
self.button = HighlightTrackingButtonNode()
|
||||
|
||||
@ -721,13 +723,16 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
strongSelf.titleTextNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.activityNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.titleCredibilityIconView.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.titleVerifiedIconView.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.titleTextNode.alpha = 0.4
|
||||
strongSelf.activityNode.alpha = 0.4
|
||||
strongSelf.titleCredibilityIconView.alpha = 0.4
|
||||
strongSelf.titleVerifiedIconView.alpha = 0.4
|
||||
} else {
|
||||
strongSelf.titleTextNode.alpha = 1.0
|
||||
strongSelf.activityNode.alpha = 1.0
|
||||
strongSelf.titleCredibilityIconView.alpha = 1.0
|
||||
strongSelf.titleVerifiedIconView.alpha = 1.0
|
||||
strongSelf.titleTextNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
strongSelf.activityNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
}
|
||||
@ -756,6 +761,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
|
||||
let titleContent = self.titleContent
|
||||
self.titleCredibilityIcon = .none
|
||||
self.titleVerifiedIcon = .none
|
||||
self.titleContent = titleContent
|
||||
let _ = self.updateStatus()
|
||||
|
||||
@ -774,6 +780,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
var leftIconWidth: CGFloat = 0.0
|
||||
var rightIconWidth: CGFloat = 0.0
|
||||
var credibilityIconWidth: CGFloat = 0.0
|
||||
var verifiedIconWidth: CGFloat = 0.0
|
||||
|
||||
if let image = self.titleLeftIconNode.image {
|
||||
if self.titleLeftIconNode.supernode == nil {
|
||||
@ -800,6 +807,22 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
titleCredibilityContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: self.theme.list.mediaPlaceholderColor, themeColor: self.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
}
|
||||
|
||||
let titleVerifiedContent: EmojiStatusComponent.Content
|
||||
switch self.titleVerifiedIcon {
|
||||
case .none:
|
||||
titleVerifiedContent = .none
|
||||
case .premium:
|
||||
titleVerifiedContent = .premium(color: self.theme.list.itemAccentColor)
|
||||
case .verified:
|
||||
titleVerifiedContent = .verified(fillColor: self.theme.list.itemCheckColors.fillColor, foregroundColor: self.theme.list.itemCheckColors.foregroundColor, sizeType: .large)
|
||||
case .fake:
|
||||
titleVerifiedContent = .text(color: self.theme.chat.message.incoming.scamColor, string: self.strings.Message_FakeAccount.uppercased())
|
||||
case .scam:
|
||||
titleVerifiedContent = .text(color: self.theme.chat.message.incoming.scamColor, string: self.strings.Message_ScamAccount.uppercased())
|
||||
case let .emojiStatus(emojiStatus):
|
||||
titleVerifiedContent = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: self.theme.list.mediaPlaceholderColor, themeColor: self.theme.list.itemAccentColor, loopMode: .count(2))
|
||||
}
|
||||
|
||||
let titleCredibilitySize = self.titleCredibilityIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
@ -814,6 +837,20 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
containerSize: CGSize(width: 20.0, height: 20.0)
|
||||
)
|
||||
|
||||
let titleVerifiedSize = self.titleVerifiedIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
context: self.context,
|
||||
animationCache: self.animationCache,
|
||||
animationRenderer: self.animationRenderer,
|
||||
content: titleVerifiedContent,
|
||||
isVisibleForAnimations: true,
|
||||
action: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 20.0, height: 20.0)
|
||||
)
|
||||
|
||||
if self.titleCredibilityIcon != .none {
|
||||
self.titleTextNode.view.addSubview(self.titleCredibilityIconView)
|
||||
credibilityIconWidth = titleCredibilitySize.width + 3.0
|
||||
@ -823,6 +860,15 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
}
|
||||
}
|
||||
|
||||
if self.titleVerifiedIcon != .none {
|
||||
self.titleTextNode.view.addSubview(self.titleVerifiedIconView)
|
||||
verifiedIconWidth = titleVerifiedSize.width + 3.0
|
||||
} else {
|
||||
if self.titleVerifiedIconView.superview != nil {
|
||||
self.titleVerifiedIconView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
if let image = self.titleRightIconNode.image {
|
||||
if self.titleRightIconNode.supernode == nil {
|
||||
self.titleTextNode.addSubnode(self.titleRightIconNode)
|
||||
@ -840,8 +886,9 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
let titleSideInset: CGFloat = 6.0
|
||||
var titleFrame: CGRect
|
||||
if size.height > 40.0 {
|
||||
var titleSize = self.titleTextNode.updateLayout(size: CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height), animated: titleTransition.isAnimated)
|
||||
var titleSize = self.titleTextNode.updateLayout(size: CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - verifiedIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height), animated: titleTransition.isAnimated)
|
||||
titleSize.width += credibilityIconWidth
|
||||
titleSize.width += verifiedIconWidth
|
||||
let activitySize = self.activityNode.updateLayout(CGSize(width: clearBounds.size.width - titleSideInset * 2.0, height: clearBounds.size.height), alignment: .center)
|
||||
let titleInfoSpacing: CGFloat = 0.0
|
||||
|
||||
@ -874,30 +921,48 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size)
|
||||
}
|
||||
|
||||
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: titleFrame.width - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
|
||||
var nextIconX: CGFloat = titleFrame.width
|
||||
|
||||
self.titleVerifiedIconView.frame = CGRect(origin: CGPoint(x: titleFrame.width - titleVerifiedSize.width, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize)
|
||||
nextIconX -= titleVerifiedSize.width
|
||||
if !titleVerifiedSize.width.isZero {
|
||||
nextIconX -= 2.0
|
||||
}
|
||||
|
||||
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
|
||||
nextIconX -= titleCredibilitySize.width
|
||||
|
||||
if let image = self.titleRightIconNode.image {
|
||||
self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0 + UIScreenPixel, y: 6.0), size: image.size)
|
||||
}
|
||||
} else {
|
||||
let titleSize = self.titleTextNode.updateLayout(size: CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0), height: size.height), animated: titleTransition.isAnimated)
|
||||
let titleSize = self.titleTextNode.updateLayout(size: CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - credibilityIconWidth - verifiedIconWidth - rightIconWidth - titleSideInset * 2.0), height: size.height), animated: titleTransition.isAnimated)
|
||||
let activitySize = self.activityNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0), height: size.height), alignment: .center)
|
||||
|
||||
let titleInfoSpacing: CGFloat = 8.0
|
||||
let combinedWidth = titleSize.width + leftIconWidth + credibilityIconWidth + rightIconWidth + activitySize.width + titleInfoSpacing
|
||||
let combinedWidth = titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + rightIconWidth + activitySize.width + titleInfoSpacing
|
||||
|
||||
titleFrame = CGRect(origin: CGPoint(x: leftIconWidth + floor((clearBounds.width - combinedWidth) / 2.0), y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
|
||||
|
||||
titleTransition.updateFrameAdditiveToCenter(view: self.titleContainerView, frame: titleFrame)
|
||||
titleTransition.updateFrameAdditiveToCenter(node: self.titleTextNode, frame: CGRect(origin: CGPoint(), size: titleFrame.size))
|
||||
|
||||
self.activityNode.frame = CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize)
|
||||
self.activityNode.frame = CGRect(origin: CGPoint(x: floor((clearBounds.width - combinedWidth) / 2.0 + titleSize.width + leftIconWidth + credibilityIconWidth + verifiedIconWidth + rightIconWidth + titleInfoSpacing), y: floor((size.height - activitySize.height) / 2.0)), size: activitySize)
|
||||
|
||||
if let image = self.titleLeftIconNode.image {
|
||||
self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX, y: titleFrame.minY + 4.0), size: image.size)
|
||||
}
|
||||
|
||||
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
|
||||
var nextIconX: CGFloat = titleFrame.maxX
|
||||
|
||||
self.titleVerifiedIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleVerifiedSize.width, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize)
|
||||
nextIconX -= titleVerifiedSize.width
|
||||
if !titleVerifiedSize.width.isZero {
|
||||
nextIconX -= 2.0
|
||||
}
|
||||
|
||||
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
|
||||
nextIconX -= titleCredibilitySize.width
|
||||
|
||||
if let image = self.titleRightIconNode.image {
|
||||
self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width, y: titleFrame.minY + 6.0), size: image.size)
|
||||
|
@ -144,6 +144,58 @@ public func animationCacheFetchFile(postbox: Postbox, userLocation: MediaResourc
|
||||
}
|
||||
}
|
||||
|
||||
private func generatePeerNameColorImage(nameColor: PeerNameColors.Colors, isDark: Bool, bounds: CGSize = CGSize(width: 40.0, height: 40.0), size: CGSize = CGSize(width: 40.0, height: 40.0)) -> UIImage? {
|
||||
return generateImage(bounds, rotatedContext: { contextSize, context in
|
||||
let bounds = CGRect(origin: CGPoint(), size: contextSize)
|
||||
context.clear(bounds)
|
||||
|
||||
let circleBounds = CGRect(origin: CGPoint(x: floorToScreenPixels((bounds.width - size.width) / 2.0), y: floorToScreenPixels((bounds.height - size.height) / 2.0)), size: size)
|
||||
context.addEllipse(in: circleBounds)
|
||||
context.clip()
|
||||
|
||||
if let secondColor = nameColor.secondary {
|
||||
var firstColor = nameColor.main
|
||||
var secondColor = secondColor
|
||||
if isDark, nameColor.tertiary == nil {
|
||||
firstColor = secondColor
|
||||
secondColor = nameColor.main
|
||||
}
|
||||
|
||||
context.setFillColor(secondColor.cgColor)
|
||||
context.fill(circleBounds)
|
||||
|
||||
if let thirdColor = nameColor.tertiary {
|
||||
context.move(to: CGPoint(x: contextSize.width, y: 0.0))
|
||||
context.addLine(to: CGPoint(x: contextSize.width, y: contextSize.height))
|
||||
context.addLine(to: CGPoint(x: 0.0, y: contextSize.height))
|
||||
context.closePath()
|
||||
context.setFillColor(firstColor.cgColor)
|
||||
context.fillPath()
|
||||
|
||||
context.setFillColor(thirdColor.cgColor)
|
||||
context.translateBy(x: contextSize.width / 2.0, y: contextSize.height / 2.0)
|
||||
context.rotate(by: .pi / 4.0)
|
||||
|
||||
let rectSide = size.width / 40.0 * 18.0
|
||||
let rectCornerRadius = round(size.width / 40.0 * 4.0)
|
||||
let path = UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: -rectSide / 2.0, y: -rectSide / 2.0), size: CGSize(width: rectSide, height: rectSide)), cornerRadius: rectCornerRadius)
|
||||
context.addPath(path.cgPath)
|
||||
context.fillPath()
|
||||
} else {
|
||||
context.move(to: .zero)
|
||||
context.addLine(to: CGPoint(x: contextSize.width, y: 0.0))
|
||||
context.addLine(to: CGPoint(x: 0.0, y: contextSize.height))
|
||||
context.closePath()
|
||||
context.setFillColor(firstColor.cgColor)
|
||||
context.fillPath()
|
||||
}
|
||||
} else {
|
||||
context.setFillColor(nameColor.main.cgColor)
|
||||
context.fill(circleBounds)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
public enum Context: Equatable {
|
||||
public final class Custom: Equatable {
|
||||
@ -317,8 +369,13 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
|
||||
super.init()
|
||||
|
||||
if let topicInfo = emoji.topicInfo {
|
||||
self.updateTopicInfo(topicInfo: topicInfo)
|
||||
if let custom = emoji.custom {
|
||||
switch custom {
|
||||
case let .topic(id, info):
|
||||
self.updateTopicInfo(topicInfo: (id, info))
|
||||
case let .nameColors(colors):
|
||||
self.updateNameColors(colors: colors)
|
||||
}
|
||||
} else if let file = file {
|
||||
self.updateFile(file: file, attemptSynchronousLoad: attemptSynchronousLoad)
|
||||
} else {
|
||||
@ -467,6 +524,30 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
}
|
||||
}
|
||||
|
||||
private func updateNameColors(colors: [UInt32]) {
|
||||
if colors.isEmpty {
|
||||
return
|
||||
}
|
||||
let main = UIColor(rgb: colors[0])
|
||||
var secondary: UIColor?
|
||||
if colors.count >= 2 {
|
||||
secondary = UIColor(rgb: colors[1])
|
||||
}
|
||||
var tertiary: UIColor?
|
||||
if colors.count >= 3 {
|
||||
tertiary = UIColor(rgb: colors[2])
|
||||
}
|
||||
let mappedColor = PeerNameColors.Colors(main: main, secondary: secondary, tertiary: tertiary)
|
||||
|
||||
let image = generateImage(CGSize(width: 18.0, height: 18.0), contextGenerator: { size, context in
|
||||
context.clear(CGRect(origin: .zero, size: size))
|
||||
if let cgImage = generatePeerNameColorImage(nameColor: mappedColor, isDark: false, bounds: CGSize(width: 18.0, height: 18.0), size: CGSize(width: 16.0, height: 16.0))?.cgImage {
|
||||
context.draw(cgImage, in: CGRect(origin: .zero, size: size))
|
||||
}
|
||||
})
|
||||
self.contents = image?.cgImage
|
||||
}
|
||||
|
||||
private func updateFile(file: TelegramMediaFile, attemptSynchronousLoad: Bool) {
|
||||
if self.file?.fileId == file.fileId {
|
||||
return
|
||||
|
@ -830,9 +830,9 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
}
|
||||
}
|
||||
|
||||
if peerId == context.account.peerId, case .peer = chatLocation {
|
||||
/*if peerId == context.account.peerId, case .peer = chatLocation {
|
||||
availablePanes?.insert(.savedMessagesChats, at: 0)
|
||||
}
|
||||
}*/
|
||||
} else {
|
||||
availablePanes = nil
|
||||
}
|
||||
|
@ -108,10 +108,17 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
let titleNodeContainer: ASDisplayNode
|
||||
let titleNodeRawContainer: ASDisplayNode
|
||||
let titleNode: MultiScaleTextNode
|
||||
|
||||
let titleCredibilityIconView: ComponentHostView<Empty>
|
||||
var credibilityIconSize: CGSize?
|
||||
let titleExpandedCredibilityIconView: ComponentHostView<Empty>
|
||||
var titleExpandedCredibilityIconSize: CGSize?
|
||||
|
||||
let titleVerifiedIconView: ComponentHostView<Empty>
|
||||
var verifiedIconSize: CGSize?
|
||||
let titleExpandedVerifiedIconView: ComponentHostView<Empty>
|
||||
var titleExpandedVerifiedIconSize: CGSize?
|
||||
|
||||
let subtitleNodeContainer: ASDisplayNode
|
||||
let subtitleNodeRawContainer: ASDisplayNode
|
||||
let subtitleNode: MultiScaleTextNode
|
||||
@ -189,6 +196,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
self.titleExpandedCredibilityIconView = ComponentHostView<Empty>()
|
||||
self.titleNode.stateNode(forKey: TitleNodeStateExpanded)?.view.addSubview(self.titleExpandedCredibilityIconView)
|
||||
|
||||
self.titleVerifiedIconView = ComponentHostView<Empty>()
|
||||
self.titleNode.stateNode(forKey: TitleNodeStateRegular)?.view.addSubview(self.titleVerifiedIconView)
|
||||
|
||||
self.titleExpandedVerifiedIconView = ComponentHostView<Empty>()
|
||||
self.titleNode.stateNode(forKey: TitleNodeStateExpanded)?.view.addSubview(self.titleExpandedVerifiedIconView)
|
||||
|
||||
self.subtitleNodeContainer = ASDisplayNode()
|
||||
self.subtitleNodeRawContainer = ASDisplayNode()
|
||||
self.subtitleNode = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
|
||||
@ -432,6 +445,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
private var currentCredibilityIcon: CredibilityIcon?
|
||||
private var currentVerifiedIcon: CredibilityIcon?
|
||||
|
||||
private var currentPanelStatusData: PeerInfoStatusData?
|
||||
func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, isMediaOnly: Bool, contentOffset: CGFloat, paneContainerY: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, threadData: MessageHistoryThreadData?, peerNotificationSettings: TelegramPeerNotificationSettings?, threadNotificationSettings: TelegramPeerNotificationSettings?, globalNotificationSettings: EngineGlobalNotificationSettings?, statusData: PeerInfoStatusData?, panelStatusData: (PeerInfoStatusData?, PeerInfoStatusData?, CGFloat?), isSecretChat: Bool, isContact: Bool, isSettings: Bool, state: PeerInfoState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition, additive: Bool, animateHeader: Bool) -> CGFloat {
|
||||
@ -471,12 +485,16 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
|
||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 })
|
||||
let credibilityIcon: CredibilityIcon
|
||||
var verifiedIcon: CredibilityIcon = .none
|
||||
if let peer = peer {
|
||||
if peer.isFake {
|
||||
credibilityIcon = .fake
|
||||
} else if peer.isScam {
|
||||
credibilityIcon = .scam
|
||||
} else if let emojiStatus = peer.emojiStatus, !premiumConfiguration.isPremiumDisabled {
|
||||
if peer is TelegramChannel, peer.isVerified {
|
||||
verifiedIcon = .verified
|
||||
}
|
||||
credibilityIcon = .emojiStatus(emojiStatus)
|
||||
} else if peer.isVerified {
|
||||
credibilityIcon = .verified
|
||||
@ -714,8 +732,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
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 iconSize = self.titleCredibilityIconView.update(
|
||||
transition: Transition(navigationTransition),
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
@ -796,6 +812,73 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
self.titleExpandedCredibilityIconSize = expandedIconSize
|
||||
}
|
||||
|
||||
do {
|
||||
self.currentVerifiedIcon = verifiedIcon
|
||||
|
||||
var currentEmojiStatus: PeerEmojiStatus?
|
||||
let emojiRegularStatusContent: EmojiStatusComponent.Content
|
||||
let emojiExpandedStatusContent: EmojiStatusComponent.Content
|
||||
switch verifiedIcon {
|
||||
case .none:
|
||||
emojiRegularStatusContent = .none
|
||||
emojiExpandedStatusContent = .none
|
||||
case .premium:
|
||||
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: navigationContentsAccentColor, foregroundColor: .clear, sizeType: .large)
|
||||
case .fake:
|
||||
emojiRegularStatusContent = .text(color: presentationData.theme.chat.message.incoming.scamColor, string: presentationData.strings.Message_FakeAccount.uppercased())
|
||||
emojiExpandedStatusContent = emojiRegularStatusContent
|
||||
case .scam:
|
||||
emojiRegularStatusContent = .text(color: presentationData.theme.chat.message.incoming.scamColor, string: presentationData.strings.Message_ScamAccount.uppercased())
|
||||
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: 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 iconSize = self.titleVerifiedIconView.update(
|
||||
transition: Transition(navigationTransition),
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
context: self.context,
|
||||
animationCache: self.animationCache,
|
||||
animationRenderer: self.animationRenderer,
|
||||
content: emojiRegularStatusContent,
|
||||
isVisibleForAnimations: true,
|
||||
useSharedAnimation: true,
|
||||
action: nil,
|
||||
emojiFileUpdated: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 34.0, height: 34.0)
|
||||
)
|
||||
let expandedIconSize = self.titleExpandedVerifiedIconView.update(
|
||||
transition: Transition(navigationTransition),
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
context: self.context,
|
||||
animationCache: self.animationCache,
|
||||
animationRenderer: self.animationRenderer,
|
||||
content: emojiExpandedStatusContent,
|
||||
isVisibleForAnimations: true,
|
||||
useSharedAnimation: true,
|
||||
action: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.displayPremiumIntro?(strongSelf.titleExpandedVerifiedIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), true)
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 34.0, height: 34.0)
|
||||
)
|
||||
|
||||
self.verifiedIconSize = iconSize
|
||||
self.titleExpandedVerifiedIconSize = expandedIconSize
|
||||
}
|
||||
|
||||
self.navigationButtonContainer.updateContentsColor(backgroundContentColor: headerButtonBackgroundColor, contentsColor: navigationContentsAccentColor, canBeExpanded: navigationContentsCanBeExpanded, transition: navigationTransition)
|
||||
|
||||
self.titleNode.updateTintColor(color: navigationContentsPrimaryColor, transition: navigationTransition)
|
||||
@ -1128,16 +1211,35 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
let usernameSize = usernameNodeLayout[TitleNodeStateRegular]!.size
|
||||
|
||||
var titleHorizontalOffset: CGFloat = 0.0
|
||||
var nextIconX: CGFloat = titleSize.width
|
||||
var nextExpandedIconX: CGFloat = titleExpandedSize.width
|
||||
|
||||
if let credibilityIconSize = self.credibilityIconSize, let titleExpandedCredibilityIconSize = self.titleExpandedCredibilityIconSize {
|
||||
titleHorizontalOffset = -(credibilityIconSize.width + 4.0) / 2.0
|
||||
titleHorizontalOffset += -(credibilityIconSize.width + 4.0) / 2.0
|
||||
|
||||
var collapsedTransitionOffset: CGFloat = 0.0
|
||||
if let navigationTransition = self.navigationTransition {
|
||||
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)), 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))
|
||||
transition.updateFrame(view: self.titleCredibilityIconView, frame: CGRect(origin: CGPoint(x: nextIconX + 4.0 + collapsedTransitionOffset, y: floor((titleSize.height - credibilityIconSize.height) / 2.0)), size: credibilityIconSize))
|
||||
nextIconX += 4.0 + credibilityIconSize.width
|
||||
transition.updateFrame(view: self.titleExpandedCredibilityIconView, frame: CGRect(origin: CGPoint(x: nextExpandedIconX + 4.0, y: floor((titleExpandedSize.height - titleExpandedCredibilityIconSize.height) / 2.0) + 1.0), size: titleExpandedCredibilityIconSize))
|
||||
nextExpandedIconX += 4.0 + titleExpandedCredibilityIconSize.width
|
||||
}
|
||||
|
||||
if let verifiedIconSize = self.verifiedIconSize, let titleExpandedVerifiedIconSize = self.titleExpandedVerifiedIconSize {
|
||||
titleHorizontalOffset += -(verifiedIconSize.width + 4.0) / 2.0
|
||||
|
||||
var collapsedTransitionOffset: CGFloat = 0.0
|
||||
if let navigationTransition = self.navigationTransition {
|
||||
collapsedTransitionOffset = -10.0 * navigationTransition.fraction
|
||||
}
|
||||
|
||||
transition.updateFrame(view: self.titleVerifiedIconView, frame: CGRect(origin: CGPoint(x: nextIconX + 4.0 + collapsedTransitionOffset, y: floor((titleSize.height - verifiedIconSize.height) / 2.0)), size: verifiedIconSize))
|
||||
nextIconX += 4.0 + verifiedIconSize.width
|
||||
transition.updateFrame(view: self.titleExpandedVerifiedIconView, frame: CGRect(origin: CGPoint(x: nextExpandedIconX + 4.0, y: floor((titleExpandedSize.height - titleExpandedVerifiedIconSize.height) / 2.0) + 1.0), size: titleExpandedVerifiedIconSize))
|
||||
nextExpandedIconX += 4.0 + titleExpandedVerifiedIconSize.width
|
||||
}
|
||||
|
||||
var titleFrame: CGRect
|
||||
|
@ -2257,6 +2257,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
private var translationState: ChatTranslationState?
|
||||
private var translationStateDisposable: Disposable?
|
||||
|
||||
private var boostStatus: ChannelBoostStatus?
|
||||
private var boostStatusDisposable: Disposable?
|
||||
|
||||
private var expiringStoryList: PeerExpiringStoryListContext?
|
||||
private var expiringStoryListState: PeerExpiringStoryListContext.State?
|
||||
private var expiringStoryListDisposable: Disposable?
|
||||
@ -4048,6 +4051,21 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
})
|
||||
|
||||
let _ = context.engine.peers.requestRecommendedChannels(peerId: peerId, forceUpdate: true).startStandalone()
|
||||
|
||||
self.boostStatusDisposable = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
||||
|> mapToSignal { peer -> Signal<ChannelBoostStatus?, NoError> in
|
||||
if case let .channel(channel) = peer, (channel.flags.contains(.isCreator) || channel.adminRights != nil) {
|
||||
return context.engine.peers.getChannelBoostStatus(peerId: peerId)
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { [weak self] boostStatus in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.boostStatus = boostStatus
|
||||
})
|
||||
}
|
||||
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel || peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
@ -4154,6 +4172,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
self.storyUploadProgressDisposable?.dispose()
|
||||
self.updateAvatarDisposable.dispose()
|
||||
self.joinChannelDisposable.dispose()
|
||||
self.boostStatusDisposable?.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -7196,7 +7215,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
let controller = PeerNameColorScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, subject: .account)
|
||||
self.controller?.push(controller)
|
||||
} else if let peer = self.data?.peer, peer is TelegramChannel {
|
||||
self.controller?.push(ChannelAppearanceScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peerId))
|
||||
self.controller?.push(ChannelAppearanceScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peerId, boostStatus: self.boostStatus))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,13 +134,16 @@ final class ChannelAppearanceScreenComponent: Component {
|
||||
|
||||
let context: AccountContext
|
||||
let peerId: EnginePeer.Id
|
||||
let boostStatus: ChannelBoostStatus?
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
peerId: EnginePeer.Id
|
||||
peerId: EnginePeer.Id,
|
||||
boostStatus: ChannelBoostStatus?
|
||||
) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.boostStatus = boostStatus
|
||||
}
|
||||
|
||||
static func ==(lhs: ChannelAppearanceScreenComponent, rhs: ChannelAppearanceScreenComponent) -> Bool {
|
||||
@ -322,6 +325,33 @@ final class ChannelAppearanceScreenComponent: Component {
|
||||
}
|
||||
|
||||
func attemptNavigation(complete: @escaping () -> Void) -> Bool {
|
||||
guard let component = self.component, let resolvedState = self.resolveState() else {
|
||||
return true
|
||||
}
|
||||
if self.isApplyingSettings {
|
||||
return false
|
||||
}
|
||||
|
||||
if !resolvedState.changes.isEmpty {
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.Channel_Appearance_UnsavedChangesAlertTitle, text: presentationData.strings.Channel_Appearance_UnsavedChangesAlertText, actions: [
|
||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Channel_Appearance_UnsavedChangesAlertDiscard, action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.environment?.controller()?.dismiss()
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Channel_Appearance_UnsavedChangesAlertApply, action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.applySettings()
|
||||
})
|
||||
]), in: .window(.root))
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -462,8 +492,15 @@ final class ChannelAppearanceScreenComponent: Component {
|
||||
}
|
||||
|
||||
var signals: [Signal<Never, ApplyError>] = []
|
||||
if !resolvedState.changes.intersection([.nameColor, .profileColor, .replyFileId, .backgroundFileId]).isEmpty {
|
||||
signals.append(component.context.engine.peers.updatePeerNameColorAndEmoji(peerId: component.peerId, nameColor: resolvedState.nameColor, backgroundEmojiId: resolvedState.replyFileId, profileColor: resolvedState.profileColor, profileBackgroundEmojiId: resolvedState.backgroundFileId)
|
||||
if !resolvedState.changes.intersection([.nameColor, .replyFileId]).isEmpty {
|
||||
signals.append(component.context.engine.peers.updatePeerNameColor(peerId: component.peerId, nameColor: resolvedState.nameColor, backgroundEmojiId: resolvedState.replyFileId)
|
||||
|> ignoreValues
|
||||
|> mapError { _ -> ApplyError in
|
||||
return .generic
|
||||
})
|
||||
}
|
||||
if !resolvedState.changes.intersection([.profileColor, .backgroundFileId]).isEmpty {
|
||||
signals.append(component.context.engine.peers.updatePeerProfileColor(peerId: component.peerId, profileColor: resolvedState.profileColor, profileBackgroundEmojiId: resolvedState.backgroundFileId)
|
||||
|> ignoreValues
|
||||
|> mapError { _ -> ApplyError in
|
||||
return .generic
|
||||
@ -512,7 +549,17 @@ final class ChannelAppearanceScreenComponent: Component {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let navigationController: NavigationController? = self.environment?.controller()?.navigationController as? NavigationController
|
||||
|
||||
self.environment?.controller()?.dismiss()
|
||||
|
||||
if let lastController = navigationController?.viewControllers.last as? ViewController {
|
||||
//TODO:localize
|
||||
let tipController = UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: nil, text: "Appearance settings have been updated.", cancel: nil, destructive: false), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false })
|
||||
lastController.present(tipController, in: .window(.root))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -733,8 +780,13 @@ final class ChannelAppearanceScreenComponent: Component {
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
if self.contentsData == nil, case let .channel(channel) = contentsData.peer {
|
||||
self.boostLevel = channel.approximateBoostLevel.flatMap(Int.init)
|
||||
if self.contentsData == nil && self.boostStatus == nil {
|
||||
if let boostStatus = component.boostStatus {
|
||||
self.boostStatus = boostStatus
|
||||
self.boostLevel = boostStatus.level
|
||||
} else if case let .channel(channel) = contentsData.peer {
|
||||
self.boostLevel = channel.approximateBoostLevel.flatMap(Int.init)
|
||||
}
|
||||
}
|
||||
if self.contentsData == nil, let peerWallpaper = contentsData.peerWallpaper {
|
||||
for cloudTheme in contentsData.availableThemes {
|
||||
@ -1448,13 +1500,15 @@ public class ChannelAppearanceScreen: ViewControllerComponentContainer {
|
||||
public init(
|
||||
context: AccountContext,
|
||||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?,
|
||||
peerId: EnginePeer.Id
|
||||
peerId: EnginePeer.Id,
|
||||
boostStatus: ChannelBoostStatus?
|
||||
) {
|
||||
self.context = context
|
||||
|
||||
super.init(context: context, component: ChannelAppearanceScreenComponent(
|
||||
context: context,
|
||||
peerId: peerId
|
||||
peerId: peerId,
|
||||
boostStatus: boostStatus
|
||||
), navigationBarAppearance: .default, theme: .default, updatedPresentationData: updatedPresentationData)
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
@ -1633,7 +1633,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
let attributedText = convertMarkdownToAttributes(NSAttributedString(string: serviceMessageText))
|
||||
let entities = generateChatInputTextEntities(attributedText)
|
||||
|
||||
let message3 = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message3 = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities, additionalAttributes: nil))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false))
|
||||
}
|
||||
|
||||
|
@ -277,16 +277,21 @@ public final class ChatTextInputTextCustomEmojiAttribute: NSObject, Codable {
|
||||
case topicInfo
|
||||
}
|
||||
|
||||
public enum Custom: Codable {
|
||||
case topic(id: Int64, info: EngineMessageHistoryThread.Info)
|
||||
case nameColors([UInt32])
|
||||
}
|
||||
|
||||
public let interactivelySelectedFromPackId: ItemCollectionId?
|
||||
public let fileId: Int64
|
||||
public let file: TelegramMediaFile?
|
||||
public let topicInfo: (Int64, EngineMessageHistoryThread.Info)?
|
||||
public let custom: Custom?
|
||||
|
||||
public init(interactivelySelectedFromPackId: ItemCollectionId?, fileId: Int64, file: TelegramMediaFile?, topicInfo: (Int64, EngineMessageHistoryThread.Info)? = nil) {
|
||||
public init(interactivelySelectedFromPackId: ItemCollectionId?, fileId: Int64, file: TelegramMediaFile?, custom: Custom? = nil) {
|
||||
self.interactivelySelectedFromPackId = interactivelySelectedFromPackId
|
||||
self.fileId = fileId
|
||||
self.file = file
|
||||
self.topicInfo = topicInfo
|
||||
self.custom = custom
|
||||
|
||||
super.init()
|
||||
}
|
||||
@ -296,11 +301,7 @@ public final class ChatTextInputTextCustomEmojiAttribute: NSObject, Codable {
|
||||
self.interactivelySelectedFromPackId = try container.decodeIfPresent(ItemCollectionId.self, forKey: .interactivelySelectedFromPackId)
|
||||
self.fileId = try container.decode(Int64.self, forKey: .fileId)
|
||||
self.file = try container.decodeIfPresent(TelegramMediaFile.self, forKey: .file)
|
||||
if let topicId = try container.decodeIfPresent(Int64.self, forKey: .topicId), let topicInfo = try container.decodeIfPresent(EngineMessageHistoryThread.Info.self, forKey: .topicInfo) {
|
||||
self.topicInfo = (topicId, topicInfo)
|
||||
} else {
|
||||
self.topicInfo = nil
|
||||
}
|
||||
self.custom = nil
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -308,16 +309,11 @@ public final class ChatTextInputTextCustomEmojiAttribute: NSObject, Codable {
|
||||
try container.encodeIfPresent(self.interactivelySelectedFromPackId, forKey: .interactivelySelectedFromPackId)
|
||||
try container.encode(self.fileId, forKey: .fileId)
|
||||
try container.encodeIfPresent(self.file, forKey: .file)
|
||||
if let (topicId, topicInfo) = self.topicInfo {
|
||||
try container.encode(topicId, forKey: .topicId)
|
||||
try container.encode(topicInfo, forKey: .topicInfo)
|
||||
}
|
||||
}
|
||||
|
||||
override public func isEqual(_ object: Any?) -> Bool {
|
||||
if let other = object as? ChatTextInputTextCustomEmojiAttribute {
|
||||
return self === other
|
||||
//return self.stickerPack == other.stickerPack && self.fileId == other.fileId && self.file?.fileId == other.file?.fileId
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ public enum UndoOverlayContent {
|
||||
case info(title: String?, text: String, timeout: Double?, customUndoText: String?)
|
||||
case emoji(name: String, text: String)
|
||||
case swipeToReply(title: String, text: String)
|
||||
case actionSucceeded(title: String, text: String, cancel: String, destructive: Bool)
|
||||
case actionSucceeded(title: String?, text: String, cancel: String?, destructive: Bool)
|
||||
case stickersModified(title: String, text: String, undo: Bool, info: StickerPackCollectionInfo, topItem: StickerPackItem?, context: AccountContext)
|
||||
case dice(dice: TelegramMediaDice, context: AccountContext, text: String, action: String?)
|
||||
case chatAddedToFolder(chatTitle: String, folderTitle: String)
|
||||
|
@ -262,10 +262,16 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
|
||||
let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: undoTextColor)
|
||||
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: link, linkAttribute: { _ in return nil }), textAlignment: .natural)
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
|
||||
if let title {
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
|
||||
}
|
||||
self.textNode.attributedText = attributedText
|
||||
displayUndo = true
|
||||
undoText = cancel
|
||||
if let cancel {
|
||||
displayUndo = true
|
||||
undoText = cancel
|
||||
} else {
|
||||
displayUndo = false
|
||||
}
|
||||
self.originalRemainingSeconds = 5
|
||||
case let .linkCopied(text):
|
||||
self.avatarNode = nil
|
||||
@ -1341,7 +1347,9 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white)
|
||||
let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: undoTextColor)
|
||||
let attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: link, linkAttribute: { _ in return nil }), textAlignment: .natural)
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
|
||||
if let title {
|
||||
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
|
||||
}
|
||||
self.textNode.attributedText = attributedText
|
||||
default:
|
||||
break
|
||||
|
Loading…
x
Reference in New Issue
Block a user