mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 11:23:48 +00:00
Various fixes
This commit is contained in:
parent
8985192fa1
commit
e380fdf6b7
@ -3,7 +3,7 @@ import UIKit
|
||||
import Display
|
||||
import AccountContext
|
||||
|
||||
final class DrawingBubbleEntity: DrawingEntity, Codable {
|
||||
public final class DrawingBubbleEntity: DrawingEntity, Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case drawType
|
||||
@ -16,28 +16,30 @@ final class DrawingBubbleEntity: DrawingEntity, Codable {
|
||||
case tailPosition
|
||||
}
|
||||
|
||||
public enum DrawType: Codable {
|
||||
enum DrawType: Codable {
|
||||
case fill
|
||||
case stroke
|
||||
}
|
||||
|
||||
let uuid: UUID
|
||||
let isAnimated: Bool
|
||||
public let uuid: UUID
|
||||
public let isAnimated: Bool
|
||||
|
||||
var drawType: DrawType
|
||||
var color: DrawingColor
|
||||
var lineWidth: CGFloat
|
||||
public var color: DrawingColor
|
||||
public var lineWidth: CGFloat
|
||||
|
||||
var referenceDrawingSize: CGSize
|
||||
var position: CGPoint
|
||||
var size: CGSize
|
||||
var rotation: CGFloat
|
||||
public var position: CGPoint
|
||||
public var size: CGSize
|
||||
public var rotation: CGFloat
|
||||
var tailPosition: CGPoint
|
||||
|
||||
var center: CGPoint {
|
||||
public var center: CGPoint {
|
||||
return self.position
|
||||
}
|
||||
|
||||
public var renderImage: UIImage?
|
||||
|
||||
init(drawType: DrawType, color: DrawingColor, lineWidth: CGFloat) {
|
||||
self.uuid = UUID()
|
||||
self.isAnimated = false
|
||||
@ -53,7 +55,7 @@ final class DrawingBubbleEntity: DrawingEntity, Codable {
|
||||
self.tailPosition = CGPoint(x: 0.16, y: 0.18)
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.uuid = try container.decode(UUID.self, forKey: .uuid)
|
||||
self.isAnimated = false
|
||||
@ -67,7 +69,7 @@ final class DrawingBubbleEntity: DrawingEntity, Codable {
|
||||
self.tailPosition = try container.decode(CGPoint.self, forKey: .tailPosition)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.uuid, forKey: .uuid)
|
||||
try container.encode(self.drawType, forKey: .drawType)
|
||||
@ -80,7 +82,7 @@ final class DrawingBubbleEntity: DrawingEntity, Codable {
|
||||
try container.encode(self.tailPosition, forKey: .tailPosition)
|
||||
}
|
||||
|
||||
func duplicate() -> DrawingEntity {
|
||||
public func duplicate() -> DrawingEntity {
|
||||
let newEntity = DrawingBubbleEntity(drawType: self.drawType, color: self.color, lineWidth: self.lineWidth)
|
||||
newEntity.referenceDrawingSize = self.referenceDrawingSize
|
||||
newEntity.position = self.position
|
||||
@ -89,8 +91,8 @@ final class DrawingBubbleEntity: DrawingEntity, Codable {
|
||||
return newEntity
|
||||
}
|
||||
|
||||
weak var currentEntityView: DrawingEntityView?
|
||||
func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
public weak var currentEntityView: DrawingEntityView?
|
||||
public func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
let entityView = DrawingBubbleEntityView(context: context, entity: self)
|
||||
self.currentEntityView = entityView
|
||||
return entityView
|
||||
|
@ -3,7 +3,7 @@ import UIKit
|
||||
import LegacyComponents
|
||||
import AccountContext
|
||||
|
||||
protocol DrawingEntity: AnyObject {
|
||||
public protocol DrawingEntity: AnyObject {
|
||||
var uuid: UUID { get }
|
||||
var isAnimated: Bool { get }
|
||||
var center: CGPoint { get }
|
||||
@ -56,6 +56,13 @@ enum CodableDrawingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
public func decodeDrawingEntities(data: Data) -> [DrawingEntity] {
|
||||
if let codableEntities = try? JSONDecoder().decode([CodableDrawingEntity].self, from: data) {
|
||||
return codableEntities.map { $0.entity }
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
extension CodableDrawingEntity: Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case type
|
||||
@ -226,11 +233,7 @@ public final class DrawingEntitiesView: UIView, TGPhotoDrawingEntitiesView {
|
||||
sticker.position = center
|
||||
if setup {
|
||||
sticker.referenceDrawingSize = self.size
|
||||
if !sticker.file.isVideoSticker && sticker.file.mimeType.hasSuffix("webm") {
|
||||
sticker.scale = 4.0
|
||||
} else {
|
||||
sticker.scale = 1.0
|
||||
}
|
||||
sticker.scale = 1.0
|
||||
}
|
||||
} else if let bubble = entity as? DrawingBubbleEntity {
|
||||
bubble.position = center
|
||||
|
@ -16,6 +16,7 @@ import LottieAnimationComponent
|
||||
import ViewControllerComponent
|
||||
import ContextUI
|
||||
import ChatEntityKeyboardInputNode
|
||||
import EntityKeyboard
|
||||
|
||||
enum DrawingToolState: Equatable {
|
||||
enum Key: CaseIterable {
|
||||
@ -463,6 +464,8 @@ private final class DrawingScreenComponent: CombinedComponent {
|
||||
var selectedEntity: DrawingEntity?
|
||||
|
||||
var lastFontSize: CGFloat = 0.5
|
||||
|
||||
private let stickerPickerInputData = Promise<StickerPickerInputData>()
|
||||
|
||||
init(context: AccountContext, updateToolState: ActionSlot<DrawingToolState>, insertEntity: ActionSlot<DrawingEntity>, deselectEntity: ActionSlot<Void>, updatePlayback: ActionSlot<Bool>, present: @escaping (ViewController) -> Void) {
|
||||
self.context = context
|
||||
@ -478,6 +481,56 @@ private final class DrawingScreenComponent: CombinedComponent {
|
||||
self.currentColor = self.drawingState.tools.first?.color ?? DrawingColor(rgb: 0xffffff)
|
||||
|
||||
self.updateToolState.invoke(self.drawingState.currentToolState)
|
||||
|
||||
let stickerPickerInputData = self.stickerPickerInputData
|
||||
Queue.concurrentDefaultQueue().after(0.5, {
|
||||
let emojiItems = EmojiPagerContentComponent.emojiInputData(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
isStandalone: false,
|
||||
isStatusSelection: false,
|
||||
isReactionSelection: false,
|
||||
isEmojiSelection: true,
|
||||
topReactionItems: [],
|
||||
areUnicodeEmojiEnabled: true,
|
||||
areCustomEmojiEnabled: true,
|
||||
chatPeerId: context.account.peerId,
|
||||
hasSearch: false
|
||||
)
|
||||
|
||||
let stickerItems = EmojiPagerContentComponent.stickerInputData(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
stickerNamespaces: [Namespaces.ItemCollection.CloudStickerPacks],
|
||||
stickerOrderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.CloudAllPremiumStickers],
|
||||
chatPeerId: context.account.peerId,
|
||||
hasSearch: false,
|
||||
hasTrending: true
|
||||
)
|
||||
|
||||
let maskItems = EmojiPagerContentComponent.stickerInputData(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
stickerNamespaces: [Namespaces.ItemCollection.CloudMaskPacks],
|
||||
stickerOrderedItemListCollectionIds: [],
|
||||
chatPeerId: context.account.peerId,
|
||||
hasSearch: false,
|
||||
hasTrending: false
|
||||
)
|
||||
|
||||
let signal = combineLatest(queue: .mainQueue(),
|
||||
emojiItems,
|
||||
stickerItems,
|
||||
maskItems
|
||||
) |> map { emoji, stickers, masks -> StickerPickerInputData in
|
||||
return StickerPickerInputData(emoji: emoji, stickers: stickers, masks: masks)
|
||||
}
|
||||
|
||||
stickerPickerInputData.set(signal)
|
||||
})
|
||||
}
|
||||
|
||||
private var currentToolState: DrawingToolState {
|
||||
@ -717,7 +770,7 @@ private final class DrawingScreenComponent: CombinedComponent {
|
||||
self.currentMode = .sticker
|
||||
|
||||
self.updatePlayback.invoke(false)
|
||||
let controller = StickerPickerScreen(context: self.context)
|
||||
let controller = StickerPickerScreen(context: self.context, inputData: self.stickerPickerInputData.get())
|
||||
controller.completion = { [weak self] file in
|
||||
self?.updatePlayback.invoke(true)
|
||||
|
||||
@ -2363,13 +2416,6 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController {
|
||||
}
|
||||
strongSelf.toggleInputMode()
|
||||
}
|
||||
// inputView?.presentController = { [weak self] c in
|
||||
// guard let strongSelf = self else {
|
||||
// return
|
||||
// }
|
||||
// strongSelf.presentController(c)
|
||||
// }
|
||||
|
||||
textView.inputView = inputView
|
||||
} else {
|
||||
textView.inputView = nil
|
||||
|
@ -3,7 +3,7 @@ import UIKit
|
||||
import Display
|
||||
import AccountContext
|
||||
|
||||
final class DrawingSimpleShapeEntity: DrawingEntity, Codable {
|
||||
public final class DrawingSimpleShapeEntity: DrawingEntity, Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case shapeType
|
||||
@ -27,23 +27,25 @@ final class DrawingSimpleShapeEntity: DrawingEntity, Codable {
|
||||
case stroke
|
||||
}
|
||||
|
||||
let uuid: UUID
|
||||
let isAnimated: Bool
|
||||
public let uuid: UUID
|
||||
public let isAnimated: Bool
|
||||
|
||||
var shapeType: ShapeType
|
||||
var drawType: DrawType
|
||||
var color: DrawingColor
|
||||
var lineWidth: CGFloat
|
||||
public var color: DrawingColor
|
||||
public var lineWidth: CGFloat
|
||||
|
||||
var referenceDrawingSize: CGSize
|
||||
var position: CGPoint
|
||||
var size: CGSize
|
||||
var rotation: CGFloat
|
||||
public var position: CGPoint
|
||||
public var size: CGSize
|
||||
public var rotation: CGFloat
|
||||
|
||||
var center: CGPoint {
|
||||
public var center: CGPoint {
|
||||
return self.position
|
||||
}
|
||||
|
||||
public var renderImage: UIImage?
|
||||
|
||||
init(shapeType: ShapeType, drawType: DrawType, color: DrawingColor, lineWidth: CGFloat) {
|
||||
self.uuid = UUID()
|
||||
self.isAnimated = false
|
||||
@ -59,7 +61,7 @@ final class DrawingSimpleShapeEntity: DrawingEntity, Codable {
|
||||
self.rotation = 0.0
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.uuid = try container.decode(UUID.self, forKey: .uuid)
|
||||
self.isAnimated = false
|
||||
@ -73,7 +75,7 @@ final class DrawingSimpleShapeEntity: DrawingEntity, Codable {
|
||||
self.rotation = try container.decode(CGFloat.self, forKey: .rotation)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.uuid, forKey: .uuid)
|
||||
try container.encode(self.shapeType, forKey: .shapeType)
|
||||
@ -86,7 +88,7 @@ final class DrawingSimpleShapeEntity: DrawingEntity, Codable {
|
||||
try container.encode(self.rotation, forKey: .rotation)
|
||||
}
|
||||
|
||||
func duplicate() -> DrawingEntity {
|
||||
public func duplicate() -> DrawingEntity {
|
||||
let newEntity = DrawingSimpleShapeEntity(shapeType: self.shapeType, drawType: self.drawType, color: self.color, lineWidth: self.lineWidth)
|
||||
newEntity.referenceDrawingSize = self.referenceDrawingSize
|
||||
newEntity.position = self.position
|
||||
@ -95,8 +97,8 @@ final class DrawingSimpleShapeEntity: DrawingEntity, Codable {
|
||||
return newEntity
|
||||
}
|
||||
|
||||
weak var currentEntityView: DrawingEntityView?
|
||||
func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
public weak var currentEntityView: DrawingEntityView?
|
||||
public func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
let entityView = DrawingSimpleShapeEntityView(context: context, entity: self)
|
||||
self.currentEntityView = entityView
|
||||
return entityView
|
||||
|
@ -8,7 +8,7 @@ import TelegramAnimatedStickerNode
|
||||
import StickerResources
|
||||
import AccountContext
|
||||
|
||||
final class DrawingStickerEntity: DrawingEntity, Codable {
|
||||
public final class DrawingStickerEntity: DrawingEntity, Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case isAnimated
|
||||
@ -20,23 +20,28 @@ final class DrawingStickerEntity: DrawingEntity, Codable {
|
||||
case mirrored
|
||||
}
|
||||
|
||||
let uuid: UUID
|
||||
let isAnimated: Bool
|
||||
let file: TelegramMediaFile
|
||||
public let uuid: UUID
|
||||
public let isAnimated: Bool
|
||||
public let file: TelegramMediaFile
|
||||
|
||||
var referenceDrawingSize: CGSize
|
||||
var position: CGPoint
|
||||
var scale: CGFloat
|
||||
var rotation: CGFloat
|
||||
var mirrored: Bool
|
||||
public var referenceDrawingSize: CGSize
|
||||
public var position: CGPoint
|
||||
public var scale: CGFloat
|
||||
public var rotation: CGFloat
|
||||
public var mirrored: Bool
|
||||
|
||||
var color: DrawingColor = DrawingColor.clear
|
||||
var lineWidth: CGFloat = 0.0
|
||||
public var color: DrawingColor = DrawingColor.clear
|
||||
public var lineWidth: CGFloat = 0.0
|
||||
|
||||
var center: CGPoint {
|
||||
public var center: CGPoint {
|
||||
return self.position
|
||||
}
|
||||
|
||||
public var baseSize: CGSize {
|
||||
let size = max(10.0, min(self.referenceDrawingSize.width, self.referenceDrawingSize.height) * 0.4)
|
||||
return CGSize(width: size, height: size)
|
||||
}
|
||||
|
||||
init(file: TelegramMediaFile) {
|
||||
self.uuid = UUID()
|
||||
self.isAnimated = file.isAnimatedSticker
|
||||
@ -50,7 +55,7 @@ final class DrawingStickerEntity: DrawingEntity, Codable {
|
||||
self.mirrored = false
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.uuid = try container.decode(UUID.self, forKey: .uuid)
|
||||
self.isAnimated = try container.decode(Bool.self, forKey: .isAnimated)
|
||||
@ -62,7 +67,7 @@ final class DrawingStickerEntity: DrawingEntity, Codable {
|
||||
self.mirrored = try container.decode(Bool.self, forKey: .mirrored)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.uuid, forKey: .uuid)
|
||||
try container.encode(self.isAnimated, forKey: .isAnimated)
|
||||
@ -74,7 +79,7 @@ final class DrawingStickerEntity: DrawingEntity, Codable {
|
||||
try container.encode(self.mirrored, forKey: .mirrored)
|
||||
}
|
||||
|
||||
func duplicate() -> DrawingEntity {
|
||||
public func duplicate() -> DrawingEntity {
|
||||
let newEntity = DrawingStickerEntity(file: self.file)
|
||||
newEntity.referenceDrawingSize = self.referenceDrawingSize
|
||||
newEntity.position = self.position
|
||||
@ -84,8 +89,8 @@ final class DrawingStickerEntity: DrawingEntity, Codable {
|
||||
return newEntity
|
||||
}
|
||||
|
||||
weak var currentEntityView: DrawingEntityView?
|
||||
func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
public weak var currentEntityView: DrawingEntityView?
|
||||
public func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
let entityView = DrawingStickerEntityView(context: context, entity: self)
|
||||
self.currentEntityView = entityView
|
||||
return entityView
|
||||
@ -256,9 +261,9 @@ final class DrawingStickerEntityView: DrawingEntityView {
|
||||
}
|
||||
self.center = self.stickerEntity.position
|
||||
|
||||
let size = max(10.0, min(self.stickerEntity.referenceDrawingSize.width, self.stickerEntity.referenceDrawingSize.height) * 0.45)
|
||||
let size = self.stickerEntity.baseSize
|
||||
|
||||
self.bounds = CGRect(origin: .zero, size: dimensions.fitted(CGSize(width: size, height: size)))
|
||||
self.bounds = CGRect(origin: .zero, size: dimensions.aspectFitted(size))
|
||||
self.transform = CGAffineTransformScale(CGAffineTransformMakeRotation(self.stickerEntity.rotation), self.stickerEntity.scale, self.stickerEntity.scale)
|
||||
|
||||
var transform = CATransform3DIdentity
|
||||
|
@ -6,7 +6,7 @@ import AccountContext
|
||||
import TextFormat
|
||||
import EmojiTextAttachmentView
|
||||
|
||||
final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
public final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
final class CustomEmojiAttribute: Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case attribute
|
||||
@ -122,8 +122,8 @@ final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
var uuid: UUID
|
||||
var isAnimated: Bool {
|
||||
public var uuid: UUID
|
||||
public var isAnimated: Bool {
|
||||
var isAnimated = false
|
||||
self.text.enumerateAttributes(in: NSMakeRange(0, self.text.length), options: [], using: { attributes, range, _ in
|
||||
if let _ = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute {
|
||||
@ -138,8 +138,8 @@ final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
var font: Font
|
||||
var alignment: Alignment
|
||||
var fontSize: CGFloat
|
||||
var color: DrawingColor
|
||||
var lineWidth: CGFloat = 0.0
|
||||
public var color: DrawingColor
|
||||
public var lineWidth: CGFloat = 0.0
|
||||
|
||||
var referenceDrawingSize: CGSize
|
||||
var position: CGPoint
|
||||
@ -147,10 +147,12 @@ final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
var scale: CGFloat
|
||||
var rotation: CGFloat
|
||||
|
||||
var center: CGPoint {
|
||||
public var center: CGPoint {
|
||||
return self.position
|
||||
}
|
||||
|
||||
public var renderImage: UIImage?
|
||||
|
||||
init(text: NSAttributedString, style: Style, font: Font, alignment: Alignment, fontSize: CGFloat, color: DrawingColor) {
|
||||
self.uuid = UUID()
|
||||
|
||||
@ -168,7 +170,7 @@ final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
self.rotation = 0.0
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.uuid = try container.decode(UUID.self, forKey: .uuid)
|
||||
let text = try container.decode(String.self, forKey: .text)
|
||||
@ -192,7 +194,7 @@ final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
self.rotation = try container.decode(CGFloat.self, forKey: .rotation)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.uuid, forKey: .uuid)
|
||||
try container.encode(self.text.string, forKey: .text)
|
||||
@ -217,7 +219,7 @@ final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
try container.encode(self.rotation, forKey: .rotation)
|
||||
}
|
||||
|
||||
func duplicate() -> DrawingEntity {
|
||||
public func duplicate() -> DrawingEntity {
|
||||
let newEntity = DrawingTextEntity(text: self.text, style: self.style, font: self.font, alignment: self.alignment, fontSize: self.fontSize, color: self.color)
|
||||
newEntity.referenceDrawingSize = self.referenceDrawingSize
|
||||
newEntity.position = self.position
|
||||
@ -227,8 +229,8 @@ final class DrawingTextEntity: DrawingEntity, Codable {
|
||||
return newEntity
|
||||
}
|
||||
|
||||
weak var currentEntityView: DrawingEntityView?
|
||||
func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
public weak var currentEntityView: DrawingEntityView?
|
||||
public func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
let entityView = DrawingTextEntityView(context: context, entity: self)
|
||||
self.currentEntityView = entityView
|
||||
return entityView
|
||||
@ -718,6 +720,9 @@ final class DrawingTextEntititySelectionView: DrawingEntitySelectionView, UIGest
|
||||
}
|
||||
|
||||
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
if let entityView = self.entityView as? DrawingTextEntityView, entityView.isEditing {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@ -726,6 +731,7 @@ final class DrawingTextEntititySelectionView: DrawingEntitySelectionView, UIGest
|
||||
guard let entityView = self.entityView, let entity = entityView.entity as? DrawingTextEntity else {
|
||||
return
|
||||
}
|
||||
|
||||
let location = gestureRecognizer.location(in: self)
|
||||
|
||||
switch gestureRecognizer.state {
|
||||
@ -781,10 +787,10 @@ final class DrawingTextEntititySelectionView: DrawingEntitySelectionView, UIGest
|
||||
}
|
||||
|
||||
override func handlePinch(_ gestureRecognizer: UIPinchGestureRecognizer) {
|
||||
guard let entityView = self.entityView, let entity = entityView.entity as? DrawingTextEntity else {
|
||||
guard let entityView = self.entityView as? DrawingTextEntityView, !entityView.isEditing, let entity = entityView.entity as? DrawingTextEntity else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
switch gestureRecognizer.state {
|
||||
case .began, .changed:
|
||||
let scale = gestureRecognizer.scale
|
||||
@ -798,7 +804,7 @@ final class DrawingTextEntititySelectionView: DrawingEntitySelectionView, UIGest
|
||||
}
|
||||
|
||||
override func handleRotate(_ gestureRecognizer: UIRotationGestureRecognizer) {
|
||||
guard let entityView = self.entityView, let entity = entityView.entity as? DrawingTextEntity else {
|
||||
guard let entityView = self.entityView as? DrawingTextEntityView, !entityView.isEditing, let entity = entityView.entity as? DrawingTextEntity else {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import UIKit
|
||||
import QuartzCore
|
||||
import simd
|
||||
|
||||
struct DrawingColor: Equatable, Codable {
|
||||
public struct DrawingColor: Equatable, Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case red
|
||||
case green
|
||||
@ -57,7 +57,7 @@ struct DrawingColor: Equatable, Codable {
|
||||
self.init(color: UIColor(rgb: rgb))
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.red = try container.decode(CGFloat.self, forKey: .red)
|
||||
self.green = try container.decode(CGFloat.self, forKey: .green)
|
||||
|
@ -3,7 +3,7 @@ import UIKit
|
||||
import Display
|
||||
import AccountContext
|
||||
|
||||
final class DrawingVectorEntity: DrawingEntity, Codable {
|
||||
public final class DrawingVectorEntity: DrawingEntity, Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case uuid
|
||||
case type
|
||||
@ -22,14 +22,14 @@ final class DrawingVectorEntity: DrawingEntity, Codable {
|
||||
case twoSidedArrow
|
||||
}
|
||||
|
||||
let uuid: UUID
|
||||
let isAnimated: Bool
|
||||
public let uuid: UUID
|
||||
public let isAnimated: Bool
|
||||
|
||||
var type: VectorType
|
||||
var color: DrawingColor
|
||||
var lineWidth: CGFloat
|
||||
public var color: DrawingColor
|
||||
public var lineWidth: CGFloat
|
||||
|
||||
var drawingSize: CGSize
|
||||
public var drawingSize: CGSize
|
||||
var referenceDrawingSize: CGSize
|
||||
var start: CGPoint
|
||||
var mid: (CGFloat, CGFloat)
|
||||
@ -46,10 +46,12 @@ final class DrawingVectorEntity: DrawingEntity, Codable {
|
||||
}
|
||||
}
|
||||
|
||||
var center: CGPoint {
|
||||
public var center: CGPoint {
|
||||
return self.start
|
||||
}
|
||||
|
||||
public var renderImage: UIImage?
|
||||
|
||||
init(type: VectorType, color: DrawingColor, lineWidth: CGFloat) {
|
||||
self.uuid = UUID()
|
||||
self.isAnimated = false
|
||||
@ -65,7 +67,7 @@ final class DrawingVectorEntity: DrawingEntity, Codable {
|
||||
self.end = CGPoint()
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.uuid = try container.decode(UUID.self, forKey: .uuid)
|
||||
self.isAnimated = false
|
||||
@ -82,7 +84,7 @@ final class DrawingVectorEntity: DrawingEntity, Codable {
|
||||
self.end = try container.decode(CGPoint.self, forKey: .end)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.uuid, forKey: .uuid)
|
||||
try container.encode(self.type, forKey: .type)
|
||||
@ -95,7 +97,7 @@ final class DrawingVectorEntity: DrawingEntity, Codable {
|
||||
try container.encode(self.end, forKey: .end)
|
||||
}
|
||||
|
||||
func duplicate() -> DrawingEntity {
|
||||
public func duplicate() -> DrawingEntity {
|
||||
let newEntity = DrawingVectorEntity(type: self.type, color: self.color, lineWidth: self.lineWidth)
|
||||
newEntity.drawingSize = self.drawingSize
|
||||
newEntity.referenceDrawingSize = self.referenceDrawingSize
|
||||
@ -105,8 +107,8 @@ final class DrawingVectorEntity: DrawingEntity, Codable {
|
||||
return newEntity
|
||||
}
|
||||
|
||||
weak var currentEntityView: DrawingEntityView?
|
||||
func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
public weak var currentEntityView: DrawingEntityView?
|
||||
public func makeView(context: AccountContext) -> DrawingEntityView {
|
||||
let entityView = DrawingVectorEntityView(context: context, entity: self)
|
||||
self.currentEntityView = entityView
|
||||
return entityView
|
||||
|
@ -14,7 +14,7 @@ import PagerComponent
|
||||
import FeaturedStickersScreen
|
||||
import TelegramNotices
|
||||
|
||||
struct InputData: Equatable {
|
||||
struct StickerPickerInputData: Equatable {
|
||||
var emoji: EmojiPagerContentComponent
|
||||
var stickers: EmojiPagerContentComponent?
|
||||
var masks: EmojiPagerContentComponent?
|
||||
@ -37,7 +37,7 @@ private final class StickerSelectionComponent: Component {
|
||||
let strings: PresentationStrings
|
||||
let deviceMetrics: DeviceMetrics
|
||||
let bottomInset: CGFloat
|
||||
let content: InputData
|
||||
let content: StickerPickerInputData
|
||||
let backgroundColor: UIColor
|
||||
let separatorColor: UIColor
|
||||
|
||||
@ -46,7 +46,7 @@ private final class StickerSelectionComponent: Component {
|
||||
strings: PresentationStrings,
|
||||
deviceMetrics: DeviceMetrics,
|
||||
bottomInset: CGFloat,
|
||||
content: InputData,
|
||||
content: StickerPickerInputData,
|
||||
backgroundColor: UIColor,
|
||||
separatorColor: UIColor
|
||||
) {
|
||||
@ -197,7 +197,7 @@ private final class StickerSelectionComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
public class StickerPickerScreen: ViewController {
|
||||
class StickerPickerScreen: ViewController {
|
||||
final class Node: ViewControllerTracingNode, UIScrollViewDelegate, UIGestureRecognizerDelegate {
|
||||
private var presentationData: PresentationData
|
||||
private weak var controller: StickerPickerScreen?
|
||||
@ -209,7 +209,7 @@ public class StickerPickerScreen: ViewController {
|
||||
let scrollView: UIScrollView
|
||||
let hostView: ComponentHostView<Empty>
|
||||
|
||||
private var content: InputData?
|
||||
private var content: StickerPickerInputData?
|
||||
private let contentDisposable = MetaDisposable()
|
||||
private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation?
|
||||
|
||||
@ -251,51 +251,9 @@ public class StickerPickerScreen: ViewController {
|
||||
self.containerView.addSubview(self.scrollView)
|
||||
self.scrollView.addSubview(self.hostView)
|
||||
|
||||
let emojiItems = EmojiPagerContentComponent.emojiInputData(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
isStandalone: false,
|
||||
isStatusSelection: false,
|
||||
isReactionSelection: false,
|
||||
isEmojiSelection: true,
|
||||
topReactionItems: [],
|
||||
areUnicodeEmojiEnabled: true,
|
||||
areCustomEmojiEnabled: true,
|
||||
chatPeerId: context.account.peerId,
|
||||
hasSearch: false
|
||||
)
|
||||
|
||||
let stickerItems = EmojiPagerContentComponent.stickerInputData(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
stickerNamespaces: [Namespaces.ItemCollection.CloudStickerPacks],
|
||||
stickerOrderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.CloudAllPremiumStickers],
|
||||
chatPeerId: context.account.peerId,
|
||||
hasSearch: false,
|
||||
hasTrending: true
|
||||
)
|
||||
|
||||
let maskItems = EmojiPagerContentComponent.stickerInputData(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
stickerNamespaces: [Namespaces.ItemCollection.CloudMaskPacks],
|
||||
stickerOrderedItemListCollectionIds: [],
|
||||
chatPeerId: context.account.peerId,
|
||||
hasSearch: false,
|
||||
hasTrending: false
|
||||
)
|
||||
|
||||
let signal = combineLatest(queue: .mainQueue(),
|
||||
emojiItems,
|
||||
stickerItems,
|
||||
maskItems
|
||||
)
|
||||
self.contentDisposable.set(signal.start(next: { [weak self] emoji, stickers, masks in
|
||||
self.contentDisposable.set(controller.inputData.start(next: { [weak self] inputData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.updateContent(InputData(emoji: emoji, stickers: stickers, masks: masks))
|
||||
strongSelf.updateContent(inputData)
|
||||
}
|
||||
}))
|
||||
}
|
||||
@ -304,7 +262,7 @@ public class StickerPickerScreen: ViewController {
|
||||
self.contentDisposable.dispose()
|
||||
}
|
||||
|
||||
func updateContent(_ content: InputData) {
|
||||
func updateContent(_ content: StickerPickerInputData) {
|
||||
self.content = content
|
||||
|
||||
content.emoji.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction(
|
||||
@ -999,6 +957,7 @@ public class StickerPickerScreen: ViewController {
|
||||
|
||||
private let context: AccountContext
|
||||
private let theme: PresentationTheme
|
||||
private let inputData: Signal<StickerPickerInputData, NoError>
|
||||
|
||||
private var currentLayout: ContainerViewLayout?
|
||||
|
||||
@ -1007,26 +966,28 @@ public class StickerPickerScreen: ViewController {
|
||||
|
||||
var completion: (TelegramMediaFile?) -> Void = { _ in }
|
||||
|
||||
public init(context: AccountContext) {
|
||||
init(context: AccountContext, inputData: Signal<StickerPickerInputData, NoError>) {
|
||||
self.context = context
|
||||
self.theme = defaultDarkColorPresentationTheme
|
||||
self.inputData = inputData
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
|
||||
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override open func loadDisplayNode() {
|
||||
override func loadDisplayNode() {
|
||||
self.displayNode = Node(context: self.context, controller: self, theme: self.theme)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
}
|
||||
|
||||
public override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
|
||||
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
|
||||
self.view.endEditing(true)
|
||||
if flag {
|
||||
self.node.animateOut(completion: {
|
||||
@ -1039,19 +1000,19 @@ public class StickerPickerScreen: ViewController {
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewDidAppear(_ animated: Bool) {
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
self.node.updateIsVisible(isVisible: true)
|
||||
}
|
||||
|
||||
override open func viewDidDisappear(_ animated: Bool) {
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
self.node.updateIsVisible(isVisible: false)
|
||||
}
|
||||
|
||||
override open func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
self.currentLayout = layout
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
+ (instancetype)dataWithDrawingData:(NSData *)data entitiesData:(NSData *)entitiesData image:(UIImage *)image stillImage:(UIImage *)stillImage hasAnimation:(bool)hasAnimation;
|
||||
|
||||
+ (instancetype)dataWithPaintingImagePath:(NSString *)imagePath entitiesData:(NSData *)entitiesData;
|
||||
+ (instancetype)dataWithPaintingImagePath:(NSString *)imagePath entitiesData:(NSData *)entitiesData hasAnimation:(bool)hasAnimation;
|
||||
|
||||
+ (instancetype)dataWithPaintingImagePath:(NSString *)imagePath;
|
||||
|
||||
|
@ -31,10 +31,11 @@
|
||||
return paintingData;
|
||||
}
|
||||
|
||||
+ (instancetype)dataWithPaintingImagePath:(NSString *)imagePath entitiesData:(NSData *)entitiesData {
|
||||
+ (instancetype)dataWithPaintingImagePath:(NSString *)imagePath entitiesData:(NSData *)entitiesData hasAnimation:(bool)hasAnimation {
|
||||
TGPaintingData *paintingData = [[TGPaintingData alloc] init];
|
||||
paintingData->_imagePath = imagePath;
|
||||
paintingData->_entitiesData = entitiesData;
|
||||
paintingData->_hasAnimation = hasAnimation;
|
||||
return paintingData;
|
||||
}
|
||||
|
||||
@ -49,6 +50,7 @@
|
||||
{
|
||||
TGPaintingData *paintingData = [[TGPaintingData alloc] init];
|
||||
paintingData->_entitiesData = _entitiesData;
|
||||
paintingData->_hasAnimation = _hasAnimation;
|
||||
return paintingData;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5;
|
||||
if (dictionary[@"originalSize"])
|
||||
adjustments->_originalSize = [dictionary[@"originalSize"] CGSizeValue];
|
||||
if (dictionary[@"entitiesData"]) {
|
||||
adjustments->_paintingData = [TGPaintingData dataWithPaintingImagePath:dictionary[@"paintingImagePath"] entitiesData:dictionary[@"entitiesData"]];
|
||||
adjustments->_paintingData = [TGPaintingData dataWithPaintingImagePath:dictionary[@"paintingImagePath"] entitiesData:dictionary[@"entitiesData"] hasAnimation:[dictionary[@"hasAnimation"] boolValue]];
|
||||
} else if (dictionary[@"paintingImagePath"]) {
|
||||
adjustments->_paintingData = [TGPaintingData dataWithPaintingImagePath:dictionary[@"paintingImagePath"]];
|
||||
}
|
||||
@ -217,6 +217,7 @@ const NSTimeInterval TGVideoEditMaximumGifDuration = 30.5;
|
||||
}
|
||||
if (self.paintingData.entitiesData != nil) {
|
||||
dict[@"entitiesData"] = self.paintingData.entitiesData;
|
||||
dict[@"hasAnimation"] = @(self.paintingData.hasAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ private class LegacyPaintStickerEntity: LegacyPaintEntity {
|
||||
}
|
||||
|
||||
var angle: CGFloat {
|
||||
return self.entity.angle
|
||||
return self.entity.rotation
|
||||
}
|
||||
|
||||
var baseSize: CGSize? {
|
||||
@ -76,7 +76,7 @@ private class LegacyPaintStickerEntity: LegacyPaintEntity {
|
||||
|
||||
let account: Account
|
||||
let file: TelegramMediaFile
|
||||
let entity: TGPhotoPaintStickerEntity
|
||||
let entity: DrawingStickerEntity
|
||||
let animated: Bool
|
||||
let durationPromise = Promise<Double>()
|
||||
|
||||
@ -92,55 +92,50 @@ private class LegacyPaintStickerEntity: LegacyPaintEntity {
|
||||
|
||||
let imagePromise = Promise<UIImage>()
|
||||
|
||||
init?(account: Account, entity: TGPhotoPaintStickerEntity) {
|
||||
let decoder = PostboxDecoder(buffer: MemoryBuffer(data: entity.document))
|
||||
if let file = decoder.decodeRootObject() as? TelegramMediaFile {
|
||||
self.account = account
|
||||
self.entity = entity
|
||||
self.file = file
|
||||
self.animated = file.isAnimatedSticker || file.isVideoSticker
|
||||
|
||||
if file.isAnimatedSticker || file.isVideoSticker {
|
||||
self.source = AnimatedStickerResourceSource(account: account, resource: file.resource, isVideo: file.isVideoSticker)
|
||||
if let source = self.source {
|
||||
let dimensions = self.file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
||||
let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 384, height: 384))
|
||||
self.disposables.add((source.cachedDataPath(width: Int(fittedDimensions.width), height: Int(fittedDimensions.height))
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] path, complete in
|
||||
if let strongSelf = self, complete {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: [.mappedRead]) {
|
||||
let queue = strongSelf.queue
|
||||
let frameSource = AnimatedStickerCachedFrameSource(queue: queue, data: data, complete: complete, notifyUpdated: {})!
|
||||
strongSelf.frameCount = frameSource.frameCount
|
||||
strongSelf.frameRate = frameSource.frameRate
|
||||
|
||||
let duration = Double(frameSource.frameCount) / Double(frameSource.frameRate)
|
||||
strongSelf.totalDuration = duration
|
||||
|
||||
strongSelf.durationPromise.set(.single(duration))
|
||||
|
||||
let frameQueue = QueueLocalObject<AnimatedStickerFrameQueue>(queue: queue, generate: {
|
||||
return AnimatedStickerFrameQueue(queue: queue, length: 1, source: frameSource)
|
||||
})
|
||||
strongSelf.frameQueue.set(.single(frameQueue))
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
self.disposables.add((chatMessageSticker(account: self.account, userLocation: .other, file: self.file, small: false, fetched: true, onlyFullSize: true, thumbnail: false, synchronousLoad: false)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] generator in
|
||||
if let strongSelf = self {
|
||||
let context = generator(TransformImageArguments(corners: ImageCorners(), imageSize: entity.baseSize, boundingSize: entity.baseSize, intrinsicInsets: UIEdgeInsets()))
|
||||
let image = context?.generateImage()
|
||||
if let image = image {
|
||||
strongSelf.imagePromise.set(.single(image))
|
||||
init(account: Account, entity: DrawingStickerEntity) {
|
||||
self.account = account
|
||||
self.entity = entity
|
||||
self.file = entity.file
|
||||
self.animated = file.isAnimatedSticker || file.isVideoSticker
|
||||
|
||||
if file.isAnimatedSticker || file.isVideoSticker {
|
||||
self.source = AnimatedStickerResourceSource(account: account, resource: file.resource, isVideo: file.isVideoSticker)
|
||||
if let source = self.source {
|
||||
let dimensions = self.file.dimensions ?? PixelDimensions(width: 512, height: 512)
|
||||
let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 384, height: 384))
|
||||
self.disposables.add((source.cachedDataPath(width: Int(fittedDimensions.width), height: Int(fittedDimensions.height))
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] path, complete in
|
||||
if let strongSelf = self, complete {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: [.mappedRead]) {
|
||||
let queue = strongSelf.queue
|
||||
let frameSource = AnimatedStickerCachedFrameSource(queue: queue, data: data, complete: complete, notifyUpdated: {})!
|
||||
strongSelf.frameCount = frameSource.frameCount
|
||||
strongSelf.frameRate = frameSource.frameRate
|
||||
|
||||
let duration = Double(frameSource.frameCount) / Double(frameSource.frameRate)
|
||||
strongSelf.totalDuration = duration
|
||||
|
||||
strongSelf.durationPromise.set(.single(duration))
|
||||
|
||||
let frameQueue = QueueLocalObject<AnimatedStickerFrameQueue>(queue: queue, generate: {
|
||||
return AnimatedStickerFrameQueue(queue: queue, length: 1, source: frameSource)
|
||||
})
|
||||
strongSelf.frameQueue.set(.single(frameQueue))
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
self.disposables.add((chatMessageSticker(account: self.account, userLocation: .other, file: self.file, small: false, fetched: true, onlyFullSize: true, thumbnail: false, synchronousLoad: false)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] generator in
|
||||
if let strongSelf = self {
|
||||
let context = generator(TransformImageArguments(corners: ImageCorners(), imageSize: entity.baseSize, boundingSize: entity.baseSize, intrinsicInsets: UIEdgeInsets()))
|
||||
let image = context?.generateImage()
|
||||
if let image = image {
|
||||
strongSelf.imagePromise.set(.single(image))
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,6 +272,126 @@ private class LegacyPaintTextEntity: LegacyPaintEntity {
|
||||
}
|
||||
}
|
||||
|
||||
private class LegacyPaintSimpleShapeEntity: LegacyPaintEntity {
|
||||
var position: CGPoint {
|
||||
return self.entity.position
|
||||
}
|
||||
|
||||
var scale: CGFloat {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
var angle: CGFloat {
|
||||
return self.entity.rotation
|
||||
}
|
||||
|
||||
var baseSize: CGSize? {
|
||||
return self.entity.size
|
||||
}
|
||||
|
||||
var mirrored: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
let entity: DrawingSimpleShapeEntity
|
||||
|
||||
init(entity: DrawingSimpleShapeEntity) {
|
||||
self.entity = entity
|
||||
}
|
||||
|
||||
var cachedCIImage: CIImage?
|
||||
func image(for time: CMTime, fps: Int, completion: @escaping (CIImage?) -> Void) {
|
||||
var image: CIImage?
|
||||
if let cachedImage = self.cachedCIImage {
|
||||
image = cachedImage
|
||||
} else if let renderImage = entity.renderImage {
|
||||
image = CIImage(image: renderImage)
|
||||
self.cachedCIImage = image
|
||||
}
|
||||
completion(image)
|
||||
}
|
||||
}
|
||||
|
||||
private class LegacyPaintBubbleEntity: LegacyPaintEntity {
|
||||
var position: CGPoint {
|
||||
return self.entity.position
|
||||
}
|
||||
|
||||
var scale: CGFloat {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
var angle: CGFloat {
|
||||
return self.entity.rotation
|
||||
}
|
||||
|
||||
var baseSize: CGSize? {
|
||||
return self.entity.size
|
||||
}
|
||||
|
||||
var mirrored: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
let entity: DrawingBubbleEntity
|
||||
|
||||
init(entity: DrawingBubbleEntity) {
|
||||
self.entity = entity
|
||||
}
|
||||
|
||||
var cachedCIImage: CIImage?
|
||||
func image(for time: CMTime, fps: Int, completion: @escaping (CIImage?) -> Void) {
|
||||
var image: CIImage?
|
||||
if let cachedImage = self.cachedCIImage {
|
||||
image = cachedImage
|
||||
} else if let renderImage = entity.renderImage {
|
||||
image = CIImage(image: renderImage)
|
||||
self.cachedCIImage = image
|
||||
}
|
||||
completion(image)
|
||||
}
|
||||
}
|
||||
|
||||
private class LegacyPaintVectorEntity: LegacyPaintEntity {
|
||||
var position: CGPoint {
|
||||
return CGPoint(x: self.entity.drawingSize.width * 0.5, y: self.entity.drawingSize.height * 0.5)
|
||||
}
|
||||
|
||||
var scale: CGFloat {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
var angle: CGFloat {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
var baseSize: CGSize? {
|
||||
return self.entity.drawingSize
|
||||
}
|
||||
|
||||
var mirrored: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
let entity: DrawingVectorEntity
|
||||
|
||||
init(entity: DrawingVectorEntity) {
|
||||
self.entity = entity
|
||||
}
|
||||
|
||||
var cachedCIImage: CIImage?
|
||||
func image(for time: CMTime, fps: Int, completion: @escaping (CIImage?) -> Void) {
|
||||
var image: CIImage?
|
||||
if let cachedImage = self.cachedCIImage {
|
||||
image = cachedImage
|
||||
} else if let renderImage = entity.renderImage {
|
||||
image = CIImage(image: renderImage)
|
||||
self.cachedCIImage = image
|
||||
}
|
||||
completion(image)
|
||||
}
|
||||
}
|
||||
|
||||
public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRenderer {
|
||||
private let account: Account?
|
||||
private let queue = Queue()
|
||||
@ -290,19 +405,24 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender
|
||||
self.originalSize = adjustments.originalSize
|
||||
self.cropRect = adjustments.cropRect.isEmpty ? nil : adjustments.cropRect
|
||||
|
||||
let entities: [LegacyPaintEntity] = []
|
||||
// if let paintingData = adjustments.paintingData, let paintingEntities = paintingData.entities {
|
||||
// for paintingEntity in paintingEntities {
|
||||
// if let sticker = paintingEntity as? TGPhotoPaintStickerEntity {
|
||||
// if let account = account, let entity = LegacyPaintStickerEntity(account: account, entity: sticker) {
|
||||
// entities.append(entity)
|
||||
// }
|
||||
// } else if let text = paintingEntity as? TGPhotoPaintTextEntity {
|
||||
// entities.append(LegacyPaintTextEntity(entity: text))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
self.entities = entities
|
||||
var renderEntities: [LegacyPaintEntity] = []
|
||||
if let account = account, let paintingData = adjustments.paintingData, let entitiesData = paintingData.entitiesData {
|
||||
let entities = decodeDrawingEntities(data: entitiesData)
|
||||
for entity in entities {
|
||||
if let sticker = entity as? DrawingStickerEntity {
|
||||
renderEntities.append(LegacyPaintStickerEntity(account: account, entity: sticker))
|
||||
} else if let _ = entity as? DrawingTextEntity {
|
||||
// renderEntities.append(LegacyPaintStickerEntity(account: account, entity: sticker))
|
||||
} else if let simpleShape = entity as? DrawingSimpleShapeEntity {
|
||||
renderEntities.append(LegacyPaintSimpleShapeEntity(entity: simpleShape))
|
||||
} else if let bubble = entity as? DrawingBubbleEntity {
|
||||
renderEntities.append(LegacyPaintBubbleEntity(entity: bubble))
|
||||
} else if let vector = entity as? DrawingVectorEntity {
|
||||
renderEntities.append(LegacyPaintVectorEntity(entity: vector))
|
||||
}
|
||||
}
|
||||
}
|
||||
self.entities = renderEntities
|
||||
|
||||
super.init()
|
||||
}
|
||||
@ -360,7 +480,7 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender
|
||||
public func entities(for time: CMTime, fps: Int, size: CGSize, completion: (([CIImage]?) -> Void)!) {
|
||||
let entities = self.entities
|
||||
let maxSide = max(size.width, size.height)
|
||||
let paintingScale = maxSide / 1920.0
|
||||
let paintingScale = maxSide / 2560.0
|
||||
|
||||
self.queue.async {
|
||||
if entities.isEmpty {
|
||||
@ -394,7 +514,7 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender
|
||||
}
|
||||
|
||||
transform = CGAffineTransform(translationX: entity.position.x * paintingScale, y: size.height - entity.position.y * paintingScale)
|
||||
transform = transform.rotated(by: CGFloat.pi * 2 - entity.angle)
|
||||
transform = transform.rotated(by: CGFloat.pi * 2.0 - entity.angle)
|
||||
transform = transform.scaledBy(x: scale, y: scale)
|
||||
if entity.mirrored {
|
||||
transform = transform.scaledBy(x: -1.0, y: 1.0)
|
||||
|
@ -30,7 +30,6 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
|
||||
private var videoStartTimestamp: Double?
|
||||
|
||||
private let buttonNode: HighlightTrackingButtonNode
|
||||
private let buttonStarsNode: PremiumStarsNode
|
||||
private let buttonTitleNode: TextNode
|
||||
|
||||
private var absoluteRect: (CGRect, CGSize)?
|
||||
@ -51,9 +50,7 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
|
||||
self.buttonNode = HighlightTrackingButtonNode()
|
||||
self.buttonNode.clipsToBounds = true
|
||||
self.buttonNode.cornerRadius = 17.0
|
||||
|
||||
self.buttonStarsNode = PremiumStarsNode()
|
||||
|
||||
|
||||
self.buttonTitleNode = TextNode()
|
||||
self.buttonTitleNode.isUserInteractionEnabled = false
|
||||
self.buttonTitleNode.displaysAsynchronously = false
|
||||
@ -65,7 +62,6 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
|
||||
self.addSubnode(self.imageNode)
|
||||
|
||||
self.addSubnode(self.buttonNode)
|
||||
self.buttonNode.addSubnode(self.buttonStarsNode)
|
||||
self.addSubnode(self.buttonTitleNode)
|
||||
|
||||
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
||||
@ -273,7 +269,6 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
|
||||
|
||||
let buttonSize = CGSize(width: buttonTitleLayout.size.width + 38.0, height: 34.0)
|
||||
strongSelf.buttonNode.frame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonSize.width) / 2.0), y: subtitleFrame.maxY + 10.0), size: buttonSize)
|
||||
strongSelf.buttonStarsNode.frame = CGRect(origin: .zero, size: buttonSize)
|
||||
|
||||
if item.controllerInteraction.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true {
|
||||
if strongSelf.mediaBackgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user