mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 14:45:21 +00:00
Fix reaction images
This commit is contained in:
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user