Skip to content

Commit

Permalink
Merge branch 'trunk' into feature/woo-2.0-brand-updates
Browse files Browse the repository at this point in the history
  • Loading branch information
hichamboushaba committed Jan 20, 2025
2 parents ff14275 + 8fcf8f9 commit 02e27aa
Show file tree
Hide file tree
Showing 299 changed files with 16,427 additions and 2,655 deletions.
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Closes: #
<!-- Id number of the GitHub issue this PR addresses. -->
<!-- Part of: # -> use this if your PR is one of many related to one issue -->

## Description
<!-- Take the time to write a good summary. Why is it needed? What does it do? When fixing bugs try to avoid just writing “See original issue” – clarify what the problem was and how you’ve fixed it. -->
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<!--
Contains editorialized release notes. Raw release notes should go into `RELEASE-NOTES.txt`.
-->
## 21.4
This update introduces the ability to hide specific stores from the store picker, perfect for agencies managing multiple sites. We’ve also enhanced plugin info fetching to handle unexpected data types, ensuring smoother performance. Additionally, a bug on iPad causing order creation issues with custom amounts has been resolved. Enjoy a more focused and reliable experience!

## 21.3

This update brings enhanced reliability and clarity to your WooCommerce experience! Enjoy improved Jetpack setup, smoother media handling, and better product and payment workflows. We’ve also optimized storage and addressed key UI issues to elevate performance. Plus, Tap to Pay onboarding now guides you with ease!

## 21.2
In just two weeks, we've jam-packed this release. There's GTIN global product identifier support, and you can edit the call-to-action in Blaze campaigns.

Expand Down
4 changes: 2 additions & 2 deletions Experiments/Experiments/DefaultFeatureFlagService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,6 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
return buildConfig == .localDeveloper || buildConfig == .alpha
case .productGlobalUniqueIdentifierSupport:
return true
case .paymentsOnboardingInPointOfSale:
return true
case .sendReceiptAfterPayment:
return true
case .sendReceiptsForPointOfSale:
Expand All @@ -102,6 +100,8 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
case .variableProductsInPointOfSale:
return buildConfig == .localDeveloper || buildConfig == .alpha
case .hideSitesInStorePicker:
return true
case .filterHistoryOnOrderAndProductLists:
return buildConfig == .localDeveloper || buildConfig == .alpha
default:
return true
Expand Down
8 changes: 4 additions & 4 deletions Experiments/Experiments/FeatureFlag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,6 @@ public enum FeatureFlag: Int {
///
case productGlobalUniqueIdentifierSupport

/// Supports Woo Payments onboarding in POS so that merchants who have not completed onboarding can access POS.
///
case paymentsOnboardingInPointOfSale

/// Enables sending receipt after the payment via the API
case sendReceiptAfterPayment

Expand All @@ -219,4 +215,8 @@ public enum FeatureFlag: Int {
/// Supports hiding sites from the store picker
///
case hideSitesInStorePicker

/// Supports managing filer history on order and product lists
///
case filterHistoryOnOrderAndProductLists
}
7 changes: 7 additions & 0 deletions Fakes/Fakes/Fake.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,10 @@ extension NSRange {
.init()
}
}

extension UUID {
/// Returns a default UUID
static func fake() -> Self {
.init()
}
}
22 changes: 22 additions & 0 deletions Fakes/Fakes/Networking.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2794,6 +2794,28 @@ extension Networking.WooShippingCustomPackage {
)
}
}
extension Networking.WooShippingOriginAddress {
/// Returns a "ready to use" type filled with fake values.
///
public static func fake() -> Networking.WooShippingOriginAddress {
.init(
id: .fake(),
company: .fake(),
address1: .fake(),
address2: .fake(),
city: .fake(),
state: .fake(),
postcode: .fake(),
country: .fake(),
phone: .fake(),
firstName: .fake(),
lastName: .fake(),
email: .fake(),
defaultAddress: .fake(),
isVerified: .fake()
)
}
}
extension Networking.WooShippingPackagePurchase {
/// Returns a "ready to use" type filled with fake values.
///
Expand Down
16 changes: 16 additions & 0 deletions Fakes/Fakes/Yosemite.generated.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ extension Yosemite.JustInTimeMessageTemplate {
.banner
}
}
extension Yosemite.POSSimpleProduct {
/// Returns a "ready to use" type filled with fake values.
///
public static func fake() -> Yosemite.POSSimpleProduct {
.init(
id: .fake(),
name: .fake(),
formattedPrice: .fake(),
productImageSource: .fake(),
productID: .fake(),
price: .fake(),
productType: .fake(),
bundledItems: .fake()
)
}
}
extension Yosemite.ProductReviewFromNoteParcel {
/// Returns a "ready to use" type filled with fake values.
///
Expand Down
100 changes: 68 additions & 32 deletions Networking/Networking.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions Networking/Networking/Mapper/SystemStatusReportMapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Foundation

/// Mapper: System Status Report
///
struct SystemStatusReportMapper: Mapper {

/// Site Identifier associated to the system status that will be parsed.
/// We're injecting this field via `JSONDecoder.userInfo` because the remote endpoints don't return the SiteID in the system plugin endpoint.
///
let siteID: Int64

/// (Attempts) to convert a dictionary into SystemStatusReport
///
func map(response: Data) throws -> SystemStatusReport {
let decoder = JSONDecoder()
decoder.userInfo = [
.siteID: siteID
]

if hasDataEnvelope(in: response) {
return try decoder.decode(SystemStatusReportEnvelope.self, from: response).systemStatusReport
} else {
return try decoder.decode(SystemStatusReport.self, from: response)
}
}
}

/// System Status Report endpoint returns the requested account in the `data` key. This entity
/// allows us to parse it with JSONDecoder.
///
struct SystemStatusReportEnvelope: Decodable {
let systemStatusReport: SystemStatusReport

private enum CodingKeys: String, CodingKey {
case systemStatusReport = "data"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

struct WooShippingOriginAddressesMapper: Mapper {
/// (Attempts) to convert a dictionary into WooShippingOriginAddress array.
///
func map(response: Data) throws -> [WooShippingOriginAddress] {
let decoder = JSONDecoder()
if hasDataEnvelope(in: response) {
return try decoder.decode(WooShippingOriginAddressesMapperEnvelope.self, from: response).data
} else {
return try decoder.decode([WooShippingOriginAddress].self, from: response)
}
}
}

/// WooShippingOriginAddressesMapperEnvelope Disposable Entity:
/// `Woo Shipping Origin Addresses` endpoint returns the shipping label origin addresses in the `data` key.
/// This entity allows us to do parse all the things with JSONDecoder.
///
private struct WooShippingOriginAddressesMapperEnvelope: Decodable {
let data: [WooShippingOriginAddress]

private enum CodingKeys: String, CodingKey {
case data = "data"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4096,6 +4096,57 @@ extension Networking.WooShippingCustomPackage {
}
}

extension Networking.WooShippingOriginAddress {
public func copy(
id: CopiableProp<String> = .copy,
company: CopiableProp<String> = .copy,
address1: CopiableProp<String> = .copy,
address2: CopiableProp<String> = .copy,
city: CopiableProp<String> = .copy,
state: CopiableProp<String> = .copy,
postcode: CopiableProp<String> = .copy,
country: CopiableProp<String> = .copy,
phone: CopiableProp<String> = .copy,
firstName: CopiableProp<String> = .copy,
lastName: CopiableProp<String> = .copy,
email: CopiableProp<String> = .copy,
defaultAddress: CopiableProp<Bool> = .copy,
isVerified: CopiableProp<Bool> = .copy
) -> Networking.WooShippingOriginAddress {
let id = id ?? self.id
let company = company ?? self.company
let address1 = address1 ?? self.address1
let address2 = address2 ?? self.address2
let city = city ?? self.city
let state = state ?? self.state
let postcode = postcode ?? self.postcode
let country = country ?? self.country
let phone = phone ?? self.phone
let firstName = firstName ?? self.firstName
let lastName = lastName ?? self.lastName
let email = email ?? self.email
let defaultAddress = defaultAddress ?? self.defaultAddress
let isVerified = isVerified ?? self.isVerified

return Networking.WooShippingOriginAddress(
id: id,
company: company,
address1: address1,
address2: address2,
city: city,
state: state,
postcode: postcode,
country: country,
phone: phone,
firstName: firstName,
lastName: lastName,
email: email,
defaultAddress: defaultAddress,
isVerified: isVerified
)
}
}

extension Networking.WooShippingPackagePurchase {
public func copy(
shipmentID: CopiableProp<String> = .copy,
Expand Down
69 changes: 69 additions & 0 deletions Networking/Networking/Model/NotificationSettings.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import Foundation

/// Notification settings for a user
///
public struct NotificationSettings: Equatable, Encodable {

/// Settings for different blogs connected to the user.
public let blogs: [Blog]

/// Convenience init to create notification settings for a given device ID.
///
public init(deviceID: Int64, enabledSites: [Int64], disabledSites: [Int64]) {
let enabledSiteSettings = enabledSites.map { siteID in
Blog(blogID: siteID, devices: [
Device(deviceID: deviceID,
newComment: true,
storeOrder: true)
])
}

let disabledSiteSettings = disabledSites.map { siteID in
Blog(blogID: siteID, devices: [
Device(deviceID: deviceID,
newComment: false,
storeOrder: false)
])
}

self.init(blogs: (enabledSiteSettings + disabledSiteSettings))
}

public init(blogs: [Blog]) {
self.blogs = blogs
}
}

public extension NotificationSettings {
/// Notification settings for a blog
struct Blog: Equatable, Encodable {
/// ID of the blog
public let blogID: Int64

/// List of settings for registered devices
public let devices: [Device]

enum CodingKeys: String, CodingKey {
case blogID = "blog_id"
case devices
}
}

/// Notification settings for a device
struct Device: Equatable, Encodable {
/// Unique ID of the device
public let deviceID: Int64

/// Whether a notification should be sent when there is a new comment on the blog
public let newComment: Bool

/// Whether a notification should be sent when there is a new order on the store.
public let storeOrder: Bool

enum CodingKeys: String, CodingKey {
case deviceID = "device_id"
case newComment = "new_comment"
case storeOrder = "store_order"
}
}
}
8 changes: 8 additions & 0 deletions Networking/Networking/Model/Product/ProductAttribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ extension ProductAttribute: Comparable {
}
}

extension ProductAttribute: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(siteID)
hasher.combine(name)
hasher.combine(attributeID)
}
}

// MARK: - Decoding Errors
//
enum ProductAttributeDecodingError: Error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,16 @@ extension WooShippingCustomPackage: Codable {

var boxWeight: Double = 0.0
// Looks like some endpoints have boxWeight as String and some as Double
if let boxWeightDouble = try? container.decodeIfPresent(Double.self, forKey: .boxWeight) {
// and some endpoints have it as box_weight and some as boxWeight
let weightTransformer = AlternativeDecodingType.string { Double($0) ?? 0.0 }
if let boxWeightDouble = container.failsafeDecodeIfPresent(targetType: Double.self,
forKey: .boxWeight,
alternativeTypes: [weightTransformer]) {
boxWeight = boxWeightDouble
}
else if let boxWeightString = try? container.decodeIfPresent(String.self, forKey: .boxWeight),
let boxWeightDouble = Double(boxWeightString) {
else if let boxWeightDouble = container.failsafeDecodeIfPresent(targetType: Double.self,
forKey: .boxWeightAlternate,
alternativeTypes: [weightTransformer]) {
boxWeight = boxWeightDouble
}

Expand All @@ -92,6 +97,7 @@ extension WooShippingCustomPackage: Codable {
case name
case type
case dimensions
case boxWeight = "box_weight"
case boxWeight
case boxWeightAlternate = "box_weight"
}
}
Loading

0 comments on commit 02e27aa

Please sign in to comment.