-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' into bosco/improve-navigation-routing-pattern
# Conflicts: # Mlem.xcodeproj/project.pbxproj # Mlem/Views/Tabs/Search/Search View.swift # Mlem/Views/Tabs/Settings/Components/Views/About/LicensesView.swift
- Loading branch information
Showing
85 changed files
with
3,187 additions
and
330 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// | ||
// APIClient+Pictrs.swift | ||
// Mlem | ||
// | ||
// Created by Sjmarf on 24/09/2023. | ||
// | ||
|
||
import Foundation | ||
|
||
extension APIClient { | ||
@discardableResult | ||
func deleteImage(file: PictrsFile) async throws -> ImageDeleteResponse { | ||
let request = try ImageDeleteRequest(session: session, file: file.file, deleteToken: file.deleteToken) | ||
return try await perform(request: request) | ||
} | ||
|
||
func uploadImage( | ||
_ imageData: Data, | ||
onProgress progressCallback: @escaping (_ progress: Double) -> Void, | ||
onCompletion completionCallback: @escaping(_ response: ImageUploadResponse?) -> Void, | ||
`catch`: @escaping (Error) -> Void | ||
) async throws -> Task<(), any Error> { | ||
|
||
let delegate = ImageUploadDelegate(callback: progressCallback) | ||
// Modify the instance URL to remove "api/v3" and add "pictrs/image". | ||
var components = URLComponents() | ||
components.scheme = try self.session.instanceUrl.scheme | ||
components.host = try self.session.instanceUrl.host | ||
components.path = "/pictrs/image" | ||
|
||
guard let url = components.url else { | ||
throw APIClientError.response(.init(error: "Failed to modify instance URL to add pictrs."), nil) | ||
} | ||
var request = URLRequest(url: url) | ||
request.httpMethod = "POST" | ||
|
||
let boundary = UUID().uuidString | ||
|
||
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") | ||
request.setValue("jwt=\(try session.token)", forHTTPHeaderField: "Cookie") | ||
|
||
let multiPartForm: MultiPartForm = try .init( | ||
mimeType: "image/png", | ||
fileName: "image.png", | ||
imageData: imageData, | ||
auth: session.token | ||
) | ||
|
||
return Task { [request] in | ||
do { | ||
let (data, _) = try await self.urlSession.upload( | ||
for: request, | ||
from: multiPartForm.createField(boundary: boundary), | ||
delegate: delegate) | ||
do { | ||
let decoder = JSONDecoder() | ||
decoder.keyDecodingStrategy = .convertFromSnakeCase | ||
let response = try decoder.decode(ImageUploadResponse.self, from: data) | ||
completionCallback(response) | ||
} catch DecodingError.dataCorrupted { | ||
throw APIClientError.decoding(data) | ||
} | ||
} catch { | ||
if !Task.isCancelled { | ||
`catch`(error) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
private struct MultiPartForm: Codable { | ||
var mimeType: String | ||
var fileName: String | ||
var imageData: Data | ||
var auth: String | ||
|
||
func createField(boundary: String) -> Data { | ||
var data = Data() | ||
data.append(Data("--\(boundary)\r\n".utf8)) | ||
data.append(Data("Content-Disposition: form-data; name=\"images[]\"; filename=\"\(fileName)\"\r\n".utf8)) | ||
data.append(Data("Content-Type: \(mimeType)\r\n".utf8)) | ||
data.append(Data("\r\n".utf8)) | ||
data.append(imageData) | ||
data.append(Data("\r\n".utf8)) | ||
data.append(Data("--\(boundary)--\r\n".utf8)) | ||
return data | ||
} | ||
} | ||
|
||
private class ImageUploadDelegate: NSObject, URLSessionTaskDelegate { | ||
public let callback: (Double) -> Void | ||
|
||
public init(callback: @escaping (Double) -> Void) { | ||
self.callback = callback | ||
} | ||
|
||
public func urlSession( | ||
_ session: URLSession, | ||
task: URLSessionTask, | ||
didSendBodyData bytesSent: Int64, | ||
totalBytesSent: Int64, | ||
totalBytesExpectedToSend: Int64 | ||
) { | ||
callback(Double(totalBytesSent) / Double(totalBytesExpectedToSend)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// | ||
// DeletePictrsFile.swift | ||
// Mlem | ||
// | ||
// Created by Sjmarf on 29/09/2023. | ||
// | ||
|
||
import Foundation | ||
|
||
struct ImageDeleteRequest: APIRequest { | ||
var path: String | ||
var instanceURL: URL | ||
|
||
var endpoint: URL { | ||
instanceURL | ||
.appending(path: path) | ||
} | ||
|
||
typealias Response = ImageDeleteResponse | ||
|
||
init(session: APISession, file: String, deleteToken: String) throws { | ||
var components = URLComponents() | ||
components.scheme = try session.instanceUrl.scheme | ||
components.host = try session.instanceUrl.host | ||
components.path = "/pictrs/image" | ||
|
||
guard let url = components.url else { | ||
throw APIClientError.response(.init(error: "Failed to modify instance URL to delete from pictrs."), nil) | ||
} | ||
self.instanceURL = url | ||
|
||
self.path = "/delete/\(deleteToken)/\(file)" | ||
} | ||
} | ||
|
||
struct ImageDeleteResponse: Decodable { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
Mlem/Dependency/Repositories/PictrsRepository+Dependency.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// | ||
// PictrsRepository+Dependency.swift | ||
// Mlem | ||
// | ||
// Created by Sjmarf on 29/09/2023. | ||
// | ||
|
||
import Dependencies | ||
import Foundation | ||
|
||
extension PictrsRespository: DependencyKey { | ||
static let liveValue = PictrsRespository() | ||
} | ||
|
||
extension DependencyValues { | ||
var pictrsRepository: PictrsRespository { | ||
get { self[PictrsRespository.self] } | ||
set { self[PictrsRespository.self] = newValue } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// AvatarType.swift | ||
// Mlem | ||
// | ||
// Created by Eric Andrews on 2023-10-02. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Enum of things that can have avatars | ||
enum AvatarType { | ||
case user, community | ||
} | ||
|
||
extension AvatarType: AssociatedIcon { | ||
var iconName: String { | ||
switch self { | ||
case .user: | ||
return Icons.user | ||
case .community: | ||
return Icons.community | ||
} | ||
} | ||
|
||
var iconNameFill: String { | ||
switch self { | ||
case .user: | ||
return Icons.userFill | ||
case .community: | ||
return Icons.communityFill | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,6 @@ | |
|
||
import Foundation | ||
|
||
enum ContentType: Int { | ||
case post | ||
enum ContentType: Int, Codable { | ||
case post, community, user | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.