Add video and link to joinmastodon.org communities for new users

This commit is contained in:
Justin Mazzocchi 2021-04-04 23:21:23 -07:00
parent 841d9e2926
commit 0811bf7274
No known key found for this signature in database
GPG Key ID: E223E6937AAFB01C
4 changed files with 150 additions and 18 deletions

View File

@ -68,6 +68,7 @@
"app-icon.rainbow-brutalist" = "Rainbow Brutalist";
"app-icon.classic" = "Classic";
"app-icon.rainbow" = "Rainbow";
"add-identity.get-started" = "Get started";
"add-identity.instance-url" = "Instance URL";
"add-identity.log-in" = "Log in";
"add-identity.browse" = "Browse";

View File

@ -228,6 +228,7 @@
D0F4362D25C10B9600E4F896 /* AddIdentityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F4362C25C10B9600E4F896 /* AddIdentityViewController.swift */; };
D0FCC105259C4E61000B67DF /* NewStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FCC104259C4E61000B67DF /* NewStatusViewController.swift */; };
D0FCC106259C4E62000B67DF /* NewStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FCC104259C4E61000B67DF /* NewStatusViewController.swift */; };
D0FCD6AD261AB2DD00113701 /* InstancePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FCD6AC261AB2DD00113701 /* InstancePickerViewController.swift */; };
D0FE1C8F253686F9003EF1EB /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FE1C8E253686F9003EF1EB /* PlayerView.swift */; };
D0FE1C9825368A9D003EF1EB /* PlayerCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FE1C9725368A9D003EF1EB /* PlayerCache.swift */; };
D0FE7C8025C4C79F00203957 /* PreviewViewModels in Frameworks */ = {isa = PBXBuildFile; productRef = D0FE7C7F25C4C79F00203957 /* PreviewViewModels */; };
@ -469,6 +470,7 @@
D0F0B135251AA12700942152 /* CollectionItem+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CollectionItem+Extensions.swift"; sourceTree = "<group>"; };
D0F4362C25C10B9600E4F896 /* AddIdentityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddIdentityViewController.swift; sourceTree = "<group>"; };
D0FCC104259C4E61000B67DF /* NewStatusViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewStatusViewController.swift; sourceTree = "<group>"; };
D0FCD6AC261AB2DD00113701 /* InstancePickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancePickerViewController.swift; sourceTree = "<group>"; };
D0FE1C8E253686F9003EF1EB /* PlayerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerView.swift; sourceTree = "<group>"; };
D0FE1C9725368A9D003EF1EB /* PlayerCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerCache.swift; sourceTree = "<group>"; };
D9E658692601CF76007C426E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -803,6 +805,7 @@
D08B8D49253FC36500B1EBEF /* ImageNavigationController.swift */,
D08B8D41253F92B600B1EBEF /* ImagePageViewController.swift */,
D08B8D3C253F929E00B1EBEF /* ImageViewController.swift */,
D0FCD6AC261AB2DD00113701 /* InstancePickerViewController.swift */,
D035F86825B7F2ED00DC75ED /* MainNavigationViewController.swift */,
D0FCC104259C4E61000B67DF /* NewStatusViewController.swift */,
D097F4C025BFA04C00859F2C /* NotificationsViewController.swift */,
@ -1240,6 +1243,7 @@
D00702312555F4AE00F38136 /* ConversationView.swift in Sources */,
D0BEB21124FA2A91001B0F04 /* EditFilterView.swift in Sources */,
D08B8D4A253FC36500B1EBEF /* ImageNavigationController.swift in Sources */,
D0FCD6AD261AB2DD00113701 /* InstancePickerViewController.swift in Sources */,
D0070252255921B100F38136 /* AccountFieldView.swift in Sources */,
D0030982250C6C8500EACB32 /* URL+Extensions.swift in Sources */,
D0BE97A325CF44310057E161 /* CGRect+Extensions.swift in Sources */,

View File

@ -2,10 +2,10 @@
import Combine
import Mastodon
import SafariServices
import SDWebImage
import SwiftUI
import ViewModels
import WebKit
final class AddIdentityViewController: UIViewController {
private let viewModel: AddIdentityViewModel
@ -26,7 +26,11 @@ final class AddIdentityViewController: UIViewController {
private let activityIndicator = UIActivityIndicatorView(style: .large)
private let joinButton = CapsuleButton()
private let browseButton = CapsuleButton()
private let whatIsMastodonButton = UIButton(type: .system)
private let whatIsMastodonBackgroundView = UIView()
private let whatIsMastodonStackView = UIStackView()
private let whatIsMastodonLabel = UILabel()
private let whatIsMastodonVideoView: WKWebView
private let getStartedButton = CapsuleButton()
private var cancellables = Set<AnyCancellable>()
init(viewModel: AddIdentityViewModel, rootViewModel: RootViewModel, displayWelcome: Bool) {
@ -34,6 +38,12 @@ final class AddIdentityViewController: UIViewController {
self.rootViewModel = rootViewModel
self.displayWelcome = displayWelcome
let configuration = WKWebViewConfiguration()
configuration.allowsInlineMediaPlayback = true
whatIsMastodonVideoView = WKWebView(frame: .zero, configuration: configuration)
super.init(nibName: nil, bundle: nil)
}
@ -55,7 +65,7 @@ final class AddIdentityViewController: UIViewController {
private extension AddIdentityViewController {
static let verticalSpacing: CGFloat = 20
static let whatIsMastodonURL = URL(string: "https://joinmastodon.org")!
static let whatIsMastodonVideoURL = URL(string: "https://www.youtube.com/embed/IPSbNdBmWKE?playsinline=1")!
// swiftlint:disable:next function_body_length
func configureViews() {
@ -134,14 +144,40 @@ private extension AddIdentityViewController {
for: .touchUpInside)
browseButton.isHidden_stackViewSafe = true
whatIsMastodonButton.setTitle(NSLocalizedString("add-identity.what-is-mastodon", comment: ""), for: .normal)
whatIsMastodonButton.addAction(
whatIsMastodonBackgroundView.backgroundColor = .secondarySystemBackground
whatIsMastodonBackgroundView.clipsToBounds = true
whatIsMastodonBackgroundView.layer.cornerRadius = .defaultCornerRadius
whatIsMastodonStackView.translatesAutoresizingMaskIntoConstraints = false
whatIsMastodonStackView.axis = .vertical
whatIsMastodonStackView.spacing = .defaultSpacing * 2
whatIsMastodonLabel.adjustsFontForContentSizeCategory = true
whatIsMastodonLabel.font = .preferredFont(forTextStyle: .headline)
whatIsMastodonLabel.textAlignment = .center
whatIsMastodonLabel.text = NSLocalizedString("add-identity.what-is-mastodon", comment: "")
getStartedButton.setTitle(NSLocalizedString("add-identity.get-started", comment: ""), for: .normal)
getStartedButton.addAction(
UIAction { [weak self] _ in
self?.present(SFSafariViewController(url: Self.whatIsMastodonURL), animated: true)
self?.urlTextField.resignFirstResponder()
self?.present(
UINavigationController(rootViewController: InstancePickerViewController {
self?.viewModel.urlFieldText = $1
self?.urlTextField.text = $1
self?.urlTextField.becomeFirstResponder()
self?.dismiss(animated: true)
}),
animated: true)
},
for: .touchUpInside)
for button in [logInButton, joinButton, browseButton, whatIsMastodonButton] {
whatIsMastodonVideoView.scrollView.isScrollEnabled = false
whatIsMastodonVideoView.clipsToBounds = true
whatIsMastodonVideoView.layer.cornerRadius = .defaultCornerRadius
whatIsMastodonVideoView.load(.init(url: Self.whatIsMastodonVideoURL))
for button in [logInButton, joinButton, browseButton] {
button.setContentCompressionResistancePriority(.required, for: .vertical)
}
}
@ -163,7 +199,11 @@ private extension AddIdentityViewController {
buttonsStackView.addArrangedSubview(joinButton)
buttonsStackView.addArrangedSubview(browseButton)
buttonsStackView.addArrangedSubview(UIView())
stackView.addArrangedSubview(whatIsMastodonButton)
stackView.addArrangedSubview(whatIsMastodonBackgroundView)
whatIsMastodonBackgroundView.addSubview(whatIsMastodonStackView)
whatIsMastodonStackView.addArrangedSubview(whatIsMastodonLabel)
whatIsMastodonStackView.addArrangedSubview(whatIsMastodonVideoView)
whatIsMastodonStackView.addArrangedSubview(getStartedButton)
}
func setupConstraints() {
@ -183,7 +223,17 @@ private extension AddIdentityViewController {
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
stackView.widthAnchor.constraint(equalTo: scrollView.readableContentGuide.widthAnchor),
stackView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
instanceImageViewWidthConstraint
instanceImageViewWidthConstraint,
whatIsMastodonStackView.leadingAnchor.constraint(equalTo: whatIsMastodonBackgroundView.leadingAnchor,
constant: .defaultSpacing * 2),
whatIsMastodonStackView.topAnchor.constraint(equalTo: whatIsMastodonBackgroundView.topAnchor,
constant: .defaultSpacing * 2),
whatIsMastodonStackView.trailingAnchor.constraint(equalTo: whatIsMastodonBackgroundView.trailingAnchor,
constant: -.defaultSpacing * 2),
whatIsMastodonStackView.bottomAnchor.constraint(equalTo: whatIsMastodonBackgroundView.bottomAnchor,
constant: -.defaultSpacing * 2),
whatIsMastodonVideoView.widthAnchor.constraint(equalTo: whatIsMastodonVideoView.heightAnchor,
multiplier: 16 / 9)
])
}
@ -213,7 +263,7 @@ private extension AddIdentityViewController {
promptLabel.alpha = 0
urlTextField.alpha = 0
logInButton.alpha = 0
whatIsMastodonButton.alpha = 0
whatIsMastodonBackgroundView.alpha = 0
UIView.animate(withDuration: .longAnimationDuration * 2) {
self.welcomeLabel.alpha = 1
@ -228,14 +278,13 @@ private extension AddIdentityViewController {
UIView.animate(withDuration: .longAnimationDuration) {
self.urlTextField.alpha = 1
} completion: { _ in
self.urlTextField.becomeFirstResponder()
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
self.whatIsMastodonBackgroundView.alpha = 1
} completion: { _ in
self.urlTextField.becomeFirstResponder()
}
}
}
@ -244,7 +293,6 @@ private extension AddIdentityViewController {
}
} else {
welcomeLabel.isHidden_stackViewSafe = true
whatIsMastodonButton.isHidden_stackViewSafe = !displayWelcome
urlTextField.becomeFirstResponder()
}
}
@ -281,13 +329,10 @@ private extension AddIdentityViewController {
}
self.browseButton.isHidden_stackViewSafe = !isPublicTimelineAvailable || loading
self.whatIsMastodonButton.isHidden_stackViewSafe = true
} else {
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 || loading
}
}
}

View File

@ -0,0 +1,82 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Combine
import UIKit
import WebKit
final class InstancePickerViewController: UIViewController {
private let selectionAction: (InstancePickerViewController, String) -> Void
private let webView: WKWebView
private let backButton: UIBarButtonItem
private let forwardButton: UIBarButtonItem
private var cancellables = Set<AnyCancellable>()
init(selectionAction: @escaping (InstancePickerViewController, String) -> Void) {
let webView = WKWebView()
webView.allowsBackForwardNavigationGestures = true
self.webView = webView
self.selectionAction = selectionAction
backButton = UIBarButtonItem(title: nil, image: UIImage(systemName: "chevron.backward"),
primaryAction: UIAction { _ in webView.goBack() })
forwardButton = UIBarButtonItem(title: nil, image: UIImage(systemName: "chevron.forward"),
primaryAction: UIAction { _ in webView.goForward() })
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
view = webView
webView.navigationDelegate = self
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(
systemItem: .done,
primaryAction: UIAction { [weak self] _ in self?.presentingViewController?.dismiss(animated: true) })
navigationItem.rightBarButtonItems = [forwardButton, backButton]
webView.publisher(for: \.canGoBack)
.sink { [weak self] in self?.backButton.isEnabled = $0 }
.store(in: &cancellables)
webView.publisher(for: \.canGoForward)
.sink { [weak self] in self?.forwardButton.isEnabled = $0 }
.store(in: &cancellables)
webView.publisher(for: \.title)
.sink { [weak self] in self?.navigationItem.title = $0 }
.store(in: &cancellables)
webView.load(.init(url: Self.url))
}
}
extension InstancePickerViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
preferences: WKWebpagePreferences,
decisionHandler: @escaping (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {
if webView.url?.host == "joinmastodon.org",
let url = navigationAction.request.url,
let host = url.host,
host != "joinmastodon.org",
url.pathComponents == ["/", "about"] {
decisionHandler(.cancel, preferences)
selectionAction(self, host)
} else {
decisionHandler(.allow, preferences)
}
}
}
private extension InstancePickerViewController {
static let url = URL(string: "https://joinmastodon.org/communities")!
}