mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Sharing refactoring
This commit is contained in:
@@ -15,6 +15,7 @@ import VideoAnimationCache
|
||||
import MultiAnimationRenderer
|
||||
import ShimmerEffect
|
||||
import TextFormat
|
||||
import TelegramUIPreferences
|
||||
|
||||
public func generateTopicIcon(title: String, backgroundColors: [UIColor], strokeColors: [UIColor], size: CGSize) -> UIImage? {
|
||||
let realSize = size
|
||||
@@ -97,8 +98,20 @@ public extension AnimationCacheAnimationType {
|
||||
}
|
||||
|
||||
public func animationCacheFetchFile(context: AccountContext, userLocation: MediaResourceUserLocation, userContentType: MediaResourceUserContentType, resource: MediaResourceReference, type: AnimationCacheAnimationType, keyframeOnly: Bool, customColor: UIColor?) -> (AnimationCacheFetchOptions) -> Disposable {
|
||||
return animationCacheFetchFile(
|
||||
postbox: context.account.postbox,
|
||||
userLocation: userLocation,
|
||||
userContentType: userContentType,
|
||||
resource: resource,
|
||||
type: type,
|
||||
keyframeOnly: keyframeOnly,
|
||||
customColor: customColor
|
||||
)
|
||||
}
|
||||
|
||||
public func animationCacheFetchFile(postbox: Postbox, userLocation: MediaResourceUserLocation, userContentType: MediaResourceUserContentType, resource: MediaResourceReference, type: AnimationCacheAnimationType, keyframeOnly: Bool, customColor: UIColor?) -> (AnimationCacheFetchOptions) -> Disposable {
|
||||
return { options in
|
||||
let source = AnimatedStickerResourceSource(account: context.account, resource: resource.resource, fitzModifier: nil, isVideo: false)
|
||||
let source = AnimatedStickerResourceSource(postbox: postbox, resource: resource.resource, fitzModifier: nil, isVideo: false)
|
||||
|
||||
let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in
|
||||
guard let result = result else {
|
||||
@@ -119,7 +132,7 @@ public func animationCacheFetchFile(context: AccountContext, userLocation: Media
|
||||
}
|
||||
})
|
||||
|
||||
let fetchDisposable = fetchedMediaResource(mediaBox: context.account.postbox.mediaBox, userLocation: userLocation, userContentType: userContentType, reference: resource).start()
|
||||
let fetchDisposable = fetchedMediaResource(mediaBox: postbox.mediaBox, userLocation: userLocation, userContentType: userContentType, reference: resource).start()
|
||||
|
||||
return ActionDisposable {
|
||||
dataDisposable.dispose()
|
||||
@@ -129,6 +142,74 @@ public func animationCacheFetchFile(context: AccountContext, userLocation: Media
|
||||
}
|
||||
|
||||
public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
public enum Context: Equatable {
|
||||
public final class Custom: Equatable {
|
||||
public let postbox: Postbox
|
||||
public let energyUsageSettings: () -> EnergyUsageSettings
|
||||
public let resolveInlineStickers: ([Int64]) -> Signal<[Int64: TelegramMediaFile], NoError>
|
||||
|
||||
public init(postbox: Postbox, energyUsageSettings: @escaping () -> EnergyUsageSettings, resolveInlineStickers: @escaping ([Int64]) -> Signal<[Int64: TelegramMediaFile], NoError>) {
|
||||
self.postbox = postbox
|
||||
self.energyUsageSettings = energyUsageSettings
|
||||
self.resolveInlineStickers = resolveInlineStickers
|
||||
}
|
||||
|
||||
public static func ==(lhs: Custom, rhs: Custom) -> Bool {
|
||||
if lhs.postbox !== rhs.postbox {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case account(AccountContext)
|
||||
case custom(Custom)
|
||||
|
||||
var postbox: Postbox {
|
||||
switch self {
|
||||
case let .account(account):
|
||||
return account.account.postbox
|
||||
case let .custom(custom):
|
||||
return custom.postbox
|
||||
}
|
||||
}
|
||||
|
||||
var energyUsageSettings: EnergyUsageSettings {
|
||||
switch self {
|
||||
case let .account(account):
|
||||
return account.sharedContext.energyUsageSettings
|
||||
case let .custom(custom):
|
||||
return custom.energyUsageSettings()
|
||||
}
|
||||
}
|
||||
|
||||
func resolveInlineStickers(fileIds: [Int64]) -> Signal<[Int64: TelegramMediaFile], NoError> {
|
||||
switch self {
|
||||
case let .account(account):
|
||||
return account.engine.stickers.resolveInlineStickers(fileIds: fileIds)
|
||||
case let .custom(custom):
|
||||
return custom.resolveInlineStickers(fileIds)
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: Context, rhs: Context) -> Bool {
|
||||
switch lhs {
|
||||
case let .account(lhsContext):
|
||||
if case let .account(rhsContext) = rhs, lhsContext === rhsContext {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .custom(custom):
|
||||
if case .custom(custom) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static let queue = Queue()
|
||||
|
||||
public struct Key: Hashable {
|
||||
@@ -141,7 +222,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
}
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private let context: InlineStickerItemLayer.Context
|
||||
private let userLocation: MediaResourceUserLocation
|
||||
private let emoji: ChatTextInputTextCustomEmojiAttribute
|
||||
private let cache: AnimationCache
|
||||
@@ -189,7 +270,24 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
}
|
||||
}
|
||||
|
||||
public init(context: AccountContext, userLocation: MediaResourceUserLocation, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, unique: Bool = false, placeholderColor: UIColor, pointSize: CGSize, dynamicColor: UIColor? = nil, loopCount: Int? = nil) {
|
||||
public convenience init(context: AccountContext, userLocation: MediaResourceUserLocation, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, unique: Bool = false, placeholderColor: UIColor, pointSize: CGSize, dynamicColor: UIColor? = nil, loopCount: Int? = nil) {
|
||||
self.init(
|
||||
context: .account(context),
|
||||
userLocation: userLocation,
|
||||
attemptSynchronousLoad: attemptSynchronousLoad,
|
||||
emoji: emoji,
|
||||
file: file,
|
||||
cache: cache,
|
||||
renderer: renderer,
|
||||
unique: unique,
|
||||
placeholderColor: placeholderColor,
|
||||
pointSize: pointSize,
|
||||
dynamicColor: dynamicColor,
|
||||
loopCount: loopCount
|
||||
)
|
||||
}
|
||||
|
||||
public init(context: InlineStickerItemLayer.Context, userLocation: MediaResourceUserLocation, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, unique: Bool = false, placeholderColor: UIColor, pointSize: CGSize, dynamicColor: UIColor? = nil, loopCount: Int? = nil) {
|
||||
self.context = context
|
||||
self.userLocation = userLocation
|
||||
self.emoji = emoji
|
||||
@@ -211,7 +309,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
} else if let file = file {
|
||||
self.updateFile(file: file, attemptSynchronousLoad: attemptSynchronousLoad)
|
||||
} else {
|
||||
self.infoDisposable = (context.engine.stickers.resolveInlineStickers(fileIds: [emoji.fileId])
|
||||
self.infoDisposable = (context.resolveInlineStickers(fileIds: [emoji.fileId])
|
||||
|> deliverOnMainQueue).start(next: { [weak self] files in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@@ -335,7 +433,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
let pointSize = self.pointSize
|
||||
let placeholderColor = self.placeholderColor
|
||||
let isThumbnailCancelled = Atomic<Bool>(value: false)
|
||||
self.loadDisposable = self.renderer.loadFirstFrame(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, fetch: animationCacheFetchFile(context: self.context, userLocation: self.userLocation, userContentType: .sticker, resource: .media(media: .standalone(media: file), resource: file.resource), type: AnimationCacheAnimationType(file: file), keyframeOnly: true, customColor: isTemplate ? .white : nil), completion: { [weak self] result, isFinal in
|
||||
self.loadDisposable = self.renderer.loadFirstFrame(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, fetch: animationCacheFetchFile(postbox: self.context.postbox, userLocation: self.userLocation, userContentType: .sticker, resource: .media(media: .standalone(media: file), resource: file.resource), type: AnimationCacheAnimationType(file: file), keyframeOnly: true, customColor: isTemplate ? .white : nil), completion: { [weak self] result, isFinal in
|
||||
if !result {
|
||||
MultiAnimationRendererImpl.firstFrameQueue.async {
|
||||
let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: pointSize, scale: min(2.0, UIScreenScale), imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: placeholderColor)
|
||||
@@ -377,10 +475,10 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
if file.isAnimatedSticker || file.isVideoSticker || file.isVideoEmoji {
|
||||
let keyframeOnly = self.pixelSize.width >= 120.0
|
||||
|
||||
self.disposable = renderer.add(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, unique: self.unique, size: self.pixelSize, fetch: animationCacheFetchFile(context: context, userLocation: self.userLocation, userContentType: .sticker, resource: .media(media: .standalone(media: file), resource: file.resource), type: AnimationCacheAnimationType(file: file), keyframeOnly: keyframeOnly, customColor: isTemplate ? .white : nil))
|
||||
self.disposable = renderer.add(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, unique: self.unique, size: self.pixelSize, fetch: animationCacheFetchFile(postbox: self.context.postbox, userLocation: self.userLocation, userContentType: .sticker, resource: .media(media: .standalone(media: file), resource: file.resource), type: AnimationCacheAnimationType(file: file), keyframeOnly: keyframeOnly, customColor: isTemplate ? .white : nil))
|
||||
} else {
|
||||
self.disposable = renderer.add(target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, unique: self.unique, size: self.pixelSize, fetch: { options in
|
||||
let dataDisposable = context.account.postbox.mediaBox.resourceData(file.resource).start(next: { result in
|
||||
let dataDisposable = context.postbox.mediaBox.resourceData(file.resource).start(next: { result in
|
||||
guard result.complete else {
|
||||
return
|
||||
}
|
||||
@@ -388,7 +486,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
cacheStillSticker(path: result.path, width: Int(options.size.width), height: Int(options.size.height), writer: options.writer, customColor: isTemplate ? .white : nil)
|
||||
})
|
||||
|
||||
let fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: self.userLocation, fileReference: .customEmoji(media: file), resource: file.resource).start()
|
||||
let fetchDisposable = freeMediaFileResourceInteractiveFetched(postbox: context.postbox, userLocation: self.userLocation, fileReference: .customEmoji(media: file), resource: file.resource).start()
|
||||
|
||||
return ActionDisposable {
|
||||
dataDisposable.dispose()
|
||||
@@ -447,13 +545,26 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
|
||||
public final class EmojiTextAttachmentView: UIView {
|
||||
private let contentLayer: InlineStickerItemLayer
|
||||
|
||||
public init(context: AccountContext, userLocation: MediaResourceUserLocation, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) {
|
||||
public convenience init(context: AccountContext, userLocation: MediaResourceUserLocation, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) {
|
||||
self.init(
|
||||
context: .account(context),
|
||||
userLocation: userLocation,
|
||||
emoji: emoji,
|
||||
file: file,
|
||||
cache: cache,
|
||||
renderer: renderer,
|
||||
placeholderColor: placeholderColor,
|
||||
pointSize: pointSize
|
||||
)
|
||||
}
|
||||
|
||||
public init(context: InlineStickerItemLayer.Context, userLocation: MediaResourceUserLocation, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) {
|
||||
self.contentLayer = InlineStickerItemLayer(context: context, userLocation: userLocation, attemptSynchronousLoad: true, emoji: emoji, file: file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: pointSize)
|
||||
|
||||
super.init(frame: CGRect())
|
||||
|
||||
self.layer.addSublayer(self.contentLayer)
|
||||
self.contentLayer.isVisibleForAnimations = context.sharedContext.energyUsageSettings.loopEmoji
|
||||
self.contentLayer.isVisibleForAnimations = context.energyUsageSettings.loopEmoji
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
|
||||
Reference in New Issue
Block a user