Remove wizard (IOS-135) (#995)

This commit is contained in:
Nathan Mattes 2023-03-28 21:36:32 +02:00 committed by GitHub
parent b7508f8fb6
commit eb826fb310
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 0 additions and 547 deletions

View File

@ -825,14 +825,8 @@
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
},
"bookmark": {
"title": "Bookmarks"
},
"followed_tags": {
"title": "Followed Tags",

View File

@ -247,7 +247,6 @@
DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */; };
DB47AB6227CF752B00CD73C7 /* MastodonUISnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB47AB6127CF752B00CD73C7 /* MastodonUISnapshotTests.swift */; };
DB482A3F261331E8008AE74C /* UserTimelineViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB482A3E261331E8008AE74C /* UserTimelineViewModel+State.swift */; };
DB4932B126F1FB5300EF46D4 /* WizardCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4932B026F1FB5300EF46D4 /* WizardCardView.swift */; };
DB4932B926F31AD300EF46D4 /* BadgeButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4932B826F31AD300EF46D4 /* BadgeButton.swift */; };
DB4AA6B327BA34B6009EC082 /* CellFrameCacheContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4AA6B227BA34B6009EC082 /* CellFrameCacheContainer.swift */; };
DB4F0963269ED06300D62E92 /* SearchResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4F0962269ED06300D62E92 /* SearchResultViewController.swift */; };
@ -314,7 +313,6 @@
DB6746EB278ED8B0008A6B94 /* PollOptionView+Configuration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6746EA278ED8B0008A6B94 /* PollOptionView+Configuration.swift */; };
DB6746ED278F45F0008A6B94 /* AutoGenerateProtocolRelayDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6746EC278F45F0008A6B94 /* AutoGenerateProtocolRelayDelegate.swift */; };
DB6746F0278F463B008A6B94 /* AutoGenerateProtocolDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6746EF278F463B008A6B94 /* AutoGenerateProtocolDelegate.swift */; };
DB67D08627312E67006A36CF /* WizardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB67D08527312E67006A36CF /* WizardViewController.swift */; };
DB6804662636DC9000430867 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D939AB425EDD8A90076FA61 /* String.swift */; };
DB68586425E619B700F0A850 /* NSKeyValueObservation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68586325E619B700F0A850 /* NSKeyValueObservation.swift */; };
DB68A04A25E9027700CFDF14 /* AdaptiveStatusBarStyleNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB68A04925E9027700CFDF14 /* AdaptiveStatusBarStyleNavigationController.swift */; };
@ -904,7 +902,6 @@
DB47AB6127CF752B00CD73C7 /* MastodonUISnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonUISnapshotTests.swift; sourceTree = "<group>"; };
DB47AB6327CF858400CD73C7 /* AppStoreSnapshotTestPlan.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = AppStoreSnapshotTestPlan.xctestplan; sourceTree = "<group>"; };
DB482A3E261331E8008AE74C /* UserTimelineViewModel+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserTimelineViewModel+State.swift"; sourceTree = "<group>"; };
DB4932B026F1FB5300EF46D4 /* WizardCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardCardView.swift; sourceTree = "<group>"; };
DB4932B826F31AD300EF46D4 /* BadgeButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeButton.swift; sourceTree = "<group>"; };
DB4AA6B227BA34B6009EC082 /* CellFrameCacheContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellFrameCacheContainer.swift; sourceTree = "<group>"; };
DB4B777F26CA4EFA00B087B3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Intents.strings; sourceTree = "<group>"; };
@ -1000,7 +997,6 @@
DB6746EA278ED8B0008A6B94 /* PollOptionView+Configuration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PollOptionView+Configuration.swift"; sourceTree = "<group>"; };
DB6746EC278F45F0008A6B94 /* AutoGenerateProtocolRelayDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoGenerateProtocolRelayDelegate.swift; sourceTree = "<group>"; };
DB6746EF278F463B008A6B94 /* AutoGenerateProtocolDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoGenerateProtocolDelegate.swift; sourceTree = "<group>"; };
DB67D08527312E67006A36CF /* WizardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardViewController.swift; sourceTree = "<group>"; };
DB68053E2638011000430867 /* NotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NotificationService.entitlements; sourceTree = "<group>"; };
DB68586325E619B700F0A850 /* NSKeyValueObservation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSKeyValueObservation.swift; sourceTree = "<group>"; };
DB68A04925E9027700CFDF14 /* AdaptiveStatusBarStyleNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveStatusBarStyleNavigationController.swift; sourceTree = "<group>"; };
@ -2360,14 +2356,6 @@
path = Template;
sourceTree = "<group>";
};
DB67D08727312E6A006A36CF /* Wizard */ = {
isa = PBXGroup;
children = (
DB67D08527312E67006A36CF /* WizardViewController.swift */,
);
path = Wizard;
sourceTree = "<group>";
};
DB68A03825E900CC00CFDF14 /* Share */ = {
isa = PBXGroup;
children = (
@ -2522,7 +2510,6 @@
DB6180E426391A500018D199 /* Transition */,
DB852D1D26FB021900FC9D81 /* Root */,
DB01409B25C40BB600F9F3CF /* Onboarding */,
DB67D08727312E6A006A36CF /* Wizard */,
DB9F58ED26EF435800E7BBE9 /* Account */,
2D38F1D325CD463600561493 /* HomeTimeline */,
0F2021F5261325ED000C64BF /* HashtagTimeline */,
@ -2775,7 +2762,6 @@
children = (
D8A6FE5929323DC200666A47 /* Pages */,
DBABE3EB25ECAC4B00879EE5 /* WelcomeIllustrationView.swift */,
DB4932B026F1FB5300EF46D4 /* WizardCardView.swift */,
DB0617EA277EF3820030EE79 /* GradientBorderView.swift */,
);
path = View;
@ -3745,7 +3731,6 @@
5B90C45F262599800002E742 /* SettingsToggleTableViewCell.swift in Sources */,
2D694A7425F9EB4E0038ADDC /* ContentWarningOverlayView.swift in Sources */,
DB0FCB7827957678006C02E2 /* DataSourceProvider+UITableViewDelegate.swift in Sources */,
DB4932B126F1FB5300EF46D4 /* WizardCardView.swift in Sources */,
DB9A486C26032AC1008B817C /* AttachmentContainerView+EmptyStateView.swift in Sources */,
5D0393902612D259007FE196 /* WebViewController.swift in Sources */,
DB98EB6227B215EB0082E365 /* ReportResultViewController.swift in Sources */,
@ -3903,7 +3888,6 @@
DBB45B5627B39FC9002DC5A7 /* MediaPreviewVideoViewController.swift in Sources */,
D8A6AB6C291C5136003AB663 /* MastodonLoginViewController.swift in Sources */,
DB0FCB8027968F70006C02E2 /* MastodonStatusThreadViewModel.swift in Sources */,
DB67D08627312E67006A36CF /* WizardViewController.swift in Sources */,
DB6746EB278ED8B0008A6B94 /* PollOptionView+Configuration.swift in Sources */,
DB0F9D54283EB3C000379AF8 /* ProfileHeaderView+ViewModel.swift in Sources */,
2A3F6FE3292ECB5E002E6DA7 /* FollowedTagsViewModel.swift in Sources */,

View File

@ -28,7 +28,6 @@ final public class SceneCoordinator {
private(set) weak var tabBarController: MainTabBarController!
private(set) weak var splitViewController: RootSplitViewController?
private(set) var wizardViewController: WizardViewController?
private(set) var secondaryStackHashValues = Set<Int>()
@ -249,19 +248,6 @@ extension SceneCoordinator {
transition: .modal(animated: true, completion: nil)
)
}
} else {
let wizardViewController = WizardViewController()
if !wizardViewController.items.isEmpty,
let delegate = rootViewController as? WizardViewControllerDelegate
{
// do not add as child view controller.
// otherwise, the tab bar controller will add as a new tab
wizardViewController.delegate = delegate
wizardViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
wizardViewController.view.frame = rootViewController.view.bounds
rootViewController.view.addSubview(wizardViewController.view)
self.wizardViewController = wizardViewController
}
}
} catch {

View File

@ -1,143 +0,0 @@
//
// WizardCardView.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-9-15.
//
import UIKit
import MastodonAsset
import MastodonLocalization
final class WizardCardView: UIView {
static let bubbleArrowHeight: CGFloat = 17
static let bubbleArrowWidth: CGFloat = 20
let contentView = UIView()
let backgroundShapeLayer = CAShapeLayer()
var arrowRectCorner: UIRectCorner = .bottomRight
let titleLabel: UILabel = {
let label = UILabel()
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold))
label.textColor = .black
return label
}()
let descriptionLabel: UILabel = {
let label = UILabel()
label.font = UIFontMetrics(forTextStyle: .subheadline).scaledFont(for: .systemFont(ofSize: 13, weight: .regular))
label.textColor = .black
label.numberOfLines = 0
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
_init()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
_init()
}
}
extension WizardCardView {
private func _init() {
layer.masksToBounds = false
layer.addSublayer(backgroundShapeLayer)
contentView.translatesAutoresizingMaskIntoConstraints = false
addSubview(contentView)
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: topAnchor, constant: WizardCardView.bubbleArrowHeight),
contentView.leadingAnchor.constraint(equalTo: leadingAnchor),
trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: WizardCardView.bubbleArrowHeight),
])
let containerStackView = UIStackView()
containerStackView.axis = .vertical
containerStackView.spacing = 2
containerStackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5),
containerStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 7),
contentView.trailingAnchor.constraint(equalTo: containerStackView.trailingAnchor, constant: 24),
contentView.bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor, constant: 5),
])
containerStackView.addArrangedSubview(titleLabel)
containerStackView.addArrangedSubview(descriptionLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
let radius: CGFloat = 5
let rect = contentView.frame
let path = UIBezierPath()
switch arrowRectCorner {
case .bottomRight:
path.move(to: CGPoint(x: rect.maxX - WizardCardView.bubbleArrowWidth, y: rect.maxY + radius))
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.maxY), radius: radius, startAngle: .pi / 2, endAngle: .pi, clockwise: true)
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.minY), radius: radius, startAngle: .pi, endAngle: .pi / 2 * 3, clockwise: true)
path.addArc(withCenter: CGPoint(x: rect.maxX, y: rect.minY), radius: radius, startAngle: .pi / 2 * 3, endAngle: .pi * 2, clockwise: true)
path.addLine(to: CGPoint(x: rect.maxX + radius, y: rect.maxY + radius + WizardCardView.bubbleArrowHeight))
path.close()
case .bottomLeft:
path.move(to: CGPoint(x: rect.minX + WizardCardView.bubbleArrowWidth, y: rect.maxY + radius))
path.addArc(withCenter: CGPoint(x: rect.maxX, y: rect.maxY), radius: radius, startAngle: .pi / 2, endAngle: 0, clockwise: false)
path.addArc(withCenter: CGPoint(x: rect.maxX, y: rect.minY), radius: radius, startAngle: 0, endAngle: -.pi / 2, clockwise: false)
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.minY), radius: radius, startAngle: -.pi / 2, endAngle: -.pi, clockwise: false)
path.addLine(to: CGPoint(x: rect.minX - radius, y: rect.maxY + radius + WizardCardView.bubbleArrowHeight))
path.close()
case .allCorners: // no arrow
path.move(to: CGPoint(x: rect.maxX, y: rect.maxY + radius))
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.maxY), radius: radius, startAngle: .pi / 2, endAngle: .pi, clockwise: true)
path.addArc(withCenter: CGPoint(x: rect.minX, y: rect.minY), radius: radius, startAngle: .pi, endAngle: .pi / 2 * 3, clockwise: true)
path.addArc(withCenter: CGPoint(x: rect.maxX, y: rect.minY), radius: radius, startAngle: .pi / 2 * 3, endAngle: .pi * 2, clockwise: true)
path.addArc(withCenter: CGPoint(x: rect.maxX, y: rect.maxY), radius: radius, startAngle: .pi * 2, endAngle: .pi / 2 * 5, clockwise: true)
path.close()
default:
assertionFailure("FIXME")
}
backgroundShapeLayer.lineCap = .round
backgroundShapeLayer.lineJoin = .round
backgroundShapeLayer.lineWidth = 3
backgroundShapeLayer.strokeColor = UIColor.white.cgColor
backgroundShapeLayer.fillColor = UIColor.white.cgColor
backgroundShapeLayer.path = path.cgPath
}
override var isAccessibilityElement: Bool {
get { true }
set { }
}
override var accessibilityLabel: String? {
get {
return [
titleLabel.text,
descriptionLabel.text
]
.compactMap { $0 }
.joined(separator: " ")
}
set { }
}
override var accessibilityHint: String? {
get {
return L10n.Scene.Wizard.accessibilityHint
}
set { }
}
}

View File

@ -544,60 +544,6 @@ extension MainTabBarController: UITabBarControllerDelegate {
}
}
// MARK: - WizardViewControllerDelegate
extension MainTabBarController: WizardViewControllerDelegate {
func readyToLayoutItem(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> Bool {
switch item {
case .multipleAccountSwitch:
return isReadyForWizardAvatarButton
}
}
func layoutSpotlight(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> UIBezierPath {
switch item {
case .multipleAccountSwitch:
guard let avatarButtonFrameInView = avatarButtonFrameInWizardView(wizardView: wizardViewController.view) else {
return UIBezierPath()
}
return UIBezierPath(ovalIn: avatarButtonFrameInView)
}
}
func layoutWizardCard(_ wizardViewController: WizardViewController, item: WizardViewController.Item) {
switch item {
case .multipleAccountSwitch:
guard let avatarButtonFrameInView = avatarButtonFrameInWizardView(wizardView: wizardViewController.view) else {
return
}
let anchorView = UIView()
anchorView.frame = avatarButtonFrameInView
wizardViewController.backgroundView.addSubview(anchorView)
let wizardCardView = WizardCardView()
wizardCardView.arrowRectCorner = view.traitCollection.layoutDirection == .leftToRight ? .bottomRight : .bottomLeft
wizardCardView.titleLabel.text = item.title
wizardCardView.descriptionLabel.text = item.description
wizardCardView.translatesAutoresizingMaskIntoConstraints = false
wizardViewController.backgroundView.addSubview(wizardCardView)
NSLayoutConstraint.activate([
anchorView.topAnchor.constraint(equalTo: wizardCardView.bottomAnchor, constant: 13), // 13pt spacing
wizardCardView.trailingAnchor.constraint(equalTo: anchorView.centerXAnchor),
wizardCardView.widthAnchor.constraint(equalTo: wizardViewController.view.widthAnchor, multiplier: 2.0/3.0).priority(.required - 1),
])
wizardCardView.setContentHuggingPriority(.defaultLow, for: .vertical)
}
}
private func avatarButtonFrameInWizardView(wizardView: UIView) -> CGRect? {
guard let superview = avatarButton.superview else {
assertionFailure()
return nil
}
return superview.convert(avatarButton.frame, to: wizardView)
}
}
// HIG: keyboard UX
// https://developer.apple.com/design/human-interface-guidelines/macos/user-interaction/keyboard/
extension MainTabBarController {

View File

@ -255,90 +255,3 @@ extension RootSplitViewController: UISplitViewControllerDelegate {
}
}
// MARK: - WizardViewControllerDelegate
extension RootSplitViewController: WizardViewControllerDelegate {
func readyToLayoutItem(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> Bool {
guard traitCollection.horizontalSizeClass != .compact else {
return compactMainTabBarViewController.readyToLayoutItem(wizardViewController, item: item)
}
switch item {
case .multipleAccountSwitch:
return contentSplitViewController.sidebarViewController.viewModel.isReadyForWizardAvatarButton
}
}
func layoutSpotlight(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> UIBezierPath {
guard traitCollection.horizontalSizeClass != .compact else {
return compactMainTabBarViewController.layoutSpotlight(wizardViewController, item: item)
}
switch item {
case .multipleAccountSwitch:
guard let frame = avatarButtonFrameInWizardView(wizardView: wizardViewController.view)
else {
assertionFailure()
return UIBezierPath()
}
return UIBezierPath(ovalIn: frame)
}
}
func layoutWizardCard(_ wizardViewController: WizardViewController, item: WizardViewController.Item) {
guard traitCollection.horizontalSizeClass != .compact else {
return compactMainTabBarViewController.layoutWizardCard(wizardViewController, item: item)
}
guard let frame = avatarButtonFrameInWizardView(wizardView: wizardViewController.view) else {
return
}
let anchorView = UIView()
anchorView.frame = frame
wizardViewController.backgroundView.addSubview(anchorView)
let wizardCardView = WizardCardView()
wizardCardView.arrowRectCorner = .allCorners // no arrow
wizardCardView.titleLabel.text = item.title
wizardCardView.descriptionLabel.text = item.description
wizardCardView.translatesAutoresizingMaskIntoConstraints = false
wizardViewController.backgroundView.addSubview(wizardCardView)
NSLayoutConstraint.activate([
wizardCardView.centerYAnchor.constraint(equalTo: anchorView.centerYAnchor),
wizardCardView.leadingAnchor.constraint(equalTo: anchorView.trailingAnchor, constant: 20), // 20pt spacing
wizardCardView.widthAnchor.constraint(equalToConstant: 320),
])
wizardCardView.setContentHuggingPriority(.defaultLow, for: .vertical)
}
private func avatarButtonFrameInWizardView(wizardView: UIView) -> CGRect? {
guard let diffableDataSource = contentSplitViewController.sidebarViewController.viewModel.diffableDataSource,
let indexPath = diffableDataSource.indexPath(for: .tab(.me)),
let cell = contentSplitViewController.sidebarViewController.collectionView.cellForItem(at: indexPath) as? SidebarListCollectionViewCell,
let contentView = cell._contentView,
let frame = sourceViewFrameInTargetView(
sourceView: contentView.avatarButton,
targetView: wizardView
)
else {
assertionFailure()
return nil
}
return frame
}
private func sourceViewFrameInTargetView(
sourceView: UIView,
targetView: UIView
) -> CGRect? {
guard let superview = sourceView.superview else {
assertionFailure()
return nil
}
return superview.convert(sourceView.frame, to: targetView)
}
}

View File

@ -1,213 +0,0 @@
//
// WizardViewController.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-11-2.
//
import os.log
import UIKit
import Combine
import MastodonAsset
import MastodonLocalization
protocol WizardViewControllerDelegate: AnyObject {
func readyToLayoutItem(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> Bool
func layoutSpotlight(_ wizardViewController: WizardViewController, item: WizardViewController.Item) -> UIBezierPath
func layoutWizardCard(_ wizardViewController: WizardViewController, item: WizardViewController.Item)
}
class WizardViewController: UIViewController {
let logger = Logger(subsystem: "Wizard", category: "UI")
var disposeBag = Set<AnyCancellable>()
weak var delegate: WizardViewControllerDelegate?
private(set) var items: [Item] = {
var items: [Item] = []
if !UserDefaults.shared.didShowMultipleAccountSwitchWizard {
items.append(.multipleAccountSwitch)
}
return items
}()
let pendingItem = CurrentValueSubject<Item?, Never>(nil)
let currentItem = CurrentValueSubject<Item?, Never>(nil)
let backgroundView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
return view
}()
deinit {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
}
}
extension WizardViewController {
override func viewDidLoad() {
super.viewDidLoad()
setup()
let backgroundTapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer
backgroundTapGestureRecognizer.addTarget(self, action: #selector(WizardViewController.backgroundTapGestureRecognizerHandler(_:)))
backgroundView.addGestureRecognizer(backgroundTapGestureRecognizer)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Create a timer to consume pending item
Timer.publish(every: 0.5, on: .main, in: .default)
.autoconnect()
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
guard let self = self else { return }
guard self.pendingItem.value != nil else { return }
self.consume()
}
.store(in: &disposeBag)
consume()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
invalidLayoutForCurrentItem()
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate { context in
} completion: { [weak self] context in
guard let self = self else { return }
self.invalidLayoutForCurrentItem()
}
}
}
extension WizardViewController {
enum Item {
case multipleAccountSwitch
var title: String {
return L10n.Scene.Wizard.newInMastodon
}
var description: String {
switch self {
case .multipleAccountSwitch:
return L10n.Scene.Wizard.multipleAccountSwitchIntroDescription
}
}
func markAsRead() {
switch self {
case .multipleAccountSwitch:
UserDefaults.shared.didShowMultipleAccountSwitchWizard = true
}
}
}
}
extension WizardViewController {
func setup() {
assert(delegate != nil, "need set delegate before use")
guard !items.isEmpty else { return }
backgroundView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
backgroundView.frame = view.bounds
view.addSubview(backgroundView)
}
func destroy() {
view.removeFromSuperview()
}
func consume() {
guard !items.isEmpty else {
destroy()
return
}
guard let first = items.first else { return }
guard delegate?.readyToLayoutItem(self, item: first) == true else {
pendingItem.value = first
return
}
pendingItem.value = nil
currentItem.value = nil
let item = items.removeFirst()
perform(item: item)
}
private func perform(item: Item) {
guard let delegate = delegate else {
assertionFailure()
return
}
// prepare for reuse
prepareForReuse()
// set wizard item read
item.markAsRead()
// add spotlight
let spotlight = delegate.layoutSpotlight(self, item: item)
let maskLayer = CAShapeLayer()
// expand rect to make sure view always fill the screen when device rotate
let expandRect: CGRect = {
var rect = backgroundView.bounds
rect.size.width *= 2
rect.size.height *= 2
return rect
}()
let path = UIBezierPath(rect: expandRect)
path.append(spotlight)
maskLayer.fillRule = .evenOdd
maskLayer.path = path.cgPath
backgroundView.layer.mask = maskLayer
// layout wizard card
delegate.layoutWizardCard(self, item: item)
currentItem.value = item
}
private func prepareForReuse() {
backgroundView.subviews.forEach { subview in
subview.removeFromSuperview()
}
backgroundView.mask = nil
backgroundView.layer.mask = nil
}
private func invalidLayoutForCurrentItem() {
if let item = currentItem.value {
perform(item: item)
}
}
}
extension WizardViewController {
@objc private func backgroundTapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
consume()
}
}

View File

@ -1530,14 +1530,6 @@ public enum L10n {
}
}
}
public enum Wizard {
/// Double tap to dismiss this wizard
public static let accessibilityHint = L10n.tr("Localizable", "Scene.Wizard.AccessibilityHint", fallback: "Double tap to dismiss this wizard")
/// Switch between multiple accounts by holding the profile button.
public static let multipleAccountSwitchIntroDescription = L10n.tr("Localizable", "Scene.Wizard.MultipleAccountSwitchIntroDescription", fallback: "Switch between multiple accounts by holding the profile button.")
/// New in Mastodon
public static let newInMastodon = L10n.tr("Localizable", "Scene.Wizard.NewInMastodon", fallback: "New in Mastodon")
}
}
public enum Widget {
public enum Common {

View File

@ -535,9 +535,6 @@ You can still send and receive emails from anyone, even if their email ends in @
"Scene.Welcome.LogIn" = "Log In";
"Scene.Welcome.Slogan" = "Social networking
back in your hands.";
"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard";
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button.";
"Scene.Wizard.NewInMastodon" = "New in Mastodon";
"Widget.Common.UnsupportedWidgetFamily" = "Sorry but this Widget family is unsupported.";
"Widget.Common.UserNotLoggedIn" = "Please open Mastodon to log in to an Account.";
"Widget.FollowersCount.ConfigurationDescription" = "Show number of followers.";

View File

@ -535,9 +535,6 @@ You can still send and receive emails from anyone, even if their email ends in @
"Scene.Welcome.LogIn" = "Log In";
"Scene.Welcome.Slogan" = "Social networking
back in your hands.";
"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard";
"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button.";
"Scene.Wizard.NewInMastodon" = "New in Mastodon";
"Widget.Common.UnsupportedWidgetFamily" = "Sorry but this Widget family is unsupported.";
"Widget.Common.UserNotLoggedIn" = "Please open Mastodon to log in to an Account.";
"Widget.FollowersCount.ConfigurationDescription" = "Show number of followers.";