diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4549157fb9..2e3328d7e6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ internal: except: - tags script: - - PYTHONPATH="$PYTHONPATH:/darwin-containers" python3 -u build-system/Make/Make.py remote-build --darwinContainersHost="http://host.docker.internal:8650" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="/telegram-private-data/build-configurations/enterprise-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=enterprise --configuration=release_arm64 + - PYTHONPATH="$PYTHONPATH:/darwin-containers" python3 -u build-system/Make/Make.py remote-build --darwinContainersHost="http://host.docker.internal:8650" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="$TELEGRAM_PRIVATE_DATA_PATH/build-configurations/enterprise-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=enterprise --configuration=release_arm64 - python3 -u build-system/Make/DeployToAppCenter.py --configuration="$TELEGRAM_PRIVATE_DATA_PATH/appcenter-configurations/appcenter-internal.json" --ipa="build/artifacts/Telegram.ipa" --dsyms="build/artifacts/Telegram.DSYMs.zip" environment: name: internal @@ -92,7 +92,7 @@ beta_testflight: except: - tags script: - - PYTHONPATH="$PYTHONPATH:/darwin-containers" python3 -u build-system/Make/Make.py remote-build --darwinContainersHost="http://host.docker.internal:8650" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appstore-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=appstore --configuration=release_universal + - PYTHONPATH="$PYTHONPATH:/darwin-containers" python3 -u build-system/Make/Make.py remote-build --darwinContainersHost="http://host.docker.internal:8650" --cacheHost="$TELEGRAM_BAZEL_CACHE_HOST" --configurationPath="build-system/appstore-configuration.json" --gitCodesigningRepository="$TELEGRAM_GIT_CODESIGNING_REPOSITORY" --gitCodesigningType=appstore --configuration=release_arm64 environment: name: testflight_llc artifacts: diff --git a/Telegram/BUILD b/Telegram/BUILD index 953b177ea5..2469290bd5 100644 --- a/Telegram/BUILD +++ b/Telegram/BUILD @@ -115,6 +115,8 @@ genrule( ], ) +minimum_os_version = "11.0" + empty_languages = [ "ar", "be", @@ -588,6 +590,18 @@ plist_fragment( """ ) +plist_fragment( + name = "RequiredDeviceCapabilitiesPlist", + extension = "plist", + template = + """ + UIRequiredDeviceCapabilities + + arm64 + + """ +) + plist_fragment( name = "AppNameInfoPlist", extension = "plist", @@ -690,7 +704,7 @@ watchos_extension( ":AppNameInfoPlist", ":WatchExtensionNSExtensionInfoPlist", ], - minimum_os_version = "5.0", + minimum_os_version = "9.0", provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:WatchExtension.mobileprovision", @@ -716,11 +730,11 @@ watchos_application( infoplists = [ ":WatchAppInfoPlist", ":VersionInfoPlist", - "BuildNumberInfoPlist", + ":BuildNumberInfoPlist", ":AppNameInfoPlist", ":WatchAppCompanionInfoPlist", ], - minimum_os_version = "5.0", + minimum_os_version = "9.0", provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:WatchApp.mobileprovision", @@ -767,8 +781,9 @@ ios_framework( ":MtProtoKitInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, extension_safe = True, ipa_post_processor = strip_framework, deps = [ @@ -807,8 +822,9 @@ ios_framework( ":SwiftSignalKitInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, extension_safe = True, ipa_post_processor = strip_framework, deps = [ @@ -847,11 +863,12 @@ ios_framework( ":PostboxInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ], frameworks = [ ":SwiftSignalKitFramework", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, extension_safe = True, ipa_post_processor = strip_framework, deps = [ @@ -890,8 +907,9 @@ ios_framework( ":TelegramApiInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, extension_safe = True, ipa_post_processor = strip_framework, deps = [ @@ -930,13 +948,14 @@ ios_framework( ":TelegramCoreInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ], frameworks = [ ":MtProtoKitFramework", ":SwiftSignalKitFramework", ":PostboxFramework", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, extension_safe = True, ipa_post_processor = strip_framework, deps = [ @@ -975,8 +994,9 @@ ios_framework( ":AsyncDisplayKitInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, extension_safe = True, ipa_post_processor = strip_framework, deps = [ @@ -1058,12 +1078,13 @@ ios_framework( ":DisplayInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ], frameworks = [ ":SwiftSignalKitFramework", ":AsyncDisplayKitFramework", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, extension_safe = True, ipa_post_processor = strip_framework, deps = [ @@ -1102,6 +1123,7 @@ ios_framework( ":TelegramUIInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ], frameworks = [ ":MtProtoKitFramework", @@ -1111,7 +1133,7 @@ ios_framework( ":AsyncDisplayKitFramework", ":DisplayFramework", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, extension_safe = True, ipa_post_processor = strip_framework, deps = [ @@ -1195,10 +1217,11 @@ ios_extension( infoplists = [ ":ShareInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":BuildNumberInfoPlist", ":AppNameInfoPlist", ], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:Share.mobileprovision", @@ -1269,7 +1292,7 @@ swift_library( ], ) -genrule( +'''genrule( name = "SetMinOsVersionNotificationContentExtension", cmd_bash = """ @@ -1286,7 +1309,7 @@ genrule( visibility = [ "//visibility:public", ] -) +)''' ios_extension( name = "NotificationContentExtension", @@ -1300,11 +1323,12 @@ ios_extension( infoplists = [ ":NotificationContentInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":BuildNumberInfoPlist", ":AppNameInfoPlist", ], - minimum_os_version = "9.0", # maintain the same minimum OS version across extensions - ipa_post_processor = ":SetMinOsVersionNotificationContentExtension", + minimum_os_version = minimum_os_version, # maintain the same minimum OS version across extensions + #ipa_post_processor = ":SetMinOsVersionNotificationContentExtension", provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:NotificationContent.mobileprovision", @@ -1404,10 +1428,11 @@ ios_extension( infoplists = [ ":WidgetInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":BuildNumberInfoPlist", ":AppNameInfoPlist", ], - minimum_os_version = "9.0", # maintain the same minimum OS version across extensions + minimum_os_version = minimum_os_version, # maintain the same minimum OS version across extensions ipa_post_processor = ":SetMinOsVersionWidgetExtension", #provides_main = True, provisioning_profile = select({ @@ -1506,7 +1531,7 @@ swift_library( ], ) -genrule( +'''genrule( name = "SetMinOsVersionIntentsExtension", cmd_bash = """ @@ -1523,7 +1548,7 @@ genrule( visibility = [ "//visibility:public", ] -) +)''' ios_extension( name = "IntentsExtension", @@ -1537,11 +1562,12 @@ ios_extension( infoplists = [ ":IntentsInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":BuildNumberInfoPlist", ":AppNameInfoPlist", ], - minimum_os_version = "9.0", # maintain the same minimum OS version across extensions - ipa_post_processor = ":SetMinOsVersionIntentsExtension", + minimum_os_version = minimum_os_version, # maintain the same minimum OS version across extensions + #ipa_post_processor = ":SetMinOsVersionIntentsExtension", provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:Intents.mobileprovision", @@ -1600,7 +1626,7 @@ swift_library( ], ) -genrule( +'''genrule( name = "SetMinOsVersionBroadcastUploadExtension", cmd_bash = """ @@ -1617,7 +1643,7 @@ genrule( visibility = [ "//visibility:public", ] -) +)''' ios_extension( name = "BroadcastUploadExtension", @@ -1631,11 +1657,12 @@ ios_extension( infoplists = [ ":BroadcastUploadInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":BuildNumberInfoPlist", ":AppNameInfoPlist", ], - minimum_os_version = "9.0", # maintain the same minimum OS version across extensions - ipa_post_processor = ":SetMinOsVersionBroadcastUploadExtension", + minimum_os_version = minimum_os_version, # maintain the same minimum OS version across extensions + #ipa_post_processor = ":SetMinOsVersionBroadcastUploadExtension", provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:BroadcastUpload.mobileprovision", @@ -1679,7 +1706,7 @@ plist_fragment( ) ) -genrule( +'''genrule( name = "SetMinOsVersionNotificationServiceExtension", cmd_bash = """ @@ -1696,7 +1723,7 @@ genrule( visibility = [ "//visibility:public", ] -) +)''' ios_extension( name = "NotificationServiceExtension", @@ -1710,11 +1737,12 @@ ios_extension( infoplists = [ ":NotificationServiceInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":BuildNumberInfoPlist", ":AppNameInfoPlist", ], - minimum_os_version = "9.0", # maintain the same minimum OS version across extensions - ipa_post_processor = ":SetMinOsVersionNotificationServiceExtension", + minimum_os_version = minimum_os_version, # maintain the same minimum OS version across extensions + #ipa_post_processor = ":SetMinOsVersionNotificationServiceExtension", provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:NotificationService.mobileprovision", @@ -1846,10 +1874,6 @@ plist_fragment( UILaunchStoryboardName LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - UIRequiresPersistentWiFi UIStatusBarStyle @@ -1912,7 +1936,7 @@ ios_application( telegram_bundle_id = telegram_bundle_id, ), families = ["iphone", "ipad"], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision", @@ -1922,6 +1946,7 @@ ios_application( ":TelegramInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":UrlTypesInfoPlist", ], alternate_icons = [ @@ -1958,7 +1983,7 @@ ios_application( }), watch_application = select({ ":disableExtensionsSetting": None, - "//conditions:default": None,#":TelegramWatchApp", + "//conditions:default": ":TelegramWatchApp", }) if telegram_enable_watch else None, deps = [ ":Main", @@ -1974,7 +1999,7 @@ ios_application( telegram_bundle_id = telegram_bundle_id, ), families = ["iphone", "ipad"], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision", @@ -1984,6 +2009,7 @@ ios_application( ":TelegramInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":UrlTypesInfoPlist", ], deps = [ @@ -1997,7 +2023,7 @@ ios_application( telegram_bundle_id = telegram_bundle_id, ), families = ["iphone", "ipad"], - minimum_os_version = "9.0", + minimum_os_version = minimum_os_version, provisioning_profile = select({ ":disableProvisioningProfilesSetting": None, "//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision", @@ -2007,6 +2033,7 @@ ios_application( ":TelegramInfoPlist", ":BuildNumberInfoPlist", ":VersionInfoPlist", + ":RequiredDeviceCapabilitiesPlist", ":UrlTypesInfoPlist", ], deps = [ diff --git a/Telegram/NotificationService/Sources/NotificationService.swift b/Telegram/NotificationService/Sources/NotificationService.swift index 44bba89c8b..61dca23a25 100644 --- a/Telegram/NotificationService/Sources/NotificationService.swift +++ b/Telegram/NotificationService/Sources/NotificationService.swift @@ -642,7 +642,7 @@ private final class NotificationServiceHandler { let logsPath = rootPath + "/logs/notification-logs" let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil) - setupSharedLogger(rootPath: rootPath, path: logsPath) + setupSharedLogger(rootPath: logsPath, path: logsPath) initializeAccountManagement() @@ -652,6 +652,24 @@ private final class NotificationServiceHandler { let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId) self.encryptionParameters = ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: deviceSpecificEncryptionParameters.key)!, salt: ValueBoxEncryptionParameters.Salt(data: deviceSpecificEncryptionParameters.salt)!) + + let semaphore = DispatchSemaphore(value: 0) + var loggingSettings = LoggingSettings.defaultSettings + let _ = (self.accountManager.transaction { transaction -> LoggingSettings in + if let value = transaction.getSharedData(SharedDataKeys.loggingSettings)?.get(LoggingSettings.self) { + return value + } else { + return LoggingSettings.defaultSettings + } + }).start(next: { value in + loggingSettings = value + semaphore.signal() + }) + semaphore.wait() + + Logger.shared.logToFile = loggingSettings.logToFile + 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, signatureDict: nil)), autolockDeadine: .single(nil), encryptionProvider: OpenSSLEncryptionProvider(), resolvedDeviceName: nil) diff --git a/Telegram/SiriIntents/IntentHandler.swift b/Telegram/SiriIntents/IntentHandler.swift index 2bbebcf1d5..5c718a5324 100644 --- a/Telegram/SiriIntents/IntentHandler.swift +++ b/Telegram/SiriIntents/IntentHandler.swift @@ -116,7 +116,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo let logsPath = rootPath + "/logs/siri-logs" let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil) - setupSharedLogger(rootPath: rootPath, path: logsPath) + setupSharedLogger(rootPath: logsPath, path: logsPath) let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown" diff --git a/Telegram/WidgetKitWidget/TodayViewController.swift b/Telegram/WidgetKitWidget/TodayViewController.swift index 6a852b13ff..3b40feb3e0 100644 --- a/Telegram/WidgetKitWidget/TodayViewController.swift +++ b/Telegram/WidgetKitWidget/TodayViewController.swift @@ -94,7 +94,7 @@ private func getCommonTimeline(friends: [Friend]?, in context: TimelineProviderC let logsPath = rootPath + "/logs/widget-logs" let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil) - setupSharedLogger(rootPath: rootPath, path: logsPath) + setupSharedLogger(rootPath: logsPath, path: logsPath) initializeAccountManagement() diff --git a/build-system/Make/Make.py b/build-system/Make/Make.py index c1b8b7ecc0..d07e1932d6 100644 --- a/build-system/Make/Make.py +++ b/build-system/Make/Make.py @@ -59,6 +59,9 @@ class BazelCommandLine: # https://docs.bazel.build/versions/master/command-line-reference.html # Print the subcommand details in case of failure. '--verbose_failures', + + # Asynchronously upload cache artifacts + '--experimental_remote_cache_async', ] self.common_build_args = [ @@ -144,7 +147,7 @@ class BazelCommandLine: '--ios_multi_cpus=armv7,arm64', # Always build universal Watch binaries. - '--watchos_cpus=armv7k,arm64_32' + '--watchos_cpus=arm64_32' ] + self.common_debug_args elif configuration == 'debug_arm64': self.configuration_args = [ @@ -155,7 +158,7 @@ class BazelCommandLine: '--ios_multi_cpus=arm64', # Always build universal Watch binaries. - '--watchos_cpus=armv7k,arm64_32' + '--watchos_cpus=arm64_32' ] + self.common_debug_args elif configuration == 'debug_sim_arm64': self.configuration_args = [ @@ -166,7 +169,7 @@ class BazelCommandLine: '--ios_multi_cpus=sim_arm64', # Always build universal Watch binaries. - '--watchos_cpus=armv7k,arm64_32' + '--watchos_cpus=arm64_32' ] + self.common_debug_args elif configuration == 'debug_armv7': self.configuration_args = [ @@ -176,7 +179,7 @@ class BazelCommandLine: '--ios_multi_cpus=armv7', # Always build universal Watch binaries. - '--watchos_cpus=armv7k,arm64_32' + '--watchos_cpus=arm64_32' ] + self.common_debug_args elif configuration == 'release_arm64': self.configuration_args = [ @@ -187,7 +190,7 @@ class BazelCommandLine: '--ios_multi_cpus=arm64', # Always build universal Watch binaries. - '--watchos_cpus=armv7k,arm64_32', + '--watchos_cpus=arm64_32', # Generate DSYM files when building. '--apple_generate_dsym', @@ -204,7 +207,7 @@ class BazelCommandLine: '--ios_multi_cpus=armv7', # Always build universal Watch binaries. - '--watchos_cpus=armv7k,arm64_32', + '--watchos_cpus=arm64_32', # Generate DSYM files when building. '--apple_generate_dsym', @@ -221,7 +224,7 @@ class BazelCommandLine: '--ios_multi_cpus=armv7,arm64', # Always build universal Watch binaries. - '--watchos_cpus=armv7k,arm64_32', + '--watchos_cpus=arm64_32', # Generate DSYM files when building. '--apple_generate_dsym', @@ -411,7 +414,7 @@ def resolve_codesigning(arguments, base_path, build_configuration, provisioning_ bundle_id=build_configuration.bundle_id, codesigning_type=arguments.gitCodesigningType, password=password, - always_fetch=arguments.gitCodesigningAlwaysFetch + always_fetch=not arguments.gitCodesigningUseCurrent ) elif arguments.codesigningInformationPath is not None: profile_source = DirectoryCodesigningSource( @@ -666,10 +669,10 @@ def add_codesigning_common_arguments(current_parser: argparse.ArgumentParser): ) current_parser.add_argument( - '--gitCodesigningAlwaysFetch', + '--gitCodesigningUseCurrent', action='store_true', required=False, - default=True, + default=False, help=''' Always refresh codesigning repository. ''' diff --git a/submodules/AccountContext/Sources/DeviceContactData.swift b/submodules/AccountContext/Sources/DeviceContactData.swift index fe5aca7de9..3a230a184f 100644 --- a/submodules/AccountContext/Sources/DeviceContactData.swift +++ b/submodules/AccountContext/Sources/DeviceContactData.swift @@ -478,8 +478,28 @@ public extension DeviceContactExtendedData { } } -extension DeviceContactAddressData { - public var dictionary: [String: String] { +public extension DeviceContactAddressData { + var asPostalAddress: CNPostalAddress { + let address = CNMutablePostalAddress() + if !self.street1.isEmpty { + address.street = self.street1 + } + if !self.city.isEmpty { + address.city = self.city + } + if !self.state.isEmpty { + address.state = self.state + } + if !self.country.isEmpty { + address.country = self.country + } + if !self.postcode.isEmpty { + address.postalCode = self.postcode + } + return address + } + + var dictionary: [String: String] { var dictionary: [String: String] = [:] if !self.street1.isEmpty { dictionary["Street"] = self.street1 @@ -499,7 +519,7 @@ extension DeviceContactAddressData { return dictionary } - public var string: String { + var string: String { var array: [String] = [] if !self.street1.isEmpty { array.append(self.street1) @@ -519,7 +539,7 @@ extension DeviceContactAddressData { return array.joined(separator: " ") } - public var displayString: String { + var displayString: String { var array: [String] = [] if !self.street1.isEmpty { array.append(self.street1) diff --git a/submodules/Camera/Sources/CameraDevice.swift b/submodules/Camera/Sources/CameraDevice.swift index 5cbf8ff7e1..58d048818c 100644 --- a/submodules/Camera/Sources/CameraDevice.swift +++ b/submodules/Camera/Sources/CameraDevice.swift @@ -17,7 +17,7 @@ final class CameraDevice { func configure(for session: AVCaptureSession, position: Camera.Position) { self.position = position if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { - self.videoDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDuoCamera, .builtInWideAngleCamera, .builtInTelephotoCamera], mediaType: .video, position: position).devices.first + self.videoDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInDualCamera, .builtInWideAngleCamera, .builtInTelephotoCamera], mediaType: .video, position: position).devices.first } else { self.videoDevice = AVCaptureDevice.devices(for: .video).filter { $0.position == position }.first } @@ -61,7 +61,7 @@ final class CameraDevice { } } - var isFlashActive: Signal { + /*var isFlashActive: Signal { return self.videoDevicePromise.get() |> mapToSignal { device -> Signal in return Signal { subscriber in @@ -75,7 +75,7 @@ final class CameraDevice { } |> distinctUntilChanged } - } + }*/ var isFlashAvailable: Signal { return self.videoDevicePromise.get() diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 04d03267f8..a8b602ebbe 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -853,8 +853,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController self.emojiStatusSelectionController?.dismiss() var selectedItems = Set() var topStatusTitle = self.presentationData.strings.PeerStatusSetup_NoTimerTitle + var currentSelection: Int64? if let peerStatus = self.titleView.title.peerStatus, case let .emoji(emojiStatus) = peerStatus { selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: emojiStatus.fileId)) + currentSelection = emojiStatus.fileId if let timestamp = emojiStatus.expirationDate { topStatusTitle = peerStatusExpirationString(statusTimestamp: timestamp, relativeTo: Int32(Date().timeIntervalSince1970), strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat) @@ -878,6 +880,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController selectedItems: selectedItems, topStatusTitle: topStatusTitle ), + currentSelection: currentSelection, destinationItemView: { [weak sourceView] in return sourceView } diff --git a/submodules/Components/ReactionListContextMenuContent/BUILD b/submodules/Components/ReactionListContextMenuContent/BUILD index cd2e7552c1..08714ce9a7 100644 --- a/submodules/Components/ReactionListContextMenuContent/BUILD +++ b/submodules/Components/ReactionListContextMenuContent/BUILD @@ -25,6 +25,7 @@ swift_library( "//submodules/TelegramUI/Components/AnimationCache:AnimationCache", "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", "//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView", + "//submodules/TelegramUI/Components/EmojiStatusComponent:EmojiStatusComponent", "//submodules/TextFormat:TextFormat", ], visibility = [ diff --git a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift index 30e2b99e87..f27503f8ad 100644 --- a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift +++ b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift @@ -16,6 +16,7 @@ import AnimationCache import MultiAnimationRenderer import EmojiTextAttachmentView import TextFormat +import EmojiStatusComponent private let avatarFont = avatarPlaceholderFont(size: 16.0) @@ -357,7 +358,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent let highlightBackgroundNode: ASDisplayNode let avatarNode: AvatarNode let titleLabelNode: ImmediateTextNode - var credibilityIconNode: ASImageNode? + var credibilityIconView: ComponentView? let separatorNode: ASDisplayNode private var reactionLayer: InlineStickerItemLayer? @@ -519,20 +520,46 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent } let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 }) - var currentCredibilityIconImage: UIImage? + var currentCredibilityIcon: EmojiStatusComponent.Content? if item.peer.isScam { - currentCredibilityIconImage = PresentationResourcesChatList.scamIcon(presentationData.theme, strings: presentationData.strings, type: .regular) + currentCredibilityIcon = .text(color: presentationData.theme.chat.message.incoming.scamColor, string: presentationData.strings.Message_ScamAccount.uppercased()) } else if item.peer.isFake { - currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(presentationData.theme, strings: presentationData.strings, type: .regular) + currentCredibilityIcon = .text(color: presentationData.theme.chat.message.incoming.scamColor, string: presentationData.strings.Message_FakeAccount.uppercased()) + } else if case let .user(user) = item.peer, let emojiStatus = user.emojiStatus { + currentCredibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: UIColor(white: 0.0, alpha: 0.1), themeColor: presentationData.theme.list.itemAccentColor, loopMode: .count(2)) } else if item.peer.isVerified { - currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(presentationData.theme) + currentCredibilityIcon = .verified(fillColor: presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: presentationData.theme.list.itemCheckColors.foregroundColor, sizeType: .compact) } else if item.peer.isPremium && !premiumConfiguration.isPremiumDisabled { - currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(presentationData.theme) + currentCredibilityIcon = .premium(color: presentationData.theme.list.itemCheckColors.fillColor) + } + + var credibilityIconSize: CGSize? + if let currentCredibilityIcon = currentCredibilityIcon { + let credibilityIconView: ComponentView + if let current = self.credibilityIconView { + credibilityIconView = current + } else { + credibilityIconView = ComponentView() + self.credibilityIconView = credibilityIconView + } + credibilityIconSize = credibilityIconView.update( + transition: .immediate, + component: AnyComponent(EmojiStatusComponent( + context: self.context, + animationCache: self.context.animationCache, + animationRenderer: self.context.animationRenderer, + content: currentCredibilityIcon, + isVisibleForAnimations: true, + action: nil + )), + environment: {}, + containerSize: CGSize(width: 24.0, height: 24.0) + ) } var additionalTitleInset: CGFloat = 0.0 - if let currentCredibilityIconImage = currentCredibilityIconImage { - additionalTitleInset += 3.0 + currentCredibilityIconImage.size.width + if let credibilityIconSize = credibilityIconSize { + additionalTitleInset += 3.0 + credibilityIconSize.width } self.highlightBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor @@ -552,23 +579,16 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent let titleFrame = CGRect(origin: CGPoint(x: avatarInset + avatarSize + avatarSpacing, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) self.titleLabelNode.frame = titleFrame - if let currentCredibilityIconImage = currentCredibilityIconImage { - let iconNode: ASImageNode - if let current = self.credibilityIconNode { - iconNode = current - } else { - iconNode = ASImageNode() - iconNode.isLayerBacked = true - iconNode.displaysAsynchronously = false - iconNode.displayWithoutProcessing = true - self.addSubnode(iconNode) - self.credibilityIconNode = iconNode + if let credibilityIconView = self.credibilityIconView, let credibilityIconSize = credibilityIconSize { + if let credibilityIconComponentView = credibilityIconView.view { + if credibilityIconComponentView.superview == nil { + self.view.addSubview(credibilityIconComponentView) + } + credibilityIconComponentView.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: floorToScreenPixels(titleFrame.midY - credibilityIconSize.height / 2.0) + 1.0 - UIScreenPixel), size: credibilityIconSize) } - iconNode.image = currentCredibilityIconImage - iconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: floorToScreenPixels(titleFrame.midY - currentCredibilityIconImage.size.height / 2.0) + 1.0 - UIScreenPixel), size: currentCredibilityIconImage.size) - } else if let credibilityIconNode = self.credibilityIconNode { - self.credibilityIconNode = nil - credibilityIconNode.removeFromSupernode() + } else if let credibilityIconView = self.credibilityIconView { + self.credibilityIconView = nil + credibilityIconView.view?.removeFromSuperview() } let reactionSize = CGSize(width: 22.0, height: 22.0) diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index a3f5f4860c..380fe516d6 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -232,8 +232,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi private var customPosition: CGPoint? private let contentContainerNode: ContextContentContainerNode private var actionsContainerNode: ContextActionsContainerNode - private var reactionContextNode: ReactionContextNode? - private var reactionContextNodeIsAnimatingOut = false private var didCompleteAnimationIn = false private var initialContinueGesturePoint: CGPoint? @@ -401,15 +399,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.hapticFeedback.tap() } } - - if let reactionContextNode = strongSelf.reactionContextNode { - let reactionPoint = strongSelf.view.convert(localPoint, to: reactionContextNode.view) - let highlightedReaction = reactionContextNode.reaction(at: reactionPoint)?.reaction - if strongSelf.highlightedReaction?.rawValue != highlightedReaction?.rawValue { - strongSelf.highlightedReaction = highlightedReaction - strongSelf.hapticFeedback.tap() - } - } } } } @@ -428,9 +417,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.highlightedActionNode = nil highlightedActionNode.performAction() } - if let highlightedReaction = strongSelf.highlightedReaction { - strongSelf.reactionContextNode?.performReactionSelection(reaction: highlightedReaction, isLarge: false) - } } else { if let highlightedActionNode = strongSelf.highlightedActionNode { strongSelf.highlightedActionNode = nil @@ -479,15 +465,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.hapticFeedback.tap() } } - - if let reactionContextNode = strongSelf.reactionContextNode { - let reactionPoint = strongSelf.view.convert(localPoint, to: reactionContextNode.view) - let highlightedReaction = reactionContextNode.reaction(at: reactionPoint)?.reaction - if strongSelf.highlightedReaction?.rawValue != highlightedReaction?.rawValue { - strongSelf.highlightedReaction = highlightedReaction - strongSelf.hapticFeedback.tap() - } - } } } } @@ -506,10 +483,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.highlightedActionNode = nil highlightedActionNode.performAction() } - - if let highlightedReaction = strongSelf.highlightedReaction { - strongSelf.reactionContextNode?.performReactionSelection(reaction: highlightedReaction, isLarge: false) - } } else { if let highlightedActionNode = strongSelf.highlightedActionNode { strongSelf.highlightedActionNode = nil @@ -593,15 +566,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi actionNode.setIsHighlighted(true) } } - - if let reactionContextNode = self.reactionContextNode { - let reactionPoint = self.view.convert(localPoint, to: reactionContextNode.view) - let highlightedReaction = reactionContextNode.reaction(at: reactionPoint)?.reaction - if self.highlightedReaction?.rawValue != highlightedReaction?.rawValue { - self.highlightedReaction = highlightedReaction - self.hapticFeedback.tap() - } - } } case .ended, .cancelled: if let presentationNode = self.presentationNode { @@ -611,10 +575,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi self.highlightedActionNode = nil highlightedActionNode.setIsHighlighted(false) } - - if let _ = self.reactionContextNode { - self.highlightedReaction = nil - } } default: break @@ -949,10 +909,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi localContentSourceFrame = localSourceFrame } - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateIn(from: CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalProjectedContentViewFrame.1.minY), size: contentParentNode.contentRect.size)) - } - self.actionsContainerNode.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: localSourceFrame.center.x - self.actionsContainerNode.position.x, y: localSourceFrame.center.y - self.actionsContainerNode.position.y + actionsOffset)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: actionsDuration, initialVelocity: 0.0, damping: springDamping, additive: true) let contentContainerOffset = CGPoint(x: localContentSourceFrame.center.x - self.contentContainerNode.frame.center.x - contentParentNode.contentRect.minX, y: localContentSourceFrame.center.y - self.contentContainerNode.frame.center.y - contentParentNode.contentRect.minY) self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentContainerOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: contentDuration, initialVelocity: 0.0, damping: springDamping, additive: true, completion: { [weak self] _ in @@ -1286,10 +1242,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi contentParentNode.updateAbsoluteRect?(self.contentContainerNode.frame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y + contentContainerOffset.y), self.bounds.size) contentParentNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: -contentContainerOffset.y), transitionCurve, transitionDuration) - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateOut(to: CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalProjectedContentViewFrame.1.minY), size: contentParentNode.contentRect.size), animatingOutToReaction: self.reactionContextNodeIsAnimatingOut) - } - contentParentNode.willUpdateIsExtractedToContextPreview?(false, .animated(duration: 0.2, curve: .easeInOut)) } else { if let snapshotView = contentParentNode.contentNode.view.snapshotContentTree(keepTransform: true) { @@ -1308,10 +1260,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi contentParentNode.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) contentParentNode.willUpdateIsExtractedToContextPreview?(false, .animated(duration: 0.2, curve: .easeInOut)) - - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateOut(to: nil, animatingOutToReaction: self.reactionContextNodeIsAnimatingOut) - } } case let .controller(source): guard let maybeContentNode = self.contentContainerNode.contentNode, case let .controller(controller) = maybeContentNode else { @@ -1449,10 +1397,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi completedContentNode = true intermediateCompletion() }) - - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateOut(to: nil, animatingOutToReaction: self.reactionContextNodeIsAnimatingOut) - } } } } @@ -1461,10 +1405,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi if let presentationNode = self.presentationNode { presentationNode.addRelativeContentOffset(offset, transition: transition) } - if self.reactionContextNodeIsAnimatingOut, let reactionContextNode = self.reactionContextNode { - reactionContextNode.bounds = reactionContextNode.bounds.offsetBy(dx: 0.0, dy: offset.y) - transition.animateOffsetAdditive(node: reactionContextNode, offset: -offset.y) - } } func cancelReactionAnimation() { @@ -1520,13 +1460,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi self.currentItems = items self.currentActionsMinHeight = minHeight - - if let reactionContextNode = self.reactionContextNode { - self.reactionContextNode = nil - reactionContextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak reactionContextNode] _ in - reactionContextNode?.removeFromSupernode() - }) - } let previousActionsContainerNode = self.actionsContainerNode let previousActionsContainerFrame = previousActionsContainerNode.view.convert(previousActionsContainerNode.bounds, to: self.view) @@ -1648,11 +1581,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size)) let actionsSideInset: CGFloat = layout.safeInsets.left + 12.0 - var contentTopInset: CGFloat = max(11.0, layout.statusBarHeight ?? 0.0) - - if let _ = self.reactionContextNode { - contentTopInset += 34.0 - } + let contentTopInset: CGFloat = max(11.0, layout.statusBarHeight ?? 0.0) let actionsBottomInset: CGFloat = 11.0 @@ -1897,12 +1826,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi let absoluteContentRect = contentContainerFrame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y) contentParentNode.updateAbsoluteRect?(absoluteContentRect, layout.size) - - if let reactionContextNode = self.reactionContextNode { - let insets = layout.insets(options: [.statusBar]) - transition.updateFrame(node: reactionContextNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - reactionContextNode.updateLayout(size: layout.size, insets: insets, anchorRect: CGRect(origin: CGPoint(x: absoluteContentRect.minX + contentParentNode.contentRect.minX, y: absoluteContentRect.minY + contentParentNode.contentRect.minY), size: contentParentNode.contentRect.size), isAnimatingOut: false, transition: transition) - } } case let .controller(contentParentNode): var projectedFrame: CGRect = convertFrame(contentParentNode.sourceView.bounds, from: contentParentNode.sourceView, to: self.view) @@ -2033,14 +1956,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi transition.animateOffsetAdditive(node: self.scrollNode, offset: currentContainerFrame.minY - previousContainerFrame.minY) } } - - let absoluteContentRect = contentContainerFrame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y) - - if let reactionContextNode = self.reactionContextNode { - let insets = layout.insets(options: [.statusBar]) - transition.updateFrame(node: reactionContextNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - reactionContextNode.updateLayout(size: layout.size, insets: insets, anchorRect: CGRect(origin: CGPoint(x: absoluteContentRect.minX, y: absoluteContentRect.minY), size: contentSize), isAnimatingOut: false, transition: transition) - } } } } @@ -2149,12 +2064,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi return presentationNode.hitTest(self.view.convert(point, to: presentationNode.view), with: event) } - if let reactionContextNode = self.reactionContextNode { - if let result = reactionContextNode.hitTest(self.view.convert(point, to: reactionContextNode.view), with: event) { - return result - } - } - let mappedPoint = self.view.convert(point, to: self.scrollNode.view) var maybePassthrough: ContextController.HandledTouchEvent? if let maybeContentNode = self.contentContainerNode.contentNode { diff --git a/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift b/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift index 95211ba751..b81ca9f64d 100644 --- a/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift @@ -724,11 +724,13 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo var reactionAnchorRect = contentRect.offsetBy(dx: contentParentGlobalFrame.minX, dy: 0.0) let bottomInset = layout.insets(options: [.input]).bottom + var isCoveredByInput = false if reactionAnchorRect.minY > layout.size.height - bottomInset { reactionAnchorRect.origin.y = layout.size.height - bottomInset + isCoveredByInput = true } - reactionContextNode.updateLayout(size: layout.size, insets: UIEdgeInsets(top: topInset, left: layout.safeInsets.left, bottom: 0.0, right: layout.safeInsets.right), anchorRect: reactionAnchorRect, isAnimatingOut: isAnimatingOut, transition: reactionContextNodeTransition) + reactionContextNode.updateLayout(size: layout.size, insets: UIEdgeInsets(top: topInset, left: layout.safeInsets.left, bottom: 0.0, right: layout.safeInsets.right), anchorRect: reactionAnchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: isAnimatingOut, transition: reactionContextNodeTransition) self.proposedReactionsPositionLock = contentRect.minY - 18.0 - reactionContextNode.contentHeight - 46.0 } else { diff --git a/submodules/DebugSettingsUI/Sources/DebugController.swift b/submodules/DebugSettingsUI/Sources/DebugController.swift index da35eaf19e..5a194093d4 100644 --- a/submodules/DebugSettingsUI/Sources/DebugController.swift +++ b/submodules/DebugSettingsUI/Sources/DebugController.swift @@ -573,7 +573,8 @@ private enum DebugControllerEntry: ItemListNodeEntry { }) case .sendNotificationLogs: return ItemListDisclosureItem(presentationData: presentationData, title: "Send Notification Logs (Up to 40 MB)", label: "", sectionId: self.section, style: .blocks, action: { - let _ = (Logger(rootPath: arguments.sharedContext.basePath, basePath: arguments.sharedContext.basePath + "/logs/notification-logs").collectLogs() + let logsPath = arguments.sharedContext.basePath + "/logs/notification-logs" + let _ = (Logger(rootPath: logsPath, basePath: logsPath).collectLogs() |> deliverOnMainQueue).start(next: { logs in let presentationData = arguments.sharedContext.currentPresentationData.with { $0 } let actionSheet = ActionSheetController(presentationData: presentationData) @@ -721,7 +722,8 @@ private enum DebugControllerEntry: ItemListNodeEntry { var logByType: [Signal<(type: String, logs: [(String, String)]), NoError>] = [] for type in logTypes { - logByType.append(Logger(rootPath: arguments.sharedContext.basePath, basePath: arguments.sharedContext.basePath + "/logs/\(type)").collectLogs() + let logsPath = arguments.sharedContext.basePath + "/logs/\(type)" + logByType.append(Logger(rootPath: logsPath, basePath: logsPath).collectLogs() |> map { result -> (type: String, logs: [(String, String)]) in return (type, result) }) diff --git a/submodules/Display/Source/ViewController.swift b/submodules/Display/Source/ViewController.swift index f699db47a4..b732c85d7b 100644 --- a/submodules/Display/Source/ViewController.swift +++ b/submodules/Display/Source/ViewController.swift @@ -375,7 +375,7 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject { } } self.navigationBar?.item = self.navigationItem - self.automaticallyAdjustsScrollViewInsets = false + //self.automaticallyAdjustsScrollViewInsets = false self.scrollToTopWithTabBar = { [weak self] in self?.scrollToTop?() diff --git a/submodules/GameUI/Sources/GameControllerNode.swift b/submodules/GameUI/Sources/GameControllerNode.swift index f86105cecf..d54b1fec04 100644 --- a/submodules/GameUI/Sources/GameControllerNode.swift +++ b/submodules/GameUI/Sources/GameControllerNode.swift @@ -65,8 +65,6 @@ final class GameControllerNode: ViewControllerTracingNode { configuration.allowsInlineMediaPlayback = true if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { configuration.mediaTypesRequiringUserActionForPlayback = [] - } else if #available(iOSApplicationExtension 9.0, iOS 9.0, *) { - configuration.requiresUserActionForMediaPlayback = false } else { configuration.mediaPlaybackRequiresUserAction = false } diff --git a/submodules/Geocoding/Sources/Geocoding.swift b/submodules/Geocoding/Sources/Geocoding.swift index e573efce2f..909196c4a4 100644 --- a/submodules/Geocoding/Sources/Geocoding.swift +++ b/submodules/Geocoding/Sources/Geocoding.swift @@ -1,4 +1,5 @@ import Foundation +import Contacts import CoreLocation import SwiftSignalKit @@ -15,10 +16,10 @@ public func geocodeLocation(address: String) -> Signal<[CLPlacemark]?, NoError> } } -public func geocodeLocation(dictionary: [String: String]) -> Signal<(Double, Double)?, NoError> { +public func geocodeLocation(address: CNPostalAddress) -> Signal<(Double, Double)?, NoError> { return Signal { subscriber in let geocoder = CLGeocoder() - geocoder.geocodeAddressDictionary(dictionary, completionHandler: { placemarks, _ in + geocoder.geocodePostalAddress(address, completionHandler: { placemarks, _ in if let location = placemarks?.first?.location { subscriber.putNext((location.coordinate.latitude, location.coordinate.longitude)) } else { diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCameraCaptureSession.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCameraCaptureSession.h index 499ecdbae8..ba7a214ef1 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCameraCaptureSession.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/PGCameraCaptureSession.h @@ -8,7 +8,10 @@ @interface PGCameraCaptureSession : AVCaptureSession @property (nonatomic, readonly) AVCaptureDevice *videoDevice; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" @property (nonatomic, readonly) AVCaptureStillImageOutput *imageOutput; +#pragma clang diagnostic pop @property (nonatomic, readonly) AVCaptureVideoDataOutput *videoOutput; @property (nonatomic, readonly) AVCaptureAudioDataOutput *audioOutput; @property (nonatomic, readonly) AVCaptureMetadataOutput *metadataOutput; diff --git a/submodules/LegacyComponents/Sources/ActionStage.mm b/submodules/LegacyComponents/Sources/ActionStage.mm index daa7759af3..6d31634fab 100644 --- a/submodules/LegacyComponents/Sources/ActionStage.mm +++ b/submodules/LegacyComponents/Sources/ActionStage.mm @@ -6,7 +6,7 @@ #import "ASActor.h" -#import +#import #include #include @@ -17,8 +17,8 @@ static dispatch_queue_t mainGraphQueue = nil; static dispatch_queue_t globalGraphQueue = nil; static dispatch_queue_t highPriorityGraphQueue = nil; -static volatile OSSpinLock removeWatcherRequestsLock = OS_SPINLOCK_INIT; -static volatile OSSpinLock removeWatcherFromPathRequestsLock = OS_SPINLOCK_INIT; +static os_unfair_lock removeWatcherRequestsLock = OS_UNFAIR_LOCK_INIT; +static os_unfair_lock removeWatcherFromPathRequestsLock = OS_UNFAIR_LOCK_INIT; @interface ActionStage () { @@ -790,11 +790,11 @@ ActionStage *ActionStageInstance() } bool alreadyExecuting = false; - OSSpinLockLock(&removeWatcherRequestsLock); + os_unfair_lock_lock(&removeWatcherRequestsLock); if (!_removeWatcherRequests.empty()) alreadyExecuting = true; _removeWatcherRequests.push_back(watcherGraphHandle); - OSSpinLockUnlock(&removeWatcherRequestsLock); + os_unfair_lock_unlock(&removeWatcherRequestsLock); if (alreadyExecuting && ![self isCurrentQueueStageQueue]) return; @@ -803,10 +803,10 @@ ActionStage *ActionStageInstance() { std::vector removeWatchers; - OSSpinLockLock(&removeWatcherRequestsLock); + os_unfair_lock_lock(&removeWatcherRequestsLock); removeWatchers.insert(removeWatchers.begin(), _removeWatcherRequests.begin(), _removeWatcherRequests.end()); _removeWatcherRequests.clear(); - OSSpinLockUnlock(&removeWatcherRequestsLock); + os_unfair_lock_unlock(&removeWatcherRequestsLock); for (std::vector::iterator it = removeWatchers.begin(); it != removeWatchers.end(); it++) { @@ -894,11 +894,11 @@ ActionStage *ActionStageInstance() } bool alreadyExecuting = false; - OSSpinLockLock(&removeWatcherFromPathRequestsLock); + os_unfair_lock_lock(&removeWatcherFromPathRequestsLock); if (!_removeWatcherFromPathRequests.empty()) alreadyExecuting = true; _removeWatcherFromPathRequests.push_back(std::pair(watcherGraphHandle, watcherPath)); - OSSpinLockUnlock(&removeWatcherFromPathRequestsLock); + os_unfair_lock_unlock(&removeWatcherFromPathRequestsLock); if (alreadyExecuting && ![self isCurrentQueueStageQueue]) return; @@ -907,10 +907,10 @@ ActionStage *ActionStageInstance() { std::vector > removeWatchersFromPath; - OSSpinLockLock(&removeWatcherFromPathRequestsLock); + os_unfair_lock_lock(&removeWatcherFromPathRequestsLock); removeWatchersFromPath.insert(removeWatchersFromPath.begin(), _removeWatcherFromPathRequests.begin(), _removeWatcherFromPathRequests.end()); _removeWatcherFromPathRequests.clear(); - OSSpinLockUnlock(&removeWatcherFromPathRequestsLock); + os_unfair_lock_unlock(&removeWatcherFromPathRequestsLock); if (removeWatchersFromPath.size() > 1) { diff --git a/submodules/LegacyComponents/Sources/POPAnimator.mm b/submodules/LegacyComponents/Sources/POPAnimator.mm index c93a8a8cb0..fa9a6390f1 100644 --- a/submodules/LegacyComponents/Sources/POPAnimator.mm +++ b/submodules/LegacyComponents/Sources/POPAnimator.mm @@ -21,9 +21,7 @@ #import "POPBasicAnimationInternal.h" #import "POPDecayAnimation.h" -#if !TARGET_OS_IPHONE -#import -#endif +#import using namespace std; using namespace POP; @@ -97,7 +95,7 @@ static BOOL _disableBackgroundThread = YES; CFTimeInterval _slowMotionLastTime; CFTimeInterval _slowMotionAccumulator; CFTimeInterval _beginTime; - OSSpinLock _lock; + os_unfair_lock _lock; BOOL _disableDisplayLink; } @end @@ -263,7 +261,7 @@ static POPAnimation *deleteDictEntry(POPAnimator *self, id __unsafe_unretained o POPAnimation *anim = nil; // lock - OSSpinLockLock(&self->_lock); + os_unfair_lock_lock(&self->_lock); NSMutableDictionary *keyAnimationsDict = (__bridge id)CFDictionaryGetValue(self->_dict, (__bridge void *)obj); if (keyAnimationsDict) { @@ -282,7 +280,7 @@ static POPAnimation *deleteDictEntry(POPAnimator *self, id __unsafe_unretained o } // unlock - OSSpinLockUnlock(&self->_lock); + os_unfair_lock_unlock(&self->_lock); return anim; } @@ -299,7 +297,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou if (shouldRemove) { // lock - OSSpinLockLock(&self->_lock); + os_unfair_lock_lock(&self->_lock); // find item in list // may have already been removed on animationDidStop: @@ -311,7 +309,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // unlock - OSSpinLockUnlock(&self->_lock); + os_unfair_lock_unlock(&self->_lock); } } @@ -352,7 +350,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou #endif _dict = POPDictionaryCreateMutableWeakPointerToStrongObject(5); - _lock = OS_SPINLOCK_INIT; + _lock = OS_UNFAIR_LOCK_INIT; return self; } @@ -377,14 +375,14 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou [self _renderTime:(0 != _beginTime) ? _beginTime : time items:_pendingList]; // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); // clear list and observer _pendingList.clear(); [self _clearPendingListObserver]; // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } - (void)_clearPendingListObserver @@ -403,7 +401,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou static const CFIndex POPAnimationApplyRunLoopOrder = CATransactionCommitRunLoopOrder - 1; // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_pendingListObserver) { __weak POPAnimator *weakSelf = self; @@ -418,7 +416,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } - (void)_renderTime:(CFTimeInterval)time items:(std::list)items @@ -432,19 +430,19 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou [delegate animatorWillAnimate:self]; // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); // count active animations const NSUInteger count = items.size(); if (0 == count) { // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } else { // copy list into vector std::vector vector{ std::begin(items), std::end(items) }; // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); for (auto item : vector) { [self _renderTime:time item:item]; @@ -457,13 +455,13 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); // update display link updateDisplayLink(self); // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); // notify delegate and commit [delegate animatorDidAnimate:self]; @@ -541,13 +539,13 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou - (NSArray *)observers { // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); // get observers NSArray *observers = 0 != _observers.count ? [_observers copy] : nil; // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return observers; } @@ -563,7 +561,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); // get key, animation dict associated with object NSMutableDictionary *keyAnimationDict = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj); @@ -577,7 +575,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou POPAnimation *existingAnim = keyAnimationDict[key]; if (existingAnim) { // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (existingAnim == anim) { return; @@ -585,7 +583,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou [self removeAnimationForObject:obj key:key cleanupDict:NO]; // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); } } keyAnimationDict[key] = anim; @@ -604,7 +602,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou updateDisplayLink(self); // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); // schedule runloop processing of pending animations [self _scheduleProcessPendingList]; @@ -613,13 +611,13 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou - (void)removeAllAnimationsForObject:(id)obj { // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); NSArray *animations = [(__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj) allValues]; CFDictionaryRemoveValue(_dict, (__bridge void *)obj); // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (0 == animations.count) { return; @@ -631,7 +629,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); POPAnimatorItemRef item; for (auto iter = _list.begin(); iter != _list.end();) { @@ -644,7 +642,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); for (POPAnimation *anim in animations) { POPAnimationState *state = POPAnimationGetState(anim); @@ -660,7 +658,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); // remove from list POPAnimatorItemRef item; @@ -686,7 +684,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); // stop animation and callout POPAnimationState *state = POPAnimationGetState(anim); @@ -701,27 +699,27 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou - (NSArray *)animationKeysForObject:(id)obj { // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); // get keys NSArray *keys = [(__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj) allKeys]; // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return keys; } - (id)animationForObject:(id)obj key:(NSString *)key { // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); // lookup animation NSDictionary *keyAnimationsDict = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj); POPAnimation *animation = keyAnimationsDict[key]; // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return animation; } @@ -771,7 +769,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_observers) { // use ordered collection for deterministic callout @@ -782,7 +780,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou updateDisplayLink(self); // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } - (void)removeObserver:(id)observer @@ -793,13 +791,13 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou } // lock - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); [_observers removeObject:observer]; updateDisplayLink(self); // unlock - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } @end diff --git a/submodules/LegacyComponents/Sources/TGImageUtils.mm b/submodules/LegacyComponents/Sources/TGImageUtils.mm index 0734f8b066..842ae8b272 100644 --- a/submodules/LegacyComponents/Sources/TGImageUtils.mm +++ b/submodules/LegacyComponents/Sources/TGImageUtils.mm @@ -5,7 +5,7 @@ #import #import -#import +#import #import #import diff --git a/submodules/LegacyComponents/Sources/TGVideoCameraPipeline.m b/submodules/LegacyComponents/Sources/TGVideoCameraPipeline.m index b080133a1d..ecf80f8b94 100644 --- a/submodules/LegacyComponents/Sources/TGVideoCameraPipeline.m +++ b/submodules/LegacyComponents/Sources/TGVideoCameraPipeline.m @@ -2,7 +2,7 @@ #import "LegacyComponentsInternal.h" -#import +#import #import #import #import @@ -69,7 +69,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16; id _watcher; id _liveUploadData; - OSSpinLock _recordLock; + os_unfair_lock _recordLock; bool _startRecordAfterAudioBuffer; CVPixelBufferRef _currentPreviewPixelBuffer; @@ -404,7 +404,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16; CFRelease(blockBuffer); - OSSpinLockLock(&_recordLock); + os_unfair_lock_lock(&_recordLock); if (_startRecordAfterAudioBuffer) { _startRecordAfterAudioBuffer = false; @@ -413,7 +413,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16; [self startRecording:_recordingURL preset:_preset liveUpload:_liveUpload]; }); } - OSSpinLockUnlock(&_recordLock); + os_unfair_lock_unlock(&_recordLock); } } @@ -669,14 +669,14 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16; _preset = preset; _liveUpload = liveUpload; - OSSpinLockLock(&_recordLock); + os_unfair_lock_lock(&_recordLock); if (self.outputAudioFormatDescription == NULL) { _startRecordAfterAudioBuffer = true; - OSSpinLockUnlock(&_recordLock); + os_unfair_lock_unlock(&_recordLock); return; } - OSSpinLockUnlock(&_recordLock); + os_unfair_lock_unlock(&_recordLock); @synchronized (self) { diff --git a/submodules/LocationUI/Sources/CachedGeocodes.swift b/submodules/LocationUI/Sources/CachedGeocodes.swift index bfc039a29b..6c3ebe1054 100644 --- a/submodules/LocationUI/Sources/CachedGeocodes.swift +++ b/submodules/LocationUI/Sources/CachedGeocodes.swift @@ -57,7 +57,7 @@ public func geocodeAddress(engine: TelegramEngine, address: DeviceContactAddress if let cached = cached { return .single((cached.latitude, cached.longitude)) } else { - return geocodeLocation(dictionary: address.dictionary) + return geocodeLocation(address: address.asPostalAddress) |> mapToSignal { coordinate in if let (latitude, longitude) = coordinate { return updateCachedGeocode(engine: engine, address: address, latitude: latitude, longitude: longitude) diff --git a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTInternalId.h b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTInternalId.h index ae5617ec1f..c4bd71d902 100644 --- a/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTInternalId.h +++ b/submodules/MtProtoKit/PublicHeaders/MtProtoKit/MTInternalId.h @@ -3,7 +3,7 @@ #ifndef MtProtoKit_MTInternalId_h #define MtProtoKit_MTInternalId_h -#import +#import #define MTInternalId(name) MT##name##InternalId diff --git a/submodules/MtProtoKit/Sources/MTAtomic.m b/submodules/MtProtoKit/Sources/MTAtomic.m index 72f68f312f..0cf6f29ccc 100644 --- a/submodules/MtProtoKit/Sources/MTAtomic.m +++ b/submodules/MtProtoKit/Sources/MTAtomic.m @@ -1,10 +1,10 @@ #import -#import +#import @interface MTAtomic () { - volatile OSSpinLock _lock; + os_unfair_lock _lock; id _value; } @@ -25,19 +25,19 @@ - (id)swap:(id)newValue { id previousValue = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); previousValue = _value; _value = newValue; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return previousValue; } - (id)value { id previousValue = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); previousValue = _value; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return previousValue; } @@ -45,19 +45,19 @@ - (id)modify:(id (^)(id))f { id newValue = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); newValue = f(_value); _value = newValue; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return newValue; } - (id)with:(id (^)(id))f { id result = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); result = f(_value); - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return result; } diff --git a/submodules/MtProtoKit/Sources/MTContext.m b/submodules/MtProtoKit/Sources/MTContext.m index 146c4db1ef..780038c086 100644 --- a/submodules/MtProtoKit/Sources/MTContext.m +++ b/submodules/MtProtoKit/Sources/MTContext.m @@ -22,7 +22,7 @@ #import -#import +#import #import "MTDiscoverConnectionSignals.h" @@ -176,7 +176,7 @@ static MTDatacenterAuthInfoMapKeyStruct parseAuthInfoMapKeyInteger(NSNumber *key NSMutableDictionary *_periodicTasksTimerByDatacenterId; - volatile OSSpinLock _passwordEntryRequiredLock; + os_unfair_lock _passwordEntryRequiredLock; NSMutableDictionary *_passwordRequiredByDatacenterId; NSMutableDictionary *_transportSchemeDisposableByDatacenterId; @@ -680,20 +680,20 @@ static void copyKeychainKey(NSString * _Nonnull group, NSString * _Nonnull key, - (bool)isPasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId { - OSSpinLockLock(&_passwordEntryRequiredLock); + os_unfair_lock_lock(&_passwordEntryRequiredLock); bool currentValue = [_passwordRequiredByDatacenterId[@(datacenterId)] boolValue]; - OSSpinLockUnlock(&_passwordEntryRequiredLock); + os_unfair_lock_unlock(&_passwordEntryRequiredLock); return currentValue; } - (bool)updatePasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId required:(bool)required { - OSSpinLockLock(&_passwordEntryRequiredLock); + os_unfair_lock_lock(&_passwordEntryRequiredLock); bool currentValue = [_passwordRequiredByDatacenterId[@(datacenterId)] boolValue]; bool updated = currentValue != required; _passwordRequiredByDatacenterId[@(datacenterId)] = @(required); - OSSpinLockUnlock(&_passwordEntryRequiredLock); + os_unfair_lock_unlock(&_passwordEntryRequiredLock); if (updated) { diff --git a/submodules/MtProtoKit/Sources/MTDisposable.m b/submodules/MtProtoKit/Sources/MTDisposable.m index 0912bed35d..cb673e0b68 100644 --- a/submodules/MtProtoKit/Sources/MTDisposable.m +++ b/submodules/MtProtoKit/Sources/MTDisposable.m @@ -1,6 +1,8 @@ #import +#import #import +#import #import @interface MTBlockDisposable () @@ -27,6 +29,8 @@ void *block = _block; if (block != NULL) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (OSAtomicCompareAndSwapPtr(block, 0, &_block)) { if (block != nil) @@ -35,6 +39,7 @@ strongBlock = nil; } } +#pragma clang diagnostic pop } } @@ -43,6 +48,8 @@ void *block = _block; if (block != NULL) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (OSAtomicCompareAndSwapPtr(block, 0, &_block)) { if (block != nil) @@ -52,6 +59,7 @@ strongBlock = nil; } } +#pragma clang diagnostic pop } } @@ -59,7 +67,7 @@ @interface MTMetaDisposable () { - OSSpinLock _lock; + os_unfair_lock _lock; bool _disposed; id _disposable; } @@ -73,14 +81,14 @@ id previousDisposable = nil; bool dispose = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); dispose = _disposed; if (!dispose) { previousDisposable = _disposable; _disposable = disposable; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (previousDisposable != nil) [previousDisposable dispose]; @@ -93,13 +101,13 @@ { id disposable = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_disposed) { disposable = _disposable; _disposed = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (disposable != nil) [disposable dispose]; @@ -109,7 +117,7 @@ @interface MTDisposableSet () { - OSSpinLock _lock; + os_unfair_lock _lock; bool _disposed; id _singleDisposable; NSArray *_multipleDisposables; @@ -126,7 +134,7 @@ bool dispose = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); dispose = _disposed; if (!dispose) { @@ -147,14 +155,14 @@ _singleDisposable = disposable; } } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (dispose) [disposable dispose]; } - (void)remove:(id)disposable { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_multipleDisposables != nil) { NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables]; @@ -165,7 +173,7 @@ { _singleDisposable = nil; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } - (void)dispose @@ -173,7 +181,7 @@ id singleDisposable = nil; NSArray *multipleDisposables = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_disposed) { _disposed = true; @@ -182,7 +190,7 @@ _singleDisposable = nil; _multipleDisposables = nil; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (singleDisposable != nil) [singleDisposable dispose]; diff --git a/submodules/MtProtoKit/Sources/MTMessageTransaction.m b/submodules/MtProtoKit/Sources/MTMessageTransaction.m index d48a1c539d..83d6b95af3 100644 --- a/submodules/MtProtoKit/Sources/MTMessageTransaction.m +++ b/submodules/MtProtoKit/Sources/MTMessageTransaction.m @@ -2,7 +2,12 @@ #import +#import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" MTInternalIdClass(MTMessageTransaction) +#pragma clang diagnostic pop @implementation MTMessageTransaction diff --git a/submodules/MtProtoKit/Sources/MTNetworkUsageManager.m b/submodules/MtProtoKit/Sources/MTNetworkUsageManager.m index 657fb44cc8..de050621c8 100644 --- a/submodules/MtProtoKit/Sources/MTNetworkUsageManager.m +++ b/submodules/MtProtoKit/Sources/MTNetworkUsageManager.m @@ -1,7 +1,7 @@ #import #include -#import +#import #import #import diff --git a/submodules/MtProtoKit/Sources/MTOutgoingMessage.m b/submodules/MtProtoKit/Sources/MTOutgoingMessage.m index 7e0e2dd741..01bdbc48a1 100644 --- a/submodules/MtProtoKit/Sources/MTOutgoingMessage.m +++ b/submodules/MtProtoKit/Sources/MTOutgoingMessage.m @@ -1,5 +1,6 @@ #import +#import #import @interface MTOutgoingMessageInternalId : NSObject @@ -17,7 +18,10 @@ if (self != nil) { static int32_t nextValue = 1; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" _value = OSAtomicIncrement32(&nextValue); +#pragma clang diagnostic pop } return self; } diff --git a/submodules/MtProtoKit/Sources/MTPreparedMessage.m b/submodules/MtProtoKit/Sources/MTPreparedMessage.m index 4be8c60b63..e85cbbf713 100644 --- a/submodules/MtProtoKit/Sources/MTPreparedMessage.m +++ b/submodules/MtProtoKit/Sources/MTPreparedMessage.m @@ -2,7 +2,12 @@ #import +#import + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" MTInternalIdClass(MTPreparedMessage) +#pragma clang diagnostic pop @implementation MTPreparedMessage diff --git a/submodules/MtProtoKit/Sources/MTRequest.m b/submodules/MtProtoKit/Sources/MTRequest.m index bef9245c52..e348537a8c 100644 --- a/submodules/MtProtoKit/Sources/MTRequest.m +++ b/submodules/MtProtoKit/Sources/MTRequest.m @@ -2,6 +2,7 @@ #import +#import #import @interface MTRequestInternalId : NSObject @@ -19,7 +20,10 @@ if (self != nil) { static int32_t nextValue = 1; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" _value = OSAtomicIncrement32(&nextValue); +#pragma clang diagnostic pop } return self; } diff --git a/submodules/MtProtoKit/Sources/MTSignal.m b/submodules/MtProtoKit/Sources/MTSignal.m index 42937568b0..8dc83040e8 100644 --- a/submodules/MtProtoKit/Sources/MTSignal.m +++ b/submodules/MtProtoKit/Sources/MTSignal.m @@ -1,6 +1,6 @@ #import -#import +#import #import #import #import @@ -55,7 +55,7 @@ @interface MTSignalQueueState : NSObject { - OSSpinLock _lock; + os_unfair_lock _lock; bool _executingSignal; bool _terminated; @@ -92,7 +92,7 @@ - (void)enqueueSignal:(MTSignal *)signal { bool startSignal = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_queueMode && _executingSignal) { [_queuedSignals addObject:signal]; @@ -102,7 +102,7 @@ _executingSignal = true; startSignal = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (startSignal) { @@ -130,7 +130,7 @@ MTSignal *nextSignal = nil; bool terminated = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); _executingSignal = false; if (_queueMode) @@ -146,7 +146,7 @@ } else terminated = _terminated; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (terminated) [_subscriber putCompletion]; @@ -174,10 +174,10 @@ - (void)beginCompletion { bool executingSignal = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); executingSignal = _executingSignal; _terminated = true; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (!executingSignal) [_subscriber putCompletion]; diff --git a/submodules/MtProtoKit/Sources/MTSubscriber.m b/submodules/MtProtoKit/Sources/MTSubscriber.m index a32d7956f8..da600346c9 100644 --- a/submodules/MtProtoKit/Sources/MTSubscriber.m +++ b/submodules/MtProtoKit/Sources/MTSubscriber.m @@ -1,6 +1,6 @@ #import -#import +#import @interface MTSubscriberBlocks : NSObject { @public @@ -28,7 +28,7 @@ @interface MTSubscriber () { @protected - OSSpinLock _lock; + os_unfair_lock _lock; bool _terminated; id _disposable; MTSubscriberBlocks *_blocks; @@ -51,13 +51,13 @@ - (void)_assignDisposable:(id)disposable { bool dispose = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_terminated) { dispose = true; } else { _disposable = disposable; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (dispose) { [disposable dispose]; @@ -66,7 +66,7 @@ - (void)_markTerminatedWithoutDisposal { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); MTSubscriberBlocks *blocks = nil; if (!_terminated) { @@ -75,7 +75,7 @@ _terminated = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (blocks) { blocks = nil; @@ -86,11 +86,11 @@ { MTSubscriberBlocks *blocks = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { blocks = _blocks; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (blocks && blocks->_next) { blocks->_next(next); @@ -102,7 +102,7 @@ bool shouldDispose = false; MTSubscriberBlocks *blocks = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { blocks = _blocks; @@ -111,7 +111,7 @@ shouldDispose = true; _terminated = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (blocks && blocks->_error) { blocks->_error(error); @@ -126,7 +126,7 @@ bool shouldDispose = false; MTSubscriberBlocks *blocks = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { blocks = _blocks; @@ -135,7 +135,7 @@ shouldDispose = true; _terminated = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (blocks && blocks->_completed) blocks->_completed(); diff --git a/submodules/MtProtoKit/Sources/MTTcpConnection.m b/submodules/MtProtoKit/Sources/MTTcpConnection.m index 5108b983c5..594f53330d 100644 --- a/submodules/MtProtoKit/Sources/MTTcpConnection.m +++ b/submodules/MtProtoKit/Sources/MTTcpConnection.m @@ -25,6 +25,8 @@ #import +#import + static id get_y2(id x, id mod, id context) { // returns y^2 = x^3 + 486662 * x^2 + x id y = [context clone:x]; @@ -495,7 +497,10 @@ static NSData *executeGenerationCode(id provider, NSData *do @end +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" MTInternalIdClass(MTTcpConnection) +#pragma clang diagnostic pop struct socks5_ident_req { diff --git a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift index 35e5fa4b4c..25312f5cae 100644 --- a/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift +++ b/submodules/PeerInfoUI/Sources/DeviceContactInfoController.swift @@ -727,7 +727,7 @@ private func deviceContactInfoEntries(account: Account, engine: TelegramEngine, var addressIndex = 0 for address in contactData.addresses { - let signal = geocodeLocation(dictionary: address.dictionary) + let signal = geocodeLocation(address: address.asPostalAddress) |> mapToSignal { coordinates -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in if let (latitude, longitude) = coordinates { let resource = MapSnapshotMediaResource(latitude: latitude, longitude: longitude, width: 90, height: 90) diff --git a/submodules/Reachability/LegacyReachability/Sources/LegacyReachability.m b/submodules/Reachability/LegacyReachability/Sources/LegacyReachability.m index ecedbeccbc..d28d36f6c5 100644 --- a/submodules/Reachability/LegacyReachability/Sources/LegacyReachability.m +++ b/submodules/Reachability/LegacyReachability/Sources/LegacyReachability.m @@ -17,6 +17,7 @@ #import #import +#import #import #pragma mark IPv6 Support diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextBackgroundNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextBackgroundNode.swift index 605b7c937f..33a3606a51 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextBackgroundNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextBackgroundNode.swift @@ -118,6 +118,7 @@ final class ReactionContextBackgroundNode: ASDisplayNode { cloudSourcePoint: CGFloat, isLeftAligned: Bool, isMinimized: Bool, + isCoveredByInput: Bool, transition: ContainedViewLayoutTransition ) { let shadowInset: CGFloat = 15.0 @@ -186,6 +187,12 @@ final class ReactionContextBackgroundNode: ASDisplayNode { transition.updateFrame(layer: self.backgroundShadowLayer, frame: backgroundFrame.insetBy(dx: -shadowInset, dy: -shadowInset), beginWithCurrentState: true) transition.updateFrame(layer: self.largeCircleShadowLayer, frame: largeCircleFrame.insetBy(dx: -shadowInset, dy: -shadowInset), beginWithCurrentState: true) + + transition.updateAlpha(layer: self.largeCircleLayer, alpha: isCoveredByInput ? 0.0 : 1.0) + transition.updateAlpha(layer: self.largeCircleShadowLayer, alpha: isCoveredByInput ? 0.0 : 1.0) + transition.updateAlpha(layer: self.smallCircleLayer, alpha: isCoveredByInput ? 0.0 : 1.0) + transition.updateAlpha(layer: self.smallCircleShadowLayer, alpha: isCoveredByInput ? 0.0 : 1.0) + transition.updateFrame(layer: self.smallCircleShadowLayer, frame: smallCircleFrame.insetBy(dx: -shadowInset, dy: -shadowInset), beginWithCurrentState: true) transition.updateFrame(view: self.backgroundView, frame: contentBounds, beginWithCurrentState: true) diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index 9f96919eaf..1bdac50f8d 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -200,7 +200,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { private var highlightedByHover = false private var didTriggerExpandedReaction: Bool = false private var continuousHaptic: Any? - private var validLayout: (CGSize, UIEdgeInsets, CGRect)? + private var validLayout: (CGSize, UIEdgeInsets, CGRect, Bool)? private var isLeftAligned: Bool = true private var itemLayout: ItemLayout? @@ -236,6 +236,9 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { private let emojiSearchDisposable = MetaDisposable() private let emojiSearchResult = Promise<(groups: [EmojiPagerContentComponent.ItemGroup], id: AnyHashable)?>(nil) + private var emptyResultEmojis: [TelegramMediaFile] = [] + private var stableEmptyResultEmoji: TelegramMediaFile? + private let stableEmptyResultEmojiDisposable = MetaDisposable() private var horizontalExpandRecognizer: UIPanGestureRecognizer? private var horizontalExpandStartLocation: CGPoint? @@ -409,6 +412,32 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { }) if let getEmojiContent = getEmojiContent { + let viewKey = PostboxViewKey.orderedItemList(id: Namespaces.OrderedItemList.CloudFeaturedEmojiPacks) + self.stableEmptyResultEmojiDisposable.set((self.context.account.postbox.combinedView(keys: [viewKey]) + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] views in + guard let strongSelf = self, let view = views.views[viewKey] as? OrderedItemListView else { + return + } + var filteredFiles: [TelegramMediaFile] = [] + let filterList: [String] = ["😖", "😫", "🫠", "😨", "❓"] + for featuredEmojiPack in view.items.lazy.map({ $0.contents.get(FeaturedStickerPackItem.self)! }) { + for item in featuredEmojiPack.topItems { + for attribute in item.file.attributes { + switch attribute { + case let .CustomEmoji(_, alt, _): + if filterList.contains(alt) { + filteredFiles.append(item.file) + } + default: + break + } + } + } + } + strongSelf.emptyResultEmojis = filteredFiles + })) + self.emojiContentDisposable = combineLatest(queue: .mainQueue(), getEmojiContent(self.animationCache, self.animationRenderer), self.emojiSearchResult.get() @@ -419,7 +448,22 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { var emojiContent = emojiContent if let emojiSearchResult = emojiSearchResult { - emojiContent = emojiContent.withUpdatedItemGroups(itemGroups: emojiSearchResult.groups, itemContentUniqueId: emojiSearchResult.id) + var emptySearchResults: EmojiPagerContentComponent.EmptySearchResults? + if !emojiSearchResult.groups.contains(where: { !$0.items.isEmpty }) { + if strongSelf.stableEmptyResultEmoji == nil { + strongSelf.stableEmptyResultEmoji = strongSelf.emptyResultEmojis.randomElement() + } + //TODO:localize + emptySearchResults = EmojiPagerContentComponent.EmptySearchResults( + text: "No emoji found", + iconFile: strongSelf.stableEmptyResultEmoji + ) + } else { + strongSelf.stableEmptyResultEmoji = nil + } + emojiContent = emojiContent.withUpdatedItemGroups(itemGroups: emojiSearchResult.groups, itemContentUniqueId: emojiSearchResult.id, emptySearchResults: emptySearchResults) + } else { + strongSelf.stableEmptyResultEmoji = nil } strongSelf.emojiContent = emojiContent @@ -477,6 +521,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { self.hasPremiumDisposable?.dispose() self.genericReactionEffectDisposable?.dispose() self.emojiSearchDisposable.dispose() + self.stableEmptyResultEmojiDisposable.dispose() } override public func didLoad() { @@ -532,8 +577,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } } - public func updateLayout(size: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, isAnimatingOut: Bool, transition: ContainedViewLayoutTransition) { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: isAnimatingOut, transition: transition, animateInFromAnchorRect: nil, animateOutToAnchorRect: nil) + public func updateLayout(size: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, isCoveredByInput: Bool, isAnimatingOut: Bool, transition: ContainedViewLayoutTransition) { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: isAnimatingOut, transition: transition, animateInFromAnchorRect: nil, animateOutToAnchorRect: nil) } public func updateIsIntersectingContent(isIntersectingContent: Bool, transition: ContainedViewLayoutTransition) { @@ -544,8 +589,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { if self.extensionDistance != distance { self.extensionDistance = distance - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: nil, animateOutToAnchorRect: nil) + if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: nil, animateOutToAnchorRect: nil) } } } @@ -818,10 +863,12 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { itemNode.selectionTintView.isHidden = false itemNode.selectionView.isHidden = false } - itemTransition.updateFrame(view: itemNode.selectionTintView, frame: selectionItemFrame.offsetBy(dx: 0.0, dy: self.extensionDistance * 0.5)) + itemTransition.updatePosition(layer: itemNode.selectionTintView.layer, position: selectionItemFrame.center) + itemTransition.updateBounds(layer: itemNode.selectionTintView.layer, bounds: CGRect(origin: CGPoint(), size: selectionItemFrame.size)) itemTransition.updateCornerRadius(layer: itemNode.selectionTintView.layer, cornerRadius: min(selectionItemFrame.width, selectionItemFrame.height) / 2.0) - itemTransition.updateFrame(view: itemNode.selectionView, frame: selectionItemFrame.offsetBy(dx: 0.0, dy: self.extensionDistance * 0.5)) + itemTransition.updatePosition(layer: itemNode.selectionView.layer, position: selectionItemFrame.center) + itemTransition.updateBounds(layer: itemNode.selectionView.layer, bounds: CGRect(origin: CGPoint(), size: selectionItemFrame.size)) itemTransition.updateCornerRadius(layer: itemNode.selectionView.layer, cornerRadius: min(selectionItemFrame.width, selectionItemFrame.height) / 2.0) } @@ -829,13 +876,22 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { itemNode.appear(animated: !self.context.sharedContext.currentPresentationData.with({ $0 }).reduceMotion) } - if self.getEmojiContent != nil && i == itemLayout.visibleItemCount - 1 { - transition.updateSublayerTransformScale(node: itemNode, scale: 0.001 * (1.0 - compressionFactor) + normalItemScale * compressionFactor) + if self.getEmojiContent != nil, i == itemLayout.visibleItemCount - 1, let itemNode = itemNode as? ReactionNode { + let itemScale: CGFloat = 0.001 * (1.0 - compressionFactor) + normalItemScale * compressionFactor + transition.updateSublayerTransformScale(node: itemNode, scale: itemScale) + transition.updateTransformScale(layer: itemNode.selectionView.layer, scale: CGPoint(x: itemScale, y: itemScale)) + transition.updateTransformScale(layer: itemNode.selectionTintView.layer, scale: CGPoint(x: itemScale, y: itemScale)) let alphaFraction = min(compressionFactor, 0.2) / 0.2 transition.updateAlpha(node: itemNode, alpha: alphaFraction) + transition.updateAlpha(layer: itemNode.selectionView.layer, alpha: alphaFraction) + transition.updateAlpha(layer: itemNode.selectionTintView.layer, alpha: alphaFraction) } else { transition.updateSublayerTransformScale(node: itemNode, scale: normalItemScale) + if let itemNode = itemNode as? ReactionNode { + transition.updateSublayerTransformScale(layer: itemNode.selectionView.layer, scale: CGPoint(x: normalItemScale, y: normalItemScale)) + transition.updateSublayerTransformScale(layer: itemNode.selectionTintView.layer, scale: CGPoint(x: normalItemScale, y: normalItemScale)) + } } } } @@ -886,12 +942,12 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } } - private func updateLayout(size: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, isAnimatingOut: Bool, transition: ContainedViewLayoutTransition, animateInFromAnchorRect: CGRect?, animateOutToAnchorRect: CGRect?, animateReactionHighlight: Bool = false) { + private func updateLayout(size: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, isCoveredByInput: Bool, isAnimatingOut: Bool, transition: ContainedViewLayoutTransition, animateInFromAnchorRect: CGRect?, animateOutToAnchorRect: CGRect?, animateReactionHighlight: Bool = false) { if let expandItemView = self.expandItemView { expandItemView.updateTheme(theme: self.presentationData.theme) } - self.validLayout = (size, insets, anchorRect) + self.validLayout = (size, insets, anchorRect, isCoveredByInput) let externalSideInset: CGFloat = 4.0 let sideInset: CGFloat = 6.0 @@ -1068,6 +1124,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { return } strongSelf.scrollNode.isHidden = true + strongSelf.mirrorContentScrollView.isHidden = true }) expandItemView.layer.animateScale(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) expandItemView.tintView.alpha = 0.0 @@ -1095,6 +1152,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { cloudSourcePoint: cloudSourcePoint - visualBackgroundFrame.minX, isLeftAligned: isLeftAligned, isMinimized: self.highlightedReaction != nil && !self.highlightedByHover, + isCoveredByInput: isCoveredByInput, transition: transition ) @@ -1276,11 +1334,13 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } strongSelf.requestUpdateOverlayWantsToBeBelowKeyboard(transition.containedViewLayoutTransition) }, - updateSearchQuery: { [weak self] query in + updateSearchQuery: { [weak self] rawQuery in guard let strongSelf = self else { return } + let query = rawQuery.trimmingCharacters(in: .whitespacesAndNewlines) + if query.isEmpty { strongSelf.emojiSearchDisposable.set(nil) strongSelf.emojiSearchResult.set(.single(nil)) @@ -1288,7 +1348,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { let context = strongSelf.context let languageCode = "en" - var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query, completeMatch: query.count < 2) + var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query, completeMatch: false) if !languageCode.lowercased().hasPrefix("en") { signal = signal |> mapToSignal { keywords in @@ -1315,9 +1375,11 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { |> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in return combineLatest( context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + context.engine.stickers.availableReactions(), hasPremium ) - |> map { view, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in + |> take(1) + |> map { view, availableReactions, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in var result: [(String, TelegramMediaFile?, String)] = [] var allEmoticons: [String: String] = [:] @@ -1369,11 +1431,25 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } return [EmojiPagerContentComponent.ItemGroup( - supergroupId: "search", groupId: "search", title: nil, subtitle: nil, actionButtonTitle: nil, isFeatured: false, isPremiumLocked: false, isEmbedded: false, hasClear: false, collapsedLineCount: nil, displayPremiumBadges: false, headerItem: nil, items: items)] + supergroupId: "search", + groupId: "search", + title: nil, + subtitle: nil, + actionButtonTitle: nil, + isFeatured: false, + isPremiumLocked: false, + isEmbedded: false, + hasClear: false, + collapsedLineCount: nil, + displayPremiumBadges: false, + headerItem: nil, + items: items + )] } } strongSelf.emojiSearchDisposable.set((resultSignal + |> delay(0.15, queue: .mainQueue()) |> deliverOnMainQueue).start(next: { result in guard let strongSelf = self else { return @@ -1396,8 +1472,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { public func animateIn(from sourceAnchorRect: CGRect) { self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: sourceAnchorRect, animateOutToAnchorRect: nil) + if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: sourceAnchorRect, animateOutToAnchorRect: nil) } let mainCircleDelay: Double = 0.01 @@ -1411,6 +1487,10 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { guard let itemNode = self.visibleItemNodes[i] else { continue } + if let itemLayout = self.itemLayout, self.getEmojiContent != nil, i == itemLayout.visibleItemCount - 1 { + itemNode.appear(animated: false) + continue + } let itemDelay: Double if let animateInInfo = self.animateInInfo { @@ -1421,7 +1501,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { } else { itemDelay = mainCircleDelay + Double(i) * 0.06 } - + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + itemDelay * UIView.animationDurationFactor(), execute: { [weak itemNode] in guard let itemNode = itemNode else { return @@ -1475,8 +1555,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { expandItemView.tintView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2) } - if let targetAnchorRect = targetAnchorRect, let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: nil, animateOutToAnchorRect: targetAnchorRect) + if let targetAnchorRect = targetAnchorRect, let (size, insets, anchorRect, isCoveredByInput) = self.validLayout { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: nil, animateOutToAnchorRect: targetAnchorRect) } } @@ -1919,8 +1999,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { self.hapticFeedback = HapticFeedback() } - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .animated(duration: longPressDuration, curve: .linear), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) + if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .animated(duration: longPressDuration, curve: .linear), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) } self.longPressTimer?.invalidate() @@ -1950,8 +2030,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { self.continuousHaptic = nil self.highlightedReaction = nil - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .animated(duration: 0.3, curve: .spring), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) + if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .animated(duration: 0.3, curve: .spring), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) } case .ended: self.longPressTimer?.invalidate() @@ -2027,8 +2107,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { self.hapticFeedback?.tap() } - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .animated(duration: 0.18, curve: .easeInOut), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) + if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .animated(duration: 0.18, curve: .easeInOut), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) } } } @@ -2043,8 +2123,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { if performAction { self.performReactionSelection(reaction: highlightedReaction, isLarge: isLarge) } else { - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .animated(duration: 0.18, curve: .easeInOut), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) + if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .animated(duration: 0.18, curve: .easeInOut), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) } } } @@ -2138,8 +2218,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate { public func setHighlightedReaction(_ value: ReactionItem.Reaction?) { self.highlightedReaction = value - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .animated(duration: 0.18, curve: .easeInOut), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) + if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout { + self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .animated(duration: 0.18, curve: .easeInOut), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) } } } diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift index 2ff7ca8fc1..66ef9faa12 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift @@ -167,17 +167,13 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode { self.animateInAnimationNode?.visibility = true } - self.selectionView.alpha = 1.0 - self.selectionView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.selectionView.layer.animateAlpha(from: 0.0, to: self.selectionView.alpha, duration: 0.2) self.selectionView.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4) - self.selectionTintView.alpha = 1.0 - self.selectionTintView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.selectionTintView.layer.animateAlpha(from: 0.0, to: self.selectionTintView.alpha, duration: 0.2) self.selectionTintView.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4) } else { self.animateInAnimationNode?.completed(true) - self.selectionView.alpha = 1.0 - self.selectionTintView.alpha = 1.0 } } diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SBlockDisposable.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SBlockDisposable.m index bf4eab6806..7a592c0549 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SBlockDisposable.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SBlockDisposable.m @@ -1,7 +1,8 @@ #import "SBlockDisposable.h" -#import +#import #import +#import @interface SBlockDisposable () { @@ -27,6 +28,8 @@ void *block = _block; if (block != NULL) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (OSAtomicCompareAndSwapPtr(block, 0, &_block)) { if (block != nil) @@ -35,6 +38,7 @@ strongBlock = nil; } } +#pragma clang diagnostic pop } } @@ -43,6 +47,8 @@ void *block = _block; if (block != NULL) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" if (OSAtomicCompareAndSwapPtr(block, 0, &_block)) { if (block != nil) @@ -52,6 +58,7 @@ strongBlock = nil; } } +#pragma clang diagnostic pop } } diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SDisposableSet.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SDisposableSet.m index 18cb3be965..d3bc255a91 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SDisposableSet.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SDisposableSet.m @@ -2,11 +2,11 @@ #import "SSignal.h" -#import +#import @interface SDisposableSet () { - OSSpinLock _lock; + os_unfair_lock _lock; bool _disposed; id _singleDisposable; NSArray *_multipleDisposables; @@ -23,7 +23,7 @@ bool dispose = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); dispose = _disposed; if (!dispose) { @@ -44,14 +44,14 @@ _singleDisposable = disposable; } } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (dispose) [disposable dispose]; } - (void)remove:(id)disposable { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_multipleDisposables != nil) { NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables]; @@ -62,7 +62,7 @@ { _singleDisposable = nil; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } - (void)dispose @@ -70,7 +70,7 @@ id singleDisposable = nil; NSArray *multipleDisposables = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_disposed) { _disposed = true; @@ -79,7 +79,7 @@ _singleDisposable = nil; _multipleDisposables = nil; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (singleDisposable != nil) [singleDisposable dispose]; diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SMetaDisposable.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SMetaDisposable.m index 4e9c8e4fab..2b8389307e 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SMetaDisposable.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SMetaDisposable.m @@ -1,10 +1,10 @@ #import "SMetaDisposable.h" -#import +#import @interface SMetaDisposable () { - OSSpinLock _lock; + os_unfair_lock _lock; bool _disposed; id _disposable; } @@ -18,14 +18,14 @@ id previousDisposable = nil; bool dispose = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); dispose = _disposed; if (!dispose) { previousDisposable = _disposable; _disposable = disposable; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (previousDisposable != nil) [previousDisposable dispose]; @@ -38,13 +38,13 @@ { id disposable = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_disposed) { disposable = _disposable; _disposed = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (disposable != nil) [disposable dispose]; diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SMulticastSignalManager.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SMulticastSignalManager.m index 1094852dd5..ee1b71b01a 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SMulticastSignalManager.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SMulticastSignalManager.m @@ -6,11 +6,11 @@ #import "SMetaDisposable.h" #import "SBlockDisposable.h" -#import +#import @interface SMulticastSignalManager () { - OSSpinLock _lock; + os_unfair_lock _lock; NSMutableDictionary *_multicastSignals; NSMutableDictionary *_standaloneSignalDisposables; NSMutableDictionary *_pipeListeners; @@ -35,9 +35,9 @@ - (void)dealloc { NSArray *disposables = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); disposables = [_standaloneSignalDisposables allValues]; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); for (id disposable in disposables) { @@ -56,7 +56,7 @@ } SSignal *signal = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); signal = _multicastSignals[key]; if (signal == nil) { @@ -70,15 +70,15 @@ __strong SMulticastSignalManager *strongSelf = weakSelf; if (strongSelf != nil) { - OSSpinLockLock(&strongSelf->_lock); + os_unfair_lock_lock(&strongSelf->_lock); [strongSelf->_multicastSignals removeObjectForKey:key]; - OSSpinLockUnlock(&strongSelf->_lock); + os_unfair_lock_unlock(&strongSelf->_lock); } }] multicast]; _multicastSignals[key] = signal; } } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return signal; } @@ -89,13 +89,13 @@ return; bool produce = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_standaloneSignalDisposables[key] == nil) { _standaloneSignalDisposables[key] = [[SMetaDisposable alloc] init]; produce = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (produce) { @@ -105,24 +105,24 @@ __strong SMulticastSignalManager *strongSelf = weakSelf; if (strongSelf != nil) { - OSSpinLockLock(&strongSelf->_lock); + os_unfair_lock_lock(&strongSelf->_lock); [strongSelf->_standaloneSignalDisposables removeObjectForKey:key]; - OSSpinLockUnlock(&strongSelf->_lock); + os_unfair_lock_unlock(&strongSelf->_lock); } } completed:^ { __strong SMulticastSignalManager *strongSelf = weakSelf; if (strongSelf != nil) { - OSSpinLockLock(&strongSelf->_lock); + os_unfair_lock_lock(&strongSelf->_lock); [strongSelf->_standaloneSignalDisposables removeObjectForKey:key]; - OSSpinLockUnlock(&strongSelf->_lock); + os_unfair_lock_unlock(&strongSelf->_lock); } }]; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); [(SMetaDisposable *)_standaloneSignalDisposables[key] setDisposable:disposable]; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } } @@ -130,7 +130,7 @@ { return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); SBag *bag = _pipeListeners[key]; if (bag == nil) { @@ -141,26 +141,26 @@ { [subscriber putNext:next]; } copy]]; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return [[SBlockDisposable alloc] initWithBlock:^ { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); SBag *bag = _pipeListeners[key]; [bag removeItem:index]; if ([bag isEmpty]) { [_pipeListeners removeObjectForKey:key]; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); }]; }]; } - (void)putNext:(id)next toMulticastedPipeForKey:(NSString *)key { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); NSArray *pipeListeners = [(SBag *)_pipeListeners[key] copyItems]; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); for (void (^listener)(id) in pipeListeners) { diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSignal+Meta.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSignal+Meta.m index f6ad4124e6..48e1313e9d 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSignal+Meta.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSignal+Meta.m @@ -6,11 +6,11 @@ #import "SAtomic.h" #import "SSignal+Pipe.h" -#import +#import @interface SSignalQueueState : NSObject { - OSSpinLock _lock; + os_unfair_lock _lock; bool _executingSignal; bool _terminated; @@ -49,7 +49,7 @@ - (void)enqueueSignal:(SSignal *)signal { bool startSignal = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_queueMode && _executingSignal) { if (_throttleMode) { [_queuedSignals removeAllObjects]; @@ -61,7 +61,7 @@ _executingSignal = true; startSignal = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (startSignal) { @@ -89,7 +89,7 @@ SSignal *nextSignal = nil; bool terminated = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); _executingSignal = false; if (_queueMode) @@ -105,7 +105,7 @@ } else terminated = _terminated; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (terminated) [_subscriber putCompletion]; @@ -133,10 +133,10 @@ - (void)beginCompletion { bool executingSignal = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); executingSignal = _executingSignal; _terminated = true; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (!executingSignal) [_subscriber putCompletion]; diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSignal+Multicast.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSignal+Multicast.m index 92976cff4a..ca4b7ee8f8 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSignal+Multicast.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSignal+Multicast.m @@ -1,6 +1,6 @@ #import "SSignal+Multicast.h" -#import +#import #import "SBag.h" #import "SBlockDisposable.h" @@ -12,7 +12,7 @@ typedef enum { @interface SSignalMulticastSubscribers : NSObject { - volatile OSSpinLock _lock; + os_unfair_lock _lock; SBag *_subscribers; SSignalMulticastState _state; id _disposable; @@ -40,7 +40,7 @@ typedef enum { - (id)addSubscriber:(SSubscriber *)subscriber start:(bool *)start { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); NSInteger index = [_subscribers addItem:subscriber]; switch (_state) { case SSignalMulticastStateReady: @@ -50,7 +50,7 @@ typedef enum { default: break; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); return [[SBlockDisposable alloc] initWithBlock:^ { @@ -62,7 +62,7 @@ typedef enum { { id currentDisposable = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); [_subscribers removeItem:index]; switch (_state) { case SSignalMulticastStateStarted: @@ -75,7 +75,7 @@ typedef enum { default: break; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); [currentDisposable dispose]; } @@ -83,9 +83,9 @@ typedef enum { - (void)notifyNext:(id)next { NSArray *currentSubscribers = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); currentSubscribers = [_subscribers copyItems]; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); for (SSubscriber *subscriber in currentSubscribers) { @@ -96,10 +96,10 @@ typedef enum { - (void)notifyError:(id)error { NSArray *currentSubscribers = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); currentSubscribers = [_subscribers copyItems]; _state = SSignalMulticastStateCompleted; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); for (SSubscriber *subscriber in currentSubscribers) { @@ -110,10 +110,10 @@ typedef enum { - (void)notifyCompleted { NSArray *currentSubscribers = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); currentSubscribers = [_subscribers copyItems]; _state = SSignalMulticastStateCompleted; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); for (SSubscriber *subscriber in currentSubscribers) { diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSubscriber.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSubscriber.m index e565b7748d..bc3482cc9f 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSubscriber.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SSubscriber.m @@ -1,6 +1,6 @@ #import "SSubscriber.h" -#import +#import @interface SSubscriberBlocks : NSObject { @public @@ -28,7 +28,7 @@ @interface SSubscriber () { @protected - OSSpinLock _lock; + os_unfair_lock _lock; bool _terminated; id _disposable; SSubscriberBlocks *_blocks; @@ -51,13 +51,13 @@ - (void)_assignDisposable:(id)disposable { bool dispose = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_terminated) { dispose = true; } else { _disposable = disposable; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (dispose) { [disposable dispose]; } @@ -65,7 +65,7 @@ - (void)_markTerminatedWithoutDisposal { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); SSubscriberBlocks *blocks = nil; if (!_terminated) { @@ -74,7 +74,7 @@ _terminated = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (blocks) { blocks = nil; @@ -85,11 +85,11 @@ { SSubscriberBlocks *blocks = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { blocks = _blocks; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (blocks && blocks->_next) { blocks->_next(next); @@ -101,7 +101,7 @@ bool shouldDispose = false; SSubscriberBlocks *blocks = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { blocks = _blocks; @@ -110,7 +110,7 @@ shouldDispose = true; _terminated = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (blocks && blocks->_error) { blocks->_error(error); @@ -125,7 +125,7 @@ bool shouldDispose = false; SSubscriberBlocks *blocks = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { blocks = _blocks; @@ -134,7 +134,7 @@ shouldDispose = true; _terminated = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (blocks && blocks->_completed) blocks->_completed(); @@ -179,7 +179,7 @@ - (void)_markTerminatedWithoutDisposal { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { NSLog(@"trace(%@ terminated)", _name); @@ -188,17 +188,17 @@ _error = nil; _completed = nil; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } - (void)putNext:(id)next { void (^fnext)(id) = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) fnext = self->_next; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (fnext) { @@ -214,7 +214,7 @@ bool shouldDispose = false; void (^ferror)(id) = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { ferror = self->_error; @@ -224,7 +224,7 @@ self->_completed = nil; _terminated = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (ferror) { @@ -243,7 +243,7 @@ bool shouldDispose = false; void (^completed)() = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (!_terminated) { completed = self->_completed; @@ -253,7 +253,7 @@ self->_completed = nil; _terminated = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (completed) { diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SThreadPool.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SThreadPool.m index 060ee29c92..8325f573ce 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SThreadPool.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SThreadPool.m @@ -1,6 +1,6 @@ #import "SThreadPool.h" -#import +#import #import #import "SQueue.h" diff --git a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SVariable.m b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SVariable.m index 45eea46a2c..8ee64e6ddf 100644 --- a/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SVariable.m +++ b/submodules/SSignalKit/SSignalKit/Source/SSignalKit/SVariable.m @@ -1,6 +1,6 @@ #import "SVariable.h" -#import +#import #import "SSignal.h" #import "SBag.h" @@ -9,7 +9,7 @@ @interface SVariable () { - OSSpinLock _lock; + os_unfair_lock _lock; id _value; bool _hasValue; SBag *_subscribers; @@ -40,14 +40,14 @@ { return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - OSSpinLockLock(&self->_lock); + os_unfair_lock_lock(&self->_lock); id currentValue = _value; bool hasValue = _hasValue; NSInteger index = [self->_subscribers addItem:[^(id value) { [subscriber putNext:value]; } copy]]; - OSSpinLockUnlock(&self->_lock); + os_unfair_lock_unlock(&self->_lock); if (hasValue) { @@ -56,18 +56,18 @@ return [[SBlockDisposable alloc] initWithBlock:^ { - OSSpinLockLock(&self->_lock); + os_unfair_lock_lock(&self->_lock); [self->_subscribers removeItem:index]; - OSSpinLockUnlock(&self->_lock); + os_unfair_lock_unlock(&self->_lock); }]; }]; } - (void)set:(SSignal *)signal { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); _hasValue = false; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); __weak SVariable *weakSelf = self; [_disposable setDisposable:[signal startWithNext:^(id next) @@ -76,11 +76,11 @@ if (strongSelf != nil) { NSArray *subscribers = nil; - OSSpinLockLock(&strongSelf->_lock); + os_unfair_lock_lock(&strongSelf->_lock); strongSelf->_value = next; strongSelf->_hasValue = true; subscribers = [strongSelf->_subscribers copyItems]; - OSSpinLockUnlock(&strongSelf->_lock); + os_unfair_lock_unlock(&strongSelf->_lock); for (void (^subscriber)(id) in subscribers) { diff --git a/submodules/SSignalKit/SwiftSignalKit/Source/Signal_Reduce.swift b/submodules/SSignalKit/SwiftSignalKit/Source/Signal_Reduce.swift index d42ad64f5b..0bff36ad5f 100644 --- a/submodules/SSignalKit/SwiftSignalKit/Source/Signal_Reduce.swift +++ b/submodules/SSignalKit/SwiftSignalKit/Source/Signal_Reduce.swift @@ -43,7 +43,7 @@ public enum Passthrough { } private final class ReduceQueueState : Disposable { - var lock: OSSpinLock = 0 + var lock = os_unfair_lock() var executingSignal = false var terminated = false @@ -68,7 +68,7 @@ private final class ReduceQueueState : Disposable { func enqueueNext(_ next: T) { var startSignal = false var currentValue: T - OSSpinLockLock(&self.lock) + os_unfair_lock_lock(&self.lock) currentValue = self.value if self.executingSignal { self.queuedValues.append(next) @@ -76,7 +76,7 @@ private final class ReduceQueueState : Disposable { self.executingSignal = true startSignal = true } - OSSpinLockUnlock(&self.lock) + os_unfair_lock_unlock(&self.lock) if startSignal { let disposable = generator(currentValue, next).start(next: { next in @@ -97,9 +97,9 @@ private final class ReduceQueueState : Disposable { } func updateValue(_ value: T) { - OSSpinLockLock(&self.lock) + os_unfair_lock_lock(&self.lock) self.value = value - OSSpinLockUnlock(&self.lock) + os_unfair_lock_unlock(&self.lock) } func headCompleted() { @@ -110,7 +110,7 @@ private final class ReduceQueueState : Disposable { var terminated = false var currentValue: T! - OSSpinLockLock(&self.lock) + os_unfair_lock_lock(&self.lock) self.executingSignal = false if self.queuedValues.count != 0 { nextSignal = self.generator(self.value, self.queuedValues[0]) @@ -120,7 +120,7 @@ private final class ReduceQueueState : Disposable { currentValue = self.value terminated = self.terminated } - OSSpinLockUnlock(&self.lock) + os_unfair_lock_unlock(&self.lock) if terminated { self.subscriber.putNext(currentValue) @@ -154,11 +154,11 @@ private final class ReduceQueueState : Disposable { func beginCompletion() { var executingSignal = false let currentValue: T - OSSpinLockLock(&self.lock) + os_unfair_lock_lock(&self.lock) executingSignal = self.executingSignal self.terminated = true currentValue = self.value - OSSpinLockUnlock(&self.lock) + os_unfair_lock_unlock(&self.lock) if !executingSignal { self.subscriber.putNext(currentValue) diff --git a/submodules/SaveToCameraRoll/Sources/SaveToCameraRoll.swift b/submodules/SaveToCameraRoll/Sources/SaveToCameraRoll.swift index b9d5eb9af7..d059463f7a 100644 --- a/submodules/SaveToCameraRoll/Sources/SaveToCameraRoll.swift +++ b/submodules/SaveToCameraRoll/Sources/SaveToCameraRoll.swift @@ -140,7 +140,6 @@ public func copyToPasteboard(context: AccountContext, postbox: Postbox, mediaRef if case let .data(data) = state, data.complete { return Signal { subscriber in let pasteboard = UIPasteboard.general - pasteboard.setPersistent(true) if mediaReference.media is TelegramMediaImage { if let fileData = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: .mappedIfSafe) { diff --git a/submodules/SettingsUI/Sources/Reactions/QuickReactionSetupController.swift b/submodules/SettingsUI/Sources/Reactions/QuickReactionSetupController.swift index 2e715a2c16..6f785c91fc 100644 --- a/submodules/SettingsUI/Sources/Reactions/QuickReactionSetupController.swift +++ b/submodules/SettingsUI/Sources/Reactions/QuickReactionSetupController.swift @@ -185,7 +185,7 @@ private func quickReactionSetupControllerEntries( dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, availableReactions: availableReactions, - reaction: state.hasReaction ? reactionSettings.quickReaction : nil + reaction: state.hasReaction ? reactionSettings.effectiveQuickReaction(hasPremium: isPremium) : nil )) entries.append(.demoDescription(presentationData.strings.Settings_QuickReactionSetup_DemoInfo)) @@ -354,6 +354,7 @@ public func quickReactionSetupController( chatPeerId: context.account.peerId, selectedItems: selectedItems ), + currentSelection: nil, destinationItemView: { [weak sourceItemNode] in return sourceItemNode?.iconView } diff --git a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index 9388b29999..9d26026883 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -927,16 +927,22 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta case .general, .modal: featured.set(context.account.viewTracker.featuredStickerPacks()) archivedPromise.set(.single(archivedPacks) |> then(context.engine.stickers.archivedStickerPacks() |> map(Optional.init))) - quickReaction = context.account.postbox.preferencesView(keys: [PreferencesKeys.reactionSettings]) - |> map { preferencesView -> MessageReaction.Reaction? in + quickReaction = combineLatest( + context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)), + context.account.postbox.preferencesView(keys: [PreferencesKeys.reactionSettings]) + ) + |> map { peer, preferencesView -> MessageReaction.Reaction? in let reactionSettings: ReactionSettings if let entry = preferencesView.values[PreferencesKeys.reactionSettings], let value = entry.get(ReactionSettings.self) { reactionSettings = value } else { reactionSettings = .default } - - return reactionSettings.quickReaction + var hasPremium = false + if case let .user(user) = peer { + hasPremium = user.isPremium + } + return reactionSettings.effectiveQuickReaction(hasPremium: hasPremium) } |> distinctUntilChanged case .masks: diff --git a/submodules/Stripe/PublicHeaders/Stripe/STPAddress.h b/submodules/Stripe/PublicHeaders/Stripe/STPAddress.h index aeb90ee1f8..5dd179da3f 100755 --- a/submodules/Stripe/PublicHeaders/Stripe/STPAddress.h +++ b/submodules/Stripe/PublicHeaders/Stripe/STPAddress.h @@ -94,6 +94,6 @@ typedef NS_ENUM(NSUInteger, STPBillingAddressFields) { - (BOOL)containsRequiredFields:(STPBillingAddressFields)requiredFields; -+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields; FAUXPAS_IGNORED_ON_LINE(APIAvailability); +//+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields; FAUXPAS_IGNORED_ON_LINE(APIAvailability); @end diff --git a/submodules/Stripe/Sources/STPAddress.m b/submodules/Stripe/Sources/STPAddress.m index 102cd04b72..5576959152 100755 --- a/submodules/Stripe/Sources/STPAddress.m +++ b/submodules/Stripe/Sources/STPAddress.m @@ -91,7 +91,7 @@ countryCode:self.country]); } -+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields { +/*+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields { FAUXPAS_IGNORED_IN_METHOD(APIAvailability); switch (billingAddressFields) { case STPBillingAddressFieldsNone: @@ -100,7 +100,7 @@ case STPBillingAddressFieldsFull: return PKAddressFieldPostalAddress; } -} +}*/ @end diff --git a/submodules/TelegramCallsUI/Sources/CallKitIntegration.swift b/submodules/TelegramCallsUI/Sources/CallKitIntegration.swift index 530ba5f7ad..3629693c2b 100644 --- a/submodules/TelegramCallsUI/Sources/CallKitIntegration.swift +++ b/submodules/TelegramCallsUI/Sources/CallKitIntegration.swift @@ -99,7 +99,7 @@ public final class CallKitIntegration { let handle = INPersonHandle(value: "tg\(peerId.id._internalGetInt64Value())", type: .unknown) let contact = INPerson(personHandle: handle, nameComponents: nil, displayName: displayTitle, image: nil, contactIdentifier: localContactId, customIdentifier: "tg\(peerId.id._internalGetInt64Value())") - let intent = INStartAudioCallIntent(contacts: [contact]) + let intent = INStartAudioCallIntent(destinationType: .normal, contacts: [contact]) let interaction = INInteraction(intent: intent, response: nil) interaction.direction = .outgoing diff --git a/submodules/TelegramCore/Sources/Settings/ReactionSettings.swift b/submodules/TelegramCore/Sources/Settings/ReactionSettings.swift index 25ad5a86ad..4069435c74 100644 --- a/submodules/TelegramCore/Sources/Settings/ReactionSettings.swift +++ b/submodules/TelegramCore/Sources/Settings/ReactionSettings.swift @@ -11,6 +11,21 @@ public struct ReactionSettings: Equatable, Codable { } } +public extension ReactionSettings { + func effectiveQuickReaction(hasPremium: Bool) -> MessageReaction.Reaction { + switch self.quickReaction { + case .builtin: + return self.quickReaction + case .custom: + if hasPremium { + return self.quickReaction + } else { + return ReactionSettings.default.quickReaction + } + } + } +} + func updateReactionSettings(transaction: Transaction, _ f: (ReactionSettings) -> ReactionSettings) { transaction.updatePreferencesEntry(key: PreferencesKeys.reactionSettings, { current in let previous = current?.get(ReactionSettings.self) ?? ReactionSettings.default diff --git a/submodules/TelegramIntents/Sources/TelegramIntents.swift b/submodules/TelegramIntents/Sources/TelegramIntents.swift index c75c83622d..3a6dbd83c6 100644 --- a/submodules/TelegramIntents/Sources/TelegramIntents.swift +++ b/submodules/TelegramIntents/Sources/TelegramIntents.swift @@ -193,12 +193,14 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou nameComponents.givenName = displayTitle } - let recipient = INPerson(personHandle: recipientHandle, nameComponents: nameComponents, displayName: displayTitle, image: nil, contactIdentifier: nil, customIdentifier: "tg\(peer.id.toInt64())") + var personImage: INImage? + if let avatarImage = avatarImage, let avatarImageData = avatarImage.jpegData(compressionQuality: 0.8) { + personImage = INImage(imageData: avatarImageData) + } + + let recipient = INPerson(personHandle: recipientHandle, nameComponents: nameComponents, displayName: displayTitle, image: personImage, contactIdentifier: nil, customIdentifier: "tg\(peer.id.toInt64())") let intent = INSendMessageIntent(recipients: [recipient], content: nil, speakableGroupName: INSpeakableString(spokenPhrase: displayTitle), conversationIdentifier: "tg\(peer.id.toInt64())", serviceName: nil, sender: nil) - if let avatarImage = avatarImage, let avatarImageData = avatarImage.jpegData(compressionQuality: 0.8) { - intent.setImage(INImage(imageData: avatarImageData), forParameterNamed: \.groupName) - } let interaction = INInteraction(intent: intent, response: nil) interaction.direction = .outgoing interaction.groupIdentifier = "sendMessage_\(peer.id.toInt64())" diff --git a/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift b/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift index 21ca0a345c..e3b44c471f 100644 --- a/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift +++ b/submodules/TelegramUI/Components/EmojiStatusSelectionComponent/Sources/EmojiStatusSelectionComponent.swift @@ -210,6 +210,7 @@ public final class EmojiStatusSelectionComponent: Component { self.panelBackgroundView.update(size: self.panelBackgroundView.bounds.size, transition: transition.containedViewLayoutTransition) transition.setFrame(view: self.panelSeparatorView, frame: CGRect(origin: CGPoint(x: 0.0, y: component.hideTopPanel ? -UIScreenPixel : topPanelHeight), size: CGSize(width: keyboardSize.width, height: UIScreenPixel))) + transition.setAlpha(view: self.panelSeparatorView, alpha: component.hideTopPanel ? 0.0 : 1.0) } return availableSize @@ -243,11 +244,17 @@ public final class EmojiStatusSelectionController: ViewController { private var presentationData: PresentationData private var validLayout: ContainerViewLayout? + private let currentSelection: Int64? + private var emojiContentDisposable: Disposable? private var emojiContent: EmojiPagerContentComponent? private var freezeUpdates: Bool = false private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation? + private let emojiSearchDisposable = MetaDisposable() + private let emojiSearchResult = Promise<(groups: [EmojiPagerContentComponent.ItemGroup], id: AnyHashable, emptyResultEmoji: TelegramMediaFile?)?>(nil) + private var stableEmptyResultEmoji: TelegramMediaFile? + private var previewItem: (groupId: AnyHashable, item: EmojiPagerContentComponent.Item)? private var dismissedPreviewItem: (groupId: AnyHashable, item: EmojiPagerContentComponent.Item)? private var previewScreenView: ComponentView? @@ -263,9 +270,12 @@ public final class EmojiStatusSelectionController: ViewController { private var isAnimatingOut: Bool = false private var isDismissed: Bool = false - init(controller: EmojiStatusSelectionController, context: AccountContext, sourceView: UIView?, emojiContent: Signal) { + private var isReactionSearchActive: Bool = false + + init(controller: EmojiStatusSelectionController, context: AccountContext, sourceView: UIView?, emojiContent: Signal, currentSelection: Int64?) { self.controller = controller self.context = context + self.currentSelection = currentSelection if let sourceView = sourceView { self.globalSourceRect = sourceView.convert(sourceView.bounds, to: nil) @@ -303,12 +313,36 @@ public final class EmojiStatusSelectionController: ViewController { self.layer.addSublayer(self.cloudLayer0) self.layer.addSublayer(self.cloudLayer1) - self.emojiContentDisposable = (emojiContent - |> deliverOnMainQueue).start(next: { [weak self] emojiContent in + self.emojiContentDisposable = (combineLatest(queue: .mainQueue(), + emojiContent, + self.emojiSearchResult.get() + ) + |> deliverOnMainQueue).start(next: { [weak self] emojiContent, emojiSearchResult in guard let strongSelf = self else { return } strongSelf.controller?._ready.set(.single(true)) + + var emojiContent = emojiContent + if let emojiSearchResult = emojiSearchResult { + var emptySearchResults: EmojiPagerContentComponent.EmptySearchResults? + if !emojiSearchResult.groups.contains(where: { !$0.items.isEmpty }) { + if strongSelf.stableEmptyResultEmoji == nil { + strongSelf.stableEmptyResultEmoji = emojiSearchResult.emptyResultEmoji + } + //TODO:localize + emptySearchResults = EmojiPagerContentComponent.EmptySearchResults( + text: "No emoji found", + iconFile: strongSelf.stableEmptyResultEmoji + ) + } else { + strongSelf.stableEmptyResultEmoji = nil + } + emojiContent = emojiContent.withUpdatedItemGroups(itemGroups: emojiSearchResult.groups, itemContentUniqueId: emojiSearchResult.id, emptySearchResults: emptySearchResults) + } else { + strongSelf.stableEmptyResultEmoji = nil + } + if strongSelf.emojiContent == nil || !strongSelf.freezeUpdates { strongSelf.emojiContent = emojiContent } @@ -363,7 +397,150 @@ public final class EmojiStatusSelectionController: ViewController { }, requestUpdate: { _ in }, - updateSearchQuery: { _ in + updateSearchQuery: { rawQuery in + guard let strongSelf = self else { + return + } + + let query = rawQuery.trimmingCharacters(in: .whitespacesAndNewlines) + + if query.isEmpty { + strongSelf.emojiSearchDisposable.set(nil) + strongSelf.emojiSearchResult.set(.single(nil)) + } else { + let context = strongSelf.context + + let languageCode = "en" + var signal = context.engine.stickers.searchEmojiKeywords(inputLanguageCode: languageCode, query: query, completeMatch: false) + if !languageCode.lowercased().hasPrefix("en") { + signal = signal + |> mapToSignal { keywords in + return .single(keywords) + |> then( + context.engine.stickers.searchEmojiKeywords(inputLanguageCode: "en-US", query: query, completeMatch: query.count < 3) + |> map { englishKeywords in + return keywords + englishKeywords + } + ) + } + } + + let hasPremium = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + |> map { peer -> Bool in + guard case let .user(user) = peer else { + return false + } + return user.isPremium + } + |> distinctUntilChanged + + let resultSignal = signal + |> mapToSignal { keywords -> Signal<(result: [EmojiPagerContentComponent.ItemGroup], emptyResultEmoji: TelegramMediaFile?), NoError> in + return combineLatest( + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + context.engine.stickers.availableReactions(), + hasPremium + ) + |> take(1) + |> map { view, availableReactions, hasPremium -> (result: [EmojiPagerContentComponent.ItemGroup], emptyResultEmoji: TelegramMediaFile?) in + var result: [(String, TelegramMediaFile?, String)] = [] + + var allEmoticons: [String: String] = [:] + for keyword in keywords { + for emoticon in keyword.emoticons { + allEmoticons[emoticon] = keyword.keyword + } + } + + for entry in view.entries { + guard let item = entry.item as? StickerPackItem else { + continue + } + for attribute in item.file.attributes { + switch attribute { + case let .CustomEmoji(_, alt, _): + if !item.file.isPremiumEmoji || hasPremium { + if !alt.isEmpty, let keyword = allEmoticons[alt] { + result.append((alt, item.file, keyword)) + } else if alt == query { + result.append((alt, item.file, alt)) + } + } + default: + break + } + } + } + + var items: [EmojiPagerContentComponent.Item] = [] + + var existingIds = Set() + for item in result { + if let itemFile = item.1 { + if existingIds.contains(itemFile.fileId) { + continue + } + existingIds.insert(itemFile.fileId) + let animationData = EntityKeyboardAnimationData(file: itemFile) + let item = EmojiPagerContentComponent.Item( + animationData: animationData, + content: .animation(animationData), + itemFile: itemFile, subgroupId: nil, + icon: .none, + accentTint: false + ) + items.append(item) + } + } + + var emptyResultEmoji: TelegramMediaFile? + if let availableReactions = availableReactions { + //let reactionFilter: [String] = ["😖", "😫", "🫠", "😨", "❓"] + let filteredReactions: [TelegramMediaFile] = availableReactions.reactions.compactMap { reaction -> TelegramMediaFile? in + switch reaction.value { + case let .builtin(value): + let _ = value + //if reactionFilter.contains(value) { + return reaction.selectAnimation + /*} else { + return nil + }*/ + case .custom: + return nil + } + } + emptyResultEmoji = filteredReactions.randomElement() + } + + return (result: [EmojiPagerContentComponent.ItemGroup( + supergroupId: "search", + groupId: "search", + title: nil, + subtitle: nil, + actionButtonTitle: nil, + isFeatured: false, + isPremiumLocked: false, + isEmbedded: false, + hasClear: false, + collapsedLineCount: nil, + displayPremiumBadges: false, + headerItem: nil, + items: items + )], + emptyResultEmoji: emptyResultEmoji + ) + } + } + + strongSelf.emojiSearchDisposable.set((resultSignal + |> delay(0.15, queue: .mainQueue()) + |> deliverOnMainQueue).start(next: { result in + guard let strongSelf = self else { + return + } + strongSelf.emojiSearchResult.set(.single((result.result, AnyHashable(query), result.emptyResultEmoji))) + })) + } }, chatPeerId: nil, peekBehavior: nil, @@ -395,6 +572,7 @@ public final class EmojiStatusSelectionController: ViewController { self.emojiContentDisposable?.dispose() self.availableReactionsDisposable?.dispose() self.genericReactionEffectDisposable?.dispose() + self.emojiSearchDisposable.dispose() } private func refreshLayout(transition: Transition) { @@ -661,8 +839,14 @@ public final class EmojiStatusSelectionController: ViewController { emojiContent: emojiContent, backgroundColor: listBackgroundColor, separatorColor: separatorColor, - hideTopPanel: false, - hideTopPanelUpdated: { _, _ in } + hideTopPanel: self.isReactionSearchActive, + hideTopPanelUpdated: { [weak self] hideTopPanel, transition in + guard let strongSelf = self else { + return + } + strongSelf.isReactionSearchActive = hideTopPanel + strongSelf.refreshLayout(transition: transition) + } )), environment: {}, containerSize: CGSize(width: componentWidth, height: min(308.0, layout.size.height)) @@ -920,6 +1104,13 @@ public final class EmojiStatusSelectionController: ViewController { } else { self.freezeUpdates = true + if case .statusSelection = controller.mode, let item = item, let currentSelection = self.currentSelection, item.itemFile?.fileId.id == currentSelection { + let _ = (self.context.engine.accountData.setEmojiStatus(file: nil, expirationDate: nil) + |> deliverOnMainQueue).start() + controller.dismiss() + return + } + if let _ = item, let destinationView = controller.destinationItemView() { if let snapshotView = destinationView.snapshotView(afterScreenUpdates: false) { snapshotView.frame = destinationView.frame @@ -1026,6 +1217,7 @@ public final class EmojiStatusSelectionController: ViewController { private let context: AccountContext private weak var sourceView: UIView? private let emojiContent: Signal + private let currentSelection: Int64? private let mode: Mode private let destinationItemView: () -> UIView? @@ -1034,11 +1226,16 @@ public final class EmojiStatusSelectionController: ViewController { return self._ready } - public init(context: AccountContext, mode: Mode, sourceView: UIView, emojiContent: Signal, destinationItemView: @escaping () -> UIView?) { + override public var overlayWantsToBeBelowKeyboard: Bool { + return true + } + + public init(context: AccountContext, mode: Mode, sourceView: UIView, emojiContent: Signal, currentSelection: Int64?, destinationItemView: @escaping () -> UIView?) { self.context = context self.mode = mode self.sourceView = sourceView self.emojiContent = emojiContent + self.currentSelection = currentSelection self.destinationItemView = destinationItemView super.init(navigationBarPresentationData: nil) @@ -1068,7 +1265,7 @@ public final class EmojiStatusSelectionController: ViewController { } override public func loadDisplayNode() { - self.displayNode = Node(controller: self, context: self.context, sourceView: self.sourceView, emojiContent: self.emojiContent) + self.displayNode = Node(controller: self, context: self.context, sourceView: self.sourceView, emojiContent: self.emojiContent, currentSelection: self.currentSelection) super.displayNodeDidLoad() } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/BUILD b/submodules/TelegramUI/Components/EntityKeyboard/BUILD index 59b25623e3..5298ee819c 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/BUILD +++ b/submodules/TelegramUI/Components/EntityKeyboard/BUILD @@ -29,14 +29,12 @@ swift_library( "//submodules/TelegramUI/Components/VideoAnimationCache:VideoAnimationCache", "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", "//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView", + "//submodules/TelegramUI/Components/EmojiStatusComponent:EmojiStatusComponent", "//submodules/SoftwareVideo:SoftwareVideo", "//submodules/ShimmerEffect:ShimmerEffect", "//submodules/PhotoResources:PhotoResources", "//submodules/StickerResources:StickerResources", "//submodules/AppBundle:AppBundle", - #"//submodules/ContextUI:ContextUI", - #"//submodules/PremiumUI:PremiumUI", - #"//submodules/StickerPeekUI:StickerPeekUI", "//submodules/UndoUI:UndoUI", "//submodules/Components/MultilineTextComponent:MultilineTextComponent", "//submodules/Components/SolidRoundedButtonComponent:SolidRoundedButtonComponent", diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 3f93fbfd84..309d8a5664 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -22,6 +22,7 @@ import UndoUI import AudioToolbox import SolidRoundedButtonComponent import EmojiTextAttachmentView +import EmojiStatusComponent private let premiumBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white) private let featuredBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PanelBadgeAdd"), color: .white) @@ -1512,6 +1513,7 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { private struct Params: Equatable { var theme: PresentationTheme var strings: PresentationStrings + var text: String var useOpaqueTheme: Bool var isActive: Bool var size: CGSize @@ -1523,6 +1525,9 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { if lhs.strings !== rhs.strings { return false } + if lhs.text != rhs.text { + return false + } if lhs.useOpaqueTheme != rhs.useOpaqueTheme { return false } @@ -1551,6 +1556,11 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { private let searchIconView: UIImageView private let searchIconTintView: UIImageView + + private let clearIconView: UIImageView + private let clearIconTintView: UIImageView + private let clearIconButton: HighlightTrackingButton + private let tintTextView: ComponentView private let textView: ComponentView private let cancelButtonTintTitle: ComponentView @@ -1580,6 +1590,13 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { self.searchIconView = UIImageView() self.searchIconTintView = UIImageView() + self.clearIconView = UIImageView() + self.clearIconTintView = UIImageView() + self.clearIconButton = HighlightableButton() + self.clearIconView.isHidden = true + self.clearIconTintView.isHidden = true + self.clearIconButton.isHidden = true + self.tintTextView = ComponentView() self.textView = ComponentView() self.cancelButtonTintTitle = ComponentView() @@ -1594,6 +1611,10 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { self.addSubview(self.searchIconView) self.tintContainerView.addSubview(self.searchIconTintView) + self.addSubview(self.clearIconView) + self.tintContainerView.addSubview(self.clearIconTintView) + self.addSubview(self.clearIconButton) + self.addSubview(self.cancelButton) self.clipsToBounds = true @@ -1627,6 +1648,23 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { } } self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), for: .touchUpInside) + + self.clearIconButton.highligthedChanged = { [weak self] highlighted in + if let strongSelf = self { + if highlighted { + strongSelf.clearIconView.layer.removeAnimation(forKey: "opacity") + strongSelf.clearIconView.alpha = 0.4 + strongSelf.clearIconTintView.layer.removeAnimation(forKey: "opacity") + strongSelf.clearIconTintView.alpha = 0.4 + } else { + strongSelf.clearIconView.alpha = 1.0 + strongSelf.clearIconView.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + strongSelf.clearIconTintView.alpha = 1.0 + strongSelf.clearIconTintView.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2) + } + } + } + self.clearIconButton.addTarget(self, action: #selector(self.clearPressed), for: .touchUpInside) } required public init?(coder: NSCoder) { @@ -1641,7 +1679,7 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { let textField = EmojiSearchTextField(frame: textFieldFrame) self.textField = textField - self.addSubview(textField) + self.insertSubview(textField, belowSubview: self.clearIconView) textField.delegate = self textField.addTarget(self, action: #selector(self.textFieldChanged(_:)), for: .editingChanged) } @@ -1655,6 +1693,10 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { @objc private func cancelPressed() { self.updateQuery("") + self.clearIconView.isHidden = true + self.clearIconTintView.isHidden = true + self.clearIconButton.isHidden = true + if let textField = self.textField { self.textField = nil @@ -1664,6 +1706,15 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { self.deactivated() } + @objc private func clearPressed() { + self.updateQuery("") + self.textField?.text = "" + + self.clearIconView.isHidden = true + self.clearIconTintView.isHidden = true + self.clearIconButton.isHidden = true + } + public func textFieldDidBeginEditing(_ textField: UITextField) { } @@ -1673,7 +1724,13 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { @objc private func textFieldChanged(_ textField: UITextField) { self.update(transition: .immediate) - self.updateQuery(textField.text ?? "") + let text = textField.text ?? "" + + self.clearIconView.isHidden = text.isEmpty + self.clearIconTintView.isHidden = text.isEmpty + self.clearIconButton.isHidden = text.isEmpty + + self.updateQuery(text) } private func update(transition: Transition) { @@ -1681,13 +1738,14 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { return } self.params = nil - self.update(theme: params.theme, strings: params.strings, useOpaqueTheme: params.useOpaqueTheme, isActive: params.isActive, size: params.size, transition: transition) + self.update(theme: params.theme, strings: params.strings, text: params.text, useOpaqueTheme: params.useOpaqueTheme, isActive: params.isActive, size: params.size, transition: transition) } - public func update(theme: PresentationTheme, strings: PresentationStrings, useOpaqueTheme: Bool, isActive: Bool, size: CGSize, transition: Transition) { + public func update(theme: PresentationTheme, strings: PresentationStrings, text: String, useOpaqueTheme: Bool, isActive: Bool, size: CGSize, transition: Transition) { let params = Params( theme: theme, strings: strings, + text: text, useOpaqueTheme: useOpaqueTheme, isActive: isActive, size: size @@ -1700,6 +1758,9 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { if self.params?.theme !== theme { self.searchIconView.image = generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Loupe"), color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor) self.searchIconTintView.image = generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Loupe"), color: .white) + + self.clearIconView.image = generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor) + self.clearIconTintView.image = generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Clear"), color: .white) } self.params = params @@ -1721,11 +1782,10 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { self.backgroundLayer.cornerRadius = inputHeight * 0.5 self.tintBackgroundLayer.cornerRadius = inputHeight * 0.5 - //TODO:localize let textSize = self.textView.update( transition: .immediate, component: AnyComponent(Text( - text: "Search Reactions", + text: text, font: Font.regular(17.0), color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor )), @@ -1735,7 +1795,7 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { let _ = self.tintTextView.update( transition: .immediate, component: AnyComponent(Text( - text: "Search Reactions", + text: text, font: Font.regular(17.0), color: .white )), @@ -1785,6 +1845,13 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { transition.setFrame(view: self.searchIconTintView, frame: iconFrame) } + if let image = self.clearIconView.image { + let iconFrame = CGRect(origin: CGPoint(x: backgroundFrame.maxX - image.size.width - 4.0, y: backgroundFrame.minY + floor((backgroundFrame.height - image.size.height) / 2.0)), size: image.size) + transition.setFrame(view: self.clearIconView, frame: iconFrame) + transition.setFrame(view: self.clearIconTintView, frame: iconFrame) + transition.setFrame(view: self.clearIconButton, frame: iconFrame.insetBy(dx: -8.0, dy: -10.0)) + } + if let textComponentView = self.textView.view { if textComponentView.superview == nil { self.addSubview(textComponentView) @@ -1830,6 +1897,99 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate { } } +private final class EmptySearchResultsView: UIView { + override public static var layerClass: AnyClass { + return PassthroughLayer.self + } + + let tintContainerView: UIView + let titleLabel: ComponentView + let titleTintLabel: ComponentView + let icon: ComponentView + + override init(frame: CGRect) { + self.tintContainerView = UIView() + + self.titleLabel = ComponentView() + self.titleTintLabel = ComponentView() + self.icon = ComponentView() + + super.init(frame: frame) + + (self.layer as? PassthroughLayer)?.mirrorLayer = self.tintContainerView.layer + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(context: AccountContext, theme: PresentationTheme, useOpaqueTheme: Bool, text: String, file: TelegramMediaFile?, size: CGSize, transition: Transition) { + let titleColor: UIColor + if useOpaqueTheme { + titleColor = theme.chat.inputMediaPanel.panelContentControlOpaqueOverlayColor + } else { + titleColor = theme.chat.inputMediaPanel.panelContentControlVibrantOverlayColor + } + + let iconSize: CGSize + if let file = file { + iconSize = self.icon.update( + transition: .immediate, + component: AnyComponent(EmojiStatusComponent( + context: context, + animationCache: context.animationCache, + animationRenderer: context.animationRenderer, + content: .animation(content: .file(file: file), size: CGSize(width: 32.0, height: 32.0), placeholderColor: titleColor, themeColor: nil, loopMode: .forever), + isVisibleForAnimations: true, + action: nil + )), + environment: {}, + containerSize: CGSize(width: 32.0, height: 32.0) + ) + } else { + iconSize = CGSize() + } + + let titleSize = self.titleLabel.update( + transition: .immediate, + component: AnyComponent(Text(text: text, font: Font.regular(15.0), color: titleColor)), + environment: {}, + containerSize: CGSize(width: size.width, height: 100.0) + ) + let _ = self.titleTintLabel.update( + transition: .immediate, + component: AnyComponent(Text(text: text, font: Font.regular(15.0), color: .white)), + environment: {}, + containerSize: CGSize(width: size.width, height: 100.0) + ) + + let spacing: CGFloat = 4.0 + let contentHeight = iconSize.height + spacing + titleSize.height + let contentOriginY = floor((size.height - contentHeight) / 2.0) + let iconFrame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: contentOriginY), size: iconSize) + let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: iconFrame.maxY + spacing), size: titleSize) + + if let iconView = self.icon.view { + if iconView.superview == nil { + self.addSubview(iconView) + } + transition.setFrame(view: iconView, frame: iconFrame) + } + if let titleLabelView = self.titleLabel.view { + if titleLabelView.superview == nil { + self.addSubview(titleLabelView) + } + transition.setFrame(view: titleLabelView, frame: titleFrame) + } + if let titleTintLabelView = self.titleTintLabel.view { + if titleTintLabelView.superview == nil { + self.tintContainerView.addSubview(titleTintLabelView) + } + transition.setFrame(view: titleTintLabelView, frame: titleFrame) + } + } +} + public protocol EmojiContentPeekBehavior: AnyObject { func setGestureRecognizerEnabled(view: UIView, isEnabled: Bool, itemAtPoint: @escaping (CGPoint) -> (AnyHashable, EmojiPagerContentComponent.View.ItemLayer, TelegramMediaFile)?) } @@ -2149,6 +2309,26 @@ public final class EmojiPagerContentComponent: Component { case detailed } + public final class EmptySearchResults: Equatable { + public let text: String + public let iconFile: TelegramMediaFile? + + public init(text: String, iconFile: TelegramMediaFile?) { + self.text = text + self.iconFile = iconFile + } + + public static func ==(lhs: EmptySearchResults, rhs: EmptySearchResults) -> Bool { + if lhs.text != rhs.text { + return false + } + if lhs.iconFile?.fileId != rhs.iconFile?.fileId { + return false + } + return true + } + } + public let id: AnyHashable public let context: AccountContext public let avatarPeer: EnginePeer? @@ -2159,7 +2339,8 @@ public final class EmojiPagerContentComponent: Component { public let itemLayoutType: ItemLayoutType public let itemContentUniqueId: AnyHashable? public let warpContentsOnEdges: Bool - public let displaySearch: Bool + public let displaySearchWithPlaceholder: String? + public let emptySearchResults: EmptySearchResults? public let enableLongPress: Bool public let selectedItems: Set @@ -2174,7 +2355,8 @@ public final class EmojiPagerContentComponent: Component { itemLayoutType: ItemLayoutType, itemContentUniqueId: AnyHashable?, warpContentsOnEdges: Bool, - displaySearch: Bool, + displaySearchWithPlaceholder: String?, + emptySearchResults: EmptySearchResults?, enableLongPress: Bool, selectedItems: Set ) { @@ -2188,12 +2370,13 @@ public final class EmojiPagerContentComponent: Component { self.itemLayoutType = itemLayoutType self.itemContentUniqueId = itemContentUniqueId self.warpContentsOnEdges = warpContentsOnEdges - self.displaySearch = displaySearch + self.displaySearchWithPlaceholder = displaySearchWithPlaceholder + self.emptySearchResults = emptySearchResults self.enableLongPress = enableLongPress self.selectedItems = selectedItems } - public func withUpdatedItemGroups(itemGroups: [ItemGroup], itemContentUniqueId: AnyHashable?) -> EmojiPagerContentComponent { + public func withUpdatedItemGroups(itemGroups: [ItemGroup], itemContentUniqueId: AnyHashable?, emptySearchResults: EmptySearchResults?) -> EmojiPagerContentComponent { return EmojiPagerContentComponent( id: self.id, context: self.context, @@ -2205,7 +2388,8 @@ public final class EmojiPagerContentComponent: Component { itemLayoutType: self.itemLayoutType, itemContentUniqueId: itemContentUniqueId, warpContentsOnEdges: self.warpContentsOnEdges, - displaySearch: self.displaySearch, + displaySearchWithPlaceholder: self.displaySearchWithPlaceholder, + emptySearchResults: emptySearchResults, enableLongPress: self.enableLongPress, selectedItems: self.selectedItems ) @@ -2242,7 +2426,10 @@ public final class EmojiPagerContentComponent: Component { if lhs.warpContentsOnEdges != rhs.warpContentsOnEdges { return false } - if lhs.displaySearch != rhs.displaySearch { + if lhs.displaySearchWithPlaceholder != rhs.displaySearchWithPlaceholder { + return false + } + if lhs.emptySearchResults != rhs.emptySearchResults { return false } if lhs.enableLongPress != rhs.enableLongPress { @@ -3017,6 +3204,7 @@ public final class EmojiPagerContentComponent: Component { private let placeholdersContainerView: UIView private var visibleSearchHeader: EmojiSearchHeaderView? + private var visibleEmptySearchResultsView: EmptySearchResultsView? private var visibleItemPlaceholderViews: [ItemLayer.Key: ItemPlaceholderView] = [:] private var visibleItemSelectionLayers: [ItemLayer.Key: ItemSelectionLayer] = [:] private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:] @@ -3856,7 +4044,7 @@ public final class EmojiPagerContentComponent: Component { for (id, layer) in self.visibleItemLayers { previousVisibleLayers[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) } - var previousVisibleItemSelectionLayers: [ItemLayer.Key: (CALayer, CGRect)] = [:] + var previousVisibleItemSelectionLayers: [ItemLayer.Key: (ItemSelectionLayer, CGRect)] = [:] for (id, layer) in self.visibleItemSelectionLayers { previousVisibleItemSelectionLayers[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) } @@ -3980,6 +4168,10 @@ public final class EmojiPagerContentComponent: Component { for (_, layer) in self.visibleItemLayers { layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) } + for (_, layer) in self.visibleItemSelectionLayers { + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, layerAndFrame) in previousVisibleLayers { if self.visibleItemLayers[id] != nil { continue @@ -3990,6 +4182,19 @@ public final class EmojiPagerContentComponent: Component { layer?.removeFromSuperlayer() }) } + for (id, layerAndFrame) in previousVisibleItemSelectionLayers { + if self.visibleItemSelectionLayers[id] != nil { + continue + } + let layer = layerAndFrame.0 + self.scrollView.layer.addSublayer(layer) + let tintContainerLayer = layer.tintContainerLayer + self.mirrorContentScrollView.layer.addSublayer(tintContainerLayer) + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak layer, weak tintContainerLayer] _ in + layer?.removeFromSuperlayer() + tintContainerLayer?.removeFromSuperlayer() + }) + } for (_, view) in self.visibleItemPlaceholderViews { view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) @@ -4163,8 +4368,11 @@ public final class EmojiPagerContentComponent: Component { let layer = layerAndFrame.0 layer.frame = layerAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY) self.scrollView.layer.addSublayer(layer) - layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak layer] _ in + let tintContainerLayer = layer.tintContainerLayer + self.mirrorContentScrollView.layer.addSublayer(tintContainerLayer) + layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -commonItemOffset), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true, completion: { [weak layer, weak tintContainerLayer] _ in layer?.removeFromSuperlayer() + tintContainerLayer?.removeFromSuperlayer() }) } @@ -5073,7 +5281,7 @@ public final class EmojiPagerContentComponent: Component { } } - itemSelectionLayer.frame = baseItemFrame + itemTransition.setFrame(layer: itemSelectionLayer, frame: baseItemFrame) itemLayer.transform = CATransform3DMakeScale(0.8, 0.8, 1.0) } else { @@ -5455,10 +5663,10 @@ public final class EmojiPagerContentComponent: Component { longTapRecognizer.isEnabled = component.enableLongPress } if let tapRecognizer = self.tapRecognizer { - tapRecognizer.isEnabled = component.enableLongPress + tapRecognizer.isEnabled = component.enableLongPress || component.inputInteractionHolder.inputInteraction?.peekBehavior != nil } if let contextGesture = self.contextGesture { - contextGesture.isEnabled = !component.enableLongPress + contextGesture.isEnabled = !component.enableLongPress && component.inputInteractionHolder.inputInteraction?.peekBehavior == nil } if let shimmerHostView = self.shimmerHostView { @@ -5621,7 +5829,7 @@ public final class EmojiPagerContentComponent: Component { itemGroups: itemGroups, expandedGroupIds: self.expandedGroupIds, curveNearBounds: component.warpContentsOnEdges, - displaySearch: component.displaySearch, + displaySearch: component.displaySearchWithPlaceholder != nil, isSearchActivated: self.isSearchActivated, customLayout: component.inputInteractionHolder.inputInteraction?.customLayout ) @@ -5648,7 +5856,7 @@ public final class EmojiPagerContentComponent: Component { transition.setPosition(view: self.scrollView, position: CGPoint(x: 0.0, y: scrollOriginY)) let previousSize = self.scrollView.bounds.size var resetScrolling = false - if self.scrollView.bounds.isEmpty && component.displaySearch { + if self.scrollView.bounds.isEmpty && component.displaySearchWithPlaceholder != nil { resetScrolling = true } if previousComponent?.itemContentUniqueId != component.itemContentUniqueId { @@ -5747,7 +5955,7 @@ public final class EmojiPagerContentComponent: Component { } if resetScrolling { - if component.displaySearch && !self.isSearchActivated { + if component.displaySearchWithPlaceholder != nil && !self.isSearchActivated { self.scrollView.bounds = CGRect(origin: CGPoint(x: 0.0, y: 50.0), size: scrollSize) } else { self.scrollView.bounds = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: scrollSize) @@ -5797,7 +6005,9 @@ public final class EmojiPagerContentComponent: Component { } } - if component.displaySearch { + let useOpaqueTheme = component.inputInteractionHolder.inputInteraction?.useOpaqueTheme ?? false + + if let displaySearchWithPlaceholder = component.displaySearchWithPlaceholder { let visibleSearchHeader: EmojiSearchHeaderView if let current = self.visibleSearchHeader { visibleSearchHeader = current @@ -5842,12 +6052,10 @@ public final class EmojiPagerContentComponent: Component { } } - let useOpaqueTheme = component.inputInteractionHolder.inputInteraction?.useOpaqueTheme ?? false - let searchHeaderFrame = CGRect(origin: CGPoint(x: itemLayout.searchInsets.left, y: itemLayout.searchInsets.top), size: CGSize(width: itemLayout.width - itemLayout.searchInsets.left - itemLayout.searchInsets.right, height: itemLayout.searchHeight)) - visibleSearchHeader.update(theme: keyboardChildEnvironment.theme, strings: keyboardChildEnvironment.strings, useOpaqueTheme: useOpaqueTheme, isActive: self.isSearchActivated, size: searchHeaderFrame.size, transition: transition) - transition.setFrame(view: visibleSearchHeader, frame: searchHeaderFrame, completion: { [weak self] _ in - guard let strongSelf = self, let visibleSearchHeader = strongSelf.visibleSearchHeader else { + visibleSearchHeader.update(theme: keyboardChildEnvironment.theme, strings: keyboardChildEnvironment.strings, text: displaySearchWithPlaceholder, useOpaqueTheme: useOpaqueTheme, isActive: self.isSearchActivated, size: searchHeaderFrame.size, transition: transition) + transition.setFrame(view: visibleSearchHeader, frame: searchHeaderFrame, completion: { [weak self] completed in + guard let strongSelf = self, completed, let visibleSearchHeader = strongSelf.visibleSearchHeader else { return } @@ -5864,6 +6072,37 @@ public final class EmojiPagerContentComponent: Component { } } + if let emptySearchResults = component.emptySearchResults { + let visibleEmptySearchResultsView: EmptySearchResultsView + var emptySearchResultsTransition = transition + if let current = self.visibleEmptySearchResultsView { + visibleEmptySearchResultsView = current + } else { + emptySearchResultsTransition = .immediate + visibleEmptySearchResultsView = EmptySearchResultsView(frame: CGRect()) + self.visibleEmptySearchResultsView = visibleEmptySearchResultsView + self.addSubview(visibleEmptySearchResultsView) + self.mirrorContentClippingView?.addSubview(visibleEmptySearchResultsView.tintContainerView) + } + let emptySearchResultsSize = CGSize(width: availableSize.width, height: availableSize.height - itemLayout.searchInsets.top - itemLayout.searchHeight) + visibleEmptySearchResultsView.update( + context: component.context, + theme: keyboardChildEnvironment.theme, + useOpaqueTheme: useOpaqueTheme, + text: emptySearchResults.text, + file: emptySearchResults.iconFile, + size: emptySearchResultsSize, + transition: emptySearchResultsTransition + ) + emptySearchResultsTransition.setFrame(view: visibleEmptySearchResultsView, frame: CGRect(origin: CGPoint(x: 0.0, y: itemLayout.searchInsets.top + itemLayout.searchHeight), size: emptySearchResultsSize)) + } else { + if let visibleEmptySearchResultsView = self.visibleEmptySearchResultsView { + self.visibleEmptySearchResultsView = nil + visibleEmptySearchResultsView.removeFromSuperview() + visibleEmptySearchResultsView.tintContainerView.removeFromSuperview() + } + } + self.updateVisibleItems(transition: itemTransition, attemptSynchronousLoads: attemptSynchronousLoads, previousItemPositions: previousItemPositions, previousAbsoluteItemPositions: previousAbsoluteItemPositions, updatedItemPositions: updatedItemPositions, hintDisappearingGroupFrame: hintDisappearingGroupFrame) return availableSize @@ -6085,6 +6324,10 @@ public final class EmojiPagerContentComponent: Component { ) if let groupIndex = itemGroupIndexById[groupId] { + if itemGroups[groupIndex].items.count >= (5 + 8) * 8 { + break + } + itemGroups[groupIndex].items.append(resultItem) } } @@ -6128,6 +6371,10 @@ public final class EmojiPagerContentComponent: Component { ) if let groupIndex = itemGroupIndexById[groupId] { + if itemGroups[groupIndex].items.count >= (5 + 8) * 8 { + break + } + itemGroups[groupIndex].items.append(resultItem) } } @@ -6533,6 +6780,13 @@ public final class EmojiPagerContentComponent: Component { } } + var displaySearchWithPlaceholder: String? + if isReactionSelection { + displaySearchWithPlaceholder = "Search Reactions" + } else if isStatusSelection { + displaySearchWithPlaceholder = "Search Statuses" + } + return EmojiPagerContentComponent( id: "emoji", context: context, @@ -6577,7 +6831,8 @@ public final class EmojiPagerContentComponent: Component { itemLayoutType: .compact, itemContentUniqueId: nil, warpContentsOnEdges: isReactionSelection || isStatusSelection, - displaySearch: isReactionSelection, + displaySearchWithPlaceholder: displaySearchWithPlaceholder, + emptySearchResults: nil, enableLongPress: (isReactionSelection && !isQuickReactionSelection) || isStatusSelection, selectedItems: selectedItems ) diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index 781b3b33bc..9e7db222b0 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -479,7 +479,6 @@ private func extractAccountManagerState(records: AccountRecordsView InputData { return InputData( - emoji: inputData.emoji.withUpdatedItemGroups(itemGroups: self.processStableItemGroupList(category: .emoji, itemGroups: inputData.emoji.itemGroups), itemContentUniqueId: nil), + emoji: inputData.emoji.withUpdatedItemGroups(itemGroups: self.processStableItemGroupList(category: .emoji, itemGroups: inputData.emoji.itemGroups), itemContentUniqueId: nil, emptySearchResults: nil), stickers: inputData.stickers.flatMap { stickers in - return stickers.withUpdatedItemGroups(itemGroups: self.processStableItemGroupList(category: .stickers, itemGroups: stickers.itemGroups), itemContentUniqueId: nil) + return stickers.withUpdatedItemGroups(itemGroups: self.processStableItemGroupList(category: .stickers, itemGroups: stickers.itemGroups), itemContentUniqueId: nil, emptySearchResults: nil) }, gifs: inputData.gifs, availableGifSearchEmojies: inputData.availableGifSearchEmojies diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index a690473be2..4ac8164acf 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -1004,15 +1004,22 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { let availableReactions = context.engine.stickers.availableReactions() - let defaultReaction = context.account.postbox.preferencesView(keys: [PreferencesKeys.reactionSettings]) - |> map { preferencesView -> MessageReaction.Reaction? in + let defaultReaction = combineLatest( + context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)), + context.account.postbox.preferencesView(keys: [PreferencesKeys.reactionSettings]) + ) + |> map { peer, preferencesView -> MessageReaction.Reaction? in let reactionSettings: ReactionSettings if let entry = preferencesView.values[PreferencesKeys.reactionSettings], let value = entry.get(ReactionSettings.self) { reactionSettings = value } else { reactionSettings = .default } - return reactionSettings.quickReaction + var hasPremium = false + if case let .user(user) = peer { + hasPremium = user.isPremium + } + return reactionSettings.effectiveQuickReaction(hasPremium: hasPremium) } |> distinctUntilChanged diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 71d60ccbec..ac5f5c6177 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -3113,10 +3113,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate strongSelf.emojiStatusSelectionController?.dismiss() var selectedItems = Set() - var topStatusTitle = "Long tap to set a timer" + var currentSelectedFileId: Int64? + var topStatusTitle = strongSelf.presentationData.strings.PeerStatusSetup_NoTimerTitle if let peer = strongSelf.data?.peer { if let user = peer as? TelegramUser, let emojiStatus = user.emojiStatus { selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: emojiStatus.fileId)) + currentSelectedFileId = emojiStatus.fileId if let timestamp = emojiStatus.expirationDate { topStatusTitle = peerStatusExpirationString(statusTimestamp: timestamp, relativeTo: Int32(Date().timeIntervalSince1970), strings: strongSelf.presentationData.strings, dateTimeFormat: strongSelf.presentationData.dateTimeFormat) @@ -3142,6 +3144,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate selectedItems: selectedItems, topStatusTitle: topStatusTitle ), + currentSelection: currentSelectedFileId, destinationItemView: { [weak sourceView] in return sourceView } diff --git a/submodules/TelegramUI/Sources/SharedNotificationManager.swift b/submodules/TelegramUI/Sources/SharedNotificationManager.swift index bfe53b0ebd..8b89f18eb0 100644 --- a/submodules/TelegramUI/Sources/SharedNotificationManager.swift +++ b/submodules/TelegramUI/Sources/SharedNotificationManager.swift @@ -464,16 +464,10 @@ public final class SharedNotificationManager { } else { let notification = UILocalNotification() - if #available(iOS 8.2, *) { - notification.alertTitle = title - notification.alertBody = body - } else { - if let title = title { - notification.alertBody = "\(title): \(body)" - } else { - notification.alertBody = body - } - } + + notification.alertTitle = title + notification.alertBody = body + notification.category = "incomingCall" notification.userInfo = ["callId": String(describing: notificationCall.internalId)] notification.soundName = "0.m4a" diff --git a/submodules/TelegramUniversalVideoContent/Sources/SystemVideoContent.swift b/submodules/TelegramUniversalVideoContent/Sources/SystemVideoContent.swift index 1df8da202d..643a93c7fd 100644 --- a/submodules/TelegramUniversalVideoContent/Sources/SystemVideoContent.swift +++ b/submodules/TelegramUniversalVideoContent/Sources/SystemVideoContent.swift @@ -259,7 +259,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent func seek(_ timestamp: Double) { assert(Queue.mainQueue().isCurrent()) self.seekId += 1 - self.playerItem.seek(to: CMTimeMake(value: Int64(timestamp) * 1000, timescale: 1000)) + self.playerItem.seek(to: CMTimeMake(value: Int64(timestamp) * 1000, timescale: 1000), completionHandler: nil) } func playOnceWithSound(playAndRecord: Bool, seek: MediaPlayerSeek, actionAtEnd: MediaPlayerPlayOnceWithSoundActionAtEnd) { diff --git a/submodules/TelegramUniversalVideoContent/Sources/WebEmbedPlayerNode.swift b/submodules/TelegramUniversalVideoContent/Sources/WebEmbedPlayerNode.swift index ce6add50ed..a680f3b7a7 100644 --- a/submodules/TelegramUniversalVideoContent/Sources/WebEmbedPlayerNode.swift +++ b/submodules/TelegramUniversalVideoContent/Sources/WebEmbedPlayerNode.swift @@ -102,8 +102,6 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate { if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { configuration.mediaTypesRequiringUserActionForPlayback = [] - } else if #available(iOSApplicationExtension 9.0, iOS 9.0, *) { - configuration.requiresUserActionForMediaPlayback = false } else { configuration.mediaPlaybackRequiresUserAction = false } diff --git a/submodules/TgVoip/Sources/OngoingCallThreadLocalContext.mm b/submodules/TgVoip/Sources/OngoingCallThreadLocalContext.mm index ce673b433c..e650e4dec9 100644 --- a/submodules/TgVoip/Sources/OngoingCallThreadLocalContext.mm +++ b/submodules/TgVoip/Sources/OngoingCallThreadLocalContext.mm @@ -5,6 +5,8 @@ #import #include +#import + static void TGCallAesIgeEncrypt(uint8_t *inBytes, uint8_t *outBytes, size_t length, uint8_t *key, uint8_t *iv) { MTAesEncryptRaw(inBytes, outBytes, length, key, iv); } diff --git a/submodules/WatchBridge/Impl/Sources/TGBridgeServer.m b/submodules/WatchBridge/Impl/Sources/TGBridgeServer.m index 7cca68f376..f0860bc183 100644 --- a/submodules/WatchBridge/Impl/Sources/TGBridgeServer.m +++ b/submodules/WatchBridge/Impl/Sources/TGBridgeServer.m @@ -2,7 +2,7 @@ #import #import -#import +#import #import @interface TGBridgeSignalManager : NSObject @@ -31,16 +31,16 @@ TGBridgeSignalManager *_signalManager; - OSSpinLock _incomingQueueLock; + os_unfair_lock _incomingQueueLock; NSMutableArray *_incomingMessageQueue; bool _requestSubscriptionList; NSArray *_initialSubscriptionList; - OSSpinLock _outgoingQueueLock; + os_unfair_lock _outgoingQueueLock; NSMutableArray *_outgoingMessageQueue; - OSSpinLock _replyHandlerMapLock; + os_unfair_lock _replyHandlerMapLock; NSMutableDictionary *_replyHandlerMap; SPipe *_appInstalled; @@ -102,14 +102,14 @@ if (self.isRunning) return; - OSSpinLockLock(&_incomingQueueLock); + os_unfair_lock_lock(&_incomingQueueLock); _isRunning = true; for (id message in _incomingMessageQueue) [self handleMessage:message replyHandler:nil finishTask:nil completion:nil]; [_incomingMessageQueue removeAllObjects]; - OSSpinLockUnlock(&_incomingQueueLock); + os_unfair_lock_unlock(&_incomingQueueLock); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self dispatch:^{ @@ -189,7 +189,7 @@ }; id message = [NSKeyedUnarchiver unarchiveObjectWithData:messageData]; - OSSpinLockLock(&_incomingQueueLock); + os_unfair_lock_lock(&_incomingQueueLock); if (!self.isRunning) { [_incomingMessageQueue addObject:message]; @@ -199,10 +199,10 @@ finishTask(4.0); - OSSpinLockUnlock(&_incomingQueueLock); + os_unfair_lock_unlock(&_incomingQueueLock); return; } - OSSpinLockUnlock(&_incomingQueueLock); + os_unfair_lock_unlock(&_incomingQueueLock); [self handleMessage:message replyHandler:replyHandler finishTask:finishTask completion:completion]; } @@ -261,9 +261,9 @@ //TGLog(@"[BridgeServer] Halt all active subscriptions"); [_signalManager haltAllSignals]; - OSSpinLockLock(&_outgoingQueueLock); + os_unfair_lock_lock(&_outgoingQueueLock); [_outgoingMessageQueue removeAllObjects]; - OSSpinLockUnlock(&_outgoingQueueLock); + os_unfair_lock_unlock(&_outgoingQueueLock); } _sessionId = ping.sessionId; @@ -307,9 +307,9 @@ SSignal *subscriptionHandler = _handler(subscription); if (replyHandler != nil) { - OSSpinLockLock(&_replyHandlerMapLock); + os_unfair_lock_lock(&_replyHandlerMapLock); _replyHandlerMap[@(subscription.identifier)] = replyHandler; - OSSpinLockUnlock(&_replyHandlerMapLock); + os_unfair_lock_unlock(&_replyHandlerMapLock); } if (subscriptionHandler != nil) @@ -318,11 +318,11 @@ { STimer *timer = [[STimer alloc] initWithTimeout:2.0 repeat:false completion:^ { - OSSpinLockLock(&_replyHandlerMapLock); + os_unfair_lock_lock(&_replyHandlerMapLock); void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)]; if (reply == nil) { - OSSpinLockUnlock(&_replyHandlerMapLock); + os_unfair_lock_unlock(&_replyHandlerMapLock); if (finishTask != nil) finishTask(2.0); @@ -331,7 +331,7 @@ reply([NSData data]); [_replyHandlerMap removeObjectForKey:@(subscription.identifier)]; - OSSpinLockUnlock(&_replyHandlerMapLock); + os_unfair_lock_unlock(&_replyHandlerMapLock); if (finishTask != nil) finishTask(4.0); @@ -369,11 +369,11 @@ } else { - OSSpinLockLock(&_replyHandlerMapLock); + os_unfair_lock_lock(&_replyHandlerMapLock); void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)]; if (reply == nil) { - OSSpinLockUnlock(&_replyHandlerMapLock); + os_unfair_lock_unlock(&_replyHandlerMapLock); if (finishTask != nil) finishTask(2.0); @@ -382,7 +382,7 @@ reply([NSData data]); [_replyHandlerMap removeObjectForKey:@(subscription.identifier)]; - OSSpinLockUnlock(&_replyHandlerMapLock); + os_unfair_lock_unlock(&_replyHandlerMapLock); if (finishTask != nil) finishTask(2.0); @@ -410,11 +410,11 @@ break; } - OSSpinLockLock(&_replyHandlerMapLock); + os_unfair_lock_lock(&_replyHandlerMapLock); void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)]; if (reply != nil) [_replyHandlerMap removeObjectForKey:@(subscription.identifier)]; - OSSpinLockUnlock(&_replyHandlerMapLock); + os_unfair_lock_unlock(&_replyHandlerMapLock); if (_processingNotification) { @@ -460,7 +460,7 @@ - (void)_enqueueResponse:(TGBridgeResponse *)response forSubscription:(TGBridgeSubscription *)subscription { - OSSpinLockLock(&_outgoingQueueLock); + os_unfair_lock_lock(&_outgoingQueueLock); NSMutableArray *updatedResponses = (_outgoingMessageQueue != nil) ? [_outgoingMessageQueue mutableCopy] : [[NSMutableArray alloc] init]; if (subscription.dropPreviouslyQueued) @@ -479,7 +479,7 @@ [updatedResponses addObject:response]; _outgoingMessageQueue = updatedResponses; - OSSpinLockUnlock(&_outgoingQueueLock); + os_unfair_lock_unlock(&_outgoingQueueLock); } - (void)_sendQueuedResponses @@ -487,7 +487,7 @@ if (_processingNotification) return; - OSSpinLockLock(&_outgoingQueueLock); + os_unfair_lock_lock(&_outgoingQueueLock); if (_outgoingMessageQueue.count > 0) { @@ -501,7 +501,7 @@ [_outgoingMessageQueue removeAllObjects]; } - OSSpinLockUnlock(&_outgoingQueueLock); + os_unfair_lock_unlock(&_outgoingQueueLock); } - (void)_requestSubscriptionList @@ -669,7 +669,7 @@ @interface TGBridgeSignalManager() { - OSSpinLock _lock; + os_unfair_lock _lock; NSMutableDictionary *_disposables; } @end @@ -689,9 +689,9 @@ - (void)dealloc { NSArray *disposables = nil; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); disposables = [_disposables allValues]; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); for (id disposable in disposables) { @@ -705,13 +705,13 @@ return false; bool produce = false; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_disposables[key] == nil) { _disposables[key] = [[SMetaDisposable alloc] init]; produce = true; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); if (produce) { @@ -721,24 +721,24 @@ __strong TGBridgeSignalManager *strongSelf = weakSelf; if (strongSelf != nil) { - OSSpinLockLock(&strongSelf->_lock); + os_unfair_lock_lock(&strongSelf->_lock); [strongSelf->_disposables removeObjectForKey:key]; - OSSpinLockUnlock(&strongSelf->_lock); + os_unfair_lock_unlock(&strongSelf->_lock); } } completed:^ { __strong TGBridgeSignalManager *strongSelf = weakSelf; if (strongSelf != nil) { - OSSpinLockLock(&strongSelf->_lock); + os_unfair_lock_lock(&strongSelf->_lock); [strongSelf->_disposables removeObjectForKey:key]; - OSSpinLockUnlock(&strongSelf->_lock); + os_unfair_lock_unlock(&strongSelf->_lock); } }]; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); [(SMetaDisposable *)_disposables[key] setDisposable:disposable]; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } return produce; @@ -749,22 +749,22 @@ if (key == nil) return; - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); if (_disposables[key] != nil) { [_disposables[key] dispose]; [_disposables removeObjectForKey:key]; } - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } - (void)haltAllSignals { - OSSpinLockLock(&_lock); + os_unfair_lock_lock(&_lock); for (NSObject *disposable in _disposables.allValues) [disposable dispose]; [_disposables removeAllObjects]; - OSSpinLockUnlock(&_lock); + os_unfair_lock_unlock(&_lock); } @end diff --git a/submodules/WebUI/Sources/WebAppWebView.swift b/submodules/WebUI/Sources/WebAppWebView.swift index 6c494aa817..b76554712e 100644 --- a/submodules/WebUI/Sources/WebAppWebView.swift +++ b/submodules/WebUI/Sources/WebAppWebView.swift @@ -68,8 +68,6 @@ final class WebAppWebView: WKWebView { configuration.allowsPictureInPictureMediaPlayback = false if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { configuration.mediaTypesRequiringUserActionForPlayback = .all - } else if #available(iOSApplicationExtension 9.0, iOS 9.0, *) { - configuration.requiresUserActionForMediaPlayback = true } else { configuration.mediaPlaybackRequiresUserAction = true } diff --git a/versions.json b/versions.json index 06b565b23b..d93efc0cff 100644 --- a/versions.json +++ b/versions.json @@ -1,5 +1,5 @@ { - "app": "9.0", - "bazel": "5.1.0", + "app": "9.0.1", + "bazel": "5.3.0", "xcode": "14.0" }