session-ios/Signal/src/ViewControllers/ConversationView/Cells/MediaUploadView.swift

118 lines
4.0 KiB
Swift

//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
public class MediaUploadView: UIView {
// MARK: -
private let attachmentId: String
private let radius: CGFloat
private let shapeLayer1 = CAShapeLayer()
private let shapeLayer2 = CAShapeLayer()
private var isAttachmentReady: Bool = false
private var lastProgress: CGFloat = 0
@objc
public required init(attachmentId: String, radius: CGFloat) {
self.attachmentId = attachmentId
self.radius = radius
super.init(frame: .zero)
layer.addSublayer(shapeLayer1)
layer.addSublayer(shapeLayer2)
NotificationCenter.default.addObserver(forName: NSNotification.Name.attachmentUploadProgress, object: nil, queue: nil) { [weak self] notification in
guard let strongSelf = self else { return }
guard let notificationAttachmentId = notification.userInfo?[kAttachmentUploadAttachmentIDKey] as? String else {
return
}
guard notificationAttachmentId == strongSelf.attachmentId else {
return
}
guard let progress = notification.userInfo?[kAttachmentUploadProgressKey] as? NSNumber else {
return
}
strongSelf.lastProgress = CGFloat(progress.floatValue)
strongSelf.updateLayers()
}
}
@available(*, unavailable, message: "use other init() instead.")
required public init?(coder aDecoder: NSCoder) {
notImplemented()
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc public override var bounds: CGRect {
didSet {
if oldValue != bounds {
updateLayers()
}
}
}
@objc public override var frame: CGRect {
didSet {
if oldValue != frame {
updateLayers()
}
}
}
internal func updateLayers() {
AssertIsOnMainThread()
shapeLayer1.frame = self.bounds
shapeLayer2.frame = self.bounds
guard !isAttachmentReady else {
shapeLayer1.path = nil
shapeLayer2.path = nil
return
}
// Prevent the shape layer from animating changes.
CATransaction.begin()
CATransaction.setDisableActions(true)
let center = CGPoint(x: self.bounds.width * 0.5,
y: self.bounds.height * 0.5)
let outerRadius: CGFloat = radius * 1.0
let innerRadius: CGFloat = radius * 0.9
let startAngle: CGFloat = CGFloat.pi * 1.5
let endAngle: CGFloat = CGFloat.pi * (1.5 + 2 * lastProgress)
let bezierPath1 = UIBezierPath()
bezierPath1.addArc(withCenter: center, radius: outerRadius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
bezierPath1.addArc(withCenter: center, radius: innerRadius, startAngle: endAngle, endAngle: startAngle, clockwise: false)
shapeLayer1.path = bezierPath1.cgPath
shapeLayer1.fillColor = UIColor.ows_white.cgColor
let innerCircleBounds = CGRect(x: center.x - innerRadius,
y: center.y - innerRadius,
width: innerRadius * 2,
height: innerRadius * 2)
let outerCircleBounds = CGRect(x: center.x - outerRadius,
y: center.y - outerRadius,
width: outerRadius * 2,
height: outerRadius * 2)
let bezierPath2 = UIBezierPath()
bezierPath2.append(UIBezierPath(ovalIn: innerCircleBounds))
bezierPath2.append(UIBezierPath(ovalIn: outerCircleBounds))
shapeLayer2.path = bezierPath2.cgPath
shapeLayer2.fillColor = UIColor(white: 1.0, alpha: 0.4).cgColor
shapeLayer2.fillRule = CAShapeLayerFillRule.evenOdd
CATransaction.commit()
}
}