WIP - Complete App refactoring
This commit is contained in:
@@ -32,7 +32,7 @@ protocol CookbookApi {
|
||||
static func importRecipe(
|
||||
auth: String,
|
||||
data: Data
|
||||
) async -> (RecipeDetail?, NetworkError?)
|
||||
) async -> (Recipe?, NetworkError?)
|
||||
|
||||
/// Get either the full image or a thumbnail sized version.
|
||||
/// - Parameters:
|
||||
@@ -42,7 +42,7 @@ protocol CookbookApi {
|
||||
/// - Returns: The image of the recipe with the specified id. A NetworkError if the request fails, otherwise nil.
|
||||
static func getImage(
|
||||
auth: String,
|
||||
id: Int,
|
||||
id: String,
|
||||
size: RecipeImage.RecipeImageSize
|
||||
) async -> (UIImage?, NetworkError?)
|
||||
|
||||
@@ -52,7 +52,7 @@ protocol CookbookApi {
|
||||
/// - Returns: A list of all recipes.
|
||||
static func getRecipes(
|
||||
auth: String
|
||||
) async -> ([Recipe]?, NetworkError?)
|
||||
) async -> ([RecipeStub]?, NetworkError?)
|
||||
|
||||
/// Create a new recipe.
|
||||
/// - Parameters:
|
||||
@@ -60,7 +60,7 @@ protocol CookbookApi {
|
||||
/// - Returns: A NetworkError if the request fails. Nil otherwise.
|
||||
static func createRecipe(
|
||||
auth: String,
|
||||
recipe: RecipeDetail
|
||||
recipe: Recipe
|
||||
) async -> (NetworkError?)
|
||||
|
||||
/// Get the recipe with the specified id.
|
||||
@@ -69,8 +69,9 @@ protocol CookbookApi {
|
||||
/// - id: The recipe id.
|
||||
/// - Returns: The recipe if it exists. A NetworkError if the request fails.
|
||||
static func getRecipe(
|
||||
auth: String, id: Int
|
||||
) async -> (RecipeDetail?, NetworkError?)
|
||||
auth: String,
|
||||
id: String
|
||||
) async -> (Recipe?, NetworkError?)
|
||||
|
||||
/// Update an existing recipe with new entries.
|
||||
/// - Parameters:
|
||||
@@ -79,7 +80,7 @@ protocol CookbookApi {
|
||||
/// - Returns: A NetworkError if the request fails. Nil otherwise.
|
||||
static func updateRecipe(
|
||||
auth: String,
|
||||
recipe: RecipeDetail
|
||||
recipe: Recipe
|
||||
) async -> (NetworkError?)
|
||||
|
||||
/// Delete the recipe with the specified id.
|
||||
@@ -89,7 +90,7 @@ protocol CookbookApi {
|
||||
/// - Returns: A NetworkError if the request fails. Nil otherwise.
|
||||
static func deleteRecipe(
|
||||
auth: String,
|
||||
id: Int
|
||||
id: String
|
||||
) async -> (NetworkError?)
|
||||
|
||||
/// Get all categories.
|
||||
@@ -108,7 +109,7 @@ protocol CookbookApi {
|
||||
static func getCategory(
|
||||
auth: String,
|
||||
named categoryName: String
|
||||
) async -> ([Recipe]?, NetworkError?)
|
||||
) async -> ([RecipeStub]?, NetworkError?)
|
||||
|
||||
/// Rename an existing category.
|
||||
/// - Parameters:
|
||||
@@ -138,7 +139,7 @@ protocol CookbookApi {
|
||||
static func getRecipesTagged(
|
||||
auth: String,
|
||||
keyword: String
|
||||
) async -> ([Recipe]?, NetworkError?)
|
||||
) async -> ([RecipeStub]?, NetworkError?)
|
||||
|
||||
/// Get the servers api version.
|
||||
/// - Parameters:
|
||||
@@ -176,3 +177,4 @@ protocol CookbookApi {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import UIKit
|
||||
class CookbookApiV1: CookbookApi {
|
||||
static let basePath: String = "/index.php/apps/cookbook/api/v1"
|
||||
|
||||
static func importRecipe(auth: String, data: Data) async -> (RecipeDetail?, NetworkError?) {
|
||||
static func importRecipe(auth: String, data: Data) async -> (Recipe?, NetworkError?) {
|
||||
let request = ApiRequest(
|
||||
path: basePath + "/import",
|
||||
method: .POST,
|
||||
@@ -22,10 +22,12 @@ class CookbookApiV1: CookbookApi {
|
||||
|
||||
let (data, error) = await request.send()
|
||||
guard let data = data else { return (nil, error) }
|
||||
return (JSONDecoder.safeDecode(data), nil)
|
||||
let recipe: CookbookApiRecipeDetailV1? = JSONDecoder.safeDecode(data)
|
||||
return (recipe?.toRecipe(), error)
|
||||
}
|
||||
|
||||
static func getImage(auth: String, id: Int, size: RecipeImage.RecipeImageSize) async -> (UIImage?, NetworkError?) {
|
||||
static func getImage(auth: String, id: String, size: RecipeImage.RecipeImageSize) async -> (UIImage?, NetworkError?) {
|
||||
guard let id = Int(id) else {return (nil, .unknownError)}
|
||||
let imageSize = (size == .FULL ? "full" : "thumb")
|
||||
let request = ApiRequest(
|
||||
path: basePath + "/recipes/\(id)/image?size=\(imageSize)",
|
||||
@@ -39,7 +41,7 @@ class CookbookApiV1: CookbookApi {
|
||||
return (UIImage(data: data), error)
|
||||
}
|
||||
|
||||
static func getRecipes(auth: String) async -> ([Recipe]?, NetworkError?) {
|
||||
static func getRecipes(auth: String) async -> ([RecipeStub]?, NetworkError?) {
|
||||
let request = ApiRequest(
|
||||
path: basePath + "/recipes",
|
||||
method: .GET,
|
||||
@@ -50,10 +52,12 @@ class CookbookApiV1: CookbookApi {
|
||||
let (data, error) = await request.send()
|
||||
guard let data = data else { return (nil, error) }
|
||||
print("\n\nRECIPE: ", String(data: data, encoding: .utf8))
|
||||
return (JSONDecoder.safeDecode(data), nil)
|
||||
let recipes: [CookbookApiRecipeV1]? = JSONDecoder.safeDecode(data)
|
||||
return (recipes?.map({ recipe in recipe.toRecipeStub() }), nil)
|
||||
}
|
||||
|
||||
static func createRecipe(auth: String, recipe: RecipeDetail) async -> (NetworkError?) {
|
||||
static func createRecipe(auth: String, recipe: Recipe) async -> (NetworkError?) {
|
||||
let recipe = CookbookApiRecipeDetailV1.fromRecipe(recipe)
|
||||
guard let recipeData = JSONEncoder.safeEncode(recipe) else {
|
||||
return .dataError
|
||||
}
|
||||
@@ -81,7 +85,8 @@ class CookbookApiV1: CookbookApi {
|
||||
return nil
|
||||
}
|
||||
|
||||
static func getRecipe(auth: String, id: Int) async -> (RecipeDetail?, NetworkError?) {
|
||||
static func getRecipe(auth: String, id: String) async -> (Recipe?, NetworkError?) {
|
||||
guard let id = Int(id) else {return (nil, .unknownError)}
|
||||
let request = ApiRequest(
|
||||
path: basePath + "/recipes/\(id)",
|
||||
method: .GET,
|
||||
@@ -91,10 +96,13 @@ class CookbookApiV1: CookbookApi {
|
||||
|
||||
let (data, error) = await request.send()
|
||||
guard let data = data else { return (nil, error) }
|
||||
return (JSONDecoder.safeDecode(data), nil)
|
||||
|
||||
let recipe: CookbookApiRecipeDetailV1? = JSONDecoder.safeDecode(data)
|
||||
return (recipe?.toRecipe(), nil)
|
||||
}
|
||||
|
||||
static func updateRecipe(auth: String, recipe: RecipeDetail) async -> (NetworkError?) {
|
||||
static func updateRecipe(auth: String, recipe: Recipe) async -> (NetworkError?) {
|
||||
let cookbookRecipe = CookbookApiRecipeDetailV1.fromRecipe(recipe)
|
||||
guard let recipeData = JSONEncoder.safeEncode(recipe) else {
|
||||
return .dataError
|
||||
}
|
||||
@@ -121,7 +129,8 @@ class CookbookApiV1: CookbookApi {
|
||||
return nil
|
||||
}
|
||||
|
||||
static func deleteRecipe(auth: String, id: Int) async -> (NetworkError?) {
|
||||
static func deleteRecipe(auth: String, id: String) async -> (NetworkError?) {
|
||||
guard let id = Int(id) else {return .unknownError}
|
||||
let request = ApiRequest(
|
||||
path: basePath + "/recipes/\(id)",
|
||||
method: .DELETE,
|
||||
@@ -147,7 +156,7 @@ class CookbookApiV1: CookbookApi {
|
||||
return (JSONDecoder.safeDecode(data), nil)
|
||||
}
|
||||
|
||||
static func getCategory(auth: String, named categoryName: String) async -> ([Recipe]?, NetworkError?) {
|
||||
static func getCategory(auth: String, named categoryName: String) async -> ([RecipeStub]?, NetworkError?) {
|
||||
let request = ApiRequest(
|
||||
path: basePath + "/category/\(categoryName)",
|
||||
method: .GET,
|
||||
@@ -157,7 +166,8 @@ class CookbookApiV1: CookbookApi {
|
||||
|
||||
let (data, error) = await request.send()
|
||||
guard let data = data else { return (nil, error) }
|
||||
return (JSONDecoder.safeDecode(data), nil)
|
||||
let recipes: [CookbookApiRecipeV1]? = JSONDecoder.safeDecode(data)
|
||||
return (recipes?.map({ recipe in recipe.toRecipeStub() }), nil)
|
||||
}
|
||||
|
||||
static func renameCategory(auth: String, named categoryName: String, newName: String) async -> (NetworkError?) {
|
||||
@@ -186,7 +196,7 @@ class CookbookApiV1: CookbookApi {
|
||||
return (JSONDecoder.safeDecode(data), nil)
|
||||
}
|
||||
|
||||
static func getRecipesTagged(auth: String, keyword: String) async -> ([Recipe]?, NetworkError?) {
|
||||
static func getRecipesTagged(auth: String, keyword: String) async -> ([RecipeStub]?, NetworkError?) {
|
||||
let request = ApiRequest(
|
||||
path: basePath + "/tags/\(keyword)",
|
||||
method: .GET,
|
||||
@@ -196,7 +206,8 @@ class CookbookApiV1: CookbookApi {
|
||||
|
||||
let (data, error) = await request.send()
|
||||
guard let data = data else { return (nil, error) }
|
||||
return (JSONDecoder.safeDecode(data), nil)
|
||||
let recipes: [CookbookApiRecipeV1]? = JSONDecoder.safeDecode(data)
|
||||
return (recipes?.map({ recipe in recipe.toRecipeStub() }), nil)
|
||||
}
|
||||
|
||||
static func getApiVersion(auth: String) async -> (NetworkError?) {
|
||||
@@ -215,3 +226,4 @@ class CookbookApiV1: CookbookApi {
|
||||
return .none
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Models.swift
|
||||
// CookbookLoginModels.swift
|
||||
// Nextcloud Cookbook iOS Client
|
||||
//
|
||||
// Created by Vincent Meilinger on 11.05.24.
|
||||
@@ -9,10 +9,7 @@ import Foundation
|
||||
import SwiftUI
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// MARK: - Login flow
|
||||
// MARK: - Login Models
|
||||
|
||||
struct LoginV2Request: Codable {
|
||||
let poll: LoginV2Poll
|
||||
|
||||
@@ -8,8 +8,18 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
struct Category: Codable, Identifiable, Hashable {
|
||||
var id: String { name }
|
||||
let name: String
|
||||
let recipe_count: Int
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case name, recipe_count
|
||||
}
|
||||
}
|
||||
|
||||
struct CookbookApiRecipeV1: Codable {
|
||||
struct CookbookApiRecipeV1: CookbookApiRecipe, Codable, Identifiable, Hashable {
|
||||
var id: String { name + String(recipe_id) }
|
||||
let name: String
|
||||
let keywords: String?
|
||||
let dateCreated: String?
|
||||
@@ -24,15 +34,22 @@ struct CookbookApiRecipeV1: Codable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case name, keywords, dateCreated, dateModified, imageUrl, imagePlaceholderUrl, recipe_id
|
||||
}
|
||||
|
||||
func toRecipeStub() -> RecipeStub {
|
||||
return RecipeStub(
|
||||
id: String(recipe_id),
|
||||
name: name,
|
||||
keywords: keywords,
|
||||
dateCreated: dateCreated,
|
||||
dateModified: dateModified,
|
||||
thumbnailPath: nil
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension CookbookApiRecipeV1: Identifiable, Hashable {
|
||||
var id: String { name }
|
||||
}
|
||||
|
||||
|
||||
struct CookbookApiRecipeDetailV1: Codable {
|
||||
struct CookbookApiRecipeDetailV1: CookbookApiRecipeDetail {
|
||||
var name: String
|
||||
var keywords: String
|
||||
var dateCreated: String?
|
||||
@@ -51,7 +68,7 @@ struct CookbookApiRecipeDetailV1: Codable {
|
||||
var recipeInstructions: [String]
|
||||
var nutrition: [String:String]
|
||||
|
||||
init(name: String, keywords: String, dateCreated: String, dateModified: String, imageUrl: String, id: String, prepTime: String? = nil, cookTime: String? = nil, totalTime: String? = nil, description: String, url: String, recipeYield: Int, recipeCategory: String, tool: [String], recipeIngredient: [String], recipeInstructions: [String], nutrition: [String:String]) {
|
||||
init(name: String, keywords: String, dateCreated: String?, dateModified: String?, imageUrl: String?, id: String, prepTime: String? = nil, cookTime: String? = nil, totalTime: String? = nil, description: String, url: String?, recipeYield: Int, recipeCategory: String, tool: [String], recipeIngredient: [String], recipeInstructions: [String], nutrition: [String:String]) {
|
||||
self.name = name
|
||||
self.keywords = keywords
|
||||
self.dateCreated = dateCreated
|
||||
@@ -117,6 +134,47 @@ struct CookbookApiRecipeDetailV1: Codable {
|
||||
|
||||
nutrition = try container.decode(Dictionary<String, JSONAny>.self, forKey: .nutrition).mapValues { String(describing: $0.value) }
|
||||
}
|
||||
|
||||
func toRecipe() -> Recipe {
|
||||
return Recipe(
|
||||
id: self.id,
|
||||
name: self.name,
|
||||
keywords: keywords.components(separatedBy: ","),
|
||||
dateCreated: self.dateCreated,
|
||||
dateModified: self.dateModified,
|
||||
prepTime: self.prepTime ?? "",
|
||||
cookTime: self.cookTime ?? "",
|
||||
totalTime: self.totalTime ?? "",
|
||||
recipeDescription: self.description,
|
||||
url: self.url,
|
||||
yield: self.recipeYield,
|
||||
category: self.recipeCategory,
|
||||
tools: self.tool,
|
||||
ingredients: self.recipeIngredient,
|
||||
instructions: self.recipeInstructions,
|
||||
nutrition: self.nutrition,
|
||||
ingredientMultiplier: 1.0
|
||||
)
|
||||
}
|
||||
|
||||
static func fromRecipe(_ recipe: Recipe) -> any CookbookApiRecipeDetail {
|
||||
return CookbookApiRecipeDetailV1(
|
||||
name: recipe.name,
|
||||
keywords: recipe.keywords.joined(separator: ","),
|
||||
dateCreated: recipe.dateCreated,
|
||||
dateModified: recipe.dateModified,
|
||||
imageUrl: "",
|
||||
id: recipe.id,
|
||||
description: recipe.recipeDescription,
|
||||
url: recipe.url,
|
||||
recipeYield: recipe.yield,
|
||||
recipeCategory: recipe.category,
|
||||
tool: recipe.tools,
|
||||
recipeIngredient: recipe.ingredients,
|
||||
recipeInstructions: recipe.instructions,
|
||||
nutrition: recipe.nutrition
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -155,7 +213,7 @@ extension CookbookApiRecipeDetailV1 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
struct RecipeImage {
|
||||
enum RecipeImageSize: String {
|
||||
case THUMB="thumb", FULL="full"
|
||||
@@ -164,7 +222,7 @@ struct RecipeImage {
|
||||
var thumb: UIImage?
|
||||
var full: UIImage?
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
struct RecipeKeyword: Codable {
|
||||
let name: String
|
||||
@@ -244,3 +302,4 @@ enum Nutrition: CaseIterable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,3 +6,13 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
protocol CookbookApiRecipe {
|
||||
func toRecipeStub() -> RecipeStub
|
||||
}
|
||||
|
||||
protocol CookbookApiRecipeDetail: Codable {
|
||||
func toRecipe() -> Recipe
|
||||
static func fromRecipe(_ recipe: Recipe) -> CookbookApiRecipeDetail
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user