Skip to content

Commit 81bb48a

Browse files
authored
Merge pull request #19638 from wordpress-mobile/task/192012-jetpack-migration-flow-success-card
Jetpack migration flow - add success card
2 parents f4935a0 + c8c1506 commit 81bb48a

File tree

10 files changed

+237
-3
lines changed

10 files changed

+237
-3
lines changed

WordPress/Classes/ViewRelated/Blog/Blog Dashboard/BlogDashboardViewController.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ final class BlogDashboardViewController: UIViewController {
134134
private func setupCollectionView() {
135135
collectionView.isScrollEnabled = !embeddedInScrollView
136136
collectionView.backgroundColor = .listBackground
137+
collectionView.register(DashboardMigrationSuccessCell.self, forCellWithReuseIdentifier: DashboardMigrationSuccessCell.self.defaultReuseID)
137138
collectionView.register(DashboardQuickActionsCardCell.self, forCellWithReuseIdentifier: DashboardQuickActionsCardCell.self.defaultReuseID)
138139
DashboardCard.allCases.forEach {
139140
collectionView.register($0.cell, forCellWithReuseIdentifier: $0.cell.defaultReuseID)
@@ -224,8 +225,9 @@ extension BlogDashboardViewController {
224225

225226
let section = NSCollectionLayoutSection(group: group)
226227
let isQuickActionSection = viewModel.isQuickActionsSection(sectionIndex)
228+
let isMigrationSuccessCardSection = viewModel.isMigrationSuccessCardSection(sectionIndex)
227229
let horizontalInset = isQuickActionSection ? 0 : Constants.horizontalSectionInset
228-
let bottomInset = isQuickActionSection ? 0 : Constants.verticalSectionInset
230+
let bottomInset = isQuickActionSection || isMigrationSuccessCardSection ? 0 : Constants.verticalSectionInset
229231
section.contentInsets = NSDirectionalEdgeInsets(top: Constants.verticalSectionInset,
230232
leading: horizontalInset,
231233
bottom: bottomInset,

WordPress/Classes/ViewRelated/Blog/Blog Dashboard/ViewModel/BlogDashboardViewModel.swift

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import UIKit
33
import CoreData
44

55
enum DashboardSection: Int, CaseIterable {
6+
case migrationSuccess
67
case quickActions
78
case cards
89
}
910

1011
typealias BlogID = Int
1112

1213
enum DashboardItem: Hashable {
14+
case migrationSuccess
1315
case quickActions(BlogID)
1416
case cards(DashboardCardModel)
1517
}
@@ -61,6 +63,10 @@ class BlogDashboardViewModel {
6163
cellConfigurable.configure(blog: blog, viewController: viewController, apiResponse: cardModel.apiResponse)
6264
}
6365
return cell
66+
case .migrationSuccess:
67+
let cellType = DashboardMigrationSuccessCell.self
68+
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.defaultReuseID, for: indexPath) as? DashboardMigrationSuccessCell
69+
return cell
6470
}
6571

6672
}
@@ -101,7 +107,14 @@ class BlogDashboardViewModel {
101107
}
102108

103109
func isQuickActionsSection(_ sectionIndex: Int) -> Bool {
104-
return sectionIndex == DashboardSection.quickActions.rawValue
110+
let showMigration = MigrationSuccessCardView.shouldShowMigrationSuccessCard && !WPDeviceIdentification.isiPad()
111+
let targetIndex = showMigration ? DashboardSection.quickActions.rawValue : DashboardSection.quickActions.rawValue - 1
112+
return sectionIndex == targetIndex
113+
}
114+
115+
func isMigrationSuccessCardSection(_ sectionIndex: Int) -> Bool {
116+
let showMigration = MigrationSuccessCardView.shouldShowMigrationSuccessCard && !WPDeviceIdentification.isiPad()
117+
return showMigration ? sectionIndex == DashboardSection.migrationSuccess.rawValue : false
105118
}
106119
}
107120

@@ -148,7 +161,13 @@ private extension BlogDashboardViewModel {
148161
let items = cards.map { DashboardItem.cards($0) }
149162
let dotComID = blog.dotComID?.intValue ?? 0
150163
var snapshot = DashboardSnapshot()
151-
snapshot.appendSections(DashboardSection.allCases)
164+
if MigrationSuccessCardView.shouldShowMigrationSuccessCard, !WPDeviceIdentification.isiPad() {
165+
snapshot.appendSections(DashboardSection.allCases)
166+
snapshot.appendItems([.migrationSuccess], toSection: .migrationSuccess)
167+
} else {
168+
snapshot.appendSections([.quickActions, .cards])
169+
}
170+
152171
snapshot.appendItems([.quickActions(dotComID)], toSection: .quickActions)
153172
snapshot.appendItems(items, toSection: .cards)
154173
return snapshot

WordPress/Classes/ViewRelated/Blog/Blog Details/BlogDetailsViewController.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef NS_ENUM(NSUInteger, BlogDetailsSectionCategory) {
1919
BlogDetailsSectionCategoryConfigure,
2020
BlogDetailsSectionCategoryExternal,
2121
BlogDetailsSectionCategoryRemoveSite,
22+
BlogDetailsSectionCategoryMigrationSuccess,
2223
};
2324

2425
typedef NS_ENUM(NSUInteger, BlogDetailsSubsection) {
@@ -38,6 +39,7 @@ typedef NS_ENUM(NSUInteger, BlogDetailsSubsection) {
3839
BlogDetailsSubsectionPeople,
3940
BlogDetailsSubsectionPlugins,
4041
BlogDetailsSubsectionHome,
42+
BlogDetailsSubsectionMigrationSuccess,
4143
};
4244

4345

WordPress/Classes/ViewRelated/Blog/Blog Details/BlogDetailsViewController.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
static NSString *const QuickStartHeaderViewNibName = @"BlogDetailsSectionHeaderView";
2929
static NSString *const BlogDetailsQuickStartCellIdentifier = @"BlogDetailsQuickStartCell";
3030
static NSString *const BlogDetailsSectionFooterIdentifier = @"BlogDetailsSectionFooterView";
31+
static NSString *const BlogDetailsMigrationSuccessCellIdentifier = @"BlogDetailsMigrationSuccessCell";
3132

3233
NSString * const WPBlogDetailsRestorationID = @"WPBlogDetailsID";
3334
NSString * const WPBlogDetailsBlogKey = @"WPBlogDetailsBlogKey";
@@ -353,6 +354,7 @@ - (void)viewDidLoad
353354
[self.tableView registerNib:qsHeaderViewNib forHeaderFooterViewReuseIdentifier:BlogDetailsSectionHeaderViewIdentifier];
354355
[self.tableView registerClass:[QuickStartCell class] forCellReuseIdentifier:BlogDetailsQuickStartCellIdentifier];
355356
[self.tableView registerClass:[BlogDetailsSectionFooterView class] forHeaderFooterViewReuseIdentifier:BlogDetailsSectionFooterIdentifier];
357+
[self.tableView registerClass:[MigrationSuccessCell class] forCellReuseIdentifier:BlogDetailsMigrationSuccessCellIdentifier];
356358

357359
self.hasLoggedDomainCreditPromptShownEvent = NO;
358360

@@ -441,6 +443,7 @@ - (void)showDetailViewForSubsection:(BlogDetailsSubsection)section
441443
case BlogDetailsSubsectionReminders:
442444
case BlogDetailsSubsectionDomainCredit:
443445
case BlogDetailsSubsectionHome:
446+
case BlogDetailsSubsectionMigrationSuccess:
444447
self.restorableSelectedIndexPath = indexPath;
445448
[self.tableView selectRowAtIndexPath:indexPath
446449
animated:NO
@@ -554,6 +557,7 @@ - (NSIndexPath *)indexPathForSubsection:(BlogDetailsSubsection)subsection
554557
switch (subsection) {
555558
case BlogDetailsSubsectionReminders:
556559
case BlogDetailsSubsectionHome:
560+
case BlogDetailsSubsectionMigrationSuccess:
557561
return [NSIndexPath indexPathForRow:0 inSection:section];
558562
case BlogDetailsSubsectionDomainCredit:
559563
return [NSIndexPath indexPathForRow:0 inSection:section];
@@ -731,6 +735,10 @@ - (void)configureTableViewData
731735
if (AppConfiguration.showsQuickActions && ![self isDashboardEnabled]) {
732736
[marr addObject:[self quickActionsSectionViewModel]];
733737
}
738+
if (MigrationSuccessCardView.shouldShowMigrationSuccessCard == YES) {
739+
[marr addObject:[self migrationSuccessSectionViewModel]];
740+
}
741+
734742
if ([DomainCreditEligibilityChecker canRedeemDomainCreditWithBlog:self.blog]) {
735743
if (!self.hasLoggedDomainCreditPromptShownEvent) {
736744
[WPAnalytics track:WPAnalyticsStatDomainCreditPromptShown];
@@ -1152,6 +1160,11 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
11521160
return cell;
11531161
}
11541162

1163+
if (section.category == BlogDetailsSectionCategoryMigrationSuccess && MigrationSuccessCardView.shouldShowMigrationSuccessCard == YES) {
1164+
MigrationSuccessCell *cell = [tableView dequeueReusableCellWithIdentifier:BlogDetailsMigrationSuccessCellIdentifier];
1165+
return cell;
1166+
}
1167+
11551168
BlogDetailsRow *row = [section.rows objectAtIndex:indexPath.row];
11561169
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:row.identifier];
11571170
cell.accessibilityHint = row.accessibilityHint;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "wp-migratrion-success-card-icon.pdf",
5+
"idiom" : "universal"
6+
}
7+
],
8+
"info" : {
9+
"author" : "xcode",
10+
"version" : 1
11+
}
12+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import UIKit
2+
3+
class DashboardMigrationSuccessCell: UICollectionViewCell, Reusable {
4+
5+
override init(frame: CGRect) {
6+
super.init(frame: frame)
7+
setup()
8+
}
9+
10+
required init?(coder: NSCoder) {
11+
fatalError("init(coder:) has not been implemented")
12+
}
13+
14+
private func setup() {
15+
let view = MigrationSuccessCardView() {
16+
// TODO: add card presentation logic here
17+
}
18+
view.translatesAutoresizingMaskIntoConstraints = false
19+
contentView.addSubview(view)
20+
contentView.pinSubviewToAllEdges(view)
21+
}
22+
}
23+
24+
extension DashboardMigrationSuccessCell: BlogDashboardCardConfigurable {
25+
func configure(blog: Blog, viewController: BlogDashboardViewController?, apiResponse: BlogDashboardRemoteEntity?) {
26+
27+
}
28+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import UIKit
2+
3+
@objc
4+
class MigrationSuccessCardView: UIView {
5+
6+
private var onTap: (() -> Void)?
7+
8+
private lazy var iconImageView: UIImageView = {
9+
let imageView = UIImageView(image: UIImage(named: Appearance.iconImageName))
10+
imageView.translatesAutoresizingMaskIntoConstraints = false
11+
imageView.layer.cornerRadius = 8
12+
imageView.layer.cornerCurve = .continuous
13+
imageView.clipsToBounds = true
14+
return imageView
15+
}()
16+
17+
private lazy var iconView: UIView = {
18+
let view = UIView()
19+
view.addSubview(iconImageView)
20+
return view
21+
}()
22+
23+
private lazy var descriptionLabel: UILabel = {
24+
let label = UILabel()
25+
label.text = Appearance.descriptionText
26+
label.font = Appearance.descriptionFont
27+
label.numberOfLines = 0
28+
label.adjustsFontForContentSizeCategory = true
29+
return label
30+
}()
31+
32+
private lazy var mainStackView: UIStackView = {
33+
let stackView = UIStackView(arrangedSubviews: [iconView, descriptionLabel])
34+
stackView.translatesAutoresizingMaskIntoConstraints = false
35+
stackView.axis = .horizontal
36+
stackView.spacing = 16
37+
return stackView
38+
}()
39+
40+
@objc
41+
private func viewTapped() {
42+
onTap?()
43+
}
44+
45+
init(onTap: (() -> Void)? = nil) {
46+
self.onTap = onTap
47+
super.init(frame: .zero)
48+
addSubview(mainStackView)
49+
pinSubviewToAllEdges(mainStackView, insets: UIEdgeInsets(allEdges: 16))
50+
NSLayoutConstraint.activate([
51+
iconImageView.heightAnchor.constraint(equalToConstant: 32),
52+
iconImageView.widthAnchor.constraint(equalToConstant: 32),
53+
iconImageView.centerXAnchor.constraint(equalTo: iconView.centerXAnchor),
54+
iconImageView.centerYAnchor.constraint(equalTo: iconView.centerYAnchor),
55+
iconView.widthAnchor.constraint(equalTo: iconImageView.widthAnchor)
56+
])
57+
backgroundColor = .listForeground
58+
layer.cornerRadius = 10
59+
clipsToBounds = true
60+
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(viewTapped)))
61+
}
62+
63+
required init?(coder: NSCoder) {
64+
fatalError("init(coder:) has not been implemented")
65+
}
66+
67+
private enum Appearance {
68+
static let iconImageName = "wp-migration-success-card-icon"
69+
static let descriptionText = NSLocalizedString("wp.migration.successcard.description",
70+
value: "Please delete the WordPress app",
71+
comment: "Description of the jetpack migration success card, used in My site.")
72+
static let descriptionFont = WPStyleGuide.fontForTextStyle(.subheadline, fontWeight: .regular)
73+
}
74+
}
75+
76+
// TODO: This extension is temporary, and should be replaced by the actual condition to check, and placed in the proper location
77+
extension MigrationSuccessCardView {
78+
@objc
79+
static var shouldShowMigrationSuccessCard: Bool {
80+
81+
AppConfiguration.isJetpack && showCard
82+
}
83+
84+
private static let showCard = false
85+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import UIKit
2+
3+
@objc
4+
class MigrationSuccessCell: UITableViewCell {
5+
6+
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
7+
super.init(style: style, reuseIdentifier: reuseIdentifier)
8+
setup()
9+
}
10+
11+
required init?(coder: NSCoder) {
12+
fatalError("init(coder:) has not been implemented")
13+
}
14+
15+
private func setup() {
16+
let view = MigrationSuccessCardView() {
17+
// TODO: add card presentation logic here
18+
}
19+
view.translatesAutoresizingMaskIntoConstraints = false
20+
contentView.addSubview(view)
21+
contentView.pinSubviewToAllEdges(view)
22+
}
23+
}
24+
25+
class MigrationSuccessRow: ImmuTableRow {
26+
var action: ImmuTableAction?
27+
28+
func configureCell(_ cell: UITableViewCell) {
29+
30+
}
31+
32+
static let cell = ImmuTableCell.class(MigrationSuccessCell.self)
33+
}
34+
35+
extension BlogDetailsViewController {
36+
37+
@objc func migrationSuccessSectionViewModel() -> BlogDetailsSection {
38+
let row = BlogDetailsRow()
39+
row.callback = {}
40+
41+
let section = BlogDetailsSection(title: nil,
42+
rows: [row],
43+
footerTitle: nil,
44+
category: .migrationSuccess)
45+
return section
46+
}
47+
}

0 commit comments

Comments
 (0)