import Foundation import UIKit import Display import SwiftSignalKit import TelegramCore import AccountContext import MediaEditor import Photos public final class DrawingMediaEntityView: DrawingEntityView, DrawingEntityMediaView { private var mediaEntity: DrawingMediaEntity { return self.entity as! DrawingMediaEntity } private var currentSize: CGSize? private var isVisible = true private var isPlaying = false private let snapTool = DrawingEntitySnapTool() init(context: AccountContext, entity: DrawingMediaEntity) { super.init(context: context, entity: entity) self.backgroundColor = UIColor.clear self.snapTool.onSnapUpdated = { [weak self] type, snapped in if let self { self.onSnapUpdated(type, snapped) } } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } public override func play() { self.isVisible = true self.applyVisibility() } public override func pause() { self.isVisible = false self.applyVisibility() } public override func seek(to timestamp: Double) { self.isVisible = false self.isPlaying = false } override func resetToStart() { self.isVisible = false self.isPlaying = false } override func updateVisibility(_ visibility: Bool) { self.isVisible = visibility self.applyVisibility() } private func applyVisibility() { let isPlaying = self.isVisible if self.isPlaying != isPlaying { self.isPlaying = isPlaying } } private var didApplyVisibility = false public override func layoutSubviews() { super.layoutSubviews() let size = self.bounds.size if size.width > 0 && self.currentSize != size { self.currentSize = size self.update(animated: false) } } public var updated: (() -> Void)? public override func update(animated: Bool) { self.center = self.mediaEntity.position let size = self.mediaEntity.baseSize let scale = self.mediaEntity.scale self.bounds = CGRect(origin: .zero, size: size) self.transform = CGAffineTransformScale(CGAffineTransformMakeRotation(self.mediaEntity.rotation), scale, scale) super.update(animated: animated) self.updated?() } override func updateSelectionView() { } override func makeSelectionView() -> DrawingEntitySelectionView? { return nil } @objc func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) { let delta = gestureRecognizer.translation(in: self.superview) var updatedPosition = self.mediaEntity.position switch gestureRecognizer.state { case .began, .changed: updatedPosition.x += delta.x updatedPosition.y += delta.y gestureRecognizer.setTranslation(.zero, in: self.superview) default: break } self.mediaEntity.position = updatedPosition self.update(animated: false) } @objc func handlePinch(_ gestureRecognizer: UIPinchGestureRecognizer) { switch gestureRecognizer.state { case .began, .changed: let scale = gestureRecognizer.scale self.mediaEntity.scale = self.mediaEntity.scale * scale self.update(animated: false) gestureRecognizer.scale = 1.0 default: break } } private var beganRotating = false @objc func handleRotate(_ gestureRecognizer: UIRotationGestureRecognizer) { var updatedRotation = self.mediaEntity.rotation var rotation: CGFloat = 0.0 let velocity = gestureRecognizer.velocity switch gestureRecognizer.state { case .began: self.beganRotating = false self.snapTool.maybeSkipFromStart(entityView: self, rotation: self.mediaEntity.rotation) case .changed: rotation = gestureRecognizer.rotation if self.beganRotating { updatedRotation += rotation gestureRecognizer.rotation = 0.0 } else if abs(rotation) >= 0.08 * .pi || abs(self.mediaEntity.rotation) >= 0.03 { self.beganRotating = true gestureRecognizer.rotation = 0.0 } updatedRotation = self.snapTool.update(entityView: self, velocity: velocity, delta: rotation, updatedRotation: updatedRotation) self.mediaEntity.rotation = updatedRotation self.update(animated: false) case .ended, .cancelled: self.snapTool.rotationReset() self.beganRotating = false default: break } } public override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { return self.bounds.contains(point) } }