Skip to content

Swift Create Media Support #412

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

Closed
wants to merge 5 commits into from
Closed
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

This file was deleted.

46 changes: 46 additions & 0 deletions native/swift/Example/Example/ExampleApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ struct ExampleApp: App {
})
]

@State
var isFileImporterDisplayed: Bool = false

var body: some Scene {
WindowGroup {
if loginManager.isLoggedIn {
Expand All @@ -72,6 +75,17 @@ struct ExampleApp: App {
Text("Select a category of settings in the sidebar.")
}.toolbar(content: {
#if os(macOS)
ToolbarItem {
Menu {
Button("Create Media") {
self.isFileImporterDisplayed = true
}
} label: {
Button("Add", systemImage: "plus") { }
}
}


ToolbarItem {
Button("Log Out") {
Task {
Expand All @@ -89,10 +103,42 @@ struct ExampleApp: App {
}
#endif
})
.fileImporter(isPresented: $isFileImporterDisplayed, allowedContentTypes: [
.image
], onCompletion: self.uploadMedia)
} else {
LoginView()
}
}
.environmentObject(loginManager)

}

private func uploadMedia(_ result: Result<URL, Error>) {

Task {
do {
let url = try result.get()
let mediaId = UUID().uuidString
let params = MediaCreateParams(dateGmt: .now, slug: mediaId, status: .publish, title: mediaId, altText: "Alt Text", caption: "caption", description: "description!")

let securityScope = url.startAccessingSecurityScopedResource()

defer {
if securityScope {
url.stopAccessingSecurityScopedResource()
}
}

let uploadRequest = try await WordPressAPI.globalInstance
.media
.create(params: params, filePath: url.path, fileContentType: "image/png")

// debugPrint(uploadRequest.data)

} catch {
debugPrint(error.localizedDescription)
}
}
}
}
2 changes: 2 additions & 0 deletions native/swift/Sources/wordpress-api/Exports.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,12 @@ public typealias PostsRequestListWithEmbedContextResponse = WordPressAPIInternal
// MARK: - Media
public typealias SparseMedia = WordPressAPIInternal.SparseMedia
public typealias MediaUploadRequest = WordPressAPIInternal.MediaUploadRequest
public typealias MediaRequestCreateResponse = WordPressAPIInternal.MediaRequestCreateResponse
public typealias MediaWithEditContext = WordPressAPIInternal.MediaWithEditContext
public typealias MediaWithViewContext = WordPressAPIInternal.MediaWithViewContext
public typealias MediaWithEmbedContext = WordPressAPIInternal.MediaWithEmbedContext
public typealias MediaListParams = WordPressAPIInternal.MediaListParams
public typealias MediaCreateParams = WordPressAPIInternal.MediaCreateParams
public typealias MediaRequestExecutor = WordPressAPIInternal.MediaRequestExecutor

public typealias MediaRequestListWithEditContextResponse = WordPressAPIInternal.MediaRequestListWithEditContextResponse
Expand Down
73 changes: 68 additions & 5 deletions native/swift/Sources/wordpress-api/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ public extension MiddlewarePipeline {
}

extension WpNetworkResponse {
init(data: Data, request: WpNetworkRequest, response: URLResponse) throws {
guard let response = response as? HTTPURLResponse else {
preconditionFailure("We should never wind up here")
}

init(data: Data, request: WpNetworkRequest, response: HTTPURLResponse) throws {
self = WpNetworkResponse(
body: data,
statusCode: UInt16(response.statusCode),
Expand All @@ -25,10 +21,77 @@ extension WpNetworkResponse {
requestHeaderMap: request.headerMap()
)
}

init(mediaUploadRequest: MediaUploadRequest, data: Data, response: HTTPURLResponse) throws {
self = WpNetworkResponse(
body: data,
statusCode: UInt16(response.statusCode),
responseHeaderMap: try WpNetworkHeaderMap.fromMap(hashMap: response.httpHeaders),
requestUrl: mediaUploadRequest.url(),
requestHeaderMap: mediaUploadRequest.headerMap()
)
}
}

extension MiddlewarePipeline {
convenience init(middlewares: Middleware...) {
self.init(middlewares: middlewares)
}
}

extension MediaUploadRequest {

private var filename: String {
filePath.lastPathComponent
}

private var filePath: URL {
URL(fileURLWithPath: self.filePath())
}

func asUrlRequest() async throws -> URLRequest {
let multipartRequestBody = try await MultipartRequestBody(parts: [
HttpPart.formData(data: self.mediaParams()),
HttpPart.file(name: filename, filePath: filePath, mimeType: self.fileContentType())
]).build()

var fileRequest = try URLRequest(url: self.url().asUrl())
fileRequest.httpMethod = self.method().rawValue
fileRequest.httpBodyStream = InputStream(url: filePath)

fileRequest.setHeaders(self.headerMap().toFlatMap())
fileRequest.setValue("attachment; filename=test-1.jpg", forHTTPHeaderField: "Content-Disposition")
if let fileSize = try? self.calculateFileSize(for: filePath) {
fileRequest.setValue(String(fileSize), forHTTPHeaderField: "Content-Length")
}
fileRequest.setValue("foo", forHTTPHeaderField: "X-REQUEST-ID") // TODO: There should be a requestID for this

return fileRequest
}

private func calculateFileSize(for url: URL) throws -> Int? {
try url.resourceValues(forKeys: [.fileSizeKey]).fileSize
}
}

enum WpEndpointUrlError: Error {
case invalidUrlString
}

extension URLRequest {
mutating func setHeaders(_ headers: [String: String]) {
for (key, value) in headers {
setValue(value, forHTTPHeaderField: key)
}
}
}

extension WpEndpointUrl {
func asUrl() throws -> URL {
guard let url = URL(string: self) else {
throw WpEndpointUrlError.invalidUrlString
}

return url
}
}
Loading