mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
7f75219a03
66 changed files with 2170 additions and 1008 deletions
|
|
@ -1,7 +1,7 @@
|
|||
http_file = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_file")
|
||||
|
||||
bazel_dep(name = "bazel_features", version = "1.30.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
||||
bazel_dep(name = "bazel_features", version = "1.33.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.8.1")
|
||||
bazel_dep(name = "platforms", version = "0.0.11")
|
||||
|
||||
bazel_dep(name = "rules_xcodeproj")
|
||||
|
|
|
|||
165
MODULE.bazel.lock
generated
165
MODULE.bazel.lock
generated
|
|
@ -9,7 +9,10 @@
|
|||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/abseil-cpp/20250512.1/source.json": "d725d73707d01bb46ab3ca59ba408b8e9bd336642ca77a2269d4bfb8bbfd413d",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
|
||||
|
|
@ -21,9 +24,9 @@
|
|||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.33.0/source.json": "13617db3930328c2cd2807a0f13d52ca870ac05f96db9668655113265147b2a6",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
|
||||
|
|
@ -36,19 +39,23 @@
|
|||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/bazel_skylib/1.8.1/source.json": "7ebaefba0b03efe59cac88ed5bbc67bcf59a3eff33af937345ede2a38b2d368a",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/nlohmann_json/3.12.0.bcr.1/MODULE.bazel": "a1c8bb07b5b91d971727c635f449d05623ac9608f6fe4f5f04254ea12f08e349",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/nlohmann_json/3.12.0.bcr.1/source.json": "93f82a5ae985eb935c539bfee95e04767187818189241ac956f3ccadbdb8fb02",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29",
|
||||
|
|
@ -64,12 +71,17 @@
|
|||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
|
||||
|
|
@ -78,16 +90,18 @@
|
|||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.1.2/source.json": "53fcb09b5816c83ca60d9d7493faf3bfaf410dfc2f15deb52d6ddd146b8d43f0",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.2.15/MODULE.bazel": "6a0a4a75a57aa6dc888300d848053a58c6b12a29f89d4304e1c41448514ec6e8",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_cc/0.2.15/source.json": "197965c6dcca5c98a9288f93849e2e1c69d622e71b0be8deb524e22d48c88e32",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
|
||||
|
|
@ -102,13 +116,15 @@
|
|||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_java/8.14.0/source.json": "8a88c4ca9e8759da53cddc88123880565c520503321e2566b4e33d0287a3d4bc",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
|
||||
|
|
@ -121,19 +137,23 @@
|
|||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.27.1/MODULE.bazel": "65dc875cc1a06c30d5bbdba7ab021fd9e551a6579e408a3943a61303e2228a53",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/1.3.0/source.json": "25932f917cd279c7baefa6cb1d3fa8750a7a29de522024449b19af6eab51f4a0",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_python/1.6.0/source.json": "e980f654cf66ec4928672f41fc66c4102b5ea54286acf4aecd23256c84211be6",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/rules_shell/0.3.0/source.json": "c55ed591aa5009401ddf80ded9762ac32c358d2517ee7820be981e2de9756cf3",
|
||||
|
|
@ -144,8 +164,8 @@
|
|||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
|
||||
"https://raw.githubusercontent.com/bazelbuild/bazel-central-registry/main/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
|
||||
|
|
@ -220,8 +240,8 @@
|
|||
},
|
||||
"@@rules_python+//python/uv:uv.bzl%uv": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=",
|
||||
"usagesDigest": "vJ5RHUxAnV24M5swNGiAnkdxMx3Hp/iOLmNANTC5Xc8=",
|
||||
"bzlTransitiveDigest": "PmZM/pIkZKEDDL68TohlKJrWPYKL5VwUw3MA7kmm6fk=",
|
||||
"usagesDigest": "p80sy6cYQuWxx5jhV3fOTu+N9EyIUFG9+F7UC/nhXic=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
|
|
@ -246,6 +266,11 @@
|
|||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"rules_python+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
],
|
||||
[
|
||||
"rules_python+",
|
||||
"platforms",
|
||||
|
|
@ -256,7 +281,7 @@
|
|||
},
|
||||
"@@rules_xcodeproj+//xcodeproj:extensions.bzl%internal": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "hsJI1bzu5CX3ZE+NX8jnNWEOh1pNDT650SbTSBnF5jA=",
|
||||
"bzlTransitiveDigest": "+qmLBZzimJ0CYyKoQg6/pbdkTnu/s4e5IisoM+TLM+8=",
|
||||
"usagesDigest": "fvsnMonVwKDYnBfww4bXuYie3WU0d9VSqT2gePSdQco=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
|
|
@ -268,93 +293,21 @@
|
|||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
[
|
||||
"bazel_features+",
|
||||
"bazel_features_globals",
|
||||
"bazel_features++version_extension+bazel_features_globals"
|
||||
],
|
||||
[
|
||||
"bazel_features+",
|
||||
"bazel_features_version",
|
||||
"bazel_features++version_extension+bazel_features_version"
|
||||
],
|
||||
[
|
||||
"rules_xcodeproj+",
|
||||
"bazel_tools",
|
||||
"bazel_tools"
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"@@rules_xcodeproj+//xcodeproj:extensions.bzl%non_module_deps": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "hsJI1bzu5CX3ZE+NX8jnNWEOh1pNDT650SbTSBnF5jA=",
|
||||
"usagesDigest": "jzxYhnOC9BE0dJ0biFLfxWXi/+R19uAAZkJ0p9CY0JI=",
|
||||
"recordedFileInputs": {},
|
||||
"recordedDirentsInputs": {},
|
||||
"envVariables": {},
|
||||
"generatedRepoSpecs": {
|
||||
"rules_xcodeproj_legacy_index_import": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"build_file_content": "load(\"@bazel_skylib//rules:native_binary.bzl\", \"native_binary\")\n\nnative_binary(\n name = \"index_import\",\n src = \"index-import\",\n out = \"index-import\",\n visibility = [\"//visibility:public\"],\n)\n",
|
||||
"canonical_id": "index-import-5.8.0.1",
|
||||
"sha256": "28c1ffa39d99e74ed70623899b207b41f79214c498c603915aef55972a851a15",
|
||||
"url": "https://github.com/MobileNativeFoundation/index-import/releases/download/5.8.0.1/index-import.tar.gz"
|
||||
}
|
||||
},
|
||||
"rules_xcodeproj_index_import": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"build_file_content": "load(\"@bazel_skylib//rules:native_binary.bzl\", \"native_binary\")\n\nnative_binary(\n name = \"index_import\",\n src = \"index-import\",\n out = \"index-import\",\n visibility = [\"//visibility:public\"],\n)\n",
|
||||
"canonical_id": "index-import-6.1.0.1",
|
||||
"sha256": "9a54fc1674af6031125a9884480a1e31e1bcf48b8f558b3e8bcc6b6fcd6e8b61",
|
||||
"url": "https://github.com/MobileNativeFoundation/index-import/releases/download/6.1.0.1/index-import.tar.gz"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_argument_parser": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"build_file_content": "load(\"@build_bazel_rules_swift//swift:swift.bzl\", \"swift_library\")\n\nswift_library(\n name = \"ArgumentParserToolInfo\",\n srcs = glob([\"Sources/ArgumentParserToolInfo/**/*.swift\"]),\n visibility = [\"//visibility:public\"],\n)\n\nswift_library(\n name = \"ArgumentParser\",\n srcs = glob([\"Sources/ArgumentParser/**/*.swift\"]),\n visibility = [\"//visibility:public\"],\n deps = [\":ArgumentParserToolInfo\"],\n)\n",
|
||||
"sha256": "4a10bbef290a2167c5cc340b39f1f7ff6a8cf4e1b5433b68548bf5f1e542e908",
|
||||
"strip_prefix": "swift-argument-parser-1.2.3",
|
||||
"url": "https://github.com/apple/swift-argument-parser/archive/refs/tags/1.2.3.tar.gz"
|
||||
}
|
||||
},
|
||||
"com_github_michaeleisel_jjliso8601dateformatter": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"build_file_content": "objc_library(\n name = \"JJLISO8601DateFormatter\",\n srcs = glob([\"Sources/JJLISO8601DateFormatter/**/*\"]),\n copts = [\n \"-Wno-incompatible-pointer-types\",\n \"-Wno-incompatible-pointer-types-discards-qualifiers\",\n \"-Wno-shorten-64-to-32\",\n \"-Wno-unreachable-code\",\n \"-Wno-unused-function\",\n \"-Wno-unused-variable\",\n ],\n includes = [\"Sources/JJLISO8601DateFormatter/include\"],\n hdrs = glob([\"Sources/JJLISO8601DateFormatter/include/*\"]),\n visibility = [\"//visibility:public\"],\n)\n",
|
||||
"patches": [
|
||||
"@@rules_xcodeproj+//third_party/com_github_michaeleisel_jjliso8601dateformatter:include_fix.patch"
|
||||
],
|
||||
"sha256": "6fe15f251f100f3df057c2802a50765387674fde9c922375683682b5ba37eef0",
|
||||
"strip_prefix": "JJLISO8601DateFormatter-0.1.6",
|
||||
"url": "https://github.com/michaeleisel/JJLISO8601DateFormatter/archive/refs/tags/0.1.6.tar.gz"
|
||||
}
|
||||
},
|
||||
"com_github_michaeleisel_zippyjsoncfamily": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"build_file_content": "objc_library(\n name = \"ZippyJSONCFamily\",\n copts = [\n \"-std=c++17\",\n \"-Wno-unused-function\",\n \"-Wno-reorder-ctor\",\n \"-Wno-return-type-c-linkage\",\n \"-Wno-shorten-64-to-32\",\n \"-Wno-unused-variable\",\n ],\n srcs = glob([\"Sources/ZippyJSONCFamily/**/*\"]),\n includes = [\"Sources/ZippyJSONCFamily/include\"],\n hdrs = glob([\"Sources/ZippyJSONCFamily/include/*\"]),\n visibility = [\"//visibility:public\"],\n)\n",
|
||||
"patches": [
|
||||
"@@rules_xcodeproj+//third_party/com_github_michaeleisel_zippyjsoncfamily:include_fix.patch"
|
||||
],
|
||||
"sha256": "b215927ada8403e1b056d39450c6a7b59122eca4b0c7fc5beb5f0b5fea2acd72",
|
||||
"strip_prefix": "ZippyJSONCFamily-1.2.9",
|
||||
"url": "https://github.com/michaeleisel/ZippyJSONCFamily/archive/refs/tags/1.2.9.tar.gz"
|
||||
}
|
||||
},
|
||||
"com_github_michaeleisel_zippyjson": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"build_file_content": "load(\"@build_bazel_rules_swift//swift:swift.bzl\", \"swift_library\")\n\nswift_library(\n name = \"ZippyJSON\",\n srcs = glob([\"Sources/ZippyJSON/**/*.swift\"]),\n deps = [\n \"@com_github_michaeleisel_jjliso8601dateformatter//:JJLISO8601DateFormatter\",\n \"@com_github_michaeleisel_zippyjsoncfamily//:ZippyJSONCFamily\",\n ],\n visibility = [\"//visibility:public\"],\n)\n",
|
||||
"sha256": "4b256843c9c3686c527e76dde54f8d76b6201c1fd903c07dc2211ab1b250bd04",
|
||||
"strip_prefix": "ZippyJSON-1.2.10",
|
||||
"url": "https://github.com/michaeleisel/ZippyJSON/archive/refs/tags/1.2.10.tar.gz"
|
||||
}
|
||||
},
|
||||
"com_github_apple_swift_collections": {
|
||||
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
|
||||
"attributes": {
|
||||
"build_file_content": "load(\"@build_bazel_rules_swift//swift:swift.bzl\", \"swift_library\")\n\nswift_library(\n name = \"Collections\",\n srcs = glob([\"Sources/Collections/**/*.swift\"]),\n deps = [\n \"@com_github_apple_swift_collections//:DequeModule\",\n ],\n visibility = [\"//visibility:public\"],\n)\n\nswift_library(\n name = \"DequeModule\",\n srcs = glob([\"Sources/DequeModule/**/*.swift\"]),\n visibility = [\"//visibility:public\"],\n)\n\nswift_library(\n name = \"OrderedCollections\",\n srcs = glob([\"Sources/OrderedCollections/**/*.swift\"]),\n visibility = [\"//visibility:public\"],\n)\n",
|
||||
"sha256": "1a2ec8cc6c63c383a9dd4eb975bf83ce3bc7a2ac21a0289a50dae98a576327d6",
|
||||
"strip_prefix": "swift-collections-4cab1c1c417855b90e9cfde40349a43aff99c536",
|
||||
"url": "https://github.com/apple/swift-collections/archive/4cab1c1c417855b90e9cfde40349a43aff99c536.tar.gz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"recordedRepoMappingEntries": [
|
||||
"bazel_features",
|
||||
"bazel_features+"
|
||||
],
|
||||
[
|
||||
"rules_xcodeproj+",
|
||||
"bazel_tools",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@ load("@build_bazel_rules_apple//apple:ios.bzl",
|
|||
"ios_application",
|
||||
"ios_extension",
|
||||
"ios_framework",
|
||||
"ios_ui_test",
|
||||
"ios_ui_test_suite",
|
||||
)
|
||||
|
||||
load(
|
||||
"@build_bazel_rules_apple//apple/testing/default_runner:ios_test_runner.bzl",
|
||||
"ios_test_runner",
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_apple//apple:resources.bzl",
|
||||
|
|
@ -21,6 +28,7 @@ load("@build_bazel_rules_swift//swift:swift.bzl",
|
|||
load(
|
||||
"@rules_xcodeproj//xcodeproj:defs.bzl",
|
||||
"top_level_targets",
|
||||
"top_level_target",
|
||||
"xcodeproj",
|
||||
"xcode_provisioning_profile",
|
||||
)
|
||||
|
|
@ -1759,12 +1767,10 @@ xcodeproj(
|
|||
bazel_path = telegram_bazel_path,
|
||||
project_name = "Telegram",
|
||||
tags = ["manual"],
|
||||
top_level_targets = top_level_targets(
|
||||
labels = [
|
||||
":Telegram",
|
||||
],
|
||||
target_environments = ["device", "simulator"],
|
||||
),
|
||||
top_level_targets = [
|
||||
top_level_target(":Telegram", target_environments = ["device", "simulator"]),
|
||||
":iOSAppUITestSuite",
|
||||
],
|
||||
xcode_configurations = {
|
||||
"Debug": {
|
||||
"//command_line_option:compilation_mode": "dbg",
|
||||
|
|
@ -1776,6 +1782,39 @@ xcodeproj(
|
|||
default_xcode_configuration = "Debug"
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "TestSources",
|
||||
srcs = glob(["Tests/Sources/**/*.swift"]),
|
||||
)
|
||||
|
||||
ios_test_runner(
|
||||
name = "iPhone-17__26.2",
|
||||
device_type = "iPhone 17",
|
||||
os_version = "26.2",
|
||||
)
|
||||
|
||||
|
||||
swift_library(
|
||||
name = "iOSAppUITestSuite.library",
|
||||
testonly = True,
|
||||
srcs = [":TestSources"],
|
||||
module_name = "iOSAppUITestSuite",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
ios_ui_test_suite(
|
||||
name = "iOSAppUITestSuite",
|
||||
bundle_id = "org.telegram.Telegram-iOS-uitests",
|
||||
minimum_os_version = "13.0",
|
||||
runners = [
|
||||
":iPhone-17__26.2",
|
||||
],
|
||||
tags = ["manual"],
|
||||
test_host = "//Telegram",
|
||||
visibility = ["@rules_xcodeproj//xcodeproj:generated"],
|
||||
deps = [":iOSAppUITestSuite.library"],
|
||||
)
|
||||
|
||||
# Temporary targets used to simplify build tests
|
||||
|
||||
ios_application(
|
||||
|
|
|
|||
|
|
@ -15751,3 +15751,6 @@ Error: %8$@";
|
|||
|
||||
"AuthConfirmation.LoginFail.Title" = "Login Failed";
|
||||
"AuthConfirmation.LoginFail.Text" = "Please try logging in to [%@]() again.";
|
||||
|
||||
"Notification.GroupCreatorChangePending" = "%2$@ will become the new main admin in 7 days if %1$@ does not return.";
|
||||
"Notification.GroupCreatorChangeApplied" = "%1$@ has transferred ownership of the group to %2$@.";
|
||||
|
|
|
|||
25
Telegram/Tests/Sources/UITests.swift
Normal file
25
Telegram/Tests/Sources/UITests.swift
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import XCTest
|
||||
|
||||
class UITests: XCTestCase {
|
||||
override func setUpWithError() throws {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
|
||||
// In UI tests it is usually best to stop immediately when a failure occurs.
|
||||
continueAfterFailure = false
|
||||
|
||||
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
|
||||
}
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
func testExample() throws {
|
||||
// UI tests must launch the application that they test.
|
||||
let app = XCUIApplication()
|
||||
app.launch()
|
||||
|
||||
// Use recording to get started writing UI tests.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 4c51f10063687af77eabbbdc035124d798ca3a3f
|
||||
Subproject commit 7967e453d1f54963935a1ae06808e1c64420bfb1
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5b448b48fc2fbd5456d55011811d77610dfd5069
|
||||
Subproject commit 39cc2529241335d20afcb6700c587d064e7a2870
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5c45bcec63147fbdba1a164bdd36c2883fc3169f
|
||||
Subproject commit 2b9261134a123ad83f8b1d2dc7fc69ae83fe7172
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit df2419de2c8d44592dddf213124e6b48bd175768
|
||||
Subproject commit 79f26ec1315531a8459fe95934440cb3ca3c16df
|
||||
|
|
@ -738,6 +738,11 @@ public enum DeviceContactInfoSubject {
|
|||
}
|
||||
|
||||
public enum PeerInfoControllerMode {
|
||||
public enum PeerInfoMediaKind {
|
||||
case photoVideo
|
||||
case file
|
||||
}
|
||||
|
||||
case generic
|
||||
case calls(messages: [Message])
|
||||
case nearbyPeer(distance: Int32)
|
||||
|
|
@ -753,6 +758,7 @@ public enum PeerInfoControllerMode {
|
|||
case monoforum(EnginePeer.Id)
|
||||
case storyAlbum(id: Int64)
|
||||
case giftCollection(id: Int64)
|
||||
case media(kind: PeerInfoMediaKind, messageIndex: EngineMessage.Index)
|
||||
}
|
||||
|
||||
public enum ContactListActionItemInlineIconPosition {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ public final class OpenChatMessageParams {
|
|||
public let playlistLocation: PeerMessagesPlaylistLocation?
|
||||
public let gallerySource: GalleryControllerItemSource?
|
||||
public let centralItemUpdated: ((MessageId) -> Void)?
|
||||
public let navigateToMessageContext: ((EngineMessage) -> Void)?
|
||||
public let getSourceRect: (() -> CGRect?)?
|
||||
public let blockInteraction: Promise<Bool>
|
||||
|
||||
|
|
@ -81,6 +82,7 @@ public final class OpenChatMessageParams {
|
|||
playlistLocation: PeerMessagesPlaylistLocation? = nil,
|
||||
gallerySource: GalleryControllerItemSource? = nil,
|
||||
centralItemUpdated: ((MessageId) -> Void)? = nil,
|
||||
navigateToMessageContext: ((EngineMessage) -> Void)? = nil,
|
||||
getSourceRect: (() -> CGRect?)? = nil
|
||||
) {
|
||||
self.context = context
|
||||
|
|
@ -112,6 +114,7 @@ public final class OpenChatMessageParams {
|
|||
self.playlistLocation = playlistLocation
|
||||
self.gallerySource = gallerySource
|
||||
self.centralItemUpdated = centralItemUpdated
|
||||
self.navigateToMessageContext = navigateToMessageContext
|
||||
self.getSourceRect = getSourceRect
|
||||
self.blockInteraction = Promise()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1152,7 +1152,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
self.hasExpandedCaptionPromise.set(scrollView.contentOffset.y > 1.0)
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> LayoutInfo {
|
||||
self.validLayout = (size, metrics, leftInset, rightInset, bottomInset, contentInset)
|
||||
|
||||
let width = size.width
|
||||
|
|
@ -1177,6 +1177,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
buttonPanelInsets.right += 18.0
|
||||
}
|
||||
|
||||
var needsShadow = false
|
||||
if !self.textNode.isHidden {
|
||||
var textFrame = CGRect()
|
||||
var visibleTextHeight: CGFloat = 0.0
|
||||
|
|
@ -1191,6 +1192,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
var textOffset: CGFloat = 0.0
|
||||
var additionalTextHeight: CGFloat = 0.0
|
||||
if displayCaption {
|
||||
needsShadow = true
|
||||
|
||||
visibleTextHeight = textSize.height
|
||||
if visibleTextHeight > 100.0 {
|
||||
visibleTextHeight = 80.0
|
||||
|
|
@ -1272,8 +1275,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
|
||||
if let scrubberView = self.scrubberView, scrubberView.superview == self.view {
|
||||
panelHeight += 10.0
|
||||
if isLandscape, case .compact = metrics.widthClass {
|
||||
panelHeight += 14.0
|
||||
if isLandscape {
|
||||
panelHeight += 34.0
|
||||
} else {
|
||||
panelHeight += 34.0
|
||||
}
|
||||
|
|
@ -1409,6 +1412,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
}
|
||||
}
|
||||
|
||||
if !centerControlItems.isEmpty && rightControlItems.isEmpty {
|
||||
rightControlItems = centerControlItems
|
||||
centerControlItems = []
|
||||
}
|
||||
|
||||
let buttonPanelSize = self.buttonPanel.update(
|
||||
transition: ComponentTransition(transition),
|
||||
component: AnyComponent(GlassControlPanelComponent(
|
||||
|
|
@ -1482,7 +1490,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
|
||||
self.contentNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))
|
||||
|
||||
return panelHeight
|
||||
return LayoutInfo(height: panelHeight, needsShadow: needsShadow)
|
||||
}
|
||||
|
||||
override func animateIn(transition: ContainedViewLayoutTransition) {
|
||||
|
|
@ -1500,7 +1508,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
scrubberView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||
}
|
||||
transition.animatePositionAdditive(node: self.scrollWrapperNode, offset: CGPoint(x: 0.0, y: self.bounds.height - fromHeight))
|
||||
self.scrollWrapperNode.alpha = 1.0
|
||||
self.scrollNode.alpha = 0.0
|
||||
ComponentTransition(transition).setAlpha(view: self.scrollNode.view, alpha: 1.0)
|
||||
if let buttonPanelView = self.buttonPanel.view {
|
||||
buttonPanelView.alpha = 1.0
|
||||
}
|
||||
|
|
@ -1510,7 +1519,6 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
self.statusNode.alpha = 1.0
|
||||
self.playbackControlButton.alpha = 1.0
|
||||
self.buttonNode?.alpha = 1.0
|
||||
self.scrollWrapperNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
|
||||
}
|
||||
|
||||
override func animateOut(transition: ContainedViewLayoutTransition) {
|
||||
|
|
@ -1527,7 +1535,9 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
scrubberView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15)
|
||||
}
|
||||
transition.updateFrame(node: self.scrollWrapperNode, frame: self.scrollWrapperNode.frame.offsetBy(dx: 0.0, dy: self.bounds.height - toHeight))
|
||||
self.scrollWrapperNode.alpha = 0.0
|
||||
ComponentTransition(transition).setAlpha(view: self.scrollNode.view, alpha: 0.0, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
|
||||
if let buttonPanelView = self.buttonPanel.view {
|
||||
buttonPanelView.alpha = 0.0
|
||||
|
|
@ -1538,9 +1548,6 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||
self.statusNode.alpha = 0.0
|
||||
self.playbackControlButton.alpha = 0.0
|
||||
self.buttonNode?.alpha = 0.0
|
||||
self.scrollWrapperNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
}
|
||||
|
||||
@objc func fullscreenButtonPressed() {
|
||||
|
|
|
|||
|
|
@ -587,6 +587,8 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
private let source: GalleryControllerItemSource
|
||||
private let invertItemOrder: Bool
|
||||
|
||||
private let titleView: GalleryTitleView
|
||||
|
||||
private let streamVideos: Bool
|
||||
|
||||
private let _ready = Promise<Bool>()
|
||||
|
|
@ -617,7 +619,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
private var configuration: GalleryConfiguration?
|
||||
|
||||
private let centralItemTitle = Promise<String>()
|
||||
private let centralItemTitleView = Promise<UIView?>()
|
||||
private let centralItemTitleContent = Promise<GalleryTitleView.Content?>()
|
||||
private let centralItemRightBarButtonItem = Promise<UIBarButtonItem?>()
|
||||
private let centralItemRightBarButtonItems = Promise<[UIBarButtonItem]?>(nil)
|
||||
private let centralItemNavigationStyle = Promise<GalleryItemNodeNavigationStyle>()
|
||||
|
|
@ -645,6 +647,8 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
public var onDidAppear: (() -> Void)?
|
||||
public var useSimpleAnimation: Bool = false
|
||||
|
||||
public var navigateToMessageContext: ((EngineMessage) -> Void)?
|
||||
|
||||
private var initialOrientation: UIInterfaceOrientation?
|
||||
|
||||
public init(context: AccountContext, source: GalleryControllerItemSource, invertItemOrder: Bool = false, streamSingleVideo: Bool = false, fromPlayingVideo: Bool = false, landscape: Bool = false, timecode: Double? = nil, playbackRate: Double? = nil, synchronousLoad: Bool = false, replaceRootController: @escaping (ViewController, Promise<Bool>?) -> Void, baseNavigationController: NavigationController?, actionInteraction: GalleryControllerActionInteraction? = nil, generateStoreAfterDownload: ((Message, TelegramMediaFile) -> (() -> Void)?)? = nil) {
|
||||
|
|
@ -680,6 +684,8 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
openActionOptionsImpl?(action, message)
|
||||
}
|
||||
|
||||
self.titleView = GalleryTitleView(context: context, presentationData: self.presentationData)
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: GalleryController.darkNavigationTheme, strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
|
||||
|
||||
let backItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.donePressed))
|
||||
|
|
@ -915,8 +921,8 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
self?.navigationItem.title = title
|
||||
}))
|
||||
|
||||
self.centralItemAttributesDisposable.add(self.centralItemTitleView.get().start(next: { [weak self] titleView in
|
||||
self?.navigationItem.titleView = titleView
|
||||
self.centralItemAttributesDisposable.add(self.centralItemTitleContent.get().start(next: { [weak self] titleContent in
|
||||
self?.titleView.setContent(content: titleContent)
|
||||
}))
|
||||
|
||||
self.centralItemAttributesDisposable.add(combineLatest(self.centralItemRightBarButtonItem.get(), self.centralItemRightBarButtonItems.get()).start(next: { [weak self] rightBarButtonItem, rightBarButtonItems in
|
||||
|
|
@ -933,7 +939,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
self.centralItemAttributesDisposable.add(self.centralItemFooterContentNode.get().start(next: { [weak self] footerContentNode, overlayContentNode in
|
||||
self?.galleryNode.updatePresentationState({
|
||||
$0.withUpdatedFooterContentNode(footerContentNode).withUpdatedOverlayContentNode(overlayContentNode)
|
||||
}, transition: .immediate)
|
||||
}, transition: .animated(duration: 0.4, curve: .spring))
|
||||
}))
|
||||
|
||||
self.centralItemAttributesDisposable.add(self.centralItemNavigationStyle.get().start(next: { [weak self] style in
|
||||
|
|
@ -1297,6 +1303,10 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
var animatedOutNode = true
|
||||
var animatedOutInterface = false
|
||||
|
||||
if forceAway {
|
||||
self._hiddenMedia.set(.single(nil))
|
||||
}
|
||||
|
||||
let completion = { [weak self] in
|
||||
if animatedOutNode && animatedOutInterface {
|
||||
self?.actionInteraction?.updateCanReadHistory(true)
|
||||
|
|
@ -1375,7 +1385,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
})
|
||||
|
||||
let disableTapNavigation = !(self.context.sharedContext.currentMediaDisplaySettings.with { $0 }.showNextMediaOnTap)
|
||||
self.displayNode = GalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction, disableTapNavigation: disableTapNavigation)
|
||||
self.displayNode = GalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction, titleView: titleView, disableTapNavigation: disableTapNavigation)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.galleryNode.statusBar = self.statusBar
|
||||
|
|
@ -1529,7 +1539,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
|
||||
if let node = strongSelf.galleryNode.pager.centralItemNode() {
|
||||
strongSelf.centralItemTitle.set(node.title())
|
||||
strongSelf.centralItemTitleView.set(node.titleView())
|
||||
strongSelf.centralItemTitleContent.set(node.titleContent())
|
||||
strongSelf.centralItemRightBarButtonItem.set(node.rightBarButtonItem())
|
||||
strongSelf.centralItemRightBarButtonItems.set(node.rightBarButtonItems())
|
||||
strongSelf.centralItemNavigationStyle.set(node.navigationStyle())
|
||||
|
|
@ -1715,7 +1725,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
let entry = self.entries[centralItemNode.index]
|
||||
|
||||
self.centralItemTitle.set(centralItemNode.title())
|
||||
self.centralItemTitleView.set(centralItemNode.titleView())
|
||||
self.centralItemTitleContent.set(centralItemNode.titleContent())
|
||||
self.centralItemRightBarButtonItem.set(centralItemNode.rightBarButtonItem())
|
||||
self.centralItemRightBarButtonItems.set(centralItemNode.rightBarButtonItems())
|
||||
self.centralItemNavigationStyle.set(centralItemNode.navigationStyle())
|
||||
|
|
@ -1768,7 +1778,7 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
if let centralItemNode = self.galleryNode.pager.centralItemNode() {
|
||||
let message = self.entries[centralItemNode.index].entry.message
|
||||
self.centralItemTitle.set(centralItemNode.title())
|
||||
self.centralItemTitleView.set(centralItemNode.titleView())
|
||||
self.centralItemTitleContent.set(centralItemNode.titleContent())
|
||||
self.centralItemRightBarButtonItem.set(centralItemNode.rightBarButtonItem())
|
||||
self.centralItemRightBarButtonItems.set(centralItemNode.rightBarButtonItems())
|
||||
self.centralItemNavigationStyle.set(centralItemNode.navigationStyle())
|
||||
|
|
@ -1913,4 +1923,11 @@ public class GalleryController: ViewController, StandalonePresentableController,
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
func dismissAndNavigateToMessageContext(message: Message) {
|
||||
if let navigateToMessageContext = self.navigateToMessageContext {
|
||||
navigateToMessageContext(EngineMessage(message))
|
||||
}
|
||||
self.dismiss(forceAway: true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,8 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
private let context: AccountContext
|
||||
|
||||
public var statusBar: StatusBar?
|
||||
public var navigationBar: NavigationBar? {
|
||||
didSet {
|
||||
|
||||
}
|
||||
}
|
||||
public var navigationBar: NavigationBar?
|
||||
private let titleView: GalleryTitleView?
|
||||
|
||||
private let headerEdgeEffectView: EdgeEffectView
|
||||
|
||||
|
|
@ -63,12 +60,13 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
}
|
||||
}
|
||||
|
||||
public init(context: AccountContext, controllerInteraction: GalleryControllerInteraction, pageGap: CGFloat = 20.0, disableTapNavigation: Bool = false) {
|
||||
public init(context: AccountContext, controllerInteraction: GalleryControllerInteraction, titleView: GalleryTitleView?, pageGap: CGFloat = 20.0, disableTapNavigation: Bool = false) {
|
||||
self.context = context
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.backgroundColor = UIColor.black
|
||||
self.scrollView = UIScrollView()
|
||||
self.scrollView.delaysContentTouches = false
|
||||
self.titleView = titleView
|
||||
|
||||
if #available(iOSApplicationExtension 11.0, iOS 11.0, *) {
|
||||
self.scrollView.contentInsetAdjustmentBehavior = .never
|
||||
|
|
@ -277,15 +275,19 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.pager.isInteractingUpdated = { [weak self] isInteracting in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.titleView?.updateIsInteracting(isInteracting: isInteracting)
|
||||
}
|
||||
}
|
||||
|
||||
override open func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
if #available(iOSApplicationExtension 11.0, iOS 11.0, *), !self.isLayerBacked {
|
||||
self.view.accessibilityIgnoresInvertColors = true
|
||||
}
|
||||
|
||||
self.view.accessibilityIgnoresInvertColors = true
|
||||
self.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
}
|
||||
|
||||
|
|
@ -312,9 +314,24 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
if self.footerNode.supernode == nil {
|
||||
self.addSubnode(self.footerNode)
|
||||
}
|
||||
if self.headerEdgeEffectView.superview == nil {
|
||||
self.view.insertSubview(self.headerEdgeEffectView, belowSubview: navigationBar.view)
|
||||
if let titleView = self.titleView {
|
||||
if titleView.superview == nil {
|
||||
self.view.addSubview(titleView)
|
||||
}
|
||||
|
||||
let titleHeight: CGFloat = navigationBarHeight - (layout.statusBarHeight ?? 0.0) - 3.0
|
||||
let titleSize = CGSize(width: layout.size.width - (layout.safeInsets.left + 44.0 + 16.0 + 8.0) * 2.0, height: titleHeight)
|
||||
var titleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - titleSize.width) * 0.5), y: (layout.statusBarHeight ?? 0.0) + 4.0), size: titleSize)
|
||||
if self.areControlsHidden {
|
||||
titleFrame.origin.y -= navigationBarHeight
|
||||
}
|
||||
let _ = titleView.updateLayout(availableSize: titleFrame.size, transition: .immediate)
|
||||
transition.updateFrame(view: titleView, frame: titleFrame)
|
||||
}
|
||||
|
||||
/*if self.headerEdgeEffectView.superview == nil {
|
||||
self.view.insertSubview(self.headerEdgeEffectView, belowSubview: navigationBar.view)
|
||||
}*/
|
||||
}
|
||||
|
||||
var thumbnailPanelHeight: CGFloat = 0.0
|
||||
|
|
@ -370,7 +387,7 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
self.statusBar?.updateAlpha(alpha, transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
})
|
||||
self.footerNode.setVisibilityAlpha(alpha, animated: animated)
|
||||
self.updateThumbnailContainerNodeAlpha(.immediate)
|
||||
self.updateThumbnailContainerNodeAlpha(animated ? .animated(duration: 0.3, curve: .easeInOut) : .immediate)
|
||||
|
||||
if let (navigationBarHeight, layout) = self.containerLayout {
|
||||
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .animated(duration: 0.4, curve: .spring))
|
||||
|
|
@ -404,6 +421,7 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
self.navigationBar?.alpha = 0.0
|
||||
self.footerNode.alpha = 0.0
|
||||
self.headerEdgeEffectView.alpha = 0.0
|
||||
self.titleView?.alpha = 0.0
|
||||
self.currentThumbnailContainerNode?.alpha = 0.0
|
||||
|
||||
self.backgroundNode.layer.animate(from: backgroundColor.withAlphaComponent(0.0).cgColor, to: backgroundColor.cgColor, keyPath: "backgroundColor", timingFunction: CAMediaTimingFunctionName.linear.rawValue, duration: 0.15)
|
||||
|
|
@ -420,7 +438,10 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
self.footerNode.alpha = 1.0
|
||||
self.footerNode.animateIn(transition: .animated(duration: 0.15, curve: .linear))
|
||||
|
||||
ComponentTransition.easeInOut(duration: 0.15).setAlpha(view: self.headerEdgeEffectView, alpha: 1.0)
|
||||
ComponentTransition.easeInOut(duration: 0.15).animateView {
|
||||
self.headerEdgeEffectView.alpha = 1.0
|
||||
self.titleView?.alpha = 1.0
|
||||
}
|
||||
}
|
||||
|
||||
if animateContent {
|
||||
|
|
@ -461,7 +482,10 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
interfaceAnimationCompleted = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
ComponentTransition.easeInOut(duration: 0.1).setAlpha(view: self.headerEdgeEffectView, alpha: 0.0)
|
||||
ComponentTransition.easeInOut(duration: 0.1).animateView {
|
||||
self.headerEdgeEffectView.alpha = 0.0
|
||||
self.titleView?.alpha = 0.0
|
||||
}
|
||||
|
||||
self.footerNode.animateOut(transition: .animated(duration: 0.1, curve: .easeInOut))
|
||||
|
||||
|
|
@ -522,6 +546,8 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
if let overlayNode = self.overlayNode {
|
||||
overlayNode.alpha = transition
|
||||
}
|
||||
self.headerEdgeEffectView.alpha = transition
|
||||
self.titleView?.alpha = transition
|
||||
}
|
||||
|
||||
open func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,16 @@ public final class GalleryControllerInteraction {
|
|||
}
|
||||
|
||||
open class GalleryFooterContentNode: ASDisplayNode {
|
||||
public struct LayoutInfo {
|
||||
let height: CGFloat
|
||||
let needsShadow: Bool
|
||||
|
||||
public init(height: CGFloat, needsShadow: Bool) {
|
||||
self.height = height
|
||||
self.needsShadow = needsShadow
|
||||
}
|
||||
}
|
||||
|
||||
public var requestLayout: ((ContainedViewLayoutTransition) -> Void)?
|
||||
public var controllerInteraction: GalleryControllerInteraction?
|
||||
|
||||
|
|
@ -37,8 +47,8 @@ open class GalleryFooterContentNode: ASDisplayNode {
|
|||
self.alpha = alpha
|
||||
}
|
||||
|
||||
open func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
return 0.0
|
||||
open func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> LayoutInfo {
|
||||
return LayoutInfo(height: 0.0, needsShadow: false)
|
||||
}
|
||||
|
||||
open func animateIn(transition: ContainedViewLayoutTransition) {
|
||||
|
|
|
|||
|
|
@ -107,32 +107,38 @@ public final class GalleryFooterNode: ASDisplayNode {
|
|||
if layout.size.width > layout.size.height {
|
||||
effectiveThumbnailPanelHeight = 0.0
|
||||
}
|
||||
var backgroundHeight: CGFloat = 0.0
|
||||
var backgroundLayoutInfo: GalleryFooterContentNode.LayoutInfo?
|
||||
let verticalOffset: CGFloat = isHidden ? (layout.size.width > layout.size.height ? 44.0 : (effectiveThumbnailPanelHeight > 0.0 ? 106.0 : 54.0)) : 0.0
|
||||
let backgroundFrame: CGRect
|
||||
var edgeEffectTransition = ComponentTransition(transition)
|
||||
if let footerContentNode = self.currentFooterContentNode {
|
||||
backgroundHeight = footerContentNode.updateLayout(size: layout.size, metrics: layout.metrics, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, contentInset: effectiveThumbnailPanelHeight, transition: transition)
|
||||
transition.updateFrame(node: footerContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundHeight + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundHeight)))
|
||||
var footerTransition = transition
|
||||
if footerContentNode.bounds.isEmpty {
|
||||
footerTransition = .immediate
|
||||
}
|
||||
let backgroundLayoutInfoValue = footerContentNode.updateLayout(size: layout.size, metrics: layout.metrics, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: cleanInsets.bottom, contentInset: effectiveThumbnailPanelHeight, transition: footerTransition)
|
||||
backgroundLayoutInfo = backgroundLayoutInfoValue
|
||||
|
||||
footerTransition.updateFrame(node: footerContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundLayoutInfoValue.height + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundLayoutInfoValue.height)))
|
||||
if let dismissedCurrentFooterContentNode = dismissedCurrentFooterContentNode {
|
||||
let contentTransition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)
|
||||
footerContentNode.animateIn(fromHeight: dismissedCurrentFooterContentNode.bounds.height, previousContentNode: dismissedCurrentFooterContentNode, transition: contentTransition)
|
||||
dismissedCurrentFooterContentNode.animateOut(toHeight: backgroundHeight, nextContentNode: footerContentNode, transition: contentTransition, completion: { [weak self, weak dismissedCurrentFooterContentNode] in
|
||||
dismissedCurrentFooterContentNode.animateOut(toHeight: backgroundLayoutInfoValue.height, nextContentNode: footerContentNode, transition: contentTransition, completion: { [weak self, weak dismissedCurrentFooterContentNode] in
|
||||
if let strongSelf = self, let dismissedCurrentFooterContentNode = dismissedCurrentFooterContentNode, dismissedCurrentFooterContentNode !== strongSelf.currentFooterContentNode {
|
||||
dismissedCurrentFooterContentNode.removeFromSupernode()
|
||||
}
|
||||
})
|
||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundHeight + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundHeight))
|
||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundLayoutInfoValue.height + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundLayoutInfoValue.height))
|
||||
edgeEffectTransition = ComponentTransition(contentTransition)
|
||||
} else {
|
||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundHeight + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundHeight))
|
||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundLayoutInfoValue.height + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundLayoutInfoValue.height))
|
||||
}
|
||||
} else {
|
||||
if let dismissedCurrentFooterContentNode = dismissedCurrentFooterContentNode {
|
||||
dismissedCurrentFooterContentNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - backgroundHeight + verticalOffset), size: CGSize(width: layout.size.width, height: backgroundHeight))
|
||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height + verticalOffset), size: CGSize(width: layout.size.width, height: 0.0))
|
||||
}
|
||||
|
||||
self.contentsFrame = backgroundFrame
|
||||
|
|
@ -144,9 +150,18 @@ public final class GalleryFooterNode: ASDisplayNode {
|
|||
edgeEffectFrame.size.height += edgeEffectOffset
|
||||
edgeEffectTransition.setFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
|
||||
self.edgeEffectView.update(content: .black, alpha: 0.65, rect: edgeEffectFrame, edge: .bottom, edgeSize: min(edgeEffectHeight, edgeEffectFrame.height), transition: edgeEffectTransition)
|
||||
if let backgroundLayoutInfo, backgroundLayoutInfo.needsShadow {
|
||||
ComponentTransition(transition).setAlpha(view: self.edgeEffectView, alpha: 1.0)
|
||||
} else {
|
||||
ComponentTransition(transition).setAlpha(view: self.edgeEffectView, alpha: 0.0)
|
||||
}
|
||||
|
||||
let contentTransition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)
|
||||
if let overlayContentNode = self.currentOverlayContentNode {
|
||||
var backgroundHeight: CGFloat = 0.0
|
||||
if let backgroundLayoutInfo {
|
||||
backgroundHeight = backgroundLayoutInfo.height
|
||||
}
|
||||
let insets = UIEdgeInsets(top: navigationBarHeight, left: layout.safeInsets.left, bottom: isHidden ? layout.intrinsicInsets.bottom : backgroundHeight, right: layout.safeInsets.right)
|
||||
overlayContentNode.updateLayout(size: layout.size, metrics: layout.metrics, insets: insets, isHidden: isHidden, transition: transition)
|
||||
transition.updateFrame(node: overlayContentNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ open class GalleryItemNode: ASDisplayNode {
|
|||
return .single("")
|
||||
}
|
||||
|
||||
open func titleView() -> Signal<UIView?, NoError> {
|
||||
open func titleContent() -> Signal<GalleryTitleView.Content?, NoError> {
|
||||
return .single(nil)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ public final class GalleryPagerNode: ASDisplayNode, ASScrollViewDelegate, ASGest
|
|||
public var completeCustomDismiss: (Bool) -> Void = { _ in }
|
||||
public var baseNavigationController: () -> NavigationController? = { return nil }
|
||||
public var galleryController: () -> ViewController? = { return nil }
|
||||
public var isInteractingUpdated: ((Bool) -> Void)?
|
||||
|
||||
private var pagingEnabled = true
|
||||
public var pagingEnabledPromise = Promise<Bool>(true)
|
||||
|
|
@ -771,15 +772,18 @@ public final class GalleryPagerNode: ASDisplayNode, ASScrollViewDelegate, ASGest
|
|||
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
|
||||
if !decelerate {
|
||||
self.ensureItemsLoaded(force: false)
|
||||
self.isInteractingUpdated?(false)
|
||||
}
|
||||
}
|
||||
|
||||
public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||
self.ensureItemsLoaded(force: true)
|
||||
self.isInteractingUpdated?(true)
|
||||
}
|
||||
|
||||
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
|
||||
self.ensureItemsLoaded(force: true)
|
||||
self.isInteractingUpdated?(false)
|
||||
}
|
||||
|
||||
private func shouldLoadItems(force: Bool) -> Bool {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import AsyncDisplayKit
|
|||
import Display
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import AccountContext
|
||||
import TelegramPresentationData
|
||||
import TelegramStringFormatting
|
||||
import GlassBackgroundComponent
|
||||
|
|
@ -14,7 +15,37 @@ import MultilineTextComponent
|
|||
private let titleFont = Font.semibold(17.0)
|
||||
private let dateFont = Font.regular(12.0)
|
||||
|
||||
final class GalleryTitleView: UIView, NavigationBarTitleView {
|
||||
public final class GalleryTitleView: UIView, NavigationBarTitleView {
|
||||
public final class Content: Equatable {
|
||||
let message: EngineMessage
|
||||
let title: String?
|
||||
let action: (() -> Void)?
|
||||
|
||||
public init(message: EngineMessage, title: String?, action: (() -> Void)?) {
|
||||
self.message = message
|
||||
self.title = title
|
||||
self.action = action
|
||||
}
|
||||
|
||||
public static func ==(lhs: Content, rhs: Content) -> Bool {
|
||||
if lhs.message != rhs.message {
|
||||
return false
|
||||
}
|
||||
if lhs.title != rhs.title {
|
||||
return false
|
||||
}
|
||||
if (lhs.action == nil) != (rhs.action == nil) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private let presentationData: PresentationData
|
||||
|
||||
private let backgroundContainer: GlassBackgroundContainerView
|
||||
private let backgroundView: GlassBackgroundView
|
||||
private let authorNameNode: ASTextNode
|
||||
private let dateNode: ASTextNode
|
||||
|
||||
|
|
@ -22,16 +53,28 @@ final class GalleryTitleView: UIView, NavigationBarTitleView {
|
|||
private let titleBackground: GlassBackgroundView
|
||||
private let title = ComponentView<Empty>()
|
||||
|
||||
private var content: Content?
|
||||
private var titleString: String?
|
||||
|
||||
var requestUpdate: ((ContainedViewLayoutTransition) -> Void)?
|
||||
public var requestUpdate: ((ContainedViewLayoutTransition) -> Void)?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
private var interactionTimer: Foundation.Timer?
|
||||
|
||||
public init(context: AccountContext, presentationData: PresentationData) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.backgroundContainer = GlassBackgroundContainerView()
|
||||
self.backgroundView = GlassBackgroundView()
|
||||
self.backgroundContainer.contentView.addSubview(self.backgroundView)
|
||||
|
||||
self.authorNameNode = ASTextNode()
|
||||
self.authorNameNode.isUserInteractionEnabled = false
|
||||
self.authorNameNode.displaysAsynchronously = false
|
||||
self.authorNameNode.maximumNumberOfLines = 1
|
||||
|
||||
self.dateNode = ASTextNode()
|
||||
self.dateNode.isUserInteractionEnabled = false
|
||||
self.dateNode.displaysAsynchronously = false
|
||||
self.dateNode.maximumNumberOfLines = 1
|
||||
|
||||
|
|
@ -40,45 +83,90 @@ final class GalleryTitleView: UIView, NavigationBarTitleView {
|
|||
|
||||
self.titleBackgroundContainer.contentView.addSubview(self.titleBackground)
|
||||
|
||||
super.init(frame: frame)
|
||||
super.init(frame: CGRect())
|
||||
|
||||
self.addSubnode(self.authorNameNode)
|
||||
self.addSubnode(self.dateNode)
|
||||
self.addSubview(self.backgroundContainer)
|
||||
|
||||
self.backgroundView.contentView.addSubview(self.authorNameNode.view)
|
||||
self.backgroundView.contentView.addSubview(self.dateNode.view)
|
||||
|
||||
self.backgroundContainer.isHidden = true
|
||||
|
||||
self.addSubview(self.titleBackgroundContainer)
|
||||
self.titleBackgroundContainer.alpha = 0.0
|
||||
|
||||
self.backgroundView.contentView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.onTapGesture(_:))))
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
required public init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func setMessage(_ message: Message, presentationData: PresentationData, accountPeerId: PeerId, title: String?) {
|
||||
let authorNameText = stringForFullAuthorName(message: EngineMessage(message), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, accountPeerId: accountPeerId).first ?? ""
|
||||
let dateText = humanReadableStringForTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, timestamp: message.timestamp).string
|
||||
|
||||
self.authorNameNode.attributedText = NSAttributedString(string: authorNameText, font: titleFont, textColor: .white)
|
||||
self.dateNode.attributedText = NSAttributedString(string: dateText, font: dateFont, textColor: UIColor(white: 1.0, alpha: 0.5))
|
||||
|
||||
self.titleString = title
|
||||
deinit {
|
||||
self.interactionTimer?.invalidate()
|
||||
}
|
||||
|
||||
func updateLayout(availableSize: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
@objc private func onTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
self.content?.action?()
|
||||
}
|
||||
}
|
||||
|
||||
public func setContent(content: Content?) {
|
||||
self.content = content
|
||||
|
||||
self.backgroundContainer.isHidden = self.content == nil
|
||||
|
||||
if let content {
|
||||
let authorNameText = stringForFullAuthorName(message: content.message, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder, accountPeerId: self.context.account.peerId).first ?? ""
|
||||
let dateText = humanReadableStringForTimestamp(strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, timestamp: content.message.timestamp).string
|
||||
|
||||
self.authorNameNode.attributedText = NSAttributedString(string: authorNameText, font: titleFont, textColor: .white)
|
||||
self.dateNode.attributedText = NSAttributedString(string: dateText, font: dateFont, textColor: UIColor(white: 1.0, alpha: 0.5))
|
||||
}
|
||||
|
||||
self.titleString = content?.title
|
||||
|
||||
if !self.bounds.isEmpty {
|
||||
let _ = self.updateLayout(availableSize: self.bounds.size, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
public func updateLayout(availableSize: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
let size = availableSize
|
||||
|
||||
let leftInset: CGFloat = 0.0
|
||||
let rightInset: CGFloat = 0.0
|
||||
let leftInset: CGFloat = 8.0 + 14.0
|
||||
let rightInset: CGFloat = 8.0 + 14.0
|
||||
|
||||
let authorNameSize = self.authorNameNode.measure(CGSize(width: max(1.0, size.width - 8.0 * 2.0 - leftInset - rightInset), height: CGFloat.greatestFiniteMagnitude))
|
||||
let dateSize = self.dateNode.measure(CGSize(width: max(1.0, size.width - 8.0 * 2.0), height: CGFloat.greatestFiniteMagnitude))
|
||||
|
||||
var backgroundSize = CGSize(width: 0.0, height: 44.0)
|
||||
|
||||
if authorNameSize.height.isZero {
|
||||
self.dateNode.frame = CGRect(origin: CGPoint(x: floor((size.width - dateSize.width) / 2.0), y: floor((size.height - dateSize.height) / 2.0)), size: dateSize)
|
||||
backgroundSize.width = dateSize.width
|
||||
} else {
|
||||
backgroundSize.width = max(authorNameSize.width, dateSize.width)
|
||||
}
|
||||
backgroundSize.width = max(150.0, backgroundSize.width)
|
||||
backgroundSize.width += 14.0 * 2.0
|
||||
|
||||
if authorNameSize.height.isZero {
|
||||
self.dateNode.frame = CGRect(origin: CGPoint(x: floor((backgroundSize.width - dateSize.width) / 2.0), y: floor((backgroundSize.height - dateSize.height) / 2.0)), size: dateSize)
|
||||
} else {
|
||||
let labelsSpacing: CGFloat = 2.0
|
||||
self.authorNameNode.frame = CGRect(origin: CGPoint(x: floor((size.width - authorNameSize.width) / 2.0), y: floor((size.height - dateSize.height - authorNameSize.height - labelsSpacing) / 2.0)), size: authorNameSize)
|
||||
self.dateNode.frame = CGRect(origin: CGPoint(x: floor((size.width - dateSize.width) / 2.0), y: floor((size.height - dateSize.height - authorNameSize.height - labelsSpacing) / 2.0) + authorNameSize.height + labelsSpacing), size: dateSize)
|
||||
self.authorNameNode.frame = CGRect(origin: CGPoint(x: floor((backgroundSize.width - authorNameSize.width) / 2.0), y: floor((backgroundSize.height - dateSize.height - authorNameSize.height - labelsSpacing) / 2.0)), size: authorNameSize)
|
||||
self.dateNode.frame = CGRect(origin: CGPoint(x: floor((backgroundSize.width - dateSize.width) / 2.0), y: floor((backgroundSize.height - dateSize.height - authorNameSize.height - labelsSpacing) / 2.0) + authorNameSize.height + labelsSpacing), size: dateSize)
|
||||
}
|
||||
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: floor((size.width - backgroundSize.width) * 0.5), y: floor((size.height - backgroundSize.height) * 0.5)), size: backgroundSize)
|
||||
|
||||
self.backgroundContainer.update(size: backgroundFrame.size, isDark: true, transition: ComponentTransition(transition))
|
||||
ComponentTransition(transition).setFrame(view: self.backgroundContainer, frame: backgroundFrame)
|
||||
|
||||
ComponentTransition(transition).setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||
self.backgroundView.update(size: backgroundSize, cornerRadius: backgroundSize.height * 0.5, isDark: true, tintColor: .init(kind: .panel), isInteractive: self.content?.action != nil, transition: ComponentTransition(transition))
|
||||
|
||||
let titleSize = self.title.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextComponent(
|
||||
|
|
@ -112,7 +200,27 @@ final class GalleryTitleView: UIView, NavigationBarTitleView {
|
|||
return availableSize
|
||||
}
|
||||
|
||||
func animateLayoutTransition() {
|
||||
|
||||
public func animateLayoutTransition() {
|
||||
}
|
||||
|
||||
public func updateIsInteracting(isInteracting: Bool) {
|
||||
if isInteracting {
|
||||
self.interactionTimer?.invalidate()
|
||||
self.interactionTimer = nil
|
||||
|
||||
ComponentTransition.easeInOut(duration: 0.2).animateView {
|
||||
self.titleBackgroundContainer.alpha = 1.0
|
||||
}
|
||||
} else {
|
||||
self.interactionTimer?.invalidate()
|
||||
self.interactionTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false, block: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
ComponentTransition.easeInOut(duration: 0.2).animateView {
|
||||
self.titleBackgroundContainer.alpha = 0.0
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ class ChatImageGalleryItem: GalleryItem {
|
|||
func node(synchronous: Bool) -> GalleryItemNode {
|
||||
let node = ChatImageGalleryItemNode(context: self.context, presentationData: self.presentationData, performAction: self.performAction, openActionOptions: self.openActionOptions, present: self.present)
|
||||
|
||||
node.setMessage(self.message, displayInfo: !self.displayInfoOnTop, translateToLanguage: self.translateToLanguage, peerIsCopyProtected: self.peerIsCopyProtected, isSecret: self.isSecret)
|
||||
node.setMessage(self.message, displayInfo: !self.displayInfoOnTop, translateToLanguage: self.translateToLanguage, peerIsCopyProtected: self.peerIsCopyProtected, isSecret: self.isSecret, location: self.location)
|
||||
for media in self.message.media {
|
||||
if let paidContent = media as? TelegramMediaPaidContent {
|
||||
let mediaIndex = self.mediaIndex ?? 0
|
||||
|
|
@ -175,26 +175,12 @@ class ChatImageGalleryItem: GalleryItem {
|
|||
}
|
||||
}
|
||||
|
||||
var title: String?
|
||||
if let _ = message.adAttribute {
|
||||
title = self.presentationData.strings.Gallery_Ad
|
||||
} else if let location = self.location {
|
||||
title = self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string
|
||||
}
|
||||
|
||||
node.titleContentView?.setMessage(self.message, presentationData: self.presentationData, accountPeerId: self.context.account.peerId, title: title)
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? ChatImageGalleryItemNode, let location = self.location {
|
||||
let title = self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string
|
||||
|
||||
if self.displayInfoOnTop {
|
||||
node.titleContentView?.setMessage(self.message, presentationData: self.presentationData, accountPeerId: self.context.account.peerId, title: title)
|
||||
}
|
||||
node.setMessage(self.message, displayInfo: !self.displayInfoOnTop, translateToLanguage: self.translateToLanguage, peerIsCopyProtected: self.peerIsCopyProtected, isSecret: self.isSecret)
|
||||
node.setMessage(self.message, displayInfo: !self.displayInfoOnTop, translateToLanguage: self.translateToLanguage, peerIsCopyProtected: self.peerIsCopyProtected, isSecret: self.isSecret, location: location)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,12 +237,11 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
private var tilingNode: TilingNode?
|
||||
fileprivate let _ready = Promise<Void>()
|
||||
fileprivate let _title = Promise<String>()
|
||||
fileprivate let _titleView = Promise<UIView?>()
|
||||
fileprivate let _titleContent = Promise<GalleryTitleView.Content?>(nil)
|
||||
fileprivate let _rightBarButtonItems = Promise<[UIBarButtonItem]?>(nil)
|
||||
private let statusNodeContainer: HighlightableButtonNode
|
||||
private let statusNode: RadialStatusNode
|
||||
private let footerContentNode: ChatItemGalleryFooterContentNode
|
||||
fileprivate var titleContentView: GalleryTitleView?
|
||||
|
||||
private var contextAndMedia: (AccountContext, AnyMediaReference)?
|
||||
|
||||
|
|
@ -320,9 +305,6 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
|
||||
self.statusNodeContainer.isUserInteractionEnabled = false
|
||||
|
||||
self.titleContentView = GalleryTitleView(frame: CGRect())
|
||||
self._titleView.set(.single(self.titleContentView))
|
||||
|
||||
self.recognitionOverlayContentNode.action = { [weak self] active in
|
||||
if let strongSelf = self {
|
||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
||||
|
|
@ -459,7 +441,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
}))
|
||||
}
|
||||
|
||||
fileprivate func setMessage(_ message: Message, displayInfo: Bool, translateToLanguage: String?, peerIsCopyProtected: Bool, isSecret: Bool) {
|
||||
fileprivate func setMessage(_ message: Message, displayInfo: Bool, translateToLanguage: String?, peerIsCopyProtected: Bool, isSecret: Bool, location: MessageHistoryEntryLocation?) {
|
||||
self.message = message
|
||||
self.displayInfo = displayInfo
|
||||
self.translateToLanguage = translateToLanguage
|
||||
|
|
@ -467,6 +449,23 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
self.isSecret = isSecret
|
||||
self.imageNode.captureProtected = message.id.peerId.namespace == Namespaces.Peer.SecretChat || message.isCopyProtected() || peerIsCopyProtected || isSecret || message.paidContent != nil
|
||||
self.updateFooter(animated: false)
|
||||
|
||||
var title: String?
|
||||
if let _ = message.adAttribute {
|
||||
title = self.presentationData.strings.Gallery_Ad
|
||||
} else if let location {
|
||||
title = self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string
|
||||
}
|
||||
|
||||
self._titleContent.set(.single(GalleryTitleView.Content(message: EngineMessage(message), title: title, action: message.adAttribute == nil ? { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard let controller = self.galleryController() as? GalleryController else {
|
||||
return
|
||||
}
|
||||
controller.dismissAndNavigateToMessageContext(message: message)
|
||||
} : nil)))
|
||||
}
|
||||
|
||||
private func updateFooter(animated: Bool) {
|
||||
|
|
@ -1133,8 +1132,8 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
return self._title.get()
|
||||
}
|
||||
|
||||
override func titleView() -> Signal<UIView?, NoError> {
|
||||
return self._titleView.get()
|
||||
override func titleContent() -> Signal<GalleryTitleView.Content?, NoError> {
|
||||
return self._titleContent.get()
|
||||
}
|
||||
|
||||
override func rightBarButtonItems() -> Signal<[UIBarButtonItem]?, NoError> {
|
||||
|
|
|
|||
|
|
@ -101,34 +101,14 @@ public class UniversalVideoGalleryItem: GalleryItem {
|
|||
public func node(synchronous: Bool) -> GalleryItemNode {
|
||||
let node = UniversalVideoGalleryItemNode(context: self.context, presentationData: self.presentationData, performAction: self.performAction, openActionOptions: self.openActionOptions, present: self.present)
|
||||
|
||||
var title: String?
|
||||
if let indexData = self.indexData {
|
||||
title = self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").string
|
||||
} else if case let .message(message, _) = self.contentInfo, let _ = message.adAttribute {
|
||||
title = self.presentationData.strings.Gallery_Ad
|
||||
}
|
||||
|
||||
node.setupItem(self)
|
||||
|
||||
if case let .message(message, _) = self.contentInfo {
|
||||
node.titleContentView?.setMessage(message, presentationData: self.presentationData, accountPeerId: self.context.account.peerId, title: title)
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
public func updateNode(node: GalleryItemNode, synchronous: Bool) {
|
||||
if let node = node as? UniversalVideoGalleryItemNode {
|
||||
var title: String?
|
||||
if let indexData = self.indexData {
|
||||
title = self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").string
|
||||
}
|
||||
|
||||
node.setupItem(self)
|
||||
|
||||
if self.displayInfoOnTop, case let .message(message, _) = self.contentInfo {
|
||||
node.titleContentView?.setMessage(message, presentationData: self.presentationData, accountPeerId: self.context.account.peerId, title: title)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -881,7 +861,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
|
||||
fileprivate let _ready = Promise<Void>()
|
||||
fileprivate let _title = Promise<String>()
|
||||
fileprivate let _titleView = Promise<UIView?>()
|
||||
fileprivate let _titleContent = Promise<GalleryTitleView.Content?>(nil)
|
||||
fileprivate let _rightBarButtonItems = Promise<[UIBarButtonItem]?>()
|
||||
|
||||
fileprivate var titleContentView: GalleryTitleView?
|
||||
|
|
@ -1136,9 +1116,6 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
self.openMoreMenu(sourceView: self.moreBarButton.referenceNode.view, gesture: gesture, adMessage: adMessage, isSettings: false)
|
||||
}
|
||||
|
||||
self.titleContentView = GalleryTitleView(frame: CGRect())
|
||||
self._titleView.set(.single(self.titleContentView))
|
||||
|
||||
let shouldHideControlsSignal: Signal<Void, NoError> = combineLatest(self.isPlayingPromise.get(), self.isInteractingPromise.get(), self.controlsVisiblePromise.get(), self.isShowingContextMenuPromise.get(), self.isShowingSettingsMenuPromise.get(), self.isShowingAdMenuPromise.get(), self.hasExpandedCaptionPromise.get())
|
||||
|> mapToSignal { isPlaying, isInteracting, controlsVisible, isShowingContextMenu, isShowingSettingsMenu, isShowingAdMenu, hasExpandedCaptionPromise -> Signal<Void, NoError> in
|
||||
if isShowingContextMenu || isShowingSettingsMenu || isShowingAdMenu || hasExpandedCaptionPromise {
|
||||
|
|
@ -1962,6 +1939,25 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
}
|
||||
self.overlayContentNode.setMessage(context: item.context, message: message)
|
||||
}
|
||||
|
||||
var title: String?
|
||||
if let indexData = item.indexData {
|
||||
title = self.presentationData.strings.Items_NOfM("\(indexData.position + 1)", "\(indexData.totalCount)").string
|
||||
} else if case let .message(message, _) = item.contentInfo, let _ = message.adAttribute {
|
||||
title = self.presentationData.strings.Gallery_Ad
|
||||
}
|
||||
|
||||
if case let .message(message, _) = item.contentInfo {
|
||||
self._titleContent.set(.single(GalleryTitleView.Content(message: EngineMessage(message), title: title, action: message.adAttribute == nil ? { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard let controller = self.galleryController() as? GalleryController else {
|
||||
return
|
||||
}
|
||||
controller.dismissAndNavigateToMessageContext(message: message)
|
||||
} : nil)))
|
||||
}
|
||||
}
|
||||
|
||||
override func controlsVisibilityUpdated(isVisible: Bool) {
|
||||
|
|
@ -2759,8 +2755,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||
return self._title.get()
|
||||
}
|
||||
|
||||
override func titleView() -> Signal<UIView?, NoError> {
|
||||
return self._titleView.get()
|
||||
override func titleContent() -> Signal<GalleryTitleView.Content?, NoError> {
|
||||
return self._titleContent.get()
|
||||
}
|
||||
|
||||
override func rightBarButtonItems() -> Signal<[UIBarButtonItem]?, NoError> {
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ public final class SecretMediaPreviewController: ViewController {
|
|||
}, currentItemNode: { [weak self] in
|
||||
return self?.controllerNode.pager.centralItemNode()
|
||||
})
|
||||
self.displayNode = SecretMediaPreviewControllerNode(context: self.context, controllerInteraction: controllerInteraction)
|
||||
self.displayNode = SecretMediaPreviewControllerNode(context: self.context, controllerInteraction: controllerInteraction, titleView: nil)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.controllerNode.statusPressed = { [weak self] _ in
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ final class SecretMediaPreviewFooterContentNode: GalleryFooterContentNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> LayoutInfo {
|
||||
let width = size.width
|
||||
let panelHeight: CGFloat = 44.0 + bottomInset
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ final class SecretMediaPreviewFooterContentNode: GalleryFooterContentNode {
|
|||
let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((width - textSize.width) / 2.0), y: floor((44.0 - textSize.height) / 2.0)), size: textSize))
|
||||
|
||||
return panelHeight
|
||||
return LayoutInfo(height: panelHeight, needsShadow: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable
|
|||
}, currentItemNode: { [weak self] in
|
||||
return self?.galleryNode.pager.centralItemNode()
|
||||
})
|
||||
self.displayNode = GalleryControllerNode(context: self.context,controllerInteraction: controllerInteraction)
|
||||
self.displayNode = GalleryControllerNode(context: self.context,controllerInteraction: controllerInteraction, titleView: nil)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.galleryNode.statusBar = self.statusBar
|
||||
|
|
@ -417,7 +417,7 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable
|
|||
|
||||
if let node = strongSelf.galleryNode.pager.centralItemNode() {
|
||||
strongSelf.centralItemTitle.set(node.title())
|
||||
strongSelf.centralItemTitleView.set(node.titleView())
|
||||
//strongSelf.centralItemTitleView.set(node.titleView())
|
||||
strongSelf.centralItemRightBarButtonItem.set(node.rightBarButtonItem())
|
||||
strongSelf.centralItemRightBarButtonItems.set(node.rightBarButtonItems())
|
||||
strongSelf.centralItemNavigationStyle.set(node.navigationStyle())
|
||||
|
|
@ -448,7 +448,7 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable
|
|||
|
||||
if let centralItemNode = self.galleryNode.pager.centralItemNode(), let presentationArguments = self.presentationArguments as? InstantPageGalleryControllerPresentationArguments {
|
||||
self.centralItemTitle.set(centralItemNode.title())
|
||||
self.centralItemTitleView.set(centralItemNode.titleView())
|
||||
//self.centralItemTitleView.set(centralItemNode.titleView())
|
||||
self.centralItemRightBarButtonItem.set(centralItemNode.rightBarButtonItem())
|
||||
self.centralItemRightBarButtonItems.set(centralItemNode.rightBarButtonItems())
|
||||
self.centralItemNavigationStyle.set(centralItemNode.navigationStyle())
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ final class InstantPageGalleryFooterContentNode: GalleryFooterContentNode {
|
|||
self.actionButton.isHidden = shareMedia == nil
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> LayoutInfo {
|
||||
let width = size.width
|
||||
var panelHeight: CGFloat = 44.0 + bottomInset + contentInset
|
||||
if !self.textNode.isHidden {
|
||||
|
|
@ -126,7 +126,7 @@ final class InstantPageGalleryFooterContentNode: GalleryFooterContentNode {
|
|||
|
||||
self.actionButton.frame = CGRect(origin: CGPoint(x: leftInset, y: panelHeight - bottomInset - 44.0), size: CGSize(width: 44.0, height: 44.0))
|
||||
|
||||
return panelHeight
|
||||
return LayoutInfo(height: panelHeight, needsShadow: false)
|
||||
}
|
||||
|
||||
override func animateIn(fromHeight: CGFloat, previousContentNode: GalleryFooterContentNode, transition: ContainedViewLayoutTransition) {
|
||||
|
|
|
|||
|
|
@ -477,6 +477,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem {
|
|||
let header: ListViewItemHeader?
|
||||
let shimmering: ItemListPeerItemShimmering?
|
||||
let displayDecorations: Bool
|
||||
let displayBackground: Bool
|
||||
let disableInteractiveTransitionIfNecessary: Bool
|
||||
let storyStats: PeerStoryStats?
|
||||
let openStories: ((UIView) -> Void)?
|
||||
|
|
@ -520,6 +521,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem {
|
|||
header: ListViewItemHeader? = nil,
|
||||
shimmering: ItemListPeerItemShimmering? = nil,
|
||||
displayDecorations: Bool = true,
|
||||
displayBackground: Bool = true,
|
||||
disableInteractiveTransitionIfNecessary: Bool = false,
|
||||
storyStats: PeerStoryStats? = nil,
|
||||
openStories: ((UIView) -> Void)? = nil
|
||||
|
|
@ -562,6 +564,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem {
|
|||
self.header = header
|
||||
self.shimmering = shimmering
|
||||
self.displayDecorations = displayDecorations
|
||||
self.displayBackground = displayBackground
|
||||
self.disableInteractiveTransitionIfNecessary = disableInteractiveTransitionIfNecessary
|
||||
self.storyStats = storyStats
|
||||
self.openStories = openStories
|
||||
|
|
@ -606,6 +609,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem {
|
|||
header: ListViewItemHeader? = nil,
|
||||
shimmering: ItemListPeerItemShimmering? = nil,
|
||||
displayDecorations: Bool = true,
|
||||
displayBackground: Bool = true,
|
||||
disableInteractiveTransitionIfNecessary: Bool = false,
|
||||
storyStats: PeerStoryStats? = nil,
|
||||
openStories: ((UIView) -> Void)? = nil
|
||||
|
|
@ -648,6 +652,7 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem {
|
|||
self.header = header
|
||||
self.shimmering = shimmering
|
||||
self.displayDecorations = displayDecorations
|
||||
self.displayBackground = displayBackground
|
||||
self.disableInteractiveTransitionIfNecessary = disableInteractiveTransitionIfNecessary
|
||||
self.storyStats = storyStats
|
||||
self.openStories = openStories
|
||||
|
|
@ -1337,6 +1342,8 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
|||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
|
||||
strongSelf.backgroundNode.isHidden = !item.displayBackground
|
||||
|
||||
let revealOffset = strongSelf.revealOffset
|
||||
|
||||
let transition: ContainedViewLayoutTransition
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ class SecureIdDocumentGalleryController: ViewController, StandalonePresentableCo
|
|||
}, currentItemNode: { [weak self] in
|
||||
return self?.galleryNode.pager.centralItemNode()
|
||||
})
|
||||
self.displayNode = GalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction)
|
||||
self.displayNode = GalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction, titleView: nil)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.galleryNode.statusBar = self.statusBar
|
||||
|
|
@ -218,7 +218,7 @@ class SecureIdDocumentGalleryController: ViewController, StandalonePresentableCo
|
|||
|
||||
if let node = strongSelf.galleryNode.pager.centralItemNode() {
|
||||
strongSelf.centralItemTitle.set(node.title())
|
||||
strongSelf.centralItemTitleView.set(node.titleView())
|
||||
//strongSelf.centralItemTitleView.set(node.titleView())
|
||||
strongSelf.centralItemNavigationStyle.set(node.navigationStyle())
|
||||
strongSelf.centralItemFooterContentNode.set(node.footerContent())
|
||||
}
|
||||
|
|
@ -237,7 +237,7 @@ class SecureIdDocumentGalleryController: ViewController, StandalonePresentableCo
|
|||
|
||||
if let centralItemNode = self.galleryNode.pager.centralItemNode(), let presentationArguments = self.presentationArguments as? SecureIdDocumentGalleryControllerPresentationArguments {
|
||||
self.centralItemTitle.set(centralItemNode.title())
|
||||
self.centralItemTitleView.set(centralItemNode.titleView())
|
||||
//self.centralItemTitleView.set(centralItemNode.titleView())
|
||||
self.centralItemNavigationStyle.set(centralItemNode.navigationStyle())
|
||||
self.centralItemFooterContentNode.set(centralItemNode.footerContent())
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ final class SecureIdDocumentGalleryFooterContentNode: GalleryFooterContentNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> LayoutInfo {
|
||||
let width = size.width
|
||||
var panelHeight: CGFloat = 44.0 + bottomInset
|
||||
panelHeight += contentInset
|
||||
|
|
@ -117,7 +117,7 @@ final class SecureIdDocumentGalleryFooterContentNode: GalleryFooterContentNode {
|
|||
self.dateNode.frame = CGRect(origin: CGPoint(x: floor((width - dateSize.width) / 2.0), y: panelHeight - bottomInset - 44.0 + floor((44.0 - dateSize.height - authorNameSize.height - labelsSpacing) / 2.0) + authorNameSize.height + labelsSpacing), size: dateSize)
|
||||
}
|
||||
|
||||
return panelHeight
|
||||
return LayoutInfo(height: panelHeight, needsShadow: false)
|
||||
}
|
||||
|
||||
override func animateIn(fromHeight: CGFloat, previousContentNode: GalleryFooterContentNode, transition: ContainedViewLayoutTransition) {
|
||||
|
|
|
|||
|
|
@ -412,7 +412,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||
private var centralEntryIndex: Int?
|
||||
|
||||
private let centralItemTitle = Promise<String>()
|
||||
private let centralItemTitleView = Promise<UIView?>()
|
||||
private let centralItemTitleContent = Promise<GalleryTitleView.Content?>()
|
||||
private let centralItemRightBarButtonItems = Promise<[UIBarButtonItem]?>(nil)
|
||||
private let centralItemNavigationStyle = Promise<GalleryItemNodeNavigationStyle>()
|
||||
private let centralItemFooterContentNode = Promise<(GalleryFooterContentNode?, GalleryOverlayContentNode?)>()
|
||||
|
|
@ -427,6 +427,8 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||
return self._hiddenMedia.get()
|
||||
}
|
||||
|
||||
private let titleView: GalleryTitleView
|
||||
|
||||
private let replaceRootController: (ViewController, Promise<Bool>?) -> Void
|
||||
|
||||
private let editDisposable = MetaDisposable ()
|
||||
|
|
@ -441,11 +443,15 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||
|
||||
self.centralEntryIndex = centralEntryIndex
|
||||
|
||||
self.titleView = GalleryTitleView(context: context, presentationData: self.presentationData)
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: GalleryController.darkNavigationTheme, strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
|
||||
|
||||
let backItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.donePressed))
|
||||
self.navigationItem.leftBarButtonItem = backItem
|
||||
|
||||
self.navigationItem.titleView = self.titleView
|
||||
|
||||
self.statusBar.statusBarStyle = .White
|
||||
|
||||
let remoteEntriesSignal: Signal<[AvatarGalleryEntry], NoError>
|
||||
|
|
@ -546,8 +552,8 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||
}
|
||||
}))
|
||||
|
||||
self.centralItemAttributesDisposable.add(self.centralItemTitleView.get().start(next: { [weak self] titleView in
|
||||
self?.navigationItem.titleView = titleView
|
||||
self.centralItemAttributesDisposable.add(self.centralItemTitleContent.get().start(next: { [weak self] titleContent in
|
||||
self?.titleView.setContent(content: titleContent)
|
||||
}))
|
||||
|
||||
self.centralItemAttributesDisposable.add(self.centralItemRightBarButtonItems.get().start(next: { [weak self] rightBarButtonItems in
|
||||
|
|
@ -633,7 +639,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||
}, currentItemNode: { [weak self] in
|
||||
return self?.galleryNode.pager.centralItemNode()
|
||||
})
|
||||
self.displayNode = GalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction)
|
||||
self.displayNode = GalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction, titleView: self.titleView)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.galleryNode.pager.updateOnReplacement = true
|
||||
|
|
@ -680,7 +686,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||
|
||||
if let node = strongSelf.galleryNode.pager.centralItemNode() {
|
||||
strongSelf.centralItemTitle.set(node.title())
|
||||
strongSelf.centralItemTitleView.set(node.titleView())
|
||||
strongSelf.centralItemTitleContent.set(node.titleContent())
|
||||
strongSelf.centralItemRightBarButtonItems.set(node.rightBarButtonItems())
|
||||
strongSelf.centralItemNavigationStyle.set(node.navigationStyle())
|
||||
strongSelf.centralItemFooterContentNode.set(node.footerContent())
|
||||
|
|
@ -709,7 +715,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
|||
|
||||
if let centralItemNode = self.galleryNode.pager.centralItemNode(), let presentationArguments = self.presentationArguments as? AvatarGalleryControllerPresentationArguments {
|
||||
self.centralItemTitle.set(centralItemNode.title())
|
||||
self.centralItemTitleView.set(centralItemNode.titleView())
|
||||
self.centralItemTitleContent.set(centralItemNode.titleContent())
|
||||
self.centralItemRightBarButtonItems.set(centralItemNode.rightBarButtonItems())
|
||||
self.centralItemNavigationStyle.set(centralItemNode.navigationStyle())
|
||||
self.centralItemFooterContentNode.set(centralItemNode.footerContent())
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> LayoutInfo {
|
||||
self.validLayout = (size, metrics, leftInset, rightInset, bottomInset, contentInset)
|
||||
|
||||
let width = size.width
|
||||
|
|
@ -203,7 +203,7 @@ final class AvatarGalleryItemFooterContentNode: GalleryFooterContentNode {
|
|||
let mainButtonSize = self.setMainButton.measure(constrainedSize)
|
||||
self.setMainButton.frame = CGRect(origin: CGPoint(x: floor((width - mainButtonSize.width) / 2.0), y: panelHeight - bottomInset - 44.0 + floor((44.0 - mainButtonSize.height) / 2.0)), size: mainButtonSize)
|
||||
|
||||
return panelHeight
|
||||
return LayoutInfo(height: panelHeight, needsShadow: false)
|
||||
}
|
||||
|
||||
override func animateIn(fromHeight: CGFloat, previousContentNode: GalleryFooterContentNode, transition: ContainedViewLayoutTransition) {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ private enum ArchiveSettingsControllerEntry: ItemListNodeEntry {
|
|||
case .unmutedHeader:
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.ArchiveSettings_UnmutedChatsHeader, sectionId: self.section)
|
||||
case let .unmutedValue(value):
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: presentationData.strings.ArchiveSettings_KeepArchived, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: presentationData.strings.ArchiveSettings_KeepArchived, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.updateUnmuted(value)
|
||||
})
|
||||
case .unmutedFooter:
|
||||
|
|
@ -97,7 +97,7 @@ private enum ArchiveSettingsControllerEntry: ItemListNodeEntry {
|
|||
case .foldersHeader:
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.ArchiveSettings_FolderChatsHeader, sectionId: self.section)
|
||||
case let .foldersValue(value):
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: presentationData.strings.ArchiveSettings_KeepArchived, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: presentationData.strings.ArchiveSettings_KeepArchived, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.updateFolders(value)
|
||||
})
|
||||
case .foldersFooter:
|
||||
|
|
@ -105,7 +105,7 @@ private enum ArchiveSettingsControllerEntry: ItemListNodeEntry {
|
|||
case .unknownHeader:
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.ArchiveSettings_UnknownChatsHeader, sectionId: self.section)
|
||||
case let .unknownValue(isOn, isLocked):
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: presentationData.strings.ArchiveSettings_AutomaticallyArchive, value: isOn, enableInteractiveChanges: !isLocked, enabled: true, displayLocked: isLocked, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: presentationData.strings.ArchiveSettings_AutomaticallyArchive, value: isOn, enableInteractiveChanges: !isLocked, enabled: true, displayLocked: isLocked, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.updateUnknown(value)
|
||||
}, activatedWhileDisabled: {
|
||||
arguments.updateUnknown(nil)
|
||||
|
|
|
|||
|
|
@ -911,15 +911,15 @@ public final class SparseItemGrid: ASDisplayNode {
|
|||
return self.scrollView.convert(layer.frame, to: self.view)
|
||||
}
|
||||
|
||||
func scrollToItem(at index: Int) {
|
||||
func scrollToItem(at index: Int, force: Bool) {
|
||||
guard let layout = self.layout, let _ = self.items else {
|
||||
return
|
||||
}
|
||||
if layout.containerLayout.lockScrollingAtTop {
|
||||
if !force && layout.containerLayout.lockScrollingAtTop {
|
||||
return
|
||||
}
|
||||
let itemFrame = layout.frame(at: index)
|
||||
var contentOffset = itemFrame.minY
|
||||
var contentOffset = floor(itemFrame.midY - self.scrollView.bounds.height / 2.0)
|
||||
if contentOffset > self.scrollView.contentSize.height - self.scrollView.bounds.height {
|
||||
contentOffset = self.scrollView.contentSize.height - self.scrollView.bounds.height
|
||||
}
|
||||
|
|
@ -2234,11 +2234,11 @@ public final class SparseItemGrid: ASDisplayNode {
|
|||
return currentViewport.visualItem(at: index)
|
||||
}
|
||||
|
||||
public func scrollToItem(at index: Int) {
|
||||
public func scrollToItem(at index: Int, force: Bool = false) {
|
||||
guard let currentViewport = self.currentViewport else {
|
||||
return
|
||||
}
|
||||
currentViewport.scrollToItem(at: index)
|
||||
currentViewport.scrollToItem(at: index, force: force)
|
||||
}
|
||||
|
||||
public func ensureItemVisible(index: Int, anyAmount: Bool = true) {
|
||||
|
|
|
|||
|
|
@ -538,25 +538,26 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[736157604] = { return Api.JSONValue.parse_jsonNumber($0) }
|
||||
dict[-1715350371] = { return Api.JSONValue.parse_jsonObject($0) }
|
||||
dict[-1222740358] = { return Api.JSONValue.parse_jsonString($0) }
|
||||
dict[-916050683] = { return Api.KeyboardButton.parse_inputKeyboardButtonRequestPeer($0) }
|
||||
dict[-802258988] = { return Api.KeyboardButton.parse_inputKeyboardButtonUrlAuth($0) }
|
||||
dict[-376962181] = { return Api.KeyboardButton.parse_inputKeyboardButtonUserProfile($0) }
|
||||
dict[-1560655744] = { return Api.KeyboardButton.parse_keyboardButton($0) }
|
||||
dict[-1344716869] = { return Api.KeyboardButton.parse_keyboardButtonBuy($0) }
|
||||
dict[901503851] = { return Api.KeyboardButton.parse_keyboardButtonCallback($0) }
|
||||
dict[1976723854] = { return Api.KeyboardButton.parse_keyboardButtonCopy($0) }
|
||||
dict[1358175439] = { return Api.KeyboardButton.parse_keyboardButtonGame($0) }
|
||||
dict[-59151553] = { return Api.KeyboardButton.parse_keyboardButtonRequestGeoLocation($0) }
|
||||
dict[1406648280] = { return Api.KeyboardButton.parse_keyboardButtonRequestPeer($0) }
|
||||
dict[-1318425559] = { return Api.KeyboardButton.parse_keyboardButtonRequestPhone($0) }
|
||||
dict[-1144565411] = { return Api.KeyboardButton.parse_keyboardButtonRequestPoll($0) }
|
||||
dict[-1598009252] = { return Api.KeyboardButton.parse_keyboardButtonSimpleWebView($0) }
|
||||
dict[-1816527947] = { return Api.KeyboardButton.parse_keyboardButtonSwitchInline($0) }
|
||||
dict[629866245] = { return Api.KeyboardButton.parse_keyboardButtonUrl($0) }
|
||||
dict[280464681] = { return Api.KeyboardButton.parse_keyboardButtonUrlAuth($0) }
|
||||
dict[814112961] = { return Api.KeyboardButton.parse_keyboardButtonUserProfile($0) }
|
||||
dict[326529584] = { return Api.KeyboardButton.parse_keyboardButtonWebView($0) }
|
||||
dict[45580630] = { return Api.KeyboardButton.parse_inputKeyboardButtonRequestPeer($0) }
|
||||
dict[1744911986] = { return Api.KeyboardButton.parse_inputKeyboardButtonUrlAuth($0) }
|
||||
dict[2103314375] = { return Api.KeyboardButton.parse_inputKeyboardButtonUserProfile($0) }
|
||||
dict[2098662655] = { return Api.KeyboardButton.parse_keyboardButton($0) }
|
||||
dict[1067792645] = { return Api.KeyboardButton.parse_keyboardButtonBuy($0) }
|
||||
dict[-433338016] = { return Api.KeyboardButton.parse_keyboardButtonCallback($0) }
|
||||
dict[-1127960816] = { return Api.KeyboardButton.parse_keyboardButtonCopy($0) }
|
||||
dict[-1983540999] = { return Api.KeyboardButton.parse_keyboardButtonGame($0) }
|
||||
dict[-1438582451] = { return Api.KeyboardButton.parse_keyboardButtonRequestGeoLocation($0) }
|
||||
dict[1527715317] = { return Api.KeyboardButton.parse_keyboardButtonRequestPeer($0) }
|
||||
dict[1098841487] = { return Api.KeyboardButton.parse_keyboardButtonRequestPhone($0) }
|
||||
dict[2047989634] = { return Api.KeyboardButton.parse_keyboardButtonRequestPoll($0) }
|
||||
dict[-514047120] = { return Api.KeyboardButton.parse_keyboardButtonSimpleWebView($0) }
|
||||
dict[-1726768644] = { return Api.KeyboardButton.parse_keyboardButtonSwitchInline($0) }
|
||||
dict[-670292500] = { return Api.KeyboardButton.parse_keyboardButtonUrl($0) }
|
||||
dict[-183499015] = { return Api.KeyboardButton.parse_keyboardButtonUrlAuth($0) }
|
||||
dict[-1057137399] = { return Api.KeyboardButton.parse_keyboardButtonUserProfile($0) }
|
||||
dict[-398020192] = { return Api.KeyboardButton.parse_keyboardButtonWebView($0) }
|
||||
dict[2002815875] = { return Api.KeyboardButtonRow.parse_keyboardButtonRow($0) }
|
||||
dict[1339896880] = { return Api.KeyboardButtonStyle.parse_keyboardButtonStyle($0) }
|
||||
dict[-886477832] = { return Api.LabeledPrice.parse_labeledPrice($0) }
|
||||
dict[-209337866] = { return Api.LangPackDifference.parse_langPackDifference($0) }
|
||||
dict[-288727837] = { return Api.LangPackLanguage.parse_langPackLanguage($0) }
|
||||
|
|
@ -579,6 +580,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[2055212554] = { return Api.Message.parse_messageService($0) }
|
||||
dict[-872240531] = { return Api.MessageAction.parse_messageActionBoostApply($0) }
|
||||
dict[-988359047] = { return Api.MessageAction.parse_messageActionBotAllowed($0) }
|
||||
dict[-511160261] = { return Api.MessageAction.parse_messageActionChangeCreator($0) }
|
||||
dict[-1781355374] = { return Api.MessageAction.parse_messageActionChannelCreate($0) }
|
||||
dict[-365344535] = { return Api.MessageAction.parse_messageActionChannelMigrateFrom($0) }
|
||||
dict[365886720] = { return Api.MessageAction.parse_messageActionChatAddUser($0) }
|
||||
|
|
@ -606,6 +608,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-1281329567] = { return Api.MessageAction.parse_messageActionGroupCallScheduled($0) }
|
||||
dict[-1615153660] = { return Api.MessageAction.parse_messageActionHistoryClear($0) }
|
||||
dict[1345295095] = { return Api.MessageAction.parse_messageActionInviteToGroupCall($0) }
|
||||
dict[-1333866363] = { return Api.MessageAction.parse_messageActionNewCreatorPending($0) }
|
||||
dict[-2068281992] = { return Api.MessageAction.parse_messageActionPaidMessagesPrice($0) }
|
||||
dict[-1407246387] = { return Api.MessageAction.parse_messageActionPaidMessagesRefunded($0) }
|
||||
dict[1102307842] = { return Api.MessageAction.parse_messageActionPaymentRefunded($0) }
|
||||
|
|
@ -2016,6 +2019,8 @@ public extension Api {
|
|||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.KeyboardButtonRow:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.KeyboardButtonStyle:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.LabeledPrice:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.LangPackDifference:
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -45,6 +45,57 @@ public extension Api {
|
|||
}
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum KeyboardButtonStyle: TypeConstructorDescription {
|
||||
public class Cons_keyboardButtonStyle {
|
||||
public var flags: Int32
|
||||
public var icon: Int64?
|
||||
public init(flags: Int32, icon: Int64?) {
|
||||
self.flags = flags
|
||||
self.icon = icon
|
||||
}
|
||||
}
|
||||
case keyboardButtonStyle(Cons_keyboardButtonStyle)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .keyboardButtonStyle(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(1339896880)
|
||||
}
|
||||
serializeInt32(_data.flags, buffer: buffer, boxed: false)
|
||||
if Int(_data.flags) & Int(1 << 3) != 0 {
|
||||
serializeInt64(_data.icon!, buffer: buffer, boxed: false)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .keyboardButtonStyle(let _data):
|
||||
return ("keyboardButtonStyle", [("flags", _data.flags as Any), ("icon", _data.icon as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_keyboardButtonStyle(_ reader: BufferReader) -> KeyboardButtonStyle? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int64?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {
|
||||
_2 = reader.readInt64()
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 3) == 0) || _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.KeyboardButtonStyle.keyboardButtonStyle(Cons_keyboardButtonStyle(flags: _1!, icon: _2))
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum LabeledPrice: TypeConstructorDescription {
|
||||
public class Cons_labeledPrice {
|
||||
|
|
@ -1513,6 +1564,12 @@ public extension Api {
|
|||
self.app = app
|
||||
}
|
||||
}
|
||||
public class Cons_messageActionChangeCreator {
|
||||
public var newCreatorId: Int64
|
||||
public init(newCreatorId: Int64) {
|
||||
self.newCreatorId = newCreatorId
|
||||
}
|
||||
}
|
||||
public class Cons_messageActionChannelCreate {
|
||||
public var title: String
|
||||
public init(title: String) {
|
||||
|
|
@ -1725,6 +1782,12 @@ public extension Api {
|
|||
self.users = users
|
||||
}
|
||||
}
|
||||
public class Cons_messageActionNewCreatorPending {
|
||||
public var newCreatorId: Int64
|
||||
public init(newCreatorId: Int64) {
|
||||
self.newCreatorId = newCreatorId
|
||||
}
|
||||
}
|
||||
public class Cons_messageActionPaidMessagesPrice {
|
||||
public var flags: Int32
|
||||
public var stars: Int64
|
||||
|
|
@ -2043,6 +2106,7 @@ public extension Api {
|
|||
}
|
||||
case messageActionBoostApply(Cons_messageActionBoostApply)
|
||||
case messageActionBotAllowed(Cons_messageActionBotAllowed)
|
||||
case messageActionChangeCreator(Cons_messageActionChangeCreator)
|
||||
case messageActionChannelCreate(Cons_messageActionChannelCreate)
|
||||
case messageActionChannelMigrateFrom(Cons_messageActionChannelMigrateFrom)
|
||||
case messageActionChatAddUser(Cons_messageActionChatAddUser)
|
||||
|
|
@ -2070,6 +2134,7 @@ public extension Api {
|
|||
case messageActionGroupCallScheduled(Cons_messageActionGroupCallScheduled)
|
||||
case messageActionHistoryClear
|
||||
case messageActionInviteToGroupCall(Cons_messageActionInviteToGroupCall)
|
||||
case messageActionNewCreatorPending(Cons_messageActionNewCreatorPending)
|
||||
case messageActionPaidMessagesPrice(Cons_messageActionPaidMessagesPrice)
|
||||
case messageActionPaidMessagesRefunded(Cons_messageActionPaidMessagesRefunded)
|
||||
case messageActionPaymentRefunded(Cons_messageActionPaymentRefunded)
|
||||
|
|
@ -2122,6 +2187,12 @@ public extension Api {
|
|||
_data.app!.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .messageActionChangeCreator(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(-511160261)
|
||||
}
|
||||
serializeInt64(_data.newCreatorId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .messageActionChannelCreate(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1781355374)
|
||||
|
|
@ -2369,6 +2440,12 @@ public extension Api {
|
|||
serializeInt64(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
break
|
||||
case .messageActionNewCreatorPending(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1333866363)
|
||||
}
|
||||
serializeInt64(_data.newCreatorId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .messageActionPaidMessagesPrice(let _data):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2068281992)
|
||||
|
|
@ -2737,6 +2814,8 @@ public extension Api {
|
|||
return ("messageActionBoostApply", [("boosts", _data.boosts as Any)])
|
||||
case .messageActionBotAllowed(let _data):
|
||||
return ("messageActionBotAllowed", [("flags", _data.flags as Any), ("domain", _data.domain as Any), ("app", _data.app as Any)])
|
||||
case .messageActionChangeCreator(let _data):
|
||||
return ("messageActionChangeCreator", [("newCreatorId", _data.newCreatorId as Any)])
|
||||
case .messageActionChannelCreate(let _data):
|
||||
return ("messageActionChannelCreate", [("title", _data.title as Any)])
|
||||
case .messageActionChannelMigrateFrom(let _data):
|
||||
|
|
@ -2791,6 +2870,8 @@ public extension Api {
|
|||
return ("messageActionHistoryClear", [])
|
||||
case .messageActionInviteToGroupCall(let _data):
|
||||
return ("messageActionInviteToGroupCall", [("call", _data.call as Any), ("users", _data.users as Any)])
|
||||
case .messageActionNewCreatorPending(let _data):
|
||||
return ("messageActionNewCreatorPending", [("newCreatorId", _data.newCreatorId as Any)])
|
||||
case .messageActionPaidMessagesPrice(let _data):
|
||||
return ("messageActionPaidMessagesPrice", [("flags", _data.flags as Any), ("stars", _data.stars as Any)])
|
||||
case .messageActionPaidMessagesRefunded(let _data):
|
||||
|
|
@ -2890,6 +2971,17 @@ public extension Api {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_messageActionChangeCreator(_ reader: BufferReader) -> MessageAction? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.MessageAction.messageActionChangeCreator(Cons_messageActionChangeCreator(newCreatorId: _1!))
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_messageActionChannelCreate(_ reader: BufferReader) -> MessageAction? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
|
|
@ -3327,6 +3419,17 @@ public extension Api {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_messageActionNewCreatorPending(_ reader: BufferReader) -> MessageAction? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.MessageAction.messageActionNewCreatorPending(Cons_messageActionNewCreatorPending(newCreatorId: _1!))
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_messageActionPaidMessagesPrice(_ reader: BufferReader) -> MessageAction? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
|
|
|
|||
|
|
@ -26,141 +26,141 @@ extension ReplyMarkupButtonAction.PeerTypes {
|
|||
extension ReplyMarkupButton {
|
||||
init(apiButton: Api.KeyboardButton) {
|
||||
switch apiButton {
|
||||
case let .keyboardButton(keyboardButtonData):
|
||||
let text = keyboardButtonData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .text)
|
||||
case let .keyboardButtonCallback(keyboardButtonCallbackData):
|
||||
let (flags, text, data) = (keyboardButtonCallbackData.flags, keyboardButtonCallbackData.text, keyboardButtonCallbackData.data)
|
||||
let memory = malloc(data.size)!
|
||||
memcpy(memory, data.data, data.size)
|
||||
let dataBuffer = MemoryBuffer(memory: memory, capacity: data.size, length: data.size, freeWhenDone: true)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .callback(requiresPassword: (flags & (1 << 0)) != 0, data: dataBuffer))
|
||||
case let .keyboardButtonRequestGeoLocation(keyboardButtonRequestGeoLocationData):
|
||||
let text = keyboardButtonRequestGeoLocationData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .requestMap)
|
||||
case let .keyboardButtonRequestPhone(keyboardButtonRequestPhoneData):
|
||||
let text = keyboardButtonRequestPhoneData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .requestPhone)
|
||||
case let .keyboardButtonSwitchInline(keyboardButtonSwitchInlineData):
|
||||
let (flags, text, query, types) = (keyboardButtonSwitchInlineData.flags, keyboardButtonSwitchInlineData.text, keyboardButtonSwitchInlineData.query, keyboardButtonSwitchInlineData.peerTypes)
|
||||
var peerTypes = ReplyMarkupButtonAction.PeerTypes()
|
||||
if let types = types {
|
||||
for type in types {
|
||||
switch type {
|
||||
case .inlineQueryPeerTypePM:
|
||||
peerTypes.insert(.users)
|
||||
case .inlineQueryPeerTypeBotPM:
|
||||
peerTypes.insert(.bots)
|
||||
case .inlineQueryPeerTypeBroadcast:
|
||||
peerTypes.insert(.channels)
|
||||
case .inlineQueryPeerTypeChat, .inlineQueryPeerTypeMegagroup:
|
||||
peerTypes.insert(.groups)
|
||||
case .inlineQueryPeerTypeSameBotPM:
|
||||
break
|
||||
}
|
||||
case let .keyboardButton(keyboardButtonData):
|
||||
let text = keyboardButtonData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .text, style: keyboardButtonData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonCallback(keyboardButtonCallbackData):
|
||||
let (flags, text, data) = (keyboardButtonCallbackData.flags, keyboardButtonCallbackData.text, keyboardButtonCallbackData.data)
|
||||
let memory = malloc(data.size)!
|
||||
memcpy(memory, data.data, data.size)
|
||||
let dataBuffer = MemoryBuffer(memory: memory, capacity: data.size, length: data.size, freeWhenDone: true)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .callback(requiresPassword: (flags & (1 << 0)) != 0, data: dataBuffer), style: keyboardButtonCallbackData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonRequestGeoLocation(keyboardButtonRequestGeoLocationData):
|
||||
let text = keyboardButtonRequestGeoLocationData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .requestMap, style: keyboardButtonRequestGeoLocationData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonRequestPhone(keyboardButtonRequestPhoneData):
|
||||
let text = keyboardButtonRequestPhoneData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .requestPhone, style: keyboardButtonRequestPhoneData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonSwitchInline(keyboardButtonSwitchInlineData):
|
||||
let (flags, text, query, types) = (keyboardButtonSwitchInlineData.flags, keyboardButtonSwitchInlineData.text, keyboardButtonSwitchInlineData.query, keyboardButtonSwitchInlineData.peerTypes)
|
||||
var peerTypes = ReplyMarkupButtonAction.PeerTypes()
|
||||
if let types = types {
|
||||
for type in types {
|
||||
switch type {
|
||||
case .inlineQueryPeerTypePM:
|
||||
peerTypes.insert(.users)
|
||||
case .inlineQueryPeerTypeBotPM:
|
||||
peerTypes.insert(.bots)
|
||||
case .inlineQueryPeerTypeBroadcast:
|
||||
peerTypes.insert(.channels)
|
||||
case .inlineQueryPeerTypeChat, .inlineQueryPeerTypeMegagroup:
|
||||
peerTypes.insert(.groups)
|
||||
case .inlineQueryPeerTypeSameBotPM:
|
||||
break
|
||||
}
|
||||
}
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .switchInline(samePeer: (flags & (1 << 0)) != 0, query: query, peerTypes: peerTypes))
|
||||
case let .keyboardButtonUrl(keyboardButtonUrlData):
|
||||
let (text, url) = (keyboardButtonUrlData.text, keyboardButtonUrlData.url)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .url(url))
|
||||
case let .keyboardButtonGame(keyboardButtonGameData):
|
||||
let text = keyboardButtonGameData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openWebApp)
|
||||
case let .keyboardButtonBuy(keyboardButtonBuyData):
|
||||
let text = keyboardButtonBuyData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .payment)
|
||||
case let .keyboardButtonUrlAuth(keyboardButtonUrlAuthData):
|
||||
let (text, fwdText, url, buttonId) = (keyboardButtonUrlAuthData.text, keyboardButtonUrlAuthData.fwdText, keyboardButtonUrlAuthData.url, keyboardButtonUrlAuthData.buttonId)
|
||||
self.init(title: text, titleWhenForwarded: fwdText, action: .urlAuth(url: url, buttonId: buttonId))
|
||||
case let .inputKeyboardButtonUrlAuth(inputKeyboardButtonUrlAuthData):
|
||||
let (text, fwdText, url) = (inputKeyboardButtonUrlAuthData.text, inputKeyboardButtonUrlAuthData.fwdText, inputKeyboardButtonUrlAuthData.url)
|
||||
self.init(title: text, titleWhenForwarded: fwdText, action: .urlAuth(url: url, buttonId: 0))
|
||||
case let .keyboardButtonRequestPoll(keyboardButtonRequestPollData):
|
||||
let (quiz, text) = (keyboardButtonRequestPollData.quiz, keyboardButtonRequestPollData.text)
|
||||
let isQuiz: Bool? = quiz.flatMap { quiz in
|
||||
if case .boolTrue = quiz {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .switchInline(samePeer: (flags & (1 << 0)) != 0, query: query, peerTypes: peerTypes), style: keyboardButtonSwitchInlineData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonUrl(keyboardButtonUrlData):
|
||||
let (text, url) = (keyboardButtonUrlData.text, keyboardButtonUrlData.url)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .url(url), style: keyboardButtonUrlData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonGame(keyboardButtonGameData):
|
||||
let text = keyboardButtonGameData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openWebApp, style: keyboardButtonGameData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonBuy(keyboardButtonBuyData):
|
||||
let text = keyboardButtonBuyData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .payment, style: keyboardButtonBuyData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonUrlAuth(keyboardButtonUrlAuthData):
|
||||
let (text, fwdText, url, buttonId) = (keyboardButtonUrlAuthData.text, keyboardButtonUrlAuthData.fwdText, keyboardButtonUrlAuthData.url, keyboardButtonUrlAuthData.buttonId)
|
||||
self.init(title: text, titleWhenForwarded: fwdText, action: .urlAuth(url: url, buttonId: buttonId), style: keyboardButtonUrlAuthData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .inputKeyboardButtonUrlAuth(inputKeyboardButtonUrlAuthData):
|
||||
let (text, fwdText, url) = (inputKeyboardButtonUrlAuthData.text, inputKeyboardButtonUrlAuthData.fwdText, inputKeyboardButtonUrlAuthData.url)
|
||||
self.init(title: text, titleWhenForwarded: fwdText, action: .urlAuth(url: url, buttonId: 0), style: inputKeyboardButtonUrlAuthData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonRequestPoll(keyboardButtonRequestPollData):
|
||||
let (quiz, text) = (keyboardButtonRequestPollData.quiz, keyboardButtonRequestPollData.text)
|
||||
let isQuiz: Bool? = quiz.flatMap { quiz in
|
||||
if case .boolTrue = quiz {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .setupPoll(isQuiz: isQuiz))
|
||||
case let .keyboardButtonUserProfile(keyboardButtonUserProfileData):
|
||||
let (text, userId) = (keyboardButtonUserProfileData.text, keyboardButtonUserProfileData.userId)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openUserProfile(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))))
|
||||
case let .inputKeyboardButtonUserProfile(inputKeyboardButtonUserProfileData):
|
||||
let text = inputKeyboardButtonUserProfileData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openUserProfile(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0))))
|
||||
case let .keyboardButtonWebView(keyboardButtonWebViewData):
|
||||
let (text, url) = (keyboardButtonWebViewData.text, keyboardButtonWebViewData.url)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openWebView(url: url, simple: false))
|
||||
case let .keyboardButtonSimpleWebView(keyboardButtonSimpleWebViewData):
|
||||
let (text, url) = (keyboardButtonSimpleWebViewData.text, keyboardButtonSimpleWebViewData.url)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openWebView(url: url, simple: true))
|
||||
case let .keyboardButtonRequestPeer(keyboardButtonRequestPeerData):
|
||||
let (text, buttonId, peerType, maxQuantity) = (keyboardButtonRequestPeerData.text, keyboardButtonRequestPeerData.buttonId, keyboardButtonRequestPeerData.peerType, keyboardButtonRequestPeerData.maxQuantity)
|
||||
let mappedPeerType: ReplyMarkupButtonRequestPeerType
|
||||
switch peerType {
|
||||
case let .requestPeerTypeUser(requestPeerTypeUserData):
|
||||
let (bot, premium) = (requestPeerTypeUserData.bot, requestPeerTypeUserData.premium)
|
||||
mappedPeerType = .user(ReplyMarkupButtonRequestPeerType.User(
|
||||
isBot: bot.flatMap({ $0 == .boolTrue }),
|
||||
isPremium: premium.flatMap({ $0 == .boolTrue })
|
||||
))
|
||||
case let .requestPeerTypeChat(requestPeerTypeChatData):
|
||||
let (flags, hasUsername, forum, userAdminRights, botAdminRights) = (requestPeerTypeChatData.flags, requestPeerTypeChatData.hasUsername, requestPeerTypeChatData.forum, requestPeerTypeChatData.userAdminRights, requestPeerTypeChatData.botAdminRights)
|
||||
mappedPeerType = .group(ReplyMarkupButtonRequestPeerType.Group(
|
||||
isCreator: (flags & (1 << 0)) != 0,
|
||||
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
|
||||
isForum: forum.flatMap({ $0 == .boolTrue }),
|
||||
botParticipant: (flags & (1 << 5)) != 0,
|
||||
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
|
||||
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
|
||||
))
|
||||
case let .requestPeerTypeBroadcast(requestPeerTypeBroadcastData):
|
||||
let (flags, hasUsername, userAdminRights, botAdminRights) = (requestPeerTypeBroadcastData.flags, requestPeerTypeBroadcastData.hasUsername, requestPeerTypeBroadcastData.userAdminRights, requestPeerTypeBroadcastData.botAdminRights)
|
||||
mappedPeerType = .channel(ReplyMarkupButtonRequestPeerType.Channel(
|
||||
isCreator: (flags & (1 << 0)) != 0,
|
||||
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
|
||||
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
|
||||
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
|
||||
))
|
||||
}
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .requestPeer(peerType: mappedPeerType, buttonId: buttonId, maxQuantity: maxQuantity))
|
||||
case let .inputKeyboardButtonRequestPeer(inputKeyboardButtonRequestPeerData):
|
||||
let (text, buttonId, peerType, maxQuantity) = (inputKeyboardButtonRequestPeerData.text, inputKeyboardButtonRequestPeerData.buttonId, inputKeyboardButtonRequestPeerData.peerType, inputKeyboardButtonRequestPeerData.maxQuantity)
|
||||
let mappedPeerType: ReplyMarkupButtonRequestPeerType
|
||||
switch peerType {
|
||||
case let .requestPeerTypeUser(requestPeerTypeUserData):
|
||||
let (bot, premium) = (requestPeerTypeUserData.bot, requestPeerTypeUserData.premium)
|
||||
mappedPeerType = .user(ReplyMarkupButtonRequestPeerType.User(
|
||||
isBot: bot.flatMap({ $0 == .boolTrue }),
|
||||
isPremium: premium.flatMap({ $0 == .boolTrue })
|
||||
))
|
||||
case let .requestPeerTypeChat(requestPeerTypeChatData):
|
||||
let (flags, hasUsername, forum, userAdminRights, botAdminRights) = (requestPeerTypeChatData.flags, requestPeerTypeChatData.hasUsername, requestPeerTypeChatData.forum, requestPeerTypeChatData.userAdminRights, requestPeerTypeChatData.botAdminRights)
|
||||
mappedPeerType = .group(ReplyMarkupButtonRequestPeerType.Group(
|
||||
isCreator: (flags & (1 << 0)) != 0,
|
||||
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
|
||||
isForum: forum.flatMap({ $0 == .boolTrue }),
|
||||
botParticipant: (flags & (1 << 5)) != 0,
|
||||
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
|
||||
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
|
||||
))
|
||||
case let .requestPeerTypeBroadcast(requestPeerTypeBroadcastData):
|
||||
let (flags, hasUsername, userAdminRights, botAdminRights) = (requestPeerTypeBroadcastData.flags, requestPeerTypeBroadcastData.hasUsername, requestPeerTypeBroadcastData.userAdminRights, requestPeerTypeBroadcastData.botAdminRights)
|
||||
mappedPeerType = .channel(ReplyMarkupButtonRequestPeerType.Channel(
|
||||
isCreator: (flags & (1 << 0)) != 0,
|
||||
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
|
||||
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
|
||||
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
|
||||
))
|
||||
}
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .requestPeer(peerType: mappedPeerType, buttonId: buttonId, maxQuantity: maxQuantity))
|
||||
case let .keyboardButtonCopy(keyboardButtonCopyData):
|
||||
let (text, payload) = (keyboardButtonCopyData.text, keyboardButtonCopyData.copyText)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .copyText(payload: payload))
|
||||
}
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .setupPoll(isQuiz: isQuiz), style: keyboardButtonRequestPollData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonUserProfile(keyboardButtonUserProfileData):
|
||||
let (text, userId) = (keyboardButtonUserProfileData.text, keyboardButtonUserProfileData.userId)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openUserProfile(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))), style: keyboardButtonUserProfileData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .inputKeyboardButtonUserProfile(inputKeyboardButtonUserProfileData):
|
||||
let text = inputKeyboardButtonUserProfileData.text
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openUserProfile(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0))), style: inputKeyboardButtonUserProfileData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonWebView(keyboardButtonWebViewData):
|
||||
let (text, url) = (keyboardButtonWebViewData.text, keyboardButtonWebViewData.url)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openWebView(url: url, simple: false), style: keyboardButtonWebViewData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonSimpleWebView(keyboardButtonSimpleWebViewData):
|
||||
let (text, url) = (keyboardButtonSimpleWebViewData.text, keyboardButtonSimpleWebViewData.url)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .openWebView(url: url, simple: true), style: keyboardButtonSimpleWebViewData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonRequestPeer(keyboardButtonRequestPeerData):
|
||||
let (text, buttonId, peerType, maxQuantity) = (keyboardButtonRequestPeerData.text, keyboardButtonRequestPeerData.buttonId, keyboardButtonRequestPeerData.peerType, keyboardButtonRequestPeerData.maxQuantity)
|
||||
let mappedPeerType: ReplyMarkupButtonRequestPeerType
|
||||
switch peerType {
|
||||
case let .requestPeerTypeUser(requestPeerTypeUserData):
|
||||
let (bot, premium) = (requestPeerTypeUserData.bot, requestPeerTypeUserData.premium)
|
||||
mappedPeerType = .user(ReplyMarkupButtonRequestPeerType.User(
|
||||
isBot: bot.flatMap({ $0 == .boolTrue }),
|
||||
isPremium: premium.flatMap({ $0 == .boolTrue })
|
||||
))
|
||||
case let .requestPeerTypeChat(requestPeerTypeChatData):
|
||||
let (flags, hasUsername, forum, userAdminRights, botAdminRights) = (requestPeerTypeChatData.flags, requestPeerTypeChatData.hasUsername, requestPeerTypeChatData.forum, requestPeerTypeChatData.userAdminRights, requestPeerTypeChatData.botAdminRights)
|
||||
mappedPeerType = .group(ReplyMarkupButtonRequestPeerType.Group(
|
||||
isCreator: (flags & (1 << 0)) != 0,
|
||||
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
|
||||
isForum: forum.flatMap({ $0 == .boolTrue }),
|
||||
botParticipant: (flags & (1 << 5)) != 0,
|
||||
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
|
||||
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
|
||||
))
|
||||
case let .requestPeerTypeBroadcast(requestPeerTypeBroadcastData):
|
||||
let (flags, hasUsername, userAdminRights, botAdminRights) = (requestPeerTypeBroadcastData.flags, requestPeerTypeBroadcastData.hasUsername, requestPeerTypeBroadcastData.userAdminRights, requestPeerTypeBroadcastData.botAdminRights)
|
||||
mappedPeerType = .channel(ReplyMarkupButtonRequestPeerType.Channel(
|
||||
isCreator: (flags & (1 << 0)) != 0,
|
||||
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
|
||||
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
|
||||
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
|
||||
))
|
||||
}
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .requestPeer(peerType: mappedPeerType, buttonId: buttonId, maxQuantity: maxQuantity), style: keyboardButtonRequestPeerData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .inputKeyboardButtonRequestPeer(inputKeyboardButtonRequestPeerData):
|
||||
let (text, buttonId, peerType, maxQuantity) = (inputKeyboardButtonRequestPeerData.text, inputKeyboardButtonRequestPeerData.buttonId, inputKeyboardButtonRequestPeerData.peerType, inputKeyboardButtonRequestPeerData.maxQuantity)
|
||||
let mappedPeerType: ReplyMarkupButtonRequestPeerType
|
||||
switch peerType {
|
||||
case let .requestPeerTypeUser(requestPeerTypeUserData):
|
||||
let (bot, premium) = (requestPeerTypeUserData.bot, requestPeerTypeUserData.premium)
|
||||
mappedPeerType = .user(ReplyMarkupButtonRequestPeerType.User(
|
||||
isBot: bot.flatMap({ $0 == .boolTrue }),
|
||||
isPremium: premium.flatMap({ $0 == .boolTrue })
|
||||
))
|
||||
case let .requestPeerTypeChat(requestPeerTypeChatData):
|
||||
let (flags, hasUsername, forum, userAdminRights, botAdminRights) = (requestPeerTypeChatData.flags, requestPeerTypeChatData.hasUsername, requestPeerTypeChatData.forum, requestPeerTypeChatData.userAdminRights, requestPeerTypeChatData.botAdminRights)
|
||||
mappedPeerType = .group(ReplyMarkupButtonRequestPeerType.Group(
|
||||
isCreator: (flags & (1 << 0)) != 0,
|
||||
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
|
||||
isForum: forum.flatMap({ $0 == .boolTrue }),
|
||||
botParticipant: (flags & (1 << 5)) != 0,
|
||||
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
|
||||
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
|
||||
))
|
||||
case let .requestPeerTypeBroadcast(requestPeerTypeBroadcastData):
|
||||
let (flags, hasUsername, userAdminRights, botAdminRights) = (requestPeerTypeBroadcastData.flags, requestPeerTypeBroadcastData.hasUsername, requestPeerTypeBroadcastData.userAdminRights, requestPeerTypeBroadcastData.botAdminRights)
|
||||
mappedPeerType = .channel(ReplyMarkupButtonRequestPeerType.Channel(
|
||||
isCreator: (flags & (1 << 0)) != 0,
|
||||
hasUsername: hasUsername.flatMap({ $0 == .boolTrue }),
|
||||
userAdminRights: userAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:)),
|
||||
botAdminRights: botAdminRights.flatMap(TelegramChatAdminRights.init(apiAdminRights:))
|
||||
))
|
||||
}
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .requestPeer(peerType: mappedPeerType, buttonId: buttonId, maxQuantity: maxQuantity), style: inputKeyboardButtonRequestPeerData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
case let .keyboardButtonCopy(keyboardButtonCopyData):
|
||||
let (text, payload) = (keyboardButtonCopyData.text, keyboardButtonCopyData.copyText)
|
||||
self.init(title: text, titleWhenForwarded: nil, action: .copyText(payload: payload), style: keyboardButtonCopyData.style.flatMap(ReplyMarkupButton.Style.init(apiStyle:)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -292,6 +292,10 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
|||
if let otherParticipants {
|
||||
result.append(contentsOf: otherParticipants.map(\.peerId))
|
||||
}
|
||||
case let .messageActionNewCreatorPending(messageActionNewCreatorPending):
|
||||
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionNewCreatorPending.newCreatorId)))
|
||||
case let .messageActionChangeCreator(messageActionChangeCreator):
|
||||
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionChangeCreator.newCreatorId)))
|
||||
}
|
||||
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
|||
text = nil
|
||||
entities = nil
|
||||
}
|
||||
return TelegramMediaAction(action: .giftCode(slug: slug, fromGiveaway: (flags & (1 << 0)) != 0, isUnclaimed: (flags & (1 << 5)) != 0, boostPeerId: boostPeer?.peerId, days: days, currency: currency, amount: amount, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount, text: text, entities: entities))
|
||||
return TelegramMediaAction(action: .giftCode(slug: slug, fromGiveaway: (flags & (1 << 0)) != 0, isUnclaimed: (flags & (1 << 5)) != 0, boostPeerId: boostPeer?.peerId, months: days, currency: currency, amount: amount, cryptoCurrency: cryptoCurrency, cryptoAmount: cryptoAmount, text: text, entities: entities))
|
||||
case let .messageActionGiveawayLaunch(messageActionGiveawayLaunchData):
|
||||
return TelegramMediaAction(action: .giveawayLaunched(stars: messageActionGiveawayLaunchData.stars))
|
||||
case let .messageActionGiveawayResults(messageActionGiveawayResultsData):
|
||||
|
|
@ -349,6 +349,16 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
|||
return nil
|
||||
}
|
||||
return TelegramMediaAction(action: .starGiftPurchaseOfferDeclined(gift: gift, amount: CurrencyAmount(apiAmount: price), hasExpired: (flags & (1 << 0)) != 0))
|
||||
case let .messageActionNewCreatorPending(messageActionNewCreatorPending):
|
||||
return TelegramMediaAction(action: .groupCreatorChange(TelegramMediaActionType.GroupCreatorChange(
|
||||
kind: .pending,
|
||||
targetPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionNewCreatorPending.newCreatorId))
|
||||
)))
|
||||
case let .messageActionChangeCreator(messageActionChangeCreator):
|
||||
return TelegramMediaAction(action: .groupCreatorChange(TelegramMediaActionType.GroupCreatorChange(
|
||||
kind: .applied,
|
||||
targetPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(messageActionChangeCreator.newCreatorId))
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -932,7 +932,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
|||
buttons.append(button)
|
||||
} else if case let .switchInline(samePeer, query, peerTypes) = button.action, sourceSentViaBot {
|
||||
let samePeer = samePeer && peerId == sourceMessage.id.peerId
|
||||
let updatedButton = ReplyMarkupButton(title: button.titleWhenForwarded ?? button.title, titleWhenForwarded: button.titleWhenForwarded, action: .switchInline(samePeer: samePeer, query: query, peerTypes: peerTypes))
|
||||
let updatedButton = ReplyMarkupButton(title: button.titleWhenForwarded ?? button.title, titleWhenForwarded: button.titleWhenForwarded, action: .switchInline(samePeer: samePeer, query: query, peerTypes: peerTypes), style: button.style)
|
||||
buttons.append(updatedButton)
|
||||
} else {
|
||||
rows.removeAll()
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
|||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 223
|
||||
return 224
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import Postbox
|
||||
import TelegramApi
|
||||
|
||||
public enum ReplyMarkupButtonRequestPeerType: Codable, Equatable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
|
|
@ -323,21 +324,79 @@ public enum ReplyMarkupButtonAction: PostboxCoding, Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
extension ReplyMarkupButton.Style {
|
||||
init(apiStyle: Api.KeyboardButtonStyle) {
|
||||
switch apiStyle {
|
||||
case let .keyboardButtonStyle(keyboardButtonStyle):
|
||||
var color: Color?
|
||||
|
||||
if keyboardButtonStyle.flags & (1 << 0) != 0 {
|
||||
color = .primary
|
||||
} else if keyboardButtonStyle.flags & (1 << 1) != 0 {
|
||||
color = .danger
|
||||
} else if keyboardButtonStyle.flags & (1 << 2) != 0 {
|
||||
color = .success
|
||||
}
|
||||
|
||||
self.init(color: color, iconFileId: keyboardButtonStyle.icon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct ReplyMarkupButton: PostboxCoding, Equatable {
|
||||
public struct Style: PostboxCoding, Equatable {
|
||||
public enum Color: Int32 {
|
||||
case primary = 0
|
||||
case danger = 1
|
||||
case success = 2
|
||||
}
|
||||
|
||||
public let color: Color?
|
||||
public let iconFileId: Int64?
|
||||
|
||||
public init(color: Color?, iconFileId: Int64?) {
|
||||
self.color = color
|
||||
self.iconFileId = iconFileId
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
let rawColor = decoder.decodeInt32ForKey("c", orElse: -1)
|
||||
if rawColor != -1 {
|
||||
self.color = Color(rawValue: rawColor)
|
||||
} else {
|
||||
self.color = nil
|
||||
}
|
||||
|
||||
self.iconFileId = decoder.decodeOptionalInt64ForKey("i")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.color?.rawValue ?? -1, forKey: "c")
|
||||
if let iconFileId = self.iconFileId {
|
||||
encoder.encodeInt64(iconFileId, forKey: "i")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "i")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public let title: String
|
||||
public let titleWhenForwarded: String?
|
||||
public let action: ReplyMarkupButtonAction
|
||||
public let style: Style?
|
||||
|
||||
public init(title: String, titleWhenForwarded: String?, action: ReplyMarkupButtonAction) {
|
||||
public init(title: String, titleWhenForwarded: String?, action: ReplyMarkupButtonAction, style: Style?) {
|
||||
self.title = title
|
||||
self.titleWhenForwarded = titleWhenForwarded
|
||||
self.action = action
|
||||
self.style = style
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.title = decoder.decodeStringForKey(".t", orElse: "")
|
||||
self.titleWhenForwarded = decoder.decodeOptionalStringForKey(".tf")
|
||||
self.action = ReplyMarkupButtonAction(decoder: decoder)
|
||||
self.style = (decoder.decodeObjectForKey(".stl", decoder: { Style(decoder: $0) }) as? Style)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
|
|
@ -348,10 +407,15 @@ public struct ReplyMarkupButton: PostboxCoding, Equatable {
|
|||
encoder.encodeNil(forKey: ".tf")
|
||||
}
|
||||
self.action.encode(encoder)
|
||||
if let style = self.style {
|
||||
encoder.encodeObject(style, forKey: ".stl")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: ".stl")
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: ReplyMarkupButton, rhs: ReplyMarkupButton) -> Bool {
|
||||
return lhs.title == rhs.title && lhs.action == rhs.action
|
||||
return lhs.title == rhs.title && lhs.action == rhs.action && lhs.style == rhs.style
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -399,6 +463,21 @@ public class ReplyMarkupMessageAttribute: MessageAttribute, Equatable {
|
|||
public let flags: ReplyMarkupMessageFlags
|
||||
public let placeholder: String?
|
||||
|
||||
public var associatedMediaIds: [MediaId] {
|
||||
var result: [MediaId] = []
|
||||
for row in rows {
|
||||
for button in row.buttons {
|
||||
if let iconFileId = button.style?.iconFileId {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: iconFileId)
|
||||
if !result.contains(mediaId) {
|
||||
result.append(mediaId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public init(rows: [ReplyMarkupRow], flags: ReplyMarkupMessageFlags, placeholder: String?) {
|
||||
self.rows = rows
|
||||
self.flags = flags
|
||||
|
|
|
|||
|
|
@ -211,6 +211,38 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
public static let isFinal = StarGiftAuctionBidFlags(rawValue: 1 << 3)
|
||||
}
|
||||
|
||||
public struct GroupCreatorChange: Codable, Equatable {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case kind = "k"
|
||||
case targetPeerId = "t"
|
||||
}
|
||||
|
||||
public enum Kind: Int32 {
|
||||
case pending = 0
|
||||
case applied = 1
|
||||
}
|
||||
|
||||
public let kind: Kind
|
||||
public let targetPeerId: PeerId
|
||||
|
||||
public init(kind: Kind, targetPeerId: PeerId) {
|
||||
self.kind = kind
|
||||
self.targetPeerId = targetPeerId
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.kind = Kind(rawValue: try container.decode(Int32.self, forKey: .kind)) ?? .pending
|
||||
self.targetPeerId = PeerId(try container.decode(Int64.self, forKey: .targetPeerId))
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(self.kind.rawValue, forKey: .kind)
|
||||
try container.encode(self.targetPeerId.toInt64(), forKey: .kind)
|
||||
}
|
||||
}
|
||||
|
||||
case unknown
|
||||
case groupCreated(title: String)
|
||||
case addedMembers(peerIds: [PeerId])
|
||||
|
|
@ -247,7 +279,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
case requestedPeer(buttonId: Int32, peerIds: [PeerId])
|
||||
case setChatWallpaper(wallpaper: TelegramWallpaper, forBoth: Bool)
|
||||
case setSameChatWallpaper(wallpaper: TelegramWallpaper)
|
||||
case giftCode(slug: String, fromGiveaway: Bool, isUnclaimed: Bool, boostPeerId: PeerId?, days: Int32, currency: String?, amount: Int64?, cryptoCurrency: String?, cryptoAmount: Int64?, text: String?, entities: [MessageTextEntity]?)
|
||||
case giftCode(slug: String, fromGiveaway: Bool, isUnclaimed: Bool, boostPeerId: PeerId?, months: Int32, currency: String?, amount: Int64?, cryptoCurrency: String?, cryptoAmount: Int64?, text: String?, entities: [MessageTextEntity]?)
|
||||
case giveawayLaunched(stars: Int64?)
|
||||
case joinedChannel
|
||||
case giveawayResults(winners: Int32, unclaimed: Int32, stars: Bool)
|
||||
|
|
@ -269,6 +301,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
case suggestedBirthday(TelegramBirthday)
|
||||
case starGiftPurchaseOffer(gift: StarGift, amount: CurrencyAmount, expireDate: Int32, isAccepted: Bool, isDeclined: Bool)
|
||||
case starGiftPurchaseOfferDeclined(gift: StarGift, amount: CurrencyAmount, hasExpired: Bool)
|
||||
case groupCreatorChange(GroupCreatorChange)
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||
|
|
@ -374,7 +407,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
case 35:
|
||||
self = .botAppAccessGranted(appName: decoder.decodeOptionalStringForKey("app"), type: decoder.decodeOptionalInt32ForKey("atp").flatMap { BotSendMessageAccessGrantedType(rawValue: $0) })
|
||||
case 36:
|
||||
self = .giftCode(slug: decoder.decodeStringForKey("slug", orElse: ""), fromGiveaway: decoder.decodeBoolForKey("give", orElse: false), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: decoder.decodeOptionalInt64ForKey("pi").flatMap { PeerId($0) }, days: decoder.decodeInt32ForKey("days", orElse: decoder.decodeInt32ForKey("months", orElse: 0)), currency: decoder.decodeOptionalStringForKey("currency"), amount: decoder.decodeOptionalInt64ForKey("amount"), cryptoCurrency: decoder.decodeOptionalStringForKey("cryptoCurrency"), cryptoAmount: decoder.decodeOptionalInt64ForKey("cryptoAmount"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"))
|
||||
self = .giftCode(slug: decoder.decodeStringForKey("slug", orElse: ""), fromGiveaway: decoder.decodeBoolForKey("give", orElse: false), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: decoder.decodeOptionalInt64ForKey("pi").flatMap { PeerId($0) }, months: decoder.decodeInt32ForKey("months", orElse: 0), currency: decoder.decodeOptionalStringForKey("currency"), amount: decoder.decodeOptionalInt64ForKey("amount"), cryptoCurrency: decoder.decodeOptionalStringForKey("cryptoCurrency"), cryptoAmount: decoder.decodeOptionalInt64ForKey("cryptoAmount"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"))
|
||||
case 37:
|
||||
self = .giveawayLaunched(stars: decoder.decodeOptionalInt64ForKey("stars"))
|
||||
case 38:
|
||||
|
|
@ -437,9 +470,11 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
case 55:
|
||||
self = .suggestedBirthday(decoder.decodeCodable(TelegramBirthday.self, forKey: "birthday") ?? TelegramBirthday(day: 1, month: 1, year: nil))
|
||||
case 56:
|
||||
self = .starGiftPurchaseOffer(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, amount: decoder.decodeCodable(CurrencyAmount.self, forKey: "amount")!, expireDate: decoder.decodeInt32ForKey("expireDate", orElse: 0), isAccepted: decoder.decodeBoolForKey("isAccepted", orElse: false), isDeclined: decoder.decodeBoolForKey("isDeclined", orElse: false))
|
||||
self = .starGiftPurchaseOffer(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, amount: decoder.decodeCodable(CurrencyAmount.self, forKey: "amount") ?? CurrencyAmount(amount: .zero, currency: .stars), expireDate: decoder.decodeInt32ForKey("expireDate", orElse: 0), isAccepted: decoder.decodeBoolForKey("isAccepted", orElse: false), isDeclined: decoder.decodeBoolForKey("isDeclined", orElse: false))
|
||||
case 57:
|
||||
self = .starGiftPurchaseOfferDeclined(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, amount: decoder.decodeCodable(CurrencyAmount.self, forKey: "amount")!, hasExpired: decoder.decodeBoolForKey("hasExpired", orElse: false))
|
||||
case 59:
|
||||
self = .groupCreatorChange(decoder.decodeCodable(GroupCreatorChange.self, forKey: "d") ?? GroupCreatorChange(kind: .pending, targetPeerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0))))
|
||||
default:
|
||||
self = .unknown
|
||||
}
|
||||
|
|
@ -632,7 +667,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
} else {
|
||||
encoder.encodeNil(forKey: "atp")
|
||||
}
|
||||
case let .giftCode(slug, fromGiveaway, unclaimed, boostPeerId, days, currency, amount, cryptoCurrency, cryptoAmount, text, entities):
|
||||
case let .giftCode(slug, fromGiveaway, unclaimed, boostPeerId, months, currency, amount, cryptoCurrency, cryptoAmount, text, entities):
|
||||
encoder.encodeInt32(36, forKey: "_rawValue")
|
||||
encoder.encodeString(slug, forKey: "slug")
|
||||
encoder.encodeBool(fromGiveaway, forKey: "give")
|
||||
|
|
@ -642,7 +677,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
} else {
|
||||
encoder.encodeNil(forKey: "pi")
|
||||
}
|
||||
encoder.encodeInt32(days, forKey: "days")
|
||||
encoder.encodeInt32(months, forKey: "months")
|
||||
if let currency = currency {
|
||||
encoder.encodeString(currency, forKey: "currency")
|
||||
} else {
|
||||
|
|
@ -931,6 +966,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
encoder.encodeObject(gift, forKey: "gift")
|
||||
encoder.encodeCodable(amount, forKey: "amount")
|
||||
encoder.encodeBool(hasExpired, forKey: "hasExpired")
|
||||
case let .groupCreatorChange(groupCreatorChange):
|
||||
encoder.encodeInt32(59, forKey: "_rawValue")
|
||||
encoder.encodeCodable(groupCreatorChange, forKey: "d")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -987,6 +1025,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||
return peerIds
|
||||
case let .conferenceCall(conferenceCall):
|
||||
return conferenceCall.otherParticipants
|
||||
case let .groupCreatorChange(groupCreatorChange):
|
||||
return [groupCreatorChange.targetPeerId]
|
||||
default:
|
||||
return []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ public enum MessageActionUrlAuthResult {
|
|||
public static let requestPhoneNumber = Flags(rawValue: 1 << 1)
|
||||
}
|
||||
|
||||
public struct ClientData {
|
||||
public struct ClientData : Equatable {
|
||||
public let browser: String
|
||||
public let platform: String
|
||||
public let ip: String
|
||||
|
|
|
|||
|
|
@ -86,13 +86,14 @@ public final class SparseMessageList {
|
|||
}
|
||||
private let loadHoleDisposable = MetaDisposable()
|
||||
private var loadingHole: LoadingHole?
|
||||
private var isLoadingInitial: Bool = false
|
||||
|
||||
private var loadingPlaceholders: [MessageId: Disposable] = [:]
|
||||
private var loadedPlaceholders: [MessageId: Message] = [:]
|
||||
|
||||
let statePromise = Promise<SparseMessageList.State>()
|
||||
|
||||
init(queue: Queue, account: Account, peerId: PeerId, threadId: Int64?, messageTag: MessageTags) {
|
||||
init(queue: Queue, account: Account, peerId: PeerId, threadId: Int64?, messageTag: MessageTags, initialMessageIndex: MessageIndex?) {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.peerId = peerId
|
||||
|
|
@ -102,6 +103,11 @@ public final class SparseMessageList {
|
|||
self.resetTopSection()
|
||||
|
||||
if self.threadId == nil {
|
||||
if initialMessageIndex != nil {
|
||||
self.isLoadingInitial = true
|
||||
self.updateState()
|
||||
}
|
||||
|
||||
self.sparseItemsDisposable = (self.account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
|
|
@ -112,7 +118,7 @@ public final class SparseMessageList {
|
|||
guard let messageFilter = messageFilterForTagMask(messageTag) else {
|
||||
return .single(SparseItems(items: []))
|
||||
}
|
||||
//TODO:api
|
||||
|
||||
return account.network.request(Api.functions.messages.getSearchResultsPositions(flags: 0, peer: inputPeer, savedPeerId: nil, filter: messageFilter, offsetId: 0, limit: 1000))
|
||||
|> map { result -> SparseItems in
|
||||
switch result {
|
||||
|
|
@ -136,7 +142,11 @@ public final class SparseMessageList {
|
|||
|
||||
var result = SparseItems(items: [])
|
||||
for i in 0 ..< positions.count {
|
||||
if i != 0 {
|
||||
if i == 0 {
|
||||
if initialMessageIndex != nil && positions[i].offset != 0 {
|
||||
result.items.append(.range(count: positions[i].offset))
|
||||
}
|
||||
} else {
|
||||
let deltaCount = positions[i].offset - 1 - positions[i - 1].offset
|
||||
if deltaCount > 0 {
|
||||
result.items.append(.range(count: deltaCount))
|
||||
|
|
@ -162,9 +172,34 @@ public final class SparseMessageList {
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.isLoadingInitial = false
|
||||
strongSelf.sparseItems = sparseItems
|
||||
if strongSelf.topSection != nil {
|
||||
strongSelf.updateState()
|
||||
if let initialMessageIndex {
|
||||
var loadHoleAnchor: MessageId?
|
||||
loop: for item in sparseItems.items {
|
||||
switch item {
|
||||
case let .anchor(id, timestamp, _):
|
||||
let anchorIndex = MessageIndex(id: id, timestamp: timestamp)
|
||||
if anchorIndex <= initialMessageIndex {
|
||||
loadHoleAnchor = id
|
||||
break loop
|
||||
}
|
||||
case .range:
|
||||
break
|
||||
}
|
||||
}
|
||||
if let loadHoleAnchor {
|
||||
strongSelf.loadHole(anchor: loadHoleAnchor, direction: .around, completion: {
|
||||
})
|
||||
} else {
|
||||
if strongSelf.topSection != nil {
|
||||
strongSelf.updateState()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if strongSelf.topSection != nil {
|
||||
strongSelf.updateState()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -593,10 +628,22 @@ public final class SparseMessageList {
|
|||
if self.topSection != topSection {
|
||||
self.topSection = topSection
|
||||
}
|
||||
self.updateState()
|
||||
if self.loadingHole == nil && !self.isLoadingInitial {
|
||||
self.updateState()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateState() {
|
||||
if self.isLoadingInitial {
|
||||
self.statePromise.set(.single(SparseMessageList.State(
|
||||
items: [],
|
||||
totalCount: 0,
|
||||
isLoading: true
|
||||
)))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var items: [SparseMessageList.State.Item] = []
|
||||
var minMessageId: MessageId?
|
||||
if let topSection = self.topSection {
|
||||
|
|
@ -694,11 +741,11 @@ public final class SparseMessageList {
|
|||
}
|
||||
}
|
||||
|
||||
init(account: Account, peerId: PeerId, threadId: Int64?, messageTag: MessageTags) {
|
||||
init(account: Account, peerId: PeerId, threadId: Int64?, messageTag: MessageTags, initialMessageIndex: MessageIndex?) {
|
||||
self.queue = Queue()
|
||||
let queue = self.queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return Impl(queue: queue, account: account, peerId: peerId, threadId: threadId, messageTag: messageTag)
|
||||
return Impl(queue: queue, account: account, peerId: peerId, threadId: threadId, messageTag: messageTag, initialMessageIndex: initialMessageIndex)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -495,8 +495,8 @@ public extension TelegramEngine {
|
|||
}
|
||||
}
|
||||
|
||||
public func sparseMessageList(peerId: EnginePeer.Id, threadId: Int64?, tag: EngineMessage.Tags) -> SparseMessageList {
|
||||
return SparseMessageList(account: self.account, peerId: peerId, threadId: threadId, messageTag: tag)
|
||||
public func sparseMessageList(peerId: EnginePeer.Id, threadId: Int64?, tag: EngineMessage.Tags, initialMessageIndex: MessageIndex? = nil) -> SparseMessageList {
|
||||
return SparseMessageList(account: self.account, peerId: peerId, threadId: threadId, messageTag: tag, initialMessageIndex: initialMessageIndex)
|
||||
}
|
||||
|
||||
public func sparseMessageCalendar(peerId: EnginePeer.Id, threadId: Int64?, tag: EngineMessage.Tags, displayMedia: Bool) -> SparseMessageCalendar {
|
||||
|
|
|
|||
|
|
@ -471,6 +471,36 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
public var isPermille: Bool {
|
||||
if case .permille = self {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public var badgeText: String {
|
||||
switch self {
|
||||
case let .permille(value):
|
||||
if value == 0 {
|
||||
return "<0.1%"
|
||||
}
|
||||
let percent = Double(value) / 10.0
|
||||
if percent.truncatingRemainder(dividingBy: 1) == 0 {
|
||||
return "\(Int(percent))%"
|
||||
} else {
|
||||
return String(format: "%.1f%%", percent)
|
||||
}
|
||||
case .rare:
|
||||
return "rare"
|
||||
case .epic:
|
||||
return "epic"
|
||||
case .legendary:
|
||||
return "legendary"
|
||||
case .uncommon:
|
||||
return "uncommon"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case model(name: String, file: TelegramMediaFile, rarity: Rarity, crafted: Bool)
|
||||
|
|
@ -1279,7 +1309,7 @@ extension StarGift {
|
|||
} else if let ownerName {
|
||||
owner = .name(ownerName)
|
||||
} else {
|
||||
owner = nil
|
||||
owner = .none
|
||||
}
|
||||
let resellAmounts = apiResellAmount?.compactMap { CurrencyAmount(apiAmount: $0) }
|
||||
var flags = StarGift.UniqueGift.Flags()
|
||||
|
|
|
|||
|
|
@ -1743,6 +1743,17 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_Rejected(peerName, giftTitle, priceString)._tuple, body: bodyAttributes, argumentAttributes: attributes)
|
||||
}
|
||||
}
|
||||
case let .groupCreatorChange(groupCreatorChange):
|
||||
var targetName = ""
|
||||
if let peer = message.peers[groupCreatorChange.targetPeerId] {
|
||||
targetName = EnginePeer(peer).displayTitle(strings: strings, displayOrder: nameDisplayOrder)
|
||||
}
|
||||
switch groupCreatorChange.kind {
|
||||
case .pending:
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_GroupCreatorChangePending(authorName, targetName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id), (1, groupCreatorChange.targetPeerId)]))
|
||||
case .applied:
|
||||
attributedString = addAttributesToStringWithRanges(strings.Notification_GroupCreatorChangeApplied(authorName, targetName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id), (1, groupCreatorChange.targetPeerId)]))
|
||||
}
|
||||
case .unknown:
|
||||
attributedString = nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ swift_library(
|
|||
"//submodules/WallpaperBackgroundNode",
|
||||
"//submodules/TelegramUI/Components/ChatControllerInteraction",
|
||||
"//submodules/TelegramUI/Components/ChatInputNode",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/Components/ComponentDisplayAdapters",
|
||||
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
|
||||
"//submodules/TelegramUI/Components/EmojiStatusComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
|
|
|||
|
|
@ -11,20 +11,19 @@ import ChatPresentationInterfaceState
|
|||
import WallpaperBackgroundNode
|
||||
import ChatControllerInteraction
|
||||
import ChatInputNode
|
||||
import ComponentFlow
|
||||
import ComponentDisplayAdapters
|
||||
import GlassBackgroundComponent
|
||||
import EmojiStatusComponent
|
||||
|
||||
private final class ChatButtonKeyboardInputButtonNode: HighlightTrackingButtonNode {
|
||||
var button: ReplyMarkupButton? {
|
||||
didSet {
|
||||
self.updateIcon()
|
||||
}
|
||||
}
|
||||
private(set) var button: ReplyMarkupButton?
|
||||
|
||||
private let backgroundContainerNode: ASDisplayNode
|
||||
private var backgroundNode: WallpaperBubbleBackgroundNode?
|
||||
private let backgroundColorNode: ASDisplayNode
|
||||
private let backgroundAdditionalColorNode: ASDisplayNode
|
||||
private let backgroundView: UIImageView
|
||||
private var icon: ComponentView<Empty>?
|
||||
|
||||
private let highlightNode: ASImageNode
|
||||
let tintMaskView: UIImageView
|
||||
|
||||
private let textNode: ImmediateTextNode
|
||||
private var iconNode: ASImageNode?
|
||||
|
|
@ -33,22 +32,11 @@ private final class ChatButtonKeyboardInputButtonNode: HighlightTrackingButtonNo
|
|||
|
||||
init() {
|
||||
self.backgroundContainerNode = ASDisplayNode()
|
||||
self.backgroundContainerNode.clipsToBounds = true
|
||||
self.backgroundContainerNode.allowsGroupOpacity = true
|
||||
self.backgroundContainerNode.isUserInteractionEnabled = false
|
||||
self.backgroundContainerNode.cornerRadius = 10.0
|
||||
self.backgroundContainerNode.layer.cornerCurve = .continuous
|
||||
|
||||
self.backgroundColorNode = ASDisplayNode()
|
||||
self.backgroundColorNode.cornerRadius = 10.0
|
||||
self.backgroundColorNode.layer.cornerCurve = .continuous
|
||||
|
||||
self.backgroundAdditionalColorNode = ASDisplayNode()
|
||||
self.backgroundAdditionalColorNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.1)
|
||||
self.backgroundAdditionalColorNode.isHidden = true
|
||||
|
||||
self.highlightNode = ASImageNode()
|
||||
self.highlightNode.isUserInteractionEnabled = false
|
||||
self.backgroundView = UIImageView()
|
||||
self.tintMaskView = UIImageView()
|
||||
|
||||
self.textNode = ImmediateTextNode()
|
||||
self.textNode.isUserInteractionEnabled = false
|
||||
|
|
@ -61,58 +49,63 @@ private final class ChatButtonKeyboardInputButtonNode: HighlightTrackingButtonNo
|
|||
|
||||
self.addSubnode(self.backgroundContainerNode)
|
||||
|
||||
self.backgroundContainerNode.addSubnode(self.backgroundColorNode)
|
||||
self.backgroundContainerNode.addSubnode(self.backgroundAdditionalColorNode)
|
||||
self.backgroundContainerNode.view.addSubview(self.backgroundView)
|
||||
self.addSubnode(self.textNode)
|
||||
|
||||
self.backgroundContainerNode.addSubnode(self.highlightNode)
|
||||
|
||||
self.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted, !strongSelf.bounds.width.isZero {
|
||||
let scale = (strongSelf.bounds.width - 10.0) / strongSelf.bounds.width
|
||||
strongSelf.layer.animateScale(from: 1.0, to: scale, duration: 0.15, removeOnCompletion: false)
|
||||
|
||||
strongSelf.backgroundContainerNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.backgroundContainerNode.alpha = 0.6
|
||||
} else if let presentationLayer = strongSelf.layer.presentation() {
|
||||
strongSelf.layer.animateScale(from: CGFloat((presentationLayer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0), to: 1.0, duration: 0.25, removeOnCompletion: false)
|
||||
|
||||
strongSelf.backgroundContainerNode.alpha = 0.9
|
||||
} else {
|
||||
strongSelf.backgroundContainerNode.alpha = 1.0
|
||||
strongSelf.backgroundContainerNode.layer.animateAlpha(from: 0.6, to: 1.0, duration: 0.2)
|
||||
strongSelf.backgroundContainerNode.layer.animateAlpha(from: 0.9, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func setAttributedTitle(_ title: NSAttributedString, for state: UIControl.State) {
|
||||
func update(context: AccountContext, size: CGSize, theme: PresentationTheme, wallpaperBackgroundNode: WallpaperBackgroundNode?, button: ReplyMarkupButton, message: EngineMessage) {
|
||||
if theme !== self.theme {
|
||||
self.theme = theme
|
||||
}
|
||||
|
||||
if self.backgroundView.image == nil {
|
||||
self.backgroundView.image = generateStretchableFilledCircleImage(diameter: 20.0, color: .white)?.withRenderingMode(.alwaysTemplate)
|
||||
self.tintMaskView.image = self.backgroundView.image
|
||||
}
|
||||
self.tintMaskView.tintColor = .black
|
||||
|
||||
var titleColor = theme.chat.inputButtonPanel.buttonTextColor
|
||||
|
||||
if let color = button.style?.color {
|
||||
switch color {
|
||||
case .primary:
|
||||
self.backgroundView.tintColor = theme.list.itemCheckColors.fillColor
|
||||
titleColor = theme.list.itemCheckColors.foregroundColor
|
||||
case .danger:
|
||||
self.backgroundView.tintColor = UIColor(rgb: 0xFF3B30)
|
||||
titleColor = .white
|
||||
case .success:
|
||||
self.backgroundView.tintColor = UIColor(rgb: 0x21B246)
|
||||
titleColor = .white
|
||||
}
|
||||
} else {
|
||||
self.backgroundView.tintColor = theme.overallDarkAppearance ? UIColor(white: 1.0, alpha: 0.25) : UIColor(white: 1.0, alpha: 0.85)
|
||||
}
|
||||
|
||||
let title = NSAttributedString(string: button.title, font: Font.regular(16.0), textColor: titleColor, paragraphAlignment: .center)
|
||||
|
||||
self.textNode.attributedText = title
|
||||
self.accessibilityLabel = title.string
|
||||
}
|
||||
|
||||
private var absoluteRect: (CGRect, CGSize)?
|
||||
func update(rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
self.absoluteRect = (rect, containerSize)
|
||||
|
||||
if let backgroundNode = self.backgroundNode {
|
||||
var backgroundFrame = backgroundNode.frame
|
||||
backgroundFrame.origin.x += rect.minX
|
||||
backgroundFrame.origin.y += rect.minY
|
||||
backgroundNode.update(rect: backgroundFrame, within: containerSize, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateIcon() {
|
||||
guard let theme = self.theme else {
|
||||
return
|
||||
}
|
||||
var iconImage: UIImage?
|
||||
if let button = self.button {
|
||||
switch button.action {
|
||||
case .openWebView:
|
||||
iconImage = PresentationResourcesChat.chatKeyboardActionButtonWebAppIconImage(theme)
|
||||
default:
|
||||
iconImage = nil
|
||||
case .openWebView:
|
||||
iconImage = PresentationResourcesChat.chatKeyboardActionButtonWebAppIconImage(theme)
|
||||
default:
|
||||
iconImage = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -129,71 +122,83 @@ private final class ChatButtonKeyboardInputButtonNode: HighlightTrackingButtonNo
|
|||
self.iconNode = nil
|
||||
}
|
||||
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
|
||||
func updateTheme(theme: PresentationTheme, wallpaperBackgroundNode: WallpaperBackgroundNode?) {
|
||||
if theme !== self.theme {
|
||||
self.theme = theme
|
||||
|
||||
self.highlightNode.image = PresentationResourcesChat.chatInputButtonPanelButtonHighlightImage(theme)
|
||||
|
||||
self.updateIcon()
|
||||
}
|
||||
|
||||
self.backgroundColorNode.backgroundColor = theme.chat.inputButtonPanel.buttonFillColor
|
||||
if let alpha = self.backgroundColorNode.backgroundColor?.alpha, alpha < 1.0 {
|
||||
self.backgroundColorNode.layer.compositingFilter = "softLightBlendMode"
|
||||
self.backgroundAdditionalColorNode.isHidden = false
|
||||
} else {
|
||||
self.backgroundColorNode.layer.compositingFilter = nil
|
||||
self.backgroundAdditionalColorNode.isHidden = true
|
||||
}
|
||||
|
||||
if wallpaperBackgroundNode?.hasExtraBubbleBackground() == true {
|
||||
if self.backgroundNode == nil, let backgroundContent = wallpaperBackgroundNode?.makeBubbleBackground(for: .free) {
|
||||
self.backgroundNode = backgroundContent
|
||||
self.backgroundContainerNode.insertSubnode(backgroundContent, at: 0)
|
||||
|
||||
self.setNeedsLayout()
|
||||
}
|
||||
} else {
|
||||
self.backgroundNode?.removeFromSupernode()
|
||||
self.backgroundNode = nil
|
||||
}
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
super.layout()
|
||||
|
||||
self.backgroundContainerNode.frame = self.bounds
|
||||
self.backgroundColorNode.frame = CGRect(origin: .zero, size: CGSize(width: self.bounds.width, height: self.bounds.height - 1.0))
|
||||
self.backgroundAdditionalColorNode.frame = self.backgroundColorNode.frame
|
||||
self.backgroundNode?.frame = self.backgroundColorNode.frame
|
||||
|
||||
self.highlightNode.frame = self.bounds
|
||||
|
||||
if let (rect, containerSize) = self.absoluteRect {
|
||||
self.update(rect: rect, within: containerSize, transition: .immediate)
|
||||
}
|
||||
self.backgroundView.frame = CGRect(origin: .zero, size: CGSize(width: self.bounds.width, height: self.bounds.height))
|
||||
|
||||
if let iconNode = self.iconNode {
|
||||
iconNode.frame = CGRect(x: self.frame.width - 16.0, y: 4.0, width: 12.0, height: 12.0)
|
||||
}
|
||||
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: self.bounds.width - 16.0, height: self.bounds.height))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.bounds.width - textSize.width) / 2.0), y: floorToScreenPixels((self.bounds.height - textSize.height) / 2.0)), size: textSize)
|
||||
var maxTextWidth = size.width - 16.0
|
||||
let iconSize = CGSize(width: 24.0, height: 24.0)
|
||||
let iconSpacing: CGFloat = 6.0
|
||||
if let iconFileId = button.style?.iconFileId {
|
||||
let icon: ComponentView<Empty>
|
||||
if let current = self.icon {
|
||||
icon = current
|
||||
} else {
|
||||
icon = ComponentView()
|
||||
self.icon = icon
|
||||
}
|
||||
maxTextWidth -= iconSize.width + iconSpacing
|
||||
|
||||
var animationContent: EmojiStatusComponent.AnimationContent = .customEmoji(fileId: iconFileId)
|
||||
if let file = message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: iconFileId)] as? TelegramMediaFile {
|
||||
animationContent = .file(file: file)
|
||||
}
|
||||
|
||||
let _ = icon.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
content: .animation(
|
||||
content: animationContent,
|
||||
size: iconSize,
|
||||
placeholderColor: theme.overallDarkAppearance ? UIColor(white: 1.0, alpha: 0.1) : UIColor(white: 0.0, alpha: 0.1),
|
||||
themeColor: theme.list.itemPrimaryTextColor,
|
||||
loopMode: .count(0)
|
||||
),
|
||||
isVisibleForAnimations: true,
|
||||
action: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: iconSize
|
||||
)
|
||||
} else if let icon = self.icon {
|
||||
self.icon = nil
|
||||
icon.view?.removeFromSuperview()
|
||||
}
|
||||
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: maxTextWidth, height: self.bounds.height))
|
||||
|
||||
var textFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.bounds.width - textSize.width) / 2.0), y: floorToScreenPixels((self.bounds.height - textSize.height) / 2.0)), size: textSize)
|
||||
if let iconView = self.icon?.view {
|
||||
let contentX = floor((size.width - textSize.width - iconSize.width - iconSpacing) * 0.5)
|
||||
textFrame.origin.x = contentX + iconSize.width + iconSpacing
|
||||
|
||||
let iconFrame = CGRect(origin: CGPoint(x: contentX, y: floor((size.height - iconSize.height) * 0.5)), size: iconSize)
|
||||
if iconView.superview == nil {
|
||||
self.view.addSubview(iconView)
|
||||
}
|
||||
iconView.frame = iconFrame
|
||||
}
|
||||
|
||||
self.textNode.frame = textFrame
|
||||
}
|
||||
}
|
||||
|
||||
public final class ChatButtonKeyboardInputNode: ChatInputNode {
|
||||
public final class ChatButtonKeyboardInputNode: ChatInputNode, UIScrollViewDelegate {
|
||||
private let context: AccountContext
|
||||
private let controllerInteraction: ChatControllerInteraction
|
||||
|
||||
private let backgroundView: BlurredBackgroundView
|
||||
private let backgroundTintView: UIImageView
|
||||
private let backgroundTintMaskView: UIView
|
||||
private let backgroundChromeView: UIImageView
|
||||
|
||||
private let scrollNode: ASScrollNode
|
||||
|
||||
private var backgroundNode: WallpaperBubbleBackgroundNode?
|
||||
private let backgroundColorNode: ASDisplayNode
|
||||
|
||||
private var buttonNodes: [ChatButtonKeyboardInputButtonNode] = []
|
||||
private var message: Message?
|
||||
|
|
@ -204,19 +209,42 @@ public final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||
self.context = context
|
||||
self.controllerInteraction = controllerInteraction
|
||||
|
||||
self.scrollNode = ASScrollNode()
|
||||
self.backgroundView = BlurredBackgroundView(color: .black, enableBlur: true)
|
||||
self.backgroundTintView = UIImageView()
|
||||
|
||||
self.backgroundColorNode = ASDisplayNode()
|
||||
self.backgroundTintMaskView = UIView()
|
||||
self.backgroundTintMaskView.backgroundColor = .white
|
||||
|
||||
self.backgroundChromeView = UIImageView()
|
||||
|
||||
self.scrollNode = ASScrollNode()
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.backgroundColorNode)
|
||||
self.view.addSubview(self.backgroundView)
|
||||
|
||||
self.view.addSubview(self.backgroundTintView)
|
||||
if let filter = CALayer.luminanceToAlpha() {
|
||||
self.backgroundTintMaskView.layer.filters = [filter]
|
||||
self.backgroundTintView.mask = self.backgroundTintMaskView
|
||||
}
|
||||
|
||||
self.view.addSubview(self.backgroundChromeView)
|
||||
|
||||
self.addSubnode(self.scrollNode)
|
||||
self.scrollNode.view.delaysContentTouches = false
|
||||
self.scrollNode.view.canCancelContentTouches = true
|
||||
self.scrollNode.view.alwaysBounceHorizontal = false
|
||||
self.scrollNode.view.alwaysBounceVertical = false
|
||||
self.scrollNode.view.delegate = self
|
||||
|
||||
self.scrollNode.view.clipsToBounds = true
|
||||
self.scrollNode.cornerRadius = 30.0
|
||||
self.scrollNode.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||||
|
||||
self.backgroundTintMaskView.clipsToBounds = true
|
||||
self.backgroundTintMaskView.layer.cornerRadius = 30.0
|
||||
self.backgroundTintMaskView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||||
}
|
||||
|
||||
override public func didLoad() {
|
||||
|
|
@ -227,38 +255,16 @@ public final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||
}
|
||||
}
|
||||
|
||||
private var absoluteRect: (CGRect, CGSize)?
|
||||
override public func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition) {
|
||||
self.absoluteRect = (rect, containerSize)
|
||||
|
||||
if let backgroundNode = self.backgroundNode {
|
||||
var backgroundFrame = backgroundNode.frame
|
||||
backgroundFrame.origin.x += rect.minX
|
||||
backgroundFrame.origin.y += rect.minY
|
||||
backgroundNode.update(rect: backgroundFrame, within: containerSize, transition: transition)
|
||||
}
|
||||
|
||||
for buttonNode in self.buttonNodes {
|
||||
var buttonFrame = buttonNode.frame
|
||||
buttonFrame.origin.x += rect.minX
|
||||
buttonFrame.origin.y += rect.minY
|
||||
buttonNode.update(rect: buttonFrame, within: containerSize, transition: transition)
|
||||
}
|
||||
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
var bounds = self.backgroundTintMaskView.bounds
|
||||
bounds.origin.y = scrollView.contentOffset.y
|
||||
self.backgroundTintMaskView.bounds = bounds
|
||||
}
|
||||
|
||||
override public func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, standardInputHeight: CGFloat, inputHeight: CGFloat, maximumHeight: CGFloat, inputPanelHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, layoutMetrics: LayoutMetrics, deviceMetrics: DeviceMetrics, isVisible: Bool, isExpanded: Bool) -> (CGFloat, CGFloat) {
|
||||
if self.backgroundNode == nil {
|
||||
if let backgroundNode = self.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) {
|
||||
self.backgroundNode = backgroundNode
|
||||
self.insertSubnode(backgroundNode, at: 0)
|
||||
}
|
||||
}
|
||||
|
||||
let updatedTheme = self.theme !== interfaceState.theme
|
||||
if updatedTheme {
|
||||
self.theme = interfaceState.theme
|
||||
|
||||
self.backgroundColorNode.backgroundColor = interfaceState.theme.chat.inputButtonPanel.panelBackgroundColor
|
||||
}
|
||||
|
||||
var validatedMarkup: ReplyMarkupMessageAttribute?
|
||||
|
|
@ -275,9 +281,9 @@ public final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||
|
||||
self.message = interfaceState.keyboardButtonsMessage
|
||||
|
||||
if let markup = validatedMarkup {
|
||||
let verticalInset: CGFloat = 16.0
|
||||
let sideInset: CGFloat = 16.0 + leftInset
|
||||
if let markup = validatedMarkup, let message = self.message {
|
||||
let verticalInset: CGFloat = 18.0
|
||||
let sideInset: CGFloat = 18.0 + leftInset
|
||||
var buttonHeight: CGFloat = 43.0
|
||||
let columnSpacing: CGFloat = 6.0
|
||||
let rowSpacing: CGFloat = 5.0
|
||||
|
|
@ -305,15 +311,14 @@ public final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||
buttonNode.titleNode.maximumNumberOfLines = 2
|
||||
buttonNode.addTarget(self, action: #selector(self.buttonPressed(_:)), forControlEvents: [.touchUpInside])
|
||||
self.scrollNode.addSubnode(buttonNode)
|
||||
self.backgroundTintMaskView.addSubview(buttonNode.tintMaskView)
|
||||
self.buttonNodes.append(buttonNode)
|
||||
}
|
||||
buttonNode.updateTheme(theme: interfaceState.theme, wallpaperBackgroundNode: self.controllerInteraction.presentationContext.backgroundNode)
|
||||
buttonIndex += 1
|
||||
if buttonNode.button != button || updatedTheme {
|
||||
buttonNode.button = button
|
||||
buttonNode.setAttributedTitle(NSAttributedString(string: button.title, font: Font.regular(16.0), textColor: interfaceState.theme.chat.inputButtonPanel.buttonTextColor, paragraphAlignment: .center), for: [])
|
||||
}
|
||||
buttonNode.frame = CGRect(origin: CGPoint(x: sideInset + CGFloat(columnIndex) * (buttonWidth + columnSpacing), y: verticalOffset), size: CGSize(width: buttonWidth, height: buttonHeight))
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: sideInset + CGFloat(columnIndex) * (buttonWidth + columnSpacing), y: verticalOffset), size: CGSize(width: buttonWidth, height: buttonHeight))
|
||||
buttonNode.frame = buttonFrame
|
||||
buttonNode.tintMaskView.frame = buttonFrame
|
||||
buttonNode.update(context: self.context, size: buttonFrame.size, theme: interfaceState.theme, wallpaperBackgroundNode: self.controllerInteraction.presentationContext.backgroundNode, button: button, message: EngineMessage(message))
|
||||
columnIndex += 1
|
||||
}
|
||||
verticalOffset += buttonHeight + rowSpacing
|
||||
|
|
@ -321,6 +326,7 @@ public final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||
|
||||
for i in (buttonIndex ..< self.buttonNodes.count).reversed() {
|
||||
self.buttonNodes[i].removeFromSupernode()
|
||||
self.buttonNodes[i].tintMaskView.removeFromSuperview()
|
||||
self.buttonNodes.remove(at: i)
|
||||
}
|
||||
|
||||
|
|
@ -335,15 +341,28 @@ public final class ChatButtonKeyboardInputNode: ChatInputNode {
|
|||
self.scrollNode.view.setContentOffset(CGPoint(), animated: false)
|
||||
}
|
||||
|
||||
if let backgroundNode = self.backgroundNode {
|
||||
backgroundNode.frame = CGRect(origin: .zero, size: CGSize(width: width, height: panelHeight))
|
||||
}
|
||||
self.backgroundColorNode.frame = CGRect(origin: .zero, size: CGSize(width: width, height: panelHeight))
|
||||
var backgroundFrame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight))
|
||||
backgroundFrame.size.height += 32.0
|
||||
let keyboardCornerRadius: CGFloat = 30.0
|
||||
|
||||
if let (rect, containerSize) = self.absoluteRect {
|
||||
self.updateAbsoluteRect(rect, within: containerSize, transition: transition)
|
||||
if self.backgroundChromeView.image == nil || updatedTheme {
|
||||
self.backgroundChromeView.image = GlassBackgroundView.generateForegroundImage(size: CGSize(width: keyboardCornerRadius * 2.0, height: keyboardCornerRadius * 2.0), isDark: interfaceState.theme.overallDarkAppearance, fillColor: .clear)
|
||||
}
|
||||
|
||||
if self.backgroundTintView.image == nil {
|
||||
self.backgroundTintView.image = generateStretchableFilledCircleImage(diameter: keyboardCornerRadius * 2.0, color: .white)?.withRenderingMode(.alwaysTemplate)
|
||||
}
|
||||
self.backgroundTintView.tintColor = interfaceState.theme.chat.inputButtonPanel.panelBackgroundColor
|
||||
|
||||
transition.updateFrame(view: self.backgroundView, frame: backgroundFrame)
|
||||
transition.updateFrame(view: self.backgroundTintView, frame: backgroundFrame)
|
||||
transition.updateFrame(view: self.backgroundTintMaskView, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||
|
||||
self.backgroundView.updateColor(color: .clear, forceKeepBlur: true, transition: .immediate)
|
||||
self.backgroundView.update(size: backgroundFrame.size, cornerRadius: keyboardCornerRadius, maskedCorners: [.layerMinXMinYCorner, .layerMaxXMinYCorner], transition: transition)
|
||||
|
||||
transition.updateFrame(view: self.backgroundChromeView, frame: backgroundFrame.insetBy(dx: -1.0, dy: 0.0))
|
||||
|
||||
return (panelHeight, 0.0)
|
||||
} else {
|
||||
return (0.0, 0.0)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ swift_library(
|
|||
"//submodules/WallpaperBackgroundNode",
|
||||
"//submodules/UrlHandling",
|
||||
"//submodules/TelegramUI/Components/TextLoadingEffect",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/Components/ComponentDisplayAdapters",
|
||||
"//submodules/TelegramUI/Components/EmojiStatusComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ import WallpaperBackgroundNode
|
|||
import UrlHandling
|
||||
import SwiftSignalKit
|
||||
import TextLoadingEffect
|
||||
import ComponentFlow
|
||||
import ComponentDisplayAdapters
|
||||
import EmojiStatusComponent
|
||||
|
||||
private let titleFont = Font.medium(16.0)
|
||||
|
||||
|
|
@ -70,9 +73,12 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
private var iconNode: ASImageNode?
|
||||
private var buttonView: HighlightTrackingButton?
|
||||
|
||||
private var icon: ComponentView<Empty>?
|
||||
|
||||
private var wallpaperBackgroundNode: WallpaperBackgroundNode?
|
||||
private var backgroundContent: WallpaperBubbleBackgroundNode?
|
||||
private var backgroundColorNode: ASDisplayNode?
|
||||
private var backgroundColorView: UIImageView?
|
||||
|
||||
private var maskPath: CGPath?
|
||||
private var loadingEffectView: TextLoadingEffectView?
|
||||
|
|
@ -175,6 +181,8 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
self.view.insertSubview(loadingEffectView, belowSubview: iconNode.view)
|
||||
} else if let titleNode = self.titleNode, titleNode.view.superview != nil {
|
||||
self.view.insertSubview(loadingEffectView, belowSubview: titleNode.view)
|
||||
} else if let iconView = self.icon?.view, iconView.superview != nil {
|
||||
self.view.insertSubview(loadingEffectView, belowSubview: iconView)
|
||||
} else {
|
||||
self.view.addSubview(loadingEffectView)
|
||||
}
|
||||
|
|
@ -320,6 +328,12 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
customIconSpaceWidth = 3.0 + iconImage.size.width
|
||||
}
|
||||
|
||||
let emojiIconSize = CGSize(width: 24.0, height: 24.0)
|
||||
let emojiIconSpacing: CGFloat = 6.0
|
||||
if button.style?.iconFileId != nil {
|
||||
customIconSpaceWidth = emojiIconSpacing + emojiIconSize.width
|
||||
}
|
||||
|
||||
let (titleSize, titleApply) = titleLayout(TextNodeLayoutArguments(attributedString: attributedTitle, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(44.0, constrainedWidth - minimumSideInset - minimumSideInset - customIconSpaceWidth), height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets(top: 1.0, left: 0.0, bottom: 1.0, right: 0.0)))
|
||||
let contentWidth = titleSize.size.width + sideInset + sideInset + customIconSpaceWidth
|
||||
|
||||
|
|
@ -345,8 +359,6 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
node.longTapRecognizer?.isEnabled = false
|
||||
}
|
||||
|
||||
//animation.animator.updateFrame(layer: node.backgroundBlurNode.layer, frame: CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0)), completion: nil)
|
||||
|
||||
if node.backgroundBlurView == nil {
|
||||
if let backgroundBlurView = backgroundNode?.makeFreeBackground() {
|
||||
node.backgroundBlurView = backgroundBlurView
|
||||
|
|
@ -357,9 +369,6 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
animation.animator.updateFrame(layer: backgroundBlurView.view.layer, frame: CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0)), completion: nil)
|
||||
}
|
||||
|
||||
/*node.backgroundBlurNode.update(size: node.backgroundBlurNode.bounds.size, cornerRadius: 0.0, animator: animation.animator)
|
||||
node.backgroundBlurNode.updateColor(color: selectDateFillStaticColor(theme: theme.theme, wallpaper: theme.wallpaper), enableBlur: context.sharedContext.energyUsageSettings.fullTranslucency && dateFillNeedsBlur(theme: theme.theme, wallpaper: theme.wallpaper), transition: .immediate)*/
|
||||
|
||||
if backgroundNode?.hasExtraBubbleBackground() == true {
|
||||
if node.backgroundContent == nil, let backgroundContent = backgroundNode?.makeBubbleBackground(for: .free) {
|
||||
backgroundContent.clipsToBounds = true
|
||||
|
|
@ -401,7 +410,6 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
node.backgroundBlurView?.view.isHidden = false
|
||||
}
|
||||
|
||||
|
||||
let rect = CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0))
|
||||
let maskPath: CGPath?
|
||||
var needsMask = true
|
||||
|
|
@ -435,6 +443,40 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
node.layer.mask = nil
|
||||
}
|
||||
}
|
||||
|
||||
if let color = button.style?.color {
|
||||
let backgroundColorView: UIImageView
|
||||
if let current = node.backgroundColorView {
|
||||
backgroundColorView = current
|
||||
} else {
|
||||
backgroundColorView = UIImageView()
|
||||
node.backgroundColorView = backgroundColorView
|
||||
|
||||
if let iconNode = node.iconNode, iconNode.view.superview != nil {
|
||||
node.view.insertSubview(backgroundColorView, belowSubview: iconNode.view)
|
||||
} else if let titleNode = node.titleNode, titleNode.view.superview != nil {
|
||||
node.view.insertSubview(backgroundColorView, belowSubview: titleNode.view)
|
||||
} else if let iconView = node.icon?.view, iconView.superview != nil {
|
||||
node.view.insertSubview(backgroundColorView, belowSubview: iconView)
|
||||
} else {
|
||||
node.view.addSubview(backgroundColorView)
|
||||
}
|
||||
}
|
||||
|
||||
animation.animator.updateFrame(layer: backgroundColorView.layer, frame: CGRect(origin: CGPoint(), size: CGSize(width: max(0.0, width), height: 42.0)), completion: nil)
|
||||
|
||||
switch color {
|
||||
case .primary:
|
||||
backgroundColorView.backgroundColor = UIColor(rgb: 0x0067D7, alpha: 0.55)
|
||||
case .danger:
|
||||
backgroundColorView.backgroundColor = UIColor(rgb: 0xD5000C, alpha: 0.55)
|
||||
case .success:
|
||||
backgroundColorView.backgroundColor = UIColor(rgb: 0x127E2D, alpha: 0.55)
|
||||
}
|
||||
} else if let backgroundColorView = node.backgroundColorView {
|
||||
node.backgroundColorView = nil
|
||||
backgroundColorView.removeFromSuperview()
|
||||
}
|
||||
|
||||
if iconImage != nil {
|
||||
if node.iconNode == nil {
|
||||
|
|
@ -459,7 +501,10 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
var titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.size.width) / 2.0), y: floor((42.0 - titleSize.size.height) / 2.0) + 1.0), size: titleSize.size)
|
||||
if let image = node.iconNode?.image, customInfo?.icon != nil {
|
||||
|
||||
if button.style?.iconFileId != nil {
|
||||
titleFrame.origin.x = floorToScreenPixels((width - titleSize.size.width - emojiIconSize.width - emojiIconSpacing) * 0.5) + emojiIconSize.width + emojiIconSpacing
|
||||
} else if let image = node.iconNode?.image, customInfo?.icon != nil {
|
||||
if customInfo?.icon == .actionArrow {
|
||||
titleFrame.origin.x = floorToScreenPixels((width - titleSize.size.width - image.size.width + 1.0) * 0.5) - 0.0
|
||||
} else {
|
||||
|
|
@ -486,6 +531,56 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||
animation.animator.updateFrame(layer: iconNode.layer, frame: iconFrame, completion: nil)
|
||||
}
|
||||
|
||||
if let iconFileId = button.style?.iconFileId {
|
||||
let icon: ComponentView<Empty>
|
||||
var iconTransition = animation.animator
|
||||
if let current = node.icon {
|
||||
icon = current
|
||||
} else {
|
||||
iconTransition = ListViewItemUpdateAnimation.None.animator
|
||||
icon = ComponentView()
|
||||
node.icon = icon
|
||||
}
|
||||
|
||||
var animationContent: EmojiStatusComponent.AnimationContent = .customEmoji(fileId: iconFileId)
|
||||
if let file = message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: iconFileId)] as? TelegramMediaFile {
|
||||
animationContent = .file(file: file)
|
||||
}
|
||||
|
||||
let _ = icon.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
context: context,
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
content: .animation(
|
||||
content: animationContent,
|
||||
size: emojiIconSize,
|
||||
placeholderColor: theme.theme.overallDarkAppearance ? UIColor(white: 1.0, alpha: 0.1) : UIColor(white: 0.0, alpha: 0.1),
|
||||
themeColor: titleColor,
|
||||
loopMode: .count(0)
|
||||
),
|
||||
isVisibleForAnimations: true,
|
||||
action: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: emojiIconSize
|
||||
)
|
||||
|
||||
let contentX = titleFrame.origin.x - emojiIconSize.width - emojiIconSpacing
|
||||
|
||||
let iconFrame = CGRect(origin: CGPoint(x: contentX, y: floor((42.0 - emojiIconSize.height) * 0.5) - 1.0), size: emojiIconSize)
|
||||
if let iconView = icon.view {
|
||||
if iconView.superview == nil {
|
||||
node.view.addSubview(iconView)
|
||||
}
|
||||
iconTransition.updateFrame(layer: iconView.layer, frame: iconFrame, completion: nil)
|
||||
}
|
||||
} else if let icon = node.icon {
|
||||
node.icon = nil
|
||||
icon.view?.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let (rect, size) = node.absolutePosition {
|
||||
node.updateAbsoluteRect(rect, within: size)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1410,11 +1410,11 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||
ReplyMarkupMessageAttribute(
|
||||
rows: [
|
||||
ReplyMarkupRow(buttons: [
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionReject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline)),
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionApprove, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove))
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionReject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline), style: ReplyMarkupButton.Style(color: .danger, iconFileId: nil)),
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionApprove, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove), style: ReplyMarkupButton.Style(color: .success, iconFileId: nil))
|
||||
]),
|
||||
ReplyMarkupRow(buttons: [
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionSuggestChanges, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonSuggestChanges))
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionSuggestChanges, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonSuggestChanges), style: nil)
|
||||
])
|
||||
],
|
||||
flags: [],
|
||||
|
|
|
|||
|
|
@ -2848,7 +2848,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||
ReplyMarkupMessageAttribute(
|
||||
rows: [
|
||||
ReplyMarkupRow(
|
||||
buttons: [ReplyMarkupButton(title: item.presentationData.strings.Channel_AdminLog_ShowMoreMessages(Int32(messages.count - 1)), titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: MemoryBuffer(data: Data())))]
|
||||
buttons: [ReplyMarkupButton(title: item.presentationData.strings.Channel_AdminLog_ShowMoreMessages(Int32(messages.count - 1)), titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: MemoryBuffer(data: Data())), style: nil)]
|
||||
)
|
||||
],
|
||||
flags: [],
|
||||
|
|
@ -2887,8 +2887,8 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||
ReplyMarkupMessageAttribute(
|
||||
rows: [
|
||||
ReplyMarkupRow(buttons: [
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_GiftPurchaseOffer_Reject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline)),
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_GiftPurchaseOffer_Accept, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove))
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_GiftPurchaseOffer_Reject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline), style: ReplyMarkupButton.Style(color: .danger, iconFileId: nil)),
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_GiftPurchaseOffer_Accept, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove), style: ReplyMarkupButton.Style(color: .success, iconFileId: nil))
|
||||
])
|
||||
],
|
||||
flags: [],
|
||||
|
|
@ -2936,11 +2936,11 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||
ReplyMarkupMessageAttribute(
|
||||
rows: [
|
||||
ReplyMarkupRow(buttons: [
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionReject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline)),
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionApprove, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove))
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionReject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline), style: ReplyMarkupButton.Style(color: .danger, iconFileId: nil)),
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionApprove, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove), style: ReplyMarkupButton.Style(color: .success, iconFileId: nil))
|
||||
]),
|
||||
ReplyMarkupRow(buttons: [
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionSuggestChanges, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonSuggestChanges))
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionSuggestChanges, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonSuggestChanges), style: nil)
|
||||
])
|
||||
],
|
||||
flags: [],
|
||||
|
|
@ -2974,7 +2974,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||
ReplyMarkupMessageAttribute(
|
||||
rows: [
|
||||
ReplyMarkupRow(buttons: [
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_MessageContinueLastThread, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: button))
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_MessageContinueLastThread, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: button), style: nil)
|
||||
])
|
||||
],
|
||||
flags: [],
|
||||
|
|
|
|||
|
|
@ -897,11 +897,11 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||
ReplyMarkupMessageAttribute(
|
||||
rows: [
|
||||
ReplyMarkupRow(buttons: [
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionReject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline)),
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionApprove, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove))
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionReject, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonDecline), style: ReplyMarkupButton.Style(color: .danger, iconFileId: nil)),
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionApprove, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonApprove), style: ReplyMarkupButton.Style(color: .success, iconFileId: nil))
|
||||
]),
|
||||
ReplyMarkupRow(buttons: [
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionSuggestChanges, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonSuggestChanges))
|
||||
ReplyMarkupButton(title: item.presentationData.strings.Chat_PostApproval_Message_ActionSuggestChanges, titleWhenForwarded: nil, action: .callback(requiresPassword: false, data: buttonSuggestChanges), style: nil)
|
||||
])
|
||||
],
|
||||
flags: [],
|
||||
|
|
|
|||
|
|
@ -1008,6 +1008,14 @@ public final class NavigationBarImpl: ASDisplayNode, NavigationBar {
|
|||
}
|
||||
}
|
||||
|
||||
if (leftTitleInset == leftInset) != (rightTitleInset == rightInset) {
|
||||
if rightTitleInset == rightInset {
|
||||
rightTitleInset = leftTitleInset
|
||||
} else if leftTitleInset == leftInset {
|
||||
leftTitleInset = rightTitleInset
|
||||
}
|
||||
}
|
||||
|
||||
if self.titleNode.view.superview != nil {
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: max(1.0, size.width - max(leftTitleInset, rightTitleInset) * 2.0), height: nominalHeight))
|
||||
|
||||
|
|
|
|||
|
|
@ -417,6 +417,7 @@ private final class PeerInfoPendingPane {
|
|||
sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?,
|
||||
initialStoryFolderId: Int64?,
|
||||
initialGiftCollectionId: Int64?,
|
||||
switchToMediaTarget: PeerInfoSwitchToMediaTarget?,
|
||||
key: PeerInfoPaneKey,
|
||||
hasBecomeReady: @escaping (PeerInfoPaneKey) -> Void,
|
||||
parentController: ViewController?,
|
||||
|
|
@ -520,7 +521,7 @@ private final class PeerInfoPendingPane {
|
|||
openAddStory()
|
||||
}
|
||||
case .media:
|
||||
let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .photoOrVideo, captureProtected: captureProtected)
|
||||
let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .photoOrVideo, captureProtected: captureProtected, initialFocusMessageIndex: switchToMediaTarget?.kind == .photoVideo ? switchToMediaTarget?.messageIndex : nil)
|
||||
paneNode = visualPaneNode
|
||||
visualPaneNode.openCurrentDate = {
|
||||
openMediaCalendar()
|
||||
|
|
@ -529,15 +530,15 @@ private final class PeerInfoPendingPane {
|
|||
paneDidScroll()
|
||||
}
|
||||
case .files:
|
||||
let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .files, captureProtected: captureProtected)
|
||||
let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .files, captureProtected: captureProtected, initialFocusMessageIndex: switchToMediaTarget?.kind == .photoVideo ? switchToMediaTarget?.messageIndex : nil)
|
||||
paneNode = visualPaneNode
|
||||
case .links:
|
||||
paneNode = PeerInfoListPaneNode(context: context, updatedPresentationData: updatedPresentationData, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, tagMask: .webPage)
|
||||
case .voice:
|
||||
let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .voiceAndVideoMessages, captureProtected: captureProtected)
|
||||
let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .voiceAndVideoMessages, captureProtected: captureProtected, initialFocusMessageIndex: nil)
|
||||
paneNode = visualPaneNode
|
||||
case .music:
|
||||
let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .music, captureProtected: captureProtected)
|
||||
let visualPaneNode = PeerInfoVisualMediaPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .music, captureProtected: captureProtected, initialFocusMessageIndex: nil)
|
||||
paneNode = visualPaneNode
|
||||
case .gifs:
|
||||
let visualPaneNode = PeerInfoGifPaneNode(context: context, chatControllerInteraction: chatControllerInteraction, peerId: chatLocationPeerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder, contentType: .gifs)
|
||||
|
|
@ -626,6 +627,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
|
|||
private var shouldFadeIn = false
|
||||
private var initialStoryFolderId: Int64?
|
||||
private var initialGiftCollectionId: Int64?
|
||||
private var switchToMediaTarget: PeerInfoSwitchToMediaTarget?
|
||||
|
||||
private var isDraggingTabs: Bool = false
|
||||
private var transitionFraction: CGFloat = 0.0
|
||||
|
|
@ -653,7 +655,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
|
|||
|
||||
private let initialPaneKey: PeerInfoPaneKey?
|
||||
|
||||
init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: PeerId, chatLocation: ChatLocation, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, isMediaOnly: Bool, initialPaneKey: PeerInfoPaneKey?, initialStoryFolderId: Int64?, initialGiftCollectionId: Int64?) {
|
||||
init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: PeerId, chatLocation: ChatLocation, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, isMediaOnly: Bool, initialPaneKey: PeerInfoPaneKey?, initialStoryFolderId: Int64?, initialGiftCollectionId: Int64?, switchToMediaTarget: PeerInfoSwitchToMediaTarget?) {
|
||||
self.context = context
|
||||
self.updatedPresentationData = updatedPresentationData
|
||||
self.peerId = peerId
|
||||
|
|
@ -664,6 +666,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
|
|||
self.initialPaneKey = initialPaneKey
|
||||
self.initialStoryFolderId = initialStoryFolderId
|
||||
self.initialGiftCollectionId = initialGiftCollectionId
|
||||
self.switchToMediaTarget = switchToMediaTarget
|
||||
|
||||
self.tabsBackgroundContainer = GlassBackgroundContainerView()
|
||||
self.tabsBackgroundView = GlassBackgroundView()
|
||||
|
|
@ -1002,6 +1005,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
|
|||
var leftScope = false
|
||||
var initialStoryFolderId: Int64?
|
||||
var initialGiftCollectionId: Int64?
|
||||
var switchToMediaTarget: PeerInfoSwitchToMediaTarget?
|
||||
if case .stories = key {
|
||||
if let initialStoryFolderIdValue = self.initialStoryFolderId {
|
||||
self.initialStoryFolderId = nil
|
||||
|
|
@ -1014,6 +1018,18 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
|
|||
initialGiftCollectionId = initialGiftCollectionIdValue
|
||||
}
|
||||
}
|
||||
if case .media = key {
|
||||
if let switchToMediaTargetValue = self.switchToMediaTarget, case .photoVideo = switchToMediaTargetValue.kind {
|
||||
self.switchToMediaTarget = nil
|
||||
switchToMediaTarget = switchToMediaTargetValue
|
||||
}
|
||||
}
|
||||
if case .files = key {
|
||||
if let switchToMediaTargetValue = self.switchToMediaTarget, case .file = switchToMediaTargetValue.kind {
|
||||
self.switchToMediaTarget = nil
|
||||
switchToMediaTarget = switchToMediaTargetValue
|
||||
}
|
||||
}
|
||||
let pane = PeerInfoPendingPane(
|
||||
context: self.context,
|
||||
updatedPresentationData: self.updatedPresentationData,
|
||||
|
|
@ -1034,6 +1050,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
|
|||
sharedMediaFromForumTopic: self.sharedMediaFromForumTopic,
|
||||
initialStoryFolderId: initialStoryFolderId,
|
||||
initialGiftCollectionId: initialGiftCollectionId,
|
||||
switchToMediaTarget: switchToMediaTarget,
|
||||
key: key,
|
||||
hasBecomeReady: { [weak self] key in
|
||||
let apply: () -> Void = {
|
||||
|
|
|
|||
|
|
@ -213,13 +213,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
let chatLocation: ChatLocation
|
||||
let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
||||
let switchToStoryFolder: Int64?
|
||||
let switchToMediaTarget: PeerInfoSwitchToMediaTarget?
|
||||
let switchToGiftsTarget: PeerInfoSwitchToGiftsTarget?
|
||||
let sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?
|
||||
|
||||
let isSettings: Bool
|
||||
let isMyProfile: Bool
|
||||
let isMediaOnly: Bool
|
||||
let initialExpandPanes: Bool
|
||||
var initialExpandPanes: Bool
|
||||
|
||||
private(set) var presentationData: PresentationData
|
||||
|
||||
|
|
@ -346,7 +347,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
}
|
||||
private var didSetReady = false
|
||||
|
||||
init(controller: PeerInfoScreenImpl, context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool, isMyProfile: Bool, hintGroupInCommon: PeerId?, requestsContext: PeerInvitationImportersContext?, profileGiftsContext: ProfileGiftsContext?, starsContext: StarsContext?, tonContext: StarsContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, switchToGiftsTarget: PeerInfoSwitchToGiftsTarget?, switchToStoryFolder: Int64?, initialPaneKey: PeerInfoPaneKey?, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?) {
|
||||
init(controller: PeerInfoScreenImpl, context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool, isMyProfile: Bool, hintGroupInCommon: PeerId?, requestsContext: PeerInvitationImportersContext?, profileGiftsContext: ProfileGiftsContext?, starsContext: StarsContext?, tonContext: StarsContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, switchToGiftsTarget: PeerInfoSwitchToGiftsTarget?, switchToStoryFolder: Int64?, switchToMediaTarget: PeerInfoSwitchToMediaTarget?, initialPaneKey: PeerInfoPaneKey?, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?) {
|
||||
self.controller = controller
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
|
|
@ -363,6 +364,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
self.isMediaOnly = context.account.peerId == peerId && !isSettings && !isMyProfile
|
||||
self.initialExpandPanes = initialPaneKey != nil
|
||||
self.switchToStoryFolder = switchToStoryFolder
|
||||
self.switchToMediaTarget = switchToMediaTarget
|
||||
self.switchToGiftsTarget = switchToGiftsTarget
|
||||
self.sharedMediaFromForumTopic = sharedMediaFromForumTopic
|
||||
|
||||
|
|
@ -386,7 +388,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
break
|
||||
}
|
||||
|
||||
self.paneContainerNode = PeerInfoPaneContainerNode(context: context, updatedPresentationData: controller.updatedPresentationData, peerId: peerId, chatLocation: chatLocation, sharedMediaFromForumTopic: sharedMediaFromForumTopic, chatLocationContextHolder: chatLocationContextHolder, isMediaOnly: self.isMediaOnly, initialPaneKey: initialPaneKey, initialStoryFolderId: switchToStoryFolder, initialGiftCollectionId: switchToGiftCollection)
|
||||
self.paneContainerNode = PeerInfoPaneContainerNode(context: context, updatedPresentationData: controller.updatedPresentationData, peerId: peerId, chatLocation: chatLocation, sharedMediaFromForumTopic: sharedMediaFromForumTopic, chatLocationContextHolder: chatLocationContextHolder, isMediaOnly: self.isMediaOnly, initialPaneKey: initialPaneKey, initialStoryFolderId: switchToStoryFolder, initialGiftCollectionId: switchToGiftCollection, switchToMediaTarget: switchToMediaTarget)
|
||||
|
||||
super.init()
|
||||
|
||||
|
|
@ -2827,6 +2829,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
self.ignoreScrolling = true
|
||||
transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: paneAreaExpansionFinalPoint), size: self.scrollNode.bounds.size))
|
||||
self.ignoreScrolling = false
|
||||
self.headerNode.headerEdgeEffectContainer.center = CGPoint(x: 0.0, y: self.scrollNode.view.contentOffset.y)
|
||||
self.updateNavigation(transition: transition, additive: false, animateHeader: true)
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition, additive: true)
|
||||
|
|
@ -5748,7 +5751,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
|
||||
let navigationBarHeight: CGFloat = !self.isSettings && layout.isModalOverlay ? 68.0 : 60.0
|
||||
let paneContainerTopInset = navigationBarHeight + (layout.statusBarHeight ?? 0.0)
|
||||
self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, topInset: paneContainerTopInset, bottomInset: bottomInset, deviceMetrics: layout.deviceMetrics, visibleHeight: visibleHeight, expansionFraction: effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, areTabsHidden: self.headerNode.customNavigationContentNode != nil, disableTabSwitching: disableTabSwitching, navigationHeight: navigationHeight, transition: transition)
|
||||
self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, topInset: paneContainerTopInset, bottomInset: bottomInset, deviceMetrics: layout.deviceMetrics, visibleHeight: visibleHeight, expansionFraction: self.initialExpandPanes ? 1.0 : effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, areTabsHidden: self.headerNode.customNavigationContentNode != nil, disableTabSwitching: disableTabSwitching, navigationHeight: navigationHeight, transition: transition)
|
||||
|
||||
transition.updateFrame(node: self.headerNode.navigationButtonContainer, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight)))
|
||||
var searchBarContainerY: CGFloat = layout.statusBarHeight ?? 0.0
|
||||
|
|
@ -6218,6 +6221,21 @@ public enum PeerInfoSwitchToGiftsTarget {
|
|||
case collection(Int64)
|
||||
}
|
||||
|
||||
public struct PeerInfoSwitchToMediaTarget {
|
||||
public enum Kind {
|
||||
case photoVideo
|
||||
case file
|
||||
}
|
||||
|
||||
public let kind: Kind
|
||||
public let messageIndex: EngineMessage.Index
|
||||
|
||||
public init(kind: Kind, messageIndex: EngineMessage.Index) {
|
||||
self.kind = kind
|
||||
self.messageIndex = messageIndex
|
||||
}
|
||||
}
|
||||
|
||||
public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortcutResponder {
|
||||
let context: AccountContext
|
||||
let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
||||
|
|
@ -6238,6 +6256,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||
private let switchToGiftsTarget: PeerInfoSwitchToGiftsTarget?
|
||||
private let switchToGroupsInCommon: Bool
|
||||
private let switchToStoryFolder: Int64?
|
||||
private let switchToMediaTarget: PeerInfoSwitchToMediaTarget?
|
||||
private let sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?
|
||||
let chatLocation: ChatLocation
|
||||
private let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
||||
|
|
@ -6321,6 +6340,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||
switchToGiftsTarget: PeerInfoSwitchToGiftsTarget? = nil,
|
||||
switchToGroupsInCommon: Bool = false,
|
||||
switchToStoryFolder: Int64? = nil,
|
||||
switchToMediaTarget: PeerInfoSwitchToMediaTarget? = nil,
|
||||
) {
|
||||
self.context = context
|
||||
self.updatedPresentationData = updatedPresentationData
|
||||
|
|
@ -6339,6 +6359,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||
self.switchToGiftsTarget = switchToGiftsTarget
|
||||
self.switchToGroupsInCommon = switchToGroupsInCommon
|
||||
self.switchToStoryFolder = switchToStoryFolder
|
||||
self.switchToMediaTarget = switchToMediaTarget
|
||||
self.sharedMediaFromForumTopic = sharedMediaFromForumTopic
|
||||
|
||||
if let forumTopicThread = forumTopicThread {
|
||||
|
|
@ -6684,8 +6705,15 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||
initialPaneKey = .groupsInCommon
|
||||
} else if self.switchToStoryFolder != nil {
|
||||
initialPaneKey = .stories
|
||||
} else if let switchToMediaTarget = self.switchToMediaTarget {
|
||||
switch switchToMediaTarget.kind {
|
||||
case .photoVideo:
|
||||
initialPaneKey = .media
|
||||
case .file:
|
||||
initialPaneKey = .files
|
||||
}
|
||||
}
|
||||
self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId, avatarInitiallyExpanded: self.avatarInitiallyExpanded, isOpenedFromChat: self.isOpenedFromChat, nearbyPeerDistance: self.nearbyPeerDistance, reactionSourceMessageId: self.reactionSourceMessageId, callMessages: self.callMessages, isSettings: self.isSettings, isMyProfile: self.isMyProfile, hintGroupInCommon: self.hintGroupInCommon, requestsContext: self.requestsContext, profileGiftsContext: self.profileGiftsContext, starsContext: self.starsContext, tonContext: self.tonContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, switchToGiftsTarget: self.switchToGiftsTarget, switchToStoryFolder: self.switchToStoryFolder, initialPaneKey: initialPaneKey, sharedMediaFromForumTopic: self.sharedMediaFromForumTopic)
|
||||
self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId, avatarInitiallyExpanded: self.avatarInitiallyExpanded, isOpenedFromChat: self.isOpenedFromChat, nearbyPeerDistance: self.nearbyPeerDistance, reactionSourceMessageId: self.reactionSourceMessageId, callMessages: self.callMessages, isSettings: self.isSettings, isMyProfile: self.isMyProfile, hintGroupInCommon: self.hintGroupInCommon, requestsContext: self.requestsContext, profileGiftsContext: self.profileGiftsContext, starsContext: self.starsContext, tonContext: self.tonContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, switchToGiftsTarget: self.switchToGiftsTarget, switchToStoryFolder: self.switchToStoryFolder, switchToMediaTarget: self.switchToMediaTarget, initialPaneKey: initialPaneKey, sharedMediaFromForumTopic: self.sharedMediaFromForumTopic)
|
||||
self.controllerNode.accountsAndPeers.set(self.accountsAndPeers.get() |> map { $0.1 })
|
||||
self.controllerNode.activeSessionsContextAndCount.set(self.activeSessionsContextAndCount.get())
|
||||
self.cachedDataPromise.set(self.controllerNode.cachedDataPromise.get())
|
||||
|
|
@ -6934,6 +6962,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||
}
|
||||
|
||||
self.controllerNode.refreshHasPersonalChannelsIfNeeded()
|
||||
self.controllerNode.initialExpandPanes = false
|
||||
}
|
||||
|
||||
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
|
|
|
|||
|
|
@ -1113,6 +1113,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
private let directMediaImageCache: DirectMediaImageCache
|
||||
private var items: SparseItemGrid.Items?
|
||||
private var didUpdateItemsOnce: Bool = false
|
||||
private var initialMessageIndex: EngineMessage.Index?
|
||||
|
||||
private var isDeceleratingAfterTracking = false
|
||||
|
||||
|
|
@ -1164,7 +1165,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
public init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, contentType: ContentType, captureProtected: Bool) {
|
||||
public init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, contentType: ContentType, captureProtected: Bool, initialFocusMessageIndex: EngineMessage.Index?) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.chatLocation = chatLocation
|
||||
|
|
@ -1173,6 +1174,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
self.contentType = contentType
|
||||
self.contentTypePromise = ValuePromise<ContentType>(contentType)
|
||||
self.stateTag = tagMaskForType(contentType)
|
||||
self.initialMessageIndex = initialFocusMessageIndex
|
||||
|
||||
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
|
|
@ -1234,7 +1236,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
threadId = message.threadId
|
||||
}
|
||||
|
||||
self.listSource = self.context.engine.messages.sparseMessageList(peerId: self.peerId, threadId: threadId, tag: tagMaskForType(self.contentType))
|
||||
self.listSource = self.context.engine.messages.sparseMessageList(peerId: self.peerId, threadId: threadId, tag: tagMaskForType(self.contentType), initialMessageIndex: initialFocusMessageIndex)
|
||||
if threadId == nil {
|
||||
switch contentType {
|
||||
case .photoOrVideo, .photo, .video:
|
||||
|
|
@ -1247,6 +1249,11 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
}
|
||||
|
||||
super.init()
|
||||
|
||||
if self.initialMessageIndex != nil {
|
||||
self.didSetReady = true
|
||||
self.ready.set(.single(true))
|
||||
}
|
||||
|
||||
let _ = (ApplicationSpecificNotice.getSharedMediaScrollingTooltip(accountManager: context.sharedContext.accountManager)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] count in
|
||||
|
|
@ -1720,6 +1727,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
}
|
||||
self.isRequestingView = true
|
||||
var firstTime = true
|
||||
var firstTimeRealData = true
|
||||
let queue = Queue()
|
||||
|
||||
self.listDisposable.set((self.listSource.state
|
||||
|
|
@ -1728,15 +1736,20 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
|
||||
var mappedItems: [SparseItemGrid.Item] = []
|
||||
var mappedHoles: [SparseItemGrid.HoleAnchor] = []
|
||||
for item in list.items {
|
||||
switch item.content {
|
||||
case let .message(message, isLocal):
|
||||
mappedItems.append(VisualMediaItem(index: item.index, message: message, localMonthTimestamp: Month(localTimestamp: message.timestamp + timezoneOffset).packedValue))
|
||||
if !isLocal {
|
||||
mappedHoles.append(VisualMediaHoleAnchor(index: item.index, messageId: message.id, localMonthTimestamp: Month(localTimestamp: message.timestamp + timezoneOffset).packedValue))
|
||||
var totalCount = list.totalCount
|
||||
if list.items.isEmpty && list.isLoading && list.totalCount == 0 {
|
||||
totalCount = 100
|
||||
} else {
|
||||
for item in list.items {
|
||||
switch item.content {
|
||||
case let .message(message, isLocal):
|
||||
mappedItems.append(VisualMediaItem(index: item.index, message: message, localMonthTimestamp: Month(localTimestamp: message.timestamp + timezoneOffset).packedValue))
|
||||
if !isLocal {
|
||||
mappedHoles.append(VisualMediaHoleAnchor(index: item.index, messageId: message.id, localMonthTimestamp: Month(localTimestamp: message.timestamp + timezoneOffset).packedValue))
|
||||
}
|
||||
case let .placeholder(id, timestamp):
|
||||
mappedHoles.append(VisualMediaHoleAnchor(index: item.index, messageId: id, localMonthTimestamp: Month(localTimestamp: timestamp + timezoneOffset).packedValue))
|
||||
}
|
||||
case let .placeholder(id, timestamp):
|
||||
mappedHoles.append(VisualMediaHoleAnchor(index: item.index, messageId: id, localMonthTimestamp: Month(localTimestamp: timestamp + timezoneOffset).packedValue))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1748,7 +1761,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
let items = SparseItemGrid.Items(
|
||||
items: mappedItems,
|
||||
holeAnchors: mappedHoles,
|
||||
count: list.totalCount,
|
||||
count: totalCount,
|
||||
itemBinding: strongSelf.itemGridBinding,
|
||||
headerText: nil,
|
||||
snapTopInset: true
|
||||
|
|
@ -1756,24 +1769,34 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
|
||||
let currentSynchronous = synchronous && firstTime
|
||||
let currentReloadAtTop = reloadAtTop && firstTime
|
||||
|
||||
var crossfade = currentReloadAtTop
|
||||
if firstTimeRealData && !list.isLoading {
|
||||
firstTimeRealData = false
|
||||
if !firstTime {
|
||||
crossfade = true
|
||||
}
|
||||
}
|
||||
|
||||
firstTime = false
|
||||
strongSelf.updateHistory(items: items, synchronous: currentSynchronous, reloadAtTop: currentReloadAtTop)
|
||||
strongSelf.updateHistory(items: items, synchronous: currentSynchronous, crossfade: crossfade)
|
||||
strongSelf.isRequestingView = false
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
private func updateHistory(items: SparseItemGrid.Items, synchronous: Bool, reloadAtTop: Bool) {
|
||||
private func updateHistory(items: SparseItemGrid.Items, synchronous: Bool, crossfade: Bool) {
|
||||
self.items = items
|
||||
|
||||
if let (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, navigationHeight, presentationData) = self.currentParams {
|
||||
var gridSnapshot: UIView?
|
||||
if reloadAtTop {
|
||||
if crossfade {
|
||||
gridSnapshot = self.itemGrid.view.snapshotView(afterScreenUpdates: false)
|
||||
}
|
||||
self.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, navigationHeight: navigationHeight, presentationData: presentationData, synchronous: false, transition: .immediate)
|
||||
if let gridSnapshot = gridSnapshot {
|
||||
self.view.addSubview(gridSnapshot)
|
||||
self.itemGrid.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
gridSnapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak gridSnapshot] _ in
|
||||
gridSnapshot?.removeFromSuperview()
|
||||
})
|
||||
|
|
@ -2194,6 +2217,23 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
|||
}
|
||||
|
||||
self.itemGrid.update(size: size, insets: UIEdgeInsets(top: topInset, left: sideInset, bottom: bottomInset, right: sideInset), useSideInsets: !isList, scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), lockScrollingAtTop: isScrollingLockedAtTop, fixedItemHeight: fixedItemHeight, fixedItemAspect: nil, items: items, theme: self.itemGridBinding.chatPresentationData.theme.theme, synchronous: wasFirstTime ? .full : .none)
|
||||
if let initialMessageIndexValue = self.initialMessageIndex, items.items.contains(where: { item in
|
||||
if let _ = item as? VisualMediaItem {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}) {
|
||||
self.initialMessageIndex = nil
|
||||
for item in items.items {
|
||||
if let item = item as? VisualMediaItem {
|
||||
if item.message.index <= initialMessageIndexValue {
|
||||
self.itemGrid.scrollToItem(at: item.index, force: true)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ public class WallpaperGalleryController: ViewController {
|
|||
}, currentItemNode: { [weak self] in
|
||||
return self?.galleryNode.pager.centralItemNode()
|
||||
})
|
||||
self.displayNode = WallpaperGalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction, pageGap: 0.0, disableTapNavigation: true)
|
||||
self.displayNode = WallpaperGalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction, titleView: nil, pageGap: 0.0, disableTapNavigation: true)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
(self.displayNode as? WallpaperGalleryControllerNode)?.nativeStatusBar = self.statusBar
|
||||
|
|
|
|||
|
|
@ -1377,189 +1377,232 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
}
|
||||
|
||||
let openChatMessageParams = OpenChatMessageParams(context: context, updatedPresentationData: self.updatedPresentationData, chatLocation: openChatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: self.chatLocationContextHolder, message: message, mediaIndex: params.mediaIndex, standalone: standalone, reverseMessageGalleryOrder: false, mode: mode, navigationController: self.effectiveNavigationController, dismissInput: { [weak self] in
|
||||
self?.chatDisplayNode.dismissInput()
|
||||
}, present: { [weak self] c, a, i in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
if case .current = i {
|
||||
c.presentationArguments = a
|
||||
c.statusBar.alphaUpdated = { [weak self] transition in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.updateStatusBarPresentation(animated: transition.isAnimated)
|
||||
}
|
||||
self.galleryPresentationContext.present(c, on: PresentationSurfaceLevel(rawValue: 0), blockInteraction: true, completion: {})
|
||||
} else {
|
||||
self.present(c, in: .window(.root), with: a, blockInteraction: true)
|
||||
}
|
||||
}, transitionNode: { [weak self] messageId, media, adjustRect in
|
||||
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||
if let self {
|
||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: adjustRect) {
|
||||
selectedNode = result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectedNode
|
||||
}, addToTransitionSurface: { [weak self] view in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let contextController = self.currentContextController {
|
||||
contextController.view.addSubview(view)
|
||||
} else {
|
||||
self.chatDisplayNode.historyNode.view.superview?.insertSubview(view, aboveSubview: self.chatDisplayNode.historyNode.view)
|
||||
}
|
||||
}, openUrl: { [weak self] url in
|
||||
self?.openUrl(url, concealed: false, skipConcealedAlert: isLocation, message: nil)
|
||||
}, openPeer: { [weak self] peer, navigation in
|
||||
self?.openPeer(peer: EnginePeer(peer), navigation: navigation, fromMessage: nil)
|
||||
}, callPeer: { [weak self] peerId, isVideo in
|
||||
self?.controllerInteraction?.callPeer(peerId, isVideo)
|
||||
}, openConferenceCall: { [weak self] message in
|
||||
self?.controllerInteraction?.openConferenceCall(message)
|
||||
}, enqueueMessage: { [weak self] message in
|
||||
self?.sendMessages([message])
|
||||
}, sendSticker: canSendMessagesToChat(self.presentationInterfaceState) ? { [weak self] fileReference, sourceNode, sourceRect in
|
||||
return self?.controllerInteraction?.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) ?? false
|
||||
} : nil, sendEmoji: canSendMessagesToChat(self.presentationInterfaceState) ? { [weak self] text, attribute in
|
||||
self?.controllerInteraction?.sendEmoji(text, attribute, false)
|
||||
} : nil, setupTemporaryHiddenMedia: { [weak self] signal, centralIndex, galleryMedia in
|
||||
if let self {
|
||||
self.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { [weak self] entry in
|
||||
if let self, let controllerInteraction = self.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
if let entry = entry as? InstantPageGalleryEntry, entry.index == centralIndex {
|
||||
messageIdAndMedia[message.id] = [galleryMedia]
|
||||
}
|
||||
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
itemNode.updateHiddenMedia()
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}, chatAvatarHiddenMedia: { [weak self] signal, media in
|
||||
if let self {
|
||||
self.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { [weak self] messageId in
|
||||
if let self, let controllerInteraction = self.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
if let messageId = messageId {
|
||||
messageIdAndMedia[messageId] = [media]
|
||||
}
|
||||
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
itemNode.updateHiddenMedia()
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}, actionInteraction: GalleryControllerActionInteraction(
|
||||
openUrl: { [weak self] url, concealed, forceExternal in
|
||||
if let self {
|
||||
self.openUrl(url, concealed: concealed, forceExternal: forceExternal, message: nil)
|
||||
}
|
||||
}, openUrlIn: { [weak self] url in
|
||||
if let self {
|
||||
self.openUrlIn(url)
|
||||
}
|
||||
}, openPeerMention: { [weak self] mention in
|
||||
if let self {
|
||||
self.controllerInteraction?.openPeerMention(mention, nil)
|
||||
}
|
||||
}, openPeer: { [weak self] peer in
|
||||
if let self {
|
||||
self.controllerInteraction?.openPeer(peer, .default, nil, .default)
|
||||
}
|
||||
}, openHashtag: { [weak self] peerName, hashtag in
|
||||
if let self {
|
||||
self.controllerInteraction?.openHashtag(peerName, hashtag)
|
||||
}
|
||||
}, openBotCommand: { [weak self] command in
|
||||
if let self {
|
||||
self.controllerInteraction?.sendBotCommand(nil, command)
|
||||
}
|
||||
}, openAd: { [weak self] messageId in
|
||||
if let self {
|
||||
self.controllerInteraction?.activateAdAction(messageId, nil, true, true)
|
||||
}
|
||||
}, addContact: { [weak self] phoneNumber in
|
||||
if let self {
|
||||
self.controllerInteraction?.addContact(phoneNumber)
|
||||
}
|
||||
}, storeMediaPlaybackState: { [weak self] messageId, timestamp, playbackRate in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
var storedState: MediaPlaybackStoredState?
|
||||
if let timestamp = timestamp {
|
||||
storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate))
|
||||
}
|
||||
let _ = updateMediaPlaybackStoredStateInteractively(engine: self.context.engine, messageId: messageId, state: storedState).startStandalone()
|
||||
}, editMedia: { [weak self] messageId, snapshots, transitionCompletion in
|
||||
let openChatMessageParams = OpenChatMessageParams(
|
||||
context: context,
|
||||
updatedPresentationData: self.updatedPresentationData,
|
||||
chatLocation: openChatLocation,
|
||||
chatFilterTag: chatFilterTag,
|
||||
chatLocationContextHolder: self.chatLocationContextHolder,
|
||||
message: message,
|
||||
mediaIndex: params.mediaIndex,
|
||||
standalone: standalone,
|
||||
reverseMessageGalleryOrder: false,
|
||||
mode: mode,
|
||||
navigationController: self.effectiveNavigationController, dismissInput: { [weak self] in
|
||||
self?.chatDisplayNode.dismissInput()
|
||||
},
|
||||
present: { [weak self] c, a, i in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] message in
|
||||
guard let self, let message = message else {
|
||||
return
|
||||
if case .current = i {
|
||||
c.presentationArguments = a
|
||||
c.statusBar.alphaUpdated = { [weak self] transition in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.updateStatusBarPresentation(animated: transition.isAnimated)
|
||||
}
|
||||
|
||||
var mediaReference: AnyMediaReference?
|
||||
for media in message.media {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
mediaReference = AnyMediaReference.standalone(media: image)
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
mediaReference = AnyMediaReference.standalone(media: file)
|
||||
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
|
||||
if let image = content.image {
|
||||
mediaReference = AnyMediaReference.standalone(media: image)
|
||||
} else if let file = content.file {
|
||||
mediaReference = AnyMediaReference.standalone(media: file)
|
||||
self.galleryPresentationContext.present(c, on: PresentationSurfaceLevel(rawValue: 0), blockInteraction: true, completion: {})
|
||||
} else {
|
||||
self.present(c, in: .window(.root), with: a, blockInteraction: true)
|
||||
}
|
||||
},
|
||||
transitionNode: { [weak self] messageId, media, adjustRect in
|
||||
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||
if let self {
|
||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: adjustRect) {
|
||||
selectedNode = result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let mediaReference = mediaReference, let peer = message.peers[message.id.peerId] {
|
||||
legacyMediaEditor(context: self.context, peer: peer, threadTitle: self.contentData?.state.threadInfo?.title, media: mediaReference, mode: .draw, initialCaption: NSAttributedString(), snapshots: snapshots, transitionCompletion: {
|
||||
transitionCompletion()
|
||||
}, getCaptionPanelView: { [weak self] in
|
||||
return self?.getCaptionPanelView(isFile: false)
|
||||
}, sendMessagesWithSignals: { [weak self] signals, _, _, isCaptionAbove in
|
||||
if let self {
|
||||
var parameters: ChatSendMessageActionSheetController.SendParameters?
|
||||
if isCaptionAbove {
|
||||
parameters = ChatSendMessageActionSheetController.SendParameters(effect: nil, textIsAboveMedia: true)
|
||||
}
|
||||
self.enqueueMediaMessages(signals: signals, silentPosting: false, parameters: parameters)
|
||||
}
|
||||
return selectedNode
|
||||
},
|
||||
addToTransitionSurface: { [weak self] view in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let contextController = self.currentContextController {
|
||||
contextController.view.addSubview(view)
|
||||
} else {
|
||||
self.chatDisplayNode.historyNode.view.superview?.insertSubview(view, aboveSubview: self.chatDisplayNode.historyNode.view)
|
||||
}
|
||||
},
|
||||
openUrl: { [weak self] url in
|
||||
self?.openUrl(url, concealed: false, skipConcealedAlert: isLocation, message: nil)
|
||||
},
|
||||
openPeer: { [weak self] peer, navigation in
|
||||
self?.openPeer(peer: EnginePeer(peer), navigation: navigation, fromMessage: nil)
|
||||
},
|
||||
callPeer: { [weak self] peerId, isVideo in
|
||||
self?.controllerInteraction?.callPeer(peerId, isVideo)
|
||||
},
|
||||
openConferenceCall: { [weak self] message in
|
||||
self?.controllerInteraction?.openConferenceCall(message)
|
||||
},
|
||||
enqueueMessage: { [weak self] message in
|
||||
self?.sendMessages([message])
|
||||
},
|
||||
sendSticker: canSendMessagesToChat(self.presentationInterfaceState) ? { [weak self] fileReference, sourceNode, sourceRect in
|
||||
return self?.controllerInteraction?.sendSticker(fileReference, false, false, nil, false, sourceNode, sourceRect, nil, []) ?? false
|
||||
} : nil,
|
||||
sendEmoji: canSendMessagesToChat(self.presentationInterfaceState) ? { [weak self] text, attribute in
|
||||
self?.controllerInteraction?.sendEmoji(text, attribute, false)
|
||||
} : nil,
|
||||
setupTemporaryHiddenMedia: { [weak self] signal, centralIndex, galleryMedia in
|
||||
if let self {
|
||||
self.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { [weak self] entry in
|
||||
if let self, let controllerInteraction = self.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
if let entry = entry as? InstantPageGalleryEntry, entry.index == centralIndex {
|
||||
messageIdAndMedia[message.id] = [galleryMedia]
|
||||
}
|
||||
}, present: { [weak self] c, a in
|
||||
self?.present(c, in: .window(.root), with: a)
|
||||
})
|
||||
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
itemNode.updateHiddenMedia()
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
},
|
||||
chatAvatarHiddenMedia: { [weak self] signal, media in
|
||||
if let self {
|
||||
self.temporaryHiddenGalleryMediaDisposable.set((signal |> deliverOnMainQueue).startStrict(next: { [weak self] messageId in
|
||||
if let self, let controllerInteraction = self.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
if let messageId = messageId {
|
||||
messageIdAndMedia[messageId] = [media]
|
||||
}
|
||||
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
itemNode.updateHiddenMedia()
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
},
|
||||
actionInteraction: GalleryControllerActionInteraction(
|
||||
openUrl: { [weak self] url, concealed, forceExternal in
|
||||
if let self {
|
||||
self.openUrl(url, concealed: concealed, forceExternal: forceExternal, message: nil)
|
||||
}
|
||||
})
|
||||
}, updateCanReadHistory: { [weak self] canReadHistory in
|
||||
self?.canReadHistory.set(canReadHistory)
|
||||
}),
|
||||
},
|
||||
openUrlIn: { [weak self] url in
|
||||
if let self {
|
||||
self.openUrlIn(url)
|
||||
}
|
||||
},
|
||||
openPeerMention: { [weak self] mention in
|
||||
if let self {
|
||||
self.controllerInteraction?.openPeerMention(mention, nil)
|
||||
}
|
||||
},
|
||||
openPeer: { [weak self] peer in
|
||||
if let self {
|
||||
self.controllerInteraction?.openPeer(peer, .default, nil, .default)
|
||||
}
|
||||
},
|
||||
openHashtag: { [weak self] peerName, hashtag in
|
||||
if let self {
|
||||
self.controllerInteraction?.openHashtag(peerName, hashtag)
|
||||
}
|
||||
},
|
||||
openBotCommand: { [weak self] command in
|
||||
if let self {
|
||||
self.controllerInteraction?.sendBotCommand(nil, command)
|
||||
}
|
||||
},
|
||||
openAd: { [weak self] messageId in
|
||||
if let self {
|
||||
self.controllerInteraction?.activateAdAction(messageId, nil, true, true)
|
||||
}
|
||||
},
|
||||
addContact: { [weak self] phoneNumber in
|
||||
if let self {
|
||||
self.controllerInteraction?.addContact(phoneNumber)
|
||||
}
|
||||
},
|
||||
storeMediaPlaybackState: { [weak self] messageId, timestamp, playbackRate in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
var storedState: MediaPlaybackStoredState?
|
||||
if let timestamp = timestamp {
|
||||
storedState = MediaPlaybackStoredState(timestamp: timestamp, playbackRate: AudioPlaybackRate(playbackRate))
|
||||
}
|
||||
let _ = updateMediaPlaybackStoredStateInteractively(engine: self.context.engine, messageId: messageId, state: storedState).startStandalone()
|
||||
},
|
||||
editMedia: { [weak self] messageId, snapshots, transitionCompletion in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] message in
|
||||
guard let self, let message = message else {
|
||||
return
|
||||
}
|
||||
|
||||
var mediaReference: AnyMediaReference?
|
||||
for media in message.media {
|
||||
if let image = media as? TelegramMediaImage {
|
||||
mediaReference = AnyMediaReference.standalone(media: image)
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
mediaReference = AnyMediaReference.standalone(media: file)
|
||||
} else if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content {
|
||||
if let image = content.image {
|
||||
mediaReference = AnyMediaReference.standalone(media: image)
|
||||
} else if let file = content.file {
|
||||
mediaReference = AnyMediaReference.standalone(media: file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let mediaReference = mediaReference, let peer = message.peers[message.id.peerId] {
|
||||
legacyMediaEditor(context: self.context, peer: peer, threadTitle: self.contentData?.state.threadInfo?.title, media: mediaReference, mode: .draw, initialCaption: NSAttributedString(), snapshots: snapshots, transitionCompletion: {
|
||||
transitionCompletion()
|
||||
}, getCaptionPanelView: { [weak self] in
|
||||
return self?.getCaptionPanelView(isFile: false)
|
||||
}, sendMessagesWithSignals: { [weak self] signals, _, _, isCaptionAbove in
|
||||
if let self {
|
||||
var parameters: ChatSendMessageActionSheetController.SendParameters?
|
||||
if isCaptionAbove {
|
||||
parameters = ChatSendMessageActionSheetController.SendParameters(effect: nil, textIsAboveMedia: true)
|
||||
}
|
||||
self.enqueueMediaMessages(signals: signals, silentPosting: false, parameters: parameters)
|
||||
}
|
||||
}, present: { [weak self] c, a in
|
||||
self?.present(c, in: .window(.root), with: a)
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
updateCanReadHistory: { [weak self] canReadHistory in
|
||||
self?.canReadHistory.set(canReadHistory)
|
||||
}
|
||||
),
|
||||
navigateToMessageContext: { [weak self] message in
|
||||
Task {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
await self.openMediaMessageContext(message: message)
|
||||
}
|
||||
},
|
||||
getSourceRect: { [weak self] in
|
||||
guard let self else {
|
||||
return nil
|
||||
|
|
@ -2112,7 +2155,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
if let context = self?.context, let navigationController = self?.effectiveNavigationController {
|
||||
let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: threadId, messageId: messageId, navigationController: navigationController, activateInput: nil, scrollToEndIfExists: false, keepStack: .always, animated: true).startStandalone()
|
||||
}
|
||||
}, tapMessage: nil, clickThroughMessage: { [weak self] view, location in
|
||||
}, tapMessage: nil,
|
||||
clickThroughMessage: { [weak self] view, location in
|
||||
self?.chatDisplayNode.dismissInput(view: view, location: location)
|
||||
}, toggleMessagesSelection: { [weak self] ids, value in
|
||||
guard let strongSelf = self, strongSelf.isNodeLoaded else {
|
||||
|
|
|
|||
|
|
@ -137,4 +137,36 @@ extension ChatControllerImpl {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func openMediaMessageContext(message: EngineMessage) async {
|
||||
guard let peer = await self.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: message.id.peerId)
|
||||
).get() else {
|
||||
return
|
||||
}
|
||||
|
||||
var kind: PeerInfoControllerMode.PeerInfoMediaKind?
|
||||
if message.tags.contains(MessageTags.photoOrVideo) {
|
||||
kind = .photoVideo
|
||||
} else if message.tags.contains(MessageTags.file) {
|
||||
kind = .file
|
||||
}
|
||||
|
||||
guard let kind else {
|
||||
return
|
||||
}
|
||||
|
||||
let peerInfoController = self.context.sharedContext.makePeerInfoController(
|
||||
context: self.context,
|
||||
updatedPresentationData: self.updatedPresentationData,
|
||||
peer: peer._asPeer(),
|
||||
mode: .media(kind: kind, messageIndex: message.index),
|
||||
avatarInitiallyExpanded: false,
|
||||
fromChat: true,
|
||||
requestsContext: nil
|
||||
)
|
||||
if let peerInfoController {
|
||||
self.push(peerInfoController)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,6 +358,10 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||
return nil
|
||||
})
|
||||
|
||||
gallery.navigateToMessageContext = { message in
|
||||
params.navigateToMessageContext?(message)
|
||||
}
|
||||
|
||||
params.present(gallery, arguments, presentInCurrent ? .current : .window(.root))
|
||||
})
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -4114,8 +4114,23 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||
}
|
||||
|
||||
private func peerInfoControllerImpl(context: AccountContext, updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, requestsContext: PeerInvitationImportersContext? = nil) -> ViewController? {
|
||||
var switchToMediaTarget: PeerInfoSwitchToMediaTarget?
|
||||
switch mode {
|
||||
case let .media(kind, index):
|
||||
let mappedKind: PeerInfoSwitchToMediaTarget.Kind
|
||||
switch kind {
|
||||
case .photoVideo:
|
||||
mappedKind = .photoVideo
|
||||
case .file:
|
||||
mappedKind = .file
|
||||
}
|
||||
switchToMediaTarget = PeerInfoSwitchToMediaTarget(kind: mappedKind, messageIndex: index)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if let _ = peer as? TelegramGroup {
|
||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [])
|
||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [], switchToMediaTarget: switchToMediaTarget)
|
||||
} else if let _ = peer as? TelegramChannel {
|
||||
var forumTopicThread: ChatReplyThreadMessage?
|
||||
var switchToRecommendedChannels = false
|
||||
|
|
@ -4138,7 +4153,7 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation
|
|||
default:
|
||||
break
|
||||
}
|
||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [], forumTopicThread: forumTopicThread, switchToRecommendedChannels: switchToRecommendedChannels, switchToGiftsTarget: switchToGiftsTarget, switchToGroupsInCommon: switchToGroupsInCommon, switchToStoryFolder: switchToStoryFolder)
|
||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [], forumTopicThread: forumTopicThread, switchToRecommendedChannels: switchToRecommendedChannels, switchToGiftsTarget: switchToGiftsTarget, switchToGroupsInCommon: switchToGroupsInCommon, switchToStoryFolder: switchToStoryFolder, switchToMediaTarget: switchToMediaTarget)
|
||||
} else if peer is TelegramUser {
|
||||
var nearbyPeerDistance: Int32?
|
||||
var reactionSourceMessageId: MessageId?
|
||||
|
|
@ -4191,9 +4206,9 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation
|
|||
default:
|
||||
break
|
||||
}
|
||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nearbyPeerDistance, reactionSourceMessageId: reactionSourceMessageId, callMessages: callMessages, isMyProfile: isMyProfile, hintGroupInCommon: hintGroupInCommon, forumTopicThread: forumTopicThread, sharedMediaFromForumTopic: sharedMediaFromForumTopic, switchToGiftsTarget: switchToGiftsTarget, switchToGroupsInCommon: switchToGroupsInCommon, switchToStoryFolder: switchToStoryFolder)
|
||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nearbyPeerDistance, reactionSourceMessageId: reactionSourceMessageId, callMessages: callMessages, isMyProfile: isMyProfile, hintGroupInCommon: hintGroupInCommon, forumTopicThread: forumTopicThread, sharedMediaFromForumTopic: sharedMediaFromForumTopic, switchToGiftsTarget: switchToGiftsTarget, switchToGroupsInCommon: switchToGroupsInCommon, switchToStoryFolder: switchToStoryFolder, switchToMediaTarget: switchToMediaTarget)
|
||||
} else if peer is TelegramSecretChat {
|
||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [])
|
||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [], switchToMediaTarget: switchToMediaTarget)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -846,7 +846,14 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||
if let peer {
|
||||
return .single(peer)
|
||||
} else {
|
||||
return context.engine.peers.findChannelById(channelId: monoforumId.id._internalGetInt64Value())
|
||||
return context.engine.peers.fetchAndUpdateCachedPeerData(peerId: channel.id)
|
||||
|> mapToSignal { result -> Signal<EnginePeer?, NoError> in
|
||||
if result {
|
||||
return context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: monoforumId))
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|> map { peer -> ResolveInternalUrlResult in
|
||||
|
|
|
|||
|
|
@ -82,10 +82,12 @@ class WebSearchGalleryController: ViewController {
|
|||
private var centralEntryIndex: Int?
|
||||
|
||||
private let centralItemTitle = Promise<String>()
|
||||
private let centralItemTitleView = Promise<UIView?>()
|
||||
private let centralItemTitleContent = Promise<GalleryTitleView.Content?>()
|
||||
private let centralItemNavigationStyle = Promise<GalleryItemNodeNavigationStyle>()
|
||||
private let centralItemFooterContentNode = Promise<(GalleryFooterContentNode?, GalleryOverlayContentNode?)>()
|
||||
private let centralItemAttributesDisposable = DisposableSet();
|
||||
private let centralItemAttributesDisposable = DisposableSet()
|
||||
|
||||
private let titleView: GalleryTitleView
|
||||
|
||||
private let checkedDisposable = MetaDisposable()
|
||||
private var checkNode: GalleryNavigationCheckNode?
|
||||
|
|
@ -105,6 +107,8 @@ class WebSearchGalleryController: ViewController {
|
|||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.titleView = GalleryTitleView(context: context, presentationData: self.presentationData)
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: WebSearchGalleryController.navigationTheme, strings: NavigationBarStrings(presentationStrings: self.presentationData.strings)))
|
||||
|
||||
self.controllerInteraction = WebSearchGalleryControllerInteraction(dismiss: { [weak self] animated in
|
||||
|
|
@ -151,8 +155,8 @@ class WebSearchGalleryController: ViewController {
|
|||
self?.navigationItem.title = title
|
||||
}))
|
||||
|
||||
self.centralItemAttributesDisposable.add(self.centralItemTitleView.get().start(next: { [weak self] titleView in
|
||||
self?.navigationItem.titleView = titleView
|
||||
self.centralItemAttributesDisposable.add(self.centralItemTitleContent.get().start(next: { [weak self] titleContent in
|
||||
self?.titleView.setContent(content: titleContent)
|
||||
}))
|
||||
|
||||
self.centralItemAttributesDisposable.add(self.centralItemFooterContentNode.get().start(next: { [weak self] footerContentNode, _ in
|
||||
|
|
@ -232,7 +236,7 @@ class WebSearchGalleryController: ViewController {
|
|||
}, currentItemNode: { [weak self] in
|
||||
return self?.galleryNode.pager.centralItemNode()
|
||||
})
|
||||
self.displayNode = GalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction)
|
||||
self.displayNode = GalleryControllerNode(context: self.context, controllerInteraction: controllerInteraction, titleView: self.titleView)
|
||||
self.displayNodeDidLoad()
|
||||
|
||||
self.galleryNode.statusBar = self.statusBar
|
||||
|
|
@ -265,7 +269,7 @@ class WebSearchGalleryController: ViewController {
|
|||
|
||||
if let node = strongSelf.galleryNode.pager.centralItemNode() {
|
||||
strongSelf.centralItemTitle.set(node.title())
|
||||
strongSelf.centralItemTitleView.set(node.titleView())
|
||||
strongSelf.centralItemTitleContent.set(node.titleContent())
|
||||
strongSelf.centralItemNavigationStyle.set(node.navigationStyle())
|
||||
strongSelf.centralItemFooterContentNode.set(node.footerContent())
|
||||
}
|
||||
|
|
@ -317,7 +321,7 @@ class WebSearchGalleryController: ViewController {
|
|||
|
||||
if let centralItemNode = self.galleryNode.pager.centralItemNode(), let presentationArguments = self.presentationArguments as? WebSearchGalleryControllerPresentationArguments {
|
||||
self.centralItemTitle.set(centralItemNode.title())
|
||||
self.centralItemTitleView.set(centralItemNode.titleView())
|
||||
self.centralItemTitleContent.set(centralItemNode.titleContent())
|
||||
self.centralItemNavigationStyle.set(centralItemNode.navigationStyle())
|
||||
self.centralItemFooterContentNode.set(centralItemNode.footerContent())
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ final class WebSearchGalleryFooterContentNode: GalleryFooterContentNode {
|
|||
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
override func updateLayout(size: CGSize, metrics: LayoutMetrics, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, contentInset: CGFloat, transition: ContainedViewLayoutTransition) -> LayoutInfo {
|
||||
let width = size.width
|
||||
let panelSize: CGFloat = 49.0
|
||||
var panelHeight: CGFloat = panelSize + bottomInset
|
||||
|
|
@ -52,7 +52,7 @@ final class WebSearchGalleryFooterContentNode: GalleryFooterContentNode {
|
|||
self.cancelButton.frame = CGRect(origin: CGPoint(x: leftInset, y: panelHeight - bottomInset - panelSize), size: CGSize(width: panelSize, height: panelSize))
|
||||
self.sendButton.frame = CGRect(origin: CGPoint(x: width - panelSize - rightInset, y: panelHeight - bottomInset - panelSize), size: CGSize(width: panelSize, height: panelSize))
|
||||
|
||||
return panelHeight
|
||||
return LayoutInfo(height: panelHeight, needsShadow: false)
|
||||
}
|
||||
|
||||
override func animateIn(fromHeight: CGFloat, previousContentNode: GalleryFooterContentNode, transition: ContainedViewLayoutTransition) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue