Skip to content

Commit

Permalink
Merge branch 'trunk' into etoledom/remove-completion-block-from-profi…
Browse files Browse the repository at this point in the history
…le-service
  • Loading branch information
etoledom authored Mar 25, 2024
2 parents 650190e + 3cad0a1 commit 6958d72
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 60 deletions.
12 changes: 6 additions & 6 deletions Demo/Demo/Gravatar-Demo/DemoAvatarDownloadViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class DemoAvatarDownloadViewController: UIViewController {
return view
}()

private lazy var forceDefaultImageSwitchWithLabel: SwitchWithLabel = {
private lazy var forceDefaultAvatarSwitchWithLabel: SwitchWithLabel = {
let view = SwitchWithLabel(labelText: "Force default avatar")
view.translatesAutoresizingMaskIntoConstraints = false
return view
Expand Down Expand Up @@ -79,7 +79,7 @@ class DemoAvatarDownloadViewController: UIViewController {
preferredAvatarLengthInputField,
gravatarRatingInputField,
igonreCacheSwitchWithLabel,
forceDefaultImageSwitchWithLabel,
forceDefaultAvatarSwitchWithLabel,
imageDefaultButton,
fetchAvatarButton,
avatarImageView
Expand Down Expand Up @@ -125,14 +125,14 @@ class DemoAvatarDownloadViewController: UIViewController {
return nil
}

private var preferredDefaultImage: DefaultAvatarOption? = nil
private var preferredDefaultAvatar: DefaultAvatarOption? = nil

@objc private func selectImageDefault() {
let controller = UIAlertController(title: "Default Avatar Option", message: nil, preferredStyle: .actionSheet)

DefaultAvatarOption.allCases.forEach { option in
controller.addAction(UIAlertAction(title: "\(option)", style: .default) { [weak self] action in
self?.preferredDefaultImage = option
self?.preferredDefaultAvatar = option
self?.imageDefaultButton.setTitle("Default Avatar Option: \(option)", for: .normal)
})
}
Expand All @@ -148,8 +148,8 @@ class DemoAvatarDownloadViewController: UIViewController {
preferredSize: .points(preferredSize),
rating: preferredRating,
forceRefresh: igonreCacheSwitchWithLabel.isOn,
forceDefaultImage: forceDefaultImageSwitchWithLabel.isOn,
defaultAvatarOption: preferredDefaultImage
forceDefaultAvatar: forceDefaultAvatarSwitchWithLabel.isOn,
defaultAvatarOption: preferredDefaultAvatar
)

avatarImageView.image = nil // Setting to nil to make the effect of `forceRefresh more visible
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ class DemoUIImageViewExtensionViewController: UIViewController {
])
}

private var preferredDefaultImage: DefaultAvatarOption? = nil
private var preferredDefaultAvatar: DefaultAvatarOption? = nil

@objc private func selectImageDefault() {
let controller = UIAlertController(title: "Default Avatar", message: nil, preferredStyle: .actionSheet)

DefaultAvatarOption.allCases.forEach { option in
controller.addAction(UIAlertAction(title: "\(option)", style: .default) { [weak self] action in
self?.preferredDefaultImage = option
self?.preferredDefaultAvatar = option
self?.imageDefaultButton.setTitle("Default Avatar: \(option)", for: .normal)
})
}
Expand All @@ -141,7 +141,7 @@ class DemoUIImageViewExtensionViewController: UIViewController {
let placeholderImage: UIImage? = showPlaceholderSwitchWithLabel.isOn ? UIImage(named: "placeholder") : nil
avatarImageView.gravatar.setImage(email: emailInputField.text ?? "",
placeholder: placeholderImage,
defaultAvatarOption: preferredDefaultImage,
defaultAvatarOption: preferredDefaultAvatar,
options: options) { result in
switch result {
case .success(let result):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ extension GravatarWrapper where Component: UIImageView {
defaultAvatarOption: defaultAvatarOption
)

let gravatarURL = GravatarURL.gravatarUrl(with: email, options: downloadOptions.imageQueryOptions)
let gravatarURL = GravatarURL.gravatarUrl(with: email, options: downloadOptions.avatarQueryOptions)
return setImage(with: gravatarURL, placeholder: placeholder, options: options, completionHandler: completionHandler)
}

Expand Down
6 changes: 3 additions & 3 deletions Sources/Gravatar/GravatarURL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public struct GravatarURL {

public let canonicalURL: URL

public func url(with options: ImageQueryOptions) -> URL {
public func url(with options: AvatarQueryOptions) -> URL {
// When `GravatarURL` is initialized successfully, the `canonicalURL` is a valid URL.
// Adding query items from the options, which is controlled by the SDK, should never
// result in an invalid URL. If it does, something terrible has happened.
Expand Down Expand Up @@ -45,7 +45,7 @@ public struct GravatarURL {
///
public static func gravatarUrl(
with email: String,
options: ImageQueryOptions = .init()
options: AvatarQueryOptions = .init()
) -> URL? {
let hash = gravatarHash(of: email)
guard let baseURL = URL(string: Defaults.baseURL + hash) else {
Expand Down Expand Up @@ -104,7 +104,7 @@ extension GravatarURL {
}

extension URL {
fileprivate func addQueryItems(from options: ImageQueryOptions) -> URL? {
fileprivate func addQueryItems(from options: AvatarQueryOptions) -> URL? {
guard var components = URLComponents(url: self, resolvingAgainstBaseURL: false) else {
return nil
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Gravatar/Network/Services/AvatarService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public struct AvatarService {
with email: String,
options: ImageDownloadOptions = ImageDownloadOptions()
) async throws -> ImageDownloadResult {
guard let gravatarURL = GravatarURL.gravatarUrl(with: email, options: options.imageQueryOptions) else {
guard let gravatarURL = GravatarURL.gravatarUrl(with: email, options: options.avatarQueryOptions) else {
throw ImageFetchingError.requestError(reason: .urlInitializationFailed)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import UIKit

/// Set of options which will be used to request the image to the Gravatar backend.
/// Set of options which will be used to request the avatar from the Gravatar backend.
///
/// For the options not specified, the backend defaults will be used.
/// For more information, see the [Gravatar developer documentation](https://docs.gravatar.com/general/images/).
public struct ImageQueryOptions {
public struct AvatarQueryOptions {
let rating: Rating?
let forceDefaultImage: Bool?
let forceDefaultAvatar: Bool?
let defaultAvatarOption: DefaultAvatarOption?
let preferredPixelSize: Int?

/// Creating an instance of `ImageQueryOptions`.
/// Creating an instance of `AvatarQueryOptions`.
///
/// For the options not specified, the backend defaults will be used.
/// - Parameters:
Expand All @@ -19,17 +19,17 @@ public struct ImageQueryOptions {
/// - gravatarRating: The lowest rating allowed to be displayed. If the requested email hash does not have an image meeting the requested rating level,
/// - defaultAvatarOption: Choose what will happen if no Gravatar image is found. See ``DefaultAvatarOption`` for more info.
/// then the default avatar is returned.
/// - forceDefaultImage: If set to `true`, the returned image will always be the default avatar, determined by the `defaultAvatarOption` parameter.
/// - forceDefaultAvatar: If set to `true`, the returned image will always be the default avatar, determined by the `defaultAvatarOption` parameter.
public init(
preferredSize: ImageSize? = nil,
rating: Rating? = nil,
defaultAvatarOption: DefaultAvatarOption? = nil,
forceDefaultImage: Bool? = nil
forceDefaultAvatar: Bool? = nil
) {
self.init(
scaleFactor: UIScreen.main.scale,
rating: rating,
forceDefaultImage: forceDefaultImage,
forceDefaultAvatar: forceDefaultAvatar,
defaultAvatarOption: defaultAvatarOption,
preferredSize: preferredSize
)
Expand All @@ -38,25 +38,25 @@ public struct ImageQueryOptions {
init(
scaleFactor: CGFloat,
rating: Rating? = nil,
forceDefaultImage: Bool? = nil,
forceDefaultAvatar: Bool? = nil,
defaultAvatarOption: DefaultAvatarOption? = nil,
preferredSize: ImageSize? = nil
) {
self.rating = rating
self.forceDefaultImage = forceDefaultImage
self.forceDefaultAvatar = forceDefaultAvatar
self.defaultAvatarOption = defaultAvatarOption
self.preferredPixelSize = preferredSize?.pixels(scaleFactor: scaleFactor)
}
}

// MARK: - Converting Query options into URLQueryItems

extension ImageQueryOptions {
extension AvatarQueryOptions {
private enum QueryName: String, CaseIterable {
case defaultAvatarOption = "d"
case preferredPixelSize = "s"
case rating = "r"
case forceDefaultImage = "f"
case forceDefaultAvatar = "f"
}

var queryItems: [URLQueryItem] {
Expand All @@ -67,8 +67,8 @@ extension ImageQueryOptions {
let value: String? = switch queryName {
case .defaultAvatarOption:
self.defaultAvatarOption.queryValue
case .forceDefaultImage:
self.forceDefaultImage.queryValue
case .forceDefaultAvatar:
self.forceDefaultAvatar.queryValue
case .rating:
self.rating.queryValue
case .preferredPixelSize:
Expand Down
10 changes: 5 additions & 5 deletions Sources/Gravatar/Options/GravatarOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public struct ImageSettingOptions {
public struct ImageDownloadOptions {
let forceRefresh: Bool
let processingMethod: ImageProcessingMethod
let imageQueryOptions: ImageQueryOptions
let avatarQueryOptions: AvatarQueryOptions

private let preferredSize: ImageSize?

Expand All @@ -86,26 +86,26 @@ public struct ImageDownloadOptions {
/// - preferredSize: Preferred image size (set to `nil` for default size)
/// - gravatarRating: Maximum rating for image (set to `nil` for default rating)
/// - forceRefresh: Force the image to be downloaded, ignoring the cache
/// - forceDefaultImage: If `true`, the returned image will always be the default avatar, determined by the `defaultAvatarOption` parameter.
/// - forceDefaultAvatar: If `true`, the returned image will always be the default avatar, determined by the `defaultAvatarOption` parameter.
/// - defaultAvatarOption: Configure the default avatar (set to `nil` to use the default default avatar)
/// - processingMethod: Method to use for processing the downloaded `Data`
public init(
preferredSize: ImageSize? = nil,
rating: Rating? = nil,
forceRefresh: Bool = false,
forceDefaultImage: Bool? = nil,
forceDefaultAvatar: Bool? = nil,
defaultAvatarOption: DefaultAvatarOption? = nil,
processingMethod: ImageProcessingMethod = .common
) {
self.forceRefresh = forceRefresh
self.processingMethod = processingMethod
self.preferredSize = preferredSize

self.imageQueryOptions = ImageQueryOptions(
self.avatarQueryOptions = AvatarQueryOptions(
preferredSize: preferredSize,
rating: rating,
defaultAvatarOption: defaultAvatarOption,
forceDefaultImage: forceDefaultImage
forceDefaultAvatar: forceDefaultAvatar
)
}
}
2 changes: 1 addition & 1 deletion Tests/GravatarTests/AvatarServiceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ final class AvatarServiceTests: XCTestCase {
XCTAssertTrue(testProcessor.processedData)
}

func testFetchImageWithDefaultImageOption() async throws {
func testFetchAvatarWithDefaultAvatarOption() async throws {
let expectedQuery = "d=mp"
let urlWithQuery = TestData.urlFromEmail.absoluteString + "?" + expectedQuery
let response = HTTPURLResponse.successResponse(with: URL(string: urlWithQuery)!)
Expand Down
52 changes: 26 additions & 26 deletions Tests/GravatarTests/GravatarURLTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,86 +17,86 @@ final class GravatarURLTests: XCTestCase {
func testGravatarURLWithDifferentPixelSizes() throws {
let url = GravatarURL(verifiedGravatarURL)
XCTAssertNotNil(url)
XCTAssertEqual(url?.url(with: ImageQueryOptions(preferredSize: .pixels(24))).query, "s=24")
XCTAssertEqual(url?.url(with: ImageQueryOptions(preferredSize: .pixels(128))).query, "s=128")
XCTAssertEqual(url?.url(with: ImageQueryOptions(preferredSize: .pixels(256))).query, "s=256")
XCTAssertEqual(url?.url(with: ImageQueryOptions(preferredSize: .pixels(0))).query, "s=0")
XCTAssertEqual(url?.url(with: ImageQueryOptions(preferredSize: .pixels(-10))).query, "s=-10")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(preferredSize: .pixels(24))).query, "s=24")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(preferredSize: .pixels(128))).query, "s=128")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(preferredSize: .pixels(256))).query, "s=256")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(preferredSize: .pixels(0))).query, "s=0")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(preferredSize: .pixels(-10))).query, "s=-10")
}

func testGravatarUrlWithPointSize() throws {
let gavatarUrl = GravatarURL(verifiedGravatarURL)
let pointSize = CGFloat(200)
let expectedPixelSize = pointSize * UIScreen.main.scale

let url = gavatarUrl?.url(with: ImageQueryOptions(preferredSize: .points(pointSize)))
let url = gavatarUrl?.url(with: AvatarQueryOptions(preferredSize: .points(pointSize)))

XCTAssertNotNil(url)
XCTAssertEqual(url?.query, "s=\(Int(expectedPixelSize))")
}

func testUrlWithDefaultImage() throws {
func testUrlWithDefaultAvatar() throws {
let url = GravatarURL(verifiedGravatarURL)
XCTAssertNotNil(url)
XCTAssertEqual(url?.url(with: ImageQueryOptions(defaultAvatarOption: .status404)).query, "d=404")
XCTAssertEqual(url?.url(with: ImageQueryOptions(defaultAvatarOption: .mysteryPerson)).query, "d=mp")
XCTAssertEqual(url?.url(with: ImageQueryOptions(defaultAvatarOption: .monsterId)).query, "d=monsterid")
XCTAssertEqual(url?.url(with: ImageQueryOptions(defaultAvatarOption: .retro)).query, "d=retro")
XCTAssertEqual(url?.url(with: ImageQueryOptions(defaultAvatarOption: .roboHash)).query, "d=robohash")
XCTAssertEqual(url?.url(with: ImageQueryOptions(defaultAvatarOption: .transparentPNG)).query, "d=blank")
XCTAssertEqual(url?.url(with: ImageQueryOptions(defaultAvatarOption: .wavatar)).query, "d=wavatar")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(defaultAvatarOption: .status404)).query, "d=404")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(defaultAvatarOption: .mysteryPerson)).query, "d=mp")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(defaultAvatarOption: .monsterId)).query, "d=monsterid")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(defaultAvatarOption: .retro)).query, "d=retro")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(defaultAvatarOption: .roboHash)).query, "d=robohash")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(defaultAvatarOption: .transparentPNG)).query, "d=blank")
XCTAssertEqual(url?.url(with: AvatarQueryOptions(defaultAvatarOption: .wavatar)).query, "d=wavatar")
}

func testUrlWithForcedImageDefault() throws {
let url = GravatarURL(verifiedGravatarURL)
XCTAssertNotNil(url)
XCTAssertEqual(url?.url(with: ImageQueryOptions()).query, nil)
XCTAssertEqual(url?.url(with: ImageQueryOptions(forceDefaultImage: true)).query, "f=y")
XCTAssertEqual(url?.url(with: AvatarQueryOptions()).query, nil)
XCTAssertEqual(url?.url(with: AvatarQueryOptions(forceDefaultAvatar: true)).query, "f=y")
}

func testUrlWithForceImageDefaultFalse() {
let url = GravatarURL(verifiedGravatarURL)
XCTAssertNotNil(url)
XCTAssertEqual(url?.url(with: ImageQueryOptions()).query, nil)
XCTAssertEqual(url?.url(with: ImageQueryOptions(forceDefaultImage: false)).query, "f=n")
XCTAssertEqual(url?.url(with: AvatarQueryOptions()).query, nil)
XCTAssertEqual(url?.url(with: AvatarQueryOptions(forceDefaultAvatar: false)).query, "f=n")
}

func testCreateGravatarUrlWithEmail() throws {
let url = GravatarURL.gravatarUrl(with: exampleEmail, options: ImageQueryOptions())
let url = GravatarURL.gravatarUrl(with: exampleEmail, options: AvatarQueryOptions())
XCTAssertEqual(
url?.absoluteString,
"https://gravatar.com/avatar/676212ff796c79a3c06261eb10e3f455aa93998ee6e45263da13679c74b1e674"
)

let urlAddingDefaultImage = GravatarURL.gravatarUrl(with: exampleEmail, options: ImageQueryOptions(defaultAvatarOption: .identicon))
let urlAddingDefaultAvatar = GravatarURL.gravatarUrl(with: exampleEmail, options: AvatarQueryOptions(defaultAvatarOption: .identicon))
XCTAssertEqual(
urlAddingDefaultImage?.absoluteString,
urlAddingDefaultAvatar?.absoluteString,
"https://gravatar.com/avatar/676212ff796c79a3c06261eb10e3f455aa93998ee6e45263da13679c74b1e674?d=identicon"
)

let urlAddingSize = GravatarURL.gravatarUrl(with: exampleEmail, options: ImageQueryOptions(preferredSize: .pixels(24)))
let urlAddingSize = GravatarURL.gravatarUrl(with: exampleEmail, options: AvatarQueryOptions(preferredSize: .pixels(24)))
XCTAssertEqual(
urlAddingSize?.absoluteString,
"https://gravatar.com/avatar/676212ff796c79a3c06261eb10e3f455aa93998ee6e45263da13679c74b1e674?s=24"
)

let urlAddingRating = GravatarURL.gravatarUrl(with: exampleEmail, options: ImageQueryOptions(rating: .parentalGuidance))
let urlAddingRating = GravatarURL.gravatarUrl(with: exampleEmail, options: AvatarQueryOptions(rating: .parentalGuidance))
XCTAssertEqual(
urlAddingRating?.absoluteString,
"https://gravatar.com/avatar/676212ff796c79a3c06261eb10e3f455aa93998ee6e45263da13679c74b1e674?r=pg"
)

let urlAddingForceDefault = GravatarURL.gravatarUrl(with: exampleEmail, options: ImageQueryOptions(forceDefaultImage: true))
let urlAddingForceDefault = GravatarURL.gravatarUrl(with: exampleEmail, options: AvatarQueryOptions(forceDefaultAvatar: true))
XCTAssertEqual(
urlAddingForceDefault?.absoluteString,
"https://gravatar.com/avatar/676212ff796c79a3c06261eb10e3f455aa93998ee6e45263da13679c74b1e674?f=y"
)

let allOptions = ImageQueryOptions(
let allOptions = AvatarQueryOptions(
preferredSize: .pixels(200),
rating: .general,
defaultAvatarOption: .monsterId,
forceDefaultImage: true
forceDefaultAvatar: true
)
let urlAddingAllOptions = GravatarURL.gravatarUrl(with: exampleEmail, options: allOptions)
XCTAssertEqual(
Expand Down
2 changes: 1 addition & 1 deletion Tests/GravatarTests/GravatarWrapper+UIImageViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ final class GravatarWrapper_UIImageViewTests: XCTestCase {
wait(for: [expectation], timeout: 2.0)
}

func testDefaultImageOptionIsSet() throws {
func testDefaultAvatarOptionIsSet() throws {
let expectedQueryItemString = "d=robohash"

let imageView = UIImageView(frame: frame)
Expand Down

0 comments on commit 6958d72

Please sign in to comment.