session-ios/SignalUtilitiesKit/Shared Views/Toast.swift

152 lines
3.9 KiB
Swift

//
// Copyright (c) 2019 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
public class ToastController: NSObject, ToastViewDelegate {
static var currentToastController: ToastController?
private let toastView: ToastView
private var isDismissing: Bool
// MARK: Initializers
@objc
required public init(text: String) {
toastView = ToastView()
toastView.text = text
isDismissing = false
super.init()
toastView.delegate = self
}
// MARK: Public
@objc
public func presentToastView(fromBottomOfView view: UIView, inset: CGFloat) {
Logger.debug("")
toastView.alpha = 0
view.addSubview(toastView)
toastView.setCompressionResistanceHigh()
toastView.autoPinEdge(.bottom, to: .bottom, of: view, withOffset: -inset)
toastView.autoPinWidthToSuperview(withMargin: 24)
if let currentToastController = type(of: self).currentToastController {
currentToastController.dismissToastView()
type(of: self).currentToastController = nil
}
type(of: self).currentToastController = self
UIView.animate(withDuration: 0.1) {
self.toastView.alpha = 1
}
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1.5) {
// intentional strong reference to self.
// As with an AlertController, the caller likely expects toast to
// be presented and dismissed without maintaining a strong reference to ToastController
self.dismissToastView()
}
}
// MARK: ToastViewDelegate
func didTapToastView(_ toastView: ToastView) {
Logger.debug("")
self.dismissToastView()
}
func didSwipeToastView(_ toastView: ToastView) {
Logger.debug("")
self.dismissToastView()
}
// MARK: Internal
func dismissToastView() {
Logger.debug("")
guard !isDismissing else {
return
}
isDismissing = true
if type(of: self).currentToastController == self {
type(of: self).currentToastController = nil
}
UIView.animate(withDuration: 0.1,
animations: {
self.toastView.alpha = 0
},
completion: { (_) in
self.toastView.removeFromSuperview()
})
}
}
protocol ToastViewDelegate: class {
func didTapToastView(_ toastView: ToastView)
func didSwipeToastView(_ toastView: ToastView)
}
class ToastView: UIView {
var text: String? {
get {
return label.text
}
set {
label.text = newValue
}
}
weak var delegate: ToastViewDelegate?
private let label: UILabel
// MARK: Initializers
override init(frame: CGRect) {
label = UILabel()
super.init(frame: frame)
self.layer.cornerRadius = 4
self.backgroundColor = Theme.toastBackgroundColor
self.layoutMargins = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
label.textAlignment = .center
label.textColor = Theme.toastForegroundColor
label.font = UIFont.ows_dynamicTypeBody
label.numberOfLines = 0
self.addSubview(label)
label.autoPinEdgesToSuperviewMargins()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTap(gesture:)))
self.addGestureRecognizer(tapGesture)
let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(didSwipe(gesture:)))
self.addGestureRecognizer(swipeGesture)
}
required init?(coder aDecoder: NSCoder) {
notImplemented()
}
// MARK: Gestures
@objc
func didTap(gesture: UITapGestureRecognizer) {
self.delegate?.didTapToastView(self)
}
@objc
func didSwipe(gesture: UISwipeGestureRecognizer) {
self.delegate?.didSwipeToastView(self)
}
}