Avatar improvements

This commit is contained in:
Ilya Laktyushin 2022-12-18 10:42:03 +04:00
parent 8cdd2076d4
commit 2d5df7debc
4 changed files with 93 additions and 97 deletions

View File

@ -8475,15 +8475,17 @@ Sorry for the inconvenience.";
"UserInfo.ResetToOriginalAlertReset" = "Reset"; "UserInfo.ResetToOriginalAlertReset" = "Reset";
"Conversation.SuggestedPhotoTitle" = "Suggested Photo"; "Conversation.SuggestedPhotoTitle" = "Suggested Photo";
"Conversation.SuggestedPhotoText" = "%@ suggests you to use this photo for your Telegram account."; "Conversation.SuggestedPhotoText" = "**%@** suggests you to use this profile photo.";
"Conversation.SuggestedPhotoTextYou" = "You suggested %@ to use this photo for their Telegram account."; "Conversation.SuggestedPhotoTextExpanded" = "%@ suggests you to use this profile photo for your Telegram account.";
"Conversation.SuggestedPhotoView" = "View"; "Conversation.SuggestedPhotoTextYou" = "You suggested **%@** to use this profile photo.";
"Conversation.SuggestedPhotoView" = "View Photo";
"Conversation.SuggestedPhotoSuccess" = "You have updated your Telegram account photo."; "Conversation.SuggestedPhotoSuccess" = "You have updated your Telegram account photo.";
"Conversation.SuggestedVideoTitle" = "Suggested Video"; "Conversation.SuggestedVideoTitle" = "Suggested Video";
"Conversation.SuggestedVideoText" = "%@ suggests you to use this video for your Telegram account."; "Conversation.SuggestedVideoText" = "**%@** suggests you to use this profile video.";
"Conversation.SuggestedVideoTextYou" = "You suggested %@ to use this video for their Telegram account."; "Conversation.SuggestedVideoTextExpanded" = "%@ suggests you to use this profile video for your Telegram account.";
"Conversation.SuggestedVideoView" = "View"; "Conversation.SuggestedVideoTextYou" = "You suggested **%@** to use this profile video.";
"Conversation.SuggestedVideoView" = "View Video";
"Conversation.SuggestedVideoSuccess" = "You have updated your Telegram account video."; "Conversation.SuggestedVideoSuccess" = "You have updated your Telegram account video.";
"CacheEvictionMenu.CategoryExceptions_1" = "%@ Exception"; "CacheEvictionMenu.CategoryExceptions_1" = "%@ Exception";

View File

@ -202,7 +202,7 @@ const CGFloat TGPhotoAvatarPreviewLandscapePanelSize = TGPhotoAvatarPreviewPanel
[_titleLabel sizeToFit]; [_titleLabel sizeToFit];
[_wrapperView addSubview:_titleLabel]; [_wrapperView addSubview:_titleLabel];
NSMutableAttributedString *subtitle = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:self.item.isVideo ? TGLocalized(@"Conversation.SuggestedVideoText") : TGLocalized(@"Conversation.SuggestedPhotoText"), _senderName]]; NSMutableAttributedString *subtitle = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:self.item.isVideo ? TGLocalized(@"Conversation.SuggestedVideoTextExpanded") : TGLocalized(@"Conversation.SuggestedPhotoTextExpanded"), _senderName]];
[subtitle addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, subtitle.string.length)]; [subtitle addAttribute:NSForegroundColorAttributeName value:[UIColor whiteColor] range:NSMakeRange(0, subtitle.string.length)];
[subtitle addAttribute:NSFontAttributeName value:TGSystemFontOfSize(15.0f) range:NSMakeRange(0, subtitle.string.length)]; [subtitle addAttribute:NSFontAttributeName value:TGSystemFontOfSize(15.0f) range:NSMakeRange(0, subtitle.string.length)];

View File

@ -77,12 +77,12 @@ private final class SelectivePrivacySettingsControllerArguments {
private enum SelectivePrivacySettingsSection: Int32 { private enum SelectivePrivacySettingsSection: Int32 {
case forwards case forwards
case setting case setting
case photo
case peers case peers
case callsP2P case callsP2P
case callsP2PPeers case callsP2PPeers
case callsIntegrationEnabled case callsIntegrationEnabled
case phoneDiscovery case phoneDiscovery
case photo
} }
private func stringForUserCount(_ peers: [PeerId: SelectivePrivacyPeer], strings: PresentationStrings) -> String { private func stringForUserCount(_ peers: [PeerId: SelectivePrivacyPeer], strings: PresentationStrings) -> String {
@ -105,9 +105,6 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
case contacts(PresentationTheme, String, Bool) case contacts(PresentationTheme, String, Bool)
case nobody(PresentationTheme, String, Bool) case nobody(PresentationTheme, String, Bool)
case settingInfo(PresentationTheme, String, String) case settingInfo(PresentationTheme, String, String)
case setPublicPhoto(PresentationTheme, String)
case removePublicPhoto(PresentationTheme, String, EnginePeer, TelegramMediaImage?, UIImage?)
case publicPhotoInfo(PresentationTheme, String)
case exceptionsHeader(PresentationTheme, String) case exceptionsHeader(PresentationTheme, String)
case disableFor(PresentationTheme, String, String) case disableFor(PresentationTheme, String, String)
case enableFor(PresentationTheme, String, String) case enableFor(PresentationTheme, String, String)
@ -126,6 +123,9 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
case phoneDiscoveryEverybody(PresentationTheme, String, Bool) case phoneDiscoveryEverybody(PresentationTheme, String, Bool)
case phoneDiscoveryMyContacts(PresentationTheme, String, Bool) case phoneDiscoveryMyContacts(PresentationTheme, String, Bool)
case phoneDiscoveryInfo(PresentationTheme, String, String) case phoneDiscoveryInfo(PresentationTheme, String, String)
case setPublicPhoto(PresentationTheme, String)
case removePublicPhoto(PresentationTheme, String, EnginePeer, TelegramMediaImage?, UIImage?)
case publicPhotoInfo(PresentationTheme, String)
var section: ItemListSectionId { var section: ItemListSectionId {
switch self { switch self {
@ -133,8 +133,6 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
return SelectivePrivacySettingsSection.forwards.rawValue return SelectivePrivacySettingsSection.forwards.rawValue
case .settingHeader, .everybody, .contacts, .nobody, .settingInfo: case .settingHeader, .everybody, .contacts, .nobody, .settingInfo:
return SelectivePrivacySettingsSection.setting.rawValue return SelectivePrivacySettingsSection.setting.rawValue
case .setPublicPhoto, .removePublicPhoto, .publicPhotoInfo:
return SelectivePrivacySettingsSection.photo.rawValue
case .exceptionsHeader, .disableFor, .enableFor, .peersInfo: case .exceptionsHeader, .disableFor, .enableFor, .peersInfo:
return SelectivePrivacySettingsSection.peers.rawValue return SelectivePrivacySettingsSection.peers.rawValue
case .callsP2PHeader, .callsP2PAlways, .callsP2PContacts, .callsP2PNever, .callsP2PInfo: case .callsP2PHeader, .callsP2PAlways, .callsP2PContacts, .callsP2PNever, .callsP2PInfo:
@ -145,6 +143,8 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
return SelectivePrivacySettingsSection.callsIntegrationEnabled.rawValue return SelectivePrivacySettingsSection.callsIntegrationEnabled.rawValue
case .phoneDiscoveryHeader, .phoneDiscoveryEverybody, .phoneDiscoveryMyContacts, .phoneDiscoveryInfo: case .phoneDiscoveryHeader, .phoneDiscoveryEverybody, .phoneDiscoveryMyContacts, .phoneDiscoveryInfo:
return SelectivePrivacySettingsSection.phoneDiscovery.rawValue return SelectivePrivacySettingsSection.phoneDiscovery.rawValue
case .setPublicPhoto, .removePublicPhoto, .publicPhotoInfo:
return SelectivePrivacySettingsSection.photo.rawValue
} }
} }
@ -164,48 +164,48 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
return 5 return 5
case .settingInfo: case .settingInfo:
return 6 return 6
case .setPublicPhoto:
return 7
case .removePublicPhoto:
return 8
case .publicPhotoInfo:
return 9
case .phoneDiscoveryHeader: case .phoneDiscoveryHeader:
return 10 return 7
case .phoneDiscoveryEverybody: case .phoneDiscoveryEverybody:
return 11 return 8
case .phoneDiscoveryMyContacts: case .phoneDiscoveryMyContacts:
return 12 return 9
case .phoneDiscoveryInfo: case .phoneDiscoveryInfo:
return 13 return 10
case .exceptionsHeader: case .exceptionsHeader:
return 14 return 11
case .disableFor: case .disableFor:
return 15 return 12
case .enableFor: case .enableFor:
return 16 return 13
case .peersInfo: case .peersInfo:
return 17 return 14
case .callsP2PHeader: case .callsP2PHeader:
return 18 return 15
case .callsP2PAlways: case .callsP2PAlways:
return 19 return 16
case .callsP2PContacts: case .callsP2PContacts:
return 20 return 17
case .callsP2PNever: case .callsP2PNever:
return 21 return 18
case .callsP2PInfo: case .callsP2PInfo:
return 22 return 19
case .callsP2PDisableFor: case .callsP2PDisableFor:
return 23 return 20
case .callsP2PEnableFor: case .callsP2PEnableFor:
return 24 return 21
case .callsP2PPeersInfo: case .callsP2PPeersInfo:
return 25 return 22
case .callsIntegrationEnabled: case .callsIntegrationEnabled:
return 26 return 23
case .callsIntegrationInfo: case .callsIntegrationInfo:
return 27 return 24
case .setPublicPhoto:
return 24
case .removePublicPhoto:
return 25
case .publicPhotoInfo:
return 26
} }
} }
@ -247,24 +247,6 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .setPublicPhoto(lhsTheme, lhsText):
if case let .setPublicPhoto(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .removePublicPhoto(lhsTheme, lhsText, lhsPeer, lhsRep, lhsImage):
if case let .removePublicPhoto(rhsTheme, rhsText, rhsPeer, rhsRep, rhsImage) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsPeer == rhsPeer, lhsRep == rhsRep, lhsImage === rhsImage {
return true
} else {
return false
}
case let .publicPhotoInfo(lhsTheme, lhsText):
if case let .publicPhotoInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .exceptionsHeader(lhsTheme, lhsText): case let .exceptionsHeader(lhsTheme, lhsText):
if case let .exceptionsHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { if case let .exceptionsHeader(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true return true
@ -379,6 +361,24 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .setPublicPhoto(lhsTheme, lhsText):
if case let .setPublicPhoto(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .removePublicPhoto(lhsTheme, lhsText, lhsPeer, lhsRep, lhsImage):
if case let .removePublicPhoto(rhsTheme, rhsText, rhsPeer, rhsRep, rhsImage) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsPeer == rhsPeer, lhsRep == rhsRep, lhsImage === rhsImage {
return true
} else {
return false
}
case let .publicPhotoInfo(lhsTheme, lhsText):
if case let .publicPhotoInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
} }
} }
@ -411,17 +411,6 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { _ in return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { _ in
arguments.copyPhoneLink?(link) arguments.copyPhoneLink?(link)
}) })
case let .setPublicPhoto(theme, text):
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addPhotoIcon(theme), title: text, sectionId: self.section, height: .generic, color: .accent, editing: false, action: {
arguments.setPublicPhoto?()
})
case let .removePublicPhoto(_, text, peer, image, completeImage):
return ItemListPeerActionItem(presentationData: presentationData, icon: completeImage, iconSignal: completeImage == nil ? peerAvatarCompleteImage(account: arguments.context.account, peer: peer, forceProvidedRepresentation: true, representation: image?.representationForDisplayAtSize(PixelDimensions(width: 28, height: 28)), size: CGSize(width: 28.0, height: 28.0)) : nil, title: text, sectionId: self.section, height: .generic, color: .destructive, editing: false, action: {
arguments.removePublicPhoto?()
})
case let .publicPhotoInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { _ in
})
case let .exceptionsHeader(_, text): case let .exceptionsHeader(_, text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .disableFor(_, title, value): case let .disableFor(_, title, value):
@ -480,6 +469,17 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { _ in return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { _ in
arguments.copyPhoneLink?(link) arguments.copyPhoneLink?(link)
}) })
case let .setPublicPhoto(theme, text):
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addPhotoIcon(theme), title: text, sectionId: self.section, height: .generic, color: .accent, editing: false, action: {
arguments.setPublicPhoto?()
})
case let .removePublicPhoto(_, text, peer, image, completeImage):
return ItemListPeerActionItem(presentationData: presentationData, icon: completeImage, iconSignal: completeImage == nil ? peerAvatarCompleteImage(account: arguments.context.account, peer: peer, forceProvidedRepresentation: true, representation: image?.representationForDisplayAtSize(PixelDimensions(width: 28, height: 28)), size: CGSize(width: 28.0, height: 28.0)) : nil, title: text, sectionId: self.section, height: .generic, color: .destructive, editing: false, action: {
arguments.removePublicPhoto?()
})
case let .publicPhotoInfo(_, text):
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { _ in
})
} }
} }
} }
@ -670,9 +670,9 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
entries.append(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody)) entries.append(.everybody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenEverybody, state.setting == .everybody))
entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts)) entries.append(.contacts(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenContacts, state.setting == .contacts))
switch kind { switch kind {
case .presence, .voiceCalls, .forwards, .phoneNumber, .voiceMessages: case .presence, .voiceCalls, .forwards, .phoneNumber, .voiceMessages, .profilePhoto:
entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody)) entries.append(.nobody(presentationData.theme, presentationData.strings.PrivacySettings_LastSeenNobody, state.setting == .nobody))
case .groupInvitations, .profilePhoto: case .groupInvitations:
break break
} }
let phoneLink = "https://t.me/+\(phoneNumber)" let phoneLink = "https://t.me/+\(phoneNumber)"
@ -687,16 +687,6 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
entries.append(.phoneDiscoveryInfo(presentationData.theme, state.phoneDiscoveryEnabled != false ? presentationData.strings.PrivacyPhoneNumberSettings_CustomPublicLink("+\(phoneNumber)").string : presentationData.strings.PrivacyPhoneNumberSettings_CustomDisabledHelp, phoneLink)) entries.append(.phoneDiscoveryInfo(presentationData.theme, state.phoneDiscoveryEnabled != false ? presentationData.strings.PrivacyPhoneNumberSettings_CustomPublicLink("+\(phoneNumber)").string : presentationData.strings.PrivacyPhoneNumberSettings_CustomDisabledHelp, phoneLink))
} }
if case .profilePhoto = kind, let peer = peer, state.setting != .everybody {
if let publicPhoto = publicPhoto {
entries.append(.setPublicPhoto(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto_UpdatePublicPhoto))
entries.append(.removePublicPhoto(presentationData.theme, !publicPhoto.videoRepresentations.isEmpty ? presentationData.strings.Privacy_ProfilePhoto_RemovePublicVideo : presentationData.strings.Privacy_ProfilePhoto_RemovePublicPhoto, peer, publicPhoto, state.uploadedPhoto))
} else {
entries.append(.setPublicPhoto(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto_SetPublicPhoto))
}
entries.append(.publicPhotoInfo(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto_PublicPhotoInfo))
}
entries.append(.exceptionsHeader(presentationData.theme, presentationData.strings.GroupInfo_Permissions_Exceptions)) entries.append(.exceptionsHeader(presentationData.theme, presentationData.strings.GroupInfo_Permissions_Exceptions))
switch state.setting { switch state.setting {
@ -737,6 +727,16 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
} }
} }
if case .profilePhoto = kind, let peer = peer, state.setting != .everybody || !state.disableFor.isEmpty {
if let publicPhoto = publicPhoto {
entries.append(.setPublicPhoto(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto_UpdatePublicPhoto))
entries.append(.removePublicPhoto(presentationData.theme, !publicPhoto.videoRepresentations.isEmpty ? presentationData.strings.Privacy_ProfilePhoto_RemovePublicVideo : presentationData.strings.Privacy_ProfilePhoto_RemovePublicPhoto, peer, publicPhoto, state.uploadedPhoto))
} else {
entries.append(.setPublicPhoto(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto_SetPublicPhoto))
}
entries.append(.publicPhotoInfo(presentationData.theme, presentationData.strings.Privacy_ProfilePhoto_PublicPhotoInfo))
}
return entries return entries
} }

View File

@ -17,11 +17,11 @@ import PhotoResources
import UniversalMediaPlayer import UniversalMediaPlayer
import TelegramUniversalVideoContent import TelegramUniversalVideoContent
import GalleryUI import GalleryUI
import Markdown
class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode { class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode {
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode? private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?
private let mediaBackgroundNode: NavigationBackgroundNode private let mediaBackgroundNode: NavigationBackgroundNode
private let titleNode: TextNode
private let subtitleNode: TextNode private let subtitleNode: TextNode
private let imageNode: TransformImageNode private let imageNode: TransformImageNode
@ -42,10 +42,6 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
self.mediaBackgroundNode.clipsToBounds = true self.mediaBackgroundNode.clipsToBounds = true
self.mediaBackgroundNode.cornerRadius = 24.0 self.mediaBackgroundNode.cornerRadius = 24.0
self.titleNode = TextNode()
self.titleNode.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = false
self.subtitleNode = TextNode() self.subtitleNode = TextNode()
self.subtitleNode.isUserInteractionEnabled = false self.subtitleNode.isUserInteractionEnabled = false
self.subtitleNode.displaysAsynchronously = false self.subtitleNode.displaysAsynchronously = false
@ -65,7 +61,6 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
super.init() super.init()
self.addSubnode(self.mediaBackgroundNode) self.addSubnode(self.mediaBackgroundNode)
self.addSubnode(self.titleNode)
self.addSubnode(self.subtitleNode) self.addSubnode(self.subtitleNode)
self.addSubnode(self.imageNode) self.addSubnode(self.imageNode)
@ -152,7 +147,6 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
} }
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) { override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
let makeImageLayout = self.imageNode.asyncLayout() let makeImageLayout = self.imageNode.asyncLayout()
let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode) let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode)
let makeButtonTitleLayout = TextNode.asyncLayout(self.buttonTitleNode) let makeButtonTitleLayout = TextNode.asyncLayout(self.buttonTitleNode)
@ -181,8 +175,6 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
let isVideo = !(photo?.videoRepresentations.isEmpty ?? true) let isVideo = !(photo?.videoRepresentations.isEmpty ?? true)
let fromYou = item.message.author?.id == item.context.account.peerId let fromYou = item.message.author?.id == item.context.account.peerId
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: isVideo ? item.presentationData.strings.Conversation_SuggestedVideoTitle : item.presentationData.strings.Conversation_SuggestedPhotoTitle, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
let peerName = item.message.peers[item.message.id.peerId].flatMap { EnginePeer($0).compactDisplayTitle } ?? "" let peerName = item.message.peers[item.message.id.peerId].flatMap { EnginePeer($0).compactDisplayTitle } ?? ""
let text: String let text: String
if fromYou { if fromYou {
@ -191,11 +183,18 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
text = isVideo ? item.presentationData.strings.Conversation_SuggestedVideoText(peerName).string : item.presentationData.strings.Conversation_SuggestedPhotoText(peerName).string text = isVideo ? item.presentationData.strings.Conversation_SuggestedVideoText(peerName).string : item.presentationData.strings.Conversation_SuggestedPhotoText(peerName).string
} }
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: text, font: Font.regular(13.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) let body = MarkdownAttributeSet(font: Font.regular(13.0), textColor: primaryTextColor)
let bold = MarkdownAttributeSet(font: Font.semibold(13.0), textColor: primaryTextColor)
let subtitle = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in
return nil
}), textAlignment: .center)
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: subtitle, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: isVideo ? item.presentationData.strings.Conversation_SuggestedVideoView : item.presentationData.strings.Conversation_SuggestedPhotoView, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: isVideo ? item.presentationData.strings.Conversation_SuggestedVideoView : item.presentationData.strings.Conversation_SuggestedPhotoView, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
let backgroundSize = CGSize(width: width, height: titleLayout.size.height + subtitleLayout.size.height + 182.0) let backgroundSize = CGSize(width: width, height: subtitleLayout.size.height + 182.0)
return (backgroundSize.width, { boundingWidth in return (backgroundSize.width, { boundingWidth in
return (backgroundSize, { [weak self] animation, synchronousLoads, _ in return (backgroundSize, { [weak self] animation, synchronousLoads, _ in
@ -256,22 +255,17 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
videoNode.removeFromSupernode() videoNode.removeFromSupernode()
} }
let backgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - width) / 2.0), y: 0.0), size: backgroundSize) let mediaBackgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - width) / 2.0), y: 0.0), size: backgroundSize)
let mediaBackgroundFrame = backgroundFrame.insetBy(dx: -2.0, dy: -2.0)
strongSelf.mediaBackgroundNode.frame = mediaBackgroundFrame strongSelf.mediaBackgroundNode.frame = mediaBackgroundFrame
strongSelf.mediaBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate) strongSelf.mediaBackgroundNode.updateColor(color: selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper), transition: .immediate)
strongSelf.mediaBackgroundNode.update(size: mediaBackgroundFrame.size, transition: .immediate) strongSelf.mediaBackgroundNode.update(size: mediaBackgroundFrame.size, transition: .immediate)
strongSelf.buttonNode.backgroundColor = item.presentationData.theme.theme.overallDarkAppearance ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12) strongSelf.buttonNode.backgroundColor = item.presentationData.theme.theme.overallDarkAppearance ? UIColor(rgb: 0xffffff, alpha: 0.12) : UIColor(rgb: 0x000000, alpha: 0.12)
let _ = titleApply()
let _ = subtitleApply() let _ = subtitleApply()
let _ = buttonTitleApply() let _ = buttonTitleApply()
let titleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - titleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 127.0), size: titleLayout.size) let subtitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 127.0), size: subtitleLayout.size)
strongSelf.titleNode.frame = titleFrame
let subtitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0) , y: titleFrame.maxY + 2.0), size: subtitleLayout.size)
strongSelf.subtitleNode.frame = subtitleFrame strongSelf.subtitleNode.frame = subtitleFrame
let buttonTitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonTitleLayout.size.width) / 2.0), y: subtitleFrame.maxY + 18.0), size: buttonTitleLayout.size) let buttonTitleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonTitleLayout.size.width) / 2.0), y: subtitleFrame.maxY + 18.0), size: buttonTitleLayout.size)