Fix reaction images

This commit is contained in:
Ali
2022-01-13 23:02:56 +04:00
parent b9831396f8
commit d3b3592a5d
5 changed files with 67 additions and 40 deletions

View File

@@ -65,7 +65,7 @@ public final class ReactionImageNode: ASDisplayNode {
private let iconNode: ASImageNode private let iconNode: ASImageNode
public init(context: AccountContext, availableReactions: AvailableReactions?, reaction: String) { public init(context: AccountContext, availableReactions: AvailableReactions?, reaction: String, displayPixelSize: CGSize) {
self.iconNode = ASImageNode() self.iconNode = ASImageNode()
var file: TelegramMediaFile? var file: TelegramMediaFile?
@@ -80,8 +80,8 @@ public final class ReactionImageNode: ASDisplayNode {
} }
} }
if let animationFile = animationFile { if let animationFile = animationFile {
self.size = animationFile.dimensions?.cgSize ?? CGSize(width: 32.0, height: 32.0) self.size = animationFile.dimensions?.cgSize ?? displayPixelSize
var displaySize = self.size.aspectFitted(CGSize(width: 20.0, height: 20.0)) var displaySize = self.size.aspectFitted(displayPixelSize)
displaySize.width = floor(displaySize.width * 2.0) displaySize.width = floor(displaySize.width * 2.0)
displaySize.height = floor(displaySize.height * 2.0) displaySize.height = floor(displaySize.height * 2.0)
self.isAnimation = true self.isAnimation = true
@@ -101,7 +101,7 @@ public final class ReactionImageNode: ASDisplayNode {
} }
}) })
} else if let file = file { } else if let file = file {
self.size = file.dimensions?.cgSize ?? CGSize(width: 32.0, height: 32.0) self.size = file.dimensions?.cgSize ?? displayPixelSize
self.isAnimation = false self.isAnimation = false
super.init() super.init()
@@ -119,7 +119,7 @@ public final class ReactionImageNode: ASDisplayNode {
} }
}) })
} else { } else {
self.size = CGSize(width: 32.0, height: 32.0) self.size = displayPixelSize
self.isAnimation = false self.isAnimation = false
super.init() super.init()
} }

View File

@@ -126,7 +126,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
self.titleLabelNode.isUserInteractionEnabled = false self.titleLabelNode.isUserInteractionEnabled = false
if let reaction = reaction { if let reaction = reaction {
self.reactionIconNode = ReactionImageNode(context: context, availableReactions: availableReactions, reaction: reaction) self.reactionIconNode = ReactionImageNode(context: context, availableReactions: availableReactions, reaction: reaction, displayPixelSize: CGSize(width: 30.0 * UIScreenScale, height: 30.0 * UIScreenScale))
self.reactionIconNode?.isUserInteractionEnabled = false self.reactionIconNode?.isUserInteractionEnabled = false
self.iconNode = nil self.iconNode = nil
} else { } else {
@@ -354,7 +354,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
let reaction: String? = item.reaction let reaction: String? = item.reaction
if let reaction = reaction { if let reaction = reaction {
if self.reactionIconNode == nil { if self.reactionIconNode == nil {
let reactionIconNode = ReactionImageNode(context: self.context, availableReactions: self.availableReactions, reaction: reaction) let reactionIconNode = ReactionImageNode(context: self.context, availableReactions: self.availableReactions, reaction: reaction, displayPixelSize: CGSize(width: 30.0 * UIScreenScale, height: 30.0 * UIScreenScale))
self.reactionIconNode = reactionIconNode self.reactionIconNode = reactionIconNode
self.addSubnode(reactionIconNode) self.addSubnode(reactionIconNode)
} }

View File

@@ -359,7 +359,7 @@ public class ItemListReactionItemNode: ListViewItemNode, ItemListItemNode {
} }
if strongSelf.imageNode == nil, let availableReactions = item.availableReactions { if strongSelf.imageNode == nil, let availableReactions = item.availableReactions {
let imageNode = ReactionImageNode(context: item.context, availableReactions: availableReactions, reaction: item.reaction) let imageNode = ReactionImageNode(context: item.context, availableReactions: availableReactions, reaction: item.reaction, displayPixelSize: CGSize(width: 30.0 * UIScreenScale, height: 30.0 * UIScreenScale))
strongSelf.imageNode = imageNode strongSelf.imageNode = imageNode
strongSelf.addSubnode(imageNode) strongSelf.addSubnode(imageNode)
} }

View File

@@ -11,6 +11,7 @@ import ItemListUI
import PresentationDataUtils import PresentationDataUtils
import AccountContext import AccountContext
import ReactionImageComponent import ReactionImageComponent
import WebPBinding
private final class QuickReactionSetupControllerArguments { private final class QuickReactionSetupControllerArguments {
let context: AccountContext let context: AccountContext
@@ -46,7 +47,7 @@ private enum QuickReactionSetupControllerEntry: ItemListNodeEntry {
case demoMessage(wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, availableReactions: AvailableReactions?, reaction: String?) case demoMessage(wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, bubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, availableReactions: AvailableReactions?, reaction: String?)
case demoDescription(String) case demoDescription(String)
case itemsHeader(String) case itemsHeader(String)
case item(index: Int, value: String, image: UIImage?, text: String, isSelected: Bool) case item(index: Int, value: String, image: UIImage?, imageIsAnimation: Bool, text: String, isSelected: Bool)
var section: ItemListSectionId { var section: ItemListSectionId {
switch self { switch self {
@@ -67,7 +68,7 @@ private enum QuickReactionSetupControllerEntry: ItemListNodeEntry {
return .demoDescription return .demoDescription
case .itemsHeader: case .itemsHeader:
return .itemsHeader return .itemsHeader
case let .item(_, value, _, _, _): case let .item(_, value, _, _, _, _):
return .item(value) return .item(value)
} }
} }
@@ -82,7 +83,7 @@ private enum QuickReactionSetupControllerEntry: ItemListNodeEntry {
return 2 return 2
case .itemsHeader: case .itemsHeader:
return 3 return 3
case let .item(index, _, _, _, _): case let .item(index, _, _, _, _, _):
return 100 + index return 100 + index
} }
} }
@@ -113,8 +114,8 @@ private enum QuickReactionSetupControllerEntry: ItemListNodeEntry {
} else { } else {
return false return false
} }
case let .item(index, value, file, text, isEnabled): case let .item(index, value, file, imageIsAnimation, text, isEnabled):
if case .item(index, value, file, text, isEnabled) = rhs { if case .item(index, value, file, imageIsAnimation, text, isEnabled) = rhs {
return true return true
} else { } else {
return false return false
@@ -152,11 +153,16 @@ private enum QuickReactionSetupControllerEntry: ItemListNodeEntry {
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
case let .itemsHeader(text): case let .itemsHeader(text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .item(_, value, image, text, isSelected): case let .item(_, value, image, imageIsAnimation, text, isSelected):
var imageFitSize = CGSize(width: 30.0, height: 30.0)
if imageIsAnimation {
imageFitSize.width = floor(imageFitSize.width * 2.0)
imageFitSize.height = floor(imageFitSize.height * 2.0)
}
return ItemListCheckboxItem( return ItemListCheckboxItem(
presentationData: presentationData, presentationData: presentationData,
icon: image, icon: image,
iconSize: image?.size.aspectFitted(CGSize(width: 30.0, height: 30.0)), iconSize: image?.size.aspectFitted(imageFitSize),
title: text, title: text,
style: .right, style: .right,
color: .accent, color: .accent,
@@ -178,7 +184,7 @@ private struct QuickReactionSetupControllerState: Equatable {
private func quickReactionSetupControllerEntries( private func quickReactionSetupControllerEntries(
presentationData: PresentationData, presentationData: PresentationData,
availableReactions: AvailableReactions?, availableReactions: AvailableReactions?,
images: [String: UIImage], images: [String: (image: UIImage, isAnimation: Bool)],
reactionSettings: ReactionSettings, reactionSettings: ReactionSettings,
state: QuickReactionSetupControllerState state: QuickReactionSetupControllerState
) -> [QuickReactionSetupControllerEntry] { ) -> [QuickReactionSetupControllerEntry] {
@@ -207,7 +213,8 @@ private func quickReactionSetupControllerEntries(
entries.append(.item( entries.append(.item(
index: index, index: index,
value: availableReaction.value, value: availableReaction.value,
image: images[availableReaction.value], image: images[availableReaction.value]?.image,
imageIsAnimation: images[availableReaction.value]?.isAnimation ?? false,
text: availableReaction.title, text: availableReaction.title,
isSelected: reactionSettings.quickReaction == availableReaction.value isSelected: reactionSettings.quickReaction == availableReaction.value
)) ))
@@ -263,39 +270,53 @@ public func quickReactionSetupController(
return reactionSettings return reactionSettings
} }
let images: Signal<[String: UIImage], NoError> = context.engine.stickers.availableReactions() let images: Signal<[String: (image: UIImage, isAnimation: Bool)], NoError> = context.engine.stickers.availableReactions()
|> mapToSignal { availableReactions -> Signal<[String: UIImage], NoError> in |> mapToSignal { availableReactions -> Signal<[String: (image: UIImage, isAnimation: Bool)], NoError> in
var signals: [Signal<(String, UIImage?), NoError>] = [] var signals: [Signal<(String, (image: UIImage, isAnimation: Bool)?), NoError>] = []
if let availableReactions = availableReactions { if let availableReactions = availableReactions {
for availableReaction in availableReactions.reactions { for availableReaction in availableReactions.reactions {
if !availableReaction.isEnabled { if !availableReaction.isEnabled {
continue continue
} }
guard let centerAnimation = availableReaction.centerAnimation else { if let centerAnimation = availableReaction.centerAnimation {
continue let signal: Signal<(String, (image: UIImage, isAnimation: Bool)?), NoError> = reactionStaticImage(context: context, animation: centerAnimation, pixelSize: CGSize(width: 72.0 * 2.0, height: 72.0 * 2.0))
|> map { data -> (String, (image: UIImage, isAnimation: Bool)?) in
guard data.isComplete else {
return (availableReaction.value, nil)
}
guard let dataValue = try? Data(contentsOf: URL(fileURLWithPath: data.path)) else {
return (availableReaction.value, nil)
}
guard let image = UIImage(data: dataValue) else {
return (availableReaction.value, nil)
}
return (availableReaction.value, (image, true))
}
signals.append(signal)
} else {
let signal: Signal<(String, (image: UIImage, isAnimation: Bool)?), NoError> = context.account.postbox.mediaBox.resourceData(availableReaction.staticIcon.resource)
|> map { data -> (String, (image: UIImage, isAnimation: Bool)?) in
guard data.complete else {
return (availableReaction.value, nil)
}
guard let dataValue = try? Data(contentsOf: URL(fileURLWithPath: data.path)) else {
return (availableReaction.value, nil)
}
guard let image = WebP.convert(fromWebP: dataValue) else {
return (availableReaction.value, nil)
}
return (availableReaction.value, (image, false))
}
signals.append(signal)
} }
let signal: Signal<(String, UIImage?), NoError> = reactionStaticImage(context: context, animation: centerAnimation, pixelSize: CGSize(width: 72.0, height: 72.0))
|> map { data -> (String, UIImage?) in
guard data.isComplete else {
return (availableReaction.value, nil)
}
guard let dataValue = try? Data(contentsOf: URL(fileURLWithPath: data.path)) else {
return (availableReaction.value, nil)
}
guard let image = UIImage(data: dataValue) else {
return (availableReaction.value, nil)
}
return (availableReaction.value, image)
}
signals.append(signal)
} }
} }
return combineLatest(queue: .mainQueue(), signals) return combineLatest(queue: .mainQueue(), signals)
|> map { values -> [String: UIImage] in |> map { values -> [String: (image: UIImage, isAnimation: Bool)] in
var dict: [String: UIImage] = [:] var dict: [String: (image: UIImage, isAnimation: Bool)] = [:]
for (key, image) in values { for (key, image) in values {
if let image = image { if let image = image {
dict[key] = image dict[key] = image

View File

@@ -2097,7 +2097,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
case .center: case .center:
let availableWidth = params.width - params.leftInset - params.rightInset let availableWidth = params.width - params.leftInset - params.rightInset
backgroundFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((availableWidth - layoutBubbleSize.width) / 2.0), y: 0.0), size: layoutBubbleSize) backgroundFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((availableWidth - layoutBubbleSize.width) / 2.0), y: 0.0), size: layoutBubbleSize)
contentOrigin = CGPoint(x: backgroundFrame.minX + floor(layoutConstants.bubble.contentInsets.right + layoutConstants.bubble.contentInsets.left) / 2.0, y: backgroundFrame.minY + layoutConstants.bubble.contentInsets.top + headerSize.height + contentVerticalOffset) let contentOriginX: CGFloat
if !hideBackground {
contentOriginX = (incoming ? layoutConstants.bubble.contentInsets.left : layoutConstants.bubble.contentInsets.right)
} else {
contentOriginX = floor(layoutConstants.bubble.contentInsets.right + layoutConstants.bubble.contentInsets.left) / 2.0
}
contentOrigin = CGPoint(x: backgroundFrame.minX + contentOriginX, y: backgroundFrame.minY + layoutConstants.bubble.contentInsets.top + headerSize.height + contentVerticalOffset)
contentUpperRightCorner = CGPoint(x: backgroundFrame.maxX - (incoming ? layoutConstants.bubble.contentInsets.right : layoutConstants.bubble.contentInsets.left), y: backgroundFrame.origin.y + layoutConstants.bubble.contentInsets.top + headerSize.height) contentUpperRightCorner = CGPoint(x: backgroundFrame.maxX - (incoming ? layoutConstants.bubble.contentInsets.right : layoutConstants.bubble.contentInsets.left), y: backgroundFrame.origin.y + layoutConstants.bubble.contentInsets.top + headerSize.height)
} }