[WIP] Started work fixing XCode 15 build issues

Reworked the EmojiGenerator to structure the 'EmojiWithSkinTones+String" file as the original structure was causing XCode 15 to build forever
Reworked the seed node certificate loading in an effort to fix a crash
Updated to the latest version of webp
Commented out a line causing build issues
Fixed a number of build warnings
Fixed an issue which could cause migration issues when upgrading from certain old versions
This commit is contained in:
Morgan Pretty 2023-09-20 16:57:59 +10:00
parent 67ab1e5194
commit 4c934d2fda
20 changed files with 6189 additions and 8508 deletions

View File

@ -13,15 +13,18 @@ PODS:
- DifferenceKit/Core
- GRDB.swift/SQLCipher (6.13.0):
- SQLCipher (>= 3.4.2)
- libwebp (1.2.1):
- libwebp/demux (= 1.2.1)
- libwebp/mux (= 1.2.1)
- libwebp/webp (= 1.2.1)
- libwebp/demux (1.2.1):
- libwebp (1.3.2):
- libwebp/demux (= 1.3.2)
- libwebp/mux (= 1.3.2)
- libwebp/sharpyuv (= 1.3.2)
- libwebp/webp (= 1.3.2)
- libwebp/demux (1.3.2):
- libwebp/webp
- libwebp/mux (1.2.1):
- libwebp/mux (1.3.2):
- libwebp/demux
- libwebp/webp (1.2.1)
- libwebp/sharpyuv (1.3.2)
- libwebp/webp (1.3.2):
- libwebp/sharpyuv
- Nimble (10.0.0)
- NVActivityIndicatorView (5.1.1):
- NVActivityIndicatorView/Base (= 5.1.1)
@ -134,7 +137,6 @@ SPEC REPOS:
- CocoaLumberjack
- DifferenceKit
- GRDB.swift
- libwebp
- Nimble
- NVActivityIndicatorView
- OpenSSL-Universal
@ -146,6 +148,7 @@ SPEC REPOS:
- SwiftProtobuf
- WebRTC-lib
trunk:
- libwebp
- xcbeautify
EXTERNAL SOURCES:
@ -186,7 +189,7 @@ SPEC CHECKSUMS:
Curve25519Kit: e63f9859ede02438ae3defc5e1a87e09d1ec7ee6
DifferenceKit: ab185c4d7f9cef8af3fcf593e5b387fb81e999ca
GRDB.swift: fe420b1af49ec519c7e96e07887ee44f5dfa2b78
libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
Nimble: 5316ef81a170ce87baf72dd961f22f89a602ff84
NVActivityIndicatorView: 1f6c5687f1171810aa27a3296814dc2d7dec3667
OpenSSL-Universal: e7311447fd2419f57420c79524b641537387eff2

View File

@ -263,26 +263,43 @@ extension EmojiGenerator {
}
}
static func writeStringConversionsFile(from emojiModel: EmojiModel) {
// Inline helpers:
var firstItem = true
func conditionalCheckForEmojiItem(_ item: EmojiModel.EmojiDefinition.Emoji) -> String {
let isFirst = (firstItem == true)
firstItem = false
let prefix = isFirst ? "" : "} else "
let suffix = "if rawValue == \"\(item.emojiChar)\" {"
return prefix + suffix
}
func conversionForEmojiItem(_ item: EmojiModel.EmojiDefinition.Emoji, definition: EmojiModel.EmojiDefinition) -> String {
let skinToneString: String
if item.skintoneSequence.isEmpty {
skinToneString = "nil"
} else {
skinToneString = "[\(item.skintoneSequence.map { ".\($0)" }.joined(separator: ", "))]"
indirect enum Structure {
enum ChunkType {
case firstScalar
case scalarSum
func chunk(_ character: Character, into size: UInt32) -> UInt32 {
guard size > 0 else { return 0 }
let scalarValues: [UInt32] = character.unicodeScalars.map { $0.value }
switch self {
case .firstScalar: return (scalarValues.first.map { $0 / size } ?? 0)
case .scalarSum: return (scalarValues.reduce(0, +) / size)
}
}
func switchString(with variableName: String = "rawValue") -> String {
switch self {
case .firstScalar: return "rawValue.unicodeScalars.map({ $0.value }).first"
case .scalarSum: return "rawValue.unicodeScalars.map({ $0.value }).reduce(0, +)"
}
}
return "self.init(baseEmoji: .\(definition.enumName), skinTones: \(skinToneString))"
}
case ifElse // XCode 15 taking over 10 min with M1 Pro (gave up)
case switchStatement // XCode 15 taking over 10 min with M1 Pro (gave up)
case directLookup // XCode 15 taking 93 sec with M1 Pro
case chunked(UInt32, Structure, ChunkType) // XCode 15 taking <10 sec with M1 Pro (chunk by 100)
}
typealias ChunkedEmojiInfo = (
variant: EmojiModel.EmojiDefinition.Emoji,
baseName: String
)
static func writeStringConversionsFile(from emojiModel: EmojiModel) {
// This combination seems to have the smallest compile time (~2.2 sec out of all of the combinations)
let desiredStructure: Structure = .chunked(100, .directLookup, .scalarSum)
// Conversion from String: Creates an initializer mapping a single character emoji string to an EmojiWithSkinTones
// e.g.
@ -291,30 +308,131 @@ extension EmojiGenerator {
writeBlock(fileName: "EmojiWithSkinTones+String.swift") { fileHandle in
fileHandle.writeLine("extension EmojiWithSkinTones {")
fileHandle.indent {
fileHandle.writeLine("init?(rawValue: String) {")
fileHandle.indent {
fileHandle.writeLine("guard rawValue.isSingleEmoji else { return nil }")
emojiModel.definitions.forEach { definition in
definition.variants.forEach { emoji in
fileHandle.writeLine(conditionalCheckForEmojiItem(emoji))
fileHandle.indent {
fileHandle.writeLine(conversionForEmojiItem(emoji, definition: definition))
switch desiredStructure {
case .chunked(let chunkSize, let childStructure, let chunkType):
let chunkedEmojiInfo = emojiModel.definitions
.reduce(into: [UInt32: [ChunkedEmojiInfo]]()) { result, next in
next.variants.forEach { emoji in
let chunk: UInt32 = chunkType.chunk(emoji.emojiChar, into: chunkSize)
result[chunk] = ((result[chunk] ?? []) + [(emoji, next.enumName)])
.sorted { lhs, rhs in lhs.variant < rhs.variant }
}
}
.sorted { lhs, rhs in lhs.key < rhs.key }
fileHandle.writeLine("init?(rawValue: String) {")
fileHandle.indent {
fileHandle.writeLine("guard rawValue.isSingleEmoji else { return nil }")
fileHandle.writeLine("switch \(chunkType.switchString()) {")
fileHandle.indent {
chunkedEmojiInfo.forEach { chunk, _ in
fileHandle.writeLine("case \(chunk): self = EmojiWithSkinTones.emojiFrom\(chunk)(rawValue)")
}
fileHandle.writeLine("default: self = EmojiWithSkinTones(unsupportedValue: rawValue)")
}
fileHandle.writeLine("}")
}
}
fileHandle.writeLine("} else {")
fileHandle.indent {
fileHandle.writeLine("self.init(unsupportedValue: rawValue)")
}
fileHandle.writeLine("}")
fileHandle.writeLine("}")
chunkedEmojiInfo.forEach { chunk, emojiInfo in
fileHandle.writeLine("")
fileHandle.writeLine("private static func emojiFrom\(chunk)(_ rawValue: String) -> EmojiWithSkinTones {")
fileHandle.indent {
switch emojiInfo.count {
case 0:
fileHandle.writeLine("return EmojiWithSkinTones(unsupportedValue: rawValue)")
default:
writeStructure(
childStructure,
for: emojiInfo,
using: fileHandle,
assignmentPrefix: "return "
)
}
}
fileHandle.writeLine("}")
}
default:
fileHandle.writeLine("init?(rawValue: String) {")
fileHandle.indent {
fileHandle.writeLine("guard rawValue.isSingleEmoji else { return nil }")
writeStructure(
desiredStructure,
for: emojiModel.definitions
.flatMap { definition in
definition.variants.map { ($0, definition.enumName) }
},
using: fileHandle
)
}
fileHandle.writeLine("}")
}
fileHandle.writeLine("}")
}
fileHandle.writeLine("}")
}
}
private static func writeStructure(
_ structure: Structure,
for emojiInfo: [ChunkedEmojiInfo],
using fileHandle: WriteHandle,
assignmentPrefix: String = "self = "
) {
func initItem(_ info: ChunkedEmojiInfo) -> String {
let skinToneString: String = {
guard !info.variant.skintoneSequence.isEmpty else { return "nil" }
return "[\(info.variant.skintoneSequence.map { ".\($0)" }.joined(separator: ", "))]"
}()
return "EmojiWithSkinTones(baseEmoji: .\(info.baseName), skinTones: \(skinToneString))"
}
switch structure {
case .ifElse:
emojiInfo.enumerated().forEach { index, info in
switch index {
case 0: fileHandle.writeLine("if rawValue == \"\(info.variant.emojiChar)\" {")
default: fileHandle.writeLine("} else if rawValue == \"\(info.variant.emojiChar)\" {")
}
fileHandle.indent {
fileHandle.writeLine("\(assignmentPrefix)\(initItem(info))")
}
}
fileHandle.writeLine("} else {")
fileHandle.indent {
fileHandle.writeLine("\(assignmentPrefix)EmojiWithSkinTones(unsupportedValue: rawValue)")
}
fileHandle.writeLine("}")
case .switchStatement:
fileHandle.writeLine("switch rawValue {")
fileHandle.indent {
emojiInfo.forEach { info in
fileHandle.writeLine("case \"\(info.variant.emojiChar)\": \(assignmentPrefix)\(initItem(info))")
}
fileHandle.writeLine("default: \(assignmentPrefix)EmojiWithSkinTones(unsupportedValue: rawValue)")
}
fileHandle.writeLine("}")
case .directLookup:
fileHandle.writeLine("let lookup: [String: EmojiWithSkinTones] = [")
fileHandle.indent {
emojiInfo.enumerated().forEach { index, info in
let isLast: Bool = (index == (emojiInfo.count - 1))
fileHandle.writeLine("\"\(info.variant.emojiChar)\": \(initItem(info))\(isLast ? "" : ",")")
}
}
fileHandle.writeLine("]")
fileHandle.writeLine("\(assignmentPrefix)(lookup[rawValue] ?? EmojiWithSkinTones(unsupportedValue: rawValue))")
case .chunked: break // Provide one of the other types
}
}
static func writeSkinToneLookupFile(from emojiModel: EmojiModel) {
writeBlock(fileName: "Emoji+SkinTones.swift") { fileHandle in
@ -514,7 +632,7 @@ extension EmojiGenerator {
fileHandle.indent {
fileHandle.writeLine("switch self {")
emojiModel.definitions.forEach {
fileHandle.writeLine("case .\($0.enumName): return \"\($0.shortNames.joined(separator:", "))\"")
fileHandle.writeLine("case .\($0.enumName): return \"\($0.shortNames.sorted().joined(separator:", "))\"")
}
fileHandle.writeLine("}")
}

View File

@ -572,7 +572,7 @@ public func serializedData() throws -> Data {
# if self.can_field_be_optional(field):
writer.add('guard proto.%s else {' % field.has_accessor_name() )
writer.push_indent()
writer.add('throw %s.invalidProtobuf(description: "\(logTag) missing required field: %s")' % ( writer.invalid_protobuf_error_name, field.name_swift, ) )
writer.add('throw %s.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: %s")' % ( writer.invalid_protobuf_error_name, field.name_swift, ) )
writer.pop_indent()
writer.add('}')

View File

@ -1924,6 +1924,7 @@
FDC438CA27BB7DB100C60D73 /* UpdateMessageRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateMessageRequest.swift; sourceTree = "<group>"; };
FDC438CC27BC641200C60D73 /* Set+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Set+Utilities.swift"; sourceTree = "<group>"; };
FDC6D75F2862B3F600B04575 /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = "<group>"; };
FDCCC6E82ABA7402002BBEF5 /* EmojiGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiGenerator.swift; sourceTree = "<group>"; };
FDCD2E022A41294E00964D6A /* LegacyGroupOnlyRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyGroupOnlyRequest.swift; sourceTree = "<group>"; };
FDCDB8DD2810F73B00352A0C /* Differentiable+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Differentiable+Utilities.swift"; sourceTree = "<group>"; };
FDCDB8DF2811007F00352A0C /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = "<group>"; };
@ -4315,6 +4316,7 @@
isa = PBXGroup;
children = (
FDE7214F287E50D50093DF33 /* ProtoWrappers.py */,
FDCCC6E82ABA7402002BBEF5 /* EmojiGenerator.swift */,
FDE72150287E50D50093DF33 /* LintLocalizableStrings.swift */,
FD5CE3442A3C5D96001A6DE3 /* DecryptExportedKey.swift */,
);

View File

@ -105,7 +105,6 @@ final class QuoteView: UIView {
availableWidth -= cancelButtonSize
}
let availableSpace = CGSize(width: availableWidth, height: .greatestFiniteMagnitude)
var body: String? = quotedText
// Main stack view

View File

@ -112,7 +112,6 @@ public final class VoiceMessageView: UIView {
}
private func setUpViewHierarchy() {
let toggleContainerSize = VoiceMessageView.toggleContainerSize
let inset = VoiceMessageView.inset
// Width & height

View File

@ -86,6 +86,7 @@ extension Emoji {
.grimacing,
.faceExhaling,
.lyingFace,
.shakingFace,
.relieved,
.pensive,
.sleepy,
@ -163,7 +164,6 @@ extension Emoji {
.seeNoEvil,
.hearNoEvil,
.speakNoEvil,
.kiss,
.loveLetter,
.cupid,
.giftHeart,
@ -178,14 +178,18 @@ extension Emoji {
.heartOnFire,
.mendingHeart,
.heart,
.pinkHeart,
.orangeHeart,
.yellowHeart,
.greenHeart,
.blueHeart,
.lightBlueHeart,
.purpleHeart,
.brownHeart,
.blackHeart,
.greyHeart,
.whiteHeart,
.kiss,
.oneHundred,
.anger,
.boom,
@ -193,7 +197,6 @@ extension Emoji {
.sweatDrops,
.dash,
.hole,
.bomb,
.speechBalloon,
.eyeInSpeechBubble,
.leftSpeechBubble,
@ -209,6 +212,8 @@ extension Emoji {
.leftwardsHand,
.palmDownHand,
.palmUpHand,
.leftwardsPushingHand,
.rightwardsPushingHand,
.okHand,
.pinchedFingers,
.pinchingHand,
@ -584,6 +589,8 @@ extension Emoji {
.tiger2,
.leopard,
.horse,
.moose,
.donkey,
.racehorse,
.unicornFace,
.zebraFace,
@ -646,6 +653,9 @@ extension Emoji {
.flamingo,
.peacock,
.parrot,
.wing,
.blackBird,
.goose,
.frog,
.crocodile,
.turtle,
@ -666,6 +676,7 @@ extension Emoji {
.octopus,
.shell,
.coral,
.jellyfish,
.snail,
.butterfly,
.bug,
@ -693,6 +704,7 @@ extension Emoji {
.sunflower,
.blossom,
.tulip,
.hyacinth,
.seedling,
.pottedPlant,
.evergreenTree,
@ -708,6 +720,7 @@ extension Emoji {
.leaves,
.emptyNest,
.nestWithEggs,
.mushroom,
]
case .food:
return [
@ -742,10 +755,11 @@ extension Emoji {
.broccoli,
.garlic,
.onion,
.mushroom,
.peanuts,
.beans,
.chestnut,
.gingerRoot,
.peaPod,
.bread,
.croissant,
.baguetteBread,
@ -903,11 +917,10 @@ extension Emoji {
.dart,
.yoYo,
.kite,
.gun,
.eightBall,
.crystalBall,
.magicWand,
.nazarAmulet,
.hamsa,
.videoGame,
.joystick,
.slotMachine,
@ -1176,6 +1189,7 @@ extension Emoji {
.shorts,
.bikini,
.womansClothes,
.foldingHandFan,
.purse,
.handbag,
.pouch,
@ -1190,6 +1204,7 @@ extension Emoji {
.sandal,
.balletShoes,
.boot,
.hairPick,
.crown,
.womansHat,
.tophat,
@ -1228,6 +1243,8 @@ extension Emoji {
.banjo,
.drumWithDrumsticks,
.longDrum,
.maracas,
.flute,
.iphone,
.calling,
.phone,
@ -1347,7 +1364,7 @@ extension Emoji {
.hammerAndWrench,
.daggerKnife,
.crossedSwords,
.gun,
.bomb,
.boomerang,
.bowAndArrow,
.shield,
@ -1408,6 +1425,8 @@ extension Emoji {
.coffin,
.headstone,
.funeralUrn,
.nazarAmulet,
.hamsa,
.moyai,
.placard,
.identificationCard,
@ -1473,6 +1492,7 @@ extension Emoji {
.peaceSymbol,
.menorahWithNineBranches,
.sixPointedStar,
.khanda,
.aries,
.taurus,
.gemini,
@ -1508,6 +1528,7 @@ extension Emoji {
.lowBrightness,
.highBrightness,
.signalStrength,
.wireless,
.vibrationMode,
.mobilePhoneOff,
.femaleSign,
@ -1962,6 +1983,7 @@ extension Emoji {
case .grimacing: return .smileysAndPeople
case .faceExhaling: return .smileysAndPeople
case .lyingFace: return .smileysAndPeople
case .shakingFace: return .smileysAndPeople
case .relieved: return .smileysAndPeople
case .pensive: return .smileysAndPeople
case .sleepy: return .smileysAndPeople
@ -2039,7 +2061,6 @@ extension Emoji {
case .seeNoEvil: return .smileysAndPeople
case .hearNoEvil: return .smileysAndPeople
case .speakNoEvil: return .smileysAndPeople
case .kiss: return .smileysAndPeople
case .loveLetter: return .smileysAndPeople
case .cupid: return .smileysAndPeople
case .giftHeart: return .smileysAndPeople
@ -2054,14 +2075,18 @@ extension Emoji {
case .heartOnFire: return .smileysAndPeople
case .mendingHeart: return .smileysAndPeople
case .heart: return .smileysAndPeople
case .pinkHeart: return .smileysAndPeople
case .orangeHeart: return .smileysAndPeople
case .yellowHeart: return .smileysAndPeople
case .greenHeart: return .smileysAndPeople
case .blueHeart: return .smileysAndPeople
case .lightBlueHeart: return .smileysAndPeople
case .purpleHeart: return .smileysAndPeople
case .brownHeart: return .smileysAndPeople
case .blackHeart: return .smileysAndPeople
case .greyHeart: return .smileysAndPeople
case .whiteHeart: return .smileysAndPeople
case .kiss: return .smileysAndPeople
case .oneHundred: return .smileysAndPeople
case .anger: return .smileysAndPeople
case .boom: return .smileysAndPeople
@ -2069,7 +2094,6 @@ extension Emoji {
case .sweatDrops: return .smileysAndPeople
case .dash: return .smileysAndPeople
case .hole: return .smileysAndPeople
case .bomb: return .smileysAndPeople
case .speechBalloon: return .smileysAndPeople
case .eyeInSpeechBubble: return .smileysAndPeople
case .leftSpeechBubble: return .smileysAndPeople
@ -2085,6 +2109,8 @@ extension Emoji {
case .leftwardsHand: return .smileysAndPeople
case .palmDownHand: return .smileysAndPeople
case .palmUpHand: return .smileysAndPeople
case .leftwardsPushingHand: return .smileysAndPeople
case .rightwardsPushingHand: return .smileysAndPeople
case .okHand: return .smileysAndPeople
case .pinchedFingers: return .smileysAndPeople
case .pinchingHand: return .smileysAndPeople
@ -2457,6 +2483,8 @@ extension Emoji {
case .tiger2: return .animals
case .leopard: return .animals
case .horse: return .animals
case .moose: return .animals
case .donkey: return .animals
case .racehorse: return .animals
case .unicornFace: return .animals
case .zebraFace: return .animals
@ -2519,6 +2547,9 @@ extension Emoji {
case .flamingo: return .animals
case .peacock: return .animals
case .parrot: return .animals
case .wing: return .animals
case .blackBird: return .animals
case .goose: return .animals
case .frog: return .animals
case .crocodile: return .animals
case .turtle: return .animals
@ -2539,6 +2570,7 @@ extension Emoji {
case .octopus: return .animals
case .shell: return .animals
case .coral: return .animals
case .jellyfish: return .animals
case .snail: return .animals
case .butterfly: return .animals
case .bug: return .animals
@ -2566,6 +2598,7 @@ extension Emoji {
case .sunflower: return .animals
case .blossom: return .animals
case .tulip: return .animals
case .hyacinth: return .animals
case .seedling: return .animals
case .pottedPlant: return .animals
case .evergreenTree: return .animals
@ -2581,6 +2614,7 @@ extension Emoji {
case .leaves: return .animals
case .emptyNest: return .animals
case .nestWithEggs: return .animals
case .mushroom: return .animals
case .grapes: return .food
case .melon: return .food
case .watermelon: return .food
@ -2612,10 +2646,11 @@ extension Emoji {
case .broccoli: return .food
case .garlic: return .food
case .onion: return .food
case .mushroom: return .food
case .peanuts: return .food
case .beans: return .food
case .chestnut: return .food
case .gingerRoot: return .food
case .peaPod: return .food
case .bread: return .food
case .croissant: return .food
case .baguetteBread: return .food
@ -2988,11 +3023,10 @@ extension Emoji {
case .dart: return .activities
case .yoYo: return .activities
case .kite: return .activities
case .gun: return .activities
case .eightBall: return .activities
case .crystalBall: return .activities
case .magicWand: return .activities
case .nazarAmulet: return .activities
case .hamsa: return .activities
case .videoGame: return .activities
case .joystick: return .activities
case .slotMachine: return .activities
@ -3037,6 +3071,7 @@ extension Emoji {
case .shorts: return .objects
case .bikini: return .objects
case .womansClothes: return .objects
case .foldingHandFan: return .objects
case .purse: return .objects
case .handbag: return .objects
case .pouch: return .objects
@ -3051,6 +3086,7 @@ extension Emoji {
case .sandal: return .objects
case .balletShoes: return .objects
case .boot: return .objects
case .hairPick: return .objects
case .crown: return .objects
case .womansHat: return .objects
case .tophat: return .objects
@ -3089,6 +3125,8 @@ extension Emoji {
case .banjo: return .objects
case .drumWithDrumsticks: return .objects
case .longDrum: return .objects
case .maracas: return .objects
case .flute: return .objects
case .iphone: return .objects
case .calling: return .objects
case .phone: return .objects
@ -3208,7 +3246,7 @@ extension Emoji {
case .hammerAndWrench: return .objects
case .daggerKnife: return .objects
case .crossedSwords: return .objects
case .gun: return .objects
case .bomb: return .objects
case .boomerang: return .objects
case .bowAndArrow: return .objects
case .shield: return .objects
@ -3269,6 +3307,8 @@ extension Emoji {
case .coffin: return .objects
case .headstone: return .objects
case .funeralUrn: return .objects
case .nazarAmulet: return .objects
case .hamsa: return .objects
case .moyai: return .objects
case .placard: return .objects
case .identificationCard: return .objects
@ -3331,6 +3371,7 @@ extension Emoji {
case .peaceSymbol: return .symbols
case .menorahWithNineBranches: return .symbols
case .sixPointedStar: return .symbols
case .khanda: return .symbols
case .aries: return .symbols
case .taurus: return .symbols
case .gemini: return .symbols
@ -3366,6 +3407,7 @@ extension Emoji {
case .lowBrightness: return .symbols
case .highBrightness: return .symbols
case .signalStrength: return .symbols
case .wireless: return .symbols
case .vibrationMode: return .symbols
case .mobilePhoneOff: return .symbols
case .femaleSign: return .symbols

File diff suppressed because it is too large Load Diff

View File

@ -106,6 +106,22 @@ extension Emoji {
[.mediumDark]: "🫴🏾",
[.dark]: "🫴🏿",
]
case .leftwardsPushingHand:
return [
[.light]: "🫷🏻",
[.mediumLight]: "🫷🏼",
[.medium]: "🫷🏽",
[.mediumDark]: "🫷🏾",
[.dark]: "🫷🏿",
]
case .rightwardsPushingHand:
return [
[.light]: "🫸🏻",
[.mediumLight]: "🫸🏼",
[.medium]: "🫸🏽",
[.mediumDark]: "🫸🏾",
[.dark]: "🫸🏿",
]
case .okHand:
return [
[.light]: "👌🏻",

View File

@ -54,6 +54,7 @@ enum Emoji: String, CaseIterable, Equatable {
case grimacing = "😬"
case faceExhaling = "😮‍💨"
case lyingFace = "🤥"
case shakingFace = "🫨"
case relieved = "😌"
case pensive = "😔"
case sleepy = "😪"
@ -131,7 +132,6 @@ enum Emoji: String, CaseIterable, Equatable {
case seeNoEvil = "🙈"
case hearNoEvil = "🙉"
case speakNoEvil = "🙊"
case kiss = "💋"
case loveLetter = "💌"
case cupid = "💘"
case giftHeart = "💝"
@ -146,14 +146,18 @@ enum Emoji: String, CaseIterable, Equatable {
case heartOnFire = "❤️‍🔥"
case mendingHeart = "❤️‍🩹"
case heart = "❤️"
case pinkHeart = "🩷"
case orangeHeart = "🧡"
case yellowHeart = "💛"
case greenHeart = "💚"
case blueHeart = "💙"
case lightBlueHeart = "🩵"
case purpleHeart = "💜"
case brownHeart = "🤎"
case blackHeart = "🖤"
case greyHeart = "🩶"
case whiteHeart = "🤍"
case kiss = "💋"
case oneHundred = "💯"
case anger = "💢"
case boom = "💥"
@ -161,7 +165,6 @@ enum Emoji: String, CaseIterable, Equatable {
case sweatDrops = "💦"
case dash = "💨"
case hole = "🕳️"
case bomb = "💣"
case speechBalloon = "💬"
case eyeInSpeechBubble = "👁️‍🗨️"
case leftSpeechBubble = "🗨️"
@ -177,6 +180,8 @@ enum Emoji: String, CaseIterable, Equatable {
case leftwardsHand = "🫲"
case palmDownHand = "🫳"
case palmUpHand = "🫴"
case leftwardsPushingHand = "🫷"
case rightwardsPushingHand = "🫸"
case okHand = "👌"
case pinchedFingers = "🤌"
case pinchingHand = "🤏"
@ -554,6 +559,8 @@ enum Emoji: String, CaseIterable, Equatable {
case tiger2 = "🐅"
case leopard = "🐆"
case horse = "🐴"
case moose = "🫎"
case donkey = "🫏"
case racehorse = "🐎"
case unicornFace = "🦄"
case zebraFace = "🦓"
@ -616,6 +623,9 @@ enum Emoji: String, CaseIterable, Equatable {
case flamingo = "🦩"
case peacock = "🦚"
case parrot = "🦜"
case wing = "🪽"
case blackBird = "🐦‍⬛"
case goose = "🪿"
case frog = "🐸"
case crocodile = "🐊"
case turtle = "🐢"
@ -636,6 +646,7 @@ enum Emoji: String, CaseIterable, Equatable {
case octopus = "🐙"
case shell = "🐚"
case coral = "🪸"
case jellyfish = "🪼"
case snail = "🐌"
case butterfly = "🦋"
case bug = "🐛"
@ -663,6 +674,7 @@ enum Emoji: String, CaseIterable, Equatable {
case sunflower = "🌻"
case blossom = "🌼"
case tulip = "🌷"
case hyacinth = "🪻"
case seedling = "🌱"
case pottedPlant = "🪴"
case evergreenTree = "🌲"
@ -678,6 +690,7 @@ enum Emoji: String, CaseIterable, Equatable {
case leaves = "🍃"
case emptyNest = "🪹"
case nestWithEggs = "🪺"
case mushroom = "🍄"
case grapes = "🍇"
case melon = "🍈"
case watermelon = "🍉"
@ -709,10 +722,11 @@ enum Emoji: String, CaseIterable, Equatable {
case broccoli = "🥦"
case garlic = "🧄"
case onion = "🧅"
case mushroom = "🍄"
case peanuts = "🥜"
case beans = "🫘"
case chestnut = "🌰"
case gingerRoot = "🫚"
case peaPod = "🫛"
case bread = "🍞"
case croissant = "🥐"
case baguetteBread = "🥖"
@ -1085,11 +1099,10 @@ enum Emoji: String, CaseIterable, Equatable {
case dart = "🎯"
case yoYo = "🪀"
case kite = "🪁"
case gun = "🔫"
case eightBall = "🎱"
case crystalBall = "🔮"
case magicWand = "🪄"
case nazarAmulet = "🧿"
case hamsa = "🪬"
case videoGame = "🎮"
case joystick = "🕹️"
case slotMachine = "🎰"
@ -1134,6 +1147,7 @@ enum Emoji: String, CaseIterable, Equatable {
case shorts = "🩳"
case bikini = "👙"
case womansClothes = "👚"
case foldingHandFan = "🪭"
case purse = "👛"
case handbag = "👜"
case pouch = "👝"
@ -1148,6 +1162,7 @@ enum Emoji: String, CaseIterable, Equatable {
case sandal = "👡"
case balletShoes = "🩰"
case boot = "👢"
case hairPick = "🪮"
case crown = "👑"
case womansHat = "👒"
case tophat = "🎩"
@ -1186,6 +1201,8 @@ enum Emoji: String, CaseIterable, Equatable {
case banjo = "🪕"
case drumWithDrumsticks = "🥁"
case longDrum = "🪘"
case maracas = "🪇"
case flute = "🪈"
case iphone = "📱"
case calling = "📲"
case phone = "☎️"
@ -1305,7 +1322,7 @@ enum Emoji: String, CaseIterable, Equatable {
case hammerAndWrench = "🛠️"
case daggerKnife = "🗡️"
case crossedSwords = "⚔️"
case gun = "🔫"
case bomb = "💣"
case boomerang = "🪃"
case bowAndArrow = "🏹"
case shield = "🛡️"
@ -1366,6 +1383,8 @@ enum Emoji: String, CaseIterable, Equatable {
case coffin = "⚰️"
case headstone = "🪦"
case funeralUrn = "⚱️"
case nazarAmulet = "🧿"
case hamsa = "🪬"
case moyai = "🗿"
case placard = "🪧"
case identificationCard = "🪪"
@ -1428,6 +1447,7 @@ enum Emoji: String, CaseIterable, Equatable {
case peaceSymbol = "☮️"
case menorahWithNineBranches = "🕎"
case sixPointedStar = "🔯"
case khanda = "🪯"
case aries = ""
case taurus = ""
case gemini = ""
@ -1463,6 +1483,7 @@ enum Emoji: String, CaseIterable, Equatable {
case lowBrightness = "🔅"
case highBrightness = "🔆"
case signalStrength = "📶"
case wireless = "🛜"
case vibrationMode = "📳"
case mobilePhoneOff = "📴"
case femaleSign = "♀️"

File diff suppressed because it is too large Load Diff

View File

@ -275,14 +275,11 @@ class PhotoCaptureViewController: OWSViewController {
let transformFromOrientation: CGAffineTransform
switch captureOrientation {
case .portrait:
transformFromOrientation = .identity
case .portraitUpsideDown:
transformFromOrientation = CGAffineTransform(rotationAngle: .pi)
case .landscapeLeft:
transformFromOrientation = CGAffineTransform(rotationAngle: .halfPi)
case .landscapeRight:
transformFromOrientation = CGAffineTransform(rotationAngle: -1 * .halfPi)
case .portrait: transformFromOrientation = .identity
case .portraitUpsideDown: transformFromOrientation = CGAffineTransform(rotationAngle: .pi)
case .landscapeLeft: transformFromOrientation = CGAffineTransform(rotationAngle: .halfPi)
case .landscapeRight: transformFromOrientation = CGAffineTransform(rotationAngle: -1 * .halfPi)
@unknown default: transformFromOrientation = .identity
}
// Don't "unrotate" the switch camera icon if the front facing camera had been selected.

View File

@ -59,8 +59,7 @@ public enum PushRegistrationError: Error {
.tryFlatMap { _ -> AnyPublisher<(pushToken: String, voipToken: String), Error> in
#if targetEnvironment(simulator)
throw PushRegistrationError.pushNotSupported(description: "Push not supported on simulators")
#endif
#else
return self.registerForVanillaPushToken()
.flatMap { vanillaPushToken -> AnyPublisher<(pushToken: String, voipToken: String), Error> in
self.registerForVoipPushToken()
@ -68,6 +67,7 @@ public enum PushRegistrationError: Error {
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
#endif
}
.eraseToAnyPublisher()
}

View File

@ -160,9 +160,7 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
return Deferred {
Future<Void, Error> { [weak self] resolver in
self?.peerConnection?.offer(for: mediaConstraints) { sdp, error in
if let error = error {
return
}
guard error == nil else { return }
guard let sdp: RTCSessionDescription = self?.correctSessionDescription(sdp: sdp) else {
preconditionFailure()

View File

@ -61,7 +61,7 @@ public struct SessionThread: Codable, Identifiable, Equatable, FetchableRecord,
public let shouldBeVisible: Bool
/// A flag indicating whether the thread is pinned
@available(*, unavailable, message: "use 'pinnedPriority' instead")
// @available(*, unavailable, message: "use 'pinnedPriority' instead")
public let isPinned: Bool = false
/// The value the user started entering into the input field before they left the conversation screen

View File

@ -165,12 +165,12 @@ public enum SNProtoError: Error {
fileprivate class func parseProto(_ proto: SessionProtos_Envelope) throws -> SNProtoEnvelope {
guard proto.hasType else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: type")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: type")
}
let type = SNProtoEnvelopeTypeWrap(proto.type)
guard proto.hasTimestamp else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: timestamp")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: timestamp")
}
let timestamp = proto.timestamp
@ -298,12 +298,12 @@ extension SNProtoEnvelope.SNProtoEnvelopeBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_TypingMessage) throws -> SNProtoTypingMessage {
guard proto.hasTimestamp else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: timestamp")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: timestamp")
}
let timestamp = proto.timestamp
guard proto.hasAction else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: action")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: action")
}
let action = SNProtoTypingMessageActionWrap(proto.action)
@ -410,12 +410,12 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_UnsendRequest) throws -> SNProtoUnsendRequest {
guard proto.hasTimestamp else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: timestamp")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: timestamp")
}
let timestamp = proto.timestamp
guard proto.hasAuthor else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: author")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: author")
}
let author = proto.author
@ -541,7 +541,7 @@ extension SNProtoUnsendRequest.SNProtoUnsendRequestBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_MessageRequestResponse) throws -> SNProtoMessageRequestResponse {
guard proto.hasIsApproved else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: isApproved")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: isApproved")
}
let isApproved = proto.isApproved
@ -961,12 +961,12 @@ extension SNProtoContent.SNProtoContentBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_CallMessage) throws -> SNProtoCallMessage {
guard proto.hasType else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: type")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: type")
}
let type = SNProtoCallMessageTypeWrap(proto.type)
guard proto.hasUuid else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: uuid")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: uuid")
}
let uuid = proto.uuid
@ -1073,12 +1073,12 @@ extension SNProtoCallMessage.SNProtoCallMessageBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_KeyPair) throws -> SNProtoKeyPair {
guard proto.hasPublicKey else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: publicKey")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: publicKey")
}
let publicKey = proto.publicKey
guard proto.hasPrivateKey else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: privateKey")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: privateKey")
}
let privateKey = proto.privateKey
@ -1211,7 +1211,7 @@ extension SNProtoKeyPair.SNProtoKeyPairBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_DataExtractionNotification) throws -> SNProtoDataExtractionNotification {
guard proto.hasType else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: type")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: type")
}
let type = SNProtoDataExtractionNotificationTypeWrap(proto.type)
@ -1620,12 +1620,12 @@ extension SNProtoDataMessageQuoteQuotedAttachment.SNProtoDataMessageQuoteQuotedA
fileprivate class func parseProto(_ proto: SessionProtos_DataMessage.Quote) throws -> SNProtoDataMessageQuote {
guard proto.hasID else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: id")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: id")
}
let id = proto.id
guard proto.hasAuthor else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: author")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: author")
}
let author = proto.author
@ -1755,7 +1755,7 @@ extension SNProtoDataMessageQuote.SNProtoDataMessageQuoteBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_DataMessage.Preview) throws -> SNProtoDataMessagePreview {
guard proto.hasURL else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: url")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: url")
}
let url = proto.url
@ -1914,17 +1914,17 @@ extension SNProtoDataMessagePreview.SNProtoDataMessagePreviewBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_DataMessage.Reaction) throws -> SNProtoDataMessageReaction {
guard proto.hasID else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: id")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: id")
}
let id = proto.id
guard proto.hasAuthor else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: author")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: author")
}
let author = proto.author
guard proto.hasAction else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: action")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: action")
}
let action = SNProtoDataMessageReactionActionWrap(proto.action)
@ -2032,12 +2032,12 @@ extension SNProtoDataMessageReaction.SNProtoDataMessageReactionBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_DataMessage.OpenGroupInvitation) throws -> SNProtoDataMessageOpenGroupInvitation {
guard proto.hasURL else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: url")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: url")
}
let url = proto.url
guard proto.hasName else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: name")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: name")
}
let name = proto.name
@ -2144,12 +2144,12 @@ extension SNProtoDataMessageOpenGroupInvitation.SNProtoDataMessageOpenGroupInvit
fileprivate class func parseProto(_ proto: SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPairWrapper) throws -> SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper {
guard proto.hasPublicKey else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: publicKey")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: publicKey")
}
let publicKey = proto.publicKey
guard proto.hasEncryptedKeyPair else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: encryptedKeyPair")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: encryptedKeyPair")
}
let encryptedKeyPair = proto.encryptedKeyPair
@ -2387,7 +2387,7 @@ extension SNProtoDataMessageClosedGroupControlMessageKeyPairWrapper.SNProtoDataM
fileprivate class func parseProto(_ proto: SessionProtos_DataMessage.ClosedGroupControlMessage) throws -> SNProtoDataMessageClosedGroupControlMessage {
guard proto.hasType else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: type")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: type")
}
let type = SNProtoDataMessageClosedGroupControlMessageTypeWrap(proto.type)
@ -3076,12 +3076,12 @@ extension SNProtoConfigurationMessageClosedGroup.SNProtoConfigurationMessageClos
fileprivate class func parseProto(_ proto: SessionProtos_ConfigurationMessage.Contact) throws -> SNProtoConfigurationMessageContact {
guard proto.hasPublicKey else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: publicKey")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: publicKey")
}
let publicKey = proto.publicKey
guard proto.hasName else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: name")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: name")
}
let name = proto.name
@ -3396,7 +3396,7 @@ extension SNProtoConfigurationMessage.SNProtoConfigurationMessageBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_ReceiptMessage) throws -> SNProtoReceiptMessage {
guard proto.hasType else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: type")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: type")
}
let type = SNProtoReceiptMessageTypeWrap(proto.type)
@ -3686,7 +3686,7 @@ extension SNProtoReceiptMessage.SNProtoReceiptMessageBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_AttachmentPointer) throws -> SNProtoAttachmentPointer {
guard proto.hasID else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: id")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: id")
}
let id = proto.id
@ -3828,17 +3828,17 @@ extension SNProtoAttachmentPointer.SNProtoAttachmentPointerBuilder {
fileprivate class func parseProto(_ proto: SessionProtos_SharedConfigMessage) throws -> SNProtoSharedConfigMessage {
guard proto.hasKind else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: kind")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: kind")
}
let kind = SNProtoSharedConfigMessageKindWrap(proto.kind)
guard proto.hasSeqno else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: seqno")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: seqno")
}
let seqno = proto.seqno
guard proto.hasData else {
throw SNProtoError.invalidProtobuf(description: "\(logTag) missing required field: data")
throw SNProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: data")
}
let data = proto.data

View File

@ -123,17 +123,17 @@ public enum WebSocketProtoError: Error {
fileprivate class func parseProto(_ proto: WebSocketProtos_WebSocketRequestMessage) throws -> WebSocketProtoWebSocketRequestMessage {
guard proto.hasVerb else {
throw WebSocketProtoError.invalidProtobuf(description: "\(logTag) missing required field: verb")
throw WebSocketProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: verb")
}
let verb = proto.verb
guard proto.hasPath else {
throw WebSocketProtoError.invalidProtobuf(description: "\(logTag) missing required field: path")
throw WebSocketProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: path")
}
let path = proto.path
guard proto.hasRequestID else {
throw WebSocketProtoError.invalidProtobuf(description: "\(logTag) missing required field: requestID")
throw WebSocketProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: requestID")
}
let requestID = proto.requestID
@ -290,12 +290,12 @@ extension WebSocketProtoWebSocketRequestMessage.WebSocketProtoWebSocketRequestMe
fileprivate class func parseProto(_ proto: WebSocketProtos_WebSocketResponseMessage) throws -> WebSocketProtoWebSocketResponseMessage {
guard proto.hasRequestID else {
throw WebSocketProtoError.invalidProtobuf(description: "\(logTag) missing required field: requestID")
throw WebSocketProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: requestID")
}
let requestID = proto.requestID
guard proto.hasStatus else {
throw WebSocketProtoError.invalidProtobuf(description: "\(logTag) missing required field: status")
throw WebSocketProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: status")
}
let status = proto.status
@ -439,7 +439,7 @@ extension WebSocketProtoWebSocketResponseMessage.WebSocketProtoWebSocketResponse
fileprivate class func parseProto(_ proto: WebSocketProtos_WebSocketMessage) throws -> WebSocketProtoWebSocketMessage {
guard proto.hasType else {
throw WebSocketProtoError.invalidProtobuf(description: "\(logTag) missing required field: type")
throw WebSocketProtoError.invalidProtobuf(description: "\(String(describing: logTag)) missing required field: type")
}
let type = WebSocketProtoWebSocketMessageTypeWrap(proto.type)

View File

@ -88,11 +88,9 @@ extension MessageReceiver {
// Need to check if the blinded id matches for open groups
switch senderSessionId.prefix {
case .blinded15, .blinded25:
let sodium: Sodium = Sodium()
guard
let userEdKeyPair: KeyPair = Identity.fetchUserEd25519KeyPair(db),
let blindedKeyPair: KeyPair = try? dependencies.crypto.generate(
let blindedKeyPair: KeyPair = dependencies.crypto.generate(
.blindedKeyPair(
serverPublicKey: openGroup.publicKey,
edKeyPair: userEdKeyPair,

View File

@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionUtilitiesKit
public extension Notification.Name {
static let missedCall = Notification.Name("missedCall")

View File

@ -4,6 +4,11 @@ import Foundation
import Combine
public enum HTTP {
private struct Certificates {
let isValid: Bool
let certificates: [SecCertificate]
}
private static let seedNodeURLSession = URLSession(configuration: .ephemeral, delegate: seedNodeURLSessionDelegate, delegateQueue: nil)
private static let seedNodeURLSessionDelegate = SeedNodeURLSessionDelegateImplementation()
private static let snodeURLSession = URLSession(configuration: .ephemeral, delegate: snodeURLSessionDelegate, delegateQueue: nil)
@ -14,22 +19,21 @@ public enum HTTP {
/// **Note:** These certificates will need to be regenerated and replaced at the start of April 2025, iOS has a restriction after iOS 13
/// where certificates can have a maximum lifetime of 825 days (https://support.apple.com/en-au/HT210176) as a result we
/// can't use the 10 year certificates that the other platforms use
private static let storageSeed1Cert: SecCertificate = {
let path = Bundle.main.path(forResource: "seed1-2023-2y", ofType: "der")!
let data = try! Data(contentsOf: URL(fileURLWithPath: path))
return SecCertificateCreateWithData(nil, data as CFData)!
}()
private static let storageSeed2Cert: SecCertificate = {
let path = Bundle.main.path(forResource: "seed2-2023-2y", ofType: "der")!
let data = try! Data(contentsOf: URL(fileURLWithPath: path))
return SecCertificateCreateWithData(nil, data as CFData)!
}()
private static let storageSeed3Cert: SecCertificate = {
let path = Bundle.main.path(forResource: "seed3-2023-2y", ofType: "der")!
let data = try! Data(contentsOf: URL(fileURLWithPath: path))
return SecCertificateCreateWithData(nil, data as CFData)!
private static let storageSeedCertificates: Atomic<Certificates> = {
let certFileNames: [String] = [
"seed1-2023-2y",
"seed2-2023-2y",
"seed3-2023-2y"
]
let paths: [String] = certFileNames.compactMap { Bundle.main.path(forResource: $0, ofType: "der") }
let certData: [Data] = paths.compactMap { try? Data(contentsOf: URL(fileURLWithPath: $0)) }
let certificates: [SecCertificate] = certData.compactMap { SecCertificateCreateWithData(nil, $0 as CFData) }
guard certificates.count == certFileNames.count else {
return Atomic(Certificates(isValid: false, certificates: []))
}
return Atomic(Certificates(isValid: true, certificates: certificates))
}()
// MARK: - Settings
@ -41,12 +45,15 @@ public enum HTTP {
private final class SeedNodeURLSessionDelegateImplementation : NSObject, URLSessionDelegate {
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard HTTP.storageSeedCertificates.wrappedValue.isValid else {
SNLog("Failed to set load seed node certificates.")
return completionHandler(.cancelAuthenticationChallenge, nil)
}
guard let trust = challenge.protectionSpace.serverTrust else {
return completionHandler(.cancelAuthenticationChallenge, nil)
}
// Mark the seed node certificates as trusted
let certificates = [ storageSeed1Cert, storageSeed2Cert, storageSeed3Cert ]
guard SecTrustSetAnchorCertificates(trust, certificates as CFArray) == errSecSuccess else {
guard SecTrustSetAnchorCertificates(trust, HTTP.storageSeedCertificates.wrappedValue.certificates as CFArray) == errSecSuccess else {
SNLog("Failed to set seed node certificates.")
return completionHandler(.cancelAuthenticationChallenge, nil)
}