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
9d5604d81d
5
Makefile
5
Makefile
@ -60,8 +60,11 @@ BAZEL_DEBUG_FLAGS=\
|
|||||||
--swiftcopt=-j${CORE_COUNT_MINUS_ONE} \
|
--swiftcopt=-j${CORE_COUNT_MINUS_ONE} \
|
||||||
|
|
||||||
BAZEL_OPT_FLAGS=\
|
BAZEL_OPT_FLAGS=\
|
||||||
--swiftcopt=-whole-module-optimization \
|
--features=swift.opt_uses_wmo \
|
||||||
|
--features=swift.opt_uses_osize \
|
||||||
--swiftcopt='-num-threads' --swiftcopt='16' \
|
--swiftcopt='-num-threads' --swiftcopt='16' \
|
||||||
|
--objc_enable_binary_stripping \
|
||||||
|
-s \
|
||||||
|
|
||||||
|
|
||||||
build_arm64: check_env
|
build_arm64: check_env
|
||||||
|
386
Telegram/BUILD
386
Telegram/BUILD
@ -69,6 +69,11 @@ debug_deps = select({
|
|||||||
"//conditions:default": [],
|
"//conditions:default": [],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
strip_framework = select({
|
||||||
|
":debug": None,
|
||||||
|
"//conditions:default": ":StripFramework",
|
||||||
|
})
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "AppResources",
|
name = "AppResources",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
@ -507,6 +512,368 @@ swift_library(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "MtProtoKitInfoPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>{telegram_bundle_id}.MtProtoKit</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{telegram_build_number}</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>MtProtoKit</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{telegram_version}</string>
|
||||||
|
""".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
telegram_version = telegram_version,
|
||||||
|
telegram_build_number = telegram_build_number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_framework(
|
||||||
|
name = "MtProtoKitFramework",
|
||||||
|
bundle_id = "{telegram_bundle_id}.MtProtoKit".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
),
|
||||||
|
families = [
|
||||||
|
"iphone",
|
||||||
|
"ipad",
|
||||||
|
],
|
||||||
|
infoplists = [
|
||||||
|
":MtProtoKitInfoPlist",
|
||||||
|
],
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
|
deps = [
|
||||||
|
"//submodules/MtProtoKit:MtProtoKit",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "SwiftSignalKitInfoPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>{telegram_bundle_id}.SwiftSignalKit</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{telegram_build_number}</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>SwiftSignalKit</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{telegram_version}</string>
|
||||||
|
""".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
telegram_version = telegram_version,
|
||||||
|
telegram_build_number = telegram_build_number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_framework(
|
||||||
|
name = "SwiftSignalKitFramework",
|
||||||
|
bundle_id = "{telegram_bundle_id}.SwiftSignalKit".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
),
|
||||||
|
families = [
|
||||||
|
"iphone",
|
||||||
|
"ipad",
|
||||||
|
],
|
||||||
|
infoplists = [
|
||||||
|
":SwiftSignalKitInfoPlist",
|
||||||
|
],
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
|
deps = [
|
||||||
|
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "PostboxInfoPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>{telegram_bundle_id}.Postbox</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{telegram_build_number}</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Postbox</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{telegram_version}</string>
|
||||||
|
""".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
telegram_version = telegram_version,
|
||||||
|
telegram_build_number = telegram_build_number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_framework(
|
||||||
|
name = "PostboxFramework",
|
||||||
|
bundle_id = "{telegram_bundle_id}.Postbox".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
),
|
||||||
|
families = [
|
||||||
|
"iphone",
|
||||||
|
"ipad",
|
||||||
|
],
|
||||||
|
infoplists = [
|
||||||
|
":PostboxInfoPlist",
|
||||||
|
],
|
||||||
|
frameworks = [
|
||||||
|
":SwiftSignalKitFramework",
|
||||||
|
],
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
|
deps = [
|
||||||
|
"//submodules/Postbox:Postbox",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "TelegramApiInfoPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>{telegram_bundle_id}.TelegramApi</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{telegram_build_number}</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>TelegramApi</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{telegram_version}</string>
|
||||||
|
""".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
telegram_version = telegram_version,
|
||||||
|
telegram_build_number = telegram_build_number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_framework(
|
||||||
|
name = "TelegramApiFramework",
|
||||||
|
bundle_id = "{telegram_bundle_id}.TelegramApi".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
),
|
||||||
|
families = [
|
||||||
|
"iphone",
|
||||||
|
"ipad",
|
||||||
|
],
|
||||||
|
infoplists = [
|
||||||
|
":TelegramApiInfoPlist",
|
||||||
|
],
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
|
deps = [
|
||||||
|
"//submodules/TelegramApi:TelegramApi",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "SyncCoreInfoPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>{telegram_bundle_id}.SyncCore</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{telegram_build_number}</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>SyncCore</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{telegram_version}</string>
|
||||||
|
""".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
telegram_version = telegram_version,
|
||||||
|
telegram_build_number = telegram_build_number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_framework(
|
||||||
|
name = "SyncCoreFramework",
|
||||||
|
bundle_id = "{telegram_bundle_id}.SyncCore".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
),
|
||||||
|
families = [
|
||||||
|
"iphone",
|
||||||
|
"ipad",
|
||||||
|
],
|
||||||
|
infoplists = [
|
||||||
|
":SyncCoreInfoPlist",
|
||||||
|
],
|
||||||
|
frameworks = [
|
||||||
|
":SwiftSignalKitFramework",
|
||||||
|
":PostboxFramework",
|
||||||
|
],
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
|
deps = [
|
||||||
|
"//submodules/SyncCore:SyncCore",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "TelegramCoreInfoPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>{telegram_bundle_id}.TelegramCore</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{telegram_build_number}</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>TelegramCore</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{telegram_version}</string>
|
||||||
|
""".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
telegram_version = telegram_version,
|
||||||
|
telegram_build_number = telegram_build_number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_framework(
|
||||||
|
name = "TelegramCoreFramework",
|
||||||
|
bundle_id = "{telegram_bundle_id}.TelegramCore".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
),
|
||||||
|
families = [
|
||||||
|
"iphone",
|
||||||
|
"ipad",
|
||||||
|
],
|
||||||
|
infoplists = [
|
||||||
|
":TelegramCoreInfoPlist",
|
||||||
|
],
|
||||||
|
frameworks = [
|
||||||
|
":MtProtoKitFramework",
|
||||||
|
":SwiftSignalKitFramework",
|
||||||
|
":PostboxFramework",
|
||||||
|
":SyncCoreFramework",
|
||||||
|
":TelegramApiFramework",
|
||||||
|
],
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
|
deps = [
|
||||||
|
"//submodules/TelegramCore:TelegramCore",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "AsyncDisplayKitInfoPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>{telegram_bundle_id}.AsyncDisplayKit</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{telegram_build_number}</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>AsyncDisplayKit</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{telegram_version}</string>
|
||||||
|
""".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
telegram_version = telegram_version,
|
||||||
|
telegram_build_number = telegram_build_number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_framework(
|
||||||
|
name = "AsyncDisplayKitFramework",
|
||||||
|
bundle_id = "{telegram_bundle_id}.AsyncDisplayKit".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
),
|
||||||
|
families = [
|
||||||
|
"iphone",
|
||||||
|
"ipad",
|
||||||
|
],
|
||||||
|
infoplists = [
|
||||||
|
":AsyncDisplayKitInfoPlist",
|
||||||
|
],
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
|
deps = [
|
||||||
|
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
plist_fragment(
|
||||||
|
name = "DisplayInfoPlist",
|
||||||
|
extension = "plist",
|
||||||
|
template =
|
||||||
|
"""
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>{telegram_bundle_id}.Display</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>{telegram_build_number}</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Display</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>{telegram_version}</string>
|
||||||
|
""".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
telegram_version = telegram_version,
|
||||||
|
telegram_build_number = telegram_build_number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
genrule(
|
||||||
|
name = "StripFramework",
|
||||||
|
cmd_bash =
|
||||||
|
"""
|
||||||
|
echo 'for f in $$1/*.framework; do binary_name=`echo $$(basename $$f) | sed -e "s/\\\\.framework//"`; strip -ST $$f/$$binary_name; done;' > $(location StripFramework.sh)
|
||||||
|
echo '' >> $(location StripFramework.sh)
|
||||||
|
""",
|
||||||
|
outs = [
|
||||||
|
"StripFramework.sh",
|
||||||
|
],
|
||||||
|
executable = True,
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
ios_framework(
|
||||||
|
name = "DisplayFramework",
|
||||||
|
bundle_id = "{telegram_bundle_id}.Display".format(
|
||||||
|
telegram_bundle_id = telegram_bundle_id,
|
||||||
|
),
|
||||||
|
families = [
|
||||||
|
"iphone",
|
||||||
|
"ipad",
|
||||||
|
],
|
||||||
|
infoplists = [
|
||||||
|
":DisplayInfoPlist",
|
||||||
|
],
|
||||||
|
frameworks = [
|
||||||
|
":SwiftSignalKitFramework",
|
||||||
|
":AsyncDisplayKitFramework",
|
||||||
|
],
|
||||||
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
|
deps = [
|
||||||
|
"//submodules/Display:Display",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
plist_fragment(
|
plist_fragment(
|
||||||
name = "TelegramUIInfoPlist",
|
name = "TelegramUIInfoPlist",
|
||||||
extension = "plist",
|
extension = "plist",
|
||||||
@ -541,7 +908,18 @@ ios_framework(
|
|||||||
infoplists = [
|
infoplists = [
|
||||||
":TelegramUIInfoPlist",
|
":TelegramUIInfoPlist",
|
||||||
],
|
],
|
||||||
|
frameworks = [
|
||||||
|
":MtProtoKitFramework",
|
||||||
|
":SwiftSignalKitFramework",
|
||||||
|
":PostboxFramework",
|
||||||
|
":TelegramApiFramework",
|
||||||
|
":SyncCoreFramework",
|
||||||
|
":TelegramCoreFramework",
|
||||||
|
":AsyncDisplayKitFramework",
|
||||||
|
":DisplayFramework",
|
||||||
|
],
|
||||||
minimum_os_version = "9.0",
|
minimum_os_version = "9.0",
|
||||||
|
ipa_post_processor = strip_framework,
|
||||||
deps = [
|
deps = [
|
||||||
"//submodules/TelegramUI:TelegramUI",
|
"//submodules/TelegramUI:TelegramUI",
|
||||||
] + debug_deps,
|
] + debug_deps,
|
||||||
@ -858,6 +1236,14 @@ ios_application(
|
|||||||
":DefaultAppIcon",
|
":DefaultAppIcon",
|
||||||
],
|
],
|
||||||
frameworks = [
|
frameworks = [
|
||||||
|
":MtProtoKitFramework",
|
||||||
|
":SwiftSignalKitFramework",
|
||||||
|
":PostboxFramework",
|
||||||
|
":TelegramApiFramework",
|
||||||
|
":SyncCoreFramework",
|
||||||
|
":TelegramCoreFramework",
|
||||||
|
":AsyncDisplayKitFramework",
|
||||||
|
":DisplayFramework",
|
||||||
":TelegramUIFramework",
|
":TelegramUIFramework",
|
||||||
],
|
],
|
||||||
strings = [
|
strings = [
|
||||||
|
@ -4360,6 +4360,7 @@ Sorry for the inconvenience.";
|
|||||||
"Channel.DiscussionGroup.HeaderLabel" = "Discuss";
|
"Channel.DiscussionGroup.HeaderLabel" = "Discuss";
|
||||||
"Channel.DiscussionGroup.Create" = "Create New Group";
|
"Channel.DiscussionGroup.Create" = "Create New Group";
|
||||||
"Channel.DiscussionGroup.PrivateGroup" = "private group";
|
"Channel.DiscussionGroup.PrivateGroup" = "private group";
|
||||||
|
"Channel.DiscussionGroup.PrivateChannel" = "private channel";
|
||||||
"Channel.DiscussionGroup.Info" = "Everything you post in the channel will be forwarded to this group.";
|
"Channel.DiscussionGroup.Info" = "Everything you post in the channel will be forwarded to this group.";
|
||||||
"Channel.DiscussionGroup.LinkGroup" = "Link Group";
|
"Channel.DiscussionGroup.LinkGroup" = "Link Group";
|
||||||
"Channel.DiscussionGroup.UnlinkGroup" = "Unlink Group";
|
"Channel.DiscussionGroup.UnlinkGroup" = "Unlink Group";
|
||||||
@ -5822,6 +5823,10 @@ Any member of this group will be able to see messages in the channel.";
|
|||||||
"ChatList.MessageMusic_1" = "1 Music File";
|
"ChatList.MessageMusic_1" = "1 Music File";
|
||||||
"ChatList.MessageMusic_any" = "%@ Music Files";
|
"ChatList.MessageMusic_any" = "%@ Music Files";
|
||||||
|
|
||||||
|
"Conversation.PinOlderMessageAlertTitle" = "Pin Message";
|
||||||
|
"Conversation.PinOlderMessageAlertText" = "Do you want to pin an older message while leaving a more recent one pinned?";
|
||||||
|
"Conversation.PinMessageAlertPin" = "Pin";
|
||||||
|
|
||||||
"Conversation.ContextMenuSelect" = "Select";
|
"Conversation.ContextMenuSelect" = "Select";
|
||||||
|
|
||||||
"Conversation.ContextMenuSelectAll_0" = "Select All %@ Items";
|
"Conversation.ContextMenuSelectAll_0" = "Select All %@ Items";
|
||||||
|
@ -8,7 +8,7 @@ export BUCK_DEBUG_OPTIONS=\
|
|||||||
export BUCK_RELEASE_OPTIONS=\
|
export BUCK_RELEASE_OPTIONS=\
|
||||||
--config custom.other_cflags="-Os" \
|
--config custom.other_cflags="-Os" \
|
||||||
--config custom.other_cxxflags="-Os" \
|
--config custom.other_cxxflags="-Os" \
|
||||||
--config custom.optimization="-O" \
|
--config custom.optimization="-Osize" \
|
||||||
--config custom.config_swift_compiler_flags="-whole-module-optimization"
|
--config custom.config_swift_compiler_flags="-whole-module-optimization"
|
||||||
|
|
||||||
export BUCK_THREADS_OPTIONS=--config build.threads=$(shell sysctl -n hw.logicalcpu)
|
export BUCK_THREADS_OPTIONS=--config build.threads=$(shell sysctl -n hw.logicalcpu)
|
||||||
|
@ -16,6 +16,9 @@ objc_library(
|
|||||||
sdk_frameworks = [
|
sdk_frameworks = [
|
||||||
"Foundation",
|
"Foundation",
|
||||||
],
|
],
|
||||||
|
sdk_dylibs = [
|
||||||
|
"libz",
|
||||||
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
],
|
],
|
||||||
|
@ -14,6 +14,7 @@ swift_library(
|
|||||||
"//submodules/Markdown:Markdown",
|
"//submodules/Markdown:Markdown",
|
||||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||||
],
|
],
|
||||||
|
alwayslink = True,
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
],
|
],
|
||||||
|
@ -569,7 +569,7 @@ private func loadLegacyMessages(account: TemporaryAccount, basePath: String, acc
|
|||||||
parsedAttributes.append(AutoremoveTimeoutMessageAttribute(timeout: autoremoveTimeout, countdownBeginTime: countdownBeginTime))
|
parsedAttributes.append(AutoremoveTimeoutMessageAttribute(timeout: autoremoveTimeout, countdownBeginTime: countdownBeginTime))
|
||||||
}
|
}
|
||||||
|
|
||||||
let (parsedTags, parsedGlobalTags) = tagsForStoreMessage(incoming: parsedFlags.contains(.Incoming), attributes: parsedAttributes, media: parsedMedia, textEntities: nil)
|
let (parsedTags, parsedGlobalTags) = tagsForStoreMessage(incoming: parsedFlags.contains(.Incoming), attributes: parsedAttributes, media: parsedMedia, textEntities: nil, isPinned: false)
|
||||||
messages.append(StoreMessage(id: parsedId, globallyUniqueId: globallyUniqueId, groupingKey: parsedGroupingKey, threadId: nil, timestamp: timestamp, flags: parsedFlags, tags: parsedTags, globalTags: parsedGlobalTags, localTags: [], forwardInfo: nil, authorId: parsedAuthorId, text: text, attributes: parsedAttributes, media: parsedMedia))
|
messages.append(StoreMessage(id: parsedId, globallyUniqueId: globallyUniqueId, groupingKey: parsedGroupingKey, threadId: nil, timestamp: timestamp, flags: parsedFlags, tags: parsedTags, globalTags: parsedGlobalTags, localTags: [], forwardInfo: nil, authorId: parsedAuthorId, text: text, attributes: parsedAttributes, media: parsedMedia))
|
||||||
|
|
||||||
//Logger.shared.log("loadLegacyMessages", "message \(messageId) completed")
|
//Logger.shared.log("loadLegacyMessages", "message \(messageId) completed")
|
||||||
|
@ -20,6 +20,10 @@ objc_library(
|
|||||||
"Foundation",
|
"Foundation",
|
||||||
"Security",
|
"Security",
|
||||||
"SystemConfiguration",
|
"SystemConfiguration",
|
||||||
|
"CFNetwork",
|
||||||
|
],
|
||||||
|
sdk_dylibs = [
|
||||||
|
"libz",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -152,8 +152,10 @@ private enum ChannelDiscussionGroupSetupControllerEntry: ItemListNodeEntry {
|
|||||||
let text: String
|
let text: String
|
||||||
if let peer = peer as? TelegramChannel, let addressName = peer.addressName, !addressName.isEmpty {
|
if let peer = peer as? TelegramChannel, let addressName = peer.addressName, !addressName.isEmpty {
|
||||||
text = "@\(addressName)"
|
text = "@\(addressName)"
|
||||||
} else {
|
} else if let peer = peer as? TelegramChannel, case .group = peer.info {
|
||||||
text = strings.Channel_DiscussionGroup_PrivateGroup
|
text = strings.Channel_DiscussionGroup_PrivateGroup
|
||||||
|
} else {
|
||||||
|
text = strings.Channel_DiscussionGroup_PrivateChannel
|
||||||
}
|
}
|
||||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .monthFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: "."), nameDisplayOrder: nameOrder, context: arguments.context, peer: peer, aliasHandling: .standard, nameStyle: .plain, presence: nil, text: .text(text), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .monthFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: "."), nameDisplayOrder: nameOrder, context: arguments.context, peer: peer, aliasHandling: .standard, nameStyle: .plain, presence: nil, text: .text(text), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||||
arguments.selectGroup(peer.id)
|
arguments.selectGroup(peer.id)
|
||||||
|
@ -98,8 +98,9 @@ public extension MessageTags {
|
|||||||
static let gif = MessageTags(rawValue: 1 << 7)
|
static let gif = MessageTags(rawValue: 1 << 7)
|
||||||
static let photo = MessageTags(rawValue: 1 << 8)
|
static let photo = MessageTags(rawValue: 1 << 8)
|
||||||
static let video = MessageTags(rawValue: 1 << 9)
|
static let video = MessageTags(rawValue: 1 << 9)
|
||||||
|
static let pinned = MessageTags(rawValue: 1 << 10)
|
||||||
|
|
||||||
static let all: MessageTags = [.photoOrVideo, .file, .music, .webPage, .voiceOrInstantVideo, .unseenPersonalMessage, .liveLocation, .gif, .photo, .video]
|
static let all: MessageTags = [.photoOrVideo, .file, .music, .webPage, .voiceOrInstantVideo, .unseenPersonalMessage, .liveLocation, .gif, .photo, .video, .pinned]
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension GlobalMessageTags {
|
public extension GlobalMessageTags {
|
||||||
|
@ -26,7 +26,10 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
|||||||
var upgradedMessageHoles: [PeerId.Namespace: [MessageId.Namespace: Set<MessageTags>]] = [:]
|
var upgradedMessageHoles: [PeerId.Namespace: [MessageId.Namespace: Set<MessageTags>]] = [:]
|
||||||
for peerNamespace in peerIdNamespacesWithInitialCloudMessageHoles {
|
for peerNamespace in peerIdNamespacesWithInitialCloudMessageHoles {
|
||||||
upgradedMessageHoles[peerNamespace] = [
|
upgradedMessageHoles[peerNamespace] = [
|
||||||
Namespaces.Message.Cloud: Set(MessageTags.gif)
|
Namespaces.Message.Cloud: Set([
|
||||||
|
MessageTags.gif,
|
||||||
|
MessageTags.pinned
|
||||||
|
])
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +259,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1178116716] = { return Api.Update.parse_updateReadChannelDiscussionOutbox($0) }
|
dict[1178116716] = { return Api.Update.parse_updateReadChannelDiscussionOutbox($0) }
|
||||||
dict[610945826] = { return Api.Update.parse_updatePeerBlocked($0) }
|
dict[610945826] = { return Api.Update.parse_updatePeerBlocked($0) }
|
||||||
dict[-13975905] = { return Api.Update.parse_updateChannelUserTyping($0) }
|
dict[-13975905] = { return Api.Update.parse_updateChannelUserTyping($0) }
|
||||||
|
dict[-2054649973] = { return Api.Update.parse_updatePinnedChannelMessages($0) }
|
||||||
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
||||||
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
||||||
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
||||||
@ -267,6 +268,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[470789295] = { return Api.ChannelParticipant.parse_channelParticipantBanned($0) }
|
dict[470789295] = { return Api.ChannelParticipant.parse_channelParticipantBanned($0) }
|
||||||
dict[-859915345] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
|
dict[-859915345] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
|
||||||
dict[1149094475] = { return Api.ChannelParticipant.parse_channelParticipantCreator($0) }
|
dict[1149094475] = { return Api.ChannelParticipant.parse_channelParticipantCreator($0) }
|
||||||
|
dict[-1010402965] = { return Api.ChannelParticipant.parse_channelParticipantLeft($0) }
|
||||||
dict[-1567730343] = { return Api.MessageUserVote.parse_messageUserVote($0) }
|
dict[-1567730343] = { return Api.MessageUserVote.parse_messageUserVote($0) }
|
||||||
dict[909603888] = { return Api.MessageUserVote.parse_messageUserVoteInputOption($0) }
|
dict[909603888] = { return Api.MessageUserVote.parse_messageUserVoteInputOption($0) }
|
||||||
dict[244310238] = { return Api.MessageUserVote.parse_messageUserVoteMultiple($0) }
|
dict[244310238] = { return Api.MessageUserVote.parse_messageUserVoteMultiple($0) }
|
||||||
@ -692,6 +694,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1187706024] = { return Api.MessagesFilter.parse_inputMessagesFilterMyMentionsUnread($0) }
|
dict[1187706024] = { return Api.MessagesFilter.parse_inputMessagesFilterMyMentionsUnread($0) }
|
||||||
dict[-419271411] = { return Api.MessagesFilter.parse_inputMessagesFilterGeo($0) }
|
dict[-419271411] = { return Api.MessagesFilter.parse_inputMessagesFilterGeo($0) }
|
||||||
dict[-530392189] = { return Api.MessagesFilter.parse_inputMessagesFilterContacts($0) }
|
dict[-530392189] = { return Api.MessagesFilter.parse_inputMessagesFilterContacts($0) }
|
||||||
|
dict[464520273] = { return Api.MessagesFilter.parse_inputMessagesFilterPinned($0) }
|
||||||
dict[364538944] = { return Api.messages.Dialogs.parse_dialogs($0) }
|
dict[364538944] = { return Api.messages.Dialogs.parse_dialogs($0) }
|
||||||
dict[1910543603] = { return Api.messages.Dialogs.parse_dialogsSlice($0) }
|
dict[1910543603] = { return Api.messages.Dialogs.parse_dialogsSlice($0) }
|
||||||
dict[-253500010] = { return Api.messages.Dialogs.parse_dialogsNotModified($0) }
|
dict[-253500010] = { return Api.messages.Dialogs.parse_dialogsNotModified($0) }
|
||||||
|
@ -6178,6 +6178,7 @@ public extension Api {
|
|||||||
case updateReadChannelDiscussionOutbox(channelId: Int32, topMsgId: Int32, readMaxId: Int32)
|
case updateReadChannelDiscussionOutbox(channelId: Int32, topMsgId: Int32, readMaxId: Int32)
|
||||||
case updatePeerBlocked(peerId: Api.Peer, blocked: Api.Bool)
|
case updatePeerBlocked(peerId: Api.Peer, blocked: Api.Bool)
|
||||||
case updateChannelUserTyping(flags: Int32, channelId: Int32, topMsgId: Int32?, userId: Int32, action: Api.SendMessageAction)
|
case updateChannelUserTyping(flags: Int32, channelId: Int32, topMsgId: Int32?, userId: Int32, action: Api.SendMessageAction)
|
||||||
|
case updatePinnedChannelMessages(flags: Int32, channelId: Int32, messages: [Int32], pts: Int32, ptsCount: Int32)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -6907,6 +6908,20 @@ public extension Api {
|
|||||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||||
action.serialize(buffer, true)
|
action.serialize(buffer, true)
|
||||||
break
|
break
|
||||||
|
case .updatePinnedChannelMessages(let flags, let channelId, let messages, let pts, let ptsCount):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-2054649973)
|
||||||
|
}
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(channelId, buffer: buffer, boxed: false)
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(messages.count))
|
||||||
|
for item in messages {
|
||||||
|
serializeInt32(item, buffer: buffer, boxed: false)
|
||||||
|
}
|
||||||
|
serializeInt32(pts, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(ptsCount, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7084,6 +7099,8 @@ public extension Api {
|
|||||||
return ("updatePeerBlocked", [("peerId", peerId), ("blocked", blocked)])
|
return ("updatePeerBlocked", [("peerId", peerId), ("blocked", blocked)])
|
||||||
case .updateChannelUserTyping(let flags, let channelId, let topMsgId, let userId, let action):
|
case .updateChannelUserTyping(let flags, let channelId, let topMsgId, let userId, let action):
|
||||||
return ("updateChannelUserTyping", [("flags", flags), ("channelId", channelId), ("topMsgId", topMsgId), ("userId", userId), ("action", action)])
|
return ("updateChannelUserTyping", [("flags", flags), ("channelId", channelId), ("topMsgId", topMsgId), ("userId", userId), ("action", action)])
|
||||||
|
case .updatePinnedChannelMessages(let flags, let channelId, let messages, let pts, let ptsCount):
|
||||||
|
return ("updatePinnedChannelMessages", [("flags", flags), ("channelId", channelId), ("messages", messages), ("pts", pts), ("ptsCount", ptsCount)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8549,6 +8566,31 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_updatePinnedChannelMessages(_ reader: BufferReader) -> Update? {
|
||||||
|
var _1: Int32?
|
||||||
|
_1 = reader.readInt32()
|
||||||
|
var _2: Int32?
|
||||||
|
_2 = reader.readInt32()
|
||||||
|
var _3: [Int32]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
_3 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
|
||||||
|
}
|
||||||
|
var _4: Int32?
|
||||||
|
_4 = reader.readInt32()
|
||||||
|
var _5: Int32?
|
||||||
|
_5 = reader.readInt32()
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
let _c2 = _2 != nil
|
||||||
|
let _c3 = _3 != nil
|
||||||
|
let _c4 = _4 != nil
|
||||||
|
let _c5 = _5 != nil
|
||||||
|
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||||
|
return Api.Update.updatePinnedChannelMessages(flags: _1!, channelId: _2!, messages: _3!, pts: _4!, ptsCount: _5!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public enum PopularContact: TypeConstructorDescription {
|
public enum PopularContact: TypeConstructorDescription {
|
||||||
@ -8635,6 +8677,7 @@ public extension Api {
|
|||||||
case channelParticipantBanned(flags: Int32, userId: Int32, kickedBy: Int32, date: Int32, bannedRights: Api.ChatBannedRights)
|
case channelParticipantBanned(flags: Int32, userId: Int32, kickedBy: Int32, date: Int32, bannedRights: Api.ChatBannedRights)
|
||||||
case channelParticipantAdmin(flags: Int32, userId: Int32, inviterId: Int32?, promotedBy: Int32, date: Int32, adminRights: Api.ChatAdminRights, rank: String?)
|
case channelParticipantAdmin(flags: Int32, userId: Int32, inviterId: Int32?, promotedBy: Int32, date: Int32, adminRights: Api.ChatAdminRights, rank: String?)
|
||||||
case channelParticipantCreator(flags: Int32, userId: Int32, adminRights: Api.ChatAdminRights, rank: String?)
|
case channelParticipantCreator(flags: Int32, userId: Int32, adminRights: Api.ChatAdminRights, rank: String?)
|
||||||
|
case channelParticipantLeft(userId: Int32)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -8684,6 +8727,12 @@ public extension Api {
|
|||||||
adminRights.serialize(buffer, true)
|
adminRights.serialize(buffer, true)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(rank!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 0) != 0 {serializeString(rank!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
|
case .channelParticipantLeft(let userId):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1010402965)
|
||||||
|
}
|
||||||
|
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8699,6 +8748,8 @@ public extension Api {
|
|||||||
return ("channelParticipantAdmin", [("flags", flags), ("userId", userId), ("inviterId", inviterId), ("promotedBy", promotedBy), ("date", date), ("adminRights", adminRights), ("rank", rank)])
|
return ("channelParticipantAdmin", [("flags", flags), ("userId", userId), ("inviterId", inviterId), ("promotedBy", promotedBy), ("date", date), ("adminRights", adminRights), ("rank", rank)])
|
||||||
case .channelParticipantCreator(let flags, let userId, let adminRights, let rank):
|
case .channelParticipantCreator(let flags, let userId, let adminRights, let rank):
|
||||||
return ("channelParticipantCreator", [("flags", flags), ("userId", userId), ("adminRights", adminRights), ("rank", rank)])
|
return ("channelParticipantCreator", [("flags", flags), ("userId", userId), ("adminRights", adminRights), ("rank", rank)])
|
||||||
|
case .channelParticipantLeft(let userId):
|
||||||
|
return ("channelParticipantLeft", [("userId", userId)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8811,6 +8862,17 @@ public extension Api {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static func parse_channelParticipantLeft(_ reader: BufferReader) -> ChannelParticipant? {
|
||||||
|
var _1: Int32?
|
||||||
|
_1 = reader.readInt32()
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
if _c1 {
|
||||||
|
return Api.ChannelParticipant.channelParticipantLeft(userId: _1!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public enum MessageUserVote: TypeConstructorDescription {
|
public enum MessageUserVote: TypeConstructorDescription {
|
||||||
@ -19590,6 +19652,7 @@ public extension Api {
|
|||||||
case inputMessagesFilterMyMentionsUnread
|
case inputMessagesFilterMyMentionsUnread
|
||||||
case inputMessagesFilterGeo
|
case inputMessagesFilterGeo
|
||||||
case inputMessagesFilterContacts
|
case inputMessagesFilterContacts
|
||||||
|
case inputMessagesFilterPinned
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -19700,6 +19763,12 @@ public extension Api {
|
|||||||
buffer.appendInt32(-530392189)
|
buffer.appendInt32(-530392189)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
case .inputMessagesFilterPinned:
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(464520273)
|
||||||
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -19742,6 +19811,8 @@ public extension Api {
|
|||||||
return ("inputMessagesFilterGeo", [])
|
return ("inputMessagesFilterGeo", [])
|
||||||
case .inputMessagesFilterContacts:
|
case .inputMessagesFilterContacts:
|
||||||
return ("inputMessagesFilterContacts", [])
|
return ("inputMessagesFilterContacts", [])
|
||||||
|
case .inputMessagesFilterPinned:
|
||||||
|
return ("inputMessagesFilterPinned", [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19807,6 +19878,9 @@ public extension Api {
|
|||||||
public static func parse_inputMessagesFilterContacts(_ reader: BufferReader) -> MessagesFilter? {
|
public static func parse_inputMessagesFilterContacts(_ reader: BufferReader) -> MessagesFilter? {
|
||||||
return Api.MessagesFilter.inputMessagesFilterContacts
|
return Api.MessagesFilter.inputMessagesFilterContacts
|
||||||
}
|
}
|
||||||
|
public static func parse_inputMessagesFilterPinned(_ reader: BufferReader) -> MessagesFilter? {
|
||||||
|
return Api.MessagesFilter.inputMessagesFilterPinned
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public enum EmojiKeyword: TypeConstructorDescription {
|
public enum EmojiKeyword: TypeConstructorDescription {
|
||||||
|
@ -2963,22 +2963,6 @@ public extension Api {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func updatePinnedMessage(flags: Int32, peer: Api.InputPeer, id: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
|
||||||
let buffer = Buffer()
|
|
||||||
buffer.appendInt32(-760547348)
|
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
|
||||||
peer.serialize(buffer, true)
|
|
||||||
serializeInt32(id, buffer: buffer, boxed: false)
|
|
||||||
return (FunctionDescription(name: "messages.updatePinnedMessage", parameters: [("flags", flags), ("peer", peer), ("id", id)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
|
||||||
let reader = BufferReader(buffer)
|
|
||||||
var result: Api.Updates?
|
|
||||||
if let signature = reader.readInt32() {
|
|
||||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public static func sendVote(peer: Api.InputPeer, msgId: Int32, options: [Buffer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
public static func sendVote(peer: Api.InputPeer, msgId: Int32, options: [Buffer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(283795844)
|
buffer.appendInt32(283795844)
|
||||||
@ -3780,6 +3764,22 @@ public extension Api {
|
|||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func updatePinnedMessage(flags: Int32, peer: Api.InputPeer, id: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-760547348)
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
serializeInt32(id, buffer: buffer, boxed: false)
|
||||||
|
return (FunctionDescription(name: "messages.updatePinnedMessage", parameters: [("flags", flags), ("peer", peer), ("id", id)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.Updates?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public struct channels {
|
public struct channels {
|
||||||
public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||||
|
@ -18,6 +18,7 @@ swift_library(
|
|||||||
"//submodules/NetworkLogging:NetworkLogging",
|
"//submodules/NetworkLogging:NetworkLogging",
|
||||||
"//submodules/Reachability:Reachability",
|
"//submodules/Reachability:Reachability",
|
||||||
],
|
],
|
||||||
|
alwayslink = True,
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
],
|
],
|
||||||
|
@ -85,6 +85,7 @@ enum AccountStateMutationOperation {
|
|||||||
case UpdatePeer(PeerId, (Peer?) -> Peer?)
|
case UpdatePeer(PeerId, (Peer?) -> Peer?)
|
||||||
case UpdateIsContact(PeerId, Bool)
|
case UpdateIsContact(PeerId, Bool)
|
||||||
case UpdateCachedPeerData(PeerId, (CachedPeerData?) -> CachedPeerData?)
|
case UpdateCachedPeerData(PeerId, (CachedPeerData?) -> CachedPeerData?)
|
||||||
|
case UpdateMessagesPinned([MessageId], Bool)
|
||||||
case MergeApiUsers([Api.User])
|
case MergeApiUsers([Api.User])
|
||||||
case MergePeerPresences([PeerId: Api.UserStatus], Bool)
|
case MergePeerPresences([PeerId: Api.UserStatus], Bool)
|
||||||
case UpdateSecretChat(chat: Api.EncryptedChat, timestamp: Int32)
|
case UpdateSecretChat(chat: Api.EncryptedChat, timestamp: Int32)
|
||||||
@ -369,6 +370,10 @@ struct AccountMutableState {
|
|||||||
self.addOperation(.UpdateCachedPeerData(id, f))
|
self.addOperation(.UpdateCachedPeerData(id, f))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutating func updateMessagesPinned(ids: [MessageId], pinned: Bool) {
|
||||||
|
self.addOperation(.UpdateMessagesPinned(ids, pinned))
|
||||||
|
}
|
||||||
|
|
||||||
mutating func updateLangPack(langCode: String, difference: Api.LangPackDifference?) {
|
mutating func updateLangPack(langCode: String, difference: Api.LangPackDifference?) {
|
||||||
self.addOperation(.UpdateLangPack(langCode, difference))
|
self.addOperation(.UpdateLangPack(langCode, difference))
|
||||||
}
|
}
|
||||||
@ -479,7 +484,7 @@ struct AccountMutableState {
|
|||||||
|
|
||||||
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||||
switch operation {
|
switch operation {
|
||||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll/*, .UpdateMessageReactions*/, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter, .UpdateReadThread:
|
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll/*, .UpdateMessageReactions*/, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter, .UpdateReadThread, .UpdateMessagesPinned:
|
||||||
break
|
break
|
||||||
case let .AddMessages(messages, location):
|
case let .AddMessages(messages, location):
|
||||||
for message in messages {
|
for message in messages {
|
||||||
|
@ -663,6 +663,13 @@ private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] {
|
|||||||
} else {
|
} else {
|
||||||
updatesByChannel[peerId]!.append(update)
|
updatesByChannel[peerId]!.append(update)
|
||||||
}
|
}
|
||||||
|
case let .updatePinnedChannelMessages(_, channelId, _, _, _):
|
||||||
|
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
|
if updatesByChannel[peerId] == nil {
|
||||||
|
updatesByChannel[peerId] = [update]
|
||||||
|
} else {
|
||||||
|
updatesByChannel[peerId]!.append(update)
|
||||||
|
}
|
||||||
case let .updateNewChannelMessage(message, _, _):
|
case let .updateNewChannelMessage(message, _, _):
|
||||||
if let peerId = apiMessagePeerId(message) {
|
if let peerId = apiMessagePeerId(message) {
|
||||||
if updatesByChannel[peerId] == nil {
|
if updatesByChannel[peerId] == nil {
|
||||||
@ -718,6 +725,8 @@ private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] {
|
|||||||
lhsPts = pts
|
lhsPts = pts
|
||||||
case let .updateEditChannelMessage(_, pts, _):
|
case let .updateEditChannelMessage(_, pts, _):
|
||||||
lhsPts = pts
|
lhsPts = pts
|
||||||
|
case let .updatePinnedChannelMessages(_, _, _, pts, _):
|
||||||
|
lhsPts = pts
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -731,6 +740,8 @@ private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] {
|
|||||||
rhsPts = pts
|
rhsPts = pts
|
||||||
case let .updateEditChannelMessage(_, pts, _):
|
case let .updateEditChannelMessage(_, pts, _):
|
||||||
rhsPts = pts
|
rhsPts = pts
|
||||||
|
case let .updatePinnedChannelMessages(_, channelId, _, pts, _):
|
||||||
|
rhsPts = pts
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1106,7 +1117,9 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
|||||||
})
|
})
|
||||||
case let .updateChannelPinnedMessage(channelId, id):
|
case let .updateChannelPinnedMessage(channelId, id):
|
||||||
let channelPeerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
let channelPeerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
updatedState.updateCachedPeerData(channelPeerId, { current in
|
updatedState.updateMessagesPinned(ids: [MessageId(peerId: channelPeerId, namespace: Namespaces.Message.Cloud, id: id)], pinned: true)
|
||||||
|
|
||||||
|
/*updatedState.updateCachedPeerData(channelPeerId, { current in
|
||||||
let previous: CachedChannelData
|
let previous: CachedChannelData
|
||||||
if let current = current as? CachedChannelData {
|
if let current = current as? CachedChannelData {
|
||||||
previous = current
|
previous = current
|
||||||
@ -1114,7 +1127,31 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
|||||||
previous = CachedChannelData()
|
previous = CachedChannelData()
|
||||||
}
|
}
|
||||||
return previous.withUpdatedPinnedMessageId(id == 0 ? nil : MessageId(peerId: channelPeerId, namespace: Namespaces.Message.Cloud, id: id))
|
return previous.withUpdatedPinnedMessageId(id == 0 ? nil : MessageId(peerId: channelPeerId, namespace: Namespaces.Message.Cloud, id: id))
|
||||||
})
|
})*/
|
||||||
|
case let .updatePinnedChannelMessages(flags, channelId, messages, pts, ptsCount):
|
||||||
|
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
|
if let previousState = updatedState.channelStates[peerId] {
|
||||||
|
if previousState.pts >= pts {
|
||||||
|
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip old pinned messages update")
|
||||||
|
} else if previousState.pts + ptsCount == pts {
|
||||||
|
let channelPeerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
|
updatedState.updateMessagesPinned(ids: messages.map { id in
|
||||||
|
MessageId(peerId: channelPeerId, namespace: Namespaces.Message.Cloud, id: id)
|
||||||
|
}, pinned: (flags & (1 << 0)) != 0)
|
||||||
|
updatedState.updateChannelState(peerId, pts: pts)
|
||||||
|
} else {
|
||||||
|
if !channelsToPoll.contains(peerId) {
|
||||||
|
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) pinned messages pts hole")
|
||||||
|
channelsToPoll.insert(peerId)
|
||||||
|
//updatedMissingUpdates = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !channelsToPoll.contains(peerId) {
|
||||||
|
//Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) state unknown")
|
||||||
|
channelsToPoll.insert(peerId)
|
||||||
|
}
|
||||||
|
}
|
||||||
case let .updateUserPinnedMessage(userId, id):
|
case let .updateUserPinnedMessage(userId, id):
|
||||||
let userPeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
let userPeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||||
updatedState.updateCachedPeerData(userPeerId, { current in
|
updatedState.updateCachedPeerData(userPeerId, { current in
|
||||||
@ -1907,6 +1944,11 @@ private func pollChannel(network: Network, peer: Peer, state: AccountMutableStat
|
|||||||
}
|
}
|
||||||
return previous.withUpdatedPinnedMessageId(id == 0 ? nil : MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id))
|
return previous.withUpdatedPinnedMessageId(id == 0 ? nil : MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id))
|
||||||
})
|
})
|
||||||
|
case let .updatePinnedChannelMessages(flags, channelId, messages, _, _):
|
||||||
|
let channelPeerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
|
updatedState.updateMessagesPinned(ids: messages.map { id in
|
||||||
|
MessageId(peerId: channelPeerId, namespace: Namespaces.Message.Cloud, id: id)
|
||||||
|
}, pinned: (flags & (1 << 0)) != 0)
|
||||||
case let .updateChannelReadMessagesContents(_, messages):
|
case let .updateChannelReadMessagesContents(_, messages):
|
||||||
updatedState.addReadMessagesContents((peer.id, messages))
|
updatedState.addReadMessagesContents((peer.id, messages))
|
||||||
case let .updateChannelMessageViews(_, id, views):
|
case let .updateChannelMessageViews(_, id, views):
|
||||||
@ -2107,7 +2149,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
|||||||
var currentAddScheduledMessages: OptimizeAddMessagesState?
|
var currentAddScheduledMessages: OptimizeAddMessagesState?
|
||||||
for operation in operations {
|
for operation in operations {
|
||||||
switch operation {
|
switch operation {
|
||||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll/*, .UpdateMessageReactions*/, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder, .UpdateReadThread:
|
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll/*, .UpdateMessageReactions*/, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder, .UpdateReadThread, .UpdateMessagesPinned:
|
||||||
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
||||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||||
}
|
}
|
||||||
@ -2771,6 +2813,28 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
|||||||
transaction.updatePeerCachedData(peerIds: Set([id]), update: { _, current in
|
transaction.updatePeerCachedData(peerIds: Set([id]), update: { _, current in
|
||||||
return f(current)
|
return f(current)
|
||||||
})
|
})
|
||||||
|
case let .UpdateMessagesPinned(messageIds, pinned):
|
||||||
|
for id in messageIds {
|
||||||
|
transaction.updateMessage(id, update: { currentMessage in
|
||||||
|
var storeForwardInfo: StoreMessageForwardInfo?
|
||||||
|
if let forwardInfo = currentMessage.forwardInfo {
|
||||||
|
storeForwardInfo = StoreMessageForwardInfo(forwardInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
var tags = currentMessage.tags
|
||||||
|
if pinned {
|
||||||
|
tags.insert(.pinned)
|
||||||
|
} else {
|
||||||
|
tags.remove(.pinned)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tags == currentMessage.tags {
|
||||||
|
return .skip
|
||||||
|
}
|
||||||
|
|
||||||
|
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: currentMessage.attributes, media: currentMessage.media))
|
||||||
|
})
|
||||||
|
}
|
||||||
case let .MergePeerPresences(statuses, explicit):
|
case let .MergePeerPresences(statuses, explicit):
|
||||||
var presences: [PeerId: PeerPresence] = [:]
|
var presences: [PeerId: PeerPresence] = [:]
|
||||||
for (peerId, status) in statuses {
|
for (peerId, status) in statuses {
|
||||||
|
@ -198,7 +198,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: currentMessage.flags.contains(.Incoming), attributes: attributes, media: media, textEntities: entitiesAttribute?.entities)
|
let (tags, globalTags) = tagsForStoreMessage(incoming: currentMessage.flags.contains(.Incoming), attributes: attributes, media: media, textEntities: entitiesAttribute?.entities, isPinned: currentMessage.tags.contains(.pinned))
|
||||||
|
|
||||||
if currentMessage.id.peerId.namespace == Namespaces.Peer.CloudChannel, !currentMessage.flags.contains(.Incoming), !Namespaces.Message.allScheduled.contains(currentMessage.id.namespace) {
|
if currentMessage.id.peerId.namespace == Namespaces.Peer.CloudChannel, !currentMessage.flags.contains(.Incoming), !Namespaces.Message.allScheduled.contains(currentMessage.id.namespace) {
|
||||||
let peerId = currentMessage.id.peerId
|
let peerId = currentMessage.id.peerId
|
||||||
@ -374,7 +374,7 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: currentMessage.flags.contains(.Incoming), attributes: attributes, media: media, textEntities: entitiesAttribute?.entities)
|
let (tags, globalTags) = tagsForStoreMessage(incoming: currentMessage.flags.contains(.Incoming), attributes: attributes, media: media, textEntities: entitiesAttribute?.entities, isPinned: currentMessage.tags.contains(.pinned))
|
||||||
|
|
||||||
return .update(StoreMessage(id: updatedId, globallyUniqueId: nil, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: updatedMessage.timestamp, flags: [], tags: tags, globalTags: globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: text, attributes: attributes, media: media))
|
return .update(StoreMessage(id: updatedId, globallyUniqueId: nil, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: updatedMessage.timestamp, flags: [], tags: tags, globalTags: globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: text, attributes: attributes, media: media))
|
||||||
})
|
})
|
||||||
|
@ -210,6 +210,8 @@ extension ChannelParticipant {
|
|||||||
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(apiAdminRights: adminRights), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: promotedBy), canBeEditedByAccountPeer: (flags & (1 << 0)) != 0), banInfo: nil, rank: rank)
|
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(apiAdminRights: adminRights), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: promotedBy), canBeEditedByAccountPeer: (flags & (1 << 0)) != 0), banInfo: nil, rank: rank)
|
||||||
case let .channelParticipantSelf(userId, _, date):
|
case let .channelParticipantSelf(userId, _, date):
|
||||||
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: nil, banInfo: nil, rank: nil)
|
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: date, adminInfo: nil, banInfo: nil, rank: nil)
|
||||||
|
case let .channelParticipantLeft(userId):
|
||||||
|
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), invitedAt: 0, adminInfo: nil, banInfo: nil, rank: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
|||||||
authorId = account.peerId
|
authorId = account.peerId
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: false, attributes: attributes, media: mediaList, textEntities: entitiesAttribute?.entities)
|
let (tags, globalTags) = tagsForStoreMessage(incoming: false, attributes: attributes, media: mediaList, textEntities: entitiesAttribute?.entities, isPinned: false)
|
||||||
|
|
||||||
var localTags: LocalMessageTags = []
|
var localTags: LocalMessageTags = []
|
||||||
for media in mediaList {
|
for media in mediaList {
|
||||||
@ -571,7 +571,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
|||||||
attributes.removeAll(where: { $0 is OutgoingScheduleInfoMessageAttribute })
|
attributes.removeAll(where: { $0 is OutgoingScheduleInfoMessageAttribute })
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: false, attributes: attributes, media: sourceMessage.media, textEntities: entitiesAttribute?.entities)
|
let (tags, globalTags) = tagsForStoreMessage(incoming: false, attributes: attributes, media: sourceMessage.media, textEntities: entitiesAttribute?.entities, isPinned: false)
|
||||||
|
|
||||||
let localGroupingKey: Int64?
|
let localGroupingKey: Int64?
|
||||||
switch grouping {
|
switch grouping {
|
||||||
|
@ -140,7 +140,7 @@ final class HistoryViewStateValidationContexts {
|
|||||||
|
|
||||||
func updateView(id: Int32, view: MessageHistoryView?, location: ChatLocationInput? = nil) {
|
func updateView(id: Int32, view: MessageHistoryView?, location: ChatLocationInput? = nil) {
|
||||||
assert(self.queue.isCurrent())
|
assert(self.queue.isCurrent())
|
||||||
guard let view = view, view.tagMask == nil || view.tagMask == MessageTags.unseenPersonalMessage || view.tagMask == MessageTags.music else {
|
guard let view = view, view.tagMask == nil || view.tagMask == MessageTags.unseenPersonalMessage || view.tagMask == MessageTags.music || view.tagMask == MessageTags.pinned else {
|
||||||
if self.contexts[id] != nil {
|
if self.contexts[id] != nil {
|
||||||
self.contexts.removeValue(forKey: id)
|
self.contexts.removeValue(forKey: id)
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ func messageFilterForTagMask(_ tagMask: MessageTags) -> Api.MessagesFilter? {
|
|||||||
return Api.MessagesFilter.inputMessagesFilterRoundVoice
|
return Api.MessagesFilter.inputMessagesFilterRoundVoice
|
||||||
} else if tagMask == .gif {
|
} else if tagMask == .gif {
|
||||||
return Api.MessagesFilter.inputMessagesFilterGif
|
return Api.MessagesFilter.inputMessagesFilterGif
|
||||||
|
} else if tagMask == .pinned {
|
||||||
|
return Api.MessagesFilter.inputMessagesFilterPinned
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -820,7 +820,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: true, attributes: attributes, media: parsedMedia, textEntities: entitiesAttribute?.entities)
|
let (tags, globalTags) = tagsForStoreMessage(incoming: true, attributes: attributes, media: parsedMedia, textEntities: entitiesAttribute?.entities, isPinned: false)
|
||||||
|
|
||||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: nil, threadId: nil, timestamp: timestamp, flags: [.Incoming], tags: tags, globalTags: globalTags, localTags: [], forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: nil, threadId: nil, timestamp: timestamp, flags: [.Incoming], tags: tags, globalTags: globalTags, localTags: [], forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
||||||
case let .decryptedMessageService(randomId, action):
|
case let .decryptedMessageService(randomId, action):
|
||||||
@ -1052,7 +1052,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: true, attributes: attributes, media: parsedMedia, textEntities: entitiesAttribute?.entities)
|
let (tags, globalTags) = tagsForStoreMessage(incoming: true, attributes: attributes, media: parsedMedia, textEntities: entitiesAttribute?.entities, isPinned: false)
|
||||||
|
|
||||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: groupingKey, threadId: nil, timestamp: timestamp, flags: [.Incoming], tags: tags, globalTags: globalTags, localTags: [], forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: groupingKey, threadId: nil, timestamp: timestamp, flags: [.Incoming], tags: tags, globalTags: globalTags, localTags: [], forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
||||||
case let .decryptedMessageService(randomId, action):
|
case let .decryptedMessageService(randomId, action):
|
||||||
@ -1290,7 +1290,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: true, attributes: attributes, media: parsedMedia, textEntities: entitiesAttribute?.entities)
|
let (tags, globalTags) = tagsForStoreMessage(incoming: true, attributes: attributes, media: parsedMedia, textEntities: entitiesAttribute?.entities, isPinned: false)
|
||||||
|
|
||||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: groupingKey, threadId: nil, timestamp: timestamp, flags: [.Incoming], tags: tags, globalTags: globalTags, localTags: [], forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: groupingKey, threadId: nil, timestamp: timestamp, flags: [.Incoming], tags: tags, globalTags: globalTags, localTags: [], forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
||||||
case let .decryptedMessageService(randomId, action):
|
case let .decryptedMessageService(randomId, action):
|
||||||
|
@ -4,7 +4,7 @@ import TelegramApi
|
|||||||
|
|
||||||
import SyncCore
|
import SyncCore
|
||||||
|
|
||||||
public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute], media: [Media], textEntities: [MessageTextEntity]?) -> (MessageTags, GlobalMessageTags) {
|
public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute], media: [Media], textEntities: [MessageTextEntity]?, isPinned: Bool) -> (MessageTags, GlobalMessageTags) {
|
||||||
var isSecret = false
|
var isSecret = false
|
||||||
var isUnconsumedPersonalMention = false
|
var isUnconsumedPersonalMention = false
|
||||||
for attribute in attributes {
|
for attribute in attributes {
|
||||||
@ -26,6 +26,10 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
|
|||||||
tags.insert(.unseenPersonalMessage)
|
tags.insert(.unseenPersonalMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isPinned {
|
||||||
|
tags.insert(.pinned)
|
||||||
|
}
|
||||||
|
|
||||||
for attachment in media {
|
for attachment in media {
|
||||||
if let _ = attachment as? TelegramMediaImage {
|
if let _ = attachment as? TelegramMediaImage {
|
||||||
if !isSecret {
|
if !isSecret {
|
||||||
@ -582,7 +586,9 @@ extension StoreMessage {
|
|||||||
attributes.append(NotificationInfoMessageAttribute(flags: notificationFlags))
|
attributes.append(NotificationInfoMessageAttribute(flags: notificationFlags))
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: storeFlags.contains(.Incoming), attributes: attributes, media: medias, textEntities: entitiesAttribute?.entities)
|
let isPinned = (flags & (1 << 24)) != 0
|
||||||
|
|
||||||
|
let (tags, globalTags) = tagsForStoreMessage(incoming: storeFlags.contains(.Incoming), attributes: attributes, media: medias, textEntities: entitiesAttribute?.entities, isPinned: isPinned)
|
||||||
|
|
||||||
storeFlags.insert(.CanBeGroupedIntoFeed)
|
storeFlags.insert(.CanBeGroupedIntoFeed)
|
||||||
|
|
||||||
@ -643,7 +649,7 @@ extension StoreMessage {
|
|||||||
media.append(action)
|
media.append(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tags, globalTags) = tagsForStoreMessage(incoming: storeFlags.contains(.Incoming), attributes: attributes, media: media, textEntities: nil)
|
let (tags, globalTags) = tagsForStoreMessage(incoming: storeFlags.contains(.Incoming), attributes: attributes, media: media, textEntities: nil, isPinned: false)
|
||||||
|
|
||||||
storeFlags.insert(.CanBeGroupedIntoFeed)
|
storeFlags.insert(.CanBeGroupedIntoFeed)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ func updateMessageMedia(transaction: Transaction, id: MediaId, media: Media?) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let (tags, _) = tagsForStoreMessage(incoming: currentMessage.flags.contains(.Incoming), attributes: currentMessage.attributes, media: currentMessage.media, textEntities: textEntities)
|
let (tags, _) = tagsForStoreMessage(incoming: currentMessage.flags.contains(.Incoming), attributes: currentMessage.attributes, media: currentMessage.media, textEntities: textEntities, isPinned: currentMessage.tags.contains(.pinned))
|
||||||
if tags == currentMessage.tags {
|
if tags == currentMessage.tags {
|
||||||
return .skip
|
return .skip
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ public enum UpdatePinnedMessageError {
|
|||||||
|
|
||||||
public enum PinnedMessageUpdate {
|
public enum PinnedMessageUpdate {
|
||||||
case pin(id: MessageId, silent: Bool)
|
case pin(id: MessageId, silent: Bool)
|
||||||
case clear
|
case clear(id: MessageId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update: PinnedMessageUpdate) -> Signal<Void, UpdatePinnedMessageError> {
|
public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update: PinnedMessageUpdate) -> Signal<Void, UpdatePinnedMessageError> {
|
||||||
@ -20,7 +20,6 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
|
|||||||
return (transaction.getPeer(peerId), transaction.getPeerCachedData(peerId: peerId))
|
return (transaction.getPeer(peerId), transaction.getPeerCachedData(peerId: peerId))
|
||||||
}
|
}
|
||||||
|> mapError { _ -> UpdatePinnedMessageError in
|
|> mapError { _ -> UpdatePinnedMessageError in
|
||||||
return .generic
|
|
||||||
}
|
}
|
||||||
|> mapToSignal { peer, cachedPeerData -> Signal<Void, UpdatePinnedMessageError> in
|
|> mapToSignal { peer, cachedPeerData -> Signal<Void, UpdatePinnedMessageError> in
|
||||||
guard let peer = peer, let inputPeer = apiInputPeer(peer) else {
|
guard let peer = peer, let inputPeer = apiInputPeer(peer) else {
|
||||||
@ -38,8 +37,9 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
|
|||||||
if silent {
|
if silent {
|
||||||
flags |= (1 << 0)
|
flags |= (1 << 0)
|
||||||
}
|
}
|
||||||
case .clear:
|
case let .clear(id):
|
||||||
messageId = 0
|
messageId = id.id
|
||||||
|
flags |= 1 << 1
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = Api.functions.messages.updatePinnedMessage(flags: flags, peer: inputPeer, id: messageId)
|
let request = Api.functions.messages.updatePinnedMessage(flags: flags, peer: inputPeer, id: messageId)
|
||||||
@ -51,7 +51,37 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
|
|||||||
|> mapToSignal { updates -> Signal<Void, UpdatePinnedMessageError> in
|
|> mapToSignal { updates -> Signal<Void, UpdatePinnedMessageError> in
|
||||||
account.stateManager.addUpdates(updates)
|
account.stateManager.addUpdates(updates)
|
||||||
return account.postbox.transaction { transaction in
|
return account.postbox.transaction { transaction in
|
||||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
switch updates {
|
||||||
|
case let .updates(updates, _, _, _, _):
|
||||||
|
if updates.isEmpty {
|
||||||
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
let messageId: MessageId
|
||||||
|
switch update {
|
||||||
|
case let .pin(id, _):
|
||||||
|
messageId = id
|
||||||
|
case let .clear(id):
|
||||||
|
messageId = id
|
||||||
|
}
|
||||||
|
transaction.updateMessage(messageId, update: { currentMessage in
|
||||||
|
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
|
||||||
|
var updatedTags = currentMessage.tags
|
||||||
|
switch update {
|
||||||
|
case .pin:
|
||||||
|
updatedTags.insert(.pinned)
|
||||||
|
case .clear:
|
||||||
|
updatedTags.remove(.pinned)
|
||||||
|
}
|
||||||
|
if updatedTags == currentMessage.tags {
|
||||||
|
return .skip
|
||||||
|
}
|
||||||
|
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: updatedTags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: currentMessage.attributes, media: currentMessage.media))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
/*transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||||
if let current = current as? CachedChannelData {
|
if let current = current as? CachedChannelData {
|
||||||
let pinnedMessageId: MessageId?
|
let pinnedMessageId: MessageId?
|
||||||
switch update {
|
switch update {
|
||||||
@ -64,9 +94,9 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
|
|||||||
} else {
|
} else {
|
||||||
return current
|
return current
|
||||||
}
|
}
|
||||||
})
|
})*/
|
||||||
}
|
}
|
||||||
|> mapError { _ -> UpdatePinnedMessageError in return .generic
|
|> mapError { _ -> UpdatePinnedMessageError in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -97,8 +127,9 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
|
|||||||
if silent {
|
if silent {
|
||||||
flags |= (1 << 0)
|
flags |= (1 << 0)
|
||||||
}
|
}
|
||||||
case .clear:
|
case let .clear(id):
|
||||||
messageId = 0
|
messageId = id.id
|
||||||
|
flags |= 1 << 1
|
||||||
}
|
}
|
||||||
|
|
||||||
let request = Api.functions.messages.updatePinnedMessage(flags: flags, peer: inputPeer, id: messageId)
|
let request = Api.functions.messages.updatePinnedMessage(flags: flags, peer: inputPeer, id: messageId)
|
||||||
@ -110,6 +141,37 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
|
|||||||
|> mapToSignal { updates -> Signal<Void, UpdatePinnedMessageError> in
|
|> mapToSignal { updates -> Signal<Void, UpdatePinnedMessageError> in
|
||||||
account.stateManager.addUpdates(updates)
|
account.stateManager.addUpdates(updates)
|
||||||
return account.postbox.transaction { transaction in
|
return account.postbox.transaction { transaction in
|
||||||
|
switch updates {
|
||||||
|
case let .updates(updates, _, _, _, _):
|
||||||
|
if updates.isEmpty {
|
||||||
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
let messageId: MessageId
|
||||||
|
switch update {
|
||||||
|
case let .pin(id, _):
|
||||||
|
messageId = id
|
||||||
|
case let .clear(id):
|
||||||
|
messageId = id
|
||||||
|
}
|
||||||
|
transaction.updateMessage(messageId, update: { currentMessage in
|
||||||
|
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
|
||||||
|
var updatedTags = currentMessage.tags
|
||||||
|
switch update {
|
||||||
|
case .pin:
|
||||||
|
updatedTags.insert(.pinned)
|
||||||
|
case .clear:
|
||||||
|
updatedTags.remove(.pinned)
|
||||||
|
}
|
||||||
|
if updatedTags == currentMessage.tags {
|
||||||
|
return .skip
|
||||||
|
}
|
||||||
|
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: updatedTags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: currentMessage.attributes, media: currentMessage.media))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||||
if let _ = peer as? TelegramGroup {
|
if let _ = peer as? TelegramGroup {
|
||||||
let current = current as? CachedGroupData ?? CachedGroupData()
|
let current = current as? CachedGroupData ?? CachedGroupData()
|
||||||
@ -138,7 +200,6 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|> mapError { _ -> UpdatePinnedMessageError in
|
|> mapError { _ -> UpdatePinnedMessageError in
|
||||||
return .generic
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -268,6 +268,8 @@ extension Api.Update {
|
|||||||
}
|
}
|
||||||
case let .updateDeleteChannelMessages(channelId, _, _, _):
|
case let .updateDeleteChannelMessages(channelId, _, _, _):
|
||||||
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
|
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
|
||||||
|
case let .updatePinnedChannelMessages(_, channelId, _, _, _):
|
||||||
|
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
|
||||||
case let .updateNewChannelMessage(message, _, _):
|
case let .updateNewChannelMessage(message, _, _):
|
||||||
return apiMessagePeerIds(message)
|
return apiMessagePeerIds(message)
|
||||||
case let .updateEditChannelMessage(message, _, _):
|
case let .updateEditChannelMessage(message, _, _):
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -3237,6 +3237,64 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.chatTitleView?.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings, hasEmbeddedTitleContent: self.hasEmbeddedTitleContent)
|
self.chatTitleView?.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings, hasEmbeddedTitleContent: self.hasEmbeddedTitleContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func topPinnedMessageSignal(latest: Bool) -> Signal<ChatPinnedMessage?, NoError> {
|
||||||
|
let topPinnedMessage: Signal<ChatPinnedMessage?, NoError>
|
||||||
|
switch self.chatLocation {
|
||||||
|
case let .peer(peerId) where peerId.namespace == Namespaces.Peer.CloudChannel:
|
||||||
|
let replyHistory: Signal<ChatHistoryViewUpdate, NoError> = (chatHistoryViewForLocation(ChatHistoryLocationInput(content: .Initial(count: 100), id: 0), context: self.context, chatLocation: .peer(peerId), chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil), scheduled: false, fixedCombinedReadStates: nil, tagMask: MessageTags.pinned, additionalData: [])
|
||||||
|
|> castError(Bool.self)
|
||||||
|
|> mapToSignal { update -> Signal<ChatHistoryViewUpdate, Bool> in
|
||||||
|
switch update {
|
||||||
|
case let .Loading(_, type):
|
||||||
|
if case .Generic(.FillHole) = type {
|
||||||
|
return .fail(true)
|
||||||
|
}
|
||||||
|
case let .HistoryView(_, type, _, _, _, _, _):
|
||||||
|
if case .Generic(.FillHole) = type {
|
||||||
|
return .fail(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return .single(update)
|
||||||
|
})
|
||||||
|
|> restartIfError
|
||||||
|
|
||||||
|
topPinnedMessage = combineLatest(
|
||||||
|
replyHistory,
|
||||||
|
latest ? .single(nil) : self.chatDisplayNode.historyNode.topVisibleMessageRange.get()
|
||||||
|
)
|
||||||
|
|> map { update, topVisibleMessageRange -> ChatPinnedMessage? in
|
||||||
|
var message: ChatPinnedMessage?
|
||||||
|
switch update {
|
||||||
|
case .Loading:
|
||||||
|
break
|
||||||
|
case let .HistoryView(view, _, _, _, _, _, _):
|
||||||
|
for i in 0 ..< view.entries.count {
|
||||||
|
let entry = view.entries[i]
|
||||||
|
var matches = false
|
||||||
|
if message == nil {
|
||||||
|
matches = true
|
||||||
|
} else if let topVisibleMessageRange = topVisibleMessageRange {
|
||||||
|
if entry.message.id < topVisibleMessageRange.upperBound {
|
||||||
|
matches = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
matches = true
|
||||||
|
}
|
||||||
|
if matches {
|
||||||
|
message = ChatPinnedMessage(message: entry.message, isLatest: i == view.entries.count - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return message
|
||||||
|
}
|
||||||
|
|> distinctUntilChanged
|
||||||
|
default:
|
||||||
|
topPinnedMessage = .single(nil)
|
||||||
|
}
|
||||||
|
return topPinnedMessage
|
||||||
|
}
|
||||||
|
|
||||||
override public func loadDisplayNode() {
|
override public func loadDisplayNode() {
|
||||||
self.displayNode = ChatControllerNode(context: self.context, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, subject: self.subject, controllerInteraction: self.controllerInteraction!, chatPresentationInterfaceState: self.presentationInterfaceState, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, navigationBar: self.navigationBar, controller: self)
|
self.displayNode = ChatControllerNode(context: self.context, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, subject: self.subject, controllerInteraction: self.controllerInteraction!, chatPresentationInterfaceState: self.presentationInterfaceState, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, navigationBar: self.navigationBar, controller: self)
|
||||||
|
|
||||||
@ -3406,60 +3464,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
let isTopReplyThreadMessageShown: Signal<Bool, NoError> = self.chatDisplayNode.historyNode.isTopReplyThreadMessageShown.get()
|
let isTopReplyThreadMessageShown: Signal<Bool, NoError> = self.chatDisplayNode.historyNode.isTopReplyThreadMessageShown.get()
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|
|
||||||
let topPinnedMessage: Signal<ChatPinnedMessage?, NoError>
|
let topPinnedMessage: Signal<ChatPinnedMessage?, NoError> = self.topPinnedMessageSignal(latest: false)
|
||||||
switch self.chatLocation {
|
|
||||||
case let .peer(peerId):
|
|
||||||
let replyHistory: Signal<ChatHistoryViewUpdate, NoError> = (chatHistoryViewForLocation(ChatHistoryLocationInput(content: .Initial(count: 100), id: 0), context: self.context, chatLocation: .peer(peerId), chatLocationContextHolder: Atomic<ChatLocationContextHolder?>(value: nil), scheduled: false, fixedCombinedReadStates: nil, tagMask: MessageTags.photoOrVideo, additionalData: [])
|
|
||||||
|> castError(Bool.self)
|
|
||||||
|> mapToSignal { update -> Signal<ChatHistoryViewUpdate, Bool> in
|
|
||||||
switch update {
|
|
||||||
case let .Loading(_, type):
|
|
||||||
if case .Generic(.FillHole) = type {
|
|
||||||
return .fail(true)
|
|
||||||
}
|
|
||||||
case let .HistoryView(_, type, _, _, _, _, _):
|
|
||||||
if case .Generic(.FillHole) = type {
|
|
||||||
return .fail(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return .single(update)
|
|
||||||
})
|
|
||||||
|> restartIfError
|
|
||||||
|
|
||||||
topPinnedMessage = combineLatest(
|
|
||||||
replyHistory,
|
|
||||||
self.chatDisplayNode.historyNode.topVisibleMessage.get()
|
|
||||||
)
|
|
||||||
|> map { update, topVisibleMessage -> ChatPinnedMessage? in
|
|
||||||
var message: ChatPinnedMessage?
|
|
||||||
switch update {
|
|
||||||
case .Loading:
|
|
||||||
break
|
|
||||||
case let .HistoryView(view, _, _, _, _, _, _):
|
|
||||||
for i in 0 ..< view.entries.count {
|
|
||||||
let entry = view.entries[i]
|
|
||||||
var matches = false
|
|
||||||
if message == nil {
|
|
||||||
matches = true
|
|
||||||
} else if let topVisibleMessage = topVisibleMessage {
|
|
||||||
if entry.message.id < topVisibleMessage.id {
|
|
||||||
matches = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
matches = true
|
|
||||||
}
|
|
||||||
if matches {
|
|
||||||
message = ChatPinnedMessage(message: entry.message, isLatest: i == view.entries.count - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return message
|
|
||||||
}
|
|
||||||
|> distinctUntilChanged
|
|
||||||
case .replyThread:
|
|
||||||
topPinnedMessage = .single(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.cachedDataDisposable = combineLatest(queue: .mainQueue(), self.chatDisplayNode.historyNode.cachedPeerDataAndMessages, hasPendingMessages, isTopReplyThreadMessageShown, topPinnedMessage).start(next: { [weak self] cachedDataAndMessages, hasPendingMessages, isTopReplyThreadMessageShown, topPinnedMessage in
|
self.cachedDataDisposable = combineLatest(queue: .mainQueue(), self.chatDisplayNode.historyNode.cachedPeerDataAndMessages, hasPendingMessages, isTopReplyThreadMessageShown, topPinnedMessage).start(next: { [weak self] cachedDataAndMessages, hasPendingMessages, isTopReplyThreadMessageShown, topPinnedMessage in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@ -3490,7 +3495,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
var pinnedMessage: ChatPinnedMessage?
|
var pinnedMessage: ChatPinnedMessage?
|
||||||
if case let .replyThread(replyThreadMessage) = strongSelf.chatLocation {
|
switch strongSelf.chatLocation {
|
||||||
|
case let .replyThread(replyThreadMessage):
|
||||||
if isTopReplyThreadMessageShown {
|
if isTopReplyThreadMessageShown {
|
||||||
pinnedMessageId = nil
|
pinnedMessageId = nil
|
||||||
} else {
|
} else {
|
||||||
@ -3501,14 +3507,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
pinnedMessage = ChatPinnedMessage(message: message, isLatest: true)
|
pinnedMessage = ChatPinnedMessage(message: message, isLatest: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case let .peer(peerId):
|
||||||
|
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||||
|
pinnedMessageId = topPinnedMessage?.message.id
|
||||||
|
pinnedMessage = topPinnedMessage
|
||||||
} else {
|
} else {
|
||||||
if let pinnedMessageId = pinnedMessageId {
|
if let pinnedMessageId = pinnedMessageId {
|
||||||
if let message = messages?[pinnedMessageId] {
|
if let message = messages?[pinnedMessageId] {
|
||||||
pinnedMessage = ChatPinnedMessage(message: message, isLatest: true)
|
pinnedMessage = ChatPinnedMessage(message: message, isLatest: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//pinnedMessageId = topPinnedMessage?.message.id
|
}
|
||||||
//pinnedMessage = topPinnedMessage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pinnedMessageUpdated = false
|
var pinnedMessageUpdated = false
|
||||||
@ -3586,7 +3595,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if case .replyThread = self.chatLocation {
|
if case .replyThread = self.chatLocation {
|
||||||
effectiveCachedDataReady = self.cachedDataReady.get()
|
effectiveCachedDataReady = self.cachedDataReady.get()
|
||||||
} else {
|
} else {
|
||||||
effectiveCachedDataReady = .single(true)
|
//effectiveCachedDataReady = .single(true)
|
||||||
|
effectiveCachedDataReady = self.cachedDataReady.get()
|
||||||
}
|
}
|
||||||
self.ready.set(combineLatest(self.chatDisplayNode.historyNode.historyState.get(), self._chatLocationInfoReady.get(), effectiveCachedDataReady, initialData) |> map { _, chatLocationInfoReady, cachedDataReady, _ in
|
self.ready.set(combineLatest(self.chatDisplayNode.historyNode.historyState.get(), self._chatLocationInfoReady.get(), effectiveCachedDataReady, initialData) |> map { _, chatLocationInfoReady, cachedDataReady, _ in
|
||||||
return chatLocationInfoReady && cachedDataReady
|
return chatLocationInfoReady && cachedDataReady
|
||||||
@ -4812,11 +4822,46 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if pinImmediately {
|
if pinImmediately {
|
||||||
pinAction(true)
|
pinAction(true)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_PinMessageAlertGroup, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlert_OnlyPin, action: {
|
let topPinnedMessage: Signal<ChatPinnedMessage?, NoError> = strongSelf.topPinnedMessageSignal(latest: true)
|
||||||
|
|> take(1)
|
||||||
|
|
||||||
|
let _ = (topPinnedMessage
|
||||||
|
|> deliverOnMainQueue).start(next: { value in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let title: String?
|
||||||
|
let text: String
|
||||||
|
let actionLayout: TextAlertContentActionLayout
|
||||||
|
let actions: [TextAlertAction]
|
||||||
|
if let value = value, value.message.id > messageId {
|
||||||
|
title = strongSelf.presentationData.strings.Conversation_PinOlderMessageAlertTitle
|
||||||
|
text = strongSelf.presentationData.strings.Conversation_PinOlderMessageAlertText
|
||||||
|
actionLayout = .vertical
|
||||||
|
actions = [
|
||||||
|
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlertPin, action: {
|
||||||
pinAction(false)
|
pinAction(false)
|
||||||
}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Yes, action: {
|
}),
|
||||||
|
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
|
||||||
|
})
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
title = nil
|
||||||
|
text = strongSelf.presentationData.strings.Conversation_PinMessageAlertGroup
|
||||||
|
actionLayout = .horizontal
|
||||||
|
actions = [
|
||||||
|
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_PinMessageAlert_OnlyPin, action: {
|
||||||
|
pinAction(false)
|
||||||
|
}),
|
||||||
|
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Yes, action: {
|
||||||
pinAction(true)
|
pinAction(true)
|
||||||
})]), in: .window(.root))
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.present(textAlertController(context: strongSelf.context, title: title, text: text, actions: actions, actionLayout: actionLayout), in: .window(.root))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let pinnedMessageId = strongSelf.presentationInterfaceState.pinnedMessage?.message.id {
|
if let pinnedMessageId = strongSelf.presentationInterfaceState.pinnedMessage?.message.id {
|
||||||
@ -4832,7 +4877,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, unpinMessage: { [weak self] in
|
}, unpinMessage: { [weak self] id in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||||
var canManagePin = false
|
var canManagePin = false
|
||||||
@ -4854,7 +4899,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
if canManagePin {
|
if canManagePin {
|
||||||
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_UnpinMessageAlert, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_Unpin, action: {
|
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_UnpinMessageAlert, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Conversation_Unpin, action: {
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let disposable: MetaDisposable
|
let disposable: MetaDisposable
|
||||||
if let current = strongSelf.unpinMessageDisposable {
|
if let current = strongSelf.unpinMessageDisposable {
|
||||||
@ -4863,9 +4908,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
disposable = MetaDisposable()
|
disposable = MetaDisposable()
|
||||||
strongSelf.unpinMessageDisposable = disposable
|
strongSelf.unpinMessageDisposable = disposable
|
||||||
}
|
}
|
||||||
disposable.set(requestUpdatePinnedMessage(account: strongSelf.context.account, peerId: peer.id, update: .clear).start())
|
disposable.set(requestUpdatePinnedMessage(account: strongSelf.context.account, peerId: peer.id, update: .clear(id: id)).start())
|
||||||
}
|
}
|
||||||
})]), in: .window(.root))
|
}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
|
||||||
} else {
|
} else {
|
||||||
if let pinnedMessage = strongSelf.presentationInterfaceState.pinnedMessage {
|
if let pinnedMessage = strongSelf.presentationInterfaceState.pinnedMessage {
|
||||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
|
||||||
|
@ -24,8 +24,9 @@ extension ChatReplyThreadMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChatTopVisibleMessage: Equatable {
|
struct ChatTopVisibleMessageRange: Equatable {
|
||||||
var id: MessageId
|
var lowerBound: MessageId
|
||||||
|
var upperBound: MessageId
|
||||||
var isLast: Bool
|
var isLast: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,7 +564,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
private var loadedMessagesFromCachedDataDisposable: Disposable?
|
private var loadedMessagesFromCachedDataDisposable: Disposable?
|
||||||
|
|
||||||
let isTopReplyThreadMessageShown = ValuePromise<Bool>(false, ignoreRepeated: true)
|
let isTopReplyThreadMessageShown = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||||
let topVisibleMessage = ValuePromise<ChatTopVisibleMessage?>(nil, ignoreRepeated: true)
|
let topVisibleMessageRange = ValuePromise<ChatTopVisibleMessageRange?>(nil, ignoreRepeated: true)
|
||||||
|
|
||||||
private let clientId: Atomic<Int32>
|
private let clientId: Atomic<Int32>
|
||||||
|
|
||||||
@ -1161,7 +1162,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
private func processDisplayedItemRangeChanged(displayedRange: ListViewDisplayedItemRange, transactionState: ChatHistoryTransactionOpaqueState) {
|
private func processDisplayedItemRangeChanged(displayedRange: ListViewDisplayedItemRange, transactionState: ChatHistoryTransactionOpaqueState) {
|
||||||
let historyView = transactionState.historyView
|
let historyView = transactionState.historyView
|
||||||
var isTopReplyThreadMessageShownValue = false
|
var isTopReplyThreadMessageShownValue = false
|
||||||
var topVisibleMessage: ChatTopVisibleMessage?
|
var topVisibleMessageRange: ChatTopVisibleMessageRange?
|
||||||
if let visible = displayedRange.visibleRange {
|
if let visible = displayedRange.visibleRange {
|
||||||
let indexRange = (historyView.filteredEntries.count - 1 - visible.lastIndex, historyView.filteredEntries.count - 1 - visible.firstIndex)
|
let indexRange = (historyView.filteredEntries.count - 1 - visible.lastIndex, historyView.filteredEntries.count - 1 - visible.firstIndex)
|
||||||
if indexRange.0 > indexRange.1 {
|
if indexRange.0 > indexRange.1 {
|
||||||
@ -1259,7 +1260,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.effectiveTopId == message.id {
|
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.effectiveTopId == message.id {
|
||||||
isTopReplyThreadMessageShownValue = true
|
isTopReplyThreadMessageShownValue = true
|
||||||
}
|
}
|
||||||
topVisibleMessage = ChatTopVisibleMessage(id: message.id, isLast: i == historyView.filteredEntries.count - 1)
|
if let topVisibleMessageRangeValue = topVisibleMessageRange {
|
||||||
|
topVisibleMessageRange = ChatTopVisibleMessageRange(lowerBound: topVisibleMessageRangeValue.lowerBound, upperBound: message.id, isLast: i == historyView.filteredEntries.count - 1)
|
||||||
|
} else {
|
||||||
|
topVisibleMessageRange = ChatTopVisibleMessageRange(lowerBound: message.id, upperBound: message.id, isLast: i == historyView.filteredEntries.count - 1)
|
||||||
|
}
|
||||||
case let .MessageGroupEntry(_, messages, _):
|
case let .MessageGroupEntry(_, messages, _):
|
||||||
for (message, _, _, _) in messages {
|
for (message, _, _, _) in messages {
|
||||||
var hasUnconsumedMention = false
|
var hasUnconsumedMention = false
|
||||||
@ -1290,7 +1295,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.effectiveTopId == message.id {
|
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.effectiveTopId == message.id {
|
||||||
isTopReplyThreadMessageShownValue = true
|
isTopReplyThreadMessageShownValue = true
|
||||||
}
|
}
|
||||||
topVisibleMessage = ChatTopVisibleMessage(id: message.id, isLast: i == historyView.filteredEntries.count - 1)
|
if let topVisibleMessageRangeValue = topVisibleMessageRange {
|
||||||
|
topVisibleMessageRange = ChatTopVisibleMessageRange(lowerBound: topVisibleMessageRangeValue.lowerBound, upperBound: message.id, isLast: i == historyView.filteredEntries.count - 1)
|
||||||
|
} else {
|
||||||
|
topVisibleMessageRange = ChatTopVisibleMessageRange(lowerBound: message.id, upperBound: message.id, isLast: i == historyView.filteredEntries.count - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@ -1410,7 +1419,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.isTopReplyThreadMessageShown.set(isTopReplyThreadMessageShownValue)
|
self.isTopReplyThreadMessageShown.set(isTopReplyThreadMessageShownValue)
|
||||||
self.topVisibleMessage.set(topVisibleMessage)
|
self.topVisibleMessageRange.set(topVisibleMessageRange)
|
||||||
|
|
||||||
if let loaded = displayedRange.loadedRange, let firstEntry = historyView.filteredEntries.first, let lastEntry = historyView.filteredEntries.last {
|
if let loaded = displayedRange.loadedRange, let firstEntry = historyView.filteredEntries.first, let lastEntry = historyView.filteredEntries.last {
|
||||||
if loaded.firstIndex < 5 && historyView.originalView.laterId != nil {
|
if loaded.firstIndex < 5 && historyView.originalView.laterId != nil {
|
||||||
|
@ -643,20 +643,37 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if data.canPin, case .peer = chatPresentationInterfaceState.chatLocation {
|
if data.canPin, case .peer = chatPresentationInterfaceState.chatLocation {
|
||||||
if chatPresentationInterfaceState.pinnedMessage?.message.id != messages[0].id {
|
var pinnedSelectedMessageId: MessageId?
|
||||||
|
if let _ = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel {
|
||||||
|
for message in messages {
|
||||||
|
if message.tags.contains(.pinned) {
|
||||||
|
pinnedSelectedMessageId = message.id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for message in messages {
|
||||||
|
if chatPresentationInterfaceState.pinnedMessage?.message.id == message.id {
|
||||||
|
pinnedSelectedMessageId = message.id
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let pinnedSelectedMessageId = pinnedSelectedMessageId {
|
||||||
|
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_Unpin, icon: { theme in
|
||||||
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Unpin"), color: theme.actionSheet.primaryTextColor)
|
||||||
|
}, action: { _, f in
|
||||||
|
interfaceInteraction.unpinMessage(pinnedSelectedMessageId)
|
||||||
|
f(.default)
|
||||||
|
})))
|
||||||
|
} else {
|
||||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_Pin, icon: { theme in
|
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_Pin, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Pin"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Pin"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
interfaceInteraction.pinMessage(messages[0].id)
|
interfaceInteraction.pinMessage(messages[0].id)
|
||||||
f(.dismissWithoutContent)
|
f(.dismissWithoutContent)
|
||||||
})))
|
})))
|
||||||
} else {
|
|
||||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_Unpin, icon: { theme in
|
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Unpin"), color: theme.actionSheet.primaryTextColor)
|
|
||||||
}, action: { _, f in
|
|
||||||
interfaceInteraction.unpinMessage()
|
|
||||||
f(.default)
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ final class ChatPanelInterfaceInteraction {
|
|||||||
let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Bool
|
let sendSticker: (FileMediaReference, ASDisplayNode, CGRect) -> Bool
|
||||||
let unblockPeer: () -> Void
|
let unblockPeer: () -> Void
|
||||||
let pinMessage: (MessageId) -> Void
|
let pinMessage: (MessageId) -> Void
|
||||||
let unpinMessage: () -> Void
|
let unpinMessage: (MessageId) -> Void
|
||||||
let shareAccountContact: () -> Void
|
let shareAccountContact: () -> Void
|
||||||
let reportPeer: () -> Void
|
let reportPeer: () -> Void
|
||||||
let presentPeerContact: () -> Void
|
let presentPeerContact: () -> Void
|
||||||
@ -171,7 +171,7 @@ final class ChatPanelInterfaceInteraction {
|
|||||||
sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool,
|
sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool,
|
||||||
unblockPeer: @escaping () -> Void,
|
unblockPeer: @escaping () -> Void,
|
||||||
pinMessage: @escaping (MessageId) -> Void,
|
pinMessage: @escaping (MessageId) -> Void,
|
||||||
unpinMessage: @escaping () -> Void,
|
unpinMessage: @escaping (MessageId) -> Void,
|
||||||
shareAccountContact: @escaping () -> Void,
|
shareAccountContact: @escaping () -> Void,
|
||||||
reportPeer: @escaping () -> Void,
|
reportPeer: @escaping () -> Void,
|
||||||
presentPeerContact: @escaping () -> Void,
|
presentPeerContact: @escaping () -> Void,
|
||||||
|
@ -98,7 +98,6 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.closeButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: [.touchUpInside])
|
self.closeButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: [.touchUpInside])
|
||||||
self.addSubnode(self.closeButton)
|
|
||||||
|
|
||||||
self.addSubnode(self.clippingContainer)
|
self.addSubnode(self.clippingContainer)
|
||||||
self.clippingContainer.addSubnode(self.contentContainer)
|
self.clippingContainer.addSubnode(self.contentContainer)
|
||||||
@ -107,6 +106,8 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
|
|||||||
self.contentContainer.addSubnode(self.textNode)
|
self.contentContainer.addSubnode(self.textNode)
|
||||||
self.contentContainer.addSubnode(self.imageNode)
|
self.contentContainer.addSubnode(self.imageNode)
|
||||||
|
|
||||||
|
self.addSubnode(self.closeButton)
|
||||||
|
|
||||||
self.tapButton.addTarget(self, action: #selector(self.tapped), forControlEvents: [.touchUpInside])
|
self.tapButton.addTarget(self, action: #selector(self.tapped), forControlEvents: [.touchUpInside])
|
||||||
self.addSubnode(self.tapButton)
|
self.addSubnode(self.tapButton)
|
||||||
|
|
||||||
@ -360,6 +361,8 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc func closePressed() {
|
@objc func closePressed() {
|
||||||
self.interfaceInteraction?.unpinMessage()
|
if let interfaceInteraction = self.interfaceInteraction, let message = self.currentMessage {
|
||||||
|
interfaceInteraction.unpinMessage(message.message.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ final class ChatRecentActionsController: TelegramBaseController {
|
|||||||
return false
|
return false
|
||||||
}, unblockPeer: {
|
}, unblockPeer: {
|
||||||
}, pinMessage: { _ in
|
}, pinMessage: { _ in
|
||||||
}, unpinMessage: {
|
}, unpinMessage: { _ in
|
||||||
}, shareAccountContact: {
|
}, shareAccountContact: {
|
||||||
}, reportPeer: {
|
}, reportPeer: {
|
||||||
}, presentPeerContact: {
|
}, presentPeerContact: {
|
||||||
|
@ -405,7 +405,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
|||||||
return false
|
return false
|
||||||
}, unblockPeer: {
|
}, unblockPeer: {
|
||||||
}, pinMessage: { _ in
|
}, pinMessage: { _ in
|
||||||
}, unpinMessage: {
|
}, unpinMessage: { _ in
|
||||||
}, shareAccountContact: {
|
}, shareAccountContact: {
|
||||||
}, reportPeer: {
|
}, reportPeer: {
|
||||||
}, presentPeerContact: {
|
}, presentPeerContact: {
|
||||||
|
Binary file not shown.
@ -449,12 +449,12 @@ public final class WalletStrings: Equatable {
|
|||||||
public var Wallet_Send_ConfirmationConfirm: String { return self._s[218]! }
|
public var Wallet_Send_ConfirmationConfirm: String { return self._s[218]! }
|
||||||
public var Wallet_Created_ExportErrorTitle: String { return self._s[219]! }
|
public var Wallet_Created_ExportErrorTitle: String { return self._s[219]! }
|
||||||
public var Wallet_Info_TransactionPendingHeader: String { return self._s[220]! }
|
public var Wallet_Info_TransactionPendingHeader: String { return self._s[220]! }
|
||||||
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
|
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
|
||||||
let form = getPluralizationForm(self.lc, value)
|
let form = getPluralizationForm(self.lc, value)
|
||||||
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
||||||
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
|
return String(format: self._ps[0 * 6 + Int(form.rawValue)]!, stringValue)
|
||||||
}
|
}
|
||||||
public func Wallet_Updated_HoursAgo(_ value: Int32) -> String {
|
public func Wallet_Updated_MinutesAgo(_ value: Int32) -> String {
|
||||||
let form = getPluralizationForm(self.lc, value)
|
let form = getPluralizationForm(self.lc, value)
|
||||||
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
let stringValue = walletStringsFormattedNumber(value, self.groupingSeparator)
|
||||||
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)
|
return String(format: self._ps[1 * 6 + Int(form.rawValue)]!, stringValue)
|
||||||
|
2
third-party/webrtc/BUILD
vendored
2
third-party/webrtc/BUILD
vendored
@ -1,4 +1,4 @@
|
|||||||
use_gn_build = False
|
use_gn_build = True
|
||||||
|
|
||||||
webrtc_libs = [
|
webrtc_libs = [
|
||||||
"libwebrtc.a",
|
"libwebrtc.a",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user