Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CoffeeKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
158467B1235A99AC00D0DAF6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 158467B0235A99AC00D0DAF6 /* Assets.xcassets */; };
158467B4235A99AC00D0DAF6 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 158467B3235A99AC00D0DAF6 /* Preview Assets.xcassets */; };
158467C2235A99AC00D0DAF6 /* CoffeeKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 158467C1235A99AC00D0DAF6 /* CoffeeKitTests.swift */; };
2C429B7523E7EB4B0013394B /* ImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C429B7423E7EB4B0013394B /* ImageView.swift */; };
2C429B7723E7EBE60013394B /* ImageLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C429B7623E7EBE60013394B /* ImageLoader.swift */; };
2C6BFBD523ADA26E0025DC5D /* CoffeeStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C6BFBD423ADA26E0025DC5D /* CoffeeStepView.swift */; };
2CD8356E2388B63A003B9F6F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2CD835702388B63A003B9F6F /* Localizable.strings */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -56,6 +59,9 @@
158467BD235A99AC00D0DAF6 /* CoffeeKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoffeeKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
158467C1235A99AC00D0DAF6 /* CoffeeKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoffeeKitTests.swift; sourceTree = "<group>"; };
158467C3235A99AC00D0DAF6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
2C429B7423E7EB4B0013394B /* ImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageView.swift; sourceTree = "<group>"; };
2C429B7623E7EBE60013394B /* ImageLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageLoader.swift; sourceTree = "<group>"; };
2C6BFBD423ADA26E0025DC5D /* CoffeeStepView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoffeeStepView.swift; sourceTree = "<group>"; };
2CD8356F2388B63A003B9F6F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
2CD835712388B641003B9F6F /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand All @@ -81,8 +87,10 @@
035B074E237F8F0F004287DB /* Views */ = {
isa = PBXGroup;
children = (
2C6BFBD423ADA26E0025DC5D /* CoffeeStepView.swift */,
158467AE235A99A800D0DAF6 /* ContentView.swift */,
035B0755237F904F004287DB /* CoffeeCell.swift */,
2C429B7423E7EB4B0013394B /* ImageView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -121,6 +129,7 @@
isa = PBXGroup;
children = (
035B075D237F9640004287DB /* LocalDataService.swift */,
2C429B7623E7EBE60013394B /* ImageLoader.swift */,
);
path = Services;
sourceTree = "<group>";
Expand Down Expand Up @@ -302,9 +311,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2C429B7723E7EBE60013394B /* ImageLoader.swift in Sources */,
158467AB235A99A800D0DAF6 /* AppDelegate.swift in Sources */,
158467AD235A99A800D0DAF6 /* SceneDelegate.swift in Sources */,
2C6BFBD523ADA26E0025DC5D /* CoffeeStepView.swift in Sources */,
0318D9CA239B46F100643730 /* Ingredient.swift in Sources */,
2C429B7523E7EB4B0013394B /* ImageView.swift in Sources */,
0318D9CE239B4BC500643730 /* PreparationStep.swift in Sources */,
0318D9C8239B431000643730 /* Grind.swift in Sources */,
0318D9CC239B4A3900643730 /* Equipment.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions CoffeeKit/Delegates/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {

// Create the SwiftUI view that provides the window contents.

// read data about known coffees from somewhere - for now, built-in service which reads app-bundle json, later update for remote server data
guard let coffees = LocalDataService.data() else {
return
}
Expand Down
56 changes: 56 additions & 0 deletions CoffeeKit/Models/Coffee.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,59 @@ extension Coffee: Hashable {
hasher.combine(id)
}
}

#if DEBUG
// this is a subset of an entry from the data.json

let testCoffees = LocalDataService.data()

// lets try for two which should be in the data.json, with default fallback so not optional in previews
let testCoffeeStovetop: Coffee = testCoffees?.first(where: {$0.name == "Stovetop Espresso"}) ?? Coffee(id: "99",
name: "Espresso",
grind: .fine,
ingredients: [],
equipment: Equipment(filter: nil,
machine: "Espresso machine",
tamper: true),
steps: [PreparationStep(order: 9,
imageUrlString: nil,
instruction: "some words for machine expresso",
duration: 0.0,
resourceUrlString: nil)]
)

// and a guaranteed one as created here, independent of data.json
let testCoffeeDebug = Coffee(id: "99",
name: "Espresso",
grind: .fine,
ingredients: [Ingredient(name: "beans",
quantity: 30.0,
metric: "grams"),
Ingredient(name: "water",
quantity: 60.0,
metric: "millilitres")],
equipment: Equipment(filter: nil,
machine: "Espresso pot",
tamper: true),
steps: [PreparationStep(order: 0,
imageUrlString: "https://placekitten.com/200/200",
instruction: "Remove the funnel from the base, fill the base with water to just below the safety valve.\n\nThe valve is a small fitting on the side of the lower part of the pot, usually attached by a hexagonal nut)",
duration: 120.0,
resourceUrlString: "https://www.youtube.com/watch?v=A8MFlzT07SU"),
PreparationStep(order: 1,
imageUrlString: nil,
instruction: "Place the funnel into the base, and slightly overfill with coffee grounds",
duration: 0.0,
resourceUrlString: ""),
PreparationStep(order: 2,
imageUrlString: "https://loremflickr.com/200/200/dog",
instruction: "Tamp down the coffee, wipe off any excess grounds, before screwing the top firmly onto the bottom",
duration: 0.0,
resourceUrlString: nil),
PreparationStep(order: 3,
imageUrlString: "https://loremflickr.com/g/200/200/paris",
instruction: "Put on gentle heat, ensuring the handle is NOT in rising high heat",
duration: 0.0,
resourceUrlString: nil)])

#endif
6 changes: 6 additions & 0 deletions CoffeeKit/Models/PreparationStep.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@

import Foundation

/// data about one step in making coffee
struct PreparationStep: Codable {
/// steps are presented sorted by order i.e. they are sequential, not a set
let order: Int
/// if present has URL for some image (thumbnail etc) of what this step looks like
let imageUrlString: String?
/// string description (how will we handle localization of this?) for this step.
let instruction: String
/// time for this step in seconds. Does this really need a non-integer type ?
let duration: Double
/// if present, URL links to more info such as a more detail webpage or a video.. probably in a WKWebview inside a UIViewRepresentable
let resourceUrlString: String?
}
Loading