mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Front camera torch for video recording
This commit is contained in:
parent
fba8017ddc
commit
0a2532b802
@ -361,10 +361,15 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateCameraMode(_ mode: CameraMode) {
|
func updateCameraMode(_ mode: CameraMode) {
|
||||||
guard let controller = self.getController(), let _ = controller.camera else {
|
guard let controller = self.getController(), let camera = controller.camera else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.updateCameraState({ $0.updatedMode(mode) }, transition: .spring(duration: 0.3))
|
controller.updateCameraState({ $0.updatedMode(mode) }, transition: .spring(duration: 0.3))
|
||||||
|
|
||||||
|
if case .video = mode, case .auto = controller.cameraState.flashMode {
|
||||||
|
camera.setFlashMode(.on)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toggleFlashMode() {
|
func toggleFlashMode() {
|
||||||
@ -375,7 +380,11 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
case .off:
|
case .off:
|
||||||
camera.setFlashMode(.on)
|
camera.setFlashMode(.on)
|
||||||
case .on:
|
case .on:
|
||||||
camera.setFlashMode(.auto)
|
if controller.cameraState.mode == .video {
|
||||||
|
camera.setFlashMode(.off)
|
||||||
|
} else {
|
||||||
|
camera.setFlashMode(.auto)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
camera.setFlashMode(.off)
|
camera.setFlashMode(.off)
|
||||||
}
|
}
|
||||||
@ -464,6 +473,39 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var initialBrightness: CGFloat?
|
||||||
|
private var brightnessArguments: (Double, Double, CGFloat, CGFloat)?
|
||||||
|
private var brightnessAnimator: ConstantDisplayLinkAnimator?
|
||||||
|
|
||||||
|
private func updateBrightness() {
|
||||||
|
if self.brightnessAnimator == nil {
|
||||||
|
self.brightnessAnimator = ConstantDisplayLinkAnimator(update: { [weak self] in
|
||||||
|
self?.updateBrightness()
|
||||||
|
})
|
||||||
|
self.brightnessAnimator?.isPaused = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (startTime, duration, initial, target) = self.brightnessArguments {
|
||||||
|
self.brightnessAnimator?.isPaused = false
|
||||||
|
|
||||||
|
let t = CGFloat(max(0.0, min(1.0, (CACurrentMediaTime() - startTime) / duration)))
|
||||||
|
let value = initial + (target - initial) * t
|
||||||
|
|
||||||
|
UIScreen.main.brightness = value
|
||||||
|
|
||||||
|
if t >= 1.0 {
|
||||||
|
self.brightnessArguments = nil
|
||||||
|
self.brightnessAnimator?.isPaused = true
|
||||||
|
self.brightnessAnimator?.invalidate()
|
||||||
|
self.brightnessAnimator = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.brightnessAnimator?.isPaused = true
|
||||||
|
self.brightnessAnimator?.invalidate()
|
||||||
|
self.brightnessAnimator = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func startVideoRecording(pressing: Bool) {
|
func startVideoRecording(pressing: Bool) {
|
||||||
guard let controller = self.getController(), let camera = controller.camera else {
|
guard let controller = self.getController(), let camera = controller.camera else {
|
||||||
return
|
return
|
||||||
@ -474,17 +516,30 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
|
|
||||||
controller.node.dismissAllTooltips()
|
controller.node.dismissAllTooltips()
|
||||||
|
|
||||||
self.resultDisposable.set((camera.startRecording()
|
let startRecording = {
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] duration in
|
self.resultDisposable.set((camera.startRecording()
|
||||||
if let self, let controller = self.getController() {
|
|> deliverOnMainQueue).start(next: { [weak self] duration in
|
||||||
controller.updateCameraState({ $0.updatedDuration(duration) }, transition: .easeInOut(duration: 0.1))
|
if let self, let controller = self.getController() {
|
||||||
if duration > 59.0 {
|
controller.updateCameraState({ $0.updatedDuration(duration) }, transition: .easeInOut(duration: 0.1))
|
||||||
self.stopVideoRecording()
|
if duration > 59.0 {
|
||||||
|
self.stopVideoRecording()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}))
|
||||||
}))
|
}
|
||||||
|
|
||||||
controller.updateCameraState({ $0.updatedRecording(pressing ? .holding : .handsFree).updatedDuration(0.0) }, transition: .spring(duration: 0.4))
|
controller.updateCameraState({ $0.updatedRecording(pressing ? .holding : .handsFree).updatedDuration(0.0) }, transition: .spring(duration: 0.4))
|
||||||
|
|
||||||
|
if case .front = controller.cameraState.position {
|
||||||
|
self.initialBrightness = UIScreen.main.brightness
|
||||||
|
UIScreen.main.brightness = 1.0
|
||||||
|
|
||||||
|
Queue.mainQueue().after(0.2, {
|
||||||
|
startRecording()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
startRecording()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopVideoRecording() {
|
func stopVideoRecording() {
|
||||||
@ -505,6 +560,12 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
})
|
})
|
||||||
|
|
||||||
controller.updateCameraState({ $0.updatedRecording(.none).updatedDuration(0.0) }, transition: .spring(duration: 0.4))
|
controller.updateCameraState({ $0.updatedRecording(.none).updatedDuration(0.0) }, transition: .spring(duration: 0.4))
|
||||||
|
|
||||||
|
if case .front = controller.cameraState.position, let initialBrightness = self.initialBrightness {
|
||||||
|
self.initialBrightness = nil
|
||||||
|
self.brightnessArguments = (CACurrentMediaTime(), 0.2, UIScreen.main.brightness, initialBrightness)
|
||||||
|
self.updateBrightness()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func lockVideoRecording() {
|
func lockVideoRecording() {
|
||||||
@ -528,6 +589,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
|
|
||||||
static var body: Body {
|
static var body: Body {
|
||||||
let placeholder = Child(PlaceholderComponent.self)
|
let placeholder = Child(PlaceholderComponent.self)
|
||||||
|
let frontFlash = Child(Rectangle.self)
|
||||||
let cancelButton = Child(CameraButton.self)
|
let cancelButton = Child(CameraButton.self)
|
||||||
let captureControls = Child(CaptureControlsComponent.self)
|
let captureControls = Child(CaptureControlsComponent.self)
|
||||||
let zoomControl = Child(ZoomComponent.self)
|
let zoomControl = Child(ZoomComponent.self)
|
||||||
@ -627,6 +689,21 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
// )
|
// )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if case .none = component.cameraState.recording {
|
||||||
|
|
||||||
|
} else if case .front = component.cameraState.position {
|
||||||
|
let frontFlash = frontFlash.update(
|
||||||
|
component: Rectangle(color: UIColor(white: 1.0, alpha: 0.6)),
|
||||||
|
availableSize: CGSize(width: availableSize.width, height: previewHeight),
|
||||||
|
transition: .easeInOut(duration: 0.2)
|
||||||
|
)
|
||||||
|
context.add(frontFlash
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: environment.safeInsets.top + previewHeight / 2.0))
|
||||||
|
.appear(.default(alpha: true))
|
||||||
|
.disappear(.default(alpha: true))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
let shutterState: ShutterButtonState
|
let shutterState: ShutterButtonState
|
||||||
if state.isTransitioning {
|
if state.isTransitioning {
|
||||||
shutterState = .transition
|
shutterState = .transition
|
||||||
@ -1042,12 +1119,6 @@ private class BlurView: UIVisualEffectView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class CameraScreen: ViewController {
|
public class CameraScreen: ViewController {
|
||||||
public enum Mode {
|
|
||||||
case generic
|
|
||||||
case story
|
|
||||||
case instantVideo
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum PIPPosition: Int32 {
|
public enum PIPPosition: Int32 {
|
||||||
case topLeft
|
case topLeft
|
||||||
case topRight
|
case topRight
|
||||||
@ -2338,7 +2409,6 @@ public class CameraScreen: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
fileprivate let mode: Mode
|
|
||||||
fileprivate let holder: CameraHolder?
|
fileprivate let holder: CameraHolder?
|
||||||
fileprivate let transitionIn: TransitionIn?
|
fileprivate let transitionIn: TransitionIn?
|
||||||
fileprivate let transitionOut: (Bool) -> TransitionOut?
|
fileprivate let transitionOut: (Bool) -> TransitionOut?
|
||||||
@ -2388,14 +2458,12 @@ public class CameraScreen: ViewController {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
mode: Mode,
|
|
||||||
holder: CameraHolder? = nil,
|
holder: CameraHolder? = nil,
|
||||||
transitionIn: TransitionIn?,
|
transitionIn: TransitionIn?,
|
||||||
transitionOut: @escaping (Bool) -> TransitionOut?,
|
transitionOut: @escaping (Bool) -> TransitionOut?,
|
||||||
completion: @escaping (Signal<CameraScreen.Result, NoError>, ResultTransition?, @escaping () -> Void) -> Void
|
completion: @escaping (Signal<CameraScreen.Result, NoError>, ResultTransition?, @escaping () -> Void) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.mode = mode
|
|
||||||
self.holder = holder
|
self.holder = holder
|
||||||
self.transitionIn = transitionIn
|
self.transitionIn = transitionIn
|
||||||
self.transitionOut = transitionOut
|
self.transitionOut = transitionOut
|
||||||
|
@ -284,7 +284,6 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
|||||||
var showDraftTooltipImpl: (() -> Void)?
|
var showDraftTooltipImpl: (() -> Void)?
|
||||||
let cameraController = CameraScreen(
|
let cameraController = CameraScreen(
|
||||||
context: context,
|
context: context,
|
||||||
mode: .story,
|
|
||||||
transitionIn: transitionIn.flatMap {
|
transitionIn: transitionIn.flatMap {
|
||||||
if let sourceView = $0.sourceView {
|
if let sourceView = $0.sourceView {
|
||||||
return CameraScreen.TransitionIn(
|
return CameraScreen.TransitionIn(
|
||||||
|
@ -234,7 +234,6 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
|||||||
if text.contains("](") {
|
if text.contains("](") {
|
||||||
isUserInteractionEnabled = true
|
isUserInteractionEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
case let .actionSucceeded(title, text, cancel, destructive):
|
case let .actionSucceeded(title, text, cancel, destructive):
|
||||||
self.avatarNode = nil
|
self.avatarNode = nil
|
||||||
self.iconNode = nil
|
self.iconNode = nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user