The old UIButton API is still functional as long as we don't use UIButton.Configuration, so we can safely ignore these warnings until we're ready to adopt the configuration API across the codebase.
173 lines
4.0 KiB
Swift
173 lines
4.0 KiB
Swift
//
|
|
// Copyright 2021 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
//
|
|
|
|
import SignalServiceKit
|
|
import YYImage
|
|
|
|
public class CVUtils {
|
|
|
|
@available(*, unavailable, message: "use other init() instead.")
|
|
private init() {}
|
|
|
|
private static let workQueue_userInitiated: DispatchQueue = {
|
|
DispatchQueue(label: "org.signal.conversation-view.user-initiated",
|
|
qos: .userInitiated,
|
|
autoreleaseFrequency: .workItem)
|
|
}()
|
|
|
|
private static let workQueue_userInteractive: DispatchQueue = {
|
|
DispatchQueue(label: "org.signal.conversation-view.user-interactive",
|
|
qos: .userInteractive,
|
|
autoreleaseFrequency: .workItem)
|
|
}()
|
|
|
|
public static func workQueue(isInitialLoad: Bool) -> DispatchQueue {
|
|
isInitialLoad ? workQueue_userInteractive : workQueue_userInitiated
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
public protocol CVView: UIView {
|
|
func reset()
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
open class CVLabel: UILabel, CVView {
|
|
public override func updateConstraints() {
|
|
super.updateConstraints()
|
|
|
|
deactivateAllConstraints()
|
|
}
|
|
|
|
public func reset() {
|
|
// NOTE: we have to reset the attributed text and then the text;
|
|
// this is the magic incantation that prevents properties from
|
|
// a previously-set attributed string from applying to subsequent
|
|
// attributed strings.
|
|
self.attributedText = nil
|
|
self.text = nil
|
|
}
|
|
}
|
|
|
|
open class CVButton: OWSButton, CVView {
|
|
open override func updateConstraints() {
|
|
super.updateConstraints()
|
|
deactivateAllConstraints()
|
|
}
|
|
|
|
public func reset() {
|
|
self.block = {}
|
|
self.dimsWhenDisabled = false
|
|
self.dimsWhenHighlighted = false
|
|
self.ows_contentEdgeInsets = .zero
|
|
self.ows_titleEdgeInsets = .zero
|
|
[
|
|
UIControl.State.normal,
|
|
.highlighted,
|
|
.disabled,
|
|
.selected,
|
|
.focused,
|
|
.application,
|
|
.reserved,
|
|
].forEach { controlState in
|
|
self.setAttributedTitle(nil, for: controlState)
|
|
self.setTitle(nil, for: controlState)
|
|
self.setImage(nil, for: controlState)
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
open class CVImageView: UIImageView, CVView {
|
|
public override func updateConstraints() {
|
|
super.updateConstraints()
|
|
|
|
deactivateAllConstraints()
|
|
}
|
|
|
|
public func reset() {
|
|
self.image = nil
|
|
}
|
|
|
|
// MARK: - Layout
|
|
|
|
public typealias LayoutBlock = (UIView) -> Void
|
|
|
|
private var layoutBlocks = [LayoutBlock]()
|
|
|
|
public func addLayoutBlock(_ layoutBlock: @escaping LayoutBlock) {
|
|
layoutBlocks.append(layoutBlock)
|
|
}
|
|
|
|
public override var bounds: CGRect {
|
|
didSet {
|
|
if oldValue.size != bounds.size {
|
|
viewSizeDidChange()
|
|
}
|
|
}
|
|
}
|
|
|
|
public override var frame: CGRect {
|
|
didSet {
|
|
if oldValue.size != frame.size {
|
|
viewSizeDidChange()
|
|
}
|
|
}
|
|
}
|
|
|
|
func viewSizeDidChange() {
|
|
layoutSubviews()
|
|
}
|
|
|
|
open override func layoutSubviews() {
|
|
layoutSubviews(skipLayoutBlocks: false)
|
|
}
|
|
|
|
public func layoutSubviews(skipLayoutBlocks: Bool = false) {
|
|
AssertIsOnMainThread()
|
|
|
|
super.layoutSubviews()
|
|
|
|
if !skipLayoutBlocks {
|
|
applyLayoutBlocks()
|
|
}
|
|
}
|
|
|
|
public func applyLayoutBlocks() {
|
|
AssertIsOnMainThread()
|
|
|
|
for layoutBlock in layoutBlocks {
|
|
layoutBlock(self)
|
|
}
|
|
}
|
|
|
|
// MARK: - Circles
|
|
|
|
public static func circleView() -> CVImageView {
|
|
let result = CVImageView()
|
|
result.addLayoutBlock { view in
|
|
view.layer.cornerRadius = min(view.width, view.height) * 0.5
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
// MARK: -
|
|
|
|
open class CVAnimatedImageView: YYAnimatedImageView, CVView {
|
|
public override func updateConstraints() {
|
|
super.updateConstraints()
|
|
|
|
deactivateAllConstraints()
|
|
}
|
|
|
|
public func reset() {
|
|
self.image = nil
|
|
}
|
|
}
|