diff --git a/Telegram/NotificationService/Sources/NotificationService.swift b/Telegram/NotificationService/Sources/NotificationService.swift index afb30be01f..83b91db681 100644 --- a/Telegram/NotificationService/Sources/NotificationService.swift +++ b/Telegram/NotificationService/Sources/NotificationService.swift @@ -745,7 +745,7 @@ private final class NotificationServiceHandler { Logger.shared.logToConsole = loggingSettings.logToConsole Logger.shared.redactSensitiveData = loggingSettings.redactSensitiveData - let networkArguments = NetworkInitializationArguments(apiId: apiId, apiHash: apiHash, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(buildConfig.bundleData(withAppToken: nil, tokenType: nil, tokenEnvironment: nil, signatureDict: nil)), externalRequestVerificationStream: .never(), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: !buildConfig.isAppStoreBuild, isICloudEnabled: false) + let networkArguments = NetworkInitializationArguments(apiId: apiId, apiHash: apiHash, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(buildConfig.bundleData(withAppToken: nil, tokenType: nil, tokenEnvironment: nil, signatureDict: nil)), externalRequestVerificationStream: .never(), externalRecaptchaRequestVerification: { _, _ in return .never() }, autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: !buildConfig.isAppStoreBuild, isICloudEnabled: false) let isLockedMessage: String? if let data = try? Data(contentsOf: URL(fileURLWithPath: appLockStatePath(rootPath: rootPath))), let state = try? JSONDecoder().decode(LockState.self, from: data), isAppLocked(state: state) { diff --git a/Telegram/SiriIntents/IntentHandler.swift b/Telegram/SiriIntents/IntentHandler.swift index 2d12681998..b1bee82fcc 100644 --- a/Telegram/SiriIntents/IntentHandler.swift +++ b/Telegram/SiriIntents/IntentHandler.swift @@ -174,7 +174,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo if let accountCache = accountCache { account = .single(accountCache) } else { - account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, apiHash: apiHash, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(buildConfig.bundleData(withAppToken: nil, tokenType: nil, tokenEnvironment: nil, signatureDict: nil)), externalRequestVerificationStream: .never(), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: !buildConfig.isAppStoreBuild, isICloudEnabled: false), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: accountAuxiliaryMethods, encryptionParameters: encryptionParameters) + account = currentAccount(allocateIfNotExists: false, networkArguments: NetworkInitializationArguments(apiId: apiId, apiHash: apiHash, languagesCategory: languagesCategory, appVersion: appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(buildConfig.bundleData(withAppToken: nil, tokenType: nil, tokenEnvironment: nil, signatureDict: nil)), externalRequestVerificationStream: .never(), externalRecaptchaRequestVerification: { _, _ in return .never() }, autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: !buildConfig.isAppStoreBuild, isICloudEnabled: false), supplementary: true, manager: accountManager, rootPath: rootPath, auxiliaryMethods: accountAuxiliaryMethods, encryptionParameters: encryptionParameters) |> mapToSignal { account -> Signal in if let account = account { switch account { diff --git a/build-system/bazel-rules/rules_apple b/build-system/bazel-rules/rules_apple index 1fbec0268c..62ee8d74df 160000 --- a/build-system/bazel-rules/rules_apple +++ b/build-system/bazel-rules/rules_apple @@ -1 +1 @@ -Subproject commit 1fbec0268ca5fe31102611ebf543e31a2bad32d1 +Subproject commit 62ee8d74df12ffa51ae5265771e45bb42fa951e5 diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h index c9b041c472..f377d9024c 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTContext.h @@ -100,7 +100,9 @@ - (void)setDiscoverBackupAddressListSignal:(MTSignal * _Nonnull)signal; - (void)setExternalRequestVerification:(MTSignal * _Nonnull (^ _Nonnull)(NSString * _Nonnull))externalRequestVerification; +- (void)setExternalRecaptchaRequestVerification:(MTSignal * _Nonnull (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))externalRecaptchaRequestVerification; - (MTSignal * _Nullable)performExternalRequestVerificationWithNonce:(NSString * _Nonnull)nonce; +- (MTSignal * _Nullable)performExternalRecaptchaRequestVerificationWithMethod:(NSString * _Nonnull)method siteKey:(NSString * _Nonnull)siteKey; - (NSTimeInterval)globalTime; - (NSTimeInterval)globalTimeDifference; diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTRequestErrorContext.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTRequestErrorContext.h index 5f2db89e02..933828ad89 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTRequestErrorContext.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTRequestErrorContext.h @@ -13,6 +13,17 @@ @end +@interface MTRequestPendingRecaptchaVerificationData : NSObject + +@property (nonatomic, strong, readonly) NSString *siteKey; +@property (nonatomic, strong) NSString *token; +@property (nonatomic) bool isResolved; +@property (nonatomic, strong) id disposable; + +- (instancetype)initWithSiteKey:(NSString *)siteKey; + +@end + @interface MTRequestErrorContext : NSObject @property (nonatomic) CFAbsoluteTime minimalExecuteTime; @@ -25,5 +36,6 @@ @property (nonatomic, strong) id waitingForRequestToComplete; @property (nonatomic, strong) MTRequestPendingVerificationData *pendingVerificationData; +@property (nonatomic, strong) MTRequestPendingRecaptchaVerificationData *pendingRecaptchaVerificationData; @end diff --git a/submodules/MtProtoKit/Sources/MTContext.m b/submodules/MtProtoKit/Sources/MTContext.m index a86308e06a..c616bb3773 100644 --- a/submodules/MtProtoKit/Sources/MTContext.m +++ b/submodules/MtProtoKit/Sources/MTContext.m @@ -182,6 +182,7 @@ static MTDatacenterAuthInfoMapKeyStruct parseAuthInfoMapKeyInteger(NSNumber *key MTSignal *_discoverBackupAddressListSignal; MTSignal * _Nonnull (^ _Nullable _externalRequestVerification)(NSString * _Nonnull); + MTSignal * _Nonnull (^ _Nullable _externalRecaptchaRequestVerification)(NSString * _Nonnull, NSString * _Nonnull); NSMutableDictionary *_discoverDatacenterAddressActions; NSMutableDictionary *_datacenterAuthActions; @@ -533,6 +534,12 @@ static void copyKeychainDictionaryKey(NSString * _Nonnull group, NSString * _Non } synchronous:true]; } +- (void)setExternalRecaptchaRequestVerification:(MTSignal * _Nonnull (^ _Nonnull)(NSString * _Nonnull, NSString * _Nonnull))externalRecaptchaRequestVerification { + [[MTContext contextQueue] dispatchOnQueue:^ { + _externalRecaptchaRequestVerification = externalRecaptchaRequestVerification; + } synchronous:true]; +} + - (MTSignal * _Nullable)performExternalRequestVerificationWithNonce:(NSString * _Nonnull)nonce { __block MTSignal * _Nonnull (^ _Nullable externalRequestVerification)(NSString * _Nonnull); [[MTContext contextQueue] dispatchOnQueue:^ { @@ -546,6 +553,19 @@ static void copyKeychainDictionaryKey(NSString * _Nonnull group, NSString * _Non } } +- (MTSignal * _Nullable)performExternalRecaptchaRequestVerificationWithMethod:(NSString * _Nonnull)method siteKey:(NSString * _Nonnull)siteKey { + __block MTSignal * _Nonnull (^ _Nullable externalRecaptchaRequestVerification)(NSString * _Nonnull, NSString * _Nonnull); + [[MTContext contextQueue] dispatchOnQueue:^ { + externalRecaptchaRequestVerification = _externalRecaptchaRequestVerification; + } synchronous:true]; + + if (externalRecaptchaRequestVerification != nil) { + return externalRecaptchaRequestVerification(method, siteKey); + } else { + return [MTSignal single:nil]; + } +} + - (NSTimeInterval)globalTime { return [[NSDate date] timeIntervalSince1970] + [self globalTimeDifference]; diff --git a/submodules/MtProtoKit/Sources/MTRequestErrorContext.m b/submodules/MtProtoKit/Sources/MTRequestErrorContext.m index 85db0d3a36..590f0360fb 100644 --- a/submodules/MtProtoKit/Sources/MTRequestErrorContext.m +++ b/submodules/MtProtoKit/Sources/MTRequestErrorContext.m @@ -12,6 +12,18 @@ @end +@implementation MTRequestPendingRecaptchaVerificationData + +- (instancetype)initWithSiteKey:(NSString *)siteKey { + self = [super init]; + if (self != nil) { + _siteKey = siteKey; + } + return self; +} + +@end + @implementation MTRequestErrorContext @end diff --git a/submodules/MtProtoKit/Sources/MTRequestMessageService.m b/submodules/MtProtoKit/Sources/MTRequestMessageService.m index 7bfdd2f6b2..27100eeecd 100644 --- a/submodules/MtProtoKit/Sources/MTRequestMessageService.m +++ b/submodules/MtProtoKit/Sources/MTRequestMessageService.m @@ -45,6 +45,24 @@ @end +@interface MTRequestRecaptchaVerificationData : NSObject + +@property (nonatomic, strong, readonly) NSString *token; + +@end + +@implementation MTRequestRecaptchaVerificationData + +- (instancetype)initWithToken:(NSString *)token { + self = [super init]; + if (self != nil) { + _token = token; + } + return self; +} + +@end + @interface MTRequestMessageService () { MTContext *_context; @@ -402,7 +420,7 @@ } } -- (NSData *)decorateRequestData:(MTRequest *)request initializeApi:(bool)initializeApi requestVerificationData:(MTRequestVerificationData *)requestVerificationData unresolvedDependencyOnRequestInternalId:(__autoreleasing id *)unresolvedDependencyOnRequestInternalId decoratedDebugDescription:(__autoreleasing NSString **)decoratedDebugDescription +- (NSData *)decorateRequestData:(MTRequest *)request initializeApi:(bool)initializeApi requestVerificationData:(MTRequestVerificationData *)requestVerificationData recaptchaVerificationData:(MTRequestRecaptchaVerificationData *)recaptchaVerificationData unresolvedDependencyOnRequestInternalId:(__autoreleasing id *)unresolvedDependencyOnRequestInternalId decoratedDebugDescription:(__autoreleasing NSString **)decoratedDebugDescription { NSData *currentData = request.payload; @@ -514,6 +532,18 @@ debugDescription = [debugDescription stringByAppendingFormat:@", apnsSecret(%@, %@)", requestVerificationData.nonce, requestVerificationData.secret]; } + if (recaptchaVerificationData != nil) { + MTBuffer *buffer = [[MTBuffer alloc] init]; + + [buffer appendInt32:(int32_t)0xadbb0f94]; + [buffer appendTLString:recaptchaVerificationData.token]; + + [buffer appendBytes:currentData.bytes length:currentData.length]; + currentData = buffer.data; + + debugDescription = [debugDescription stringByAppendingFormat:@", recaptcha(%@)", recaptchaVerificationData.token]; + } + if (decoratedDebugDescription != nil) { *decoratedDebugDescription = debugDescription; } @@ -548,6 +578,11 @@ continue; } } + if (request.errorContext.pendingRecaptchaVerificationData != nil) { + if (!request.errorContext.pendingRecaptchaVerificationData.isResolved) { + continue; + } + } bool foundDependency = false; for (MTRequest *anotherRequest in _requests) { @@ -588,7 +623,16 @@ } } - NSData *decoratedRequestData = [self decorateRequestData:request initializeApi:requestsWillInitializeApi requestVerificationData:requestVerificationData unresolvedDependencyOnRequestInternalId:&autoreleasingUnresolvedDependencyOnRequestInternalId decoratedDebugDescription:&decoratedDebugDescription]; + MTRequestRecaptchaVerificationData *recaptchaVerificationData = nil; + if (request.errorContext != nil) { + if (request.errorContext.pendingRecaptchaVerificationData != nil) { + if (request.errorContext.pendingRecaptchaVerificationData.isResolved) { + recaptchaVerificationData = [[MTRequestRecaptchaVerificationData alloc] initWithToken:request.errorContext.pendingRecaptchaVerificationData.token]; + } + } + } + + NSData *decoratedRequestData = [self decorateRequestData:request initializeApi:requestsWillInitializeApi requestVerificationData:requestVerificationData recaptchaVerificationData:recaptchaVerificationData unresolvedDependencyOnRequestInternalId:&autoreleasingUnresolvedDependencyOnRequestInternalId decoratedDebugDescription:&decoratedDebugDescription]; MTOutgoingMessage *outgoingMessage = [[MTOutgoingMessage alloc] initWithData:decoratedRequestData metadata:request.metadata additionalDebugDescription:decoratedDebugDescription shortMetadata:request.shortMetadata messageId:messageId messageSeqNo:messageSeqNo]; outgoingMessage.needsQuickAck = request.acknowledgementReceived != nil; @@ -950,6 +994,45 @@ }]; restartRequest = true; + } else if (rpcError.errorCode == 403 && [rpcError.errorDescription rangeOfString:@"RECAPTCHA_CHECK_"].location != NSNotFound) { + NSString *checkData = [rpcError.errorDescription substringFromIndex:[@"RECAPTCHA_CHECK_" length]]; + + NSRange separatorRange = [checkData rangeOfString:@"__"]; + NSString *method = nil; + NSString *siteKey = nil; + if (separatorRange.location != NSNotFound) { + method = [checkData substringToIndex:separatorRange.location]; + siteKey = [checkData substringFromIndex:separatorRange.location + separatorRange.length]; + } + + if (method != nil && siteKey != nil) { + if (request.errorContext == nil) { + request.errorContext = [[MTRequestErrorContext alloc] init]; + } + + request.errorContext.pendingRecaptchaVerificationData = [[MTRequestPendingRecaptchaVerificationData alloc] initWithSiteKey:siteKey]; + + __weak MTRequestMessageService *weakSelf = self; + MTQueue *queue = _queue; + id requestId = request.internalId; + request.errorContext.pendingRecaptchaVerificationData.disposable = [[_context performExternalRecaptchaRequestVerificationWithMethod:method siteKey:siteKey] startWithNext:^(id result) { + [queue dispatchOnQueue:^{ + __strong MTRequestMessageService *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + for (MTRequest *request in strongSelf->_requests) { + if (request.internalId == requestId) { + request.errorContext.pendingRecaptchaVerificationData.token = result; + request.errorContext.pendingRecaptchaVerificationData.isResolved = true; + } + } + [strongSelf->_mtProto requestTransportTransaction]; + }]; + }]; + + restartRequest = true; + } } else if (rpcError.errorCode == 406) { if (_didReceiveSoftAuthResetError) { _didReceiveSoftAuthResetError(); diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 856a5e7ad6..0ac4db3efb 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -715,6 +715,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1282352120] = { return Api.PageRelatedArticle.parse_pageRelatedArticle($0) } dict[878078826] = { return Api.PageTableCell.parse_pageTableCell($0) } dict[-524237339] = { return Api.PageTableRow.parse_pageTableRow($0) } + dict[520887001] = { return Api.PaidReactionPrivacy.parse_paidReactionPrivacyAnonymous($0) } + dict[543872158] = { return Api.PaidReactionPrivacy.parse_paidReactionPrivacyDefault($0) } + dict[-596837136] = { return Api.PaidReactionPrivacy.parse_paidReactionPrivacyPeer($0) } dict[982592842] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow($0) } dict[-732254058] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoUnknown($0) } dict[-368917890] = { return Api.PaymentCharge.parse_paymentCharge($0) } @@ -1068,7 +1071,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1753886890] = { return Api.Update.parse_updateNewStickerSet($0) } dict[405070859] = { return Api.Update.parse_updateNewStoryReaction($0) } dict[-1094555409] = { return Api.Update.parse_updateNotifySettings($0) } - dict[1372224236] = { return Api.Update.parse_updatePaidReactionPrivacy($0) } + dict[-1955438642] = { return Api.Update.parse_updatePaidReactionPrivacy($0) } dict[-337610926] = { return Api.Update.parse_updatePeerBlocked($0) } dict[-1147422299] = { return Api.Update.parse_updatePeerHistoryTTL($0) } dict[-1263546448] = { return Api.Update.parse_updatePeerLocated($0) } @@ -1940,6 +1943,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.PageTableRow: _1.serialize(buffer, boxed) + case let _1 as Api.PaidReactionPrivacy: + _1.serialize(buffer, boxed) case let _1 as Api.PasswordKdfAlgo: _1.serialize(buffer, boxed) case let _1 as Api.PaymentCharge: diff --git a/submodules/TelegramApi/Sources/Api19.swift b/submodules/TelegramApi/Sources/Api19.swift index 415ec1d40d..cf343c765b 100644 --- a/submodules/TelegramApi/Sources/Api19.swift +++ b/submodules/TelegramApi/Sources/Api19.swift @@ -334,6 +334,68 @@ public extension Api { } } +public extension Api { + indirect enum PaidReactionPrivacy: TypeConstructorDescription { + case paidReactionPrivacyAnonymous + case paidReactionPrivacyDefault + case paidReactionPrivacyPeer(peer: Api.InputPeer) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .paidReactionPrivacyAnonymous: + if boxed { + buffer.appendInt32(520887001) + } + + break + case .paidReactionPrivacyDefault: + if boxed { + buffer.appendInt32(543872158) + } + + break + case .paidReactionPrivacyPeer(let peer): + if boxed { + buffer.appendInt32(-596837136) + } + peer.serialize(buffer, true) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .paidReactionPrivacyAnonymous: + return ("paidReactionPrivacyAnonymous", []) + case .paidReactionPrivacyDefault: + return ("paidReactionPrivacyDefault", []) + case .paidReactionPrivacyPeer(let peer): + return ("paidReactionPrivacyPeer", [("peer", peer as Any)]) + } + } + + public static func parse_paidReactionPrivacyAnonymous(_ reader: BufferReader) -> PaidReactionPrivacy? { + return Api.PaidReactionPrivacy.paidReactionPrivacyAnonymous + } + public static func parse_paidReactionPrivacyDefault(_ reader: BufferReader) -> PaidReactionPrivacy? { + return Api.PaidReactionPrivacy.paidReactionPrivacyDefault + } + public static func parse_paidReactionPrivacyPeer(_ reader: BufferReader) -> PaidReactionPrivacy? { + var _1: Api.InputPeer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputPeer + } + let _c1 = _1 != nil + if _c1 { + return Api.PaidReactionPrivacy.paidReactionPrivacyPeer(peer: _1!) + } + else { + return nil + } + } + + } +} public extension Api { enum PasswordKdfAlgo: TypeConstructorDescription { case passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(salt1: Buffer, salt2: Buffer, g: Int32, p: Buffer) @@ -1332,87 +1394,3 @@ public extension Api { } } -public extension Api { - enum PhoneCallDiscardReason: TypeConstructorDescription { - case phoneCallDiscardReasonAllowGroupCall(encryptedKey: Buffer) - case phoneCallDiscardReasonBusy - case phoneCallDiscardReasonDisconnect - case phoneCallDiscardReasonHangup - case phoneCallDiscardReasonMissed - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .phoneCallDiscardReasonAllowGroupCall(let encryptedKey): - if boxed { - buffer.appendInt32(-1344096199) - } - serializeBytes(encryptedKey, buffer: buffer, boxed: false) - break - case .phoneCallDiscardReasonBusy: - if boxed { - buffer.appendInt32(-84416311) - } - - break - case .phoneCallDiscardReasonDisconnect: - if boxed { - buffer.appendInt32(-527056480) - } - - break - case .phoneCallDiscardReasonHangup: - if boxed { - buffer.appendInt32(1471006352) - } - - break - case .phoneCallDiscardReasonMissed: - if boxed { - buffer.appendInt32(-2048646399) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .phoneCallDiscardReasonAllowGroupCall(let encryptedKey): - return ("phoneCallDiscardReasonAllowGroupCall", [("encryptedKey", encryptedKey as Any)]) - case .phoneCallDiscardReasonBusy: - return ("phoneCallDiscardReasonBusy", []) - case .phoneCallDiscardReasonDisconnect: - return ("phoneCallDiscardReasonDisconnect", []) - case .phoneCallDiscardReasonHangup: - return ("phoneCallDiscardReasonHangup", []) - case .phoneCallDiscardReasonMissed: - return ("phoneCallDiscardReasonMissed", []) - } - } - - public static func parse_phoneCallDiscardReasonAllowGroupCall(_ reader: BufferReader) -> PhoneCallDiscardReason? { - var _1: Buffer? - _1 = parseBytes(reader) - let _c1 = _1 != nil - if _c1 { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonAllowGroupCall(encryptedKey: _1!) - } - else { - return nil - } - } - public static func parse_phoneCallDiscardReasonBusy(_ reader: BufferReader) -> PhoneCallDiscardReason? { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonBusy - } - public static func parse_phoneCallDiscardReasonDisconnect(_ reader: BufferReader) -> PhoneCallDiscardReason? { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonDisconnect - } - public static func parse_phoneCallDiscardReasonHangup(_ reader: BufferReader) -> PhoneCallDiscardReason? { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonHangup - } - public static func parse_phoneCallDiscardReasonMissed(_ reader: BufferReader) -> PhoneCallDiscardReason? { - return Api.PhoneCallDiscardReason.phoneCallDiscardReasonMissed - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api20.swift b/submodules/TelegramApi/Sources/Api20.swift index 986cf509f0..cc8bcaea8e 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -1,3 +1,87 @@ +public extension Api { + enum PhoneCallDiscardReason: TypeConstructorDescription { + case phoneCallDiscardReasonAllowGroupCall(encryptedKey: Buffer) + case phoneCallDiscardReasonBusy + case phoneCallDiscardReasonDisconnect + case phoneCallDiscardReasonHangup + case phoneCallDiscardReasonMissed + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .phoneCallDiscardReasonAllowGroupCall(let encryptedKey): + if boxed { + buffer.appendInt32(-1344096199) + } + serializeBytes(encryptedKey, buffer: buffer, boxed: false) + break + case .phoneCallDiscardReasonBusy: + if boxed { + buffer.appendInt32(-84416311) + } + + break + case .phoneCallDiscardReasonDisconnect: + if boxed { + buffer.appendInt32(-527056480) + } + + break + case .phoneCallDiscardReasonHangup: + if boxed { + buffer.appendInt32(1471006352) + } + + break + case .phoneCallDiscardReasonMissed: + if boxed { + buffer.appendInt32(-2048646399) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .phoneCallDiscardReasonAllowGroupCall(let encryptedKey): + return ("phoneCallDiscardReasonAllowGroupCall", [("encryptedKey", encryptedKey as Any)]) + case .phoneCallDiscardReasonBusy: + return ("phoneCallDiscardReasonBusy", []) + case .phoneCallDiscardReasonDisconnect: + return ("phoneCallDiscardReasonDisconnect", []) + case .phoneCallDiscardReasonHangup: + return ("phoneCallDiscardReasonHangup", []) + case .phoneCallDiscardReasonMissed: + return ("phoneCallDiscardReasonMissed", []) + } + } + + public static func parse_phoneCallDiscardReasonAllowGroupCall(_ reader: BufferReader) -> PhoneCallDiscardReason? { + var _1: Buffer? + _1 = parseBytes(reader) + let _c1 = _1 != nil + if _c1 { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonAllowGroupCall(encryptedKey: _1!) + } + else { + return nil + } + } + public static func parse_phoneCallDiscardReasonBusy(_ reader: BufferReader) -> PhoneCallDiscardReason? { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonBusy + } + public static func parse_phoneCallDiscardReasonDisconnect(_ reader: BufferReader) -> PhoneCallDiscardReason? { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonDisconnect + } + public static func parse_phoneCallDiscardReasonHangup(_ reader: BufferReader) -> PhoneCallDiscardReason? { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonHangup + } + public static func parse_phoneCallDiscardReasonMissed(_ reader: BufferReader) -> PhoneCallDiscardReason? { + return Api.PhoneCallDiscardReason.phoneCallDiscardReasonMissed + } + + } +} public extension Api { enum PhoneCallProtocol: TypeConstructorDescription { case phoneCallProtocol(flags: Int32, minLayer: Int32, maxLayer: Int32, libraryVersions: [String]) diff --git a/submodules/TelegramApi/Sources/Api26.swift b/submodules/TelegramApi/Sources/Api26.swift index e8e2023011..4d6ba7fbaf 100644 --- a/submodules/TelegramApi/Sources/Api26.swift +++ b/submodules/TelegramApi/Sources/Api26.swift @@ -1069,7 +1069,7 @@ public extension Api { case updateNewStickerSet(stickerset: Api.messages.StickerSet) case updateNewStoryReaction(storyId: Int32, peer: Api.Peer, reaction: Api.Reaction) case updateNotifySettings(peer: Api.NotifyPeer, notifySettings: Api.PeerNotifySettings) - case updatePaidReactionPrivacy(private: Api.Bool) + case updatePaidReactionPrivacy(private: Api.PaidReactionPrivacy) case updatePeerBlocked(flags: Int32, peerId: Api.Peer) case updatePeerHistoryTTL(flags: Int32, peer: Api.Peer, ttlPeriod: Int32?) case updatePeerLocated(peers: [Api.PeerLocated]) @@ -1912,7 +1912,7 @@ public extension Api { break case .updatePaidReactionPrivacy(let `private`): if boxed { - buffer.appendInt32(1372224236) + buffer.appendInt32(-1955438642) } `private`.serialize(buffer, true) break @@ -4305,9 +4305,9 @@ public extension Api { } } public static func parse_updatePaidReactionPrivacy(_ reader: BufferReader) -> Update? { - var _1: Api.Bool? + var _1: Api.PaidReactionPrivacy? if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Bool + _1 = Api.parse(reader, signature: signature) as? Api.PaidReactionPrivacy } let _c1 = _1 != nil if _c1 { diff --git a/submodules/TelegramApi/Sources/Api38.swift b/submodules/TelegramApi/Sources/Api38.swift index a9b0a4f693..bc1130d7c5 100644 --- a/submodules/TelegramApi/Sources/Api38.swift +++ b/submodules/TelegramApi/Sources/Api38.swift @@ -8152,9 +8152,9 @@ public extension Api.functions.messages { } } public extension Api.functions.messages { - static func sendPaidReaction(flags: Int32, peer: Api.InputPeer, msgId: Int32, count: Int32, randomId: Int64, `private`: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func sendPaidReaction(flags: Int32, peer: Api.InputPeer, msgId: Int32, count: Int32, randomId: Int64, `private`: Api.PaidReactionPrivacy?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-1646877061) + buffer.appendInt32(1488702288) serializeInt32(flags, buffer: buffer, boxed: false) peer.serialize(buffer, true) serializeInt32(msgId, buffer: buffer, boxed: false) @@ -8664,9 +8664,9 @@ public extension Api.functions.messages { } } public extension Api.functions.messages { - static func togglePaidReactionPrivacy(peer: Api.InputPeer, msgId: Int32, `private`: Api.Bool) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func togglePaidReactionPrivacy(peer: Api.InputPeer, msgId: Int32, `private`: Api.PaidReactionPrivacy) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-2070228073) + buffer.appendInt32(1129874869) peer.serialize(buffer, true) serializeInt32(msgId, buffer: buffer, boxed: false) `private`.serialize(buffer, true) diff --git a/submodules/TelegramCallsUI/Sources/CallController.swift b/submodules/TelegramCallsUI/Sources/CallController.swift index 7b8cf3a91e..020a0d321a 100644 --- a/submodules/TelegramCallsUI/Sources/CallController.swift +++ b/submodules/TelegramCallsUI/Sources/CallController.swift @@ -483,12 +483,25 @@ public final class CallController: ViewController { } private func conferenceAddParticipant() { + var disablePeerIds: [EnginePeer.Id] = [] + disablePeerIds.append(self.call.context.account.peerId) + disablePeerIds.append(self.call.peerId) + let controller = CallController.openConferenceAddParticipant(context: self.call.context, disablePeerIds: disablePeerIds, completion: { [weak self] peerIds in + guard let self else { + return + } + + let _ = self.call.upgradeToConference(invitePeerIds: peerIds, completion: { _ in + }) + }) + self.push(controller) + } + + static func openConferenceAddParticipant(context: AccountContext, disablePeerIds: [EnginePeer.Id], completion: @escaping ([EnginePeer.Id]) -> Void) -> ViewController { //TODO:localize - let context = self.call.context - let callPeerId = self.call.peerId let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkPresentationTheme) - let controller = self.call.context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams( - context: self.call.context, + let controller = context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams( + context: context, updatedPresentationData: (initial: presentationData, signal: .single(presentationData)), title: "Invite Members", mode: .peerSelection(searchChatList: true, searchGroups: false, searchChannels: false), @@ -496,7 +509,7 @@ public final class CallController: ViewController { guard case let .user(user) = peer else { return false } - if user.id == context.account.peerId || user.id == callPeerId { + if disablePeerIds.contains(user.id) { return false } if user.botInfo != nil { @@ -506,11 +519,7 @@ public final class CallController: ViewController { } )) controller.navigationPresentation = .modal - let _ = (controller.result |> take(1) |> deliverOnMainQueue).startStandalone(next: { [weak self, weak controller] result in - guard let self else { - controller?.dismiss() - return - } + let _ = (controller.result |> take(1) |> deliverOnMainQueue).startStandalone(next: { [weak controller] result in guard case let .result(peerIds, _) = result else { controller?.dismiss() return @@ -532,11 +541,10 @@ public final class CallController: ViewController { } } - let _ = self.call.upgradeToConference(invitePeerIds: invitePeerIds, completion: { _ in - }) + completion(invitePeerIds) }) - self.push(controller) + return controller } @objc private func backPressed() { diff --git a/submodules/TelegramCallsUI/Sources/PresentationCall.swift b/submodules/TelegramCallsUI/Sources/PresentationCall.swift index c06fdd894f..bbed98f38b 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCall.swift @@ -177,6 +177,7 @@ public final class PresentationCallImpl: PresentationCall { public let internalId: CallSessionInternalId public let peerId: EnginePeer.Id public let isOutgoing: Bool + private let isIncomingConference: Bool public var isVideo: Bool public var isVideoPossible: Bool private let enableStunMarking: Bool @@ -327,6 +328,7 @@ public final class PresentationCallImpl: PresentationCall { internalId: CallSessionInternalId, peerId: EnginePeer.Id, isOutgoing: Bool, + isIncomingConference: Bool, peer: EnginePeer?, proxyServer: ProxyServerSettings?, auxiliaryServers: [CallAuxiliaryServer], @@ -361,6 +363,7 @@ public final class PresentationCallImpl: PresentationCall { self.internalId = internalId self.peerId = peerId self.isOutgoing = isOutgoing + self.isIncomingConference = isIncomingConference self.isVideo = initialState?.type == .video self.isVideoPossible = isVideoPossible self.enableStunMarking = enableStunMarking @@ -805,6 +808,9 @@ public final class PresentationCallImpl: PresentationCall { conferenceCall.upgradedConferenceCall = self conferenceCall.setInvitedPeers(self.pendingInviteToConferencePeerIds) + for peerId in self.pendingInviteToConferencePeerIds { + let _ = conferenceCall.invitePeer(peerId) + } conferenceCall.setIsMuted(action: self.isMutedValue ? .muted(isPushToTalkActive: false) : .unmuted) if let videoCapturer = self.videoCapturer { @@ -1027,9 +1033,33 @@ public final class PresentationCallImpl: PresentationCall { self.callKitIntegration?.dropCall(uuid: self.internalId) } } - if let presentationState { - self.statePromise.set(presentationState) - self.updateTone(presentationState, callContextState: callContextState, previous: previous) + + var isConference = false + if case let .active(_, _, _, _, _, _, _, _, conferenceCall) = sessionState.state { + isConference = conferenceCall != nil + } else if case .switchedToConference = sessionState.state { + isConference = true + } + if self.conferenceCallImpl != nil { + isConference = true + } + if self.conferenceStateValue != nil { + isConference = true + } + if self.isIncomingConference { + isConference = true + } + + if isConference { + if self.currentTone != nil { + self.currentTone = nil + self.sharedAudioContext?.audioDevice?.setTone(tone: nil) + } + } else { + if let presentationState { + self.statePromise.set(presentationState) + self.updateTone(presentationState, callContextState: callContextState, previous: previous) + } } } @@ -1161,11 +1191,15 @@ public final class PresentationCallImpl: PresentationCall { present(c, a) }, openSettings: { openSettings() - }, { [weak self] value in - guard let strongSelf = self else { + }, { [weak strongSelf] value in + guard let strongSelf else { return } if value { + if strongSelf.isIncomingConference { + strongSelf.conferenceStateValue = .preparing + } + strongSelf.callSessionManager.accept(internalId: strongSelf.internalId) if !fromCallKitAction { strongSelf.callKitIntegration?.answerCall(uuid: strongSelf.internalId) @@ -1175,6 +1209,10 @@ public final class PresentationCallImpl: PresentationCall { } }) } else { + if strongSelf.isIncomingConference { + strongSelf.conferenceStateValue = .preparing + } + strongSelf.callSessionManager.accept(internalId: strongSelf.internalId) if !fromCallKitAction { strongSelf.callKitIntegration?.answerCall(uuid: strongSelf.internalId) @@ -1316,23 +1354,12 @@ public final class PresentationCallImpl: PresentationCall { public func upgradeToConference(invitePeerIds: [EnginePeer.Id], completion: @escaping (PresentationGroupCall) -> Void) -> Disposable { if let conferenceCall = self.conferenceCall { completion(conferenceCall) - - for peerId in invitePeerIds { - let _ = self.requestAddToConference(peerId: peerId) - } - return EmptyDisposable } self.pendingInviteToConferencePeerIds = invitePeerIds - let index = self.upgradedToConferenceCompletions.add({ [weak self] call in + let index = self.upgradedToConferenceCompletions.add({ call in completion(call) - - if let self { - for peerId in invitePeerIds { - let _ = self.requestAddToConference(peerId: peerId) - } - } }) self.conferenceStateValue = .preparing @@ -1348,32 +1375,6 @@ public final class PresentationCallImpl: PresentationCall { } } - private func requestAddToConference(peerId: EnginePeer.Id) -> Disposable { - var conferenceCall: (conference: GroupCallReference, encryptionKey: Data)? - if let sessionState = self.sessionState { - switch sessionState.state { - case let .active(_, key, _, _, _, _, _, _, conferenceCallValue): - if let conferenceCallValue { - conferenceCall = (conferenceCallValue, key) - } - case let .switchedToConference(key, _, conferenceCallValue): - conferenceCall = (conferenceCallValue, key) - default: - break - } - } - guard let conferenceCall else { - return EmptyDisposable - } - return (self.callSessionManager.request(peerId: peerId, isVideo: false, enableVideo: true, conferenceCall: conferenceCall) - |> deliverOnMainQueue).startStandalone(next: { [weak self] requestedInternalId in - guard let self else { - return - } - let _ = self - }) - } - public func setCurrentAudioOutput(_ output: AudioSessionOutput) { if let sharedAudioContext = self.sharedAudioContext { sharedAudioContext.setCurrentAudioOutput(output) diff --git a/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift b/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift index 84852f730a..f6f1714e20 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift @@ -325,6 +325,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager { internalId: firstState.2.id, peerId: firstState.2.peerId, isOutgoing: false, + isIncomingConference: firstState.2.isConference, peer: EnginePeer(firstState.1), proxyServer: strongSelf.proxyServer, auxiliaryServers: [], @@ -572,6 +573,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager { internalId: internalId, peerId: peerId, isOutgoing: true, + isIncomingConference: false, peer: nil, proxyServer: strongSelf.proxyServer, auxiliaryServers: [], diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index 823cadcdac..cdacb13681 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -600,6 +600,52 @@ private final class ScreencastEmbeddedIPCContext: ScreencastIPCContext { } } +private final class PendingConferenceInvitationContext { + private let callSessionManager: CallSessionManager + private var requestDisposable: Disposable? + private var stateDisposable: Disposable? + private var internalId: CallSessionInternalId? + + private var didNotifyEnded: Bool = false + + init(callSessionManager: CallSessionManager, groupCall: GroupCallReference, encryptionKey: Data, peerId: PeerId, onEnded: @escaping () -> Void) { + self.callSessionManager = callSessionManager + + self.requestDisposable = (callSessionManager.request(peerId: peerId, isVideo: false, enableVideo: true, conferenceCall: (groupCall, encryptionKey)) + |> deliverOnMainQueue).startStrict(next: { [weak self] internalId in + guard let self else { + return + } + self.internalId = internalId + + self.stateDisposable = (self.callSessionManager.callState(internalId: internalId) + |> deliverOnMainQueue).startStrict(next: { [weak self] state in + guard let self else { + return + } + switch state.state { + case .dropping, .terminated: + if !self.didNotifyEnded { + self.didNotifyEnded = true + onEnded() + } + default: + break + } + }) + }) + } + + deinit { + self.requestDisposable?.dispose() + self.stateDisposable?.dispose() + + if let internalId = self.internalId { + self.callSessionManager.drop(internalId: internalId, reason: .hangUp, debugLog: .single(nil)) + } + } +} + public final class PresentationGroupCallImpl: PresentationGroupCall { private enum InternalState { case requesting @@ -1018,7 +1064,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { let debugLog = Promise() - weak var upgradedConferenceCall: PresentationCallImpl? + public weak var upgradedConferenceCall: PresentationCallImpl? + private var conferenceInvitationContexts: [PeerId: PendingConferenceInvitationContext] = [:] init( accountContext: AccountContext, @@ -1859,6 +1906,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { var encryptionKey: Data? encryptionKey = self.encryptionKey?.key + encryptionKey = nil let contextAudioSessionActive: Signal if self.sharedAudioContext != nil { @@ -3575,17 +3623,55 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } public func invitePeer(_ peerId: PeerId) -> Bool { - guard let callInfo = self.internalState.callInfo, !self.invitedPeersValue.contains(peerId) else { + if self.isConference { + guard let initialCall = self.initialCall, let encryptionKey = self.encryptionKey else { + return false + } + if conferenceInvitationContexts[peerId] != nil { + return false + } + var onEnded: (() -> Void)? + var didEndAlready = false + let invitationContext = PendingConferenceInvitationContext( + callSessionManager: self.accountContext.account.callSessionManager, + groupCall: GroupCallReference(id: initialCall.id, accessHash: initialCall.accessHash), + encryptionKey: encryptionKey.key, + peerId: peerId, + onEnded: { + didEndAlready = true + onEnded?() + } + ) + if !didEndAlready { + conferenceInvitationContexts[peerId] = invitationContext + if !self.invitedPeersValue.contains(peerId) { + self.invitedPeersValue.append(peerId) + } + onEnded = { [weak self, weak invitationContext] in + guard let self, let invitationContext else { + return + } + if self.conferenceInvitationContexts[peerId] === invitationContext { + self.conferenceInvitationContexts.removeValue(forKey: peerId) + self.invitedPeersValue.removeAll(where: { $0 == peerId }) + } + } + } + return false + } else { + guard let callInfo = self.internalState.callInfo, !self.invitedPeersValue.contains(peerId) else { + return false + } + + var updatedInvitedPeers = self.invitedPeersValue + updatedInvitedPeers.insert(peerId, at: 0) + self.invitedPeersValue = updatedInvitedPeers + + let _ = self.accountContext.engine.calls.inviteToGroupCall(callId: callInfo.id, accessHash: callInfo.accessHash, peerId: peerId).start() + + return true } - - var updatedInvitedPeers = self.invitedPeersValue - updatedInvitedPeers.insert(peerId, at: 0) - self.invitedPeersValue = updatedInvitedPeers - - let _ = self.accountContext.engine.calls.inviteToGroupCall(callId: callInfo.id, accessHash: callInfo.accessHash, peerId: peerId).start() - - return true } func setInvitedPeers(_ peerIds: [PeerId]) { diff --git a/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift b/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift index 2156452ce6..faa3b83808 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift @@ -1609,15 +1609,19 @@ final class VideoChatScreenComponent: Component { if let members = self.members, let callState = self.callState { var canInvite = true var inviteIsLink = false - if case let .channel(peer) = self.peer { - if peer.flags.contains(.isGigagroup) { - if peer.flags.contains(.isCreator) || peer.adminRights != nil { - } else { - canInvite = false + if case let .group(groupCall) = self.currentCall, groupCall.isConference { + canInvite = true + } else { + if case let .channel(peer) = self.peer { + if peer.flags.contains(.isGigagroup) { + if peer.flags.contains(.isCreator) || peer.adminRights != nil { + } else { + canInvite = false + } + } + if case .broadcast = peer.info, !(peer.addressName?.isEmpty ?? true) { + inviteIsLink = true } - } - if case .broadcast = peer.info, !(peer.addressName?.isEmpty ?? true) { - inviteIsLink = true } } var inviteType: VideoChatParticipantsComponent.Participants.InviteType? diff --git a/submodules/TelegramCallsUI/Sources/VideoChatScreenInviteMembers.swift b/submodules/TelegramCallsUI/Sources/VideoChatScreenInviteMembers.swift index 9cb562c58c..22557857bc 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatScreenInviteMembers.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatScreenInviteMembers.swift @@ -13,336 +13,358 @@ extension VideoChatScreenComponent.View { return } - var canInvite = true - var inviteIsLink = false - if case let .channel(peer) = self.peer { - if peer.flags.contains(.isGigagroup) { - if peer.flags.contains(.isCreator) || peer.adminRights != nil { - } else { - canInvite = false + if groupCall.isConference { + var disablePeerIds: [EnginePeer.Id] = [] + disablePeerIds.append(groupCall.accountContext.account.peerId) + if let members = self.members { + for participant in members.participants { + if !disablePeerIds.contains(participant.peer.id) { + disablePeerIds.append(participant.peer.id) + } } } - if case .broadcast = peer.info, !(peer.addressName?.isEmpty ?? true) { - inviteIsLink = true - } - } - var inviteType: VideoChatParticipantsComponent.Participants.InviteType? - if canInvite { - if inviteIsLink { - inviteType = .shareLink - } else { - inviteType = .invite - } - } - - guard let inviteType else { - return - } - guard let peerId = groupCall.peerId else { - return - } - - switch inviteType { - case .invite: - let groupPeer = groupCall.accountContext.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) - let _ = (groupPeer - |> deliverOnMainQueue).start(next: { [weak self] groupPeer in - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall, let groupPeer else { + let controller = CallController.openConferenceAddParticipant(context: groupCall.accountContext, disablePeerIds: disablePeerIds, completion: { [weak self] peerIds in + guard let self, case let .group(groupCall) = self.currentCall else { return } - let inviteLinks = self.inviteLinks - if case let .channel(groupPeer) = groupPeer { - var canInviteMembers = true - if case .broadcast = groupPeer.info, !(groupPeer.addressName?.isEmpty ?? true) { - canInviteMembers = false - } - if !canInviteMembers { - if let inviteLinks { - self.presentShare(inviteLinks) - } - return - } + for peerId in peerIds { + let _ = groupCall.invitePeer(peerId) } - - var filters: [ChannelMembersSearchFilter] = [] - if let members = self.members { - filters.append(.disable(Array(members.participants.map { $0.peer.id }))) - } - if case let .channel(groupPeer) = groupPeer { - if !groupPeer.hasPermission(.inviteMembers) && inviteLinks?.listenerLink == nil { - filters.append(.excludeNonMembers) - } - } else if case let .legacyGroup(groupPeer) = groupPeer { - if groupPeer.hasBannedPermission(.banAddMembers) { - filters.append(.excludeNonMembers) - } - } - filters.append(.excludeBots) - - var dismissController: (() -> Void)? - let controller = ChannelMembersSearchController(context: groupCall.accountContext, peerId: groupPeer.id, forceTheme: environment.theme, mode: .inviteToCall, filters: filters, openPeer: { [weak self] peer, participant in - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { - dismissController?() - return - } - guard let callState = self.callState else { - return - } - - let presentationData = groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: environment.theme) - if peer.id == callState.myPeerId { - return - } - if let participant { - dismissController?() - - if groupCall.invitePeer(participant.peer.id) { - let text: String - if case let .channel(channel) = self.peer, case .broadcast = channel.info { - text = environment.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string - } else { - text = environment.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string - } - self.presentUndoOverlay(content: .invitedToVoiceChat(context: groupCall.accountContext, peer: EnginePeer(participant.peer), title: nil, text: text, action: nil, duration: 3), action: { _ in return false }) - } + }) + self.environment?.controller()?.push(controller) + } else { + var canInvite = true + var inviteIsLink = false + if case let .channel(peer) = self.peer { + if peer.flags.contains(.isGigagroup) { + if peer.flags.contains(.isCreator) || peer.adminRights != nil { } else { - if case let .channel(groupPeer) = groupPeer, let listenerLink = inviteLinks?.listenerLink, !groupPeer.hasPermission(.inviteMembers) { - let text = environment.strings.VoiceChat_SendPublicLinkText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder), EnginePeer(groupPeer).displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string - - environment.controller()?.present(textAlertController(context: groupCall.accountContext, forceTheme: environment.theme, title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: environment.strings.VoiceChat_SendPublicLinkSend, action: { [weak self] in - dismissController?() - - guard let self, case let .group(groupCall) = self.currentCall else { - return - } - - let _ = (enqueueMessages(account: groupCall.accountContext.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) - |> deliverOnMainQueue).start(next: { [weak self] _ in - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { - return - } - self.presentUndoOverlay(content: .forward(savedMessages: false, text: environment.strings.UserInfo_LinkForwardTooltip_Chat_One(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string), action: { _ in return true }) - }) - })]), in: .window(.root)) - } else { - let text: String - if case let .channel(groupPeer) = groupPeer, case .broadcast = groupPeer.info { - text = environment.strings.VoiceChat_InviteMemberToChannelFirstText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder), EnginePeer(groupPeer).displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string - } else { - text = environment.strings.VoiceChat_InviteMemberToGroupFirstText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder), groupPeer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string + canInvite = false + } + } + if case .broadcast = peer.info, !(peer.addressName?.isEmpty ?? true) { + inviteIsLink = true + } + } + var inviteType: VideoChatParticipantsComponent.Participants.InviteType? + if canInvite { + if inviteIsLink { + inviteType = .shareLink + } else { + inviteType = .invite + } + } + + guard let inviteType else { + return + } + guard let peerId = groupCall.peerId else { + return + } + + switch inviteType { + case .invite: + let groupPeer = groupCall.accountContext.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) + let _ = (groupPeer + |> deliverOnMainQueue).start(next: { [weak self] groupPeer in + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall, let groupPeer else { + return + } + let inviteLinks = self.inviteLinks + + if case let .channel(groupPeer) = groupPeer { + var canInviteMembers = true + if case .broadcast = groupPeer.info, !(groupPeer.addressName?.isEmpty ?? true) { + canInviteMembers = false + } + if !canInviteMembers { + if let inviteLinks { + self.presentShare(inviteLinks) } - - environment.controller()?.present(textAlertController(context: groupCall.accountContext, forceTheme: environment.theme, title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: environment.strings.VoiceChat_InviteMemberToGroupFirstAdd, action: { [weak self] in - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { - return - } - - if case let .channel(groupPeer) = groupPeer { - guard let selfController = environment.controller() else { - return - } - let inviteDisposable = self.inviteDisposable - var inviteSignal = groupCall.accountContext.peerChannelMemberCategoriesContextsManager.addMembers(engine: groupCall.accountContext.engine, peerId: groupPeer.id, memberIds: [peer.id]) - var cancelImpl: (() -> Void)? - let progressSignal = Signal { [weak selfController] subscriber in - let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { - cancelImpl?() - })) - selfController?.present(controller, in: .window(.root)) - return ActionDisposable { [weak controller] in - Queue.mainQueue().async() { - controller?.dismiss() - } - } - } - |> runOn(Queue.mainQueue()) - |> delay(0.15, queue: Queue.mainQueue()) - let progressDisposable = progressSignal.start() - - inviteSignal = inviteSignal - |> afterDisposed { - Queue.mainQueue().async { - progressDisposable.dispose() - } - } - cancelImpl = { - inviteDisposable.set(nil) - } - - inviteDisposable.set((inviteSignal |> deliverOnMainQueue).start(error: { [weak self] error in - dismissController?() - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { - return - } - - let text: String - switch error { - case .limitExceeded: - text = environment.strings.Channel_ErrorAddTooMuch - case .tooMuchJoined: - text = environment.strings.Invite_ChannelsTooMuch - case .generic: - text = environment.strings.Login_UnknownError - case .restricted: - text = environment.strings.Channel_ErrorAddBlocked - case .notMutualContact: - if case .broadcast = groupPeer.info { - text = environment.strings.Channel_AddUserLeftError - } else { - text = environment.strings.GroupInfo_AddUserLeftError - } - case .botDoesntSupportGroups: - text = environment.strings.Channel_BotDoesntSupportGroups - case .tooMuchBots: - text = environment.strings.Channel_TooMuchBots - case .bot: - text = environment.strings.Login_UnknownError - case .kicked: - text = environment.strings.Channel_AddUserKickedError - } - environment.controller()?.present(textAlertController(context: groupCall.accountContext, forceTheme: environment.theme, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) - }, completed: { [weak self] in - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { - dismissController?() - return - } - dismissController?() - - if groupCall.invitePeer(peer.id) { - let text: String - if case let .channel(channel) = self.peer, case .broadcast = channel.info { - text = environment.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder)).string - } else { - text = environment.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder)).string - } - self.presentUndoOverlay(content: .invitedToVoiceChat(context: groupCall.accountContext, peer: peer, title: nil, text: text, action: nil, duration: 3), action: { _ in return false }) - } - })) - } else if case let .legacyGroup(groupPeer) = groupPeer { - guard let selfController = environment.controller() else { - return - } - let inviteDisposable = self.inviteDisposable - var inviteSignal = groupCall.accountContext.engine.peers.addGroupMember(peerId: groupPeer.id, memberId: peer.id) - var cancelImpl: (() -> Void)? - let progressSignal = Signal { [weak selfController] subscriber in - let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { - cancelImpl?() - })) - selfController?.present(controller, in: .window(.root)) - return ActionDisposable { [weak controller] in - Queue.mainQueue().async() { - controller?.dismiss() - } - } - } - |> runOn(Queue.mainQueue()) - |> delay(0.15, queue: Queue.mainQueue()) - let progressDisposable = progressSignal.start() - - inviteSignal = inviteSignal - |> afterDisposed { - Queue.mainQueue().async { - progressDisposable.dispose() - } - } - cancelImpl = { - inviteDisposable.set(nil) - } - - inviteDisposable.set((inviteSignal |> deliverOnMainQueue).start(error: { [weak self] error in - dismissController?() - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { - return - } - let context = groupCall.accountContext - - switch error { - case .privacy: - let _ = (groupCall.accountContext.account.postbox.loadedPeerWithId(peer.id) - |> deliverOnMainQueue).start(next: { [weak self] peer in - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { - return - } - environment.controller()?.present(textAlertController(context: groupCall.accountContext, title: nil, text: environment.strings.Privacy_GroupsAndChannels_InviteToGroupError(EnginePeer(peer).compactDisplayTitle, EnginePeer(peer).compactDisplayTitle).string, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) - }) - case .notMutualContact: - environment.controller()?.present(textAlertController(context: context, title: nil, text: environment.strings.GroupInfo_AddUserLeftError, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) - case .tooManyChannels: - environment.controller()?.present(textAlertController(context: context, title: nil, text: environment.strings.Invite_ChannelsTooMuch, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) - case .groupFull, .generic: - environment.controller()?.present(textAlertController(context: context, forceTheme: environment.theme, title: nil, text: environment.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) - } - }, completed: { [weak self] in - guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { - dismissController?() - return - } - dismissController?() - - if groupCall.invitePeer(peer.id) { - let text: String - if case let .channel(channel) = self.peer, case .broadcast = channel.info { - text = environment.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder)).string - } else { - text = environment.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder)).string - } - self.presentUndoOverlay(content: .invitedToVoiceChat(context: groupCall.accountContext, peer: peer, title: nil, text: text, action: nil, duration: 3), action: { _ in return false }) - } - })) - } - })]), in: .window(.root)) + return } } - }) - controller.copyInviteLink = { [weak self] in - dismissController?() - guard let self, case let .group(groupCall) = self.currentCall else { - return + var filters: [ChannelMembersSearchFilter] = [] + if let members = self.members { + filters.append(.disable(Array(members.participants.map { $0.peer.id }))) } - guard let callPeerId = groupCall.peerId else { - return - } - - let _ = (groupCall.accountContext.engine.data.get( - TelegramEngine.EngineData.Item.Peer.Peer(id: callPeerId), - TelegramEngine.EngineData.Item.Peer.ExportedInvitation(id: callPeerId) - ) - |> map { peer, exportedInvitation -> String? in - if let link = inviteLinks?.listenerLink { - return link - } else if let peer = peer, let addressName = peer.addressName, !addressName.isEmpty { - return "https://t.me/\(addressName)" - } else if let link = exportedInvitation?.link { - return link - } else { - return nil + if case let .channel(groupPeer) = groupPeer { + if !groupPeer.hasPermission(.inviteMembers) && inviteLinks?.listenerLink == nil { + filters.append(.excludeNonMembers) + } + } else if case let .legacyGroup(groupPeer) = groupPeer { + if groupPeer.hasBannedPermission(.banAddMembers) { + filters.append(.excludeNonMembers) } } - |> deliverOnMainQueue).start(next: { [weak self] link in - guard let self, let environment = self.environment else { + filters.append(.excludeBots) + + var dismissController: (() -> Void)? + let controller = ChannelMembersSearchController(context: groupCall.accountContext, peerId: groupPeer.id, forceTheme: environment.theme, mode: .inviteToCall, filters: filters, openPeer: { [weak self] peer, participant in + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { + dismissController?() + return + } + guard let callState = self.callState else { return } - if let link { - UIPasteboard.general.string = link + let presentationData = groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: environment.theme) + if peer.id == callState.myPeerId { + return + } + if let participant { + dismissController?() - self.presentUndoOverlay(content: .linkCopied(title: nil, text: environment.strings.VoiceChat_InviteLinkCopiedText), action: { _ in return false }) + if groupCall.invitePeer(participant.peer.id) { + let text: String + if case let .channel(channel) = self.peer, case .broadcast = channel.info { + text = environment.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string + } else { + text = environment.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string + } + self.presentUndoOverlay(content: .invitedToVoiceChat(context: groupCall.accountContext, peer: EnginePeer(participant.peer), title: nil, text: text, action: nil, duration: 3), action: { _ in return false }) + } + } else { + if case let .channel(groupPeer) = groupPeer, let listenerLink = inviteLinks?.listenerLink, !groupPeer.hasPermission(.inviteMembers) { + let text = environment.strings.VoiceChat_SendPublicLinkText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder), EnginePeer(groupPeer).displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string + + environment.controller()?.present(textAlertController(context: groupCall.accountContext, forceTheme: environment.theme, title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: environment.strings.VoiceChat_SendPublicLinkSend, action: { [weak self] in + dismissController?() + + guard let self, case let .group(groupCall) = self.currentCall else { + return + } + + let _ = (enqueueMessages(account: groupCall.accountContext.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) + |> deliverOnMainQueue).start(next: { [weak self] _ in + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { + return + } + self.presentUndoOverlay(content: .forward(savedMessages: false, text: environment.strings.UserInfo_LinkForwardTooltip_Chat_One(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string), action: { _ in return true }) + }) + })]), in: .window(.root)) + } else { + let text: String + if case let .channel(groupPeer) = groupPeer, case .broadcast = groupPeer.info { + text = environment.strings.VoiceChat_InviteMemberToChannelFirstText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder), EnginePeer(groupPeer).displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string + } else { + text = environment.strings.VoiceChat_InviteMemberToGroupFirstText(peer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder), groupPeer.displayTitle(strings: environment.strings, displayOrder: groupCall.accountContext.sharedContext.currentPresentationData.with({ $0 }).nameDisplayOrder)).string + } + + environment.controller()?.present(textAlertController(context: groupCall.accountContext, forceTheme: environment.theme, title: nil, text: text, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: environment.strings.VoiceChat_InviteMemberToGroupFirstAdd, action: { [weak self] in + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { + return + } + + if case let .channel(groupPeer) = groupPeer { + guard let selfController = environment.controller() else { + return + } + let inviteDisposable = self.inviteDisposable + var inviteSignal = groupCall.accountContext.peerChannelMemberCategoriesContextsManager.addMembers(engine: groupCall.accountContext.engine, peerId: groupPeer.id, memberIds: [peer.id]) + var cancelImpl: (() -> Void)? + let progressSignal = Signal { [weak selfController] subscriber in + let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { + cancelImpl?() + })) + selfController?.present(controller, in: .window(.root)) + return ActionDisposable { [weak controller] in + Queue.mainQueue().async() { + controller?.dismiss() + } + } + } + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + + inviteSignal = inviteSignal + |> afterDisposed { + Queue.mainQueue().async { + progressDisposable.dispose() + } + } + cancelImpl = { + inviteDisposable.set(nil) + } + + inviteDisposable.set((inviteSignal |> deliverOnMainQueue).start(error: { [weak self] error in + dismissController?() + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { + return + } + + let text: String + switch error { + case .limitExceeded: + text = environment.strings.Channel_ErrorAddTooMuch + case .tooMuchJoined: + text = environment.strings.Invite_ChannelsTooMuch + case .generic: + text = environment.strings.Login_UnknownError + case .restricted: + text = environment.strings.Channel_ErrorAddBlocked + case .notMutualContact: + if case .broadcast = groupPeer.info { + text = environment.strings.Channel_AddUserLeftError + } else { + text = environment.strings.GroupInfo_AddUserLeftError + } + case .botDoesntSupportGroups: + text = environment.strings.Channel_BotDoesntSupportGroups + case .tooMuchBots: + text = environment.strings.Channel_TooMuchBots + case .bot: + text = environment.strings.Login_UnknownError + case .kicked: + text = environment.strings.Channel_AddUserKickedError + } + environment.controller()?.present(textAlertController(context: groupCall.accountContext, forceTheme: environment.theme, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) + }, completed: { [weak self] in + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { + dismissController?() + return + } + dismissController?() + + if groupCall.invitePeer(peer.id) { + let text: String + if case let .channel(channel) = self.peer, case .broadcast = channel.info { + text = environment.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder)).string + } else { + text = environment.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder)).string + } + self.presentUndoOverlay(content: .invitedToVoiceChat(context: groupCall.accountContext, peer: peer, title: nil, text: text, action: nil, duration: 3), action: { _ in return false }) + } + })) + } else if case let .legacyGroup(groupPeer) = groupPeer { + guard let selfController = environment.controller() else { + return + } + let inviteDisposable = self.inviteDisposable + var inviteSignal = groupCall.accountContext.engine.peers.addGroupMember(peerId: groupPeer.id, memberId: peer.id) + var cancelImpl: (() -> Void)? + let progressSignal = Signal { [weak selfController] subscriber in + let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { + cancelImpl?() + })) + selfController?.present(controller, in: .window(.root)) + return ActionDisposable { [weak controller] in + Queue.mainQueue().async() { + controller?.dismiss() + } + } + } + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + + inviteSignal = inviteSignal + |> afterDisposed { + Queue.mainQueue().async { + progressDisposable.dispose() + } + } + cancelImpl = { + inviteDisposable.set(nil) + } + + inviteDisposable.set((inviteSignal |> deliverOnMainQueue).start(error: { [weak self] error in + dismissController?() + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { + return + } + let context = groupCall.accountContext + + switch error { + case .privacy: + let _ = (groupCall.accountContext.account.postbox.loadedPeerWithId(peer.id) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { + return + } + environment.controller()?.present(textAlertController(context: groupCall.accountContext, title: nil, text: environment.strings.Privacy_GroupsAndChannels_InviteToGroupError(EnginePeer(peer).compactDisplayTitle, EnginePeer(peer).compactDisplayTitle).string, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) + }) + case .notMutualContact: + environment.controller()?.present(textAlertController(context: context, title: nil, text: environment.strings.GroupInfo_AddUserLeftError, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) + case .tooManyChannels: + environment.controller()?.present(textAlertController(context: context, title: nil, text: environment.strings.Invite_ChannelsTooMuch, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) + case .groupFull, .generic: + environment.controller()?.present(textAlertController(context: context, forceTheme: environment.theme, title: nil, text: environment.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: environment.strings.Common_OK, action: {})]), in: .window(.root)) + } + }, completed: { [weak self] in + guard let self, let environment = self.environment, case let .group(groupCall) = self.currentCall else { + dismissController?() + return + } + dismissController?() + + if groupCall.invitePeer(peer.id) { + let text: String + if case let .channel(channel) = self.peer, case .broadcast = channel.info { + text = environment.strings.LiveStream_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder)).string + } else { + text = environment.strings.VoiceChat_InvitedPeerText(peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder)).string + } + self.presentUndoOverlay(content: .invitedToVoiceChat(context: groupCall.accountContext, peer: peer, title: nil, text: text, action: nil, duration: 3), action: { _ in return false }) + } + })) + } + })]), in: .window(.root)) + } } }) + controller.copyInviteLink = { [weak self] in + dismissController?() + + guard let self, case let .group(groupCall) = self.currentCall else { + return + } + guard let callPeerId = groupCall.peerId else { + return + } + + let _ = (groupCall.accountContext.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: callPeerId), + TelegramEngine.EngineData.Item.Peer.ExportedInvitation(id: callPeerId) + ) + |> map { peer, exportedInvitation -> String? in + if let link = inviteLinks?.listenerLink { + return link + } else if let peer = peer, let addressName = peer.addressName, !addressName.isEmpty { + return "https://t.me/\(addressName)" + } else if let link = exportedInvitation?.link { + return link + } else { + return nil + } + } + |> deliverOnMainQueue).start(next: { [weak self] link in + guard let self, let environment = self.environment else { + return + } + + if let link { + UIPasteboard.general.string = link + + self.presentUndoOverlay(content: .linkCopied(title: nil, text: environment.strings.VoiceChat_InviteLinkCopiedText), action: { _ in return false }) + } + }) + } + dismissController = { [weak controller] in + controller?.dismiss() + } + environment.controller()?.push(controller) + }) + case .shareLink: + guard let inviteLinks = self.inviteLinks else { + return } - dismissController = { [weak controller] in - controller?.dismiss() - } - environment.controller()?.push(controller) - }) - case .shareLink: - guard let inviteLinks = self.inviteLinks else { - return + self.presentShare(inviteLinks) } - self.presentShare(inviteLinks) } } } diff --git a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift index 9973824ba0..3d4da7d122 100644 --- a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift +++ b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift @@ -131,7 +131,7 @@ enum AccountStateMutationOperation { case UpdateRevenueBalances(peerId: PeerId, balances: RevenueStats.Balances) case UpdateStarsBalance(peerId: PeerId, balance: Api.StarsAmount) case UpdateStarsRevenueStatus(peerId: PeerId, status: StarsRevenueStats.Balances) - case UpdateStarsReactionsAreAnonymousByDefault(isAnonymous: Bool) + case UpdateStarsReactionsDefaultPrivacy(privacy: TelegramPaidReactionPrivacy) case ReportMessageDelivery([MessageId]) } @@ -699,8 +699,8 @@ struct AccountMutableState { self.addOperation(.UpdateStarsRevenueStatus(peerId: peerId, status: status)) } - mutating func updateStarsReactionsAreAnonymousByDefault(isAnonymous: Bool) { - self.addOperation(.UpdateStarsReactionsAreAnonymousByDefault(isAnonymous: isAnonymous)) + mutating func updateStarsReactionsDefaultPrivacy(privacy: TelegramPaidReactionPrivacy) { + self.addOperation(.UpdateStarsReactionsDefaultPrivacy(privacy: privacy)) } mutating func addReportMessageDelivery(messageIds: [MessageId]) { @@ -709,7 +709,7 @@ struct AccountMutableState { mutating func addOperation(_ operation: AccountStateMutationOperation) { switch operation { - case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .UpdateWallpaper, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter, .UpdateReadThread, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateMessagesPinned, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsAreAnonymousByDefault, .ReportMessageDelivery: + case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .UpdateWallpaper, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter, .UpdateReadThread, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateMessagesPinned, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsDefaultPrivacy, .ReportMessageDelivery: break case let .AddMessages(messages, location): for message in messages { diff --git a/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift b/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift index f087707497..c282b7dcb7 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift @@ -215,12 +215,40 @@ public func mergedMessageReactions(attributes: [MessageAttribute], isTags: Bool) if let index = topPeers.firstIndex(where: { $0.isMy }) { topPeers[index].count += pendingStars.count } else { - topPeers.append(ReactionsMessageAttribute.TopPeer(peerId: pendingStars.accountPeerId, count: pendingStars.count, isTop: false, isMy: true, isAnonymous: pendingStars.isAnonymous)) + let isAnonymous: Bool + let topPeerId: PeerId? + switch pendingStars.privacy { + case .anonymous: + isAnonymous = true + topPeerId = pendingStars.accountPeerId + case .default: + isAnonymous = false + topPeerId = pendingStars.accountPeerId + case let .peer(peerId): + isAnonymous = false + topPeerId = peerId + } + + topPeers.append(ReactionsMessageAttribute.TopPeer(peerId: topPeerId, count: pendingStars.count, isTop: false, isMy: true, isAnonymous: isAnonymous)) } reactions.insert(MessageReaction(value: .stars, count: updatedCount, chosenOrder: -1), at: 0) return ReactionsMessageAttribute(canViewList: current?.canViewList ?? false, isTags: current?.isTags ?? isTags, reactions: reactions, recentPeers: result.recentPeers, topPeers: topPeers) } else { - return ReactionsMessageAttribute(canViewList: current?.canViewList ?? false, isTags: current?.isTags ?? isTags, reactions: [MessageReaction(value: .stars, count: pendingStars.count, chosenOrder: -1)], recentPeers: [], topPeers: [ReactionsMessageAttribute.TopPeer(peerId: pendingStars.accountPeerId, count: pendingStars.count, isTop: false, isMy: true, isAnonymous: pendingStars.isAnonymous)]) + let isAnonymous: Bool + let topPeerId: PeerId? + switch pendingStars.privacy { + case .anonymous: + isAnonymous = true + topPeerId = pendingStars.accountPeerId + case .default: + isAnonymous = false + topPeerId = pendingStars.accountPeerId + case let .peer(peerId): + isAnonymous = false + topPeerId = peerId + } + + return ReactionsMessageAttribute(canViewList: current?.canViewList ?? false, isTags: current?.isTags ?? isTags, reactions: [MessageReaction(value: .stars, count: pendingStars.count, chosenOrder: -1)], recentPeers: [], topPeers: [ReactionsMessageAttribute.TopPeer(peerId: topPeerId, count: pendingStars.count, isTop: false, isMy: true, isAnonymous: isAnonymous)]) } } else { return result diff --git a/submodules/TelegramCore/Sources/Network/Network.swift b/submodules/TelegramCore/Sources/Network/Network.swift index 5821411918..bf4031ff4e 100644 --- a/submodules/TelegramCore/Sources/Network/Network.swift +++ b/submodules/TelegramCore/Sources/Network/Network.swift @@ -435,13 +435,14 @@ public struct NetworkInitializationArguments { public let voipVersions: [CallSessionManagerImplementationVersion] public let appData: Signal public let externalRequestVerificationStream: Signal<[String: String], NoError> + public let externalRecaptchaRequestVerification: (String, String) -> Signal public let autolockDeadine: Signal public let encryptionProvider: EncryptionProvider public let deviceModelName:String? public let useBetaFeatures: Bool public let isICloudEnabled: Bool - public init(apiId: Int32, apiHash: String, languagesCategory: String, appVersion: String, voipMaxLayer: Int32, voipVersions: [CallSessionManagerImplementationVersion], appData: Signal, externalRequestVerificationStream: Signal<[String: String], NoError>, autolockDeadine: Signal, encryptionProvider: EncryptionProvider, deviceModelName: String?, useBetaFeatures: Bool, isICloudEnabled: Bool) { + public init(apiId: Int32, apiHash: String, languagesCategory: String, appVersion: String, voipMaxLayer: Int32, voipVersions: [CallSessionManagerImplementationVersion], appData: Signal, externalRequestVerificationStream: Signal<[String: String], NoError>, externalRecaptchaRequestVerification: @escaping (String, String) -> Signal, autolockDeadine: Signal, encryptionProvider: EncryptionProvider, deviceModelName: String?, useBetaFeatures: Bool, isICloudEnabled: Bool) { self.apiId = apiId self.apiHash = apiHash self.languagesCategory = languagesCategory @@ -450,6 +451,7 @@ public struct NetworkInitializationArguments { self.voipVersions = voipVersions self.appData = appData self.externalRequestVerificationStream = externalRequestVerificationStream + self.externalRecaptchaRequestVerification = externalRecaptchaRequestVerification self.autolockDeadine = autolockDeadine self.encryptionProvider = encryptionProvider self.deviceModelName = deviceModelName @@ -589,6 +591,22 @@ func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializa subscriber?.putCompletion() }) + return MTBlockDisposable(block: { + disposable.dispose() + }) + }) + }) + let externalRecaptchaRequestVerification = arguments.externalRecaptchaRequestVerification + context.setExternalRecaptchaRequestVerification({ method, siteKey in + return MTSignal(generator: { subscriber in + let disposable = (externalRecaptchaRequestVerification(method, siteKey) + |> filter { $0 != nil } + |> take(1) + |> timeout(15.0, queue: .mainQueue(), alternate: .single("RECAPTCHA_TIMEOUT"))).start(next: { token in + subscriber?.putNext(token) + subscriber?.putCompletion() + }) + return MTBlockDisposable(block: { disposable.dispose() }) diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 8bea175a4a..cd4d1e7e3c 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1803,8 +1803,34 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox: updatedState.updateStarsBalance(peerId: accountPeerId, balance: balance) case let .updateStarsRevenueStatus(peer, status): updatedState.updateStarsRevenueStatus(peerId: peer.peerId, status: StarsRevenueStats.Balances(apiStarsRevenueStatus: status)) - case let .updatePaidReactionPrivacy(isPrivate): - updatedState.updateStarsReactionsAreAnonymousByDefault(isAnonymous: isPrivate == .boolTrue) + case let .updatePaidReactionPrivacy(privacy): + let mappedPrivacy: TelegramPaidReactionPrivacy + switch privacy { + case .paidReactionPrivacyDefault: + mappedPrivacy = .default + case .paidReactionPrivacyAnonymous: + mappedPrivacy = .anonymous + case let .paidReactionPrivacyPeer(peer): + let peerId: PeerId + switch peer { + case let .inputPeerChannel(channelId, _): + peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)) + case let .inputPeerChannelFromMessage(_, _, channelId): + peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId)) + case let .inputPeerChat(chatId): + peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId)) + case .inputPeerEmpty: + peerId = accountPeerId + case .inputPeerSelf: + peerId = accountPeerId + case let .inputPeerUser(userId, _): + peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)) + case let .inputPeerUserFromMessage(_, _, userId): + peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)) + } + mappedPrivacy = .peer(peerId) + } + updatedState.updateStarsReactionsDefaultPrivacy(privacy: mappedPrivacy) default: break } @@ -3296,7 +3322,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation]) var currentAddQuickReplyMessages: OptimizeAddMessagesState? for operation in operations { switch operation { - case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder, .UpdateReadThread, .UpdateMessagesPinned, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateWallpaper, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsAreAnonymousByDefault, .ReportMessageDelivery: + case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder, .UpdateReadThread, .UpdateMessagesPinned, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateWallpaper, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsDefaultPrivacy, .ReportMessageDelivery: if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty { result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location)) } @@ -3434,7 +3460,7 @@ func replayFinalState( var updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:] var updatedStarsBalance: [PeerId: StarsAmount] = [:] var updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:] - var updatedStarsReactionsAreAnonymousByDefault: Bool? + var updatedStarsReactionsDefaultPrivacy: TelegramPaidReactionPrivacy? var reportMessageDelivery = Set() var holesFromPreviousStateMessageIds: [MessageId] = [] @@ -4868,8 +4894,8 @@ func replayFinalState( updatedStarsBalance[peerId] = StarsAmount(apiAmount: balance) case let .UpdateStarsRevenueStatus(peerId, status): updatedStarsRevenueStatus[peerId] = status - case let .UpdateStarsReactionsAreAnonymousByDefault(value): - updatedStarsReactionsAreAnonymousByDefault = value + case let .UpdateStarsReactionsDefaultPrivacy(value): + updatedStarsReactionsDefaultPrivacy = value case let .ReportMessageDelivery(messageIds): reportMessageDelivery = Set(messageIds) } @@ -5366,8 +5392,8 @@ func replayFinalState( } } - if let updatedStarsReactionsAreAnonymousByDefault { - _internal_setStarsReactionDefaultToPrivate(isPrivate: updatedStarsReactionsAreAnonymousByDefault, transaction: transaction) + if let updatedStarsReactionsDefaultPrivacy { + _internal_setStarsReactionDefaultPrivacy(privacy: updatedStarsReactionsDefaultPrivacy, transaction: transaction) } return AccountReplayedFinalState( diff --git a/submodules/TelegramCore/Sources/State/CallSessionManager.swift b/submodules/TelegramCore/Sources/State/CallSessionManager.swift index c21584858e..51d4f5a6dc 100644 --- a/submodules/TelegramCore/Sources/State/CallSessionManager.swift +++ b/submodules/TelegramCore/Sources/State/CallSessionManager.swift @@ -137,6 +137,7 @@ public struct CallSessionRingingState: Equatable { public let peerId: PeerId public let isVideo: Bool public let isVideoPossible: Bool + public let isConference: Bool } public enum DropCallReason { @@ -334,6 +335,7 @@ private func parseConnectionSet(primary: Api.PhoneConnection, alternative: [Api. private final class CallSessionContext { let peerId: PeerId let isOutgoing: Bool + let isConference: Bool var type: CallSession.CallType var isVideoPossible: Bool let pendingConference: (conference: GroupCallReference, encryptionKey: Data)? @@ -353,9 +355,10 @@ private final class CallSessionContext { } } - init(peerId: PeerId, isOutgoing: Bool, type: CallSession.CallType, isVideoPossible: Bool, pendingConference: (conference: GroupCallReference, encryptionKey: Data)?, state: CallSessionInternalState) { + init(peerId: PeerId, isOutgoing: Bool, isConference: Bool, type: CallSession.CallType, isVideoPossible: Bool, pendingConference: (conference: GroupCallReference, encryptionKey: Data)?, state: CallSessionInternalState) { self.peerId = peerId self.isOutgoing = isOutgoing + self.isConference = isConference self.type = type self.isVideoPossible = isVideoPossible self.pendingConference = pendingConference @@ -547,7 +550,13 @@ private final class CallSessionManagerContext { var ringingContexts: [CallSessionRingingState] = [] for (id, context) in self.contexts { if case .ringing = context.state { - ringingContexts.append(CallSessionRingingState(id: id, peerId: context.peerId, isVideo: context.type == .video, isVideoPossible: context.isVideoPossible)) + ringingContexts.append(CallSessionRingingState( + id: id, + peerId: context.peerId, + isVideo: context.type == .video, + isVideoPossible: context.isVideoPossible, + isConference: context.isConference + )) } } return ringingContexts @@ -590,7 +599,7 @@ private final class CallSessionManagerContext { //#endif let internalId = CallSessionManager.getStableIncomingUUID(stableId: stableId) - let context = CallSessionContext(peerId: peerId, isOutgoing: false, type: isVideo ? .video : .audio, isVideoPossible: isVideoPossible, pendingConference: nil, state: .ringing(id: stableId, accessHash: accessHash, gAHash: gAHash, b: b, versions: versions, conferenceCall: conferenceCall)) + let context = CallSessionContext(peerId: peerId, isOutgoing: false, isConference: conferenceCall != nil, type: isVideo ? .video : .audio, isVideoPossible: isVideoPossible, pendingConference: nil, state: .ringing(id: stableId, accessHash: accessHash, gAHash: gAHash, b: b, versions: versions, conferenceCall: conferenceCall)) self.contexts[internalId] = context let queue = self.queue @@ -1164,7 +1173,7 @@ private final class CallSessionManagerContext { let randomStatus = SecRandomCopyBytes(nil, 256, aBytes.assumingMemoryBound(to: UInt8.self)) let a = Data(bytesNoCopy: aBytes, count: 256, deallocator: .free) if randomStatus == 0 { - self.contexts[internalId] = CallSessionContext(peerId: peerId, isOutgoing: true, type: isVideo ? .video : .audio, isVideoPossible: enableVideo || isVideo, pendingConference: conferenceCall, state: .requesting(a: a, conferenceCall: conferenceCall?.conference, disposable: (requestCallSession(postbox: self.postbox, network: self.network, peerId: peerId, a: a, maxLayer: self.maxLayer, versions: self.filteredVersions(enableVideo: true), isVideo: isVideo, conferenceCall: conferenceCall?.conference) |> deliverOn(queue)).start(next: { [weak self] result in + self.contexts[internalId] = CallSessionContext(peerId: peerId, isOutgoing: true, isConference: conferenceCall != nil, type: isVideo ? .video : .audio, isVideoPossible: enableVideo || isVideo, pendingConference: conferenceCall, state: .requesting(a: a, conferenceCall: conferenceCall?.conference, disposable: (requestCallSession(postbox: self.postbox, network: self.network, peerId: peerId, a: a, maxLayer: self.maxLayer, versions: self.filteredVersions(enableVideo: true), isVideo: isVideo, conferenceCall: conferenceCall?.conference) |> deliverOn(queue)).start(next: { [weak self] result in if let strongSelf = self, let context = strongSelf.contexts[internalId] { if case .requesting = context.state { switch result { diff --git a/submodules/TelegramCore/Sources/State/MessageReactions.swift b/submodules/TelegramCore/Sources/State/MessageReactions.swift index 37f01b1c83..b7c7e96849 100644 --- a/submodules/TelegramCore/Sources/State/MessageReactions.swift +++ b/submodules/TelegramCore/Sources/State/MessageReactions.swift @@ -172,10 +172,10 @@ public func updateMessageReactionsInteractively(account: Account, messageIds: [M |> ignoreValues } -func _internal_sendStarsReactionsInteractively(account: Account, messageId: MessageId, count: Int, isAnonymous: Bool?) -> Signal { - return account.postbox.transaction { transaction -> Bool in +func _internal_sendStarsReactionsInteractively(account: Account, messageId: MessageId, count: Int, privacy: TelegramPaidReactionPrivacy?) -> Signal { + return account.postbox.transaction { transaction -> TelegramPaidReactionPrivacy in transaction.setPendingMessageAction(type: .sendStarsReaction, id: messageId, action: SendStarsReactionsAction(randomId: Int64.random(in: Int64.min ... Int64.max))) - var resolvedIsAnonymousValue = false + var resolvedPrivacyValue: TelegramPaidReactionPrivacy = .default transaction.updateMessage(messageId, update: { currentMessage in var storeForwardInfo: StoreMessageForwardInfo? if let forwardInfo = currentMessage.forwardInfo { @@ -183,36 +183,36 @@ func _internal_sendStarsReactionsInteractively(account: Account, messageId: Mess } var mappedCount = Int32(count) var attributes = currentMessage.attributes - var resolvedIsAnonymous = _internal_getStarsReactionDefaultToPrivate(transaction: transaction) + var resolvedPrivacy = _internal_getStarsReactionDefaultPrivacy(transaction: transaction) for attribute in attributes { if let attribute = attribute as? ReactionsMessageAttribute { if let myReaction = attribute.topPeers.first(where: { $0.isMy }) { - resolvedIsAnonymous = myReaction.isAnonymous + resolvedPrivacy = myReaction.isAnonymous ? .anonymous : .default } } } loop: for j in 0 ..< attributes.count { if let current = attributes[j] as? PendingStarsReactionsMessageAttribute { mappedCount += current.count - resolvedIsAnonymous = current.isAnonymous + resolvedPrivacy = current.privacy attributes.remove(at: j) break loop } } - if let isAnonymous { - resolvedIsAnonymous = isAnonymous - _internal_setStarsReactionDefaultToPrivate(isPrivate: isAnonymous, transaction: transaction) + if let privacy { + resolvedPrivacy = privacy + _internal_setStarsReactionDefaultPrivacy(privacy: privacy, transaction: transaction) } - attributes.append(PendingStarsReactionsMessageAttribute(accountPeerId: account.peerId, count: mappedCount, isAnonymous: resolvedIsAnonymous)) + attributes.append(PendingStarsReactionsMessageAttribute(accountPeerId: account.peerId, count: mappedCount, privacy: resolvedPrivacy)) - resolvedIsAnonymousValue = resolvedIsAnonymous + resolvedPrivacyValue = resolvedPrivacy return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) }) - return resolvedIsAnonymousValue + return resolvedPrivacyValue } } @@ -244,9 +244,9 @@ func _internal_forceSendPendingSendStarsReaction(account: Account, messageId: Me return .complete() } -func _internal_updateStarsReactionIsAnonymous(account: Account, messageId: MessageId, isAnonymous: Bool) -> Signal { - return account.postbox.transaction { transaction -> Api.InputPeer? in - _internal_setStarsReactionDefaultToPrivate(isPrivate: isAnonymous, transaction: transaction) +func _internal_updateStarsReactionPrivacy(account: Account, messageId: MessageId, privacy: TelegramPaidReactionPrivacy) -> Signal { + return account.postbox.transaction { transaction -> (Api.InputPeer?, Api.InputPeer?) in + _internal_setStarsReactionDefaultPrivacy(privacy: privacy, transaction: transaction) transaction.updateMessage(messageId, update: { currentMessage in var storeForwardInfo: StoreMessageForwardInfo? @@ -258,7 +258,17 @@ func _internal_updateStarsReactionIsAnonymous(account: Account, messageId: Messa if let attribute = attributes[j] as? ReactionsMessageAttribute { var updatedTopPeers = attribute.topPeers if let index = updatedTopPeers.firstIndex(where: { $0.isMy }) { - updatedTopPeers[index].isAnonymous = isAnonymous + switch privacy { + case .anonymous: + updatedTopPeers[index].isAnonymous = true + updatedTopPeers[index].peerId = nil + case .default: + updatedTopPeers[index].isAnonymous = false + updatedTopPeers[index].peerId = account.peerId + case let .peer(peerId): + updatedTopPeers[index].isAnonymous = false + updatedTopPeers[index].peerId = peerId + } } attributes[j] = ReactionsMessageAttribute(canViewList: attribute.canViewList, isTags: attribute.isTags, reactions: attribute.reactions, recentPeers: attribute.recentPeers, topPeers: updatedTopPeers) } @@ -266,14 +276,35 @@ func _internal_updateStarsReactionIsAnonymous(account: Account, messageId: Messa return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) }) - return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer) + var privacyPeerId: PeerId? + if case let .peer(peerId) = privacy { + privacyPeerId = peerId + } + + return ( + transaction.getPeer(messageId.peerId).flatMap(apiInputPeer), + privacyPeerId.flatMap { privacyPeerId in transaction.getPeer(privacyPeerId).flatMap(apiInputPeer) } + ) } - |> mapToSignal { inputPeer -> Signal in + |> mapToSignal { inputPeer, inputPrivacyPeer -> Signal in guard let inputPeer else { return .complete() } - return account.network.request(Api.functions.messages.togglePaidReactionPrivacy(peer: inputPeer, msgId: messageId.id, private: isAnonymous ? .boolTrue : .boolFalse)) + let mappedPrivacy: Api.PaidReactionPrivacy + switch privacy { + case .anonymous: + mappedPrivacy = .paidReactionPrivacyAnonymous + case .default: + mappedPrivacy = .paidReactionPrivacyDefault + case .peer: + guard let inputPrivacyPeer else { + return .complete() + } + mappedPrivacy = .paidReactionPrivacyPeer(peer: inputPrivacyPeer) + } + + return account.network.request(Api.functions.messages.togglePaidReactionPrivacy(peer: inputPeer, msgId: messageId.id, private: mappedPrivacy)) |> `catch` { _ -> Signal in return .single(.boolFalse) } @@ -369,7 +400,7 @@ private func requestUpdateMessageReaction(postbox: Postbox, network: Network, st } private func requestSendStarsReaction(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId) -> Signal { - return postbox.transaction { transaction -> (Peer, Int32, Bool)? in + return postbox.transaction { transaction -> (Peer, Int32, Api.PaidReactionPrivacy)? in guard let peer = transaction.getPeer(messageId.peerId) else { return nil } @@ -377,19 +408,32 @@ private func requestSendStarsReaction(postbox: Postbox, network: Network, stateM return nil } var count: Int32 = 0 - var isAnonymous = false + var privacy: Api.PaidReactionPrivacy = .paidReactionPrivacyDefault for attribute in message.attributes { if let attribute = attribute as? PendingStarsReactionsMessageAttribute { count += attribute.count - isAnonymous = attribute.isAnonymous + + let mappedPrivacy: Api.PaidReactionPrivacy + switch attribute.privacy { + case .anonymous: + mappedPrivacy = .paidReactionPrivacyAnonymous + case .default: + mappedPrivacy = .paidReactionPrivacyDefault + case let .peer(peerId): + guard let inputPrivacyPeer = transaction.getPeer(peerId).flatMap(apiInputPeer) else { + return nil + } + mappedPrivacy = .paidReactionPrivacyPeer(peer: inputPrivacyPeer) + } + privacy = mappedPrivacy break } } - return (peer, count, isAnonymous) + return (peer, count, privacy) } |> castError(RequestUpdateMessageReactionError.self) |> mapToSignal { peerAndValue in - guard let (peer, count, isAnonymous) = peerAndValue else { + guard let (peer, count, privacy) = peerAndValue else { return .fail(.generic) } guard let inputPeer = apiInputPeer(peer) else { @@ -407,7 +451,7 @@ private func requestSendStarsReaction(postbox: Postbox, network: Network, stateM var flags: Int32 = 0 flags |= 1 << 0 - let signal: Signal = network.request(Api.functions.messages.sendPaidReaction(flags: flags, peer: inputPeer, msgId: messageId.id, count: count, randomId: Int64(bitPattern: randomId), private: isAnonymous ? .boolTrue : .boolFalse)) + let signal: Signal = network.request(Api.functions.messages.sendPaidReaction(flags: flags, peer: inputPeer, msgId: messageId.id, count: count, randomId: Int64(bitPattern: randomId), private: privacy)) |> mapError { _ -> RequestUpdateMessageReactionError in return .generic } @@ -1031,10 +1075,29 @@ func _internal_updateDefaultReaction(account: Account, reaction: MessageReaction } struct StarsReactionDefaultToPrivateData: Codable { - var isPrivate: Bool + private enum CodingKeys: String, CodingKey { + case isPrivate = "isPrivate" + case privacy = "p" + } - init(isPrivate: Bool) { - self.isPrivate = isPrivate + var privacy: TelegramPaidReactionPrivacy + + init(privacy: TelegramPaidReactionPrivacy) { + self.privacy = privacy + } + + init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if let privacy = try container.decodeIfPresent(TelegramPaidReactionPrivacy.self, forKey: .privacy) { + self.privacy = privacy + } else { + self.privacy = try container.decode(Bool.self, forKey: .isPrivate) ? .anonymous : .default + } + } + + func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(self.privacy, forKey: .privacy) } static func key() -> ValueBoxKey { @@ -1044,15 +1107,15 @@ struct StarsReactionDefaultToPrivateData: Codable { } } -func _internal_getStarsReactionDefaultToPrivate(transaction: Transaction) -> Bool { +func _internal_getStarsReactionDefaultPrivacy(transaction: Transaction) -> TelegramPaidReactionPrivacy { guard let value = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.starsReactionDefaultToPrivate, key: StarsReactionDefaultToPrivateData.key()))?.get(StarsReactionDefaultToPrivateData.self) else { - return false + return .default } - return value.isPrivate + return value.privacy } -func _internal_setStarsReactionDefaultToPrivate(isPrivate: Bool, transaction: Transaction) { - guard let entry = CodableEntry(StarsReactionDefaultToPrivateData(isPrivate: isPrivate)) else { +func _internal_setStarsReactionDefaultPrivacy(privacy: TelegramPaidReactionPrivacy, transaction: Transaction) { + guard let entry = CodableEntry(StarsReactionDefaultToPrivateData(privacy: privacy)) else { return } transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.starsReactionDefaultToPrivate, key: StarsReactionDefaultToPrivateData.key()), entry: entry) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift index 5b0fa01ee0..a836eb71f1 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift @@ -565,7 +565,7 @@ public final class PendingReactionsMessageAttribute: MessageAttribute { public final class PendingStarsReactionsMessageAttribute: MessageAttribute { public let accountPeerId: PeerId? public let count: Int32 - public let isAnonymous: Bool + public let privacy: TelegramPaidReactionPrivacy public var associatedPeerIds: [PeerId] { var peerIds: [PeerId] = [] @@ -575,16 +575,21 @@ public final class PendingStarsReactionsMessageAttribute: MessageAttribute { return peerIds } - public init(accountPeerId: PeerId?, count: Int32, isAnonymous: Bool) { + public init(accountPeerId: PeerId?, count: Int32, privacy: TelegramPaidReactionPrivacy) { self.accountPeerId = accountPeerId self.count = count - self.isAnonymous = isAnonymous + self.privacy = privacy } required public init(decoder: PostboxDecoder) { self.accountPeerId = decoder.decodeOptionalInt64ForKey("ap").flatMap(PeerId.init) self.count = decoder.decodeInt32ForKey("cnt", orElse: 1) - self.isAnonymous = decoder.decodeBoolForKey("anon", orElse: false) + + if let privacy = decoder.decode(TelegramPaidReactionPrivacy.self, forKey: "priv") { + self.privacy = privacy + } else { + self.privacy = decoder.decodeBoolForKey("anon", orElse: false) ? .anonymous : .default + } } public func encode(_ encoder: PostboxEncoder) { @@ -594,6 +599,6 @@ public final class PendingStarsReactionsMessageAttribute: MessageAttribute { encoder.encodeNil(forKey: "ap") } encoder.encodeInt32(self.count, forKey: "cnt") - encoder.encodeBool(self.isAnonymous, forKey: "anon") + encoder.encodeCodable(self.privacy, forKey: "priv") } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift index 2a7532b66b..2a096a11a8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/PeersData.swift @@ -2279,8 +2279,8 @@ public extension TelegramEngine.EngineData.Item { } } - public struct StarsReactionDefaultToPrivate: TelegramEngineDataItem, PostboxViewDataItem { - public typealias Result = Bool + public struct StarsReactionDefaultPrivacy: TelegramEngineDataItem, PostboxViewDataItem { + public typealias Result = TelegramPaidReactionPrivacy public init() { } @@ -2291,9 +2291,9 @@ public extension TelegramEngine.EngineData.Item { func extract(view: PostboxView) -> Result { if let value = (view as? CachedItemView)?.value?.get(StarsReactionDefaultToPrivateData.self) { - return value.isPrivate + return value.privacy } else { - return false + return .default } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index 83d0119ae9..d06770b90d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -337,8 +337,8 @@ public extension TelegramEngine { ).startStandalone() } - public func sendStarsReaction(id: EngineMessage.Id, count: Int, isAnonymous: Bool?) -> Signal { - return _internal_sendStarsReactionsInteractively(account: self.account, messageId: id, count: count, isAnonymous: isAnonymous) + public func sendStarsReaction(id: EngineMessage.Id, count: Int, privacy: TelegramPaidReactionPrivacy?) -> Signal { + return _internal_sendStarsReactionsInteractively(account: self.account, messageId: id, count: count, privacy: privacy) } public func cancelPendingSendStarsReaction(id: EngineMessage.Id) { @@ -349,8 +349,8 @@ public extension TelegramEngine { let _ = _internal_forceSendPendingSendStarsReaction(account: self.account, messageId: id).startStandalone() } - public func updateStarsReactionIsAnonymous(id: EngineMessage.Id, isAnonymous: Bool) -> Signal { - return _internal_updateStarsReactionIsAnonymous(account: self.account, messageId: id, isAnonymous: isAnonymous) + public func updateStarsReactionPrivacy(id: EngineMessage.Id, privacy: TelegramPaidReactionPrivacy) -> Signal { + return _internal_updateStarsReactionPrivacy(account: self.account, messageId: id, privacy: privacy) } public func requestChatContextResults(botId: PeerId, peerId: PeerId, query: String, location: Signal<(Double, Double)?, NoError> = .single(nil), offset: String, incompleteResults: Bool = false, staleCachedResults: Bool = false) -> Signal { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index c651e178c0..7839b38918 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -95,6 +95,42 @@ public final class TelegramResolvedMessageLink { } } +public enum TelegramPaidReactionPrivacy: Equatable, Codable { + case `default` + case anonymous + case peer(PeerId) + + enum CodingKeys: String, CodingKey { + case `default` = "d" + case anonymous = "a" + case peer = "p" + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if try container.decodeNil(forKey: .default) { + self = .default + } else if try container.decodeNil(forKey: .anonymous) { + self = .anonymous + } else { + let peerId = PeerId(try container.decode(Int64.self, forKey: .peer)) + self = .peer(peerId) + } + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + switch self { + case .default: + try container.encodeNil(forKey: .default) + case .anonymous: + try container.encodeNil(forKey: .anonymous) + case let .peer(peerId): + try container.encode(peerId.toInt64(), forKey: .peer) + } + } +} + public extension TelegramEngine { enum NextUnreadChannelLocation: Equatable { case same @@ -1650,9 +1686,9 @@ public extension TelegramEngine { } } - public func setStarsReactionDefaultToPrivate(isPrivate: Bool) { + public func setStarsReactionDefaultPrivacy(privacy: TelegramPaidReactionPrivacy) { let _ = self.account.postbox.transaction({ transaction in - _internal_setStarsReactionDefaultToPrivate(isPrivate: isPrivate, transaction: transaction) + _internal_setStarsReactionDefaultPrivacy(privacy: privacy, transaction: transaction) }).startStandalone() } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 0e39803e1e..f9c6afdd7d 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -463,6 +463,7 @@ swift_library( "//submodules/TelegramUI/Components/Gifts/GiftOptionsScreen", "//submodules/TelegramUI/Components/ContentReportScreen", "//submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen", + "//third-party/recaptcha:RecaptchaEnterprise", ] + select({ "@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets, "//build-system:ios_sim_arm64": [], diff --git a/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/ConferenceButtonView.swift b/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/ConferenceButtonView.swift index c04926106a..3430c7ea91 100644 --- a/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/ConferenceButtonView.swift +++ b/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/ConferenceButtonView.swift @@ -91,7 +91,7 @@ final class ConferenceButtonView: HighlightTrackingButton, OverlayMaskContainerV transition.setFrame(view: self.backdropBackgroundView, frame: CGRect(origin: CGPoint(), size: params.size)) if self.iconView.image == nil { - self.iconView.image = UIImage(bundleImageName: "Contact List/AddMemberIcon")?.withRenderingMode(.alwaysTemplate) + self.iconView.image = UIImage(bundleImageName: "Call/CallNavigationAddPerson")?.withRenderingMode(.alwaysTemplate) self.iconView.tintColor = .white } diff --git a/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/EmojiTooltipView.swift b/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/EmojiTooltipView.swift index efb0bdd5d6..17aae06536 100644 --- a/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/EmojiTooltipView.swift +++ b/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/EmojiTooltipView.swift @@ -67,7 +67,7 @@ final class EmojiTooltipView: OverlayMaskContainerView { } func animateIn() { - let anchorPoint = CGPoint(x: self.bounds.width - 46.0, y: 0.0) + let anchorPoint = CGPoint(x: self.bounds.width * 0.5, y: 0.0) self.layer.animateSpring(from: 0.001 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5) self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) @@ -75,7 +75,7 @@ final class EmojiTooltipView: OverlayMaskContainerView { } func animateOut(completion: @escaping () -> Void) { - let anchorPoint = CGPoint(x: self.bounds.width - 46.0, y: 0.0) + let anchorPoint = CGPoint(x: self.bounds.width * 0.5, y: 0.0) self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in completion() }) @@ -126,7 +126,7 @@ final class EmojiTooltipView: OverlayMaskContainerView { addRoundedRectPath(context: context, rect: CGRect(origin: CGPoint(x: 0.0, y: arrowHeight), size: CGSize(width: size.width, height: size.height - arrowHeight)), radius: 14.0) context.fillPath() - context.translateBy(x: size.width - floor(params.subjectWidth * 0.5) - 20.0, y: 0.0) + context.translateBy(x: size.width * 0.5 - 10.0, y: 0.0) let _ = try? drawSvgPath(context, path: "M9.0981,1.1979 C9.547,0.6431 10.453,0.6431 10.9019,1.1979 C12.4041,3.0542 15.6848,6.5616 20,8 H-0.0002 C4.3151,6.5616 7.5959,3.0542 9.0981,1.1978 Z ") }) self.backgroundView.frame = CGRect(origin: CGPoint(), size: size) diff --git a/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/KeyEmojiView.swift b/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/KeyEmojiView.swift index 557c56a4d1..21814cde23 100644 --- a/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/KeyEmojiView.swift +++ b/submodules/TelegramUI/Components/Calls/CallScreen/Sources/Components/KeyEmojiView.swift @@ -93,7 +93,7 @@ final class KeyEmojiView: HighlightTrackingButton { for i in 0 ..< self.emojiViews.count { let emojiView = self.emojiViews[i] emojiView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) - emojiView.layer.animatePosition(from: CGPoint(x: -CGFloat(self.emojiViews.count - 1 - i) * 30.0, y: 0.0), to: CGPoint(), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + emojiView.layer.animatePosition(from: CGPoint(x: CGFloat(i) * 30.0, y: 0.0), to: CGPoint(), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, additive: true) } } @@ -109,7 +109,7 @@ final class KeyEmojiView: HighlightTrackingButton { } private func update(params: Params, transition: ComponentTransition) -> CGSize { - let itemSpacing: CGFloat = 3.0 + let itemSpacing: CGFloat = 1.0 var height: CGFloat = 0.0 var nextX = 0.0 diff --git a/submodules/TelegramUI/Components/Calls/CallScreen/Sources/PrivateCallScreen.swift b/submodules/TelegramUI/Components/Calls/CallScreen/Sources/PrivateCallScreen.swift index caa0d4c1e9..b9ff915b87 100644 --- a/submodules/TelegramUI/Components/Calls/CallScreen/Sources/PrivateCallScreen.swift +++ b/submodules/TelegramUI/Components/Calls/CallScreen/Sources/PrivateCallScreen.swift @@ -610,7 +610,7 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu if self.hideEmojiTooltipTimer == nil && !self.areControlsHidden { self.displayEmojiTooltip = true - self.hideEmojiTooltipTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 3.0, repeats: false, block: { [weak self] _ in + self.hideEmojiTooltipTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false, block: { [weak self] _ in guard let self else { return } @@ -962,126 +962,6 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu } } - if !isConferencePossible, case let .active(activeState) = params.state.lifecycleState { - let emojiView: KeyEmojiView - var emojiTransition = transition - var emojiAlphaTransition = genericAlphaTransition - if let current = self.emojiView { - emojiView = current - } else { - emojiTransition = transition.withAnimation(.none) - emojiAlphaTransition = genericAlphaTransition.withAnimation(.none) - emojiView = KeyEmojiView(emoji: activeState.emojiKey) - self.emojiView = emojiView - emojiView.pressAction = { [weak self] in - guard let self else { - return - } - if !self.isEmojiKeyExpanded { - self.isEmojiKeyExpanded = true - self.displayEmojiTooltip = false - self.update(transition: .spring(duration: 0.4)) - } - } - } - if emojiView.superview == nil { - self.addSubview(emojiView) - if !transition.animation.isImmediate { - emojiView.animateIn() - } - } - emojiView.isUserInteractionEnabled = !self.isEmojiKeyExpanded - - let emojiViewWasExpanded = emojiView.isExpanded - let emojiViewSize = emojiView.update(isExpanded: self.isEmojiKeyExpanded, transition: emojiTransition) - - if self.isEmojiKeyExpanded { - let emojiViewFrame = CGRect(origin: CGPoint(x: floor((params.size.width - emojiViewSize.width) * 0.5), y: params.insets.top + 93.0), size: emojiViewSize) - - if case let .curve(duration, curve) = transition.animation, let emojiViewWasExpanded, !emojiViewWasExpanded { - let distance = CGPoint(x: emojiViewFrame.midX - emojiView.center.x, y: emojiViewFrame.midY - emojiView.center.y) - let positionKeyframes = generateParabollicMotionKeyframes(from: emojiView.center, to: emojiViewFrame.center, elevation: -distance.y * 0.8, duration: duration, curve: curve, reverse: false) - emojiView.center = emojiViewFrame.center - emojiView.layer.animateKeyframes(values: positionKeyframes.map { NSValue(cgPoint: $0) }, duration: duration, keyPath: "position", additive: false) - } else { - emojiTransition.setPosition(view: emojiView, position: emojiViewFrame.center) - } - emojiTransition.setBounds(view: emojiView, bounds: CGRect(origin: CGPoint(), size: emojiViewFrame.size)) - if self.isAnimatedOutToGroupCall { - emojiAlphaTransition.setAlpha(view: emojiView, alpha: (currentAreControlsHidden || self.isAnimatedOutToGroupCall) ? 0.0 : 1.0) - } - - if let emojiTooltipView = self.emojiTooltipView { - self.emojiTooltipView = nil - emojiTooltipView.animateOut(completion: { [weak emojiTooltipView] in - emojiTooltipView?.removeFromSuperview() - }) - } - } else { - let emojiY: CGFloat - if currentAreControlsHidden { - emojiY = -8.0 - emojiViewSize.height - } else { - emojiY = params.insets.top + 12.0 - } - let emojiViewFrame = CGRect(origin: CGPoint(x: params.size.width - params.insets.right - 12.0 - emojiViewSize.width, y: emojiY), size: emojiViewSize) - - if case let .curve(duration, curve) = transition.animation, let emojiViewWasExpanded, emojiViewWasExpanded { - let distance = CGPoint(x: emojiViewFrame.midX - emojiView.center.x, y: emojiViewFrame.midY - emojiView.center.y) - let positionKeyframes = generateParabollicMotionKeyframes(from: emojiViewFrame.center, to: emojiView.center, elevation: distance.y * 0.8, duration: duration, curve: curve, reverse: true) - emojiView.center = emojiViewFrame.center - emojiView.layer.animateKeyframes(values: positionKeyframes.map { NSValue(cgPoint: $0) }, duration: duration, keyPath: "position", additive: false) - } else { - emojiTransition.setPosition(view: emojiView, position: emojiViewFrame.center) - } - emojiTransition.setBounds(view: emojiView, bounds: CGRect(origin: CGPoint(), size: emojiViewFrame.size)) - emojiAlphaTransition.setAlpha(view: emojiView, alpha: (currentAreControlsHidden || self.isAnimatedOutToGroupCall) ? 0.0 : 1.0) - - if self.displayEmojiTooltip { - let emojiTooltipView: EmojiTooltipView - var emojiTooltipTransition = transition - var animateIn = false - if let current = self.emojiTooltipView { - emojiTooltipView = current - } else { - emojiTooltipTransition = emojiTooltipTransition.withAnimation(.none) - emojiTooltipView = EmojiTooltipView(text: params.state.strings.Call_EncryptionKeyTooltip) - animateIn = true - self.emojiTooltipView = emojiTooltipView - self.addSubview(emojiTooltipView) - } - - let emojiTooltipSize = emojiTooltipView.update(constrainedWidth: params.size.width - 32.0 * 2.0, subjectWidth: emojiViewSize.width - 20.0) - let emojiTooltipFrame = CGRect(origin: CGPoint(x: emojiViewFrame.maxX - emojiTooltipSize.width, y: emojiViewFrame.maxY + 8.0), size: emojiTooltipSize) - emojiTooltipTransition.setFrame(view: emojiTooltipView, frame: emojiTooltipFrame) - - if animateIn && !transition.animation.isImmediate { - emojiTooltipView.animateIn() - } - } else if let emojiTooltipView = self.emojiTooltipView { - self.emojiTooltipView = nil - emojiTooltipView.animateOut(completion: { [weak emojiTooltipView] in - emojiTooltipView?.removeFromSuperview() - }) - } - } - - emojiAlphaTransition.setAlpha(view: emojiView, alpha: 1.0) - } else { - if let emojiView = self.emojiView { - self.emojiView = nil - genericAlphaTransition.setAlpha(view: emojiView, alpha: 0.0, completion: { [weak emojiView] _ in - emojiView?.removeFromSuperview() - }) - } - if let emojiTooltipView = self.emojiTooltipView { - self.emojiTooltipView = nil - emojiTooltipView.animateOut(completion: { [weak emojiTooltipView] in - emojiTooltipView?.removeFromSuperview() - }) - } - } - let collapsedAvatarSize: CGFloat = 136.0 let blobSize: CGFloat = collapsedAvatarSize + 40.0 @@ -1435,9 +1315,91 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu transition.setFrame(view: self.titleView, frame: titleFrame) genericAlphaTransition.setAlpha(view: self.titleView, alpha: (currentAreControlsHidden || self.isAnimatedOutToGroupCall) ? 0.0 : 1.0) + var emojiViewSizeValue: CGSize? + var emojiTransition = transition + var emojiAlphaTransition = genericAlphaTransition + let emojiViewWasExpanded = self.emojiView?.isExpanded ?? false + if case let .active(activeState) = params.state.lifecycleState { + let emojiView: KeyEmojiView + if let current = self.emojiView { + emojiView = current + } else { + emojiTransition = transition.withAnimation(.none) + emojiAlphaTransition = genericAlphaTransition.withAnimation(.none) + emojiView = KeyEmojiView(emoji: activeState.emojiKey) + self.emojiView = emojiView + emojiView.pressAction = { [weak self] in + guard let self else { + return + } + if !self.isEmojiKeyExpanded { + self.isEmojiKeyExpanded = true + self.displayEmojiTooltip = false + self.update(transition: .spring(duration: 0.4)) + } + } + } + if emojiView.superview == nil { + self.addSubview(emojiView) + if !transition.animation.isImmediate { + emojiView.animateIn() + } + } + emojiView.isUserInteractionEnabled = !self.isEmojiKeyExpanded + + let emojiViewSize = emojiView.update(isExpanded: self.isEmojiKeyExpanded, transition: emojiTransition) + emojiViewSizeValue = emojiViewSize + + if self.isEmojiKeyExpanded { + let emojiViewFrame = CGRect(origin: CGPoint(x: floor((params.size.width - emojiViewSize.width) * 0.5), y: params.insets.top + 93.0), size: emojiViewSize) + + if case let .curve(duration, curve) = transition.animation, !emojiViewWasExpanded { + let distance = CGPoint(x: emojiViewFrame.midX - emojiView.center.x, y: emojiViewFrame.midY - emojiView.center.y) + let positionKeyframes = generateParabollicMotionKeyframes(from: emojiView.center, to: emojiViewFrame.center, elevation: -distance.y * 0.8, duration: duration, curve: curve, reverse: false) + emojiView.center = emojiViewFrame.center + emojiView.layer.animateKeyframes(values: positionKeyframes.map { NSValue(cgPoint: $0) }, duration: duration, keyPath: "position", additive: false) + } else { + emojiTransition.setPosition(view: emojiView, position: emojiViewFrame.center) + } + emojiTransition.setBounds(view: emojiView, bounds: CGRect(origin: CGPoint(), size: emojiViewFrame.size)) + if self.isAnimatedOutToGroupCall { + emojiAlphaTransition.setAlpha(view: emojiView, alpha: (currentAreControlsHidden || self.isAnimatedOutToGroupCall) ? 0.0 : 1.0) + } + + if let emojiTooltipView = self.emojiTooltipView { + self.emojiTooltipView = nil + emojiTooltipView.animateOut(completion: { [weak emojiTooltipView] in + emojiTooltipView?.removeFromSuperview() + }) + } + } else { + // Inline mode handled after calculating status frame + } + + emojiAlphaTransition.setAlpha(view: emojiView, alpha: 1.0) + } else { + if let emojiView = self.emojiView { + self.emojiView = nil + genericAlphaTransition.setAlpha(view: emojiView, alpha: 0.0, completion: { [weak emojiView] _ in + emojiView?.removeFromSuperview() + }) + } + if let emojiTooltipView = self.emojiTooltipView { + self.emojiTooltipView = nil + emojiTooltipView.animateOut(completion: { [weak emojiTooltipView] in + emojiTooltipView?.removeFromSuperview() + }) + } + } + + var statusEmojiWidth: CGFloat = 0.0 + let statusEmojiSpacing: CGFloat = 8.0 + if !self.isEmojiKeyExpanded, let emojiViewSize = emojiViewSizeValue { + statusEmojiWidth = statusEmojiSpacing + emojiViewSize.width + } let statusFrame = CGRect( origin: CGPoint( - x: (params.size.width - statusSize.width) * 0.5, + x: (params.size.width - statusSize.width - statusEmojiWidth) * 0.5, y: titleFrame.maxY + (havePrimaryVideo ? 0.0 : 4.0) ), size: statusSize @@ -1455,6 +1417,51 @@ public final class PrivateCallScreen: OverlayMaskContainerView, AVPictureInPictu genericAlphaTransition.setAlpha(view: self.statusView, alpha: (currentAreControlsHidden || self.isAnimatedOutToGroupCall) ? 0.0 : 1.0) } + if case .active = params.state.lifecycleState { + if let emojiView = self.emojiView, !self.isEmojiKeyExpanded, let emojiViewSize = emojiViewSizeValue { + let emojiViewFrame = CGRect(origin: CGPoint(x: statusFrame.maxX + statusEmojiSpacing, y: statusFrame.minY + floorToScreenPixels((statusFrame.height - emojiViewSize.height) * 0.5)), size: emojiViewSize) + + if case let .curve(duration, curve) = transition.animation, emojiViewWasExpanded { + let distance = CGPoint(x: emojiViewFrame.midX - emojiView.center.x, y: emojiViewFrame.midY - emojiView.center.y) + let positionKeyframes = generateParabollicMotionKeyframes(from: emojiViewFrame.center, to: emojiView.center, elevation: distance.y * 0.8, duration: duration, curve: curve, reverse: true) + emojiView.center = emojiViewFrame.center + emojiView.layer.animateKeyframes(values: positionKeyframes.map { NSValue(cgPoint: $0) }, duration: duration, keyPath: "position", additive: false) + } else { + emojiTransition.setPosition(view: emojiView, position: emojiViewFrame.center) + } + emojiTransition.setBounds(view: emojiView, bounds: CGRect(origin: CGPoint(), size: emojiViewFrame.size)) + emojiAlphaTransition.setAlpha(view: emojiView, alpha: (currentAreControlsHidden || self.isAnimatedOutToGroupCall) ? 0.0 : 1.0) + + if self.displayEmojiTooltip { + let emojiTooltipView: EmojiTooltipView + var emojiTooltipTransition = transition + var animateIn = false + if let current = self.emojiTooltipView { + emojiTooltipView = current + } else { + emojiTooltipTransition = emojiTooltipTransition.withAnimation(.none) + emojiTooltipView = EmojiTooltipView(text: params.state.strings.Call_EncryptionKeyTooltip) + animateIn = true + self.emojiTooltipView = emojiTooltipView + self.addSubview(emojiTooltipView) + } + + let emojiTooltipSize = emojiTooltipView.update(constrainedWidth: params.size.width - 32.0 * 2.0, subjectWidth: emojiViewSize.width * 0.5) + let emojiTooltipFrame = CGRect(origin: CGPoint(x: emojiViewFrame.minX + floor((emojiViewFrame.width - emojiTooltipSize.width) * 0.5), y: emojiViewFrame.maxY + 8.0), size: emojiTooltipSize) + emojiTooltipTransition.setFrame(view: emojiTooltipView, frame: emojiTooltipFrame) + + if animateIn && !transition.animation.isImmediate { + emojiTooltipView.animateIn() + } + } else if let emojiTooltipView = self.emojiTooltipView { + self.emojiTooltipView = nil + emojiTooltipView.animateOut(completion: { [weak emojiTooltipView] in + emojiTooltipView?.removeFromSuperview() + }) + } + } + } + if case let .active(activeState) = params.state.lifecycleState, activeState.signalInfo.quality <= 0.2, !self.isEmojiKeyExpanded, (!self.displayEmojiTooltip || !havePrimaryVideo) { let weakSignalView: WeakSignalView if let current = self.weakSignalView { diff --git a/submodules/TelegramUI/Components/Chat/ChatSendStarsScreen/Sources/ChatSendStarsScreen.swift b/submodules/TelegramUI/Components/Chat/ChatSendStarsScreen/Sources/ChatSendStarsScreen.swift index deb455dbab..42700406b4 100644 --- a/submodules/TelegramUI/Components/Chat/ChatSendStarsScreen/Sources/ChatSendStarsScreen.swift +++ b/submodules/TelegramUI/Components/Chat/ChatSendStarsScreen/Sources/ChatSendStarsScreen.swift @@ -822,7 +822,6 @@ private final class ChatSendStarsScreenComponent: Component { let context: AccountContext let peer: EnginePeer let myPeer: EnginePeer - let sendAsPeer: EnginePeer let channelsForPublicReaction: [EnginePeer] let messageId: EngineMessage.Id let maxAmount: Int @@ -830,13 +829,12 @@ private final class ChatSendStarsScreenComponent: Component { let currentSentAmount: Int? let topPeers: [ChatSendStarsScreen.TopPeer] let myTopPeer: ChatSendStarsScreen.TopPeer? - let completion: (Int64, Bool, Bool, ChatSendStarsScreen.TransitionOut) -> Void + let completion: (Int64, TelegramPaidReactionPrivacy, Bool, ChatSendStarsScreen.TransitionOut) -> Void init( context: AccountContext, peer: EnginePeer, myPeer: EnginePeer, - sendAsPeer: EnginePeer, channelsForPublicReaction: [EnginePeer], messageId: EngineMessage.Id, maxAmount: Int, @@ -844,12 +842,11 @@ private final class ChatSendStarsScreenComponent: Component { currentSentAmount: Int?, topPeers: [ChatSendStarsScreen.TopPeer], myTopPeer: ChatSendStarsScreen.TopPeer?, - completion: @escaping (Int64, Bool, Bool, ChatSendStarsScreen.TransitionOut) -> Void + completion: @escaping (Int64, TelegramPaidReactionPrivacy, Bool, ChatSendStarsScreen.TransitionOut) -> Void ) { self.context = context self.peer = peer self.myPeer = myPeer - self.sendAsPeer = sendAsPeer self.channelsForPublicReaction = channelsForPublicReaction self.messageId = messageId self.maxAmount = maxAmount @@ -870,9 +867,6 @@ private final class ChatSendStarsScreenComponent: Component { if lhs.myPeer != rhs.myPeer { return false } - if lhs.sendAsPeer != rhs.sendAsPeer { - return false - } if lhs.channelsForPublicReaction != rhs.channelsForPublicReaction { return false } @@ -991,6 +985,12 @@ private final class ChatSendStarsScreenComponent: Component { } } + private enum PrivacyPeer: Equatable { + case account + case anonymous + case peer(EnginePeer) + } + final class View: UIView, UIScrollViewDelegate { private let dimView: UIView private let backgroundLayer: SimpleLayer @@ -1041,7 +1041,7 @@ private final class ChatSendStarsScreenComponent: Component { private var amount: Amount = Amount(realValue: 1, maxRealValue: 1000, maxSliderValue: 1000, isLogarithmic: true) private var didChangeAmount: Bool = false - private var isAnonymous: Bool = false + private var privacyPeer: PrivacyPeer = .account private var cachedStarImage: (UIImage, PresentationTheme)? private var cachedCloseImage: UIImage? @@ -1386,7 +1386,25 @@ private final class ChatSendStarsScreenComponent: Component { if self.currentMyPeer != peer { self.currentMyPeer = peer - let _ = component.context.engine.peers.updatePeerSendAsPeer(peerId: component.peer.id, sendAs: peer.id).startStandalone() + if peer.id == component.context.account.peerId { + self.privacyPeer = .account + } else { + self.privacyPeer = .peer(peer) + } + + if component.myTopPeer != nil { + let mappedPrivacy: TelegramPaidReactionPrivacy + switch self.privacyPeer { + case .account: + mappedPrivacy = .default + case .anonymous: + mappedPrivacy = .anonymous + case let .peer(peer): + mappedPrivacy = .peer(peer.id) + } + + let _ = component.context.engine.messages.updateStarsReactionPrivacy(id: component.messageId, privacy: mappedPrivacy).startStandalone() + } } self.state?.updated(transition: .immediate) @@ -1421,7 +1439,16 @@ private final class ChatSendStarsScreenComponent: Component { } self.amount = Amount(realValue: 50, maxRealValue: component.maxAmount, maxSliderValue: 999, isLogarithmic: isLogarithmic) if let myTopPeer = component.myTopPeer { - self.isAnonymous = myTopPeer.isAnonymous + if myTopPeer.isAnonymous { + self.privacyPeer = .anonymous + } else if myTopPeer.peer?.id == component.context.account.peerId { + self.privacyPeer = .account + } else if let peer = myTopPeer.peer { + self.privacyPeer = .peer(peer) + self.currentMyPeer = peer + } else { + self.privacyPeer = .account + } } if let starsContext = component.context.starsContext { @@ -1439,8 +1466,7 @@ private final class ChatSendStarsScreenComponent: Component { }) } - //TODO:wip-release - /*self.channelsForPublicReactionDisposable = (component.context.engine.peers.channelsForPublicReaction(useLocalCache: false) + self.channelsForPublicReactionDisposable = (component.context.engine.peers.channelsForPublicReaction(useLocalCache: false) |> deliverOnMainQueue).startStrict(next: { [weak self] peers in guard let self else { return @@ -1449,7 +1475,7 @@ private final class ChatSendStarsScreenComponent: Component { self.channelsForPublicReaction = peers self.state?.updated(transition: .immediate) } - })*/ + }) } self.component = component @@ -1861,9 +1887,19 @@ private final class ChatSendStarsScreenComponent: Component { } myCount += myCountAddition if myCount != 0 { + var topPeer: EnginePeer? + switch self.privacyPeer { + case .anonymous: + topPeer = nil + case .account: + topPeer = component.myPeer + case let .peer(peer): + topPeer = peer + } + mappedTopPeers.append(ChatSendStarsScreen.TopPeer( randomIndex: -1, - peer: self.isAnonymous ? nil : currentMyPeer, + peer: topPeer, isMy: true, count: myCount )) @@ -2021,7 +2057,7 @@ private final class ChatSendStarsScreenComponent: Component { content: AnyComponent(HStack([ AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(CheckComponent( theme: checkTheme, - selected: !self.isAnonymous + selected: self.privacyPeer != .anonymous ))), AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString(string: environment.strings.SendStarReactions_ShowMyselfInTop, font: Font.regular(16.0), textColor: environment.theme.list.itemPrimaryTextColor)) @@ -2034,11 +2070,33 @@ private final class ChatSendStarsScreenComponent: Component { guard let self, let component = self.component else { return } - self.isAnonymous = !self.isAnonymous + + switch self.privacyPeer { + case .anonymous: + if let currentMyPeer = self.currentMyPeer { + if currentMyPeer.id == component.context.account.peerId { + self.privacyPeer = .account + } else { + self.privacyPeer = .peer(currentMyPeer) + } + } + default: + self.privacyPeer = .anonymous + } self.state?.updated(transition: .easeInOut(duration: 0.2)) if component.myTopPeer != nil { - let _ = component.context.engine.messages.updateStarsReactionIsAnonymous(id: component.messageId, isAnonymous: self.isAnonymous).startStandalone() + let mappedPrivacy: TelegramPaidReactionPrivacy + switch self.privacyPeer { + case .account: + mappedPrivacy = .default + case .anonymous: + mappedPrivacy = .anonymous + case let .peer(peer): + mappedPrivacy = .peer(peer.id) + } + + let _ = component.context.engine.messages.updateStarsReactionPrivacy(id: component.messageId, privacy: mappedPrivacy).startStandalone() } }, animateAlpha: false, @@ -2132,9 +2190,19 @@ private final class ChatSendStarsScreenComponent: Component { isBecomingTop = true } + let mappedPrivacy: TelegramPaidReactionPrivacy + switch self.privacyPeer { + case .account: + mappedPrivacy = .default + case .anonymous: + mappedPrivacy = .anonymous + case let .peer(peer): + mappedPrivacy = .peer(peer.id) + } + component.completion( Int64(self.amount.realValue), - self.isAnonymous, + mappedPrivacy, isBecomingTop, ChatSendStarsScreen.TransitionOut( sourceView: badgeView.badgeIcon @@ -2248,7 +2316,6 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer { public final class InitialData { fileprivate let peer: EnginePeer fileprivate let myPeer: EnginePeer - fileprivate let sendAsPeer: EnginePeer fileprivate let channelsForPublicReaction: [EnginePeer] fileprivate let messageId: EngineMessage.Id fileprivate let balance: StarsAmount? @@ -2259,7 +2326,6 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer { fileprivate init( peer: EnginePeer, myPeer: EnginePeer, - sendAsPeer: EnginePeer, channelsForPublicReaction: [EnginePeer], messageId: EngineMessage.Id, balance: StarsAmount?, @@ -2269,7 +2335,6 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer { ) { self.peer = peer self.myPeer = myPeer - self.sendAsPeer = sendAsPeer self.channelsForPublicReaction = channelsForPublicReaction self.messageId = messageId self.balance = balance @@ -2344,7 +2409,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer { private var presenceDisposable: Disposable? - public init(context: AccountContext, initialData: InitialData, completion: @escaping (Int64, Bool, Bool, TransitionOut) -> Void) { + public init(context: AccountContext, initialData: InitialData, completion: @escaping (Int64, TelegramPaidReactionPrivacy, Bool, TransitionOut) -> Void) { self.context = context var maxAmount = 2500 @@ -2356,7 +2421,6 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer { context: context, peer: initialData.peer, myPeer: initialData.myPeer, - sendAsPeer: initialData.sendAsPeer, channelsForPublicReaction: initialData.channelsForPublicReaction, messageId: initialData.messageId, maxAmount: maxAmount, @@ -2420,10 +2484,7 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer { topPeers = Array(topPeers.prefix(3)) } - //TODO:wip-release - //let channelsForPublicReaction = context.engine.peers.channelsForPublicReaction(useLocalCache: true) - let channelsForPublicReaction: Signal<[EnginePeer], NoError> = .single([]) - let sendAsPeer: Signal = .single(nil) + let channelsForPublicReaction = context.engine.peers.channelsForPublicReaction(useLocalCache: true) return combineLatest( context.engine.data.get( @@ -2432,10 +2493,9 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer { EngineDataMap(allPeerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:))) ), balance, - sendAsPeer, channelsForPublicReaction ) - |> map { peerAndTopPeerMap, balance, sendAsPeer, channelsForPublicReaction -> InitialData? in + |> map { peerAndTopPeerMap, balance, channelsForPublicReaction -> InitialData? in let (peer, myPeer, topPeerMap) = peerAndTopPeerMap guard let peer, let myPeer else { return nil @@ -2445,7 +2505,6 @@ public class ChatSendStarsScreen: ViewControllerComponentContainer { return InitialData( peer: peer, myPeer: myPeer, - sendAsPeer: sendAsPeer ?? myPeer, channelsForPublicReaction: channelsForPublicReaction, messageId: messageId, balance: balance, diff --git a/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift b/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift index 1f00632fb8..f33b368637 100644 --- a/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift +++ b/submodules/TelegramUI/Components/ShareExtensionContext/Sources/ShareExtensionContext.swift @@ -391,6 +391,7 @@ public class ShareRootControllerImpl { voipVersions: [], appData: .single(nil), externalRequestVerificationStream: .never(), + externalRecaptchaRequestVerification: { _, _ in return .never() }, autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, diff --git a/submodules/TelegramUI/Images.xcassets/Call/CallNavigationAddPerson.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Call/CallNavigationAddPerson.imageset/Contents.json new file mode 100644 index 0000000000..f3d3c4027c --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Call/CallNavigationAddPerson.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "addcaller.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Call/CallNavigationAddPerson.imageset/addcaller.pdf b/submodules/TelegramUI/Images.xcassets/Call/CallNavigationAddPerson.imageset/addcaller.pdf new file mode 100644 index 0000000000..cd0252b6f8 Binary files /dev/null and b/submodules/TelegramUI/Images.xcassets/Call/CallNavigationAddPerson.imageset/addcaller.pdf differ diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index 68d2ffec7e..f6d074fba6 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -42,6 +42,7 @@ import MediaEditor import TelegramUIDeclareEncodables import ContextMenuScreen import MetalEngine +import RecaptchaEnterprise #if canImport(AppCenter) import AppCenter @@ -322,6 +323,8 @@ private func extractAccountManagerState(records: AccountRecordsView(nil) private let regularDeviceToken = Promise(nil) + + private var recaptchaClientsBySiteKey: [String: Promise] = [:] func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { precondition(!testIsLaunched) @@ -511,7 +514,63 @@ private func extractAccountManagerState(records: AccountRecordsView + if let current = self.recaptchaClientsBySiteKey[siteKey] { + recaptchaClient = current + } else { + recaptchaClient = Promise() + self.recaptchaClientsBySiteKey[siteKey] = recaptchaClient + + Recaptcha.fetchClient(withSiteKey: siteKey) { client, error in + Queue.mainQueue().async { + guard let client else { + Logger.shared.log("App \(self.episodeId)", "RecaptchaClient creation error: \(String(describing: error)).") + return + } + recaptchaClient.set(.single(client)) + } + } + } + + return (recaptchaClient.get() + |> take(1) + |> mapToSignal { recaptchaClient -> Signal in + return Signal { subscriber in + var recaptchaAction: RecaptchaAction? + switch method { + case "signup": + recaptchaAction = RecaptchaAction.signup + default: + break + } + + guard let recaptchaAction else { + subscriber.putNext(nil) + subscriber.putCompletion() + + return EmptyDisposable + } + recaptchaClient.execute(withAction: recaptchaAction) { token, error in + if let token { + subscriber.putNext(token) + Logger.shared.log("App \(self.episodeId)", "RecaptchaClient executed successfully") + } else { + subscriber.putNext(nil) + Logger.shared.log("App \(self.episodeId)", "RecaptchaClient execute error: \(String(describing: error))") + } + subscriber.putCompletion() + } + + return ActionDisposable { + } + } + |> runOn(Queue.mainQueue()) + }).startStandalone(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion) + } + |> runOn(Queue.mainQueue()) + }, autolockDeadine: autolockDeadine, encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: !buildConfig.isAppStoreBuild, isICloudEnabled: buildConfig.isICloudEnabled) guard let appGroupUrl = maybeAppGroupUrl else { self.mainWindow?.presentNative(UIAlertController(title: nil, message: "Error 2", preferredStyle: .alert)) diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift index f869e5fce7..eec8e97cd6 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift @@ -457,12 +457,12 @@ extension ChatControllerImpl { return } - let _ = (strongSelf.context.engine.messages.sendStarsReaction(id: message.id, count: 1, isAnonymous: nil) - |> deliverOnMainQueue).startStandalone(next: { isAnonymous in + let _ = (strongSelf.context.engine.messages.sendStarsReaction(id: message.id, count: 1, privacy: nil) + |> deliverOnMainQueue).startStandalone(next: { privacy in guard let strongSelf = self else { return } - strongSelf.displayOrUpdateSendStarsUndo(messageId: message.id, count: 1, isAnonymous: isAnonymous) + strongSelf.displayOrUpdateSendStarsUndo(messageId: message.id, count: 1, privacy: privacy) }) }) } else { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index c1b4051e36..91522c1bf0 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1787,12 +1787,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } - let _ = (strongSelf.context.engine.messages.sendStarsReaction(id: message.id, count: 1, isAnonymous: nil) - |> deliverOnMainQueue).startStandalone(next: { isAnonymous in + let _ = (strongSelf.context.engine.messages.sendStarsReaction(id: message.id, count: 1, privacy: nil) + |> deliverOnMainQueue).startStandalone(next: { privacy in guard let strongSelf = self else { return } - strongSelf.displayOrUpdateSendStarsUndo(messageId: message.id, count: 1, isAnonymous: isAnonymous) + strongSelf.displayOrUpdateSendStarsUndo(messageId: message.id, count: 1, privacy: privacy) }) }) } else { diff --git a/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift b/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift index 3bf0cf4150..0f6a4423f6 100644 --- a/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift +++ b/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift @@ -391,7 +391,7 @@ extension ChatControllerImpl { return } HapticFeedback().tap() - self.push(ChatSendStarsScreen(context: self.context, initialData: initialData, completion: { [weak self] amount, isAnonymous, isBecomingTop, transitionOut in + self.push(ChatSendStarsScreen(context: self.context, initialData: initialData, completion: { [weak self] amount, privacy, isBecomingTop, transitionOut in guard let self, amount > 0 else { return } @@ -485,14 +485,14 @@ extension ChatControllerImpl { } } - let _ = self.context.engine.messages.sendStarsReaction(id: message.id, count: Int(amount), isAnonymous: isAnonymous).startStandalone() - self.displayOrUpdateSendStarsUndo(messageId: message.id, count: Int(amount), isAnonymous: isAnonymous) + let _ = self.context.engine.messages.sendStarsReaction(id: message.id, count: Int(amount), privacy: privacy).startStandalone() + self.displayOrUpdateSendStarsUndo(messageId: message.id, count: Int(amount), privacy: privacy) })) }) }) } - func displayOrUpdateSendStarsUndo(messageId: EngineMessage.Id, count: Int, isAnonymous: Bool) { + func displayOrUpdateSendStarsUndo(messageId: EngineMessage.Id, count: Int, privacy: TelegramPaidReactionPrivacy) { if self.currentSendStarsUndoMessageId != messageId { if let current = self.currentSendStarsUndoController { self.currentSendStarsUndoController = nil @@ -507,7 +507,7 @@ extension ChatControllerImpl { } let title: String - if isAnonymous { + if case .anonymous = privacy { title = self.presentationData.strings.Chat_ToastStarsSent_AnonymousTitle(Int32(self.currentSendStarsUndoCount)) } else { title = self.presentationData.strings.Chat_ToastStarsSent_Title(Int32(self.currentSendStarsUndoCount)) diff --git a/submodules/TelegramUI/Sources/NotificationContentContext.swift b/submodules/TelegramUI/Sources/NotificationContentContext.swift index af8eb26068..973a939726 100644 --- a/submodules/TelegramUI/Sources/NotificationContentContext.swift +++ b/submodules/TelegramUI/Sources/NotificationContentContext.swift @@ -140,7 +140,7 @@ public final class NotificationViewControllerImpl { return nil }) - sharedAccountContext = SharedAccountContextImpl(mainWindow: nil, sharedContainerPath: self.initializationData.appGroupPath, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, notificationController: nil, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, apiHash: self.initializationData.apiHash, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(self.initializationData.bundleData), externalRequestVerificationStream: .never(), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: self.initializationData.useBetaFeatures, isICloudEnabled: false), hasInAppPurchases: false, rootPath: rootPath, legacyBasePath: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), firebaseSecretStream: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in }, appDelegate: nil) + sharedAccountContext = SharedAccountContextImpl(mainWindow: nil, sharedContainerPath: self.initializationData.appGroupPath, basePath: rootPath, encryptionParameters: ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: self.initializationData.encryptionParameters.0)!, salt: ValueBoxEncryptionParameters.Salt(data: self.initializationData.encryptionParameters.1)!), accountManager: accountManager, appLockContext: appLockContext, notificationController: nil, applicationBindings: applicationBindings, initialPresentationDataAndSettings: initialPresentationDataAndSettings!, networkArguments: NetworkInitializationArguments(apiId: self.initializationData.apiId, apiHash: self.initializationData.apiHash, languagesCategory: self.initializationData.languagesCategory, appVersion: self.initializationData.appVersion, voipMaxLayer: 0, voipVersions: [], appData: .single(self.initializationData.bundleData), externalRequestVerificationStream: .never(), externalRecaptchaRequestVerification: { _, _ in return .never() }, autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), deviceModelName: nil, useBetaFeatures: self.initializationData.useBetaFeatures, isICloudEnabled: false), hasInAppPurchases: false, rootPath: rootPath, legacyBasePath: nil, apsNotificationToken: .never(), voipNotificationToken: .never(), firebaseSecretStream: .never(), setNotificationCall: { _ in }, navigateToChat: { _, _, _ in }, appDelegate: nil) presentationDataPromise.set(sharedAccountContext!.presentationData) } diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 936e89ac60..4bc8355609 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -807,6 +807,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { } if call !== self.call { + let previousCall = self.call self.call = call self.callController?.dismiss() @@ -814,6 +815,25 @@ public final class SharedAccountContextImpl: SharedAccountContext { self.hasOngoingCall.set(false) self.callState.set(.single(nil)) + if let previousCall, let groupCallController = self.groupCallController { + var matches = false + switch groupCallController.call { + case let .conferenceSource(conferenceSource): + if conferenceSource === previousCall { + matches = true + } + case let .group(groupCall): + if (groupCall as? PresentationGroupCallImpl)?.upgradedConferenceCall === previousCall { + matches = true + } + } + + if matches { + self.groupCallController = nil + groupCallController.dismiss(closing: true, manual: false) + } + } + self.notificationController?.setBlocking(nil) self.callPeerDisposable?.dispose() @@ -822,7 +842,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { self.callIsConferenceDisposable = nil if let call { - if call.conferenceCall == nil { + if call.conferenceStateValue == nil && call.conferenceCall == nil { self.callState.set(call.state |> map(Optional.init)) } @@ -841,6 +861,11 @@ public final class SharedAccountContextImpl: SharedAccountContext { return } guard let callController = self.callController, callController.call === call else { + if self.callController == nil, call.conferenceStateValue != nil { + self.callState.set(.single(nil)) + self.presentControllerWithCurrentCall() + self.notificationController?.setBlocking(nil) + } return } if call.conferenceStateValue != nil { diff --git a/third-party/recaptcha/BUILD b/third-party/recaptcha/BUILD new file mode 100644 index 0000000000..50d806febc --- /dev/null +++ b/third-party/recaptcha/BUILD @@ -0,0 +1,14 @@ +load( + "@build_bazel_rules_apple//apple:apple.bzl", + "apple_dynamic_xcframework_import", + "apple_static_xcframework_import", + "apple_dynamic_framework_import", +) + +apple_static_xcframework_import( + name = "RecaptchaEnterprise", + xcframework_imports = glob(["RecaptchaEnterprise.xcframework/**"]), + visibility = [ + "//visibility:public", + ], +) diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/Info.plist b/third-party/recaptcha/RecaptchaEnterprise.xcframework/Info.plist new file mode 100644 index 0000000000..a1151258b6 --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/Info.plist @@ -0,0 +1,40 @@ + + + + + AvailableLibraries + + + LibraryIdentifier + ios-arm64 + LibraryPath + RecaptchaEnterprise.framework + SupportedArchitectures + + arm64 + + SupportedPlatform + ios + + + LibraryIdentifier + ios-arm64_x86_64-simulator + LibraryPath + RecaptchaEnterprise.framework + SupportedArchitectures + + arm64 + x86_64 + + SupportedPlatform + ios + SupportedPlatformVariant + simulator + + + CFBundlePackageType + XFWK + XCFrameworkFormatVersion + 1.0 + + diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeDirectory b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeDirectory new file mode 100644 index 0000000000..13f8d998b9 Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeDirectory differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeRequirements b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeRequirements new file mode 100644 index 0000000000..9c2f3ecfbf Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeRequirements differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeRequirements-1 b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeRequirements-1 new file mode 100644 index 0000000000..8d59539156 Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeRequirements-1 differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeResources b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeResources new file mode 100644 index 0000000000..d8dcd1ef47 --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeResources @@ -0,0 +1,338 @@ + + + + + files + + ios-arm64/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h + + 4VDxU6SZ65gQBn3rUWCCNqxbb2Q= + + ios-arm64/RecaptchaEnterprise.framework/Info.plist + + lLz/4hKuGngSXx+1idP1Qd7K96Q= + + ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc + + EhXEo2CcyN6grvu7hRiGTj5N5/Q= + + ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface + + HKWaSFA8HkKEhv60fJePQ6MMw6A= + + ios-arm64/RecaptchaEnterprise.framework/Modules/module.modulemap + + e79+f2szYbQmmcycLjb4qvAm9ic= + + ios-arm64/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy + + d34/WdITFALLLJjkSHGiQSA6Z3Y= + + ios-arm64/RecaptchaEnterprise.framework/RecaptchaEnterprise + + Vl9+I/cFYuo5INyhscdU7ZKuJKM= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h + + 4VDxU6SZ65gQBn3rUWCCNqxbb2Q= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Info.plist + + qvXMamMsVpa8+m+Nzwchfsvt/eE= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc + + U/f1XLQrWkvQeR+Px1/pRwRc/cc= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface + + spJ76Pm8/Wr3VMBn4v2XqjpgBVQ= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftdoc + + f96x+pLmntLoPnADpTqimN2ipfI= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftinterface + + s1JZ2QV5QeLTytibw4yKa97YXMg= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/module.modulemap + + e79+f2szYbQmmcycLjb4qvAm9ic= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy + + d34/WdITFALLLJjkSHGiQSA6Z3Y= + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/RecaptchaEnterprise + + Bj5s+c75uv9OG+DFaJDzCJQdNR4= + + + files2 + + ios-arm64/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h + + hash + + 4VDxU6SZ65gQBn3rUWCCNqxbb2Q= + + hash2 + + DVSRC0UZpbiuicyY3o0XyRn5J4W67BXA3EZoseXSJ+E= + + + ios-arm64/RecaptchaEnterprise.framework/Info.plist + + hash + + lLz/4hKuGngSXx+1idP1Qd7K96Q= + + hash2 + + 69AqI/t+mFQl1WdbSZTMvyjw8Arr/BaO45RgklSi/OY= + + + ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc + + hash + + EhXEo2CcyN6grvu7hRiGTj5N5/Q= + + hash2 + + FjQ9BxuUBuAipikhZdGTwdVPGVtsVSoqgo5laiu4cGk= + + + ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface + + hash + + HKWaSFA8HkKEhv60fJePQ6MMw6A= + + hash2 + + 01O3JDW+YCBhgBZ+F9hJi88lBiR0CKI8XKA7R9aJ5M4= + + + ios-arm64/RecaptchaEnterprise.framework/Modules/module.modulemap + + hash + + e79+f2szYbQmmcycLjb4qvAm9ic= + + hash2 + + PteZu5hZeSnScpxe2bKzAkh/J6tvZqHOPjJPPX9L3B0= + + + ios-arm64/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy + + hash + + d34/WdITFALLLJjkSHGiQSA6Z3Y= + + hash2 + + 9ogbL0FljSMHAXmM5vR4v1xZZKB2oE8aTODyTk0qUj8= + + + ios-arm64/RecaptchaEnterprise.framework/RecaptchaEnterprise + + hash + + Vl9+I/cFYuo5INyhscdU7ZKuJKM= + + hash2 + + vQn3SxzkE8c0pSwmCUM4R8oKZsHxVsafDddQf0HeFTo= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h + + hash + + 4VDxU6SZ65gQBn3rUWCCNqxbb2Q= + + hash2 + + DVSRC0UZpbiuicyY3o0XyRn5J4W67BXA3EZoseXSJ+E= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Info.plist + + hash + + qvXMamMsVpa8+m+Nzwchfsvt/eE= + + hash2 + + jnZiaN642xbrWF2l7fQF33YSTgePAQACl0FbRUmayMI= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc + + hash + + U/f1XLQrWkvQeR+Px1/pRwRc/cc= + + hash2 + + tuY9mB+LTHtCEGJRwTeUGym5ANc4iiGERy3vedGcZqo= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface + + hash + + spJ76Pm8/Wr3VMBn4v2XqjpgBVQ= + + hash2 + + vlFk7bczYlw+XSHD42G8VkhH755HVehFT7fD1snaME4= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftdoc + + hash + + f96x+pLmntLoPnADpTqimN2ipfI= + + hash2 + + zHc1oXV0xksHw1i1q0HYnVIF0FJ3244NSbUty6NT3g8= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftinterface + + hash + + s1JZ2QV5QeLTytibw4yKa97YXMg= + + hash2 + + 5enubvBpufjdyyeqCZwbNZnVGNchHIwyNhUx56fzXto= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/module.modulemap + + hash + + e79+f2szYbQmmcycLjb4qvAm9ic= + + hash2 + + PteZu5hZeSnScpxe2bKzAkh/J6tvZqHOPjJPPX9L3B0= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy + + hash + + d34/WdITFALLLJjkSHGiQSA6Z3Y= + + hash2 + + 9ogbL0FljSMHAXmM5vR4v1xZZKB2oE8aTODyTk0qUj8= + + + ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/RecaptchaEnterprise + + hash + + Bj5s+c75uv9OG+DFaJDzCJQdNR4= + + hash2 + + dwEBfc7UHwM0emsKXMYVXM6SRC1m7w/jOCVveRoW9jY= + + + + rules + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^.* + + ^.*\.lproj/ + + optional + + weight + 1000 + + ^.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Base\.lproj/ + + weight + 1010 + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeSignature b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeSignature new file mode 100644 index 0000000000..c112a3fdde Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/_CodeSignature/CodeSignature differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h new file mode 100644 index 0000000000..1013def31c --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h @@ -0,0 +1,523 @@ +// Generated by Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) +#ifndef RECAPTCHAENTERPRISE_SWIFT_H +#define RECAPTCHAENTERPRISE_SWIFT_H +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgcc-compat" + +#if !defined(__has_include) +# define __has_include(x) 0 +#endif +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif +#if !defined(__has_warning) +# define __has_warning(x) 0 +#endif + +#if __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#if defined(__OBJC__) +#include +#endif +#if defined(__cplusplus) +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif +#if defined(__cplusplus) +#if defined(__arm64e__) && __has_include() +# include +#else +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-macro-identifier" +# ifndef __ptrauth_swift_value_witness_function_pointer +# define __ptrauth_swift_value_witness_function_pointer(x) +# endif +# ifndef __ptrauth_swift_class_method_pointer +# define __ptrauth_swift_class_method_pointer(x) +# endif +#pragma clang diagnostic pop +#endif +#endif + +#if !defined(SWIFT_TYPEDEFS) +# define SWIFT_TYPEDEFS 1 +# if __has_include() +# include +# elif !defined(__cplusplus) +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +# endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); +typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); +typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); +#endif + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif +#if !defined(SWIFT_CLASS_PROPERTY) +# if __has_feature(objc_class_property) +# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ +# else +# define SWIFT_CLASS_PROPERTY(...) +# endif +#endif +#if !defined(SWIFT_RUNTIME_NAME) +# if __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +# else +# define SWIFT_RUNTIME_NAME(X) +# endif +#endif +#if !defined(SWIFT_COMPILE_NAME) +# if __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +# else +# define SWIFT_COMPILE_NAME(X) +# endif +#endif +#if !defined(SWIFT_METHOD_FAMILY) +# if __has_attribute(objc_method_family) +# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) +# else +# define SWIFT_METHOD_FAMILY(X) +# endif +#endif +#if !defined(SWIFT_NOESCAPE) +# if __has_attribute(noescape) +# define SWIFT_NOESCAPE __attribute__((noescape)) +# else +# define SWIFT_NOESCAPE +# endif +#endif +#if !defined(SWIFT_RELEASES_ARGUMENT) +# if __has_attribute(ns_consumed) +# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed)) +# else +# define SWIFT_RELEASES_ARGUMENT +# endif +#endif +#if !defined(SWIFT_WARN_UNUSED_RESULT) +# if __has_attribute(warn_unused_result) +# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +# else +# define SWIFT_WARN_UNUSED_RESULT +# endif +#endif +#if !defined(SWIFT_NORETURN) +# if __has_attribute(noreturn) +# define SWIFT_NORETURN __attribute__((noreturn)) +# else +# define SWIFT_NORETURN +# endif +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif +#if !defined(SWIFT_RESILIENT_CLASS) +# if __has_attribute(objc_class_stub) +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub)) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME) +# else +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME) +# endif +#endif +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM_ATTR) +# if __has_attribute(enum_extensibility) +# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) +# else +# define SWIFT_ENUM_ATTR(_extensibility) +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# if __has_feature(generalized_swift_name) +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# else +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) +# endif +#endif +#if !defined(SWIFT_UNAVAILABLE) +# define SWIFT_UNAVAILABLE __attribute__((unavailable)) +#endif +#if !defined(SWIFT_UNAVAILABLE_MSG) +# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) +#endif +#if !defined(SWIFT_AVAILABILITY) +# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) +#endif +#if !defined(SWIFT_WEAK_IMPORT) +# define SWIFT_WEAK_IMPORT __attribute__((weak_import)) +#endif +#if !defined(SWIFT_DEPRECATED) +# define SWIFT_DEPRECATED __attribute__((deprecated)) +#endif +#if !defined(SWIFT_DEPRECATED_MSG) +# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) +#endif +#if !defined(SWIFT_DEPRECATED_OBJC) +# if __has_feature(attribute_diagnose_if_objc) +# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) +# else +# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) +# endif +#endif +#if defined(__OBJC__) +#if !defined(IBSegueAction) +# define IBSegueAction +#endif +#endif +#if !defined(SWIFT_EXTERN) +# if defined(__cplusplus) +# define SWIFT_EXTERN extern "C" +# else +# define SWIFT_EXTERN extern +# endif +#endif +#if !defined(SWIFT_CALL) +# define SWIFT_CALL __attribute__((swiftcall)) +#endif +#if !defined(SWIFT_INDIRECT_RESULT) +# define SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result)) +#endif +#if !defined(SWIFT_CONTEXT) +# define SWIFT_CONTEXT __attribute__((swift_context)) +#endif +#if !defined(SWIFT_ERROR_RESULT) +# define SWIFT_ERROR_RESULT __attribute__((swift_error_result)) +#endif +#if defined(__cplusplus) +# define SWIFT_NOEXCEPT noexcept +#else +# define SWIFT_NOEXCEPT +#endif +#if !defined(SWIFT_C_INLINE_THUNK) +# if __has_attribute(always_inline) +# if __has_attribute(nodebug) +# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) __attribute__((nodebug)) +# else +# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) +# endif +# else +# define SWIFT_C_INLINE_THUNK inline +# endif +#endif +#if defined(_WIN32) +#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL) +# define SWIFT_IMPORT_STDLIB_SYMBOL __declspec(dllimport) +#endif +#else +#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL) +# define SWIFT_IMPORT_STDLIB_SYMBOL +#endif +#endif +#if defined(__OBJC__) +#if 1 /* #if __has_feature(objc_modules) */ +#if __has_warning("-Watimport-in-framework-header") +#pragma clang diagnostic ignored "-Watimport-in-framework-header" +#endif +// Rewritten: @import Foundation; +// From module Foundation +#import +// Rewritten: @import ObjectiveC; +// From module ObjectiveC +// From module ObjectiveC.NSObject +#import +// From module ObjectiveC.message +#import +// From module ObjectiveC.NSObjCRuntime +#import +// From module ObjectiveC.objc_api +#import +// From module ObjectiveC.objc_auto +#import +// From module ObjectiveC.objc_exception +#import +// From module ObjectiveC.objc_sync +#import +// From module ObjectiveC.objc +#import +// From module ObjectiveC.runtime +#import +#endif + +#endif +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +#if __has_warning("-Wpragma-clang-attribute") +# pragma clang diagnostic ignored "-Wpragma-clang-attribute" +#endif +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wnullability" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#if __has_attribute(external_source_symbol) +# pragma push_macro("any") +# undef any +# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="RecaptchaEnterprise",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) +# pragma pop_macro("any") +#endif + +#if defined(__OBJC__) + + +@class NSString; +@class RecaptchaClient; +@class NSError; + +/// Interface to interact with reCAPTCHA. +SWIFT_CLASS("_TtC19RecaptchaEnterprise9Recaptcha") +@interface Recaptcha : NSObject +/// Builds a new reCAPTCHA Client for the given Site Key. +/// The SDK accepts one Site Key. Passing a different Site Key will throw an exception. +/// \param siteKey reCAPTCHA Site Key for the app. +/// +/// \param completion Callback function to return the RecaptchaClient or an error. +/// ++ (void)fetchClientWithSiteKey:(NSString * _Nonnull)siteKey completion:(void (^ _Nonnull)(RecaptchaClient * _Nullable, NSError * _Nullable))completion; +/// Builds a new reCAPTCHA Client for the given Site Key and timeout. +/// The SDK accepts one Site Key. Passing a different Site Key will +/// throw an exception. +/// At least a 10000 milliseconds timeout is suggested to allow for slow +/// networking, though in some cases longer timeouts may be necessary. The +/// minimum allowable value is 5000 milliseconds. +/// \param siteKey reCAPTCHA Site Key for the app. +/// +/// \param timeout Timeout for getClient in milliseconds. +/// +/// \param completion Callback function to return the RecaptchaClient or an error. +/// ++ (void)getClientWithSiteKey:(NSString * _Nonnull)siteKey withTimeout:(double)timeout completion:(void (^ _Nonnull)(RecaptchaClient * _Nullable, NSError * _Nullable))completion SWIFT_DEPRECATED_MSG("Use the new api `fetchClient(withSiteKey:completion:)` instead."); +/// Builds a new reCAPTCHA Client for the given Site Key and timeout. +/// The SDK accepts one Site Key. Passing a different Site Key will +/// throw an exception. +/// This function will timeout after 10 seconds. +/// \param siteKey reCAPTCHA Site Key for the app. +/// +/// \param completion Callback function to return the RecaptchaClient or an error. +/// ++ (void)getClientWithSiteKey:(NSString * _Nonnull)siteKey completion:(void (^ _Nonnull)(RecaptchaClient * _Nullable, NSError * _Nullable))completion SWIFT_DEPRECATED_MSG("Use the new api `fetchClient(withSiteKey:completion:)` instead."); +/// Builds a new reCAPTCHA Client for the given SiteKey. +/// This function will timeout after 10 seconds. +/// \param siteKey reCAPTCHA Site Key for the app. +/// +/// \param completionHandler Callback function to return the RecaptchaClient or an error. +/// ++ (void)getClientWithSiteKey:(NSString * _Nonnull)siteKey completionHandler:(void (^ _Nonnull)(RecaptchaClient * _Nullable, NSError * _Nullable))completionHandler SWIFT_DEPRECATED_MSG("Use the new api `fetchClient(withSiteKey:completion:)` instead."); +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + +enum RecaptchaActionType : NSInteger; + +/// Action intended to be protected by reCAPTCHA. This object should be passed +/// to RecaptchaClient.execute. +SWIFT_CLASS("_TtC19RecaptchaEnterprise15RecaptchaAction") +@interface RecaptchaAction : NSObject +/// Creates an object with a predefined reCAPTCHA action. +/// \param action The type of the action. +/// +/// +/// returns: +/// A RecaptchaAction object with the given action type. +- (nonnull instancetype)initWithAction:(enum RecaptchaActionType)action OBJC_DESIGNATED_INITIALIZER SWIFT_DEPRECATED_MSG("Please use customAction with the regular RecaptchaAction.custom() function"); +/// Indicates that the protected action is a Login workflow. +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong) RecaptchaAction * _Nonnull login;) ++ (RecaptchaAction * _Nonnull)login SWIFT_WARN_UNUSED_RESULT; +/// Indicates that the protected action is a Signup workflow. +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong) RecaptchaAction * _Nonnull signup;) ++ (RecaptchaAction * _Nonnull)signup SWIFT_WARN_UNUSED_RESULT; +/// Creates a custom action from a String. ++ (RecaptchaAction * _Nonnull)custom:(NSString * _Nonnull)action SWIFT_WARN_UNUSED_RESULT; +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + +/// Action type intended to be protected by reCAPTCHA. +typedef SWIFT_ENUM(NSInteger, RecaptchaActionType, open) { +/// Indicates that the protected action is a Login workflow. + RecaptchaActionTypeLogin = 0, +/// Indicates that the protected action is a Signup workflow. + RecaptchaActionTypeSignup = 1, +/// When a custom action is specified, reCAPTCHA uses this value automatically. + RecaptchaActionTypeOther = 2, +}; + +@class RecaptchaToken; +@class RecaptchaError; + +/// Interface to interact with reCAPTCHA. +SWIFT_CLASS("_TtC19RecaptchaEnterprise15RecaptchaClient") +@interface RecaptchaClient : NSObject +/// Executes reCAPTCHA on a user action. +/// It is suggested the usage of 10 seconds for the timeout. The minimum value +/// 5 seconds. +/// \param action The user action to protect. +/// +/// \param timeout Timeout for execute in milliseconds. +/// +/// \param completion Callback function to return the execute response. +/// +- (void)executeWithAction:(RecaptchaAction * _Nonnull)action withTimeout:(double)timeout completion:(void (^ _Nonnull)(NSString * _Nullable, NSError * _Nullable))completion; +/// Executes reCAPTCHA on a user action. +/// This function throws a timeout exception after 10 seconds. +/// \param action The user action to protect. +/// +/// \param completion Callback function to return the execute response. +/// +- (void)executeWithAction:(RecaptchaAction * _Nonnull)action completion:(void (^ _Nonnull)(NSString * _Nullable, NSError * _Nullable))completion; +/// Executes reCAPTCHA on a user action. +/// This function throws a timeout exception after 10 seconds. +/// \param action The user action to protect. +/// +/// \param completion Callback function to return the execute response. +/// +- (void)execute:(RecaptchaAction * _Nonnull)action completion:(void (^ _Nonnull)(NSString * _Nullable, NSError * _Nullable))completion; +/// Executes reCAPTCHA on a user action. +/// This function throws a timeout exception after 10 seconds. +/// \param action The user action to protect. +/// +/// \param completionHandler Callback function to return the execute response. +/// +- (void)execute:(RecaptchaAction * _Nonnull)action completionHandler:(void (^ _Nonnull)(RecaptchaToken * _Nullable, RecaptchaError * _Nullable))completionHandler SWIFT_DEPRECATED_MSG("Use `execute(withAction:completion:)` instead."); +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + + +SWIFT_CLASS("_TtC19RecaptchaEnterprise17RecaptchaConstant") +@interface RecaptchaConstant : NSObject +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, copy) NSString * _Nonnull clientVersion;) ++ (NSString * _Nonnull)clientVersion SWIFT_WARN_UNUSED_RESULT; +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly) double defaultTimeoutExecute;) ++ (double)defaultTimeoutExecute SWIFT_WARN_UNUSED_RESULT; +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly) double defaultTimeoutInit;) ++ (double)defaultTimeoutInit SWIFT_WARN_UNUSED_RESULT; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + +enum RecaptchaErrorCode : NSInteger; +@class NSCoder; + +/// Error class for reCAPTCHA Events. +SWIFT_CLASS("_TtC19RecaptchaEnterprise14RecaptchaError") +@interface RecaptchaError : NSError +/// Code relative to the error that was thrown. It maps to RecaptchaErrorCode. +@property (nonatomic, readonly) enum RecaptchaErrorCode errorCode; +/// Human readable error message. +@property (nonatomic, readonly, copy) NSString * _Nonnull errorMessage; +/// Required by NSError but should not be used. +- (nonnull instancetype)initWithCoder:(NSCoder * _Nonnull)coder SWIFT_UNAVAILABLE; +- (nonnull instancetype)initWithDomain:(NSString * _Nonnull)domain code:(NSInteger)code userInfo:(NSDictionary * _Nullable)dict SWIFT_UNAVAILABLE; +@end + +/// List of errors that can be returned from the SDK. +/// IMPORTANT: This list is add-only. Never change any existing value, since this class is +/// publicly visible and customers rely on these values to do error checking. +typedef SWIFT_ENUM(NSInteger, RecaptchaErrorCode, open) { +/// Unknown error occurred during the workflow. + RecaptchaErrorCodeErrorCodeUnknown = 0, +/// reCAPTCHA cannot connect to Google servers, please make sure the app has network access. + RecaptchaErrorCodeErrorNetworkError = 1, +/// The site key used to call reCAPTCHA is invalid. + RecaptchaErrorCodeErrorInvalidSiteKey = 2, +/// Cannot create a reCAPTCHA interface because the key used cannot be used on iOS. +/// Please register new site key with the key type set to “iOS App” via +/// Create Key. + RecaptchaErrorCodeErroInvalidKeyType = 3, +/// Cannot create a reCAPTCHA interface because the site key used doesn’t support the calling +/// package. + RecaptchaErrorCodeErrorInvalidPackageName = 4, +/// reCAPTCHA cannot accept the action used, see custom +/// action guidelines. + RecaptchaErrorCodeErrorInvalidAction = 5, +/// reCAPTCHA cannot accept timeout provided, see +/// timeout guidelines. + RecaptchaErrorCodeErrorInvalidTimeout = 6, +/// No network was found in the device. + RecaptchaErrorCodeErrorNoNetwork = 7, +/// reCAPTCHA has faced an internal error, please try again in a bit. + RecaptchaErrorCodeErrorCodeInternalError = 100, +}; + + +/// Swift implementation for RecaptchaTokenSwift that holds the response of a successful +/// execute call. +SWIFT_CLASS("_TtC19RecaptchaEnterprise14RecaptchaToken") SWIFT_DEPRECATED_MSG("Newer implementations return the Token as a string.") +@interface RecaptchaToken : NSObject +/// The Token to be used for verification. +@property (nonatomic, readonly, copy) NSString * _Nonnull recaptchaToken; +- (nonnull instancetype)init:(NSString * _Nonnull)mobilemivdvtyi OBJC_DESIGNATED_INITIALIZER SWIFT_DEPRECATED_MSG("Newer implementations return the Token as a string."); +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + + + +#endif +#if __has_attribute(external_source_symbol) +# pragma clang attribute pop +#endif +#if defined(__cplusplus) +#endif +#pragma clang diagnostic pop +#endif diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Info.plist b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Info.plist new file mode 100644 index 0000000000..f47c7a7448 Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Info.plist differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc new file mode 100644 index 0000000000..dd3433dfd9 Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface new file mode 100644 index 0000000000..3b3a7e9227 --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface @@ -0,0 +1,107 @@ +// swift-interface-format-version: 1.0 +// swift-compiler-version: Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) +// swift-module-flags: -target arm64-apple-ios12.0 -enable-objc-interop -enable-library-evolution -enforce-exclusivity=checked -O -enable-experimental-feature AccessLevelOnImport -enable-bare-slash-regex -module-name RecaptchaEnterprise -package-name googlemac/iPhone/recaptcha/enterprise +import CryptoKit +import DeviceCheck +import Foundation +import Network +import Swift +import UIKit +import WebKit +import _Concurrency +import _StringProcessing +import _SwiftConcurrencyShims +@objc @_inheritsConvenienceInitializers @objcMembers public class RecaptchaConstant : ObjectiveC.NSObject { + @objc public static let clientVersion: Swift.String + @objc public static let defaultTimeoutExecute: Swift.Double + @objc public static let defaultTimeoutInit: Swift.Double + @objc override dynamic public init() + @objc deinit +} +@_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers @objc public class Recaptcha : ObjectiveC.NSObject { + @objc public static func fetchClient(withSiteKey siteKey: Swift.String, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + #if compiler(>=5.3) && $AsyncAwait + @available(iOS 13.0, *) + public static func fetchClient(withSiteKey siteKey: Swift.String) async throws -> RecaptchaEnterprise.RecaptchaClient + #endif + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(withSiteKey siteKey: Swift.String, withTimeout timeout: Swift.Double, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(withSiteKey siteKey: Swift.String, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(siteKey: Swift.String, completionHandler: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @objc deinit +} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +@objc public enum RecaptchaActionType : Swift.Int { + case login + case signup + case other + public init?(rawValue: Swift.Int) + public typealias RawValue = Swift.Int + public var rawValue: Swift.Int { + get + } +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaAction : ObjectiveC.NSObject { + convenience public init(customAction: Swift.String) + @available(*, deprecated, message: "Please use customAction with the regular RecaptchaAction.custom() function") + @objc public init(action: RecaptchaEnterprise.RecaptchaActionType) + @objc public static let login: RecaptchaEnterprise.RecaptchaAction + @objc public static let signup: RecaptchaEnterprise.RecaptchaAction + @objc public static func custom(_ action: Swift.String) -> RecaptchaEnterprise.RecaptchaAction + @objc deinit +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaClient : ObjectiveC.NSObject { + @objc public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, withTimeout timeout: Swift.Double, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + #if compiler(>=5.3) && $AsyncAwait + @available(iOS 13.0, *) + public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, withTimeout timeout: Swift.Double = RecaptchaConstant.defaultTimeoutExecute) async throws -> Swift.String + #endif + @objc public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + @objc public func execute(_ action: RecaptchaEnterprise.RecaptchaAction, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use `execute(withAction:completion:)` instead.") + @objc public func execute(_ action: RecaptchaEnterprise.RecaptchaAction, completionHandler: @escaping (RecaptchaEnterprise.RecaptchaToken?, RecaptchaEnterprise.RecaptchaError?) -> Swift.Void) + @objc deinit +} +@objc public enum RecaptchaErrorCode : Swift.Int { + case errorCodeUnknown = 0 + case errorNetworkError = 1 + case errorInvalidSiteKey = 2 + case erroInvalidKeyType = 3 + case errorInvalidPackageName = 4 + case errorInvalidAction = 5 + case errorInvalidTimeout = 6 + case errorNoNetwork = 7 + case errorCodeInternalError = 100 + public init?(rawValue: Swift.Int) + public typealias RawValue = Swift.Int + public var rawValue: Swift.Int { + get + } +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaError : Foundation.NSError { + @objc public var errorCode: RecaptchaEnterprise.RecaptchaErrorCode { + @objc get + } + @objc public var errorMessage: Swift.String { + @objc get + } + @objc deinit +} +@available(*, deprecated, message: "Newer implementations return the Token as a string.") +@objc public class RecaptchaToken : ObjectiveC.NSObject { + @objc final public let recaptchaToken: Swift.String + @available(*, deprecated, message: "Newer implementations return the Token as a string.") + @objc public init(_ mobilemivdvtyi: Swift.String) + @objc deinit +} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.Equatable {} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.Hashable {} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.RawRepresentable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.Equatable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.Hashable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.RawRepresentable {} diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/module.modulemap b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/module.modulemap new file mode 100644 index 0000000000..e0b51e8d85 --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +framework module RecaptchaEnterprise { + header "RecaptchaEnterprise.h" + requires objc +} diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy new file mode 100644 index 0000000000..74847dded7 --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy @@ -0,0 +1,56 @@ + + + + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeDeviceID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypePerformanceData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeProductInteraction + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + + \ No newline at end of file diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/RecaptchaEnterprise b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/RecaptchaEnterprise new file mode 100644 index 0000000000..737e71e03c Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64/RecaptchaEnterprise.framework/RecaptchaEnterprise differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h new file mode 100644 index 0000000000..1013def31c --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Headers/RecaptchaEnterprise.h @@ -0,0 +1,523 @@ +// Generated by Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) +#ifndef RECAPTCHAENTERPRISE_SWIFT_H +#define RECAPTCHAENTERPRISE_SWIFT_H +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wgcc-compat" + +#if !defined(__has_include) +# define __has_include(x) 0 +#endif +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif +#if !defined(__has_feature) +# define __has_feature(x) 0 +#endif +#if !defined(__has_warning) +# define __has_warning(x) 0 +#endif + +#if __has_include() +# include +#endif + +#pragma clang diagnostic ignored "-Wauto-import" +#if defined(__OBJC__) +#include +#endif +#if defined(__cplusplus) +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif +#if defined(__cplusplus) +#if defined(__arm64e__) && __has_include() +# include +#else +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-macro-identifier" +# ifndef __ptrauth_swift_value_witness_function_pointer +# define __ptrauth_swift_value_witness_function_pointer(x) +# endif +# ifndef __ptrauth_swift_class_method_pointer +# define __ptrauth_swift_class_method_pointer(x) +# endif +#pragma clang diagnostic pop +#endif +#endif + +#if !defined(SWIFT_TYPEDEFS) +# define SWIFT_TYPEDEFS 1 +# if __has_include() +# include +# elif !defined(__cplusplus) +typedef uint_least16_t char16_t; +typedef uint_least32_t char32_t; +# endif +typedef float swift_float2 __attribute__((__ext_vector_type__(2))); +typedef float swift_float3 __attribute__((__ext_vector_type__(3))); +typedef float swift_float4 __attribute__((__ext_vector_type__(4))); +typedef double swift_double2 __attribute__((__ext_vector_type__(2))); +typedef double swift_double3 __attribute__((__ext_vector_type__(3))); +typedef double swift_double4 __attribute__((__ext_vector_type__(4))); +typedef int swift_int2 __attribute__((__ext_vector_type__(2))); +typedef int swift_int3 __attribute__((__ext_vector_type__(3))); +typedef int swift_int4 __attribute__((__ext_vector_type__(4))); +typedef unsigned int swift_uint2 __attribute__((__ext_vector_type__(2))); +typedef unsigned int swift_uint3 __attribute__((__ext_vector_type__(3))); +typedef unsigned int swift_uint4 __attribute__((__ext_vector_type__(4))); +#endif + +#if !defined(SWIFT_PASTE) +# define SWIFT_PASTE_HELPER(x, y) x##y +# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y) +#endif +#if !defined(SWIFT_METATYPE) +# define SWIFT_METATYPE(X) Class +#endif +#if !defined(SWIFT_CLASS_PROPERTY) +# if __has_feature(objc_class_property) +# define SWIFT_CLASS_PROPERTY(...) __VA_ARGS__ +# else +# define SWIFT_CLASS_PROPERTY(...) +# endif +#endif +#if !defined(SWIFT_RUNTIME_NAME) +# if __has_attribute(objc_runtime_name) +# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X))) +# else +# define SWIFT_RUNTIME_NAME(X) +# endif +#endif +#if !defined(SWIFT_COMPILE_NAME) +# if __has_attribute(swift_name) +# define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X))) +# else +# define SWIFT_COMPILE_NAME(X) +# endif +#endif +#if !defined(SWIFT_METHOD_FAMILY) +# if __has_attribute(objc_method_family) +# define SWIFT_METHOD_FAMILY(X) __attribute__((objc_method_family(X))) +# else +# define SWIFT_METHOD_FAMILY(X) +# endif +#endif +#if !defined(SWIFT_NOESCAPE) +# if __has_attribute(noescape) +# define SWIFT_NOESCAPE __attribute__((noescape)) +# else +# define SWIFT_NOESCAPE +# endif +#endif +#if !defined(SWIFT_RELEASES_ARGUMENT) +# if __has_attribute(ns_consumed) +# define SWIFT_RELEASES_ARGUMENT __attribute__((ns_consumed)) +# else +# define SWIFT_RELEASES_ARGUMENT +# endif +#endif +#if !defined(SWIFT_WARN_UNUSED_RESULT) +# if __has_attribute(warn_unused_result) +# define SWIFT_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +# else +# define SWIFT_WARN_UNUSED_RESULT +# endif +#endif +#if !defined(SWIFT_NORETURN) +# if __has_attribute(noreturn) +# define SWIFT_NORETURN __attribute__((noreturn)) +# else +# define SWIFT_NORETURN +# endif +#endif +#if !defined(SWIFT_CLASS_EXTRA) +# define SWIFT_CLASS_EXTRA +#endif +#if !defined(SWIFT_PROTOCOL_EXTRA) +# define SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_ENUM_EXTRA) +# define SWIFT_ENUM_EXTRA +#endif +#if !defined(SWIFT_CLASS) +# if __has_attribute(objc_subclassing_restricted) +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# else +# define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA +# endif +#endif +#if !defined(SWIFT_RESILIENT_CLASS) +# if __has_attribute(objc_class_stub) +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) __attribute__((objc_class_stub)) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_class_stub)) SWIFT_CLASS_NAMED(SWIFT_NAME) +# else +# define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) +# define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) SWIFT_CLASS_NAMED(SWIFT_NAME) +# endif +#endif +#if !defined(SWIFT_PROTOCOL) +# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +# define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA +#endif +#if !defined(SWIFT_EXTENSION) +# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__) +#endif +#if !defined(OBJC_DESIGNATED_INITIALIZER) +# if __has_attribute(objc_designated_initializer) +# define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) +# else +# define OBJC_DESIGNATED_INITIALIZER +# endif +#endif +#if !defined(SWIFT_ENUM_ATTR) +# if __has_attribute(enum_extensibility) +# define SWIFT_ENUM_ATTR(_extensibility) __attribute__((enum_extensibility(_extensibility))) +# else +# define SWIFT_ENUM_ATTR(_extensibility) +# endif +#endif +#if !defined(SWIFT_ENUM) +# define SWIFT_ENUM(_type, _name, _extensibility) enum _name : _type _name; enum SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# if __has_feature(generalized_swift_name) +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR(_extensibility) SWIFT_ENUM_EXTRA _name : _type +# else +# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME, _extensibility) SWIFT_ENUM(_type, _name, _extensibility) +# endif +#endif +#if !defined(SWIFT_UNAVAILABLE) +# define SWIFT_UNAVAILABLE __attribute__((unavailable)) +#endif +#if !defined(SWIFT_UNAVAILABLE_MSG) +# define SWIFT_UNAVAILABLE_MSG(msg) __attribute__((unavailable(msg))) +#endif +#if !defined(SWIFT_AVAILABILITY) +# define SWIFT_AVAILABILITY(plat, ...) __attribute__((availability(plat, __VA_ARGS__))) +#endif +#if !defined(SWIFT_WEAK_IMPORT) +# define SWIFT_WEAK_IMPORT __attribute__((weak_import)) +#endif +#if !defined(SWIFT_DEPRECATED) +# define SWIFT_DEPRECATED __attribute__((deprecated)) +#endif +#if !defined(SWIFT_DEPRECATED_MSG) +# define SWIFT_DEPRECATED_MSG(...) __attribute__((deprecated(__VA_ARGS__))) +#endif +#if !defined(SWIFT_DEPRECATED_OBJC) +# if __has_feature(attribute_diagnose_if_objc) +# define SWIFT_DEPRECATED_OBJC(Msg) __attribute__((diagnose_if(1, Msg, "warning"))) +# else +# define SWIFT_DEPRECATED_OBJC(Msg) SWIFT_DEPRECATED_MSG(Msg) +# endif +#endif +#if defined(__OBJC__) +#if !defined(IBSegueAction) +# define IBSegueAction +#endif +#endif +#if !defined(SWIFT_EXTERN) +# if defined(__cplusplus) +# define SWIFT_EXTERN extern "C" +# else +# define SWIFT_EXTERN extern +# endif +#endif +#if !defined(SWIFT_CALL) +# define SWIFT_CALL __attribute__((swiftcall)) +#endif +#if !defined(SWIFT_INDIRECT_RESULT) +# define SWIFT_INDIRECT_RESULT __attribute__((swift_indirect_result)) +#endif +#if !defined(SWIFT_CONTEXT) +# define SWIFT_CONTEXT __attribute__((swift_context)) +#endif +#if !defined(SWIFT_ERROR_RESULT) +# define SWIFT_ERROR_RESULT __attribute__((swift_error_result)) +#endif +#if defined(__cplusplus) +# define SWIFT_NOEXCEPT noexcept +#else +# define SWIFT_NOEXCEPT +#endif +#if !defined(SWIFT_C_INLINE_THUNK) +# if __has_attribute(always_inline) +# if __has_attribute(nodebug) +# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) __attribute__((nodebug)) +# else +# define SWIFT_C_INLINE_THUNK inline __attribute__((always_inline)) +# endif +# else +# define SWIFT_C_INLINE_THUNK inline +# endif +#endif +#if defined(_WIN32) +#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL) +# define SWIFT_IMPORT_STDLIB_SYMBOL __declspec(dllimport) +#endif +#else +#if !defined(SWIFT_IMPORT_STDLIB_SYMBOL) +# define SWIFT_IMPORT_STDLIB_SYMBOL +#endif +#endif +#if defined(__OBJC__) +#if 1 /* #if __has_feature(objc_modules) */ +#if __has_warning("-Watimport-in-framework-header") +#pragma clang diagnostic ignored "-Watimport-in-framework-header" +#endif +// Rewritten: @import Foundation; +// From module Foundation +#import +// Rewritten: @import ObjectiveC; +// From module ObjectiveC +// From module ObjectiveC.NSObject +#import +// From module ObjectiveC.message +#import +// From module ObjectiveC.NSObjCRuntime +#import +// From module ObjectiveC.objc_api +#import +// From module ObjectiveC.objc_auto +#import +// From module ObjectiveC.objc_exception +#import +// From module ObjectiveC.objc_sync +#import +// From module ObjectiveC.objc +#import +// From module ObjectiveC.runtime +#import +#endif + +#endif +#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch" +#pragma clang diagnostic ignored "-Wduplicate-method-arg" +#if __has_warning("-Wpragma-clang-attribute") +# pragma clang diagnostic ignored "-Wpragma-clang-attribute" +#endif +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wnullability" +#pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" + +#if __has_attribute(external_source_symbol) +# pragma push_macro("any") +# undef any +# pragma clang attribute push(__attribute__((external_source_symbol(language="Swift", defined_in="RecaptchaEnterprise",generated_declaration))), apply_to=any(function,enum,objc_interface,objc_category,objc_protocol)) +# pragma pop_macro("any") +#endif + +#if defined(__OBJC__) + + +@class NSString; +@class RecaptchaClient; +@class NSError; + +/// Interface to interact with reCAPTCHA. +SWIFT_CLASS("_TtC19RecaptchaEnterprise9Recaptcha") +@interface Recaptcha : NSObject +/// Builds a new reCAPTCHA Client for the given Site Key. +/// The SDK accepts one Site Key. Passing a different Site Key will throw an exception. +/// \param siteKey reCAPTCHA Site Key for the app. +/// +/// \param completion Callback function to return the RecaptchaClient or an error. +/// ++ (void)fetchClientWithSiteKey:(NSString * _Nonnull)siteKey completion:(void (^ _Nonnull)(RecaptchaClient * _Nullable, NSError * _Nullable))completion; +/// Builds a new reCAPTCHA Client for the given Site Key and timeout. +/// The SDK accepts one Site Key. Passing a different Site Key will +/// throw an exception. +/// At least a 10000 milliseconds timeout is suggested to allow for slow +/// networking, though in some cases longer timeouts may be necessary. The +/// minimum allowable value is 5000 milliseconds. +/// \param siteKey reCAPTCHA Site Key for the app. +/// +/// \param timeout Timeout for getClient in milliseconds. +/// +/// \param completion Callback function to return the RecaptchaClient or an error. +/// ++ (void)getClientWithSiteKey:(NSString * _Nonnull)siteKey withTimeout:(double)timeout completion:(void (^ _Nonnull)(RecaptchaClient * _Nullable, NSError * _Nullable))completion SWIFT_DEPRECATED_MSG("Use the new api `fetchClient(withSiteKey:completion:)` instead."); +/// Builds a new reCAPTCHA Client for the given Site Key and timeout. +/// The SDK accepts one Site Key. Passing a different Site Key will +/// throw an exception. +/// This function will timeout after 10 seconds. +/// \param siteKey reCAPTCHA Site Key for the app. +/// +/// \param completion Callback function to return the RecaptchaClient or an error. +/// ++ (void)getClientWithSiteKey:(NSString * _Nonnull)siteKey completion:(void (^ _Nonnull)(RecaptchaClient * _Nullable, NSError * _Nullable))completion SWIFT_DEPRECATED_MSG("Use the new api `fetchClient(withSiteKey:completion:)` instead."); +/// Builds a new reCAPTCHA Client for the given SiteKey. +/// This function will timeout after 10 seconds. +/// \param siteKey reCAPTCHA Site Key for the app. +/// +/// \param completionHandler Callback function to return the RecaptchaClient or an error. +/// ++ (void)getClientWithSiteKey:(NSString * _Nonnull)siteKey completionHandler:(void (^ _Nonnull)(RecaptchaClient * _Nullable, NSError * _Nullable))completionHandler SWIFT_DEPRECATED_MSG("Use the new api `fetchClient(withSiteKey:completion:)` instead."); +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + +enum RecaptchaActionType : NSInteger; + +/// Action intended to be protected by reCAPTCHA. This object should be passed +/// to RecaptchaClient.execute. +SWIFT_CLASS("_TtC19RecaptchaEnterprise15RecaptchaAction") +@interface RecaptchaAction : NSObject +/// Creates an object with a predefined reCAPTCHA action. +/// \param action The type of the action. +/// +/// +/// returns: +/// A RecaptchaAction object with the given action type. +- (nonnull instancetype)initWithAction:(enum RecaptchaActionType)action OBJC_DESIGNATED_INITIALIZER SWIFT_DEPRECATED_MSG("Please use customAction with the regular RecaptchaAction.custom() function"); +/// Indicates that the protected action is a Login workflow. +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong) RecaptchaAction * _Nonnull login;) ++ (RecaptchaAction * _Nonnull)login SWIFT_WARN_UNUSED_RESULT; +/// Indicates that the protected action is a Signup workflow. +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, strong) RecaptchaAction * _Nonnull signup;) ++ (RecaptchaAction * _Nonnull)signup SWIFT_WARN_UNUSED_RESULT; +/// Creates a custom action from a String. ++ (RecaptchaAction * _Nonnull)custom:(NSString * _Nonnull)action SWIFT_WARN_UNUSED_RESULT; +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + +/// Action type intended to be protected by reCAPTCHA. +typedef SWIFT_ENUM(NSInteger, RecaptchaActionType, open) { +/// Indicates that the protected action is a Login workflow. + RecaptchaActionTypeLogin = 0, +/// Indicates that the protected action is a Signup workflow. + RecaptchaActionTypeSignup = 1, +/// When a custom action is specified, reCAPTCHA uses this value automatically. + RecaptchaActionTypeOther = 2, +}; + +@class RecaptchaToken; +@class RecaptchaError; + +/// Interface to interact with reCAPTCHA. +SWIFT_CLASS("_TtC19RecaptchaEnterprise15RecaptchaClient") +@interface RecaptchaClient : NSObject +/// Executes reCAPTCHA on a user action. +/// It is suggested the usage of 10 seconds for the timeout. The minimum value +/// 5 seconds. +/// \param action The user action to protect. +/// +/// \param timeout Timeout for execute in milliseconds. +/// +/// \param completion Callback function to return the execute response. +/// +- (void)executeWithAction:(RecaptchaAction * _Nonnull)action withTimeout:(double)timeout completion:(void (^ _Nonnull)(NSString * _Nullable, NSError * _Nullable))completion; +/// Executes reCAPTCHA on a user action. +/// This function throws a timeout exception after 10 seconds. +/// \param action The user action to protect. +/// +/// \param completion Callback function to return the execute response. +/// +- (void)executeWithAction:(RecaptchaAction * _Nonnull)action completion:(void (^ _Nonnull)(NSString * _Nullable, NSError * _Nullable))completion; +/// Executes reCAPTCHA on a user action. +/// This function throws a timeout exception after 10 seconds. +/// \param action The user action to protect. +/// +/// \param completion Callback function to return the execute response. +/// +- (void)execute:(RecaptchaAction * _Nonnull)action completion:(void (^ _Nonnull)(NSString * _Nullable, NSError * _Nullable))completion; +/// Executes reCAPTCHA on a user action. +/// This function throws a timeout exception after 10 seconds. +/// \param action The user action to protect. +/// +/// \param completionHandler Callback function to return the execute response. +/// +- (void)execute:(RecaptchaAction * _Nonnull)action completionHandler:(void (^ _Nonnull)(RecaptchaToken * _Nullable, RecaptchaError * _Nullable))completionHandler SWIFT_DEPRECATED_MSG("Use `execute(withAction:completion:)` instead."); +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + + +SWIFT_CLASS("_TtC19RecaptchaEnterprise17RecaptchaConstant") +@interface RecaptchaConstant : NSObject +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly, copy) NSString * _Nonnull clientVersion;) ++ (NSString * _Nonnull)clientVersion SWIFT_WARN_UNUSED_RESULT; +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly) double defaultTimeoutExecute;) ++ (double)defaultTimeoutExecute SWIFT_WARN_UNUSED_RESULT; +SWIFT_CLASS_PROPERTY(@property (nonatomic, class, readonly) double defaultTimeoutInit;) ++ (double)defaultTimeoutInit SWIFT_WARN_UNUSED_RESULT; +- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; +@end + +enum RecaptchaErrorCode : NSInteger; +@class NSCoder; + +/// Error class for reCAPTCHA Events. +SWIFT_CLASS("_TtC19RecaptchaEnterprise14RecaptchaError") +@interface RecaptchaError : NSError +/// Code relative to the error that was thrown. It maps to RecaptchaErrorCode. +@property (nonatomic, readonly) enum RecaptchaErrorCode errorCode; +/// Human readable error message. +@property (nonatomic, readonly, copy) NSString * _Nonnull errorMessage; +/// Required by NSError but should not be used. +- (nonnull instancetype)initWithCoder:(NSCoder * _Nonnull)coder SWIFT_UNAVAILABLE; +- (nonnull instancetype)initWithDomain:(NSString * _Nonnull)domain code:(NSInteger)code userInfo:(NSDictionary * _Nullable)dict SWIFT_UNAVAILABLE; +@end + +/// List of errors that can be returned from the SDK. +/// IMPORTANT: This list is add-only. Never change any existing value, since this class is +/// publicly visible and customers rely on these values to do error checking. +typedef SWIFT_ENUM(NSInteger, RecaptchaErrorCode, open) { +/// Unknown error occurred during the workflow. + RecaptchaErrorCodeErrorCodeUnknown = 0, +/// reCAPTCHA cannot connect to Google servers, please make sure the app has network access. + RecaptchaErrorCodeErrorNetworkError = 1, +/// The site key used to call reCAPTCHA is invalid. + RecaptchaErrorCodeErrorInvalidSiteKey = 2, +/// Cannot create a reCAPTCHA interface because the key used cannot be used on iOS. +/// Please register new site key with the key type set to “iOS App” via +/// Create Key. + RecaptchaErrorCodeErroInvalidKeyType = 3, +/// Cannot create a reCAPTCHA interface because the site key used doesn’t support the calling +/// package. + RecaptchaErrorCodeErrorInvalidPackageName = 4, +/// reCAPTCHA cannot accept the action used, see custom +/// action guidelines. + RecaptchaErrorCodeErrorInvalidAction = 5, +/// reCAPTCHA cannot accept timeout provided, see +/// timeout guidelines. + RecaptchaErrorCodeErrorInvalidTimeout = 6, +/// No network was found in the device. + RecaptchaErrorCodeErrorNoNetwork = 7, +/// reCAPTCHA has faced an internal error, please try again in a bit. + RecaptchaErrorCodeErrorCodeInternalError = 100, +}; + + +/// Swift implementation for RecaptchaTokenSwift that holds the response of a successful +/// execute call. +SWIFT_CLASS("_TtC19RecaptchaEnterprise14RecaptchaToken") SWIFT_DEPRECATED_MSG("Newer implementations return the Token as a string.") +@interface RecaptchaToken : NSObject +/// The Token to be used for verification. +@property (nonatomic, readonly, copy) NSString * _Nonnull recaptchaToken; +- (nonnull instancetype)init:(NSString * _Nonnull)mobilemivdvtyi OBJC_DESIGNATED_INITIALIZER SWIFT_DEPRECATED_MSG("Newer implementations return the Token as a string."); +- (nonnull instancetype)init SWIFT_UNAVAILABLE; ++ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable"); +@end + + + +#endif +#if __has_attribute(external_source_symbol) +# pragma clang attribute pop +#endif +#if defined(__cplusplus) +#endif +#pragma clang diagnostic pop +#endif diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Info.plist b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Info.plist new file mode 100644 index 0000000000..7804000254 Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Info.plist differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc new file mode 100644 index 0000000000..7d55a1ac05 Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftdoc differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface new file mode 100644 index 0000000000..d5bdfe47aa --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/arm64.swiftinterface @@ -0,0 +1,107 @@ +// swift-interface-format-version: 1.0 +// swift-compiler-version: Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) +// swift-module-flags: -target arm64-apple-ios14.0-simulator -enable-objc-interop -enable-library-evolution -enforce-exclusivity=checked -O -enable-experimental-feature AccessLevelOnImport -enable-bare-slash-regex -module-name RecaptchaEnterprise -package-name googlemac/iPhone/recaptcha/enterprise +import CryptoKit +import DeviceCheck +import Foundation +import Network +import Swift +import UIKit +import WebKit +import _Concurrency +import _StringProcessing +import _SwiftConcurrencyShims +@objc @_inheritsConvenienceInitializers @objcMembers public class RecaptchaConstant : ObjectiveC.NSObject { + @objc public static let clientVersion: Swift.String + @objc public static let defaultTimeoutExecute: Swift.Double + @objc public static let defaultTimeoutInit: Swift.Double + @objc override dynamic public init() + @objc deinit +} +@_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers @objc public class Recaptcha : ObjectiveC.NSObject { + @objc public static func fetchClient(withSiteKey siteKey: Swift.String, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + #if compiler(>=5.3) && $AsyncAwait + @available(iOS 13.0, *) + public static func fetchClient(withSiteKey siteKey: Swift.String) async throws -> RecaptchaEnterprise.RecaptchaClient + #endif + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(withSiteKey siteKey: Swift.String, withTimeout timeout: Swift.Double, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(withSiteKey siteKey: Swift.String, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(siteKey: Swift.String, completionHandler: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @objc deinit +} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +@objc public enum RecaptchaActionType : Swift.Int { + case login + case signup + case other + public init?(rawValue: Swift.Int) + public typealias RawValue = Swift.Int + public var rawValue: Swift.Int { + get + } +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaAction : ObjectiveC.NSObject { + convenience public init(customAction: Swift.String) + @available(*, deprecated, message: "Please use customAction with the regular RecaptchaAction.custom() function") + @objc public init(action: RecaptchaEnterprise.RecaptchaActionType) + @objc public static let login: RecaptchaEnterprise.RecaptchaAction + @objc public static let signup: RecaptchaEnterprise.RecaptchaAction + @objc public static func custom(_ action: Swift.String) -> RecaptchaEnterprise.RecaptchaAction + @objc deinit +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaClient : ObjectiveC.NSObject { + @objc public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, withTimeout timeout: Swift.Double, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + #if compiler(>=5.3) && $AsyncAwait + @available(iOS 13.0, *) + public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, withTimeout timeout: Swift.Double = RecaptchaConstant.defaultTimeoutExecute) async throws -> Swift.String + #endif + @objc public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + @objc public func execute(_ action: RecaptchaEnterprise.RecaptchaAction, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use `execute(withAction:completion:)` instead.") + @objc public func execute(_ action: RecaptchaEnterprise.RecaptchaAction, completionHandler: @escaping (RecaptchaEnterprise.RecaptchaToken?, RecaptchaEnterprise.RecaptchaError?) -> Swift.Void) + @objc deinit +} +@objc public enum RecaptchaErrorCode : Swift.Int { + case errorCodeUnknown = 0 + case errorNetworkError = 1 + case errorInvalidSiteKey = 2 + case erroInvalidKeyType = 3 + case errorInvalidPackageName = 4 + case errorInvalidAction = 5 + case errorInvalidTimeout = 6 + case errorNoNetwork = 7 + case errorCodeInternalError = 100 + public init?(rawValue: Swift.Int) + public typealias RawValue = Swift.Int + public var rawValue: Swift.Int { + get + } +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaError : Foundation.NSError { + @objc public var errorCode: RecaptchaEnterprise.RecaptchaErrorCode { + @objc get + } + @objc public var errorMessage: Swift.String { + @objc get + } + @objc deinit +} +@available(*, deprecated, message: "Newer implementations return the Token as a string.") +@objc public class RecaptchaToken : ObjectiveC.NSObject { + @objc final public let recaptchaToken: Swift.String + @available(*, deprecated, message: "Newer implementations return the Token as a string.") + @objc public init(_ mobilemivdvtyi: Swift.String) + @objc deinit +} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.Equatable {} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.Hashable {} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.RawRepresentable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.Equatable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.Hashable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.RawRepresentable {} diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftdoc b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftdoc new file mode 100644 index 0000000000..13d487c72f Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftdoc differ diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftinterface b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftinterface new file mode 100644 index 0000000000..cb495ffa18 --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/RecaptchaEnterprise.swiftmodule/x86_64.swiftinterface @@ -0,0 +1,107 @@ +// swift-interface-format-version: 1.0 +// swift-compiler-version: Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4) +// swift-module-flags: -target x86_64-apple-ios12.0-simulator -enable-objc-interop -enable-library-evolution -enforce-exclusivity=checked -O -enable-experimental-feature AccessLevelOnImport -enable-bare-slash-regex -module-name RecaptchaEnterprise -package-name googlemac/iPhone/recaptcha/enterprise +import CryptoKit +import DeviceCheck +import Foundation +import Network +import Swift +import UIKit +import WebKit +import _Concurrency +import _StringProcessing +import _SwiftConcurrencyShims +@objc @_inheritsConvenienceInitializers @objcMembers public class RecaptchaConstant : ObjectiveC.NSObject { + @objc public static let clientVersion: Swift.String + @objc public static let defaultTimeoutExecute: Swift.Double + @objc public static let defaultTimeoutInit: Swift.Double + @objc override dynamic public init() + @objc deinit +} +@_inheritsConvenienceInitializers @_hasMissingDesignatedInitializers @objc public class Recaptcha : ObjectiveC.NSObject { + @objc public static func fetchClient(withSiteKey siteKey: Swift.String, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + #if compiler(>=5.3) && $AsyncAwait + @available(iOS 13.0, *) + public static func fetchClient(withSiteKey siteKey: Swift.String) async throws -> RecaptchaEnterprise.RecaptchaClient + #endif + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(withSiteKey siteKey: Swift.String, withTimeout timeout: Swift.Double, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(withSiteKey siteKey: Swift.String, completion: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use the new api `fetchClient(withSiteKey:completion:)` instead.") + @objc public static func getClient(siteKey: Swift.String, completionHandler: @escaping (RecaptchaEnterprise.RecaptchaClient?, Foundation.NSError?) -> Swift.Void) + @objc deinit +} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +@objc public enum RecaptchaActionType : Swift.Int { + case login + case signup + case other + public init?(rawValue: Swift.Int) + public typealias RawValue = Swift.Int + public var rawValue: Swift.Int { + get + } +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaAction : ObjectiveC.NSObject { + convenience public init(customAction: Swift.String) + @available(*, deprecated, message: "Please use customAction with the regular RecaptchaAction.custom() function") + @objc public init(action: RecaptchaEnterprise.RecaptchaActionType) + @objc public static let login: RecaptchaEnterprise.RecaptchaAction + @objc public static let signup: RecaptchaEnterprise.RecaptchaAction + @objc public static func custom(_ action: Swift.String) -> RecaptchaEnterprise.RecaptchaAction + @objc deinit +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaClient : ObjectiveC.NSObject { + @objc public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, withTimeout timeout: Swift.Double, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + #if compiler(>=5.3) && $AsyncAwait + @available(iOS 13.0, *) + public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, withTimeout timeout: Swift.Double = RecaptchaConstant.defaultTimeoutExecute) async throws -> Swift.String + #endif + @objc public func execute(withAction action: RecaptchaEnterprise.RecaptchaAction, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + @objc public func execute(_ action: RecaptchaEnterprise.RecaptchaAction, completion: @escaping (Swift.String?, Foundation.NSError?) -> Swift.Void) + @available(*, deprecated, message: "Use `execute(withAction:completion:)` instead.") + @objc public func execute(_ action: RecaptchaEnterprise.RecaptchaAction, completionHandler: @escaping (RecaptchaEnterprise.RecaptchaToken?, RecaptchaEnterprise.RecaptchaError?) -> Swift.Void) + @objc deinit +} +@objc public enum RecaptchaErrorCode : Swift.Int { + case errorCodeUnknown = 0 + case errorNetworkError = 1 + case errorInvalidSiteKey = 2 + case erroInvalidKeyType = 3 + case errorInvalidPackageName = 4 + case errorInvalidAction = 5 + case errorInvalidTimeout = 6 + case errorNoNetwork = 7 + case errorCodeInternalError = 100 + public init?(rawValue: Swift.Int) + public typealias RawValue = Swift.Int + public var rawValue: Swift.Int { + get + } +} +@_hasMissingDesignatedInitializers @objc public class RecaptchaError : Foundation.NSError { + @objc public var errorCode: RecaptchaEnterprise.RecaptchaErrorCode { + @objc get + } + @objc public var errorMessage: Swift.String { + @objc get + } + @objc deinit +} +@available(*, deprecated, message: "Newer implementations return the Token as a string.") +@objc public class RecaptchaToken : ObjectiveC.NSObject { + @objc final public let recaptchaToken: Swift.String + @available(*, deprecated, message: "Newer implementations return the Token as a string.") + @objc public init(_ mobilemivdvtyi: Swift.String) + @objc deinit +} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.Equatable {} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.Hashable {} +@available(*, deprecated, message: "Use RecaptchaAction enums instead.") +extension RecaptchaEnterprise.RecaptchaActionType : Swift.RawRepresentable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.Equatable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.Hashable {} +extension RecaptchaEnterprise.RecaptchaErrorCode : Swift.RawRepresentable {} diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/module.modulemap b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/module.modulemap new file mode 100644 index 0000000000..e0b51e8d85 --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +framework module RecaptchaEnterprise { + header "RecaptchaEnterprise.h" + requires objc +} diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy new file mode 100644 index 0000000000..74847dded7 --- /dev/null +++ b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/PrivacyInfo.xcprivacy @@ -0,0 +1,56 @@ + + + + + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeDeviceID + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypePerformanceData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeProductInteraction + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + + \ No newline at end of file diff --git a/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/RecaptchaEnterprise b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/RecaptchaEnterprise new file mode 100644 index 0000000000..0f73fbcfaf Binary files /dev/null and b/third-party/recaptcha/RecaptchaEnterprise.xcframework/ios-arm64_x86_64-simulator/RecaptchaEnterprise.framework/RecaptchaEnterprise differ diff --git a/third-party/webp/BUILD b/third-party/webp/BUILD index b6ef3be99f..310c69bfd3 100644 --- a/third-party/webp/BUILD +++ b/third-party/webp/BUILD @@ -56,7 +56,7 @@ genrule( mkdir -p "$$BUILD_DIR/Public/libwebp" - PATH="$$PATH:$$CMAKE_DIR/cmake-3.23.1-macos-universal/CMake.app/Contents/bin" sh $$BUILD_DIR/build-webp-bazel.sh $$BUILD_ARCH "$$BUILD_DIR/libwebp" "$$BUILD_DIR" + PATH="$$PATH:$$CMAKE_DIR/cmake-3.23.1-macos-universal/CMake.app/Contents/bin" sh $$BUILD_DIR/build-webp-bazel.sh $$BUILD_ARCH "$$BUILD_DIR/libwebp" "$$BUILD_DIR" >/dev/null 2>&1 """ + "\n".join([ "cp -f \"$$BUILD_DIR/libwebp/src/webp/{}\" \"$(location Public/webp/{})\"".format(header, header) for header in headers