Skip to content

Commit 0b05643

Browse files
authored
Merge branch 'trunk' into gutenberg/integrate_release_1.75.0
2 parents 3adfbe8 + 5ef12d7 commit 0b05643

53 files changed

Lines changed: 1876 additions & 139 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

RELEASE-NOTES.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
* [**] Self hosted sites are not restricted by video length during media uploads [https://github.com/wordpress-mobile/WordPress-iOS/pull/18414]
44
* [*] [internal] My Site Dashboard: Made some changes to the code architecture of the dashboard. The majority of the changes are related to the posts cards. It should have no visible changes but could cause regressions. Please test it by creating/trashing drafts and scheduled posts and testing that they appear correctly on the dashboard. [#18405]
55
* [*] Quick Start: Updated the Stats tour. The tour can now be accessed from either the dashboard or the menu tab. [#18413]
6+
* [*] Quick Start: Updated the Reader tour. The tour now highlights the Discover tab and guides users to follow topics via the Settings screen. [#18450]
67
* [*] [internal] Quick Start: Refactored some code related to the tasks displayed in the Quick Start Card and the Quick Start modal. It should have no visible changes but could cause regressions. [#18395]
78
* [*] Block Editor: Latest Posts block: Add featured image settings [https://github.com/WordPress/gutenberg/pull/39257]
89
* [*] Block Editor: Prevent incorrect notices displaying when switching between HTML-Visual mode quickly [https://github.com/WordPress/gutenberg/pull/40415]
910
* [*] Block Editor: Embed block: Fix inline preview cut-off when editing URL [https://github.com/WordPress/gutenberg/pull/35326]
1011
* [*] Block Editor: Prevent gaps shown around floating toolbar when using external keyboard [https://github.com/WordPress/gutenberg/pull/40266]
11-
12+
* [**] We'll now ask users logging in which area of the app they'd like to focus on to build towards a more personalized experience. [#18385]
1213

1314
19.7
1415
-----
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'xcodeproj'
4+
5+
REPO_ROOT = Pathname.new(__dir__) + '../..'
6+
7+
def lint(file_path:, target_name:)
8+
violations_count = 0
9+
File.foreach(file_path, mode: 'rb:BOM|UTF-8').with_index do |line, line_no|
10+
next if line.match? %r(^\s*//) # Skip commented lines
11+
12+
col_no = line.index('NSLocalizedString')
13+
next if col_no.nil?
14+
15+
puts "#{file_path}:#{line_no+1}:#{col_no+1}: error: Use `AppLocalizedString` instead of `NSLocalizedString` in source files that are used in the `#{target_name}` extension target. See paNNhX-nP-p2 for more info."
16+
violations_count += 1
17+
end
18+
violations_count
19+
end
20+
21+
## Main ##
22+
23+
project = Xcodeproj::Project.open(REPO_ROOT + 'WordPress/WordPress.xcodeproj')
24+
targets_to_analyze = if ARGV.count.positive?
25+
project.targets.select { |t| t.name == ARGV.first }
26+
else
27+
project.targets.select { |t| t.is_a?(Xcodeproj::Project::Object::PBXNativeTarget) && t.extension_target_type? }
28+
end
29+
30+
violations_count = 0
31+
targets_to_analyze.each do |target|
32+
build_phase = target.build_phases.find { |p| p.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase) }
33+
next if build_phase.nil?
34+
35+
puts "Linting extension target #{target.name} for improper NSLocalizedString usage..."
36+
source_files = build_phase.files_references.map(&:real_path).select { |f| ['.m', '.swift'].any? { |ext| f.extname == ext } }
37+
source_files.each { |f| violations_count += lint(file_path: f, target_name: target.name) }
38+
puts "Done."
39+
end
40+
41+
exit 1 if violations_count > 0

Scripts/BuildPhases/runRubyScript

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/bash -eu
2+
3+
# Use this to run a Ruby script from a "Script Build Phase" from Xcode.
4+
#
5+
# Since shell scripts ran by Xcode do not source the user shell profile, typical user setups like the configurations of `rbenv` or `rvm` would not be set up properly.
6+
# This script check if either `rbenv` or `rvm` is installed on the Mac and runs the setup steps as appropriate, before running the ruby script via `bundle exec`
7+
#
8+
# Usage:
9+
# `runRubyScript <script_name.rb> <optional_args>`
10+
#
11+
# Where <script_name.rb` can be either an absolute path, or a path relative to this runRubyScript wrapper script.
12+
#
13+
# Inspiration: https://mgrebenets.github.io/xcode/2019/04/04/xcode-build-phases-and-environment
14+
#
15+
16+
# Add `rbenv` and `rvm` binaries to PATH, so that we support both
17+
export PATH="$HOME/.rbenv/shims:$HOME/.rvm/bin:$PATH"
18+
RUBY_VERSION="$(cat "${PROJECT_DIR}/../.ruby-version")"
19+
if command -v rvm; then
20+
source "$(rvm "${RUBY_VERSION}" do rvm env --path | tail -n1)"
21+
fi
22+
23+
# Run the script with bundle exec
24+
echo "Running the script using 'bundle exec' ..."
25+
cd "$(dirname "${BASH_SOURCE[0]}")"
26+
bundle exec ruby "$@"
27+
cd -

WordPress/Classes/Utility/Analytics/WPAnalyticsEvent.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,16 @@ import Foundation
338338
// Quick Start
339339
case quickStartStarted
340340

341+
// Onboarding Question Prompt
342+
case onboardingQuestionsDisplayed
343+
case onboardingQuestionsItemSelected
344+
case onboardingQuestionsSkipped
345+
346+
// Onboarding Enable Notifications Prompt
347+
case onboardingEnableNotificationsDisplayed
348+
case onboardingEnableNotificationsSkipped
349+
case onboardingEnableNotificationsEnableTapped
350+
341351
/// A String that represents the event
342352
var value: String {
343353
switch self {
@@ -895,6 +905,21 @@ import Foundation
895905
case .enhancedSiteCreationIntentQuestionExperiment:
896906
return "enhanced_site_creation_intent_question_experiment"
897907

908+
// Onboarding Question Prompt
909+
case .onboardingQuestionsDisplayed:
910+
return "onboarding_questions_displayed"
911+
case .onboardingQuestionsItemSelected:
912+
return "onboarding_questions_item_selected"
913+
case .onboardingQuestionsSkipped:
914+
return "onboarding_questions_skipped"
915+
916+
// Onboarding Enable Notifications Prompt
917+
case .onboardingEnableNotificationsDisplayed:
918+
return "onboarding_enable_notifications_displayed"
919+
case .onboardingEnableNotificationsSkipped:
920+
return "onboarding_enable_notifications_skipped"
921+
case .onboardingEnableNotificationsEnableTapped:
922+
return "onboarding_enable_notifications_enable_tapped"
898923
// Site Name
899924
case .enhancedSiteCreationSiteNameCanceled:
900925
return "enhanced_site_creation_site_name_canceled"

WordPress/Classes/Utility/FormattableContent/Actions/FormattableContentAction.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ public enum NotificationDeletionKind {
1212
public var legendText: String {
1313
switch self {
1414
case .deletion:
15-
return NSLocalizedString("Comment has been deleted", comment: "Displayed when a Comment is deleted")
15+
return AppLocalizedString("Comment has been deleted", comment: "Displayed when a Comment is deleted")
1616
case .spamming:
17-
return NSLocalizedString("Comment has been marked as Spam", comment: "Displayed when a Comment is spammed")
17+
return AppLocalizedString("Comment has been marked as Spam", comment: "Displayed when a Comment is spammed")
1818
}
1919
}
2020
}

WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Posts/DashboardEmptyPostsCardCell.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import UIKit
2+
import WordPressShared
23

34
/// Card cell prompting the user to create their first post
45
final class DashboardFirstPostCardCell: DashboardEmptyPostsCardCell, BlogDashboardCardConfigurable {
@@ -48,7 +49,7 @@ class DashboardEmptyPostsCardCell: UICollectionViewCell, Reusable {
4849
private lazy var titleLabel: UILabel = {
4950
let titleLabel = UILabel()
5051
titleLabel.text = "Create your first post"
51-
titleLabel.font = WPStyleGuide.notoBoldFontForTextStyle(.title3)
52+
titleLabel.font = WPStyleGuide.serifFontForTextStyle(.title3, fontWeight: .semibold)
5253
titleLabel.adjustsFontForContentSizeCategory = true
5354
titleLabel.adjustsFontSizeToFitWidth = true
5455
titleLabel.minimumScaleFactor = 0.5

WordPress/Classes/ViewRelated/Blog/Blog Dashboard/Cards/Prompts/DashboardPromptsCardCell.swift

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,32 @@ class DashboardPromptsCardCell: UICollectionViewCell, Reusable {
1313
}
1414
}
1515

16+
// This is public so it can be accessed from the BloggingPromptsFeatureDescriptionView.
17+
private(set) lazy var cardFrameView: BlogDashboardCardFrameView = {
18+
let frameView = BlogDashboardCardFrameView()
19+
frameView.translatesAutoresizingMaskIntoConstraints = false
20+
frameView.title = Strings.cardFrameTitle
21+
frameView.icon = Style.frameIconImage
22+
23+
// NOTE: Remove the logic for iOS 13 once we drop that version.
24+
if #available (iOS 14.0, *) {
25+
// assign an empty closure so the button appears.
26+
frameView.onEllipsisButtonTap = {}
27+
frameView.ellipsisButton.showsMenuAsPrimaryAction = true
28+
frameView.ellipsisButton.menu = contextMenu
29+
} else {
30+
// Show a fallback implementation using `MenuSheetViewController`.
31+
// iOS 13 doesn't support showing UIMenu programmatically.
32+
frameView.onEllipsisButtonTap = { [weak self] in
33+
self?.showMenuSheet()
34+
}
35+
}
36+
37+
return frameView
38+
}()
39+
40+
// MARK: - Private Properties
41+
1642
/// When set to true, a "default" version of the card is displayed. That is:
1743
/// - `maxAvatarCount` number of avatars.
1844
/// - `maxAvatarCount` answer count.
@@ -25,8 +51,6 @@ class DashboardPromptsCardCell: UICollectionViewCell, Reusable {
2551
}
2652
}
2753

28-
// MARK: - Private Properties
29-
3054
// Used to present the menu sheet for contextual menu.
3155
// NOTE: Remove this once we drop support for iOS 13.
3256
private weak var presenterViewController: BlogDashboardViewController? = nil
@@ -39,35 +63,12 @@ class DashboardPromptsCardCell: UICollectionViewCell, Reusable {
3963
return stackView
4064
}()
4165

42-
private lazy var cardFrameView: BlogDashboardCardFrameView = {
43-
let frameView = BlogDashboardCardFrameView()
44-
frameView.translatesAutoresizingMaskIntoConstraints = false
45-
frameView.title = Strings.cardFrameTitle
46-
frameView.icon = Style.frameIconImage
47-
48-
// NOTE: Remove the logic for iOS 13 once we drop that version.
49-
if #available (iOS 14.0, *) {
50-
// assign an empty closure so the button appears.
51-
frameView.onEllipsisButtonTap = {}
52-
frameView.ellipsisButton.showsMenuAsPrimaryAction = true
53-
frameView.ellipsisButton.menu = contextMenu
54-
} else {
55-
// Show a fallback implementation using `MenuSheetViewController`.
56-
// iOS 13 doesn't support showing UIMenu programmatically.
57-
frameView.onEllipsisButtonTap = { [weak self] in
58-
self?.showMenuSheet()
59-
}
60-
}
61-
62-
return frameView
63-
}()
64-
6566
// MARK: Top row views
6667

6768
private lazy var promptLabel: UILabel = {
6869
let label = UILabel()
6970
label.translatesAutoresizingMaskIntoConstraints = false
70-
label.font = Style.promptContentFont
71+
label.font = WPStyleGuide.BloggingPrompts.promptContentFont
7172
label.textAlignment = .center
7273
label.numberOfLines = 0
7374
label.adjustsFontForContentSizeCategory = true
@@ -129,8 +130,8 @@ class DashboardPromptsCardCell: UICollectionViewCell, Reusable {
129130
let label = UILabel()
130131
label.translatesAutoresizingMaskIntoConstraints = false
131132
label.text = answerInfoText
132-
label.font = Style.answerInfoLabelFont
133-
label.textColor = Style.answerInfoLabelColor
133+
label.font = WPStyleGuide.BloggingPrompts.answerInfoLabelFont
134+
label.textColor = WPStyleGuide.BloggingPrompts.answerInfoLabelColor
134135
label.textAlignment = (effectiveUserInterfaceLayoutDirection == .leftToRight ? .left : .right)
135136
label.numberOfLines = 0
136137
label.adjustsFontForContentSizeCategory = true
@@ -166,8 +167,8 @@ class DashboardPromptsCardCell: UICollectionViewCell, Reusable {
166167
let button = UIButton()
167168
button.translatesAutoresizingMaskIntoConstraints = false
168169
button.setTitle(Strings.answerButtonTitle, for: .normal)
169-
button.setTitleColor(Style.buttonTitleColor, for: .normal)
170-
button.titleLabel?.font = Style.buttonTitleFont
170+
button.setTitleColor(WPStyleGuide.BloggingPrompts.buttonTitleColor, for: .normal)
171+
button.titleLabel?.font = WPStyleGuide.BloggingPrompts.buttonTitleFont
171172
button.titleLabel?.adjustsFontForContentSizeCategory = true
172173
button.titleLabel?.adjustsFontSizeToFitWidth = true
173174

@@ -178,8 +179,8 @@ class DashboardPromptsCardCell: UICollectionViewCell, Reusable {
178179

179180
private lazy var answeredLabel: UILabel = {
180181
let label = UILabel()
181-
label.font = Style.buttonTitleFont
182-
label.textColor = Style.answeredLabelColor
182+
label.font = WPStyleGuide.BloggingPrompts.buttonTitleFont
183+
label.textColor = WPStyleGuide.BloggingPrompts.answeredLabelColor
183184
label.text = Strings.answeredLabelTitle
184185

185186
// The 'answered' label needs to be close to the Share button.
@@ -195,8 +196,8 @@ class DashboardPromptsCardCell: UICollectionViewCell, Reusable {
195196
let button = UIButton()
196197
button.translatesAutoresizingMaskIntoConstraints = false
197198
button.setTitle(Strings.shareButtonTitle, for: .normal)
198-
button.setTitleColor(Style.buttonTitleColor, for: .normal)
199-
button.titleLabel?.font = Style.buttonTitleFont
199+
button.setTitleColor(WPStyleGuide.BloggingPrompts.buttonTitleColor, for: .normal)
200+
button.titleLabel?.font = WPStyleGuide.BloggingPrompts.buttonTitleFont
200201
button.titleLabel?.adjustsFontForContentSizeCategory = true
201202
button.titleLabel?.adjustsFontSizeToFitWidth = true
202203
button.contentHorizontalAlignment = .leading
@@ -353,12 +354,6 @@ private extension DashboardPromptsCardCell {
353354
struct Style {
354355
static let frameIconImage = UIImage(named: "icon-lightbulb-outline")?.resizedImage(Constants.cardIconSize, interpolationQuality: .default)
355356
static let avatarPlaceholderImage = UIImage(color: .quaternarySystemFill)
356-
static let promptContentFont = WPStyleGuide.serifFontForTextStyle(.headline, fontWeight: .semibold)
357-
static let answerInfoLabelFont = WPStyleGuide.fontForTextStyle(.caption1)
358-
static let answerInfoLabelColor = UIColor.primary
359-
static let buttonTitleFont = WPStyleGuide.fontForTextStyle(.subheadline)
360-
static let buttonTitleColor = UIColor.primary
361-
static let answeredLabelColor = UIColor.muriel(name: .green, .shade50)
362357
}
363358

364359
struct Constants {

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ typedef NS_ENUM(NSInteger, QuickStartTourElement) {
6060
QuickStartTourElementSharing = 8,
6161
QuickStartTourElementConnections = 9,
6262
QuickStartTourElementReaderTab = 10,
63-
QuickStartTourElementReaderSearch = 12,
63+
QuickStartTourElementReaderDiscoverSettings = 12,
6464
QuickStartTourElementTourCompleted = 13,
6565
QuickStartTourElementCongratulations = 14,
6666
QuickStartTourElementSiteIcon = 15,
@@ -71,8 +71,9 @@ typedef NS_ENUM(NSInteger, QuickStartTourElement) {
7171
QuickStartTourElementSiteTitle = 20,
7272
QuickStartTourElementEditHomepage = 21,
7373
QuickStartTourElementSiteMenu = 22,
74-
QuickStartTourElementSetupQuickStart = 23,
75-
QuickStartTourElementRemoveQuickStart = 24,
74+
QuickStartTourElementNotifications = 23,
75+
QuickStartTourElementSetupQuickStart = 24,
76+
QuickStartTourElementRemoveQuickStart = 25,
7677
};
7778

7879
typedef NS_ENUM(NSUInteger, BlogDetailsNavigationSource) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import Foundation
2+
3+
extension MySiteViewController {
4+
func startObservingOnboardingPrompt() {
5+
NotificationCenter.default.addObserver(self, selector: #selector(onboardingPromptWasDismissed(_:)), name: .onboardingPromptWasDismissed, object: nil)
6+
}
7+
8+
@objc func onboardingPromptWasDismissed(_ notification: NSNotification) {
9+
guard
10+
let userInfo = notification.userInfo,
11+
let option = userInfo["option"] as? OnboardingOption
12+
else {
13+
return
14+
}
15+
16+
switch option {
17+
case .stats:
18+
// Show the stats view for the current blog
19+
if let blog = blog {
20+
StatsViewController.show(for: blog, from: self)
21+
}
22+
case .writing:
23+
// Open the editor
24+
let controller = tabBarController as? WPTabBarController
25+
controller?.showPostTab(completion: {
26+
self.startAlertTimer()
27+
})
28+
29+
case .showMeAround:
30+
// Start the quick start
31+
if let blog = blog {
32+
let type: QuickStartType = FeatureFlag.quickStartForExistingUsers.enabled ? .existingSite : .newSite
33+
QuickStartTourGuide.shared.setup(for: blog, type: type)
34+
}
35+
36+
case .skip, .reader, .notifications:
37+
// Skip: Do nothing
38+
// Reader and notifications will be handled by:
39+
// WPAuthenticationManager.handleOnboardingQuestionsWillDismiss
40+
break
41+
}
42+
}
43+
}

WordPress/Classes/ViewRelated/Blog/My Site/MySiteViewController.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ class MySiteViewController: UIViewController, NoResultsViewHost {
155155
subscribeToModelChanges()
156156
subscribeToContentSizeCategory()
157157
startObservingQuickStart()
158+
startObservingOnboardingPrompt()
158159
}
159160

160161
override func viewWillAppear(_ animated: Bool) {
@@ -268,8 +269,7 @@ class MySiteViewController: UIViewController, NoResultsViewHost {
268269
segmentedControlContainerView.isHidden = hideSegmentedControl
269270

270271
if !hideSegmentedControl && switchTabsIfNeeded {
271-
segmentedControl.selectedSegmentIndex = mySiteSettings.defaultSection.rawValue
272-
segmentedControlValueChanged()
272+
switchTab(to: mySiteSettings.defaultSection)
273273
}
274274
}
275275

@@ -478,6 +478,13 @@ class MySiteViewController: UIViewController, NoResultsViewHost {
478478
}
479479
}
480480

481+
/// Changes between the site menu and dashboard
482+
/// - Parameter section: The section to switch to
483+
func switchTab(to section: Section) {
484+
segmentedControl.selectedSegmentIndex = section.rawValue
485+
segmentedControlValueChanged()
486+
}
487+
481488
// MARK: - Child VC logic
482489

483490
private func embedChildInStackView(_ child: UIViewController) {
@@ -765,8 +772,7 @@ class MySiteViewController: UIViewController, NoResultsViewHost {
765772
}
766773

767774
if !blog.isAccessibleThroughWPCom() && self.isShowingDashboard {
768-
self.segmentedControl.selectedSegmentIndex = Section.siteMenu.rawValue
769-
self.segmentedControlValueChanged()
775+
self.switchTab(to: .siteMenu)
770776
}
771777

772778
self.updateNavigationTitle(for: blog)

0 commit comments

Comments
 (0)