Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document and demo Transport #103

Merged
merged 4 commits into from
Oct 24, 2024
Merged
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
4 changes: 4 additions & 0 deletions Examples/BlocksApp/BlocksApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
008D62CC2A56C35800254FD9 /* ImagePickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 008D62CB2A56C35800254FD9 /* ImagePickerView.swift */; };
008D62CE2A56C96E00254FD9 /* MailComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 008D62CD2A56C96E00254FD9 /* MailComposeView.swift */; };
008D62D02A56EA1500254FD9 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 008D62CF2A56EA1500254FD9 /* UniformTypeIdentifiers.framework */; };
00A12BF42CC0F84B0006D9F7 /* TransportDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00A12BF32CC0F8450006D9F7 /* TransportDemoView.swift */; };
00A37E302B1911A800FA4B5F /* FileSystemExplorerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00A37E2F2B1911A800FA4B5F /* FileSystemExplorerView.swift */; };
00A37E322B19135400FA4B5F /* ObjectiveBlocks in Frameworks */ = {isa = PBXBuildFile; productRef = 00A37E312B19135400FA4B5F /* ObjectiveBlocks */; };
00D1E2482A36327100E8D275 /* BlocksApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00D1E2472A36327100E8D275 /* BlocksApp.swift */; };
Expand Down Expand Up @@ -61,6 +62,7 @@
008D62CB2A56C35800254FD9 /* ImagePickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePickerView.swift; sourceTree = "<group>"; };
008D62CD2A56C96E00254FD9 /* MailComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailComposeView.swift; sourceTree = "<group>"; };
008D62CF2A56EA1500254FD9 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
00A12BF32CC0F8450006D9F7 /* TransportDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransportDemoView.swift; sourceTree = "<group>"; };
00A37E2F2B1911A800FA4B5F /* FileSystemExplorerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileSystemExplorerView.swift; sourceTree = "<group>"; };
00D1E2442A36327100E8D275 /* BlocksApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BlocksApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
00D1E2472A36327100E8D275 /* BlocksApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlocksApp.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -114,6 +116,7 @@
008D62CA2A56C2AF00254FD9 /* Features */ = {
isa = PBXGroup;
children = (
00A12BF32CC0F8450006D9F7 /* TransportDemoView.swift */,
008D62CB2A56C35800254FD9 /* ImagePickerView.swift */,
008D62CD2A56C96E00254FD9 /* MailComposeView.swift */,
007314A62AF00BFC0092F234 /* FontsView.swift */,
Expand Down Expand Up @@ -331,6 +334,7 @@
003995752AFBF4680051BFCE /* BackgroundTaskView.swift in Sources */,
008D62CE2A56C96E00254FD9 /* MailComposeView.swift in Sources */,
002136DD2B57C2570031AE9A /* PlainDateDemoView.swift in Sources */,
00A12BF42CC0F84B0006D9F7 /* TransportDemoView.swift in Sources */,
00333CCB2C45682900A58365 /* SlugifyView.swift in Sources */,
00D1E24A2A36327100E8D275 /* ContentView.swift in Sources */,
007314A72AF00BFC0092F234 /* FontsView.swift in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions Examples/BlocksApp/BlocksApp/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct ContentView: View {
case plainDateDemo = "PlainDate demo"
case loggingPlayground = "Logging Playground"
case slugifyPlayground = "Slugify Playground"
case transportDemo = "Transport demo"

var id: String {
rawValue
Expand Down Expand Up @@ -106,6 +107,8 @@ struct ContentView: View {
LoggingPlaygroundView()
case .slugifyPlayground:
SlugifyView()
case .transportDemo:
TransportDemoView()
}
} else {
Text("Select a section")
Expand Down
102 changes: 102 additions & 0 deletions Examples/BlocksApp/BlocksApp/Features/TransportDemoView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import Blocks
import SwiftUI

class DummyJSONClient {
static let defaultTransport: Transport = RetryTransport(
wrapping: StatusCodeCheckingTransport(
wrapping: LoggingTransport(
wrapping: URLSession.shared,
subsystem: "net.mickf.blocks"
)
)
)

enum RandomQuote {
struct Response: Codable {
let id: Int
let quote: String
let author: String
}
}

func randomQuote() async throws -> Endpoint<RandomQuote.Response> {
let url = try URL.dummyJSONURLComponents(path: "/quotes/random")
return Endpoint(json: .get, url: url)
}
}

extension URL {
static func dummyJSONURLComponents(path: String) throws -> URL {
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "dummyjson.com"
urlComponents.path = path

guard let url = urlComponents.url else {
throw TransportError.unmetURLComponentsRequirements
}

return url
}
}

struct TransportDemoView: View {
let readme: LocalizedStringKey = """
A `Transport` can compose behaviors dealing with URL requests.
The one demoed here will:
1. **Load data** from the internet (`URLSession.shared`);
2. **Log requests** and responses to OSLog (`LoggingTransport`);
3. **Throw** if the status code is an error one (`StatusCodeCheckingTransport`);
4. **Retry** the request if it failed a couple of times (`RetryTransport`).
"""

@State var taskState: TaskState = .notStarted
@State var quote: String?
@State var author: String?

var body: some View {
VStack(spacing: 32) {
VStack(alignment: .leading) {
Text(readme)
}.frame(maxWidth: .infinity, alignment: .leading)
Divider()
TaskStateButton(
"Load quote",
runningTitleKey: "Loading quote…",
action: {
Task {
do {
taskState = .running
let quoteResponse = try await DummyJSONClient.defaultTransport.load(
DummyJSONClient().randomQuote()
)
taskState = .completed
quote = quoteResponse.quote
author = quoteResponse.author
} catch {
taskState = .failed(errorDescription: error.localizedDescription)
}
}
},
disabledWhenCompleted: false,
state: taskState
)
.buttonStyle(.borderedProminent)
.padding(32)
VStack {
Text(quote ?? "")
Text(author ?? "")
.font(.caption)
}
Spacer()
}
.padding()
.navigationTitle("Transport Demo")
}
}

#Preview {
TransportDemoView()
}
9 changes: 4 additions & 5 deletions Sources/Blocks/Documentation.docc/Articles/Transport.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,10 @@ responses, will snapshot results on disks, will throw if the response's status
code is in not in the 200 to 399 range, then, you could use:

```swift
SnapshottingTransport(
wrapping: LogginTransport(
wrapping: StatusCodeCheckingTransport(
wrapping: URLSession.shared
)
StatusCodeCheckingTransport(
wrapping: LoggingTransport(
wrapping: URLSession.shared,
subsystem: bundleId
)
)
```
Expand Down
4 changes: 2 additions & 2 deletions Sources/Blocks/Transport/LoggingTransport.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#if canImport(os)
#if canImport(OSLog)
import Foundation
import os
import OSLog

@available(iOS 15.0.0, *)
@available(macOS 12.0, *)
Expand Down
Loading