Skip to content

Commit 2b2a3b1

Browse files
committed
Merge remote-tracking branch 'origin/trunk' into merge/release-19.7-into-trunk
Got a conflict in `WordPress/Classes/ViewRelated/Site Creation/Site Name/SiteNameView.swift` because: - 0caf937 changed it on `trunk` - 3be617f changed in on `release/19.7` The commit on `trunk` was older (by one day) but the code it results with seems better to me because it doesn't use arbitrary emojis as delimiters for the selected site name. I ensured the app built, but did not run the tests locally or manually verified the how the screen where `SiteNameView` is used renders. The conflict was: ```diff diff --cc WordPress/Classes/ViewRelated/Site Creation/Site Name/SiteNameView.swift index 28af882,85375f6e2b..0000000000 --- a/WordPress/Classes/ViewRelated/Site Creation/Site Name/SiteNameView.swift +++ b/WordPress/Classes/ViewRelated/Site Creation/Site Name/SiteNameView.swift @@@ -144,15 -142,11 +144,23 @@@ private extension SiteNameView /// Highlghts the site name in blue func setupTitleColors() { ++<<<<<<< HEAD + // enclose the vertical name between two characters that are not in the title + // (and reasonably never will..) to distinguish it from any substring in the title + let selectedVerticalName = "😎" + siteVerticalName + "🙃" + let fullTitle = String(format: TextContent.title, selectedVerticalName) + var attributedTitle = NSMutableAttributedString(string: fullTitle) + // Use default title if the vertical name is empty or too long + guard let range = fullTitle.nsRange(of: selectedVerticalName), + !siteVerticalName.isEmpty, + siteVerticalName.count <= Metrics.verticalNameDisplayLimit else { ++======= + // find the index where the vertical name goes, so that it won't be confused + // with any word in the title + let replacementIndex = NSString(string: TextContent.title).range(of: "%@") + + guard !siteVerticalName.isEmpty, replacementIndex.length > 0 else { ++>>>>>>> origin/trunk titleLabel.setText(TextContent.defaultTitle) return } ```
2 parents 8ec0a3d + 5ef12d7 commit 2b2a3b1

145 files changed

Lines changed: 5198 additions & 1867 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.

Gemfile.lock

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@ GEM
1616
artifactory (3.0.15)
1717
atomos (0.1.3)
1818
aws-eventstream (1.2.0)
19-
aws-partitions (1.552.0)
20-
aws-sdk-core (3.126.0)
19+
aws-partitions (1.579.0)
20+
aws-sdk-core (3.130.1)
2121
aws-eventstream (~> 1, >= 1.0.2)
2222
aws-partitions (~> 1, >= 1.525.0)
2323
aws-sigv4 (~> 1.1)
2424
jmespath (~> 1.0)
25-
aws-sdk-kms (1.54.0)
26-
aws-sdk-core (~> 3, >= 3.126.0)
25+
aws-sdk-kms (1.56.0)
26+
aws-sdk-core (~> 3, >= 3.127.0)
2727
aws-sigv4 (~> 1.1)
28-
aws-sdk-s3 (1.112.0)
29-
aws-sdk-core (~> 3, >= 3.126.0)
28+
aws-sdk-s3 (1.113.0)
29+
aws-sdk-core (~> 3, >= 3.127.0)
3030
aws-sdk-kms (~> 1)
3131
aws-sigv4 (~> 1.4)
32-
aws-sigv4 (1.4.0)
32+
aws-sigv4 (1.5.0)
3333
aws-eventstream (~> 1, >= 1.0.2)
3434
babosa (1.0.4)
3535
bigdecimal (1.4.4)
@@ -92,7 +92,7 @@ GEM
9292
escape (0.0.4)
9393
ethon (0.15.0)
9494
ffi (>= 1.15.0)
95-
excon (0.91.0)
95+
excon (0.92.2)
9696
faraday (1.10.0)
9797
faraday-em_http (~> 1.0)
9898
faraday-em_synchrony (~> 1.0)
@@ -122,7 +122,7 @@ GEM
122122
faraday_middleware (1.2.0)
123123
faraday (~> 1.0)
124124
fastimage (2.2.6)
125-
fastlane (2.204.2)
125+
fastlane (2.205.2)
126126
CFPropertyList (>= 2.3, < 4.0.0)
127127
addressable (>= 2.8, < 3.0.0)
128128
artifactory (~> 3.0)
@@ -183,7 +183,7 @@ GEM
183183
gh_inspector (1.1.3)
184184
git (1.11.0)
185185
rchardet (~> 1.8)
186-
google-apis-androidpublisher_v3 (0.16.0)
186+
google-apis-androidpublisher_v3 (0.19.0)
187187
google-apis-core (>= 0.4, < 2.a)
188188
google-apis-core (0.4.2)
189189
addressable (~> 2.5, >= 2.5.1)
@@ -198,24 +198,24 @@ GEM
198198
google-apis-core (>= 0.4, < 2.a)
199199
google-apis-playcustomapp_v1 (0.7.0)
200200
google-apis-core (>= 0.4, < 2.a)
201-
google-apis-storage_v1 (0.11.0)
201+
google-apis-storage_v1 (0.13.0)
202202
google-apis-core (>= 0.4, < 2.a)
203203
google-cloud-core (1.6.0)
204204
google-cloud-env (~> 1.0)
205205
google-cloud-errors (~> 1.0)
206-
google-cloud-env (1.5.0)
207-
faraday (>= 0.17.3, < 2.0)
206+
google-cloud-env (1.6.0)
207+
faraday (>= 0.17.3, < 3.0)
208208
google-cloud-errors (1.2.0)
209-
google-cloud-storage (1.36.0)
209+
google-cloud-storage (1.36.2)
210210
addressable (~> 2.8)
211211
digest-crc (~> 0.4)
212212
google-apis-iamcredentials_v1 (~> 0.1)
213213
google-apis-storage_v1 (~> 0.1)
214214
google-cloud-core (~> 1.6)
215215
googleauth (>= 0.16.2, < 2.a)
216216
mini_mime (~> 1.0)
217-
googleauth (1.1.0)
218-
faraday (>= 0.17.3, < 2.0)
217+
googleauth (1.1.3)
218+
faraday (>= 0.17.3, < 3.a)
219219
jwt (>= 1.4, < 3.0)
220220
memoist (~> 0.16)
221221
multi_json (~> 1.11)
@@ -227,7 +227,7 @@ GEM
227227
httpclient (2.8.3)
228228
i18n (1.10.0)
229229
concurrent-ruby (~> 1.0)
230-
jmespath (1.5.0)
230+
jmespath (1.6.1)
231231
json (2.6.1)
232232
jsonlint (0.3.0)
233233
oj (~> 3)
@@ -261,7 +261,7 @@ GEM
261261
progress_bar (1.3.3)
262262
highline (>= 1.6, < 3)
263263
options (~> 2.3.0)
264-
public_suffix (4.0.6)
264+
public_suffix (4.0.7)
265265
racc (1.6.0)
266266
rake (13.0.6)
267267
rake-compiler (1.2.0)
@@ -284,9 +284,9 @@ GEM
284284
addressable (>= 2.3.5)
285285
faraday (> 0.8, < 2.0)
286286
security (0.1.3)
287-
signet (0.16.0)
287+
signet (0.16.1)
288288
addressable (~> 2.8)
289-
faraday (>= 0.17.3, < 2.0)
289+
faraday (>= 0.17.5, < 3.0)
290290
jwt (>= 1.5, < 3.0)
291291
multi_json (~> 1.10)
292292
simctl (1.6.8)
@@ -308,7 +308,7 @@ GEM
308308
uber (0.1.0)
309309
unf (0.1.4)
310310
unf_ext
311-
unf_ext (0.0.8)
311+
unf_ext (0.0.8.1)
312312
unicode-display_width (1.8.0)
313313
webrick (1.7.0)
314314
word_wrap (1.0.0)

RELEASE-NOTES.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
19.8
22
-----
3-
3+
* [**] Self hosted sites are not restricted by video length during media uploads [https://github.com/wordpress-mobile/WordPress-iOS/pull/18414]
4+
* [*] [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]
5+
* [*] 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]
7+
* [*] [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]
8+
* [**] 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]
49

510
19.7
611
-----
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/Extensions/UIScrollView+Helpers.swift

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import UIKit
22

33
extension UIScrollView {
44

5-
// Scroll to a specific view so that it's top is at the top our scrollview
6-
@objc func scrollToView(_ view: UIView, animated: Bool) {
5+
// MARK: - Vertical scrollview
6+
7+
// Scroll to a specific view in a vertical scrollview so that it's top is at the top our scrollview
8+
@objc func scrollVerticallyToView(_ view: UIView, animated: Bool) {
79
if let origin = view.superview {
810

911
// Get the Y position of your child view
@@ -16,39 +18,82 @@ extension UIScrollView {
1618
//
1719
if childStartPoint.y + safeAreaLayoutGuide.layoutFrame.height < contentSize.height {
1820
let targetRect = CGRect(x: 0,
19-
y: childStartPoint.y - Constants.yOffset,
20-
width: Constants.targetRectWidth,
21+
y: childStartPoint.y - Constants.targetRectPadding,
22+
width: Constants.targetRectDimension,
2123
height: safeAreaLayoutGuide.layoutFrame.height)
2224
scrollRectToVisible(targetRect, animated: animated)
25+
26+
// This ensures scrolling to the correct position, especially when there are layout changes
27+
//
28+
// See: https://stackoverflow.com/a/35437399
29+
//
30+
layoutIfNeeded()
2331
} else {
2432
scrollToBottom(animated: true)
2533
}
26-
27-
// This ensures scrolling to the correct position, especially when there are layout changes
28-
//
29-
// See: https://stackoverflow.com/a/35437399
30-
//
31-
layoutIfNeeded()
3234
}
3335
}
3436

3537
@objc func scrollToTop(animated: Bool) {
3638
let topOffset = CGPoint(x: 0, y: -adjustedContentInset.top)
3739
setContentOffset(topOffset, animated: animated)
40+
layoutIfNeeded()
3841
}
3942

4043
@objc func scrollToBottom(animated: Bool) {
4144
let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height + adjustedContentInset.bottom)
4245
if bottomOffset.y > 0 {
4346
setContentOffset(bottomOffset, animated: animated)
47+
layoutIfNeeded()
48+
}
49+
}
50+
51+
// MARK: - Horizontal scrollview
52+
53+
// Scroll to a specific view in a horizontal scrollview so that it's leading edge is at the leading edge of our scrollview
54+
@objc func scrollHorizontallyToView(_ view: UIView, animated: Bool) {
55+
if let origin = view.superview {
56+
57+
// Get the X position of your child view
58+
let childStartPoint = origin.convert(view.frame.origin, to: self)
59+
60+
// Scroll to a rectangle starting at the X of your subview, with a width of the scrollview safe area
61+
// if the end of the rectangle is within the content size width.
62+
//
63+
// Otherwise, scroll all the way to the end.
64+
//
65+
if childStartPoint.x + safeAreaLayoutGuide.layoutFrame.width < contentSize.width {
66+
let targetRect = CGRect(x: childStartPoint.x - Constants.targetRectPadding,
67+
y: 0,
68+
width: safeAreaLayoutGuide.layoutFrame.width,
69+
height: Constants.targetRectDimension)
70+
scrollRectToVisible(targetRect, animated: animated)
71+
72+
// This ensures scrolling to the correct position, especially when there are layout changes
73+
//
74+
// See: https://stackoverflow.com/a/35437399
75+
//
76+
layoutIfNeeded()
77+
} else {
78+
scrollToEnd(animated: true)
79+
}
80+
81+
}
82+
}
83+
84+
func scrollToEnd(animated: Bool) {
85+
let endOffset = CGPoint(x: contentSize.width - bounds.size.width, y: 0)
86+
if endOffset.x > 0 {
87+
setContentOffset(endOffset, animated: animated)
88+
layoutIfNeeded()
4489
}
4590
}
4691

4792
private enum Constants {
4893
/// An arbitrary placeholder value for the target rect -- must be some value larger than 0
49-
static let targetRectWidth: CGFloat = 1
94+
static let targetRectDimension: CGFloat = 1
5095

51-
/// Vertical padding for the target rect
52-
static let yOffset: CGFloat = 24
96+
/// Padding for the target rect
97+
static let targetRectPadding: CGFloat = 20
5398
}
5499
}

WordPress/Classes/Models/Blog+QuickStart.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@ extension Blog {
99
return quickStartTours?.filter { $0.skipped }
1010
}
1111

12+
var quickStartType: QuickStartType {
13+
get {
14+
guard let value = quickStartTypeValue?.intValue,
15+
let type = QuickStartType(rawValue: value) else {
16+
return .undefined
17+
}
18+
return type
19+
}
20+
21+
set {
22+
quickStartTypeValue = NSNumber(value: newValue.rawValue)
23+
let context = managedObjectContext ?? ContextManager.sharedInstance().mainContext
24+
ContextManager.sharedInstance().saveContextAndWait(context)
25+
}
26+
}
27+
1228
public func skipTour(_ tourID: String) {
1329
let tourState = findOrCreate(tour: tourID)
1430
tourState.skipped = true

WordPress/Classes/Models/Blog.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ typedef NS_ENUM(NSInteger, SiteVisibility) {
156156
@property (nonatomic, strong, readwrite, nullable) NSSet *sharingButtons;
157157
@property (nonatomic, strong, readwrite, nullable) NSDictionary *capabilities;
158158
@property (nonatomic, strong, readwrite, nullable) NSSet<QuickStartTourState *> *quickStartTours;
159+
@property (nonatomic, strong, readwrite, nullable) NSNumber *quickStartTypeValue;
159160
/// The blog's user ID for the current user
160161
@property (nonatomic, strong, readwrite, nullable) NSNumber *userID;
161162
/// Disk quota for site, this is only available for WP.com sites

WordPress/Classes/Models/Blog.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ @implementation Blog
8787
@dynamic sharingButtons;
8888
@dynamic capabilities;
8989
@dynamic quickStartTours;
90+
@dynamic quickStartTypeValue;
9091
@dynamic userID;
9192
@dynamic quotaSpaceAllowed;
9293
@dynamic quotaSpaceUsed;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Foundation
2+
3+
@propertyWrapper
4+
struct Atomic<Value> {
5+
6+
private var value: Value
7+
private let lock = NSLock()
8+
9+
init(wrappedValue value: Value) {
10+
self.value = value
11+
}
12+
13+
var wrappedValue: Value {
14+
get { return load() }
15+
set { store(newValue: newValue) }
16+
}
17+
18+
func load() -> Value {
19+
lock.lock()
20+
defer { lock.unlock() }
21+
return value
22+
}
23+
24+
mutating func store(newValue: Value) {
25+
lock.lock()
26+
defer { lock.unlock() }
27+
value = newValue
28+
}
29+
}

0 commit comments

Comments
 (0)