Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class BlogDashboardViewModel {
case .migrationSuccess:
let cellType = DashboardMigrationSuccessCell.self
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.defaultReuseID, for: indexPath) as? DashboardMigrationSuccessCell
cell?.configure(with: viewController)
return cell
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N

if (section.category == BlogDetailsSectionCategoryMigrationSuccess && MigrationSuccessCardView.shouldShowMigrationSuccessCard == YES) {
MigrationSuccessCell *cell = [tableView dequeueReusableCellWithIdentifier:BlogDetailsMigrationSuccessCellIdentifier];
[cell configureWithViewController:self];
return cell;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Foundation

struct MigrationHelper {
static func isWordPressInstalled() -> Bool {
guard let wordPressScheme = URL(string: "wordpress://") else {
return false
}
return UIApplication.shared.canOpenURL(wordPressScheme)
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
struct MigrationActionsViewConfiguration {
let step: MigrationStep

let primaryTitle: String?
let secondaryTitle: String?
let primaryHandler: (() -> Void)?
let secondaryHandler: (() -> Void)?
}

extension MigrationActionsViewConfiguration {

init(step: MigrationStep, primaryHandler: (() -> Void)? = nil, secondaryHandler: (() -> Void)? = nil) {
self.step = step
self.primaryHandler = primaryHandler
self.secondaryHandler = secondaryHandler
self.primaryTitle = Appearance.primaryTitle(for: step)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
struct MigrationCenterViewConfiguration {

let attributedText: NSAttributedString
}

extension MigrationCenterViewConfiguration {

init(step: MigrationStep) {
self.attributedText = Appearance.highlightText(Appearance.highlightedText(for: step), inString: Appearance.text(for: step))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
struct MigrationHeaderConfiguration {

let step: MigrationStep
let title: String?
let image: UIImage?
let primaryDescription: String?
let secondaryDescription: String?
}

init(step: MigrationStep, multiSite: Bool = false) {
self.step = step
extension MigrationHeaderConfiguration {

init(step: MigrationStep, multiSite: Bool = false) {
image = Appearance.image(for: step)
title = Appearance.title(for: step)
primaryDescription = Appearance.primaryDescription(for: step)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ import UIKit

class MigrationStepView: UIView {

// MARK: - Configuration

var additionalContentInset = UIEdgeInsets(
top: Constants.topContentInset,
left: 0,
bottom: Constants.additionalBottomContentInset,
right: 0
)

// MARK: - Views

private let headerView: MigrationHeaderView
private let centerView: UIView
private let actionsView: MigrationActionsView
Expand Down Expand Up @@ -34,6 +45,8 @@ class MigrationStepView: UIView {
return scrollView
}()

// MARK: - Init

init(headerView: MigrationHeaderView,
actionsView: MigrationActionsView,
centerView: UIView) {
Expand Down Expand Up @@ -79,9 +92,13 @@ class MigrationStepView: UIView {
override func layoutSubviews() {
super.layoutSubviews()
let bottomInset = actionsView.frame.size.height - safeAreaInsets.bottom
mainScrollView.contentInset.bottom = bottomInset + Constants.additionalBottomContentInset
mainScrollView.contentInset = .init(
top: additionalContentInset.top,
left: additionalContentInset.left,
bottom: bottomInset + additionalContentInset.bottom,
right: additionalContentInset.right
)
mainScrollView.verticalScrollIndicatorInsets.bottom = bottomInset
mainScrollView.contentInset.top = Constants.topContentInset
}

private enum Constants {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import UIKit

final class MigrationDeleteWordPressViewController: UIViewController {

// MARK: - Dependencies

private let viewModel: MigrationDeleteWordPressViewModel

// MARK: - Init

init(viewModel: MigrationDeleteWordPressViewModel) {
self.viewModel = viewModel
super.init(nibName: nil, bundle: nil)
}

convenience init() {
let actions = MigrationDeleteWordPressViewModel.Actions()
self.init(viewModel: MigrationDeleteWordPressViewModel(actions: actions))
actions.primary = { [weak self] in
self?.primaryButtonTapped()
}
actions.secondary = { [weak self] in
self?.secondaryButtonTapped()
}
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - View Lifecycle

override func loadView() {
let centerContentView = MigrationDoneCenterView()
let centerView = MigrationCenterView(
contentView: centerContentView,
configuration: viewModel.content
)
let migrationView = MigrationStepView(
headerView: MigrationHeaderView(configuration: viewModel.header),
actionsView: MigrationActionsView(configuration: viewModel.actions),
centerView: centerView
)
migrationView.additionalContentInset.top = 0
self.view = migrationView
}

override func viewDidLoad() {
super.viewDidLoad()
self.setupNavigationBar()
self.setupDismissButton()
}

// MARK: - Setup

private func setupNavigationBar() {
let appearance = UINavigationBarAppearance()
appearance.configureWithTransparentBackground()
appearance.backgroundColor = MigrationAppearance.backgroundColor
navigationItem.standardAppearance = appearance
navigationItem.scrollEdgeAppearance = appearance
navigationItem.compactAppearance = appearance
if #available(iOS 15.0, *) {
navigationItem.compactScrollEdgeAppearance = appearance
}
}

private func setupDismissButton() {
let closeButton = UIButton.makeCloseButton()
closeButton.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside)
let item = UIBarButtonItem(customView: closeButton)
self.navigationItem.rightBarButtonItem = item
}

// MARK: - User Interaction

@objc private func closeButtonTapped() {
self.dismiss(animated: true)
}

private func primaryButtonTapped() {
self.dismiss(animated: true)
}

private func secondaryButtonTapped() {
let destination = SupportTableViewController()
self.present(UINavigationController(rootViewController: destination), animated: true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Foundation

final class MigrationDeleteWordPressViewModel {

// MARK: - Configuration

let header: MigrationHeaderConfiguration
let content: MigrationCenterViewConfiguration
let actions: MigrationActionsViewConfiguration

// MARK: - Init

init(actions: Actions) {
self.header = .init(
title: Strings.title,
image: UIImage(named: "wp-migration-welcome"),
primaryDescription: Strings.description,
secondaryDescription: nil
)
self.content = .init(step: .done)
self.actions = .init(
primaryTitle: Strings.primaryAction,
secondaryTitle: Strings.secondaryAction,
primaryHandler: { actions.primary?() },
secondaryHandler: { actions.secondary?() }
)
}

// MARK: - Types

enum Strings {
static let title = NSLocalizedString(
"migration.deleteWordpress.title",
value: "You no longer need the WordPress app",
comment: "The title in the Delete WordPress screen"
)
static let description = NSLocalizedString(
"migration.deleteWordpress.description",
value: "It looks like you still have the WordPress app installed. We recommend you delete the WordPress app to avoid data conflicts.",
comment: "The description in the Delete WordPress screen"
)
static let primaryAction = NSLocalizedString(
"migration.deleteWordpress.primaryButton",
value: "Got it",
comment: "The primary button title in the Delete WordPress screen"
)
static let secondaryAction = NSLocalizedString(
"migration.deleteWordpress.secondaryButton",
value: "Need help?",
comment: "The secondary button title in the Delete WordPress screen"
)
}

class Actions {
var primary: (() -> Void)?
var secondary: (() -> Void)?
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import UIKit

extension UIButton {

private static var closeButtonImage: UIImage {
let fontForSystemImage = UIFont.systemFont(ofSize: Metrics.closeButtonRadius)
let configuration = UIImage.SymbolConfiguration(font: fontForSystemImage)

// fallback to the gridicon if for any reason the system image fails to render
return UIImage(systemName: Constants.closeButtonSystemName, withConfiguration: configuration) ??
UIImage.gridicon(.crossCircle, size: CGSize(width: Metrics.closeButtonRadius, height: Metrics.closeButtonRadius))
}

static func makeCloseButton() -> UIButton {
let closeButton = CircularImageButton()

closeButton.setImage(closeButtonImage, for: .normal)
closeButton.tintColor = Colors.closeButtonTintColor
closeButton.setImageBackgroundColor(UIColor(light: .black, dark: .white))

NSLayoutConstraint.activate([
closeButton.widthAnchor.constraint(equalToConstant: Metrics.closeButtonRadius),
closeButton.heightAnchor.constraint(equalTo: closeButton.widthAnchor)
])

return closeButton
}

private enum Constants {
static let closeButtonSystemName = "xmark.circle.fill"
}

private enum Metrics {
static let closeButtonRadius: CGFloat = 30
}

private enum Colors {
static let closeButtonTintColor = UIColor(
light: .muriel(color: .gray, .shade5),
dark: .muriel(color: .jetpackGreen, .shade90)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import UIKit

extension DashboardMigrationSuccessCell {

func configure(with viewController: UIViewController) {
self.onTap = { [weak viewController] in
guard let viewController else {
return
}
let handler = MigrationSuccessActionHandler()
handler.showDeleteWordPressOverlay(with: viewController)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

extension DashboardMigrationSuccessCell {

func configure(with viewController: UIViewController) {
// Adding an empty implementation of this method so Xcode doesn't complain.
// The whole `DashboardMigrationSuccessCell` shouldn't exist in WordPress. It's only needed for Jetpack.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import UIKit

class DashboardMigrationSuccessCell: UICollectionViewCell, Reusable {

var onTap: (() -> Void)?

override init(frame: CGRect) {
super.init(frame: frame)
setup()
Expand All @@ -13,7 +15,7 @@ class DashboardMigrationSuccessCell: UICollectionViewCell, Reusable {

private func setup() {
let view = MigrationSuccessCardView() {
// TODO: add card presentation logic here
self.onTap?()
}
view.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(view)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Foundation

extension MigrationSuccessCardView {

// TODO: Perhaps this logic should move to another location
@objc static var shouldShowMigrationSuccessCard: Bool {
let migrationCompleted = false // Refactor to UserDefaults.standard.bool("migration-ready")
let wordPressAppExists = MigrationHelper.isWordPressInstalled()
return migrationCompleted && wordPressAppExists
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Foundation

extension MigrationSuccessCardView {

@objc static var shouldShowMigrationSuccessCard: Bool {
// Adding an empty implementation of this variable so Xcode doesn't complain.
// The whole `shouldShowMigrationSuccessCard` shouldn't exist in WordPress. It's only needed for Jetpack.
return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,3 @@ class MigrationSuccessCardView: UIView {
static let descriptionFont = WPStyleGuide.fontForTextStyle(.subheadline, fontWeight: .regular)
}
}

// TODO: This extension is temporary, and should be replaced by the actual condition to check, and placed in the proper location
extension MigrationSuccessCardView {
@objc
static var shouldShowMigrationSuccessCard: Bool {

AppConfiguration.isJetpack && showCard
}

private static let showCard = false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import UIKit

@objcMembers final class MigrationSuccessActionHandler {

func showDeleteWordPressOverlay(with viewController: UIViewController) {
let destination = MigrationDeleteWordPressViewController()
viewController.present(UINavigationController(rootViewController: destination), animated: true)
}
}
Loading