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

Test 3.0.0 release candidate #476

Draft
wants to merge 19 commits into
base: trunk
Choose a base branch
from
Draft
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
1 change: 0 additions & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ steps:
plugins: [$CI_TOOLKIT]
depends_on:
- "test"
- "test_demo"
- "validate"
- "lint"
if: build.tag != null
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ fastlane/README.md
fastlane/report.xml
fastlane/test_output

# SwiftGen (part of wpmreleasetoolkit)
vendor/swiftgen

# Other
openapi-generator/
Demo/Demo/Secrets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,16 @@ final class DemoQuickEditorViewController: UIViewController {

func updateLogoutButton(_ button: UIButton? = nil) {
guard let savedEmail else { return }
let session = OAuthSession()
let button = button ?? logoutButton
UIView.animate {
button.isHidden = !session.hasSession(with: Email(savedEmail))
button.isHidden = !OAuthSession.hasSession(with: Email(savedEmail))
button.alpha = button.isHidden ? 0 : 1
}
}

func logout() {
guard let savedEmail else { return }
let session = OAuthSession()
session.deleteSession(with: Email(savedEmail))
OAuthSession.deleteSession(with: Email(savedEmail))
updateLogoutButton()
}

Expand Down
38 changes: 8 additions & 30 deletions Sources/Gravatar/Network/Services/AvatarService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,19 @@ public struct AvatarService: Sendable {
private let imageDownloader: ImageDownloader
private let imageUploader: ImageUploader

/// Creates a new `AvatarService`
///
/// Optionally, you can pass a custom type conforming to ``HTTPClient`` to gain control over networking tasks.
/// Similarly, you can pass a custom type conforming to ``ImageCaching`` to use your custom caching system.
/// - Parameters:
/// - client: A type which will perform basic networking operations.
/// - cache: A type which will perform image caching operations.
public init(client: HTTPClient, cache: ImageCaching? = nil) {
self.imageDownloader = ImageDownloadService(client: client, cache: cache)
self.imageUploader = ImageUploadService(client: client)
}

/// Creates a new `AvatarService`
///
/// Optionally, you can pass a custom type conforming to ``URLSessionProtocol``.
/// Similarly, you can pass a custom type conforming to ``ImageCaching`` to use your custom caching system.
/// - Parameters:
/// - session: A type which will perform basic networking operations. By default, a properly configured URLSession instance will be used.
/// - cache: A type which will perform image caching operations.
public init(session: URLSessionProtocol? = nil, cache: ImageCaching? = nil) {
let client = URLSessionHTTPClient(urlSession: session)
self.init(client: client, cache: cache)
/// - urlSession: Manages the network tasks. It can be a [URLSession] or any other type that conforms to ``URLSessionProtocol``.
/// If not provided, a properly configured [URLSession] is used.
/// - cache: An image cache of type ``ImageCaching``. If not provided, it defaults to SDK's in-memory cache.
///
/// [URLSession]: https://developer.apple.com/documentation/foundation/urlsession
public init(urlSession: URLSessionProtocol? = nil, cache: ImageCaching? = nil) {
self.imageDownloader = ImageDownloadService(urlSession: urlSession, cache: cache)
self.imageUploader = ImageUploadService(urlSession: urlSession)
}

/// Fetches a Gravatar user profile image using an `AvatarId`, and delivers the image asynchronously. See also: ``ImageDownloadService`` to
Expand All @@ -49,19 +40,6 @@ public struct AvatarService: Sendable {
return try await imageDownloader.fetchImage(with: gravatarURL, forceRefresh: options.forceRefresh, processingMethod: options.processingMethod)
}

/// Uploads an image to be used as the user's Gravatar profile image, and returns the `URLResponse` of the network tasks asynchronously. Throws
/// ``ImageUploadError``.
/// - Parameters:
/// - image: The image to be uploaded.
/// - email: An`Email` object
/// - accessToken: The authentication token for the user. This is a WordPress.com OAuth2 access token.
/// - Returns: An asynchronously-delivered `URLResponse` instance, containing the response of the upload network task.
@discardableResult
@available(*, deprecated, renamed: "upload(_:accessToken:)")
public func upload(_ image: UIImage, email: Email, accessToken: String) async throws -> URLResponse {
try await imageUploader.uploadImage(image, accessToken: accessToken, additionalHTTPHeaders: nil).response
}

/// Uploads an image to be used as the user's Gravatar profile image, and returns the `URLResponse` of the network tasks asynchronously. Throws
/// ``ImageUploadError``.
/// - Parameters:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@ import Foundation
package struct CheckTokenAuthorizationService: Sendable {
private let client: HTTPClient

package init(session: URLSession? = nil) {
if let session {
self.client = URLSessionHTTPClient(urlSession: session)
} else {
self.client = URLSessionHTTPClient()
}
package init(session: URLSessionProtocol? = nil) {
self.client = URLSessionHTTPClient(urlSession: session)
}

/// Checks if the given access token is authorized to make changes to this Gravatar account.
Expand Down
2 changes: 1 addition & 1 deletion Sources/Gravatar/Network/Services/HTTPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Foundation
///
/// You can provide your own type conforming to this protocol to gain control over all networking operations performed internally by this SDK.
/// For more info, see ``AvatarService/init(client:cache:)`` and ``ProfileService/init(client:)``.
public protocol HTTPClient: Sendable {
protocol HTTPClient: Sendable {
/// Performs a data request using the information provided, and delivers the result asynchronously.
/// - Parameter request: A URL request object that provides request-specific information such as the URL and cache policy.
/// - Returns: An asynchronously-delivered tuple that contains the URL contents as a Data instance, and a HTTPURLResponse.
Expand Down
20 changes: 7 additions & 13 deletions Sources/Gravatar/Network/Services/ImageDownloadService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,19 @@ import UIKit

/// A service to perform image downloading.
///
/// This is the default type which implements ``ImageDownloader``..
/// Unless specified otherwise, `ImageDownloadService` will use a `URLSession` based `HTTPClient`, and a in-memory image cache.
/// This is the default type which implements ``ImageDownloader``.
public actor ImageDownloadService: ImageDownloader, Sendable {
private let client: HTTPClient
let imageCache: ImageCaching

/// Creates a new `ImageDownloadService`
///
/// Optionally, you can pass a custom type conforming to ``HTTPClient`` to gain control over networking tasks.
/// Similarly, you can pass a custom type conforming to ``ImageCaching`` to use your custom caching system.
/// - Parameters:
/// - client: A type which will perform basic networking operations.
/// - cache: A type which will perform image caching operations.
public init(client: HTTPClient? = nil, cache: ImageCaching? = nil) {
self.client = client ?? URLSessionHTTPClient()
self.imageCache = cache ?? ImageCache.shared
}

public init(urlSession: URLSession, cache: ImageCaching? = nil) {
/// - urlSession: Manages the network tasks. It can be a [URLSession] or any other type that conforms to ``URLSessionProtocol``.
/// If not provided, a properly configured [URLSession] is used.
/// - cache: An image cache of type ``ImageCaching``. If not provided, it defaults to SDK's in-memory cache.
///
/// [URLSession]: https://developer.apple.com/documentation/foundation/urlsession
public init(urlSession: URLSessionProtocol? = nil, cache: ImageCaching? = nil) {
self.client = URLSessionHTTPClient(urlSession: urlSession)
self.imageCache = cache ?? ImageCache.shared
}
Expand Down
7 changes: 3 additions & 4 deletions Sources/Gravatar/Network/Services/ImageUploadService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ import UIKit

/// A service to perform uploading images to Gravatar.
///
/// This is the default type which implements ``ImageUploader``..
/// Unless specified otherwise, `ImageUploadService` will use a `URLSession` based `HTTPClient`.
/// This is the default type which implements ``ImageUploader``.
struct ImageUploadService: ImageUploader {
private let client: HTTPClient

init(client: HTTPClient? = nil) {
self.client = client ?? URLSessionHTTPClient()
init(urlSession: URLSessionProtocol? = nil) {
self.client = URLSessionHTTPClient(urlSession: urlSession)
}

@discardableResult
Expand Down
10 changes: 6 additions & 4 deletions Sources/Gravatar/Network/Services/ProfileService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ public struct ProfileService: ProfileFetching, Sendable {
private let client: HTTPClient

/// Creates a new `ProfileService`.
/// - Parameters:
/// - urlSession: Manages the network tasks. It can be a [URLSession] or any other type that conforms to ``URLSessionProtocol``.
/// If not provided, a properly configured [URLSession] is used.
///
/// Optionally, you can pass a custom type conforming to ``HTTPClient`` to gain control over networking tasks.
/// - Parameter client: A type which will perform basic networking operations.
public init(client: HTTPClient? = nil) {
self.client = client ?? URLSessionHTTPClient()
/// [URLSession]: https://developer.apple.com/documentation/foundation/urlsession
public init(urlSession: URLSessionProtocol? = nil) {
self.client = URLSessionHTTPClient(urlSession: urlSession)
}

public func fetch(with profileID: ProfileIdentifier) async throws -> Profile {
Expand Down
9 changes: 3 additions & 6 deletions Sources/Gravatar/Network/URLSessionProtocol.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import UIKit

/// Protocol for dependency injection purposes. `URLSession` conforms to this protocol.
/// Protocol for dependency injection purposes. [URLSession] conforms to this protocol.
///
/// [URLSession]: https://developer.apple.com/documentation/foundation/urlsession
public protocol URLSessionProtocol: Sendable {
func dataTask(
with request: URLRequest,
completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void
) -> URLSessionDataTask

func data(for request: URLRequest) async throws -> (Data, URLResponse)

func upload(for request: URLRequest, from bodyData: Data) async throws -> (Data, URLResponse)
Expand Down
16 changes: 1 addition & 15 deletions Sources/Gravatar/OpenApi/Generated/AssociatedResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,18 @@ struct AssociatedResponse: Codable, Hashable, Sendable {
/// Whether the entity is associated with the account.
private(set) var associated: Bool

@available(*, deprecated, message: "init will become internal on the next release")
init(associated: Bool) {
self.associated = associated
}

@available(*, deprecated, message: "CodingKeys will become internal on the next release.")
enum CodingKeys: String, CodingKey, CaseIterable {
case associated
}

enum InternalCodingKeys: String, CodingKey, CaseIterable {
case associated
}

// Encodable protocol methods

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: InternalCodingKeys.self)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(associated, forKey: .associated)
}

// Decodable protocol methods

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: InternalCodingKeys.self)

associated = try container.decode(Bool.self, forKey: .associated)
}
}
28 changes: 2 additions & 26 deletions Sources/Gravatar/OpenApi/Generated/Avatar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ package struct Avatar: Codable, Hashable, Sendable {
/// Whether the image is currently selected as the provided selected email's avatar.
package private(set) var selected: Bool?

@available(*, deprecated, message: "init will become internal on the next release")
package init(imageId: String, imageUrl: String, rating: Rating, updatedDate: Date, altText: String, selected: Bool? = nil) {
self.imageId = imageId
self.imageUrl = imageUrl
Expand All @@ -33,17 +32,7 @@ package struct Avatar: Codable, Hashable, Sendable {
self.selected = selected
}

@available(*, deprecated, message: "CodingKeys will become internal on the next release.")
package enum CodingKeys: String, CodingKey, CaseIterable {
case imageId = "image_id"
case imageUrl = "image_url"
case rating
case updatedDate = "updated_date"
case altText = "alt_text"
case selected
}

enum InternalCodingKeys: String, CodingKey, CaseIterable {
enum CodingKeys: String, CodingKey, CaseIterable {
case imageId = "image_id"
case imageUrl = "image_url"
case rating
Expand All @@ -55,25 +44,12 @@ package struct Avatar: Codable, Hashable, Sendable {
// Encodable protocol methods

package func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: InternalCodingKeys.self)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(imageId, forKey: .imageId)
try container.encode(imageUrl, forKey: .imageUrl)
try container.encode(rating, forKey: .rating)
try container.encode(updatedDate, forKey: .updatedDate)
try container.encode(altText, forKey: .altText)
try container.encodeIfPresent(selected, forKey: .selected)
}

// Decodable protocol methods

package init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: InternalCodingKeys.self)

imageId = try container.decode(String.self, forKey: .imageId)
imageUrl = try container.decode(String.self, forKey: .imageUrl)
rating = try container.decode(Rating.self, forKey: .rating)
updatedDate = try container.decode(Date.self, forKey: .updatedDate)
altText = try container.decode(String.self, forKey: .altText)
selected = try container.decodeIfPresent(Bool.self, forKey: .selected)
}
}
22 changes: 3 additions & 19 deletions Sources/Gravatar/OpenApi/Generated/CryptoWalletAddress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,21 @@ public struct CryptoWalletAddress: Codable, Hashable, Sendable {
/// The wallet address for the crypto currency.
public private(set) var address: String

@available(*, deprecated, message: "init will become internal on the next release")
public init(label: String, address: String) {
init(label: String, address: String) {
self.label = label
self.address = address
}

@available(*, deprecated, message: "CodingKeys will become internal on the next release.")
public enum CodingKeys: String, CodingKey, CaseIterable {
case label
case address
}

enum InternalCodingKeys: String, CodingKey, CaseIterable {
enum CodingKeys: String, CodingKey, CaseIterable {
case label
case address
}

// Encodable protocol methods

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: InternalCodingKeys.self)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(label, forKey: .label)
try container.encode(address, forKey: .address)
}

// Decodable protocol methods

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: InternalCodingKeys.self)

label = try container.decode(String.self, forKey: .label)
address = try container.decode(String.self, forKey: .address)
}
}
25 changes: 2 additions & 23 deletions Sources/Gravatar/OpenApi/Generated/GalleryImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,21 @@ public struct GalleryImage: Codable, Hashable, Sendable {
/// The image alt text.
public private(set) var altText: String?

@available(*, deprecated, message: "init will become internal on the next release")
public init(url: String) {
self.url = url
}

// NOTE: This init is maintained manually.
// Avoid deleting this init until the deprecation of is applied.
init(url: String, altText: String? = nil) {
self.url = url
self.altText = altText
}

@available(*, deprecated, message: "CodingKeys will become internal on the next release.")
public enum CodingKeys: String, CodingKey, CaseIterable {
case url
}

enum InternalCodingKeys: String, CodingKey, CaseIterable {
enum CodingKeys: String, CodingKey, CaseIterable {
case url
case altText = "alt_text"
}

// Encodable protocol methods

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: InternalCodingKeys.self)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(url, forKey: .url)
try container.encodeIfPresent(altText, forKey: .altText)
}

// Decodable protocol methods

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: InternalCodingKeys.self)

url = try container.decode(String.self, forKey: .url)
altText = try container.decodeIfPresent(String.self, forKey: .altText)
}
}
Loading