mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 08:48:39 +09:00
Dactyloidae iOS initial commit
This commit is contained in:
parent
daa6179d22
commit
7154a0497e
2123 changed files with 197052 additions and 0 deletions
181
mobile/ios/Client/Frontend/Browser/ButtonToast.swift
Normal file
181
mobile/ios/Client/Frontend/Browser/ButtonToast.swift
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import Foundation
|
||||
import Shared
|
||||
import SnapKit
|
||||
|
||||
struct ButtonToastUX {
|
||||
static let ToastPadding = 15.0
|
||||
static let TitleSpacing = 2.0
|
||||
static let ToastButtonPadding: CGFloat = 10.0
|
||||
static let TitleButtonPadding: CGFloat = 5.0
|
||||
static let ToastDelay = DispatchTimeInterval.milliseconds(900)
|
||||
static let ToastButtonBorderRadius: CGFloat = 5
|
||||
static let ToastButtonBorderWidth: CGFloat = 1
|
||||
}
|
||||
|
||||
private class HighlightableButton: UIButton {
|
||||
override var isHighlighted: Bool {
|
||||
didSet {
|
||||
if isHighlighted {
|
||||
self.backgroundColor = UIColor.white
|
||||
} else {
|
||||
self.backgroundColor = UIColor.clear
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ButtonToast: UIView {
|
||||
|
||||
fileprivate var dismissed = false
|
||||
fileprivate var completionHandler: ((Bool) -> Void)?
|
||||
fileprivate lazy var toast: UIView = {
|
||||
let toast = UIView()
|
||||
toast.backgroundColor = SimpleToastUX.ToastDefaultColor
|
||||
return toast
|
||||
}()
|
||||
fileprivate var animationConstraint: Constraint?
|
||||
fileprivate lazy var gestureRecognizer: UITapGestureRecognizer = {
|
||||
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ButtonToast.handleTap(_:)))
|
||||
gestureRecognizer.cancelsTouchesInView = false
|
||||
return gestureRecognizer
|
||||
}()
|
||||
|
||||
init(labelText: String, descriptionText: String? = nil, buttonText: String, completion:@escaping (_ buttonPressed: Bool) -> Void) {
|
||||
super.init(frame: CGRect.zero)
|
||||
completionHandler = completion
|
||||
|
||||
self.clipsToBounds = true
|
||||
self.addSubview(createView(labelText, descriptionText: descriptionText, buttonText: buttonText))
|
||||
|
||||
toast.snp.makeConstraints { make in
|
||||
make.left.right.height.equalTo(self)
|
||||
animationConstraint = make.top.equalTo(self).offset(SimpleToastUX.ToastHeight).constraint
|
||||
}
|
||||
self.snp.makeConstraints { make in
|
||||
make.height.equalTo(SimpleToastUX.ToastHeight)
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
fileprivate func createView(_ labelText: String, descriptionText: String?, buttonText: String) -> UIView {
|
||||
let label = UILabel()
|
||||
label.textColor = UIColor.white
|
||||
label.font = SimpleToastUX.ToastFont
|
||||
label.text = labelText
|
||||
label.lineBreakMode = .byWordWrapping
|
||||
label.numberOfLines = 0
|
||||
toast.addSubview(label)
|
||||
|
||||
let button = HighlightableButton()
|
||||
button.layer.cornerRadius = ButtonToastUX.ToastButtonBorderRadius
|
||||
button.layer.borderWidth = ButtonToastUX.ToastButtonBorderWidth
|
||||
button.layer.borderColor = UIColor.white.cgColor
|
||||
button.setTitle(buttonText, for: UIControlState())
|
||||
button.setTitleColor(self.toast.backgroundColor, for: .highlighted)
|
||||
button.titleLabel?.font = SimpleToastUX.ToastFont
|
||||
button.titleLabel?.numberOfLines = 1
|
||||
button.titleLabel?.lineBreakMode = .byClipping
|
||||
button.titleLabel?.adjustsFontSizeToFitWidth = true
|
||||
button.titleLabel?.minimumScaleFactor = 0.1
|
||||
|
||||
let recognizer = UITapGestureRecognizer(target: self, action: #selector(ButtonToast.buttonPressed(_:)))
|
||||
button.addGestureRecognizer(recognizer)
|
||||
toast.addSubview(button)
|
||||
var descriptionLabel: UILabel?
|
||||
|
||||
if let text = descriptionText {
|
||||
let textLabel = UILabel()
|
||||
textLabel.textColor = UIColor.white
|
||||
textLabel.font = SimpleToastUX.ToastFont
|
||||
textLabel.text = text
|
||||
textLabel.lineBreakMode = .byTruncatingTail
|
||||
toast.addSubview(textLabel)
|
||||
descriptionLabel = textLabel
|
||||
}
|
||||
|
||||
if let description = descriptionLabel {
|
||||
label.numberOfLines = 1 // if showing a description we cant wrap to the second line
|
||||
label.lineBreakMode = .byClipping
|
||||
label.adjustsFontSizeToFitWidth = true
|
||||
label.snp.makeConstraints { (make) in
|
||||
make.leading.equalTo(toast).offset(ButtonToastUX.ToastPadding)
|
||||
make.top.equalTo(toast).offset(ButtonToastUX.TitleButtonPadding)
|
||||
make.trailing.equalTo(button.snp.leading).offset(-ButtonToastUX.TitleButtonPadding)
|
||||
}
|
||||
description.snp.makeConstraints { (make) in
|
||||
make.leading.equalTo(toast).offset(ButtonToastUX.ToastPadding)
|
||||
make.top.equalTo(label.snp.bottom).offset(ButtonToastUX.TitleSpacing)
|
||||
make.trailing.equalTo(button.snp.leading).offset(-ButtonToastUX.TitleButtonPadding)
|
||||
}
|
||||
} else {
|
||||
label.snp.makeConstraints { (make) in
|
||||
make.leading.equalTo(toast).offset(ButtonToastUX.ToastPadding)
|
||||
make.centerY.equalTo(toast)
|
||||
make.trailing.equalTo(button.snp.leading).offset(-ButtonToastUX.TitleButtonPadding)
|
||||
}
|
||||
}
|
||||
|
||||
button.snp.makeConstraints { (make) in
|
||||
make.trailing.equalTo(toast).offset(-ButtonToastUX.ToastPadding)
|
||||
make.centerY.equalTo(toast)
|
||||
make.width.equalTo(button.titleLabel!.intrinsicContentSize.width + 2*ButtonToastUX.ToastButtonPadding)
|
||||
}
|
||||
|
||||
return toast
|
||||
}
|
||||
|
||||
fileprivate func dismiss(_ buttonPressed: Bool) {
|
||||
guard dismissed == false else {
|
||||
return
|
||||
}
|
||||
dismissed = true
|
||||
superview?.removeGestureRecognizer(gestureRecognizer)
|
||||
|
||||
UIView.animate(withDuration: SimpleToastUX.ToastAnimationDuration, animations: {
|
||||
self.animationConstraint?.update(offset: SimpleToastUX.ToastHeight)
|
||||
self.layoutIfNeeded()
|
||||
},
|
||||
completion: { finished in
|
||||
self.removeFromSuperview()
|
||||
if !buttonPressed {
|
||||
self.completionHandler?(false)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
func showToast(duration: DispatchTimeInterval = SimpleToastUX.ToastDismissAfter) {
|
||||
layoutIfNeeded()
|
||||
UIView.animate(withDuration: SimpleToastUX.ToastAnimationDuration, animations: {
|
||||
self.animationConstraint?.update(offset: 0)
|
||||
self.layoutIfNeeded()
|
||||
},
|
||||
completion: { finished in
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
|
||||
self.dismiss(false)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@objc func buttonPressed(_ gestureRecognizer: UIGestureRecognizer) {
|
||||
self.completionHandler?(true)
|
||||
self.dismiss(true)
|
||||
}
|
||||
|
||||
override func didMoveToSuperview() {
|
||||
super.didMoveToSuperview()
|
||||
superview?.addGestureRecognizer(gestureRecognizer)
|
||||
}
|
||||
|
||||
func handleTap(_ gestureRecognizer: UIGestureRecognizer) {
|
||||
dismiss(false)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue