mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
cb6e4bd4cc
@ -18,7 +18,7 @@ internal:
|
|||||||
except:
|
except:
|
||||||
- tags
|
- tags
|
||||||
script:
|
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"
|
- 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:
|
environment:
|
||||||
name: internal
|
name: internal
|
||||||
@ -92,7 +92,7 @@ beta_testflight:
|
|||||||
except:
|
except:
|
||||||
- tags
|
- tags
|
||||||
script:
|
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:
|
environment:
|
||||||
name: testflight_llc
|
name: testflight_llc
|
||||||
artifacts:
|
artifacts:
|
||||||
|
101
Telegram/BUILD
101
Telegram/BUILD
@ -115,6 +115,8 @@ genrule(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
minimum_os_version = "11.0"
|
||||||
|
|
||||||
empty_languages = [
|
empty_languages = [
|
||||||
"ar",
|
"ar",
|
||||||
"be",
|
"be",
|
||||||
@ -588,6 +590,18 @@ plist_fragment(
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "RequiredDeviceCapabilitiesPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
plist_fragment(
|
plist_fragment(
|
||||||
name = "AppNameInfoPlist",
|
name = "AppNameInfoPlist",
|
||||||
extension = "plist",
|
extension = "plist",
|
||||||
@ -690,7 +704,7 @@ watchos_extension(
|
|||||||
":AppNameInfoPlist",
|
":AppNameInfoPlist",
|
||||||
":WatchExtensionNSExtensionInfoPlist",
|
":WatchExtensionNSExtensionInfoPlist",
|
||||||
],
|
],
|
||||||
minimum_os_version = "5.0",
|
minimum_os_version = "9.0",
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:WatchExtension.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:WatchExtension.mobileprovision",
|
||||||
@ -716,11 +730,11 @@ watchos_application(
|
|||||||
infoplists = [
|
infoplists = [
|
||||||
":WatchAppInfoPlist",
|
":WatchAppInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
"BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":AppNameInfoPlist",
|
":AppNameInfoPlist",
|
||||||
":WatchAppCompanionInfoPlist",
|
":WatchAppCompanionInfoPlist",
|
||||||
],
|
],
|
||||||
minimum_os_version = "5.0",
|
minimum_os_version = "9.0",
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:WatchApp.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:WatchApp.mobileprovision",
|
||||||
@ -767,8 +781,9 @@ ios_framework(
|
|||||||
":MtProtoKitInfoPlist",
|
":MtProtoKitInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
extension_safe = True,
|
extension_safe = True,
|
||||||
ipa_post_processor = strip_framework,
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
@ -807,8 +822,9 @@ ios_framework(
|
|||||||
":SwiftSignalKitInfoPlist",
|
":SwiftSignalKitInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
extension_safe = True,
|
extension_safe = True,
|
||||||
ipa_post_processor = strip_framework,
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
@ -847,11 +863,12 @@ ios_framework(
|
|||||||
":PostboxInfoPlist",
|
":PostboxInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
],
|
],
|
||||||
frameworks = [
|
frameworks = [
|
||||||
":SwiftSignalKitFramework",
|
":SwiftSignalKitFramework",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
extension_safe = True,
|
extension_safe = True,
|
||||||
ipa_post_processor = strip_framework,
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
@ -890,8 +907,9 @@ ios_framework(
|
|||||||
":TelegramApiInfoPlist",
|
":TelegramApiInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
extension_safe = True,
|
extension_safe = True,
|
||||||
ipa_post_processor = strip_framework,
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
@ -930,13 +948,14 @@ ios_framework(
|
|||||||
":TelegramCoreInfoPlist",
|
":TelegramCoreInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
],
|
],
|
||||||
frameworks = [
|
frameworks = [
|
||||||
":MtProtoKitFramework",
|
":MtProtoKitFramework",
|
||||||
":SwiftSignalKitFramework",
|
":SwiftSignalKitFramework",
|
||||||
":PostboxFramework",
|
":PostboxFramework",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
extension_safe = True,
|
extension_safe = True,
|
||||||
ipa_post_processor = strip_framework,
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
@ -975,8 +994,9 @@ ios_framework(
|
|||||||
":AsyncDisplayKitInfoPlist",
|
":AsyncDisplayKitInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
extension_safe = True,
|
extension_safe = True,
|
||||||
ipa_post_processor = strip_framework,
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
@ -1058,12 +1078,13 @@ ios_framework(
|
|||||||
":DisplayInfoPlist",
|
":DisplayInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
],
|
],
|
||||||
frameworks = [
|
frameworks = [
|
||||||
":SwiftSignalKitFramework",
|
":SwiftSignalKitFramework",
|
||||||
":AsyncDisplayKitFramework",
|
":AsyncDisplayKitFramework",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
extension_safe = True,
|
extension_safe = True,
|
||||||
ipa_post_processor = strip_framework,
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
@ -1102,6 +1123,7 @@ ios_framework(
|
|||||||
":TelegramUIInfoPlist",
|
":TelegramUIInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
],
|
],
|
||||||
frameworks = [
|
frameworks = [
|
||||||
":MtProtoKitFramework",
|
":MtProtoKitFramework",
|
||||||
@ -1111,7 +1133,7 @@ ios_framework(
|
|||||||
":AsyncDisplayKitFramework",
|
":AsyncDisplayKitFramework",
|
||||||
":DisplayFramework",
|
":DisplayFramework",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
extension_safe = True,
|
extension_safe = True,
|
||||||
ipa_post_processor = strip_framework,
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
@ -1195,10 +1217,11 @@ ios_extension(
|
|||||||
infoplists = [
|
infoplists = [
|
||||||
":ShareInfoPlist",
|
":ShareInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":AppNameInfoPlist",
|
":AppNameInfoPlist",
|
||||||
],
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:Share.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:Share.mobileprovision",
|
||||||
@ -1269,7 +1292,7 @@ swift_library(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
genrule(
|
'''genrule(
|
||||||
name = "SetMinOsVersionNotificationContentExtension",
|
name = "SetMinOsVersionNotificationContentExtension",
|
||||||
cmd_bash =
|
cmd_bash =
|
||||||
"""
|
"""
|
||||||
@ -1286,7 +1309,7 @@ genrule(
|
|||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
]
|
]
|
||||||
)
|
)'''
|
||||||
|
|
||||||
ios_extension(
|
ios_extension(
|
||||||
name = "NotificationContentExtension",
|
name = "NotificationContentExtension",
|
||||||
@ -1300,11 +1323,12 @@ ios_extension(
|
|||||||
infoplists = [
|
infoplists = [
|
||||||
":NotificationContentInfoPlist",
|
":NotificationContentInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":AppNameInfoPlist",
|
":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 = ":SetMinOsVersionNotificationContentExtension",
|
#ipa_post_processor = ":SetMinOsVersionNotificationContentExtension",
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:NotificationContent.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:NotificationContent.mobileprovision",
|
||||||
@ -1404,10 +1428,11 @@ ios_extension(
|
|||||||
infoplists = [
|
infoplists = [
|
||||||
":WidgetInfoPlist",
|
":WidgetInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":AppNameInfoPlist",
|
":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",
|
ipa_post_processor = ":SetMinOsVersionWidgetExtension",
|
||||||
#provides_main = True,
|
#provides_main = True,
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
@ -1506,7 +1531,7 @@ swift_library(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
genrule(
|
'''genrule(
|
||||||
name = "SetMinOsVersionIntentsExtension",
|
name = "SetMinOsVersionIntentsExtension",
|
||||||
cmd_bash =
|
cmd_bash =
|
||||||
"""
|
"""
|
||||||
@ -1523,7 +1548,7 @@ genrule(
|
|||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
]
|
]
|
||||||
)
|
)'''
|
||||||
|
|
||||||
ios_extension(
|
ios_extension(
|
||||||
name = "IntentsExtension",
|
name = "IntentsExtension",
|
||||||
@ -1537,11 +1562,12 @@ ios_extension(
|
|||||||
infoplists = [
|
infoplists = [
|
||||||
":IntentsInfoPlist",
|
":IntentsInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":AppNameInfoPlist",
|
":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 = ":SetMinOsVersionIntentsExtension",
|
#ipa_post_processor = ":SetMinOsVersionIntentsExtension",
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:Intents.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:Intents.mobileprovision",
|
||||||
@ -1600,7 +1626,7 @@ swift_library(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
genrule(
|
'''genrule(
|
||||||
name = "SetMinOsVersionBroadcastUploadExtension",
|
name = "SetMinOsVersionBroadcastUploadExtension",
|
||||||
cmd_bash =
|
cmd_bash =
|
||||||
"""
|
"""
|
||||||
@ -1617,7 +1643,7 @@ genrule(
|
|||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
]
|
]
|
||||||
)
|
)'''
|
||||||
|
|
||||||
ios_extension(
|
ios_extension(
|
||||||
name = "BroadcastUploadExtension",
|
name = "BroadcastUploadExtension",
|
||||||
@ -1631,11 +1657,12 @@ ios_extension(
|
|||||||
infoplists = [
|
infoplists = [
|
||||||
":BroadcastUploadInfoPlist",
|
":BroadcastUploadInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":AppNameInfoPlist",
|
":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 = ":SetMinOsVersionBroadcastUploadExtension",
|
#ipa_post_processor = ":SetMinOsVersionBroadcastUploadExtension",
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:BroadcastUpload.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:BroadcastUpload.mobileprovision",
|
||||||
@ -1679,7 +1706,7 @@ plist_fragment(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
genrule(
|
'''genrule(
|
||||||
name = "SetMinOsVersionNotificationServiceExtension",
|
name = "SetMinOsVersionNotificationServiceExtension",
|
||||||
cmd_bash =
|
cmd_bash =
|
||||||
"""
|
"""
|
||||||
@ -1696,7 +1723,7 @@ genrule(
|
|||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
]
|
]
|
||||||
)
|
)'''
|
||||||
|
|
||||||
ios_extension(
|
ios_extension(
|
||||||
name = "NotificationServiceExtension",
|
name = "NotificationServiceExtension",
|
||||||
@ -1710,11 +1737,12 @@ ios_extension(
|
|||||||
infoplists = [
|
infoplists = [
|
||||||
":NotificationServiceInfoPlist",
|
":NotificationServiceInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":AppNameInfoPlist",
|
":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 = ":SetMinOsVersionNotificationServiceExtension",
|
#ipa_post_processor = ":SetMinOsVersionNotificationServiceExtension",
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:NotificationService.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:NotificationService.mobileprovision",
|
||||||
@ -1846,10 +1874,6 @@ plist_fragment(
|
|||||||
<false/>
|
<false/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
|
||||||
<array>
|
|
||||||
<string>armv7</string>
|
|
||||||
</array>
|
|
||||||
<key>UIRequiresPersistentWiFi</key>
|
<key>UIRequiresPersistentWiFi</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIStatusBarStyle</key>
|
<key>UIStatusBarStyle</key>
|
||||||
@ -1912,7 +1936,7 @@ ios_application(
|
|||||||
telegram_bundle_id = telegram_bundle_id,
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
),
|
),
|
||||||
families = ["iphone", "ipad"],
|
families = ["iphone", "ipad"],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision",
|
||||||
@ -1922,6 +1946,7 @@ ios_application(
|
|||||||
":TelegramInfoPlist",
|
":TelegramInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":UrlTypesInfoPlist",
|
":UrlTypesInfoPlist",
|
||||||
],
|
],
|
||||||
alternate_icons = [
|
alternate_icons = [
|
||||||
@ -1958,7 +1983,7 @@ ios_application(
|
|||||||
}),
|
}),
|
||||||
watch_application = select({
|
watch_application = select({
|
||||||
":disableExtensionsSetting": None,
|
":disableExtensionsSetting": None,
|
||||||
"//conditions:default": None,#":TelegramWatchApp",
|
"//conditions:default": ":TelegramWatchApp",
|
||||||
}) if telegram_enable_watch else None,
|
}) if telegram_enable_watch else None,
|
||||||
deps = [
|
deps = [
|
||||||
":Main",
|
":Main",
|
||||||
@ -1974,7 +1999,7 @@ ios_application(
|
|||||||
telegram_bundle_id = telegram_bundle_id,
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
),
|
),
|
||||||
families = ["iphone", "ipad"],
|
families = ["iphone", "ipad"],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision",
|
||||||
@ -1984,6 +2009,7 @@ ios_application(
|
|||||||
":TelegramInfoPlist",
|
":TelegramInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":UrlTypesInfoPlist",
|
":UrlTypesInfoPlist",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
@ -1997,7 +2023,7 @@ ios_application(
|
|||||||
telegram_bundle_id = telegram_bundle_id,
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
),
|
),
|
||||||
families = ["iphone", "ipad"],
|
families = ["iphone", "ipad"],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = minimum_os_version,
|
||||||
provisioning_profile = select({
|
provisioning_profile = select({
|
||||||
":disableProvisioningProfilesSetting": None,
|
":disableProvisioningProfilesSetting": None,
|
||||||
"//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision",
|
"//conditions:default": "@build_configuration//provisioning:Telegram.mobileprovision",
|
||||||
@ -2007,6 +2033,7 @@ ios_application(
|
|||||||
":TelegramInfoPlist",
|
":TelegramInfoPlist",
|
||||||
":BuildNumberInfoPlist",
|
":BuildNumberInfoPlist",
|
||||||
":VersionInfoPlist",
|
":VersionInfoPlist",
|
||||||
|
":RequiredDeviceCapabilitiesPlist",
|
||||||
":UrlTypesInfoPlist",
|
":UrlTypesInfoPlist",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
|
@ -642,7 +642,7 @@ private final class NotificationServiceHandler {
|
|||||||
let logsPath = rootPath + "/logs/notification-logs"
|
let logsPath = rootPath + "/logs/notification-logs"
|
||||||
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
||||||
|
|
||||||
setupSharedLogger(rootPath: rootPath, path: logsPath)
|
setupSharedLogger(rootPath: logsPath, path: logsPath)
|
||||||
|
|
||||||
initializeAccountManagement()
|
initializeAccountManagement()
|
||||||
|
|
||||||
@ -652,6 +652,24 @@ private final class NotificationServiceHandler {
|
|||||||
|
|
||||||
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)
|
let deviceSpecificEncryptionParameters = BuildConfig.deviceSpecificEncryptionParameters(rootPath, baseAppBundleId: baseAppBundleId)
|
||||||
self.encryptionParameters = ValueBoxEncryptionParameters(forceEncryptionIfNoSet: false, key: ValueBoxEncryptionParameters.Key(data: deviceSpecificEncryptionParameters.key)!, salt: ValueBoxEncryptionParameters.Salt(data: deviceSpecificEncryptionParameters.salt)!)
|
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)
|
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)
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ class DefaultIntentHandler: INExtension, INSendMessageIntentHandling, INSearchFo
|
|||||||
let logsPath = rootPath + "/logs/siri-logs"
|
let logsPath = rootPath + "/logs/siri-logs"
|
||||||
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
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"
|
let appVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "unknown"
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ private func getCommonTimeline(friends: [Friend]?, in context: TimelineProviderC
|
|||||||
let logsPath = rootPath + "/logs/widget-logs"
|
let logsPath = rootPath + "/logs/widget-logs"
|
||||||
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)
|
||||||
|
|
||||||
setupSharedLogger(rootPath: rootPath, path: logsPath)
|
setupSharedLogger(rootPath: logsPath, path: logsPath)
|
||||||
|
|
||||||
initializeAccountManagement()
|
initializeAccountManagement()
|
||||||
|
|
||||||
|
@ -59,6 +59,9 @@ class BazelCommandLine:
|
|||||||
# https://docs.bazel.build/versions/master/command-line-reference.html
|
# https://docs.bazel.build/versions/master/command-line-reference.html
|
||||||
# Print the subcommand details in case of failure.
|
# Print the subcommand details in case of failure.
|
||||||
'--verbose_failures',
|
'--verbose_failures',
|
||||||
|
|
||||||
|
# Asynchronously upload cache artifacts
|
||||||
|
'--experimental_remote_cache_async',
|
||||||
]
|
]
|
||||||
|
|
||||||
self.common_build_args = [
|
self.common_build_args = [
|
||||||
@ -144,7 +147,7 @@ class BazelCommandLine:
|
|||||||
'--ios_multi_cpus=armv7,arm64',
|
'--ios_multi_cpus=armv7,arm64',
|
||||||
|
|
||||||
# Always build universal Watch binaries.
|
# Always build universal Watch binaries.
|
||||||
'--watchos_cpus=armv7k,arm64_32'
|
'--watchos_cpus=arm64_32'
|
||||||
] + self.common_debug_args
|
] + self.common_debug_args
|
||||||
elif configuration == 'debug_arm64':
|
elif configuration == 'debug_arm64':
|
||||||
self.configuration_args = [
|
self.configuration_args = [
|
||||||
@ -155,7 +158,7 @@ class BazelCommandLine:
|
|||||||
'--ios_multi_cpus=arm64',
|
'--ios_multi_cpus=arm64',
|
||||||
|
|
||||||
# Always build universal Watch binaries.
|
# Always build universal Watch binaries.
|
||||||
'--watchos_cpus=armv7k,arm64_32'
|
'--watchos_cpus=arm64_32'
|
||||||
] + self.common_debug_args
|
] + self.common_debug_args
|
||||||
elif configuration == 'debug_sim_arm64':
|
elif configuration == 'debug_sim_arm64':
|
||||||
self.configuration_args = [
|
self.configuration_args = [
|
||||||
@ -166,7 +169,7 @@ class BazelCommandLine:
|
|||||||
'--ios_multi_cpus=sim_arm64',
|
'--ios_multi_cpus=sim_arm64',
|
||||||
|
|
||||||
# Always build universal Watch binaries.
|
# Always build universal Watch binaries.
|
||||||
'--watchos_cpus=armv7k,arm64_32'
|
'--watchos_cpus=arm64_32'
|
||||||
] + self.common_debug_args
|
] + self.common_debug_args
|
||||||
elif configuration == 'debug_armv7':
|
elif configuration == 'debug_armv7':
|
||||||
self.configuration_args = [
|
self.configuration_args = [
|
||||||
@ -176,7 +179,7 @@ class BazelCommandLine:
|
|||||||
'--ios_multi_cpus=armv7',
|
'--ios_multi_cpus=armv7',
|
||||||
|
|
||||||
# Always build universal Watch binaries.
|
# Always build universal Watch binaries.
|
||||||
'--watchos_cpus=armv7k,arm64_32'
|
'--watchos_cpus=arm64_32'
|
||||||
] + self.common_debug_args
|
] + self.common_debug_args
|
||||||
elif configuration == 'release_arm64':
|
elif configuration == 'release_arm64':
|
||||||
self.configuration_args = [
|
self.configuration_args = [
|
||||||
@ -187,7 +190,7 @@ class BazelCommandLine:
|
|||||||
'--ios_multi_cpus=arm64',
|
'--ios_multi_cpus=arm64',
|
||||||
|
|
||||||
# Always build universal Watch binaries.
|
# Always build universal Watch binaries.
|
||||||
'--watchos_cpus=armv7k,arm64_32',
|
'--watchos_cpus=arm64_32',
|
||||||
|
|
||||||
# Generate DSYM files when building.
|
# Generate DSYM files when building.
|
||||||
'--apple_generate_dsym',
|
'--apple_generate_dsym',
|
||||||
@ -204,7 +207,7 @@ class BazelCommandLine:
|
|||||||
'--ios_multi_cpus=armv7',
|
'--ios_multi_cpus=armv7',
|
||||||
|
|
||||||
# Always build universal Watch binaries.
|
# Always build universal Watch binaries.
|
||||||
'--watchos_cpus=armv7k,arm64_32',
|
'--watchos_cpus=arm64_32',
|
||||||
|
|
||||||
# Generate DSYM files when building.
|
# Generate DSYM files when building.
|
||||||
'--apple_generate_dsym',
|
'--apple_generate_dsym',
|
||||||
@ -221,7 +224,7 @@ class BazelCommandLine:
|
|||||||
'--ios_multi_cpus=armv7,arm64',
|
'--ios_multi_cpus=armv7,arm64',
|
||||||
|
|
||||||
# Always build universal Watch binaries.
|
# Always build universal Watch binaries.
|
||||||
'--watchos_cpus=armv7k,arm64_32',
|
'--watchos_cpus=arm64_32',
|
||||||
|
|
||||||
# Generate DSYM files when building.
|
# Generate DSYM files when building.
|
||||||
'--apple_generate_dsym',
|
'--apple_generate_dsym',
|
||||||
@ -411,7 +414,7 @@ def resolve_codesigning(arguments, base_path, build_configuration, provisioning_
|
|||||||
bundle_id=build_configuration.bundle_id,
|
bundle_id=build_configuration.bundle_id,
|
||||||
codesigning_type=arguments.gitCodesigningType,
|
codesigning_type=arguments.gitCodesigningType,
|
||||||
password=password,
|
password=password,
|
||||||
always_fetch=arguments.gitCodesigningAlwaysFetch
|
always_fetch=not arguments.gitCodesigningUseCurrent
|
||||||
)
|
)
|
||||||
elif arguments.codesigningInformationPath is not None:
|
elif arguments.codesigningInformationPath is not None:
|
||||||
profile_source = DirectoryCodesigningSource(
|
profile_source = DirectoryCodesigningSource(
|
||||||
@ -666,10 +669,10 @@ def add_codesigning_common_arguments(current_parser: argparse.ArgumentParser):
|
|||||||
)
|
)
|
||||||
|
|
||||||
current_parser.add_argument(
|
current_parser.add_argument(
|
||||||
'--gitCodesigningAlwaysFetch',
|
'--gitCodesigningUseCurrent',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
required=False,
|
required=False,
|
||||||
default=True,
|
default=False,
|
||||||
help='''
|
help='''
|
||||||
Always refresh codesigning repository.
|
Always refresh codesigning repository.
|
||||||
'''
|
'''
|
||||||
|
@ -478,8 +478,28 @@ public extension DeviceContactExtendedData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DeviceContactAddressData {
|
public extension DeviceContactAddressData {
|
||||||
public var dictionary: [String: String] {
|
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] = [:]
|
var dictionary: [String: String] = [:]
|
||||||
if !self.street1.isEmpty {
|
if !self.street1.isEmpty {
|
||||||
dictionary["Street"] = self.street1
|
dictionary["Street"] = self.street1
|
||||||
@ -499,7 +519,7 @@ extension DeviceContactAddressData {
|
|||||||
return dictionary
|
return dictionary
|
||||||
}
|
}
|
||||||
|
|
||||||
public var string: String {
|
var string: String {
|
||||||
var array: [String] = []
|
var array: [String] = []
|
||||||
if !self.street1.isEmpty {
|
if !self.street1.isEmpty {
|
||||||
array.append(self.street1)
|
array.append(self.street1)
|
||||||
@ -519,7 +539,7 @@ extension DeviceContactAddressData {
|
|||||||
return array.joined(separator: " ")
|
return array.joined(separator: " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
public var displayString: String {
|
var displayString: String {
|
||||||
var array: [String] = []
|
var array: [String] = []
|
||||||
if !self.street1.isEmpty {
|
if !self.street1.isEmpty {
|
||||||
array.append(self.street1)
|
array.append(self.street1)
|
||||||
|
@ -17,7 +17,7 @@ final class CameraDevice {
|
|||||||
func configure(for session: AVCaptureSession, position: Camera.Position) {
|
func configure(for session: AVCaptureSession, position: Camera.Position) {
|
||||||
self.position = position
|
self.position = position
|
||||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
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 {
|
} else {
|
||||||
self.videoDevice = AVCaptureDevice.devices(for: .video).filter { $0.position == position }.first
|
self.videoDevice = AVCaptureDevice.devices(for: .video).filter { $0.position == position }.first
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ final class CameraDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var isFlashActive: Signal<Bool, NoError> {
|
/*var isFlashActive: Signal<Bool, NoError> {
|
||||||
return self.videoDevicePromise.get()
|
return self.videoDevicePromise.get()
|
||||||
|> mapToSignal { device -> Signal<Bool, NoError> in
|
|> mapToSignal { device -> Signal<Bool, NoError> in
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
@ -75,7 +75,7 @@ final class CameraDevice {
|
|||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
var isFlashAvailable: Signal<Bool, NoError> {
|
var isFlashAvailable: Signal<Bool, NoError> {
|
||||||
return self.videoDevicePromise.get()
|
return self.videoDevicePromise.get()
|
||||||
|
@ -853,8 +853,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
self.emojiStatusSelectionController?.dismiss()
|
self.emojiStatusSelectionController?.dismiss()
|
||||||
var selectedItems = Set<MediaId>()
|
var selectedItems = Set<MediaId>()
|
||||||
var topStatusTitle = self.presentationData.strings.PeerStatusSetup_NoTimerTitle
|
var topStatusTitle = self.presentationData.strings.PeerStatusSetup_NoTimerTitle
|
||||||
|
var currentSelection: Int64?
|
||||||
if let peerStatus = self.titleView.title.peerStatus, case let .emoji(emojiStatus) = peerStatus {
|
if let peerStatus = self.titleView.title.peerStatus, case let .emoji(emojiStatus) = peerStatus {
|
||||||
selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: emojiStatus.fileId))
|
selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: emojiStatus.fileId))
|
||||||
|
currentSelection = emojiStatus.fileId
|
||||||
|
|
||||||
if let timestamp = emojiStatus.expirationDate {
|
if let timestamp = emojiStatus.expirationDate {
|
||||||
topStatusTitle = peerStatusExpirationString(statusTimestamp: timestamp, relativeTo: Int32(Date().timeIntervalSince1970), strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat)
|
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,
|
selectedItems: selectedItems,
|
||||||
topStatusTitle: topStatusTitle
|
topStatusTitle: topStatusTitle
|
||||||
),
|
),
|
||||||
|
currentSelection: currentSelection,
|
||||||
destinationItemView: { [weak sourceView] in
|
destinationItemView: { [weak sourceView] in
|
||||||
return sourceView
|
return sourceView
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/AnimationCache:AnimationCache",
|
"//submodules/TelegramUI/Components/AnimationCache:AnimationCache",
|
||||||
"//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer",
|
"//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer",
|
||||||
"//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView",
|
"//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView",
|
||||||
|
"//submodules/TelegramUI/Components/EmojiStatusComponent:EmojiStatusComponent",
|
||||||
"//submodules/TextFormat:TextFormat",
|
"//submodules/TextFormat:TextFormat",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
|
@ -16,6 +16,7 @@ import AnimationCache
|
|||||||
import MultiAnimationRenderer
|
import MultiAnimationRenderer
|
||||||
import EmojiTextAttachmentView
|
import EmojiTextAttachmentView
|
||||||
import TextFormat
|
import TextFormat
|
||||||
|
import EmojiStatusComponent
|
||||||
|
|
||||||
private let avatarFont = avatarPlaceholderFont(size: 16.0)
|
private let avatarFont = avatarPlaceholderFont(size: 16.0)
|
||||||
|
|
||||||
@ -357,7 +358,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
|
|||||||
let highlightBackgroundNode: ASDisplayNode
|
let highlightBackgroundNode: ASDisplayNode
|
||||||
let avatarNode: AvatarNode
|
let avatarNode: AvatarNode
|
||||||
let titleLabelNode: ImmediateTextNode
|
let titleLabelNode: ImmediateTextNode
|
||||||
var credibilityIconNode: ASImageNode?
|
var credibilityIconView: ComponentView<Empty>?
|
||||||
let separatorNode: ASDisplayNode
|
let separatorNode: ASDisplayNode
|
||||||
|
|
||||||
private var reactionLayer: InlineStickerItemLayer?
|
private var reactionLayer: InlineStickerItemLayer?
|
||||||
@ -519,20 +520,46 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
|
|||||||
}
|
}
|
||||||
|
|
||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 })
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 })
|
||||||
var currentCredibilityIconImage: UIImage?
|
var currentCredibilityIcon: EmojiStatusComponent.Content?
|
||||||
if item.peer.isScam {
|
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 {
|
} 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 {
|
} 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 {
|
} 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<Empty>
|
||||||
|
if let current = self.credibilityIconView {
|
||||||
|
credibilityIconView = current
|
||||||
|
} else {
|
||||||
|
credibilityIconView = ComponentView<Empty>()
|
||||||
|
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
|
var additionalTitleInset: CGFloat = 0.0
|
||||||
if let currentCredibilityIconImage = currentCredibilityIconImage {
|
if let credibilityIconSize = credibilityIconSize {
|
||||||
additionalTitleInset += 3.0 + currentCredibilityIconImage.size.width
|
additionalTitleInset += 3.0 + credibilityIconSize.width
|
||||||
}
|
}
|
||||||
|
|
||||||
self.highlightBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor
|
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)
|
let titleFrame = CGRect(origin: CGPoint(x: avatarInset + avatarSize + avatarSpacing, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
|
||||||
self.titleLabelNode.frame = titleFrame
|
self.titleLabelNode.frame = titleFrame
|
||||||
|
|
||||||
if let currentCredibilityIconImage = currentCredibilityIconImage {
|
if let credibilityIconView = self.credibilityIconView, let credibilityIconSize = credibilityIconSize {
|
||||||
let iconNode: ASImageNode
|
if let credibilityIconComponentView = credibilityIconView.view {
|
||||||
if let current = self.credibilityIconNode {
|
if credibilityIconComponentView.superview == nil {
|
||||||
iconNode = current
|
self.view.addSubview(credibilityIconComponentView)
|
||||||
} else {
|
}
|
||||||
iconNode = ASImageNode()
|
credibilityIconComponentView.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: floorToScreenPixels(titleFrame.midY - credibilityIconSize.height / 2.0) + 1.0 - UIScreenPixel), size: credibilityIconSize)
|
||||||
iconNode.isLayerBacked = true
|
|
||||||
iconNode.displaysAsynchronously = false
|
|
||||||
iconNode.displayWithoutProcessing = true
|
|
||||||
self.addSubnode(iconNode)
|
|
||||||
self.credibilityIconNode = iconNode
|
|
||||||
}
|
}
|
||||||
iconNode.image = currentCredibilityIconImage
|
} else if let credibilityIconView = self.credibilityIconView {
|
||||||
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)
|
self.credibilityIconView = nil
|
||||||
} else if let credibilityIconNode = self.credibilityIconNode {
|
credibilityIconView.view?.removeFromSuperview()
|
||||||
self.credibilityIconNode = nil
|
|
||||||
credibilityIconNode.removeFromSupernode()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let reactionSize = CGSize(width: 22.0, height: 22.0)
|
let reactionSize = CGSize(width: 22.0, height: 22.0)
|
||||||
|
@ -232,8 +232,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
private var customPosition: CGPoint?
|
private var customPosition: CGPoint?
|
||||||
private let contentContainerNode: ContextContentContainerNode
|
private let contentContainerNode: ContextContentContainerNode
|
||||||
private var actionsContainerNode: ContextActionsContainerNode
|
private var actionsContainerNode: ContextActionsContainerNode
|
||||||
private var reactionContextNode: ReactionContextNode?
|
|
||||||
private var reactionContextNodeIsAnimatingOut = false
|
|
||||||
|
|
||||||
private var didCompleteAnimationIn = false
|
private var didCompleteAnimationIn = false
|
||||||
private var initialContinueGesturePoint: CGPoint?
|
private var initialContinueGesturePoint: CGPoint?
|
||||||
@ -401,15 +399,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
strongSelf.hapticFeedback.tap()
|
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
|
strongSelf.highlightedActionNode = nil
|
||||||
highlightedActionNode.performAction()
|
highlightedActionNode.performAction()
|
||||||
}
|
}
|
||||||
if let highlightedReaction = strongSelf.highlightedReaction {
|
|
||||||
strongSelf.reactionContextNode?.performReactionSelection(reaction: highlightedReaction, isLarge: false)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if let highlightedActionNode = strongSelf.highlightedActionNode {
|
if let highlightedActionNode = strongSelf.highlightedActionNode {
|
||||||
strongSelf.highlightedActionNode = nil
|
strongSelf.highlightedActionNode = nil
|
||||||
@ -479,15 +465,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
strongSelf.hapticFeedback.tap()
|
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
|
strongSelf.highlightedActionNode = nil
|
||||||
highlightedActionNode.performAction()
|
highlightedActionNode.performAction()
|
||||||
}
|
}
|
||||||
|
|
||||||
if let highlightedReaction = strongSelf.highlightedReaction {
|
|
||||||
strongSelf.reactionContextNode?.performReactionSelection(reaction: highlightedReaction, isLarge: false)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if let highlightedActionNode = strongSelf.highlightedActionNode {
|
if let highlightedActionNode = strongSelf.highlightedActionNode {
|
||||||
strongSelf.highlightedActionNode = nil
|
strongSelf.highlightedActionNode = nil
|
||||||
@ -593,15 +566,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
actionNode.setIsHighlighted(true)
|
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:
|
case .ended, .cancelled:
|
||||||
if let presentationNode = self.presentationNode {
|
if let presentationNode = self.presentationNode {
|
||||||
@ -611,10 +575,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
self.highlightedActionNode = nil
|
self.highlightedActionNode = nil
|
||||||
highlightedActionNode.setIsHighlighted(false)
|
highlightedActionNode.setIsHighlighted(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let _ = self.reactionContextNode {
|
|
||||||
self.highlightedReaction = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@ -949,10 +909,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
localContentSourceFrame = localSourceFrame
|
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)
|
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)
|
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
|
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.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)
|
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))
|
contentParentNode.willUpdateIsExtractedToContextPreview?(false, .animated(duration: 0.2, curve: .easeInOut))
|
||||||
} else {
|
} else {
|
||||||
if let snapshotView = contentParentNode.contentNode.view.snapshotContentTree(keepTransform: true) {
|
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.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
contentParentNode.willUpdateIsExtractedToContextPreview?(false, .animated(duration: 0.2, curve: .easeInOut))
|
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):
|
case let .controller(source):
|
||||||
guard let maybeContentNode = self.contentContainerNode.contentNode, case let .controller(controller) = maybeContentNode else {
|
guard let maybeContentNode = self.contentContainerNode.contentNode, case let .controller(controller) = maybeContentNode else {
|
||||||
@ -1449,10 +1397,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
completedContentNode = true
|
completedContentNode = true
|
||||||
intermediateCompletion()
|
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 {
|
if let presentationNode = self.presentationNode {
|
||||||
presentationNode.addRelativeContentOffset(offset, transition: transition)
|
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() {
|
func cancelReactionAnimation() {
|
||||||
@ -1520,13 +1460,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
|
|
||||||
self.currentItems = items
|
self.currentItems = items
|
||||||
self.currentActionsMinHeight = minHeight
|
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 previousActionsContainerNode = self.actionsContainerNode
|
||||||
let previousActionsContainerFrame = previousActionsContainerNode.view.convert(previousActionsContainerNode.bounds, to: self.view)
|
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))
|
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||||
|
|
||||||
let actionsSideInset: CGFloat = layout.safeInsets.left + 12.0
|
let actionsSideInset: CGFloat = layout.safeInsets.left + 12.0
|
||||||
var contentTopInset: CGFloat = max(11.0, layout.statusBarHeight ?? 0.0)
|
let contentTopInset: CGFloat = max(11.0, layout.statusBarHeight ?? 0.0)
|
||||||
|
|
||||||
if let _ = self.reactionContextNode {
|
|
||||||
contentTopInset += 34.0
|
|
||||||
}
|
|
||||||
|
|
||||||
let actionsBottomInset: CGFloat = 11.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)
|
let absoluteContentRect = contentContainerFrame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y)
|
||||||
|
|
||||||
contentParentNode.updateAbsoluteRect?(absoluteContentRect, layout.size)
|
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):
|
case let .controller(contentParentNode):
|
||||||
var projectedFrame: CGRect = convertFrame(contentParentNode.sourceView.bounds, from: contentParentNode.sourceView, to: self.view)
|
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)
|
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)
|
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)
|
let mappedPoint = self.view.convert(point, to: self.scrollNode.view)
|
||||||
var maybePassthrough: ContextController.HandledTouchEvent?
|
var maybePassthrough: ContextController.HandledTouchEvent?
|
||||||
if let maybeContentNode = self.contentContainerNode.contentNode {
|
if let maybeContentNode = self.contentContainerNode.contentNode {
|
||||||
|
@ -724,11 +724,13 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
|
|||||||
var reactionAnchorRect = contentRect.offsetBy(dx: contentParentGlobalFrame.minX, dy: 0.0)
|
var reactionAnchorRect = contentRect.offsetBy(dx: contentParentGlobalFrame.minX, dy: 0.0)
|
||||||
|
|
||||||
let bottomInset = layout.insets(options: [.input]).bottom
|
let bottomInset = layout.insets(options: [.input]).bottom
|
||||||
|
var isCoveredByInput = false
|
||||||
if reactionAnchorRect.minY > layout.size.height - bottomInset {
|
if reactionAnchorRect.minY > layout.size.height - bottomInset {
|
||||||
reactionAnchorRect.origin.y = 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
|
self.proposedReactionsPositionLock = contentRect.minY - 18.0 - reactionContextNode.contentHeight - 46.0
|
||||||
} else {
|
} else {
|
||||||
|
@ -573,7 +573,8 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||||||
})
|
})
|
||||||
case .sendNotificationLogs:
|
case .sendNotificationLogs:
|
||||||
return ItemListDisclosureItem(presentationData: presentationData, title: "Send Notification Logs (Up to 40 MB)", label: "", sectionId: self.section, style: .blocks, action: {
|
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
|
|> deliverOnMainQueue).start(next: { logs in
|
||||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||||
@ -721,7 +722,8 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
|||||||
|
|
||||||
var logByType: [Signal<(type: String, logs: [(String, String)]), NoError>] = []
|
var logByType: [Signal<(type: String, logs: [(String, String)]), NoError>] = []
|
||||||
for type in logTypes {
|
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
|
|> map { result -> (type: String, logs: [(String, String)]) in
|
||||||
return (type, result)
|
return (type, result)
|
||||||
})
|
})
|
||||||
|
@ -375,7 +375,7 @@ public protocol CustomViewControllerNavigationDataSummary: AnyObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.navigationBar?.item = self.navigationItem
|
self.navigationBar?.item = self.navigationItem
|
||||||
self.automaticallyAdjustsScrollViewInsets = false
|
//self.automaticallyAdjustsScrollViewInsets = false
|
||||||
|
|
||||||
self.scrollToTopWithTabBar = { [weak self] in
|
self.scrollToTopWithTabBar = { [weak self] in
|
||||||
self?.scrollToTop?()
|
self?.scrollToTop?()
|
||||||
|
@ -65,8 +65,6 @@ final class GameControllerNode: ViewControllerTracingNode {
|
|||||||
configuration.allowsInlineMediaPlayback = true
|
configuration.allowsInlineMediaPlayback = true
|
||||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||||
configuration.mediaTypesRequiringUserActionForPlayback = []
|
configuration.mediaTypesRequiringUserActionForPlayback = []
|
||||||
} else if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
|
|
||||||
configuration.requiresUserActionForMediaPlayback = false
|
|
||||||
} else {
|
} else {
|
||||||
configuration.mediaPlaybackRequiresUserAction = false
|
configuration.mediaPlaybackRequiresUserAction = false
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import Contacts
|
||||||
import CoreLocation
|
import CoreLocation
|
||||||
import SwiftSignalKit
|
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
|
return Signal { subscriber in
|
||||||
let geocoder = CLGeocoder()
|
let geocoder = CLGeocoder()
|
||||||
geocoder.geocodeAddressDictionary(dictionary, completionHandler: { placemarks, _ in
|
geocoder.geocodePostalAddress(address, completionHandler: { placemarks, _ in
|
||||||
if let location = placemarks?.first?.location {
|
if let location = placemarks?.first?.location {
|
||||||
subscriber.putNext((location.coordinate.latitude, location.coordinate.longitude))
|
subscriber.putNext((location.coordinate.latitude, location.coordinate.longitude))
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,7 +8,10 @@
|
|||||||
@interface PGCameraCaptureSession : AVCaptureSession
|
@interface PGCameraCaptureSession : AVCaptureSession
|
||||||
|
|
||||||
@property (nonatomic, readonly) AVCaptureDevice *videoDevice;
|
@property (nonatomic, readonly) AVCaptureDevice *videoDevice;
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
@property (nonatomic, readonly) AVCaptureStillImageOutput *imageOutput;
|
@property (nonatomic, readonly) AVCaptureStillImageOutput *imageOutput;
|
||||||
|
#pragma clang diagnostic pop
|
||||||
@property (nonatomic, readonly) AVCaptureVideoDataOutput *videoOutput;
|
@property (nonatomic, readonly) AVCaptureVideoDataOutput *videoOutput;
|
||||||
@property (nonatomic, readonly) AVCaptureAudioDataOutput *audioOutput;
|
@property (nonatomic, readonly) AVCaptureAudioDataOutput *audioOutput;
|
||||||
@property (nonatomic, readonly) AVCaptureMetadataOutput *metadataOutput;
|
@property (nonatomic, readonly) AVCaptureMetadataOutput *metadataOutput;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#import "ASActor.h"
|
#import "ASActor.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -17,8 +17,8 @@ static dispatch_queue_t mainGraphQueue = nil;
|
|||||||
static dispatch_queue_t globalGraphQueue = nil;
|
static dispatch_queue_t globalGraphQueue = nil;
|
||||||
static dispatch_queue_t highPriorityGraphQueue = nil;
|
static dispatch_queue_t highPriorityGraphQueue = nil;
|
||||||
|
|
||||||
static volatile OSSpinLock removeWatcherRequestsLock = OS_SPINLOCK_INIT;
|
static os_unfair_lock removeWatcherRequestsLock = OS_UNFAIR_LOCK_INIT;
|
||||||
static volatile OSSpinLock removeWatcherFromPathRequestsLock = OS_SPINLOCK_INIT;
|
static os_unfair_lock removeWatcherFromPathRequestsLock = OS_UNFAIR_LOCK_INIT;
|
||||||
|
|
||||||
@interface ActionStage ()
|
@interface ActionStage ()
|
||||||
{
|
{
|
||||||
@ -790,11 +790,11 @@ ActionStage *ActionStageInstance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool alreadyExecuting = false;
|
bool alreadyExecuting = false;
|
||||||
OSSpinLockLock(&removeWatcherRequestsLock);
|
os_unfair_lock_lock(&removeWatcherRequestsLock);
|
||||||
if (!_removeWatcherRequests.empty())
|
if (!_removeWatcherRequests.empty())
|
||||||
alreadyExecuting = true;
|
alreadyExecuting = true;
|
||||||
_removeWatcherRequests.push_back(watcherGraphHandle);
|
_removeWatcherRequests.push_back(watcherGraphHandle);
|
||||||
OSSpinLockUnlock(&removeWatcherRequestsLock);
|
os_unfair_lock_unlock(&removeWatcherRequestsLock);
|
||||||
|
|
||||||
if (alreadyExecuting && ![self isCurrentQueueStageQueue])
|
if (alreadyExecuting && ![self isCurrentQueueStageQueue])
|
||||||
return;
|
return;
|
||||||
@ -803,10 +803,10 @@ ActionStage *ActionStageInstance()
|
|||||||
{
|
{
|
||||||
std::vector<ASHandle *> removeWatchers;
|
std::vector<ASHandle *> removeWatchers;
|
||||||
|
|
||||||
OSSpinLockLock(&removeWatcherRequestsLock);
|
os_unfair_lock_lock(&removeWatcherRequestsLock);
|
||||||
removeWatchers.insert(removeWatchers.begin(), _removeWatcherRequests.begin(), _removeWatcherRequests.end());
|
removeWatchers.insert(removeWatchers.begin(), _removeWatcherRequests.begin(), _removeWatcherRequests.end());
|
||||||
_removeWatcherRequests.clear();
|
_removeWatcherRequests.clear();
|
||||||
OSSpinLockUnlock(&removeWatcherRequestsLock);
|
os_unfair_lock_unlock(&removeWatcherRequestsLock);
|
||||||
|
|
||||||
for (std::vector<ASHandle *>::iterator it = removeWatchers.begin(); it != removeWatchers.end(); it++)
|
for (std::vector<ASHandle *>::iterator it = removeWatchers.begin(); it != removeWatchers.end(); it++)
|
||||||
{
|
{
|
||||||
@ -894,11 +894,11 @@ ActionStage *ActionStageInstance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool alreadyExecuting = false;
|
bool alreadyExecuting = false;
|
||||||
OSSpinLockLock(&removeWatcherFromPathRequestsLock);
|
os_unfair_lock_lock(&removeWatcherFromPathRequestsLock);
|
||||||
if (!_removeWatcherFromPathRequests.empty())
|
if (!_removeWatcherFromPathRequests.empty())
|
||||||
alreadyExecuting = true;
|
alreadyExecuting = true;
|
||||||
_removeWatcherFromPathRequests.push_back(std::pair<ASHandle *, NSString *>(watcherGraphHandle, watcherPath));
|
_removeWatcherFromPathRequests.push_back(std::pair<ASHandle *, NSString *>(watcherGraphHandle, watcherPath));
|
||||||
OSSpinLockUnlock(&removeWatcherFromPathRequestsLock);
|
os_unfair_lock_unlock(&removeWatcherFromPathRequestsLock);
|
||||||
|
|
||||||
if (alreadyExecuting && ![self isCurrentQueueStageQueue])
|
if (alreadyExecuting && ![self isCurrentQueueStageQueue])
|
||||||
return;
|
return;
|
||||||
@ -907,10 +907,10 @@ ActionStage *ActionStageInstance()
|
|||||||
{
|
{
|
||||||
std::vector<std::pair<ASHandle *, NSString *> > removeWatchersFromPath;
|
std::vector<std::pair<ASHandle *, NSString *> > removeWatchersFromPath;
|
||||||
|
|
||||||
OSSpinLockLock(&removeWatcherFromPathRequestsLock);
|
os_unfair_lock_lock(&removeWatcherFromPathRequestsLock);
|
||||||
removeWatchersFromPath.insert(removeWatchersFromPath.begin(), _removeWatcherFromPathRequests.begin(), _removeWatcherFromPathRequests.end());
|
removeWatchersFromPath.insert(removeWatchersFromPath.begin(), _removeWatcherFromPathRequests.begin(), _removeWatcherFromPathRequests.end());
|
||||||
_removeWatcherFromPathRequests.clear();
|
_removeWatcherFromPathRequests.clear();
|
||||||
OSSpinLockUnlock(&removeWatcherFromPathRequestsLock);
|
os_unfair_lock_unlock(&removeWatcherFromPathRequestsLock);
|
||||||
|
|
||||||
if (removeWatchersFromPath.size() > 1)
|
if (removeWatchersFromPath.size() > 1)
|
||||||
{
|
{
|
||||||
|
@ -21,9 +21,7 @@
|
|||||||
#import "POPBasicAnimationInternal.h"
|
#import "POPBasicAnimationInternal.h"
|
||||||
#import "POPDecayAnimation.h"
|
#import "POPDecayAnimation.h"
|
||||||
|
|
||||||
#if !TARGET_OS_IPHONE
|
#import <os/lock.h>
|
||||||
#import <libkern/OSAtomic.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace POP;
|
using namespace POP;
|
||||||
@ -97,7 +95,7 @@ static BOOL _disableBackgroundThread = YES;
|
|||||||
CFTimeInterval _slowMotionLastTime;
|
CFTimeInterval _slowMotionLastTime;
|
||||||
CFTimeInterval _slowMotionAccumulator;
|
CFTimeInterval _slowMotionAccumulator;
|
||||||
CFTimeInterval _beginTime;
|
CFTimeInterval _beginTime;
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
BOOL _disableDisplayLink;
|
BOOL _disableDisplayLink;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
@ -263,7 +261,7 @@ static POPAnimation *deleteDictEntry(POPAnimator *self, id __unsafe_unretained o
|
|||||||
POPAnimation *anim = nil;
|
POPAnimation *anim = nil;
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&self->_lock);
|
os_unfair_lock_lock(&self->_lock);
|
||||||
|
|
||||||
NSMutableDictionary *keyAnimationsDict = (__bridge id)CFDictionaryGetValue(self->_dict, (__bridge void *)obj);
|
NSMutableDictionary *keyAnimationsDict = (__bridge id)CFDictionaryGetValue(self->_dict, (__bridge void *)obj);
|
||||||
if (keyAnimationsDict) {
|
if (keyAnimationsDict) {
|
||||||
@ -282,7 +280,7 @@ static POPAnimation *deleteDictEntry(POPAnimator *self, id __unsafe_unretained o
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&self->_lock);
|
os_unfair_lock_unlock(&self->_lock);
|
||||||
return anim;
|
return anim;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +297,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
|
|
||||||
if (shouldRemove) {
|
if (shouldRemove) {
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&self->_lock);
|
os_unfair_lock_lock(&self->_lock);
|
||||||
|
|
||||||
// find item in list
|
// find item in list
|
||||||
// may have already been removed on animationDidStop:
|
// may have already been removed on animationDidStop:
|
||||||
@ -311,7 +309,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&self->_lock);
|
os_unfair_lock_unlock(&self->_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +350,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
_dict = POPDictionaryCreateMutableWeakPointerToStrongObject(5);
|
_dict = POPDictionaryCreateMutableWeakPointerToStrongObject(5);
|
||||||
_lock = OS_SPINLOCK_INIT;
|
_lock = OS_UNFAIR_LOCK_INIT;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -377,14 +375,14 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
[self _renderTime:(0 != _beginTime) ? _beginTime : time items:_pendingList];
|
[self _renderTime:(0 != _beginTime) ? _beginTime : time items:_pendingList];
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
// clear list and observer
|
// clear list and observer
|
||||||
_pendingList.clear();
|
_pendingList.clear();
|
||||||
[self _clearPendingListObserver];
|
[self _clearPendingListObserver];
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_clearPendingListObserver
|
- (void)_clearPendingListObserver
|
||||||
@ -403,7 +401,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
static const CFIndex POPAnimationApplyRunLoopOrder = CATransactionCommitRunLoopOrder - 1;
|
static const CFIndex POPAnimationApplyRunLoopOrder = CATransactionCommitRunLoopOrder - 1;
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
if (!_pendingListObserver) {
|
if (!_pendingListObserver) {
|
||||||
__weak POPAnimator *weakSelf = self;
|
__weak POPAnimator *weakSelf = self;
|
||||||
@ -418,7 +416,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_renderTime:(CFTimeInterval)time items:(std::list<POPAnimatorItemRef>)items
|
- (void)_renderTime:(CFTimeInterval)time items:(std::list<POPAnimatorItemRef>)items
|
||||||
@ -432,19 +430,19 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
[delegate animatorWillAnimate:self];
|
[delegate animatorWillAnimate:self];
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
// count active animations
|
// count active animations
|
||||||
const NSUInteger count = items.size();
|
const NSUInteger count = items.size();
|
||||||
if (0 == count) {
|
if (0 == count) {
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
} else {
|
} else {
|
||||||
// copy list into vector
|
// copy list into vector
|
||||||
std::vector<POPAnimatorItemRef> vector{ std::begin(items), std::end(items) };
|
std::vector<POPAnimatorItemRef> vector{ std::begin(items), std::end(items) };
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
for (auto item : vector) {
|
for (auto item : vector) {
|
||||||
[self _renderTime:time item:item];
|
[self _renderTime:time item:item];
|
||||||
@ -457,13 +455,13 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
// update display link
|
// update display link
|
||||||
updateDisplayLink(self);
|
updateDisplayLink(self);
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
// notify delegate and commit
|
// notify delegate and commit
|
||||||
[delegate animatorDidAnimate:self];
|
[delegate animatorDidAnimate:self];
|
||||||
@ -541,13 +539,13 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
- (NSArray *)observers
|
- (NSArray *)observers
|
||||||
{
|
{
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
// get observers
|
// get observers
|
||||||
NSArray *observers = 0 != _observers.count ? [_observers copy] : nil;
|
NSArray *observers = 0 != _observers.count ? [_observers copy] : nil;
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
return observers;
|
return observers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +561,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
// get key, animation dict associated with object
|
// get key, animation dict associated with object
|
||||||
NSMutableDictionary *keyAnimationDict = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj);
|
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];
|
POPAnimation *existingAnim = keyAnimationDict[key];
|
||||||
if (existingAnim) {
|
if (existingAnim) {
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (existingAnim == anim) {
|
if (existingAnim == anim) {
|
||||||
return;
|
return;
|
||||||
@ -585,7 +583,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
[self removeAnimationForObject:obj key:key cleanupDict:NO];
|
[self removeAnimationForObject:obj key:key cleanupDict:NO];
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyAnimationDict[key] = anim;
|
keyAnimationDict[key] = anim;
|
||||||
@ -604,7 +602,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
updateDisplayLink(self);
|
updateDisplayLink(self);
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
// schedule runloop processing of pending animations
|
// schedule runloop processing of pending animations
|
||||||
[self _scheduleProcessPendingList];
|
[self _scheduleProcessPendingList];
|
||||||
@ -613,13 +611,13 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
- (void)removeAllAnimationsForObject:(id)obj
|
- (void)removeAllAnimationsForObject:(id)obj
|
||||||
{
|
{
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
NSArray *animations = [(__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj) allValues];
|
NSArray *animations = [(__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj) allValues];
|
||||||
CFDictionaryRemoveValue(_dict, (__bridge void *)obj);
|
CFDictionaryRemoveValue(_dict, (__bridge void *)obj);
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (0 == animations.count) {
|
if (0 == animations.count) {
|
||||||
return;
|
return;
|
||||||
@ -631,7 +629,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
POPAnimatorItemRef item;
|
POPAnimatorItemRef item;
|
||||||
for (auto iter = _list.begin(); iter != _list.end();) {
|
for (auto iter = _list.begin(); iter != _list.end();) {
|
||||||
@ -644,7 +642,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
for (POPAnimation *anim in animations) {
|
for (POPAnimation *anim in animations) {
|
||||||
POPAnimationState *state = POPAnimationGetState(anim);
|
POPAnimationState *state = POPAnimationGetState(anim);
|
||||||
@ -660,7 +658,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
// remove from list
|
// remove from list
|
||||||
POPAnimatorItemRef item;
|
POPAnimatorItemRef item;
|
||||||
@ -686,7 +684,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
// stop animation and callout
|
// stop animation and callout
|
||||||
POPAnimationState *state = POPAnimationGetState(anim);
|
POPAnimationState *state = POPAnimationGetState(anim);
|
||||||
@ -701,27 +699,27 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
- (NSArray *)animationKeysForObject:(id)obj
|
- (NSArray *)animationKeysForObject:(id)obj
|
||||||
{
|
{
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
// get keys
|
// get keys
|
||||||
NSArray *keys = [(__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj) allKeys];
|
NSArray *keys = [(__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj) allKeys];
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)animationForObject:(id)obj key:(NSString *)key
|
- (id)animationForObject:(id)obj key:(NSString *)key
|
||||||
{
|
{
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
// lookup animation
|
// lookup animation
|
||||||
NSDictionary *keyAnimationsDict = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj);
|
NSDictionary *keyAnimationsDict = (__bridge id)CFDictionaryGetValue(_dict, (__bridge void *)obj);
|
||||||
POPAnimation *animation = keyAnimationsDict[key];
|
POPAnimation *animation = keyAnimationsDict[key];
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
return animation;
|
return animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,7 +769,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
if (!_observers) {
|
if (!_observers) {
|
||||||
// use ordered collection for deterministic callout
|
// use ordered collection for deterministic callout
|
||||||
@ -782,7 +780,7 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
updateDisplayLink(self);
|
updateDisplayLink(self);
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)removeObserver:(id<POPAnimatorObserving>)observer
|
- (void)removeObserver:(id<POPAnimatorObserving>)observer
|
||||||
@ -793,13 +791,13 @@ static void stopAndCleanup(POPAnimator *self, POPAnimatorItemRef item, bool shou
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lock
|
// lock
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
|
|
||||||
[_observers removeObject:observer];
|
[_observers removeObject:observer];
|
||||||
updateDisplayLink(self);
|
updateDisplayLink(self);
|
||||||
|
|
||||||
// unlock
|
// unlock
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#import <Accelerate/Accelerate.h>
|
#import <Accelerate/Accelerate.h>
|
||||||
#import <CommonCrypto/CommonCrypto.h>
|
#import <CommonCrypto/CommonCrypto.h>
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
#import <map>
|
#import <map>
|
||||||
|
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#import "LegacyComponentsInternal.h"
|
#import "LegacyComponentsInternal.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
#import <CoreMedia/CoreMedia.h>
|
#import <CoreMedia/CoreMedia.h>
|
||||||
#import <ImageIO/ImageIO.h>
|
#import <ImageIO/ImageIO.h>
|
||||||
#import <Accelerate/Accelerate.h>
|
#import <Accelerate/Accelerate.h>
|
||||||
@ -69,7 +69,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
id<TGLiveUploadInterface> _watcher;
|
id<TGLiveUploadInterface> _watcher;
|
||||||
id _liveUploadData;
|
id _liveUploadData;
|
||||||
|
|
||||||
OSSpinLock _recordLock;
|
os_unfair_lock _recordLock;
|
||||||
bool _startRecordAfterAudioBuffer;
|
bool _startRecordAfterAudioBuffer;
|
||||||
|
|
||||||
CVPixelBufferRef _currentPreviewPixelBuffer;
|
CVPixelBufferRef _currentPreviewPixelBuffer;
|
||||||
@ -404,7 +404,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
|
|
||||||
CFRelease(blockBuffer);
|
CFRelease(blockBuffer);
|
||||||
|
|
||||||
OSSpinLockLock(&_recordLock);
|
os_unfair_lock_lock(&_recordLock);
|
||||||
if (_startRecordAfterAudioBuffer)
|
if (_startRecordAfterAudioBuffer)
|
||||||
{
|
{
|
||||||
_startRecordAfterAudioBuffer = false;
|
_startRecordAfterAudioBuffer = false;
|
||||||
@ -413,7 +413,7 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
[self startRecording:_recordingURL preset:_preset liveUpload:_liveUpload];
|
[self startRecording:_recordingURL preset:_preset liveUpload:_liveUpload];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_recordLock);
|
os_unfair_lock_unlock(&_recordLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,14 +669,14 @@ const NSInteger TGVideoCameraRetainedBufferCount = 16;
|
|||||||
_preset = preset;
|
_preset = preset;
|
||||||
_liveUpload = liveUpload;
|
_liveUpload = liveUpload;
|
||||||
|
|
||||||
OSSpinLockLock(&_recordLock);
|
os_unfair_lock_lock(&_recordLock);
|
||||||
if (self.outputAudioFormatDescription == NULL)
|
if (self.outputAudioFormatDescription == NULL)
|
||||||
{
|
{
|
||||||
_startRecordAfterAudioBuffer = true;
|
_startRecordAfterAudioBuffer = true;
|
||||||
OSSpinLockUnlock(&_recordLock);
|
os_unfair_lock_unlock(&_recordLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_recordLock);
|
os_unfair_lock_unlock(&_recordLock);
|
||||||
|
|
||||||
@synchronized (self)
|
@synchronized (self)
|
||||||
{
|
{
|
||||||
|
@ -57,7 +57,7 @@ public func geocodeAddress(engine: TelegramEngine, address: DeviceContactAddress
|
|||||||
if let cached = cached {
|
if let cached = cached {
|
||||||
return .single((cached.latitude, cached.longitude))
|
return .single((cached.latitude, cached.longitude))
|
||||||
} else {
|
} else {
|
||||||
return geocodeLocation(dictionary: address.dictionary)
|
return geocodeLocation(address: address.asPostalAddress)
|
||||||
|> mapToSignal { coordinate in
|
|> mapToSignal { coordinate in
|
||||||
if let (latitude, longitude) = coordinate {
|
if let (latitude, longitude) = coordinate {
|
||||||
return updateCachedGeocode(engine: engine, address: address, latitude: latitude, longitude: longitude)
|
return updateCachedGeocode(engine: engine, address: address, latitude: latitude, longitude: longitude)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#ifndef MtProtoKit_MTInternalId_h
|
#ifndef MtProtoKit_MTInternalId_h
|
||||||
#define MtProtoKit_MTInternalId_h
|
#define MtProtoKit_MTInternalId_h
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
#define MTInternalId(name) MT##name##InternalId
|
#define MTInternalId(name) MT##name##InternalId
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#import <MtProtoKit/MTAtomic.h>
|
#import <MtProtoKit/MTAtomic.h>
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
@interface MTAtomic ()
|
@interface MTAtomic ()
|
||||||
{
|
{
|
||||||
volatile OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
id _value;
|
id _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,19 +25,19 @@
|
|||||||
- (id)swap:(id)newValue
|
- (id)swap:(id)newValue
|
||||||
{
|
{
|
||||||
id previousValue = nil;
|
id previousValue = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
previousValue = _value;
|
previousValue = _value;
|
||||||
_value = newValue;
|
_value = newValue;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
return previousValue;
|
return previousValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)value
|
- (id)value
|
||||||
{
|
{
|
||||||
id previousValue = nil;
|
id previousValue = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
previousValue = _value;
|
previousValue = _value;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
return previousValue;
|
return previousValue;
|
||||||
}
|
}
|
||||||
@ -45,19 +45,19 @@
|
|||||||
- (id)modify:(id (^)(id))f
|
- (id)modify:(id (^)(id))f
|
||||||
{
|
{
|
||||||
id newValue = nil;
|
id newValue = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
newValue = f(_value);
|
newValue = f(_value);
|
||||||
_value = newValue;
|
_value = newValue;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)with:(id (^)(id))f
|
- (id)with:(id (^)(id))f
|
||||||
{
|
{
|
||||||
id result = nil;
|
id result = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
result = f(_value);
|
result = f(_value);
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#import <MtProtoKit/MTApiEnvironment.h>
|
#import <MtProtoKit/MTApiEnvironment.h>
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
#import "MTDiscoverConnectionSignals.h"
|
#import "MTDiscoverConnectionSignals.h"
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ static MTDatacenterAuthInfoMapKeyStruct parseAuthInfoMapKeyInteger(NSNumber *key
|
|||||||
|
|
||||||
NSMutableDictionary *_periodicTasksTimerByDatacenterId;
|
NSMutableDictionary *_periodicTasksTimerByDatacenterId;
|
||||||
|
|
||||||
volatile OSSpinLock _passwordEntryRequiredLock;
|
os_unfair_lock _passwordEntryRequiredLock;
|
||||||
NSMutableDictionary *_passwordRequiredByDatacenterId;
|
NSMutableDictionary *_passwordRequiredByDatacenterId;
|
||||||
|
|
||||||
NSMutableDictionary *_transportSchemeDisposableByDatacenterId;
|
NSMutableDictionary *_transportSchemeDisposableByDatacenterId;
|
||||||
@ -680,20 +680,20 @@ static void copyKeychainKey(NSString * _Nonnull group, NSString * _Nonnull key,
|
|||||||
|
|
||||||
- (bool)isPasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId
|
- (bool)isPasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_passwordEntryRequiredLock);
|
os_unfair_lock_lock(&_passwordEntryRequiredLock);
|
||||||
bool currentValue = [_passwordRequiredByDatacenterId[@(datacenterId)] boolValue];
|
bool currentValue = [_passwordRequiredByDatacenterId[@(datacenterId)] boolValue];
|
||||||
OSSpinLockUnlock(&_passwordEntryRequiredLock);
|
os_unfair_lock_unlock(&_passwordEntryRequiredLock);
|
||||||
|
|
||||||
return currentValue;
|
return currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (bool)updatePasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId required:(bool)required
|
- (bool)updatePasswordInputRequiredForDatacenterWithId:(NSInteger)datacenterId required:(bool)required
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_passwordEntryRequiredLock);
|
os_unfair_lock_lock(&_passwordEntryRequiredLock);
|
||||||
bool currentValue = [_passwordRequiredByDatacenterId[@(datacenterId)] boolValue];
|
bool currentValue = [_passwordRequiredByDatacenterId[@(datacenterId)] boolValue];
|
||||||
bool updated = currentValue != required;
|
bool updated = currentValue != required;
|
||||||
_passwordRequiredByDatacenterId[@(datacenterId)] = @(required);
|
_passwordRequiredByDatacenterId[@(datacenterId)] = @(required);
|
||||||
OSSpinLockUnlock(&_passwordEntryRequiredLock);
|
os_unfair_lock_unlock(&_passwordEntryRequiredLock);
|
||||||
|
|
||||||
if (updated)
|
if (updated)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#import <MtProtoKit/MTDisposable.h>
|
#import <MtProtoKit/MTDisposable.h>
|
||||||
|
|
||||||
|
#import <os/lock.h>
|
||||||
#import <libkern/OSAtomic.h>
|
#import <libkern/OSAtomic.h>
|
||||||
|
#import <stdatomic.h>
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
|
|
||||||
@interface MTBlockDisposable ()
|
@interface MTBlockDisposable ()
|
||||||
@ -27,6 +29,8 @@
|
|||||||
void *block = _block;
|
void *block = _block;
|
||||||
if (block != NULL)
|
if (block != NULL)
|
||||||
{
|
{
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
||||||
{
|
{
|
||||||
if (block != nil)
|
if (block != nil)
|
||||||
@ -35,6 +39,7 @@
|
|||||||
strongBlock = nil;
|
strongBlock = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +48,8 @@
|
|||||||
void *block = _block;
|
void *block = _block;
|
||||||
if (block != NULL)
|
if (block != NULL)
|
||||||
{
|
{
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
||||||
{
|
{
|
||||||
if (block != nil)
|
if (block != nil)
|
||||||
@ -52,6 +59,7 @@
|
|||||||
strongBlock = nil;
|
strongBlock = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +67,7 @@
|
|||||||
|
|
||||||
@interface MTMetaDisposable ()
|
@interface MTMetaDisposable ()
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
bool _disposed;
|
bool _disposed;
|
||||||
id<MTDisposable> _disposable;
|
id<MTDisposable> _disposable;
|
||||||
}
|
}
|
||||||
@ -73,14 +81,14 @@
|
|||||||
id<MTDisposable> previousDisposable = nil;
|
id<MTDisposable> previousDisposable = nil;
|
||||||
bool dispose = false;
|
bool dispose = false;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
dispose = _disposed;
|
dispose = _disposed;
|
||||||
if (!dispose)
|
if (!dispose)
|
||||||
{
|
{
|
||||||
previousDisposable = _disposable;
|
previousDisposable = _disposable;
|
||||||
_disposable = disposable;
|
_disposable = disposable;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (previousDisposable != nil)
|
if (previousDisposable != nil)
|
||||||
[previousDisposable dispose];
|
[previousDisposable dispose];
|
||||||
@ -93,13 +101,13 @@
|
|||||||
{
|
{
|
||||||
id<MTDisposable> disposable = nil;
|
id<MTDisposable> disposable = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_disposed)
|
if (!_disposed)
|
||||||
{
|
{
|
||||||
disposable = _disposable;
|
disposable = _disposable;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (disposable != nil)
|
if (disposable != nil)
|
||||||
[disposable dispose];
|
[disposable dispose];
|
||||||
@ -109,7 +117,7 @@
|
|||||||
|
|
||||||
@interface MTDisposableSet ()
|
@interface MTDisposableSet ()
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
bool _disposed;
|
bool _disposed;
|
||||||
id<MTDisposable> _singleDisposable;
|
id<MTDisposable> _singleDisposable;
|
||||||
NSArray *_multipleDisposables;
|
NSArray *_multipleDisposables;
|
||||||
@ -126,7 +134,7 @@
|
|||||||
|
|
||||||
bool dispose = false;
|
bool dispose = false;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
dispose = _disposed;
|
dispose = _disposed;
|
||||||
if (!dispose)
|
if (!dispose)
|
||||||
{
|
{
|
||||||
@ -147,14 +155,14 @@
|
|||||||
_singleDisposable = disposable;
|
_singleDisposable = disposable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (dispose)
|
if (dispose)
|
||||||
[disposable dispose];
|
[disposable dispose];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)remove:(id<MTDisposable>)disposable {
|
- (void)remove:(id<MTDisposable>)disposable {
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_multipleDisposables != nil)
|
if (_multipleDisposables != nil)
|
||||||
{
|
{
|
||||||
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables];
|
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables];
|
||||||
@ -165,7 +173,7 @@
|
|||||||
{
|
{
|
||||||
_singleDisposable = nil;
|
_singleDisposable = nil;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dispose
|
- (void)dispose
|
||||||
@ -173,7 +181,7 @@
|
|||||||
id<MTDisposable> singleDisposable = nil;
|
id<MTDisposable> singleDisposable = nil;
|
||||||
NSArray *multipleDisposables = nil;
|
NSArray *multipleDisposables = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_disposed)
|
if (!_disposed)
|
||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
@ -182,7 +190,7 @@
|
|||||||
_singleDisposable = nil;
|
_singleDisposable = nil;
|
||||||
_multipleDisposables = nil;
|
_multipleDisposables = nil;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (singleDisposable != nil)
|
if (singleDisposable != nil)
|
||||||
[singleDisposable dispose];
|
[singleDisposable dispose];
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
|
|
||||||
#import <MtProtoKit/MTInternalId.h>
|
#import <MtProtoKit/MTInternalId.h>
|
||||||
|
|
||||||
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
MTInternalIdClass(MTMessageTransaction)
|
MTInternalIdClass(MTMessageTransaction)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
@implementation MTMessageTransaction
|
@implementation MTMessageTransaction
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#import <MtProtoKit/MTNetworkUsageManager.h>
|
#import <MtProtoKit/MTNetworkUsageManager.h>
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
#import <MtProtoKit/MTNetworkUsageCalculationInfo.h>
|
#import <MtProtoKit/MTNetworkUsageCalculationInfo.h>
|
||||||
#import <MtProtoKit/MTSignal.h>
|
#import <MtProtoKit/MTSignal.h>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#import <MtProtoKit/MTOutgoingMessage.h>
|
#import <MtProtoKit/MTOutgoingMessage.h>
|
||||||
|
|
||||||
|
#import <os/lock.h>
|
||||||
#import <libkern/OSAtomic.h>
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
@interface MTOutgoingMessageInternalId : NSObject <NSCopying>
|
@interface MTOutgoingMessageInternalId : NSObject <NSCopying>
|
||||||
@ -17,7 +18,10 @@
|
|||||||
if (self != nil)
|
if (self != nil)
|
||||||
{
|
{
|
||||||
static int32_t nextValue = 1;
|
static int32_t nextValue = 1;
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
_value = OSAtomicIncrement32(&nextValue);
|
_value = OSAtomicIncrement32(&nextValue);
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
|
|
||||||
#import <MtProtoKit/MTInternalId.h>
|
#import <MtProtoKit/MTInternalId.h>
|
||||||
|
|
||||||
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
MTInternalIdClass(MTPreparedMessage)
|
MTInternalIdClass(MTPreparedMessage)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
@implementation MTPreparedMessage
|
@implementation MTPreparedMessage
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#import <MtProtoKit/MTRpcError.h>
|
#import <MtProtoKit/MTRpcError.h>
|
||||||
|
|
||||||
|
#import <os/lock.h>
|
||||||
#import <libkern/OSAtomic.h>
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
@interface MTRequestInternalId : NSObject <NSCopying>
|
@interface MTRequestInternalId : NSObject <NSCopying>
|
||||||
@ -19,7 +20,10 @@
|
|||||||
if (self != nil)
|
if (self != nil)
|
||||||
{
|
{
|
||||||
static int32_t nextValue = 1;
|
static int32_t nextValue = 1;
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
_value = OSAtomicIncrement32(&nextValue);
|
_value = OSAtomicIncrement32(&nextValue);
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#import <MtProtoKit/MTSignal.h>
|
#import <MtProtoKit/MTSignal.h>
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
#import <MtProtoKit/MTTimer.h>
|
#import <MtProtoKit/MTTimer.h>
|
||||||
#import <MtProtoKit/MTQueue.h>
|
#import <MtProtoKit/MTQueue.h>
|
||||||
#import <MtProtoKit/MTAtomic.h>
|
#import <MtProtoKit/MTAtomic.h>
|
||||||
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
@interface MTSignalQueueState : NSObject <MTDisposable>
|
@interface MTSignalQueueState : NSObject <MTDisposable>
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
bool _executingSignal;
|
bool _executingSignal;
|
||||||
bool _terminated;
|
bool _terminated;
|
||||||
|
|
||||||
@ -92,7 +92,7 @@
|
|||||||
- (void)enqueueSignal:(MTSignal *)signal
|
- (void)enqueueSignal:(MTSignal *)signal
|
||||||
{
|
{
|
||||||
bool startSignal = false;
|
bool startSignal = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_queueMode && _executingSignal)
|
if (_queueMode && _executingSignal)
|
||||||
{
|
{
|
||||||
[_queuedSignals addObject:signal];
|
[_queuedSignals addObject:signal];
|
||||||
@ -102,7 +102,7 @@
|
|||||||
_executingSignal = true;
|
_executingSignal = true;
|
||||||
startSignal = true;
|
startSignal = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (startSignal)
|
if (startSignal)
|
||||||
{
|
{
|
||||||
@ -130,7 +130,7 @@
|
|||||||
MTSignal *nextSignal = nil;
|
MTSignal *nextSignal = nil;
|
||||||
|
|
||||||
bool terminated = false;
|
bool terminated = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
_executingSignal = false;
|
_executingSignal = false;
|
||||||
|
|
||||||
if (_queueMode)
|
if (_queueMode)
|
||||||
@ -146,7 +146,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
terminated = _terminated;
|
terminated = _terminated;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (terminated)
|
if (terminated)
|
||||||
[_subscriber putCompletion];
|
[_subscriber putCompletion];
|
||||||
@ -174,10 +174,10 @@
|
|||||||
- (void)beginCompletion
|
- (void)beginCompletion
|
||||||
{
|
{
|
||||||
bool executingSignal = false;
|
bool executingSignal = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
executingSignal = _executingSignal;
|
executingSignal = _executingSignal;
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (!executingSignal)
|
if (!executingSignal)
|
||||||
[_subscriber putCompletion];
|
[_subscriber putCompletion];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#import <MtProtoKit/MTSubscriber.h>
|
#import <MtProtoKit/MTSubscriber.h>
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
@interface MTSubscriberBlocks : NSObject {
|
@interface MTSubscriberBlocks : NSObject {
|
||||||
@public
|
@public
|
||||||
@ -28,7 +28,7 @@
|
|||||||
@interface MTSubscriber ()
|
@interface MTSubscriber ()
|
||||||
{
|
{
|
||||||
@protected
|
@protected
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
bool _terminated;
|
bool _terminated;
|
||||||
id<MTDisposable> _disposable;
|
id<MTDisposable> _disposable;
|
||||||
MTSubscriberBlocks *_blocks;
|
MTSubscriberBlocks *_blocks;
|
||||||
@ -51,13 +51,13 @@
|
|||||||
- (void)_assignDisposable:(id<MTDisposable>)disposable
|
- (void)_assignDisposable:(id<MTDisposable>)disposable
|
||||||
{
|
{
|
||||||
bool dispose = false;
|
bool dispose = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_terminated) {
|
if (_terminated) {
|
||||||
dispose = true;
|
dispose = true;
|
||||||
} else {
|
} else {
|
||||||
_disposable = disposable;
|
_disposable = disposable;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (dispose) {
|
if (dispose) {
|
||||||
[disposable dispose];
|
[disposable dispose];
|
||||||
@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
- (void)_markTerminatedWithoutDisposal
|
- (void)_markTerminatedWithoutDisposal
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
MTSubscriberBlocks *blocks = nil;
|
MTSubscriberBlocks *blocks = nil;
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (blocks) {
|
if (blocks) {
|
||||||
blocks = nil;
|
blocks = nil;
|
||||||
@ -86,11 +86,11 @@
|
|||||||
{
|
{
|
||||||
MTSubscriberBlocks *blocks = nil;
|
MTSubscriberBlocks *blocks = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated) {
|
if (!_terminated) {
|
||||||
blocks = _blocks;
|
blocks = _blocks;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (blocks && blocks->_next) {
|
if (blocks && blocks->_next) {
|
||||||
blocks->_next(next);
|
blocks->_next(next);
|
||||||
@ -102,7 +102,7 @@
|
|||||||
bool shouldDispose = false;
|
bool shouldDispose = false;
|
||||||
MTSubscriberBlocks *blocks = nil;
|
MTSubscriberBlocks *blocks = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
blocks = _blocks;
|
blocks = _blocks;
|
||||||
@ -111,7 +111,7 @@
|
|||||||
shouldDispose = true;
|
shouldDispose = true;
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (blocks && blocks->_error) {
|
if (blocks && blocks->_error) {
|
||||||
blocks->_error(error);
|
blocks->_error(error);
|
||||||
@ -126,7 +126,7 @@
|
|||||||
bool shouldDispose = false;
|
bool shouldDispose = false;
|
||||||
MTSubscriberBlocks *blocks = nil;
|
MTSubscriberBlocks *blocks = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
blocks = _blocks;
|
blocks = _blocks;
|
||||||
@ -135,7 +135,7 @@
|
|||||||
shouldDispose = true;
|
shouldDispose = true;
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (blocks && blocks->_completed)
|
if (blocks && blocks->_completed)
|
||||||
blocks->_completed();
|
blocks->_completed();
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#import <EncryptionProvider/EncryptionProvider.h>
|
#import <EncryptionProvider/EncryptionProvider.h>
|
||||||
|
|
||||||
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
static id<MTBignum> get_y2(id<MTBignum> x, id<MTBignum> mod, id<MTBignumContext> context) {
|
static id<MTBignum> get_y2(id<MTBignum> x, id<MTBignum> mod, id<MTBignumContext> context) {
|
||||||
// returns y^2 = x^3 + 486662 * x^2 + x
|
// returns y^2 = x^3 + 486662 * x^2 + x
|
||||||
id<MTBignum> y = [context clone:x];
|
id<MTBignum> y = [context clone:x];
|
||||||
@ -495,7 +497,10 @@ static NSData *executeGenerationCode(id<EncryptionProvider> provider, NSData *do
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
MTInternalIdClass(MTTcpConnection)
|
MTInternalIdClass(MTTcpConnection)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
struct socks5_ident_req
|
struct socks5_ident_req
|
||||||
{
|
{
|
||||||
|
@ -727,7 +727,7 @@ private func deviceContactInfoEntries(account: Account, engine: TelegramEngine,
|
|||||||
|
|
||||||
var addressIndex = 0
|
var addressIndex = 0
|
||||||
for address in contactData.addresses {
|
for address in contactData.addresses {
|
||||||
let signal = geocodeLocation(dictionary: address.dictionary)
|
let signal = geocodeLocation(address: address.asPostalAddress)
|
||||||
|> mapToSignal { coordinates -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in
|
|> mapToSignal { coordinates -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in
|
||||||
if let (latitude, longitude) = coordinates {
|
if let (latitude, longitude) = coordinates {
|
||||||
let resource = MapSnapshotMediaResource(latitude: latitude, longitude: longitude, width: 90, height: 90)
|
let resource = MapSnapshotMediaResource(latitude: latitude, longitude: longitude, width: 90, height: 90)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#import <LegacyReachability/LegacyReachability.h>
|
#import <LegacyReachability/LegacyReachability.h>
|
||||||
|
|
||||||
#import <pthread.h>
|
#import <pthread.h>
|
||||||
|
#import <os/lock.h>
|
||||||
#import <libkern/OSAtomic.h>
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
#pragma mark IPv6 Support
|
#pragma mark IPv6 Support
|
||||||
|
@ -118,6 +118,7 @@ final class ReactionContextBackgroundNode: ASDisplayNode {
|
|||||||
cloudSourcePoint: CGFloat,
|
cloudSourcePoint: CGFloat,
|
||||||
isLeftAligned: Bool,
|
isLeftAligned: Bool,
|
||||||
isMinimized: Bool,
|
isMinimized: Bool,
|
||||||
|
isCoveredByInput: Bool,
|
||||||
transition: ContainedViewLayoutTransition
|
transition: ContainedViewLayoutTransition
|
||||||
) {
|
) {
|
||||||
let shadowInset: CGFloat = 15.0
|
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.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.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(layer: self.smallCircleShadowLayer, frame: smallCircleFrame.insetBy(dx: -shadowInset, dy: -shadowInset), beginWithCurrentState: true)
|
||||||
|
|
||||||
transition.updateFrame(view: self.backgroundView, frame: contentBounds, beginWithCurrentState: true)
|
transition.updateFrame(view: self.backgroundView, frame: contentBounds, beginWithCurrentState: true)
|
||||||
|
@ -200,7 +200,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
private var highlightedByHover = false
|
private var highlightedByHover = false
|
||||||
private var didTriggerExpandedReaction: Bool = false
|
private var didTriggerExpandedReaction: Bool = false
|
||||||
private var continuousHaptic: Any?
|
private var continuousHaptic: Any?
|
||||||
private var validLayout: (CGSize, UIEdgeInsets, CGRect)?
|
private var validLayout: (CGSize, UIEdgeInsets, CGRect, Bool)?
|
||||||
private var isLeftAligned: Bool = true
|
private var isLeftAligned: Bool = true
|
||||||
private var itemLayout: ItemLayout?
|
private var itemLayout: ItemLayout?
|
||||||
|
|
||||||
@ -236,6 +236,9 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
private let emojiSearchDisposable = MetaDisposable()
|
private let emojiSearchDisposable = MetaDisposable()
|
||||||
private let emojiSearchResult = Promise<(groups: [EmojiPagerContentComponent.ItemGroup], id: AnyHashable)?>(nil)
|
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 horizontalExpandRecognizer: UIPanGestureRecognizer?
|
||||||
private var horizontalExpandStartLocation: CGPoint?
|
private var horizontalExpandStartLocation: CGPoint?
|
||||||
@ -409,6 +412,32 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if let getEmojiContent = getEmojiContent {
|
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(),
|
self.emojiContentDisposable = combineLatest(queue: .mainQueue(),
|
||||||
getEmojiContent(self.animationCache, self.animationRenderer),
|
getEmojiContent(self.animationCache, self.animationRenderer),
|
||||||
self.emojiSearchResult.get()
|
self.emojiSearchResult.get()
|
||||||
@ -419,7 +448,22 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
var emojiContent = emojiContent
|
var emojiContent = emojiContent
|
||||||
if let emojiSearchResult = emojiSearchResult {
|
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
|
strongSelf.emojiContent = emojiContent
|
||||||
@ -477,6 +521,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.hasPremiumDisposable?.dispose()
|
self.hasPremiumDisposable?.dispose()
|
||||||
self.genericReactionEffectDisposable?.dispose()
|
self.genericReactionEffectDisposable?.dispose()
|
||||||
self.emojiSearchDisposable.dispose()
|
self.emojiSearchDisposable.dispose()
|
||||||
|
self.stableEmptyResultEmojiDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func didLoad() {
|
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) {
|
public func updateLayout(size: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, isCoveredByInput: Bool, isAnimatingOut: Bool, transition: ContainedViewLayoutTransition) {
|
||||||
self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: isAnimatingOut, transition: transition, animateInFromAnchorRect: nil, animateOutToAnchorRect: nil)
|
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) {
|
public func updateIsIntersectingContent(isIntersectingContent: Bool, transition: ContainedViewLayoutTransition) {
|
||||||
@ -544,8 +589,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
if self.extensionDistance != distance {
|
if self.extensionDistance != distance {
|
||||||
self.extensionDistance = distance
|
self.extensionDistance = distance
|
||||||
|
|
||||||
if let (size, insets, anchorRect) = self.validLayout {
|
if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout {
|
||||||
self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: nil, animateOutToAnchorRect: nil)
|
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.selectionTintView.isHidden = false
|
||||||
itemNode.selectionView.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.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)
|
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)
|
itemNode.appear(animated: !self.context.sharedContext.currentPresentationData.with({ $0 }).reduceMotion)
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.getEmojiContent != nil && i == itemLayout.visibleItemCount - 1 {
|
if self.getEmojiContent != nil, i == itemLayout.visibleItemCount - 1, let itemNode = itemNode as? ReactionNode {
|
||||||
transition.updateSublayerTransformScale(node: itemNode, scale: 0.001 * (1.0 - compressionFactor) + normalItemScale * compressionFactor)
|
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
|
let alphaFraction = min(compressionFactor, 0.2) / 0.2
|
||||||
transition.updateAlpha(node: itemNode, alpha: alphaFraction)
|
transition.updateAlpha(node: itemNode, alpha: alphaFraction)
|
||||||
|
transition.updateAlpha(layer: itemNode.selectionView.layer, alpha: alphaFraction)
|
||||||
|
transition.updateAlpha(layer: itemNode.selectionTintView.layer, alpha: alphaFraction)
|
||||||
} else {
|
} else {
|
||||||
transition.updateSublayerTransformScale(node: itemNode, scale: normalItemScale)
|
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 {
|
if let expandItemView = self.expandItemView {
|
||||||
expandItemView.updateTheme(theme: self.presentationData.theme)
|
expandItemView.updateTheme(theme: self.presentationData.theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.validLayout = (size, insets, anchorRect)
|
self.validLayout = (size, insets, anchorRect, isCoveredByInput)
|
||||||
|
|
||||||
let externalSideInset: CGFloat = 4.0
|
let externalSideInset: CGFloat = 4.0
|
||||||
let sideInset: CGFloat = 6.0
|
let sideInset: CGFloat = 6.0
|
||||||
@ -1068,6 +1124,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.scrollNode.isHidden = true
|
strongSelf.scrollNode.isHidden = true
|
||||||
|
strongSelf.mirrorContentScrollView.isHidden = true
|
||||||
})
|
})
|
||||||
expandItemView.layer.animateScale(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
expandItemView.layer.animateScale(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||||
expandItemView.tintView.alpha = 0.0
|
expandItemView.tintView.alpha = 0.0
|
||||||
@ -1095,6 +1152,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
cloudSourcePoint: cloudSourcePoint - visualBackgroundFrame.minX,
|
cloudSourcePoint: cloudSourcePoint - visualBackgroundFrame.minX,
|
||||||
isLeftAligned: isLeftAligned,
|
isLeftAligned: isLeftAligned,
|
||||||
isMinimized: self.highlightedReaction != nil && !self.highlightedByHover,
|
isMinimized: self.highlightedReaction != nil && !self.highlightedByHover,
|
||||||
|
isCoveredByInput: isCoveredByInput,
|
||||||
transition: transition
|
transition: transition
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1276,11 +1334,13 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
strongSelf.requestUpdateOverlayWantsToBeBelowKeyboard(transition.containedViewLayoutTransition)
|
strongSelf.requestUpdateOverlayWantsToBeBelowKeyboard(transition.containedViewLayoutTransition)
|
||||||
},
|
},
|
||||||
updateSearchQuery: { [weak self] query in
|
updateSearchQuery: { [weak self] rawQuery in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let query = rawQuery.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
|
||||||
if query.isEmpty {
|
if query.isEmpty {
|
||||||
strongSelf.emojiSearchDisposable.set(nil)
|
strongSelf.emojiSearchDisposable.set(nil)
|
||||||
strongSelf.emojiSearchResult.set(.single(nil))
|
strongSelf.emojiSearchResult.set(.single(nil))
|
||||||
@ -1288,7 +1348,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
let context = strongSelf.context
|
let context = strongSelf.context
|
||||||
|
|
||||||
let languageCode = "en"
|
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") {
|
if !languageCode.lowercased().hasPrefix("en") {
|
||||||
signal = signal
|
signal = signal
|
||||||
|> mapToSignal { keywords in
|
|> mapToSignal { keywords in
|
||||||
@ -1315,9 +1375,11 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
|
|> mapToSignal { keywords -> Signal<[EmojiPagerContentComponent.ItemGroup], NoError> in
|
||||||
return combineLatest(
|
return combineLatest(
|
||||||
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000),
|
context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000),
|
||||||
|
context.engine.stickers.availableReactions(),
|
||||||
hasPremium
|
hasPremium
|
||||||
)
|
)
|
||||||
|> map { view, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in
|
|> take(1)
|
||||||
|
|> map { view, availableReactions, hasPremium -> [EmojiPagerContentComponent.ItemGroup] in
|
||||||
var result: [(String, TelegramMediaFile?, String)] = []
|
var result: [(String, TelegramMediaFile?, String)] = []
|
||||||
|
|
||||||
var allEmoticons: [String: String] = [:]
|
var allEmoticons: [String: String] = [:]
|
||||||
@ -1369,11 +1431,25 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [EmojiPagerContentComponent.ItemGroup(
|
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
|
strongSelf.emojiSearchDisposable.set((resultSignal
|
||||||
|
|> delay(0.15, queue: .mainQueue())
|
||||||
|> deliverOnMainQueue).start(next: { result in
|
|> deliverOnMainQueue).start(next: { result in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -1396,8 +1472,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
public func animateIn(from sourceAnchorRect: CGRect) {
|
public func animateIn(from sourceAnchorRect: CGRect) {
|
||||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||||
|
|
||||||
if let (size, insets, anchorRect) = self.validLayout {
|
if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout {
|
||||||
self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: sourceAnchorRect, animateOutToAnchorRect: nil)
|
self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isCoveredByInput: isCoveredByInput, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: sourceAnchorRect, animateOutToAnchorRect: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mainCircleDelay: Double = 0.01
|
let mainCircleDelay: Double = 0.01
|
||||||
@ -1411,6 +1487,10 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
guard let itemNode = self.visibleItemNodes[i] else {
|
guard let itemNode = self.visibleItemNodes[i] else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if let itemLayout = self.itemLayout, self.getEmojiContent != nil, i == itemLayout.visibleItemCount - 1 {
|
||||||
|
itemNode.appear(animated: false)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
let itemDelay: Double
|
let itemDelay: Double
|
||||||
if let animateInInfo = self.animateInInfo {
|
if let animateInInfo = self.animateInInfo {
|
||||||
@ -1421,7 +1501,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
} else {
|
} else {
|
||||||
itemDelay = mainCircleDelay + Double(i) * 0.06
|
itemDelay = mainCircleDelay + Double(i) * 0.06
|
||||||
}
|
}
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + itemDelay * UIView.animationDurationFactor(), execute: { [weak itemNode] in
|
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + itemDelay * UIView.animationDurationFactor(), execute: { [weak itemNode] in
|
||||||
guard let itemNode = itemNode else {
|
guard let itemNode = itemNode else {
|
||||||
return
|
return
|
||||||
@ -1475,8 +1555,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
expandItemView.tintView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
|
expandItemView.tintView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let targetAnchorRect = targetAnchorRect, let (size, insets, anchorRect) = self.validLayout {
|
if let targetAnchorRect = targetAnchorRect, let (size, insets, anchorRect, isCoveredByInput) = self.validLayout {
|
||||||
self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .immediate, animateInFromAnchorRect: nil, animateOutToAnchorRect: targetAnchorRect)
|
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()
|
self.hapticFeedback = HapticFeedback()
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (size, insets, anchorRect) = self.validLayout {
|
if let (size, insets, anchorRect, isCoveredByInput) = self.validLayout {
|
||||||
self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, isAnimatingOut: false, transition: .animated(duration: longPressDuration, curve: .linear), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true)
|
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()
|
self.longPressTimer?.invalidate()
|
||||||
@ -1950,8 +2030,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.continuousHaptic = nil
|
self.continuousHaptic = nil
|
||||||
|
|
||||||
self.highlightedReaction = nil
|
self.highlightedReaction = nil
|
||||||
if let (size, insets, anchorRect) = self.validLayout {
|
if let (size, insets, anchorRect, isCoveredByInput) = 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)
|
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:
|
case .ended:
|
||||||
self.longPressTimer?.invalidate()
|
self.longPressTimer?.invalidate()
|
||||||
@ -2027,8 +2107,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.hapticFeedback?.tap()
|
self.hapticFeedback?.tap()
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (size, insets, anchorRect) = self.validLayout {
|
if let (size, insets, anchorRect, isCoveredByInput) = 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)
|
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 {
|
if performAction {
|
||||||
self.performReactionSelection(reaction: highlightedReaction, isLarge: isLarge)
|
self.performReactionSelection(reaction: highlightedReaction, isLarge: isLarge)
|
||||||
} else {
|
} else {
|
||||||
if let (size, insets, anchorRect) = self.validLayout {
|
if let (size, insets, anchorRect, isCoveredByInput) = 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)
|
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?) {
|
public func setHighlightedReaction(_ value: ReactionItem.Reaction?) {
|
||||||
self.highlightedReaction = value
|
self.highlightedReaction = value
|
||||||
if let (size, insets, anchorRect) = self.validLayout {
|
if let (size, insets, anchorRect, isCoveredByInput) = 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)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,17 +167,13 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode {
|
|||||||
self.animateInAnimationNode?.visibility = true
|
self.animateInAnimationNode?.visibility = true
|
||||||
}
|
}
|
||||||
|
|
||||||
self.selectionView.alpha = 1.0
|
self.selectionView.layer.animateAlpha(from: 0.0, to: self.selectionView.alpha, duration: 0.2)
|
||||||
self.selectionView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
|
||||||
self.selectionView.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4)
|
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: self.selectionTintView.alpha, duration: 0.2)
|
||||||
self.selectionTintView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
|
||||||
self.selectionTintView.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4)
|
self.selectionTintView.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4)
|
||||||
} else {
|
} else {
|
||||||
self.animateInAnimationNode?.completed(true)
|
self.animateInAnimationNode?.completed(true)
|
||||||
self.selectionView.alpha = 1.0
|
|
||||||
self.selectionTintView.alpha = 1.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#import "SBlockDisposable.h"
|
#import "SBlockDisposable.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
#import <objc/runtime.h>
|
#import <objc/runtime.h>
|
||||||
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
@interface SBlockDisposable ()
|
@interface SBlockDisposable ()
|
||||||
{
|
{
|
||||||
@ -27,6 +28,8 @@
|
|||||||
void *block = _block;
|
void *block = _block;
|
||||||
if (block != NULL)
|
if (block != NULL)
|
||||||
{
|
{
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
||||||
{
|
{
|
||||||
if (block != nil)
|
if (block != nil)
|
||||||
@ -35,6 +38,7 @@
|
|||||||
strongBlock = nil;
|
strongBlock = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,6 +47,8 @@
|
|||||||
void *block = _block;
|
void *block = _block;
|
||||||
if (block != NULL)
|
if (block != NULL)
|
||||||
{
|
{
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||||
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
if (OSAtomicCompareAndSwapPtr(block, 0, &_block))
|
||||||
{
|
{
|
||||||
if (block != nil)
|
if (block != nil)
|
||||||
@ -52,6 +58,7 @@
|
|||||||
strongBlock = nil;
|
strongBlock = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
#import "SSignal.h"
|
#import "SSignal.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
@interface SDisposableSet ()
|
@interface SDisposableSet ()
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
bool _disposed;
|
bool _disposed;
|
||||||
id<SDisposable> _singleDisposable;
|
id<SDisposable> _singleDisposable;
|
||||||
NSArray *_multipleDisposables;
|
NSArray *_multipleDisposables;
|
||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
bool dispose = false;
|
bool dispose = false;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
dispose = _disposed;
|
dispose = _disposed;
|
||||||
if (!dispose)
|
if (!dispose)
|
||||||
{
|
{
|
||||||
@ -44,14 +44,14 @@
|
|||||||
_singleDisposable = disposable;
|
_singleDisposable = disposable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (dispose)
|
if (dispose)
|
||||||
[disposable dispose];
|
[disposable dispose];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)remove:(id<SDisposable>)disposable {
|
- (void)remove:(id<SDisposable>)disposable {
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_multipleDisposables != nil)
|
if (_multipleDisposables != nil)
|
||||||
{
|
{
|
||||||
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables];
|
NSMutableArray *multipleDisposables = [[NSMutableArray alloc] initWithArray:_multipleDisposables];
|
||||||
@ -62,7 +62,7 @@
|
|||||||
{
|
{
|
||||||
_singleDisposable = nil;
|
_singleDisposable = nil;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dispose
|
- (void)dispose
|
||||||
@ -70,7 +70,7 @@
|
|||||||
id<SDisposable> singleDisposable = nil;
|
id<SDisposable> singleDisposable = nil;
|
||||||
NSArray *multipleDisposables = nil;
|
NSArray *multipleDisposables = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_disposed)
|
if (!_disposed)
|
||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
@ -79,7 +79,7 @@
|
|||||||
_singleDisposable = nil;
|
_singleDisposable = nil;
|
||||||
_multipleDisposables = nil;
|
_multipleDisposables = nil;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (singleDisposable != nil)
|
if (singleDisposable != nil)
|
||||||
[singleDisposable dispose];
|
[singleDisposable dispose];
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
#import "SMetaDisposable.h"
|
#import "SMetaDisposable.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
@interface SMetaDisposable ()
|
@interface SMetaDisposable ()
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
bool _disposed;
|
bool _disposed;
|
||||||
id<SDisposable> _disposable;
|
id<SDisposable> _disposable;
|
||||||
}
|
}
|
||||||
@ -18,14 +18,14 @@
|
|||||||
id<SDisposable> previousDisposable = nil;
|
id<SDisposable> previousDisposable = nil;
|
||||||
bool dispose = false;
|
bool dispose = false;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
dispose = _disposed;
|
dispose = _disposed;
|
||||||
if (!dispose)
|
if (!dispose)
|
||||||
{
|
{
|
||||||
previousDisposable = _disposable;
|
previousDisposable = _disposable;
|
||||||
_disposable = disposable;
|
_disposable = disposable;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (previousDisposable != nil)
|
if (previousDisposable != nil)
|
||||||
[previousDisposable dispose];
|
[previousDisposable dispose];
|
||||||
@ -38,13 +38,13 @@
|
|||||||
{
|
{
|
||||||
id<SDisposable> disposable = nil;
|
id<SDisposable> disposable = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_disposed)
|
if (!_disposed)
|
||||||
{
|
{
|
||||||
disposable = _disposable;
|
disposable = _disposable;
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (disposable != nil)
|
if (disposable != nil)
|
||||||
[disposable dispose];
|
[disposable dispose];
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
#import "SMetaDisposable.h"
|
#import "SMetaDisposable.h"
|
||||||
#import "SBlockDisposable.h"
|
#import "SBlockDisposable.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
@interface SMulticastSignalManager ()
|
@interface SMulticastSignalManager ()
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
NSMutableDictionary *_multicastSignals;
|
NSMutableDictionary *_multicastSignals;
|
||||||
NSMutableDictionary *_standaloneSignalDisposables;
|
NSMutableDictionary *_standaloneSignalDisposables;
|
||||||
NSMutableDictionary *_pipeListeners;
|
NSMutableDictionary *_pipeListeners;
|
||||||
@ -35,9 +35,9 @@
|
|||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
NSArray *disposables = nil;
|
NSArray *disposables = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
disposables = [_standaloneSignalDisposables allValues];
|
disposables = [_standaloneSignalDisposables allValues];
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
for (id<SDisposable> disposable in disposables)
|
for (id<SDisposable> disposable in disposables)
|
||||||
{
|
{
|
||||||
@ -56,7 +56,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
SSignal *signal = nil;
|
SSignal *signal = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
signal = _multicastSignals[key];
|
signal = _multicastSignals[key];
|
||||||
if (signal == nil)
|
if (signal == nil)
|
||||||
{
|
{
|
||||||
@ -70,15 +70,15 @@
|
|||||||
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
||||||
if (strongSelf != nil)
|
if (strongSelf != nil)
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&strongSelf->_lock);
|
os_unfair_lock_lock(&strongSelf->_lock);
|
||||||
[strongSelf->_multicastSignals removeObjectForKey:key];
|
[strongSelf->_multicastSignals removeObjectForKey:key];
|
||||||
OSSpinLockUnlock(&strongSelf->_lock);
|
os_unfair_lock_unlock(&strongSelf->_lock);
|
||||||
}
|
}
|
||||||
}] multicast];
|
}] multicast];
|
||||||
_multicastSignals[key] = signal;
|
_multicastSignals[key] = signal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
return signal;
|
return signal;
|
||||||
}
|
}
|
||||||
@ -89,13 +89,13 @@
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
bool produce = false;
|
bool produce = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_standaloneSignalDisposables[key] == nil)
|
if (_standaloneSignalDisposables[key] == nil)
|
||||||
{
|
{
|
||||||
_standaloneSignalDisposables[key] = [[SMetaDisposable alloc] init];
|
_standaloneSignalDisposables[key] = [[SMetaDisposable alloc] init];
|
||||||
produce = true;
|
produce = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (produce)
|
if (produce)
|
||||||
{
|
{
|
||||||
@ -105,24 +105,24 @@
|
|||||||
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
||||||
if (strongSelf != nil)
|
if (strongSelf != nil)
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&strongSelf->_lock);
|
os_unfair_lock_lock(&strongSelf->_lock);
|
||||||
[strongSelf->_standaloneSignalDisposables removeObjectForKey:key];
|
[strongSelf->_standaloneSignalDisposables removeObjectForKey:key];
|
||||||
OSSpinLockUnlock(&strongSelf->_lock);
|
os_unfair_lock_unlock(&strongSelf->_lock);
|
||||||
}
|
}
|
||||||
} completed:^
|
} completed:^
|
||||||
{
|
{
|
||||||
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
__strong SMulticastSignalManager *strongSelf = weakSelf;
|
||||||
if (strongSelf != nil)
|
if (strongSelf != nil)
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&strongSelf->_lock);
|
os_unfair_lock_lock(&strongSelf->_lock);
|
||||||
[strongSelf->_standaloneSignalDisposables removeObjectForKey:key];
|
[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];
|
[(SMetaDisposable *)_standaloneSignalDisposables[key] setDisposable:disposable];
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@
|
|||||||
{
|
{
|
||||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
|
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
SBag *bag = _pipeListeners[key];
|
SBag *bag = _pipeListeners[key];
|
||||||
if (bag == nil)
|
if (bag == nil)
|
||||||
{
|
{
|
||||||
@ -141,26 +141,26 @@
|
|||||||
{
|
{
|
||||||
[subscriber putNext:next];
|
[subscriber putNext:next];
|
||||||
} copy]];
|
} copy]];
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
return [[SBlockDisposable alloc] initWithBlock:^
|
return [[SBlockDisposable alloc] initWithBlock:^
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
SBag *bag = _pipeListeners[key];
|
SBag *bag = _pipeListeners[key];
|
||||||
[bag removeItem:index];
|
[bag removeItem:index];
|
||||||
if ([bag isEmpty]) {
|
if ([bag isEmpty]) {
|
||||||
[_pipeListeners removeObjectForKey:key];
|
[_pipeListeners removeObjectForKey:key];
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}];
|
}];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)putNext:(id)next toMulticastedPipeForKey:(NSString *)key
|
- (void)putNext:(id)next toMulticastedPipeForKey:(NSString *)key
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
NSArray *pipeListeners = [(SBag *)_pipeListeners[key] copyItems];
|
NSArray *pipeListeners = [(SBag *)_pipeListeners[key] copyItems];
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
for (void (^listener)(id) in pipeListeners)
|
for (void (^listener)(id) in pipeListeners)
|
||||||
{
|
{
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
#import "SAtomic.h"
|
#import "SAtomic.h"
|
||||||
#import "SSignal+Pipe.h"
|
#import "SSignal+Pipe.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
@interface SSignalQueueState : NSObject <SDisposable>
|
@interface SSignalQueueState : NSObject <SDisposable>
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
bool _executingSignal;
|
bool _executingSignal;
|
||||||
bool _terminated;
|
bool _terminated;
|
||||||
|
|
||||||
@ -49,7 +49,7 @@
|
|||||||
- (void)enqueueSignal:(SSignal *)signal
|
- (void)enqueueSignal:(SSignal *)signal
|
||||||
{
|
{
|
||||||
bool startSignal = false;
|
bool startSignal = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_queueMode && _executingSignal) {
|
if (_queueMode && _executingSignal) {
|
||||||
if (_throttleMode) {
|
if (_throttleMode) {
|
||||||
[_queuedSignals removeAllObjects];
|
[_queuedSignals removeAllObjects];
|
||||||
@ -61,7 +61,7 @@
|
|||||||
_executingSignal = true;
|
_executingSignal = true;
|
||||||
startSignal = true;
|
startSignal = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (startSignal)
|
if (startSignal)
|
||||||
{
|
{
|
||||||
@ -89,7 +89,7 @@
|
|||||||
SSignal *nextSignal = nil;
|
SSignal *nextSignal = nil;
|
||||||
|
|
||||||
bool terminated = false;
|
bool terminated = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
_executingSignal = false;
|
_executingSignal = false;
|
||||||
|
|
||||||
if (_queueMode)
|
if (_queueMode)
|
||||||
@ -105,7 +105,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
terminated = _terminated;
|
terminated = _terminated;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (terminated)
|
if (terminated)
|
||||||
[_subscriber putCompletion];
|
[_subscriber putCompletion];
|
||||||
@ -133,10 +133,10 @@
|
|||||||
- (void)beginCompletion
|
- (void)beginCompletion
|
||||||
{
|
{
|
||||||
bool executingSignal = false;
|
bool executingSignal = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
executingSignal = _executingSignal;
|
executingSignal = _executingSignal;
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (!executingSignal)
|
if (!executingSignal)
|
||||||
[_subscriber putCompletion];
|
[_subscriber putCompletion];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#import "SSignal+Multicast.h"
|
#import "SSignal+Multicast.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
#import "SBag.h"
|
#import "SBag.h"
|
||||||
#import "SBlockDisposable.h"
|
#import "SBlockDisposable.h"
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ typedef enum {
|
|||||||
|
|
||||||
@interface SSignalMulticastSubscribers : NSObject
|
@interface SSignalMulticastSubscribers : NSObject
|
||||||
{
|
{
|
||||||
volatile OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
SBag *_subscribers;
|
SBag *_subscribers;
|
||||||
SSignalMulticastState _state;
|
SSignalMulticastState _state;
|
||||||
id<SDisposable> _disposable;
|
id<SDisposable> _disposable;
|
||||||
@ -40,7 +40,7 @@ typedef enum {
|
|||||||
|
|
||||||
- (id<SDisposable>)addSubscriber:(SSubscriber *)subscriber start:(bool *)start
|
- (id<SDisposable>)addSubscriber:(SSubscriber *)subscriber start:(bool *)start
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
NSInteger index = [_subscribers addItem:subscriber];
|
NSInteger index = [_subscribers addItem:subscriber];
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case SSignalMulticastStateReady:
|
case SSignalMulticastStateReady:
|
||||||
@ -50,7 +50,7 @@ typedef enum {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
return [[SBlockDisposable alloc] initWithBlock:^
|
return [[SBlockDisposable alloc] initWithBlock:^
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ typedef enum {
|
|||||||
{
|
{
|
||||||
id<SDisposable> currentDisposable = nil;
|
id<SDisposable> currentDisposable = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
[_subscribers removeItem:index];
|
[_subscribers removeItem:index];
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case SSignalMulticastStateStarted:
|
case SSignalMulticastStateStarted:
|
||||||
@ -75,7 +75,7 @@ typedef enum {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
[currentDisposable dispose];
|
[currentDisposable dispose];
|
||||||
}
|
}
|
||||||
@ -83,9 +83,9 @@ typedef enum {
|
|||||||
- (void)notifyNext:(id)next
|
- (void)notifyNext:(id)next
|
||||||
{
|
{
|
||||||
NSArray *currentSubscribers = nil;
|
NSArray *currentSubscribers = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
currentSubscribers = [_subscribers copyItems];
|
currentSubscribers = [_subscribers copyItems];
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
for (SSubscriber *subscriber in currentSubscribers)
|
for (SSubscriber *subscriber in currentSubscribers)
|
||||||
{
|
{
|
||||||
@ -96,10 +96,10 @@ typedef enum {
|
|||||||
- (void)notifyError:(id)error
|
- (void)notifyError:(id)error
|
||||||
{
|
{
|
||||||
NSArray *currentSubscribers = nil;
|
NSArray *currentSubscribers = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
currentSubscribers = [_subscribers copyItems];
|
currentSubscribers = [_subscribers copyItems];
|
||||||
_state = SSignalMulticastStateCompleted;
|
_state = SSignalMulticastStateCompleted;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
for (SSubscriber *subscriber in currentSubscribers)
|
for (SSubscriber *subscriber in currentSubscribers)
|
||||||
{
|
{
|
||||||
@ -110,10 +110,10 @@ typedef enum {
|
|||||||
- (void)notifyCompleted
|
- (void)notifyCompleted
|
||||||
{
|
{
|
||||||
NSArray *currentSubscribers = nil;
|
NSArray *currentSubscribers = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
currentSubscribers = [_subscribers copyItems];
|
currentSubscribers = [_subscribers copyItems];
|
||||||
_state = SSignalMulticastStateCompleted;
|
_state = SSignalMulticastStateCompleted;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
for (SSubscriber *subscriber in currentSubscribers)
|
for (SSubscriber *subscriber in currentSubscribers)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#import "SSubscriber.h"
|
#import "SSubscriber.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
@interface SSubscriberBlocks : NSObject {
|
@interface SSubscriberBlocks : NSObject {
|
||||||
@public
|
@public
|
||||||
@ -28,7 +28,7 @@
|
|||||||
@interface SSubscriber ()
|
@interface SSubscriber ()
|
||||||
{
|
{
|
||||||
@protected
|
@protected
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
bool _terminated;
|
bool _terminated;
|
||||||
id<SDisposable> _disposable;
|
id<SDisposable> _disposable;
|
||||||
SSubscriberBlocks *_blocks;
|
SSubscriberBlocks *_blocks;
|
||||||
@ -51,13 +51,13 @@
|
|||||||
- (void)_assignDisposable:(id<SDisposable>)disposable
|
- (void)_assignDisposable:(id<SDisposable>)disposable
|
||||||
{
|
{
|
||||||
bool dispose = false;
|
bool dispose = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_terminated) {
|
if (_terminated) {
|
||||||
dispose = true;
|
dispose = true;
|
||||||
} else {
|
} else {
|
||||||
_disposable = disposable;
|
_disposable = disposable;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
if (dispose) {
|
if (dispose) {
|
||||||
[disposable dispose];
|
[disposable dispose];
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@
|
|||||||
|
|
||||||
- (void)_markTerminatedWithoutDisposal
|
- (void)_markTerminatedWithoutDisposal
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
SSubscriberBlocks *blocks = nil;
|
SSubscriberBlocks *blocks = nil;
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (blocks) {
|
if (blocks) {
|
||||||
blocks = nil;
|
blocks = nil;
|
||||||
@ -85,11 +85,11 @@
|
|||||||
{
|
{
|
||||||
SSubscriberBlocks *blocks = nil;
|
SSubscriberBlocks *blocks = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated) {
|
if (!_terminated) {
|
||||||
blocks = _blocks;
|
blocks = _blocks;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (blocks && blocks->_next) {
|
if (blocks && blocks->_next) {
|
||||||
blocks->_next(next);
|
blocks->_next(next);
|
||||||
@ -101,7 +101,7 @@
|
|||||||
bool shouldDispose = false;
|
bool shouldDispose = false;
|
||||||
SSubscriberBlocks *blocks = nil;
|
SSubscriberBlocks *blocks = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
blocks = _blocks;
|
blocks = _blocks;
|
||||||
@ -110,7 +110,7 @@
|
|||||||
shouldDispose = true;
|
shouldDispose = true;
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (blocks && blocks->_error) {
|
if (blocks && blocks->_error) {
|
||||||
blocks->_error(error);
|
blocks->_error(error);
|
||||||
@ -125,7 +125,7 @@
|
|||||||
bool shouldDispose = false;
|
bool shouldDispose = false;
|
||||||
SSubscriberBlocks *blocks = nil;
|
SSubscriberBlocks *blocks = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
blocks = _blocks;
|
blocks = _blocks;
|
||||||
@ -134,7 +134,7 @@
|
|||||||
shouldDispose = true;
|
shouldDispose = true;
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (blocks && blocks->_completed)
|
if (blocks && blocks->_completed)
|
||||||
blocks->_completed();
|
blocks->_completed();
|
||||||
@ -179,7 +179,7 @@
|
|||||||
|
|
||||||
- (void)_markTerminatedWithoutDisposal
|
- (void)_markTerminatedWithoutDisposal
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
NSLog(@"trace(%@ terminated)", _name);
|
NSLog(@"trace(%@ terminated)", _name);
|
||||||
@ -188,17 +188,17 @@
|
|||||||
_error = nil;
|
_error = nil;
|
||||||
_completed = nil;
|
_completed = nil;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)putNext:(id)next
|
- (void)putNext:(id)next
|
||||||
{
|
{
|
||||||
void (^fnext)(id) = nil;
|
void (^fnext)(id) = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
fnext = self->_next;
|
fnext = self->_next;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (fnext)
|
if (fnext)
|
||||||
{
|
{
|
||||||
@ -214,7 +214,7 @@
|
|||||||
bool shouldDispose = false;
|
bool shouldDispose = false;
|
||||||
void (^ferror)(id) = nil;
|
void (^ferror)(id) = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
ferror = self->_error;
|
ferror = self->_error;
|
||||||
@ -224,7 +224,7 @@
|
|||||||
self->_completed = nil;
|
self->_completed = nil;
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (ferror)
|
if (ferror)
|
||||||
{
|
{
|
||||||
@ -243,7 +243,7 @@
|
|||||||
bool shouldDispose = false;
|
bool shouldDispose = false;
|
||||||
void (^completed)() = nil;
|
void (^completed)() = nil;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (!_terminated)
|
if (!_terminated)
|
||||||
{
|
{
|
||||||
completed = self->_completed;
|
completed = self->_completed;
|
||||||
@ -253,7 +253,7 @@
|
|||||||
self->_completed = nil;
|
self->_completed = nil;
|
||||||
_terminated = true;
|
_terminated = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (completed)
|
if (completed)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#import "SThreadPool.h"
|
#import "SThreadPool.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
#import <pthread.h>
|
#import <pthread.h>
|
||||||
#import "SQueue.h"
|
#import "SQueue.h"
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#import "SVariable.h"
|
#import "SVariable.h"
|
||||||
|
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
|
|
||||||
#import "SSignal.h"
|
#import "SSignal.h"
|
||||||
#import "SBag.h"
|
#import "SBag.h"
|
||||||
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
@interface SVariable ()
|
@interface SVariable ()
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
id _value;
|
id _value;
|
||||||
bool _hasValue;
|
bool _hasValue;
|
||||||
SBag *_subscribers;
|
SBag *_subscribers;
|
||||||
@ -40,14 +40,14 @@
|
|||||||
{
|
{
|
||||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
|
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&self->_lock);
|
os_unfair_lock_lock(&self->_lock);
|
||||||
id currentValue = _value;
|
id currentValue = _value;
|
||||||
bool hasValue = _hasValue;
|
bool hasValue = _hasValue;
|
||||||
NSInteger index = [self->_subscribers addItem:[^(id value)
|
NSInteger index = [self->_subscribers addItem:[^(id value)
|
||||||
{
|
{
|
||||||
[subscriber putNext:value];
|
[subscriber putNext:value];
|
||||||
} copy]];
|
} copy]];
|
||||||
OSSpinLockUnlock(&self->_lock);
|
os_unfair_lock_unlock(&self->_lock);
|
||||||
|
|
||||||
if (hasValue)
|
if (hasValue)
|
||||||
{
|
{
|
||||||
@ -56,18 +56,18 @@
|
|||||||
|
|
||||||
return [[SBlockDisposable alloc] initWithBlock:^
|
return [[SBlockDisposable alloc] initWithBlock:^
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&self->_lock);
|
os_unfair_lock_lock(&self->_lock);
|
||||||
[self->_subscribers removeItem:index];
|
[self->_subscribers removeItem:index];
|
||||||
OSSpinLockUnlock(&self->_lock);
|
os_unfair_lock_unlock(&self->_lock);
|
||||||
}];
|
}];
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)set:(SSignal *)signal
|
- (void)set:(SSignal *)signal
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
_hasValue = false;
|
_hasValue = false;
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
__weak SVariable *weakSelf = self;
|
__weak SVariable *weakSelf = self;
|
||||||
[_disposable setDisposable:[signal startWithNext:^(id next)
|
[_disposable setDisposable:[signal startWithNext:^(id next)
|
||||||
@ -76,11 +76,11 @@
|
|||||||
if (strongSelf != nil)
|
if (strongSelf != nil)
|
||||||
{
|
{
|
||||||
NSArray *subscribers = nil;
|
NSArray *subscribers = nil;
|
||||||
OSSpinLockLock(&strongSelf->_lock);
|
os_unfair_lock_lock(&strongSelf->_lock);
|
||||||
strongSelf->_value = next;
|
strongSelf->_value = next;
|
||||||
strongSelf->_hasValue = true;
|
strongSelf->_hasValue = true;
|
||||||
subscribers = [strongSelf->_subscribers copyItems];
|
subscribers = [strongSelf->_subscribers copyItems];
|
||||||
OSSpinLockUnlock(&strongSelf->_lock);
|
os_unfair_lock_unlock(&strongSelf->_lock);
|
||||||
|
|
||||||
for (void (^subscriber)(id) in subscribers)
|
for (void (^subscriber)(id) in subscribers)
|
||||||
{
|
{
|
||||||
|
@ -43,7 +43,7 @@ public enum Passthrough<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class ReduceQueueState<T, E> : Disposable {
|
private final class ReduceQueueState<T, E> : Disposable {
|
||||||
var lock: OSSpinLock = 0
|
var lock = os_unfair_lock()
|
||||||
var executingSignal = false
|
var executingSignal = false
|
||||||
var terminated = false
|
var terminated = false
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ private final class ReduceQueueState<T, E> : Disposable {
|
|||||||
func enqueueNext(_ next: T) {
|
func enqueueNext(_ next: T) {
|
||||||
var startSignal = false
|
var startSignal = false
|
||||||
var currentValue: T
|
var currentValue: T
|
||||||
OSSpinLockLock(&self.lock)
|
os_unfair_lock_lock(&self.lock)
|
||||||
currentValue = self.value
|
currentValue = self.value
|
||||||
if self.executingSignal {
|
if self.executingSignal {
|
||||||
self.queuedValues.append(next)
|
self.queuedValues.append(next)
|
||||||
@ -76,7 +76,7 @@ private final class ReduceQueueState<T, E> : Disposable {
|
|||||||
self.executingSignal = true
|
self.executingSignal = true
|
||||||
startSignal = true
|
startSignal = true
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&self.lock)
|
os_unfair_lock_unlock(&self.lock)
|
||||||
|
|
||||||
if startSignal {
|
if startSignal {
|
||||||
let disposable = generator(currentValue, next).start(next: { next in
|
let disposable = generator(currentValue, next).start(next: { next in
|
||||||
@ -97,9 +97,9 @@ private final class ReduceQueueState<T, E> : Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateValue(_ value: T) {
|
func updateValue(_ value: T) {
|
||||||
OSSpinLockLock(&self.lock)
|
os_unfair_lock_lock(&self.lock)
|
||||||
self.value = value
|
self.value = value
|
||||||
OSSpinLockUnlock(&self.lock)
|
os_unfair_lock_unlock(&self.lock)
|
||||||
}
|
}
|
||||||
|
|
||||||
func headCompleted() {
|
func headCompleted() {
|
||||||
@ -110,7 +110,7 @@ private final class ReduceQueueState<T, E> : Disposable {
|
|||||||
|
|
||||||
var terminated = false
|
var terminated = false
|
||||||
var currentValue: T!
|
var currentValue: T!
|
||||||
OSSpinLockLock(&self.lock)
|
os_unfair_lock_lock(&self.lock)
|
||||||
self.executingSignal = false
|
self.executingSignal = false
|
||||||
if self.queuedValues.count != 0 {
|
if self.queuedValues.count != 0 {
|
||||||
nextSignal = self.generator(self.value, self.queuedValues[0])
|
nextSignal = self.generator(self.value, self.queuedValues[0])
|
||||||
@ -120,7 +120,7 @@ private final class ReduceQueueState<T, E> : Disposable {
|
|||||||
currentValue = self.value
|
currentValue = self.value
|
||||||
terminated = self.terminated
|
terminated = self.terminated
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&self.lock)
|
os_unfair_lock_unlock(&self.lock)
|
||||||
|
|
||||||
if terminated {
|
if terminated {
|
||||||
self.subscriber.putNext(currentValue)
|
self.subscriber.putNext(currentValue)
|
||||||
@ -154,11 +154,11 @@ private final class ReduceQueueState<T, E> : Disposable {
|
|||||||
func beginCompletion() {
|
func beginCompletion() {
|
||||||
var executingSignal = false
|
var executingSignal = false
|
||||||
let currentValue: T
|
let currentValue: T
|
||||||
OSSpinLockLock(&self.lock)
|
os_unfair_lock_lock(&self.lock)
|
||||||
executingSignal = self.executingSignal
|
executingSignal = self.executingSignal
|
||||||
self.terminated = true
|
self.terminated = true
|
||||||
currentValue = self.value
|
currentValue = self.value
|
||||||
OSSpinLockUnlock(&self.lock)
|
os_unfair_lock_unlock(&self.lock)
|
||||||
|
|
||||||
if !executingSignal {
|
if !executingSignal {
|
||||||
self.subscriber.putNext(currentValue)
|
self.subscriber.putNext(currentValue)
|
||||||
|
@ -140,7 +140,6 @@ public func copyToPasteboard(context: AccountContext, postbox: Postbox, mediaRef
|
|||||||
if case let .data(data) = state, data.complete {
|
if case let .data(data) = state, data.complete {
|
||||||
return Signal<Void, NoError> { subscriber in
|
return Signal<Void, NoError> { subscriber in
|
||||||
let pasteboard = UIPasteboard.general
|
let pasteboard = UIPasteboard.general
|
||||||
pasteboard.setPersistent(true)
|
|
||||||
|
|
||||||
if mediaReference.media is TelegramMediaImage {
|
if mediaReference.media is TelegramMediaImage {
|
||||||
if let fileData = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: .mappedIfSafe) {
|
if let fileData = try? Data(contentsOf: URL(fileURLWithPath: data.path), options: .mappedIfSafe) {
|
||||||
|
@ -185,7 +185,7 @@ private func quickReactionSetupControllerEntries(
|
|||||||
dateTimeFormat: presentationData.dateTimeFormat,
|
dateTimeFormat: presentationData.dateTimeFormat,
|
||||||
nameDisplayOrder: presentationData.nameDisplayOrder,
|
nameDisplayOrder: presentationData.nameDisplayOrder,
|
||||||
availableReactions: availableReactions,
|
availableReactions: availableReactions,
|
||||||
reaction: state.hasReaction ? reactionSettings.quickReaction : nil
|
reaction: state.hasReaction ? reactionSettings.effectiveQuickReaction(hasPremium: isPremium) : nil
|
||||||
))
|
))
|
||||||
entries.append(.demoDescription(presentationData.strings.Settings_QuickReactionSetup_DemoInfo))
|
entries.append(.demoDescription(presentationData.strings.Settings_QuickReactionSetup_DemoInfo))
|
||||||
|
|
||||||
@ -354,6 +354,7 @@ public func quickReactionSetupController(
|
|||||||
chatPeerId: context.account.peerId,
|
chatPeerId: context.account.peerId,
|
||||||
selectedItems: selectedItems
|
selectedItems: selectedItems
|
||||||
),
|
),
|
||||||
|
currentSelection: nil,
|
||||||
destinationItemView: { [weak sourceItemNode] in
|
destinationItemView: { [weak sourceItemNode] in
|
||||||
return sourceItemNode?.iconView
|
return sourceItemNode?.iconView
|
||||||
}
|
}
|
||||||
|
@ -927,16 +927,22 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
case .general, .modal:
|
case .general, .modal:
|
||||||
featured.set(context.account.viewTracker.featuredStickerPacks())
|
featured.set(context.account.viewTracker.featuredStickerPacks())
|
||||||
archivedPromise.set(.single(archivedPacks) |> then(context.engine.stickers.archivedStickerPacks() |> map(Optional.init)))
|
archivedPromise.set(.single(archivedPacks) |> then(context.engine.stickers.archivedStickerPacks() |> map(Optional.init)))
|
||||||
quickReaction = context.account.postbox.preferencesView(keys: [PreferencesKeys.reactionSettings])
|
quickReaction = combineLatest(
|
||||||
|> map { preferencesView -> MessageReaction.Reaction? in
|
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
|
let reactionSettings: ReactionSettings
|
||||||
if let entry = preferencesView.values[PreferencesKeys.reactionSettings], let value = entry.get(ReactionSettings.self) {
|
if let entry = preferencesView.values[PreferencesKeys.reactionSettings], let value = entry.get(ReactionSettings.self) {
|
||||||
reactionSettings = value
|
reactionSettings = value
|
||||||
} else {
|
} else {
|
||||||
reactionSettings = .default
|
reactionSettings = .default
|
||||||
}
|
}
|
||||||
|
var hasPremium = false
|
||||||
return reactionSettings.quickReaction
|
if case let .user(user) = peer {
|
||||||
|
hasPremium = user.isPremium
|
||||||
|
}
|
||||||
|
return reactionSettings.effectiveQuickReaction(hasPremium: hasPremium)
|
||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
case .masks:
|
case .masks:
|
||||||
|
@ -94,6 +94,6 @@ typedef NS_ENUM(NSUInteger, STPBillingAddressFields) {
|
|||||||
|
|
||||||
- (BOOL)containsRequiredFields:(STPBillingAddressFields)requiredFields;
|
- (BOOL)containsRequiredFields:(STPBillingAddressFields)requiredFields;
|
||||||
|
|
||||||
+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields; FAUXPAS_IGNORED_ON_LINE(APIAvailability);
|
//+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields; FAUXPAS_IGNORED_ON_LINE(APIAvailability);
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -91,7 +91,7 @@
|
|||||||
countryCode:self.country]);
|
countryCode:self.country]);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields {
|
/*+ (PKAddressField)applePayAddressFieldsFromBillingAddressFields:(STPBillingAddressFields)billingAddressFields {
|
||||||
FAUXPAS_IGNORED_IN_METHOD(APIAvailability);
|
FAUXPAS_IGNORED_IN_METHOD(APIAvailability);
|
||||||
switch (billingAddressFields) {
|
switch (billingAddressFields) {
|
||||||
case STPBillingAddressFieldsNone:
|
case STPBillingAddressFieldsNone:
|
||||||
@ -100,7 +100,7 @@
|
|||||||
case STPBillingAddressFieldsFull:
|
case STPBillingAddressFieldsFull:
|
||||||
return PKAddressFieldPostalAddress;
|
return PKAddressFieldPostalAddress;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ public final class CallKitIntegration {
|
|||||||
let handle = INPersonHandle(value: "tg\(peerId.id._internalGetInt64Value())", type: .unknown)
|
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 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)
|
let interaction = INInteraction(intent: intent, response: nil)
|
||||||
interaction.direction = .outgoing
|
interaction.direction = .outgoing
|
||||||
|
@ -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) {
|
func updateReactionSettings(transaction: Transaction, _ f: (ReactionSettings) -> ReactionSettings) {
|
||||||
transaction.updatePreferencesEntry(key: PreferencesKeys.reactionSettings, { current in
|
transaction.updatePreferencesEntry(key: PreferencesKeys.reactionSettings, { current in
|
||||||
let previous = current?.get(ReactionSettings.self) ?? ReactionSettings.default
|
let previous = current?.get(ReactionSettings.self) ?? ReactionSettings.default
|
||||||
|
@ -193,12 +193,14 @@ public func donateSendMessageIntent(account: Account, sharedContext: SharedAccou
|
|||||||
nameComponents.givenName = displayTitle
|
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)
|
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)
|
let interaction = INInteraction(intent: intent, response: nil)
|
||||||
interaction.direction = .outgoing
|
interaction.direction = .outgoing
|
||||||
interaction.groupIdentifier = "sendMessage_\(peer.id.toInt64())"
|
interaction.groupIdentifier = "sendMessage_\(peer.id.toInt64())"
|
||||||
|
@ -210,6 +210,7 @@ public final class EmojiStatusSelectionComponent: Component {
|
|||||||
self.panelBackgroundView.update(size: self.panelBackgroundView.bounds.size, transition: transition.containedViewLayoutTransition)
|
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.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
|
return availableSize
|
||||||
@ -243,11 +244,17 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
private var validLayout: ContainerViewLayout?
|
private var validLayout: ContainerViewLayout?
|
||||||
|
|
||||||
|
private let currentSelection: Int64?
|
||||||
|
|
||||||
private var emojiContentDisposable: Disposable?
|
private var emojiContentDisposable: Disposable?
|
||||||
private var emojiContent: EmojiPagerContentComponent?
|
private var emojiContent: EmojiPagerContentComponent?
|
||||||
private var freezeUpdates: Bool = false
|
private var freezeUpdates: Bool = false
|
||||||
private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation?
|
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 previewItem: (groupId: AnyHashable, item: EmojiPagerContentComponent.Item)?
|
||||||
private var dismissedPreviewItem: (groupId: AnyHashable, item: EmojiPagerContentComponent.Item)?
|
private var dismissedPreviewItem: (groupId: AnyHashable, item: EmojiPagerContentComponent.Item)?
|
||||||
private var previewScreenView: ComponentView<Empty>?
|
private var previewScreenView: ComponentView<Empty>?
|
||||||
@ -263,9 +270,12 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
private var isAnimatingOut: Bool = false
|
private var isAnimatingOut: Bool = false
|
||||||
private var isDismissed: Bool = false
|
private var isDismissed: Bool = false
|
||||||
|
|
||||||
init(controller: EmojiStatusSelectionController, context: AccountContext, sourceView: UIView?, emojiContent: Signal<EmojiPagerContentComponent, NoError>) {
|
private var isReactionSearchActive: Bool = false
|
||||||
|
|
||||||
|
init(controller: EmojiStatusSelectionController, context: AccountContext, sourceView: UIView?, emojiContent: Signal<EmojiPagerContentComponent, NoError>, currentSelection: Int64?) {
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.currentSelection = currentSelection
|
||||||
|
|
||||||
if let sourceView = sourceView {
|
if let sourceView = sourceView {
|
||||||
self.globalSourceRect = sourceView.convert(sourceView.bounds, to: nil)
|
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.cloudLayer0)
|
||||||
self.layer.addSublayer(self.cloudLayer1)
|
self.layer.addSublayer(self.cloudLayer1)
|
||||||
|
|
||||||
self.emojiContentDisposable = (emojiContent
|
self.emojiContentDisposable = (combineLatest(queue: .mainQueue(),
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] emojiContent in
|
emojiContent,
|
||||||
|
self.emojiSearchResult.get()
|
||||||
|
)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] emojiContent, emojiSearchResult in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.controller?._ready.set(.single(true))
|
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 {
|
if strongSelf.emojiContent == nil || !strongSelf.freezeUpdates {
|
||||||
strongSelf.emojiContent = emojiContent
|
strongSelf.emojiContent = emojiContent
|
||||||
}
|
}
|
||||||
@ -363,7 +397,150 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
},
|
},
|
||||||
requestUpdate: { _ in
|
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<MediaId>()
|
||||||
|
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,
|
chatPeerId: nil,
|
||||||
peekBehavior: nil,
|
peekBehavior: nil,
|
||||||
@ -395,6 +572,7 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
self.emojiContentDisposable?.dispose()
|
self.emojiContentDisposable?.dispose()
|
||||||
self.availableReactionsDisposable?.dispose()
|
self.availableReactionsDisposable?.dispose()
|
||||||
self.genericReactionEffectDisposable?.dispose()
|
self.genericReactionEffectDisposable?.dispose()
|
||||||
|
self.emojiSearchDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func refreshLayout(transition: Transition) {
|
private func refreshLayout(transition: Transition) {
|
||||||
@ -661,8 +839,14 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
emojiContent: emojiContent,
|
emojiContent: emojiContent,
|
||||||
backgroundColor: listBackgroundColor,
|
backgroundColor: listBackgroundColor,
|
||||||
separatorColor: separatorColor,
|
separatorColor: separatorColor,
|
||||||
hideTopPanel: false,
|
hideTopPanel: self.isReactionSearchActive,
|
||||||
hideTopPanelUpdated: { _, _ in }
|
hideTopPanelUpdated: { [weak self] hideTopPanel, transition in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
strongSelf.isReactionSearchActive = hideTopPanel
|
||||||
|
strongSelf.refreshLayout(transition: transition)
|
||||||
|
}
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: componentWidth, height: min(308.0, layout.size.height))
|
containerSize: CGSize(width: componentWidth, height: min(308.0, layout.size.height))
|
||||||
@ -920,6 +1104,13 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
} else {
|
} else {
|
||||||
self.freezeUpdates = true
|
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 _ = item, let destinationView = controller.destinationItemView() {
|
||||||
if let snapshotView = destinationView.snapshotView(afterScreenUpdates: false) {
|
if let snapshotView = destinationView.snapshotView(afterScreenUpdates: false) {
|
||||||
snapshotView.frame = destinationView.frame
|
snapshotView.frame = destinationView.frame
|
||||||
@ -1026,6 +1217,7 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private weak var sourceView: UIView?
|
private weak var sourceView: UIView?
|
||||||
private let emojiContent: Signal<EmojiPagerContentComponent, NoError>
|
private let emojiContent: Signal<EmojiPagerContentComponent, NoError>
|
||||||
|
private let currentSelection: Int64?
|
||||||
private let mode: Mode
|
private let mode: Mode
|
||||||
private let destinationItemView: () -> UIView?
|
private let destinationItemView: () -> UIView?
|
||||||
|
|
||||||
@ -1034,11 +1226,16 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
return self._ready
|
return self._ready
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(context: AccountContext, mode: Mode, sourceView: UIView, emojiContent: Signal<EmojiPagerContentComponent, NoError>, destinationItemView: @escaping () -> UIView?) {
|
override public var overlayWantsToBeBelowKeyboard: Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(context: AccountContext, mode: Mode, sourceView: UIView, emojiContent: Signal<EmojiPagerContentComponent, NoError>, currentSelection: Int64?, destinationItemView: @escaping () -> UIView?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.sourceView = sourceView
|
self.sourceView = sourceView
|
||||||
self.emojiContent = emojiContent
|
self.emojiContent = emojiContent
|
||||||
|
self.currentSelection = currentSelection
|
||||||
self.destinationItemView = destinationItemView
|
self.destinationItemView = destinationItemView
|
||||||
|
|
||||||
super.init(navigationBarPresentationData: nil)
|
super.init(navigationBarPresentationData: nil)
|
||||||
@ -1068,7 +1265,7 @@ public final class EmojiStatusSelectionController: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public func loadDisplayNode() {
|
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()
|
super.displayNodeDidLoad()
|
||||||
}
|
}
|
||||||
|
@ -29,14 +29,12 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/VideoAnimationCache:VideoAnimationCache",
|
"//submodules/TelegramUI/Components/VideoAnimationCache:VideoAnimationCache",
|
||||||
"//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer",
|
"//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer",
|
||||||
"//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView",
|
"//submodules/TelegramUI/Components/EmojiTextAttachmentView:EmojiTextAttachmentView",
|
||||||
|
"//submodules/TelegramUI/Components/EmojiStatusComponent:EmojiStatusComponent",
|
||||||
"//submodules/SoftwareVideo:SoftwareVideo",
|
"//submodules/SoftwareVideo:SoftwareVideo",
|
||||||
"//submodules/ShimmerEffect:ShimmerEffect",
|
"//submodules/ShimmerEffect:ShimmerEffect",
|
||||||
"//submodules/PhotoResources:PhotoResources",
|
"//submodules/PhotoResources:PhotoResources",
|
||||||
"//submodules/StickerResources:StickerResources",
|
"//submodules/StickerResources:StickerResources",
|
||||||
"//submodules/AppBundle:AppBundle",
|
"//submodules/AppBundle:AppBundle",
|
||||||
#"//submodules/ContextUI:ContextUI",
|
|
||||||
#"//submodules/PremiumUI:PremiumUI",
|
|
||||||
#"//submodules/StickerPeekUI:StickerPeekUI",
|
|
||||||
"//submodules/UndoUI:UndoUI",
|
"//submodules/UndoUI:UndoUI",
|
||||||
"//submodules/Components/MultilineTextComponent:MultilineTextComponent",
|
"//submodules/Components/MultilineTextComponent:MultilineTextComponent",
|
||||||
"//submodules/Components/SolidRoundedButtonComponent:SolidRoundedButtonComponent",
|
"//submodules/Components/SolidRoundedButtonComponent:SolidRoundedButtonComponent",
|
||||||
|
@ -22,6 +22,7 @@ import UndoUI
|
|||||||
import AudioToolbox
|
import AudioToolbox
|
||||||
import SolidRoundedButtonComponent
|
import SolidRoundedButtonComponent
|
||||||
import EmojiTextAttachmentView
|
import EmojiTextAttachmentView
|
||||||
|
import EmojiStatusComponent
|
||||||
|
|
||||||
private let premiumBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white)
|
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)
|
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 {
|
private struct Params: Equatable {
|
||||||
var theme: PresentationTheme
|
var theme: PresentationTheme
|
||||||
var strings: PresentationStrings
|
var strings: PresentationStrings
|
||||||
|
var text: String
|
||||||
var useOpaqueTheme: Bool
|
var useOpaqueTheme: Bool
|
||||||
var isActive: Bool
|
var isActive: Bool
|
||||||
var size: CGSize
|
var size: CGSize
|
||||||
@ -1523,6 +1525,9 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
if lhs.strings !== rhs.strings {
|
if lhs.strings !== rhs.strings {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.text != rhs.text {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.useOpaqueTheme != rhs.useOpaqueTheme {
|
if lhs.useOpaqueTheme != rhs.useOpaqueTheme {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -1551,6 +1556,11 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
|
|
||||||
private let searchIconView: UIImageView
|
private let searchIconView: UIImageView
|
||||||
private let searchIconTintView: UIImageView
|
private let searchIconTintView: UIImageView
|
||||||
|
|
||||||
|
private let clearIconView: UIImageView
|
||||||
|
private let clearIconTintView: UIImageView
|
||||||
|
private let clearIconButton: HighlightTrackingButton
|
||||||
|
|
||||||
private let tintTextView: ComponentView<Empty>
|
private let tintTextView: ComponentView<Empty>
|
||||||
private let textView: ComponentView<Empty>
|
private let textView: ComponentView<Empty>
|
||||||
private let cancelButtonTintTitle: ComponentView<Empty>
|
private let cancelButtonTintTitle: ComponentView<Empty>
|
||||||
@ -1580,6 +1590,13 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
self.searchIconView = UIImageView()
|
self.searchIconView = UIImageView()
|
||||||
self.searchIconTintView = 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.tintTextView = ComponentView()
|
||||||
self.textView = ComponentView()
|
self.textView = ComponentView()
|
||||||
self.cancelButtonTintTitle = ComponentView()
|
self.cancelButtonTintTitle = ComponentView()
|
||||||
@ -1594,6 +1611,10 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
self.addSubview(self.searchIconView)
|
self.addSubview(self.searchIconView)
|
||||||
self.tintContainerView.addSubview(self.searchIconTintView)
|
self.tintContainerView.addSubview(self.searchIconTintView)
|
||||||
|
|
||||||
|
self.addSubview(self.clearIconView)
|
||||||
|
self.tintContainerView.addSubview(self.clearIconTintView)
|
||||||
|
self.addSubview(self.clearIconButton)
|
||||||
|
|
||||||
self.addSubview(self.cancelButton)
|
self.addSubview(self.cancelButton)
|
||||||
self.clipsToBounds = true
|
self.clipsToBounds = true
|
||||||
|
|
||||||
@ -1627,6 +1648,23 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), for: .touchUpInside)
|
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) {
|
required public init?(coder: NSCoder) {
|
||||||
@ -1641,7 +1679,7 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
|
|
||||||
let textField = EmojiSearchTextField(frame: textFieldFrame)
|
let textField = EmojiSearchTextField(frame: textFieldFrame)
|
||||||
self.textField = textField
|
self.textField = textField
|
||||||
self.addSubview(textField)
|
self.insertSubview(textField, belowSubview: self.clearIconView)
|
||||||
textField.delegate = self
|
textField.delegate = self
|
||||||
textField.addTarget(self, action: #selector(self.textFieldChanged(_:)), for: .editingChanged)
|
textField.addTarget(self, action: #selector(self.textFieldChanged(_:)), for: .editingChanged)
|
||||||
}
|
}
|
||||||
@ -1655,6 +1693,10 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
@objc private func cancelPressed() {
|
@objc private func cancelPressed() {
|
||||||
self.updateQuery("")
|
self.updateQuery("")
|
||||||
|
|
||||||
|
self.clearIconView.isHidden = true
|
||||||
|
self.clearIconTintView.isHidden = true
|
||||||
|
self.clearIconButton.isHidden = true
|
||||||
|
|
||||||
if let textField = self.textField {
|
if let textField = self.textField {
|
||||||
self.textField = nil
|
self.textField = nil
|
||||||
|
|
||||||
@ -1664,6 +1706,15 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
self.deactivated()
|
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) {
|
public func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1673,7 +1724,13 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
@objc private func textFieldChanged(_ textField: UITextField) {
|
@objc private func textFieldChanged(_ textField: UITextField) {
|
||||||
self.update(transition: .immediate)
|
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) {
|
private func update(transition: Transition) {
|
||||||
@ -1681,13 +1738,14 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.params = nil
|
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(
|
let params = Params(
|
||||||
theme: theme,
|
theme: theme,
|
||||||
strings: strings,
|
strings: strings,
|
||||||
|
text: text,
|
||||||
useOpaqueTheme: useOpaqueTheme,
|
useOpaqueTheme: useOpaqueTheme,
|
||||||
isActive: isActive,
|
isActive: isActive,
|
||||||
size: size
|
size: size
|
||||||
@ -1700,6 +1758,9 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
if self.params?.theme !== theme {
|
if self.params?.theme !== theme {
|
||||||
self.searchIconView.image = generateTintedImage(image: UIImage(bundleImageName: "Components/Search Bar/Loupe"), color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor)
|
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.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
|
self.params = params
|
||||||
@ -1721,11 +1782,10 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
self.backgroundLayer.cornerRadius = inputHeight * 0.5
|
self.backgroundLayer.cornerRadius = inputHeight * 0.5
|
||||||
self.tintBackgroundLayer.cornerRadius = inputHeight * 0.5
|
self.tintBackgroundLayer.cornerRadius = inputHeight * 0.5
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
let textSize = self.textView.update(
|
let textSize = self.textView.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(Text(
|
component: AnyComponent(Text(
|
||||||
text: "Search Reactions",
|
text: text,
|
||||||
font: Font.regular(17.0),
|
font: Font.regular(17.0),
|
||||||
color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor
|
color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor
|
||||||
)),
|
)),
|
||||||
@ -1735,7 +1795,7 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
let _ = self.tintTextView.update(
|
let _ = self.tintTextView.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(Text(
|
component: AnyComponent(Text(
|
||||||
text: "Search Reactions",
|
text: text,
|
||||||
font: Font.regular(17.0),
|
font: Font.regular(17.0),
|
||||||
color: .white
|
color: .white
|
||||||
)),
|
)),
|
||||||
@ -1785,6 +1845,13 @@ public final class EmojiSearchHeaderView: UIView, UITextFieldDelegate {
|
|||||||
transition.setFrame(view: self.searchIconTintView, frame: iconFrame)
|
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 let textComponentView = self.textView.view {
|
||||||
if textComponentView.superview == nil {
|
if textComponentView.superview == nil {
|
||||||
self.addSubview(textComponentView)
|
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<Empty>
|
||||||
|
let titleTintLabel: ComponentView<Empty>
|
||||||
|
let icon: ComponentView<Empty>
|
||||||
|
|
||||||
|
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 {
|
public protocol EmojiContentPeekBehavior: AnyObject {
|
||||||
func setGestureRecognizerEnabled(view: UIView, isEnabled: Bool, itemAtPoint: @escaping (CGPoint) -> (AnyHashable, EmojiPagerContentComponent.View.ItemLayer, TelegramMediaFile)?)
|
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
|
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 id: AnyHashable
|
||||||
public let context: AccountContext
|
public let context: AccountContext
|
||||||
public let avatarPeer: EnginePeer?
|
public let avatarPeer: EnginePeer?
|
||||||
@ -2159,7 +2339,8 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
public let itemLayoutType: ItemLayoutType
|
public let itemLayoutType: ItemLayoutType
|
||||||
public let itemContentUniqueId: AnyHashable?
|
public let itemContentUniqueId: AnyHashable?
|
||||||
public let warpContentsOnEdges: Bool
|
public let warpContentsOnEdges: Bool
|
||||||
public let displaySearch: Bool
|
public let displaySearchWithPlaceholder: String?
|
||||||
|
public let emptySearchResults: EmptySearchResults?
|
||||||
public let enableLongPress: Bool
|
public let enableLongPress: Bool
|
||||||
public let selectedItems: Set<MediaId>
|
public let selectedItems: Set<MediaId>
|
||||||
|
|
||||||
@ -2174,7 +2355,8 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
itemLayoutType: ItemLayoutType,
|
itemLayoutType: ItemLayoutType,
|
||||||
itemContentUniqueId: AnyHashable?,
|
itemContentUniqueId: AnyHashable?,
|
||||||
warpContentsOnEdges: Bool,
|
warpContentsOnEdges: Bool,
|
||||||
displaySearch: Bool,
|
displaySearchWithPlaceholder: String?,
|
||||||
|
emptySearchResults: EmptySearchResults?,
|
||||||
enableLongPress: Bool,
|
enableLongPress: Bool,
|
||||||
selectedItems: Set<MediaId>
|
selectedItems: Set<MediaId>
|
||||||
) {
|
) {
|
||||||
@ -2188,12 +2370,13 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
self.itemLayoutType = itemLayoutType
|
self.itemLayoutType = itemLayoutType
|
||||||
self.itemContentUniqueId = itemContentUniqueId
|
self.itemContentUniqueId = itemContentUniqueId
|
||||||
self.warpContentsOnEdges = warpContentsOnEdges
|
self.warpContentsOnEdges = warpContentsOnEdges
|
||||||
self.displaySearch = displaySearch
|
self.displaySearchWithPlaceholder = displaySearchWithPlaceholder
|
||||||
|
self.emptySearchResults = emptySearchResults
|
||||||
self.enableLongPress = enableLongPress
|
self.enableLongPress = enableLongPress
|
||||||
self.selectedItems = selectedItems
|
self.selectedItems = selectedItems
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withUpdatedItemGroups(itemGroups: [ItemGroup], itemContentUniqueId: AnyHashable?) -> EmojiPagerContentComponent {
|
public func withUpdatedItemGroups(itemGroups: [ItemGroup], itemContentUniqueId: AnyHashable?, emptySearchResults: EmptySearchResults?) -> EmojiPagerContentComponent {
|
||||||
return EmojiPagerContentComponent(
|
return EmojiPagerContentComponent(
|
||||||
id: self.id,
|
id: self.id,
|
||||||
context: self.context,
|
context: self.context,
|
||||||
@ -2205,7 +2388,8 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
itemLayoutType: self.itemLayoutType,
|
itemLayoutType: self.itemLayoutType,
|
||||||
itemContentUniqueId: itemContentUniqueId,
|
itemContentUniqueId: itemContentUniqueId,
|
||||||
warpContentsOnEdges: self.warpContentsOnEdges,
|
warpContentsOnEdges: self.warpContentsOnEdges,
|
||||||
displaySearch: self.displaySearch,
|
displaySearchWithPlaceholder: self.displaySearchWithPlaceholder,
|
||||||
|
emptySearchResults: emptySearchResults,
|
||||||
enableLongPress: self.enableLongPress,
|
enableLongPress: self.enableLongPress,
|
||||||
selectedItems: self.selectedItems
|
selectedItems: self.selectedItems
|
||||||
)
|
)
|
||||||
@ -2242,7 +2426,10 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
if lhs.warpContentsOnEdges != rhs.warpContentsOnEdges {
|
if lhs.warpContentsOnEdges != rhs.warpContentsOnEdges {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.displaySearch != rhs.displaySearch {
|
if lhs.displaySearchWithPlaceholder != rhs.displaySearchWithPlaceholder {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.emptySearchResults != rhs.emptySearchResults {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.enableLongPress != rhs.enableLongPress {
|
if lhs.enableLongPress != rhs.enableLongPress {
|
||||||
@ -3017,6 +3204,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
|
|
||||||
private let placeholdersContainerView: UIView
|
private let placeholdersContainerView: UIView
|
||||||
private var visibleSearchHeader: EmojiSearchHeaderView?
|
private var visibleSearchHeader: EmojiSearchHeaderView?
|
||||||
|
private var visibleEmptySearchResultsView: EmptySearchResultsView?
|
||||||
private var visibleItemPlaceholderViews: [ItemLayer.Key: ItemPlaceholderView] = [:]
|
private var visibleItemPlaceholderViews: [ItemLayer.Key: ItemPlaceholderView] = [:]
|
||||||
private var visibleItemSelectionLayers: [ItemLayer.Key: ItemSelectionLayer] = [:]
|
private var visibleItemSelectionLayers: [ItemLayer.Key: ItemSelectionLayer] = [:]
|
||||||
private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:]
|
private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:]
|
||||||
@ -3856,7 +4044,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
for (id, layer) in self.visibleItemLayers {
|
for (id, layer) in self.visibleItemLayers {
|
||||||
previousVisibleLayers[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY))
|
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 {
|
for (id, layer) in self.visibleItemSelectionLayers {
|
||||||
previousVisibleItemSelectionLayers[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY))
|
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 {
|
for (_, layer) in self.visibleItemLayers {
|
||||||
layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true)
|
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 {
|
for (id, layerAndFrame) in previousVisibleLayers {
|
||||||
if self.visibleItemLayers[id] != nil {
|
if self.visibleItemLayers[id] != nil {
|
||||||
continue
|
continue
|
||||||
@ -3990,6 +4182,19 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
layer?.removeFromSuperlayer()
|
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 {
|
for (_, view) in self.visibleItemPlaceholderViews {
|
||||||
view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true)
|
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
|
let layer = layerAndFrame.0
|
||||||
layer.frame = layerAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY)
|
layer.frame = layerAndFrame.1.offsetBy(dx: 0.0, dy: self.scrollView.bounds.minY)
|
||||||
self.scrollView.layer.addSublayer(layer)
|
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()
|
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)
|
itemLayer.transform = CATransform3DMakeScale(0.8, 0.8, 1.0)
|
||||||
} else {
|
} else {
|
||||||
@ -5455,10 +5663,10 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
longTapRecognizer.isEnabled = component.enableLongPress
|
longTapRecognizer.isEnabled = component.enableLongPress
|
||||||
}
|
}
|
||||||
if let tapRecognizer = self.tapRecognizer {
|
if let tapRecognizer = self.tapRecognizer {
|
||||||
tapRecognizer.isEnabled = component.enableLongPress
|
tapRecognizer.isEnabled = component.enableLongPress || component.inputInteractionHolder.inputInteraction?.peekBehavior != nil
|
||||||
}
|
}
|
||||||
if let contextGesture = self.contextGesture {
|
if let contextGesture = self.contextGesture {
|
||||||
contextGesture.isEnabled = !component.enableLongPress
|
contextGesture.isEnabled = !component.enableLongPress && component.inputInteractionHolder.inputInteraction?.peekBehavior == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let shimmerHostView = self.shimmerHostView {
|
if let shimmerHostView = self.shimmerHostView {
|
||||||
@ -5621,7 +5829,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
itemGroups: itemGroups,
|
itemGroups: itemGroups,
|
||||||
expandedGroupIds: self.expandedGroupIds,
|
expandedGroupIds: self.expandedGroupIds,
|
||||||
curveNearBounds: component.warpContentsOnEdges,
|
curveNearBounds: component.warpContentsOnEdges,
|
||||||
displaySearch: component.displaySearch,
|
displaySearch: component.displaySearchWithPlaceholder != nil,
|
||||||
isSearchActivated: self.isSearchActivated,
|
isSearchActivated: self.isSearchActivated,
|
||||||
customLayout: component.inputInteractionHolder.inputInteraction?.customLayout
|
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))
|
transition.setPosition(view: self.scrollView, position: CGPoint(x: 0.0, y: scrollOriginY))
|
||||||
let previousSize = self.scrollView.bounds.size
|
let previousSize = self.scrollView.bounds.size
|
||||||
var resetScrolling = false
|
var resetScrolling = false
|
||||||
if self.scrollView.bounds.isEmpty && component.displaySearch {
|
if self.scrollView.bounds.isEmpty && component.displaySearchWithPlaceholder != nil {
|
||||||
resetScrolling = true
|
resetScrolling = true
|
||||||
}
|
}
|
||||||
if previousComponent?.itemContentUniqueId != component.itemContentUniqueId {
|
if previousComponent?.itemContentUniqueId != component.itemContentUniqueId {
|
||||||
@ -5747,7 +5955,7 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resetScrolling {
|
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)
|
self.scrollView.bounds = CGRect(origin: CGPoint(x: 0.0, y: 50.0), size: scrollSize)
|
||||||
} else {
|
} else {
|
||||||
self.scrollView.bounds = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: scrollSize)
|
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
|
let visibleSearchHeader: EmojiSearchHeaderView
|
||||||
if let current = self.visibleSearchHeader {
|
if let current = self.visibleSearchHeader {
|
||||||
visibleSearchHeader = current
|
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))
|
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)
|
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] _ in
|
transition.setFrame(view: visibleSearchHeader, frame: searchHeaderFrame, completion: { [weak self] completed in
|
||||||
guard let strongSelf = self, let visibleSearchHeader = strongSelf.visibleSearchHeader else {
|
guard let strongSelf = self, completed, let visibleSearchHeader = strongSelf.visibleSearchHeader else {
|
||||||
return
|
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)
|
self.updateVisibleItems(transition: itemTransition, attemptSynchronousLoads: attemptSynchronousLoads, previousItemPositions: previousItemPositions, previousAbsoluteItemPositions: previousAbsoluteItemPositions, updatedItemPositions: updatedItemPositions, hintDisappearingGroupFrame: hintDisappearingGroupFrame)
|
||||||
|
|
||||||
return availableSize
|
return availableSize
|
||||||
@ -6085,6 +6324,10 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if let groupIndex = itemGroupIndexById[groupId] {
|
if let groupIndex = itemGroupIndexById[groupId] {
|
||||||
|
if itemGroups[groupIndex].items.count >= (5 + 8) * 8 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
itemGroups[groupIndex].items.append(resultItem)
|
itemGroups[groupIndex].items.append(resultItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6128,6 +6371,10 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if let groupIndex = itemGroupIndexById[groupId] {
|
if let groupIndex = itemGroupIndexById[groupId] {
|
||||||
|
if itemGroups[groupIndex].items.count >= (5 + 8) * 8 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
itemGroups[groupIndex].items.append(resultItem)
|
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(
|
return EmojiPagerContentComponent(
|
||||||
id: "emoji",
|
id: "emoji",
|
||||||
context: context,
|
context: context,
|
||||||
@ -6577,7 +6831,8 @@ public final class EmojiPagerContentComponent: Component {
|
|||||||
itemLayoutType: .compact,
|
itemLayoutType: .compact,
|
||||||
itemContentUniqueId: nil,
|
itemContentUniqueId: nil,
|
||||||
warpContentsOnEdges: isReactionSelection || isStatusSelection,
|
warpContentsOnEdges: isReactionSelection || isStatusSelection,
|
||||||
displaySearch: isReactionSelection,
|
displaySearchWithPlaceholder: displaySearchWithPlaceholder,
|
||||||
|
emptySearchResults: nil,
|
||||||
enableLongPress: (isReactionSelection && !isQuickReactionSelection) || isStatusSelection,
|
enableLongPress: (isReactionSelection && !isQuickReactionSelection) || isStatusSelection,
|
||||||
selectedItems: selectedItems
|
selectedItems: selectedItems
|
||||||
)
|
)
|
||||||
|
@ -479,7 +479,6 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
TempBox.initializeShared(basePath: rootPath, processType: "app", launchSpecificId: Int64.random(in: Int64.min ... Int64.max))
|
TempBox.initializeShared(basePath: rootPath, processType: "app", launchSpecificId: Int64.random(in: Int64.min ... Int64.max))
|
||||||
|
|
||||||
let legacyLogs: [String] = [
|
let legacyLogs: [String] = [
|
||||||
"logs",
|
|
||||||
"broadcast-logs",
|
"broadcast-logs",
|
||||||
"siri-logs",
|
"siri-logs",
|
||||||
"widget-logs",
|
"widget-logs",
|
||||||
@ -529,7 +528,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
}, canOpenUrl: { url in
|
}, canOpenUrl: { url in
|
||||||
return UIApplication.shared.canOpenURL(url)
|
return UIApplication.shared.canOpenURL(url)
|
||||||
}, openUrl: { url in
|
}, openUrl: { url in
|
||||||
UIApplication.shared.openURL(url)
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
@ -555,9 +554,9 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let parsedUrl = parsedUrl {
|
if let parsedUrl = parsedUrl {
|
||||||
UIApplication.shared.openURL(parsedUrl)
|
UIApplication.shared.open(parsedUrl, options: [:], completionHandler: nil)
|
||||||
} else if let escapedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let parsedUrl = URL(string: escapedUrl) {
|
} else if let escapedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let parsedUrl = URL(string: escapedUrl) {
|
||||||
UIApplication.shared.openURL(parsedUrl)
|
UIApplication.shared.open(parsedUrl, options: [:], completionHandler: nil)
|
||||||
}
|
}
|
||||||
}, openUniversalUrl: { url, completion in
|
}, openUniversalUrl: { url, completion in
|
||||||
if #available(iOS 10.0, *) {
|
if #available(iOS 10.0, *) {
|
||||||
@ -633,12 +632,12 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
return disposable
|
return disposable
|
||||||
}, openSettings: {
|
}, openSettings: {
|
||||||
if let url = URL(string: UIApplication.openSettingsURLString) {
|
if let url = URL(string: UIApplication.openSettingsURLString) {
|
||||||
UIApplication.shared.openURL(url)
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||||
}
|
}
|
||||||
}, openAppStorePage: {
|
}, openAppStorePage: {
|
||||||
let appStoreId = buildConfig.appStoreId
|
let appStoreId = buildConfig.appStoreId
|
||||||
if let url = URL(string: "itms-apps://itunes.apple.com/app/id\(appStoreId)") {
|
if let url = URL(string: "itms-apps://itunes.apple.com/app/id\(appStoreId)") {
|
||||||
UIApplication.shared.openURL(url)
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||||
}
|
}
|
||||||
}, openSubscriptions: {
|
}, openSubscriptions: {
|
||||||
if #available(iOS 15, *), let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
|
if #available(iOS 15, *), let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
|
||||||
@ -646,7 +645,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
try await AppStore.showManageSubscriptions(in: scene)
|
try await AppStore.showManageSubscriptions(in: scene)
|
||||||
}
|
}
|
||||||
} else if let url = URL(string: "https://apps.apple.com/account/subscriptions") {
|
} else if let url = URL(string: "https://apps.apple.com/account/subscriptions") {
|
||||||
UIApplication.shared.openURL(url)
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
||||||
}
|
}
|
||||||
}, registerForNotifications: { completion in
|
}, registerForNotifications: { completion in
|
||||||
let _ = (self.context.get()
|
let _ = (self.context.get()
|
||||||
@ -1434,11 +1433,11 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
|
/*func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
|
||||||
if (application.applicationState == .inactive) {
|
if (application.applicationState == .inactive) {
|
||||||
Logger.shared.log("App \(self.episodeId)", "tap local notification \(String(describing: notification.userInfo)), applicationState \(application.applicationState)")
|
Logger.shared.log("App \(self.episodeId)", "tap local notification \(String(describing: notification.userInfo)), applicationState \(application.applicationState)")
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
|
public func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, for type: PKPushType) {
|
||||||
if #available(iOS 9.0, *) {
|
if #available(iOS 9.0, *) {
|
||||||
@ -1697,7 +1696,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
let presentationData = authContext.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = authContext.sharedContext.currentPresentationData.with { $0 }
|
||||||
authContext.rootController.currentWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.Passport_NotLoggedInMessage, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Calls_NotNow, action: {
|
authContext.rootController.currentWindow?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.Passport_NotLoggedInMessage, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Calls_NotNow, action: {
|
||||||
if let callbackUrl = URL(string: secureIdCallbackUrl(with: secureIdData.callbackUrl, peerId: secureIdData.peerId, result: .cancel, parameters: [:])) {
|
if let callbackUrl = URL(string: secureIdCallbackUrl(with: secureIdData.callbackUrl, peerId: secureIdData.peerId, result: .cancel, parameters: [:])) {
|
||||||
UIApplication.shared.openURL(callbackUrl)
|
UIApplication.shared.open(callbackUrl, options: [:], completionHandler: nil)
|
||||||
}
|
}
|
||||||
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), on: .root, blockInteraction: false, completion: {})
|
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), on: .root, blockInteraction: false, completion: {})
|
||||||
} else if let confirmationCode = parseConfirmationCodeUrl(url) {
|
} else if let confirmationCode = parseConfirmationCodeUrl(url) {
|
||||||
@ -2153,14 +2152,9 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
|||||||
reply.identifier = "reply"
|
reply.identifier = "reply"
|
||||||
reply.title = replyString
|
reply.title = replyString
|
||||||
reply.isDestructive = false
|
reply.isDestructive = false
|
||||||
if #available(iOS 9.0, *) {
|
reply.isAuthenticationRequired = false
|
||||||
reply.isAuthenticationRequired = false
|
reply.behavior = .textInput
|
||||||
reply.behavior = .textInput
|
reply.activationMode = .background
|
||||||
reply.activationMode = .background
|
|
||||||
} else {
|
|
||||||
reply.isAuthenticationRequired = true
|
|
||||||
reply.activationMode = .foreground
|
|
||||||
}
|
|
||||||
|
|
||||||
let unknownMessageCategory = UIMutableUserNotificationCategory()
|
let unknownMessageCategory = UIMutableUserNotificationCategory()
|
||||||
unknownMessageCategory.identifier = "unknown"
|
unknownMessageCategory.identifier = "unknown"
|
||||||
|
@ -465,7 +465,7 @@ final class AuthorizedApplicationContext {
|
|||||||
declineImpl?()
|
declineImpl?()
|
||||||
}, openUrl: { url in
|
}, openUrl: { url in
|
||||||
if let parsedUrl = URL(string: url) {
|
if let parsedUrl = URL(string: url) {
|
||||||
UIApplication.shared.openURL(parsedUrl)
|
UIApplication.shared.open(parsedUrl, options: [:], completionHandler: nil)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -537,7 +537,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
itemLayoutType: .detailed,
|
itemLayoutType: .detailed,
|
||||||
itemContentUniqueId: nil,
|
itemContentUniqueId: nil,
|
||||||
warpContentsOnEdges: false,
|
warpContentsOnEdges: false,
|
||||||
displaySearch: false,
|
displaySearchWithPlaceholder: nil,
|
||||||
|
emptySearchResults: nil,
|
||||||
enableLongPress: false,
|
enableLongPress: false,
|
||||||
selectedItems: Set()
|
selectedItems: Set()
|
||||||
)
|
)
|
||||||
@ -1714,9 +1715,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
|
|||||||
|
|
||||||
private func processInputData(inputData: InputData) -> InputData {
|
private func processInputData(inputData: InputData) -> InputData {
|
||||||
return 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
|
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,
|
gifs: inputData.gifs,
|
||||||
availableGifSearchEmojies: inputData.availableGifSearchEmojies
|
availableGifSearchEmojies: inputData.availableGifSearchEmojies
|
||||||
|
@ -1004,15 +1004,22 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
let availableReactions = context.engine.stickers.availableReactions()
|
let availableReactions = context.engine.stickers.availableReactions()
|
||||||
|
|
||||||
let defaultReaction = context.account.postbox.preferencesView(keys: [PreferencesKeys.reactionSettings])
|
let defaultReaction = combineLatest(
|
||||||
|> map { preferencesView -> MessageReaction.Reaction? in
|
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
|
let reactionSettings: ReactionSettings
|
||||||
if let entry = preferencesView.values[PreferencesKeys.reactionSettings], let value = entry.get(ReactionSettings.self) {
|
if let entry = preferencesView.values[PreferencesKeys.reactionSettings], let value = entry.get(ReactionSettings.self) {
|
||||||
reactionSettings = value
|
reactionSettings = value
|
||||||
} else {
|
} else {
|
||||||
reactionSettings = .default
|
reactionSettings = .default
|
||||||
}
|
}
|
||||||
return reactionSettings.quickReaction
|
var hasPremium = false
|
||||||
|
if case let .user(user) = peer {
|
||||||
|
hasPremium = user.isPremium
|
||||||
|
}
|
||||||
|
return reactionSettings.effectiveQuickReaction(hasPremium: hasPremium)
|
||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|
|
||||||
|
@ -3113,10 +3113,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
|
|
||||||
strongSelf.emojiStatusSelectionController?.dismiss()
|
strongSelf.emojiStatusSelectionController?.dismiss()
|
||||||
var selectedItems = Set<MediaId>()
|
var selectedItems = Set<MediaId>()
|
||||||
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 peer = strongSelf.data?.peer {
|
||||||
if let user = peer as? TelegramUser, let emojiStatus = user.emojiStatus {
|
if let user = peer as? TelegramUser, let emojiStatus = user.emojiStatus {
|
||||||
selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: emojiStatus.fileId))
|
selectedItems.insert(MediaId(namespace: Namespaces.Media.CloudFile, id: emojiStatus.fileId))
|
||||||
|
currentSelectedFileId = emojiStatus.fileId
|
||||||
|
|
||||||
if let timestamp = emojiStatus.expirationDate {
|
if let timestamp = emojiStatus.expirationDate {
|
||||||
topStatusTitle = peerStatusExpirationString(statusTimestamp: timestamp, relativeTo: Int32(Date().timeIntervalSince1970), strings: strongSelf.presentationData.strings, dateTimeFormat: strongSelf.presentationData.dateTimeFormat)
|
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,
|
selectedItems: selectedItems,
|
||||||
topStatusTitle: topStatusTitle
|
topStatusTitle: topStatusTitle
|
||||||
),
|
),
|
||||||
|
currentSelection: currentSelectedFileId,
|
||||||
destinationItemView: { [weak sourceView] in
|
destinationItemView: { [weak sourceView] in
|
||||||
return sourceView
|
return sourceView
|
||||||
}
|
}
|
||||||
|
@ -464,16 +464,10 @@ public final class SharedNotificationManager {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
let notification = UILocalNotification()
|
let notification = UILocalNotification()
|
||||||
if #available(iOS 8.2, *) {
|
|
||||||
notification.alertTitle = title
|
notification.alertTitle = title
|
||||||
notification.alertBody = body
|
notification.alertBody = body
|
||||||
} else {
|
|
||||||
if let title = title {
|
|
||||||
notification.alertBody = "\(title): \(body)"
|
|
||||||
} else {
|
|
||||||
notification.alertBody = body
|
|
||||||
}
|
|
||||||
}
|
|
||||||
notification.category = "incomingCall"
|
notification.category = "incomingCall"
|
||||||
notification.userInfo = ["callId": String(describing: notificationCall.internalId)]
|
notification.userInfo = ["callId": String(describing: notificationCall.internalId)]
|
||||||
notification.soundName = "0.m4a"
|
notification.soundName = "0.m4a"
|
||||||
|
@ -259,7 +259,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
|
|||||||
func seek(_ timestamp: Double) {
|
func seek(_ timestamp: Double) {
|
||||||
assert(Queue.mainQueue().isCurrent())
|
assert(Queue.mainQueue().isCurrent())
|
||||||
self.seekId += 1
|
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) {
|
func playOnceWithSound(playAndRecord: Bool, seek: MediaPlayerSeek, actionAtEnd: MediaPlayerPlayOnceWithSoundActionAtEnd) {
|
||||||
|
@ -102,8 +102,6 @@ final class WebEmbedPlayerNode: ASDisplayNode, WKNavigationDelegate {
|
|||||||
|
|
||||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||||
configuration.mediaTypesRequiringUserActionForPlayback = []
|
configuration.mediaTypesRequiringUserActionForPlayback = []
|
||||||
} else if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
|
|
||||||
configuration.requiresUserActionForMediaPlayback = false
|
|
||||||
} else {
|
} else {
|
||||||
configuration.mediaPlaybackRequiresUserAction = false
|
configuration.mediaPlaybackRequiresUserAction = false
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#import <MtProtoKit/MtProtoKit.h>
|
#import <MtProtoKit/MtProtoKit.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#import <libkern/OSAtomic.h>
|
||||||
|
|
||||||
static void TGCallAesIgeEncrypt(uint8_t *inBytes, uint8_t *outBytes, size_t length, uint8_t *key, uint8_t *iv) {
|
static void TGCallAesIgeEncrypt(uint8_t *inBytes, uint8_t *outBytes, size_t length, uint8_t *key, uint8_t *iv) {
|
||||||
MTAesEncryptRaw(inBytes, outBytes, length, key, iv);
|
MTAesEncryptRaw(inBytes, outBytes, length, key, iv);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#import <LegacyComponents/LegacyComponents.h>
|
#import <LegacyComponents/LegacyComponents.h>
|
||||||
#import <WatchConnectivity/WatchConnectivity.h>
|
#import <WatchConnectivity/WatchConnectivity.h>
|
||||||
#import <libkern/OSAtomic.h>
|
#import <os/lock.h>
|
||||||
#import <WatchCommon/WatchCommon.h>
|
#import <WatchCommon/WatchCommon.h>
|
||||||
|
|
||||||
@interface TGBridgeSignalManager : NSObject
|
@interface TGBridgeSignalManager : NSObject
|
||||||
@ -31,16 +31,16 @@
|
|||||||
|
|
||||||
TGBridgeSignalManager *_signalManager;
|
TGBridgeSignalManager *_signalManager;
|
||||||
|
|
||||||
OSSpinLock _incomingQueueLock;
|
os_unfair_lock _incomingQueueLock;
|
||||||
NSMutableArray *_incomingMessageQueue;
|
NSMutableArray *_incomingMessageQueue;
|
||||||
|
|
||||||
bool _requestSubscriptionList;
|
bool _requestSubscriptionList;
|
||||||
NSArray *_initialSubscriptionList;
|
NSArray *_initialSubscriptionList;
|
||||||
|
|
||||||
OSSpinLock _outgoingQueueLock;
|
os_unfair_lock _outgoingQueueLock;
|
||||||
NSMutableArray *_outgoingMessageQueue;
|
NSMutableArray *_outgoingMessageQueue;
|
||||||
|
|
||||||
OSSpinLock _replyHandlerMapLock;
|
os_unfair_lock _replyHandlerMapLock;
|
||||||
NSMutableDictionary *_replyHandlerMap;
|
NSMutableDictionary *_replyHandlerMap;
|
||||||
|
|
||||||
SPipe *_appInstalled;
|
SPipe *_appInstalled;
|
||||||
@ -102,14 +102,14 @@
|
|||||||
if (self.isRunning)
|
if (self.isRunning)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OSSpinLockLock(&_incomingQueueLock);
|
os_unfair_lock_lock(&_incomingQueueLock);
|
||||||
_isRunning = true;
|
_isRunning = true;
|
||||||
|
|
||||||
for (id message in _incomingMessageQueue)
|
for (id message in _incomingMessageQueue)
|
||||||
[self handleMessage:message replyHandler:nil finishTask:nil completion:nil];
|
[self handleMessage:message replyHandler:nil finishTask:nil completion:nil];
|
||||||
|
|
||||||
[_incomingMessageQueue removeAllObjects];
|
[_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(), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
[self dispatch:^{
|
[self dispatch:^{
|
||||||
@ -189,7 +189,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
id message = [NSKeyedUnarchiver unarchiveObjectWithData:messageData];
|
id message = [NSKeyedUnarchiver unarchiveObjectWithData:messageData];
|
||||||
OSSpinLockLock(&_incomingQueueLock);
|
os_unfair_lock_lock(&_incomingQueueLock);
|
||||||
if (!self.isRunning)
|
if (!self.isRunning)
|
||||||
{
|
{
|
||||||
[_incomingMessageQueue addObject:message];
|
[_incomingMessageQueue addObject:message];
|
||||||
@ -199,10 +199,10 @@
|
|||||||
|
|
||||||
finishTask(4.0);
|
finishTask(4.0);
|
||||||
|
|
||||||
OSSpinLockUnlock(&_incomingQueueLock);
|
os_unfair_lock_unlock(&_incomingQueueLock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_incomingQueueLock);
|
os_unfair_lock_unlock(&_incomingQueueLock);
|
||||||
|
|
||||||
[self handleMessage:message replyHandler:replyHandler finishTask:finishTask completion:completion];
|
[self handleMessage:message replyHandler:replyHandler finishTask:finishTask completion:completion];
|
||||||
}
|
}
|
||||||
@ -261,9 +261,9 @@
|
|||||||
//TGLog(@"[BridgeServer] Halt all active subscriptions");
|
//TGLog(@"[BridgeServer] Halt all active subscriptions");
|
||||||
[_signalManager haltAllSignals];
|
[_signalManager haltAllSignals];
|
||||||
|
|
||||||
OSSpinLockLock(&_outgoingQueueLock);
|
os_unfair_lock_lock(&_outgoingQueueLock);
|
||||||
[_outgoingMessageQueue removeAllObjects];
|
[_outgoingMessageQueue removeAllObjects];
|
||||||
OSSpinLockUnlock(&_outgoingQueueLock);
|
os_unfair_lock_unlock(&_outgoingQueueLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
_sessionId = ping.sessionId;
|
_sessionId = ping.sessionId;
|
||||||
@ -307,9 +307,9 @@
|
|||||||
SSignal *subscriptionHandler = _handler(subscription);
|
SSignal *subscriptionHandler = _handler(subscription);
|
||||||
if (replyHandler != nil)
|
if (replyHandler != nil)
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_replyHandlerMapLock);
|
os_unfair_lock_lock(&_replyHandlerMapLock);
|
||||||
_replyHandlerMap[@(subscription.identifier)] = replyHandler;
|
_replyHandlerMap[@(subscription.identifier)] = replyHandler;
|
||||||
OSSpinLockUnlock(&_replyHandlerMapLock);
|
os_unfair_lock_unlock(&_replyHandlerMapLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subscriptionHandler != nil)
|
if (subscriptionHandler != nil)
|
||||||
@ -318,11 +318,11 @@
|
|||||||
{
|
{
|
||||||
STimer *timer = [[STimer alloc] initWithTimeout:2.0 repeat:false completion:^
|
STimer *timer = [[STimer alloc] initWithTimeout:2.0 repeat:false completion:^
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_replyHandlerMapLock);
|
os_unfair_lock_lock(&_replyHandlerMapLock);
|
||||||
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];
|
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];
|
||||||
if (reply == nil)
|
if (reply == nil)
|
||||||
{
|
{
|
||||||
OSSpinLockUnlock(&_replyHandlerMapLock);
|
os_unfair_lock_unlock(&_replyHandlerMapLock);
|
||||||
|
|
||||||
if (finishTask != nil)
|
if (finishTask != nil)
|
||||||
finishTask(2.0);
|
finishTask(2.0);
|
||||||
@ -331,7 +331,7 @@
|
|||||||
|
|
||||||
reply([NSData data]);
|
reply([NSData data]);
|
||||||
[_replyHandlerMap removeObjectForKey:@(subscription.identifier)];
|
[_replyHandlerMap removeObjectForKey:@(subscription.identifier)];
|
||||||
OSSpinLockUnlock(&_replyHandlerMapLock);
|
os_unfair_lock_unlock(&_replyHandlerMapLock);
|
||||||
|
|
||||||
if (finishTask != nil)
|
if (finishTask != nil)
|
||||||
finishTask(4.0);
|
finishTask(4.0);
|
||||||
@ -369,11 +369,11 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_replyHandlerMapLock);
|
os_unfair_lock_lock(&_replyHandlerMapLock);
|
||||||
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];
|
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];
|
||||||
if (reply == nil)
|
if (reply == nil)
|
||||||
{
|
{
|
||||||
OSSpinLockUnlock(&_replyHandlerMapLock);
|
os_unfair_lock_unlock(&_replyHandlerMapLock);
|
||||||
|
|
||||||
if (finishTask != nil)
|
if (finishTask != nil)
|
||||||
finishTask(2.0);
|
finishTask(2.0);
|
||||||
@ -382,7 +382,7 @@
|
|||||||
|
|
||||||
reply([NSData data]);
|
reply([NSData data]);
|
||||||
[_replyHandlerMap removeObjectForKey:@(subscription.identifier)];
|
[_replyHandlerMap removeObjectForKey:@(subscription.identifier)];
|
||||||
OSSpinLockUnlock(&_replyHandlerMapLock);
|
os_unfair_lock_unlock(&_replyHandlerMapLock);
|
||||||
|
|
||||||
if (finishTask != nil)
|
if (finishTask != nil)
|
||||||
finishTask(2.0);
|
finishTask(2.0);
|
||||||
@ -410,11 +410,11 @@
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
OSSpinLockLock(&_replyHandlerMapLock);
|
os_unfair_lock_lock(&_replyHandlerMapLock);
|
||||||
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];
|
void (^reply)(NSData *) = _replyHandlerMap[@(subscription.identifier)];
|
||||||
if (reply != nil)
|
if (reply != nil)
|
||||||
[_replyHandlerMap removeObjectForKey:@(subscription.identifier)];
|
[_replyHandlerMap removeObjectForKey:@(subscription.identifier)];
|
||||||
OSSpinLockUnlock(&_replyHandlerMapLock);
|
os_unfair_lock_unlock(&_replyHandlerMapLock);
|
||||||
|
|
||||||
if (_processingNotification)
|
if (_processingNotification)
|
||||||
{
|
{
|
||||||
@ -460,7 +460,7 @@
|
|||||||
|
|
||||||
- (void)_enqueueResponse:(TGBridgeResponse *)response forSubscription:(TGBridgeSubscription *)subscription
|
- (void)_enqueueResponse:(TGBridgeResponse *)response forSubscription:(TGBridgeSubscription *)subscription
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_outgoingQueueLock);
|
os_unfair_lock_lock(&_outgoingQueueLock);
|
||||||
NSMutableArray *updatedResponses = (_outgoingMessageQueue != nil) ? [_outgoingMessageQueue mutableCopy] : [[NSMutableArray alloc] init];
|
NSMutableArray *updatedResponses = (_outgoingMessageQueue != nil) ? [_outgoingMessageQueue mutableCopy] : [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
if (subscription.dropPreviouslyQueued)
|
if (subscription.dropPreviouslyQueued)
|
||||||
@ -479,7 +479,7 @@
|
|||||||
[updatedResponses addObject:response];
|
[updatedResponses addObject:response];
|
||||||
|
|
||||||
_outgoingMessageQueue = updatedResponses;
|
_outgoingMessageQueue = updatedResponses;
|
||||||
OSSpinLockUnlock(&_outgoingQueueLock);
|
os_unfair_lock_unlock(&_outgoingQueueLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_sendQueuedResponses
|
- (void)_sendQueuedResponses
|
||||||
@ -487,7 +487,7 @@
|
|||||||
if (_processingNotification)
|
if (_processingNotification)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OSSpinLockLock(&_outgoingQueueLock);
|
os_unfair_lock_lock(&_outgoingQueueLock);
|
||||||
|
|
||||||
if (_outgoingMessageQueue.count > 0)
|
if (_outgoingMessageQueue.count > 0)
|
||||||
{
|
{
|
||||||
@ -501,7 +501,7 @@
|
|||||||
|
|
||||||
[_outgoingMessageQueue removeAllObjects];
|
[_outgoingMessageQueue removeAllObjects];
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_outgoingQueueLock);
|
os_unfair_lock_unlock(&_outgoingQueueLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_requestSubscriptionList
|
- (void)_requestSubscriptionList
|
||||||
@ -669,7 +669,7 @@
|
|||||||
|
|
||||||
@interface TGBridgeSignalManager()
|
@interface TGBridgeSignalManager()
|
||||||
{
|
{
|
||||||
OSSpinLock _lock;
|
os_unfair_lock _lock;
|
||||||
NSMutableDictionary *_disposables;
|
NSMutableDictionary *_disposables;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
@ -689,9 +689,9 @@
|
|||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
NSArray *disposables = nil;
|
NSArray *disposables = nil;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
disposables = [_disposables allValues];
|
disposables = [_disposables allValues];
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
for (id<SDisposable> disposable in disposables)
|
for (id<SDisposable> disposable in disposables)
|
||||||
{
|
{
|
||||||
@ -705,13 +705,13 @@
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool produce = false;
|
bool produce = false;
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_disposables[key] == nil)
|
if (_disposables[key] == nil)
|
||||||
{
|
{
|
||||||
_disposables[key] = [[SMetaDisposable alloc] init];
|
_disposables[key] = [[SMetaDisposable alloc] init];
|
||||||
produce = true;
|
produce = true;
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
|
|
||||||
if (produce)
|
if (produce)
|
||||||
{
|
{
|
||||||
@ -721,24 +721,24 @@
|
|||||||
__strong TGBridgeSignalManager *strongSelf = weakSelf;
|
__strong TGBridgeSignalManager *strongSelf = weakSelf;
|
||||||
if (strongSelf != nil)
|
if (strongSelf != nil)
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&strongSelf->_lock);
|
os_unfair_lock_lock(&strongSelf->_lock);
|
||||||
[strongSelf->_disposables removeObjectForKey:key];
|
[strongSelf->_disposables removeObjectForKey:key];
|
||||||
OSSpinLockUnlock(&strongSelf->_lock);
|
os_unfair_lock_unlock(&strongSelf->_lock);
|
||||||
}
|
}
|
||||||
} completed:^
|
} completed:^
|
||||||
{
|
{
|
||||||
__strong TGBridgeSignalManager *strongSelf = weakSelf;
|
__strong TGBridgeSignalManager *strongSelf = weakSelf;
|
||||||
if (strongSelf != nil)
|
if (strongSelf != nil)
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&strongSelf->_lock);
|
os_unfair_lock_lock(&strongSelf->_lock);
|
||||||
[strongSelf->_disposables removeObjectForKey:key];
|
[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];
|
[(SMetaDisposable *)_disposables[key] setDisposable:disposable];
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return produce;
|
return produce;
|
||||||
@ -749,22 +749,22 @@
|
|||||||
if (key == nil)
|
if (key == nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
if (_disposables[key] != nil)
|
if (_disposables[key] != nil)
|
||||||
{
|
{
|
||||||
[_disposables[key] dispose];
|
[_disposables[key] dispose];
|
||||||
[_disposables removeObjectForKey:key];
|
[_disposables removeObjectForKey:key];
|
||||||
}
|
}
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)haltAllSignals
|
- (void)haltAllSignals
|
||||||
{
|
{
|
||||||
OSSpinLockLock(&_lock);
|
os_unfair_lock_lock(&_lock);
|
||||||
for (NSObject <SDisposable> *disposable in _disposables.allValues)
|
for (NSObject <SDisposable> *disposable in _disposables.allValues)
|
||||||
[disposable dispose];
|
[disposable dispose];
|
||||||
[_disposables removeAllObjects];
|
[_disposables removeAllObjects];
|
||||||
OSSpinLockUnlock(&_lock);
|
os_unfair_lock_unlock(&_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -68,8 +68,6 @@ final class WebAppWebView: WKWebView {
|
|||||||
configuration.allowsPictureInPictureMediaPlayback = false
|
configuration.allowsPictureInPictureMediaPlayback = false
|
||||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||||
configuration.mediaTypesRequiringUserActionForPlayback = .all
|
configuration.mediaTypesRequiringUserActionForPlayback = .all
|
||||||
} else if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
|
|
||||||
configuration.requiresUserActionForMediaPlayback = true
|
|
||||||
} else {
|
} else {
|
||||||
configuration.mediaPlaybackRequiresUserAction = true
|
configuration.mediaPlaybackRequiresUserAction = true
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "9.0",
|
"app": "9.0.1",
|
||||||
"bazel": "5.1.0",
|
"bazel": "5.3.0",
|
||||||
"xcode": "14.0"
|
"xcode": "14.0"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user