From 9593f3737362fa183d14132935beff006531076e Mon Sep 17 00:00:00 2001 From: Nora Trapp Date: Wed, 27 May 2020 23:51:31 -0700 Subject: [PATCH] Add a helper to see if a given emoji is available on the current iOS version --- Signal.xcodeproj/project.pbxproj | 4 ++ Signal/src/util/Emoji/Emoji+Available.swift | 44 +++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 Signal/src/util/Emoji/Emoji+Available.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 8c2e7c2723..c197ec59f5 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -620,6 +620,7 @@ 880BFFEA234590FA00F6FAB1 /* ConversationSplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 880BFFE82345907600F6FAB1 /* ConversationSplitViewController.swift */; }; 880C0FF7233D3F7C00386FB8 /* playPauseButton.json in Resources */ = {isa = PBXBuildFile; fileRef = 880C0FF6233D3F7C00386FB8 /* playPauseButton.json */; }; 880D9025247F8841003D2B14 /* Emoji+Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = 880D9024247F8841003D2B14 /* Emoji+Name.swift */; }; + 880D9027247F90CC003D2B14 /* Emoji+Available.swift in Sources */ = {isa = PBXBuildFile; fileRef = 880D9026247F90CC003D2B14 /* Emoji+Available.swift */; }; 8810223722DF9C2300A7C44F /* OnboardingPinAttemptsExhaustedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8810223622DF9C2300A7C44F /* OnboardingPinAttemptsExhaustedViewController.swift */; }; 8811CF842295D8DA00FF6549 /* VolumeButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8811CF832295D8DA00FF6549 /* VolumeButtons.swift */; }; 881218F0238CA51600E6F271 /* MessageReactionPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 881218EF238CA51600E6F271 /* MessageReactionPicker.swift */; }; @@ -1576,6 +1577,7 @@ 880BFFE82345907600F6FAB1 /* ConversationSplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationSplitViewController.swift; sourceTree = ""; }; 880C0FF6233D3F7C00386FB8 /* playPauseButton.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = playPauseButton.json; sourceTree = ""; }; 880D9024247F8841003D2B14 /* Emoji+Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Emoji+Name.swift"; sourceTree = ""; }; + 880D9026247F90CC003D2B14 /* Emoji+Available.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Emoji+Available.swift"; sourceTree = ""; }; 880FC0A023BFDADC00A2A900 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = translations/sk.lproj/Localizable.strings; sourceTree = ""; }; 8810223622DF9C2300A7C44F /* OnboardingPinAttemptsExhaustedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingPinAttemptsExhaustedViewController.swift; sourceTree = ""; }; 8811CF832295D8DA00FF6549 /* VolumeButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeButtons.swift; sourceTree = ""; }; @@ -3114,6 +3116,7 @@ 887889B0247F2E72001B5FCF /* Emoji.swift */, 887889AF247F2E72001B5FCF /* Emoji+Category.swift */, 880D9024247F8841003D2B14 /* Emoji+Name.swift */, + 880D9026247F90CC003D2B14 /* Emoji+Available.swift */, ); path = Emoji; sourceTree = ""; @@ -4744,6 +4747,7 @@ 340CCB6A23032762005243B3 /* YDBLegacyMigration.m in Sources */, 88A4CC09246CB0960082211F /* OnboardingTransferChoiceViewController.swift in Sources */, 3496955D219B605E00DCFE74 /* PhotoCollectionPickerController.swift in Sources */, + 880D9027247F90CC003D2B14 /* Emoji+Available.swift in Sources */, 8835DDFD230CEE8900DC6B66 /* RecipientPickerDelegate.swift in Sources */, 34E6003A24251AD50026AD4B /* GroupViewUtils.swift in Sources */, 340E9AC4236095CD00FA362C /* AttachmentMultisend.swift in Sources */, diff --git a/Signal/src/util/Emoji/Emoji+Available.swift b/Signal/src/util/Emoji/Emoji+Available.swift new file mode 100644 index 0000000000..ebe881bbe1 --- /dev/null +++ b/Signal/src/util/Emoji/Emoji+Available.swift @@ -0,0 +1,44 @@ +// +// Copyright (c) 2020 Open Whisper Systems. All rights reserved. +// + +extension Emoji { + static var availableCache = [Emoji: Bool]() + + /// Indicates whether the given emoji is available on this iOS + /// version. We cache the availability in memory. + var available: Bool { + guard let available = Emoji.availableCache[self] else { + let available = rawValue.isUnicodeStringAvailable + Emoji.availableCache[self] = available + return available + } + + return available + } +} + +private extension String { + /// A known undefined unicode character for comparison + private static let unknownUnicodeStringPng = "\u{1fff}".unicodeStringPngRepresentation + + // Based on https://stackoverflow.com/a/41393387 + // Check if an emoji is available on the current iOS version + // by verifying its image is different than the "unknwon" + // reference image + var isUnicodeStringAvailable: Bool { + return String.unknownUnicodeStringPng != unicodeStringPngRepresentation + } + + var unicodeStringPngRepresentation: Data? { + let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 8)] + let size = (self as NSString).size(withAttributes: attributes) + + UIGraphicsBeginImageContext(size) + defer { UIGraphicsEndImageContext() } + (self as NSString).draw(at: CGPoint(x: 0, y: 0), withAttributes: attributes) + + guard let unicodeImage = UIGraphicsGetImageFromCurrentImageContext() else { return nil } + return unicodeImage.pngData() + } +}