Skip to content

Commit

Permalink
Merge pull request #60 from worthbak/wb/iphone_14
Browse files Browse the repository at this point in the history
Adds iPhone 14 support
  • Loading branch information
worthbak authored Sep 13, 2022
2 parents 2f835eb + 0d10edd commit 3dc6782
Show file tree
Hide file tree
Showing 7 changed files with 1,052 additions and 44 deletions.
16 changes: 10 additions & 6 deletions InventoryWatch.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
380CF9FB27448E860080472A /* iPhoneModels-intl.json in Resources */ = {isa = PBXBuildFile; fileRef = 380CF9FA27448E860080472A /* iPhoneModels-intl.json */; };
380CF9FB27448E860080472A /* iPhoneModels13-intl.json in Resources */ = {isa = PBXBuildFile; fileRef = 380CF9FA27448E860080472A /* iPhoneModels13-intl.json */; };
3817268E273AA898003B8D76 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3817268D273AA898003B8D76 /* SettingsView.swift */; };
386FDC572739DA7300C1BAC2 /* InventoryWatchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 386FDC562739DA7300C1BAC2 /* InventoryWatchApp.swift */; };
386FDC592739DA7300C1BAC2 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 386FDC582739DA7300C1BAC2 /* ContentView.swift */; };
Expand All @@ -16,6 +16,7 @@
386FDC662739DADD00C1BAC2 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 386FDC652739DADD00C1BAC2 /* Model.swift */; };
386FDC68273A18F800C1BAC2 /* SKUData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 386FDC67273A18F800C1BAC2 /* SKUData.swift */; };
386FDC6A273A200000C1BAC2 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 386FDC69273A200000C1BAC2 /* NotificationManager.swift */; };
387F6E7628CCF5B300E68AC0 /* iPhoneModels14-intl.json in Resources */ = {isa = PBXBuildFile; fileRef = 387F6E7528CCF5B300E68AC0 /* iPhoneModels14-intl.json */; };
3885D54C2891711E00BD6A78 /* Store.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3885D54B2891711E00BD6A78 /* Store.swift */; };
3885D54E2891713200BD6A78 /* PartAvailability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3885D54D2891713200BD6A78 /* PartAvailability.swift */; };
3885D5502891714400BD6A78 /* ProductType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3885D54F2891714400BD6A78 /* ProductType.swift */; };
Expand All @@ -29,7 +30,7 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
380CF9FA27448E860080472A /* iPhoneModels-intl.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "iPhoneModels-intl.json"; sourceTree = "<group>"; };
380CF9FA27448E860080472A /* iPhoneModels13-intl.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "iPhoneModels13-intl.json"; sourceTree = "<group>"; };
3817268D273AA898003B8D76 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
386FDC532739DA7300C1BAC2 /* InventoryWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InventoryWatch.app; sourceTree = BUILT_PRODUCTS_DIR; };
386FDC562739DA7300C1BAC2 /* InventoryWatchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InventoryWatchApp.swift; sourceTree = "<group>"; };
Expand All @@ -40,6 +41,7 @@
386FDC652739DADD00C1BAC2 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = "<group>"; };
386FDC67273A18F800C1BAC2 /* SKUData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SKUData.swift; sourceTree = "<group>"; };
386FDC69273A200000C1BAC2 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
387F6E7528CCF5B300E68AC0 /* iPhoneModels14-intl.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "iPhoneModels14-intl.json"; sourceTree = "<group>"; };
3885D54B2891711E00BD6A78 /* Store.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Store.swift; sourceTree = "<group>"; };
3885D54D2891713200BD6A78 /* PartAvailability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartAvailability.swift; sourceTree = "<group>"; };
3885D54F2891714400BD6A78 /* ProductType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductType.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -90,7 +92,8 @@
38E1C21927E6714E0047703D /* Helpers.swift */,
38D307DA2745E2E700A0686D /* Analytics.swift */,
38DBAF38273D6692009992D8 /* Stores.json */,
380CF9FA27448E860080472A /* iPhoneModels-intl.json */,
380CF9FA27448E860080472A /* iPhoneModels13-intl.json */,
387F6E7528CCF5B300E68AC0 /* iPhoneModels14-intl.json */,
386FDC67273A18F800C1BAC2 /* SKUData.swift */,
38D0C3A1273C60B500A7DE65 /* Countries.swift */,
386FDC5A2739DA7300C1BAC2 /* Assets.xcassets */,
Expand Down Expand Up @@ -180,9 +183,10 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
387F6E7628CCF5B300E68AC0 /* iPhoneModels14-intl.json in Resources */,
38E4279E273EF542006BF6D7 /* Credits.rtf in Resources */,
38DBAF39273D6692009992D8 /* Stores.json in Resources */,
380CF9FB27448E860080472A /* iPhoneModels-intl.json in Resources */,
380CF9FB27448E860080472A /* iPhoneModels13-intl.json in Resources */,
386FDC5E2739DA7300C1BAC2 /* Preview Assets.xcassets in Resources */,
386FDC5B2739DA7300C1BAC2 /* Assets.xcassets in Resources */,
);
Expand Down Expand Up @@ -352,7 +356,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.5;
MARKETING_VERSION = 0.1.2;
MARKETING_VERSION = 0.1.3;
PRODUCT_BUNDLE_IDENTIFIER = com.worthbak.InventoryWatch;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down Expand Up @@ -382,7 +386,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.5;
MARKETING_VERSION = 0.1.2;
MARKETING_VERSION = 0.1.3;
PRODUCT_BUNDLE_IDENTIFIER = com.worthbak.InventoryWatch;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down
2 changes: 1 addition & 1 deletion InventoryWatch/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct ContentView: View {


if let preferredStoreInfo = model.preferredStoreInfo {
Text("at \(preferredStoreInfo)")
Text("near \(preferredStoreInfo)")
.font(.title2)
}
}
Expand Down
7 changes: 5 additions & 2 deletions InventoryWatch/Model/AllPhoneModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ struct AllPhoneModels {
let productName: String
}

var proMax13: [PhoneModel]
var pro13: [PhoneModel]
var proMax14: [PhoneModel]
var pro14: [PhoneModel]
var regular14: [PhoneModel]
var plus14: [PhoneModel]

var mini13: [PhoneModel]
var regular13: [PhoneModel]

Expand Down
115 changes: 86 additions & 29 deletions InventoryWatch/Model/Model.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

import Foundation

// TODO
// fetch store data dynamically from:
// https://www.apple.com/rsp-web/store-list?locale=en_US

final class Model: ObservableObject {
enum ModelError: Swift.Error, LocalizedError {
case couldNotGenerateURL
Expand Down Expand Up @@ -69,36 +73,58 @@ final class Model: ObservableObject {
}()

lazy private var iPhoneModels: [Country: AllPhoneModels] = {
let phoneModelsJson = loadIPhoneModels()
var rv = [Country: AllPhoneModels]()

for (countryCode, phones) in phoneModelsJson {
guard let country = Countries[countryCode.uppercased()] else {
self.updateErrorState(to: ModelError.invalidLocalModelStore)
return [:]
}

let modelsData = [
(phones["proMax13"], \AllPhoneModels.proMax13),
(phones["pro13"], \AllPhoneModels.pro13),
(phones["mini13"], \AllPhoneModels.mini13),
(phones["regular13"], \AllPhoneModels.regular13)
]
for phoneModel in iPhoneModel.allCases {
let phoneModelsJson = loadIPhoneModels(for: phoneModel)

var phoneModels = AllPhoneModels(proMax13: [], pro13: [], mini13: [], regular13: [])
for (models, keyPath) in modelsData {
guard let models = models else {
continue
for (countryCode, phones) in phoneModelsJson {
guard let country = Countries[countryCode.uppercased()] else {
self.updateErrorState(to: ModelError.invalidLocalModelStore)
return [:]
}

let unmappedModelsData: [(String, WritableKeyPath<AllPhoneModels, [AllPhoneModels.PhoneModel]>)]
switch phoneModel {
case .thirteen:
unmappedModelsData = [
("mini13", \AllPhoneModels.mini13),
("regular13", \AllPhoneModels.regular13)
]
case .fourteen:
unmappedModelsData = [
("plus14", \AllPhoneModels.plus14),
("regular14", \AllPhoneModels.regular14),
("pro14", \AllPhoneModels.pro14),
("proMax14", \AllPhoneModels.proMax14)
]
}

let parsed: [AllPhoneModels.PhoneModel] = models.map { modelData in
return AllPhoneModels.PhoneModel(sku: modelData.key, productName: modelData.value)
let modelsData = unmappedModelsData.map { first, second in
return (phones[first], second)
}

var phoneModels: AllPhoneModels
if let existing = rv[country] {
phoneModels = existing
} else {
phoneModels = AllPhoneModels(proMax14: [], pro14: [], regular14: [], plus14: [], mini13: [], regular13: [])
}

for (models, keyPath) in modelsData {
guard let models = models else {
continue
}

let parsed: [AllPhoneModels.PhoneModel] = models.map { modelData in
return AllPhoneModels.PhoneModel(sku: modelData.key, productName: modelData.value)
}

phoneModels[keyPath: keyPath] = parsed
}

phoneModels[keyPath: keyPath] = parsed
rv[country] = phoneModels
}

rv[country] = phoneModels
}

return rv
Expand All @@ -107,22 +133,49 @@ final class Model: ObservableObject {
func phoneModels(for country: Country) -> AllPhoneModels {
guard let models = iPhoneModels[country] else {
self.updateErrorState(to: ModelError.invalidLocalModelStore)
return AllPhoneModels(proMax13: [], pro13: [], mini13: [], regular13: [])
return AllPhoneModels(proMax14: [], pro14: [], regular14: [], plus14: [], mini13: [], regular13: [])
}

return models
}

private var cachedPhoneData13: [String: [String: [String: String]]]?
private var cachedPhoneData14: [String: [String: [String: String]]]?

private enum iPhoneModel: CaseIterable {
case thirteen, fourteen
}

// country: type: model: description
private func loadIPhoneModels() -> [String: [String: [String: String]]] {
let location = "iPhoneModels-intl"
private func loadIPhoneModels(for model: iPhoneModel) -> [String: [String: [String: String]]] {
let location: String
switch model {
case .thirteen:
if let cached = cachedPhoneData13 {
return cached
} else {
location = "iPhoneModels13-intl"
}
case .fourteen:
if let cached = cachedPhoneData14 {
return cached
} else {
location = "iPhoneModels14-intl"
}
}

let fileType = "json"
if let path = Bundle.main.path(forResource: location, ofType: fileType) {
do {
let data = try Data(contentsOf: URL(fileURLWithPath: path))
let decoder = JSONDecoder()

if let jsonStores = try? decoder.decode([String: [String: [String: String]]].self, from: data) {
switch model {
case .thirteen: cachedPhoneData13 = jsonStores
case .fourteen: cachedPhoneData14 = jsonStores
}

return jsonStores
} else {
return [:]
Expand Down Expand Up @@ -201,10 +254,14 @@ final class Model: ObservableObject {
return phoneModels(for: country).toSkuData(\.regular13)
case .iPhoneMini13:
return phoneModels(for: country).toSkuData(\.mini13)
case .iPhonePro13:
return phoneModels(for: country).toSkuData(\.pro13)
case .iPhoneProMax13:
return phoneModels(for: country).toSkuData(\.proMax13)
case .iPhoneRegular14:
return phoneModels(for: country).toSkuData(\.regular14)
case .iPhonePlus14:
return phoneModels(for: country).toSkuData(\.plus14)
case .iPhonePro14:
return phoneModels(for: country).toSkuData(\.pro14)
case .iPhoneProMax14:
return phoneModels(for: country).toSkuData(\.proMax14)
}
}

Expand Down
18 changes: 12 additions & 6 deletions InventoryWatch/Model/ProductType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ enum ProductType: String, Codable, CaseIterable, Identifiable {
case iPadCellular
case iPhoneRegular13
case iPhoneMini13
case iPhonePro13
case iPhoneProMax13
case iPhoneRegular14
case iPhonePlus14
case iPhonePro14
case iPhoneProMax14

var presentableName: String {
switch self {
Expand All @@ -42,10 +44,14 @@ enum ProductType: String, Codable, CaseIterable, Identifiable {
return "iPhone 13"
case .iPhoneMini13:
return "iPhone 13 mini"
case .iPhonePro13:
return "iPhone 13 Pro"
case .iPhoneProMax13:
return "iPhone 13 Pro Max"
case .iPhoneRegular14:
return "iPhone 14"
case .iPhonePlus14:
return "iPhone 14 Plus"
case .iPhonePro14:
return "iPhone 14 Pro"
case .iPhoneProMax14:
return "iPhone 14 Pro Max"
}
}
}
File renamed without changes.
Loading

0 comments on commit 3dc6782

Please sign in to comment.