62 lines
1.9 KiB
Swift
62 lines
1.9 KiB
Swift
import Foundation
|
|
import SwiftUI
|
|
|
|
struct ShelfCategory: Identifiable {
|
|
let id: String
|
|
let name: String
|
|
let books: [BookRemote]
|
|
}
|
|
|
|
@MainActor
|
|
final class HomeViewModel: ObservableObject {
|
|
@Published var categories: [ShelfCategory] = []
|
|
|
|
func refresh(from localBooks: [LibraryBook]) {
|
|
var map: [String: [BookRemote]] = [:]
|
|
for local in localBooks {
|
|
let targets = local.categories.isEmpty ? ["Design"] : local.categories
|
|
let remote = Self.makeRemote(from: local)
|
|
for name in targets {
|
|
map[name, default: []].append(remote)
|
|
}
|
|
}
|
|
|
|
let preferred = ["Design", "Psychology", "Novels"]
|
|
var built = preferred.map { name in
|
|
ShelfCategory(id: name, name: name, books: map[name] ?? [])
|
|
}
|
|
|
|
let extras = map.keys
|
|
.filter { !preferred.contains($0) }
|
|
.sorted()
|
|
.map { ShelfCategory(id: $0, name: $0, books: map[$0] ?? []) }
|
|
built.append(contentsOf: extras)
|
|
|
|
categories = built
|
|
}
|
|
|
|
func gradient(for name: String) -> LinearGradient {
|
|
switch name.lowercased() {
|
|
case "design": return Theme.designShelf
|
|
case "psychology": return Theme.psychologyShelf
|
|
case "novels": return Theme.novelsShelf
|
|
default: return Theme.novelsShelf
|
|
}
|
|
}
|
|
|
|
private static func makeRemote(from local: LibraryBook) -> BookRemote {
|
|
BookRemote(
|
|
title: local.title,
|
|
authors: local.authors,
|
|
publishedYear: local.publishedYear,
|
|
isbn10: local.isbn10,
|
|
isbn13: local.isbn13,
|
|
coverImageUrl: local.coverUrlString.flatMap(URL.init(string:)),
|
|
language: local.language,
|
|
description: local.summary,
|
|
categories: local.categories,
|
|
sourceLocale: local.sourceLocale
|
|
)
|
|
}
|
|
}
|