Skip to content

Commit

Permalink
SwiftUI: Refactor OPDS facets (#501)
Browse files Browse the repository at this point in the history
  • Loading branch information
FuzzzzyBoy authored Nov 19, 2024
1 parent 165440b commit 1348437
Show file tree
Hide file tree
Showing 11 changed files with 365 additions and 140 deletions.
61 changes: 29 additions & 32 deletions TestApp/Sources/OPDS/Base.lproj/OPDS.storyboard

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions TestApp/Sources/OPDS/OPDSCatalogs/OPDSCatalogsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
import SwiftUI

struct OPDSCatalogsView: View {
@StateObject private var viewModel: OPDSCatalogsViewModel
@State private var viewModel: OPDSCatalogsViewModel

init(viewModel: OPDSCatalogsViewModel) {
_viewModel = StateObject(wrappedValue: viewModel)
self.viewModel = viewModel
}

var body: some View {
Expand Down
7 changes: 4 additions & 3 deletions TestApp/Sources/OPDS/OPDSCatalogs/OPDSCatalogsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

import Foundation

final class OPDSCatalogsViewModel: ObservableObject {
@Published var catalogs: [OPDSCatalog] = [] {
@Observable
final class OPDSCatalogsViewModel {
var catalogs: [OPDSCatalog] = [] {
didSet {
UserDefaults.standard.set(
catalogs.map(\.toDictionary),
Expand All @@ -16,7 +17,7 @@ final class OPDSCatalogsViewModel: ObservableObject {
}
}

@Published var editingCatalog: OPDSCatalog?
var editingCatalog: OPDSCatalog?

var openCatalog: ((URL, IndexPath) -> Void)?

Expand Down
77 changes: 0 additions & 77 deletions TestApp/Sources/OPDS/OPDSFacetViewController.swift

This file was deleted.

222 changes: 222 additions & 0 deletions TestApp/Sources/OPDS/OPDSFacets/Feed+preview.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
//
// Copyright 2024 Readium Foundation. All rights reserved.
// Use of this source code is governed by the BSD-style license
// available in the top-level LICENSE file of the project.
//

import Foundation
import ReadiumOPDS
import ReadiumShared

extension Feed {
static var preview: Feed {
try! OPDS2Parser.parse(
jsonData: .preview,
url: URL(string: "http://opds-spec.org/opds.json")!,
response: URLResponse()
).feed!
}
}

private extension Data {
static var preview: Data {
let jsonString = """
{
"@context": "http://opds-spec.org/opds.json",
"metadata": {
"title": "Example Library",
"modified": "2024-11-05T12:00:00Z",
"numberOfItems": 5000,
"itemsPerPage": 30
},
"links": [
{
"rel": "self",
"href": "/opds",
"type": "application/opds+json"
}
],
"facets": [
{
"metadata": {
"title": "Genre"
},
"links": [
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?genre=fiction",
"title": "Fiction",
"type": "application/opds+json",
"properties": {
"numberOfItems": 1250
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?genre=mystery",
"title": "Mystery & Detective",
"type": "application/opds+json",
"properties": {
"numberOfItems": 850
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?genre=scifi",
"title": "Science Fiction",
"type": "application/opds+json",
"properties": {
"numberOfItems": 725
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?genre=non-fiction",
"title": "Non-Fiction",
"type": "application/opds+json",
"properties": {
"numberOfItems": 2175
}
}
]
},
{
"metadata": {
"title": "Language"
},
"links": [
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?language=en",
"title": "English",
"type": "application/opds+json",
"properties": {
"numberOfItems": 3000
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?language=es",
"title": "Spanish",
"type": "application/opds+json",
"properties": {
"numberOfItems": 1000
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?language=ru",
"title": "Russian",
"type": "application/opds+json",
"properties": {
"numberOfItems": 800
}
}
]
},
{
"metadata": {
"title": "Availability"
},
"links": [
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?availability=free",
"title": "Free",
"type": "application/opds+json",
"properties": {
"numberOfItems": 1500
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?availability=subscription",
"title": "Subscription",
"type": "application/opds+json",
"properties": {
"numberOfItems": 2500
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?availability=buy",
"title": "Purchase Required",
"type": "application/opds+json",
"properties": {
"numberOfItems": 1000
}
}
]
},
{
"metadata": {
"title": "Reading Age"
},
"links": [
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?age=children",
"title": "Children (0-11)",
"type": "application/opds+json",
"properties": {
"numberOfItems": 800
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?age=teen",
"title": "Teen (12-18)",
"type": "application/opds+json",
"properties": {
"numberOfItems": 1200
}
},
{
"rel": "http://opds-spec.org/facet",
"href": "/opds/books/new?age=adult",
"title": "Adult (18+)",
"type": "application/opds+json",
"properties": {
"numberOfItems": 3000
}
}
]
}
],
"publications": [
{
"metadata": {
"title": "Sample Book",
"identifier": "urn:uuid:6409a00b-7bf2-405e-826c-3fdff0fd0734",
"modified": "2024-11-05T12:00:00Z",
"language": ["en"],
"published": "2024",
"author": [
{
"name": "Sample Author"
}
],
"subject": [
{
"name": "Fiction",
"code": "fiction"
}
]
},
"links": [
{
"rel": "http://opds-spec.org/acquisition",
"href": "/books/sample.epub",
"type": "application/epub+zip"
}
]
}
]
}
"""
guard let data = jsonString.data(using: .utf8) else {
return Data()
}
return data
}
}
39 changes: 39 additions & 0 deletions TestApp/Sources/OPDS/OPDSFacets/OPDSFacetLink.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// Copyright 2024 Readium Foundation. All rights reserved.
// Use of this source code is governed by the BSD-style license
// available in the top-level LICENSE file of the project.
//

import ReadiumShared
import SwiftUI

struct OPDSFacetLink: View {
let link: ReadiumShared.Link

var body: some View {
HStack {
if let title = link.title {
Text(title)
.foregroundStyle(Color.primary)
}

Spacer()

if let count = link.properties.numberOfItems {
Text("\(count)")
.foregroundStyle(Color.secondary)
.font(.subheadline)
}

Image(systemName: "chevron.right")
}
.font(.body)
}
}

#Preview {
OPDSFacetLink(
link: Feed.preview.facets[0].links[0]
)
.padding()
}
Loading

0 comments on commit 1348437

Please sign in to comment.