Comments update

This commit is contained in:
Ali 2020-09-08 19:10:33 +01:00
parent 892a3a177d
commit 2334adfa2b
24 changed files with 2488 additions and 2393 deletions

View File

@ -5789,3 +5789,5 @@ Any member of this group will be able to see messages in the channel.";
"ChatList.Search.Music_any" = "%@ audio files";
"Conversation.InputTextAnonymousPlaceholder" = "Send anonymously";
"DialogList.Replies" = "Replies";

View File

@ -15,6 +15,7 @@ import Emoji
private let deletedIcon = UIImage(bundleImageName: "Avatar/DeletedIcon")?.precomposed()
private let savedMessagesIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/SavedMessagesIcon"), color: .white)
private let archivedChatsIcon = UIImage(bundleImageName: "Avatar/ArchiveAvatarIcon")?.precomposed()
private let repliesIcon = generateTintedImage(image: UIImage(bundleImageName: "Avatar/RepliesMessagesIcon"), color: .white)
public func avatarPlaceholderFont(size: CGFloat) -> UIFont {
return Font.with(size: size, design: .round, traits: [.bold])
@ -100,6 +101,7 @@ private func ==(lhs: AvatarNodeState, rhs: AvatarNodeState) -> Bool {
private enum AvatarNodeIcon: Equatable {
case none
case savedMessagesIcon
case repliesIcon
case archivedChatsIcon(hiddenByDefault: Bool)
case editAvatarIcon
case deletedIcon
@ -109,6 +111,7 @@ public enum AvatarNodeImageOverride: Equatable {
case none
case image(TelegramMediaImageRepresentation)
case savedMessagesIcon
case repliesIcon
case archivedChatsIcon(hiddenByDefault: Bool)
case editAvatarIcon
case deletedIcon
@ -308,6 +311,9 @@ public final class AvatarNode: ASDisplayNode {
case .savedMessagesIcon:
representation = nil
icon = .savedMessagesIcon
case .repliesIcon:
representation = nil
icon = .repliesIcon
case let .archivedChatsIcon(hiddenByDefault):
representation = nil
icon = .archivedChatsIcon(hiddenByDefault: hiddenByDefault)
@ -452,6 +458,8 @@ public final class AvatarNode: ASDisplayNode {
colorsArray = grayscaleColors
} else if case .savedMessagesIcon = parameters.icon {
colorsArray = savedMessagesColors
} else if case .repliesIcon = parameters.icon {
colorsArray = savedMessagesColors
} else if case .editAvatarIcon = parameters.icon, let theme = parameters.theme {
colorsArray = [theme.list.itemAccentColor.withAlphaComponent(0.1).cgColor, theme.list.itemAccentColor.withAlphaComponent(0.1).cgColor]
} else if case let .archivedChatsIcon(hiddenByDefault) = parameters.icon, let theme = parameters.theme {
@ -506,6 +514,15 @@ public final class AvatarNode: ASDisplayNode {
if let savedMessagesIcon = savedMessagesIcon {
context.draw(savedMessagesIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - savedMessagesIcon.size.width) / 2.0), y: floor((bounds.size.height - savedMessagesIcon.size.height) / 2.0)), size: savedMessagesIcon.size))
}
} else if case .repliesIcon = parameters.icon {
let factor = bounds.size.width / 60.0
context.translateBy(x: bounds.size.width / 2.0, y: bounds.size.height / 2.0)
context.scaleBy(x: factor, y: -factor)
context.translateBy(x: -bounds.size.width / 2.0, y: -bounds.size.height / 2.0)
if let repliesIcon = repliesIcon {
context.draw(repliesIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - repliesIcon.size.width) / 2.0), y: floor((bounds.size.height - repliesIcon.size.height) / 2.0)), size: repliesIcon.size))
}
} else if case .editAvatarIcon = parameters.icon, let theme = parameters.theme, !parameters.hasImage {
context.translateBy(x: bounds.size.width / 2.0, y: bounds.size.height / 2.0)
context.scaleBy(x: 1.0, y: -1.0)

View File

@ -638,7 +638,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
if let peer = peer {
var overrideImage: AvatarNodeImageOverride?
if peer.id.isReplies {
overrideImage = .savedMessagesIcon
overrideImage = .repliesIcon
} else if peer.id == item.context.account.peerId && !displayAsMessage {
overrideImage = .savedMessagesIcon
} else if peer.isDeleted {
@ -1101,6 +1101,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.ChatList_ArchivedChatsTitle, font: titleFont, textColor: theme.titleColor)
} else if itemPeer.chatMainPeer?.id == item.context.account.peerId {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: titleFont, textColor: theme.titleColor)
} else if let id = itemPeer.chatMainPeer?.id, id.isReplies {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Replies, font: titleFont, textColor: theme.titleColor)
} else if let displayTitle = itemPeer.chatMainPeer?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) {
titleAttributedString = NSAttributedString(string: displayTitle, font: titleFont, textColor: item.index.messageIndex.id.peerId.namespace == Namespaces.Peer.SecretChat ? theme.secretTitleColor : theme.titleColor)
}

View File

@ -556,6 +556,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
if let user = peer as? TelegramUser {
if peer.id == item.context.account.peerId, case .generalSearch = item.peerMode {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: titleBoldFont, textColor: textColor)
} else if peer.id.isReplies {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Replies, font: titleBoldFont, textColor: textColor)
} else if let firstName = user.firstName, let lastName = user.lastName, !firstName.isEmpty, !lastName.isEmpty {
let string = NSMutableAttributedString()
switch item.displayOrder {
@ -747,6 +749,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
var overrideImage: AvatarNodeImageOverride?
if peer.id == item.context.account.peerId, case .generalSearch = item.peerMode {
overrideImage = .savedMessagesIcon
} else if peer.id.isReplies, case .generalSearch = item.peerMode {
overrideImage = .repliesIcon
} else if peer.isDeleted {
overrideImage = .deletedIcon
}

View File

@ -77,6 +77,8 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
if chatPeer.id == context.account.peerId {
self.avatarNode.setPeer(context: context, theme: (context.sharedContext.currentPresentationData.with { $0 }).theme, peer: peer, overrideImage: .savedMessagesIcon)
} else if chatPeer.id.isReplies {
self.avatarNode.setPeer(context: context, theme: (context.sharedContext.currentPresentationData.with { $0 }).theme, peer: peer, overrideImage: .repliesIcon)
} else {
var overrideImage: AvatarNodeImageOverride?
if chatPeer.isDeleted {

View File

@ -42,6 +42,8 @@ final class HashtagSearchControllerNode: ASDisplayNode {
var items: [String] = []
if peer?.id == context.account.peerId {
items.append(presentationData.strings.Conversation_SavedMessages)
} else if let id = peer?.id, id.isReplies {
items.append(presentationData.strings.DialogList_Replies)
} else {
items.append(peer?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) ?? "")
}

View File

@ -683,6 +683,8 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
if item.peer.id == item.context.account.peerId, case .threatSelfAsSaved = item.aliasHandling {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: currentBoldFont, textColor: titleColor)
} else if item.peer.id.isReplies {
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Replies, font: currentBoldFont, textColor: titleColor)
} else if let user = item.peer as? TelegramUser {
if let firstName = user.firstName, let lastName = user.lastName, !firstName.isEmpty, !lastName.isEmpty {
let string = NSMutableAttributedString()
@ -1059,6 +1061,8 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
if item.peer.id == item.context.account.peerId, case .threatSelfAsSaved = item.aliasHandling {
strongSelf.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: item.peer, overrideImage: .savedMessagesIcon, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoad)
} else if item.peer.id.isReplies {
strongSelf.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: item.peer, overrideImage: .repliesIcon, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoad)
} else {
var overrideImage: AvatarNodeImageOverride?
if item.peer.isDeleted {

View File

@ -149,6 +149,9 @@ public final class SelectablePeerNode: ASDisplayNode {
if peer.peerId == context.account.peerId {
text = strings.DialogList_SavedMessages
overrideImage = .savedMessagesIcon
} else if peer.peerId.isReplies {
text = strings.DialogList_Replies
overrideImage = .repliesIcon
} else {
text = mainPeer.compactDisplayTitle
if mainPeer.isDeleted {

View File

@ -74,20 +74,14 @@ private func updateMessageThreadStatsInternal(transaction: Transaction, threadMe
let countDifference = Int32(difference)
var attributes = currentMessage.attributes
var updated = false
loop: for j in 0 ..< attributes.count {
if let attribute = attributes[j] as? ReplyThreadMessageAttribute {
let count = max(0, attribute.count + countDifference)
attributes[j] = ReplyThreadMessageAttribute(count: count, latestUsers: mergeLatestUsers(current: attribute.latestUsers, added: addedMessagePeers, isGroup: isGroup, isEmpty: count == 0), commentsPeerId: attribute.commentsPeerId)
updated = true
} else if let attribute = attributes[j] as? SourceReferenceMessageAttribute {
channelThreadMessageId = attribute.messageId
}
}
if !updated && isGroup {
let count = max(0, countDifference)
attributes.append(ReplyThreadMessageAttribute(count: count, latestUsers: mergeLatestUsers(current: [], added: addedMessagePeers, isGroup: isGroup, isEmpty: count == 0), commentsPeerId: nil))
}
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init), authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
})

View File

@ -262,4 +262,5 @@ public enum PresentationResourceParameterKey: Hashable {
case chatMessageCommentsIcon(incoming: Bool)
case chatMessageCommentsArrowIcon(incoming: Bool)
case chatMessageRepliesIcon(incoming: Bool)
}

View File

@ -1099,6 +1099,14 @@ public struct PresentationResourcesChat {
})
}
public static func chatMessageRepliesIcon(_ theme: PresentationTheme, incoming: Bool) -> UIImage? {
return theme.image(PresentationResourceParameterKey.chatMessageRepliesIcon(incoming: incoming), { theme in
let messageTheme = incoming ? theme.chat.message.incoming : theme.chat.message.outgoing
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/BubbleReplies"), color: messageTheme.accentTextColor)
})
}
public static func chatMessageCommentsArrowIcon(_ theme: PresentationTheme, incoming: Bool) -> UIImage? {
return theme.image(PresentationResourceParameterKey.chatMessageCommentsArrowIcon(incoming: incoming), { theme in
let messageTheme = incoming ? theme.chat.message.incoming : theme.chat.message.outgoing

View File

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

View File

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

View File

@ -2425,6 +2425,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let imageOverride: AvatarNodeImageOverride?
if strongSelf.context.account.peerId == peer.id {
imageOverride = .savedMessagesIcon
} else if peer.id.isReplies {
imageOverride = .repliesIcon
} else if peer.isDeleted {
imageOverride = .deletedIcon
} else {

View File

@ -371,27 +371,32 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
return transaction.getPreferencesEntry(key: PreferencesKeys.limitsConfiguration) as? LimitsConfiguration ?? LimitsConfiguration.defaultValue
}
let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia]), NoError> = combineLatest(
let cachedData = context.account.postbox.transaction { transaction -> CachedPeerData? in
return transaction.getPeerCachedData(peerId: messages[0].id.peerId)
}
let dataSignal: Signal<(MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], CachedPeerData?), NoError> = combineLatest(
loadLimits,
loadStickerSaveStatusSignal,
loadResourceStatusSignal,
context.sharedContext.chatAvailableMessageActions(postbox: context.account.postbox, accountPeerId: context.account.peerId, messageIds: Set(messages.map { $0.id })),
context.account.pendingUpdateMessageManager.updatingMessageMedia
|> take(1)
|> take(1),
cachedData
)
|> map { limitsConfiguration, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia]) in
|> map { limitsConfiguration, stickerSaveStatus, resourceStatus, messageActions, updatingMessageMedia, cachedData -> (MessageContextMenuData, [MessageId: ChatUpdatingMessageMedia], CachedPeerData?) in
var canEdit = false
if !isAction {
let message = messages[0]
canEdit = canEditMessage(context: context, limitsConfiguration: limitsConfiguration, message: message)
}
return (MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions), updatingMessageMedia)
return (MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions), updatingMessageMedia, cachedData)
}
return dataSignal
|> deliverOnMainQueue
|> map { data, updatingMessageMedia -> [ContextMenuItem] in
|> map { data, updatingMessageMedia, cachedData -> [ContextMenuItem] in
var actions: [ContextMenuItem] = []
if let starStatus = data.starStatus {
@ -576,7 +581,7 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
var threadId: Int64?
var threadMessageCount: Int = 0
if case .peer = chatPresentationInterfaceState.chatLocation {
if case .peer = chatPresentationInterfaceState.chatLocation, let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .group = channel.info, let cachedData = cachedData as? CachedChannelData, case let .known(maybeValue) = cachedData.linkedDiscussionPeerId, let _ = maybeValue {
if let value = messages[0].threadId {
threadId = value
} else {

View File

@ -161,6 +161,8 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(
if canComment {
result.append((firstMessage, ChatMessageCommentFooterContentNode.self, ChatMessageEntryAttributes(), false))
}
} else if firstMessage.id.peerId.isReplies {
result.append((firstMessage, ChatMessageCommentFooterContentNode.self, ChatMessageEntryAttributes(), false))
}
}
@ -903,10 +905,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
var needShareButton = false
if isFailed || Namespaces.Message.allScheduled.contains(item.message.id.namespace) {
needShareButton = false
} else if item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
} else if item.message.id.peerId == item.context.account.peerId {
if let _ = sourceReference {
needShareButton = true
}
} else if item.message.id.peerId.isReplies {
needShareButton = false
} else if item.message.effectivelyIncoming(item.context.account.peerId) {
if let _ = sourceReference {
needShareButton = true
@ -1178,10 +1182,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
} else {
if inlineBotNameString == nil && (ignoreForward || firstMessage.forwardInfo == nil) && replyMessage == nil {
if let first = contentPropertiesAndLayouts.first, first.1.hidesSimpleAuthorHeader {
if let author = firstMessage.author as? TelegramChannel, case .group = author.info, author.id == firstMessage.id.peerId, !incoming {
} else {
initialDisplayHeader = false
}
}
}
}
if initialDisplayHeader && displayAuthorInfo {
if let peer = firstMessage.peers[firstMessage.id.peerId] as? TelegramChannel, case .broadcast = peer.info {

View File

@ -81,8 +81,17 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
guard let item = self.item else {
return
}
if item.message.id.peerId.isReplies {
for attribute in item.message.attributes {
if let attribute = attribute as? SourceReferenceMessageAttribute {
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId)
break
}
}
} else {
item.controllerInteraction.openMessageReplies(item.message.id)
}
}
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))) {
let textLayout = TextNode.asyncLayout(self.textNode)
@ -100,13 +109,7 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
let incoming = item.message.effectivelyIncoming(item.context.account.peerId)
var maxTextWidth = CGFloat.greatestFiniteMagnitude
for media in item.message.media {
if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, content.type == "telegram_background" || content.type == "telegram_theme" {
maxTextWidth = layoutConstants.wallpapers.maxTextWidth
break
}
}
let maxTextWidth = CGFloat.greatestFiniteMagnitude
let horizontalInset = layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right
@ -124,7 +127,9 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
//TODO:localize
let rawText: String
if dateReplies > 0 {
if item.message.id.peerId.isReplies {
rawText = "View Reply"
} else if dateReplies > 0 {
if dateReplies == 1 {
rawText = "1 Comment"
} else {
@ -144,7 +149,7 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
textLeftInset = 15.0 + imageSize * min(1.0, CGFloat(replyPeers.count)) + (imageSpacing) * max(0.0, min(2.0, CGFloat(replyPeers.count - 1)))
}
let textConstrainedSize = CGSize(width: min(maxTextWidth, constrainedSize.width - horizontalInset - textLeftInset - 20.0), height: constrainedSize.height)
let textConstrainedSize = CGSize(width: min(maxTextWidth, constrainedSize.width - horizontalInset - textLeftInset - 28.0), height: constrainedSize.height)
let attributedText: NSAttributedString
@ -166,9 +171,17 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
var suggestedBoundingWidth: CGFloat
suggestedBoundingWidth = textFrameWithoutInsets.width
suggestedBoundingWidth += layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right + textLeftInset + 20.0
suggestedBoundingWidth += layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right + textLeftInset + 28.0
let iconImage = PresentationResourcesChat.chatMessageCommentsIcon(item.presentationData.theme.theme, incoming: incoming)
let iconImage: UIImage?
let iconOffset: CGPoint
if item.message.id.peerId.isReplies {
iconImage = PresentationResourcesChat.chatMessageRepliesIcon(item.presentationData.theme.theme, incoming: incoming)
iconOffset = CGPoint(x: -4.0, y: -4.0)
} else {
iconImage = PresentationResourcesChat.chatMessageCommentsIcon(item.presentationData.theme.theme, incoming: incoming)
iconOffset = CGPoint()
}
let arrowImage = PresentationResourcesChat.chatMessageCommentsArrowIcon(item.presentationData.theme.theme, incoming: incoming)
return (suggestedBoundingWidth, { boundingWidth in
@ -212,12 +225,12 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
if let iconImage = iconImage {
strongSelf.iconNode.image = iconImage
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: 15.0, y: 6.0), size: iconImage.size)
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: 15.0 + iconOffset.x, y: 6.0 + iconOffset.y), size: iconImage.size)
}
if let arrowImage = arrowImage {
strongSelf.arrowNode.image = arrowImage
strongSelf.arrowNode.frame = CGRect(origin: CGPoint(x: boundingWidth - 27.0, y: 6.0), size: arrowImage.size)
strongSelf.arrowNode.frame = CGRect(origin: CGPoint(x: boundingWidth - 33.0, y: 6.0), size: arrowImage.size)
}
strongSelf.iconNode.isHidden = !replyPeers.isEmpty

View File

@ -131,7 +131,7 @@ private func messagesShouldBeMerged(accountPeerId: PeerId, _ lhs: Message, _ rhs
}
var sameAuthor = false
if lhsEffectiveAuthor?.id == rhsEffectiveAuthor?.id {
if lhsEffectiveAuthor?.id == rhsEffectiveAuthor?.id && lhs.effectivelyIncoming(accountPeerId) == rhs.effectivelyIncoming(accountPeerId) {
sameAuthor = true
}

View File

@ -18,6 +18,8 @@ import CounterContollerTitleView
private func peerTokenTitle(accountPeerId: PeerId, peer: Peer, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder) -> String {
if peer.id == accountPeerId {
return strings.DialogList_SavedMessages
} else if peer.id.isReplies {
return strings.DialogList_Replies
} else {
return peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)
}

View File

@ -2851,6 +2851,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
if let peer = peer {
if peer.id == self.context.account.peerId && !self.isSettings {
titleString = NSAttributedString(string: presentationData.strings.Conversation_SavedMessages, font: Font.medium(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
} else if peer.id == self.context.account.peerId && !self.isSettings {
titleString = NSAttributedString(string: presentationData.strings.DialogList_Replies, font: Font.medium(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
} else {
titleString = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.medium(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
}