mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 17:30:12 +00:00
Camera and editor improvements
This commit is contained in:
parent
65ed79b44d
commit
97e871fa22
@ -56,6 +56,7 @@ swift_library(
|
|||||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||||
"//submodules/Display:Display",
|
"//submodules/Display:Display",
|
||||||
|
"//submodules/ImageBlur:ImageBlur",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import UIKit
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import AVFoundation
|
import AVFoundation
|
||||||
|
import CoreImage
|
||||||
|
|
||||||
private final class CameraContext {
|
private final class CameraContext {
|
||||||
private let queue: Queue
|
private let queue: Queue
|
||||||
@ -38,6 +40,19 @@ private final class CameraContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var lastSnapshotTimestamp: Double = CACurrentMediaTime()
|
||||||
|
private func savePreviewSnapshot(pixelBuffer: CVPixelBuffer) {
|
||||||
|
Queue.concurrentDefaultQueue().async {
|
||||||
|
let ciContext = CIContext()
|
||||||
|
var ciImage = CIImage(cvImageBuffer: pixelBuffer)
|
||||||
|
ciImage = ciImage.transformed(by: CGAffineTransform(scaleX: 0.33, y: 0.33))
|
||||||
|
if let cgImage = ciContext.createCGImage(ciImage, from: ciImage.extent) {
|
||||||
|
let uiImage = UIImage(cgImage: cgImage, scale: 1.0, orientation: .right)
|
||||||
|
CameraSimplePreviewView.saveLastState(uiImage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var videoOrientation: AVCaptureVideoOrientation?
|
private var videoOrientation: AVCaptureVideoOrientation?
|
||||||
init(queue: Queue, session: AVCaptureSession, configuration: Camera.Configuration, metrics: Camera.Metrics, previewView: CameraSimplePreviewView?) {
|
init(queue: Queue, session: AVCaptureSession, configuration: Camera.Configuration, metrics: Camera.Metrics, previewView: CameraSimplePreviewView?) {
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
@ -59,24 +74,30 @@ private final class CameraContext {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let previewView = self.previewView, !self.changingPosition {
|
|
||||||
let videoOrientation = connection.videoOrientation
|
let timestamp = CACurrentMediaTime()
|
||||||
if #available(iOS 13.0, *) {
|
if timestamp > self.lastSnapshotTimestamp + 5.0 {
|
||||||
previewView.mirroring = connection.inputPorts.first?.sourceDevicePosition == .front
|
self.savePreviewSnapshot(pixelBuffer: pixelBuffer)
|
||||||
}
|
self.lastSnapshotTimestamp = timestamp
|
||||||
if let rotation = CameraPreviewView.Rotation(with: .portrait, videoOrientation: videoOrientation, cameraPosition: self.device.position) {
|
|
||||||
previewView.rotation = rotation
|
|
||||||
}
|
|
||||||
if #available(iOS 13.0, *), connection.inputPorts.first?.sourceDevicePosition == .front {
|
|
||||||
let width = CVPixelBufferGetWidth(pixelBuffer)
|
|
||||||
let height = CVPixelBufferGetHeight(pixelBuffer)
|
|
||||||
previewView.captureDeviceResolution = CGSize(width: width, height: height)
|
|
||||||
}
|
|
||||||
previewView.pixelBuffer = pixelBuffer
|
|
||||||
Queue.mainQueue().async {
|
|
||||||
self.videoOrientation = videoOrientation
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// if let previewView = self.previewView, !self.changingPosition {
|
||||||
|
// let videoOrientation = connection.videoOrientation
|
||||||
|
// if #available(iOS 13.0, *) {
|
||||||
|
// previewView.mirroring = connection.inputPorts.first?.sourceDevicePosition == .front
|
||||||
|
// }
|
||||||
|
// if let rotation = CameraPreviewView.Rotation(with: .portrait, videoOrientation: videoOrientation, cameraPosition: self.device.position) {
|
||||||
|
// previewView.rotation = rotation
|
||||||
|
// }
|
||||||
|
// if #available(iOS 13.0, *), connection.inputPorts.first?.sourceDevicePosition == .front {
|
||||||
|
// let width = CVPixelBufferGetWidth(pixelBuffer)
|
||||||
|
// let height = CVPixelBufferGetHeight(pixelBuffer)
|
||||||
|
// previewView.captureDeviceResolution = CGSize(width: width, height: height)
|
||||||
|
// }
|
||||||
|
// previewView.pixelBuffer = pixelBuffer
|
||||||
|
// Queue.mainQueue().async {
|
||||||
|
// self.videoOrientation = videoOrientation
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
self.output.processFaceLandmarks = { [weak self] observations in
|
self.output.processFaceLandmarks = { [weak self] observations in
|
||||||
|
|||||||
@ -225,6 +225,10 @@ extension CameraOutput: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let videoPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) {
|
||||||
|
self.processSampleBuffer?(videoPixelBuffer, connection)
|
||||||
|
}
|
||||||
|
|
||||||
// let finalSampleBuffer: CMSampleBuffer = sampleBuffer
|
// let finalSampleBuffer: CMSampleBuffer = sampleBuffer
|
||||||
// if let videoPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer), let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) {
|
// if let videoPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer), let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) {
|
||||||
// var finalVideoPixelBuffer = videoPixelBuffer
|
// var finalVideoPixelBuffer = videoPixelBuffer
|
||||||
|
|||||||
@ -7,8 +7,65 @@ import Metal
|
|||||||
import MetalKit
|
import MetalKit
|
||||||
import CoreMedia
|
import CoreMedia
|
||||||
import Vision
|
import Vision
|
||||||
|
import ImageBlur
|
||||||
|
|
||||||
public class CameraSimplePreviewView: UIView {
|
public class CameraSimplePreviewView: UIView {
|
||||||
|
static func lastStateImage() -> UIImage {
|
||||||
|
let imagePath = NSTemporaryDirectory() + "cameraImage.jpg"
|
||||||
|
if let data = try? Data(contentsOf: URL(fileURLWithPath: imagePath)), let image = UIImage(data: data) {
|
||||||
|
return image
|
||||||
|
} else {
|
||||||
|
return UIImage(bundleImageName: "Camera/Placeholder")!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func saveLastState(_ image: UIImage) {
|
||||||
|
let imagePath = NSTemporaryDirectory() + "cameraImage.jpg"
|
||||||
|
if let blurredImage = blurredImage(image, radius: 60.0), let data = blurredImage.jpegData(compressionQuality: 0.85) {
|
||||||
|
try? data.write(to: URL(fileURLWithPath: imagePath))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var previewingDisposable: Disposable?
|
||||||
|
private let placeholderView = UIImageView()
|
||||||
|
public override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
self.placeholderView.image = CameraSimplePreviewView.lastStateImage()
|
||||||
|
self.addSubview(self.placeholderView)
|
||||||
|
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
self.previewingDisposable = (self.isPreviewing
|
||||||
|
|> filter { $0 }
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||||
|
UIView.animate(withDuration: 0.3) {
|
||||||
|
self?.placeholderView.alpha = 0.0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Queue.mainQueue().after(0.5) {
|
||||||
|
UIView.animate(withDuration: 0.3) {
|
||||||
|
self.placeholderView.alpha = 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.previewingDisposable?.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
self.placeholderView.frame = self.bounds
|
||||||
|
}
|
||||||
|
|
||||||
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
|
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
|
||||||
guard let layer = layer as? AVCaptureVideoPreviewLayer else {
|
guard let layer = layer as? AVCaptureVideoPreviewLayer else {
|
||||||
fatalError()
|
fatalError()
|
||||||
|
|||||||
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushSelectedPen.imageset/Contents.json
vendored
Normal file
12
submodules/LegacyComponents/LegacyImages.xcassets/Editor/BrushSelectedPen.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "ic_editor_brush1.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
@ -254,10 +254,6 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
let controller = environment.controller
|
let controller = environment.controller
|
||||||
let availableSize = context.availableSize
|
let availableSize = context.availableSize
|
||||||
|
|
||||||
let accountContext = component.context
|
|
||||||
let push = component.push
|
|
||||||
let completion = component.completion
|
|
||||||
|
|
||||||
let topControlInset: CGFloat = 20.0
|
let topControlInset: CGFloat = 20.0
|
||||||
|
|
||||||
component.changeMode.connect({ [weak state] mode in
|
component.changeMode.connect({ [weak state] mode in
|
||||||
@ -394,15 +390,10 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
state.camera.togglePosition()
|
state.camera.togglePosition()
|
||||||
},
|
},
|
||||||
galleryTapped: {
|
galleryTapped: {
|
||||||
var dismissGalleryControllerImpl: (() -> Void)?
|
guard let controller = environment.controller() as? CameraScreen else {
|
||||||
let controller = accountContext.sharedContext.makeMediaPickerScreen(context: accountContext, completion: { asset in
|
return
|
||||||
dismissGalleryControllerImpl?()
|
|
||||||
completion.invoke(.single(.asset(asset)))
|
|
||||||
})
|
|
||||||
dismissGalleryControllerImpl = { [weak controller] in
|
|
||||||
controller?.dismiss(animated: true)
|
|
||||||
}
|
}
|
||||||
push(controller)
|
controller.presentGallery()
|
||||||
},
|
},
|
||||||
swipeHintUpdated: { hint in
|
swipeHintUpdated: { hint in
|
||||||
state.updateSwipeHint(hint)
|
state.updateSwipeHint(hint)
|
||||||
@ -824,6 +815,10 @@ public class CameraScreen: ViewController {
|
|||||||
self.containerLayoutUpdated(layout: layout, transition: .easeInOut(duration: 0.2))
|
self.containerLayoutUpdated(layout: layout, transition: .easeInOut(duration: 0.2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if translation.y < -10.0 {
|
||||||
|
self.controller?.presentGallery()
|
||||||
|
gestureRecognizer.isEnabled = false
|
||||||
|
gestureRecognizer.isEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .ended:
|
case .ended:
|
||||||
@ -872,12 +867,13 @@ public class CameraScreen: ViewController {
|
|||||||
|
|
||||||
if let transitionIn = self.controller?.transitionIn, let sourceView = transitionIn.sourceView {
|
if let transitionIn = self.controller?.transitionIn, let sourceView = transitionIn.sourceView {
|
||||||
let sourceLocalFrame = sourceView.convert(transitionIn.sourceRect, to: self.view)
|
let sourceLocalFrame = sourceView.convert(transitionIn.sourceRect, to: self.view)
|
||||||
let innerSourceLocalFrame = CGRect(origin: CGPoint(x: sourceLocalFrame.minX - self.previewContainerView.frame.minX, y: sourceLocalFrame.minY - self.previewContainerView.frame.minY), size: sourceLocalFrame.size)
|
|
||||||
|
|
||||||
|
let sourceScale = sourceLocalFrame.width / self.previewContainerView.frame.width
|
||||||
self.previewContainerView.layer.animatePosition(from: sourceLocalFrame.center, to: self.previewContainerView.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
self.previewContainerView.layer.animatePosition(from: sourceLocalFrame.center, to: self.previewContainerView.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
self.previewContainerView.layer.animateBounds(from: CGRect(origin: CGPoint(x: innerSourceLocalFrame.minX, y: innerSourceLocalFrame.minY), size: sourceLocalFrame.size), to: self.previewContainerView.bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
self.previewContainerView.layer.animateScale(from: sourceScale, to: 1.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
|
self.previewContainerView.layer.animateBounds(from: CGRect(origin: CGPoint(x: 0.0, y: (self.previewContainerView.bounds.height - self.previewContainerView.bounds.width) / 2.0), size: CGSize(width: self.previewContainerView.bounds.width, height: self.previewContainerView.bounds.width)), to: self.previewContainerView.bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
self.previewContainerView.layer.animate(
|
self.previewContainerView.layer.animate(
|
||||||
from: transitionIn.sourceCornerRadius as NSNumber,
|
from: self.previewContainerView.bounds.width / 2.0 as NSNumber,
|
||||||
to: self.previewContainerView.layer.cornerRadius as NSNumber,
|
to: self.previewContainerView.layer.cornerRadius as NSNumber,
|
||||||
keyPath: "cornerRadius",
|
keyPath: "cornerRadius",
|
||||||
timingFunction: kCAMediaTimingFunctionSpring,
|
timingFunction: kCAMediaTimingFunctionSpring,
|
||||||
@ -886,7 +882,7 @@ public class CameraScreen: ViewController {
|
|||||||
|
|
||||||
if let view = self.componentHost.view {
|
if let view = self.componentHost.view {
|
||||||
view.layer.animatePosition(from: sourceLocalFrame.center, to: view.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
view.layer.animatePosition(from: sourceLocalFrame.center, to: view.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
view.layer.animateBounds(from: CGRect(origin: CGPoint(x: innerSourceLocalFrame.minX, y: innerSourceLocalFrame.minY), size: sourceLocalFrame.size), to: view.bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
view.layer.animateScale(from: 0.1, to: 1.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -902,16 +898,17 @@ public class CameraScreen: ViewController {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if let transitionOut = self.controller?.transitionOut(false), let destinationView = transitionOut.destinationView {
|
if let transitionOut = self.controller?.transitionOut(false), let destinationView = transitionOut.destinationView {
|
||||||
let sourceLocalFrame = destinationView.convert(transitionOut.destinationRect, to: self.view)
|
let destinationLocalFrame = destinationView.convert(transitionOut.destinationRect, to: self.view)
|
||||||
let innerSourceLocalFrame = CGRect(origin: CGPoint(x: sourceLocalFrame.minX - self.previewContainerView.frame.minX, y: sourceLocalFrame.minY - self.previewContainerView.frame.minY), size: sourceLocalFrame.size)
|
|
||||||
|
|
||||||
self.previewContainerView.layer.animatePosition(from: self.previewContainerView.center, to: sourceLocalFrame.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
let targetScale = destinationLocalFrame.width / self.previewContainerView.frame.width
|
||||||
|
self.previewContainerView.layer.animatePosition(from: self.previewContainerView.center, to: destinationLocalFrame.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
||||||
completion()
|
completion()
|
||||||
})
|
})
|
||||||
self.previewContainerView.layer.animateBounds(from: self.previewContainerView.bounds, to: CGRect(origin: CGPoint(x: innerSourceLocalFrame.minX, y: innerSourceLocalFrame.minY), size: sourceLocalFrame.size), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
self.previewContainerView.layer.animateScale(from: 1.0, to: targetScale, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
|
self.previewContainerView.layer.animateBounds(from: self.previewContainerView.bounds, to: CGRect(origin: CGPoint(x: 0.0, y: (self.previewContainerView.bounds.height - self.previewContainerView.bounds.width) / 2.0), size: CGSize(width: self.previewContainerView.bounds.width, height: self.previewContainerView.bounds.width)), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
self.previewContainerView.layer.animate(
|
self.previewContainerView.layer.animate(
|
||||||
from: self.previewContainerView.layer.cornerRadius as NSNumber,
|
from: self.previewContainerView.layer.cornerRadius as NSNumber,
|
||||||
to: transitionOut.destinationCornerRadius as NSNumber,
|
to: self.previewContainerView.bounds.width / 2.0 as NSNumber,
|
||||||
keyPath: "cornerRadius",
|
keyPath: "cornerRadius",
|
||||||
timingFunction: kCAMediaTimingFunctionSpring,
|
timingFunction: kCAMediaTimingFunctionSpring,
|
||||||
duration: 0.3,
|
duration: 0.3,
|
||||||
@ -919,8 +916,8 @@ public class CameraScreen: ViewController {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if let view = self.componentHost.view {
|
if let view = self.componentHost.view {
|
||||||
view.layer.animatePosition(from: view.center, to: sourceLocalFrame.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
view.layer.animatePosition(from: view.center, to: destinationLocalFrame.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
view.layer.animateBounds(from: view.bounds, to: CGRect(origin: CGPoint(x: innerSourceLocalFrame.minX, y: innerSourceLocalFrame.minY), size: sourceLocalFrame.size), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
view.layer.animateScale(from: 1.0, to: targetScale, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1075,10 +1072,6 @@ public class CameraScreen: ViewController {
|
|||||||
let componentFrame = CGRect(origin: .zero, size: componentSize)
|
let componentFrame = CGRect(origin: .zero, size: componentSize)
|
||||||
transition.setFrame(view: componentView, frame: componentFrame)
|
transition.setFrame(view: componentView, frame: componentFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isFirstTime {
|
|
||||||
self.animateIn()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transition.setFrame(view: self.backgroundDimView, frame: CGRect(origin: .zero, size: layout.size))
|
transition.setFrame(view: self.backgroundDimView, frame: CGRect(origin: .zero, size: layout.size))
|
||||||
@ -1090,6 +1083,10 @@ public class CameraScreen: ViewController {
|
|||||||
transition.setFrame(view: self.effectivePreviewView, frame: CGRect(origin: .zero, size: previewFrame.size))
|
transition.setFrame(view: self.effectivePreviewView, frame: CGRect(origin: .zero, size: previewFrame.size))
|
||||||
transition.setFrame(view: self.previewBlurView, frame: CGRect(origin: .zero, size: previewFrame.size))
|
transition.setFrame(view: self.previewBlurView, frame: CGRect(origin: .zero, size: previewFrame.size))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isFirstTime {
|
||||||
|
self.animateIn()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1141,6 +1138,20 @@ public class CameraScreen: ViewController {
|
|||||||
self.node.animateInFromEditor()
|
self.node.animateInFromEditor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func presentGallery() {
|
||||||
|
var dismissGalleryControllerImpl: (() -> Void)?
|
||||||
|
let controller = self.context.sharedContext.makeMediaPickerScreen(context: self.context, completion: { [weak self] asset in
|
||||||
|
dismissGalleryControllerImpl?()
|
||||||
|
if let self {
|
||||||
|
self.completion(.single(.asset(asset)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dismissGalleryControllerImpl = { [weak controller] in
|
||||||
|
controller?.dismiss(animated: true)
|
||||||
|
}
|
||||||
|
push(controller)
|
||||||
|
}
|
||||||
|
|
||||||
private var isDismissed = false
|
private var isDismissed = false
|
||||||
fileprivate func requestDismiss(animated: Bool) {
|
fileprivate func requestDismiss(animated: Bool) {
|
||||||
guard !self.isDismissed else {
|
guard !self.isDismissed else {
|
||||||
|
|||||||
@ -364,6 +364,8 @@ final class CaptureControlsComponent: Component {
|
|||||||
|
|
||||||
private let lockImage = UIImage(bundleImageName: "Camera/LockIcon")
|
private let lockImage = UIImage(bundleImageName: "Camera/LockIcon")
|
||||||
|
|
||||||
|
private let hapticFeedback = HapticFeedback()
|
||||||
|
|
||||||
public func matches(tag: Any) -> Bool {
|
public func matches(tag: Any) -> Bool {
|
||||||
if let component = self.component, let componentTag = component.tag {
|
if let component = self.component, let componentTag = component.tag {
|
||||||
let tag = tag as AnyObject
|
let tag = tag as AnyObject
|
||||||
@ -392,7 +394,6 @@ final class CaptureControlsComponent: Component {
|
|||||||
let location = gestureRecognizer.location(in: self)
|
let location = gestureRecognizer.location(in: self)
|
||||||
switch gestureRecognizer.state {
|
switch gestureRecognizer.state {
|
||||||
case .began:
|
case .began:
|
||||||
self.hapticFeedback.impact(.click05)
|
|
||||||
self.component?.shutterPressed()
|
self.component?.shutterPressed()
|
||||||
self.component?.swipeHintUpdated(.zoom)
|
self.component?.swipeHintUpdated(.zoom)
|
||||||
self.shutterUpdateOffset.invoke((0.0, .immediate))
|
self.shutterUpdateOffset.invoke((0.0, .immediate))
|
||||||
@ -415,8 +416,6 @@ final class CaptureControlsComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let hapticFeedback = HapticFeedback()
|
|
||||||
|
|
||||||
private var didFlip = false
|
private var didFlip = false
|
||||||
private var wasBanding: Bool?
|
private var wasBanding: Bool?
|
||||||
private var panBlobState: ShutterBlobView.BlobState?
|
private var panBlobState: ShutterBlobView.BlobState?
|
||||||
@ -667,6 +666,7 @@ final class CaptureControlsComponent: Component {
|
|||||||
),
|
),
|
||||||
automaticHighlight: false,
|
automaticHighlight: false,
|
||||||
action: { [weak self] in
|
action: { [weak self] in
|
||||||
|
self?.hapticFeedback.impact(.light)
|
||||||
self?.shutterUpdateOffset.invoke((0.0, .immediate))
|
self?.shutterUpdateOffset.invoke((0.0, .immediate))
|
||||||
component.shutterTapped()
|
component.shutterTapped()
|
||||||
},
|
},
|
||||||
|
|||||||
@ -988,7 +988,7 @@ public final class MediaEditorScreen: ViewController {
|
|||||||
completion()
|
completion()
|
||||||
})
|
})
|
||||||
self.previewContainerView.layer.animateScale(from: 1.0, to: targetScale, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
self.previewContainerView.layer.animateScale(from: 1.0, to: targetScale, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
self.previewContainerView.layer.animateBounds(from: self.previewContainerView.bounds, to: CGRect(origin: CGPoint(x: 0.0, y: (self.previewContainerView.frame.height - self.previewContainerView.frame.width) / 2.0), size: CGSize(width: self.previewContainerView.bounds.width, height: self.previewContainerView.bounds.width)), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
self.previewContainerView.layer.animateBounds(from: self.previewContainerView.bounds, to: CGRect(origin: CGPoint(x: 0.0, y: (self.previewContainerView.bounds.height - self.previewContainerView.bounds.width) / 2.0), size: CGSize(width: self.previewContainerView.bounds.width, height: self.previewContainerView.bounds.width)), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
self.previewContainerView.layer.animate(
|
self.previewContainerView.layer.animate(
|
||||||
from: self.previewContainerView.layer.cornerRadius as NSNumber,
|
from: self.previewContainerView.layer.cornerRadius as NSNumber,
|
||||||
to: self.previewContainerView.bounds.width / 2.0 as NSNumber,
|
to: self.previewContainerView.bounds.width / 2.0 as NSNumber,
|
||||||
@ -1002,7 +1002,7 @@ public final class MediaEditorScreen: ViewController {
|
|||||||
componentView.clipsToBounds = true
|
componentView.clipsToBounds = true
|
||||||
componentView.layer.animatePosition(from: componentView.center, to: destinationLocalFrame.center, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
componentView.layer.animatePosition(from: componentView.center, to: destinationLocalFrame.center, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
componentView.layer.animateScale(from: 1.0, to: targetScale, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
componentView.layer.animateScale(from: 1.0, to: targetScale, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
componentView.layer.animateBounds(from: componentView.bounds, to: CGRect(origin: CGPoint(x: 0.0, y: (componentView.frame.height - componentView.frame.width) / 2.0), size: CGSize(width: componentView.bounds.width, height: componentView.bounds.width)), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
componentView.layer.animateBounds(from: componentView.bounds, to: CGRect(origin: CGPoint(x: 0.0, y: (componentView.bounds.height - componentView.bounds.width) / 2.0), size: CGSize(width: componentView.bounds.width, height: componentView.bounds.width)), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
componentView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
componentView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
componentView.layer.animate(
|
componentView.layer.animate(
|
||||||
from: componentView.layer.cornerRadius as NSNumber,
|
from: componentView.layer.cornerRadius as NSNumber,
|
||||||
|
|||||||
BIN
submodules/TelegramUI/Images.xcassets/Camera/Placeholder.imageset/CameraPlaceholder.jpg
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Camera/Placeholder.imageset/CameraPlaceholder.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
12
submodules/TelegramUI/Images.xcassets/Camera/Placeholder.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Camera/Placeholder.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "CameraPlaceholder.jpg",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user