mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
UI optimizations
This commit is contained in:
parent
5c71c08b6e
commit
5f3de7a40b
@ -5,7 +5,7 @@ import Lottie
|
|||||||
import AppBundle
|
import AppBundle
|
||||||
import Display
|
import Display
|
||||||
|
|
||||||
public final class AnimationNode : ASDisplayNode {
|
public final class AnimationNode: ASDisplayNode {
|
||||||
private let scale: CGFloat
|
private let scale: CGFloat
|
||||||
public var speed: CGFloat = 1.0 {
|
public var speed: CGFloat = 1.0 {
|
||||||
didSet {
|
didSet {
|
||||||
@ -15,8 +15,6 @@ public final class AnimationNode : ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//private var colorCallbacks: [LOTColorValueCallback] = []
|
|
||||||
|
|
||||||
public var didPlay = false
|
public var didPlay = false
|
||||||
public var completion: (() -> Void)?
|
public var completion: (() -> Void)?
|
||||||
private var internalCompletion: (() -> Void)?
|
private var internalCompletion: (() -> Void)?
|
||||||
@ -43,9 +41,6 @@ public final class AnimationNode : ASDisplayNode {
|
|||||||
if let colors = colors {
|
if let colors = colors {
|
||||||
for (key, value) in colors {
|
for (key, value) in colors {
|
||||||
view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color"))
|
view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color"))
|
||||||
/*let colorCallback = LOTColorValueCallback(color: value.cgColor)
|
|
||||||
self.colorCallbacks.append(colorCallback)
|
|
||||||
view.setValueDelegate(colorCallback, for: LOTKeypath(string: "\(key).Color"))*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = colors["__allcolors__"] {
|
if let value = colors["__allcolors__"] {
|
||||||
@ -77,9 +72,6 @@ public final class AnimationNode : ASDisplayNode {
|
|||||||
if let colors = colors {
|
if let colors = colors {
|
||||||
for (key, value) in colors {
|
for (key, value) in colors {
|
||||||
view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color"))
|
view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color"))
|
||||||
/*let colorCallback = LOTColorValueCallback(color: value.cgColor)
|
|
||||||
self.colorCallbacks.append(colorCallback)
|
|
||||||
view.setValueDelegate(colorCallback, for: LOTKeypath(string: "\(key).Color"))*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let value = colors["__allcolors__"] {
|
if let value = colors["__allcolors__"] {
|
||||||
@ -121,9 +113,6 @@ public final class AnimationNode : ASDisplayNode {
|
|||||||
if let colors = colors {
|
if let colors = colors {
|
||||||
for (key, value) in colors {
|
for (key, value) in colors {
|
||||||
self.animationView()?.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color"))
|
self.animationView()?.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color"))
|
||||||
/*let colorCallback = LOTColorValueCallback(color: value.cgColor)
|
|
||||||
self.colorCallbacks.append(colorCallback)
|
|
||||||
self.animationView()?.setValueDelegate(colorCallback, for: LOTKeypath(string: "\(key).Color"))*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,6 @@ func localizedCountryNamesAndCodes(strings: PresentationStrings) -> [((String, S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.append(((englishCountryName, countryName), country.id, codes))
|
result.append(((englishCountryName, countryName), country.id, codes))
|
||||||
} else {
|
|
||||||
assertionFailure()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
@ -6,6 +6,22 @@ public enum DeviceType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum DeviceMetrics: CaseIterable, Equatable {
|
public enum DeviceMetrics: CaseIterable, Equatable {
|
||||||
|
public struct Performance {
|
||||||
|
public let isGraphicallyCapable: Bool
|
||||||
|
|
||||||
|
init() {
|
||||||
|
var length: Int = 4
|
||||||
|
var cpuCount: UInt32 = 0
|
||||||
|
sysctlbyname("hw.ncpu", &cpuCount, &length, nil, 0)
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
cpuCount = 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
self.isGraphicallyCapable = cpuCount >= 6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case iPhone4
|
case iPhone4
|
||||||
case iPhone5
|
case iPhone5
|
||||||
case iPhone6
|
case iPhone6
|
||||||
@ -33,6 +49,8 @@ public enum DeviceMetrics: CaseIterable, Equatable {
|
|||||||
case iPadPro3rdGen
|
case iPadPro3rdGen
|
||||||
case iPadMini6thGen
|
case iPadMini6thGen
|
||||||
case unknown(screenSize: CGSize, statusBarHeight: CGFloat, onScreenNavigationHeight: CGFloat?)
|
case unknown(screenSize: CGSize, statusBarHeight: CGFloat, onScreenNavigationHeight: CGFloat?)
|
||||||
|
|
||||||
|
public static let performance = Performance()
|
||||||
|
|
||||||
public static var allCases: [DeviceMetrics] {
|
public static var allCases: [DeviceMetrics] {
|
||||||
return [
|
return [
|
||||||
|
@ -290,7 +290,7 @@ private final class ChatListViewSpaceState {
|
|||||||
|
|
||||||
postboxLog("existingEntityIds not unique: \(allEntityIds)")
|
postboxLog("existingEntityIds not unique: \(allEntityIds)")
|
||||||
postboxLog("allIndices: \(allIndices)")
|
postboxLog("allIndices: \(allIndices)")
|
||||||
assert(false)
|
//assert(false)
|
||||||
//preconditionFailure()
|
//preconditionFailure()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,8 +327,6 @@ private class RecentSessionScreenNode: ViewControllerTracingNode, UIScrollViewDe
|
|||||||
let animationNode = AnimationNode(animation: animationName, colors: colors, scale: 1.0)
|
let animationNode = AnimationNode(animation: animationName, colors: colors, scale: 1.0)
|
||||||
self.animationNode = animationNode
|
self.animationNode = animationNode
|
||||||
|
|
||||||
animationNode.animationView()?.logHierarchyKeypaths()
|
|
||||||
|
|
||||||
let animationBackgroundNode = ASDisplayNode()
|
let animationBackgroundNode = ASDisplayNode()
|
||||||
animationBackgroundNode.cornerRadius = 20.0
|
animationBackgroundNode.cornerRadius = 20.0
|
||||||
animationBackgroundNode.backgroundColor = backgroundColor
|
animationBackgroundNode.backgroundColor = backgroundColor
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import Display
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import TelegramUIPreferences
|
import TelegramUIPreferences
|
||||||
import Postbox
|
import Postbox
|
||||||
@ -28,6 +29,10 @@ public func selectReactionFillStaticColor(theme: PresentationTheme, wallpaper: T
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func dateFillNeedsBlur(theme: PresentationTheme, wallpaper: TelegramWallpaper) -> Bool {
|
public func dateFillNeedsBlur(theme: PresentationTheme, wallpaper: TelegramWallpaper) -> Bool {
|
||||||
|
if !DeviceMetrics.performance.isGraphicallyCapable {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
if case .builtin = wallpaper {
|
if case .builtin = wallpaper {
|
||||||
return false
|
return false
|
||||||
} else if case .color = wallpaper {
|
} else if case .color = wallpaper {
|
||||||
|
@ -353,6 +353,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/ChatEntityKeyboardInputNode",
|
"//submodules/TelegramUI/Components/ChatEntityKeyboardInputNode",
|
||||||
"//submodules/TelegramUI/Components/StorageUsageScreen",
|
"//submodules/TelegramUI/Components/StorageUsageScreen",
|
||||||
"//submodules/TelegramUI/Components/AvatarEditorScreen",
|
"//submodules/TelegramUI/Components/AvatarEditorScreen",
|
||||||
|
"//submodules/TelegramUI/Components/LottieComponent",
|
||||||
"//submodules/MediaPasteboardUI:MediaPasteboardUI",
|
"//submodules/MediaPasteboardUI:MediaPasteboardUI",
|
||||||
"//submodules/DrawingUI:DrawingUI",
|
"//submodules/DrawingUI:DrawingUI",
|
||||||
"//submodules/FeaturedStickersScreen:FeaturedStickersScreen",
|
"//submodules/FeaturedStickersScreen:FeaturedStickersScreen",
|
||||||
|
@ -39,10 +39,10 @@ private final class LottieDirectContent: LottieComponent.Content {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override func load(_ f: @escaping (Data) -> Void) -> Disposable {
|
override func load(_ f: @escaping (Data, String?) -> Void) -> Disposable {
|
||||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: self.path)) {
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: self.path)) {
|
||||||
let result = TGGUnzipData(data, 2 * 1024 * 1024) ?? data
|
let result = TGGUnzipData(data, 2 * 1024 * 1024) ?? data
|
||||||
f(result)
|
f(result, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return EmptyDisposable
|
return EmptyDisposable
|
||||||
|
@ -15,6 +15,7 @@ swift_library(
|
|||||||
"//submodules/Components/HierarchyTrackingLayer",
|
"//submodules/Components/HierarchyTrackingLayer",
|
||||||
"//submodules/rlottie:RLottieBinding",
|
"//submodules/rlottie:RLottieBinding",
|
||||||
"//submodules/SSignalKit/SwiftSignalKit",
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
|
"//submodules/AppBundle",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -5,7 +5,7 @@ import ComponentFlow
|
|||||||
import HierarchyTrackingLayer
|
import HierarchyTrackingLayer
|
||||||
import RLottieBinding
|
import RLottieBinding
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import Accelerate
|
import AppBundle
|
||||||
|
|
||||||
public final class LottieComponent: Component {
|
public final class LottieComponent: Component {
|
||||||
public typealias EnvironmentType = Empty
|
public typealias EnvironmentType = Empty
|
||||||
@ -25,10 +25,36 @@ public final class LottieComponent: Component {
|
|||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
}
|
}
|
||||||
|
|
||||||
open func load(_ f: @escaping (Data) -> Void) -> Disposable {
|
open func load(_ f: @escaping (Data, String?) -> Void) -> Disposable {
|
||||||
preconditionFailure()
|
preconditionFailure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class AppBundleContent: Content {
|
||||||
|
public let name: String
|
||||||
|
|
||||||
|
public init(name: String) {
|
||||||
|
self.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func isEqual(to other: Content) -> Bool {
|
||||||
|
guard let other = other as? AppBundleContent else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if self.name != other.name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func load(_ f: @escaping (Data, String?) -> Void) -> Disposable {
|
||||||
|
if let url = getAppBundle().url(forResource: self.name, withExtension: "json"), let data = try? Data(contentsOf: url) {
|
||||||
|
f(data, url.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return EmptyDisposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public let content: Content
|
public let content: Content
|
||||||
public let color: UIColor
|
public let color: UIColor
|
||||||
@ -63,6 +89,9 @@ public final class LottieComponent: Component {
|
|||||||
private var currentFrame: Int = 0
|
private var currentFrame: Int = 0
|
||||||
private var currentFrameStartTime: Double?
|
private var currentFrameStartTime: Double?
|
||||||
|
|
||||||
|
private var hierarchyTrackingLayer: HierarchyTrackingLayer?
|
||||||
|
private var isVisible: Bool = false
|
||||||
|
|
||||||
private var displayLink: SharedDisplayLinkDriver.Link?
|
private var displayLink: SharedDisplayLinkDriver.Link?
|
||||||
|
|
||||||
private var currentTemplateFrameImage: UIImage?
|
private var currentTemplateFrameImage: UIImage?
|
||||||
@ -76,11 +105,30 @@ public final class LottieComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
//self.hierarchyTrackingLayer = HierarchyTrackingLayer()
|
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
//self.layer.addSublayer(self.hierarchyTrackingLayer)
|
let hierarchyTrackingLayer = HierarchyTrackingLayer()
|
||||||
|
self.hierarchyTrackingLayer = hierarchyTrackingLayer
|
||||||
|
self.layer.addSublayer(hierarchyTrackingLayer)
|
||||||
|
|
||||||
|
hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !self.isVisible {
|
||||||
|
self.isVisible = true
|
||||||
|
self.visibilityUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hierarchyTrackingLayer.didExitHierarchy = { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.isVisible {
|
||||||
|
self.isVisible = false
|
||||||
|
self.visibilityUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
@ -91,11 +139,22 @@ public final class LottieComponent: Component {
|
|||||||
self.currentContentDisposable?.dispose()
|
self.currentContentDisposable?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func visibilityUpdated() {
|
||||||
|
if self.isVisible {
|
||||||
|
if self.scheduledPlayOnce {
|
||||||
|
self.playOnce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func playOnce(delay: Double = 0.0) {
|
public func playOnce(delay: Double = 0.0) {
|
||||||
guard let _ = self.animationInstance else {
|
guard let _ = self.animationInstance else {
|
||||||
self.scheduledPlayOnce = true
|
self.scheduledPlayOnce = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !self.isVisible {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
self.scheduledPlayOnce = false
|
self.scheduledPlayOnce = false
|
||||||
|
|
||||||
@ -135,8 +194,8 @@ public final class LottieComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func loadAnimation(data: Data) {
|
private func loadAnimation(data: Data, cacheKey: String?) {
|
||||||
self.animationInstance = LottieInstance(data: data, fitzModifier: .none, colorReplacements: nil, cacheKey: "")
|
self.animationInstance = LottieInstance(data: data, fitzModifier: .none, colorReplacements: nil, cacheKey: cacheKey ?? "")
|
||||||
if self.scheduledPlayOnce {
|
if self.scheduledPlayOnce {
|
||||||
self.scheduledPlayOnce = false
|
self.scheduledPlayOnce = false
|
||||||
self.playOnce()
|
self.playOnce()
|
||||||
@ -184,12 +243,6 @@ public final class LottieComponent: Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var destinationBuffer = vImage_Buffer()
|
|
||||||
destinationBuffer.width = UInt(context.scaledSize.width)
|
|
||||||
destinationBuffer.height = UInt(context.scaledSize.height)
|
|
||||||
destinationBuffer.data = context.bytes
|
|
||||||
destinationBuffer.rowBytes = context.bytesPerRow
|
|
||||||
|
|
||||||
animationInstance.renderFrame(with: Int32(self.currentFrame % Int(animationInstance.frameCount)), into: context.bytes.assumingMemoryBound(to: UInt8.self), width: Int32(currentDisplaySize.width), height: Int32(currentDisplaySize.height), bytesPerRow: Int32(context.bytesPerRow))
|
animationInstance.renderFrame(with: Int32(self.currentFrame % Int(animationInstance.frameCount)), into: context.bytes.assumingMemoryBound(to: UInt8.self), width: Int32(currentDisplaySize.width), height: Int32(currentDisplaySize.height), bytesPerRow: Int32(context.bytesPerRow))
|
||||||
self.currentTemplateFrameImage = context.generateImage()?.withRenderingMode(.alwaysTemplate)
|
self.currentTemplateFrameImage = context.generateImage()?.withRenderingMode(.alwaysTemplate)
|
||||||
self.image = self.currentTemplateFrameImage
|
self.image = self.currentTemplateFrameImage
|
||||||
@ -216,12 +269,12 @@ public final class LottieComponent: Component {
|
|||||||
if previousComponent?.content != component.content {
|
if previousComponent?.content != component.content {
|
||||||
self.currentContentDisposable?.dispose()
|
self.currentContentDisposable?.dispose()
|
||||||
let content = component.content
|
let content = component.content
|
||||||
self.currentContentDisposable = component.content.load { [weak self, weak content] data in
|
self.currentContentDisposable = component.content.load { [weak self, weak content] data, cacheKey in
|
||||||
Queue.mainQueue().async {
|
Queue.mainQueue().async {
|
||||||
guard let self, self.component?.content == content else {
|
guard let self, self.component?.content == content else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.loadAnimation(data: data)
|
self.loadAnimation(data: data, cacheKey: cacheKey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if redrawImage {
|
} else if redrawImage {
|
||||||
|
@ -30,7 +30,7 @@ public extension LottieComponent {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func load(_ f: @escaping (Data) -> Void) -> Disposable {
|
override public func load(_ f: @escaping (Data, String?) -> Void) -> Disposable {
|
||||||
let fileId = self.fileId
|
let fileId = self.fileId
|
||||||
let mediaBox = self.context.account.postbox.mediaBox
|
let mediaBox = self.context.account.postbox.mediaBox
|
||||||
return (self.context.engine.stickers.resolveInlineStickers(fileIds: [fileId])
|
return (self.context.engine.stickers.resolveInlineStickers(fileIds: [fileId])
|
||||||
@ -60,7 +60,7 @@ public extension LottieComponent {
|
|||||||
guard let data else {
|
guard let data else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f(data)
|
f(data, nil)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,7 +491,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
if (strongSelf.context.sharedContext.currentPresentationData.with({ $0 })).reduceMotion {
|
if (strongSelf.context.sharedContext.currentPresentationData.with({ $0 })).reduceMotion {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.backgroundNode.animateEvent(transition: transition, extendAnimation: false)
|
if DeviceMetrics.performance.isGraphicallyCapable {
|
||||||
|
strongSelf.backgroundNode.animateEvent(transition: transition, extendAnimation: false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getMessageTransitionNode = { [weak self] in
|
getMessageTransitionNode = { [weak self] in
|
||||||
@ -2214,7 +2216,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
if (self.context.sharedContext.currentPresentationData.with({ $0 })).reduceMotion {
|
if (self.context.sharedContext.currentPresentationData.with({ $0 })).reduceMotion {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.backgroundNode.animateEvent(transition: transition, extendAnimation: false)
|
if DeviceMetrics.performance.isGraphicallyCapable {
|
||||||
|
self.backgroundNode.animateEvent(transition: transition, extendAnimation: false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//self.historyNode.didScrollWithOffset?(listBottomInset - previousListBottomInset, transition, nil)
|
//self.historyNode.didScrollWithOffset?(listBottomInset - previousListBottomInset, transition, nil)
|
||||||
}
|
}
|
||||||
|
@ -184,10 +184,16 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode {
|
|||||||
|
|
||||||
self.addSubnode(self.containerNode)
|
self.addSubnode(self.containerNode)
|
||||||
self.containerNode.addSubnode(self.backgroundColorNode)
|
self.containerNode.addSubnode(self.backgroundColorNode)
|
||||||
self.containerNode.addSubnode(self.effectNode)
|
|
||||||
|
if DeviceMetrics.performance.isGraphicallyCapable {
|
||||||
|
self.containerNode.addSubnode(self.effectNode)
|
||||||
|
}
|
||||||
|
|
||||||
self.addSubnode(self.borderNode)
|
self.addSubnode(self.borderNode)
|
||||||
self.borderNode.addSubnode(self.borderEffectNode)
|
|
||||||
|
if DeviceMetrics.performance.isGraphicallyCapable {
|
||||||
|
self.borderNode.addSubnode(self.borderEffectNode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didLoad() {
|
override func didLoad() {
|
||||||
@ -196,7 +202,9 @@ final class ChatLoadingPlaceholderNode: ASDisplayNode {
|
|||||||
self.containerNode.view.mask = self.maskNode.view
|
self.containerNode.view.mask = self.maskNode.view
|
||||||
self.borderNode.view.mask = self.borderMaskNode.view
|
self.borderNode.view.mask = self.borderMaskNode.view
|
||||||
|
|
||||||
self.backgroundNode?.updateIsLooping(true)
|
if DeviceMetrics.performance.isGraphicallyCapable {
|
||||||
|
self.backgroundNode?.updateIsLooping(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var bottomInset: (Int, CGFloat)?
|
private var bottomInset: (Int, CGFloat)?
|
||||||
|
@ -12,6 +12,7 @@ import AudioBlob
|
|||||||
import ChatPresentationInterfaceState
|
import ChatPresentationInterfaceState
|
||||||
import ComponentFlow
|
import ComponentFlow
|
||||||
import LottieAnimationComponent
|
import LottieAnimationComponent
|
||||||
|
import LottieComponent
|
||||||
|
|
||||||
private let offsetThreshold: CGFloat = 10.0
|
private let offsetThreshold: CGFloat = 10.0
|
||||||
private let dismissOffsetThreshold: CGFloat = 70.0
|
private let dismissOffsetThreshold: CGFloat = 70.0
|
||||||
@ -289,11 +290,17 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lazy var micLock: (UIView & TGModernConversationInputMicButtonLock) = {
|
private var micLockValue: (UIView & TGModernConversationInputMicButtonLock)?
|
||||||
let lockView = LockView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 60.0)), theme: self.theme, strings: self.strings)
|
private var micLock: UIView & TGModernConversationInputMicButtonLock {
|
||||||
lockView.addTarget(self, action: #selector(handleStopTap), for: .touchUpInside)
|
if let current = self.micLockValue {
|
||||||
return lockView
|
return current
|
||||||
}()
|
} else {
|
||||||
|
let lockView = LockView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 60.0)), theme: self.theme, strings: self.strings)
|
||||||
|
lockView.addTarget(self, action: #selector(handleStopTap), for: .touchUpInside)
|
||||||
|
self.micLockValue = lockView
|
||||||
|
return lockView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init(theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) {
|
init(theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
@ -363,37 +370,34 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto
|
|||||||
animationName = "anim_micToVideo"
|
animationName = "anim_micToVideo"
|
||||||
}
|
}
|
||||||
|
|
||||||
var animationMode: LottieAnimationComponent.AnimationItem.Mode = .still(position: .end)
|
//var animationMode: LottieAnimationComponent.AnimationItem.Mode = .still(position: .end)
|
||||||
if previousMode != mode {
|
|
||||||
animationMode = .animating(loop: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
let colorKeys = ["__allcolors__"]
|
/*let colorKeys = ["__allcolors__"]
|
||||||
var colors: [String: UIColor] = [:]
|
var colors: [String: UIColor] = [:]
|
||||||
for colorKey in colorKeys {
|
for colorKey in colorKeys {
|
||||||
colors[colorKey] = self.theme.chat.inputPanel.panelControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0)
|
colors[colorKey] = self.theme.chat.inputPanel.panelControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
let _ = animationView.update(
|
let _ = animationView.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(LottieAnimationComponent(
|
component: AnyComponent(LottieComponent(
|
||||||
animation: LottieAnimationComponent.AnimationItem(
|
content: LottieComponent.AppBundleContent(name: animationName),
|
||||||
name: animationName,
|
color: self.theme.chat.inputPanel.panelControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0)
|
||||||
mode: animationMode
|
|
||||||
),
|
|
||||||
colors: colors,
|
|
||||||
size: animationFrame.size
|
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: animationFrame.size
|
containerSize: animationFrame.size
|
||||||
)
|
)
|
||||||
|
|
||||||
if let view = animationView.view {
|
if let view = animationView.view as? LottieComponent.View {
|
||||||
view.isUserInteractionEnabled = false
|
view.isUserInteractionEnabled = false
|
||||||
if view.superview == nil {
|
if view.superview == nil {
|
||||||
self.insertSubview(view, at: 0)
|
self.insertSubview(view, at: 0)
|
||||||
}
|
}
|
||||||
view.frame = animationFrame
|
view.frame = animationFrame
|
||||||
|
|
||||||
|
if previousMode != mode {
|
||||||
|
view.playOnce()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +408,7 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto
|
|||||||
|
|
||||||
self.pallete = legacyInputMicPalette(from: theme)
|
self.pallete = legacyInputMicPalette(from: theme)
|
||||||
self.micDecorationValue?.setColor(self.theme.chat.inputPanel.actionControlFillColor)
|
self.micDecorationValue?.setColor(self.theme.chat.inputPanel.actionControlFillColor)
|
||||||
(self.micLock as? LockView)?.updateTheme(theme)
|
(self.micLockValue as? LockView)?.updateTheme(theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
@ -33,6 +33,7 @@ import ChatControllerInteraction
|
|||||||
import UndoUI
|
import UndoUI
|
||||||
import PremiumUI
|
import PremiumUI
|
||||||
import StickerPeekUI
|
import StickerPeekUI
|
||||||
|
import LottieComponent
|
||||||
|
|
||||||
private let accessoryButtonFont = Font.medium(14.0)
|
private let accessoryButtonFont = Font.medium(14.0)
|
||||||
private let counterFont = Font.with(size: 14.0, design: .regular, traits: [.monospacedNumbers])
|
private let counterFont = Font.with(size: 14.0, design: .regular, traits: [.monospacedNumbers])
|
||||||
@ -184,11 +185,11 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode {
|
|||||||
|
|
||||||
if let animationView = self.animationView {
|
if let animationView = self.animationView {
|
||||||
let width = AccessoryItemIconButtonNode.calculateWidth(item: item, image: image, text: "", strings: self.strings)
|
let width = AccessoryItemIconButtonNode.calculateWidth(item: item, image: image, text: "", strings: self.strings)
|
||||||
let iconSize = CGSize(width: width, height: width)
|
//let iconSize = CGSize(width: width, height: width)
|
||||||
|
|
||||||
let animationFrame = CGRect(origin: CGPoint(x: floor((size.width - width) / 2.0), y: floor((size.height - width) / 2.0) - bottomInset), size: CGSize(width: width, height: width))
|
let animationFrame = CGRect(origin: CGPoint(x: floor((size.width - width) / 2.0), y: floor((size.height - width) / 2.0) - bottomInset), size: CGSize(width: width, height: width))
|
||||||
|
|
||||||
let colorKeys: [String] = ["__allcolors__"]
|
//let colorKeys: [String] = ["__allcolors__"]
|
||||||
let animationName: String
|
let animationName: String
|
||||||
var animationMode: LottieAnimationComponent.AnimationItem.Mode = .still(position: .end)
|
var animationMode: LottieAnimationComponent.AnimationItem.Mode = .still(position: .end)
|
||||||
|
|
||||||
@ -286,30 +287,30 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var colors: [String: UIColor] = [:]
|
/*var colors: [String: UIColor] = [:]
|
||||||
for colorKey in colorKeys {
|
for colorKey in colorKeys {
|
||||||
colors[colorKey] = self.theme.chat.inputPanel.inputControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0)
|
colors[colorKey] = self.theme.chat.inputPanel.inputControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
let animationSize = animationView.update(
|
let animationSize = animationView.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(LottieAnimationComponent(
|
component: AnyComponent(LottieComponent(
|
||||||
animation: LottieAnimationComponent.AnimationItem(
|
content: LottieComponent.AppBundleContent(name: animationName),
|
||||||
name: animationName,
|
color: self.theme.chat.inputPanel.inputControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0)
|
||||||
mode: animationMode
|
|
||||||
),
|
|
||||||
colors: colors,
|
|
||||||
size: iconSize
|
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: animationFrame.size
|
containerSize: animationFrame.size
|
||||||
)
|
)
|
||||||
if let view = animationView.view {
|
if let view = animationView.view as? LottieComponent.View {
|
||||||
view.isUserInteractionEnabled = false
|
view.isUserInteractionEnabled = false
|
||||||
if view.superview == nil {
|
if view.superview == nil {
|
||||||
self.view.addSubview(view)
|
self.view.addSubview(view)
|
||||||
}
|
}
|
||||||
view.frame = CGRect(origin: CGPoint(x: animationFrame.minX + floor((animationFrame.width - animationSize.width) / 2.0), y: animationFrame.minY + floor((animationFrame.height - animationSize.height) / 2.0)), size: animationSize)
|
view.frame = CGRect(origin: CGPoint(x: animationFrame.minX + floor((animationFrame.width - animationSize.width) / 2.0), y: animationFrame.minY + floor((animationFrame.height - animationSize.height) / 2.0)), size: animationSize)
|
||||||
|
|
||||||
|
if case .animating = animationMode {
|
||||||
|
view.playOnce()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_animation = rlottie::Animation::loadFromData(std::string(reinterpret_cast<const char *>(data.bytes), data.length), std::string([cacheKey UTF8String]), "", false, colorsVector, modifier);
|
_animation = rlottie::Animation::loadFromData(std::string(reinterpret_cast<const char *>(data.bytes), data.length), std::string([cacheKey UTF8String]), "", cacheKey.length != 0, colorsVector, modifier);
|
||||||
if (_animation == nullptr) {
|
if (_animation == nullptr) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -22,4 +22,8 @@
|
|||||||
#define LOTTIE_IMAGE_MODULE_DISABLED
|
#define LOTTIE_IMAGE_MODULE_DISABLED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOTTIE_CACHE_SUPPORT
|
||||||
|
#define LOTTIE_CACHE_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // CONFIG_H
|
#endif // CONFIG_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user