Merge commit '6783076846f4e34c8e6f28e9f6bbd40cd56d6875'

This commit is contained in:
Ali 2023-07-12 22:56:25 +04:00
commit a6985734a2
24 changed files with 344 additions and 218 deletions

View File

@ -366,17 +366,17 @@ private final class CameraContext {
|> map { first, second in
return first && second
}
|> filter { $0 }
|> take(1)
|> delay(0.1, queue: self.queue)
|> deliverOn(self.queue)).start(next: { [weak self] _ in
|> filter { $0 }
|> take(1)
|> delay(0.1, queue: self.queue)
|> deliverOn(self.queue)).start(next: { [weak self] _ in
self?.modeChange = .none
})
} else {
let _ = (previewView.isPreviewing
|> filter { $0 }
|> take(1)
|> deliverOn(self.queue)).start(next: { [weak self] _ in
|> filter { $0 }
|> take(1)
|> deliverOn(self.queue)).start(next: { [weak self] _ in
self?.modeChange = .none
})
}

View File

@ -75,7 +75,6 @@ final class CameraOutput: NSObject {
let videoOutput = AVCaptureVideoDataOutput()
let audioOutput = AVCaptureAudioDataOutput()
let metadataOutput = AVCaptureMetadataOutput()
private let faceLandmarksOutput = FaceLandmarksDataOutput()
let exclusive: Bool
@ -85,17 +84,12 @@ final class CameraOutput: NSObject {
private let queue = DispatchQueue(label: "")
private let metadataQueue = DispatchQueue(label: "")
private let faceLandmarksQueue = DispatchQueue(label: "")
private var photoCaptureRequests: [Int64: PhotoCaptureContext] = [:]
private var videoRecorder: VideoRecorder?
var activeFilter: CameraFilter?
var faceLandmarks: Bool = false
var processSampleBuffer: ((CMSampleBuffer, CVImageBuffer, AVCaptureConnection) -> Void)?
var processCodes: (([CameraCode]) -> Void)?
var processFaceLandmarks: (([VNFaceObservation]) -> Void)?
init(exclusive: Bool) {
self.exclusive = exclusive
@ -104,12 +98,6 @@ final class CameraOutput: NSObject {
self.videoOutput.alwaysDiscardsLateVideoFrames = false
self.videoOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] as [String : Any]
self.faceLandmarksOutput.outputFaceObservations = { [weak self] observations in
if let self {
self.processFaceLandmarks?(observations)
}
}
}
deinit {
@ -273,7 +261,7 @@ final class CameraOutput: NSObject {
}
let uniqueId = settings.uniqueID
let photoCapture = PhotoCaptureContext(settings: settings, filter: self.activeFilter, mirror: mirror)
let photoCapture = PhotoCaptureContext(settings: settings, filter: nil, mirror: mirror)
self.photoCaptureRequests[uniqueId] = photoCapture
self.photoOutput.capturePhoto(with: settings, delegate: photoCapture)
@ -361,32 +349,10 @@ extension CameraOutput: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureA
return
}
if self.faceLandmarks {
self.faceLandmarksQueue.async {
self.faceLandmarksOutput.process(sampleBuffer: sampleBuffer)
}
}
if let videoPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
self.processSampleBuffer?(sampleBuffer, videoPixelBuffer, connection)
}
// let finalSampleBuffer: CMSampleBuffer = sampleBuffer
// if let videoPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer), let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) {
// var finalVideoPixelBuffer = videoPixelBuffer
// if let filter = self.activeFilter {
// if !filter.isPrepared {
// filter.prepare(with: formatDescription, outputRetainedBufferCountHint: 3)
// }
//
// guard let filteredBuffer = filter.render(pixelBuffer: finalVideoPixelBuffer) else {
// return
// }
// finalVideoPixelBuffer = filteredBuffer
// }
// self.processSampleBuffer?(finalVideoPixelBuffer, connection)
// }
if let videoRecorder = self.videoRecorder, videoRecorder.isRecording {
videoRecorder.appendSampleBuffer(sampleBuffer)
}

View File

@ -1227,7 +1227,7 @@ private final class DrawingScreenComponent: CombinedComponent {
case .filled:
nextStyle = .semi
case .semi:
nextStyle = .stroke
nextStyle = .regular
case .stroke:
nextStyle = .regular
}
@ -2975,6 +2975,8 @@ public final class DrawingToolsInteraction {
private var isActive = false
private var validLayout: ContainerViewLayout?
private let startTimestamp = CACurrentMediaTime()
public init(
context: AccountContext,
drawingView: DrawingView,
@ -3126,6 +3128,10 @@ public final class DrawingToolsInteraction {
if let textEntityView = entityView as? DrawingTextEntityView {
textEntityView.beginEditing(accessoryView: self.textEditAccessoryView)
} else {
if self.isVideo {
entityView.seek(to: 0.0)
}
entityView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
entityView.layer.animateScale(from: 0.1, to: entity.scale, duration: 0.2)
@ -3474,7 +3480,7 @@ public final class DrawingToolsInteraction {
case .filled:
nextStyle = .semi
case .semi:
nextStyle = .stroke
nextStyle = .regular
case .stroke:
nextStyle = .regular
}

View File

@ -295,7 +295,6 @@ private final class StickerSelectionComponent: Component {
},
peekBehavior: stickerPeekBehavior
)
return searchContainerNode
},
contentIdUpdated: { _ in },

View File

@ -31,6 +31,8 @@ swift_library(
"//submodules/StickerResources:StickerResources",
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
"//submodules/TelegramUI/Components/EmojiTextAttachmentView",
"//submodules/TextFormat",
],
visibility = [
"//visibility:public",

View File

@ -1059,8 +1059,8 @@ private enum FeaturedSearchEntry: Identifiable, Comparable {
func item(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction, itemContext: StickerPaneSearchGlobalItemContext) -> GridItem {
switch self {
case let .sticker(_, code, stickerItem, theme):
return StickerPaneSearchStickerItem(context: context, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, theme: theme, selected: { node, rect in
interaction.sendSticker(.standalone(media: stickerItem.file), node.view, rect)
return StickerPaneSearchStickerItem(context: context, theme: theme, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, selected: { node, layer, rect in
interaction.sendSticker(.standalone(media: stickerItem.file), node.view, layer, rect)
})
case let .global(_, info, topItems, installed, topSeparator):
return StickerPaneSearchGlobalItem(context: context, theme: theme, strings: strings, listAppearance: true, fillsRow: true, info: info, topItems: topItems, topSeparator: topSeparator, regularInsets: false, installed: installed, unread: false, open: {
@ -1201,7 +1201,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode {
|> deliverOnMainQueue).start(next: { _ in
})
}
}, sendSticker: { [weak self] file, sourceView, sourceRect in
}, sendSticker: { [weak self] file, sourceView, layer, sourceRect in
if let strongSelf = self {
let _ = strongSelf.sendSticker?(file, sourceView, sourceRect)
}
@ -1521,10 +1521,10 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode {
public final class StickerPaneSearchInteraction {
public let open: (StickerPackCollectionInfo) -> Void
public let install: (StickerPackCollectionInfo, [ItemCollectionItem], Bool) -> Void
public let sendSticker: (FileMediaReference, UIView, CGRect) -> Void
public let sendSticker: (FileMediaReference, UIView, CALayer, CGRect) -> Void
public let getItemIsPreviewed: (StickerPackItem) -> Bool
public init(open: @escaping (StickerPackCollectionInfo) -> Void, install: @escaping (StickerPackCollectionInfo, [ItemCollectionItem], Bool) -> Void, sendSticker: @escaping (FileMediaReference, UIView, CGRect) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
public init(open: @escaping (StickerPackCollectionInfo) -> Void, install: @escaping (StickerPackCollectionInfo, [ItemCollectionItem], Bool) -> Void, sendSticker: @escaping (FileMediaReference, UIView, CALayer, CGRect) -> Void, getItemIsPreviewed: @escaping (StickerPackItem) -> Bool) {
self.open = open
self.install = install
self.sendSticker = sendSticker

View File

@ -11,6 +11,8 @@ import AccountContext
import AnimatedStickerNode
import TelegramAnimatedStickerNode
import ChatPresentationInterfaceState
import EmojiTextAttachmentView
import TextFormat
final class StickerPaneSearchStickerSection: GridSection {
let code: String
@ -50,10 +52,11 @@ final class StickerPaneSearchStickerSectionNode: ASDisplayNode {
super.init()
self.addSubnode(self.titleNode)
self.titleNode.attributedText = NSAttributedString(string: code, font: sectionTitleFont, textColor: theme.chat.inputMediaPanel.stickersSectionTextColor)
self.titleNode.maximumNumberOfLines = 1
self.titleNode.truncationMode = .byTruncatingTail
self.addSubnode(self.titleNode)
}
override func layout() {
@ -68,15 +71,17 @@ final class StickerPaneSearchStickerSectionNode: ASDisplayNode {
public final class StickerPaneSearchStickerItem: GridItem {
public let context: AccountContext
public let theme: PresentationTheme
public let code: String?
public let stickerItem: FoundStickerItem
public let selected: (ASDisplayNode, CGRect) -> Void
public let selected: (ASDisplayNode, CALayer, CGRect) -> Void
public let inputNodeInteraction: ChatMediaInputNodeInteraction
public let section: GridSection?
public init(context: AccountContext, code: String?, stickerItem: FoundStickerItem, inputNodeInteraction: ChatMediaInputNodeInteraction, theme: PresentationTheme, selected: @escaping (ASDisplayNode, CGRect) -> Void) {
public init(context: AccountContext, theme: PresentationTheme, code: String?, stickerItem: FoundStickerItem, inputNodeInteraction: ChatMediaInputNodeInteraction, selected: @escaping (ASDisplayNode, CALayer, CGRect) -> Void) {
self.context = context
self.theme = theme
self.stickerItem = stickerItem
self.inputNodeInteraction = inputNodeInteraction
self.selected = selected
@ -87,7 +92,7 @@ public final class StickerPaneSearchStickerItem: GridItem {
public func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
let node = StickerPaneSearchStickerItemNode()
node.inputNodeInteraction = self.inputNodeInteraction
node.setup(context: self.context, stickerItem: self.stickerItem, code: self.code)
node.setup(context: self.context, theme: self.theme, stickerItem: self.stickerItem, code: self.code)
node.selected = self.selected
return node
}
@ -98,7 +103,7 @@ public final class StickerPaneSearchStickerItem: GridItem {
return
}
node.inputNodeInteraction = self.inputNodeInteraction
node.setup(context: self.context, stickerItem: self.stickerItem, code: self.code)
node.setup(context: self.context, theme: self.theme, stickerItem: self.stickerItem, code: self.code)
node.selected = self.selected
}
}
@ -107,8 +112,7 @@ private let textFont = Font.regular(20.0)
public final class StickerPaneSearchStickerItemNode: GridItemNode {
private var currentState: (AccountContext, FoundStickerItem, CGSize)?
public let imageNode: TransformImageNode
public private(set) var animationNode: AnimatedStickerNode?
var itemLayer: InlineStickerItemLayer?
private let textNode: ASTextNode
private let stickerFetchedDisposable = MetaDisposable()
@ -124,22 +128,21 @@ public final class StickerPaneSearchStickerItemNode: GridItemNode {
private var isPlaying = false
public var inputNodeInteraction: ChatMediaInputNodeInteraction?
public var selected: ((ASDisplayNode, CGRect) -> Void)?
public var selected: ((ASDisplayNode, CALayer, CGRect) -> Void)?
public var stickerItem: FoundStickerItem? {
return self.currentState?.1
}
public override init() {
self.imageNode = TransformImageNode()
self.textNode = ASTextNode()
self.textNode.isUserInteractionEnabled = false
super.init()
self.addSubnode(self.imageNode)
self.addSubnode(self.textNode)
self.textNode.maximumNumberOfLines = 1
self.addSubnode(self.textNode)
}
deinit {
@ -149,39 +152,43 @@ public final class StickerPaneSearchStickerItemNode: GridItemNode {
public override func didLoad() {
super.didLoad()
self.imageNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
}
func setup(context: AccountContext, stickerItem: FoundStickerItem, code: String?) {
func setup(context: AccountContext, theme: PresentationTheme, stickerItem: FoundStickerItem, code: String?) {
if self.currentState == nil || self.currentState!.0 !== context || self.currentState!.1 != stickerItem {
self.textNode.attributedText = NSAttributedString(string: code ?? "", font: textFont, textColor: .black)
if let dimensions = stickerItem.file.dimensions {
if stickerItem.file.isAnimatedSticker || stickerItem.file.isVideoSticker {
if self.animationNode == nil {
let animationNode = DefaultAnimatedStickerNodeImpl()
animationNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
self.animationNode = animationNode
self.insertSubnode(animationNode, belowSubnode: self.textNode)
}
let dimensions = stickerItem.file.dimensions ?? PixelDimensions(width: 512, height: 512)
let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0))
self.animationNode?.setup(source: AnimatedStickerResourceSource(account: context.account, resource: stickerItem.file.resource, isVideo: stickerItem.file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .cached)
self.animationNode?.visibility = self.isVisibleInGrid && context.sharedContext.energyUsageSettings.loopStickers
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: stickerItem.file.resource).start())
} else {
if let animationNode = self.animationNode {
animationNode.visibility = false
self.animationNode = nil
animationNode.removeFromSupernode()
}
self.imageNode.setSignal(chatMessageSticker(account: context.account, userLocation: .other, file: stickerItem.file, small: true))
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: context.account, userLocation: .other, fileReference: stickerPackFileReference(stickerItem.file), resource: chatMessageStickerResource(file: stickerItem.file, small: true)).start())
}
self.currentState = (context, stickerItem, dimensions.cgSize)
self.setNeedsLayout()
let file = stickerItem.file
let itemDimensions = file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)
let playbackItemSize = CGSize(width: 96.0, height: 96.0)
let itemPlaybackSize = itemDimensions.aspectFitted(playbackItemSize)
let itemLayer: InlineStickerItemLayer
if let current = self.itemLayer {
itemLayer = current
itemLayer.dynamicColor = .white
} else {
itemLayer = InlineStickerItemLayer(
context: context,
userLocation: .other,
attemptSynchronousLoad: false,
emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: file.fileId.id, file: file),
file: file,
cache: context.animationCache,
renderer: context.animationRenderer,
placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1),
pointSize: itemPlaybackSize,
dynamicColor: .white
)
self.itemLayer = itemLayer
self.layer.insertSublayer(itemLayer, at: 0)
}
self.currentState = (context, stickerItem, itemDimensions)
self.setNeedsLayout()
self.updateVisibility()
}
}
@ -191,29 +198,26 @@ public final class StickerPaneSearchStickerItemNode: GridItemNode {
let bounds = self.bounds
let boundingSize = bounds.insetBy(dx: 6.0, dy: 6.0).size
if let (_, _, mediaDimensions) = self.currentState {
let imageSize = mediaDimensions.aspectFitted(boundingSize)
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))()
let imageFrame = CGRect(origin: CGPoint(x: floor((bounds.size.width - imageSize.width) / 2.0), y: (bounds.size.height - imageSize.height) / 2.0), size: imageSize)
self.imageNode.frame = imageFrame
if let animationNode = self.animationNode {
animationNode.frame = imageFrame
animationNode.updateLayout(size: imageSize)
if let (_, _, itemDimensions) = self.currentState {
let itemSize = itemDimensions.aspectFitted(boundingSize)
let itemFrame = CGRect(origin: CGPoint(x: floor((bounds.size.width - itemSize.width) / 2.0), y: (bounds.size.height - itemSize.height) / 2.0), size: itemSize)
if let itemLayer = self.itemLayer {
itemLayer.frame = itemFrame
}
let textSize = self.textNode.measure(CGSize(width: bounds.size.width - 24.0, height: CGFloat.greatestFiniteMagnitude))
self.textNode.frame = CGRect(origin: CGPoint(x: bounds.size.width - textSize.width, y: bounds.size.height - textSize.height), size: textSize)
}
}
@objc func imageNodeTap(_ recognizer: UITapGestureRecognizer) {
self.selected?(self, self.bounds)
guard let itemLayer = self.itemLayer else {
return
}
self.selected?(self, itemLayer, self.bounds)
}
public func transitionNode() -> ASDisplayNode? {
return self.imageNode
return self
}
public func updateVisibility() {
@ -222,9 +226,9 @@ public final class StickerPaneSearchStickerItemNode: GridItemNode {
}
let isPlaying = self.isVisibleInGrid && context.sharedContext.energyUsageSettings.loopStickers
if self.isPlaying != isPlaying {
if self.isPlaying != isPlaying, let itemLayer = self.itemLayer {
self.isPlaying = isPlaying
self.animationNode?.visibility = isPlaying
itemLayer.isVisibleForAnimations = isPlaying
}
}

View File

@ -43,7 +43,8 @@ swift_library(
"//submodules/MoreButtonNode:MoreButtonNode",
"//submodules/InvisibleInkDustNode:InvisibleInkDustNode",
"//submodules/TelegramUI/Components/CameraScreen",
"//submodules/TelegramUI/Components/MediaEditor",
"//submodules/TelegramUI/Components/MediaEditor",
"//submodules/RadialStatusNode",
],
visibility = [
"//visibility:public",

View File

@ -17,7 +17,7 @@ final class AssetDownloadManager {
let identifier: String
let updated: () -> Void
var status: AssetDownloadStatus = .progress(0.0)
var status: AssetDownloadStatus = .none
var disposable: Disposable?
init(identifier: String, updated: @escaping () -> Void) {
@ -40,9 +40,7 @@ final class AssetDownloadManager {
}
func download(asset: PHAsset) {
if let currentAssetContext = self.currentAssetContext {
currentAssetContext.disposable?.dispose()
}
self.cancelAllDownloads()
let queue = self.queue
let identifier = asset.localIdentifier
@ -59,6 +57,7 @@ final class AssetDownloadManager {
}
}
})
self.currentAssetContext = assetContext
assetContext.disposable = (downloadAssetMediaData(asset)
|> deliverOn(queue)).start(next: { [weak self] status in
guard let self else {
@ -69,13 +68,31 @@ final class AssetDownloadManager {
currentAssetContext.updated()
}
})
self.currentAssetContext = assetContext
}
func cancelAllDownloads() {
if let currentAssetContext = self.currentAssetContext {
currentAssetContext.status = .none
currentAssetContext.updated()
currentAssetContext.disposable?.dispose()
self.queue.justDispatch {
if self.currentAssetContext === currentAssetContext {
self.currentAssetContext = nil
}
}
}
}
func cancel(identifier: String) {
if let currentAssetContext = self.currentAssetContext, currentAssetContext.identifier == identifier {
currentAssetContext.status = .none
currentAssetContext.updated()
currentAssetContext.disposable?.dispose()
self.currentAssetContext = nil
self.queue.justDispatch {
if self.currentAssetContext === currentAssetContext {
self.currentAssetContext = nil
}
}
}
}
@ -93,7 +110,7 @@ final class AssetDownloadManager {
if let currentAssetContext = self.currentAssetContext, currentAssetContext.identifier == identifier {
next(currentAssetContext.status)
} else {
next(.progress(0.0))
next(.none)
}
let queue = self.queue
@ -129,27 +146,35 @@ final class AssetDownloadManager {
}
func checkIfAssetIsLocal(_ asset: PHAsset) -> Signal<Bool, NoError> {
if asset.isLocallyAvailable == true {
return .single(true)
}
return Signal { subscriber in
let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = false
let requestId: PHImageRequestID
if #available(iOS 13, *) {
requestId = imageManager.requestImageDataAndOrientation(for: asset, options: options) { data, _, _, _ in
if data != nil {
subscriber.putNext(data != nil)
}
if case .video = asset.mediaType {
let options = PHVideoRequestOptions()
options.isNetworkAccessAllowed = false
requestId = imageManager.requestAVAsset(forVideo: asset, options: options) { asset, _, _ in
subscriber.putNext(asset != nil)
subscriber.putCompletion()
}
} else {
requestId = imageManager.requestImageData(for: asset, options: options) { data, _, _, _ in
if data != nil {
let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = false
if #available(iOS 13, *) {
requestId = imageManager.requestImageDataAndOrientation(for: asset, options: options) { data, _, _, _ in
subscriber.putNext(data != nil)
subscriber.putCompletion()
}
} else {
requestId = imageManager.requestImageData(for: asset, options: options) { data, _, _, _ in
subscriber.putNext(data != nil)
subscriber.putCompletion()
}
subscriber.putCompletion()
}
}
return ActionDisposable {
imageManager.cancelImageRequest(requestId)
}
@ -157,32 +182,57 @@ func checkIfAssetIsLocal(_ asset: PHAsset) -> Signal<Bool, NoError> {
}
enum AssetDownloadStatus {
case none
case progress(Float)
case completed
}
private func downloadAssetMediaData(_ asset: PHAsset) -> Signal<AssetDownloadStatus, NoError> {
return Signal { subscriber in
let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = true
options.progressHandler = { progress, _, _, _ in
subscriber.putNext(.progress(Float(progress)))
}
let requestId: PHImageRequestID
if #available(iOS 13, *) {
requestId = imageManager.requestImageDataAndOrientation(for: asset, options: options) { data, _, _, _ in
if data != nil {
if case .video = asset.mediaType {
let options = PHVideoRequestOptions()
options.isNetworkAccessAllowed = true
options.progressHandler = { progress, _, _, _ in
subscriber.putNext(.progress(Float(progress)))
}
subscriber.putNext(.progress(0.0))
requestId = imageManager.requestAVAsset(forVideo: asset, options: options) { asset, _, _ in
if asset != nil {
subscriber.putNext(.completed)
} else {
subscriber.putNext(.none)
}
subscriber.putCompletion()
}
} else {
requestId = imageManager.requestImageData(for: asset, options: options) { data, _, _, _ in
if data != nil {
subscriber.putNext(.completed)
let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = true
options.progressHandler = { progress, _, _, _ in
subscriber.putNext(.progress(Float(progress)))
}
subscriber.putNext(.progress(0.0))
if #available(iOS 13, *) {
requestId = imageManager.requestImageDataAndOrientation(for: asset, options: options) { data, _, _, _ in
if data != nil {
subscriber.putNext(.completed)
} else {
subscriber.putNext(.none)
}
subscriber.putCompletion()
}
} else {
requestId = imageManager.requestImageData(for: asset, options: options) { data, _, _, _ in
if data != nil {
subscriber.putNext(.completed)
} else {
subscriber.putNext(.none)
}
subscriber.putCompletion()
}
subscriber.putCompletion()
}
}

View File

@ -16,6 +16,7 @@ import InvisibleInkDustNode
import ImageBlur
import FastBlur
import MediaEditor
import RadialStatusNode
enum MediaPickerGridItemContent: Equatable {
case asset(PHFetchResult<PHAsset>, Int)
@ -90,7 +91,9 @@ private let maskImage = generateImage(CGSize(width: 1.0, height: 36.0), opaque:
final class MediaPickerGridItemNode: GridItemNode {
var currentMediaState: (TGMediaSelectableItem, Int)?
var currentState: (PHFetchResult<PHAsset>, Int)?
var currentAssetState: (PHFetchResult<PHAsset>, Int)?
var currentAsset: PHAsset?
var currentDraftState: (MediaEditorDraft, Int)?
var enableAnimations: Bool = true
var stories: Bool = false
@ -103,6 +106,7 @@ final class MediaPickerGridItemNode: GridItemNode {
private let typeIconNode: ASImageNode
private let durationNode: ImmediateTextNode
private let draftNode: ImmediateTextNode
private var statusNode: RadialStatusNode?
private let activateAreaNode: AccessibilityAreaNode
@ -112,6 +116,8 @@ final class MediaPickerGridItemNode: GridItemNode {
private let spoilerDisposable = MetaDisposable()
var spoilerNode: SpoilerOverlayNode?
private let progressDisposable = MetaDisposable()
private var currentIsPreviewing = false
var selected: (() -> Void)?
@ -140,7 +146,7 @@ final class MediaPickerGridItemNode: GridItemNode {
self.activateAreaNode = AccessibilityAreaNode()
self.activateAreaNode.accessibilityTraits = [.image]
super.init()
self.clipsToBounds = true
@ -168,7 +174,7 @@ final class MediaPickerGridItemNode: GridItemNode {
var selectableItem: TGMediaSelectableItem? {
if let (media, _) = self.currentMediaState {
return media
} else if let (fetchResult, index) = self.currentState {
} else if let (fetchResult, index) = self.currentAssetState {
return TGMediaAsset(phAsset: fetchResult[index])
} else {
return nil
@ -179,7 +185,7 @@ final class MediaPickerGridItemNode: GridItemNode {
var tag: Int32? {
if let tag = self._cachedTag {
return tag
} else if let (fetchResult, index) = self.currentState {
} else if let (fetchResult, index) = self.currentAssetState {
let asset = fetchResult.object(at: index)
if let localTimestamp = asset.creationDate?.timeIntervalSince1970 {
let tag = Month(localTimestamp: Int32(localTimestamp)).packedValue
@ -251,6 +257,32 @@ final class MediaPickerGridItemNode: GridItemNode {
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:))))
}
func updateProgress(_ value: Float?, animated: Bool) {
if let value {
let statusNode: RadialStatusNode
if let current = self.statusNode {
statusNode = current
} else {
statusNode = RadialStatusNode(backgroundNodeColor: UIColor(rgb: 0x000000, alpha: 0.6))
statusNode.isUserInteractionEnabled = false
self.addSubnode(statusNode)
self.statusNode = statusNode
}
let adjustedProgress = max(0.027, CGFloat(value))
let state: RadialStatusNodeState = .progress(color: .white, lineWidth: nil, value: adjustedProgress, cancelEnabled: true, animateRotation: true)
statusNode.transitionToState(state)
} else if let statusNode = self.statusNode {
self.statusNode = nil
if animated {
statusNode.transitionToState(.none, animated: true, completion: { [weak statusNode] in
statusNode?.removeFromSupernode()
})
} else {
statusNode.removeFromSupernode()
}
}
}
func setup(interaction: MediaPickerInteraction, draft: MediaEditorDraft, index: Int, theme: PresentationTheme, selectable: Bool, enableAnimations: Bool, stories: Bool) {
self.interaction = interaction
self.theme = theme
@ -259,14 +291,18 @@ final class MediaPickerGridItemNode: GridItemNode {
self.backgroundColor = theme.list.mediaPlaceholderColor
if self.currentDraftState == nil || self.currentDraftState?.0.path != draft.path || self.currentDraftState!.1 != index || self.currentState != nil {
if self.currentDraftState == nil || self.currentDraftState?.0.path != draft.path || self.currentDraftState!.1 != index || self.currentAssetState != nil {
let imageSignal: Signal<UIImage?, NoError> = .single(draft.thumbnail)
self.imageNode.setSignal(imageSignal)
self.currentDraftState = (draft, index)
if self.currentState != nil {
self.currentState = nil
if self.currentAssetState != nil {
self.currentAsset = nil
self.currentAssetState = nil
self.typeIconNode.removeFromSupernode()
self.progressDisposable.set(nil)
self.updateProgress(nil, animated: false)
}
if self.draftNode.supernode == nil {
@ -354,11 +390,30 @@ final class MediaPickerGridItemNode: GridItemNode {
self.draftNode.removeFromSupernode()
}
if self.currentState == nil || self.currentState!.0 !== fetchResult || self.currentState!.1 != index || self.currentDraftState != nil {
self.backgroundNode.image = nil
if self.currentAssetState == nil || self.currentAssetState!.0 !== fetchResult || self.currentAssetState!.1 != index || self.currentDraftState != nil {
let editingContext = interaction.editingState
let asset = fetchResult.object(at: index)
if asset.localIdentifier == self.currentAsset?.localIdentifier {
return
}
self.progressDisposable.set(
(interaction.downloadManager.downloadProgress(identifier: asset.localIdentifier)
|> deliverOnMainQueue).start(next: { [weak self] status in
if let self {
switch status {
case .none, .completed:
self.updateProgress(nil, animated: true)
case let .progress(progress):
self.updateProgress(progress, animated: true)
}
}
})
)
self.backgroundNode.image = nil
if #available(iOS 15.0, *) {
self.activateAreaNode.accessibilityLabel = "Photo \(asset.creationDate?.formatted(date: .abbreviated, time: .standard) ?? "")"
}
@ -489,7 +544,8 @@ final class MediaPickerGridItemNode: GridItemNode {
}
}
self.currentState = (fetchResult, index)
self.currentAssetState = (fetchResult, index)
self.currentAsset = asset
self.setNeedsLayout()
}
@ -554,6 +610,11 @@ final class MediaPickerGridItemNode: GridItemNode {
spoilerNode.frame = self.bounds
spoilerNode.update(size: self.bounds.size, transition: .immediate)
}
let statusSize = CGSize(width: 40.0, height: 40.0)
if let statusNode = self.statusNode {
statusNode.view.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.bounds.width - statusSize.width) / 2.0), y: floorToScreenPixels((self.bounds.height - statusSize.height) / 2.0)), size: statusSize)
}
}
func transitionView(snapshot: Bool) -> UIView {
@ -589,10 +650,16 @@ final class MediaPickerGridItemNode: GridItemNode {
self.interaction?.openDraft(draft, self.imageNode.image)
return
}
guard let (fetchResult, index) = self.currentState else {
guard let (fetchResult, index) = self.currentAssetState else {
return
}
self.interaction?.openMedia(fetchResult, index, self.imageNode.image)
if self.statusNode != nil {
if let asset = self.currentAsset {
self.interaction?.downloadManager.cancel(identifier: asset.localIdentifier)
}
} else {
self.interaction?.openMedia(fetchResult, index, self.imageNode.image)
}
}
}

View File

@ -25,6 +25,7 @@ import CameraScreen
import MediaEditor
final class MediaPickerInteraction {
let downloadManager: AssetDownloadManager
let openMedia: (PHFetchResult<PHAsset>, Int, UIImage?) -> Void
let openSelectedMedia: (TGMediaSelectableItem, UIImage?) -> Void
let openDraft: (MediaEditorDraft, UIImage?) -> Void
@ -36,7 +37,8 @@ final class MediaPickerInteraction {
let editingState: TGMediaEditingContext
var hiddenMediaId: String?
init(openMedia: @escaping (PHFetchResult<PHAsset>, Int, UIImage?) -> Void, openSelectedMedia: @escaping (TGMediaSelectableItem, UIImage?) -> Void, openDraft: @escaping (MediaEditorDraft, UIImage?) -> Void, toggleSelection: @escaping (TGMediaSelectableItem, Bool, Bool) -> Bool, sendSelected: @escaping (TGMediaSelectableItem?, Bool, Int32?, Bool, @escaping () -> Void) -> Void, schedule: @escaping () -> Void, dismissInput: @escaping () -> Void, selectionState: TGMediaSelectionContext?, editingState: TGMediaEditingContext) {
init(downloadManager: AssetDownloadManager, openMedia: @escaping (PHFetchResult<PHAsset>, Int, UIImage?) -> Void, openSelectedMedia: @escaping (TGMediaSelectableItem, UIImage?) -> Void, openDraft: @escaping (MediaEditorDraft, UIImage?) -> Void, toggleSelection: @escaping (TGMediaSelectableItem, Bool, Bool) -> Bool, sendSelected: @escaping (TGMediaSelectableItem?, Bool, Int32?, Bool, @escaping () -> Void) -> Void, schedule: @escaping () -> Void, dismissInput: @escaping () -> Void, selectionState: TGMediaSelectionContext?, editingState: TGMediaEditingContext) {
self.downloadManager = downloadManager
self.openMedia = openMedia
self.openSelectedMedia = openSelectedMedia
self.openDraft = openDraft
@ -393,6 +395,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.selectionChangedDisposable?.dispose()
self.itemsDimensionsUpdatedDisposable?.dispose()
self.fastScrollDisposable?.dispose()
self.currentAssetDownloadDisposable.dispose()
}
override func didLoad() {
@ -777,8 +780,29 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
private weak var currentGalleryController: TGModernGalleryController?
private func requestAssetDownload(_ asset: PHAsset) {
fileprivate var currentAssetDownloadDisposable = MetaDisposable()
fileprivate func cancelAssetDownloads() {
guard let downloadManager = self.controller?.downloadManager else {
return
}
self.currentAssetDownloadDisposable.set(nil)
downloadManager.cancelAllDownloads()
}
fileprivate func requestAssetDownload(asset: PHAsset) {
guard let downloadManager = self.controller?.downloadManager else {
return
}
downloadManager.download(asset: asset)
self.currentAssetDownloadDisposable.set(
(downloadManager.downloadProgress(identifier: asset.localIdentifier)
|> deliverOnMainQueue).start(next: { [weak self] status in
if let self, case .completed = status, let controller = self.controller, let customSelection = self.controller?.customSelection {
customSelection(controller, asset)
}
})
)
}
private var openingMedia = false
@ -794,26 +818,19 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.openingMedia = true
let asset = fetchResult[index]
customSelection(controller, asset)
// let isLocallyAvailable = asset.isLocallyAvailable
//
// if let isLocallyAvailable {
// if isLocallyAvailable {
// customSelection(controller, asset)
// } else {
// self.requestAssetDownload(asset)
// }
// } else {
// let _ = (checkIfAssetIsLocal(asset)
// |> deliverOnMainQueue).start(next: { [weak self] isLocallyAvailable in
// if isLocallyAvailable {
// customSelection(controller, asset)
// } else {
// self?.requestAssetDownload(asset)
// }
// })
// }
let _ = (checkIfAssetIsLocal(asset)
|> deliverOnMainQueue).start(next: { [weak self] isLocallyAvailable in
guard let self else {
return
}
if isLocallyAvailable {
self.cancelAssetDownloads()
customSelection(controller, asset)
} else {
self.requestAssetDownload(asset: asset)
}
})
Queue.mainQueue().after(0.3) {
self.openingMedia = false
@ -1365,6 +1382,8 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
}
private let groupedPromise = ValuePromise<Bool>(true)
private let downloadManager = AssetDownloadManager()
private var isDismissing = false
fileprivate let mainButtonState: AttachmentMainButtonState?
@ -1538,13 +1557,17 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
}
}
self.interaction = MediaPickerInteraction(openMedia: { [weak self] fetchResult, index, immediateThumbnail in
self.interaction = MediaPickerInteraction(downloadManager: self.downloadManager,
openMedia: { [weak self] fetchResult, index, immediateThumbnail in
self?.controllerNode.openMedia(fetchResult: fetchResult, index: index, immediateThumbnail: immediateThumbnail)
}, openSelectedMedia: { [weak self] item, immediateThumbnail in
},
openSelectedMedia: { [weak self] item, immediateThumbnail in
self?.controllerNode.openSelectedMedia(item: item, immediateThumbnail: immediateThumbnail)
}, openDraft: { [weak self] draft, immediateThumbnail in
},
openDraft: { [weak self] draft, immediateThumbnail in
self?.controllerNode.openDraft(draft: draft, immediateThumbnail: immediateThumbnail)
}, toggleSelection: { [weak self] item, value, suggestUndo in
},
toggleSelection: { [weak self] item, value, suggestUndo in
if let self = self, let selectionState = self.interaction?.selectionState {
if let _ = item as? TGMediaPickerGalleryPhotoItem {
if self.bannedSendPhotos != nil {
@ -1798,7 +1821,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.undoOverlayController?.dismissWithCommitAction()
}
public func requestDismiss(completion: @escaping () -> Void) {
public func requestDismiss(completion: @escaping () -> Void) {
if let selectionState = self.interaction?.selectionState, selectionState.count() > 0 {
self.isDismissing = true
@ -1837,6 +1860,12 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.dismiss()
}
public override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
self.controllerNode.cancelAssetDownloads()
super.dismiss(animated: flag, completion: completion)
}
@objc private func rightButtonPressed() {
self.moreButtonNode.buttonPressed()
}

View File

@ -284,6 +284,7 @@ final class PendingStoryManager {
self.currentPendingItemContext = pendingItemContext
let stableId = firstItem.stableId
Logger.shared.log("PendingStoryManager", "setting up item context for: \(firstItem.stableId) randomId: \(firstItem.randomId)")
pendingItemContext.disposable = (_internal_uploadStoryImpl(postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, stateManager: self.stateManager, messageMediaPreuploadManager: self.messageMediaPreuploadManager, revalidationContext: self.revalidationContext, auxiliaryMethods: self.auxiliaryMethods, stableId: stableId, media: firstItem.media, text: firstItem.text, entities: firstItem.entities, embeddedStickers: firstItem.embeddedStickers, pin: firstItem.pin, privacy: firstItem.privacy, isForwardingDisabled: firstItem.isForwardingDisabled, period: Int(firstItem.period), randomId: firstItem.randomId)
|> deliverOn(self.queue)).start(next: { [weak self] event in
guard let `self` = self else {

View File

@ -755,6 +755,7 @@ func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text:
period: Int32(period),
randomId: randomId
))
Logger.shared.log("UploadStory", "Appended new pending item stableId: \(stableId) randomId: \(randomId)")
transaction.setLocalStoryState(state: CodableEntry(currentState))
}).start()
}
@ -798,6 +799,7 @@ private func _internal_putPendingStoryIdMapping(accountPeerId: PeerId, stableId:
}
func _internal_uploadStoryImpl(postbox: Postbox, network: Network, accountPeerId: PeerId, stateManager: AccountStateManager, messageMediaPreuploadManager: MessageMediaPreuploadManager, revalidationContext: MediaReferenceRevalidationContext, auxiliaryMethods: AccountAuxiliaryMethods, stableId: Int32, media: Media, text: String, entities: [MessageTextEntity], embeddedStickers: [TelegramMediaFile], pin: Bool, privacy: EngineStoryPrivacy, isForwardingDisabled: Bool, period: Int, randomId: Int64) -> Signal<StoryUploadResult, NoError> {
Logger.shared.log("UploadStory", "uploadStoryImpl for stableId: \(stableId) randomId: \(randomId)")
let passFetchProgress = media is TelegramMediaFile
let (contentSignal, originalMedia) = uploadedStoryContent(postbox: postbox, network: network, media: media, embeddedStickers: embeddedStickers, accountPeerId: accountPeerId, messageMediaPreuploadManager: messageMediaPreuploadManager, revalidationContext: revalidationContext, auxiliaryMethods: auxiliaryMethods, passFetchProgress: passFetchProgress)
return contentSignal

View File

@ -303,6 +303,8 @@ private final class CameraScreenComponent: CombinedComponent {
self.isPressingButton = true
}
self.buttonPressTimestamp = nil
self.buttonPressTimer?.invalidate()
self.buttonPressTimer = nil
}
}, queue: Queue.mainQueue())
self.buttonPressTimer?.start()
@ -641,11 +643,15 @@ private final class CameraScreenComponent: CombinedComponent {
}
controller.presentGallery()
},
swipeHintUpdated: { hint in
state.updateSwipeHint(hint)
swipeHintUpdated: { [weak state] hint in
if let state {
state.updateSwipeHint(hint)
}
},
zoomUpdated: { fraction in
state.updateZoom(fraction: fraction)
zoomUpdated: { [weak state] fraction in
if let state {
state.updateZoom(fraction: fraction)
}
},
flipAnimationAction: animateFlipAction
),
@ -737,10 +743,9 @@ private final class CameraScreenComponent: CombinedComponent {
component: CameraButton(
content: flashContentComponent,
action: { [weak state] in
guard let state else {
return
if let state {
state.toggleFlashMode()
}
state.toggleFlashMode()
}
).tagged(flashButtonTag),
availableSize: CGSize(width: 40.0, height: 40.0),
@ -762,10 +767,9 @@ private final class CameraScreenComponent: CombinedComponent {
)
),
action: { [weak state] in
guard let state else {
return
if let state {
state.toggleDualCamera()
}
state.toggleDualCamera()
}
).tagged(dualButtonTag),
availableSize: CGSize(width: 40.0, height: 40.0),

View File

@ -89,8 +89,8 @@ private enum StickerSearchEntry: Identifiable, Comparable {
func item(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, interaction: StickerPaneSearchInteraction, inputNodeInteraction: ChatMediaInputNodeInteraction) -> GridItem {
switch self {
case let .sticker(_, code, stickerItem, theme):
return StickerPaneSearchStickerItem(context: context, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, theme: theme, selected: { node, rect in
interaction.sendSticker(.standalone(media: stickerItem.file), node.view, rect)
return StickerPaneSearchStickerItem(context: context, theme: theme, code: code, stickerItem: stickerItem, inputNodeInteraction: inputNodeInteraction, selected: { node, layer, rect in
interaction.sendSticker(.standalone(media: stickerItem.file), node.view, layer, rect)
})
case let .global(_, info, topItems, installed, topSeparator):
let itemContext = StickerPaneSearchGlobalItemContext()
@ -316,9 +316,10 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode {
|> deliverOnMainQueue).start(next: { _ in
})
}
}, sendSticker: { [weak self] file, sourceView, sourceRect in
if let strongSelf = self {
let _ = strongSelf.interaction.sendSticker(file, false, false, nil, false, sourceView, sourceRect, nil, [])
}, sendSticker: { [weak self] file, sourceView, sourceLayer, sourceRect in
if let self {
let sourceRect = sourceView.convert(sourceRect, to: self.view)
let _ = self.interaction.sendSticker(file, false, false, nil, false, self.view, sourceRect, sourceLayer, [])
}
}, getItemIsPreviewed: { item in
return inputNodeInteraction.previewedStickerPackItemFile?.id == item.file.id

View File

@ -743,10 +743,11 @@ public final class EntityKeyboardComponent: Component {
panelHideBehavior = .hideOnScroll
}
let isContentInFocus = component.isContentInFocus && self.searchComponent == nil
let pagerSize = self.pagerView.update(
transition: transition,
component: AnyComponent(PagerComponent(
isContentInFocus: component.isContentInFocus,
isContentInFocus: isContentInFocus,
contentInsets: component.containerInsets,
contents: contents,
contentTopPanels: contentTopPanels,
@ -801,7 +802,7 @@ public final class EntityKeyboardComponent: Component {
EntityKeyboardChildEnvironment(
theme: component.theme,
strings: component.strings,
isContentInFocus: component.isContentInFocus,
isContentInFocus: isContentInFocus,
getContentActiveItemUpdated: { id in
if id == AnyHashable("gifs") {
return gifsContentItemIdUpdated
@ -950,7 +951,7 @@ public final class EntityKeyboardComponent: Component {
}
)
}
//self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring)))
component.hideInputUpdated(true, true, Transition(animation: .curve(duration: 0.3, curve: .spring)))
}
}

View File

@ -507,7 +507,9 @@ public final class MediaEditor {
self.onPlaybackAction(.seek(start))
self.player?.play()
self.additionalPlayer?.play()
self.onPlaybackAction(.play)
Queue.mainQueue().justDispatch {
self.onPlaybackAction(.play)
}
}
})
Queue.mainQueue().justDispatch {

View File

@ -3615,6 +3615,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
}
let fittedSize = resultImage.size.aspectFitted(CGSize(width: 128.0, height: 128.0))
let context = self.context
let saveImageDraft: (UIImage, PixelDimensions) -> Void = { image, dimensions in
if let thumbnailImage = generateScaledImage(image: resultImage, size: fittedSize) {
let path = "\(Int64.random(in: .min ... .max)).jpg"
@ -3622,9 +3623,9 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
let draft = MediaEditorDraft(path: path, isVideo: false, thumbnail: thumbnailImage, dimensions: dimensions, duration: nil, values: values, caption: caption, privacy: privacy, timestamp: timestamp)
try? data.write(to: URL(fileURLWithPath: draft.fullPath()))
if let id {
saveStorySource(engine: self.context.engine, item: draft, id: id)
saveStorySource(engine: context.engine, item: draft, id: id)
} else {
addStoryDraft(engine: self.context.engine, item: draft)
addStoryDraft(engine: context.engine, item: draft)
}
}
}
@ -3636,9 +3637,9 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
let draft = MediaEditorDraft(path: path, isVideo: true, thumbnail: thumbnailImage, dimensions: dimensions, duration: duration, values: values, caption: caption, privacy: privacy, timestamp: timestamp)
try? FileManager.default.moveItem(atPath: videoPath, toPath: draft.fullPath())
if let id {
saveStorySource(engine: self.context.engine, item: draft, id: id)
saveStorySource(engine: context.engine, item: draft, id: id)
} else {
addStoryDraft(engine: self.context.engine, item: draft)
addStoryDraft(engine: context.engine, item: draft)
}
}
}
@ -3861,6 +3862,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
if let self {
makeEditorImageComposition(context: self.node.ciContext, account: self.context.account, inputImage: image ?? UIImage(), dimensions: storyDimensions, values: mediaEditor.values, time: .zero, completion: { [weak self] coverImage in
if let self {
Logger.shared.log("Media Editor", "completed with video \(videoResult)")
self.completion(randomId, .video(video: videoResult, coverImage: coverImage, values: mediaEditor.values, duration: duration, dimensions: mediaEditor.values.resultDimensions), caption, self.state.privacy, stickers, { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()
@ -3883,6 +3885,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
makeEditorImageComposition(context: self.node.ciContext, account: self.context.account, inputImage: image, dimensions: storyDimensions, values: mediaEditor.values, time: .zero, completion: { [weak self] resultImage in
if let self, let resultImage {
Logger.shared.log("Media Editor", "completed with image \(resultImage)")
self.completion(randomId, .image(image: resultImage, dimensions: PixelDimensions(resultImage.size)), caption, self.state.privacy, stickers, { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()

View File

@ -322,10 +322,10 @@ final class ContextResultPanelComponent: Component {
transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: minimizedHeight)))
let visibleTopContentHeight = min(scrollContentSize.height, measureItemSize.height * 3.5 + 19.0)
let visibleTopContentHeight = min(scrollContentSize.height, measureItemSize.height * 3.5)
let topInset = availableSize.height - visibleTopContentHeight
let scrollContentInsets = UIEdgeInsets(top: topInset, left: 0.0, bottom: 19.0, right: 0.0)
let scrollContentInsets = UIEdgeInsets(top: topInset, left: 0.0, bottom: 0.0, right: 0.0)
let scrollIndicatorInsets = UIEdgeInsets(top: topInset + 17.0, left: 0.0, bottom: 19.0, right: 0.0)
if self.scrollView.contentInset != scrollContentInsets {
self.scrollView.contentInset = scrollContentInsets

View File

@ -1449,7 +1449,7 @@ public final class MessageInputPanelComponent: Component {
containerSize: CGSize(width: availableSize.width - panelLeftInset - panelRightInset, height: availablePanelHeight)
)
let panelFrame = CGRect(origin: CGPoint(x: insets.left, y: -panelSize.height + 33.0), size: panelSize)
let panelFrame = CGRect(origin: CGPoint(x: insets.left, y: -panelSize.height + 14.0), size: CGSize(width: panelSize.width, height: panelSize.height + 19.0))
if let panelView = panel.view as? ContextResultPanelComponent.View {
if panelView.superview == nil {
self.insertSubview(panelView, at: 0)

View File

@ -295,12 +295,7 @@ final class StickersResultPanelComponent: Component {
let controller = PeekController(presentationData: presentationData, content: content, sourceView: {
return (sourceView, sourceRect)
})
// controller.visibilityUpdated = { [weak self] visible in
// self?.previewingStickersPromise.set(visible)
// }
component.presentInGlobalOverlay(controller)
// strongSelf.peekController = controller
// strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(controller, nil)
return controller
}
return nil

View File

@ -2160,8 +2160,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
} else if let sourceNode = sourceView.asyncdisplaykit_node as? HorizontalStickerGridItemNode {
strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .mediaPanel(itemNode: sourceNode), replyPanel: replyPanel), initiated: {})
} else if let sourceNode = sourceView.asyncdisplaykit_node as? StickerPaneSearchStickerItemNode {
strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .inputPanelSearch(itemNode: sourceNode), replyPanel: replyPanel), initiated: {})
} else if let sourceNode = sourceView.asyncdisplaykit_node as? ChatEmptyNodeStickerContentNode {
strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .emptyPanel(itemNode: sourceNode), replyPanel: nil), initiated: {})
} else if let sourceLayer = sourceLayer {

View File

@ -188,7 +188,6 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
case inputPanel(itemNode: ChatMediaInputStickerGridItemNode)
case mediaPanel(itemNode: HorizontalStickerGridItemNode)
case universal(sourceContainerView: UIView, sourceRect: CGRect, sourceLayer: CALayer)
case inputPanelSearch(itemNode: StickerPaneSearchStickerItemNode)
case emptyPanel(itemNode: ChatEmptyNodeStickerContentNode)
}
@ -442,9 +441,6 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
case let .universal(sourceContainerView, sourceRect, sourceLayer):
stickerSource = Sticker(imageNode: nil, animationNode: nil, placeholderNode: nil, imageLayer: sourceLayer, relativeSourceRect: sourceLayer.frame)
sourceAbsoluteRect = convertAnimatingSourceRect(sourceRect, fromView: sourceContainerView, toView: self.view)
case let .inputPanelSearch(sourceItemNode):
stickerSource = Sticker(imageNode: sourceItemNode.imageNode, animationNode: sourceItemNode.animationNode, placeholderNode: nil, imageLayer: nil, relativeSourceRect: sourceItemNode.imageNode.frame)
sourceAbsoluteRect = sourceItemNode.view.convert(sourceItemNode.imageNode.frame, to: self.view)
case let .emptyPanel(sourceItemNode):
stickerSource = Sticker(imageNode: sourceItemNode.stickerNode.imageNode, animationNode: sourceItemNode.stickerNode.animationNode, placeholderNode: nil, imageLayer: nil, relativeSourceRect: sourceItemNode.stickerNode.imageNode.frame)
sourceAbsoluteRect = sourceItemNode.stickerNode.view.convert(sourceItemNode.stickerNode.imageNode.frame, to: self.view)
@ -495,8 +491,6 @@ public final class ChatMessageTransitionNode: ASDisplayNode, ChatMessageTransiti
break
case let .mediaPanel(sourceItemNode):
sourceItemNode.isHidden = true
case let .inputPanelSearch(sourceItemNode):
sourceItemNode.isHidden = true
case let .emptyPanel(sourceItemNode):
sourceItemNode.isHidden = true
}

View File

@ -374,6 +374,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
case let .image(image, dimensions):
if let imageData = compressImageToJPEG(image, quality: 0.7) {
let entities = generateChatInputTextEntities(caption)
Logger.shared.log("MediaEditor", "Calling uploadStory for image, randomId \(randomId)")
self.context.engine.messages.uploadStory(media: .image(dimensions: dimensions, data: imageData, stickers: stickers), text: caption.string, entities: entities, pin: privacy.pin, privacy: privacy.privacy, isForwardingDisabled: privacy.isForwardingDisabled, period: privacy.timeout, randomId: randomId)
Queue.mainQueue().justDispatch {
commit({})
@ -404,7 +405,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
return nil
}
}
Logger.shared.log("MediaEditor", "Calling uploadStory for video, randomId \(randomId)")
let entities = generateChatInputTextEntities(caption)
self.context.engine.messages.uploadStory(media: .video(dimensions: dimensions, duration: duration, resource: resource, firstFrameFile: firstFrameFile, stickers: stickers), text: caption.string, entities: entities, pin: privacy.pin, privacy: privacy.privacy, isForwardingDisabled: privacy.isForwardingDisabled, period: privacy.timeout, randomId: randomId)
Queue.mainQueue().justDispatch {