add new placeholder icon

This commit is contained in:
Ryan ZHAO 2020-09-08 13:36:52 +10:00
parent 65030b7b46
commit 38c6d05236
4 changed files with 82 additions and 1 deletions

View File

@ -472,6 +472,7 @@
7BDCFC08242186E700641C39 /* NotificationServiceExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */; };
7BDCFC092421894900641C39 /* MessageFetcherJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 452ECA4C1E087E7200E2F016 /* MessageFetcherJob.swift */; };
7BDCFC0B2421EB7600641C39 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6F509951AA53F760068F56A /* Localizable.strings */; };
7BF3FF002505B8E400609570 /* PlaceholderIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BF3FEFF2505B8E400609570 /* PlaceholderIcon.swift */; };
A10FDF79184FB4BB007FF963 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 76C87F18181EFCE600C4ACAB /* MediaPlayer.framework */; };
A11CD70D17FA230600A2D1B1 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */; };
A123C14916F902EE000AE905 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A163E8AA16F3F6A90094D68B /* Security.framework */; };
@ -1247,6 +1248,7 @@
7BC01A3F241F40AB00BC7C55 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7BDCFC0424206E7300641C39 /* LokiPushNotificationService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LokiPushNotificationService.entitlements; sourceTree = "<group>"; };
7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtensionContext.swift; sourceTree = "<group>"; };
7BF3FEFF2505B8E400609570 /* PlaceholderIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlaceholderIcon.swift; sourceTree = "<group>"; };
8981C8F64D94D3C52EB67A2C /* Pods-SignalTests.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalTests.test.xcconfig"; path = "Pods/Target Support Files/Pods-SignalTests/Pods-SignalTests.test.xcconfig"; sourceTree = "<group>"; };
8EEE74B0753448C085B48721 /* Pods-SignalMessaging.app store release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalMessaging.app store release.xcconfig"; path = "Pods/Target Support Files/Pods-SignalMessaging/Pods-SignalMessaging.app store release.xcconfig"; sourceTree = "<group>"; };
948239851C08032C842937CC /* Pods-SignalMessaging.test.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalMessaging.test.xcconfig"; path = "Pods/Target Support Files/Pods-SignalMessaging/Pods-SignalMessaging.test.xcconfig"; sourceTree = "<group>"; };
@ -2601,6 +2603,7 @@
B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */,
241C6312231F5F1D00B4198E /* CGFloat+Rounding.swift */,
241C6310231F5C4400B4198E /* UIColor+Helper.swift */,
7BF3FEFF2505B8E400609570 /* PlaceholderIcon.swift */,
);
path = "Jazz Icon";
sourceTree = "<group>";
@ -3700,6 +3703,7 @@
241C6315231F64CE00B4198E /* CGFloat+Rounding.swift in Sources */,
34480B561FD0A7A400BC14EF /* DebugLogger.m in Sources */,
459B775C207BA46C0071D0AB /* OWSQuotedReplyModel.m in Sources */,
7BF3FF002505B8E400609570 /* PlaceholderIcon.swift in Sources */,
340872D622397E6800CB25B0 /* AttachmentCaptionToolbar.swift in Sources */,
34ABB2C42090C59700C727A6 /* OWSResaveCollectionDBMigration.m in Sources */,
4C948FF72146EB4800349F0D /* BlockListCache.swift in Sources */,

View File

@ -10,4 +10,13 @@ public final class Identicon : NSObject {
let image = renderer.image { iconLayer.render(in: $0.cgContext) }
return image
}
@objc public static func generatePlaceholderIcon(seed: String, text: String, size: CGFloat) -> UIImage {
let icon = PlaceholderIcon(seed: seed)
let iconLayer = icon.generateLayer(ofSize: size, with: text.substring(to: 1))
let rect = CGRect(origin: CGPoint.zero, size: iconLayer.frame.size)
let renderer = UIGraphicsImageRenderer(size: rect.size)
let image = renderer.image { iconLayer.render(in: $0.cgContext) }
return image
}
}

View File

@ -0,0 +1,67 @@
import CryptoSwift
public class PlaceholderIcon {
private let seed: Int
// Colour palette
private var colours: [UIColor] = [
0x5ff8b0,
0x26cdb9,
0xf3c615,
0xfcac5a
].map { UIColor(rgb: $0) }
init(seed: Int, colours: [UIColor]? = nil) {
self.seed = seed
if let colours = colours {
self.colours = colours
}
}
convenience init(seed: String, colours: [UIColor]? = nil) {
// Ensure we have a correct hash
var hash = seed
if !hash.matches("^[0-9A-Fa-f]+$") || hash.count < 12 { hash = seed.sha512() }
guard let number = Int(hash.substring(to: 12), radix: 16) else {
owsFailDebug("[PlaceholderIcon] Failed to generate number from seed string: \(seed)")
self.init(seed: 0, colours: colours)
return
}
self.init(seed: number, colours: colours)
}
public func generateLayer(ofSize diameter: CGFloat, with text: String) -> CALayer {
let colour = self.colours[seed % self.colours.count].cgColor
let base = getTextLayer(with: diameter, colour: colour, text: text)
base.masksToBounds = true
return base
}
private func getTextLayer(with diameter: CGFloat, colour: CGColor? = nil, text: String) -> CALayer {
let font = UIFont.boldSystemFont(ofSize: diameter/2)
let height = NSString(string: text).boundingRect(with: CGSize(width: diameter, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil).height
let frame = CGRect(x: 0, y: (diameter - height)/2, width: diameter, height: height)
let layer = CATextLayer()
layer.frame = frame
layer.foregroundColor = UIColor.white.cgColor
layer.contentsScale = UIScreen.main.scale
let fontName = font.fontName;
let fontRef = CGFont(fontName as CFString);
layer.font = fontRef;
layer.fontSize = font.pointSize;
layer.alignmentMode = .center
layer.string = text
let base = CALayer()
base.frame = CGRect(x: 0, y: 0, width: diameter, height: diameter)
base.backgroundColor = colour
base.addSublayer(layer)
return base
}
}

View File

@ -46,8 +46,9 @@ public final class ProfilePictureView : UIView {
@objc public func update() {
AssertIsOnMainThread()
func getProfilePicture(of size: CGFloat, for hexEncodedPublicKey: String) -> UIImage? {
OWSLogger.debug("[Ryan] \(hexEncodedPublicKey)")
guard !hexEncodedPublicKey.isEmpty else { return nil }
return OWSProfileManager.shared().profileAvatar(forRecipientId: hexEncodedPublicKey) ?? Identicon.generateIcon(string: hexEncodedPublicKey, size: size)
return OWSProfileManager.shared().profileAvatar(forRecipientId: hexEncodedPublicKey) ?? Identicon.generatePlaceholderIcon(seed: hexEncodedPublicKey, text: OWSProfileManager.shared().profileNameForRecipient(withID: hexEncodedPublicKey) ?? hexEncodedPublicKey, size: size)
}
let size: CGFloat
if let additionalHexEncodedPublicKey = additionalHexEncodedPublicKey, !isRSSFeed, openGroupProfilePicture == nil {