Merge branch 'mlin/PR/VariousFixes'
This commit is contained in:
commit
532db84e73
99
Gemfile.lock
99
Gemfile.lock
@ -10,7 +10,8 @@ GIT
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.3)
|
||||
CFPropertyList (3.0.5)
|
||||
rexml
|
||||
activesupport (5.2.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
@ -24,21 +25,21 @@ GEM
|
||||
anbt-sql-formatter (0.1.0)
|
||||
artifactory (3.0.15)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.1.1)
|
||||
aws-partitions (1.479.0)
|
||||
aws-sdk-core (3.117.0)
|
||||
aws-eventstream (1.2.0)
|
||||
aws-partitions (1.568.0)
|
||||
aws-sdk-core (3.130.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.239.0)
|
||||
aws-partitions (~> 1, >= 1.525.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
jmespath (~> 1.0)
|
||||
aws-sdk-kms (1.44.0)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sdk-kms (1.55.0)
|
||||
aws-sdk-core (~> 3, >= 3.127.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.96.2)
|
||||
aws-sdk-core (~> 3, >= 3.112.0)
|
||||
aws-sdk-s3 (1.113.0)
|
||||
aws-sdk-core (~> 3, >= 3.127.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sigv4 (1.2.4)
|
||||
aws-sigv4 (~> 1.4)
|
||||
aws-sigv4 (1.4.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
claide (1.0.3)
|
||||
@ -85,25 +86,27 @@ GEM
|
||||
highline (~> 2.0.0)
|
||||
concurrent-ruby (1.1.9)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.6.3)
|
||||
digest-crc (0.6.4)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.5.20190701)
|
||||
unf (>= 0.0.5, < 1.0.0)
|
||||
dotenv (2.7.6)
|
||||
emoji_regex (3.2.2)
|
||||
emoji_regex (3.2.3)
|
||||
escape (0.0.4)
|
||||
ethon (0.14.0)
|
||||
ffi (>= 1.15.0)
|
||||
excon (0.85.0)
|
||||
faraday (1.5.1)
|
||||
excon (0.92.1)
|
||||
faraday (1.10.0)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.1)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-cookie_jar (0.0.7)
|
||||
faraday (>= 0.8.0)
|
||||
@ -112,13 +115,17 @@ GEM
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.0.3)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday-net_http (1.0.1)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday_middleware (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
faraday_middleware (1.2.0)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.2.4)
|
||||
fastlane (2.188.0)
|
||||
fastimage (2.2.6)
|
||||
fastlane (2.205.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
@ -135,7 +142,7 @@ GEM
|
||||
faraday_middleware (~> 1.0)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.1)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
@ -144,6 +151,7 @@ GEM
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (~> 2.0.0)
|
||||
naturally (~> 2.2)
|
||||
optparse (~> 0.1.1)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 2.0.0, < 3.0.0)
|
||||
security (= 0.1.3)
|
||||
@ -160,9 +168,9 @@ GEM
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.8.0)
|
||||
google-apis-androidpublisher_v3 (0.16.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-core (0.4.1)
|
||||
google-apis-core (0.4.2)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
@ -171,45 +179,45 @@ GEM
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
webrick
|
||||
google-apis-iamcredentials_v1 (0.6.0)
|
||||
google-apis-iamcredentials_v1 (0.10.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.5.0)
|
||||
google-apis-playcustomapp_v1 (0.7.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-apis-storage_v1 (0.6.0)
|
||||
google-apis-storage_v1 (0.11.0)
|
||||
google-apis-core (>= 0.4, < 2.a)
|
||||
google-cloud-core (1.6.0)
|
||||
google-cloud-env (~> 1.0)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.5.0)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
google-cloud-errors (1.1.0)
|
||||
google-cloud-storage (1.34.1)
|
||||
addressable (~> 2.5)
|
||||
google-cloud-errors (1.2.0)
|
||||
google-cloud-storage (1.36.1)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.1)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (0.16.2)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
googleauth (1.1.2)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
memoist (~> 0.16)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (~> 0.14)
|
||||
signet (>= 0.16, < 2.a)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.4)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.8.10)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jmespath (1.4.0)
|
||||
json (2.5.1)
|
||||
jwt (2.2.3)
|
||||
jmespath (1.6.1)
|
||||
json (2.6.1)
|
||||
jwt (2.3.0)
|
||||
memoist (0.16.2)
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.0)
|
||||
mini_mime (1.1.2)
|
||||
minitest (5.14.4)
|
||||
molinillo (0.6.6)
|
||||
multi_json (1.15.0)
|
||||
@ -218,7 +226,8 @@ GEM
|
||||
nap (1.1.0)
|
||||
naturally (2.2.1)
|
||||
netrc (0.11.0)
|
||||
os (1.1.1)
|
||||
optparse (0.1.1)
|
||||
os (1.1.4)
|
||||
plist (3.6.0)
|
||||
public_suffix (4.0.6)
|
||||
rake (13.0.6)
|
||||
@ -233,9 +242,9 @@ GEM
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
security (0.1.3)
|
||||
signet (0.15.0)
|
||||
addressable (~> 2.3)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
signet (0.16.1)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.0)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.8)
|
||||
@ -245,7 +254,7 @@ GEM
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
trailblazer-option (0.1.1)
|
||||
trailblazer-option (0.1.2)
|
||||
tty-cursor (0.7.1)
|
||||
tty-screen (0.8.1)
|
||||
tty-spinner (0.9.3)
|
||||
@ -257,14 +266,14 @@ GEM
|
||||
uber (0.1.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
unf_ext (0.0.8.1)
|
||||
unicode-display_width (1.8.0)
|
||||
webrick (1.7.0)
|
||||
word_wrap (1.0.0)
|
||||
xcode-install (2.7.0)
|
||||
claide (>= 0.9.1, < 1.1.0)
|
||||
fastlane (>= 2.1.0, < 3.0.0)
|
||||
xcodeproj (1.20.0)
|
||||
xcodeproj (1.21.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
|
||||
@ -177,6 +177,17 @@ struct EmojiModel {
|
||||
}
|
||||
}
|
||||
|
||||
var isNormalized: Bool { enumName == normalizedEnumName }
|
||||
var normalizedEnumName: String {
|
||||
switch enumName {
|
||||
// flagUm (US Minor Outlying Islands) looks identical to the
|
||||
// US flag. We don't present it as a sendable reaction option
|
||||
// This matches the iOS keyboard behavior.
|
||||
case "flagUm": return "us"
|
||||
default: return enumName
|
||||
}
|
||||
}
|
||||
|
||||
static func parseCodePointString(_ pointString: String) -> [UnicodeScalar] {
|
||||
return pointString
|
||||
.components(separatedBy: "-")
|
||||
@ -413,15 +424,17 @@ extension EmojiGenerator {
|
||||
fileHandle.writeLine("")
|
||||
|
||||
// Emoji lookup per category
|
||||
fileHandle.writeLine("var emoji: [Emoji] {")
|
||||
fileHandle.writeLine("var normalizedEmoji: [Emoji] {")
|
||||
fileHandle.indent {
|
||||
fileHandle.writeLine("switch self {")
|
||||
|
||||
let emojiPerCategory: [RemoteModel.EmojiCategory: [EmojiModel.EmojiDefinition]]
|
||||
emojiPerCategory = emojiModel.definitions.reduce(into: [:]) { result, emojiDef in
|
||||
var categoryList = result[emojiDef.category] ?? []
|
||||
categoryList.append(emojiDef)
|
||||
result[emojiDef.category] = categoryList
|
||||
let normalizedEmojiPerCategory: [RemoteModel.EmojiCategory: [EmojiModel.EmojiDefinition]]
|
||||
normalizedEmojiPerCategory = emojiModel.definitions.reduce(into: [:]) { result, emojiDef in
|
||||
if emojiDef.isNormalized {
|
||||
var categoryList = result[emojiDef.category] ?? []
|
||||
categoryList.append(emojiDef)
|
||||
result[emojiDef.category] = categoryList
|
||||
}
|
||||
}
|
||||
|
||||
for category in outputCategories {
|
||||
@ -430,9 +443,9 @@ extension EmojiGenerator {
|
||||
case .smileysAndPeople:
|
||||
// Merge smileys & people. It's important we initially bucket these separately,
|
||||
// because we want the emojis to be sorted smileys followed by people
|
||||
return emojiPerCategory[.smileys]! + emojiPerCategory[.people]!
|
||||
return normalizedEmojiPerCategory[.smileys]! + normalizedEmojiPerCategory[.people]!
|
||||
default:
|
||||
return emojiPerCategory[category]!
|
||||
return normalizedEmojiPerCategory[category]!
|
||||
}
|
||||
}()
|
||||
|
||||
@ -469,6 +482,20 @@ extension EmojiGenerator {
|
||||
fileHandle.writeLine("}")
|
||||
}
|
||||
fileHandle.writeLine("}")
|
||||
fileHandle.writeLine("")
|
||||
|
||||
// Normalized variant mapping
|
||||
fileHandle.writeLine("var isNormalized: Bool { normalized == self }")
|
||||
fileHandle.writeLine("var normalized: Emoji {")
|
||||
fileHandle.indent {
|
||||
fileHandle.writeLine("switch self {")
|
||||
emojiModel.definitions.filter { !$0.isNormalized }.forEach {
|
||||
fileHandle.writeLine("case .\($0.enumName): return .\($0.normalizedEnumName)")
|
||||
}
|
||||
fileHandle.writeLine("default: return self")
|
||||
fileHandle.writeLine("}")
|
||||
}
|
||||
fileHandle.writeLine("}")
|
||||
}
|
||||
fileHandle.writeLine("}")
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -24,9 +24,9 @@ class EmojiPickerCollectionView: UICollectionView {
|
||||
private let recentEmoji: [EmojiWithSkinTones]
|
||||
var hasRecentEmoji: Bool { !recentEmoji.isEmpty }
|
||||
|
||||
private let allAvailableEmojiByCategory: [Emoji.Category: [EmojiWithSkinTones]]
|
||||
private lazy var allAvailableEmoji: [EmojiWithSkinTones] = {
|
||||
return Array(allAvailableEmojiByCategory.values).flatMap({$0})
|
||||
private let allSendableEmojiByCategory: [Emoji.Category: [EmojiWithSkinTones]]
|
||||
private lazy var allSendableEmoji: [EmojiWithSkinTones] = {
|
||||
return Array(allSendableEmojiByCategory.values).flatMap({$0})
|
||||
}()
|
||||
|
||||
static let emojiWidth: CGFloat = 38
|
||||
@ -59,16 +59,32 @@ class EmojiPickerCollectionView: UICollectionView {
|
||||
layout.minimumInteritemSpacing = EmojiPickerCollectionView.minimumSpacing
|
||||
layout.sectionInset = UIEdgeInsets(top: 0, leading: EmojiPickerCollectionView.margins, bottom: 0, trailing: EmojiPickerCollectionView.margins)
|
||||
|
||||
(recentEmoji, allAvailableEmojiByCategory) = SDSDatabaseStorage.shared.read { transaction in
|
||||
let rawEmoji = EmojiPickerCollectionView.keyValueStore.getObject(
|
||||
(recentEmoji, allSendableEmojiByCategory) = SDSDatabaseStorage.shared.read { transaction in
|
||||
let rawRecentEmoji = EmojiPickerCollectionView.keyValueStore.getObject(
|
||||
forKey: EmojiPickerCollectionView.recentEmojiKey,
|
||||
transaction: transaction
|
||||
) as? [String] ?? []
|
||||
let recentEmoji = rawEmoji.compactMap { EmojiWithSkinTones(rawValue: $0) }
|
||||
let allAvailableEmojiByCategory = Emoji.allAvailableEmojiByCategoryWithPreferredSkinTones(
|
||||
|
||||
var recentEmoji = rawRecentEmoji.compactMap { EmojiWithSkinTones(rawValue: $0) }
|
||||
|
||||
// Some emoji have two different code points but identical appearances. Let's remove them!
|
||||
// If we normalize to a different emoji than the one currently in our array, we want to drop
|
||||
// the non-normalized variant if the normalized variant already exists. Otherwise, map to the
|
||||
// normalized variant.
|
||||
for (idx, emoji) in recentEmoji.enumerated().reversed() {
|
||||
if !emoji.isNormalized {
|
||||
if recentEmoji.contains(emoji.normalized) {
|
||||
recentEmoji.remove(at: idx)
|
||||
} else {
|
||||
recentEmoji[idx] = emoji.normalized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let allSendableEmojiByCategory = Emoji.allSendableEmojiByCategoryWithPreferredSkinTones(
|
||||
transaction: transaction
|
||||
)
|
||||
return (recentEmoji, allAvailableEmojiByCategory)
|
||||
return (recentEmoji, allSendableEmojiByCategory)
|
||||
}
|
||||
|
||||
super.init(frame: .zero, collectionViewLayout: layout)
|
||||
@ -121,7 +137,7 @@ class EmojiPickerCollectionView: UICollectionView {
|
||||
return []
|
||||
}
|
||||
|
||||
guard let categoryEmoji = allAvailableEmojiByCategory[category] else {
|
||||
guard let categoryEmoji = allSendableEmojiByCategory[category] else {
|
||||
owsFailDebug("Unexpectedly missing emoji for category \(category)")
|
||||
return []
|
||||
}
|
||||
@ -149,6 +165,10 @@ class EmojiPickerCollectionView: UICollectionView {
|
||||
|
||||
func recordRecentEmoji(_ emoji: EmojiWithSkinTones, transaction: SDSAnyWriteTransaction) {
|
||||
guard recentEmoji.first != emoji else { return }
|
||||
guard emoji.isNormalized else {
|
||||
recordRecentEmoji(emoji.normalized, transaction: transaction)
|
||||
return
|
||||
}
|
||||
|
||||
var newRecentEmoji = recentEmoji
|
||||
|
||||
@ -192,7 +212,7 @@ class EmojiPickerCollectionView: UICollectionView {
|
||||
func searchWithText(_ searchText: String?) {
|
||||
if let searchText = searchText {
|
||||
if let emojiSearchIndex = emojiSearchIndex {
|
||||
emojiSearchResults = allAvailableEmoji.filter { emoji in
|
||||
emojiSearchResults = allSendableEmoji.filter { emoji in
|
||||
let rawEmoji = emoji.baseEmoji.rawValue
|
||||
if let terms = emojiSearchIndex[rawEmoji] {
|
||||
for term in terms {
|
||||
@ -204,7 +224,7 @@ class EmojiPickerCollectionView: UICollectionView {
|
||||
return false
|
||||
}
|
||||
} else { // Search on raw emoji name if no index is available
|
||||
emojiSearchResults = allAvailableEmoji.filter { emoji in
|
||||
emojiSearchResults = allSendableEmoji.filter { emoji in
|
||||
return emoji.baseEmoji.name.range(of: searchText, options: [.caseInsensitive, .anchored]) != nil
|
||||
}
|
||||
}
|
||||
@ -594,3 +614,18 @@ private class EmojiSearchIndex: NSObject {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension EmojiWithSkinTones {
|
||||
|
||||
var normalized: EmojiWithSkinTones {
|
||||
switch (baseEmoji, skinTones) {
|
||||
case (let base, nil) where base.normalized != base:
|
||||
return EmojiWithSkinTones(baseEmoji: base.normalized)
|
||||
default:
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
var isNormalized: Bool { self == normalized }
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -335,6 +335,7 @@ public class OnboardingProfileCreationViewController: OnboardingBaseViewControll
|
||||
primaryView.addSubview(spinner)
|
||||
spinner.autoCenterInSuperviewMargins()
|
||||
spinner.startAnimating()
|
||||
saveButton.setEnabled(false)
|
||||
|
||||
firstly(on: .sharedUserInitiated) {
|
||||
OWSProfileManager.updateLocalProfilePromise(
|
||||
@ -345,14 +346,28 @@ public class OnboardingProfileCreationViewController: OnboardingBaseViewControll
|
||||
profileAvatarData: avatarData,
|
||||
visibleBadgeIds: [],
|
||||
userProfileWriter: .registration)
|
||||
}.recover { error in
|
||||
owsFailDebug("Error: \(error)")
|
||||
}.done {
|
||||
self.profileCompleted()
|
||||
UIView.animate(withDuration: 0.15) {
|
||||
spinner.alpha = 0
|
||||
} completion: { _ in
|
||||
spinner.removeFromSuperview()
|
||||
self.saveButton.setEnabled(self.isValidProfile)
|
||||
}
|
||||
}.catch { error in
|
||||
spinner.stopAnimating(success: false) {
|
||||
spinner.removeFromSuperview()
|
||||
self.saveButton.setEnabled(self.isValidProfile)
|
||||
|
||||
if error.isNetworkConnectivityFailure {
|
||||
OWSActionSheets.showErrorAlert(
|
||||
message: NSLocalizedString(
|
||||
"PROFILE_VIEW_NO_CONNECTION",
|
||||
comment: "Error shown when the user tries to update their profile when the app is not connected to the internet.")
|
||||
)
|
||||
} else {
|
||||
OWSActionSheets.showErrorAlert(message: error.userErrorDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ extension Emoji {
|
||||
}
|
||||
}
|
||||
|
||||
var emoji: [Emoji] {
|
||||
var normalizedEmoji: [Emoji] {
|
||||
switch self {
|
||||
case .smileysAndPeople:
|
||||
return [
|
||||
@ -1887,7 +1887,6 @@ extension Emoji {
|
||||
.flagTz,
|
||||
.flagUa,
|
||||
.flagUg,
|
||||
.flagUm,
|
||||
.flagUn,
|
||||
.us,
|
||||
.flagUy,
|
||||
@ -3769,4 +3768,12 @@ extension Emoji {
|
||||
default: fatalError("Unexpected case \(self)")
|
||||
}
|
||||
}
|
||||
|
||||
var isNormalized: Bool { normalized == self }
|
||||
var normalized: Emoji {
|
||||
switch self {
|
||||
case .flagUm: return .us
|
||||
default: return self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
public struct EmojiWithSkinTones: Hashable {
|
||||
@ -31,9 +31,9 @@ public struct EmojiWithSkinTones: Hashable {
|
||||
extension Emoji {
|
||||
private static let keyValueStore = SDSKeyValueStore(collection: "Emoji+PreferredSkinTonePermutation")
|
||||
|
||||
static func allAvailableEmojiByCategoryWithPreferredSkinTones(transaction: SDSAnyReadTransaction) -> [Category: [EmojiWithSkinTones]] {
|
||||
static func allSendableEmojiByCategoryWithPreferredSkinTones(transaction: SDSAnyReadTransaction) -> [Category: [EmojiWithSkinTones]] {
|
||||
return Category.allCases.reduce(into: [Category: [EmojiWithSkinTones]]()) { result, category in
|
||||
result[category] = category.emoji.filter { $0.available }.map { $0.withPreferredSkinTones(transaction: transaction) }
|
||||
result[category] = category.normalizedEmoji.filter { $0.available }.map { $0.withPreferredSkinTones(transaction: transaction) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RESTNetworkManager.h"
|
||||
@ -176,9 +176,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
dispatch_async(NetworkManagerQueue(), ^{
|
||||
[sessionManagerPool returnToPool:sessionManager];
|
||||
});
|
||||
|
||||
|
||||
dispatch_async(completionQueue, ^{
|
||||
OWSLogInfo(@"%@ succeeded : %@", label, request);
|
||||
OWSLogInfo(@"%@ succeeded (%ld) : %@", label, response.responseStatusCode, request);
|
||||
|
||||
if (request.canUseAuth && request.shouldHaveAuthorizationHeaders) {
|
||||
[RESTNetworkManager.tsAccountManager setIsDeregistered:NO];
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2021 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2022 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@ -186,6 +186,30 @@ public class OWSHttpHeaders: NSObject {
|
||||
request.replace(httpHeaders: httpHeaders)
|
||||
return request
|
||||
}
|
||||
|
||||
// MARK: - NSObject Overrides
|
||||
|
||||
static let whitelistedLoggedHeaderKeys = Set([
|
||||
"retry-after",
|
||||
"x-signal-timestamp"
|
||||
// Have a header key who's value you'd like to see logged? Add it here (lowercased)!
|
||||
])
|
||||
|
||||
override public var description: String {
|
||||
let loggedPairsString: String = headers.lazy
|
||||
.filter { Self.whitelistedLoggedHeaderKeys.contains($0.key.lowercased()) == true }
|
||||
.map { "\($0.key): \($0.value.description)" }
|
||||
.joined(separator: "; ")
|
||||
|
||||
let leftoverKeysString: String = headers.keys.lazy
|
||||
.filter { Self.whitelistedLoggedHeaderKeys.contains($0.lowercased()) == false }
|
||||
.joined(separator: ", ")
|
||||
|
||||
return "<\(super.description)"
|
||||
.appending(loggedPairsString.count > 0 ? " (\(loggedPairsString))" : "")
|
||||
.appending(leftoverKeysString.count > 0 ? " (\(leftoverKeysString))" : "")
|
||||
.appending(">")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - HTTP Headers
|
||||
|
||||
@ -1154,31 +1154,28 @@ extension OWSWebSocket {
|
||||
let webSocketType = self.webSocketType
|
||||
let canUseAuth = webSocketType == .identified && !request.isUDRequest
|
||||
|
||||
self.makeRequestInternal(request,
|
||||
unsubmittedRequestToken: unsubmittedRequestToken,
|
||||
success: { (response: HTTPResponse, requestInfo: SocketRequestInfo) in
|
||||
let label = Self.label(forRequest: request,
|
||||
webSocketType: webSocketType,
|
||||
requestInfo: requestInfo)
|
||||
self.makeRequestInternal(
|
||||
request,
|
||||
unsubmittedRequestToken: unsubmittedRequestToken,
|
||||
success: { (response: HTTPResponse, requestInfo: SocketRequestInfo) in
|
||||
let label = Self.label(forRequest: request, webSocketType: webSocketType, requestInfo: requestInfo)
|
||||
Logger.info("\(label): Request Succeeded (\(response.responseStatusCode))")
|
||||
|
||||
Logger.info("\(label): Request Succeeded")
|
||||
if canUseAuth, request.shouldHaveAuthorizationHeaders {
|
||||
Self.tsAccountManager.setIsDeregistered(false)
|
||||
}
|
||||
|
||||
if canUseAuth,
|
||||
request.shouldHaveAuthorizationHeaders {
|
||||
Self.tsAccountManager.setIsDeregistered(false)
|
||||
}
|
||||
successParam(response)
|
||||
|
||||
successParam(response)
|
||||
Self.outageDetection.reportConnectionSuccess()
|
||||
},
|
||||
failure: { (failure: OWSHTTPErrorWrapper) in
|
||||
if failure.error.responseStatusCode == AppExpiry.appExpiredStatusCode {
|
||||
Self.appExpiry.setHasAppExpiredAtCurrentVersion()
|
||||
}
|
||||
|
||||
Self.outageDetection.reportConnectionSuccess()
|
||||
},
|
||||
failure: { (failure: OWSHTTPErrorWrapper) in
|
||||
if failure.error.responseStatusCode == AppExpiry.appExpiredStatusCode {
|
||||
Self.appExpiry.setHasAppExpiredAtCurrentVersion()
|
||||
}
|
||||
|
||||
failureParam(failure)
|
||||
})
|
||||
failureParam(failure)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user