Skip to content

Commit af0722d

Browse files
committed
Merge branch '0.9.6'
2 parents 7a367af + ef06d53 commit af0722d

File tree

9 files changed

+168
-34
lines changed

9 files changed

+168
-34
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1540"
4+
version = "1.7">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES"
8+
buildArchitectures = "Automatic">
9+
<BuildActionEntries>
10+
<BuildActionEntry
11+
buildForTesting = "YES"
12+
buildForRunning = "YES"
13+
buildForProfiling = "YES"
14+
buildForArchiving = "YES"
15+
buildForAnalyzing = "YES">
16+
<BuildableReference
17+
BuildableIdentifier = "primary"
18+
BlueprintIdentifier = "OpenFoodFactsSDK"
19+
BuildableName = "OpenFoodFactsSDK"
20+
BlueprintName = "OpenFoodFactsSDK"
21+
ReferencedContainer = "container:">
22+
</BuildableReference>
23+
</BuildActionEntry>
24+
</BuildActionEntries>
25+
</BuildAction>
26+
<TestAction
27+
buildConfiguration = "Debug"
28+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
29+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
30+
shouldUseLaunchSchemeArgsEnv = "YES"
31+
shouldAutocreateTestPlan = "YES">
32+
<Testables>
33+
<TestableReference
34+
skipped = "NO">
35+
<BuildableReference
36+
BuildableIdentifier = "primary"
37+
BlueprintIdentifier = "OpenFoodFactsSDK-iosTests"
38+
BuildableName = "OpenFoodFactsSDK-iosTests"
39+
BlueprintName = "OpenFoodFactsSDK-iosTests"
40+
ReferencedContainer = "container:">
41+
</BuildableReference>
42+
</TestableReference>
43+
</Testables>
44+
</TestAction>
45+
<LaunchAction
46+
buildConfiguration = "Debug"
47+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
48+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
49+
launchStyle = "0"
50+
useCustomWorkingDirectory = "NO"
51+
ignoresPersistentStateOnLaunch = "NO"
52+
debugDocumentVersioning = "YES"
53+
debugServiceExtension = "internal"
54+
allowLocationSimulation = "YES">
55+
</LaunchAction>
56+
<ProfileAction
57+
buildConfiguration = "Release"
58+
shouldUseLaunchSchemeArgsEnv = "YES"
59+
savedToolIdentifier = ""
60+
useCustomWorkingDirectory = "NO"
61+
debugDocumentVersioning = "YES">
62+
<MacroExpansion>
63+
<BuildableReference
64+
BuildableIdentifier = "primary"
65+
BlueprintIdentifier = "OpenFoodFactsSDK"
66+
BuildableName = "OpenFoodFactsSDK"
67+
BlueprintName = "OpenFoodFactsSDK"
68+
ReferencedContainer = "container:">
69+
</BuildableReference>
70+
</MacroExpansion>
71+
</ProfileAction>
72+
<AnalyzeAction
73+
buildConfiguration = "Debug">
74+
</AnalyzeAction>
75+
<ArchiveAction
76+
buildConfiguration = "Release"
77+
revealArchiveInOrganizer = "YES">
78+
</ArchiveAction>
79+
</Scheme>

Sources/Model/OFF/OpenFoodFactsLanguage.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ public enum OpenFoodFactsLanguage: String, CaseIterable, Identifiable, Equatable
195195
case ZULU
196196
case UNDEFINED
197197

198-
var info: (code: String, description: String) {
198+
public var info: (code: String, description: String) {
199199
switch self {
200200
case .ENGLISH:
201201
return ("en", "English")

Sources/Model/OFF/Product.swift

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,34 +46,42 @@ public struct Product: Codable, Equatable, Sendable {
4646
public let brands: String?
4747
public let lang: OpenFoodFactsLanguage?
4848
public let quantity: String?
49-
public let packagingQuantity: Double?
49+
public let packagingQuantity: Double
50+
public let packagingQuantityUnit: String
5051
public let servingSize: String?
51-
public let servingQuantity: Double?
52+
public let servingQuantity: Double
53+
public let servingQuantityUnit: String
5254
public let dataPer: String?
5355
public let categories: String?
5456
public var nutriments: [String: Any]?
5557
public let imageFront: String?
5658
public let imageIngredients: String?
5759
public let imageNutrition: String?
5860
public let keywords: [String]?
61+
public let novaGroup: Double?
62+
public let nutriScore: String?
5963

6064
enum CodingKeys: String, CodingKey {
6165
case code
6266
case lang
6367
case brands
6468
case quantity
6569
case packagingQuantity = "product_quantity"
70+
case packagingQuantityUnit = "product_quantity_unit"
6671
case categories
6772
case images
6873
case productName = "product_name"
6974
case productNameEn = "product_name_en"
7075
case servingSize = "serving_size"
7176
case servingQuantity = "serving_quantity"
77+
case servingQuantityUnit = "serving_quantity_unit"
7278
case dataPer = "nutrition_data_per"
7379
case nutriments = "nutriments"
7480
case imageFront = "image_front_url"
7581
case imageIngredients = "image_ingredients_url"
7682
case imageNutrition = "image_nutrition_url"
83+
case novaGroup = "nova_group"
84+
case nutriScore = "nutriscore_grade"
7785
case keywords = "_keywords"
7886
}
7987

@@ -91,23 +99,28 @@ public struct Product: Codable, Equatable, Sendable {
9199
imageIngredients = try container.decodeIfPresent(String.self, forKey: .imageIngredients)
92100
imageNutrition = try container.decodeIfPresent(String.self, forKey: .imageNutrition)
93101
keywords = try container.decodeIfPresent([String].self, forKey: .keywords)
102+
nutriScore = try container.decodeIfPresent(String.self, forKey: .nutriScore)
103+
novaGroup = try container.decodeIfPresent(Double.self, forKey: .novaGroup)
104+
servingQuantityUnit = try container.decodeIfPresent(String.self, forKey: .servingQuantityUnit) ?? "g"
105+
packagingQuantityUnit = try container.decodeIfPresent(String.self, forKey: .packagingQuantityUnit) ?? "g"
94106

95107
if let packagingQuantityValue = try? container.decode(Double.self, forKey: .packagingQuantity) {
96108
packagingQuantity = packagingQuantityValue
97-
} else if let packagingQuantityString = try? container.decode(String.self, forKey: .packagingQuantity),
98-
let packagingQuantityValue = Double(packagingQuantityString) {
99-
packagingQuantity = packagingQuantityValue
109+
} else if let packagingQuantityString = try? container.decode(String.self, forKey: .packagingQuantity) {
110+
let cleanedString = packagingQuantityString.filter { $0.isNumber || $0 == "." || $0 == "," }
111+
packagingQuantity = Double(cleanedString) ?? 0.0
112+
100113
} else {
101-
packagingQuantity = nil
114+
packagingQuantity = 100
102115
}
103-
116+
104117
if let servingQuantityValue = try? container.decode(Double.self, forKey: .servingQuantity) {
105118
servingQuantity = servingQuantityValue
106-
} else if let servingQuantityString = try? container.decode(String.self, forKey: .servingQuantity),
107-
let servingQuantityValue = Double(servingQuantityString) {
108-
servingQuantity = servingQuantityValue
119+
} else if let servingQuantityString = try? container.decode(String.self, forKey: .servingQuantity) {
120+
let cleanedString = servingQuantityString.filter { $0.isNumber || $0 == "." || $0 == "," }
121+
servingQuantity = Double(cleanedString) ?? 0.0
109122
} else {
110-
servingQuantity = nil
123+
servingQuantity = 100
111124
}
112125

113126
if let nutrimentsContainer = try? container.nestedContainer(keyedBy: AnyCodingKey.self, forKey: .nutriments) {
@@ -136,15 +149,19 @@ public struct Product: Codable, Equatable, Sendable {
136149
try container.encodeIfPresent(productNameEn, forKey: .productNameEn)
137150
try container.encodeIfPresent(quantity, forKey: .quantity)
138151
try container.encodeIfPresent(packagingQuantity, forKey: .packagingQuantity)
152+
try container.encodeIfPresent(packagingQuantityUnit, forKey: .packagingQuantityUnit)
139153
try container.encodeIfPresent(servingSize, forKey: .servingSize)
140154
try container.encodeIfPresent(servingQuantity, forKey: .servingQuantity)
155+
try container.encodeIfPresent(servingQuantityUnit, forKey: .servingQuantityUnit)
141156
try container.encodeIfPresent(dataPer, forKey: .dataPer)
142157
try container.encodeIfPresent(categories, forKey: .categories)
143158
try container.encodeIfPresent(imageFront, forKey: .imageFront)
144159
try container.encodeIfPresent(imageIngredients, forKey: .imageIngredients)
145160
try container.encodeIfPresent(imageNutrition, forKey: .imageNutrition)
146161
try container.encodeIfPresent(keywords, forKey: .keywords)
147-
try container.encodeIfPresent(self.lang?.rawValue, forKey: .lang)
162+
try container.encodeIfPresent(lang?.rawValue, forKey: .lang)
163+
try container.encodeIfPresent(nutriScore, forKey: .nutriScore)
164+
try container.encodeIfPresent(novaGroup, forKey: .novaGroup)
148165

149166
if let nutriments = self.nutriments {
150167
var nutrimentsContainer = container.nestedContainer(keyedBy: AnyCodingKey.self, forKey: .nutriments)

Sources/Model/OFF/ProductConfiguration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public struct ProductQueryConfiguration {
1212
var languages: [OpenFoodFactsLanguage]
1313
var fields: [ProductField]?
1414

15-
init(barcode: String,
15+
public init(barcode: String,
1616
languages: [OpenFoodFactsLanguage] = [],
1717
country: OpenFoodFactsCountry? = nil,
1818
fields: [ProductField]? = nil) {

Sources/Model/OFF/ProductField.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import Foundation
99

10-
enum ProductField: String {
10+
public enum ProductField: String {
1111
case barcode = "code"
1212
case name = "product_name"
1313
case nameInLanguages = "product_name_"

Sources/Model/OFF/ProductResponse.swift

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,66 @@ import Foundation
1010
public struct ProductResponse: Decodable {
1111

1212
/// Possible value for [status]: the operation failed.
13-
static let statusFailure = "failure"
13+
public static let statusFailure = "failure"
1414

1515
/// Possible value for [status]: the operation succeeded with warnings.
16-
static let statusWarning = "success_with_warnings"
16+
public static let statusWarning = "success_with_warnings"
1717

1818
/// Possible value for [status]: the operation succeeded.
19-
static let statusSuccess = "success"
19+
public static let statusSuccess = "success"
2020

2121
/// Possible value for [result.id]: product found
22-
static let resultProductFound = "product_found"
22+
public static let resultProductFound = "product_found"
2323

2424
/// Possible value for [result.id]: product not found
25-
static let resultProductNotFound = "product_not_found"
25+
public static let resultProductNotFound = "product_not_found"
2626

27-
let barcode: String?
28-
let status: String?
29-
let product: Product?
27+
public let barcode: String?
28+
public let status: Int?
29+
public let statusVerbose: String?
30+
public let product: Product?
3031

31-
enum CodingKeys: String, CodingKey {
32+
public enum CodingKeys: String, CodingKey {
3233
case barcode = "code"
3334
case status
3435
case product
36+
case statusVerbose = "status_verbose"
3537
}
3638

37-
func hasProduct() -> Bool {
39+
public func hasProduct() -> Bool {
40+
guard let status = self.statusVerbose else { return false }
41+
return status == ProductResponse.resultProductFound || status == ProductResponse.statusSuccess || status == ProductResponse.statusWarning
42+
}
43+
}
44+
45+
public struct ProductResponseV3: Decodable {
46+
47+
/// Possible value for [status]: the operation failed.
48+
public static let statusFailure = "failure"
49+
50+
/// Possible value for [status]: the operation succeeded with warnings.
51+
public static let statusWarning = "success_with_warnings"
52+
53+
/// Possible value for [status]: the operation succeeded.
54+
public static let statusSuccess = "success"
55+
56+
/// Possible value for [result.id]: product found
57+
public static let resultProductFound = "product_found"
58+
59+
/// Possible value for [result.id]: product not found
60+
public static let resultProductNotFound = "product_not_found"
61+
62+
public let barcode: String?
63+
public let status: String?
64+
public let product: Product?
65+
66+
public enum CodingKeys: String, CodingKey {
67+
case barcode = "code"
68+
case status
69+
case product
70+
}
71+
72+
public func hasProduct() -> Bool {
3873
guard let status = self.status else { return false }
3974
return status == ProductResponse.resultProductFound || status == ProductResponse.statusSuccess || status == ProductResponse.statusWarning
4075
}

Sources/Model/OFF/UserAgent.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@ public struct UserAgent: Codable {
3636
var result = ""
3737

3838
let mirror = Mirror(reflecting: self)
39-
for child in mirror.children {
39+
for (index, child) in mirror.children.enumerated() {
4040
if let value = child.value as? String {
41-
result += " - \(value)"
41+
result += "\(value)"
42+
if index < mirror.children.count - 1 {
43+
result += "-"
44+
}
4245
}
4346
}
4447

Sources/Networking/OpenFoodAPIClient.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ final public actor OpenFoodAPIClient {
5353

5454
let queryParameters = config.getParametersMap()
5555

56-
guard let uriPath = UriHelper.getUri(path: "/api/v3/product/\(config.barcode)", queryParameters: queryParameters) else {
56+
guard let uriPath = UriHelper.getUri(path: "/api/v2/product/\(config.barcode)", queryParameters: queryParameters) else {
5757
throw NSError(domain: "Couldn't compose uri for \(#function) call", code: 400)
5858
}
5959
do {
@@ -94,7 +94,7 @@ final public actor OpenFoodAPIClient {
9494
"limit": "\(limit)",
9595
]
9696

97-
guard let uri = UriHelper.getUri(path: "/api/v3/taxonomy_suggestions", queryParameters: queryParameters) else {
97+
guard let uri = UriHelper.getUri(path: "/api/v2/taxonomy_suggestions", queryParameters: queryParameters) else {
9898
throw NSError(domain: "Couldn't compose uri for \(#function) call", code: 400)
9999
}
100100

Sources/OFFConfig.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ final public class OFFConfig {
5353
withSystem: Bool = true, system: String = "",
5454
withId: Bool = true, id: String = "") -> String {
5555
var appInfo = ""
56-
let infoDelimiter = " - "
56+
let infoDelimiter = "-"
5757

5858
if withName {
59-
appInfo += infoDelimiter + name
59+
appInfo += name
6060
}
6161
if withVersion {
6262
appInfo += infoDelimiter + version
@@ -79,9 +79,9 @@ final public class OFFConfig {
7979
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
8080
let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? ""
8181

82-
let version = "\(appVersion)+\(buildNumber)"
83-
let system = "\(UIDevice.current.systemName)+\(UIDevice.current.systemVersion)"
84-
let comment = getAppInfoComment(name: appName, version: version, system: system, id: uuid)
82+
let version = "\(appVersion)_\(buildNumber)"
83+
let system = "\(UIDevice.current.systemName)_\(UIDevice.current.systemVersion)"
84+
let comment = getAppInfoComment(name: appName, version: version, system: system, id: uuid.replacingOccurrences(of: "-", with: ""))
8585

8686
self.userAgent = UserAgent(
8787
name: appName,

0 commit comments

Comments
 (0)