Swiftgram/TelegramUI/LegacyInstantVideoController.swift
Ilya Laktyushin 0d41a372c9 Fixed media thumbnail not appearing immediately after upload started
Fixed instant video automatic download
Fixed Passport document recognition for uploaded scans
2018-10-17 16:03:43 +03:00

170 lines
8.8 KiB
Swift

import Foundation
import Display
import TelegramCore
import Postbox
import SwiftSignalKit
import LegacyComponents
final class InstantVideoControllerRecordingStatus {
let micLevel: Signal<Float, NoError>
init(micLevel: Signal<Float, NoError>) {
self.micLevel = micLevel
}
}
final class InstantVideoController: LegacyController {
private var captureController: TGVideoMessageCaptureController?
var onDismiss: (() -> Void)?
var onStop: (() -> Void)?
private let micLevelValue = ValuePromise<Float>(0.0)
let audioStatus: InstantVideoControllerRecordingStatus
private var dismissedVideo = false
override init(presentation: LegacyControllerPresentation, theme: PresentationTheme?, strings: PresentationStrings? = nil, initialLayout: ContainerViewLayout? = nil) {
self.audioStatus = InstantVideoControllerRecordingStatus(micLevel: self.micLevelValue.get())
super.init(presentation: presentation, theme: theme, initialLayout: initialLayout)
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func bindCaptureController(_ captureController: TGVideoMessageCaptureController?) {
self.captureController = captureController
if let captureController = captureController {
captureController.micLevel = { [weak self] (level: CGFloat) -> Void in
self?.micLevelValue.set(Float(level))
}
captureController.onDismiss = { [weak self] _ in
self?.onDismiss?()
}
captureController.onStop = { [weak self] in
self?.onStop?()
}
}
}
func dismissVideo() {
if let captureController = self.captureController, !self.dismissedVideo {
self.dismissedVideo = true
captureController.dismiss()
}
}
func completeVideo() {
if let captureController = self.captureController, !self.dismissedVideo {
self.dismissedVideo = true
captureController.complete()
}
}
func stopVideo() -> Bool {
if let captureController = self.captureController {
return captureController.stop()
}
return false
}
func lockVideo() {
if let captureController = self.captureController {
return captureController.setLocked()
}
}
func updateRecordButtonInteraction(_ value: CGFloat) {
if let captureController = self.captureController {
captureController.buttonInteractionUpdate(CGPoint(x: value, y: 0.0))
}
}
}
func legacyInstantVideoController(theme: PresentationTheme, panelFrame: CGRect, account: Account, peerId: PeerId, send: @escaping (EnqueueMessage) -> Void) -> InstantVideoController {
let legacyController = InstantVideoController(presentation: .custom, theme: theme)
legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .all)
legacyController.statusBar.statusBarStyle = .Hide
let baseController = TGViewController(context: legacyController.context)!
legacyController.bind(controller: baseController)
legacyController.presentationCompleted = { [weak legacyController, weak baseController] in
if let legacyController = legacyController, let baseController = baseController {
legacyController.view.disablesInteractiveTransitionGestureRecognizer = true
let inputPanelTheme = theme.chat.inputPanel
var uploadInterface: LegacyLiveUploadInterface?
if peerId.namespace != Namespaces.Peer.SecretChat {
uploadInterface = LegacyLiveUploadInterface(account: account)
}
let controller = TGVideoMessageCaptureController(context: legacyController.context, assets: TGVideoMessageCaptureControllerAssets(send: PresentationResourcesChat.chatInputPanelSendButtonImage(theme)!, slideToCancel: PresentationResourcesChat.chatInputPanelMediaRecordingCancelArrowImage(theme)!, actionDelete: generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionThrash"), color: theme.chat.inputPanel.panelControlAccentColor))!, transitionInView: {
return nil
}, parentController: baseController, controlsFrame: panelFrame, isAlreadyLocked: {
return false
}, liveUploadInterface: uploadInterface, pallete: TGModernConversationInputMicPallete(dark: theme.overallDarkAppearance, buttonColor: inputPanelTheme.actionControlFillColor, iconColor: inputPanelTheme.actionControlForegroundColor, backgroundColor: inputPanelTheme.panelBackgroundColor, borderColor: inputPanelTheme.panelStrokeColor, lock: inputPanelTheme.panelControlAccentColor, textColor: inputPanelTheme.primaryTextColor, secondaryTextColor: inputPanelTheme.secondaryTextColor, recording: inputPanelTheme.mediaRecordingDotColor))!
controller.finishedWithVideo = { videoUrl, previewImage, _, duration, dimensions, liveUploadData, adjustments in
guard let videoUrl = videoUrl else {
return
}
var finalDimensions: CGSize = dimensions
var finalDuration: Double = duration
var previewRepresentations: [TelegramMediaImageRepresentation] = []
if let previewImage = previewImage {
let resource = LocalFileMediaResource(fileId: arc4random64())
let thumbnailSize = finalDimensions.aspectFitted(CGSize(width: 90.0, height: 90.0))
let thumbnailImage = TGScaleImageToPixelSize(previewImage, thumbnailSize)!
if let thumbnailData = UIImageJPEGRepresentation(thumbnailImage, 0.4) {
account.postbox.mediaBox.storeResourceData(resource.id, data: thumbnailData)
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: thumbnailSize, resource: resource))
}
}
finalDimensions = TGMediaVideoConverter.dimensions(for: finalDimensions, adjustments: adjustments, preset: TGMediaVideoConversionPresetVideoMessage)
var resourceAdjustments: VideoMediaResourceAdjustments?
if let adjustments = adjustments {
if adjustments.trimApplied() {
finalDuration = adjustments.trimEndValue - adjustments.trimStartValue
}
let adjustmentsData = MemoryBuffer(data: NSKeyedArchiver.archivedData(withRootObject: adjustments.dictionary()))
let digest = MemoryBuffer(data: adjustmentsData.md5Digest())
resourceAdjustments = VideoMediaResourceAdjustments(data: adjustmentsData, digest: digest)
}
if finalDuration.isZero || finalDuration.isNaN {
return
}
let resource: TelegramMediaResource
if let liveUploadData = liveUploadData as? LegacyLiveUploadInterfaceResult, resourceAdjustments == nil, let data = try? Data(contentsOf: videoUrl) {
resource = LocalFileMediaResource(fileId: liveUploadData.id)
account.postbox.mediaBox.storeResourceData(resource.id, data: data)
} else {
resource = LocalFileVideoMediaResource(randomId: arc4random64(), path: videoUrl.path, adjustments: resourceAdjustments)
}
if let previewImage = previewImage {
if let data = compressImageToJPEG(previewImage, quality: 0.7) {
account.postbox.mediaBox.storeCachedResourceRepresentation(resource, representation: CachedVideoFirstFrameRepresentation(), data: data)
}
}
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: arc4random64()), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, mimeType: "video/mp4", size: nil, attributes: [.FileName(fileName: "video.mp4"), .Video(duration: Int(finalDuration), size: finalDimensions, flags: [.instantRoundVideo])])
let attributes: [MessageAttribute] = []
send(.message(text: "", attributes: attributes, mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil))
}
controller.didDismiss = { [weak legacyController] in
if let legacyController = legacyController {
legacyController.dismiss()
}
}
legacyController.bindCaptureController(controller)
}
}
return legacyController
}