Various improvements

This commit is contained in:
Isaac 2024-01-26 20:14:16 +01:00
parent f28303a1bf
commit fc21b289a7
7 changed files with 159 additions and 27 deletions

View File

@ -9,7 +9,7 @@ public final class AdMessageAttribute: MessageAttribute {
public enum MessageTarget {
case peer(id: EnginePeer.Id, message: EngineMessage.Id?, startParam: String?)
case join(title: String, joinHash: String)
case join(title: String, joinHash: String, peer: EnginePeer?)
case webPage(title: String, url: String)
case botApp(peerId: EnginePeer.Id, app: BotApp, startParam: String?)
}

View File

@ -43,18 +43,40 @@ private class AdMessagesHistoryContextImpl {
case joinHash
case nameColor
case image
case peer
}
var title: String
var joinHash: String
var nameColor: PeerNameColor?
var image: TelegramMediaImage?
var peer: Peer?
init(title: String, joinHash: String, nameColor: PeerNameColor?, image: TelegramMediaImage?) {
init(title: String, joinHash: String, nameColor: PeerNameColor?, image: TelegramMediaImage?, peer: Peer?) {
self.title = title
self.joinHash = joinHash
self.nameColor = nameColor
self.image = image
self.peer = peer
}
static func ==(lhs: Invite, rhs: Invite) -> Bool {
if lhs.title != rhs.title {
return false
}
if lhs.joinHash != rhs.joinHash {
return false
}
if lhs.nameColor != rhs.nameColor {
return false
}
if lhs.image != rhs.image {
return false
}
if !arePeersEqual(lhs.peer, rhs.peer) {
return false
}
return true
}
init(from decoder: Decoder) throws {
@ -66,6 +88,9 @@ private class AdMessagesHistoryContextImpl {
self.image = (try container.decodeIfPresent(Data.self, forKey: .image)).flatMap { data in
return TelegramMediaImage(decoder: PostboxDecoder(buffer: MemoryBuffer(data: data)))
}
self.peer = (try container.decodeIfPresent(Data.self, forKey: .peer)).flatMap { data in
return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Peer
}
}
func encode(to encoder: Encoder) throws {
@ -79,6 +104,11 @@ private class AdMessagesHistoryContextImpl {
image.encode(encoder)
return encoder.makeData()
}, forKey: .image)
try container.encodeIfPresent(self.peer.flatMap { peer in
let encoder = PostboxEncoder()
encoder.encodeRootObject(peer)
return encoder.makeData()
}, forKey: .peer)
}
}
@ -272,7 +302,7 @@ private class AdMessagesHistoryContextImpl {
case let .peer(peerId):
target = .peer(id: peerId, message: self.messageId, startParam: self.startParam)
case let .invite(invite):
target = .join(title: invite.title, joinHash: invite.joinHash)
target = .join(title: invite.title, joinHash: invite.joinHash, peer: invite.peer.flatMap(EnginePeer.init))
case let .webPage(webPage):
target = .webPage(title: webPage.title, url: webPage.url)
case let .botApp(peerId, botApp):
@ -604,7 +634,8 @@ private class AdMessagesHistoryContextImpl {
title: title,
joinHash: chatInviteHash,
nameColor: PeerNameColor(rawValue: nameColor),
image: image
image: image,
peer: nil
))
case let .chatInvitePeek(chat, _):
if let peer = parseTelegramGroupOrChannel(chat: chat) {
@ -612,16 +643,20 @@ private class AdMessagesHistoryContextImpl {
title: peer.debugDisplayTitle,
joinHash: chatInviteHash,
nameColor: peer.nameColor,
image: nil
image: nil,
peer: peer
))
}
case let .chatInviteAlready(chat):
if let peer = parseTelegramGroupOrChannel(chat: chat) {
displayAvatar = false
target = .invite(CachedMessage.Target.Invite(
title: peer.debugDisplayTitle,
joinHash: chatInviteHash,
nameColor: peer.nameColor,
image: nil
image: nil,
peer: peer
))
}
}

View File

@ -31,6 +31,7 @@ import ChatMessageAttachedContentButtonNode
import MessageInlineBlockBackgroundView
import ComponentFlow
import PlainButtonComponent
import AvatarNode
public enum ChatMessageAttachedContentActionIcon {
case instant
@ -55,6 +56,28 @@ public struct ChatMessageAttachedContentNodeMediaFlags: OptionSet {
}
public final class ChatMessageAttachedContentNode: ASDisplayNode {
private enum InlineMedia: Equatable {
case media(Media)
case peerAvatar(EnginePeer)
static func ==(lhs: InlineMedia, rhs: InlineMedia) -> Bool {
switch lhs {
case let .media(lhsMedia):
if case let .media(rhsMedia) = rhs {
return lhsMedia.isSemanticallyEqual(to: rhsMedia)
} else {
return false
}
case let .peerAvatar(lhsPeer):
if case let .peerAvatar(rhsPeer) = rhs {
return lhsPeer.largeProfileImage == rhsPeer.largeProfileImage
} else {
return false
}
}
}
}
private var backgroundView: MessageInlineBlockBackgroundView?
private let transformContainer: ASDisplayNode
@ -72,7 +95,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
private var closeButton: ComponentView<Empty>?
private var closeButtonImage: UIImage?
private var inlineMediaValue: Media?
private var inlineMediaValue: InlineMedia?
//private var additionalImageBadgeNode: ChatMessageInteractiveMediaBadge?
private var linkHighlightingNode: LinkHighlightingNode?
@ -281,6 +304,8 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
}
var contentMediaInline = false
var contentMediaImagePeer: EnginePeer?
if let (media, flags) = mediaAndFlags {
contentMediaInline = flags.contains(.preferMediaInline)
@ -326,21 +351,25 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
} else if let _ = media as? TelegramMediaStory {
contentMediaValue = media
}
} else if let adAttribute = message.adAttribute, case let .join(_, _, peer) = adAttribute.target, let peer, peer.largeProfileImage != nil {
contentMediaInline = true
contentMediaImagePeer = peer
}
var maxWidth: CGFloat = .greatestFiniteMagnitude
let contentMediaContinueLayout: ((CGSize, Bool, Bool, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> ChatMessageInteractiveMediaNode)))?
let inlineMediaAndSize: (Media, CGSize)?
let inlineMediaAndSize: (InlineMedia, CGSize)?
if let contentMediaValue {
if contentMediaInline {
contentMediaContinueLayout = nil
if let image = contentMediaValue as? TelegramMediaImage {
inlineMediaAndSize = (image, CGSize(width: 54.0, height: 54.0))
inlineMediaAndSize = (.media(image), CGSize(width: 54.0, height: 54.0))
} else if let file = contentMediaValue as? TelegramMediaFile, !file.previewRepresentations.isEmpty {
inlineMediaAndSize = (file, CGSize(width: 54.0, height: 54.0))
inlineMediaAndSize = (.media(file), CGSize(width: 54.0, height: 54.0))
} else {
inlineMediaAndSize = nil
}
@ -368,6 +397,9 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
inlineMediaAndSize = nil
}
} else if let contentMediaImagePeer {
contentMediaContinueLayout = nil
inlineMediaAndSize = (.peerAvatar(contentMediaImagePeer), CGSize(width: 54.0, height: 54.0))
} else {
contentMediaContinueLayout = nil
inlineMediaAndSize = nil
@ -906,7 +938,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
inlineMedia = current
if let curentInlineMediaValue = self.inlineMediaValue {
updateMedia = !curentInlineMediaValue.isSemanticallyEqual(to: inlineMediaValue)
updateMedia = curentInlineMediaValue != inlineMediaValue
} else {
updateMedia = true
}
@ -929,25 +961,58 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
self.inlineMediaValue = inlineMediaValue
var fittedImageSize = inlineMediaSize
if let image = inlineMediaValue as? TelegramMediaImage {
if let dimensions = image.representations.last?.dimensions.cgSize {
fittedImageSize = dimensions.aspectFilled(inlineMediaSize)
}
} else if let file = inlineMediaValue as? TelegramMediaFile {
if let dimensions = file.dimensions?.cgSize {
fittedImageSize = dimensions.aspectFilled(inlineMediaSize)
switch inlineMediaValue {
case let .media(inlineMediaValue):
if let image = inlineMediaValue as? TelegramMediaImage {
if let dimensions = image.representations.last?.dimensions.cgSize {
fittedImageSize = dimensions.aspectFilled(inlineMediaSize)
}
} else if let file = inlineMediaValue as? TelegramMediaFile {
if let dimensions = file.dimensions?.cgSize {
fittedImageSize = dimensions.aspectFilled(inlineMediaSize)
}
}
case .peerAvatar:
fittedImageSize = inlineMediaSize
}
if updateMedia {
let resolvedInlineMediaValue = inlineMediaValue
if let image = resolvedInlineMediaValue as? TelegramMediaImage {
let updateInlineImageSignal = chatWebpageSnippetPhoto(account: context.account, userLocation: .peer(message.id.peerId), photoReference: .message(message: MessageReference(message), media: image), placeholderColor: mainColor.withMultipliedAlpha(0.1))
inlineMedia.setSignal(updateInlineImageSignal)
} else if let file = resolvedInlineMediaValue as? TelegramMediaFile, let representation = file.previewRepresentations.last {
let updateInlineImageSignal = chatWebpageSnippetFile(account: context.account, userLocation: .peer(message.id.peerId), mediaReference: .message(message: MessageReference(message), media: file), representation: representation)
inlineMedia.setSignal(updateInlineImageSignal)
switch resolvedInlineMediaValue {
case let .media(resolvedInlineMediaValue):
if let image = resolvedInlineMediaValue as? TelegramMediaImage {
let updateInlineImageSignal = chatWebpageSnippetPhoto(account: context.account, userLocation: .peer(message.id.peerId), photoReference: .message(message: MessageReference(message), media: image), placeholderColor: mainColor.withMultipliedAlpha(0.1))
inlineMedia.setSignal(updateInlineImageSignal)
} else if let file = resolvedInlineMediaValue as? TelegramMediaFile, let representation = file.previewRepresentations.last {
let updateInlineImageSignal = chatWebpageSnippetFile(account: context.account, userLocation: .peer(message.id.peerId), mediaReference: .message(message: MessageReference(message), media: file), representation: representation)
inlineMedia.setSignal(updateInlineImageSignal)
}
case let .peerAvatar(peer):
if let peerReference = PeerReference(peer._asPeer()) {
if let signal = peerAvatarImage(account: context.account, peerReference: peerReference, authorOfMessage: nil, representation: peer.largeProfileImage, displayDimensions: inlineMediaSize, clipStyle: .none, blurred: false, inset: 0.0, emptyColor: mainColor.withMultipliedAlpha(0.1), synchronousLoad: synchronousLoads, provideUnrounded: false) {
let updateInlineImageSignal = signal |> map { images -> (TransformImageArguments) -> DrawingContext? in
let image = images?.0
return { arguments in
guard let context = DrawingContext(size: arguments.drawingSize, scale: arguments.scale ?? 0.0, clear: true) else {
return nil
}
context.withFlippedContext { c in
if let cgImage = image?.cgImage {
c.draw(cgImage, in: CGRect(origin: CGPoint(), size: arguments.drawingSize))
}
}
addCorners(context, arguments: arguments)
return context
}
}
inlineMedia.setSignal(updateInlineImageSignal)
}
}
}
}

View File

@ -497,7 +497,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
for media in item.message.media {
switch media {
case _ as TelegramMediaImage, _ as TelegramMediaFile, _ as TelegramMediaStory:
mediaAndFlags = (media, ChatMessageAttachedContentNodeMediaFlags())
mediaAndFlags = (media, [.preferMediaInline])
default:
break
}

View File

@ -1266,6 +1266,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
if !force && message.areReactionsTags(accountPeerId: strongSelf.context.account.peerId) {
if !strongSelf.presentationInterfaceState.isPremium {
//TODO:localize
let context = strongSelf.context
var replaceImpl: ((ViewController) -> Void)?
let controller = PremiumDemoScreen(context: context, subject: .uniqueReactions, action: {
let controller = PremiumIntroScreen(context: context, source: .reactions)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
strongSelf.push(controller)
return
}
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
guard let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item else {
return
@ -3958,7 +3973,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
})
}
case let .join(_, joinHash):
case let .join(_, joinHash, _):
self.controllerInteraction?.openJoinLink(joinHash)
case let .webPage(_, url):
self.controllerInteraction?.openUrl(ChatControllerInteraction.OpenUrl(url: url, concealed: false, external: true))

View File

@ -14,6 +14,7 @@ import StickerPackPreviewUI
import TextNodeWithEntities
import ChatPresentationInterfaceState
import SavedTagNameAlertController
import PremiumUI
extension ChatControllerImpl {
func openMessageReactionContextMenu(message: Message, sourceView: ContextExtractedContentContainingView, gesture: ContextGesture?, value: MessageReaction.Reaction) {
@ -23,6 +24,22 @@ extension ChatControllerImpl {
}
if message.areReactionsTags(accountPeerId: self.context.account.peerId) {
if !self.presentationInterfaceState.isPremium {
//TODO:localize
let context = self.context
var replaceImpl: ((ViewController) -> Void)?
let controller = PremiumDemoScreen(context: context, subject: .uniqueReactions, action: {
let controller = PremiumIntroScreen(context: context, source: .reactions)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
self.push(controller)
return
}
let reactionFile: Signal<TelegramMediaFile?, NoError>
switch value {
case .builtin:

View File

@ -1,5 +1,5 @@
{
"app": "10.6.2",
"app": "10.6.4",
"bazel": "6.4.0",
"xcode": "15.1",
"macos": "13.0"