Skip to content

Commit

Permalink
Merge pull request #133 from wordpress-mobile/task/refactor-gravatar
Browse files Browse the repository at this point in the history
UI Modernization: Extract gravatarUrl to Gravatar
  • Loading branch information
momo-ozawa authored Aug 25, 2023
2 parents 733e331 + 4b8c5b7 commit ecc2e79
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 72 deletions.
79 changes: 77 additions & 2 deletions Sources/WordPressUI/Extensions/Gravatar/Gravatar.swift
Original file line number Diff line number Diff line change
@@ -1,17 +1,55 @@
import Foundation

/// Helper Enum that specifies all of the available Gravatar Image Ratings
/// TODO: Convert into a pure Swift String Enum. It's done this way to maintain ObjC Compatibility
///
@objc
public enum GravatarRatings: Int {
case g
case pg
case r
case x
case `default`

func stringValue() -> String {
switch self {
case .default:
fallthrough
case .g:
return "g"
case .pg:
return "pg"
case .r:
return "r"
case .x:
return "x"
}
}
}

/// Helper Enum that specifies some of the options for default images
/// To see all available options, visit : https://en.gravatar.com/site/implement/images/
///
public enum GravatarDefaultImage: String {
case fileNotFound = "404"
case mp
case identicon
}

public struct Gravatar {
fileprivate struct Defaults {
static let scheme = "https"
static let host = "secure.gravatar.com"
static let unknownHash = "ad516503a11cd5ca435acc9bb6523536"
static let baseURL = "https://gravatar.com/avatar"
static let imageSize = 80
}

public let canonicalURL: URL

public func urlWithSize(_ size: Int) -> URL {
public func urlWithSize(_ size: Int, defaultImage: GravatarDefaultImage? = nil) -> URL {
var components = URLComponents(url: canonicalURL, resolvingAgainstBaseURL: false)!
components.query = "s=\(size)&d=404"
components.query = "s=\(size)&d=\(defaultImage?.rawValue ?? GravatarDefaultImage.fileNotFound.rawValue)"
return components.url!
}

Expand All @@ -30,6 +68,43 @@ public struct Gravatar {

return true
}

/// Returns the Gravatar URL, for a given email, with the specified size + rating.
///
/// - Parameters:
/// - email: the user's email
/// - size: required download size
/// - rating: image rating filtering
///
/// - Returns: Gravatar's URL
///
public static func gravatarUrl(for email: String,
defaultImage: GravatarDefaultImage? = nil,
size: Int? = nil,
rating: GravatarRatings = .default) -> URL? {
let hash = gravatarHash(of: email)
let targetURL = String(format: "%@/%@?d=%@&s=%d&r=%@",
Defaults.baseURL,
hash,
defaultImage?.rawValue ?? GravatarDefaultImage.fileNotFound.rawValue,
size ?? Defaults.imageSize,
rating.stringValue())
return URL(string: targetURL)
}

/// Returns the gravatar hash of an email
///
/// - Parameter email: the email associated with the gravatar
/// - Returns: hashed email
///
/// This really ought to be in a different place, like Gravatar.swift, but there's
/// lots of duplication around gravatars -nh
private static func gravatarHash(of email: String) -> String {
return email
.lowercased()
.trimmingCharacters(in: .whitespaces)
.sha256Hash()
}
}

extension Gravatar: Equatable {}
Expand Down
63 changes: 3 additions & 60 deletions Sources/WordPressUI/Extensions/UIImageView+Gravatar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,6 @@ private class GravatarNotificationWrapper {
///
extension UIImageView {

/// Helper Enum that specifies all of the available Gravatar Image Ratings
/// TODO: Convert into a pure Swift String Enum. It's done this way to maintain ObjC Compatibility
///
@objc
public enum GravatarRatings: Int {
case g
case pg
case r
case x
case `default`

func stringValue() -> String {
switch self {
case .default:
fallthrough
case .g:
return "g"
case .pg:
return "pg"
case .r:
return "r"
case .x:
return "x"
}
}
}

/// Downloads and sets the User's Gravatar, given his email.
/// TODO: This is a convenience method. Please, remove once all of the code has been migrated over to Swift.
///
Expand All @@ -70,7 +43,7 @@ extension UIImageView {
///
@objc
public func downloadGravatarWithEmail(_ email: String, rating: GravatarRatings = .default, placeholderImage: UIImage = .gravatarPlaceholderImage) {
let gravatarURL = gravatarUrl(for: email, size: gravatarDefaultSize(), rating: rating)
let gravatarURL = Gravatar.gravatarUrl(for: email, size: gravatarDefaultSize(), rating: rating)

listenForGravatarChanges(forEmail: email)
downloadImage(from: gravatarURL, placeholderImage: placeholderImage)
Expand Down Expand Up @@ -167,7 +140,7 @@ extension UIImageView {
/// Hope buddah, and the code reviewer, can forgive me for this hack.
///
@objc public func overrideGravatarImageCache(_ image: UIImage, rating: GravatarRatings, email: String) {
guard let gravatarURL = gravatarUrl(for: email, size: gravatarDefaultSize(), rating: rating) else {
guard let gravatarURL = Gravatar.gravatarUrl(for: email, size: gravatarDefaultSize(), rating: rating) else {
return
}

Expand All @@ -191,35 +164,6 @@ extension UIImageView {

// MARK: - Private Helpers

/// Returns the Gravatar URL, for a given email, with the specified size + rating.
///
/// - Parameters:
/// - email: the user's email
/// - size: required download size
/// - rating: image rating filtering
///
/// - Returns: Gravatar's URL
///
private func gravatarUrl(for email: String, size: Int, rating: GravatarRatings) -> URL? {
let hash = gravatarHash(of: email)
let targetURL = String(format: "%@/%@?d=404&s=%d&r=%@", Defaults.baseURL, hash, size, rating.stringValue())
return URL(string: targetURL)
}

/// Returns the gravatar hash of an email
///
/// - Parameter email: the email associated with the gravatar
/// - Returns: hashed email
///
/// This really ought to be in a different place, like Gravatar.swift, but there's
/// lots of duplication around gravatars -nh
private func gravatarHash(of email: String) -> String {
return email
.lowercased()
.trimmingCharacters(in: .whitespaces)
.md5Hash()
}

/// Returns the required gravatar size. If the current view's size is zero, falls back to the default size.
///
private func gravatarDefaultSize() -> Int {
Expand All @@ -235,13 +179,12 @@ extension UIImageView {
///
private struct Defaults {
static let imageSize = 80
static let baseURL = "https://gravatar.com/avatar"
static var gravatarWrapperKey = "gravatarWrapperKey"
static let emailKey = "email"
static let imageKey = "image"
}
}

extension NSNotification.Name {
public extension NSNotification.Name {
static let GravatarImageUpdateNotification = NSNotification.Name(rawValue: "GravatarImageUpdateNotification")
}
2 changes: 1 addition & 1 deletion Sources/WordPressUIObjC/Extensions/NSString+Gravatar.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

@interface NSString (Gravatar)

- (NSString *)md5Hash;
- (NSString *)sha256Hash;

@end
16 changes: 8 additions & 8 deletions Sources/WordPressUIObjC/Extensions/NSString+Gravatar.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@

@implementation NSString (Gravatar)

- (NSString *)md5Hash
- (NSString *)sha256Hash
{
const char *cStr = [self UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
unsigned char result[CC_SHA256_DIGEST_LENGTH];

CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
CC_SHA256(cStr, (CC_LONG)strlen(cStr), result);

return [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]
];
NSMutableString *hashString = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[hashString appendFormat:@"%02x",result[i]];
}
return hashString;
}

@end
2 changes: 1 addition & 1 deletion WordPressUI.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Pod::Spec.new do |s|
s.name = 'WordPressUI'
s.version = '1.14.1'
s.version = '1.14.2-beta.1'

s.summary = 'Home of reusable WordPress UI components.'
s.description = <<-DESC
Expand Down

0 comments on commit ecc2e79

Please sign in to comment.