mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-25 01:31:02 +00:00
Add account overhaul
This commit is contained in:
parent
5bed334d30
commit
72c08642d8
4 changed files with 145 additions and 68 deletions
|
@ -39,6 +39,7 @@
|
|||
D025B16025C4EA81001C69A8 /* ImageCacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B14525C4D26A001C69A8 /* ImageCacheSerializer.swift */; };
|
||||
D025B16A25C4EB18001C69A8 /* ServiceLayer in Frameworks */ = {isa = PBXBuildFile; productRef = D025B16925C4EB18001C69A8 /* ServiceLayer */; };
|
||||
D025B17025C4EB58001C69A8 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = D025B16F25C4EB58001C69A8 /* Kingfisher */; };
|
||||
D025B17E25C500BC001C69A8 /* CapsuleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B17D25C500BC001C69A8 /* CapsuleButton.swift */; };
|
||||
D02E1F95250B13210071AD56 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02E1F94250B13210071AD56 /* SafariView.swift */; };
|
||||
D035F86925B7F2ED00DC75ED /* MainNavigationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035F86825B7F2ED00DC75ED /* MainNavigationViewController.swift */; };
|
||||
D035F86F25B7F30E00DC75ED /* MainNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035F86E25B7F30E00DC75ED /* MainNavigationView.swift */; };
|
||||
|
@ -229,6 +230,7 @@
|
|||
D021A63525C38ADB008A0C0D /* AcknowledgmentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcknowledgmentsView.swift; sourceTree = "<group>"; };
|
||||
D025B14525C4D26A001C69A8 /* ImageCacheSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCacheSerializer.swift; sourceTree = "<group>"; };
|
||||
D025B14C25C4E482001C69A8 /* ImageCacheConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCacheConfiguration.swift; sourceTree = "<group>"; };
|
||||
D025B17D25C500BC001C69A8 /* CapsuleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapsuleButton.swift; sourceTree = "<group>"; };
|
||||
D02E1F94250B13210071AD56 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = "<group>"; };
|
||||
D035F86825B7F2ED00DC75ED /* MainNavigationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavigationViewController.swift; sourceTree = "<group>"; };
|
||||
D035F86E25B7F30E00DC75ED /* MainNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavigationView.swift; sourceTree = "<group>"; };
|
||||
|
@ -401,6 +403,7 @@
|
|||
D01F41E224F8889700D55A2D /* AttachmentsView.swift */,
|
||||
D0CE9F86258B076900E3A6B6 /* AttachmentUploadView.swift */,
|
||||
D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */,
|
||||
D025B17D25C500BC001C69A8 /* CapsuleButton.swift */,
|
||||
D0EA593F2522AC8700804347 /* CardView.swift */,
|
||||
D021A66F25C3E1F9008A0C0D /* Collection View Cells */,
|
||||
D0E9F9A9258450B300EF503D /* CompositionInputAccessoryView.swift */,
|
||||
|
@ -1015,6 +1018,7 @@
|
|||
D0030982250C6C8500EACB32 /* URL+Extensions.swift in Sources */,
|
||||
D00CB2ED2533ACC00080096B /* StatusView.swift in Sources */,
|
||||
D0A1F4F7252E7D4B004435BF /* TableViewDataSource.swift in Sources */,
|
||||
D025B17E25C500BC001C69A8 /* CapsuleButton.swift in Sources */,
|
||||
D0C7D4C424F7616A001EBDBB /* AppDelegate.swift in Sources */,
|
||||
D0C7D49924F7616A001EBDBB /* AddIdentityView.swift in Sources */,
|
||||
D0FCC105259C4E61000B67DF /* NewStatusViewController.swift in Sources */,
|
||||
|
|
|
@ -16,15 +16,16 @@ final class AddIdentityViewController: UIViewController {
|
|||
private let promptLabel = UILabel()
|
||||
private let urlTextField = UITextField()
|
||||
private let welcomeLabel = UILabel()
|
||||
private let instanceVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterial))
|
||||
private let instanceAndButtonsStackView = UIStackView()
|
||||
private let instanceStackView = UIStackView()
|
||||
private let instanceImageView = AnimatedImageView()
|
||||
private let instanceTitleLabel = UILabel()
|
||||
private let instanceURLLabel = UILabel()
|
||||
private let instanceImageView = AnimatedImageView()
|
||||
private let logInButton = UIButton(type: .system)
|
||||
private let activityIndicator = UIActivityIndicatorView()
|
||||
private let joinButton = UIButton(type: .system)
|
||||
private let browseButton = UIButton(type: .system)
|
||||
private let buttonsStackView = UIStackView()
|
||||
private let logInButton = CapsuleButton()
|
||||
private let activityIndicator = UIActivityIndicatorView(style: .large)
|
||||
private let joinButton = CapsuleButton()
|
||||
private let browseButton = CapsuleButton()
|
||||
private let whatIsMastodonButton = UIButton(type: .system)
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
|
@ -53,6 +54,7 @@ final class AddIdentityViewController: UIViewController {
|
|||
}
|
||||
|
||||
private extension AddIdentityViewController {
|
||||
static let verticalSpacing: CGFloat = 20
|
||||
static let whatIsMastodonURL = URL(string: "https://joinmastodon.org")!
|
||||
|
||||
// swiftlint:disable:next function_body_length
|
||||
|
@ -60,10 +62,10 @@ private extension AddIdentityViewController {
|
|||
scrollView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
stackView.spacing = .defaultSpacing
|
||||
stackView.spacing = Self.verticalSpacing
|
||||
stackView.axis = .vertical
|
||||
stackView.distribution = .equalSpacing
|
||||
|
||||
welcomeLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
welcomeLabel.numberOfLines = 0
|
||||
welcomeLabel.textAlignment = .center
|
||||
welcomeLabel.adjustsFontForContentSizeCategory = true
|
||||
|
@ -86,18 +88,13 @@ private extension AddIdentityViewController {
|
|||
UIAction { [weak self] _ in self?.viewModel.urlFieldText = self?.urlTextField.text ?? "" },
|
||||
for: .editingChanged)
|
||||
|
||||
logInButton.setTitle(NSLocalizedString("add-identity.log-in", comment: ""), for: .normal)
|
||||
logInButton.addAction(
|
||||
UIAction { [weak self] _ in self?.viewModel.logInTapped() },
|
||||
for: .touchUpInside)
|
||||
|
||||
activityIndicator.hidesWhenStopped = true
|
||||
|
||||
instanceVisualEffectView.translatesAutoresizingMaskIntoConstraints = false
|
||||
instanceAndButtonsStackView.spacing = .defaultSpacing
|
||||
instanceAndButtonsStackView.distribution = .fillEqually
|
||||
|
||||
instanceStackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
instanceStackView.axis = .vertical
|
||||
instanceStackView.spacing = .compactSpacing
|
||||
instanceStackView.isHidden_stackViewSafe = true
|
||||
|
||||
instanceTitleLabel.numberOfLines = 0
|
||||
instanceTitleLabel.textAlignment = .center
|
||||
|
@ -114,15 +111,25 @@ private extension AddIdentityViewController {
|
|||
instanceImageView.layer.cornerRadius = .defaultCornerRadius
|
||||
instanceImageView.clipsToBounds = true
|
||||
instanceImageView.kf.indicatorType = .activity
|
||||
instanceImageView.isHidden = true
|
||||
|
||||
buttonsStackView.axis = .vertical
|
||||
buttonsStackView.spacing = .defaultSpacing
|
||||
|
||||
activityIndicator.hidesWhenStopped = true
|
||||
|
||||
logInButton.setTitle(NSLocalizedString("add-identity.log-in", comment: ""), for: .normal)
|
||||
logInButton.addAction(
|
||||
UIAction { [weak self] _ in self?.viewModel.logInTapped() },
|
||||
for: .touchUpInside)
|
||||
|
||||
joinButton.addAction(UIAction { [weak self] _ in self?.join() }, for: .touchUpInside)
|
||||
joinButton.isHidden_stackViewSafe = true
|
||||
|
||||
browseButton.setTitle(NSLocalizedString("add-identity.browse", comment: ""), for: .normal)
|
||||
browseButton.isHidden = true
|
||||
browseButton.addAction(
|
||||
UIAction { [weak self] _ in self?.viewModel.browseTapped() },
|
||||
for: .touchUpInside)
|
||||
browseButton.isHidden_stackViewSafe = true
|
||||
|
||||
whatIsMastodonButton.setTitle(NSLocalizedString("add-identity.what-is-mastodon", comment: ""), for: .normal)
|
||||
whatIsMastodonButton.addAction(
|
||||
|
@ -131,27 +138,28 @@ private extension AddIdentityViewController {
|
|||
},
|
||||
for: .touchUpInside)
|
||||
|
||||
for button in [logInButton, browseButton, joinButton, whatIsMastodonButton] {
|
||||
button.titleLabel?.adjustsFontForContentSizeCategory = true
|
||||
button.titleLabel?.font = .preferredFont(forTextStyle: .title3)
|
||||
for button in [logInButton, joinButton, browseButton, whatIsMastodonButton] {
|
||||
button.setContentCompressionResistancePriority(.required, for: .vertical)
|
||||
}
|
||||
}
|
||||
|
||||
func setupViewHierarchy() {
|
||||
view.addSubview(welcomeLabel)
|
||||
view.addSubview(scrollView)
|
||||
scrollView.addSubview(stackView)
|
||||
stackView.addArrangedSubview(promptLabel)
|
||||
stackView.addArrangedSubview(urlTextField)
|
||||
stackView.addArrangedSubview(welcomeLabel)
|
||||
stackView.addArrangedSubview(instanceAndButtonsStackView)
|
||||
instanceStackView.addArrangedSubview(instanceImageView)
|
||||
instanceStackView.addArrangedSubview(instanceTitleLabel)
|
||||
instanceStackView.addArrangedSubview(instanceURLLabel)
|
||||
instanceVisualEffectView.contentView.addSubview(instanceStackView)
|
||||
instanceImageView.addSubview(instanceVisualEffectView)
|
||||
stackView.addArrangedSubview(instanceImageView)
|
||||
stackView.addArrangedSubview(activityIndicator)
|
||||
stackView.addArrangedSubview(logInButton)
|
||||
stackView.addArrangedSubview(joinButton)
|
||||
stackView.addArrangedSubview(browseButton)
|
||||
instanceAndButtonsStackView.addArrangedSubview(instanceStackView)
|
||||
instanceAndButtonsStackView.addArrangedSubview(buttonsStackView)
|
||||
buttonsStackView.addArrangedSubview(activityIndicator)
|
||||
buttonsStackView.addArrangedSubview(logInButton)
|
||||
buttonsStackView.addArrangedSubview(joinButton)
|
||||
buttonsStackView.addArrangedSubview(browseButton)
|
||||
buttonsStackView.addArrangedSubview(UIView())
|
||||
stackView.addArrangedSubview(whatIsMastodonButton)
|
||||
}
|
||||
|
||||
|
@ -161,6 +169,9 @@ private extension AddIdentityViewController {
|
|||
instanceImageViewWidthConstraint.priority = .justBelowMax
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
welcomeLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
welcomeLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||
welcomeLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor),
|
||||
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||
|
@ -169,16 +180,7 @@ private extension AddIdentityViewController {
|
|||
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
|
||||
stackView.widthAnchor.constraint(equalTo: scrollView.readableContentGuide.widthAnchor),
|
||||
stackView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
|
||||
instanceImageViewWidthConstraint,
|
||||
instanceVisualEffectView.leadingAnchor.constraint(equalTo: instanceImageView.leadingAnchor),
|
||||
instanceVisualEffectView.trailingAnchor.constraint(equalTo: instanceImageView.trailingAnchor),
|
||||
instanceVisualEffectView.bottomAnchor.constraint(equalTo: instanceImageView.bottomAnchor),
|
||||
instanceStackView.leadingAnchor.constraint(equalTo: instanceVisualEffectView.contentView.leadingAnchor),
|
||||
instanceStackView.topAnchor.constraint(equalTo: instanceVisualEffectView.contentView.topAnchor,
|
||||
constant: .defaultSpacing),
|
||||
instanceStackView.trailingAnchor.constraint(equalTo: instanceVisualEffectView.contentView.trailingAnchor),
|
||||
instanceStackView.bottomAnchor.constraint(equalTo: instanceVisualEffectView.contentView.bottomAnchor,
|
||||
constant: -.defaultSpacing)
|
||||
instanceImageViewWidthConstraint
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -188,21 +190,23 @@ private extension AddIdentityViewController {
|
|||
|
||||
if $0 {
|
||||
self.activityIndicator.startAnimating()
|
||||
self.logInButton.isHidden = true
|
||||
self.joinButton.isHidden = true
|
||||
self.browseButton.isHidden = true
|
||||
self.whatIsMastodonButton.isHidden = true
|
||||
self.logInButton.isHidden_stackViewSafe = true
|
||||
self.joinButton.isHidden_stackViewSafe = true
|
||||
self.browseButton.isHidden_stackViewSafe = true
|
||||
self.whatIsMastodonButton.isHidden_stackViewSafe = true
|
||||
} else {
|
||||
self.activityIndicator.stopAnimating()
|
||||
self.logInButton.isHidden = false
|
||||
self.joinButton.isHidden = !(self.viewModel.instance?.registrations ?? true)
|
||||
self.browseButton.isHidden = !self.viewModel.isPublicTimelineAvailable
|
||||
self.whatIsMastodonButton.isHidden = false
|
||||
self.logInButton.isHidden_stackViewSafe = false
|
||||
self.joinButton.isHidden_stackViewSafe = !(self.viewModel.instance?.registrations ?? false)
|
||||
self.browseButton.isHidden_stackViewSafe = !self.viewModel.isPublicTimelineAvailable
|
||||
self.whatIsMastodonButton.isHidden_stackViewSafe =
|
||||
!self.displayWelcome || self.viewModel.instance == nil
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
viewModel.$instance.combineLatest(viewModel.$isPublicTimelineAvailable)
|
||||
.throttle(for: .seconds(.defaultAnimationDuration), scheduler: DispatchQueue.main, latest: true)
|
||||
.sink { [weak self] in self?.configure(instance: $0, isPublicTimelineAvailable: $1) }
|
||||
.store(in: &cancellables)
|
||||
|
||||
|
@ -245,6 +249,8 @@ private extension AddIdentityViewController {
|
|||
UIView.animate(withDuration: .longAnimationDuration) {
|
||||
self.logInButton.alpha = 1
|
||||
} completion: { _ in
|
||||
self.whatIsMastodonButton.isHidden_stackViewSafe = false
|
||||
self.whatIsMastodonButton.alpha = 0
|
||||
UIView.animate(withDuration: .longAnimationDuration) {
|
||||
self.whatIsMastodonButton.alpha = 1
|
||||
}
|
||||
|
@ -254,39 +260,43 @@ private extension AddIdentityViewController {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
welcomeLabel.isHidden = true
|
||||
whatIsMastodonButton.isHidden = true
|
||||
welcomeLabel.isHidden_stackViewSafe = true
|
||||
whatIsMastodonButton.isHidden_stackViewSafe = true
|
||||
urlTextField.becomeFirstResponder()
|
||||
}
|
||||
}
|
||||
|
||||
func configure(instance: Instance?, isPublicTimelineAvailable: Bool) {
|
||||
if let instance = instance {
|
||||
instanceTitleLabel.text = instance.title
|
||||
instanceURLLabel.text = instance.uri
|
||||
instanceImageView.kf.setImage(with: instance.thumbnail)
|
||||
instanceImageView.isHidden = false
|
||||
UIView.animate(withDuration: .zeroIfReduceMotion(.defaultAnimationDuration)) {
|
||||
if let instance = instance {
|
||||
self.instanceTitleLabel.text = instance.title
|
||||
self.instanceURLLabel.text = instance.uri
|
||||
self.instanceImageView.kf.setImage(with: instance.thumbnail)
|
||||
self.instanceStackView.isHidden_stackViewSafe = false
|
||||
|
||||
if instance.registrations {
|
||||
let joinButtonTitle: String
|
||||
if instance.registrations {
|
||||
let joinButtonTitle: String
|
||||
|
||||
if instance.approvalRequired {
|
||||
joinButtonTitle = NSLocalizedString("add-identity.request-invite", comment: "")
|
||||
if instance.approvalRequired {
|
||||
joinButtonTitle = NSLocalizedString("add-identity.request-invite", comment: "")
|
||||
} else {
|
||||
joinButtonTitle = NSLocalizedString("add-identity.join", comment: "")
|
||||
}
|
||||
|
||||
self.joinButton.setTitle(joinButtonTitle, for: .normal)
|
||||
self.joinButton.isHidden_stackViewSafe = false
|
||||
} else {
|
||||
joinButtonTitle = NSLocalizedString("add-identity.join", comment: "")
|
||||
self.joinButton.isHidden_stackViewSafe = true
|
||||
}
|
||||
|
||||
joinButton.setTitle(joinButtonTitle, for: .normal)
|
||||
joinButton.isHidden = false
|
||||
self.browseButton.isHidden_stackViewSafe = !isPublicTimelineAvailable
|
||||
self.whatIsMastodonButton.isHidden_stackViewSafe = true
|
||||
} else {
|
||||
joinButton.isHidden = true
|
||||
self.instanceStackView.isHidden_stackViewSafe = true
|
||||
self.joinButton.isHidden_stackViewSafe = true
|
||||
self.browseButton.isHidden_stackViewSafe = true
|
||||
self.whatIsMastodonButton.isHidden_stackViewSafe = !self.displayWelcome || self.logInButton.alpha < 1
|
||||
}
|
||||
|
||||
browseButton.isHidden = !isPublicTimelineAvailable
|
||||
} else {
|
||||
instanceImageView.isHidden = true
|
||||
joinButton.isHidden = true
|
||||
browseButton.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,3 +310,16 @@ private extension AddIdentityViewController {
|
|||
show(registrationViewController, sender: self)
|
||||
}
|
||||
}
|
||||
|
||||
// http://www.openradar.me/25087688
|
||||
extension UIView {
|
||||
var isHidden_stackViewSafe: Bool {
|
||||
get { isHidden }
|
||||
set {
|
||||
if isHidden != newValue {
|
||||
isHidden = newValue
|
||||
alpha = isHidden ? 0 : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ struct AddAccountView_Previews: PreviewProvider {
|
|||
NavigationView {
|
||||
AddIdentityView(viewModelClosure: { RootViewModel.preview.addIdentityViewModel() }, displayWelcome: false)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.environmentObject(RootViewModel.preview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
49
Views/UIKit/CapsuleButton.swift
Normal file
49
Views/UIKit/CapsuleButton.swift
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright © 2021 Metabolist. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
|
||||
final class CapsuleButton: UIButton {
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
initialSetup()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
layer.cornerRadius = bounds.height / 2
|
||||
}
|
||||
|
||||
override var isHighlighted: Bool {
|
||||
didSet {
|
||||
backgroundColor = isHighlighted ? Self.highlightedColor : .link
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension CapsuleButton {
|
||||
static let highlightedColor: UIColor = {
|
||||
var hue: CGFloat = 0
|
||||
var saturation: CGFloat = 0
|
||||
var brightness: CGFloat = 0
|
||||
var alpha: CGFloat = 0
|
||||
|
||||
UIColor.link.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
|
||||
|
||||
return UIColor(hue: hue, saturation: saturation, brightness: brightness * 3 / 4, alpha: alpha)
|
||||
}()
|
||||
|
||||
func initialSetup() {
|
||||
backgroundColor = .link
|
||||
titleLabel?.adjustsFontForContentSizeCategory = true
|
||||
titleLabel?.font = .preferredFont(forTextStyle: .headline)
|
||||
setTitleColor(.white, for: .normal)
|
||||
setTitleColor(.lightText, for: .highlighted)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue