Skip to content

Commit d16587f

Browse files
committed
Merge branch 'trunk' into task/make-codegen-module-aware
# Conflicts: # Yosemite/Yosemite/Actions/JustInTimeMessageAction.swift # Yosemite/Yosemite/Stores/JustInTimeMessageStore.swift
2 parents df0d3db + 850f506 commit d16587f

File tree

139 files changed

+4542
-659
lines changed

Some content is hidden

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

139 files changed

+4542
-659
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<!--
22
Contains editorialized release notes. Raw release notes should go into `RELEASE-NOTES.txt`.
33
-->
4+
## 11.0
5+
Even though this release doesn’t have any surprising new features, we still put a lot of love into it! We fixed a few bugs and made several improvements to make your experience smoother.
6+
47
## 10.9
58
This release includes a lot more stability fixes to help you log in much easier. You can now connect your WordPress.com account with Jetpack and access your store that much faster. We've also updated our app to support devices with iOS 15+ only. Please update your device to iOS 15 to continue to use the app.
69

Experiments/Experiments/DefaultFeatureFlagService.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
5151
return buildConfig == .localDeveloper || buildConfig == .alpha
5252
case .productsOnboarding:
5353
return buildConfig == .localDeveloper || buildConfig == .alpha
54+
case .performanceMonitoring,
55+
.performanceMonitoringCoreData,
56+
.performanceMonitoringFileIO,
57+
.performanceMonitoringNetworking,
58+
.performanceMonitoringViewController,
59+
.performanceMonitoringUserInteraction:
60+
// Disabled by default to avoid costs spikes, unless in internal testing builds.
61+
return buildConfig == .alpha
5462
default:
5563
return true
5664
}

Experiments/Experiments/FeatureFlag.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,39 @@ public enum FeatureFlag: Int {
9898
/// Hides products onboarding development.
9999
///
100100
case productsOnboarding
101+
102+
// MARK: - Performance Monitoring
103+
//
104+
// These flags are not transient. That is, they are not here to help us rollout a feature,
105+
// but to serve a safety switches to granularly turn off performance monitoring if it looks
106+
// like we are consuming too many events.
107+
108+
/// Whether to enable performance monitoring.
109+
///
110+
case performanceMonitoring
111+
112+
/// Whether to enable performance monitoring for Core Data operations.
113+
///
114+
/// - Note: The app will ignore this if `performanceMonitoring` is `false`
115+
case performanceMonitoringCoreData
116+
117+
/// Whether to enable performance monitoring for file IO operations.
118+
///
119+
/// - Note: The app will ignore this if `performanceMonitoring` is `false`
120+
case performanceMonitoringFileIO
121+
122+
/// Whether to enable performance monitoring for networking operations.
123+
///
124+
/// - Note: The app will ignore this if `performanceMonitoring` is `false`
125+
case performanceMonitoringNetworking
126+
127+
/// Whether to enable performance monitoring for user interaction events.
128+
///
129+
/// - Note: The app will ignore this if `performanceMonitoring` is `false`
130+
case performanceMonitoringUserInteraction
131+
132+
/// Whether to enable performance monitoring for `UIViewController` life-cycle events.
133+
///
134+
/// - Note: The app will ignore this if `performanceMonitoring` is `false`.
135+
case performanceMonitoringViewController
101136
}

Gemfile.lock

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ GEM
1717
ast (2.4.2)
1818
atomos (0.1.3)
1919
aws-eventstream (1.2.0)
20-
aws-partitions (1.631.0)
21-
aws-sdk-core (3.148.0)
20+
aws-partitions (1.653.0)
21+
aws-sdk-core (3.166.0)
2222
aws-eventstream (~> 1, >= 1.0.2)
23-
aws-partitions (~> 1, >= 1.525.0)
24-
aws-sigv4 (~> 1.1)
23+
aws-partitions (~> 1, >= 1.651.0)
24+
aws-sigv4 (~> 1.5)
2525
jmespath (~> 1, >= 1.6.1)
26-
aws-sdk-kms (1.58.0)
27-
aws-sdk-core (~> 3, >= 3.127.0)
26+
aws-sdk-kms (1.59.0)
27+
aws-sdk-core (~> 3, >= 3.165.0)
2828
aws-sigv4 (~> 1.1)
29-
aws-sdk-s3 (1.114.0)
30-
aws-sdk-core (~> 3, >= 3.127.0)
29+
aws-sdk-s3 (1.117.1)
30+
aws-sdk-core (~> 3, >= 3.165.0)
3131
aws-sdk-kms (~> 1)
3232
aws-sigv4 (~> 1.4)
33-
aws-sigv4 (1.5.1)
33+
aws-sigv4 (1.5.2)
3434
aws-eventstream (~> 1, >= 1.0.2)
3535
babosa (1.0.4)
3636
bigdecimal (1.4.4)
@@ -94,7 +94,7 @@ GEM
9494
escape (0.0.4)
9595
ethon (0.15.0)
9696
ffi (>= 1.15.0)
97-
excon (0.92.4)
97+
excon (0.93.1)
9898
faraday (1.10.2)
9999
faraday-em_http (~> 1.0)
100100
faraday-em_synchrony (~> 1.0)
@@ -124,7 +124,7 @@ GEM
124124
faraday_middleware (1.2.0)
125125
faraday (~> 1.0)
126126
fastimage (2.2.6)
127-
fastlane (2.210.0)
127+
fastlane (2.210.1)
128128
CFPropertyList (>= 2.3, < 4.0.0)
129129
addressable (>= 2.8, < 3.0.0)
130130
artifactory (~> 3.0)
@@ -164,8 +164,9 @@ GEM
164164
xcpretty (~> 0.3.0)
165165
xcpretty-travis-formatter (>= 0.0.3)
166166
fastlane-plugin-appcenter (1.11.1)
167-
fastlane-plugin-sentry (1.11.1)
168-
fastlane-plugin-wpmreleasetoolkit (5.5.0)
167+
fastlane-plugin-sentry (1.14.0)
168+
os (~> 1.1, >= 1.1.4)
169+
fastlane-plugin-wpmreleasetoolkit (5.6.0)
169170
activesupport (~> 5)
170171
bigdecimal (~> 1.4)
171172
buildkit (~> 1.5)
@@ -188,9 +189,9 @@ GEM
188189
git (1.12.0)
189190
addressable (~> 2.8)
190191
rchardet (~> 1.8)
191-
google-apis-androidpublisher_v3 (0.26.0)
192-
google-apis-core (>= 0.7, < 2.a)
193-
google-apis-core (0.7.2)
192+
google-apis-androidpublisher_v3 (0.29.0)
193+
google-apis-core (>= 0.9.0, < 2.a)
194+
google-apis-core (0.9.1)
194195
addressable (~> 2.5, >= 2.5.1)
195196
googleauth (>= 0.16.2, < 2.a)
196197
httpclient (>= 2.8.1, < 3.a)
@@ -199,27 +200,27 @@ GEM
199200
retriable (>= 2.0, < 4.a)
200201
rexml
201202
webrick
202-
google-apis-iamcredentials_v1 (0.13.0)
203-
google-apis-core (>= 0.7, < 2.a)
204-
google-apis-playcustomapp_v1 (0.10.0)
205-
google-apis-core (>= 0.7, < 2.a)
206-
google-apis-storage_v1 (0.17.0)
207-
google-apis-core (>= 0.7, < 2.a)
203+
google-apis-iamcredentials_v1 (0.15.0)
204+
google-apis-core (>= 0.9.0, < 2.a)
205+
google-apis-playcustomapp_v1 (0.12.0)
206+
google-apis-core (>= 0.9.1, < 2.a)
207+
google-apis-storage_v1 (0.19.0)
208+
google-apis-core (>= 0.9.0, < 2.a)
208209
google-cloud-core (1.6.0)
209210
google-cloud-env (~> 1.0)
210211
google-cloud-errors (~> 1.0)
211212
google-cloud-env (1.6.0)
212213
faraday (>= 0.17.3, < 3.0)
213214
google-cloud-errors (1.3.0)
214-
google-cloud-storage (1.40.0)
215+
google-cloud-storage (1.43.0)
215216
addressable (~> 2.8)
216217
digest-crc (~> 0.4)
217218
google-apis-iamcredentials_v1 (~> 0.1)
218-
google-apis-storage_v1 (~> 0.17.0)
219+
google-apis-storage_v1 (~> 0.19.0)
219220
google-cloud-core (~> 1.6)
220221
googleauth (>= 0.16.2, < 2.a)
221222
mini_mime (~> 1.0)
222-
googleauth (1.2.0)
223+
googleauth (1.3.0)
223224
faraday (>= 0.17.3, < 3.a)
224225
jwt (>= 1.4, < 3.0)
225226
memoist (~> 0.16)
@@ -250,10 +251,10 @@ GEM
250251
nap (1.1.0)
251252
naturally (2.2.1)
252253
netrc (0.11.0)
253-
nokogiri (1.13.8)
254+
nokogiri (1.13.9)
254255
mini_portile2 (~> 2.8.0)
255256
racc (~> 1.4)
256-
nokogiri (1.13.8-x86_64-darwin)
257+
nokogiri (1.13.9-x86_64-darwin)
257258
racc (~> 1.4)
258259
octokit (4.25.1)
259260
faraday (>= 1, < 3)

Networking/Networking.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
0359EA2127AAE58C0048DE2D /* wcpay-charge-card-present.json in Resources */ = {isa = PBXBuildFile; fileRef = 0359EA2027AAE58C0048DE2D /* wcpay-charge-card-present.json */; };
103103
0359EA2527AAF7D60048DE2D /* wcpay-charge-card.json in Resources */ = {isa = PBXBuildFile; fileRef = 0359EA2427AAF7D60048DE2D /* wcpay-charge-card.json */; };
104104
0359EA2927AC2AAD0048DE2D /* wcpay-charge-error.json in Resources */ = {isa = PBXBuildFile; fileRef = 0359EA2827AC2AAD0048DE2D /* wcpay-charge-error.json */; };
105+
035BA3AA29113CBD0056F0AD /* DataBoolMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035BA3A929113CBD0056F0AD /* DataBoolMapper.swift */; };
105106
036563DB2906938600D84BFD /* JustInTimeMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036563DA2906938600D84BFD /* JustInTimeMessage.swift */; };
106107
036563DD29069BE400D84BFD /* JustInTimeMessageListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036563DC29069BE400D84BFD /* JustInTimeMessageListMapper.swift */; };
107108
036563DF29069C8F00D84BFD /* JustInTimeMessageListMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 036563DE29069C8F00D84BFD /* JustInTimeMessageListMapperTests.swift */; };
@@ -164,6 +165,8 @@
164165
2670C3FE270F4E6A002FE931 /* sites-malformed.json in Resources */ = {isa = PBXBuildFile; fileRef = 2670C3FD270F4E6A002FE931 /* sites-malformed.json */; };
165166
267313312559CC930026F7EF /* PaymentGateway.swift in Sources */ = {isa = PBXBuildFile; fileRef = 267313302559CC930026F7EF /* PaymentGateway.swift */; };
166167
26731337255ACA850026F7EF /* PaymentGatewayListMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26731336255ACA850026F7EF /* PaymentGatewayListMapper.swift */; };
168+
2676F4CE290AE6BB00C7A15B /* EntityIDMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2676F4CD290AE6BB00C7A15B /* EntityIDMapper.swift */; };
169+
2676F4D0290B0EC800C7A15B /* product-id-only.json in Resources */ = {isa = PBXBuildFile; fileRef = 2676F4CF290B0EC700C7A15B /* product-id-only.json */; };
167170
2683D70E24456DB8002A1589 /* categories-empty.json in Resources */ = {isa = PBXBuildFile; fileRef = 2683D70D24456DB7002A1589 /* categories-empty.json */; };
168171
2683D71024456EE4002A1589 /* categories-extra.json in Resources */ = {isa = PBXBuildFile; fileRef = 2683D70F24456EE4002A1589 /* categories-extra.json */; };
169172
2685C0D2263B069500D9EE97 /* AddOnGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2685C0D1263B069500D9EE97 /* AddOnGroup.swift */; };
@@ -833,6 +836,7 @@
833836
0359EA2027AAE58C0048DE2D /* wcpay-charge-card-present.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "wcpay-charge-card-present.json"; sourceTree = "<group>"; };
834837
0359EA2427AAF7D60048DE2D /* wcpay-charge-card.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "wcpay-charge-card.json"; sourceTree = "<group>"; };
835838
0359EA2827AC2AAD0048DE2D /* wcpay-charge-error.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "wcpay-charge-error.json"; sourceTree = "<group>"; };
839+
035BA3A929113CBD0056F0AD /* DataBoolMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataBoolMapper.swift; sourceTree = "<group>"; };
836840
036563DA2906938600D84BFD /* JustInTimeMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JustInTimeMessage.swift; sourceTree = "<group>"; };
837841
036563DC29069BE400D84BFD /* JustInTimeMessageListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JustInTimeMessageListMapper.swift; sourceTree = "<group>"; };
838842
036563DE29069C8F00D84BFD /* JustInTimeMessageListMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JustInTimeMessageListMapperTests.swift; sourceTree = "<group>"; };
@@ -887,6 +891,8 @@
887891
2670C3FD270F4E6A002FE931 /* sites-malformed.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "sites-malformed.json"; sourceTree = "<group>"; };
888892
267313302559CC930026F7EF /* PaymentGateway.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentGateway.swift; sourceTree = "<group>"; };
889893
26731336255ACA850026F7EF /* PaymentGatewayListMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaymentGatewayListMapper.swift; sourceTree = "<group>"; };
894+
2676F4CD290AE6BB00C7A15B /* EntityIDMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntityIDMapper.swift; sourceTree = "<group>"; };
895+
2676F4CF290B0EC700C7A15B /* product-id-only.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "product-id-only.json"; sourceTree = "<group>"; };
890896
2683D70D24456DB7002A1589 /* categories-empty.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "categories-empty.json"; sourceTree = "<group>"; };
891897
2683D70F24456EE4002A1589 /* categories-extra.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "categories-extra.json"; sourceTree = "<group>"; };
892898
2685C0D1263B069500D9EE97 /* AddOnGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddOnGroup.swift; sourceTree = "<group>"; };
@@ -2083,6 +2089,7 @@
20832089
09885C7F27C3FFD200910A62 /* product-variations-bulk-update.json */,
20842090
451274A525276C82009911FF /* product-variation.json */,
20852091
CE0A0F1E223998A00075ED8D /* products-load-all.json */,
2092+
2676F4CF290B0EC700C7A15B /* product-id-only.json */,
20862093
CCF434652906C2A400B4475A /* products-ids-only.json */,
20872094
CCF434692906C9C300B4475A /* products-ids-only-empty.json */,
20882095
0282DD90233A120A006A5FDB /* products-search-photo.json */,
@@ -2214,7 +2221,9 @@
22142221
03DCB785262739D200C8953D /* CouponMapper.swift */,
22152222
DE2095BE279583A100171F1C /* CouponReportListMapper.swift */,
22162223
45150A9D26836A57006922EA /* CountryListMapper.swift */,
2224+
035BA3A929113CBD0056F0AD /* DataBoolMapper.swift */,
22172225
B524193E21AC5FE400D6FC0A /* DotcomDeviceMapper.swift */,
2226+
2676F4CD290AE6BB00C7A15B /* EntityIDMapper.swift */,
22182227
24F98C572502EA8800F49B68 /* FeatureFlagMapper.swift */,
22192228
DE50295C28C6068B00551736 /* JetpackUserMapper.swift */,
22202229
AEF9458A27297FF6001DCCFB /* IgnoringResponseMapper.swift */,
@@ -2821,6 +2830,7 @@
28212830
68CB801628D8A39700E169F8 /* customer.json in Resources */,
28222831
03EB99982907F4AA00F06A39 /* just-in-time-message-list-multiple.json in Resources */,
28232832
451A97DE260B59870059D135 /* shipping-label-packages-success.json in Resources */,
2833+
2676F4D0290B0EC800C7A15B /* product-id-only.json in Resources */,
28242834
31D27C8F2602B553002EDB1D /* plugins.json in Resources */,
28252835
261CF1B4255AD6B30090D8D3 /* payment-gateway-list.json in Resources */,
28262836
268B68FB24C87384007EBF1D /* leaderboards-products.json in Resources */,
@@ -3154,6 +3164,7 @@
31543164
B963A5CC2853870000EFADA0 /* OrderItemRefundMetaData.swift in Sources */,
31553165
E18152BE28F85B5B0011A0EC /* InAppPurchasesRemote.swift in Sources */,
31563166
0329CF9B27A82E19008AFF91 /* WCPayCharge.swift in Sources */,
3167+
035BA3AA29113CBD0056F0AD /* DataBoolMapper.swift in Sources */,
31573168
74749B97224134FF005C4CF2 /* ProductMapper.swift in Sources */,
31583169
26455E2A25F669F0008A1D32 /* ProductAttributeTermMapper.swift in Sources */,
31593170
0359EA1127AAC6740048DE2D /* WCPayPaymentMethodType.swift in Sources */,
@@ -3240,6 +3251,7 @@
32403251
029BA53B255DFABD006171FD /* ShippingLabelPrintDataMapper.swift in Sources */,
32413252
0359EA0D27AAC5F80048DE2D /* WCPayChargeStatus.swift in Sources */,
32423253
CE430674234BA6AD0073CBFF /* RefundMapper.swift in Sources */,
3254+
2676F4CE290AE6BB00C7A15B /* EntityIDMapper.swift in Sources */,
32433255
CE0A0F1B223989670075ED8D /* ProductsRemote.swift in Sources */,
32443256
0359EA1527AAC7460048DE2D /* WCPayCardBrand.swift in Sources */,
32453257
2665032E261F4FBF0079A159 /* ProductAddOnOption.swift in Sources */,
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import Foundation
2+
3+
/// Mapper: Bool Result Wrapped in `data` Key
4+
///
5+
struct DataBoolMapper: Mapper {
6+
7+
/// (Attempts) to extract the boolean flag from a given JSON Encoded response.
8+
///
9+
func map(response: Data) throws -> Bool {
10+
try JSONDecoder().decode(DataBool.self, from: response).data
11+
}
12+
}
13+
14+
/// DataBoolResultEnvelope Disposable Entity
15+
///
16+
/// Some endpoints return a Bool response in the `data` key. This entity
17+
/// allows us to parse that response with JSONDecoder.
18+
///
19+
private struct DataBool: Decodable {
20+
let data: Bool
21+
22+
private enum CodingKeys: String, CodingKey {
23+
case data
24+
}
25+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import Foundation
2+
3+
/// Mapper: Single Entity ID
4+
///
5+
struct EntityIDMapper: Mapper {
6+
7+
/// (Attempts) to convert an instance of Data into an into an ID
8+
///
9+
func map(response: Data) throws -> Int64 {
10+
let decoder = JSONDecoder()
11+
12+
return try decoder.decode(EntityIDEnvelope.self, from: response).id
13+
}
14+
}
15+
16+
/// Disposable Entity:
17+
/// Allows us to parse a product ID with JSONDecoder.
18+
///
19+
private struct EntityIDEnvelope: Decodable {
20+
private let data: [String: Int64]
21+
22+
// Extracts the entity ID from the underlying data
23+
var id: Int64 {
24+
data["id"] ?? .zero
25+
}
26+
27+
private enum CodingKeys: String, CodingKey {
28+
case data = "data"
29+
}
30+
}

Networking/Networking/Model/Product/ProductStatus.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ public enum ProductStatus: Codable, Hashable, GeneratedFakeable {
88
case draft
99
case pending
1010
case privateStatus // `private` is a reserved keyword
11+
case autoDraft
1112
case custom(String) // in case there are extensions modifying product statuses
1213
}
1314

@@ -28,6 +29,8 @@ extension ProductStatus: RawRepresentable {
2829
self = .pending
2930
case Keys.privateStatus:
3031
self = .privateStatus
32+
case Keys.autoDraft:
33+
self = .autoDraft
3134
default:
3235
self = .custom(rawValue)
3336
}
@@ -41,6 +44,7 @@ extension ProductStatus: RawRepresentable {
4144
case .draft: return Keys.draft
4245
case .pending: return Keys.pending
4346
case .privateStatus: return Keys.privateStatus
47+
case .autoDraft: return Keys.autoDraft
4448
case .custom(let payload): return payload
4549
}
4650
}
@@ -57,6 +61,8 @@ extension ProductStatus: RawRepresentable {
5761
return NSLocalizedString("Pending review", comment: "Display label for the product's pending status")
5862
case .privateStatus:
5963
return NSLocalizedString("Privately published", comment: "Display label for the product's private status")
64+
case .autoDraft:
65+
return "Auto Draft" // We don't need to localize this now.
6066
case .custom(let payload):
6167
return payload // unable to localize at runtime.
6268
}
@@ -71,4 +77,5 @@ private enum Keys {
7177
static let draft = "draft"
7278
static let pending = "pending"
7379
static let privateStatus = "private"
80+
static let autoDraft = "auto-draft"
7481
}

Networking/Networking/Remote/AccountRemote.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ public enum CreateAccountError: Error, Equatable {
233233
self = .invalidEmail
234234
case Constants.invalidPassword:
235235
self = .invalidPassword(message: message)
236-
case Constants.invalidUsername:
236+
case Constants.invalidUsername, Constants.usernameExists:
237237
self = .invalidUsername
238238
default:
239239
self = .unexpected(error: error)
@@ -249,6 +249,7 @@ public enum CreateAccountError: Error, Equatable {
249249
static let emailExists = "email_exists"
250250
static let invalidEmail = "email_invalid"
251251
static let invalidPassword = "password_invalid"
252-
static let invalidUsername = "username_exists"
252+
static let usernameExists = "username_exists"
253+
static let invalidUsername = "username_invalid"
253254
}
254255
}

0 commit comments

Comments
 (0)