mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various improvements
This commit is contained in:
parent
f28303a1bf
commit
fc21b289a7
@ -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?)
|
||||
}
|
||||
|
@ -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
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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:
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"app": "10.6.2",
|
||||
"app": "10.6.4",
|
||||
"bazel": "6.4.0",
|
||||
"xcode": "15.1",
|
||||
"macos": "13.0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user