Minimize use of implicitly unwrapped optionals in code.

And mark `init(coder:)` as unavailable.
This commit is contained in:
Igor Solomennikov 2022-03-02 13:31:10 -08:00
parent 09048dad07
commit 45db3a963e
3 changed files with 144 additions and 176 deletions

View File

@ -562,7 +562,7 @@ private class TitleView: UIView {
private let label = UILabel()
private let iconView = UIImageView()
private var stackView: UIStackView!
private let stackView: UIStackView
// Returns same font as UIBarButtonItem uses.
private func titleLabelFont() -> UIFont {
@ -573,18 +573,10 @@ private class TitleView: UIView {
// MARK: - Initializers
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
stackView = UIStackView(arrangedSubviews: [label, iconView])
super.init(frame: frame)
stackView.axis = .horizontal
stackView.alignment = .center
stackView.spacing = 5
@ -605,6 +597,11 @@ private class TitleView: UIView {
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(titleTapped)))
}
@available(*, unavailable, message: "Use init(frame:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
override func tintColorDidChange() {
super.tintColorDidChange()
label.textColor = tintColor

View File

@ -40,8 +40,8 @@ class CameraCaptureControl: UIView {
private static let shutterButtonDefaultSize: CGFloat = 72
private static let shutterButtonRecordingSize: CGFloat = 122
private var outerCircleSizeConstraint: NSLayoutConstraint!
private var innerCircleSizeConstraint: NSLayoutConstraint!
private let outerCircleSizeConstraint: NSLayoutConstraint
private let innerCircleSizeConstraint: NSLayoutConstraint
private var slidingCircleHPositionConstraint: NSLayoutConstraint!
private var slidingCircleVPositionConstraint: NSLayoutConstraint!
@ -67,23 +67,13 @@ class CameraCaptureControl: UIView {
weak var delegate: CameraCaptureControlDelegate?
convenience init(axis: NSLayoutConstraint.Axis) {
self.init(frame: CGRect(origin: .zero, size: CameraCaptureControl.intrinsicContentSize(forAxis: axis)))
required init(axis: NSLayoutConstraint.Axis) {
innerCircleSizeConstraint = shutterButtonInnerCircle.autoSetDimension(.width, toSize: CameraCaptureControl.shutterButtonDefaultSize)
outerCircleSizeConstraint = shutterButtonOuterCircle.autoSetDimension(.width, toSize: CameraCaptureControl.shutterButtonDefaultSize)
super.init(frame: CGRect(origin: .zero, size: CameraCaptureControl.intrinsicContentSize(forAxis: axis)))
self.axis = axis
reactivateConstraintsForCurrentAxis()
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
// Round Shutter Button
addLayoutGuide(shutterButtonLayoutGuide)
@ -104,11 +94,9 @@ class CameraCaptureControl: UIView {
addSubview(shutterButtonOuterCircle)
shutterButtonOuterCircle.centerXAnchor.constraint(equalTo: shutterButtonLayoutGuide.centerXAnchor).isActive = true
shutterButtonOuterCircle.centerYAnchor.constraint(equalTo: shutterButtonLayoutGuide.centerYAnchor).isActive = true
outerCircleSizeConstraint = shutterButtonOuterCircle.autoSetDimension(.width, toSize: CameraCaptureControl.shutterButtonDefaultSize)
shutterButtonOuterCircle.autoPin(toAspectRatio: 1)
addSubview(shutterButtonInnerCircle)
innerCircleSizeConstraint = shutterButtonInnerCircle.autoSetDimension(.width, toSize: CameraCaptureControl.shutterButtonDefaultSize)
shutterButtonInnerCircle.autoPin(toAspectRatio: 1)
shutterButtonInnerCircle.isUserInteractionEnabled = false
shutterButtonInnerCircle.backgroundColor = .clear
@ -119,13 +107,18 @@ class CameraCaptureControl: UIView {
// The long press handles both the tap and the hold interaction, as well as the animation
// the presents as the user begins to hold (and the button begins to grow prior to recording)
longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress))
longPressGesture.minimumPressDuration = 0
shutterButtonOuterCircle.addGestureRecognizer(longPressGesture)
reactivateConstraintsForCurrentAxis()
}
@available(*, unavailable, message: "Use init(axis:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
// MARK: - UI State
enum State {
@ -154,12 +147,13 @@ class CameraCaptureControl: UIView {
}
}
func setState(_ state: State, animationDuration: TimeInterval = 0) {
func setState(_ state: State, isRecordingWithLongPress: Bool = false, animationDuration: TimeInterval = 0) {
guard _internalState != state else { return }
Logger.debug("New state: \(_internalState) -> \(state)")
_internalState = state
self.isRecordingWithLongPress = isRecordingWithLongPress
if animationDuration > 0 {
UIView.animate(withDuration: animationDuration,
delay: 0,
@ -190,12 +184,11 @@ class CameraCaptureControl: UIView {
case .recording:
prepareRecordingControlsIfNecessary()
let recordingWithLongPress = longPressGesture.state != .possible
let sliderProgress = recordingWithLongPress ? sliderTrackingProgress : 0
let sliderProgress = isRecordingWithLongPress ? sliderTrackingProgress : 0
// element visibility
stopButton.isHidden = sliderProgress == 0
slidingCircleView.isHidden = sliderProgress == 0
lockIconView.isHidden = !recordingWithLongPress
lockIconView.isHidden = !isRecordingWithLongPress
lockIconView.setState(sliderProgress > 0.5 ? .locking : .unlocked, animated: true)
shutterButtonInnerCircle.backgroundColor = .ows_white
// element sizes
@ -307,7 +300,7 @@ class CameraCaptureControl: UIView {
// MARK: - Gestures
private var longPressGesture: UILongPressGestureRecognizer!
private var isRecordingWithLongPress = false
private static let longPressDurationThreshold = 0.5
private static let minDistanceBeforeActivatingLockSlider: CGFloat = 30
private var initialTouchLocation: CGPoint?
@ -340,7 +333,7 @@ class CameraCaptureControl: UIView {
) { [weak self] _ in
guard let self = self else { return }
self.setState(.recording, animationDuration: 0.4)
self.setState(.recording, isRecordingWithLongPress: true, animationDuration: 0.4)
self.delegate?.cameraCaptureControlDidRequestStartVideoRecording(self)
}
@ -471,10 +464,10 @@ class CameraCaptureControl: UIView {
private class LockView: UIView {
private var imageViewLock = UIImageView(image: UIImage(named: "media-composer-lock-outline-24"))
private var blurBackgroundView = CircleBlurView(effect: UIBlurEffect(style: .dark))
private var whiteBackgroundView = CircleView()
private var whiteCircleView = CircleView()
private let imageViewLock = UIImageView(image: UIImage(named: "media-composer-lock-outline-24"))
private let blurBackgroundView = CircleBlurView(effect: UIBlurEffect(style: .dark))
private let whiteBackgroundView = CircleView()
private let whiteCircleView = CircleView()
enum State {
case unlocked
@ -531,15 +524,7 @@ private class LockView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
isUserInteractionEnabled = false
addSubview(blurBackgroundView)
@ -562,6 +547,11 @@ private class LockView: UIView {
updateAppearance()
}
@available(*, unavailable, message: "Use init(frame:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
override var intrinsicContentSize: CGSize {
CGSize(width: CameraCaptureControl.recordingLockControlSize, height: CameraCaptureControl.recordingLockControlSize)
}
@ -621,7 +611,11 @@ class CameraOverlayButton: UIButton, UserInterfaceStyleOverride {
}
}
private var backgroundView: UIVisualEffectView!
private let backgroundView: CircleBlurView = {
let view = CircleBlurView(effect: UIBlurEffect(style: .regular))
view.isUserInteractionEnabled = false
return view
}()
private static let visibleButtonSize: CGFloat = 36 // both height and width
private static let defaultInset: CGFloat = 4
@ -632,32 +626,28 @@ class CameraOverlayButton: UIButton, UserInterfaceStyleOverride {
}
}
convenience init(image: UIImage?, userInterfaceStyleOverride: UIUserInterfaceStyle = .unspecified) {
self.init(frame: CGRect(origin: .zero, size: .square(Self.visibleButtonSize + 2*Self.defaultInset)))
required init(image: UIImage?, userInterfaceStyleOverride: UIUserInterfaceStyle = .unspecified) {
super.init(frame: CGRect(origin: .zero, size: .square(Self.visibleButtonSize + 2*Self.defaultInset)))
self.userInterfaceStyleOverride = userInterfaceStyleOverride
layoutMargins = contentInsets
addSubview(backgroundView)
backgroundView.autoPinEdgesToSuperviewMargins()
setImage(image, for: .normal)
updateStyle()
}
private override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
@available(*, unavailable, message: "Use init(image:userInterfaceStyleOverride:) instead")
override init(frame: CGRect) {
notImplemented()
}
@available(*, unavailable, message: "Use init(image:userInterfaceStyleOverride:) instead")
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
layoutMargins = contentInsets
backgroundView = CircleBlurView(effect: UIBlurEffect(style: CameraOverlayButton.blurEffectStyle(for: effectiveUserInterfaceStyle)))
backgroundView.isUserInteractionEnabled = false
addSubview(backgroundView)
backgroundView.autoPinEdgesToSuperviewMargins()
updateStyle()
notImplemented()
}
override func layoutSubviews() {
@ -700,14 +690,8 @@ class MediaDoneButton: UIButton, UserInterfaceStyleOverride {
}
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
private static var font: UIFont {
return UIFont.ows_dynamicTypeSubheadline.ows_monospaced
}
private let numberFormatter: NumberFormatter = {
@ -720,22 +704,38 @@ class MediaDoneButton: UIButton, UserInterfaceStyleOverride {
let label = UILabel()
label.textColor = .ows_white
label.textAlignment = .center
label.font = .ows_dynamicTypeSubheadline.ows_monospaced
label.font = MediaDoneButton.font
return label
}()
private var pillView: PillView!
private var blurBackgroundView: UIVisualEffectView!
private var chevronImageView: UIImageView!
private var dimmerView: UIView!
private func commonInit() {
pillView = PillView(frame: bounds)
private let pillView: PillView = {
let pillView = PillView(frame: .zero)
pillView.isUserInteractionEnabled = false
pillView.layoutMargins = UIEdgeInsets(hMargin: 8, vMargin: 7)
return pillView
}()
private let blurBackgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
private let chevronImageView: UIImageView = {
let image: UIImage?
if #available(iOS 13, *) {
image = CurrentAppContext().isRTL ? UIImage(systemName: "chevron.backward") : UIImage(systemName: "chevron.right")
} else {
image = CurrentAppContext().isRTL ? UIImage(named: "chevron-left-20") : UIImage(named: "chevron-right-20")
}
let chevronImageView = UIImageView(image: image!.withRenderingMode(.alwaysTemplate))
chevronImageView.contentMode = .center
if #available(iOS 13, *) {
chevronImageView.preferredSymbolConfiguration = UIImage.SymbolConfiguration(pointSize: MediaDoneButton.font.pointSize)
}
return chevronImageView
}()
private var dimmerView: UIView?
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(pillView)
pillView.autoPinEdgesToSuperviewEdges()
blurBackgroundView = UIVisualEffectView(effect: UIBlurEffect(style: MediaDoneButton.blurEffectStyle(for: effectiveUserInterfaceStyle)))
pillView.addSubview(blurBackgroundView)
blurBackgroundView.autoPinEdgesToSuperviewEdges()
@ -745,18 +745,6 @@ class MediaDoneButton: UIButton, UserInterfaceStyleOverride {
blueBadgeView.addSubview(textLabel)
textLabel.autoPinEdgesToSuperviewMargins()
let image: UIImage?
if #available(iOS 13, *) {
image = CurrentAppContext().isRTL ? UIImage(systemName: "chevron.backward") : UIImage(systemName: "chevron.right")
} else {
image = CurrentAppContext().isRTL ? UIImage(named: "chevron-left-20") : UIImage(named: "chevron-right-20")
}
chevronImageView = UIImageView(image: image!.withRenderingMode(.alwaysTemplate))
chevronImageView.contentMode = .center
if #available(iOS 13, *) {
chevronImageView.preferredSymbolConfiguration = UIImage.SymbolConfiguration(pointSize: textLabel.font.pointSize)
}
let hStack = UIStackView(arrangedSubviews: [blueBadgeView, chevronImageView])
hStack.spacing = 6
pillView.addSubview(hStack)
@ -765,6 +753,11 @@ class MediaDoneButton: UIButton, UserInterfaceStyleOverride {
updateStyle()
}
@available(*, unavailable, message: "Use init(frame:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
if traitCollection.preferredContentSizeCategory != previousTraitCollection?.preferredContentSizeCategory {
textLabel.font = .ows_dynamicTypeSubheadline.ows_monospaced
@ -781,13 +774,14 @@ class MediaDoneButton: UIButton, UserInterfaceStyleOverride {
didSet {
if isHighlighted {
if dimmerView == nil {
dimmerView = UIView(frame: bounds)
let dimmerView = UIView(frame: bounds)
dimmerView.isUserInteractionEnabled = false
dimmerView.backgroundColor = .ows_black
pillView.addSubview(dimmerView)
dimmerView.autoPinEdgesToSuperviewEdges()
self.dimmerView = dimmerView
}
dimmerView.alpha = 0.5
dimmerView?.alpha = 0.5
} else if let dimmerView = dimmerView {
dimmerView.alpha = 0
}

View File

@ -707,45 +707,38 @@ private struct ButtonImages {
}
private class TopBar: UIView {
private(set) var closeButton: CameraOverlayButton!
let closeButton = CameraOverlayButton(image: ButtonImages.close, userInterfaceStyleOverride: .dark)
private var cameraControlsContainerView: UIView!
private(set) var flashModeButton: CameraOverlayButton!
private(set) var batchModeButton: CameraOverlayButton!
private let cameraControlsContainerView: UIStackView
let flashModeButton = CameraOverlayButton(image: ButtonImages.flashAuto, userInterfaceStyleOverride: .dark)
let batchModeButton = CameraOverlayButton(image: ButtonImages.flashAuto, userInterfaceStyleOverride: .dark)
private(set) var recordingTimerView: RecordingTimerView!
let recordingTimerView = RecordingTimerView(frame: .zero)
override init(frame: CGRect) {
cameraControlsContainerView = UIStackView(arrangedSubviews: [ batchModeButton, flashModeButton ])
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
layoutMargins = UIEdgeInsets(hMargin: 8, vMargin: 4)
closeButton = CameraOverlayButton(image: ButtonImages.close, userInterfaceStyleOverride: .dark)
addSubview(closeButton)
closeButton.autoPinHeightToSuperviewMargins()
closeButton.autoPinLeadingToSuperviewMargin()
recordingTimerView = RecordingTimerView(frame: .zero)
addSubview(recordingTimerView)
recordingTimerView.autoPinHeightToSuperview(withMargin: 8)
recordingTimerView.autoHCenterInSuperview()
flashModeButton = CameraOverlayButton(image: ButtonImages.flashAuto, userInterfaceStyleOverride: .dark)
batchModeButton = CameraOverlayButton(image: ButtonImages.batchModeOff, userInterfaceStyleOverride: .dark)
let stackView = UIStackView(arrangedSubviews: [ batchModeButton, flashModeButton ])
stackView.spacing = 16
addSubview(stackView)
stackView.autoPinHeightToSuperviewMargins()
stackView.autoPinTrailingToSuperviewMargin()
cameraControlsContainerView = stackView
cameraControlsContainerView.spacing = 16
addSubview(cameraControlsContainerView)
cameraControlsContainerView.autoPinHeightToSuperviewMargins()
cameraControlsContainerView.autoPinTrailingToSuperviewMargin()
}
@available(*, unavailable, message: "Use init(frame:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
// MARK: - Mode
@ -760,12 +753,12 @@ private class TopBar: UIView {
case .cameraControls:
closeButton.isHidden = false
cameraControlsContainerView.isHidden = false
recordingTimerView?.isHidden = true
recordingTimerView.isHidden = true
case .closeButton:
closeButton.isHidden = false
cameraControlsContainerView.isHidden = true
recordingTimerView?.isHidden = true
recordingTimerView.isHidden = true
case .videoRecording:
closeButton.isHidden = true
@ -793,47 +786,36 @@ private class BottomBar: UIView {
}
}
private(set) var photoLibraryButton: MediaPickerThumbnailButton!
private(set) var switchCameraButton: CameraOverlayButton!
let photoLibraryButton = MediaPickerThumbnailButton(frame: .zero)
let switchCameraButton = CameraOverlayButton(image: ButtonImages.switchCamera, userInterfaceStyleOverride: .dark)
let controlButtonsLayoutGuide = UILayoutGuide() // area encompassing Photo Library and Switch Camera buttons.
private(set) var captureControl: CameraCaptureControl!
let captureControl = CameraCaptureControl(axis: .horizontal)
var shutterButtonLayoutGuide: UILayoutGuide {
captureControl.shutterButtonLayoutGuide
}
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
layoutMargins = UIEdgeInsets(top: 0, leading: 12, bottom: 0, trailing: 14)
addLayoutGuide(controlButtonsLayoutGuide)
addConstraints([ controlButtonsLayoutGuide.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
controlButtonsLayoutGuide.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor) ])
photoLibraryButton = MediaPickerThumbnailButton(frame: CGRect(origin: .zero, size: .square(bounds.height)))
photoLibraryButton.translatesAutoresizingMaskIntoConstraints = false
addSubview(photoLibraryButton)
addConstraints([ photoLibraryButton.leadingAnchor.constraint(equalTo: controlButtonsLayoutGuide.leadingAnchor),
photoLibraryButton.centerYAnchor.constraint(equalTo: controlButtonsLayoutGuide.centerYAnchor),
photoLibraryButton.topAnchor.constraint(greaterThanOrEqualTo: controlButtonsLayoutGuide.topAnchor) ])
switchCameraButton = CameraOverlayButton(image: ButtonImages.switchCamera, userInterfaceStyleOverride: .dark)
switchCameraButton.translatesAutoresizingMaskIntoConstraints = false
addSubview(switchCameraButton)
addConstraints([ switchCameraButton.trailingAnchor.constraint(equalTo: controlButtonsLayoutGuide.trailingAnchor),
switchCameraButton.topAnchor.constraint(greaterThanOrEqualTo: controlButtonsLayoutGuide.topAnchor),
switchCameraButton.centerYAnchor.constraint(equalTo: controlButtonsLayoutGuide.centerYAnchor) ])
captureControl = CameraCaptureControl(axis: .horizontal)
captureControl.translatesAutoresizingMaskIntoConstraints = false
addSubview(captureControl)
captureControl.autoPinTopToSuperviewMargin()
@ -849,6 +831,11 @@ private class BottomBar: UIView {
updateCompactHeightLayoutConstraints()
}
@available(*, unavailable, message: "Use init(frame:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
private func updateCompactHeightLayoutConstraints() {
if isCompactHeightLayout {
removeConstraints(regularHeightLayoutConstraints)
@ -869,49 +856,41 @@ private class SideBar: UIView {
}
}
private var cameraControlsContainerView: UIView!
private(set) var flashModeButton: CameraOverlayButton!
private(set) var batchModeButton: CameraOverlayButton!
private(set) var switchCameraButton: CameraOverlayButton!
private let cameraControlsContainerView: UIStackView
let flashModeButton = CameraOverlayButton(image: ButtonImages.flashAuto, userInterfaceStyleOverride: .dark)
let batchModeButton = CameraOverlayButton(image: ButtonImages.batchModeOff, userInterfaceStyleOverride: .dark)
let switchCameraButton = CameraOverlayButton(image: ButtonImages.switchCamera, userInterfaceStyleOverride: .dark)
private(set) var photoLibraryButton: MediaPickerThumbnailButton!
let photoLibraryButton = MediaPickerThumbnailButton(frame: .zero)
private(set) var cameraCaptureControl = CameraCaptureControl(axis: .vertical)
override init(frame: CGRect) {
cameraControlsContainerView = UIStackView(arrangedSubviews: [ batchModeButton, flashModeButton, switchCameraButton ])
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
layoutMargins = UIEdgeInsets(margin: 8)
flashModeButton = CameraOverlayButton(image: ButtonImages.flashAuto, userInterfaceStyleOverride: .dark)
switchCameraButton = CameraOverlayButton(image: ButtonImages.switchCamera, userInterfaceStyleOverride: .dark)
batchModeButton = CameraOverlayButton(image: ButtonImages.batchModeOff, userInterfaceStyleOverride: .dark)
let stackView = UIStackView(arrangedSubviews: [ batchModeButton, flashModeButton, switchCameraButton ])
stackView.spacing = 16
stackView.axis = .vertical
addSubview(stackView)
stackView.autoPinWidthToSuperviewMargins()
stackView.autoPinTopToSuperviewMargin()
cameraControlsContainerView = stackView
cameraControlsContainerView.spacing = 16
cameraControlsContainerView.axis = .vertical
addSubview(cameraControlsContainerView)
cameraControlsContainerView.autoPinWidthToSuperviewMargins()
cameraControlsContainerView.autoPinTopToSuperviewMargin()
addSubview(cameraCaptureControl)
cameraCaptureControl.autoHCenterInSuperview()
cameraCaptureControl.shutterButtonLayoutGuide.topAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 36).isActive = true
cameraCaptureControl.shutterButtonLayoutGuide.topAnchor.constraint(equalTo: cameraControlsContainerView.bottomAnchor, constant: 36).isActive = true
photoLibraryButton = MediaPickerThumbnailButton(frame: CGRect(origin: .zero, size: .square(bounds.height)))
addSubview(photoLibraryButton)
photoLibraryButton.autoHCenterInSuperview()
photoLibraryButton.topAnchor.constraint(equalTo: cameraCaptureControl.shutterButtonLayoutGuide.bottomAnchor, constant: 36).isActive = true
photoLibraryButton.bottomAnchor.constraint(lessThanOrEqualTo: layoutMarginsGuide.bottomAnchor).isActive = true
}
@available(*, unavailable, message: "Use init(frame:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
}
@ -1114,8 +1093,9 @@ class CapturePreviewView: UIView {
layer.addSublayer(previewLayer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
@available(*, unavailable, message: "Use init(session:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
}
@ -1123,15 +1103,7 @@ private class RecordingTimerView: PillView {
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
layoutMargins = UIEdgeInsets(hMargin: 16, vMargin: 0)
let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
@ -1148,9 +1120,14 @@ private class RecordingTimerView: PillView {
updateView()
}
@available(*, unavailable, message: "Use init(frame:) instead")
required init?(coder: NSCoder) {
notImplemented()
}
// MARK: - Subviews
private lazy var label: UILabel = {
private let label: UILabel = {
let label = UILabel()
label.font = UIFont.ows_monospacedDigitFont(withSize: 20)
label.textAlignment = .center