Merge commit '2cb0c7f147' into beta

This commit is contained in:
Ilya Laktyushin 2025-12-04 08:01:56 +04:00
commit f97eca0172
1642 changed files with 847925 additions and 2906 deletions

View file

@ -22,3 +22,9 @@ build --spawn_strategy=standalone
build --strategy=SwiftCompile=standalone
build --define RULES_SWIFT_BUILD_DUMMY_WORKER=1
common:index_build --experimental_convenience_symlinks=ignore
common:index_build --bes_backend= --bes_results_url=
common:index_build --nolegacy_important_outputs
common:index_build --show_result=0
common:index_build --define=buildNumber=10000
common:index_build --define=telegramVersion=12.2.2

1
.gitignore vendored
View file

@ -74,3 +74,4 @@ buildServer.json
Telegram.LSP.json
**/.build/**
spm-files
.bsp/**

3
.gitmodules vendored
View file

@ -35,3 +35,6 @@ url=../tgcalls.git
[submodule "third-party/XcodeGen"]
path = third-party/XcodeGen
url = https://github.com/yonaskolb/XcodeGen.git
[submodule "build-system/bazel-rules/sourcekit-bazel-bsp"]
path = build-system/bazel-rules/sourcekit-bazel-bsp
url=https://github.com/ali-fareed/sourcekit-bazel-bsp.git

View file

@ -0,0 +1,9 @@
{
"backgroundIndexing": true,
"backgroundPreparationMode": "build",
"defaultWorkspaceType": "buildServer",
"logging": {
"level": "error",
"privacyLevel": "sensitive"
}
}

59
.vscode/launch.json vendored
View file

@ -1,44 +1,31 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "swift",
"request": "launch",
"args": [],
"cwd": "${workspaceFolder:telegram-ios}",
"name": "Debug Telegram",
"program": "${workspaceFolder:telegram-ios}/.build/debug/Telegram",
"preLaunchTask": "swift: Build Debug Telegram"
"type": "lldb-dap",
"request": "attach",
"preLaunchTask": "_launch_telegram",
"debuggerRoot": "${workspaceFolder}",
"attachCommands": [
"process connect connect://localhost:6667"
],
"internalConsoleOptions": "openOnSessionStart",
"timeout": 1000
},
{
"type": "swift",
"request": "launch",
"args": [],
"cwd": "${workspaceFolder:telegram-ios}",
"name": "Release Telegram",
"program": "${workspaceFolder:telegram-ios}/.build/release/Telegram",
"preLaunchTask": "swift: Build Release Telegram"
"name": "Restart Debug Telegram",
"type": "lldb-dap",
"request": "attach",
"preLaunchTask": "Restart Telegram Debug",
"debuggerRoot": "${workspaceFolder}",
"attachCommands": [
"process connect connect://localhost:6667"
],
"internalConsoleOptions": "openOnSessionStart",
"timeout": 1000
},
{
"type": "swift",
"request": "launch",
"args": [],
"cwd": "${workspaceFolder:telegram-ios}",
"name": "Debug telegram-ios",
"program": "${workspaceFolder:telegram-ios}/.build/debug/telegram-ios",
"preLaunchTask": "swift: Build Debug telegram-ios"
},
{
"type": "swift",
"request": "launch",
"args": [],
"cwd": "${workspaceFolder:telegram-ios}",
"name": "Release telegram-ios",
"program": "${workspaceFolder:telegram-ios}/.build/release/telegram-ios",
"preLaunchTask": "swift: Build Release telegram-ios"
}
]
],
"options": {
"console": "integratedTerminal",
}
}

17
.vscode/settings.json vendored
View file

@ -1,7 +1,4 @@
{
"sweetpad.build.xcodeWorkspacePath": "Telegram/Telegram.xcodeproj/project.xcworkspace",
"lldb.library": "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB",
"lldb.launch.expressions": "native",
"search.followSymlinks": false,
"files.exclude": {
".git/**": true
@ -13,5 +10,17 @@
".git/**": true
},
"files.associations": {
}
},
"swift.sourcekit-lsp.backgroundIndexing": "on",
"swift.sourcekit-lsp.trace.server": "messages",
"terminal.integrated.profiles.osx": {
"zsh": {
"path": "/bin/zsh",
"args": [
"-l",
"-i"
]
}
},
"swift.sourcekit-lsp.serverPath": "${workspaceFolder}/build-input/sourcekit-lsp",
}

105
.vscode/tasks.json vendored
View file

@ -1,6 +1,101 @@
{
"version": "2.0.0",
"tasks": [
]
}
"version": "2.0.0",
"tasks": [
{
"label": "Build Telegram",
"type": "shell",
"command": "${workspaceFolder}/build-input/bazel-8.4.2-darwin-arm64",
"args": [
"build",
"Telegram/Telegram",
"--features=swift.use_global_module_cache",
"--verbose_failures",
"--remote_cache_async",
"--features=swift.skip_function_bodies_for_derived_files",
"--jobs=16",
"--define=buildNumber=10000",
"--define=telegramVersion=12.2.2",
"--disk_cache=${HOME}/telegram-bazel-cache",
"-c",
"dbg",
"--ios_multi_cpus=sim_arm64",
"--watchos_cpus=arm64_32",
"--features=swift.enable_batch_mode"
],
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [],
"runOptions": {
"instanceLimit": 1
}
},
// Hidden never-ending task that handles the launch / debugging bits for Cmd+Shift+D.
// The problemMatcher field defines when the task is effectively ready to be debugged
// by the attach task in launch.json.
{
"label": "_launch_telegram",
"type": "shell",
"command": "./scripts/launch_and_debug.sh",
"presentation": {
"reveal": "always"
},
"hide": true,
"isBackground": true,
"problemMatcher": [
{
"pattern": [
{
"regexp": "\\b\\B",
"file": 1,
"location": 2,
"message": 3
}
],
"background": {
"activeOnStart": true,
"beginsPattern": "^.*Building....*",
"endsPattern": "^.*Listening to port 6667 for a connection from .*"
}
}
],
"runOptions": {
"instanceLimit": 1
}
},
{
"label": "Stream SourceKitBazelBSP Logs",
"type": "shell",
"command": "log stream --process sourcekit-bazel-bsp --debug",
"problemMatcher": [],
"isBackground": false,
"presentation": {
"reveal": "always",
"panel": "dedicated"
}
},
{
"label": "Stop Telegram Debug Session",
"type": "shell",
"command": "pkill -f 'launch_and_debug.sh' || true; lsof -ti:6667 | xargs kill -9 2>/dev/null || true",
"problemMatcher": [],
"presentation": {
"reveal": "silent",
"close": true
}
},
{
"label": "Restart Telegram Debug",
"dependsOrder": "sequence",
"dependsOn": [
"Stop Telegram Debug Session",
"_launch_telegram"
],
"problemMatcher": [],
"presentation": {
"reveal": "always"
}
}
]
}

15
BUILD.bazel Normal file
View file

@ -0,0 +1,15 @@
load("@sourcekit_bazel_bsp//rules:setup_sourcekit_bsp.bzl", "setup_sourcekit_bsp")
setup_sourcekit_bsp(
name = "setup_sourcekit_bsp_telegram_project",
bazel_wrapper = "./build-input/bazel-8.4.2-darwin-arm64",
files_to_watch = [
"**/*.swift",
],
index_flags = [
"config=index_build",
],
targets = [
"//Telegram:Telegram",
],
)

View file

@ -30,8 +30,8 @@ local_path_override(
http_file(
name = "cmake_tar_gz",
urls = ["https://github.com/Kitware/CMake/releases/download/v3.23.1/cmake-3.23.1-macos-universal.tar.gz"],
sha256 = "f794ed92ccb4e9b6619a77328f313497d7decf8fb7e047ba35a348b838e0e1e2",
urls = ["https://github.com/Kitware/CMake/releases/download/v4.1.2/cmake-4.1.2-macos-universal.tar.gz"],
sha256 = "3be85f5b999e327b1ac7d804cbc9acd767059e9f603c42ec2765f6ab68fbd367",
)
http_file(
@ -62,3 +62,9 @@ local_path_override(
module_name = "build_configuration",
path = "./build-input/configuration-repository",
)
bazel_dep(name = "sourcekit_bazel_bsp", version = "0.3.0")
local_path_override(
module_name = "sourcekit_bazel_bsp",
path = "build-system/bazel-rules/sourcekit-bazel-bsp",
)

10
MODULE.bazel.lock generated
View file

@ -98,8 +98,8 @@
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
"https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/8.12.0/MODULE.bazel": "8e6590b961f2defdfc2811c089c75716cb2f06c8a4edeb9a8d85eaa64ee2a761",
"https://bcr.bazel.build/modules/rules_java/8.12.0/source.json": "cbd5d55d9d38d4008a7d00bee5b5a5a4b6031fcd4a56515c9accbcd42c7be2ba",
"https://bcr.bazel.build/modules/rules_java/8.14.0/MODULE.bazel": "717717ed40cc69994596a45aec6ea78135ea434b8402fb91b009b9151dd65615",
"https://bcr.bazel.build/modules/rules_java/8.14.0/source.json": "8a88c4ca9e8759da53cddc88123880565c520503321e2566b4e33d0287a3d4bc",
"https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
"https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
@ -156,7 +156,7 @@
"moduleExtensions": {
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": {
"bzlTransitiveDigest": "hUTp2w+RUVdL7ma5esCXZJAFnX7vLbVfLd7FwnQI6bU=",
"bzlTransitiveDigest": "OlvsB0HsvxbR8ZN+J9Vf00X/+WVz/Y/5Xrq2LgcVfdo=",
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
@ -256,7 +256,7 @@
},
"@@rules_xcodeproj+//xcodeproj:extensions.bzl%internal": {
"general": {
"bzlTransitiveDigest": "/r7IWMTdpceHqqiSh7G9bQLHvIkfqE/cesswbkTSJZw=",
"bzlTransitiveDigest": "hsJI1bzu5CX3ZE+NX8jnNWEOh1pNDT650SbTSBnF5jA=",
"usagesDigest": "fvsnMonVwKDYnBfww4bXuYie3WU0d9VSqT2gePSdQco=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
@ -278,7 +278,7 @@
},
"@@rules_xcodeproj+//xcodeproj:extensions.bzl%non_module_deps": {
"general": {
"bzlTransitiveDigest": "/r7IWMTdpceHqqiSh7G9bQLHvIkfqE/cesswbkTSJZw=",
"bzlTransitiveDigest": "hsJI1bzu5CX3ZE+NX8jnNWEOh1pNDT650SbTSBnF5jA=",
"usagesDigest": "jzxYhnOC9BE0dJ0biFLfxWXi/+R19uAAZkJ0p9CY0JI=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},

View file

@ -495,6 +495,8 @@ associated_domains_fragment = "" if telegram_bundle_id not in official_bundle_id
<string>applinks:telegram.me</string>
<string>applinks:t.me</string>
<string>applinks:*.t.me</string>
<string>webcredentials:t.me</string>
<string>webcredentials:telegram.org</string>
</array>
"""

View file

@ -15432,3 +15432,194 @@ Error: %8$@";
"LiveStream.ErrorMaxAllowedEmoji.Text_1" = "You can send up to %d emoji.";
"LiveStream.ErrorMaxAllowedEmoji.Text_any" = "You can send up to %d emoji.";
"Stars.Purchase.StarGiftOfferInfo" = "Buy Stars to make a gift buy offer.";
"Notification.StarsGiftOffer.Offer" = "%1$@ offered you %2$@ for your gift %3$@";
"Notification.StarsGiftOffer.Offer.Stars_1" = "%@ Star";
"Notification.StarsGiftOffer.Offer.Stars_any" = "%@ Stars";
"Notification.StarsGiftOffer.OfferYou" = "You offered %1$@ %2$@ for their gift %3$@";
"Notification.StarsGiftOffer.OfferYou.Stars_1" = "%@ Star";
"Notification.StarsGiftOffer.OfferYou.Stars_any" = "%@ Stars";
"Notification.StarsGiftOffer.Accepted" = "%1$@ accepted your offer and sold you %2$@ for %3$@";
"Notification.StarsGiftOffer.Accepted.Stars_1" = "%@ Star";
"Notification.StarsGiftOffer.Accepted.Stars_any" = "%@ Stars";
"Notification.StarsGiftOffer.AcceptedYou" = "You sold %1$@ to %2$@ for %3$@";
"Notification.StarsGiftOffer.AcceptedYou.Stars_1" = "%@ Star";
"Notification.StarsGiftOffer.AcceptedYou.Stars_any" = "%@ Stars";
"Notification.StarsGiftOffer.Rejected" = "%1$@ rejected your offer for %2$@ your %3$@ have been refunded";
"Notification.StarsGiftOffer.Rejected.Stars_1" = "%@ Star";
"Notification.StarsGiftOffer.Rejected.Stars_any" = "%@ Stars";
"Notification.StarsGiftOffer.RejectedYou" = "You rejected %1$@'s offer";
"Notification.StarsGiftOffer.RejectedYou.Stars_1" = "%@ Star";
"Notification.StarsGiftOffer.RejectedYou.Stars_any" = "%@ Stars";
"Notification.StarsGiftOffer.Expired" = "%1$@ didn't respond to your offer for %2$@ within %3$@ your %4$@ have been refunded";
"Notification.StarsGiftOffer.Expired.Stars_1" = "%@ Star";
"Notification.StarsGiftOffer.Expired.Stars_any" = "%@ Stars";
"Notification.StarsGiftOffer.ExpiredYou" = "The offer from %1$@ to buy your %2$@ for %3$@ has expired";
"Notification.StarsGiftOffer.ExpiredYou.Stars_1" = "%@ Star";
"Notification.StarsGiftOffer.ExpiredYou.Stars_any" = "%@ Stars";
"CreateExternalStream.RevokeStreamKey" = "Revoke Stream Key";
"CreateExternalStream.Revoke.Text" = "Do you want to revoke the stream key?";
"CreateExternalStream.Revoke.Revoke" = "Revoke";
"Gift.AuctionBid.UntilEnd" = "until the end";
"Gift.AuctionBid.BeforeStart" = "before start";
"Gift.AuctionBid.RoundSubtitle" = "Round %@ of %@";
"Gift.AuctionBid.TopWinnersTotal" = "Top 3 of %@ Winners";
"Gift.Acquired.GiftRound" = "%1$@ in round %2$@";
"Gift.Options.Gift.Soon" = "soon";
"Chat.Auction.StartsIn" = "starts in ";
"Chat.Auction.View" = "VIEW";
"Chat.Auction.Upcoming" = "Upcoming Auction";
"Gift.Auction.Start" = "Start";
"Gift.Auction.End" = "End";
"Gift.Auction.Quantity" = "Quantity";
"Gift.Auction.TotalRounds" = "Rounds";
"Gift.Auction.TimeRound" = "Round %@";
"Gift.Auction.TimeRounds" = "Rounds %@";
"Gift.Auction.StartsInHours" = "auction starts in {h}:{m}:{s}";
"Gift.Auction.StartsInMinutes" = "auction starts in {m}:{s}";
"Gift.Auction.EarlyBid" = "Place an Early Bid";
"Gift.Auction.ViewVariants" = "View";
"Gift.Auction.Variants_1" = "%@ Variant";
"Gift.Auction.Variants_any" = "%@ Variants";
"Gift.Auction.Hours_1" = "%@ hour";
"Gift.Auction.Hours_any" = "%@ hours";
"Gift.Auction.Minutes_1" = "%@ minute";
"Gift.Auction.Minutes_any" = "%@ minutes";
"Gift.Auction.Seconds_1" = "%@ second";
"Gift.Auction.Seconds_any" = "%@ seconds";
"Gift.Auction.HoursEach_1" = "%@ hour each";
"Gift.Auction.HoursEach_any" = "%@ hours each";
"Gift.Auction.MinutesEach_1" = "%@ minute each";
"Gift.Auction.MinutesEach_any" = "%@ minutes each";
"Gift.Auction.Extension" = "+ %1$@ for late bids in top %2$@";
"ChatList.Auctions.UpcomingAuction" = "Upcoming Auction";
"Gift.AuctionBid.UpcomingBid" = "You've placed an early bid";
"ChatList.Auctions.Status.UpcomingBid" = "You've placed an early bid.";
"Gift.ActiveAuctions.UpcomingBid" = "You've placed an early bid";
"Login.PhoneWithPasskeySubtitle" = "Enter your phone number\nor [log in using Passkey >](passkey)";
"PrivacySettings.Passkey" = "Passkey";
"Attachment.SharedAudio" = "SHARED AUDIO";
"Attachment.FilesSearchPlaceholder" = "Search shared audio";
"Chat.GiftPurchaseOffer.Reject" = "Reject";
"Chat.GiftPurchaseOffer.Accept" = "Accept";
"Chat.GiftPurchaseOffer.RejectConfirmation.Title" = "Reject Offer";
"Chat.GiftPurchaseOffer.RejectConfirmation.Text" = "Are you sure you want to reject the offer from **%@**?";
"Chat.GiftPurchaseOffer.RejectConfirmation.Reject" = "Reject";
"Passkeys.DeleteAlert.Title" = "Delete Passkey?";
"Passkeys.DeleteAlert.Text" = "Once deleted, this passkey can't be used to log in.\n\nDon't forget to remove it from your password manager too.";
"Passkeys.DeleteAlert.Action" = "Delete";
"Passkeys.Into.Title" = "Protect your account";
"Passkeys.Subtitle" = "Log in safely and keep your account secure.";
"Passkeys.Into.Title0" = "Create a Passkey";
"Passkeys.Into.Text0" = "Make a passkey to sign in easily and safely.";
"Passkeys.Into.Title1" = "Log in with Face ID";
"Passkeys.Into.Text1" = "Use Face ID, Touch ID, or your passcode to sign in.";
"Passkeys.Into.Title2" = "Store Passkey Securely";
"Passkeys.Into.Text2" = "Your passkey is safely kept in your iCloud Keychain.";
"Passkeys.ButtonCreate" = "Create Passkey";
"Passkeys.ButtonSkip" = "Skip";
"Passkeys.Title" = "Passkeys";
"Passkeys.Subtitle" = "Log in safely and keep your account secure.";
"Passkeys.EmptyName" = "Passkey";
"Passkeys.PasskeyCreatedPattern" = "created %@";
"Passkeys.PasskeyCreatedAndUsedPattern" = "created %1$@ • used %2$@";
"Passkeys.AddPasskey" = "Create Passkey";
"Passkeys.ListFooter" = "Your passkeys are stored securely in your password manager.";
"Gift.Demo.Title" = "Unique Collectibles";
"Gift.Demo.Description" = "Telegram Gifts are collectible items you can trade or showcase on your profile.";
"Gift.Demo.Unique.Title" = "Unique";
"Gift.Demo.Unique.Text" = "Upgrade your gifts to get a unique number, model, backdrop and symbol.";
"Gift.Demo.Tradable.Title" = "Tradable";
"Gift.Demo.Tradable.Text" = "Sell your gift on Telegram or on third-party NFT marketplaces.";
"Gift.Demo.Wearable.Title" = "Wearable";
"Gift.Demo.Wearable.Text" = "Display gifts on your page and set them as profile covers or statuses.";
"Gift.Demo.Understood" = "Understood";
"Gift.Variants.RandomTraits" = "Random Traits";
"Gift.Variants.SelectedTraits" = "Selected Traits";
"Gift.Variants.Randomize" = "Randomize Traits";
"Gift.Variants.Model" = "model";
"Gift.Variants.Backdrop" = "backdrop";
"Gift.Variants.Symbol" = "symbol";
"Gift.Variants.Models" = "Models";
"Gift.Variants.Backdrops" = "Backdrops";
"Gift.Variants.Symbols" = "Symbols";
"Gift.Variants.CollectionInfo" = "This collection features %@";
"Gift.Variants.CollectionInfo.Model_1" = "**%@** unique model";
"Gift.Variants.CollectionInfo.Model_any" = "**%@** unique models";
"Gift.Variants.CollectionInfo.Backdrop_1" = "**%@** unique backdrop";
"Gift.Variants.CollectionInfo.Backdrop_any" = "**%@** unique backdrops";
"Gift.Variants.CollectionInfo.Symbol_1" = "**%@** unique symbol";
"Gift.Variants.CollectionInfo.Symbol_any" = "**%@** unique symbols";
"Gift.Auction.GiftAuction" = "Upcoming Auction";
"Gift.Auction.UpcomingAuction" = "Upcoming Auction";
"Gift.Auction.LearnMore" = "Learn more about Telegram Gifts >";
"Gift.AuctionBid.UpcomingTitle" = "Place an Early Bid";
"Gift.View.Context.BuyOffer" = "Offer to Buy";
"Gift.Offer.Title" = "Offer to Buy";
"Gift.Offer.OfferStars" = "Offer Stars";
"Gift.Offer.OfferTon" = "Offer TON";
"Gift.Offer.PriceSectionStars" = "STARS TO OFFER";
"Gift.Offer.PriceSectionTon" = "TON TO OFFER";
"Gift.Offer.PricePlaceholder" = "Price";
"Gift.Offer.PriceDescriptionStars" = "Enter the number of Stars you'd like to offer for **%@**.";
"Gift.Offer.PriceDescriptionTon" = "Enter the number of TON you'd like to offer for **%@**.";
"Gift.Offer.Duration" = "Offer Duration";
"Gift.Offer.DurationDescriptionStars" = "Choose how long **%@** can accept your offer. When the time expires, your Stars will be automatically refunded.";
"Gift.Offer.DurationDescriptionTon" = "Choose how long **%@** can accept your offer. When the time expires, your TON will be automatically refunded.";
"Gift.Offer.Duration.Hours_1" = "%@ Hour";
"Gift.Offer.Duration.Hours_any" = "%@ Hours";
"Gift.Offer.Offer" = "Offer";
"Gift.Offer.GiftMinAmountToast.Text" = "You cannot offer less than %@ for this gift";
"Gift.WearPreview.Limited" = "limited";
"Gift.WearPreview.Upgraded" = "upgraded";
"Gift.WearPreview.FreeUpgrade" = "Free\nUpgrade";
"Gift.WearPreview.LearnMore" = "Learn more about wearing Telegram Gifts >";
"Notification.StarGift.Sold" = "sold";
"Notification.StarGiftOffer.Offer" = "**%1$@** offered you **%2$@** for your gift **%3$@**.";
"Notification.StarGiftOffer.OfferYou" = "You offered **%1$@** **%2$@** for their gift **%3$@**.";
"Notification.StarGiftOffer.Offer.Stars_1" = "%@ Star";
"Notification.StarGiftOffer.Offer.Stars_any" = "%@ Stars";
"Notification.StarGiftOffer.Status.Accepted" = "This offer was accepted.";
"Notification.StarGiftOffer.Status.Expired" = "This offer has expired.";
"Notification.StarGiftOffer.Status.Expires" = "This offer expires in %@";
"Notification.StarGiftOffer.Status.Rejected" = "This offer was rejected.";
"Notification.StarGiftOffer.Expiration.Hours_1" = "%@ h";
"Notification.StarGiftOffer.Expiration.Hours_any" = "%@ h";
"Notification.StarGiftOffer.Expiration.Minutes_1" = "%@ m";
"Notification.StarGiftOffer.Expiration.Minutes_any" = "%@ m";
"Notification.StarGiftOffer.Expiration.Delimiter" = "";
"Chat.GiftPurchaseOffer.AcceptConfirmation.Title" = "Confirm Sale";
"Chat.GiftPurchaseOffer.AcceptConfirmation.Text" = "Do you want to sell **%1$@** to %2$@ for **%3$@**? You'll receive **%4$@** after fees.";
"Chat.GiftPurchaseOffer.AcceptConfirmation.Text.Stars_1" = "%@ Star";
"Chat.GiftPurchaseOffer.AcceptConfirmation.Text.Stars_any" = "%@ Stars";
"Chat.GiftPurchaseOffer.AcceptConfirmation.BadValue" = "The value of this gift is **%@** higher than the offer.";
"Chat.GiftPurchaseOffer.AcceptConfirmation.Confirm" = "Confirm Sale";

View file

@ -40,7 +40,6 @@ class BazelCommandLine:
self.additional_args = None
self.build_number = None
self.configuration_args = None
self.configuration_path = None
self.split_submodules = False
self.custom_target = None
self.continue_on_error = False
@ -68,7 +67,7 @@ class BazelCommandLine:
'--verbose_failures',
# Asynchronously upload cache artifacts
'--experimental_remote_cache_async',
'--remote_cache_async',
]
self.common_build_args = [
@ -89,12 +88,6 @@ class BazelCommandLine:
# invoking a smaller number of frontend processes and passing them batches of
# source files.
'--features=swift.enable_batch_mode',
# https://docs.bazel.build/versions/master/command-line-reference.html
# Set the number of parallel jobs per module to saturate the available CPU resources.
#'--swiftcopt=-j{}'.format(os.cpu_count() - 1),
'--@build_bazel_rules_swift//swift:copt="-j{}"'.format(os.cpu_count() - 1),
'--@build_bazel_rules_swift//swift:copt="-whole-module-optimization"',
]
self.common_release_args = [
@ -147,9 +140,6 @@ class BazelCommandLine:
def set_split_swiftmodules(self, value):
self.split_submodules = value
def set_configuration_path(self, path):
self.configuration_path = path
def set_disable_provisioning_profiles(self):
self.disable_provisioning_profiles = True
@ -203,8 +193,6 @@ class BazelCommandLine:
# Require DSYM files as build output.
'--output_groups=+dsyms',
#'--@build_bazel_rules_swift//swift:copt="-num-threads 0"',
] + self.common_release_args
else:
raise Exception('Unknown configuration {}'.format(configuration))
@ -296,13 +284,6 @@ class BazelCommandLine:
if self.disable_provisioning_profiles:
combined_arguments += ['--//Telegram:disableProvisioningProfiles']
if self.configuration_path is None:
raise Exception('configuration_path is not defined')
combined_arguments += [
'--override_repository=build_configuration={}'.format(self.configuration_path)
]
combined_arguments += self.common_args
combined_arguments += self.common_build_args
combined_arguments += self.get_define_arguments()
@ -336,13 +317,6 @@ class BazelCommandLine:
combined_arguments += ['Tests/AllTests']
if self.configuration_path is None:
raise Exception('configuration_path is not defined')
combined_arguments += [
'--override_repository=build_configuration={}'.format(self.configuration_path)
]
combined_arguments += self.common_args
combined_arguments += self.common_build_args
combined_arguments += self.get_define_arguments()
@ -371,13 +345,6 @@ class BazelCommandLine:
combined_arguments += self.get_startup_bazel_arguments()
combined_arguments += ['aquery']
if self.configuration_path is None:
raise Exception('configuration_path is not defined')
combined_arguments += [
'--override_repository=build_configuration={}'.format(self.configuration_path)
]
combined_arguments += [
'-c', 'dbg',
'--ios_multi_cpus=sim_arm64',
@ -425,13 +392,6 @@ class BazelCommandLine:
if self.disable_provisioning_profiles:
combined_arguments += ['--//Telegram:disableProvisioningProfiles']
if self.configuration_path is None:
raise Exception('configuration_path is not defined')
combined_arguments += [
'--override_repository=build_configuration={}'.format(self.configuration_path)
]
combined_arguments += self.common_args
combined_arguments += self.common_build_args
combined_arguments += self.get_define_arguments()
@ -562,9 +522,6 @@ def resolve_configuration(base_path, bazel_command_line: BazelCommandLine, argum
file.write(' "{}",\n'.format(file_name))
file.write('])\n')
if bazel_command_line is not None:
bazel_command_line.set_configuration_path(configuration_repository_path)
def generate_project(bazel, arguments):
bazel_command_line = BazelCommandLine(
@ -617,7 +574,6 @@ def generate_project(bazel, arguments):
disable_provisioning_profiles=disable_provisioning_profiles,
include_release=project_include_release,
generate_dsym=generate_dsym,
configuration_path=bazel_command_line.configuration_path,
bazel_app_arguments=bazel_command_line.get_project_generation_arguments(),
target_name=target_name
)
@ -1006,14 +962,10 @@ if __name__ == '__main__':
buildParser.add_argument(
'--configuration',
choices=[
'debug_universal',
'debug_arm64',
'debug_armv7',
'debug_sim_arm64',
'release_sim_arm64',
'release_arm64',
'release_armv7',
'release_universal'
],
required=True,
help='Build configuration'
@ -1254,14 +1206,10 @@ if __name__ == '__main__':
spm_parser.add_argument(
'--configuration',
choices=[
'debug_universal',
'debug_arm64',
'debug_armv7',
'debug_sim_arm64',
'release_sim_arm64',
'release_arm64',
'release_armv7',
'release_universal'
],
required=True,
help='Build configuration'

View file

@ -9,7 +9,7 @@ def remove_directory(path):
if os.path.isdir(path):
shutil.rmtree(path)
def generate_xcodeproj(build_environment: BuildEnvironment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, configuration_path, bazel_app_arguments, target_name):
def generate_xcodeproj(build_environment: BuildEnvironment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, bazel_app_arguments, target_name):
if '/' in target_name:
app_target_spec = target_name.split('/')[0] + '/' + target_name.split('/')[1] + ':' + target_name.split('/')[1]
app_target = target_name
@ -22,7 +22,6 @@ def generate_xcodeproj(build_environment: BuildEnvironment, disable_extensions,
bazel_generate_arguments = [build_environment.bazel_path]
bazel_generate_arguments += ['run', '//{}_xcodeproj'.format(app_target_spec)]
bazel_generate_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
if target_name == 'Telegram':
if disable_extensions:
@ -32,7 +31,6 @@ def generate_xcodeproj(build_environment: BuildEnvironment, disable_extensions,
project_bazel_arguments = []
for argument in bazel_app_arguments:
project_bazel_arguments.append(argument)
project_bazel_arguments += ['--override_repository=build_configuration={}'.format(configuration_path)]
if target_name == 'Telegram':
if disable_extensions:
@ -54,5 +52,5 @@ def generate_xcodeproj(build_environment: BuildEnvironment, disable_extensions,
return xcodeproj_path
def generate(build_environment: BuildEnvironment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, configuration_path, bazel_app_arguments, target_name) -> str:
return generate_xcodeproj(build_environment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, configuration_path, bazel_app_arguments, target_name)
def generate(build_environment: BuildEnvironment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, bazel_app_arguments, target_name) -> str:
return generate_xcodeproj(build_environment, disable_extensions, disable_provisioning_profiles, include_release, generate_dsym, bazel_app_arguments, target_name)

@ -0,0 +1 @@
Subproject commit fb37d850e8715df81761feeea25f2158514fa2be

View file

@ -52,9 +52,9 @@ class EncryptionV2
iv = keyIv[32..43]
auth_data = keyIv[44..-1]
puts "key: #{key.inspect}"
puts "iv: #{iv.inspect}"
puts "auth_data: #{auth_data.inspect}"
#puts "key: #{key.inspect}"
#puts "iv: #{iv.inspect}"
#puts "auth_data: #{auth_data.inspect}"
cipher.key = key
cipher.iv = iv

755
scripts/Telegram Executable file
View file

@ -0,0 +1,755 @@
#!/usr/bin/env python3
# Copyright 2020 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Invoked by `bazel run` to launch *_application targets in the simulator."""
# This script works in one of two modes.
#
# If either --ios_simulator_version or --ios_simulator_device were not
# passed to bazel:
#
# 1. Discovers a simulator compatible with the minimum_os of the
# *_application target, preferring already-booted simulators
# if possible
# 2. Boots the simulator if needed
# 3. Installs and launches the application
# 4. Displays the application's output on the console
#
# This mode does not kill running simulators or shutdown or delete the simulator
# after it completes.
#
# If --ios_simulator_version and --ios_simulator_device were both passed
# to bazel:
#
# 1. Creates a new temporary simulator by running "simctl create ..."
# 2. Boots the new temporary simulator
# 3. Installs and launches the application
# 4. Displays the application's output on the console
# 5. When done, shuts down and deletes the newly-created simulator
#
# All environment variables with names starting with "IOS_" are passed to the
# application, after stripping the prefix "IOS_".
import collections.abc
import contextlib
import json
import logging
import os
import os.path
import pathlib
import platform
import plistlib
import shutil
import subprocess
import sys
import tempfile
import time
from typing import Dict, Optional
import zipfile
# Custom type for methods yielding an Apple simulator UDID.
AppleSimulatorUDID = collections.abc.Generator[str, None, None]
logging.basicConfig(
format="%(asctime)s.%(msecs)03d %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
level=logging.INFO,
)
logger = logging.getLogger(__name__)
if platform.system() != "Darwin":
raise Exception(
"Cannot run Apple platform application targets on a non-mac machine."
)
class DeviceType(collections.abc.Mapping):
"""Wraps the `devicetype` dictionary from `simctl list -j`.
Provides an ordering so iPhones > iPads. In addition, maintains the
original order from `simctl list` as `simctl_list_index` to ensure
newer device types are sorted after older device types.
"""
def __init__(self, device_type, simctl_list_index):
self.device_type = device_type
self.simctl_list_index = simctl_list_index
def __getitem__(self, name):
return self.device_type[name]
def __iter__(self):
return iter(self.device_type)
def __len__(self):
return len(self.device_type)
def __repr__(self):
return self["name"] + " (" + self["identifier"] + ")"
def __lt__(self, other):
# Order iPhones ahead of (later in the list than) iPads.
if self.is_ipad() and other.is_iphone():
return True
elif self.is_iphone() and other.is_ipad():
return False
# Order device types from the same product family in the same order
# as `simctl list`.
return self.simctl_list_index < other.simctl_list_index
def supports_platform_type(self, platform_type: str) -> bool:
"""Returns boolean to indicate if device supports given Apple platform type."""
if platform_type == "ios":
return self.is_iphone() or self.is_ipad()
elif platform_type == "tvos":
return self.is_apple_tv()
elif platform_type == "watchos":
return self.is_apple_watch()
elif platform_type == "visionos":
return self.is_apple_vision()
else:
raise ValueError(
f"Apple platform type not supported for simulator: {platform_type}."
)
def is_apple_tv(self) -> bool:
return self.has_product_family_or_identifier("Apple TV")
def is_apple_watch(self) -> bool:
return self.has_product_family_or_identifier("Apple Watch")
def is_apple_vision(self) -> bool:
return self.has_product_family_or_identifier("Apple Vision")
def is_iphone(self) -> bool:
return self.has_product_family_or_identifier("iPhone")
def is_ipad(self) -> bool:
return self.has_product_family_or_identifier("iPad")
def has_product_family_or_identifier(self, device_type: str) -> bool:
product_family = self.get("productFamily")
if product_family:
return product_family == device_type
# Some older simulators are missing `productFamily`. Try to guess from the
# identifier.
return device_type in self["identifier"]
class Device(collections.abc.Mapping):
"""Wraps the `device` dictionary from `simctl list -j`.
Provides an ordering so booted devices > shutdown devices, delegating
to `DeviceType` order when both devices have the same state.
"""
def __init__(self, device, device_type):
self.device = device
self.device_type = device_type
def is_shutdown(self):
return self["state"] == "Shutdown"
def is_booted(self):
return self["state"] == "Booted"
def __getitem__(self, name):
return self.device[name]
def __iter__(self):
return iter(self.device)
def __len__(self):
return len(self.device)
def __repr__(self):
return self["name"] + "(" + self["udid"] + ")"
def __lt__(self, other):
if self.is_shutdown() and other.is_booted():
return True
elif self.is_booted() and other.is_shutdown():
return False
else:
return self.device_type < other.device_type
def minimum_os_to_simctl_runtime_version(minimum_os: str) -> int:
"""Converts a minimum OS string to a simctl RuntimeVersion integer.
Args:
minimum_os: A string in the form '12.2' or '13.2.3'.
Returns:
An integer in the form 0xAABBCC, where AA is the major version, BB is
the minor version, and CC is the micro version.
"""
# Pad the minimum OS version to major.minor.micro.
minimum_os_components = (minimum_os.split(".") + ["0"] * 3)[:3]
result = 0
for component in minimum_os_components:
result = (result << 8) | int(component)
return result
def discover_best_compatible_simulator(
*,
platform_type: str,
simctl_path: str,
minimum_os: str,
sim_device: str,
sim_os_version: str,
) -> (Optional[DeviceType], Optional[Device]):
"""Discovers the best compatible simulator device type and device.
Args:
platform_type: The Apple platform type for the given *_application() target.
simctl_path: The path to the `simctl` binary.
minimum_os: The minimum OS version required by the *_application() target.
sim_device: Optional name of the device (e.g. "iPhone 8 Plus").
sim_os_version: Optional version of the Apple platform runtime (e.g.
"13.2").
Returns:
A tuple (device_type, device) containing the DeviceType and Device
of the best compatible simulator (might be None if no match was found).
Raises:
subprocess.SubprocessError: if `simctl list` fails or times out.
"""
# The `simctl list` CLI provides only very basic case-insensitive description
# matching search term functionality.
#
# This code needs to enforce a numeric floor on `minimum_os`, so it directly
# parses the JSON output by `simctl list` instead of repeatedly invoking
# `simctl list` with search terms.
cmd = [simctl_path, "list", "-j"]
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as process:
simctl_data = json.load(process.stdout)
if process.wait() != os.EX_OK:
raise subprocess.CalledProcessError(process.returncode, cmd)
compatible_device_types = []
minimum_runtime_version = minimum_os_to_simctl_runtime_version(minimum_os)
# Prepare the device name for case-insensitive matching.
sim_device = sim_device and sim_device.casefold()
# `simctl list` orders device types from oldest to newest. Remember
# the index of each device type to preserve that ordering when
# sorting device types.
for simctl_list_index, device_type in enumerate(simctl_data["devicetypes"]):
device_type = DeviceType(device_type, simctl_list_index)
if not device_type.supports_platform_type(platform_type):
continue
# Some older simulators are missing `maxRuntimeVersion`. Assume those
# simulators support all OSes (even though it's not true).
max_runtime_version = device_type.get("maxRuntimeVersion")
if max_runtime_version and max_runtime_version < minimum_runtime_version:
continue
if sim_device and device_type["name"].casefold() != sim_device:
continue
compatible_device_types.append(device_type)
compatible_device_types.sort()
# logger.info(
# "Found %d potentialcompatible device types.", len(compatible_device_types)
# )
compatible_runtime_identifiers = set()
for runtime in simctl_data["runtimes"]:
if not runtime["isAvailable"]:
continue
if sim_os_version and runtime["version"] != sim_os_version:
continue
compatible_runtime_identifiers.add(runtime["identifier"])
compatible_devices = []
for runtime_identifier, devices in simctl_data["devices"].items():
if runtime_identifier not in compatible_runtime_identifiers:
continue
for device in devices:
if not device["isAvailable"]:
continue
compatible_device = None
for device_type in compatible_device_types:
if device["deviceTypeIdentifier"] == device_type["identifier"]:
compatible_device = Device(device, device_type)
break
if not compatible_device:
continue
compatible_devices.append(compatible_device)
compatible_devices.sort()
logger.debug("Found %d compatible devices.", len(compatible_devices))
if compatible_device_types:
best_compatible_device_type = compatible_device_types[-1]
else:
best_compatible_device_type = None
if compatible_devices:
best_compatible_device = compatible_devices[-1]
else:
best_compatible_device = None
return (best_compatible_device_type, best_compatible_device)
def persistent_simulator(
*,
platform_type: str,
simctl_path: str,
minimum_os: str,
sim_device: str,
sim_os_version: str,
) -> str:
"""Finds or creates a persistent compatible Apple simulator.
Boots the simulator if needed. Does not shut down or delete the simulator when
done.
Args:
platform_type: The Apple platform type for the given *_application() target.
simctl_path: The path to the `simctl` binary.
minimum_os: The minimum OS version required by the *_application() target.
sim_device: Optional name of the device (e.g. "iPhone 8 Plus").
sim_os_version: Optional version of the Apple platform runtime (e.g.
"13.2").
Returns:
The UDID of the compatible Apple simulator.
Raises:
Exception: if a compatible simulator was not found.
"""
(best_compatible_device_type, best_compatible_device) = (
discover_best_compatible_simulator(
platform_type=platform_type,
simctl_path=simctl_path,
minimum_os=minimum_os,
sim_device=sim_device,
sim_os_version=sim_os_version,
)
)
if best_compatible_device:
udid = best_compatible_device["udid"]
if best_compatible_device.is_shutdown():
logger.debug("Booting compatible device: %s", best_compatible_device)
subprocess.run([simctl_path, "boot", udid], check=True)
else:
logger.debug("Using compatible device: %s", best_compatible_device)
return udid
if best_compatible_device_type:
device_name = best_compatible_device_type["name"]
device_id = best_compatible_device_type["identifier"]
# logger.info("Creating new %s simulator", device_name)
create_result = subprocess.run(
[simctl_path, "create", device_name, device_id],
encoding="utf-8",
stdout=subprocess.PIPE,
check=True,
)
udid = create_result.stdout.rstrip()
logger.debug("Created new simulator: %s", udid)
return udid
raise Exception(
f"Could not find or create a simulator for the {platform_type} platform"
f"compatible with minimum OS version {minimum_os} (device name "
f"{sim_device}, OS version {sim_os_version})"
)
def wait_for_sim_to_boot(simctl_path: str, udid: str) -> bool:
"""Blocks until the given simulator is booted.
Args:
simctl_path: The path to the `simctl` binary.
udid: The identifier of the simulator to wait for.
Returns:
True if the simulator boots within 60 seconds, False otherwise.
"""
logger.info("Waiting for simulator to boot...")
for _ in range(0, 60):
# The expected output of "simctl list" is like:
# -- iOS 8.4 --
# iPhone 5s (E946FA1C-26AB-465C-A7AC-24750D520BEA) (Shutdown)
# TestDevice (8491C4BC-B18E-4E2D-934A-54FA76365E48) (Booted)
# So if there's any booted simulator, $booted_device will not be empty.
#logger.info("will list devices with udid: %s", udid)
simctl_list_result = subprocess.run(
[simctl_path, "list", "devices"],
encoding="utf-8",
check=True,
stdout=subprocess.PIPE,
)
#logger.info(simctl_list_result.stdout)
for line in simctl_list_result.stdout.split("\n"):
if line.find(udid) != -1 and line.find("Booted") != -1:
logger.debug("Simulator is booted.")
# Simulator is booted.
return True
logger.debug("Simulator not booted, still waiting...")
time.sleep(1)
return False
def boot_simulator(*, developer_path: str, simctl_path: str, udid: str) -> None:
"""Launches the Apple simulator for the given identifier.
Ensures the Simulator process is in the foreground.
Args:
developer_path: The path to /Applications/Xcode.app/Contents/Developer.
simctl_path: The path to the `simctl` binary.
udid: The identifier of the simulator to wait for.
Raises:
Exception: if the simulator did not launch within 60 seconds.
"""
logger.info("Launching simulator with udid: %s", udid)
# Using subprocess.Popen() to launch Simulator.app and then
# `osascript -e "tell application \"Simulator\" to activate" is racy
# and can fail with:
#
# Simulator got an error: Connection is invalid. (-609)
#
# This is likely because the newly-spawned Simulator.app process
# hasn't had time to connect to the Apple Events system which
# `osascript` relies on.
simulator_path = os.path.join(developer_path, "Applications/Simulator.app")
subprocess.run(
["open", "-a", simulator_path, "--args", "-CurrentDeviceUDID", udid],
check=True,
)
logger.debug("Simulator launched.")
if not wait_for_sim_to_boot(simctl_path, udid):
raise Exception("Failed to launch simulator with UDID: " + udid)
@contextlib.contextmanager
def temporary_simulator(
*, platform_type: str, simctl_path: str, device: str, version: str
) -> AppleSimulatorUDID:
"""Creates a temporary Apple simulator, cleaned up automatically upon close.
Args:
platform_type: The Apple platform type for the given *_application() target.
simctl_path: The path to the `simctl` binary.
device: The name of the device (e.g. "iPhone 8 Plus").
version: The version of the Apple platform runtime (e.g. "13.2").
Yields:
The UDID of the newly-created Apple simulator.
"""
runtime_version_name = version.replace(".", "-")
# capitalizes 'os' from Apple platform type string (e.g. watchos -> watchOS)
runtime_platform = platform_type[0:-2].lower() + platform_type[-2:].upper()
# logger.info("Creating simulator, device=%s, version=%s", device, version)
simctl_create_result = subprocess.run(
[
simctl_path,
"create",
"TestDevice",
device,
"{prefix}.{runtime_platform}-{runtime_version_name}".format(
prefix="com.apple.CoreSimulator.SimRuntime",
runtime_platform=runtime_platform,
runtime_version_name=runtime_version_name,
),
],
encoding="utf-8",
check=True,
stdout=subprocess.PIPE,
)
udid = simctl_create_result.stdout.rstrip()
try:
logger.info("Killing all running simulators...")
subprocess.run(
["pkill", "Simulator"], stderr=subprocess.DEVNULL, check=False
)
yield udid
finally:
logger.info("Shutting down simulator with udid: %s", udid)
subprocess.run(
[simctl_path, "shutdown", udid], stderr=subprocess.DEVNULL, check=False
)
logger.info("Deleting simulator with udid: %s", udid)
subprocess.run([simctl_path, "delete", udid], check=True)
def register_dsyms(dsyms_dir: str):
"""Adds all dSYMs in `dsyms_dir` to the symbolscache.
Args:
dsyms_dir: Path to directory potentially containing dSYMs
"""
symbolscache_command = [
"/usr/bin/symbolscache",
"delete",
"--tag",
"Bazel",
"compact",
"add",
"--tag",
"Bazel",
] + [
a
for a in pathlib.Path(dsyms_dir).glob(
"**/*.dSYM/Contents/Resources/DWARF/*"
)
]
logger.debug("Running command: %s", symbolscache_command)
result = subprocess.run(
symbolscache_command,
capture_output=True,
check=True,
encoding="utf-8",
text=True,
)
logger.debug("symbolscache output: %s", result.stdout)
@contextlib.contextmanager
def extracted_app(
application_output_path: str, app_name: str
) -> AppleSimulatorUDID:
"""Extracts Foo.app from *_application() output and makes it writable.
Args:
application_output_path: Path to the output of an `*_application()`. If the
path is a directory, copies it to a temporary directory and makes the
contents writable, as `simctl install` fails to install an `.app` that is
read-only. If the path is an .ipa archive, unzips it to a temporary
directory.
app_name: The name of the application (e.g. "Foo" for "Foo.app").
Yields:
Path to Foo.app in temporary directory (re-used if already present).
"""
if os.path.isdir(application_output_path):
# Re-use the same path for each run and rsync to it (reducing
# copies). Ensure the result is writable, or `simctl install` will
# fail with `Unhandled error domain NSPOSIXErrorDomain, code 13`.
dst_dir = os.path.join(tempfile.gettempdir(), "bazel_temp_" + app_name)
os.makedirs(dst_dir, exist_ok=True)
# NOTE: use `which` to find the path to `rsync`.
# In macOS 15.4, the system `rsync` is using `openrsync` which contains some permission issues.
# This allows users to workaround the issue by overriding the system `rsync` with a working version.
# Remove this once we no longer support macOS versions with broken `rsync`.
rsync_path = shutil.which("rsync")
rsync_command = [
rsync_path,
"--archive",
"--delete",
"--checksum",
"--chmod=u+w",
"--verbose",
# The output path might itself be a symlink; resolve to the
# real path so rsync doesn't just copy the symlink.
os.path.realpath(application_output_path),
dst_dir,
]
logger.debug(
"Found app directory: %s, running command: %s",
application_output_path,
rsync_command,
)
result = subprocess.run(
rsync_command,
capture_output=True,
check=True,
encoding="utf-8",
text=True,
)
logger.debug("rsync output: %s", result.stdout)
yield os.path.join(dst_dir, app_name + ".app")
else:
# Create a new temporary directory for each run, deleting it
# afterwards (there's no efficient way to "sync" an unzip, so this
# can't re-use the output directory).
with tempfile.TemporaryDirectory(prefix="bazel_temp") as temp_dir:
logger.debug(
"Unzipping IPA from %s to %s", application_output_path, temp_dir
)
with zipfile.ZipFile(application_output_path) as ipa_zipfile:
ipa_zipfile.extractall(temp_dir)
yield os.path.join(temp_dir, "Payload", app_name + ".app")
def bundle_id(bundle_path: str) -> str:
"""Returns the bundle ID given a bundle directory path."""
info_plist_path = os.path.join(bundle_path, "Info.plist")
with open(info_plist_path, mode="rb") as plist_file:
plist = plistlib.load(plist_file)
return plist["CFBundleIdentifier"]
def simctl_launch_environ() -> Dict[str, str]:
"""Calculates an environment dictionary for running `simctl launch`."""
# Pass environment variables prefixed with "IOS_" to the simulator, replace
# the prefix with "SIMCTL_CHILD_". bazel adds "IOS_" to the env vars which
# will be passed to the app as prefix to differentiate from other env vars. We
# replace the prefix "IOS_" with "SIMCTL_CHILD_" here, because "simctl" only
# pass the env vars prefixed with "SIMCTL_CHILD_" to the app.
result = {}
for k, v in os.environ.items():
if not k.startswith("IOS_"):
continue
new_key = k.replace("IOS_", "SIMCTL_CHILD_", 1)
result[new_key] = v
if "IDE_DISABLED_OS_ACTIVITY_DT_MODE" not in os.environ:
# Ensure os_log() mirrors writes to stderr. (lldb and Xcode set this
# environment variable as well.)
result["SIMCTL_CHILD_OS_ACTIVITY_DT_MODE"] = "enable"
return result
@contextlib.contextmanager
def apple_simulator(
*,
platform_type: str,
simctl_path: str,
minimum_os: str,
sim_device: str,
sim_os_version: str,
) -> AppleSimulatorUDID:
"""Finds either a temporary or persistent Apple simulator based on args.
Args:
platform_type: The Apple platform type for the given *_application() target.
simctl_path: The path to the `simctl` binary.
minimum_os: The minimum OS version required by the *_application() target.
sim_device: Optional name of the device (e.g. "iPhone 8 Plus").
sim_os_version: Optional version of the Apple platform runtime (e.g.
"13.2").
Yields:
The UDID of the simulator.
"""
yield persistent_simulator(
platform_type=platform_type,
simctl_path=simctl_path,
minimum_os=minimum_os,
sim_device=sim_device,
sim_os_version=sim_os_version,
)
def run_app_in_simulator(
*,
simulator_udid: str,
developer_path: str,
simctl_path: str,
application_output_path: str,
app_name: str,
) -> None:
"""Installs and runs an app in the specified simulator.
Args:
simulator_udid: The UDID of the simulator in which to run the app.
developer_path: The path to /Applications/Xcode.app/Contents/Developer.
simctl_path: The path to the `simctl` binary.
application_output_path: Path to the output of an `*_application()`.
app_name: The name of the application (e.g. "Foo" for "Foo.app").
"""
boot_simulator(
developer_path=developer_path,
simctl_path=simctl_path,
udid=simulator_udid,
)
root_dir = os.path.dirname(application_output_path)
register_dsyms(root_dir)
with extracted_app(application_output_path, app_name) as app_path:
logger.info("Will use simulator: %s", simulator_udid)
logger.info(
"Terminating any existing instances of the app in that simulator..."
)
# First, quietly kill any existing instances of the app
app_bundle_id = bundle_id(app_path)
subprocess.run(
[simctl_path, "terminate", simulator_udid, app_bundle_id],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
logger.info("Installing...")
subprocess.run(
[simctl_path, "install", simulator_udid, app_path], check=True
)
logger.info(
"Launching..."
)
args = [
simctl_path,
"launch",
]
# Append optional launch arguments.
args.extend(sys.argv[1:])
args.extend([
simulator_udid,
app_bundle_id,
])
subprocess.run(args, env=simctl_launch_environ(), check=True)
def main(
*,
app_name: str,
application_output_path: str,
minimum_os: str,
platform_type: str,
sim_device: str,
sim_os_version: str,
):
"""Main entry point to `bazel run` for *_application() targets.
Args:
app_name: The name of the application (e.g. "Foo" for "Foo.app").
application_output_path: Path to the output of an *_application().
minimum_os: The minimum OS version required by the *_application() target.
platform_type: The Apple platform type for the given *_application() target.
sim_device: The name of the device (e.g. "iPhone 8 Plus").
sim_os_version: The version of the Apple platform runtime (e.g. "13.2").
"""
xcode_select_result = subprocess.run(
["xcode-select", "-p"],
encoding="utf-8",
check=True,
stdout=subprocess.PIPE,
)
developer_path = xcode_select_result.stdout.rstrip()
simctl_path = os.path.join(developer_path, "usr", "bin", "simctl")
with apple_simulator(
platform_type=platform_type,
simctl_path=simctl_path,
minimum_os=minimum_os,
sim_device=sim_device,
sim_os_version=sim_os_version,
) as simulator_udid:
run_app_in_simulator(
simulator_udid=simulator_udid,
developer_path=developer_path,
simctl_path=simctl_path,
application_output_path=application_output_path,
app_name=app_name,
)
if __name__ == "__main__":
main(
app_name="Telegram",
application_output_path="Telegram/Telegram.ipa",
minimum_os="13.0",
platform_type="ios",
sim_device="iPhone 16 Pro",
sim_os_version="26.0",
)

39
scripts/launch_and_debug.sh Executable file
View file

@ -0,0 +1,39 @@
#!/bin/zsh
set -e
# We don't use bazelisk run because it does a bunch of things we don't want in this case.
# Instead, we have our own script for launching the simulator and lldb.
# Ideally we should upstream these changes back to rules_apple since they should be useful for everyone.
echo "Building..."
./build-input/bazel-8.4.2-darwin-arm64 build Telegram/Telegram --announce_rc --features=swift.use_global_module_cache --verbose_failures --remote_cache_async --jobs=16 --define=buildNumber=10000 --define=telegramVersion=12.2.1 --disk_cache=/Users/ali/telegram-bazel-cache -c dbg --ios_multi_cpus=sim_arm64 --watchos_cpus=arm64_32 --features=swift.enable_batch_mode
chmod -R 777 ./bazel-bin/Telegram
tmp_file=$(pwd)/bazel-bin/Telegram/pid.txt
rm ${tmp_file} > /dev/null 2>&1 || true
touch ${tmp_file}
cp ./scripts/Telegram ./bazel-bin/Telegram/Telegram
pushd ./bazel-bin
python3 ./Telegram/Telegram --wait-for-debugger --stdout=$(tty) --stderr=$(tty) > ${tmp_file}
popd
# Get pid from the tmp_file
echo "$(cat "${tmp_file}" | awk -F': ' '{print $2}')" > ${tmp_file}
# Ugly hack to remove the newline from the file
pid=$(tr -d '\n' < ${tmp_file})
echo "Launched app's pid: ${pid}"
xcode_path=$(xcode-select -p)
debugserver_path="${xcode_path}/../SharedFrameworks/LLDB.framework/Versions/A/Resources/debugserver"
# Just for sanity, kill any other debugservers that might be running
pgrep -lfa Resources/debugserver | awk '{print $1}' | xargs kill -9
# Launch the debugserver. The output of this command will signal the IDE to launch the lldb extension,
# which is hardcoded to connect to port 6667.
${debugserver_path} "localhost:6667" --attach ${pid}
# Kill the app when debugging ends, just like in Xcode.
kill -9 ${pid} > /dev/null 2>&1 || true

View file

@ -1178,6 +1178,7 @@ public enum StarsWithdrawalScreenSubject {
case enterAmount(current: StarsAmount, minValue: StarsAmount, fractionAfterCommission: Int, kind: PaidMessageKind, completion: (Int64) -> Void)
case postSuggestion(channel: EnginePeer, isFromAdmin: Bool, current: CurrencyAmount, timestamp: Int32?, completion: (CurrencyAmount, Int32?) -> Void)
case postSuggestionModification(current: CurrencyAmount, timestamp: Int32?, completion: (CurrencyAmount, Int32?) -> Void)
case starGiftOffer(peer: EnginePeer, gift: StarGift.UniqueGift, completion: (CurrencyAmount, Int32) -> Void)
}
public enum ChannelMembersSearchControllerMode {
@ -1272,6 +1273,7 @@ public protocol SharedAccountContext: AnyObject {
func navigateToChat(accountId: AccountRecordId, peerId: PeerId, messageId: MessageId?)
func openChatMessage(_ params: OpenChatMessageParams) -> Bool
func messageFromPreloadedChatHistoryViewForLocation(id: MessageId, location: ChatHistoryLocationInput, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject?, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, tag: HistoryViewInputTag?) -> Signal<(MessageIndex?, Bool), NoError>
func makeOverlayAudioPlayerController(context: AccountContext, chatLocation: ChatLocation, type: MediaManagerPlayerType, initialMessageId: MessageId, initialOrder: MusicPlaybackSettingsOrder, playlistLocation: SharedMediaPlaylistLocation?, parentNavigationController: NavigationController?) -> ViewController & OverlayAudioPlayerController
func makePeerInfoController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, fromChat: Bool, requestsContext: PeerInvitationImportersContext?) -> ViewController?
func makeChannelAdminController(context: AccountContext, peerId: PeerId, adminId: PeerId, initialParticipant: ChannelParticipant) -> ViewController?
@ -1355,54 +1357,34 @@ public protocol SharedAccountContext: AnyObject {
func makeInstantPageController(context: AccountContext, message: Message, sourcePeerType: MediaAutoDownloadPeerType?) -> ViewController?
func makeInstantPageController(context: AccountContext, webPage: TelegramMediaWebpage, anchor: String?, sourceLocation: InstantPageSourceLocation) -> ViewController
func openChatWallpaper(context: AccountContext, message: Message, present: @escaping (ViewController, Any?) -> Void)
func makeRecentSessionsController(context: AccountContext, activeSessionsContext: ActiveSessionsContext) -> ViewController & RecentSessionsController
func makeChatQrCodeScreen(context: AccountContext, peer: Peer, threadId: Int64?, temporary: Bool) -> ViewController
func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController
func makePremiumIntroController(sharedContext: SharedAccountContext, engine: TelegramEngineUnauthorized, inAppPurchaseManager: InAppPurchaseManager, source: PremiumIntroSource, proceed: (() -> Void)?) -> ViewController
func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, forceDark: Bool, action: @escaping () -> Void, dismissed: (() -> Void)?) -> ViewController
func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController
func makeStarsGiftController(context: AccountContext, birthdays: [EnginePeer.Id: TelegramBirthday]?, completion: @escaping (([EnginePeer.Id]) -> Void)) -> ViewController
func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (([EnginePeer.Id]) -> Signal<Never, TransferStarGiftError>)?) -> ViewController
func makeGiftOptionsController(context: AccountContext, peerId: EnginePeer.Id, premiumOptions: [CachedPremiumGiftOption], hasBirthday: Bool, completion: (() -> Void)?) -> ViewController
func makeGiftStoreController(context: AccountContext, peerId: EnginePeer.Id, gift: StarGift.Gift) -> ViewController
func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController
func makePremiumBoostLevelsController(context: AccountContext, peerId: EnginePeer.Id, subject: BoostSubject, boostStatus: ChannelBoostStatus, myBoostStatus: MyBoostStatus, forceDark: Bool, openStats: (() -> Void)?) -> ViewController
func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], actionTitle: String?, isEditing: Bool, expandIfNeeded: Bool, parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?, actionPerformed: ((Bool) -> Void)?) -> ViewController
func makeCameraScreen(context: AccountContext, mode: CameraScreenMode, cameraHolder: Any?, transitionIn: CameraScreenTransitionIn?, transitionOut: @escaping (Bool) -> CameraScreenTransitionOut?, completion: @escaping (Any, @escaping () -> Void) -> Void, transitionedOut: (() -> Void)?) -> ViewController
func makeMediaPickerScreen(context: AccountContext, hasSearch: Bool, completion: @escaping (Any) -> Void) -> ViewController
func makeStoryMediaEditorScreen(context: AccountContext, source: Any?, text: String?, link: (url: String, name: String?)?, remainingCount: Int32, completion: @escaping ([MediaEditorScreenResult], MediaEditorTransitionOutExternalState, @escaping (@escaping () -> Void) -> Void) -> Void) -> ViewController
func makeBotPreviewEditorScreen(context: AccountContext, source: Any?, target: Stories.PendingTarget, transitionArguments: (UIView, CGRect, UIImage?)?, transitionOut: @escaping () -> BotPreviewEditorTransitionOut?, externalState: MediaEditorTransitionOutExternalState, completion: @escaping (MediaEditorScreenResult, @escaping (@escaping () -> Void) -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController
func makeStickerEditorScreen(context: AccountContext, source: Any?, intro: Bool, transitionArguments: (UIView, CGRect, UIImage?)?, completion: @escaping (TelegramMediaFile, [String], @escaping () -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController
func makeStickerMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect?, completion: @escaping (Any?, UIView?, CGRect, UIImage?, Bool, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController
func makeAvatarMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect?, canDelete: Bool, performDelete: @escaping () -> Void, completion: @escaping (Any?, UIView?, CGRect, UIImage?, Bool, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController
func makeStoryMediaPickerScreen(context: AccountContext, isDark: Bool, forCollage: Bool, selectionLimit: Int?, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, multipleCompletion: @escaping ([Any], Bool) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController
func makeStickerPickerScreen(context: AccountContext, inputData: Promise<StickerPickerInput>, completion: @escaping (FileMediaReference) -> Void) -> ViewController
func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController
func makeDataAndStorageController(context: AccountContext, sensitiveContent: Bool) -> ViewController
func makeInstalledStickerPacksController(context: AccountContext, mode: InstalledStickerPacksControllerMode, forceTheme: PresentationTheme?) -> ViewController
func makeChannelStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: EnginePeer.Id, boosts: Bool, boostStatus: ChannelBoostStatus?) -> ViewController
func makeMessagesStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, messageId: EngineMessage.Id) -> ViewController
func makeStoryStatsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: EnginePeer.Id, storyId: Int32, storyItem: EngineStoryItem, fromStory: Bool) -> ViewController
func makeStarsTransactionsScreen(context: AccountContext, starsContext: StarsContext) -> ViewController
func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [Any], purpose: StarsPurchasePurpose, targetPeerId: EnginePeer.Id?, customTheme: PresentationTheme?, completion: @escaping (Int64) -> Void) -> ViewController
func makeStarsTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, source: BotPaymentInvoiceSource, extendedMedia: [TelegramExtendedMedia], inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?, EnginePeer?)?, NoError>, completion: @escaping (Bool) -> Void) -> ViewController
@ -1421,38 +1403,32 @@ public protocol SharedAccountContext: AnyObject {
func makeStarsIntroScreen(context: AccountContext) -> ViewController
func makeGiftViewScreen(context: AccountContext, message: EngineMessage, shareStory: ((StarGift.UniqueGift) -> Void)?) -> ViewController
func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: ((StarGift.UniqueGift) -> Void)?, openChatTheme: (() -> Void)?, dismissed: (() -> Void)?) -> ViewController
func makeGiftWearPreviewScreen(context: AccountContext, gift: StarGift.UniqueGift) -> ViewController
func makeGiftWearPreviewScreen(context: AccountContext, gift: StarGift, attributes: [StarGift.UniqueGift.Attribute]?) -> ViewController
func makeGiftUpgradePreviewScreen(context: AccountContext, attributes: [StarGift.UniqueGift.Attribute], peerName: String) -> ViewController
func makeGiftAuctionInfoScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: (() -> Void)?) -> ViewController
func makeGiftAuctionBidScreen(context: AccountContext, toPeerId: EnginePeer.Id, text: String?, entities: [MessageTextEntity]?, hideName: Bool, auctionContext: GiftAuctionContext, acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?) -> ViewController
func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: @escaping (Signal<[GiftAuctionAcquiredGift], NoError>) -> Void) -> ViewController
func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: @escaping (Signal<[GiftAuctionAcquiredGift], NoError>, [StarGift.UniqueGift.Attribute]?) -> Void) -> ViewController
func makeGiftAuctionActiveBidsScreen(context: AccountContext) -> ViewController
func makeGiftOfferScreen(context: AccountContext, gift: StarGift.UniqueGift, peer: EnginePeer, amount: CurrencyAmount, commit: @escaping () -> Void) -> ViewController
func makeGiftUpgradeVariantsPreviewScreen(context: AccountContext, gift: StarGift, attributes: [StarGift.UniqueGift.Attribute]) -> ViewController
func makeGiftAuctionWearPreviewScreen(context: AccountContext, auctionContext: GiftAuctionContext, acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?, attributes: [StarGift.UniqueGift.Attribute], completion: @escaping () -> Void) -> ViewController
func makeGiftDemoScreen(context: AccountContext) -> ViewController
func makeStorySharingScreen(context: AccountContext, subject: StorySharingSubject, parentController: ViewController) -> ViewController
func makeContentReportScreen(context: AccountContext, subject: ReportContentSubject, forceDark: Bool, present: @escaping (ViewController) -> Void, completion: @escaping () -> Void, requestSelectMessages: ((String, Data, String?) -> Void)?)
func makeShareController(context: AccountContext, subject: ShareControllerSubject, forceExternal: Bool, shareStory: (() -> Void)?, enqueued: (([PeerId], [Int64]) -> Void)?, actionCompleted: (() -> Void)?) -> ViewController
func makeMiniAppListScreenInitialData(context: AccountContext) -> Signal<MiniAppListScreenInitialData, NoError>
func makeMiniAppListScreen(context: AccountContext, initialData: MiniAppListScreenInitialData) -> ViewController
func makeIncomingMessagePrivacyScreen(context: AccountContext, value: GlobalPrivacySettings.NonContactChatsPrivacy, exceptions: SelectivePrivacySettings, update: @escaping (GlobalPrivacySettings.NonContactChatsPrivacy) -> Void) -> ViewController
func openWebApp(context: AccountContext, parentController: ViewController, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, botPeer: EnginePeer, chatPeer: EnginePeer?, threadId: Int64?, buttonText: String, url: String, simple: Bool, source: ChatOpenWebViewSource, skipTermsOfService: Bool, payload: String?, verifyAgeCompletion: ((Int) -> Void)?)
func makeAffiliateProgramSetupScreenInitialData(context: AccountContext, peerId: EnginePeer.Id, mode: AffiliateProgramSetupScreenMode) -> Signal<AffiliateProgramSetupScreenInitialData, NoError>
func makeAffiliateProgramSetupScreen(context: AccountContext, initialData: AffiliateProgramSetupScreenInitialData) -> ViewController
func makeAffiliateProgramJoinScreen(context: AccountContext, sourcePeer: EnginePeer, commissionPermille: Int32, programDuration: Int32?, revenuePerUser: Double, mode: JoinAffiliateProgramScreenMode) -> ViewController
func makeJoinSubjectScreen(context: AccountContext, mode: JoinSubjectScreenMode) -> ViewController
func makeOldChannelsController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, intent: OldChannelsControllerIntent, completed: @escaping (Bool) -> Void) -> ViewController
func makeGalleryController(context: AccountContext, source: GalleryControllerItemSource, streamSingleVideo: Bool, isPreview: Bool) -> ViewController
func makeAccountFreezeInfoScreen(context: AccountContext) -> ViewController
func makeSendInviteLinkScreen(context: AccountContext, subject: SendInviteLinkScreenSubject, peers: [TelegramForbiddenInvitePeer], theme: PresentationTheme?) -> ViewController
@available(iOS 13.0, *)
func makePostSuggestionsSettingsScreen(context: AccountContext, peerId: EnginePeer.Id) async -> ViewController
@ -1471,6 +1447,7 @@ public protocol SharedAccountContext: AnyObject {
func makeNewContactScreen(context: AccountContext, peer: EnginePeer?, phoneNumber: String?, shareViaException: Bool, completion: @escaping (EnginePeer?, DeviceContactStableId?, DeviceContactExtendedData?) -> Void) -> ViewController
func makeLoginEmailSetupController(context: AccountContext, blocking: Bool, emailPattern: String?, canAutoDismissIfNeeded: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController
func makePasskeySetupController(context: AccountContext, displaySkip: Bool, navigationController: NavigationController?, completion: @escaping () -> Void, dismiss: @escaping () -> Void) -> ViewController
func navigateToCurrentCall()
var hasOngoingCall: ValuePromise<Bool> { get }

View file

@ -144,6 +144,7 @@ public enum StarsPurchasePurpose: Equatable {
case sendMessage(peerId: EnginePeer.Id, requiredStars: Int64)
case buyStarGift(requiredStars: Int64)
case removeOriginalDetailsStarGift(requiredStars: Int64)
case starGiftOffer(requiredStars: Int64)
}
public struct PremiumConfiguration {

View file

@ -170,7 +170,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
if let currentController = currentController {
controller = currentController
} else {
controller = AuthorizationSequencePhoneEntryController(sharedContext: self.sharedContext, account: self.account, isTestingEnvironment: self.account.testingEnvironment, otherAccountPhoneNumbers: self.otherAccountPhoneNumbers, network: self.account.network, presentationData: self.presentationData, openUrl: { [weak self] url in
controller = AuthorizationSequencePhoneEntryController(sharedContext: self.sharedContext, account: self.account, apiId: self.apiId, apiHash: self.apiHash, isTestingEnvironment: self.account.testingEnvironment, otherAccountPhoneNumbers: self.otherAccountPhoneNumbers, network: self.account.network, presentationData: self.presentationData, openUrl: { [weak self] url in
self?.openUrl(url)
}, back: { [weak self] in
guard let strongSelf = self else {
@ -315,6 +315,48 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
}
})
}
controller.loginWithPasskey = { [weak self, weak controller] passkey, syncContacts in
guard let self else {
return
}
self.actionDisposable.set((authorizeWithPasskey(
accountManager: self.sharedContext.accountManager,
account: self.account,
passkey: passkey,
foreignDatacenter: nil,
forcedPasswordSetupNotice: { value in
guard let entry = CodableEntry(ApplicationSpecificCounterNotice(value: value)) else {
return nil
}
return (ApplicationSpecificNotice.forcedPasswordSetupKey(), entry)
},
syncContacts: syncContacts
)
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
guard let self else {
return
}
if result.updatedAccount !== self.account {
self.account = result.updatedAccount
self.inAppPurchaseManager = InAppPurchaseManager(engine: .unauthorized(self.engine))
}
}, error: { [weak self, weak controller] error in
Queue.mainQueue().async {
if let strongSelf = self, let controller {
let text: String
switch error {
case .limitExceeded:
text = strongSelf.presentationData.strings.Login_CodeFloodError
case .generic, .invalidEmailAddress, .codeExpired, .invalidEmailToken, .invalidCode:
text = strongSelf.presentationData.strings.Login_UnknownError
}
controller.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}
}
}))
}
}
controller.updateData(countryCode: countryCode, countryName: nil, number: number)
return controller

View file

@ -12,8 +12,9 @@ import CountrySelectionUI
import PhoneNumberFormat
import DebugSettingsUI
import MessageUI
import AuthenticationServices
public final class AuthorizationSequencePhoneEntryController: ViewController, MFMailComposeViewControllerDelegate {
public final class AuthorizationSequencePhoneEntryController: ViewController, MFMailComposeViewControllerDelegate, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
private var controllerNode: AuthorizationSequencePhoneEntryControllerNode {
return self.displayNode as! AuthorizationSequencePhoneEntryControllerNode
}
@ -22,6 +23,8 @@ public final class AuthorizationSequencePhoneEntryController: ViewController, MF
private let sharedContext: SharedAccountContext
private var account: UnauthorizedAccount?
private let apiId: Int32
private let apiHash: String
private let isTestingEnvironment: Bool
private let otherAccountPhoneNumbers: ((String, AccountRecordId, Bool)?, [(String, AccountRecordId, Bool)])
private let network: Network
@ -52,6 +55,7 @@ public final class AuthorizationSequencePhoneEntryController: ViewController, MF
}
}
public var loginWithNumber: ((String, Bool) -> Void)?
public var loginWithPasskey: ((AuthorizationPasskeyData, Bool) -> Void)?
var accountUpdated: ((UnauthorizedAccount) -> Void)?
weak var confirmationController: PhoneConfirmationController?
@ -60,9 +64,11 @@ public final class AuthorizationSequencePhoneEntryController: ViewController, MF
private let hapticFeedback = HapticFeedback()
public init(sharedContext: SharedAccountContext, account: UnauthorizedAccount?, countriesConfiguration: CountriesConfiguration? = nil, isTestingEnvironment: Bool, otherAccountPhoneNumbers: ((String, AccountRecordId, Bool)?, [(String, AccountRecordId, Bool)]), network: Network, presentationData: PresentationData, openUrl: @escaping (String) -> Void, back: @escaping () -> Void) {
public init(sharedContext: SharedAccountContext, account: UnauthorizedAccount?, countriesConfiguration: CountriesConfiguration? = nil, apiId: Int32, apiHash: String, isTestingEnvironment: Bool, otherAccountPhoneNumbers: ((String, AccountRecordId, Bool)?, [(String, AccountRecordId, Bool)]), network: Network, presentationData: PresentationData, openUrl: @escaping (String) -> Void, back: @escaping () -> Void) {
self.sharedContext = sharedContext
self.account = account
self.apiId = apiId
self.apiHash = apiHash
self.isTestingEnvironment = isTestingEnvironment
self.otherAccountPhoneNumbers = otherAccountPhoneNumbers
self.network = network
@ -151,6 +157,12 @@ public final class AuthorizationSequencePhoneEntryController: ViewController, MF
strongSelf.account = account
strongSelf.accountUpdated?(account)
}
self.controllerNode.retryPasskey = { [weak self] in
guard let self else {
return
}
self.loadAndPresentPasskey(force: true)
}
if let (code, name, number) = self.currentData {
self.controllerNode.codeAndNumber = (code, name, number)
@ -187,6 +199,124 @@ public final class AuthorizationSequencePhoneEntryController: ViewController, MF
} else {
self.controllerNode.updateCountryCode()
}
self.loadAndPresentPasskey(force: false)
}
private func loadAndPresentPasskey(force: Bool) {
if #available(iOS 16.0, *) {
Task { @MainActor [weak self] in
guard let self, let account = self.account else {
return
}
let decodeBase64: (String) -> Data? = { string in
var string = string.replacingOccurrences(of: "-", with: "+")
.replacingOccurrences(of: "_", with: "/")
while string.count % 4 != 0 {
string.append("=")
}
return Data(base64Encoded: string)
}
let engine = TelegramEngineUnauthorized(account: account)
let passkeyDataString = await engine.auth.requestPasskeyLoginData(apiId: self.apiId, apiHash: self.apiHash).get()
guard let passkeyDataString, let passkeyData = passkeyDataString.data(using: .utf8) else {
return
}
guard let params = try? JSONSerialization.jsonObject(with: passkeyData) as? [String: Any] else {
return
}
guard let pkDict = params["publicKey"] as? [String: Any] else {
return
}
guard let relyingPartyIdentifier = pkDict["rpId"] as? String else {
return
}
guard let challengeBase64 = pkDict["challenge"] as? String else {
return
}
guard let challengeData = decodeBase64(challengeBase64) else {
return
}
let platformProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: relyingPartyIdentifier)
let platformKeyRequest = platformProvider.createCredentialAssertionRequest(challenge: challengeData)
let authController = ASAuthorizationController(authorizationRequests: [platformKeyRequest])
authController.delegate = self
authController.presentationContextProvider = self
if force {
authController.performRequests()
} else {
authController.performRequests(options: [.preferImmediatelyAvailableCredentials])
}
}
}
}
public func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
Task { @MainActor [weak self] in
guard let self, let account = self.account else {
return
}
let encodeBase64URL: (Data) -> String = { data in
var string = data.base64EncodedString()
string = string
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
string = string.replacingOccurrences(of: "=", with: "")
return string
}
if #available(iOS 17.0, *) {
if let credential = authorization.credential as? ASAuthorizationPlatformPublicKeyCredentialAssertion {
guard let clientData = String(data: credential.rawClientDataJSON, encoding: .utf8) else {
return
}
guard let userHandle = String(data: credential.userID, encoding: .utf8) else {
return
}
let passkey = AuthorizationPasskeyData(
id: encodeBase64URL(credential.credentialID),
clientData: clientData,
authenticatorData: credential.rawAuthenticatorData,
signature: credential.signature,
userHandle: userHandle
)
self.loginWithPasskey?(passkey, self.controllerNode.syncContacts)
/*if let clientData = String(data: credential.rawClientDataJSON, encoding: .utf8), let attestationObject = credential.rawAttestationObject {
let passkey = await component.context.engine.auth.requestCreatePasskey(id: encodeBase64URL(credential.credentialID), clientData: clientData, attestationObject: attestationObject).get()
if let passkey {
if self.passkeysData == nil {
self.passkeysData = []
self.passkeysData?.insert(passkey, at: 0)
}
self.state?.updated(transition: .immediate)
}
}*/
let _ = account
let _ = credential
}
}
}
}
public func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: any Error) {
if (error as NSError).domain == "com.apple.AuthenticationServices.AuthorizationError" && (error as NSError).code == 1001 {
self.controllerNode.updateDisplayPasskeyLoginOption()
if let validLayout = self.validLayout {
self.containerLayoutUpdated(validLayout, transition: .immediate)
}
}
}
public func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
guard let windowScene = self.view.window?.windowScene else {
preconditionFailure()
}
return ASPresentationAnchor(windowScene: windowScene)
}
public func updateCountryCode() {

View file

@ -15,6 +15,7 @@ import TelegramAnimatedStickerNode
import SolidRoundedButtonNode
import AuthorizationUtils
import ManagedAnimationNode
import Markdown
private final class PhoneAndCountryNode: ASDisplayNode {
let strings: PresentationStrings
@ -312,7 +313,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
private let managedAnimationNode: ManagedPhoneAnimationNode
private let titleNode: ASTextNode
private let titleActivateAreaNode: AccessibilityAreaNode
private let noticeNode: ASTextNode
private let noticeNode: ImmediateTextNode
private let noticeActivateAreaNode: AccessibilityAreaNode
private let phoneAndCountryNode: PhoneAndCountryNode
private let contactSyncNode: ContactSyncNode
@ -323,6 +324,8 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
private let tokenEventsDisposable = MetaDisposable()
var accountUpdated: ((UnauthorizedAccount) -> Void)?
var retryPasskey: (() -> Void)?
private let debugAction: () -> Void
var currentNumber: String {
@ -405,7 +408,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
self.titleActivateAreaNode = AccessibilityAreaNode()
self.titleActivateAreaNode.accessibilityTraits = .staticText
self.noticeNode = ASTextNode()
self.noticeNode = ImmediateTextNode()
self.noticeNode.maximumNumberOfLines = 0
self.noticeNode.isUserInteractionEnabled = true
self.noticeNode.displaysAsynchronously = false
@ -443,6 +446,23 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
self.addSubnode(self.managedAnimationNode)
self.contactSyncNode.isHidden = true
self.noticeNode.highlightAttributeAction = { attributes in
if let _ = attributes[NSAttributedString.Key(rawValue: "URL")] {
return NSAttributedString.Key(rawValue: "URL")
} else {
return nil
}
}
self.noticeNode.tapAttributeAction = { [weak self] attributes, _ in
guard let self else {
return
}
if let _ = attributes[NSAttributedString.Key(rawValue: "URL")] as? String {
self.retryPasskey?()
}
}
self.noticeNode.linkHighlightColor = theme.list.itemAccentColor.withAlphaComponent(0.2)
self.phoneAndCountryNode.selectCountryCode = { [weak self] in
self?.selectCountryCode?()
}
@ -484,7 +504,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
super.didLoad()
self.titleNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.debugTap(_:))))
#if DEBUG
#if DEBUG && false
self.noticeNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.debugQrTap(_:))))
#endif
}
@ -555,6 +575,27 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
let _ = self.phoneAndCountryNode.processNumberChange(number: self.phoneAndCountryNode.phoneInputNode.number)
}
func updateDisplayPasskeyLoginOption() {
if self.account == nil {
return
}
let attributedText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(self.strings.Login_PhoneWithPasskeySubtitle, attributes: MarkdownAttributes(
body: MarkdownAttributeSet(font: Font.regular(17.0), textColor: self.theme.list.itemPrimaryTextColor),
bold: MarkdownAttributeSet(font: Font.semibold(17.0), textColor: self.theme.list.itemPrimaryTextColor),
link: MarkdownAttributeSet(font: Font.regular(17.0), textColor: self.theme.list.itemAccentColor),
linkAttribute: { url in
return ("URL", url)
}
)))
let chevronImage = generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: self.theme.list.itemAccentColor)
if let range = attributedText.string.range(of: ">"), let chevronImage {
attributedText.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: attributedText.string))
}
self.noticeNode.attributedText = attributedText
}
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
var insets = layout.insets(options: [])
insets.top = layout.statusBarHeight ?? 20.0
@ -565,7 +606,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
let titleInset: CGFloat = layout.size.width > 320.0 ? 18.0 : 0.0
let additionalBottomInset: CGFloat = layout.size.width > 320.0 ? 80.0 : 10.0
self.titleNode.attributedText = NSAttributedString(string: self.account == nil ? strings.Login_NewNumber : strings.Login_PhoneTitle, font: Font.bold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
self.titleNode.attributedText = NSAttributedString(string: self.account == nil ? self.strings.Login_NewNumber : self.strings.Login_PhoneTitle, font: Font.bold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
self.titleActivateAreaNode.accessibilityLabel = self.titleNode.attributedText?.string ?? ""
let inset: CGFloat = 24.0
@ -576,7 +617,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
let noticeInset: CGFloat = self.account == nil ? 32.0 : 0.0
let noticeSize = self.noticeNode.measure(CGSize(width: min(274.0 + noticeInset, maximumWidth - 28.0), height: CGFloat.greatestFiniteMagnitude))
let noticeSize = self.noticeNode.updateLayout(CGSize(width: min(274.0 + noticeInset, maximumWidth - 28.0), height: CGFloat.greatestFiniteMagnitude))
let proceedHeight = self.proceedNode.updateLayout(width: maximumWidth - inset * 2.0, transition: transition)
let proceedSize = CGSize(width: maximumWidth - inset * 2.0, height: proceedHeight)

View file

@ -13,14 +13,14 @@ enum BotCheckoutActionButtonState: Equatable {
private let titleFont = Font.semibold(17.0)
final class BotCheckoutActionButton: HighlightableButtonNode {
final class BotCheckoutActionButton: HighlightTrackingButtonNode {
static var height: CGFloat = 52.0
private var activeFillColor: UIColor
private var inactiveFillColor: UIColor
private var foregroundColor: UIColor
private let activeBackgroundNode: ASImageNode
private let activeBackgroundNode: ASDisplayNode
private var applePayButton: UIButton?
private let labelNode: TextNode
@ -29,23 +29,17 @@ final class BotCheckoutActionButton: HighlightableButtonNode {
private var placeholderNode: ShimmerEffectNode?
private var activeImage: UIImage?
private var inactiveImage: UIImage?
init(activeFillColor: UIColor, inactiveFillColor: UIColor, foregroundColor: UIColor) {
self.activeFillColor = activeFillColor
self.inactiveFillColor = inactiveFillColor
self.foregroundColor = foregroundColor
let diameter: CGFloat = 20.0
self.activeImage = generateStretchableFilledCircleImage(diameter: diameter, color: activeFillColor)
self.inactiveImage = generateStretchableFilledCircleImage(diameter: diameter, color: inactiveFillColor)
let diameter: CGFloat = 52.0
self.activeBackgroundNode = ASImageNode()
self.activeBackgroundNode.displaysAsynchronously = false
self.activeBackgroundNode.displayWithoutProcessing = true
self.activeBackgroundNode = ASDisplayNode()
self.activeBackgroundNode.isLayerBacked = true
self.activeBackgroundNode.image = self.activeImage
self.activeBackgroundNode.backgroundColor = activeFillColor
self.activeBackgroundNode.cornerRadius = diameter / 2.0
self.labelNode = TextNode()
self.labelNode.displaysAsynchronously = false
@ -55,6 +49,21 @@ final class BotCheckoutActionButton: HighlightableButtonNode {
self.addSubnode(self.activeBackgroundNode)
self.addSubnode(self.labelNode)
self.highligthedChanged = { [weak self] highlighted in
guard let self else {
return
}
let transition = ContainedViewLayoutTransition.animated(duration: highlighted ? 0.25 : 0.35, curve: .spring)
if highlighted {
let highlightedColor = self.activeFillColor.withMultiplied(hue: 1.0, saturation: 0.77, brightness: 1.01)
transition.updateBackgroundColor(node: self.activeBackgroundNode, color: highlightedColor)
transition.updateTransformScale(node: self, scale: 1.05)
} else {
transition.updateBackgroundColor(node: self.activeBackgroundNode, color: self.activeFillColor)
transition.updateTransformScale(node: self, scale: 1.0)
}
}
}
func setState(_ state: BotCheckoutActionButtonState) {
@ -93,14 +102,8 @@ final class BotCheckoutActionButton: HighlightableButtonNode {
placeholderNode.removeFromSupernode()
}
let image = isEnabled ? self.activeImage : self.inactiveImage
if let image = image, let currentImage = self.activeBackgroundNode.image, currentImage !== image {
self.activeBackgroundNode.image = image
self.activeBackgroundNode.layer.animate(from: currentImage.cgImage! as AnyObject, to: image.cgImage! as AnyObject, keyPath: "contents", timingFunction: CAMediaTimingFunctionName.linear.rawValue, duration: 0.2)
} else {
self.activeBackgroundNode.image = image
}
self.activeBackgroundNode.backgroundColor = isEnabled ? self.activeFillColor : self.inactiveFillColor
let makeLayout = TextNode.asyncLayout(self.labelNode)
let (labelLayout, labelApply) = makeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: title, font: titleFont, textColor: self.foregroundColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: size, alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let _ = labelApply()

View file

@ -259,31 +259,31 @@ enum BotCheckoutEntry: ItemListNodeEntry {
}
})
case let .paymentMethod(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
arguments.openPaymentMethod()
})
case let .shippingInfo(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
arguments.openInfo(.address(.street1))
})
case let .shippingMethod(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
arguments.openShippingMethod()
})
case let .nameInfo(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
arguments.openInfo(.name)
})
case let .emailInfo(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
arguments.openInfo(.email)
})
case let .phoneInfo(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
arguments.openInfo(.phone)
})
case let .actionPlaceholder(_, shimmeringIndex):
return ItemListDisclosureItem(presentationData: presentationData, title: " ", label: " ", sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, title: " ", label: " ", sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
}, shimmeringIndex: shimmeringIndex)
}
}
@ -1245,7 +1245,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition, additionalInsets: UIEdgeInsets) {
var updatedInsets = layout.intrinsicInsets
let bottomPanelHorizontalInset: CGFloat = 16.0
let bottomPanelHorizontalInset: CGFloat = 30.0
var botName: String?
if let botPeer = self.botPeerValue {

View file

@ -270,7 +270,7 @@ class BotCheckoutHeaderItemNode: ListViewItemNode {
strongSelf.bottomStripeNode.isHidden = hasCorners
}
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: true) : nil
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: contentSize.height - separatorHeight), size: CGSize(width: params.width, height: separatorHeight))

View file

@ -141,13 +141,13 @@ class BotCheckoutPriceItemNode: ListViewItemNode {
let naturalContentHeight: CGFloat
var verticalOffset: CGFloat = 0.0
if item.isFinal {
naturalContentHeight = 44.0
naturalContentHeight = 52.0
} else {
switch neighbors.bottom {
case .otherSection, .none:
naturalContentHeight = 44.0
naturalContentHeight = 52.0
default:
naturalContentHeight = 34.0
naturalContentHeight = 42.0
}
}
if let _ = previousItem as? BotCheckoutHeaderItem {
@ -209,7 +209,7 @@ class BotCheckoutPriceItemNode: ListViewItemNode {
strongSelf.separatorNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
strongSelf.separatorNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: params.width - leftInset, height: UIScreenPixel))
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: true) : nil
strongSelf.bottomSeparatorNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
strongSelf.bottomSeparatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: contentSize.height), size: CGSize(width: params.width, height: UIScreenPixel))

View file

@ -70,15 +70,17 @@ final class BotPaymentActionItemNode: BotPaymentItemNode {
self.titleNode.attributedText = NSAttributedString(string: self.title, font: titleFont, textColor: theme.list.itemAccentColor)
}
self.buttonNode.frame = CGRect(origin: CGPoint(x: sideInset, y: 0.0), size: CGSize(width: width - sideInset * 2.0, height: 44.0))
transition.updateFrame(node: self.highlightedBackgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: 44.0 + UIScreenPixel)))
let height: CGFloat = 52.0
self.buttonNode.frame = CGRect(origin: CGPoint(x: sideInset, y: 0.0), size: CGSize(width: width - sideInset * 2.0, height: height))
transition.updateFrame(node: self.highlightedBackgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: height + UIScreenPixel)))
let leftInset: CGFloat = 16.0
let titleSize = self.titleNode.measure(CGSize(width: width - leftInset - 32.0 - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: 11.0), size: titleSize))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: 16.0), size: titleSize))
return 44.0
return height
}
@objc func buttonPressed() {

View file

@ -45,9 +45,9 @@ final class BotPaymentCardInputItemNode: BotPaymentItemNode, STPPaymentCardTextF
self.cardField.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
}
self.cardField.frame = CGRect(origin: CGPoint(x: 5.0 + sideInset, y: 0.0), size: CGSize(width: width - 10.0 - sideInset * 2.0, height: 44.0))
self.cardField.frame = CGRect(origin: CGPoint(x: 5.0 + sideInset, y: 4.0), size: CGSize(width: width - 10.0 - sideInset * 2.0, height: 44.0))
return 44.0
return 52.0
}
func paymentCardTextFieldDidChange(_ textField: STPPaymentCardTextField) {

View file

@ -102,13 +102,15 @@ class BotPaymentDisclosureItemNode: BotPaymentItemNode {
}
}
self.buttonNode.frame = CGRect(origin: CGPoint(x: sideInset, y: 0.0), size: CGSize(width: width - sideInset * 2.0, height: 44.0))
transition.updateFrame(node: self.highlightedBackgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: 44.0 + UIScreenPixel)))
let height: CGFloat = 52.0
self.buttonNode.frame = CGRect(origin: CGPoint(x: sideInset, y: 0.0), size: CGSize(width: width - sideInset * 2.0, height: height))
transition.updateFrame(node: self.highlightedBackgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: height + UIScreenPixel)))
let leftInset: CGFloat = 16.0
let titleSize = self.titleNode.measure(CGSize(width: width - leftInset - 70.0 - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: 11.0), size: titleSize))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: 16.0), size: titleSize))
var textInset = leftInset
if !titleSize.width.isZero {
@ -117,9 +119,9 @@ class BotPaymentDisclosureItemNode: BotPaymentItemNode {
textInset = max(measuredInset, textInset)
let textSize = self.textNode.measure(CGSize(width: width - measuredInset - 8.0 - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: textInset + sideInset, y: 11.0), size: textSize))
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: textInset + sideInset, y: 16.0), size: textSize))
return 44.0
return height
}
@objc func buttonPressed() {

View file

@ -108,11 +108,12 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
self.textField.textField.tintColor = theme.list.itemAccentColor
}
let height: CGFloat = 52.0
let leftInset: CGFloat = 16.0
let titleSize = self.titleNode.measure(CGSize(width: width - leftInset - 70.0 - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: 11.0), size: titleSize))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: 16.0), size: titleSize))
var textInset = leftInset
if !titleSize.width.isZero {
@ -121,9 +122,9 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate {
textInset = max(measuredInset, textInset)
transition.updateFrame(node: self.textField, frame: CGRect(origin: CGPoint(x: textInset + sideInset, y: 0.0), size: CGSize(width: max(1.0, width - textInset - 8.0), height: 40.0)))
transition.updateFrame(node: self.textField, frame: CGRect(origin: CGPoint(x: textInset + sideInset, y: 5.0), size: CGSize(width: max(1.0, width - textInset - 8.0), height: 40.0)))
return 44.0
return height
}
func activateInput() {

View file

@ -74,7 +74,7 @@ class BotPaymentItemNode: ASDisplayNode {
self.bottomSeparatorNode.isHidden = hasCorners
}
self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(theme, top: hasTopCorners, bottom: hasBottomCorners, glass: true) : nil
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: height)))
transition.updateFrame(node: self.maskNode, frame: self.backgroundNode.frame.insetBy(dx: sideInset, dy: 0.0))

View file

@ -74,14 +74,14 @@ final class BotPaymentSwitchItemNode: BotPaymentItemNode {
let titleSize = self.titleNode.measure(CGSize(width: width - leftInset - 70.0 - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: 11.0), size: titleSize))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + sideInset, y: 16.0), size: titleSize))
let switchSize = self.switchNode.measure(CGSize(width: 100.0, height: 100.0))
let switchFrame = CGRect(origin: CGPoint(x: width - switchSize.width - 15.0 - sideInset, y: 6.0), size: switchSize)
let switchFrame = CGRect(origin: CGPoint(x: width - switchSize.width - 15.0 - sideInset, y: 12.0), size: switchSize)
transition.updateFrame(node: self.switchNode, frame: switchFrame)
transition.updateFrame(node: self.buttonNode, frame: switchFrame)
return 44.0
return 52.0
}
@objc private func buttonPressed() {

View file

@ -335,7 +335,7 @@ final class BotReceiptControllerNode: ItemListControllerNode {
override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition, additionalInsets: UIEdgeInsets) {
var updatedInsets = layout.intrinsicInsets
let bottomPanelHorizontalInset: CGFloat = 16.0
let bottomPanelHorizontalInset: CGFloat = 30.0
let bottomPanelVerticalInset: CGFloat = 16.0
let bottomPanelHeight = max(updatedInsets.bottom, layout.inputHeight ?? 0.0) + bottomPanelVerticalInset * 2.0 + BotCheckoutActionButton.height

View file

@ -1425,9 +1425,13 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
var nodeList = document.getElementsByTagName('link');
for (var i = 0; i < nodeList.length; i++)
{
if((nodeList[i].getAttribute('rel') == 'icon')||(nodeList[i].getAttribute('rel') == 'shortcut icon')||(nodeList[i].getAttribute('rel').startsWith('apple-touch-icon')))
{
const node = nodeList[i];
var rel = nodeList[i].getAttribute('rel') || '';
if (
rel === 'icon' ||
rel === 'shortcut icon' ||
rel.indexOf('apple-touch-icon') === 0
) {
var node = nodeList[i];
favicons.push({
url: node.getAttribute('href'),
sizes: node.getAttribute('sizes')

View file

@ -137,6 +137,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
private let dismissAutoarchiveDisposable = MetaDisposable()
private var didSuggestAutoarchive = false
private var didSuggestLoginEmailSetup = false
private var didSuggestLoginPasskeySetup = false
private var presentationData: PresentationData
private let presentationDataValue = Promise<PresentationData>()
@ -2586,6 +2587,30 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return
}
if values.contains(.setupPasskey) {
if strongSelf.didSuggestLoginPasskeySetup {
return
}
strongSelf.didSuggestLoginPasskeySetup = true
let _ = (context.engine.notices.getServerProvidedSuggestions(reload: true)
|> deliverOnMainQueue).start(next: { [weak strongSelf] currentValues in
guard let strongSelf, currentValues.contains(.setupPasskey) else {
return
}
if let navigationController = strongSelf.navigationController as? NavigationController {
let controller = strongSelf.context.sharedContext.makePasskeySetupController(context: strongSelf.context, displaySkip: true, navigationController: navigationController, completion: {
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPasskey.id).startStandalone()
}, dismiss: {
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: ServerProvidedSuggestion.setupPasskey.id).startStandalone()
})
navigationController.pushViewController(controller)
}
})
return
}
if strongSelf.didSuggestAutoarchive {
return
}

View file

@ -58,6 +58,19 @@ private extension ComponentTransition.Animation.Curve {
preconditionFailure()
}
}
var viewAnimationOptions: UIView.AnimationOptions {
switch self {
case .linear:
return [.curveLinear]
case .easeInOut:
return [.curveEaseInOut]
case .spring:
return UIView.AnimationOptions(rawValue: 7 << 16)
case .custom:
return []
}
}
}
public extension ComponentTransition.Animation {
@ -70,6 +83,24 @@ public extension ComponentTransition.Animation {
}
}
public extension ComponentTransition {
func animateView(allowUserInteraction: Bool = false, delay: Double = 0.0, _ f: @escaping () -> Void, completion: ((Bool) -> Void)? = nil) {
switch self.animation {
case .none:
f()
completion?(true)
case let .curve(duration, curve):
var options = curve.viewAnimationOptions
if allowUserInteraction {
options.insert(.allowUserInteraction)
}
UIView.animate(withDuration: duration, delay: delay, options: options, animations: {
f()
}, completion: completion)
}
}
}
public struct ComponentTransition {
public enum Animation {
public enum Curve {

View file

@ -157,40 +157,6 @@ public final class SheetComponent<ChildEnvironmentType: Sendable & Equatable>: C
}
}
final class BackgroundView: UIView {
let topCornersView = UIView()
let bottomCornersView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
self.topCornersView.clipsToBounds = true
self.topCornersView.layer.cornerCurve = .continuous
self.topCornersView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
self.bottomCornersView.clipsToBounds = true
self.bottomCornersView.layer.cornerCurve = .continuous
self.bottomCornersView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
self.addSubview(self.topCornersView)
self.topCornersView.addSubview(self.bottomCornersView)
}
required init?(coder: NSCoder) {
preconditionFailure()
}
func update(size: CGSize, color: UIColor, topCornerRadius: CGFloat, bottomCornerRadius: CGFloat, transition: ComponentTransition) {
transition.setCornerRadius(layer: self.topCornersView.layer, cornerRadius: topCornerRadius)
transition.setCornerRadius(layer: self.bottomCornersView.layer, cornerRadius: bottomCornerRadius)
transition.setFrame(view: self.topCornersView, frame: CGRect(origin: .zero, size: size))
transition.setFrame(view: self.bottomCornersView, frame: CGRect(origin: .zero, size: size))
transition.setBackgroundColor(view: self.bottomCornersView, color: color)
}
}
public final class View: UIView, UIScrollViewDelegate, ComponentTaggedView {
public final class Tag {
public init() {
@ -208,9 +174,9 @@ public final class SheetComponent<ChildEnvironmentType: Sendable & Equatable>: C
private let dimView: UIView
private let scrollView: ScrollView
private let backgroundView: BackgroundView
private let backgroundView: SheetBackgroundView
private var effectView: UIVisualEffectView?
private let clipView: BackgroundView
private let clipView: SheetBackgroundView
private let contentView: ComponentView<ChildEnvironmentType>
private var headerView: ComponentView<Empty>?
@ -233,8 +199,8 @@ public final class SheetComponent<ChildEnvironmentType: Sendable & Equatable>: C
self.scrollView.showsHorizontalScrollIndicator = false
self.scrollView.alwaysBounceVertical = true
self.backgroundView = BackgroundView()
self.clipView = BackgroundView()
self.backgroundView = SheetBackgroundView()
self.clipView = SheetBackgroundView()
self.contentView = ComponentView<ChildEnvironmentType>()
@ -589,3 +555,37 @@ public final class SheetComponent<ChildEnvironmentType: Sendable & Equatable>: C
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}
public final class SheetBackgroundView: UIView {
let topCornersView = UIView()
let bottomCornersView = UIView()
public override init(frame: CGRect) {
super.init(frame: frame)
self.topCornersView.clipsToBounds = true
self.topCornersView.layer.cornerCurve = .continuous
self.topCornersView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
self.bottomCornersView.clipsToBounds = true
self.bottomCornersView.layer.cornerCurve = .continuous
self.bottomCornersView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
self.addSubview(self.topCornersView)
self.topCornersView.addSubview(self.bottomCornersView)
}
required init?(coder: NSCoder) {
preconditionFailure()
}
public func update(size: CGSize, color: UIColor, topCornerRadius: CGFloat, bottomCornerRadius: CGFloat, transition: ComponentTransition) {
transition.setCornerRadius(layer: self.topCornersView.layer, cornerRadius: topCornerRadius)
transition.setCornerRadius(layer: self.bottomCornersView.layer, cornerRadius: bottomCornerRadius)
transition.setFrame(view: self.topCornersView, frame: CGRect(origin: .zero, size: size))
transition.setFrame(view: self.bottomCornersView, frame: CGRect(origin: .zero, size: size))
transition.setBackgroundColor(view: self.bottomCornersView, color: color)
}
}

View file

@ -371,7 +371,7 @@ class GeneralChartComponentController: ChartThemeContainer {
values.append(ChartDetailsViewModel.Value(
prefix: nil,
title: self.strings.revenueInUsd,
value: "$\(convertedValueString)",
value: "~$\(convertedValueString)",
color: color,
visible: firstValue.visible
))

View file

@ -161,7 +161,7 @@ class BarsComponentController: GeneralChartComponentController {
} else {
text = String(format: "%0.3f", convertedValue)
}
updatedLabels.append(LinesChartLabel(value: label.value, text: "$\(text)"))
updatedLabels.append(LinesChartLabel(value: label.value, text: "~$\(text)"))
}
labels = updatedLabels
}

View file

@ -494,7 +494,7 @@ private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state:
var label: String = ""
if let subscriptionFee = state.subscriptionFee, subscriptionFee > StarsAmount.zero {
let usdRate = Double(configuration.usdWithdrawRate) / 1000.0 / 100.0
label = presentationData.strings.InviteLink_Create_FeePerMonth("\(formatTonUsdValue(subscriptionFee.value, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))").string
label = presentationData.strings.InviteLink_Create_FeePerMonth("~\(formatTonUsdValue(subscriptionFee.value, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))").string
}
entries.append(.subscriptionFee(presentationData.theme, presentationData.strings.InviteLink_Create_FeePlaceholder, isEditingEnabled, state.subscriptionFee, label, StarsAmount(value: configuration.maxFee, nanos: 0)))
}

View file

@ -44,7 +44,7 @@ public final class ListMessageItemInteraction {
})
}
public final class ListMessageItem: ListViewItem {
public final class ListMessageItem: ListViewItem, ItemListItem {
let presentationData: ChatPresentationData
let systemStyle: ItemListSystemStyle
let context: AccountContext
@ -57,6 +57,7 @@ public final class ListMessageItem: ListViewItem {
let isGlobalSearchResult: Bool
let isDownloadList: Bool
let isSavedMusic: Bool
let isStoryMusic: Bool
let displayFileInfo: Bool
let displayBackground: Bool
let canReorder: Bool
@ -64,9 +65,11 @@ public final class ListMessageItem: ListViewItem {
let header: ListViewItemHeader?
public var sectionId: ItemListSectionId
public let selectable: Bool = true
public init(presentationData: ChatPresentationData, systemStyle: ItemListSystemStyle = .legacy, context: AccountContext, chatLocation: ChatLocation, interaction: ListMessageItemInteraction, message: Message?, translateToLanguage: String? = nil, selection: ChatHistoryMessageSelection, displayHeader: Bool, customHeader: ListViewItemHeader? = nil, hintIsLink: Bool = false, isGlobalSearchResult: Bool = false, isDownloadList: Bool = false, isSavedMusic: Bool = false, displayFileInfo: Bool = true, displayBackground: Bool = false, canReorder: Bool = false, style: ItemListStyle = .plain) {
public init(presentationData: ChatPresentationData, systemStyle: ItemListSystemStyle = .legacy, context: AccountContext, chatLocation: ChatLocation, interaction: ListMessageItemInteraction, message: Message?, translateToLanguage: String? = nil, selection: ChatHistoryMessageSelection, displayHeader: Bool, customHeader: ListViewItemHeader? = nil, hintIsLink: Bool = false, isGlobalSearchResult: Bool = false, isDownloadList: Bool = false, isSavedMusic: Bool = false, isStoryMusic: Bool = false, displayFileInfo: Bool = true, displayBackground: Bool = false, canReorder: Bool = false, style: ItemListStyle = .plain, sectionId: ItemListSectionId = 0) {
self.presentationData = presentationData
self.systemStyle = systemStyle
self.context = context
@ -86,10 +89,12 @@ public final class ListMessageItem: ListViewItem {
self.isGlobalSearchResult = isGlobalSearchResult
self.isDownloadList = isDownloadList
self.isSavedMusic = isSavedMusic
self.isStoryMusic = isStoryMusic
self.displayFileInfo = displayFileInfo
self.displayBackground = displayBackground
self.canReorder = canReorder
self.style = style
self.sectionId = sectionId
}
public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
@ -120,7 +125,23 @@ public final class ListMessageItem: ListViewItem {
node.setupItem(self)
let nodeLayout = node.asyncLayout()
let (top, bottom, dateAtBottom) = (previousItem != nil && !(previousItem is ItemListItem), nextItem != nil, self.getDateAtBottom(top: previousItem, bottom: nextItem))
var topMerged = false
if let previousItem {
if let previousItem = previousItem as? ItemListItem, previousItem.sectionId == self.sectionId && !previousItem.isAlwaysPlain {
topMerged = true
}
}
var bottomMerged = false
if let nextItem {
if let nextItem = nextItem as? ItemListItem, nextItem.sectionId == self.sectionId && !nextItem.isAlwaysPlain {
bottomMerged = true
}
}
let (top, bottom, dateAtBottom) = (topMerged, bottomMerged, self.getDateAtBottom(top: previousItem, bottom: nextItem))
let (layout, apply) = nodeLayout(self, params, top, bottom, dateAtBottom)
node.updateSelectionState(animated: false)
@ -152,9 +173,22 @@ public final class ListMessageItem: ListViewItem {
let nodeLayout = nodeValue.asyncLayout()
var topMerged = false
if let previousItem {
if let previousItem = previousItem as? ItemListItem, previousItem.sectionId == self.sectionId && !previousItem.isAlwaysPlain {
topMerged = true
}
}
var bottomMerged = false
if let nextItem {
if let nextItem = nextItem as? ItemListItem, nextItem.sectionId == self.sectionId && !nextItem.isAlwaysPlain {
bottomMerged = true
}
}
async {
let (top, bottom, dateAtBottom) = (previousItem != nil && !(previousItem is ItemListItem), nextItem != nil, self.getDateAtBottom(top: previousItem, bottom: nextItem))
let (top, bottom, dateAtBottom) = (topMerged, bottomMerged, self.getDateAtBottom(top: previousItem, bottom: nextItem))
let (layout, apply) = nodeLayout(self, params, top, bottom, dateAtBottom)
Queue.mainQueue().async {
completion(layout, { _ in

View file

@ -446,9 +446,9 @@ public func storyLocationPickerController(
) -> ViewController {
let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme)
let updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) = (presentationData, .single(presentationData))
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false)
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, style: .glass, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false)
controller.requestController = { _, present in
let locationPickerController = LocationPickerController(context: context, updatedPresentationData: updatedPresentationData, mode: .share(peer: nil, selfPeer: nil, hasLiveLocation: false), source: .story, initialLocation: location, completion: { location, queryId, resultId, address, countryCode in
let locationPickerController = LocationPickerController(context: context, style: .glass, updatedPresentationData: updatedPresentationData, mode: .share(peer: nil, selfPeer: nil, hasLiveLocation: false), source: .story, initialLocation: location, completion: { location, queryId, resultId, address, countryCode in
completion(location, queryId, resultId, address, countryCode)
})
present(locationPickerController, locationPickerController.mediaPickerContext)

View file

@ -19,7 +19,7 @@ public func mediaPasteboardScreen(
getSourceRect: (() -> CGRect?)? = nil,
makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView? = { return nil }
) -> ViewController {
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: peer.id), buttons: [.standalone], initialButton: .standalone, makeEntityInputView: makeEntityInputView)
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, style: .glass, chatLocation: .peer(id: peer.id), buttons: [.standalone], initialButton: .standalone, makeEntityInputView: makeEntityInputView)
controller.requestController = { _, present in
presentMediaPicker(.media(subjects), false, nil, nil, { mediaPicker, mediaPickerContext in
present(mediaPicker, mediaPickerContext)

View file

@ -26,6 +26,9 @@ swift_library(
"//submodules/Components/ActivityIndicatorComponent",
"//submodules/TelegramUI/Components/ButtonComponent",
"//submodules/TelegramUI/Components/GlassBarButtonComponent",
"//submodules/TelegramUI/Components/ListSectionComponent",
"//submodules/TelegramUI/Components/ListActionItemComponent",
"//submodules/TelegramUI/Components/PlainButtonComponent",
],
visibility = [
"//visibility:public",

View file

@ -14,6 +14,9 @@ import BundleIconComponent
import AnimatedStickerComponent
import ActivityIndicatorComponent
import GlassBarButtonComponent
import ListSectionComponent
import ListActionItemComponent
import PlainButtonComponent
private final class CreateExternalMediaStreamScreenComponent: CombinedComponent {
typealias EnvironmentType = ViewControllerComponentContainer.Environment
@ -49,41 +52,51 @@ private final class CreateExternalMediaStreamScreenComponent: CombinedComponent
final class State: ComponentState {
let context: AccountContext
let peerId: EnginePeer.Id
let mode: CreateExternalMediaStreamScreen.Mode
private(set) var credentials: GroupCallStreamCredentials?
var isDelayingLoadingIndication: Bool = true
private var credentialsDisposable: Disposable?
private let credentialsDisposable = MetaDisposable()
private let activeActionDisposable = MetaDisposable()
init(context: AccountContext, peerId: EnginePeer.Id, credentialsPromise: Promise<GroupCallStreamCredentials>?) {
init(context: AccountContext, peerId: EnginePeer.Id, mode: CreateExternalMediaStreamScreen.Mode, credentialsPromise: Promise<GroupCallStreamCredentials>?) {
self.context = context
self.peerId = peerId
self.mode = mode
super.init()
self.getCredentials(credentialsPromise: credentialsPromise)
}
deinit {
self.credentialsDisposable.dispose()
self.activeActionDisposable.dispose()
}
func getCredentials(credentialsPromise: Promise<GroupCallStreamCredentials>? = nil, revoke: Bool = false) {
let credentialsSignal: Signal<GroupCallStreamCredentials, NoError>
if let credentialsPromise = credentialsPromise {
credentialsSignal = credentialsPromise.get()
} else {
credentialsSignal = context.engine.calls.getGroupCallStreamCredentials(peerId: peerId, isLiveStream: false, revokePreviousCredentials: false)
var isLiveStream = false
if case let .create(isLiveStreamValue) = self.mode {
isLiveStream = isLiveStreamValue
}
credentialsSignal = self.context.engine.calls.getGroupCallStreamCredentials(peerId: self.peerId, isLiveStream: isLiveStream, revokePreviousCredentials: revoke)
|> `catch` { _ -> Signal<GroupCallStreamCredentials, NoError> in
return .never()
}
}
self.credentialsDisposable = (credentialsSignal |> deliverOnMainQueue).start(next: { [weak self] result in
self.credentialsDisposable.set((credentialsSignal |> deliverOnMainQueue).start(next: { [weak self] result in
guard let strongSelf = self else {
return
}
strongSelf.credentials = result
strongSelf.updated(transition: .immediate)
})
}
deinit {
self.credentialsDisposable?.dispose()
self.activeActionDisposable.dispose()
}))
}
func copyCredentials(_ key: KeyPath<GroupCallStreamCredentials, String>) {
@ -160,7 +173,7 @@ private final class CreateExternalMediaStreamScreenComponent: CombinedComponent
}
func makeState() -> State {
return State(context: self.context, peerId: self.peerId, credentialsPromise: self.credentialsPromise)
return State(context: self.context, peerId: self.peerId, mode: self.mode, credentialsPromise: self.credentialsPromise)
}
static var body: Body {
@ -176,26 +189,25 @@ private final class CreateExternalMediaStreamScreenComponent: CombinedComponent
let activityIndicator = Child(ActivityIndicatorComponent.self)
let credentialsBackground = Child(RoundedRectangle.self)
let credentialsSection = Child(ListSectionComponent.self)
let credentialsStripe = Child(Rectangle.self)
let credentialsURLTitle = Child(MultilineTextComponent.self)
let credentialsURLText = Child(MultilineTextComponent.self)
let credentialsKeyTitle = Child(MultilineTextComponent.self)
let credentialsKeyText = Child(MultilineTextComponent.self)
let credentialsCopyURLButton = Child(Button.self)
let credentialsCopyKeyButton = Child(Button.self)
// let credentialsBackground = Child(RoundedRectangle.self)
// let credentialsStripe = Child(Rectangle.self)
// let credentialsURLTitle = Child(MultilineTextComponent.self)
// let credentialsURLText = Child(MultilineTextComponent.self)
//
// let credentialsKeyTitle = Child(MultilineTextComponent.self)
// let credentialsKeyText = Child(MultilineTextComponent.self)
//
// let credentialsCopyURLButton = Child(Button.self)
// let credentialsCopyKeyButton = Child(Button.self)
return { context in
let topInset: CGFloat = 16.0
let sideInset: CGFloat = 16.0
let buttonSideInset: CGFloat = 36.0
let credentialsSideInset: CGFloat = 16.0
let credentialsTopInset: CGFloat = 12.0
let credentialsTitleSpacing: CGFloat = 5.0
let component = context.component
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
let state = context.state
@ -355,124 +367,145 @@ private final class CreateExternalMediaStreamScreenComponent: CombinedComponent
)
let textFrame = CGRect(origin: CGPoint(x: floor((context.availableSize.width - text.size.width) / 2.0), y: animationFrame.maxY + 18.0), size: text.size)
context.add(text
.position(CGPoint(x: textFrame.midX, y: textFrame.midY))
)
let credentialsFrame = CGRect(origin: CGPoint(x: sideInset, y: textFrame.maxY + 30.0), size: credentialsAreaSize)
if let credentials = context.state.credentials {
let credentialsURLTitle = credentialsURLTitle.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(string: environment.strings.CreateExternalStream_ServerUrl, font: Font.regular(15.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .left)),
horizontalAlignment: .left,
maximumNumberOfLines: 1
),
availableSize: CGSize(width: credentialsAreaSize.width - credentialsSideInset * 2.0, height: credentialsAreaSize.height),
transition: context.transition
var credentialsSectionItems: [AnyComponentWithIdentity<Empty>] = []
credentialsSectionItems.append(
AnyComponentWithIdentity(id: "url", component: AnyComponent(
ListActionItemComponent(
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: environment.strings.CreateExternalStream_ServerUrl,
font: Font.regular(15.0),
textColor: theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 1
))),
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: credentials.url, font: Font.regular(17.0), textColor: theme.list.itemAccentColor, paragraphAlignment: .left)),
horizontalAlignment: .left,
truncationType: .middle,
maximumNumberOfLines: 1
)))
], alignment: .left, spacing: 5.0)),
contentInsets: UIEdgeInsets(top: 14.0, left: 0.0, bottom: 14.0, right: 0.0),
accessory: .custom(ListActionItemComponent.CustomAccessory(
component: AnyComponentWithIdentity(
id: "copy",
component: AnyComponent(
PlainButtonComponent(
content: AnyComponent(BundleIconComponent(name: "Chat/Context Menu/Copy", tintColor: theme.list.itemAccentColor)),
action: { [weak state] in
guard let state = state else {
return
}
state.copyCredentials(\.url)
},
animateScale: false
)
)
),
insets: UIEdgeInsets(top: 0.0, left: 8.0, bottom: 0.0, right: 14.0),
isInteractive: true
)),
action: nil
)
))
)
let credentialsKeyTitle = credentialsKeyTitle.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(string: environment.strings.CreateExternalStream_StreamKey, font: Font.regular(15.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .left)),
horizontalAlignment: .left,
maximumNumberOfLines: 1
),
availableSize: CGSize(width: credentialsAreaSize.width - credentialsSideInset * 2.0, height: credentialsAreaSize.height),
transition: context.transition
credentialsSectionItems.append(
AnyComponentWithIdentity(id: "key", component: AnyComponent(
ListActionItemComponent(
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: environment.strings.CreateExternalStream_StreamKey,
font: Font.regular(15.0),
textColor: theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 1
))),
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: credentials.streamKey, font: Font.regular(17.0), textColor: theme.list.itemAccentColor, paragraphAlignment: .left)),
horizontalAlignment: .left,
truncationType: .middle,
maximumNumberOfLines: 1
)))
], alignment: .left, spacing: 5.0)),
contentInsets: UIEdgeInsets(top: 14.0, left: 0.0, bottom: 14.0, right: 0.0),
accessory: .custom(ListActionItemComponent.CustomAccessory(
component: AnyComponentWithIdentity(
id: "copy",
component: AnyComponent(
PlainButtonComponent(
content: AnyComponent(BundleIconComponent(name: "Chat/Context Menu/Copy", tintColor: theme.list.itemAccentColor)),
action: { [weak state] in
guard let state = state else {
return
}
state.copyCredentials(\.streamKey)
},
animateScale: false
)
)
),
insets: UIEdgeInsets(top: 0.0, left: 8.0, bottom: 0.0, right: 14.0),
isInteractive: true
)),
action: nil
)
))
)
let credentialsURLText = credentialsURLText.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(string: credentials.url, font: Font.regular(17.0), textColor: theme.list.itemAccentColor, paragraphAlignment: .left)),
horizontalAlignment: .left,
truncationType: .middle,
maximumNumberOfLines: 1
),
availableSize: CGSize(width: credentialsAreaSize.width - credentialsSideInset * 2.0 - 22.0, height: credentialsAreaSize.height),
transition: context.transition
)
let credentialsKeyText = credentialsKeyText.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(string: credentials.streamKey, font: Font.regular(17.0), textColor: theme.list.itemAccentColor, paragraphAlignment: .left)),
horizontalAlignment: .left,
truncationType: .middle,
maximumNumberOfLines: 1
),
availableSize: CGSize(width: credentialsAreaSize.width - credentialsSideInset * 2.0 - 48.0, height: credentialsAreaSize.height),
transition: context.transition
)
let credentialsBackground = credentialsBackground.update(
component: RoundedRectangle(color: theme.list.itemBlocksBackgroundColor, cornerRadius: 26.0),
availableSize: credentialsAreaSize,
transition: context.transition
)
let credentialsStripe = credentialsStripe.update(
component: Rectangle(color: theme.list.itemPlainSeparatorColor),
availableSize: CGSize(width: credentialsAreaSize.width - credentialsSideInset * 2.0, height: UIScreenPixel),
transition: context.transition
)
let credentialsCopyURLButton = credentialsCopyURLButton.update(
component: Button(
content: AnyComponent(BundleIconComponent(name: "Chat/Context Menu/Copy", tintColor: theme.list.itemAccentColor)),
action: { [weak state] in
guard let state = state else {
return
credentialsSectionItems.append(
AnyComponentWithIdentity(id: "revoke", component: AnyComponent(
ListActionItemComponent(
theme: theme,
style: .glass,
title: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: environment.strings.CreateExternalStream_RevokeStreamKey, font: Font.regular(17.0), textColor: theme.list.itemDestructiveColor)),
horizontalAlignment: .center,
truncationType: .middle,
maximumNumberOfLines: 1
)),
titleAlignment: .center,
action: { [weak state] _ in
guard let state = state else {
return
}
let alertController = textAlertController(context: component.context, title: nil, text: environment.strings.CreateExternalStream_Revoke_Text, actions: [TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {
}), TextAlertAction(type: .defaultAction, title: environment.strings.CreateExternalStream_Revoke_Revoke, action: { [weak state] in
state?.getCredentials(revoke: true)
})])
environment.controller()?.present(alertController, in: .window(.root))
}
state.copyCredentials(\.url)
}
).minSize(CGSize(width: 44.0, height: 44.0)),
availableSize: CGSize(width: 44.0, height: 44.0),
)
))
)
let credentialsSection = credentialsSection.update(
component: ListSectionComponent(
theme: theme,
style: .glass,
header: nil,
footer: nil,
items: credentialsSectionItems
),
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: context.availableSize.height),
transition: context.transition
)
let credentialsCopyKeyButton = credentialsCopyKeyButton.update(
component: Button(
content: AnyComponent(BundleIconComponent(name: "Chat/Context Menu/Copy", tintColor: theme.list.itemAccentColor)),
action: { [weak state] in
guard let state = state else {
return
}
state.copyCredentials(\.streamKey)
}
).minSize(CGSize(width: 44.0, height: 44.0)),
availableSize: CGSize(width: 44.0, height: 44.0),
transition: context.transition
)
context.add(credentialsBackground
.position(CGPoint(x: credentialsFrame.midX, y: credentialsFrame.midY))
)
context.add(credentialsStripe
.position(CGPoint(x: credentialsFrame.minX + credentialsSideInset + credentialsStripe.size.width / 2.0, y: credentialsFrame.minY + credentialsItemHeight))
)
context.add(credentialsURLTitle
.position(CGPoint(x: credentialsFrame.minX + credentialsSideInset + credentialsURLTitle.size.width / 2.0, y: credentialsFrame.minY + credentialsTopInset + credentialsURLTitle.size.height / 2.0))
)
context.add(credentialsURLText
.position(CGPoint(x: credentialsFrame.minX + credentialsSideInset + credentialsURLText.size.width / 2.0, y: credentialsFrame.minY + credentialsTopInset + credentialsTitleSpacing + credentialsURLTitle.size.height + credentialsURLText.size.height / 2.0))
)
context.add(credentialsCopyURLButton
.position(CGPoint(x: credentialsFrame.maxX - 4.0 - credentialsCopyURLButton.size.width / 2.0, y: credentialsFrame.minY + credentialsItemHeight / 2.0))
)
context.add(credentialsKeyTitle
.position(CGPoint(x: credentialsFrame.minX + credentialsSideInset + credentialsKeyTitle.size.width / 2.0, y: credentialsFrame.minY + credentialsItemHeight + credentialsTopInset + credentialsKeyTitle.size.height / 2.0))
)
context.add(credentialsKeyText
.position(CGPoint(x: credentialsFrame.minX + credentialsSideInset + credentialsKeyText.size.width / 2.0, y: credentialsFrame.minY + credentialsItemHeight + credentialsTopInset + credentialsTitleSpacing + credentialsKeyTitle.size.height + credentialsKeyText.size.height / 2.0))
)
context.add(credentialsCopyKeyButton
.position(CGPoint(x: credentialsFrame.maxX - 4.0 - credentialsCopyKeyButton.size.width / 2.0, y: credentialsFrame.minY + credentialsItemHeight + credentialsItemHeight / 2.0))
)
context.add(credentialsSection
.position(CGPoint(x: context.availableSize.width / 2.0, y: textFrame.maxY + 30.0 + credentialsSection.size.height / 2.0)))
} else if !context.state.isDelayingLoadingIndication {
let credentialsFrame = CGRect(origin: CGPoint(x: sideInset, y: textFrame.maxY + 30.0), size: credentialsAreaSize)
let activityIndicator = activityIndicator.update(
component: ActivityIndicatorComponent(color: theme.list.controlSecondaryColor),
availableSize: CGSize(width: 100.0, height: 100.0),

View file

@ -548,34 +548,6 @@ private func stringForRight(strings: PresentationStrings, right: TelegramChatAdm
}
}
private func rightDependencies(_ right: TelegramChatAdminRightsFlags) -> [TelegramChatAdminRightsFlags] {
if right.contains(.canChangeInfo) {
return []
} else if right.contains(.canPostMessages) {
return []
} else if right.contains(.canEditMessages) {
return []
} else if right.contains(.canDeleteMessages) {
return []
} else if right.contains(.canBanUsers) {
return []
} else if right.contains(.canInviteUsers) {
return []
} else if right.contains(.canPinMessages) {
return []
} else if right.contains(.canAddAdmins) {
return []
} else if right.contains(.canManageDirect) {
return []
} else if right.contains(.canManageCalls) {
return []
} else if right.contains(.canBeAnonymous) {
return []
} else {
return []
}
}
private func canEditAdminRights(accountPeerId: EnginePeer.Id, channelPeer: EnginePeer, initialParticipant: ChannelParticipant?) -> Bool {
if case let .channel(channel) = channelPeer {
if channel.flags.contains(.isCreator) {
@ -658,6 +630,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s
.direct(.canChangeInfo),
.sub(.messages, messageRelatedFlags),
.sub(.stories, storiesRelatedFlags),
.direct(.canBanUsers),
.direct(.canInviteUsers),
.direct(.canManageDirect),
.direct(.canManageCalls),

View file

@ -732,7 +732,7 @@ private func channelPermissionsControllerEntries(context: AccountContext, presen
var price: String = ""
let usdRate = Double(configuration.usdWithdrawRate) / 1000.0 / 100.0
price = "\(formatTonUsdValue(sendPaidMessageStars, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
price = "~\(formatTonUsdValue(sendPaidMessageStars, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
entries.append(.messagePriceHeader(presentationData.theme, presentationData.strings.GroupInfo_Permissions_MessagePrice))
entries.append(.messagePrice(presentationData.theme, sendPaidMessageStars, configuration.paidMessageMaxAmount, price))

View file

@ -354,15 +354,15 @@ protocol PhoneDemoDecorationView: UIView {
func resetAnimation()
}
final class PhoneDemoComponent: Component {
typealias EnvironmentType = DemoPageEnvironment
public final class PhoneDemoComponent: Component {
public typealias EnvironmentType = DemoPageEnvironment
enum Position {
public enum Position {
case top
case bottom
}
enum BackgroundDecoration {
public enum BackgroundDecoration {
case none
case dataRain
case swirlStars
@ -375,7 +375,7 @@ final class PhoneDemoComponent: Component {
case todo
}
enum Model {
public enum Model {
case notch
case island
}
@ -419,11 +419,11 @@ final class PhoneDemoComponent: Component {
return true
}
final class View: UIView, ComponentTaggedView {
final class Tag {
public final class View: UIView, ComponentTaggedView {
public final class Tag {
}
func matches(tag: Any) -> Bool {
public func matches(tag: Any) -> Bool {
if let _ = tag as? Tag, self.isCentral {
return true
}

View file

@ -155,7 +155,7 @@ public final class PremiumGradientBackgroundComponent: Component {
}
}
final class DemoPageEnvironment: Equatable {
public final class DemoPageEnvironment: Equatable {
public let isDisplaying: Bool
public let isCentral: Bool
public let position: CGFloat
@ -1134,13 +1134,13 @@ private final class DemoSheetContent: CombinedComponent {
let closeButton = closeButton.update(
component: GlassBarButtonComponent(
size: CGSize(width: 40.0, height: 40.0),
backgroundColor: theme.rootController.navigationBar.glassBarButtonBackgroundColor,
isDark: theme.overallDarkAppearance,
state: .glass,
backgroundColor: UIColor(rgb: 0x7f76f4),
isDark: false,
state: .tintedGlass,
component: AnyComponentWithIdentity(id: "close", component: AnyComponent(
BundleIconComponent(
name: "Navigation/Close",
tintColor: theme.rootController.navigationBar.glassBarButtonForegroundColor
tintColor: .white
)
)),
action: { _ in

View file

@ -2049,7 +2049,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
}
subtitle = "\(environment.strings.Gift_Options_Premium_Months(product.months))\(product.price)"
} else {
subtitle = product.price
//subtitle = product.price
subtitle = "\(environment.strings.Gift_Options_Premium_Months(product.months))\(product.price)"
}
}
if product.isCurrent {

View file

@ -126,6 +126,7 @@ swift_library(
"//submodules/TelegramUI/Components/Settings/ThemeAccentColorScreen",
"//submodules/TelegramUI/Components/Settings/GenerateThemeName",
"//submodules/TelegramUI/Components/Settings/PeerNameColorItem",
"//submodules/TelegramUI/Components/Settings/PasskeysScreen",
"//submodules/TelegramUI/Components/FaceScanScreen",
"//submodules/ComponentFlow",
"//submodules/Components/BundleIconComponent",

View file

@ -22,7 +22,7 @@ public func ChangePhoneNumberController(context: AccountContext) -> ViewControll
let requestDisposable = MetaDisposable()
let changePhoneDisposable = MetaDisposable()
let controller = AuthorizationSequencePhoneEntryController(sharedContext: context.sharedContext, account: nil, countriesConfiguration: context.currentCountriesConfiguration.with { $0 }, isTestingEnvironment: false, otherAccountPhoneNumbers: (nil, []), network: context.account.network, presentationData: presentationData, openUrl: { _ in }, back: {
let controller = AuthorizationSequencePhoneEntryController(sharedContext: context.sharedContext, account: nil, countriesConfiguration: context.currentCountriesConfiguration.with { $0 }, apiId: 0, apiHash: "", isTestingEnvironment: false, otherAccountPhoneNumbers: (nil, []), network: context.account.network, presentationData: presentationData, openUrl: { _ in }, back: {
dismissImpl?()
})
controller.loginWithNumber = { [weak controller] phoneNumber, _ in

View file

@ -194,7 +194,7 @@ private func incomingMessagePrivacyScreenEntries(presentationData: PresentationD
let usdRate = Double(configuration.usdWithdrawRate) / 1000.0 / 100.0
let price = "\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
let price = "~\(formatTonUsdValue(amount.value, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
entries.append(.price(value: amount.value, maxValue: configuration.paidMessageMaxAmount, price: price, isEnabled: isPremium))
entries.append(.priceInfo(commission: configuration.paidMessageCommissionPermille / 10, value: price))

View file

@ -19,6 +19,7 @@ import PremiumUI
import AuthorizationUI
import AuthenticationServices
import ChatTimerScreen
import PasskeysScreen
private final class PrivacyAndSecurityControllerArguments {
let account: Account
@ -35,6 +36,7 @@ private final class PrivacyAndSecurityControllerArguments {
let openSavedMusicPrivacy: () -> Void
let openPasscode: () -> Void
let openTwoStepVerification: (TwoStepVerificationAccessConfiguration?) -> Void
let openPasskeys: () -> Void
let openActiveSessions: () -> Void
let toggleArchiveAndMuteNonContacts: (Bool) -> Void
let setupAccountAutoremove: () -> Void
@ -44,7 +46,7 @@ private final class PrivacyAndSecurityControllerArguments {
let openMessagePrivacy: () -> Void
let openGiftsPrivacy: () -> Void
init(account: Account, openBlockedUsers: @escaping () -> Void, openLastSeenPrivacy: @escaping () -> Void, openGroupsPrivacy: @escaping () -> Void, openVoiceCallPrivacy: @escaping () -> Void, openProfilePhotoPrivacy: @escaping () -> Void, openForwardPrivacy: @escaping () -> Void, openPhoneNumberPrivacy: @escaping () -> Void, openVoiceMessagePrivacy: @escaping () -> Void, openBioPrivacy: @escaping () -> Void, openBirthdayPrivacy: @escaping () -> Void, openSavedMusicPrivacy: @escaping () -> Void, openPasscode: @escaping () -> Void, openTwoStepVerification: @escaping (TwoStepVerificationAccessConfiguration?) -> Void, openActiveSessions: @escaping () -> Void, toggleArchiveAndMuteNonContacts: @escaping (Bool) -> Void, setupAccountAutoremove: @escaping () -> Void, setupMessageAutoremove: @escaping () -> Void, openDataSettings: @escaping () -> Void, openEmailSettings: @escaping (String?) -> Void, openMessagePrivacy: @escaping () -> Void, openGiftsPrivacy: @escaping () -> Void) {
init(account: Account, openBlockedUsers: @escaping () -> Void, openLastSeenPrivacy: @escaping () -> Void, openGroupsPrivacy: @escaping () -> Void, openVoiceCallPrivacy: @escaping () -> Void, openProfilePhotoPrivacy: @escaping () -> Void, openForwardPrivacy: @escaping () -> Void, openPhoneNumberPrivacy: @escaping () -> Void, openVoiceMessagePrivacy: @escaping () -> Void, openBioPrivacy: @escaping () -> Void, openBirthdayPrivacy: @escaping () -> Void, openSavedMusicPrivacy: @escaping () -> Void, openPasscode: @escaping () -> Void, openTwoStepVerification: @escaping (TwoStepVerificationAccessConfiguration?) -> Void, openPasskeys: @escaping () -> Void, openActiveSessions: @escaping () -> Void, toggleArchiveAndMuteNonContacts: @escaping (Bool) -> Void, setupAccountAutoremove: @escaping () -> Void, setupMessageAutoremove: @escaping () -> Void, openDataSettings: @escaping () -> Void, openEmailSettings: @escaping (String?) -> Void, openMessagePrivacy: @escaping () -> Void, openGiftsPrivacy: @escaping () -> Void) {
self.account = account
self.openBlockedUsers = openBlockedUsers
self.openLastSeenPrivacy = openLastSeenPrivacy
@ -59,6 +61,7 @@ private final class PrivacyAndSecurityControllerArguments {
self.openSavedMusicPrivacy = openSavedMusicPrivacy
self.openPasscode = openPasscode
self.openTwoStepVerification = openTwoStepVerification
self.openPasskeys = openPasskeys
self.openActiveSessions = openActiveSessions
self.toggleArchiveAndMuteNonContacts = toggleArchiveAndMuteNonContacts
self.setupAccountAutoremove = setupAccountAutoremove
@ -113,6 +116,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
case selectivePrivacyInfo(PresentationTheme, String)
case passcode(PresentationTheme, String, Bool, String)
case twoStepVerification(PresentationTheme, String, String, TwoStepVerificationAccessConfiguration?)
case passkeys(PresentationTheme, String, String)
case loginEmail(PresentationTheme, String, String?)
case loginEmailInfo(PresentationTheme, String)
case activeSessions(PresentationTheme, String, String)
@ -129,7 +133,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
var section: ItemListSectionId {
switch self {
case .blockedPeers, .activeSessions, .passcode, .twoStepVerification, .messageAutoremoveTimeout, .messageAutoremoveInfo:
case .blockedPeers, .activeSessions, .passcode, .twoStepVerification, .passkeys, .messageAutoremoveTimeout, .messageAutoremoveInfo:
return PrivacyAndSecuritySection.general.rawValue
case .loginEmail, .loginEmailInfo:
return PrivacyAndSecuritySection.loginEmail.rawValue
@ -154,60 +158,62 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
return 3
case .twoStepVerification:
return 4
case .messageAutoremoveTimeout:
case .passkeys:
return 5
case .messageAutoremoveInfo:
case .messageAutoremoveTimeout:
return 6
case .loginEmail:
case .messageAutoremoveInfo:
return 7
case .loginEmailInfo:
case .loginEmail:
return 8
case .privacyHeader:
case .loginEmailInfo:
return 9
case .phoneNumberPrivacy:
case .privacyHeader:
return 10
case .lastSeenPrivacy:
case .phoneNumberPrivacy:
return 11
case .profilePhotoPrivacy:
case .lastSeenPrivacy:
return 12
case .bioPrivacy:
case .profilePhotoPrivacy:
return 13
case .giftsAutoSavePrivacy:
case .bioPrivacy:
return 14
case .birthdayPrivacy:
case .giftsAutoSavePrivacy:
return 15
case .savedMusicPrivacy:
case .birthdayPrivacy:
return 16
case .forwardPrivacy:
case .savedMusicPrivacy:
return 17
case .voiceCallPrivacy:
case .forwardPrivacy:
return 18
case .voiceMessagePrivacy:
case .voiceCallPrivacy:
return 19
case .messagePrivacy:
case .voiceMessagePrivacy:
return 20
case .groupPrivacy:
case .messagePrivacy:
return 21
case .groupPrivacyFooter:
case .groupPrivacy:
return 22
case .selectivePrivacyInfo:
case .groupPrivacyFooter:
return 23
case .autoArchiveHeader:
case .selectivePrivacyInfo:
return 24
case .autoArchive:
case .autoArchiveHeader:
return 25
case .autoArchiveInfo:
case .autoArchive:
return 26
case .accountHeader:
case .autoArchiveInfo:
return 27
case .accountTimeout:
case .accountHeader:
return 28
case .accountInfo:
case .accountTimeout:
return 29
case .dataSettings:
case .accountInfo:
return 30
case .dataSettingsInfo:
case .dataSettings:
return 31
case .dataSettingsInfo:
return 32
}
}
@ -321,6 +327,12 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
} else {
return false
}
case let .passkeys(lhsTheme, lhsText, lhsValue):
if case let .passkeys(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .loginEmail(lhsTheme, lhsText, lhsEmailPattern):
if case let .loginEmail(rhsTheme, rhsText, rhsEmailPattern) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEmailPattern == rhsEmailPattern {
return true
@ -488,6 +500,10 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, icon: UIImage(bundleImageName: "Settings/Menu/TwoStepAuth")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: {
arguments.openTwoStepVerification(data)
})
case let .passkeys(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, icon: UIImage(bundleImageName: "Settings/Menu/Passkeys")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: {
arguments.openPasskeys()
})
case let .messageAutoremoveTimeout(_, text, value):
return ItemListDisclosureItem(presentationData: presentationData, systemStyle: .glass, icon: UIImage(bundleImageName: "Settings/Menu/Timer")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: {
arguments.setupMessageAutoremove()
@ -617,6 +633,8 @@ private func privacyAndSecurityControllerEntries(
activeWebsitesCount: Int,
hasTwoStepAuth: Bool?,
twoStepAuthData: TwoStepVerificationAccessConfiguration?,
hasPasskeys: Bool?,
displayPasskeys: Bool,
canAutoarchive: Bool,
isPremiumDisabled: Bool,
isPremium: Bool,
@ -654,6 +672,14 @@ private func privacyAndSecurityControllerEntries(
}
entries.append(.twoStepVerification(presentationData.theme, presentationData.strings.PrivacySettings_TwoStepAuth, twoStepAuthString, twoStepAuthData))
if displayPasskeys {
var passkeysString = ""
if let hasPasskeys = hasPasskeys {
passkeysString = hasPasskeys ? presentationData.strings.PrivacySettings_PasscodeOn : presentationData.strings.PrivacySettings_PasscodeOff
}
entries.append(.passkeys(presentationData.theme, presentationData.strings.PrivacySettings_Passkey, passkeysString))
}
if let privacySettings = privacySettings {
let value: Int32?
if let updatingMessageAutoremoveTimeoutValue = state.updatingMessageAutoremoveTimeoutValue {
@ -788,6 +814,7 @@ public func privacyAndSecurityController(
updatedSettings: ((AccountPrivacySettings?) -> Void)? = nil,
updatedBlockedPeers: ((BlockedPeersContext?) -> Void)? = nil,
updatedHasTwoStepAuth: ((Bool) -> Void)? = nil,
updatedHasPasskeys: ((Bool) -> Void)? = nil,
focusOnItemTag: PrivacyAndSecurityEntryTag? = nil,
activeSessionsContext: ActiveSessionsContext? = nil,
webSessionsContext: WebSessionsContext? = nil,
@ -835,6 +862,10 @@ public func privacyAndSecurityController(
let updateTwoStepAuthDisposable = MetaDisposable()
actionsDisposable.add(updateTwoStepAuthDisposable)
let updatePasskeyDataDisposable = MetaDisposable()
actionsDisposable.add(updatePasskeyDataDisposable)
let twoStepAuthDataValue = Promise<TwoStepVerificationAccessConfiguration?>(nil)
let hasTwoStepAuthDataValue = twoStepAuthDataValue.get()
|> mapToSignal { data -> Signal<Bool?, NoError> in
@ -855,6 +886,19 @@ public func privacyAndSecurityController(
} else {
twoStepAuth.set(hasTwoStepAuthDataValue)
}
let passkeysDataValue = Promise<[TelegramPasskey]?>(nil)
let hasPasskeysDataValue = passkeysDataValue.get()
|> mapToSignal { data -> Signal<Bool?, NoError> in
if let data = data {
return .single(!data.isEmpty)
} else {
return .single(nil)
}
}
let passkeys = Promise<Bool?>()
passkeys.set(hasPasskeysDataValue)
let loginEmail: Signal<String?, NoError>
if let loginEmailPattern = loginEmailPattern {
@ -893,6 +937,23 @@ public func privacyAndSecurityController(
)
}
updateHasTwoStepAuth()
let updateHasPasskeys: () -> Void = {
let signal = context.engine.auth.passkeysData()
|> map { value -> [TelegramPasskey]? in
return value
}
|> deliverOnMainQueue
updatePasskeyDataDisposable.set(
signal.start(next: { value in
passkeysDataValue.set(.single(value))
if let value {
updatedHasPasskeys?(!value.isEmpty)
}
})
)
}
updateHasPasskeys()
var setupEmailImpl: ((String?) -> Void)?
@ -1203,6 +1264,14 @@ public func privacyAndSecurityController(
let controller = twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: data.flatMap({ Signal<TwoStepVerificationUnlockSettingsControllerData, NoError>.single(.access(configuration: $0)) })))
pushControllerImpl?(controller, true)
})
}, openPasskeys: {
Task { @MainActor in
let initialPasskeysData = await (passkeysDataValue.get() |> take(1)).get()
let passkeysScreen = PasskeysScreen(context: context, displaySkip: false, initialPasskeysData: initialPasskeysData, passkeysDataUpdated: { passkeysData in
passkeysDataValue.set(.single(passkeysData))
}, completion: {}, cancel: {})
pushControllerImpl?(passkeysScreen, true)
}
}, openActiveSessions: {
pushControllerImpl?(recentSessionsController(context: context, activeSessionsContext: activeSessionsContext, webSessionsContext: webSessionsContext, websitesOnly: true), true)
}, toggleArchiveAndMuteNonContacts: { archiveValue in
@ -1442,6 +1511,15 @@ public func privacyAndSecurityController(
updatedBlockedPeers?(blockedPeersContext)
}))
var displayPasskeys = false
if let data = context.currentAppConfiguration.with({ $0 }).data {
if let _ = data["ios_display_passkeys"] {
displayPasskeys = true
} else if let isDev = data["dev"] as? Double, isDev == 1.0 {
displayPasskeys = true
}
}
let signal = combineLatest(
queue: .mainQueue(),
context.sharedContext.presentationData,
@ -1454,11 +1532,12 @@ public func privacyAndSecurityController(
webSessionsContext.state,
context.sharedContext.accountManager.accessChallengeData(),
combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()),
combineLatest(passkeys.get(), passkeysDataValue.get()),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.App()),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)),
loginEmail
)
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, appConfiguration, accountPeer, loginEmail -> (ItemListControllerState, (ItemListNodeState, Any)) in
|> map { presentationData, state, privacySettings, noticeView, sharedData, recentPeers, blockedPeersState, activeWebsitesState, accessChallengeData, twoStepAuth, passkeys, appConfiguration, accountPeer, loginEmail -> (ItemListControllerState, (ItemListNodeState, Any)) in
var canAutoarchive = false
if let data = appConfiguration.data, let hasAutoarchive = data["autoarchive_setting_available"] as? Bool {
canAutoarchive = hasAutoarchive
@ -1474,7 +1553,7 @@ public func privacyAndSecurityController(
let isPremium = accountPeer?.isPremium ?? false
let isPremiumDisabled = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }).isPremiumDisabled
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, canAutoarchive: canAutoarchive, isPremiumDisabled: isPremiumDisabled, isPremium: isPremium, loginEmail: loginEmail, accountPeer: accountPeer), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: privacyAndSecurityControllerEntries(presentationData: presentationData, state: state, privacySettings: privacySettings, accessChallengeData: accessChallengeData.data, blockedPeerCount: blockedPeersState.totalCount, activeWebsitesCount: activeWebsitesState.sessions.count, hasTwoStepAuth: twoStepAuth.0, twoStepAuthData: twoStepAuth.1, hasPasskeys: passkeys.0, displayPasskeys: displayPasskeys, canAutoarchive: canAutoarchive, isPremiumDisabled: isPremiumDisabled, isPremium: isPremium, loginEmail: loginEmail, accountPeer: accountPeer), style: .blocks, ensureVisibleItemTag: focusOnItemTag, animateChanges: false)
return (controllerState, (listState, arguments))
}

View file

@ -180,10 +180,10 @@ final class MonetizationBalanceItemNode: ListViewItemNode, ItemListItemNode {
case .ton:
let cryptoValue = formatTonAmountText(stats.balances.availableBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat)
amountString = tonAmountAttributedString(cryptoValue, integralFont: integralFont, fractionalFont: fractionalFont, color: item.presentationData.theme.list.itemPrimaryTextColor, decimalSeparator: item.presentationData.dateTimeFormat.decimalSeparator)
value = stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))"
value = stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "~\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))"
case .stars:
amountString = NSAttributedString(string: presentationStringsFormattedNumber(stats.balances.availableBalance.amount, item.presentationData.dateTimeFormat.groupingSeparator), font: integralFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
value = stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))"
value = stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "~\(formatTonUsdValue(stats.balances.availableBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))"
isStars = true
}
} else {

View file

@ -443,7 +443,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
item.publicShares.flatMap { "\( compactNumericCountString(max(0, stats.forwards - Int($0))))" } ?? "",
item.publicShares.flatMap { "~\( compactNumericCountString(max(0, stats.forwards - Int($0))))" } ?? "",
item.presentationData.strings.Stats_Message_PrivateShares,
nil,
.generic
@ -485,7 +485,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
item.publicShares.flatMap { "\( compactNumericCountString(max(0, views.forwardCount - Int($0))))" } ?? "",
item.publicShares.flatMap { "~\( compactNumericCountString(max(0, views.forwardCount - Int($0))))" } ?? "",
item.presentationData.strings.Stats_Message_PrivateShares,
nil,
.generic
@ -512,7 +512,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.context,
params.width,
item.presentationData,
"\(Int(stats.premiumAudience?.value ?? 0))",
"~\(Int(stats.premiumAudience?.value ?? 0))",
item.isGroup ? item.presentationData.strings.Stats_Boosts_PremiumMembers : item.presentationData.strings.Stats_Boosts_PremiumSubscribers,
(String(format: "%.02f%%", premiumSubscribers * 100.0), .generic),
.generic
@ -770,7 +770,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatTonAmountText(stats.balances.availableBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Available,
(stats.balances.availableBalance.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.availableBalance.amount.value == 0 ? "" : "~\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -780,7 +780,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatTonAmountText(stats.balances.currentBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Current,
(stats.balances.currentBalance.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.currentBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.currentBalance.amount.value == 0 ? "" : "~\(formatTonUsdValue(stats.balances.currentBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -790,7 +790,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatTonAmountText(stats.balances.overallRevenue.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Total,
(stats.balances.overallRevenue.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.overallRevenue.amount.value == 0 ? "" : "~\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -800,7 +800,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatStarsAmountText(additionalStats.balances.availableBalance.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
" ",
(additionalStats.balances.availableBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.availableBalance.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(additionalStats.balances.availableBalance.amount == StarsAmount.zero ? "" : "~\(formatTonUsdValue(additionalStats.balances.availableBalance.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -810,7 +810,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatStarsAmountText(additionalStats.balances.currentBalance.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
" ",
(additionalStats.balances.currentBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.currentBalance.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(additionalStats.balances.currentBalance.amount == StarsAmount.zero ? "" : "~\(formatTonUsdValue(additionalStats.balances.currentBalance.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -820,7 +820,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatStarsAmountText(additionalStats.balances.overallRevenue.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
" ",
(additionalStats.balances.overallRevenue.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(additionalStats.balances.overallRevenue.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(additionalStats.balances.overallRevenue.amount == StarsAmount.zero ? "" : "~\(formatTonUsdValue(additionalStats.balances.overallRevenue.amount.value, divide: false, rate: additionalStats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -834,7 +834,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatTonAmountText(stats.balances.availableBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_Overview_Available,
(stats.balances.availableBalance.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.availableBalance.amount.value == 0 ? "" : "~\(formatTonUsdValue(stats.balances.availableBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -844,7 +844,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatTonAmountText(stats.balances.currentBalance.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_Overview_Current,
(stats.balances.currentBalance.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.currentBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.currentBalance.amount.value == 0 ? "" : "~\(formatTonUsdValue(stats.balances.currentBalance.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -854,7 +854,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatTonAmountText(stats.balances.overallRevenue.amount.value, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_Overview_Total,
(stats.balances.overallRevenue.amount.value == 0 ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.overallRevenue.amount.value == 0 ? "" : "~\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.ton
)
@ -869,7 +869,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatStarsAmountText(stats.balances.availableBalance.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Available,
(stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.availableBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.availableBalance.amount == StarsAmount.zero ? "" : "~\(formatTonUsdValue(stats.balances.availableBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -879,7 +879,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatStarsAmountText(stats.balances.currentBalance.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Current,
(stats.balances.currentBalance.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.currentBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.currentBalance.amount == StarsAmount.zero ? "" : "~\(formatTonUsdValue(stats.balances.currentBalance.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)
@ -889,7 +889,7 @@ class StatsOverviewItemNode: ListViewItemNode {
item.presentationData,
formatStarsAmountText(stats.balances.overallRevenue.amount, dateTimeFormat: item.presentationData.dateTimeFormat),
item.presentationData.strings.Monetization_StarsProceeds_Total,
(stats.balances.overallRevenue.amount == StarsAmount.zero ? "" : "\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
(stats.balances.overallRevenue.amount == StarsAmount.zero ? "" : "~\(formatTonUsdValue(stats.balances.overallRevenue.amount.value, divide: false, rate: stats.usdRate, dateTimeFormat: item.presentationData.dateTimeFormat))", .generic),
.stars
)

View file

@ -432,6 +432,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1548122514] = { return Api.InputNotifyPeer.parse_inputNotifyForumTopic($0) }
dict[-1195615476] = { return Api.InputNotifyPeer.parse_inputNotifyPeer($0) }
dict[423314455] = { return Api.InputNotifyPeer.parse_inputNotifyUsers($0) }
dict[1009235855] = { return Api.InputPasskeyCredential.parse_inputPasskeyCredentialPublicKey($0) }
dict[-1021329078] = { return Api.InputPasskeyResponse.parse_inputPasskeyResponseLogin($0) }
dict[1046713180] = { return Api.InputPasskeyResponse.parse_inputPasskeyResponseRegister($0) }
dict[873977640] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentials($0) }
dict[178373535] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentialsApplePay($0) }
dict[-1966921727] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentialsGooglePay($0) }
@ -617,7 +620,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1189364422] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) }
dict[1348510708] = { return Api.MessageAction.parse_messageActionSetChatWallPaper($0) }
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
dict[-614898352] = { return Api.MessageAction.parse_messageActionStarGift($0) }
dict[-366202413] = { return Api.MessageAction.parse_messageActionStarGift($0) }
dict[2000845012] = { return Api.MessageAction.parse_messageActionStarGiftPurchaseOffer($0) }
dict[1940760427] = { return Api.MessageAction.parse_messageActionStarGiftPurchaseOfferDeclined($0) }
dict[-1787656893] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
dict[747579941] = { return Api.MessageAction.parse_messageActionSuggestBirthday($0) }
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
@ -756,6 +761,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[520887001] = { return Api.PaidReactionPrivacy.parse_paidReactionPrivacyAnonymous($0) }
dict[543872158] = { return Api.PaidReactionPrivacy.parse_paidReactionPrivacyDefault($0) }
dict[-596837136] = { return Api.PaidReactionPrivacy.parse_paidReactionPrivacyPeer($0) }
dict[-1738457409] = { return Api.Passkey.parse_passkey($0) }
dict[982592842] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow($0) }
dict[-732254058] = { return Api.PasswordKdfAlgo.parse_passwordKdfAlgoUnknown($0) }
dict[-368917890] = { return Api.PaymentCharge.parse_paymentCharge($0) }
@ -909,7 +915,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1681948327] = { return Api.SavedDialog.parse_monoForumDialog($0) }
dict[-1115174036] = { return Api.SavedDialog.parse_savedDialog($0) }
dict[-881854424] = { return Api.SavedReactionTag.parse_savedReactionTag($0) }
dict[-1987861422] = { return Api.SavedStarGift.parse_savedStarGift($0) }
dict[-355041186] = { return Api.SavedStarGift.parse_savedStarGift($0) }
dict[1040931690] = { return Api.SearchPostsFlood.parse_searchPostsFlood($0) }
dict[-911191137] = { return Api.SearchResultsCalendarPeriod.parse_searchResultsCalendarPeriod($0) }
dict[2137295719] = { return Api.SearchResultsPosition.parse_searchResultPosition($0) }
@ -974,8 +980,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[2109703795] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
dict[-963180333] = { return Api.SponsoredPeer.parse_sponsoredPeer($0) }
dict[463097215] = { return Api.StarGift.parse_starGift($0) }
dict[-1329630181] = { return Api.StarGift.parse_starGiftUnique($0) }
dict[825922887] = { return Api.StarGift.parse_starGift($0) }
dict[1453155529] = { return Api.StarGift.parse_starGiftUnique($0) }
dict[-753154979] = { return Api.StarGiftActiveAuctionState.parse_starGiftActiveAuctionState($0) }
dict[-650279524] = { return Api.StarGiftAttribute.parse_starGiftAttributeBackdrop($0) }
dict[970559507] = { return Api.StarGiftAttribute.parse_starGiftAttributeModel($0) }
@ -985,11 +991,14 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[520210263] = { return Api.StarGiftAttributeId.parse_starGiftAttributeIdBackdrop($0) }
dict[1219145276] = { return Api.StarGiftAttributeId.parse_starGiftAttributeIdModel($0) }
dict[1242965043] = { return Api.StarGiftAttributeId.parse_starGiftAttributeIdPattern($0) }
dict[-1419714037] = { return Api.StarGiftAuctionAcquiredGift.parse_starGiftAuctionAcquiredGift($0) }
dict[1571835723] = { return Api.StarGiftAuctionState.parse_starGiftAuctionState($0) }
dict[2107014202] = { return Api.StarGiftAuctionState.parse_starGiftAuctionStateFinished($0) }
dict[1118831432] = { return Api.StarGiftAuctionAcquiredGift.parse_starGiftAuctionAcquiredGift($0) }
dict[984483112] = { return Api.StarGiftAuctionRound.parse_starGiftAuctionRound($0) }
dict[178266597] = { return Api.StarGiftAuctionRound.parse_starGiftAuctionRoundExtendable($0) }
dict[1998212710] = { return Api.StarGiftAuctionState.parse_starGiftAuctionState($0) }
dict[-1758614593] = { return Api.StarGiftAuctionState.parse_starGiftAuctionStateFinished($0) }
dict[-30197422] = { return Api.StarGiftAuctionState.parse_starGiftAuctionStateNotModified($0) }
dict[787403204] = { return Api.StarGiftAuctionUserState.parse_starGiftAuctionUserState($0) }
dict[-1342872680] = { return Api.StarGiftBackground.parse_starGiftBackground($0) }
dict[-1653926992] = { return Api.StarGiftCollection.parse_starGiftCollection($0) }
dict[-1712704739] = { return Api.StarGiftUpgradePrice.parse_starGiftUpgradePrice($0) }
dict[-586389774] = { return Api.StarRefProgram.parse_starRefProgram($0) }
@ -1246,7 +1255,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[555358088] = { return Api.WebPage.parse_webPageEmpty($0) }
dict[1930545681] = { return Api.WebPage.parse_webPageNotModified($0) }
dict[-1328464313] = { return Api.WebPage.parse_webPagePending($0) }
dict[55150251] = { return Api.WebPageAttribute.parse_webPageAttributeStarGiftAuction($0) }
dict[29770178] = { return Api.WebPageAttribute.parse_webPageAttributeStarGiftAuction($0) }
dict[835375875] = { return Api.WebPageAttribute.parse_webPageAttributeStarGiftCollection($0) }
dict[1355547603] = { return Api.WebPageAttribute.parse_webPageAttributeStickerSet($0) }
dict[781501415] = { return Api.WebPageAttribute.parse_webPageAttributeStory($0) }
@ -1268,6 +1277,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1866176559] = { return Api.account.EmojiStatuses.parse_emojiStatuses($0) }
dict[-796072379] = { return Api.account.EmojiStatuses.parse_emojiStatusesNotModified($0) }
dict[504403720] = { return Api.account.PaidMessagesRevenue.parse_paidMessagesRevenue($0) }
dict[-513057567] = { return Api.account.PasskeyRegistrationOptions.parse_passkeyRegistrationOptions($0) }
dict[-119494116] = { return Api.account.Passkeys.parse_passkeys($0) }
dict[-1787080453] = { return Api.account.Password.parse_password($0) }
dict[-1036572727] = { return Api.account.PasswordInputSettings.parse_passwordInputSettings($0) }
dict[-1705233435] = { return Api.account.PasswordSettings.parse_passwordSettings($0) }
@ -1302,6 +1313,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1654593920] = { return Api.auth.LoginToken.parse_loginToken($0) }
dict[110008598] = { return Api.auth.LoginToken.parse_loginTokenMigrateTo($0) }
dict[957176926] = { return Api.auth.LoginToken.parse_loginTokenSuccess($0) }
dict[-503089271] = { return Api.auth.PasskeyLoginOptions.parse_passkeyLoginOptions($0) }
dict[326715557] = { return Api.auth.PasswordRecovery.parse_passwordRecovery($0) }
dict[1577067778] = { return Api.auth.SentCode.parse_sentCode($0) }
dict[-527082948] = { return Api.auth.SentCode.parse_sentCodePaymentRequired($0) }
@ -1484,12 +1496,13 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1803939105] = { return Api.payments.ResaleStarGifts.parse_resaleStarGifts($0) }
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }
dict[-1779201615] = { return Api.payments.SavedStarGifts.parse_savedStarGifts($0) }
dict[-1745778728] = { return Api.payments.StarGiftActiveAuctions.parse_starGiftActiveAuctions($0) }
dict[-1359565892] = { return Api.payments.StarGiftActiveAuctions.parse_starGiftActiveAuctions($0) }
dict[-617358640] = { return Api.payments.StarGiftActiveAuctions.parse_starGiftActiveAuctionsNotModified($0) }
dict[2103169520] = { return Api.payments.StarGiftAuctionAcquiredGifts.parse_starGiftAuctionAcquiredGifts($0) }
dict[244900980] = { return Api.payments.StarGiftAuctionState.parse_starGiftAuctionState($0) }
dict[1798960364] = { return Api.payments.StarGiftAuctionState.parse_starGiftAuctionState($0) }
dict[-1977011469] = { return Api.payments.StarGiftCollections.parse_starGiftCollections($0) }
dict[-1598402793] = { return Api.payments.StarGiftCollections.parse_starGiftCollectionsNotModified($0) }
dict[1187439471] = { return Api.payments.StarGiftUpgradeAttributes.parse_starGiftUpgradeAttributes($0) }
dict[1038213101] = { return Api.payments.StarGiftUpgradePreview.parse_starGiftUpgradePreview($0) }
dict[-2069218660] = { return Api.payments.StarGiftWithdrawalUrl.parse_starGiftWithdrawalUrl($0) }
dict[785918357] = { return Api.payments.StarGifts.parse_starGifts($0) }
@ -1930,6 +1943,10 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.InputNotifyPeer:
_1.serialize(buffer, boxed)
case let _1 as Api.InputPasskeyCredential:
_1.serialize(buffer, boxed)
case let _1 as Api.InputPasskeyResponse:
_1.serialize(buffer, boxed)
case let _1 as Api.InputPaymentCredentials:
_1.serialize(buffer, boxed)
case let _1 as Api.InputPeer:
@ -2066,6 +2083,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.PaidReactionPrivacy:
_1.serialize(buffer, boxed)
case let _1 as Api.Passkey:
_1.serialize(buffer, boxed)
case let _1 as Api.PasswordKdfAlgo:
_1.serialize(buffer, boxed)
case let _1 as Api.PaymentCharge:
@ -2228,10 +2247,14 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.StarGiftAuctionAcquiredGift:
_1.serialize(buffer, boxed)
case let _1 as Api.StarGiftAuctionRound:
_1.serialize(buffer, boxed)
case let _1 as Api.StarGiftAuctionState:
_1.serialize(buffer, boxed)
case let _1 as Api.StarGiftAuctionUserState:
_1.serialize(buffer, boxed)
case let _1 as Api.StarGiftBackground:
_1.serialize(buffer, boxed)
case let _1 as Api.StarGiftCollection:
_1.serialize(buffer, boxed)
case let _1 as Api.StarGiftUpgradePrice:
@ -2376,6 +2399,10 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.account.PaidMessagesRevenue:
_1.serialize(buffer, boxed)
case let _1 as Api.account.PasskeyRegistrationOptions:
_1.serialize(buffer, boxed)
case let _1 as Api.account.Passkeys:
_1.serialize(buffer, boxed)
case let _1 as Api.account.Password:
_1.serialize(buffer, boxed)
case let _1 as Api.account.PasswordInputSettings:
@ -2416,6 +2443,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.auth.LoginToken:
_1.serialize(buffer, boxed)
case let _1 as Api.auth.PasskeyLoginOptions:
_1.serialize(buffer, boxed)
case let _1 as Api.auth.PasswordRecovery:
_1.serialize(buffer, boxed)
case let _1 as Api.auth.SentCode:
@ -2656,6 +2685,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarGiftCollections:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarGiftUpgradeAttributes:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarGiftUpgradePreview:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarGiftWithdrawalUrl:

View file

@ -868,6 +868,128 @@ public extension Api {
}
}
public extension Api {
enum InputPasskeyCredential: TypeConstructorDescription {
case inputPasskeyCredentialPublicKey(id: String, rawId: String, response: Api.InputPasskeyResponse)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPasskeyCredentialPublicKey(let id, let rawId, let response):
if boxed {
buffer.appendInt32(1009235855)
}
serializeString(id, buffer: buffer, boxed: false)
serializeString(rawId, buffer: buffer, boxed: false)
response.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPasskeyCredentialPublicKey(let id, let rawId, let response):
return ("inputPasskeyCredentialPublicKey", [("id", id as Any), ("rawId", rawId as Any), ("response", response as Any)])
}
}
public static func parse_inputPasskeyCredentialPublicKey(_ reader: BufferReader) -> InputPasskeyCredential? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
var _3: Api.InputPasskeyResponse?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.InputPasskeyResponse
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputPasskeyCredential.inputPasskeyCredentialPublicKey(id: _1!, rawId: _2!, response: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputPasskeyResponse: TypeConstructorDescription {
case inputPasskeyResponseLogin(clientData: Api.DataJSON, authenticatorData: Buffer, signature: Buffer, userHandle: String)
case inputPasskeyResponseRegister(clientData: Api.DataJSON, attestationData: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPasskeyResponseLogin(let clientData, let authenticatorData, let signature, let userHandle):
if boxed {
buffer.appendInt32(-1021329078)
}
clientData.serialize(buffer, true)
serializeBytes(authenticatorData, buffer: buffer, boxed: false)
serializeBytes(signature, buffer: buffer, boxed: false)
serializeString(userHandle, buffer: buffer, boxed: false)
break
case .inputPasskeyResponseRegister(let clientData, let attestationData):
if boxed {
buffer.appendInt32(1046713180)
}
clientData.serialize(buffer, true)
serializeBytes(attestationData, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPasskeyResponseLogin(let clientData, let authenticatorData, let signature, let userHandle):
return ("inputPasskeyResponseLogin", [("clientData", clientData as Any), ("authenticatorData", authenticatorData as Any), ("signature", signature as Any), ("userHandle", userHandle as Any)])
case .inputPasskeyResponseRegister(let clientData, let attestationData):
return ("inputPasskeyResponseRegister", [("clientData", clientData as Any), ("attestationData", attestationData as Any)])
}
}
public static func parse_inputPasskeyResponseLogin(_ reader: BufferReader) -> InputPasskeyResponse? {
var _1: Api.DataJSON?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
var _2: Buffer?
_2 = parseBytes(reader)
var _3: Buffer?
_3 = parseBytes(reader)
var _4: String?
_4 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputPasskeyResponse.inputPasskeyResponseLogin(clientData: _1!, authenticatorData: _2!, signature: _3!, userHandle: _4!)
}
else {
return nil
}
}
public static func parse_inputPasskeyResponseRegister(_ reader: BufferReader) -> InputPasskeyResponse? {
var _1: Api.DataJSON?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
var _2: Buffer?
_2 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputPasskeyResponse.inputPasskeyResponseRegister(clientData: _1!, attestationData: _2!)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputPaymentCredentials: TypeConstructorDescription {
case inputPaymentCredentials(flags: Int32, data: Api.DataJSON)

View file

@ -1069,7 +1069,9 @@ public extension Api {
case messageActionSetChatTheme(theme: Api.ChatTheme)
case messageActionSetChatWallPaper(flags: Int32, wallpaper: Api.WallPaper)
case messageActionSetMessagesTTL(flags: Int32, period: Int32, autoSettingFrom: Int64?)
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeMsgId: Int32?, upgradeStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?, prepaidUpgradeHash: String?, giftMsgId: Int32?, toId: Api.Peer?)
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeMsgId: Int32?, upgradeStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?, prepaidUpgradeHash: String?, giftMsgId: Int32?, toId: Api.Peer?, giftNum: Int32?)
case messageActionStarGiftPurchaseOffer(flags: Int32, gift: Api.StarGift, price: Api.StarsAmount, expiresAt: Int32)
case messageActionStarGiftPurchaseOfferDeclined(flags: Int32, gift: Api.StarGift, price: Api.StarsAmount)
case messageActionStarGiftUnique(flags: Int32, gift: Api.StarGift, canExportAt: Int32?, transferStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?, resaleAmount: Api.StarsAmount?, canTransferAt: Int32?, canResellAt: Int32?, dropOriginalDetailsStars: Int64?)
case messageActionSuggestBirthday(birthday: Api.Birthday)
case messageActionSuggestProfilePhoto(photo: Api.Photo)
@ -1460,9 +1462,9 @@ public extension Api {
serializeInt32(period, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(autoSettingFrom!, buffer: buffer, boxed: false)}
break
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars, let fromId, let peer, let savedId, let prepaidUpgradeHash, let giftMsgId, let toId):
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars, let fromId, let peer, let savedId, let prepaidUpgradeHash, let giftMsgId, let toId, let giftNum):
if boxed {
buffer.appendInt32(-614898352)
buffer.appendInt32(-366202413)
}
serializeInt32(flags, buffer: buffer, boxed: false)
gift.serialize(buffer, true)
@ -1476,6 +1478,24 @@ public extension Api {
if Int(flags) & Int(1 << 14) != 0 {serializeString(prepaidUpgradeHash!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 15) != 0 {serializeInt32(giftMsgId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 18) != 0 {toId!.serialize(buffer, true)}
if Int(flags) & Int(1 << 19) != 0 {serializeInt32(giftNum!, buffer: buffer, boxed: false)}
break
case .messageActionStarGiftPurchaseOffer(let flags, let gift, let price, let expiresAt):
if boxed {
buffer.appendInt32(2000845012)
}
serializeInt32(flags, buffer: buffer, boxed: false)
gift.serialize(buffer, true)
price.serialize(buffer, true)
serializeInt32(expiresAt, buffer: buffer, boxed: false)
break
case .messageActionStarGiftPurchaseOfferDeclined(let flags, let gift, let price):
if boxed {
buffer.appendInt32(1940760427)
}
serializeInt32(flags, buffer: buffer, boxed: false)
gift.serialize(buffer, true)
price.serialize(buffer, true)
break
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars, let fromId, let peer, let savedId, let resaleAmount, let canTransferAt, let canResellAt, let dropOriginalDetailsStars):
if boxed {
@ -1678,8 +1698,12 @@ public extension Api {
return ("messageActionSetChatWallPaper", [("flags", flags as Any), ("wallpaper", wallpaper as Any)])
case .messageActionSetMessagesTTL(let flags, let period, let autoSettingFrom):
return ("messageActionSetMessagesTTL", [("flags", flags as Any), ("period", period as Any), ("autoSettingFrom", autoSettingFrom as Any)])
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars, let fromId, let peer, let savedId, let prepaidUpgradeHash, let giftMsgId, let toId):
return ("messageActionStarGift", [("flags", flags as Any), ("gift", gift as Any), ("message", message as Any), ("convertStars", convertStars as Any), ("upgradeMsgId", upgradeMsgId as Any), ("upgradeStars", upgradeStars as Any), ("fromId", fromId as Any), ("peer", peer as Any), ("savedId", savedId as Any), ("prepaidUpgradeHash", prepaidUpgradeHash as Any), ("giftMsgId", giftMsgId as Any), ("toId", toId as Any)])
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars, let fromId, let peer, let savedId, let prepaidUpgradeHash, let giftMsgId, let toId, let giftNum):
return ("messageActionStarGift", [("flags", flags as Any), ("gift", gift as Any), ("message", message as Any), ("convertStars", convertStars as Any), ("upgradeMsgId", upgradeMsgId as Any), ("upgradeStars", upgradeStars as Any), ("fromId", fromId as Any), ("peer", peer as Any), ("savedId", savedId as Any), ("prepaidUpgradeHash", prepaidUpgradeHash as Any), ("giftMsgId", giftMsgId as Any), ("toId", toId as Any), ("giftNum", giftNum as Any)])
case .messageActionStarGiftPurchaseOffer(let flags, let gift, let price, let expiresAt):
return ("messageActionStarGiftPurchaseOffer", [("flags", flags as Any), ("gift", gift as Any), ("price", price as Any), ("expiresAt", expiresAt as Any)])
case .messageActionStarGiftPurchaseOfferDeclined(let flags, let gift, let price):
return ("messageActionStarGiftPurchaseOfferDeclined", [("flags", flags as Any), ("gift", gift as Any), ("price", price as Any)])
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars, let fromId, let peer, let savedId, let resaleAmount, let canTransferAt, let canResellAt, let dropOriginalDetailsStars):
return ("messageActionStarGiftUnique", [("flags", flags as Any), ("gift", gift as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any), ("fromId", fromId as Any), ("peer", peer as Any), ("savedId", savedId as Any), ("resaleAmount", resaleAmount as Any), ("canTransferAt", canTransferAt as Any), ("canResellAt", canResellAt as Any), ("dropOriginalDetailsStars", dropOriginalDetailsStars as Any)])
case .messageActionSuggestBirthday(let birthday):
@ -2454,6 +2478,8 @@ public extension Api {
if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _13: Int32?
if Int(_1!) & Int(1 << 19) != 0 {_13 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
@ -2466,8 +2492,54 @@ public extension Api {
let _c10 = (Int(_1!) & Int(1 << 14) == 0) || _10 != nil
let _c11 = (Int(_1!) & Int(1 << 15) == 0) || _11 != nil
let _c12 = (Int(_1!) & Int(1 << 18) == 0) || _12 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 {
return Api.MessageAction.messageActionStarGift(flags: _1!, gift: _2!, message: _3, convertStars: _4, upgradeMsgId: _5, upgradeStars: _6, fromId: _7, peer: _8, savedId: _9, prepaidUpgradeHash: _10, giftMsgId: _11, toId: _12)
let _c13 = (Int(_1!) & Int(1 << 19) == 0) || _13 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 {
return Api.MessageAction.messageActionStarGift(flags: _1!, gift: _2!, message: _3, convertStars: _4, upgradeMsgId: _5, upgradeStars: _6, fromId: _7, peer: _8, savedId: _9, prepaidUpgradeHash: _10, giftMsgId: _11, toId: _12, giftNum: _13)
}
else {
return nil
}
}
public static func parse_messageActionStarGiftPurchaseOffer(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.StarGift?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarGift
}
var _3: Api.StarsAmount?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.MessageAction.messageActionStarGiftPurchaseOffer(flags: _1!, gift: _2!, price: _3!, expiresAt: _4!)
}
else {
return nil
}
}
public static func parse_messageActionStarGiftPurchaseOfferDeclined(_ reader: BufferReader) -> MessageAction? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.StarGift?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarGift
}
var _3: Api.StarsAmount?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.MessageAction.messageActionStarGiftPurchaseOfferDeclined(flags: _1!, gift: _2!, price: _3!)
}
else {
return nil

View file

@ -396,6 +396,62 @@ public extension Api {
}
}
public extension Api {
enum Passkey: TypeConstructorDescription {
case passkey(flags: Int32, id: String, name: String, date: Int32, softwareEmojiId: Int64?, lastUsageDate: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .passkey(let flags, let id, let name, let date, let softwareEmojiId, let lastUsageDate):
if boxed {
buffer.appendInt32(-1738457409)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
serializeString(name, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(softwareEmojiId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(lastUsageDate!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .passkey(let flags, let id, let name, let date, let softwareEmojiId, let lastUsageDate):
return ("passkey", [("flags", flags as Any), ("id", id as Any), ("name", name as Any), ("date", date as Any), ("softwareEmojiId", softwareEmojiId as Any), ("lastUsageDate", lastUsageDate as Any)])
}
}
public static func parse_passkey(_ reader: BufferReader) -> Passkey? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: Int32?
_4 = reader.readInt32()
var _5: Int64?
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() }
var _6: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_6 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.Passkey.passkey(flags: _1!, id: _2!, name: _3!, date: _4!, softwareEmojiId: _5, lastUsageDate: _6)
}
else {
return nil
}
}
}
}
public extension Api {
enum PasswordKdfAlgo: TypeConstructorDescription {
case passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow(salt1: Buffer, salt2: Buffer, g: Int32, p: Buffer)

View file

@ -626,13 +626,13 @@ public extension Api {
}
public extension Api {
enum SavedStarGift: TypeConstructorDescription {
case savedStarGift(flags: Int32, fromId: Api.Peer?, date: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, msgId: Int32?, savedId: Int64?, convertStars: Int64?, upgradeStars: Int64?, canExportAt: Int32?, transferStars: Int64?, canTransferAt: Int32?, canResellAt: Int32?, collectionId: [Int32]?, prepaidUpgradeHash: String?, dropOriginalDetailsStars: Int64?)
case savedStarGift(flags: Int32, fromId: Api.Peer?, date: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, msgId: Int32?, savedId: Int64?, convertStars: Int64?, upgradeStars: Int64?, canExportAt: Int32?, transferStars: Int64?, canTransferAt: Int32?, canResellAt: Int32?, collectionId: [Int32]?, prepaidUpgradeHash: String?, dropOriginalDetailsStars: Int64?, giftNum: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedStarGift(let flags, let fromId, let date, let gift, let message, let msgId, let savedId, let convertStars, let upgradeStars, let canExportAt, let transferStars, let canTransferAt, let canResellAt, let collectionId, let prepaidUpgradeHash, let dropOriginalDetailsStars):
case .savedStarGift(let flags, let fromId, let date, let gift, let message, let msgId, let savedId, let convertStars, let upgradeStars, let canExportAt, let transferStars, let canTransferAt, let canResellAt, let collectionId, let prepaidUpgradeHash, let dropOriginalDetailsStars, let giftNum):
if boxed {
buffer.appendInt32(-1987861422)
buffer.appendInt32(-355041186)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {fromId!.serialize(buffer, true)}
@ -654,14 +654,15 @@ public extension Api {
}}
if Int(flags) & Int(1 << 16) != 0 {serializeString(prepaidUpgradeHash!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 18) != 0 {serializeInt64(dropOriginalDetailsStars!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 19) != 0 {serializeInt32(giftNum!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedStarGift(let flags, let fromId, let date, let gift, let message, let msgId, let savedId, let convertStars, let upgradeStars, let canExportAt, let transferStars, let canTransferAt, let canResellAt, let collectionId, let prepaidUpgradeHash, let dropOriginalDetailsStars):
return ("savedStarGift", [("flags", flags as Any), ("fromId", fromId as Any), ("date", date as Any), ("gift", gift as Any), ("message", message as Any), ("msgId", msgId as Any), ("savedId", savedId as Any), ("convertStars", convertStars as Any), ("upgradeStars", upgradeStars as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any), ("canTransferAt", canTransferAt as Any), ("canResellAt", canResellAt as Any), ("collectionId", collectionId as Any), ("prepaidUpgradeHash", prepaidUpgradeHash as Any), ("dropOriginalDetailsStars", dropOriginalDetailsStars as Any)])
case .savedStarGift(let flags, let fromId, let date, let gift, let message, let msgId, let savedId, let convertStars, let upgradeStars, let canExportAt, let transferStars, let canTransferAt, let canResellAt, let collectionId, let prepaidUpgradeHash, let dropOriginalDetailsStars, let giftNum):
return ("savedStarGift", [("flags", flags as Any), ("fromId", fromId as Any), ("date", date as Any), ("gift", gift as Any), ("message", message as Any), ("msgId", msgId as Any), ("savedId", savedId as Any), ("convertStars", convertStars as Any), ("upgradeStars", upgradeStars as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any), ("canTransferAt", canTransferAt as Any), ("canResellAt", canResellAt as Any), ("collectionId", collectionId as Any), ("prepaidUpgradeHash", prepaidUpgradeHash as Any), ("dropOriginalDetailsStars", dropOriginalDetailsStars as Any), ("giftNum", giftNum as Any)])
}
}
@ -706,6 +707,8 @@ public extension Api {
if Int(_1!) & Int(1 << 16) != 0 {_15 = parseString(reader) }
var _16: Int64?
if Int(_1!) & Int(1 << 18) != 0 {_16 = reader.readInt64() }
var _17: Int32?
if Int(_1!) & Int(1 << 19) != 0 {_17 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 1) == 0) || _2 != nil
let _c3 = _3 != nil
@ -722,8 +725,9 @@ public extension Api {
let _c14 = (Int(_1!) & Int(1 << 15) == 0) || _14 != nil
let _c15 = (Int(_1!) & Int(1 << 16) == 0) || _15 != nil
let _c16 = (Int(_1!) & Int(1 << 18) == 0) || _16 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 {
return Api.SavedStarGift.savedStarGift(flags: _1!, fromId: _2, date: _3!, gift: _4!, message: _5, msgId: _6, savedId: _7, convertStars: _8, upgradeStars: _9, canExportAt: _10, transferStars: _11, canTransferAt: _12, canResellAt: _13, collectionId: _14, prepaidUpgradeHash: _15, dropOriginalDetailsStars: _16)
let _c17 = (Int(_1!) & Int(1 << 19) == 0) || _17 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
return Api.SavedStarGift.savedStarGift(flags: _1!, fromId: _2, date: _3!, gift: _4!, message: _5, msgId: _6, savedId: _7, convertStars: _8, upgradeStars: _9, canExportAt: _10, transferStars: _11, canTransferAt: _12, canResellAt: _13, collectionId: _14, prepaidUpgradeHash: _15, dropOriginalDetailsStars: _16, giftNum: _17)
}
else {
return nil

View file

@ -288,14 +288,14 @@ public extension Api {
}
public extension Api {
enum StarGift: TypeConstructorDescription {
case starGift(flags: Int32, id: Int64, sticker: Api.Document, stars: Int64, availabilityRemains: Int32?, availabilityTotal: Int32?, availabilityResale: Int64?, convertStars: Int64, firstSaleDate: Int32?, lastSaleDate: Int32?, upgradeStars: Int64?, resellMinStars: Int64?, title: String?, releasedBy: Api.Peer?, perUserTotal: Int32?, perUserRemains: Int32?, lockedUntilDate: Int32?, auctionSlug: String?, giftsPerRound: Int32?)
case starGiftUnique(flags: Int32, id: Int64, giftId: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, ownerAddress: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32, giftAddress: String?, resellAmount: [Api.StarsAmount]?, releasedBy: Api.Peer?, valueAmount: Int64?, valueCurrency: String?, themePeer: Api.Peer?, peerColor: Api.PeerColor?, hostId: Api.Peer?)
case starGift(flags: Int32, id: Int64, sticker: Api.Document, stars: Int64, availabilityRemains: Int32?, availabilityTotal: Int32?, availabilityResale: Int64?, convertStars: Int64, firstSaleDate: Int32?, lastSaleDate: Int32?, upgradeStars: Int64?, resellMinStars: Int64?, title: String?, releasedBy: Api.Peer?, perUserTotal: Int32?, perUserRemains: Int32?, lockedUntilDate: Int32?, auctionSlug: String?, giftsPerRound: Int32?, auctionStartDate: Int32?, upgradeVariants: Int32?, background: Api.StarGiftBackground?)
case starGiftUnique(flags: Int32, id: Int64, giftId: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, ownerAddress: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32, giftAddress: String?, resellAmount: [Api.StarsAmount]?, releasedBy: Api.Peer?, valueAmount: Int64?, valueCurrency: String?, valueUsdAmount: Int64?, themePeer: Api.Peer?, peerColor: Api.PeerColor?, hostId: Api.Peer?, offerMinStars: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let availabilityResale, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars, let resellMinStars, let title, let releasedBy, let perUserTotal, let perUserRemains, let lockedUntilDate, let auctionSlug, let giftsPerRound):
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let availabilityResale, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars, let resellMinStars, let title, let releasedBy, let perUserTotal, let perUserRemains, let lockedUntilDate, let auctionSlug, let giftsPerRound, let auctionStartDate, let upgradeVariants, let background):
if boxed {
buffer.appendInt32(463097215)
buffer.appendInt32(825922887)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(id, buffer: buffer, boxed: false)
@ -316,10 +316,13 @@ public extension Api {
if Int(flags) & Int(1 << 9) != 0 {serializeInt32(lockedUntilDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeString(auctionSlug!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeInt32(giftsPerRound!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 11) != 0 {serializeInt32(auctionStartDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 12) != 0 {serializeInt32(upgradeVariants!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 13) != 0 {background!.serialize(buffer, true)}
break
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor, let hostId):
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let valueUsdAmount, let themePeer, let peerColor, let hostId, let offerMinStars):
if boxed {
buffer.appendInt32(-1329630181)
buffer.appendInt32(1453155529)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(id, buffer: buffer, boxed: false)
@ -346,19 +349,21 @@ public extension Api {
if Int(flags) & Int(1 << 5) != 0 {releasedBy!.serialize(buffer, true)}
if Int(flags) & Int(1 << 8) != 0 {serializeInt64(valueAmount!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 8) != 0 {serializeString(valueCurrency!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 8) != 0 {serializeInt64(valueUsdAmount!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 10) != 0 {themePeer!.serialize(buffer, true)}
if Int(flags) & Int(1 << 11) != 0 {peerColor!.serialize(buffer, true)}
if Int(flags) & Int(1 << 12) != 0 {hostId!.serialize(buffer, true)}
if Int(flags) & Int(1 << 13) != 0 {serializeInt32(offerMinStars!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let availabilityResale, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars, let resellMinStars, let title, let releasedBy, let perUserTotal, let perUserRemains, let lockedUntilDate, let auctionSlug, let giftsPerRound):
return ("starGift", [("flags", flags as Any), ("id", id as Any), ("sticker", sticker as Any), ("stars", stars as Any), ("availabilityRemains", availabilityRemains as Any), ("availabilityTotal", availabilityTotal as Any), ("availabilityResale", availabilityResale as Any), ("convertStars", convertStars as Any), ("firstSaleDate", firstSaleDate as Any), ("lastSaleDate", lastSaleDate as Any), ("upgradeStars", upgradeStars as Any), ("resellMinStars", resellMinStars as Any), ("title", title as Any), ("releasedBy", releasedBy as Any), ("perUserTotal", perUserTotal as Any), ("perUserRemains", perUserRemains as Any), ("lockedUntilDate", lockedUntilDate as Any), ("auctionSlug", auctionSlug as Any), ("giftsPerRound", giftsPerRound as Any)])
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let themePeer, let peerColor, let hostId):
return ("starGiftUnique", [("flags", flags as Any), ("id", id as Any), ("giftId", giftId as Any), ("title", title as Any), ("slug", slug as Any), ("num", num as Any), ("ownerId", ownerId as Any), ("ownerName", ownerName as Any), ("ownerAddress", ownerAddress as Any), ("attributes", attributes as Any), ("availabilityIssued", availabilityIssued as Any), ("availabilityTotal", availabilityTotal as Any), ("giftAddress", giftAddress as Any), ("resellAmount", resellAmount as Any), ("releasedBy", releasedBy as Any), ("valueAmount", valueAmount as Any), ("valueCurrency", valueCurrency as Any), ("themePeer", themePeer as Any), ("peerColor", peerColor as Any), ("hostId", hostId as Any)])
case .starGift(let flags, let id, let sticker, let stars, let availabilityRemains, let availabilityTotal, let availabilityResale, let convertStars, let firstSaleDate, let lastSaleDate, let upgradeStars, let resellMinStars, let title, let releasedBy, let perUserTotal, let perUserRemains, let lockedUntilDate, let auctionSlug, let giftsPerRound, let auctionStartDate, let upgradeVariants, let background):
return ("starGift", [("flags", flags as Any), ("id", id as Any), ("sticker", sticker as Any), ("stars", stars as Any), ("availabilityRemains", availabilityRemains as Any), ("availabilityTotal", availabilityTotal as Any), ("availabilityResale", availabilityResale as Any), ("convertStars", convertStars as Any), ("firstSaleDate", firstSaleDate as Any), ("lastSaleDate", lastSaleDate as Any), ("upgradeStars", upgradeStars as Any), ("resellMinStars", resellMinStars as Any), ("title", title as Any), ("releasedBy", releasedBy as Any), ("perUserTotal", perUserTotal as Any), ("perUserRemains", perUserRemains as Any), ("lockedUntilDate", lockedUntilDate as Any), ("auctionSlug", auctionSlug as Any), ("giftsPerRound", giftsPerRound as Any), ("auctionStartDate", auctionStartDate as Any), ("upgradeVariants", upgradeVariants as Any), ("background", background as Any)])
case .starGiftUnique(let flags, let id, let giftId, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy, let valueAmount, let valueCurrency, let valueUsdAmount, let themePeer, let peerColor, let hostId, let offerMinStars):
return ("starGiftUnique", [("flags", flags as Any), ("id", id as Any), ("giftId", giftId as Any), ("title", title as Any), ("slug", slug as Any), ("num", num as Any), ("ownerId", ownerId as Any), ("ownerName", ownerName as Any), ("ownerAddress", ownerAddress as Any), ("attributes", attributes as Any), ("availabilityIssued", availabilityIssued as Any), ("availabilityTotal", availabilityTotal as Any), ("giftAddress", giftAddress as Any), ("resellAmount", resellAmount as Any), ("releasedBy", releasedBy as Any), ("valueAmount", valueAmount as Any), ("valueCurrency", valueCurrency as Any), ("valueUsdAmount", valueUsdAmount as Any), ("themePeer", themePeer as Any), ("peerColor", peerColor as Any), ("hostId", hostId as Any), ("offerMinStars", offerMinStars as Any)])
}
}
@ -405,6 +410,14 @@ public extension Api {
if Int(_1!) & Int(1 << 11) != 0 {_18 = parseString(reader) }
var _19: Int32?
if Int(_1!) & Int(1 << 11) != 0 {_19 = reader.readInt32() }
var _20: Int32?
if Int(_1!) & Int(1 << 11) != 0 {_20 = reader.readInt32() }
var _21: Int32?
if Int(_1!) & Int(1 << 12) != 0 {_21 = reader.readInt32() }
var _22: Api.StarGiftBackground?
if Int(_1!) & Int(1 << 13) != 0 {if let signature = reader.readInt32() {
_22 = Api.parse(reader, signature: signature) as? Api.StarGiftBackground
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -424,8 +437,11 @@ public extension Api {
let _c17 = (Int(_1!) & Int(1 << 9) == 0) || _17 != nil
let _c18 = (Int(_1!) & Int(1 << 11) == 0) || _18 != nil
let _c19 = (Int(_1!) & Int(1 << 11) == 0) || _19 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 {
return Api.StarGift.starGift(flags: _1!, id: _2!, sticker: _3!, stars: _4!, availabilityRemains: _5, availabilityTotal: _6, availabilityResale: _7, convertStars: _8!, firstSaleDate: _9, lastSaleDate: _10, upgradeStars: _11, resellMinStars: _12, title: _13, releasedBy: _14, perUserTotal: _15, perUserRemains: _16, lockedUntilDate: _17, auctionSlug: _18, giftsPerRound: _19)
let _c20 = (Int(_1!) & Int(1 << 11) == 0) || _20 != nil
let _c21 = (Int(_1!) & Int(1 << 12) == 0) || _21 != nil
let _c22 = (Int(_1!) & Int(1 << 13) == 0) || _22 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 {
return Api.StarGift.starGift(flags: _1!, id: _2!, sticker: _3!, stars: _4!, availabilityRemains: _5, availabilityTotal: _6, availabilityResale: _7, convertStars: _8!, firstSaleDate: _9, lastSaleDate: _10, upgradeStars: _11, resellMinStars: _12, title: _13, releasedBy: _14, perUserTotal: _15, perUserRemains: _16, lockedUntilDate: _17, auctionSlug: _18, giftsPerRound: _19, auctionStartDate: _20, upgradeVariants: _21, background: _22)
}
else {
return nil
@ -474,18 +490,22 @@ public extension Api {
if Int(_1!) & Int(1 << 8) != 0 {_16 = reader.readInt64() }
var _17: String?
if Int(_1!) & Int(1 << 8) != 0 {_17 = parseString(reader) }
var _18: Api.Peer?
var _18: Int64?
if Int(_1!) & Int(1 << 8) != 0 {_18 = reader.readInt64() }
var _19: Api.Peer?
if Int(_1!) & Int(1 << 10) != 0 {if let signature = reader.readInt32() {
_18 = Api.parse(reader, signature: signature) as? Api.Peer
_19 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _19: Api.PeerColor?
var _20: Api.PeerColor?
if Int(_1!) & Int(1 << 11) != 0 {if let signature = reader.readInt32() {
_19 = Api.parse(reader, signature: signature) as? Api.PeerColor
_20 = Api.parse(reader, signature: signature) as? Api.PeerColor
} }
var _20: Api.Peer?
var _21: Api.Peer?
if Int(_1!) & Int(1 << 12) != 0 {if let signature = reader.readInt32() {
_20 = Api.parse(reader, signature: signature) as? Api.Peer
_21 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _22: Int32?
if Int(_1!) & Int(1 << 13) != 0 {_22 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -503,11 +523,13 @@ public extension Api {
let _c15 = (Int(_1!) & Int(1 << 5) == 0) || _15 != nil
let _c16 = (Int(_1!) & Int(1 << 8) == 0) || _16 != nil
let _c17 = (Int(_1!) & Int(1 << 8) == 0) || _17 != nil
let _c18 = (Int(_1!) & Int(1 << 10) == 0) || _18 != nil
let _c19 = (Int(_1!) & Int(1 << 11) == 0) || _19 != nil
let _c20 = (Int(_1!) & Int(1 << 12) == 0) || _20 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 {
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, giftId: _3!, title: _4!, slug: _5!, num: _6!, ownerId: _7, ownerName: _8, ownerAddress: _9, attributes: _10!, availabilityIssued: _11!, availabilityTotal: _12!, giftAddress: _13, resellAmount: _14, releasedBy: _15, valueAmount: _16, valueCurrency: _17, themePeer: _18, peerColor: _19, hostId: _20)
let _c18 = (Int(_1!) & Int(1 << 8) == 0) || _18 != nil
let _c19 = (Int(_1!) & Int(1 << 10) == 0) || _19 != nil
let _c20 = (Int(_1!) & Int(1 << 11) == 0) || _20 != nil
let _c21 = (Int(_1!) & Int(1 << 12) == 0) || _21 != nil
let _c22 = (Int(_1!) & Int(1 << 13) == 0) || _22 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 {
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, giftId: _3!, title: _4!, slug: _5!, num: _6!, ownerId: _7, ownerName: _8, ownerAddress: _9, attributes: _10!, availabilityIssued: _11!, availabilityTotal: _12!, giftAddress: _13, resellAmount: _14, releasedBy: _15, valueAmount: _16, valueCurrency: _17, valueUsdAmount: _18, themePeer: _19, peerColor: _20, hostId: _21, offerMinStars: _22)
}
else {
return nil
@ -848,13 +870,13 @@ public extension Api {
}
public extension Api {
enum StarGiftAuctionAcquiredGift: TypeConstructorDescription {
case starGiftAuctionAcquiredGift(flags: Int32, peer: Api.Peer, date: Int32, bidAmount: Int64, round: Int32, pos: Int32, message: Api.TextWithEntities?)
case starGiftAuctionAcquiredGift(flags: Int32, peer: Api.Peer, date: Int32, bidAmount: Int64, round: Int32, pos: Int32, message: Api.TextWithEntities?, giftNum: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starGiftAuctionAcquiredGift(let flags, let peer, let date, let bidAmount, let round, let pos, let message):
case .starGiftAuctionAcquiredGift(let flags, let peer, let date, let bidAmount, let round, let pos, let message, let giftNum):
if boxed {
buffer.appendInt32(-1419714037)
buffer.appendInt32(1118831432)
}
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
@ -863,14 +885,15 @@ public extension Api {
serializeInt32(round, buffer: buffer, boxed: false)
serializeInt32(pos, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {message!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(giftNum!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starGiftAuctionAcquiredGift(let flags, let peer, let date, let bidAmount, let round, let pos, let message):
return ("starGiftAuctionAcquiredGift", [("flags", flags as Any), ("peer", peer as Any), ("date", date as Any), ("bidAmount", bidAmount as Any), ("round", round as Any), ("pos", pos as Any), ("message", message as Any)])
case .starGiftAuctionAcquiredGift(let flags, let peer, let date, let bidAmount, let round, let pos, let message, let giftNum):
return ("starGiftAuctionAcquiredGift", [("flags", flags as Any), ("peer", peer as Any), ("date", date as Any), ("bidAmount", bidAmount as Any), ("round", round as Any), ("pos", pos as Any), ("message", message as Any), ("giftNum", giftNum as Any)])
}
}
@ -893,6 +916,8 @@ public extension Api {
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.TextWithEntities
} }
var _8: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_8 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -900,8 +925,81 @@ public extension Api {
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.StarGiftAuctionAcquiredGift.starGiftAuctionAcquiredGift(flags: _1!, peer: _2!, date: _3!, bidAmount: _4!, round: _5!, pos: _6!, message: _7)
let _c8 = (Int(_1!) & Int(1 << 2) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.StarGiftAuctionAcquiredGift.starGiftAuctionAcquiredGift(flags: _1!, peer: _2!, date: _3!, bidAmount: _4!, round: _5!, pos: _6!, message: _7, giftNum: _8)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarGiftAuctionRound: TypeConstructorDescription {
case starGiftAuctionRound(num: Int32, duration: Int32)
case starGiftAuctionRoundExtendable(num: Int32, duration: Int32, extendTop: Int32, extendWindow: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starGiftAuctionRound(let num, let duration):
if boxed {
buffer.appendInt32(984483112)
}
serializeInt32(num, buffer: buffer, boxed: false)
serializeInt32(duration, buffer: buffer, boxed: false)
break
case .starGiftAuctionRoundExtendable(let num, let duration, let extendTop, let extendWindow):
if boxed {
buffer.appendInt32(178266597)
}
serializeInt32(num, buffer: buffer, boxed: false)
serializeInt32(duration, buffer: buffer, boxed: false)
serializeInt32(extendTop, buffer: buffer, boxed: false)
serializeInt32(extendWindow, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starGiftAuctionRound(let num, let duration):
return ("starGiftAuctionRound", [("num", num as Any), ("duration", duration as Any)])
case .starGiftAuctionRoundExtendable(let num, let duration, let extendTop, let extendWindow):
return ("starGiftAuctionRoundExtendable", [("num", num as Any), ("duration", duration as Any), ("extendTop", extendTop as Any), ("extendWindow", extendWindow as Any)])
}
}
public static func parse_starGiftAuctionRound(_ reader: BufferReader) -> StarGiftAuctionRound? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.StarGiftAuctionRound.starGiftAuctionRound(num: _1!, duration: _2!)
}
else {
return nil
}
}
public static func parse_starGiftAuctionRoundExtendable(_ reader: BufferReader) -> StarGiftAuctionRound? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.StarGiftAuctionRound.starGiftAuctionRoundExtendable(num: _1!, duration: _2!, extendTop: _3!, extendWindow: _4!)
}
else {
return nil
@ -912,15 +1010,15 @@ public extension Api {
}
public extension Api {
enum StarGiftAuctionState: TypeConstructorDescription {
case starGiftAuctionState(version: Int32, startDate: Int32, endDate: Int32, minBidAmount: Int64, bidLevels: [Api.AuctionBidLevel], topBidders: [Int64], nextRoundAt: Int32, giftsLeft: Int32, currentRound: Int32, totalRounds: Int32)
case starGiftAuctionStateFinished(startDate: Int32, endDate: Int32, averagePrice: Int64)
case starGiftAuctionState(version: Int32, startDate: Int32, endDate: Int32, minBidAmount: Int64, bidLevels: [Api.AuctionBidLevel], topBidders: [Int64], nextRoundAt: Int32, lastGiftNum: Int32, giftsLeft: Int32, currentRound: Int32, totalRounds: Int32, rounds: [Api.StarGiftAuctionRound])
case starGiftAuctionStateFinished(flags: Int32, startDate: Int32, endDate: Int32, averagePrice: Int64, listedCount: Int32?, fragmentListedCount: Int32?, fragmentListedUrl: String?)
case starGiftAuctionStateNotModified
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starGiftAuctionState(let version, let startDate, let endDate, let minBidAmount, let bidLevels, let topBidders, let nextRoundAt, let giftsLeft, let currentRound, let totalRounds):
case .starGiftAuctionState(let version, let startDate, let endDate, let minBidAmount, let bidLevels, let topBidders, let nextRoundAt, let lastGiftNum, let giftsLeft, let currentRound, let totalRounds, let rounds):
if boxed {
buffer.appendInt32(1571835723)
buffer.appendInt32(1998212710)
}
serializeInt32(version, buffer: buffer, boxed: false)
serializeInt32(startDate, buffer: buffer, boxed: false)
@ -937,17 +1035,27 @@ public extension Api {
serializeInt64(item, buffer: buffer, boxed: false)
}
serializeInt32(nextRoundAt, buffer: buffer, boxed: false)
serializeInt32(lastGiftNum, buffer: buffer, boxed: false)
serializeInt32(giftsLeft, buffer: buffer, boxed: false)
serializeInt32(currentRound, buffer: buffer, boxed: false)
serializeInt32(totalRounds, buffer: buffer, boxed: false)
break
case .starGiftAuctionStateFinished(let startDate, let endDate, let averagePrice):
if boxed {
buffer.appendInt32(2107014202)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(rounds.count))
for item in rounds {
item.serialize(buffer, true)
}
break
case .starGiftAuctionStateFinished(let flags, let startDate, let endDate, let averagePrice, let listedCount, let fragmentListedCount, let fragmentListedUrl):
if boxed {
buffer.appendInt32(-1758614593)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(startDate, buffer: buffer, boxed: false)
serializeInt32(endDate, buffer: buffer, boxed: false)
serializeInt64(averagePrice, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(listedCount!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(fragmentListedCount!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(fragmentListedUrl!, buffer: buffer, boxed: false)}
break
case .starGiftAuctionStateNotModified:
if boxed {
@ -960,10 +1068,10 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starGiftAuctionState(let version, let startDate, let endDate, let minBidAmount, let bidLevels, let topBidders, let nextRoundAt, let giftsLeft, let currentRound, let totalRounds):
return ("starGiftAuctionState", [("version", version as Any), ("startDate", startDate as Any), ("endDate", endDate as Any), ("minBidAmount", minBidAmount as Any), ("bidLevels", bidLevels as Any), ("topBidders", topBidders as Any), ("nextRoundAt", nextRoundAt as Any), ("giftsLeft", giftsLeft as Any), ("currentRound", currentRound as Any), ("totalRounds", totalRounds as Any)])
case .starGiftAuctionStateFinished(let startDate, let endDate, let averagePrice):
return ("starGiftAuctionStateFinished", [("startDate", startDate as Any), ("endDate", endDate as Any), ("averagePrice", averagePrice as Any)])
case .starGiftAuctionState(let version, let startDate, let endDate, let minBidAmount, let bidLevels, let topBidders, let nextRoundAt, let lastGiftNum, let giftsLeft, let currentRound, let totalRounds, let rounds):
return ("starGiftAuctionState", [("version", version as Any), ("startDate", startDate as Any), ("endDate", endDate as Any), ("minBidAmount", minBidAmount as Any), ("bidLevels", bidLevels as Any), ("topBidders", topBidders as Any), ("nextRoundAt", nextRoundAt as Any), ("lastGiftNum", lastGiftNum as Any), ("giftsLeft", giftsLeft as Any), ("currentRound", currentRound as Any), ("totalRounds", totalRounds as Any), ("rounds", rounds as Any)])
case .starGiftAuctionStateFinished(let flags, let startDate, let endDate, let averagePrice, let listedCount, let fragmentListedCount, let fragmentListedUrl):
return ("starGiftAuctionStateFinished", [("flags", flags as Any), ("startDate", startDate as Any), ("endDate", endDate as Any), ("averagePrice", averagePrice as Any), ("listedCount", listedCount as Any), ("fragmentListedCount", fragmentListedCount as Any), ("fragmentListedUrl", fragmentListedUrl as Any)])
case .starGiftAuctionStateNotModified:
return ("starGiftAuctionStateNotModified", [])
}
@ -994,6 +1102,12 @@ public extension Api {
_9 = reader.readInt32()
var _10: Int32?
_10 = reader.readInt32()
var _11: Int32?
_11 = reader.readInt32()
var _12: [Api.StarGiftAuctionRound]?
if let _ = reader.readInt32() {
_12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarGiftAuctionRound.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -1004,8 +1118,10 @@ public extension Api {
let _c8 = _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
return Api.StarGiftAuctionState.starGiftAuctionState(version: _1!, startDate: _2!, endDate: _3!, minBidAmount: _4!, bidLevels: _5!, topBidders: _6!, nextRoundAt: _7!, giftsLeft: _8!, currentRound: _9!, totalRounds: _10!)
let _c11 = _11 != nil
let _c12 = _12 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 {
return Api.StarGiftAuctionState.starGiftAuctionState(version: _1!, startDate: _2!, endDate: _3!, minBidAmount: _4!, bidLevels: _5!, topBidders: _6!, nextRoundAt: _7!, lastGiftNum: _8!, giftsLeft: _9!, currentRound: _10!, totalRounds: _11!, rounds: _12!)
}
else {
return nil
@ -1016,13 +1132,25 @@ public extension Api {
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int64?
_3 = reader.readInt64()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int64?
_4 = reader.readInt64()
var _5: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() }
var _6: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_6 = reader.readInt32() }
var _7: String?
if Int(_1!) & Int(1 << 1) != 0 {_7 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.StarGiftAuctionState.starGiftAuctionStateFinished(startDate: _1!, endDate: _2!, averagePrice: _3!)
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.StarGiftAuctionState.starGiftAuctionStateFinished(flags: _1!, startDate: _2!, endDate: _3!, averagePrice: _4!, listedCount: _5, fragmentListedCount: _6, fragmentListedUrl: _7)
}
else {
return nil
@ -1092,6 +1220,50 @@ public extension Api {
}
}
public extension Api {
enum StarGiftBackground: TypeConstructorDescription {
case starGiftBackground(centerColor: Int32, edgeColor: Int32, textColor: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starGiftBackground(let centerColor, let edgeColor, let textColor):
if boxed {
buffer.appendInt32(-1342872680)
}
serializeInt32(centerColor, buffer: buffer, boxed: false)
serializeInt32(edgeColor, buffer: buffer, boxed: false)
serializeInt32(textColor, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starGiftBackground(let centerColor, let edgeColor, let textColor):
return ("starGiftBackground", [("centerColor", centerColor as Any), ("edgeColor", edgeColor as Any), ("textColor", textColor as Any)])
}
}
public static func parse_starGiftBackground(_ reader: BufferReader) -> StarGiftBackground? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.StarGiftBackground.starGiftBackground(centerColor: _1!, edgeColor: _2!, textColor: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarGiftCollection: TypeConstructorDescription {
case starGiftCollection(flags: Int32, collectionId: Int32, title: String, icon: Api.Document?, giftsCount: Int32, hash: Int64)
@ -1470,187 +1642,3 @@ public extension Api {
}
}
public extension Api {
enum StarsRating: TypeConstructorDescription {
case starsRating(flags: Int32, level: Int32, currentLevelStars: Int64, stars: Int64, nextLevelStars: Int64?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsRating(let flags, let level, let currentLevelStars, let stars, let nextLevelStars):
if boxed {
buffer.appendInt32(453922567)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(level, buffer: buffer, boxed: false)
serializeInt64(currentLevelStars, buffer: buffer, boxed: false)
serializeInt64(stars, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(nextLevelStars!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsRating(let flags, let level, let currentLevelStars, let stars, let nextLevelStars):
return ("starsRating", [("flags", flags as Any), ("level", level as Any), ("currentLevelStars", currentLevelStars as Any), ("stars", stars as Any), ("nextLevelStars", nextLevelStars as Any)])
}
}
public static func parse_starsRating(_ reader: BufferReader) -> StarsRating? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int64?
_3 = reader.readInt64()
var _4: Int64?
_4 = reader.readInt64()
var _5: Int64?
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.StarsRating.starsRating(flags: _1!, level: _2!, currentLevelStars: _3!, stars: _4!, nextLevelStars: _5)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsRevenueStatus: TypeConstructorDescription {
case starsRevenueStatus(flags: Int32, currentBalance: Api.StarsAmount, availableBalance: Api.StarsAmount, overallRevenue: Api.StarsAmount, nextWithdrawalAt: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsRevenueStatus(let flags, let currentBalance, let availableBalance, let overallRevenue, let nextWithdrawalAt):
if boxed {
buffer.appendInt32(-21080943)
}
serializeInt32(flags, buffer: buffer, boxed: false)
currentBalance.serialize(buffer, true)
availableBalance.serialize(buffer, true)
overallRevenue.serialize(buffer, true)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(nextWithdrawalAt!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsRevenueStatus(let flags, let currentBalance, let availableBalance, let overallRevenue, let nextWithdrawalAt):
return ("starsRevenueStatus", [("flags", flags as Any), ("currentBalance", currentBalance as Any), ("availableBalance", availableBalance as Any), ("overallRevenue", overallRevenue as Any), ("nextWithdrawalAt", nextWithdrawalAt as Any)])
}
}
public static func parse_starsRevenueStatus(_ reader: BufferReader) -> StarsRevenueStatus? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.StarsAmount?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
var _3: Api.StarsAmount?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
var _4: Api.StarsAmount?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
var _5: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.StarsRevenueStatus.starsRevenueStatus(flags: _1!, currentBalance: _2!, availableBalance: _3!, overallRevenue: _4!, nextWithdrawalAt: _5)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsSubscription: TypeConstructorDescription {
case starsSubscription(flags: Int32, id: String, peer: Api.Peer, untilDate: Int32, pricing: Api.StarsSubscriptionPricing, chatInviteHash: String?, title: String?, photo: Api.WebDocument?, invoiceSlug: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsSubscription(let flags, let id, let peer, let untilDate, let pricing, let chatInviteHash, let title, let photo, let invoiceSlug):
if boxed {
buffer.appendInt32(779004698)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt32(untilDate, buffer: buffer, boxed: false)
pricing.serialize(buffer, true)
if Int(flags) & Int(1 << 3) != 0 {serializeString(chatInviteHash!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 5) != 0 {photo!.serialize(buffer, true)}
if Int(flags) & Int(1 << 6) != 0 {serializeString(invoiceSlug!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsSubscription(let flags, let id, let peer, let untilDate, let pricing, let chatInviteHash, let title, let photo, let invoiceSlug):
return ("starsSubscription", [("flags", flags as Any), ("id", id as Any), ("peer", peer as Any), ("untilDate", untilDate as Any), ("pricing", pricing as Any), ("chatInviteHash", chatInviteHash as Any), ("title", title as Any), ("photo", photo as Any), ("invoiceSlug", invoiceSlug as Any)])
}
}
public static func parse_starsSubscription(_ reader: BufferReader) -> StarsSubscription? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Api.Peer?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _4: Int32?
_4 = reader.readInt32()
var _5: Api.StarsSubscriptionPricing?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
}
var _6: String?
if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) }
var _7: String?
if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) }
var _8: Api.WebDocument?
if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.WebDocument
} }
var _9: String?
if Int(_1!) & Int(1 << 6) != 0 {_9 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.StarsSubscription.starsSubscription(flags: _1!, id: _2!, peer: _3!, untilDate: _4!, pricing: _5!, chatInviteHash: _6, title: _7, photo: _8, invoiceSlug: _9)
}
else {
return nil
}
}
}
}

View file

@ -1,3 +1,187 @@
public extension Api {
enum StarsRating: TypeConstructorDescription {
case starsRating(flags: Int32, level: Int32, currentLevelStars: Int64, stars: Int64, nextLevelStars: Int64?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsRating(let flags, let level, let currentLevelStars, let stars, let nextLevelStars):
if boxed {
buffer.appendInt32(453922567)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(level, buffer: buffer, boxed: false)
serializeInt64(currentLevelStars, buffer: buffer, boxed: false)
serializeInt64(stars, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(nextLevelStars!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsRating(let flags, let level, let currentLevelStars, let stars, let nextLevelStars):
return ("starsRating", [("flags", flags as Any), ("level", level as Any), ("currentLevelStars", currentLevelStars as Any), ("stars", stars as Any), ("nextLevelStars", nextLevelStars as Any)])
}
}
public static func parse_starsRating(_ reader: BufferReader) -> StarsRating? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int64?
_3 = reader.readInt64()
var _4: Int64?
_4 = reader.readInt64()
var _5: Int64?
if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.StarsRating.starsRating(flags: _1!, level: _2!, currentLevelStars: _3!, stars: _4!, nextLevelStars: _5)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsRevenueStatus: TypeConstructorDescription {
case starsRevenueStatus(flags: Int32, currentBalance: Api.StarsAmount, availableBalance: Api.StarsAmount, overallRevenue: Api.StarsAmount, nextWithdrawalAt: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsRevenueStatus(let flags, let currentBalance, let availableBalance, let overallRevenue, let nextWithdrawalAt):
if boxed {
buffer.appendInt32(-21080943)
}
serializeInt32(flags, buffer: buffer, boxed: false)
currentBalance.serialize(buffer, true)
availableBalance.serialize(buffer, true)
overallRevenue.serialize(buffer, true)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(nextWithdrawalAt!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsRevenueStatus(let flags, let currentBalance, let availableBalance, let overallRevenue, let nextWithdrawalAt):
return ("starsRevenueStatus", [("flags", flags as Any), ("currentBalance", currentBalance as Any), ("availableBalance", availableBalance as Any), ("overallRevenue", overallRevenue as Any), ("nextWithdrawalAt", nextWithdrawalAt as Any)])
}
}
public static func parse_starsRevenueStatus(_ reader: BufferReader) -> StarsRevenueStatus? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.StarsAmount?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
var _3: Api.StarsAmount?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
var _4: Api.StarsAmount?
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.StarsAmount
}
var _5: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.StarsRevenueStatus.starsRevenueStatus(flags: _1!, currentBalance: _2!, availableBalance: _3!, overallRevenue: _4!, nextWithdrawalAt: _5)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsSubscription: TypeConstructorDescription {
case starsSubscription(flags: Int32, id: String, peer: Api.Peer, untilDate: Int32, pricing: Api.StarsSubscriptionPricing, chatInviteHash: String?, title: String?, photo: Api.WebDocument?, invoiceSlug: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsSubscription(let flags, let id, let peer, let untilDate, let pricing, let chatInviteHash, let title, let photo, let invoiceSlug):
if boxed {
buffer.appendInt32(779004698)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt32(untilDate, buffer: buffer, boxed: false)
pricing.serialize(buffer, true)
if Int(flags) & Int(1 << 3) != 0 {serializeString(chatInviteHash!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 5) != 0 {photo!.serialize(buffer, true)}
if Int(flags) & Int(1 << 6) != 0 {serializeString(invoiceSlug!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsSubscription(let flags, let id, let peer, let untilDate, let pricing, let chatInviteHash, let title, let photo, let invoiceSlug):
return ("starsSubscription", [("flags", flags as Any), ("id", id as Any), ("peer", peer as Any), ("untilDate", untilDate as Any), ("pricing", pricing as Any), ("chatInviteHash", chatInviteHash as Any), ("title", title as Any), ("photo", photo as Any), ("invoiceSlug", invoiceSlug as Any)])
}
}
public static func parse_starsSubscription(_ reader: BufferReader) -> StarsSubscription? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Api.Peer?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _4: Int32?
_4 = reader.readInt32()
var _5: Api.StarsSubscriptionPricing?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
}
var _6: String?
if Int(_1!) & Int(1 << 3) != 0 {_6 = parseString(reader) }
var _7: String?
if Int(_1!) & Int(1 << 4) != 0 {_7 = parseString(reader) }
var _8: Api.WebDocument?
if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.WebDocument
} }
var _9: String?
if Int(_1!) & Int(1 << 6) != 0 {_9 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 4) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 5) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.StarsSubscription.starsSubscription(flags: _1!, id: _2!, peer: _3!, untilDate: _4!, pricing: _5!, chatInviteHash: _6, title: _7, photo: _8, invoiceSlug: _9)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsSubscriptionPricing: TypeConstructorDescription {
case starsSubscriptionPricing(period: Int32, amount: Int64)
@ -1104,283 +1288,3 @@ public extension Api {
}
}
public extension Api {
enum StoryAlbum: TypeConstructorDescription {
case storyAlbum(flags: Int32, albumId: Int32, title: String, iconPhoto: Api.Photo?, iconVideo: Api.Document?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyAlbum(let flags, let albumId, let title, let iconPhoto, let iconVideo):
if boxed {
buffer.appendInt32(-1826262950)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(albumId, buffer: buffer, boxed: false)
serializeString(title, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {iconPhoto!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {iconVideo!.serialize(buffer, true)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyAlbum(let flags, let albumId, let title, let iconPhoto, let iconVideo):
return ("storyAlbum", [("flags", flags as Any), ("albumId", albumId as Any), ("title", title as Any), ("iconPhoto", iconPhoto as Any), ("iconVideo", iconVideo as Any)])
}
}
public static func parse_storyAlbum(_ reader: BufferReader) -> StoryAlbum? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: String?
_3 = parseString(reader)
var _4: Api.Photo?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Photo
} }
var _5: Api.Document?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.Document
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.StoryAlbum.storyAlbum(flags: _1!, albumId: _2!, title: _3!, iconPhoto: _4, iconVideo: _5)
}
else {
return nil
}
}
}
}
public extension Api {
enum StoryFwdHeader: TypeConstructorDescription {
case storyFwdHeader(flags: Int32, from: Api.Peer?, fromName: String?, storyId: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyFwdHeader(let flags, let from, let fromName, let storyId):
if boxed {
buffer.appendInt32(-1205411504)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {from!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(fromName!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(storyId!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyFwdHeader(let flags, let from, let fromName, let storyId):
return ("storyFwdHeader", [("flags", flags as Any), ("from", from as Any), ("fromName", fromName as Any), ("storyId", storyId as Any)])
}
}
public static func parse_storyFwdHeader(_ reader: BufferReader) -> StoryFwdHeader? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Peer?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _3: String?
if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) }
var _4: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.StoryFwdHeader.storyFwdHeader(flags: _1!, from: _2, fromName: _3, storyId: _4)
}
else {
return nil
}
}
}
}
public extension Api {
indirect enum StoryItem: TypeConstructorDescription {
case storyItem(flags: Int32, id: Int32, date: Int32, fromId: Api.Peer?, fwdFrom: Api.StoryFwdHeader?, expireDate: Int32, caption: String?, entities: [Api.MessageEntity]?, media: Api.MessageMedia, mediaAreas: [Api.MediaArea]?, privacy: [Api.PrivacyRule]?, views: Api.StoryViews?, sentReaction: Api.Reaction?, albums: [Int32]?)
case storyItemDeleted(id: Int32)
case storyItemSkipped(flags: Int32, id: Int32, date: Int32, expireDate: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyItem(let flags, let id, let date, let fromId, let fwdFrom, let expireDate, let caption, let entities, let media, let mediaAreas, let privacy, let views, let sentReaction, let albums):
if boxed {
buffer.appendInt32(-302947087)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 18) != 0 {fromId!.serialize(buffer, true)}
if Int(flags) & Int(1 << 17) != 0 {fwdFrom!.serialize(buffer, true)}
serializeInt32(expireDate, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeString(caption!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
media.serialize(buffer, true)
if Int(flags) & Int(1 << 14) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(mediaAreas!.count))
for item in mediaAreas! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 2) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(privacy!.count))
for item in privacy! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 3) != 0 {views!.serialize(buffer, true)}
if Int(flags) & Int(1 << 15) != 0 {sentReaction!.serialize(buffer, true)}
if Int(flags) & Int(1 << 19) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(albums!.count))
for item in albums! {
serializeInt32(item, buffer: buffer, boxed: false)
}}
break
case .storyItemDeleted(let id):
if boxed {
buffer.appendInt32(1374088783)
}
serializeInt32(id, buffer: buffer, boxed: false)
break
case .storyItemSkipped(let flags, let id, let date, let expireDate):
if boxed {
buffer.appendInt32(-5388013)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeInt32(expireDate, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyItem(let flags, let id, let date, let fromId, let fwdFrom, let expireDate, let caption, let entities, let media, let mediaAreas, let privacy, let views, let sentReaction, let albums):
return ("storyItem", [("flags", flags as Any), ("id", id as Any), ("date", date as Any), ("fromId", fromId as Any), ("fwdFrom", fwdFrom as Any), ("expireDate", expireDate as Any), ("caption", caption as Any), ("entities", entities as Any), ("media", media as Any), ("mediaAreas", mediaAreas as Any), ("privacy", privacy as Any), ("views", views as Any), ("sentReaction", sentReaction as Any), ("albums", albums as Any)])
case .storyItemDeleted(let id):
return ("storyItemDeleted", [("id", id as Any)])
case .storyItemSkipped(let flags, let id, let date, let expireDate):
return ("storyItemSkipped", [("flags", flags as Any), ("id", id as Any), ("date", date as Any), ("expireDate", expireDate as Any)])
}
}
public static func parse_storyItem(_ reader: BufferReader) -> StoryItem? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Api.Peer?
if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _5: Api.StoryFwdHeader?
if Int(_1!) & Int(1 << 17) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StoryFwdHeader
} }
var _6: Int32?
_6 = reader.readInt32()
var _7: String?
if Int(_1!) & Int(1 << 0) != 0 {_7 = parseString(reader) }
var _8: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
var _9: Api.MessageMedia?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.MessageMedia
}
var _10: [Api.MediaArea]?
if Int(_1!) & Int(1 << 14) != 0 {if let _ = reader.readInt32() {
_10 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MediaArea.self)
} }
var _11: [Api.PrivacyRule]?
if Int(_1!) & Int(1 << 2) != 0 {if let _ = reader.readInt32() {
_11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PrivacyRule.self)
} }
var _12: Api.StoryViews?
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StoryViews
} }
var _13: Api.Reaction?
if Int(_1!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.Reaction
} }
var _14: [Int32]?
if Int(_1!) & Int(1 << 19) != 0 {if let _ = reader.readInt32() {
_14 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 18) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 17) == 0) || _5 != nil
let _c6 = _6 != nil
let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 1) == 0) || _8 != nil
let _c9 = _9 != nil
let _c10 = (Int(_1!) & Int(1 << 14) == 0) || _10 != nil
let _c11 = (Int(_1!) & Int(1 << 2) == 0) || _11 != nil
let _c12 = (Int(_1!) & Int(1 << 3) == 0) || _12 != nil
let _c13 = (Int(_1!) & Int(1 << 15) == 0) || _13 != nil
let _c14 = (Int(_1!) & Int(1 << 19) == 0) || _14 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 {
return Api.StoryItem.storyItem(flags: _1!, id: _2!, date: _3!, fromId: _4, fwdFrom: _5, expireDate: _6!, caption: _7, entities: _8, media: _9!, mediaAreas: _10, privacy: _11, views: _12, sentReaction: _13, albums: _14)
}
else {
return nil
}
}
public static func parse_storyItemDeleted(_ reader: BufferReader) -> StoryItem? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.StoryItem.storyItemDeleted(id: _1!)
}
else {
return nil
}
}
public static func parse_storyItemSkipped(_ reader: BufferReader) -> StoryItem? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.StoryItem.storyItemSkipped(flags: _1!, id: _2!, date: _3!, expireDate: _4!)
}
else {
return nil
}
}
}
}

View file

@ -1,3 +1,283 @@
public extension Api {
enum StoryAlbum: TypeConstructorDescription {
case storyAlbum(flags: Int32, albumId: Int32, title: String, iconPhoto: Api.Photo?, iconVideo: Api.Document?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyAlbum(let flags, let albumId, let title, let iconPhoto, let iconVideo):
if boxed {
buffer.appendInt32(-1826262950)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(albumId, buffer: buffer, boxed: false)
serializeString(title, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {iconPhoto!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {iconVideo!.serialize(buffer, true)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyAlbum(let flags, let albumId, let title, let iconPhoto, let iconVideo):
return ("storyAlbum", [("flags", flags as Any), ("albumId", albumId as Any), ("title", title as Any), ("iconPhoto", iconPhoto as Any), ("iconVideo", iconVideo as Any)])
}
}
public static func parse_storyAlbum(_ reader: BufferReader) -> StoryAlbum? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: String?
_3 = parseString(reader)
var _4: Api.Photo?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Photo
} }
var _5: Api.Document?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.Document
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.StoryAlbum.storyAlbum(flags: _1!, albumId: _2!, title: _3!, iconPhoto: _4, iconVideo: _5)
}
else {
return nil
}
}
}
}
public extension Api {
enum StoryFwdHeader: TypeConstructorDescription {
case storyFwdHeader(flags: Int32, from: Api.Peer?, fromName: String?, storyId: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyFwdHeader(let flags, let from, let fromName, let storyId):
if boxed {
buffer.appendInt32(-1205411504)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {from!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(fromName!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(storyId!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyFwdHeader(let flags, let from, let fromName, let storyId):
return ("storyFwdHeader", [("flags", flags as Any), ("from", from as Any), ("fromName", fromName as Any), ("storyId", storyId as Any)])
}
}
public static func parse_storyFwdHeader(_ reader: BufferReader) -> StoryFwdHeader? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Peer?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _3: String?
if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) }
var _4: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.StoryFwdHeader.storyFwdHeader(flags: _1!, from: _2, fromName: _3, storyId: _4)
}
else {
return nil
}
}
}
}
public extension Api {
indirect enum StoryItem: TypeConstructorDescription {
case storyItem(flags: Int32, id: Int32, date: Int32, fromId: Api.Peer?, fwdFrom: Api.StoryFwdHeader?, expireDate: Int32, caption: String?, entities: [Api.MessageEntity]?, media: Api.MessageMedia, mediaAreas: [Api.MediaArea]?, privacy: [Api.PrivacyRule]?, views: Api.StoryViews?, sentReaction: Api.Reaction?, albums: [Int32]?)
case storyItemDeleted(id: Int32)
case storyItemSkipped(flags: Int32, id: Int32, date: Int32, expireDate: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyItem(let flags, let id, let date, let fromId, let fwdFrom, let expireDate, let caption, let entities, let media, let mediaAreas, let privacy, let views, let sentReaction, let albums):
if boxed {
buffer.appendInt32(-302947087)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 18) != 0 {fromId!.serialize(buffer, true)}
if Int(flags) & Int(1 << 17) != 0 {fwdFrom!.serialize(buffer, true)}
serializeInt32(expireDate, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeString(caption!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
media.serialize(buffer, true)
if Int(flags) & Int(1 << 14) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(mediaAreas!.count))
for item in mediaAreas! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 2) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(privacy!.count))
for item in privacy! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 3) != 0 {views!.serialize(buffer, true)}
if Int(flags) & Int(1 << 15) != 0 {sentReaction!.serialize(buffer, true)}
if Int(flags) & Int(1 << 19) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(albums!.count))
for item in albums! {
serializeInt32(item, buffer: buffer, boxed: false)
}}
break
case .storyItemDeleted(let id):
if boxed {
buffer.appendInt32(1374088783)
}
serializeInt32(id, buffer: buffer, boxed: false)
break
case .storyItemSkipped(let flags, let id, let date, let expireDate):
if boxed {
buffer.appendInt32(-5388013)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeInt32(expireDate, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyItem(let flags, let id, let date, let fromId, let fwdFrom, let expireDate, let caption, let entities, let media, let mediaAreas, let privacy, let views, let sentReaction, let albums):
return ("storyItem", [("flags", flags as Any), ("id", id as Any), ("date", date as Any), ("fromId", fromId as Any), ("fwdFrom", fwdFrom as Any), ("expireDate", expireDate as Any), ("caption", caption as Any), ("entities", entities as Any), ("media", media as Any), ("mediaAreas", mediaAreas as Any), ("privacy", privacy as Any), ("views", views as Any), ("sentReaction", sentReaction as Any), ("albums", albums as Any)])
case .storyItemDeleted(let id):
return ("storyItemDeleted", [("id", id as Any)])
case .storyItemSkipped(let flags, let id, let date, let expireDate):
return ("storyItemSkipped", [("flags", flags as Any), ("id", id as Any), ("date", date as Any), ("expireDate", expireDate as Any)])
}
}
public static func parse_storyItem(_ reader: BufferReader) -> StoryItem? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Api.Peer?
if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.Peer
} }
var _5: Api.StoryFwdHeader?
if Int(_1!) & Int(1 << 17) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StoryFwdHeader
} }
var _6: Int32?
_6 = reader.readInt32()
var _7: String?
if Int(_1!) & Int(1 << 0) != 0 {_7 = parseString(reader) }
var _8: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
var _9: Api.MessageMedia?
if let signature = reader.readInt32() {
_9 = Api.parse(reader, signature: signature) as? Api.MessageMedia
}
var _10: [Api.MediaArea]?
if Int(_1!) & Int(1 << 14) != 0 {if let _ = reader.readInt32() {
_10 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MediaArea.self)
} }
var _11: [Api.PrivacyRule]?
if Int(_1!) & Int(1 << 2) != 0 {if let _ = reader.readInt32() {
_11 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PrivacyRule.self)
} }
var _12: Api.StoryViews?
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
_12 = Api.parse(reader, signature: signature) as? Api.StoryViews
} }
var _13: Api.Reaction?
if Int(_1!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() {
_13 = Api.parse(reader, signature: signature) as? Api.Reaction
} }
var _14: [Int32]?
if Int(_1!) & Int(1 << 19) != 0 {if let _ = reader.readInt32() {
_14 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 18) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 17) == 0) || _5 != nil
let _c6 = _6 != nil
let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 1) == 0) || _8 != nil
let _c9 = _9 != nil
let _c10 = (Int(_1!) & Int(1 << 14) == 0) || _10 != nil
let _c11 = (Int(_1!) & Int(1 << 2) == 0) || _11 != nil
let _c12 = (Int(_1!) & Int(1 << 3) == 0) || _12 != nil
let _c13 = (Int(_1!) & Int(1 << 15) == 0) || _13 != nil
let _c14 = (Int(_1!) & Int(1 << 19) == 0) || _14 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 {
return Api.StoryItem.storyItem(flags: _1!, id: _2!, date: _3!, fromId: _4, fwdFrom: _5, expireDate: _6!, caption: _7, entities: _8, media: _9!, mediaAreas: _10, privacy: _11, views: _12, sentReaction: _13, albums: _14)
}
else {
return nil
}
}
public static func parse_storyItemDeleted(_ reader: BufferReader) -> StoryItem? {
var _1: Int32?
_1 = reader.readInt32()
let _c1 = _1 != nil
if _c1 {
return Api.StoryItem.storyItemDeleted(id: _1!)
}
else {
return nil
}
}
public static func parse_storyItemSkipped(_ reader: BufferReader) -> StoryItem? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.StoryItem.storyItemSkipped(flags: _1!, id: _2!, date: _3!, expireDate: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
indirect enum StoryReaction: TypeConstructorDescription {
case storyReaction(peerId: Api.Peer, date: Int32, reaction: Api.Reaction)

View file

@ -1,6 +1,6 @@
public extension Api {
indirect enum WebPageAttribute: TypeConstructorDescription {
case webPageAttributeStarGiftAuction(gift: Api.StarGift, endDate: Int32, centerColor: Int32, edgeColor: Int32, textColor: Int32)
case webPageAttributeStarGiftAuction(gift: Api.StarGift, endDate: Int32)
case webPageAttributeStarGiftCollection(icons: [Api.Document])
case webPageAttributeStickerSet(flags: Int32, stickers: [Api.Document])
case webPageAttributeStory(flags: Int32, peer: Api.Peer, id: Int32, story: Api.StoryItem?)
@ -9,15 +9,12 @@ public extension Api {
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .webPageAttributeStarGiftAuction(let gift, let endDate, let centerColor, let edgeColor, let textColor):
case .webPageAttributeStarGiftAuction(let gift, let endDate):
if boxed {
buffer.appendInt32(55150251)
buffer.appendInt32(29770178)
}
gift.serialize(buffer, true)
serializeInt32(endDate, buffer: buffer, boxed: false)
serializeInt32(centerColor, buffer: buffer, boxed: false)
serializeInt32(edgeColor, buffer: buffer, boxed: false)
serializeInt32(textColor, buffer: buffer, boxed: false)
break
case .webPageAttributeStarGiftCollection(let icons):
if boxed {
@ -72,8 +69,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .webPageAttributeStarGiftAuction(let gift, let endDate, let centerColor, let edgeColor, let textColor):
return ("webPageAttributeStarGiftAuction", [("gift", gift as Any), ("endDate", endDate as Any), ("centerColor", centerColor as Any), ("edgeColor", edgeColor as Any), ("textColor", textColor as Any)])
case .webPageAttributeStarGiftAuction(let gift, let endDate):
return ("webPageAttributeStarGiftAuction", [("gift", gift as Any), ("endDate", endDate as Any)])
case .webPageAttributeStarGiftCollection(let icons):
return ("webPageAttributeStarGiftCollection", [("icons", icons as Any)])
case .webPageAttributeStickerSet(let flags, let stickers):
@ -94,19 +91,10 @@ public extension Api {
}
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
_5 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.WebPageAttribute.webPageAttributeStarGiftAuction(gift: _1!, endDate: _2!, centerColor: _3!, edgeColor: _4!, textColor: _5!)
if _c1 && _c2 {
return Api.WebPageAttribute.webPageAttributeStarGiftAuction(gift: _1!, endDate: _2!)
}
else {
return nil
@ -936,6 +924,86 @@ public extension Api.account {
}
}
public extension Api.account {
enum PasskeyRegistrationOptions: TypeConstructorDescription {
case passkeyRegistrationOptions(options: Api.DataJSON)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .passkeyRegistrationOptions(let options):
if boxed {
buffer.appendInt32(-513057567)
}
options.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .passkeyRegistrationOptions(let options):
return ("passkeyRegistrationOptions", [("options", options as Any)])
}
}
public static func parse_passkeyRegistrationOptions(_ reader: BufferReader) -> PasskeyRegistrationOptions? {
var _1: Api.DataJSON?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
if _c1 {
return Api.account.PasskeyRegistrationOptions.passkeyRegistrationOptions(options: _1!)
}
else {
return nil
}
}
}
}
public extension Api.account {
enum Passkeys: TypeConstructorDescription {
case passkeys(passkeys: [Api.Passkey])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .passkeys(let passkeys):
if boxed {
buffer.appendInt32(-119494116)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(passkeys.count))
for item in passkeys {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .passkeys(let passkeys):
return ("passkeys", [("passkeys", passkeys as Any)])
}
}
public static func parse_passkeys(_ reader: BufferReader) -> Passkeys? {
var _1: [Api.Passkey]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Passkey.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.account.Passkeys.passkeys(passkeys: _1!)
}
else {
return nil
}
}
}
}
public extension Api.account {
enum Password: TypeConstructorDescription {
case password(flags: Int32, currentAlgo: Api.PasswordKdfAlgo?, srpB: Buffer?, srpId: Int64?, hint: String?, emailUnconfirmedPattern: String?, newAlgo: Api.PasswordKdfAlgo, newSecureAlgo: Api.SecurePasswordKdfAlgo, secureRandom: Buffer, pendingResetDate: Int32?, loginEmailPattern: String?)
@ -1330,57 +1398,3 @@ public extension Api.account {
}
}
public extension Api.account {
enum SavedMusicIds: TypeConstructorDescription {
case savedMusicIds(ids: [Int64])
case savedMusicIdsNotModified
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedMusicIds(let ids):
if boxed {
buffer.appendInt32(-1718786506)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(ids.count))
for item in ids {
serializeInt64(item, buffer: buffer, boxed: false)
}
break
case .savedMusicIdsNotModified:
if boxed {
buffer.appendInt32(1338514798)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedMusicIds(let ids):
return ("savedMusicIds", [("ids", ids as Any)])
case .savedMusicIdsNotModified:
return ("savedMusicIdsNotModified", [])
}
}
public static func parse_savedMusicIds(_ reader: BufferReader) -> SavedMusicIds? {
var _1: [Int64]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.account.SavedMusicIds.savedMusicIds(ids: _1!)
}
else {
return nil
}
}
public static func parse_savedMusicIdsNotModified(_ reader: BufferReader) -> SavedMusicIds? {
return Api.account.SavedMusicIds.savedMusicIdsNotModified
}
}
}

View file

@ -1,3 +1,57 @@
public extension Api.account {
enum SavedMusicIds: TypeConstructorDescription {
case savedMusicIds(ids: [Int64])
case savedMusicIdsNotModified
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedMusicIds(let ids):
if boxed {
buffer.appendInt32(-1718786506)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(ids.count))
for item in ids {
serializeInt64(item, buffer: buffer, boxed: false)
}
break
case .savedMusicIdsNotModified:
if boxed {
buffer.appendInt32(1338514798)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedMusicIds(let ids):
return ("savedMusicIds", [("ids", ids as Any)])
case .savedMusicIdsNotModified:
return ("savedMusicIdsNotModified", [])
}
}
public static func parse_savedMusicIds(_ reader: BufferReader) -> SavedMusicIds? {
var _1: [Int64]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.account.SavedMusicIds.savedMusicIds(ids: _1!)
}
else {
return nil
}
}
public static func parse_savedMusicIdsNotModified(_ reader: BufferReader) -> SavedMusicIds? {
return Api.account.SavedMusicIds.savedMusicIdsNotModified
}
}
}
public extension Api.account {
enum SavedRingtone: TypeConstructorDescription {
case savedRingtone
@ -712,6 +766,44 @@ public extension Api.auth {
}
}
public extension Api.auth {
enum PasskeyLoginOptions: TypeConstructorDescription {
case passkeyLoginOptions(options: Api.DataJSON)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .passkeyLoginOptions(let options):
if boxed {
buffer.appendInt32(-503089271)
}
options.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .passkeyLoginOptions(let options):
return ("passkeyLoginOptions", [("options", options as Any)])
}
}
public static func parse_passkeyLoginOptions(_ reader: BufferReader) -> PasskeyLoginOptions? {
var _1: Api.DataJSON?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
if _c1 {
return Api.auth.PasskeyLoginOptions.passkeyLoginOptions(options: _1!)
}
else {
return nil
}
}
}
}
public extension Api.auth {
enum PasswordRecovery: TypeConstructorDescription {
case passwordRecovery(emailPattern: String)

View file

@ -278,14 +278,14 @@ public extension Api.payments {
}
public extension Api.payments {
enum StarGiftActiveAuctions: TypeConstructorDescription {
case starGiftActiveAuctions(auctions: [Api.StarGiftActiveAuctionState], users: [Api.User])
case starGiftActiveAuctions(auctions: [Api.StarGiftActiveAuctionState], users: [Api.User], chats: [Api.Chat])
case starGiftActiveAuctionsNotModified
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starGiftActiveAuctions(let auctions, let users):
case .starGiftActiveAuctions(let auctions, let users, let chats):
if boxed {
buffer.appendInt32(-1745778728)
buffer.appendInt32(-1359565892)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(auctions.count))
@ -297,6 +297,11 @@ public extension Api.payments {
for item in users {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
break
case .starGiftActiveAuctionsNotModified:
if boxed {
@ -309,8 +314,8 @@ public extension Api.payments {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starGiftActiveAuctions(let auctions, let users):
return ("starGiftActiveAuctions", [("auctions", auctions as Any), ("users", users as Any)])
case .starGiftActiveAuctions(let auctions, let users, let chats):
return ("starGiftActiveAuctions", [("auctions", auctions as Any), ("users", users as Any), ("chats", chats as Any)])
case .starGiftActiveAuctionsNotModified:
return ("starGiftActiveAuctionsNotModified", [])
}
@ -325,10 +330,15 @@ public extension Api.payments {
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
var _3: [Api.Chat]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.payments.StarGiftActiveAuctions.starGiftActiveAuctions(auctions: _1!, users: _2!)
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.payments.StarGiftActiveAuctions.starGiftActiveAuctions(auctions: _1!, users: _2!, chats: _3!)
}
else {
return nil
@ -404,13 +414,13 @@ public extension Api.payments {
}
public extension Api.payments {
enum StarGiftAuctionState: TypeConstructorDescription {
case starGiftAuctionState(gift: Api.StarGift, state: Api.StarGiftAuctionState, userState: Api.StarGiftAuctionUserState, timeout: Int32, users: [Api.User])
case starGiftAuctionState(gift: Api.StarGift, state: Api.StarGiftAuctionState, userState: Api.StarGiftAuctionUserState, timeout: Int32, users: [Api.User], chats: [Api.Chat])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starGiftAuctionState(let gift, let state, let userState, let timeout, let users):
case .starGiftAuctionState(let gift, let state, let userState, let timeout, let users, let chats):
if boxed {
buffer.appendInt32(244900980)
buffer.appendInt32(1798960364)
}
gift.serialize(buffer, true)
state.serialize(buffer, true)
@ -421,14 +431,19 @@ public extension Api.payments {
for item in users {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starGiftAuctionState(let gift, let state, let userState, let timeout, let users):
return ("starGiftAuctionState", [("gift", gift as Any), ("state", state as Any), ("userState", userState as Any), ("timeout", timeout as Any), ("users", users as Any)])
case .starGiftAuctionState(let gift, let state, let userState, let timeout, let users, let chats):
return ("starGiftAuctionState", [("gift", gift as Any), ("state", state as Any), ("userState", userState as Any), ("timeout", timeout as Any), ("users", users as Any), ("chats", chats as Any)])
}
}
@ -451,13 +466,18 @@ public extension Api.payments {
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
var _6: [Api.Chat]?
if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.payments.StarGiftAuctionState.starGiftAuctionState(gift: _1!, state: _2!, userState: _3!, timeout: _4!, users: _5!)
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.payments.StarGiftAuctionState.starGiftAuctionState(gift: _1!, state: _2!, userState: _3!, timeout: _4!, users: _5!, chats: _6!)
}
else {
return nil
@ -520,6 +540,48 @@ public extension Api.payments {
}
}
public extension Api.payments {
enum StarGiftUpgradeAttributes: TypeConstructorDescription {
case starGiftUpgradeAttributes(attributes: [Api.StarGiftAttribute])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starGiftUpgradeAttributes(let attributes):
if boxed {
buffer.appendInt32(1187439471)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(attributes.count))
for item in attributes {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starGiftUpgradeAttributes(let attributes):
return ("starGiftUpgradeAttributes", [("attributes", attributes as Any)])
}
}
public static func parse_starGiftUpgradeAttributes(_ reader: BufferReader) -> StarGiftUpgradeAttributes? {
var _1: [Api.StarGiftAttribute]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarGiftAttribute.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.payments.StarGiftUpgradeAttributes.starGiftUpgradeAttributes(attributes: _1!)
}
else {
return nil
}
}
}
}
public extension Api.payments {
enum StarGiftUpgradePreview: TypeConstructorDescription {
case starGiftUpgradePreview(sampleAttributes: [Api.StarGiftAttribute], prices: [Api.StarGiftUpgradePrice], nextPrices: [Api.StarGiftUpgradePrice])
@ -1616,51 +1678,3 @@ public extension Api.phone {
}
}
public extension Api.photos {
enum Photo: TypeConstructorDescription {
case photo(photo: Api.Photo, users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .photo(let photo, let users):
if boxed {
buffer.appendInt32(539045032)
}
photo.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .photo(let photo, let users):
return ("photo", [("photo", photo as Any), ("users", users as Any)])
}
}
public static func parse_photo(_ reader: BufferReader) -> Photo? {
var _1: Api.Photo?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.Photo
}
var _2: [Api.User]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.photos.Photo.photo(photo: _1!, users: _2!)
}
else {
return nil
}
}
}
}

View file

@ -1,3 +1,51 @@
public extension Api.photos {
enum Photo: TypeConstructorDescription {
case photo(photo: Api.Photo, users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .photo(let photo, let users):
if boxed {
buffer.appendInt32(539045032)
}
photo.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .photo(let photo, let users):
return ("photo", [("photo", photo as Any), ("users", users as Any)])
}
}
public static func parse_photo(_ reader: BufferReader) -> Photo? {
var _1: Api.Photo?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.Photo
}
var _2: [Api.User]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.photos.Photo.photo(photo: _1!, users: _2!)
}
else {
return nil
}
}
}
}
public extension Api.photos {
enum Photos: TypeConstructorDescription {
case photos(photos: [Api.Photo], users: [Api.User])
@ -1474,77 +1522,3 @@ public extension Api.stories {
}
}
public extension Api.stories {
enum StoryReactionsList: TypeConstructorDescription {
case storyReactionsList(flags: Int32, count: Int32, reactions: [Api.StoryReaction], chats: [Api.Chat], users: [Api.User], nextOffset: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyReactionsList(let flags, let count, let reactions, let chats, let users, let nextOffset):
if boxed {
buffer.appendInt32(-1436583780)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(reactions.count))
for item in reactions {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyReactionsList(let flags, let count, let reactions, let chats, let users, let nextOffset):
return ("storyReactionsList", [("flags", flags as Any), ("count", count as Any), ("reactions", reactions as Any), ("chats", chats as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)])
}
}
public static func parse_storyReactionsList(_ reader: BufferReader) -> StoryReactionsList? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: [Api.StoryReaction]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryReaction.self)
}
var _4: [Api.Chat]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _5: [Api.User]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
var _6: String?
if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.stories.StoryReactionsList.storyReactionsList(flags: _1!, count: _2!, reactions: _3!, chats: _4!, users: _5!, nextOffset: _6)
}
else {
return nil
}
}
}
}

View file

@ -1,3 +1,77 @@
public extension Api.stories {
enum StoryReactionsList: TypeConstructorDescription {
case storyReactionsList(flags: Int32, count: Int32, reactions: [Api.StoryReaction], chats: [Api.Chat], users: [Api.User], nextOffset: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .storyReactionsList(let flags, let count, let reactions, let chats, let users, let nextOffset):
if boxed {
buffer.appendInt32(-1436583780)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(reactions.count))
for item in reactions {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
for item in chats {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .storyReactionsList(let flags, let count, let reactions, let chats, let users, let nextOffset):
return ("storyReactionsList", [("flags", flags as Any), ("count", count as Any), ("reactions", reactions as Any), ("chats", chats as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)])
}
}
public static func parse_storyReactionsList(_ reader: BufferReader) -> StoryReactionsList? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: [Api.StoryReaction]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryReaction.self)
}
var _4: [Api.Chat]?
if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _5: [Api.User]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
var _6: String?
if Int(_1!) & Int(1 << 0) != 0 {_6 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.stories.StoryReactionsList.storyReactionsList(flags: _1!, count: _2!, reactions: _3!, chats: _4!, users: _5!, nextOffset: _6)
}
else {
return nil
}
}
}
}
public extension Api.stories {
enum StoryViews: TypeConstructorDescription {
case storyViews(views: [Api.StoryViews], users: [Api.User])

View file

@ -232,6 +232,21 @@ public extension Api.functions.account {
})
}
}
public extension Api.functions.account {
static func deletePasskey(id: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(-172665281)
serializeString(id, buffer: buffer, boxed: false)
return (FunctionDescription(name: "account.deletePasskey", parameters: [("id", String(describing: id))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool
}
return result
})
}
}
public extension Api.functions.account {
static func deleteSecureValue(types: [Api.SecureValueType]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
@ -666,6 +681,21 @@ public extension Api.functions.account {
})
}
}
public extension Api.functions.account {
static func getPasskeys() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.account.Passkeys>) {
let buffer = Buffer()
buffer.appendInt32(-367063982)
return (FunctionDescription(name: "account.getPasskeys", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.Passkeys? in
let reader = BufferReader(buffer)
var result: Api.account.Passkeys?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.account.Passkeys
}
return result
})
}
}
public extension Api.functions.account {
static func getPassword() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.account.Password>) {
let buffer = Buffer()
@ -900,6 +930,21 @@ public extension Api.functions.account {
})
}
}
public extension Api.functions.account {
static func initPasskeyRegistration() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.account.PasskeyRegistrationOptions>) {
let buffer = Buffer()
buffer.appendInt32(1117079528)
return (FunctionDescription(name: "account.initPasskeyRegistration", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.account.PasskeyRegistrationOptions? in
let reader = BufferReader(buffer)
var result: Api.account.PasskeyRegistrationOptions?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.account.PasskeyRegistrationOptions
}
return result
})
}
}
public extension Api.functions.account {
static func initTakeoutSession(flags: Int32, fileMaxSize: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.account.Takeout>) {
let buffer = Buffer()
@ -993,6 +1038,21 @@ public extension Api.functions.account {
})
}
}
public extension Api.functions.account {
static func registerPasskey(credential: Api.InputPasskeyCredential) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Passkey>) {
let buffer = Buffer()
buffer.appendInt32(1437867990)
credential.serialize(buffer, true)
return (FunctionDescription(name: "account.registerPasskey", parameters: [("credential", String(describing: credential))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Passkey? in
let reader = BufferReader(buffer)
var result: Api.Passkey?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Passkey
}
return result
})
}
}
public extension Api.functions.account {
static func reorderUsernames(order: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
@ -2075,6 +2135,24 @@ public extension Api.functions.auth {
})
}
}
public extension Api.functions.auth {
static func finishPasskeyLogin(flags: Int32, credential: Api.InputPasskeyCredential, fromDcId: Int32?, fromAuthKeyId: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.auth.Authorization>) {
let buffer = Buffer()
buffer.appendInt32(-1739084537)
serializeInt32(flags, buffer: buffer, boxed: false)
credential.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(fromDcId!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(fromAuthKeyId!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "auth.finishPasskeyLogin", parameters: [("flags", String(describing: flags)), ("credential", String(describing: credential)), ("fromDcId", String(describing: fromDcId)), ("fromAuthKeyId", String(describing: fromAuthKeyId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in
let reader = BufferReader(buffer)
var result: Api.auth.Authorization?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.auth.Authorization
}
return result
})
}
}
public extension Api.functions.auth {
static func importAuthorization(id: Int64, bytes: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.auth.Authorization>) {
let buffer = Buffer()
@ -2141,6 +2219,22 @@ public extension Api.functions.auth {
})
}
}
public extension Api.functions.auth {
static func initPasskeyLogin(apiId: Int32, apiHash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.auth.PasskeyLoginOptions>) {
let buffer = Buffer()
buffer.appendInt32(1368051895)
serializeInt32(apiId, buffer: buffer, boxed: false)
serializeString(apiHash, buffer: buffer, boxed: false)
return (FunctionDescription(name: "auth.initPasskeyLogin", parameters: [("apiId", String(describing: apiId)), ("apiHash", String(describing: apiHash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.PasskeyLoginOptions? in
let reader = BufferReader(buffer)
var result: Api.auth.PasskeyLoginOptions?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.auth.PasskeyLoginOptions
}
return result
})
}
}
public extension Api.functions.auth {
static func logOut() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.auth.LoggedOut>) {
let buffer = Buffer()
@ -5736,9 +5830,9 @@ public extension Api.functions.messages {
}
}
public extension Api.functions.messages {
static func forwardMessages(flags: Int32, fromPeer: Api.InputPeer, id: [Int32], randomId: [Int64], toPeer: Api.InputPeer, topMsgId: Int32?, replyTo: Api.InputReplyTo?, scheduleDate: Int32?, scheduleRepeatPeriod: Int32?, sendAs: Api.InputPeer?, quickReplyShortcut: Api.InputQuickReplyShortcut?, videoTimestamp: Int32?, allowPaidStars: Int64?, suggestedPost: Api.SuggestedPost?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
static func forwardMessages(flags: Int32, fromPeer: Api.InputPeer, id: [Int32], randomId: [Int64], toPeer: Api.InputPeer, topMsgId: Int32?, replyTo: Api.InputReplyTo?, scheduleDate: Int32?, scheduleRepeatPeriod: Int32?, sendAs: Api.InputPeer?, quickReplyShortcut: Api.InputQuickReplyShortcut?, effect: Int64?, videoTimestamp: Int32?, allowPaidStars: Int64?, suggestedPost: Api.SuggestedPost?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(1104419550)
buffer.appendInt32(326126204)
serializeInt32(flags, buffer: buffer, boxed: false)
fromPeer.serialize(buffer, true)
buffer.appendInt32(481674261)
@ -5758,10 +5852,11 @@ public extension Api.functions.messages {
if Int(flags) & Int(1 << 24) != 0 {serializeInt32(scheduleRepeatPeriod!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 13) != 0 {sendAs!.serialize(buffer, true)}
if Int(flags) & Int(1 << 17) != 0 {quickReplyShortcut!.serialize(buffer, true)}
if Int(flags) & Int(1 << 18) != 0 {serializeInt64(effect!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 20) != 0 {serializeInt32(videoTimestamp!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 21) != 0 {serializeInt64(allowPaidStars!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 23) != 0 {suggestedPost!.serialize(buffer, true)}
return (FunctionDescription(name: "messages.forwardMessages", parameters: [("flags", String(describing: flags)), ("fromPeer", String(describing: fromPeer)), ("id", String(describing: id)), ("randomId", String(describing: randomId)), ("toPeer", String(describing: toPeer)), ("topMsgId", String(describing: topMsgId)), ("replyTo", String(describing: replyTo)), ("scheduleDate", String(describing: scheduleDate)), ("scheduleRepeatPeriod", String(describing: scheduleRepeatPeriod)), ("sendAs", String(describing: sendAs)), ("quickReplyShortcut", String(describing: quickReplyShortcut)), ("videoTimestamp", String(describing: videoTimestamp)), ("allowPaidStars", String(describing: allowPaidStars)), ("suggestedPost", String(describing: suggestedPost))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
return (FunctionDescription(name: "messages.forwardMessages", parameters: [("flags", String(describing: flags)), ("fromPeer", String(describing: fromPeer)), ("id", String(describing: id)), ("randomId", String(describing: randomId)), ("toPeer", String(describing: toPeer)), ("topMsgId", String(describing: topMsgId)), ("replyTo", String(describing: replyTo)), ("scheduleDate", String(describing: scheduleDate)), ("scheduleRepeatPeriod", String(describing: scheduleRepeatPeriod)), ("sendAs", String(describing: sendAs)), ("quickReplyShortcut", String(describing: quickReplyShortcut)), ("effect", String(describing: effect)), ("videoTimestamp", String(describing: videoTimestamp)), ("allowPaidStars", String(describing: allowPaidStars)), ("suggestedPost", String(describing: suggestedPost))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
@ -9816,6 +9911,21 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func getStarGiftUpgradeAttributes(giftId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarGiftUpgradeAttributes>) {
let buffer = Buffer()
buffer.appendInt32(1828948824)
serializeInt64(giftId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.getStarGiftUpgradeAttributes", parameters: [("giftId", String(describing: giftId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarGiftUpgradeAttributes? in
let reader = BufferReader(buffer)
var result: Api.payments.StarGiftUpgradeAttributes?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.StarGiftUpgradeAttributes
}
return result
})
}
}
public extension Api.functions.payments {
static func getStarGiftUpgradePreview(giftId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarGiftUpgradePreview>) {
let buffer = Buffer()
@ -10131,6 +10241,22 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func resolveStarGiftOffer(flags: Int32, offerMsgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-372344804)
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(offerMsgId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.resolveStarGiftOffer", parameters: [("flags", String(describing: flags)), ("offerMsgId", String(describing: offerMsgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
}
public extension Api.functions.payments {
static func saveStarGift(flags: Int32, stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
@ -10168,6 +10294,27 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func sendStarGiftOffer(flags: Int32, peer: Api.InputPeer, slug: String, price: Api.StarsAmount, duration: Int32, randomId: Int64, allowPaidStars: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-1883739327)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeString(slug, buffer: buffer, boxed: false)
price.serialize(buffer, true)
serializeInt32(duration, buffer: buffer, boxed: false)
serializeInt64(randomId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(allowPaidStars!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "payments.sendStarGiftOffer", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("slug", String(describing: slug)), ("price", String(describing: price)), ("duration", String(describing: duration)), ("randomId", String(describing: randomId)), ("allowPaidStars", String(describing: allowPaidStars))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
}
public extension Api.functions.payments {
static func sendStarsForm(formId: Int64, invoice: Api.InputInvoice) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.PaymentResult>) {
let buffer = Buffer()

View file

@ -103,8 +103,9 @@ final class GiftAuctionAccessoryPanel: ASDisplayNode {
}
}
let titleText: String = self.strings.ChatList_Auctions_ActiveAuction(Int32(self.states.count))
titleItems.append(AnyComponentWithIdentity(id: "label", component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: titleText, font: titleFont, textColor: self.theme.rootController.navigationBar.primaryTextColor))))))
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
var titleText: String = self.strings.ChatList_Auctions_ActiveAuction(Int32(self.states.count))
let subtitleText: String
var subtitleTextColor = self.theme.rootController.navigationBar.secondaryTextColor
@ -113,8 +114,21 @@ final class GiftAuctionAccessoryPanel: ASDisplayNode {
var buttonAnimatedTitleItems: [AnimatedTextComponent.Item] = []
if self.states.count == 1, let auctionState = self.states.first {
var isUpcoming = false
var startTime = currentTime
var endTime = currentTime
if case let .ongoing(_, startDate, _, _, _, _, nextRoundDate, _, _, _, _, _) = auctionState.auctionState {
startTime = startDate
endTime = nextRoundDate
if currentTime < startDate {
isUpcoming = true
}
}
let place = auctionState.place ?? 1
if case let .generic(gift) = auctionState.gift, let auctionGiftsPerRound = gift.auctionGiftsPerRound, place > auctionGiftsPerRound {
if isUpcoming {
subtitleText = self.strings.ChatList_Auctions_Status_UpcomingBid
} else if case let .generic(gift) = auctionState.gift, let auctionGiftsPerRound = gift.auctionGiftsPerRound, place > auctionGiftsPerRound {
subtitleText = self.strings.ChatList_Auctions_Status_Single_Outbid
subtitleTextColor = self.theme.list.itemDestructiveColor
isOutbid = true
@ -134,14 +148,14 @@ final class GiftAuctionAccessoryPanel: ASDisplayNode {
subtitleText = self.strings.ChatList_Auctions_Status_Single_Winning(placeText).string
}
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
var endTime = currentTime
if case let .ongoing(_, _, _, _, _, _, nextRoundDate, _, _, _) = auctionState.auctionState {
endTime = nextRoundDate
let endTimeout: Int32
if currentTime < startTime {
endTimeout = max(0, startTime - currentTime)
titleText = self.strings.ChatList_Auctions_UpcomingAuction
} else {
endTimeout = max(0, endTime - currentTime)
}
let endTimeout = max(0, endTime - currentTime)
let hours = Int(endTimeout / 3600)
let minutes = Int((endTimeout % 3600) / 60)
let seconds = Int(endTimeout % 60)
@ -179,6 +193,8 @@ final class GiftAuctionAccessoryPanel: ASDisplayNode {
buttonAnimatedTitleItems.append(AnimatedTextComponent.Item(id: "view", content: .text(self.strings.ChatList_Auctions_View)))
}
titleItems.append(AnyComponentWithIdentity(id: "label", component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: titleText, font: titleFont, textColor: self.theme.rootController.navigationBar.primaryTextColor))))))
let buttonSize = self.button.update(
transition: .spring(duration: 0.2),
component: AnyComponent(

View file

@ -340,7 +340,13 @@ public func accountWithId(accountManager: AccountManager<TelegramAccountManagerT
}
}
return initializedNetwork(accountId: id, arguments: networkArguments, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: beginWithTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil, useRequestTimeoutTimers: useRequestTimeoutTimers, appConfiguration: appConfig)
#if DEBUG
let initialDatacenterId: Int = 1
#else
let initialDatacenterId: Int = 2
#endif
return initializedNetwork(accountId: id, arguments: networkArguments, supplementary: supplementary, datacenterId: initialDatacenterId, keychain: keychain, basePath: path, testingEnvironment: beginWithTestingEnvironment, languageCode: localizationSettings?.primaryComponent.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil, useRequestTimeoutTimers: useRequestTimeoutTimers, appConfiguration: appConfig)
|> map { network -> AccountResult in
return .unauthorized(UnauthorizedAccount(accountManager: accountManager, networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: beginWithTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection))
}
@ -453,6 +459,131 @@ func _internal_twoStepAuthData(_ network: Network) -> Signal<TwoStepAuthData, MT
}
}
public final class TelegramPasskey: Equatable {
public let id: String
public let name: String
public let date: Int32
public let emojiId: Int64?
public let lastUsageDate: Int32?
public init(id: String, name: String, date: Int32, emojiId: Int64?, lastUsageDate: Int32?) {
self.id = id
self.name = name
self.date = date
self.emojiId = emojiId
self.lastUsageDate = lastUsageDate
}
public static func ==(lhs: TelegramPasskey, rhs: TelegramPasskey) -> Bool {
if lhs.id != rhs.id {
return false
}
if lhs.name != rhs.name {
return false
}
if lhs.date != rhs.date {
return false
}
if lhs.emojiId != rhs.emojiId {
return false
}
if lhs.lastUsageDate != rhs.lastUsageDate {
return false
}
return true
}
}
extension TelegramPasskey {
convenience init(apiPasskey: Api.Passkey) {
switch apiPasskey {
case let .passkey(_, id, name, date, softwareEmojiId, lastUsageDate):
self.init(id: id, name: name, date: date, emojiId: softwareEmojiId, lastUsageDate: lastUsageDate)
}
}
}
func _internal_passkeysData(network: Network) -> Signal<[TelegramPasskey], NoError> {
return network.request(Api.functions.account.getPasskeys())
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.account.Passkeys?, NoError> in
return .single(nil)
}
|> map { passkeys -> [TelegramPasskey] in
guard let passkeys else {
return []
}
switch passkeys {
case let .passkeys(passkeys):
return passkeys.map { passkey in
return TelegramPasskey(apiPasskey: passkey)
}
}
}
}
func _internal_requestPasskeyRegistration(network: Network) -> Signal<String?, NoError> {
return network.request(Api.functions.account.initPasskeyRegistration())
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.account.PasskeyRegistrationOptions?, NoError> in
return .single(nil)
}
|> map { options -> String? in
guard let options else {
return nil
}
switch options {
case let .passkeyRegistrationOptions(options):
switch options {
case let .dataJSON(data):
return data
}
}
}
}
func _internal_requestCreatePasskey(network: Network, id: String, clientData: String, attestationObject: Data) -> Signal<TelegramPasskey?, NoError> {
return network.request(Api.functions.account.registerPasskey(credential: .inputPasskeyCredentialPublicKey(id: id, rawId: id, response: .inputPasskeyResponseRegister(clientData: .dataJSON(data: clientData), attestationData: Buffer(data: attestationObject)))))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Passkey?, NoError> in
return .single(nil)
}
|> map { result -> TelegramPasskey? in
guard let result else {
return nil
}
return TelegramPasskey(apiPasskey: result)
}
}
func _internal_deletePasskey(network: Network, id: String) -> Signal<Never, NoError> {
return network.request(Api.functions.account.deletePasskey(id: id))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
|> ignoreValues
}
func _internal_requestPasskeyLoginData(network: Network, apiId: Int32, apiHash: String) -> Signal<String?, NoError> {
return network.request(Api.functions.auth.initPasskeyLogin(apiId: apiId, apiHash: apiHash))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.auth.PasskeyLoginOptions?, NoError> in
return .single(nil)
}
|> map { result -> String? in
guard let result else {
return nil
}
switch result {
case let .passkeyLoginOptions(options):
switch options {
case let .dataJSON(data):
return data
}
}
}
}
public func hexString(_ data: Data) -> String {
let hexString = NSMutableString()
data.withUnsafeBytes { rawBytes -> Void in

View file

@ -232,7 +232,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
}
switch action {
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon, .messageActionSuggestedPostSuccess, .messageActionSuggestedPostRefund, .messageActionSuggestBirthday:
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionGiftStars, .messageActionTopicCreate, .messageActionTopicEdit, .messageActionSuggestProfilePhoto, .messageActionSetChatWallPaper, .messageActionGiveawayLaunch, .messageActionGiveawayResults, .messageActionBoostApply, .messageActionRequestedPeerSentMe, .messageActionStarGift, .messageActionStarGiftUnique, .messageActionPaidMessagesRefunded, .messageActionPaidMessagesPrice, .messageActionTodoCompletions, .messageActionTodoAppendTasks, .messageActionSuggestedPostApproval, .messageActionGiftTon, .messageActionSuggestedPostSuccess, .messageActionSuggestedPostRefund, .messageActionSuggestBirthday, .messageActionStarGiftPurchaseOffer, .messageActionStarGiftPurchaseOfferDeclined:
break
case let .messageActionChannelMigrateFrom(_, chatId):
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId)))

View file

@ -181,7 +181,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .paymentRefunded(peerId: peer.peerId, currency: currency, totalAmount: totalAmount, payload: payload?.makeData(), transactionId: transactionId))
case let .messageActionPrizeStars(flags, stars, transactionId, boostPeer, giveawayMsgId):
return TelegramMediaAction(action: .prizeStars(amount: stars, isUnclaimed: (flags & (1 << 2)) != 0, boostPeerId: boostPeer.peerId, transactionId: transactionId, giveawayMessageId: MessageId(peerId: boostPeer.peerId, namespace: Namespaces.Message.Cloud, id: giveawayMsgId)))
case let .messageActionStarGift(flags, apiGift, message, convertStars, upgradeMessageId, upgradeStars, fromId, peer, savedId, prepaidUpgradeHash, giftMessageId, toId):
case let .messageActionStarGift(flags, apiGift, message, convertStars, upgradeMessageId, upgradeStars, fromId, peer, savedId, prepaidUpgradeHash, giftMessageId, toId, number):
let text: String?
let entities: [MessageTextEntity]?
switch message {
@ -195,12 +195,12 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, canUpgrade: (flags & (1 << 10)) != 0, upgradeStars: upgradeStars, isRefunded: (flags & (1 << 9)) != 0, isPrepaidUpgrade: (flags & (1 << 13)) != 0, upgradeMessageId: upgradeMessageId, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, prepaidUpgradeHash: prepaidUpgradeHash, giftMessageId: giftMessageId, upgradeSeparate: (flags & (1 << 16)) != 0, isAuctionAcquired: (flags & (1 << 17)) != 0, toPeerId: toId?.peerId))
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, canUpgrade: (flags & (1 << 10)) != 0, upgradeStars: upgradeStars, isRefunded: (flags & (1 << 9)) != 0, isPrepaidUpgrade: (flags & (1 << 13)) != 0, upgradeMessageId: upgradeMessageId, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, prepaidUpgradeHash: prepaidUpgradeHash, giftMessageId: giftMessageId, upgradeSeparate: (flags & (1 << 16)) != 0, isAuctionAcquired: (flags & (1 << 17)) != 0, toPeerId: toId?.peerId, number: number))
case let .messageActionStarGiftUnique(flags, apiGift, canExportAt, transferStars, fromId, peer, savedId, resaleAmount, canTransferDate, canResaleDate, dropOriginalDetailsStars):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftUnique(gift: gift, isUpgrade: (flags & (1 << 0)) != 0, isTransferred: (flags & (1 << 1)) != 0, savedToProfile: (flags & (1 << 2)) != 0, canExportDate: canExportAt, transferStars: transferStars, isRefunded: (flags & (1 << 5)) != 0, isPrepaidUpgrade: (flags & (1 << 11)) != 0, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, resaleAmount: resaleAmount.flatMap { CurrencyAmount(apiAmount: $0) }, canTransferDate: canTransferDate, canResaleDate: canResaleDate, dropOriginalDetailsStars: dropOriginalDetailsStars, assigned: (flags & (1 << 13)) != 0))
return TelegramMediaAction(action: .starGiftUnique(gift: gift, isUpgrade: (flags & (1 << 0)) != 0, isTransferred: (flags & (1 << 1)) != 0, savedToProfile: (flags & (1 << 2)) != 0, canExportDate: canExportAt, transferStars: transferStars, isRefunded: (flags & (1 << 5)) != 0, isPrepaidUpgrade: (flags & (1 << 11)) != 0, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, resaleAmount: resaleAmount.flatMap { CurrencyAmount(apiAmount: $0) }, canTransferDate: canTransferDate, canResaleDate: canResaleDate, dropOriginalDetailsStars: dropOriginalDetailsStars, assigned: (flags & (1 << 13)) != 0, fromOffer: (flags & (1 << 14)) != 0))
case let .messageActionPaidMessagesRefunded(count, stars):
return TelegramMediaAction(action: .paidMessagesRefunded(count: count, stars: stars))
case let .messageActionPaidMessagesPrice(flags, stars):
@ -274,6 +274,17 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .suggestedPostRefund(TelegramMediaActionType.SuggestedPostRefund(isUserInitiated: (flags & (1 << 0)) != 0)))
case let .messageActionSuggestBirthday(birthday):
return TelegramMediaAction(action: .suggestedBirthday(TelegramBirthday(apiBirthday: birthday)))
case let .messageActionStarGiftPurchaseOffer(flags, apiGift, price, expiresAt):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftPurchaseOffer(gift: gift, amount: CurrencyAmount(apiAmount: price), expireDate: expiresAt, isAccepted: (flags & (1 << 0)) != 0, isDeclined: (flags & (1 << 1)) != 0))
case let .messageActionStarGiftPurchaseOfferDeclined(flags, apiGift, price):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return TelegramMediaAction(action: .starGiftPurchaseOfferDeclined(gift: gift, amount: CurrencyAmount(apiAmount: price), hasExpired: (flags & (1 << 0)) != 0))
}
}

View file

@ -32,11 +32,11 @@ func telegramMediaWebpageAttributeFromApiWebpageAttribute(_ attribute: Api.WebPa
var files: [TelegramMediaFile] = []
files = icons.compactMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }
return .giftCollection(TelegramMediaWebpageGiftCollectionAttribute(files: files))
case let .webPageAttributeStarGiftAuction(apiGift, endDate, centerColor, edgeColor, textColor):
case let .webPageAttributeStarGiftAuction(apiGift, endDate):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
return .giftAuction(TelegramMediaWebpageGiftAuctionAttribute(gift: gift, endDate: endDate, centerColor: centerColor, edgeColor: edgeColor, textColor: textColor))
return .giftAuction(TelegramMediaWebpageGiftAuctionAttribute(gift: gift, endDate: endDate))
case .webPageAttributeStory:
return nil
}

View file

@ -1167,6 +1167,135 @@ public func authorizeWithPassword(accountManager: AccountManager<TelegramAccount
}
}
public final class AuthorizationPasskeyData {
public let id: String
public let clientData: String
public let authenticatorData: Data
public let signature: Data
public let userHandle: String
public init(id: String, clientData: String, authenticatorData: Data, signature: Data, userHandle: String) {
self.id = id
self.clientData = clientData
self.authenticatorData = authenticatorData
self.signature = signature
self.userHandle = userHandle
}
}
public final class AuthorizeWithPasskeyResult {
public let updatedAccount: UnauthorizedAccount
init(updatedAccount: UnauthorizedAccount) {
self.updatedAccount = updatedAccount
}
}
public func authorizeWithPasskey(accountManager: AccountManager<TelegramAccountManagerTypes>, account: UnauthorizedAccount, passkey: AuthorizationPasskeyData, foreignDatacenter: (id: Int, authKeyId: Int64)?, forcedPasswordSetupNotice: @escaping (Int32) -> (NoticeEntryKey, CodableEntry)?, syncContacts: Bool) -> Signal<AuthorizeWithPasskeyResult, AuthorizationCodeVerificationError> {
let userHandle = passkey.userHandle.components(separatedBy: ":")
var targetDatacenterId: Int?
if foreignDatacenter == nil && userHandle.count >= 2 {
targetDatacenterId = Int(userHandle[0])
}
if let targetDatacenterId, account.masterDatacenterId != Int32(targetDatacenterId) {
let initialDatacenterId = account.masterDatacenterId
return account.network.getAuthKeyId()
|> castError(AuthorizationCodeVerificationError.self)
|> mapToSignal { sourceAuthKeyId -> Signal<AuthorizeWithPasskeyResult, AuthorizationCodeVerificationError> in
let updatedAccount = account.changedMasterDatacenterId(accountManager: accountManager, masterDatacenterId: Int32(targetDatacenterId))
return updatedAccount
|> mapToSignalPromotingError { updatedAccount -> Signal<AuthorizeWithPasskeyResult, AuthorizationCodeVerificationError> in
return authorizeWithPasskey(accountManager: accountManager, account: updatedAccount, passkey: passkey, foreignDatacenter: (Int(initialDatacenterId), sourceAuthKeyId), forcedPasswordSetupNotice: forcedPasswordSetupNotice, syncContacts: syncContacts)
}
}
}
var flags: Int32 = 0
if foreignDatacenter != nil {
flags |= 1 << 0
}
return account.network.request(Api.functions.auth.finishPasskeyLogin(flags: flags, credential: .inputPasskeyCredentialPublicKey(id: passkey.id, rawId: passkey.id, response: .inputPasskeyResponseLogin(clientData: .dataJSON(data: passkey.clientData), authenticatorData: Buffer(data: passkey.authenticatorData), signature: Buffer(data: passkey.signature), userHandle: passkey.userHandle)), fromDcId: (foreignDatacenter?.id).flatMap(Int32.init), fromAuthKeyId: foreignDatacenter?.authKeyId), automaticFloodWait: false)
|> map { authorization in
return .authorization(authorization)
}
|> `catch` { error -> Signal<AuthorizationCodeResult, AuthorizationCodeVerificationError> in
switch (error.errorCode, error.errorDescription ?? "") {
case (401, "SESSION_PASSWORD_NEEDED"):
return account.network.request(Api.functions.account.getPassword(), automaticFloodWait: false)
|> mapError { error -> AuthorizationCodeVerificationError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else {
return .generic
}
}
|> mapToSignal { result -> Signal<AuthorizationCodeResult, AuthorizationCodeVerificationError> in
switch result {
case let .password(_, _, _, _, hint, _, _, _, _, _, _):
return .single(.password(hint: hint ?? ""))
}
}
case let (_, errorDescription):
if errorDescription.hasPrefix("FLOOD_WAIT") {
return .fail(.limitExceeded)
} else if errorDescription == "PHONE_CODE_INVALID" || errorDescription == "EMAIL_CODE_INVALID" {
return .fail(.invalidCode)
} else if errorDescription == "CODE_HASH_EXPIRED" || errorDescription == "PHONE_CODE_EXPIRED" {
return .fail(.codeExpired)
} else if errorDescription == "PHONE_NUMBER_UNOCCUPIED" {
return .single(.signUp)
} else if errorDescription == "EMAIL_TOKEN_INVALID" {
return .fail(.invalidEmailToken)
} else if errorDescription == "EMAIL_ADDRESS_INVALID" {
return .fail(.invalidEmailAddress)
} else {
return .fail(.generic)
}
}
}
|> mapToSignal { result -> Signal<AuthorizeWithPasskeyResult, AuthorizationCodeVerificationError> in
return account.postbox.transaction { transaction -> Signal<AuthorizeWithPasskeyResult, AuthorizationCodeVerificationError> in
switch result {
case .signUp:
return .fail(.generic)
case let .password(hint):
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: nil, code: nil, suggestReset: false, syncContacts: syncContacts)))
return .single(AuthorizeWithPasskeyResult(updatedAccount: account))
case let .authorization(authorization):
switch authorization {
case let .authorization(_, otherwiseReloginDays, _, futureAuthToken, user):
if let futureAuthToken = futureAuthToken {
storeFutureLoginToken(accountManager: accountManager, token: futureAuthToken.makeData())
}
let user = TelegramUser(user: user)
var isSupportUser = false
if let phone = user.phone, phone.hasPrefix("42") {
isSupportUser = true
}
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil, invalidatedChannels: [])
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts)
transaction.setState(state)
if let otherwiseReloginDays = otherwiseReloginDays, let value = forcedPasswordSetupNotice(otherwiseReloginDays) {
transaction.setNoticeEntry(key: value.0, value: value.1)
}
return accountManager.transaction { transaction -> AuthorizeWithPasskeyResult in
switchToAuthorizedAccount(transaction: transaction, account: account, isSupportUser: isSupportUser)
return AuthorizeWithPasskeyResult(updatedAccount: account)
}
|> castError(AuthorizationCodeVerificationError.self)
case .authorizationSignUpRequired:
return .fail(.generic)
}
}
}
|> mapError { _ -> AuthorizationCodeVerificationError in
}
|> switchToLatest
}
}
public enum PasswordRecoveryRequestError {
case limitExceeded
case generic
@ -1466,3 +1595,4 @@ func _internal_reportMissingCode(network: Network, phoneNumber: String, phoneCod
return .complete()
}
}

View file

@ -1065,6 +1065,22 @@ public final class Network: NSObject, MTRequestMessageServiceDelegate {
}
}
public func getAuthKeyId() -> Signal<Int64, NoError> {
let mtContext = self.mtProto.context
let datacenterId = self.datacenterId
return Signal { subscriber in
MTContext.contextQueue().dispatch(onQueue: {
var result: Int64 = 0
if let authInfo = mtContext?.authInfoForDatacenter(withId: datacenterId, selector: .persistent) {
result = authInfo.authKeyId
}
subscriber.putNext(result)
})
return EmptyDisposable
}
}
public func requestWithAdditionalInfo<T>(_ data: (FunctionDescription, Buffer, DeserializeFunctionResponse<T>), info: NetworkRequestAdditionalInfo, tag: NetworkRequestDependencyTag? = nil, automaticFloodWait: Bool = true, onFloodWaitError: ((String) -> Void)? = nil) -> Signal<NetworkRequestResult<T>, MTRpcError> {
let requestService = self.requestService
return Signal { subscriber in

View file

@ -499,7 +499,7 @@ private func sendUploadedMessageContent(
}
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: nil, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: nil), tag: dependencyTag)
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: nil, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: nil), tag: dependencyTag)
|> map(NetworkRequestResult.result)
} else {
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))

View file

@ -360,10 +360,12 @@ func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Ne
releasedBy: nil,
valueAmount: nil,
valueCurrency: nil,
valueUsdAmount: nil,
flags: [],
themePeerId: nil,
peerColor: nil,
hostPeerId: nil
hostPeerId: nil,
minOfferStars: nil
)
if let entry = CodableEntry(RecentStarGiftItem(gift)) {
items.append(OrderedItemListEntry(id: RecentStarGiftItemId(id).rawValue, contents: entry))

View file

@ -1133,7 +1133,7 @@ public final class PendingMessageManager {
} else if let inputSourcePeerId = forwardPeerIds.first, let inputSourcePeer = transaction.getPeer(inputSourcePeerId).flatMap(apiInputPeer) {
let dependencyTag = PendingMessageRequestDependencyTag(messageId: messages[0].0.id)
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), tag: dependencyTag)
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, effect: nil, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), tag: dependencyTag)
} else {
assertionFailure()
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "Invalid forward source"))
@ -1831,7 +1831,7 @@ public final class PendingMessageManager {
}
if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) {
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), tag: dependencyTag)
sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, topMsgId: topMsgId, replyTo: replyTo, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, effect: nil, videoTimestamp: videoTimestamp, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), tag: dependencyTag)
|> map(NetworkRequestResult.result)
} else {
sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal"))

View file

@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
public class Serialization: NSObject, MTSerialization {
public func currentLayer() -> UInt {
return 218
return 220
}
public func parseMessage(_ data: Data!) -> Any! {

View file

@ -20,6 +20,7 @@ public enum ServerProvidedSuggestion: Equatable {
case setupPhoto
case setupLoginEmail
case setupLoginEmailBlocking
case setupPasskey
case link(id: String, url: String, title: ServerSuggestionInfo.Item.Text, subtitle: ServerSuggestionInfo.Item.Text)
init?(string: String) {
@ -56,6 +57,8 @@ public enum ServerProvidedSuggestion: Equatable {
self = .setupLoginEmail
case "SETUP_LOGIN_EMAIL_NOSKIP":
self = .setupLoginEmailBlocking
case "SETUP_PASSKEY":
self = .setupPasskey
default:
return nil
}
@ -95,6 +98,8 @@ public enum ServerProvidedSuggestion: Equatable {
return "SETUP_LOGIN_EMAIL"
case .setupLoginEmailBlocking:
return "SETUP_LOGIN_EMAIL_NOSKIP"
case .setupPasskey:
return "SETUP_PASSKEY"
case let .link(id, _, _, _):
return id
}

View file

@ -148,6 +148,7 @@ public struct Namespaces {
public static let cachedProfileSavedMusic: Int8 = 49
public static let cachedChatThemes: Int8 = 50
public static let cachedLiveStorySendAsPeers: Int8 = 51
public static let cachedGiftUpgradesAttributes: Int8 = 52
}
public struct UnorderedItemList {

View file

@ -255,8 +255,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case paymentRefunded(peerId: PeerId, currency: String, totalAmount: Int64, payload: Data?, transactionId: String)
case giftStars(currency: String, amount: Int64, count: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, transactionId: String?)
case prizeStars(amount: Int64, isUnclaimed: Bool, boostPeerId: PeerId?, transactionId: String?, giveawayMessageId: MessageId?)
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, isRefunded: Bool, isPrepaidUpgrade: Bool, upgradeMessageId: Int32?, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, prepaidUpgradeHash: String?, giftMessageId: Int32?, upgradeSeparate: Bool, isAuctionAcquired: Bool, toPeerId: EnginePeer.Id?)
case starGiftUnique(gift: StarGift, isUpgrade: Bool, isTransferred: Bool, savedToProfile: Bool, canExportDate: Int32?, transferStars: Int64?, isRefunded: Bool, isPrepaidUpgrade: Bool, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, resaleAmount: CurrencyAmount?, canTransferDate: Int32?, canResaleDate: Int32?, dropOriginalDetailsStars: Int64?, assigned: Bool)
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, isRefunded: Bool, isPrepaidUpgrade: Bool, upgradeMessageId: Int32?, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, prepaidUpgradeHash: String?, giftMessageId: Int32?, upgradeSeparate: Bool, isAuctionAcquired: Bool, toPeerId: EnginePeer.Id?, number: Int32?)
case starGiftUnique(gift: StarGift, isUpgrade: Bool, isTransferred: Bool, savedToProfile: Bool, canExportDate: Int32?, transferStars: Int64?, isRefunded: Bool, isPrepaidUpgrade: Bool, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, resaleAmount: CurrencyAmount?, canTransferDate: Int32?, canResaleDate: Int32?, dropOriginalDetailsStars: Int64?, assigned: Bool, fromOffer: Bool)
case paidMessagesRefunded(count: Int32, stars: Int64)
case paidMessagesPriceEdited(stars: Int64, broadcastMessagesAllowed: Bool)
case conferenceCall(ConferenceCall)
@ -267,6 +267,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case suggestedPostSuccess(amount: CurrencyAmount)
case suggestedPostRefund(SuggestedPostRefund)
case suggestedBirthday(TelegramBirthday)
case starGiftPurchaseOffer(gift: StarGift, amount: CurrencyAmount, expireDate: Int32, isAccepted: Bool, isDeclined: Bool)
case starGiftPurchaseOfferDeclined(gift: StarGift, amount: CurrencyAmount, hasExpired: Bool)
public init(decoder: PostboxDecoder) {
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
@ -394,7 +396,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
}
self = .prizeStars(amount: decoder.decodeInt64ForKey("amount", orElse: 0), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: boostPeerId, transactionId: decoder.decodeOptionalStringForKey("transactionId"), giveawayMessageId: giveawayMessageId)
case 44:
self = .starGift(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, convertStars: decoder.decodeOptionalInt64ForKey("convertStars"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"), nameHidden: decoder.decodeBoolForKey("nameHidden", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), converted: decoder.decodeBoolForKey("converted", orElse: false), upgraded: decoder.decodeBoolForKey("upgraded", orElse: false), canUpgrade: decoder.decodeBoolForKey("canUpgrade", orElse: false), upgradeStars: decoder.decodeOptionalInt64ForKey("upgradeStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), isPrepaidUpgrade: decoder.decodeBoolForKey("isPrepaidUpgrade", orElse: false), upgradeMessageId: decoder.decodeOptionalInt32ForKey("upgradeMessageId"), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), prepaidUpgradeHash: decoder.decodeOptionalStringForKey("prepaidUpgradeHash"), giftMessageId: decoder.decodeOptionalInt32ForKey("giftMessageId"), upgradeSeparate: decoder.decodeOptionalBoolForKey("upgradeSeparate") ?? false, isAuctionAcquired: decoder.decodeOptionalBoolForKey("isAuctionAcquired") ?? false, toPeerId: decoder.decodeOptionalInt64ForKey("toPeerId").flatMap { EnginePeer.Id($0) })
self = .starGift(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, convertStars: decoder.decodeOptionalInt64ForKey("convertStars"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"), nameHidden: decoder.decodeBoolForKey("nameHidden", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), converted: decoder.decodeBoolForKey("converted", orElse: false), upgraded: decoder.decodeBoolForKey("upgraded", orElse: false), canUpgrade: decoder.decodeBoolForKey("canUpgrade", orElse: false), upgradeStars: decoder.decodeOptionalInt64ForKey("upgradeStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), isPrepaidUpgrade: decoder.decodeBoolForKey("isPrepaidUpgrade", orElse: false), upgradeMessageId: decoder.decodeOptionalInt32ForKey("upgradeMessageId"), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), prepaidUpgradeHash: decoder.decodeOptionalStringForKey("prepaidUpgradeHash"), giftMessageId: decoder.decodeOptionalInt32ForKey("giftMessageId"), upgradeSeparate: decoder.decodeOptionalBoolForKey("upgradeSeparate") ?? false, isAuctionAcquired: decoder.decodeOptionalBoolForKey("isAuctionAcquired") ?? false, toPeerId: decoder.decodeOptionalInt64ForKey("toPeerId").flatMap { EnginePeer.Id($0) }, number: decoder.decodeOptionalInt32ForKey("number"))
case 45:
var resaleAmount: CurrencyAmount?
if let amount = decoder.decodeCodable(CurrencyAmount.self, forKey: "resaleAmount") {
@ -402,7 +404,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else if let stars = decoder.decodeOptionalInt64ForKey("resaleStars") {
resaleAmount = CurrencyAmount(amount: StarsAmount(value: stars, nanos: 0), currency: .stars)
}
self = .starGiftUnique(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, isUpgrade: decoder.decodeBoolForKey("isUpgrade", orElse: false), isTransferred: decoder.decodeBoolForKey("isTransferred", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), canExportDate: decoder.decodeOptionalInt32ForKey("canExportDate"), transferStars: decoder.decodeOptionalInt64ForKey("transferStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), isPrepaidUpgrade: decoder.decodeBoolForKey("isPrepaidUpgrade", orElse: false), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), resaleAmount: resaleAmount, canTransferDate: decoder.decodeOptionalInt32ForKey("canTransferDate"), canResaleDate: decoder.decodeOptionalInt32ForKey("canResaleDate"), dropOriginalDetailsStars: decoder.decodeOptionalInt64ForKey("dropOriginalDetailsStars"), assigned: decoder.decodeBoolForKey("assigned", orElse: false))
self = .starGiftUnique(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, isUpgrade: decoder.decodeBoolForKey("isUpgrade", orElse: false), isTransferred: decoder.decodeBoolForKey("isTransferred", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), canExportDate: decoder.decodeOptionalInt32ForKey("canExportDate"), transferStars: decoder.decodeOptionalInt64ForKey("transferStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false), isPrepaidUpgrade: decoder.decodeBoolForKey("isPrepaidUpgrade", orElse: false), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), resaleAmount: resaleAmount, canTransferDate: decoder.decodeOptionalInt32ForKey("canTransferDate"), canResaleDate: decoder.decodeOptionalInt32ForKey("canResaleDate"), dropOriginalDetailsStars: decoder.decodeOptionalInt64ForKey("dropOriginalDetailsStars"), assigned: decoder.decodeBoolForKey("assigned", orElse: false), fromOffer: decoder.decodeBoolForKey("fromOffer", orElse: false))
case 46:
self = .paidMessagesRefunded(count: decoder.decodeInt32ForKey("count", orElse: 0), stars: decoder.decodeInt64ForKey("stars", orElse: 0))
case 47:
@ -434,6 +436,10 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
self = .suggestedPostRefund(decoder.decodeCodable(SuggestedPostRefund.self, forKey: "s") ?? SuggestedPostRefund(isUserInitiated: true))
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))
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))
default:
self = .unknown
}
@ -728,7 +734,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "giveawayMsgId")
}
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, isPrepaidUpgrade, upgradeMessageId, peerId, senderId, savedId, prepaidUpgradeHash, giftMessageId, upgradeSeparate, isAuctionAcquired, toPeerId):
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded, isPrepaidUpgrade, upgradeMessageId, peerId, senderId, savedId, prepaidUpgradeHash, giftMessageId, upgradeSeparate, isAuctionAcquired, toPeerId, number):
encoder.encodeInt32(44, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
if let convertStars {
@ -792,7 +798,12 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
} else {
encoder.encodeNil(forKey: "toPeerId")
}
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, dropOriginalDetailsStars, assigned):
if let number {
encoder.encodeInt32(number, forKey: "number")
} else {
encoder.encodeNil(forKey: "number")
}
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, dropOriginalDetailsStars, assigned, fromOffer):
encoder.encodeInt32(45, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
encoder.encodeBool(isUpgrade, forKey: "isUpgrade")
@ -846,6 +857,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
encoder.encodeNil(forKey: "dropOriginalDetailsStars")
}
encoder.encodeBool(assigned, forKey: "assigned")
encoder.encodeBool(fromOffer, forKey: "fromOffer")
case let .paidMessagesRefunded(count, stars):
encoder.encodeInt32(46, forKey: "_rawValue")
encoder.encodeInt32(count, forKey: "count")
@ -899,6 +911,18 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
case let .suggestedBirthday(birthday):
encoder.encodeInt32(55, forKey: "_rawValue")
encoder.encodeCodable(birthday, forKey: "birthday")
case let .starGiftPurchaseOffer(gift, amount, expireDate, isAccepted, isDeclined):
encoder.encodeInt32(56, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
encoder.encodeCodable(amount, forKey: "amount")
encoder.encodeInt32(expireDate, forKey: "expireDate")
encoder.encodeBool(isAccepted, forKey: "isAccepted")
encoder.encodeBool(isDeclined, forKey: "isDeclined")
case let .starGiftPurchaseOfferDeclined(gift, amount, hasExpired):
encoder.encodeInt32(57, forKey: "_rawValue")
encoder.encodeObject(gift, forKey: "gift")
encoder.encodeCodable(amount, forKey: "amount")
encoder.encodeBool(hasExpired, forKey: "hasExpired")
}
}
@ -926,7 +950,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
return [peerId]
case let .prizeStars(_, _, boostPeerId, _, _):
return boostPeerId.flatMap { [$0] } ?? []
case let .starGift(gift, _, _, _, _, _, _, _, _, _, _, _, _, peerId, senderId, _, _, _, _, _, toPeerId):
case let .starGift(gift, _, _, _, _, _, _, _, _, _, _, _, _, peerId, senderId, _, _, _, _, _, toPeerId, _):
var peerIds: [PeerId] = []
if let peerId {
peerIds.append(peerId)
@ -941,7 +965,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
peerIds.append(toPeerId)
}
return peerIds
case let .starGiftUnique(gift, _, _, _, _, _, _, _, peerId, senderId, _, _, _, _, _, _):
case let .starGiftUnique(gift, _, _, _, _, _, _, _, peerId, senderId, _, _, _, _, _, _, _):
var peerIds: [PeerId] = []
if let peerId {
peerIds.append(peerId)

View file

@ -210,52 +210,28 @@ public final class TelegramMediaWebpageGiftAuctionAttribute: PostboxCoding, Equa
if lhs.endDate != rhs.endDate {
return false
}
if lhs.centerColor != rhs.centerColor {
return false
}
if lhs.edgeColor != rhs.edgeColor {
return false
}
if lhs.textColor != rhs.textColor {
return false
}
return true
}
public let gift: StarGift
public let endDate: Int32
public let centerColor: Int32
public let edgeColor: Int32
public let textColor: Int32
public init(
gift: StarGift,
endDate: Int32,
centerColor: Int32,
edgeColor: Int32,
textColor: Int32
endDate: Int32
) {
self.gift = gift
self.endDate = endDate
self.centerColor = centerColor
self.edgeColor = edgeColor
self.textColor = textColor
}
public init(decoder: PostboxDecoder) {
self.gift = decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift
self.endDate = decoder.decodeInt32ForKey("endDate", orElse: 0)
self.centerColor = decoder.decodeInt32ForKey("centerColor", orElse: 0)
self.edgeColor = decoder.decodeInt32ForKey("edgeColor", orElse: 0)
self.textColor = decoder.decodeInt32ForKey("textColor", orElse: 0)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeObject(self.gift, forKey: "gift")
encoder.encodeInt32(self.endDate, forKey: "endDate")
encoder.encodeInt32(self.centerColor, forKey: "centerColor")
encoder.encodeInt32(self.edgeColor, forKey: "edgeColor")
encoder.encodeInt32(self.textColor, forKey: "textColor")
}
}

View file

@ -25,10 +25,9 @@ public class TranslationMessageAttribute: MessageAttribute, Equatable {
public let entities: [MessageTextEntity]
public let toLang: String
public let additional:[Additional]
public let additional: [Additional]
public let pollSolution: Additional?
public var associatedPeerIds: [PeerId] {
return []
}

View file

@ -56,6 +56,10 @@ public extension TelegramEngineUnauthorized {
return _internal_reportMissingCode(network: self.account.network, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, mnc: mnc)
}
public func requestPasskeyLoginData(apiId: Int32, apiHash: String) -> Signal<String?, NoError> {
return _internal_requestPasskeyLoginData(network: self.account.network, apiId: apiId, apiHash: apiHash)
}
public func state() -> Signal<TelegramEngineAuthorizationState?, NoError> {
return self.account.postbox.stateView()
|> map { view -> TelegramEngineAuthorizationState? in
@ -210,6 +214,22 @@ public extension TelegramEngine {
public func reportMissingCode(phoneNumber: String, phoneCodeHash: String, mnc: String) -> Signal<Never, ReportMissingCodeError> {
return _internal_reportMissingCode(network: self.account.network, phoneNumber: phoneNumber, phoneCodeHash: phoneCodeHash, mnc: mnc)
}
public func passkeysData() -> Signal<[TelegramPasskey], NoError> {
return _internal_passkeysData(network: self.account.network)
}
public func requestPasskeyRegistration() -> Signal<String?, NoError> {
return _internal_requestPasskeyRegistration(network: self.account.network)
}
public func requestCreatePasskey(id: String, clientData: String, attestationObject: Data) -> Signal<TelegramPasskey?, NoError> {
return _internal_requestCreatePasskey(network: self.account.network, id: id, clientData: clientData, attestationObject: attestationObject)
}
public func deletePasskey(id: String) -> Signal<Never, NoError> {
return _internal_deletePasskey(network: self.account.network, id: id)
}
}
}

View file

@ -209,7 +209,7 @@ func _internal_clearHistoryInteractively(postbox: Postbox, peerId: PeerId, threa
func _internal_clearAuthorHistory(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(peerId), let memberPeer = transaction.getPeer(memberId), let inputChannel = apiInputChannel(peer), let inputUser = apiInputPeer(memberPeer) {
let signal = account.network.request(Api.functions.channels.deleteParticipantHistory(channel: inputChannel, participant: inputUser))
let signal = peer.isMonoForum ? .fail(true) : account.network.request(Api.functions.channels.deleteParticipantHistory(channel: inputChannel, participant: inputUser))
|> map { result -> Api.messages.AffectedHistory? in
return result
}

View file

@ -14,7 +14,7 @@ func _internal_forwardGameWithScore(account: Account, messageId: MessageId, to p
flags |= (1 << 13)
}
return account.network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: fromInputPeer, id: [messageId.id], randomId: [Int64.random(in: Int64.min ... Int64.max)], toPeer: toInputPeer, topMsgId: threadId.flatMap { Int32(clamping: $0) }, replyTo: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, sendAs: sendAsInputPeer, quickReplyShortcut: nil, videoTimestamp: nil, allowPaidStars: nil, suggestedPost: nil))
return account.network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: fromInputPeer, id: [messageId.id], randomId: [Int64.random(in: Int64.min ... Int64.max)], toPeer: toInputPeer, topMsgId: threadId.flatMap { Int32(clamping: $0) }, replyTo: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, videoTimestamp: nil, allowPaidStars: nil, suggestedPost: nil))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)

View file

@ -593,7 +593,7 @@ public extension TelegramEngine {
}
public func translate(texts: [(String, [MessageTextEntity])], toLang: String) -> Signal<[(String, [MessageTextEntity])], TranslationError> {
return _internal_translate_texts(network: self.account.network, texts: texts, toLang: toLang)
return _internal_translateTexts(network: self.account.network, texts: texts, toLang: toLang)
}
public func translateMessages(messageIds: [EngineMessage.Id], fromLang: String?, toLang: String, enableLocalIfPossible: Bool) -> Signal<Never, TranslationError> {

View file

@ -48,7 +48,7 @@ func _internal_translate(network: Network, text: String, toLang: String, entitie
}
}
func _internal_translate_texts(network: Network, texts: [(String, [MessageTextEntity])], toLang: String) -> Signal<[(String, [MessageTextEntity])], TranslationError> {
func _internal_translateTexts(network: Network, texts: [(String, [MessageTextEntity])], toLang: String) -> Signal<[(String, [MessageTextEntity])], TranslationError> {
var flags: Int32 = 0
flags |= (1 << 1)
@ -112,9 +112,9 @@ private func _internal_translateMessagesByPeerId(account: Account, peerId: Engin
return .never()
}
let polls = messages.compactMap { msg in
if let poll = msg.media.first as? TelegramMediaPoll {
return (poll, msg.id)
let polls = messages.compactMap { message in
if let poll = message.media.first as? TelegramMediaPoll {
return (poll, message.id)
} else {
return nil
}
@ -128,9 +128,19 @@ private func _internal_translateMessagesByPeerId(account: Account, peerId: Engin
if let solution = poll.results.solution {
texts.append((solution.text, solution.entities))
}
return _internal_translate_texts(network: account.network, texts: texts, toLang: toLang)
return _internal_translateTexts(network: account.network, texts: texts, toLang: toLang)
}
let audioTranscriptions = messages.compactMap { message in
if let audioTranscription = message.attributes.first(where: { $0 is AudioTranscriptionMessageAttribute }) as? AudioTranscriptionMessageAttribute, !audioTranscription.text.isEmpty && !audioTranscription.isPending {
return (audioTranscription.text, message.id)
} else {
return nil
}
}
let audioTranscriptionsSignals = audioTranscriptions.map { (text, id) in
return _internal_translate(network: account.network, text: text, toLang: toLang)
}
var flags: Int32 = 0
flags |= (1 << 0)
@ -197,8 +207,8 @@ private func _internal_translateMessagesByPeerId(account: Account, peerId: Engin
}
}
return combineLatest(msgs, combineLatest(pollSignals))
|> mapToSignal { (result, pollResults) -> Signal<Void, TranslationError> in
return combineLatest(msgs, combineLatest(pollSignals), combineLatest(audioTranscriptionsSignals))
|> mapToSignal { (result, pollResults, audioTranscriptionsResults) -> Signal<Void, TranslationError> in
return account.postbox.transaction { transaction in
if case let .translateResult(results) = result {
var index = 0
@ -218,6 +228,7 @@ private func _internal_translateMessagesByPeerId(account: Account, peerId: Engin
index += 1
}
}
if !pollResults.isEmpty {
for (i, poll) in polls.enumerated() {
let result = pollResults[i]
@ -231,12 +242,12 @@ private func _internal_translateMessagesByPeerId(account: Account, peerId: Engin
if translated.0.isEmpty {
translated = (poll.0.options[i].text, poll.0.options[i].entities)
}
attrOptions.append(.init(text: translated.0, entities: translated.1))
attrOptions.append(TranslationMessageAttribute.Additional(text: translated.0, entities: translated.1))
}
let solution: TranslationMessageAttribute.Additional?
if result.count > 1 + poll.0.options.count, !result[result.count - 1].0.isEmpty {
solution = .init(text: result[result.count - 1].0, entities: result[result.count - 1].1)
solution = TranslationMessageAttribute.Additional(text: result[result.count - 1].0, entities: result[result.count - 1].1)
} else {
solution = nil
}
@ -251,6 +262,22 @@ private func _internal_translateMessagesByPeerId(account: Account, peerId: Engin
}
}
}
if !audioTranscriptionsResults.isEmpty {
for (i, audioTranscription) in audioTranscriptions.enumerated() {
if let result = audioTranscriptionsResults[i] {
transaction.updateMessage(audioTranscription.1, update: { currentMessage in
let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init)
var attributes = currentMessage.attributes.filter { !($0 is TranslationMessageAttribute) }
let updatedAttribute: TranslationMessageAttribute = TranslationMessageAttribute(text: result.0, entities: result.1, additional: [], pollSolution: nil, toLang: toLang)
attributes.append(updatedAttribute)
return .update(StoreMessage(id: currentMessage.id, customStableId: nil, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
})
}
}
}
}
|> castError(TranslationError.self)
}

View file

@ -62,6 +62,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
case lockedUntilDate
case auctionSlug
case auctionGiftsPerRound
case auctionStartDate
case upgradeVariantsCount
case background
}
public struct Availability: Equatable, Codable, PostboxCoding {
@ -169,6 +172,40 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
}
}
public struct Background: Equatable, Codable, PostboxCoding {
enum CodingKeys: String, CodingKey {
case centerColor
case edgeColor
case textColor
}
public let centerColor: Int32
public let edgeColor: Int32
public let textColor: Int32
public init(
centerColor: Int32,
edgeColor: Int32,
textColor: Int32
) {
self.centerColor = centerColor
self.edgeColor = edgeColor
self.textColor = textColor
}
public init(decoder: PostboxDecoder) {
self.centerColor = decoder.decodeInt32ForKey(CodingKeys.centerColor.rawValue, orElse: 0)
self.edgeColor = decoder.decodeInt32ForKey(CodingKeys.edgeColor.rawValue, orElse: 0)
self.textColor = decoder.decodeInt32ForKey(CodingKeys.textColor.rawValue, orElse: 0)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt32(self.centerColor, forKey: CodingKeys.centerColor.rawValue)
encoder.encodeInt32(self.edgeColor, forKey: CodingKeys.edgeColor.rawValue)
encoder.encodeInt32(self.textColor, forKey: CodingKeys.textColor.rawValue)
}
}
public enum DecodingError: Error {
case generic
}
@ -187,8 +224,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
public let lockedUntilDate: Int32?
public let auctionSlug: String?
public let auctionGiftsPerRound: Int32?
public let auctionStartDate: Int32?
public let upgradeVariantsCount: Int32?
public let background: Background?
public init(id: Int64, title: String?, file: TelegramMediaFile, price: Int64, convertStars: Int64, availability: Availability?, soldOut: SoldOut?, flags: Flags, upgradeStars: Int64?, releasedBy: EnginePeer.Id?, perUserLimit: PerUserLimit?, lockedUntilDate: Int32?, auctionSlug: String?, auctionGiftsPerRound: Int32?) {
public init(id: Int64, title: String?, file: TelegramMediaFile, price: Int64, convertStars: Int64, availability: Availability?, soldOut: SoldOut?, flags: Flags, upgradeStars: Int64?, releasedBy: EnginePeer.Id?, perUserLimit: PerUserLimit?, lockedUntilDate: Int32?, auctionSlug: String?, auctionGiftsPerRound: Int32?, auctionStartDate: Int32?, upgradeVariantsCount: Int32?, background: Background?) {
self.id = id
self.title = title
self.file = file
@ -203,6 +243,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.lockedUntilDate = lockedUntilDate
self.auctionSlug = auctionSlug
self.auctionGiftsPerRound = auctionGiftsPerRound
self.auctionStartDate = auctionStartDate
self.upgradeVariantsCount = upgradeVariantsCount
self.background = background
}
public init(from decoder: Decoder) throws {
@ -227,6 +270,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.lockedUntilDate = try container.decodeIfPresent(Int32.self, forKey: .lockedUntilDate)
self.auctionSlug = try container.decodeIfPresent(String.self, forKey: .auctionSlug)
self.auctionGiftsPerRound = try container.decodeIfPresent(Int32.self, forKey: .auctionGiftsPerRound)
self.auctionStartDate = try container.decodeIfPresent(Int32.self, forKey: .auctionStartDate)
self.upgradeVariantsCount = try container.decodeIfPresent(Int32.self, forKey: .upgradeVariantsCount)
self.background = try container.decodeIfPresent(Background.self, forKey: .background)
}
public init(decoder: PostboxDecoder) {
@ -244,6 +290,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.lockedUntilDate = decoder.decodeOptionalInt32ForKey(CodingKeys.lockedUntilDate.rawValue)
self.auctionSlug = decoder.decodeOptionalStringForKey(CodingKeys.auctionSlug.rawValue)
self.auctionGiftsPerRound = decoder.decodeOptionalInt32ForKey(CodingKeys.auctionGiftsPerRound.rawValue)
self.auctionStartDate = decoder.decodeOptionalInt32ForKey(CodingKeys.auctionStartDate.rawValue)
self.upgradeVariantsCount = decoder.decodeOptionalInt32ForKey(CodingKeys.upgradeVariantsCount.rawValue)
self.background = decoder.decodeObjectForKey(CodingKeys.background.rawValue, decoder: { StarGift.Gift.Background(decoder: $0) }) as? StarGift.Gift.Background
}
public func encode(to encoder: Encoder) throws {
@ -267,6 +316,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
try container.encodeIfPresent(self.lockedUntilDate, forKey: .lockedUntilDate)
try container.encodeIfPresent(self.auctionSlug, forKey: .auctionSlug)
try container.encodeIfPresent(self.auctionGiftsPerRound, forKey: .auctionGiftsPerRound)
try container.encodeIfPresent(self.auctionStartDate, forKey: .auctionStartDate)
try container.encodeIfPresent(self.upgradeVariantsCount, forKey: .upgradeVariantsCount)
try container.encodeIfPresent(self.background, forKey: .background)
}
public func encode(_ encoder: PostboxEncoder) {
@ -320,6 +372,21 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
} else {
encoder.encodeNil(forKey: CodingKeys.auctionGiftsPerRound.rawValue)
}
if let auctionStartDate = self.auctionStartDate {
encoder.encodeInt32(auctionStartDate, forKey: CodingKeys.auctionStartDate.rawValue)
} else {
encoder.encodeNil(forKey: CodingKeys.auctionStartDate.rawValue)
}
if let upgradeVariantsCount = self.upgradeVariantsCount {
encoder.encodeInt32(upgradeVariantsCount, forKey: CodingKeys.upgradeVariantsCount.rawValue)
} else {
encoder.encodeNil(forKey: CodingKeys.upgradeVariantsCount.rawValue)
}
if let background = self.background {
encoder.encodeObject(background, forKey: CodingKeys.background.rawValue)
} else {
encoder.encodeNil(forKey: CodingKeys.background.rawValue)
}
}
}
@ -342,10 +409,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
case releasedBy
case valueAmount
case valueCurrency
case valueUsdAmount
case flags
case themePeerId
case peerColor
case hostPeerId
case minOfferStars
}
public struct Flags: OptionSet {
@ -631,12 +700,14 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
public let releasedBy: EnginePeer.Id?
public let valueAmount: Int64?
public let valueCurrency: String?
public let valueUsdAmount: Int64?
public let flags: Flags
public let themePeerId: EnginePeer.Id?
public let peerColor: PeerCollectibleColor?
public let hostPeerId: EnginePeer.Id?
public let minOfferStars: Int64?
public init(id: Int64, giftId: Int64, title: String, number: Int32, slug: String, owner: Owner, attributes: [Attribute], availability: Availability, giftAddress: String?, resellAmounts: [CurrencyAmount]?, resellForTonOnly: Bool, releasedBy: EnginePeer.Id?, valueAmount: Int64?, valueCurrency: String?, flags: Flags, themePeerId: EnginePeer.Id?, peerColor: PeerCollectibleColor?, hostPeerId: EnginePeer.Id?) {
public init(id: Int64, giftId: Int64, title: String, number: Int32, slug: String, owner: Owner, attributes: [Attribute], availability: Availability, giftAddress: String?, resellAmounts: [CurrencyAmount]?, resellForTonOnly: Bool, releasedBy: EnginePeer.Id?, valueAmount: Int64?, valueCurrency: String?, valueUsdAmount: Int64?, flags: Flags, themePeerId: EnginePeer.Id?, peerColor: PeerCollectibleColor?, hostPeerId: EnginePeer.Id?, minOfferStars: Int64?) {
self.id = id
self.giftId = giftId
self.title = title
@ -651,10 +722,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.releasedBy = releasedBy
self.valueAmount = valueAmount
self.valueCurrency = valueCurrency
self.valueUsdAmount = valueUsdAmount
self.flags = flags
self.themePeerId = themePeerId
self.peerColor = peerColor
self.hostPeerId = hostPeerId
self.minOfferStars = minOfferStars
}
public init(from decoder: Decoder) throws {
@ -687,10 +760,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.releasedBy = try container.decodeIfPresent(EnginePeer.Id.self, forKey: .releasedBy)
self.valueAmount = try container.decodeIfPresent(Int64.self, forKey: .valueAmount)
self.valueCurrency = try container.decodeIfPresent(String.self, forKey: .valueCurrency)
self.valueUsdAmount = try container.decodeIfPresent(Int64.self, forKey: .valueUsdAmount)
self.flags = try container.decodeIfPresent(Int32.self, forKey: .flags).flatMap { Flags(rawValue: $0) } ?? []
self.themePeerId = try container.decodeIfPresent(Int64.self, forKey: .themePeerId).flatMap { EnginePeer.Id($0) }
self.peerColor = try container.decodeIfPresent(PeerCollectibleColor.self, forKey: .peerColor)
self.hostPeerId = try container.decodeIfPresent(Int64.self, forKey: .hostPeerId).flatMap { EnginePeer.Id($0) }
self.minOfferStars = try container.decodeIfPresent(Int64.self, forKey: .minOfferStars)
}
public init(decoder: PostboxDecoder) {
@ -722,10 +797,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
self.releasedBy = decoder.decodeOptionalInt64ForKey(CodingKeys.releasedBy.rawValue).flatMap { EnginePeer.Id($0) }
self.valueAmount = decoder.decodeOptionalInt64ForKey(CodingKeys.valueAmount.rawValue)
self.valueCurrency = decoder.decodeOptionalStringForKey(CodingKeys.valueCurrency.rawValue)
self.valueUsdAmount = decoder.decodeOptionalInt64ForKey(CodingKeys.valueUsdAmount.rawValue)
self.flags = decoder.decodeOptionalInt32ForKey(CodingKeys.flags.rawValue).flatMap { Flags(rawValue: $0) } ?? []
self.themePeerId = decoder.decodeOptionalInt64ForKey(CodingKeys.themePeerId.rawValue).flatMap { EnginePeer.Id($0) }
self.peerColor = decoder.decodeCodable(PeerCollectibleColor.self, forKey: CodingKeys.peerColor.rawValue)
self.hostPeerId = decoder.decodeOptionalInt64ForKey(CodingKeys.hostPeerId.rawValue).flatMap { EnginePeer.Id($0) }
self.minOfferStars = decoder.decodeOptionalInt64ForKey(CodingKeys.minOfferStars.rawValue)
}
public func encode(to encoder: Encoder) throws {
@ -751,10 +828,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
try container.encodeIfPresent(self.releasedBy, forKey: .releasedBy)
try container.encodeIfPresent(self.valueAmount, forKey: .valueAmount)
try container.encodeIfPresent(self.valueCurrency, forKey: .valueCurrency)
try container.encodeIfPresent(self.valueUsdAmount, forKey: .valueUsdAmount)
try container.encode(self.flags.rawValue, forKey: .flags)
try container.encodeIfPresent(self.themePeerId?.toInt64(), forKey: .themePeerId)
try container.encodeIfPresent(self.peerColor, forKey: .peerColor)
try container.encodeIfPresent(self.hostPeerId?.toInt64(), forKey: .hostPeerId)
try container.encodeIfPresent(self.minOfferStars, forKey: .minOfferStars)
}
public func encode(_ encoder: PostboxEncoder) {
@ -796,6 +875,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
encoder.encodeNil(forKey: CodingKeys.valueAmount.rawValue)
encoder.encodeNil(forKey: CodingKeys.valueCurrency.rawValue)
}
if let valueUsdAmount = self.valueUsdAmount {
encoder.encodeInt64(valueUsdAmount, forKey: CodingKeys.valueUsdAmount.rawValue)
} else {
encoder.encodeNil(forKey: CodingKeys.valueUsdAmount.rawValue)
}
encoder.encodeInt32(self.flags.rawValue, forKey: CodingKeys.flags.rawValue)
if let themePeerId = self.themePeerId {
encoder.encodeInt64(themePeerId.toInt64(), forKey: CodingKeys.themePeerId.rawValue)
@ -812,6 +896,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
} else {
encoder.encodeNil(forKey: CodingKeys.hostPeerId.rawValue)
}
if let minOfferStars = self.minOfferStars {
encoder.encodeInt64(minOfferStars, forKey: CodingKeys.minOfferStars.rawValue)
} else {
encoder.encodeNil(forKey: CodingKeys.minOfferStars.rawValue)
}
}
public func withResellAmounts(_ resellAmounts: [CurrencyAmount]?) -> UniqueGift {
@ -830,10 +919,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
releasedBy: self.releasedBy,
valueAmount: self.valueAmount,
valueCurrency: self.valueCurrency,
valueUsdAmount: self.valueUsdAmount,
flags: self.flags,
themePeerId: self.themePeerId,
peerColor: self.peerColor,
hostPeerId: self.hostPeerId
hostPeerId: self.hostPeerId,
minOfferStars: self.minOfferStars
)
}
@ -853,10 +944,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
releasedBy: self.releasedBy,
valueAmount: self.valueAmount,
valueCurrency: self.valueCurrency,
valueUsdAmount: self.valueUsdAmount,
flags: self.flags,
themePeerId: self.themePeerId,
peerColor: self.peerColor,
hostPeerId: self.hostPeerId
hostPeerId: self.hostPeerId,
minOfferStars: self.minOfferStars
)
}
@ -876,10 +969,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
releasedBy: self.releasedBy,
valueAmount: self.valueAmount,
valueCurrency: self.valueCurrency,
valueUsdAmount: self.valueUsdAmount,
flags: self.flags,
themePeerId: themePeerId,
peerColor: self.peerColor,
hostPeerId: self.hostPeerId
hostPeerId: self.hostPeerId,
minOfferStars: self.minOfferStars
)
}
@ -899,10 +994,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
releasedBy: self.releasedBy,
valueAmount: self.valueAmount,
valueCurrency: self.valueCurrency,
valueUsdAmount: self.valueUsdAmount,
flags: self.flags,
themePeerId: self.themePeerId,
peerColor: self.peerColor,
hostPeerId: self.hostPeerId
hostPeerId: self.hostPeerId,
minOfferStars: self.minOfferStars
)
}
}
@ -978,6 +1075,15 @@ public extension StarGift {
}
}
var title: String {
switch self {
case let .generic(gift):
return gift.title ?? ""
case let .unique(gift):
return gift.title
}
}
var releasedBy: EnginePeer.Id? {
switch self {
case let .generic(gift):
@ -991,7 +1097,7 @@ public extension StarGift {
extension StarGift {
init?(apiStarGift: Api.StarGift) {
switch apiStarGift {
case let .starGift(apiFlags, id, sticker, stars, availabilityRemains, availabilityTotal, availabilityResale, convertStars, firstSale, lastSale, upgradeStars, minResaleStars, title, releasedBy, perUserTotal, perUserRemains, lockedUntilDate, auctionSlug, giftsPerRound):
case let .starGift(apiFlags, id, sticker, stars, availabilityRemains, availabilityTotal, availabilityResale, convertStars, firstSale, lastSale, upgradeStars, minResaleStars, title, releasedBy, perUserTotal, perUserRemains, lockedUntilDate, auctionSlug, giftsPerRound, auctionStartDate, upgradeVariantsCount, apiBackground):
var flags = StarGift.Gift.Flags()
if (apiFlags & (1 << 2)) != 0 {
flags.insert(.isBirthdayGift)
@ -1023,11 +1129,36 @@ extension StarGift {
if let perUserTotal, let perUserRemains {
perUserLimit = StarGift.Gift.PerUserLimit(total: perUserTotal, remains: perUserRemains)
}
var background: StarGift.Gift.Background?
switch apiBackground {
case let .starGiftBackground(centerColor, edgeColor, textColor):
background = StarGift.Gift.Background(centerColor: centerColor, edgeColor: edgeColor, textColor: textColor)
default:
break
}
guard let file = telegramMediaFileFromApiDocument(sticker, altDocuments: nil) else {
return nil
}
self = .generic(StarGift.Gift(id: id, title: title, file: file, price: stars, convertStars: convertStars, availability: availability, soldOut: soldOut, flags: flags, upgradeStars: upgradeStars, releasedBy: releasedBy?.peerId, perUserLimit: perUserLimit, lockedUntilDate: lockedUntilDate, auctionSlug: auctionSlug, auctionGiftsPerRound: giftsPerRound))
case let .starGiftUnique(apiFlags, id, giftId, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellAmounts, releasedBy, valueAmount, valueCurrency, themePeer, peerColor, hostPeerId):
self = .generic(StarGift.Gift(
id: id,
title: title,
file: file,
price: stars,
convertStars: convertStars,
availability: availability,
soldOut: soldOut,
flags: flags,
upgradeStars: upgradeStars,
releasedBy: releasedBy?.peerId,
perUserLimit: perUserLimit,
lockedUntilDate: lockedUntilDate,
auctionSlug: auctionSlug,
auctionGiftsPerRound: giftsPerRound,
auctionStartDate: auctionStartDate,
upgradeVariantsCount: upgradeVariantsCount,
background: background
))
case let .starGiftUnique(apiFlags, id, giftId, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellAmounts, releasedBy, valueAmount, valueCurrency, valueUsdAmount, themePeer, peerColor, hostPeerId, minOfferStars):
let owner: StarGift.UniqueGift.Owner
if let ownerAddress {
owner = .address(ownerAddress)
@ -1059,7 +1190,29 @@ extension StarGift {
break
}
self = .unique(StarGift.UniqueGift(id: id, giftId: giftId, title: title, number: num, slug: slug, owner: owner, attributes: attributes.compactMap { UniqueGift.Attribute(apiAttribute: $0) }, availability: UniqueGift.Availability(issued: availabilityIssued, total: availabilityTotal), giftAddress: giftAddress, resellAmounts: resellAmounts, resellForTonOnly: (apiFlags & (1 << 7)) != 0, releasedBy: releasedBy?.peerId, valueAmount: valueAmount, valueCurrency: valueCurrency, flags: flags, themePeerId: themePeer?.peerId, peerColor: peerCollectibleColor, hostPeerId: hostPeerId?.peerId))
self = .unique(StarGift.UniqueGift(
id: id,
giftId: giftId,
title: title,
number: num,
slug: slug,
owner: owner,
attributes: attributes.compactMap { UniqueGift.Attribute(apiAttribute: $0)
},
availability: UniqueGift.Availability(issued: availabilityIssued, total: availabilityTotal),
giftAddress: giftAddress,
resellAmounts: resellAmounts,
resellForTonOnly: (apiFlags & (1 << 7)) != 0,
releasedBy: releasedBy?.peerId,
valueAmount: valueAmount,
valueCurrency: valueCurrency,
valueUsdAmount: valueUsdAmount,
flags: flags,
themePeerId: themePeer?.peerId,
peerColor: peerCollectibleColor,
hostPeerId: hostPeerId?.peerId,
minOfferStars: minOfferStars.flatMap { Int64($0) }
))
}
}
}
@ -1270,7 +1423,7 @@ func _internal_dropStarGiftOriginalDetails(account: Account, reference: StarGift
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags)
}
var media = currentMessage.media
if let action = media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, _, assigned) = action.action, case let .unique(uniqueGift) = gift {
if let action = media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, isPrepaidUpgrade, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate, _, assigned, fromOffer) = action.action, case let .unique(uniqueGift) = gift {
let updatedAttributes = uniqueGift.attributes.filter { $0.attributeType != .originalInfo }
media = [
TelegramMediaAction(
@ -1290,7 +1443,9 @@ func _internal_dropStarGiftOriginalDetails(account: Account, reference: StarGift
canTransferDate: canTransferDate,
canResaleDate: canResaleDate,
dropOriginalDetailsStars: nil,
assigned: assigned)
assigned: assigned,
fromOffer: fromOffer
)
)
]
}
@ -1395,7 +1550,7 @@ func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: Star
case let .updateNewMessage(message, _, _):
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: false) {
for media in message.media {
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _) = action.action, case let .Id(messageId) = message.id {
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _, _) = action.action, case let .Id(messageId) = message.id {
let reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)
@ -1422,7 +1577,8 @@ func _internal_upgradeStarGift(account: Account, formId: Int64?, reference: Star
collectionIds: nil,
prepaidUpgradeHash: nil,
upgradeSeparate: false,
dropOriginalDetailsStars: dropOriginalDetailsStars
dropOriginalDetailsStars: dropOriginalDetailsStars,
number: nil
))
}
}
@ -2376,6 +2532,7 @@ public final class ProfileGiftsContext {
case prepaidUpgradeHash
case upgradeSeparate
case dropOriginalDetailsStars
case number
}
public let gift: TelegramCore.StarGift
@ -2398,6 +2555,7 @@ public final class ProfileGiftsContext {
public let prepaidUpgradeHash: String?
public let upgradeSeparate: Bool
public let dropOriginalDetailsStars: Int64?
public let number: Int32?
fileprivate let _fromPeerId: EnginePeer.Id?
@ -2425,7 +2583,8 @@ public final class ProfileGiftsContext {
collectionIds: [Int32]?,
prepaidUpgradeHash: String?,
upgradeSeparate: Bool,
dropOriginalDetailsStars: Int64?
dropOriginalDetailsStars: Int64?,
number: Int32?
) {
self.gift = gift
self.reference = reference
@ -2448,6 +2607,7 @@ public final class ProfileGiftsContext {
self.prepaidUpgradeHash = prepaidUpgradeHash
self.upgradeSeparate = upgradeSeparate
self.dropOriginalDetailsStars = dropOriginalDetailsStars
self.number = number
}
public init(from decoder: Decoder) throws {
@ -2480,6 +2640,7 @@ public final class ProfileGiftsContext {
self.prepaidUpgradeHash = try container.decodeIfPresent(String.self, forKey: .prepaidUpgradeHash)
self.upgradeSeparate = try container.decodeIfPresent(Bool.self, forKey: .upgradeSeparate) ?? false
self.dropOriginalDetailsStars = try container.decodeIfPresent(Int64.self, forKey: .dropOriginalDetailsStars)
self.number = try container.decodeIfPresent(Int32.self, forKey: .number)
}
public func encode(to encoder: Encoder) throws {
@ -2505,6 +2666,7 @@ public final class ProfileGiftsContext {
try container.encodeIfPresent(self.prepaidUpgradeHash, forKey: .prepaidUpgradeHash)
try container.encode(self.upgradeSeparate, forKey: .upgradeSeparate)
try container.encodeIfPresent(self.dropOriginalDetailsStars, forKey: .dropOriginalDetailsStars)
try container.encodeIfPresent(self.number, forKey: .number)
}
public func withGift(_ gift: TelegramCore.StarGift) -> StarGift {
@ -2528,7 +2690,8 @@ public final class ProfileGiftsContext {
collectionIds: self.collectionIds,
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
)
}
@ -2553,7 +2716,8 @@ public final class ProfileGiftsContext {
collectionIds: self.collectionIds,
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
)
}
@ -2578,7 +2742,8 @@ public final class ProfileGiftsContext {
collectionIds: self.collectionIds,
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
)
}
fileprivate func withFromPeer(_ fromPeer: EnginePeer?) -> StarGift {
@ -2602,7 +2767,8 @@ public final class ProfileGiftsContext {
collectionIds: self.collectionIds,
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
)
}
@ -2627,7 +2793,8 @@ public final class ProfileGiftsContext {
collectionIds: collectionIds,
prepaidUpgradeHash: self.prepaidUpgradeHash,
upgradeSeparate: self.upgradeSeparate,
dropOriginalDetailsStars: self.dropOriginalDetailsStars
dropOriginalDetailsStars: self.dropOriginalDetailsStars,
number: self.number
)
}
}
@ -2845,7 +3012,7 @@ public final class ProfileGiftsContext {
extension ProfileGiftsContext.State.StarGift {
init?(apiSavedStarGift: Api.SavedStarGift, peerId: EnginePeer.Id, transaction: Transaction) {
switch apiSavedStarGift {
case let .savedStarGift(flags, fromId, date, apiGift, message, msgId, savedId, convertStars, upgradeStars, canExportDate, transferStars, canTransferAt, canResaleAt, collectionIds, prepaidUpgradeHash, dropOriginalDetailsStars):
case let .savedStarGift(flags, fromId, date, apiGift, message, msgId, savedId, convertStars, upgradeStars, canExportDate, transferStars, canTransferAt, canResaleAt, collectionIds, prepaidUpgradeHash, dropOriginalDetailsStars, number):
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
@ -2895,6 +3062,7 @@ extension ProfileGiftsContext.State.StarGift {
self.prepaidUpgradeHash = prepaidUpgradeHash
self.upgradeSeparate = (flags & (1 << 17)) != 0
self.dropOriginalDetailsStars = dropOriginalDetailsStars
self.number = number
}
}
}
@ -2962,8 +3130,6 @@ func _internal_getUniqueStarGiftValueInfo(account: Account, slug: String) -> Sig
if let result {
switch result {
case let .uniqueStarGiftValueInfo(flags, currency, value, initialSaleDate, initialSaleStars, initialSalePrice, lastSaleDate, lastSalePrice, floorPrice, averagePrice, listedCount, fragmentListedCount, fragmentListedUrl):
let _ = listedCount
let _ = fragmentListedCount
return StarGift.UniqueGift.ValueInfo(
isLastSaleOnFragment: flags & (1 << 1) != 0,
valueIsAverage: flags & (1 << 6) != 0,
@ -3623,3 +3789,65 @@ public final class ResaleGiftsContext {
return state
}
}
func giftUpgradesId(giftId: Int64) -> ItemCacheEntryId {
let cacheKey = ValueBoxKey(length: 8)
cacheKey.setInt64(0, value: giftId)
return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedGiftUpgradesAttributes, key: cacheKey)
}
final class CachedStartGiftUpgradeAttributes: Codable {
enum CodingKeys: String, CodingKey {
case attributes
}
var attributes: [StarGift.UniqueGift.Attribute]
init(attributes: [StarGift.UniqueGift.Attribute]) {
self.attributes = attributes
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.attributes = try container.decode([StarGift.UniqueGift.Attribute].self, forKey: .attributes)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.attributes, forKey: .attributes)
}
}
func _internal_getStarGiftUpgradeAttributes(account: Account, giftId: Int64) -> Signal<[StarGift.UniqueGift.Attribute]?, NoError> {
return account.postbox.transaction { transaction in
if let cachedGifts = transaction.retrieveItemCacheEntry(id: giftUpgradesId(giftId: giftId))?.get(CachedStartGiftUpgradeAttributes.self) {
return .single(cachedGifts.attributes)
} else {
return account.network.request(Api.functions.payments.getStarGiftUpgradeAttributes(giftId: giftId))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.payments.StarGiftUpgradeAttributes?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<[StarGift.UniqueGift.Attribute]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case let .starGiftUpgradeAttributes(apiAttributes):
let attributes = apiAttributes.compactMap { StarGift.UniqueGift.Attribute(apiAttribute: $0) }
return account.postbox.transaction { transaction in
if !attributes.isEmpty {
if let entry = CodableEntry(CachedStartGiftUpgradeAttributes(attributes: attributes)) {
transaction.putItemCacheEntry(id: giftUpgradesId(giftId: giftId), entry: entry)
}
}
return attributes
}
}
}
}
}
|> switchToLatest
}

View file

@ -30,8 +30,8 @@ private func _internal_getStarGiftAuctionState(postbox: Postbox, network: Networ
}
return postbox.transaction { transaction -> (gift: StarGift, state: GiftAuctionContext.State.AuctionState?, myState: GiftAuctionContext.State.MyState, timeout: Int32)? in
switch result {
case let .starGiftAuctionState(apiGift, state, userState, timeout, users):
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(users: users))
case let .starGiftAuctionState(apiGift, state, userState, timeout, users, chats):
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: AccumulatedPeers(chats: chats, users: users))
guard let gift = StarGift(apiStarGift: apiGift) else {
return nil
}
@ -54,9 +54,28 @@ public final class GiftAuctionContext {
public var date: Int32
}
public enum Round: Equatable {
case generic(num: Int32, duration: Int32)
case extendable(num: Int32, duration: Int32, extendTop: Int32, extendWindow: Int32)
public var num: Int32 {
switch self {
case let .generic(num, _), let .extendable(num, _, _, _):
return num
}
}
public var duration: Int32 {
switch self {
case let .generic(_, duration), let .extendable(_, duration, _, _):
return duration
}
}
}
public enum AuctionState: Equatable {
case ongoing(version: Int32, startDate: Int32, endDate: Int32, minBidAmount: Int64, bidLevels: [BidLevel], topBidders: [EnginePeer], nextRoundDate: Int32, giftsLeft: Int32, currentRound: Int32, totalRounds: Int32)
case finished(startDate: Int32, endDate: Int32, averagePrice: Int64)
case ongoing(version: Int32, startDate: Int32, endDate: Int32, minBidAmount: Int64, bidLevels: [BidLevel], topBidders: [EnginePeer], nextRoundDate: Int32, giftsLeft: Int32, currentRound: Int32, totalRounds: Int32, rounds: [Round], lastGiftNumber: Int32)
case finished(startDate: Int32, endDate: Int32, averagePrice: Int64, listedCount: Int32?, fragmentListedCount: Int32?, fragmentListedUrl: String?)
}
public struct MyState: Equatable {
@ -114,6 +133,15 @@ public final class GiftAuctionContext {
}
}
public var isUpcoming: Bool {
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
if case let .ongoing(_, startTime, _, _, _, _, _, _, _, _, _, _) = self.auctionState {
return currentTime < startTime
} else {
return false
}
}
public convenience init(account: Account, gift: StarGift) {
self.init(account: account, gift: gift, initialAuctionState: nil, initialMyState: nil, initialTimeout: nil)
}
@ -136,7 +164,7 @@ public final class GiftAuctionContext {
private var currentVersion: Int32 {
var currentVersion: Int32 = 0
if case let .ongoing(version, _, _, _, _, _, _, _, _, _) = self.auctionState {
if case let .ongoing(version, _, _, _, _, _, _, _, _, _, _, _) = self.auctionState {
currentVersion = version
}
return currentVersion
@ -154,7 +182,7 @@ public final class GiftAuctionContext {
return
}
if case let .ongoing(version, _, _, _, _, _, _, _, _, _) = auctionState, version < self.currentVersion {
if case let .ongoing(version, _, _, _, _, _, _, _, _, _, _, _) = auctionState, version < self.currentVersion {
} else if let auctionState {
self.auctionState = auctionState
}
@ -163,7 +191,7 @@ public final class GiftAuctionContext {
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
var effectiveTimeout = timeout
if case let .ongoing(_, _, _, _, _, _, nextRoundDate, _, _, _) = auctionState {
if case let .ongoing(_, _, _, _, _, _, nextRoundDate, _, _, _, _, _) = auctionState {
let delta = nextRoundDate - currentTime
if delta > 0 && delta < timeout {
effectiveTimeout = delta
@ -184,7 +212,7 @@ public final class GiftAuctionContext {
}
func updateAuctionState(_ auctionState: GiftAuctionContext.State.AuctionState) {
if case let .ongoing(version, _, _, _, _, _, _, _, _, _) = auctionState, version < self.currentVersion {
if case let .ongoing(version, _, _, _, _, _, _, _, _, _, _, _) = auctionState, version < self.currentVersion {
} else {
self.auctionState = auctionState
}
@ -225,16 +253,45 @@ extension GiftAuctionContext.State.BidLevel {
extension GiftAuctionContext.State.AuctionState {
init?(apiAuctionState: Api.StarGiftAuctionState, peers: [PeerId: Peer]) {
switch apiAuctionState {
case let .starGiftAuctionState(version, startDate, endDate, minBidAmount, bidLevels, topBiddersPeerIds, nextRoundAt, giftsLeft, currentRound, totalRounds):
case let .starGiftAuctionState(version, startDate, endDate, minBidAmount, bidLevels, topBiddersPeerIds, nextRoundAt, lastGiftNumber, giftsLeft, currentRound, totalRounds, apiRounds):
var topBidders: [EnginePeer] = []
for peerId in topBiddersPeerIds {
if let peer = peers[PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(peerId))] {
topBidders.append(EnginePeer(peer))
}
}
self = .ongoing(version: version, startDate: startDate, endDate: endDate, minBidAmount: minBidAmount, bidLevels: bidLevels.map(GiftAuctionContext.State.BidLevel.init(apiBidLevel:)), topBidders: topBidders, nextRoundDate: nextRoundAt, giftsLeft: giftsLeft, currentRound: currentRound, totalRounds: totalRounds)
case let .starGiftAuctionStateFinished(startDate, endDate, averagePrice):
self = .finished(startDate: startDate, endDate: endDate, averagePrice: averagePrice)
var rounds: [GiftAuctionContext.State.Round] = []
for apiRound in apiRounds {
switch apiRound {
case let .starGiftAuctionRound(num, duration):
rounds.append(.generic(num: num, duration: duration))
case let .starGiftAuctionRoundExtendable(num, duration, extendTop, extendWindow):
rounds.append(.extendable(num: num, duration: duration, extendTop: extendTop, extendWindow: extendWindow))
}
}
self = .ongoing(
version: version,
startDate: startDate,
endDate: endDate,
minBidAmount: minBidAmount,
bidLevels: bidLevels.map(GiftAuctionContext.State.BidLevel.init(apiBidLevel:)),
topBidders: topBidders,
nextRoundDate: nextRoundAt,
giftsLeft: giftsLeft,
currentRound: currentRound,
totalRounds: totalRounds,
rounds: rounds,
lastGiftNumber: lastGiftNumber
)
case let .starGiftAuctionStateFinished(_, startDate, endDate, averagePrice, listedCount, fragmentListedCount, fragmentListedUrl):
self = .finished(
startDate: startDate,
endDate: endDate,
averagePrice: averagePrice,
listedCount: listedCount,
fragmentListedCount: fragmentListedCount,
fragmentListedUrl: fragmentListedUrl
)
case .starGiftAuctionStateNotModified:
return nil
}
@ -242,16 +299,45 @@ extension GiftAuctionContext.State.AuctionState {
init?(apiAuctionState: Api.StarGiftAuctionState, transaction: Transaction) {
switch apiAuctionState {
case let .starGiftAuctionState(version, startDate, endDate, minBidAmount, bidLevels, topBiddersPeerIds, nextRoundAt, giftsLeft, currentRound, totalRounds):
case let .starGiftAuctionState(version, startDate, endDate, minBidAmount, bidLevels, topBiddersPeerIds, nextRoundAt, lastGiftNumber, giftsLeft, currentRound, totalRounds, apiRounds):
var topBidders: [EnginePeer] = []
for peerId in topBiddersPeerIds {
if let peer = transaction.getPeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(peerId))) {
topBidders.append(EnginePeer(peer))
}
}
self = .ongoing(version: version, startDate: startDate, endDate: endDate, minBidAmount: minBidAmount, bidLevels: bidLevels.map(GiftAuctionContext.State.BidLevel.init(apiBidLevel:)), topBidders: topBidders, nextRoundDate: nextRoundAt, giftsLeft: giftsLeft, currentRound: currentRound, totalRounds: totalRounds)
case let .starGiftAuctionStateFinished(startDate, endDate, averagePrice):
self = .finished(startDate: startDate, endDate: endDate, averagePrice: averagePrice)
var rounds: [GiftAuctionContext.State.Round] = []
for apiRound in apiRounds {
switch apiRound {
case let .starGiftAuctionRound(num, duration):
rounds.append(.generic(num: num, duration: duration))
case let .starGiftAuctionRoundExtendable(num, duration, extendTop, extendWindow):
rounds.append(.extendable(num: num, duration: duration, extendTop: extendTop, extendWindow: extendWindow))
}
}
self = .ongoing(
version: version,
startDate: startDate,
endDate: endDate,
minBidAmount: minBidAmount,
bidLevels: bidLevels.map(GiftAuctionContext.State.BidLevel.init(apiBidLevel:)),
topBidders: topBidders,
nextRoundDate: nextRoundAt,
giftsLeft: giftsLeft,
currentRound: currentRound,
totalRounds: totalRounds,
rounds: rounds,
lastGiftNumber: lastGiftNumber
)
case let .starGiftAuctionStateFinished(_, startDate, endDate, averagePrice, listedCount, fragmentListedCount, fragmentListedUrl):
self = .finished(
startDate: startDate,
endDate: endDate,
averagePrice: averagePrice,
listedCount: listedCount,
fragmentListedCount: fragmentListedCount,
fragmentListedUrl: fragmentListedUrl
)
case .starGiftAuctionStateNotModified:
return nil
}
@ -281,6 +367,7 @@ public struct GiftAuctionAcquiredGift: Equatable {
public let position: Int32
public let text: String?
public let entities: [MessageTextEntity]?
public let number: Int32?
}
func _internal_getGiftAuctionAcquiredGifts(account: Account, giftId: Int64) -> Signal<[GiftAuctionAcquiredGift], NoError> {
@ -302,7 +389,7 @@ func _internal_getGiftAuctionAcquiredGifts(account: Account, giftId: Int64) -> S
var mappedGifts: [GiftAuctionAcquiredGift] = []
for gift in gifts {
switch gift {
case let .starGiftAuctionAcquiredGift(flags, peerId, date, bidAmount, round, pos, message):
case let .starGiftAuctionAcquiredGift(flags, peerId, date, bidAmount, round, pos, message, number):
if let peer = transaction.getPeer(peerId.peerId) {
var text: String?
var entities: [MessageTextEntity]?
@ -321,7 +408,8 @@ func _internal_getGiftAuctionAcquiredGifts(account: Account, giftId: Int64) -> S
round: round,
position: pos,
text: text,
entities: entities
entities: entities,
number: number
))
}
}
@ -338,8 +426,8 @@ func _internal_getActiveGiftAuctions(account: Account, hash: Int64) -> Signal<[G
|> mapToSignal { result in
return account.postbox.transaction { transaction -> [GiftAuctionContext]? in
switch result {
case let .starGiftActiveAuctions(auctions, users):
let parsedPeers = AccumulatedPeers(users: users)
case let .starGiftActiveAuctions(auctions, users, chats):
let parsedPeers = AccumulatedPeers(chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: parsedPeers)
var auctionContexts: [GiftAuctionContext] = []
@ -493,7 +581,7 @@ public class GiftAuctionsManager {
public extension GiftAuctionContext.State {
func getPlace(myBid: Int64?, myBidDate: Int32?) -> Int32? {
guard case let .ongoing(_, _, _, _, bidLevels, _, _, _, _, _) = self.auctionState else {
guard case let .ongoing(_, _, _, _, bidLevels, _, _, _, _, _, _, _) = self.auctionState else {
return nil
}
guard let myBid = myBid ?? self.myState.bidAmount else {
@ -550,18 +638,18 @@ public extension GiftAuctionContext.State {
var startDate: Int32 {
switch self.auctionState {
case let .ongoing(_, startDate, _, _, _, _, _, _, _, _):
case let .ongoing(_, startDate, _, _, _, _, _, _, _, _, _, _):
return startDate
case let .finished(startDate, _, _):
case let .finished(startDate, _, _, _, _, _):
return startDate
}
}
var endDate: Int32 {
switch self.auctionState {
case let .ongoing(_, _, endDate, _, _, _, _, _, _, _):
case let .ongoing(_, _, endDate, _, _, _, _, _, _, _, _, _):
return endDate
case let .finished(_, endDate, _):
case let .finished(_, endDate, _, _, _, _):
return endDate
}
}

View file

@ -0,0 +1,55 @@
import Foundation
import Postbox
import MtProtoKit
import SwiftSignalKit
import TelegramApi
public enum ResolveStarGiftOfferError {
case generic
}
func _internal_resolveStarGiftOffer(account: Account, messageId: EngineMessage.Id, accept: Bool) -> Signal<Never, ResolveStarGiftOfferError> {
var flags: Int32 = 0
if !accept {
flags |= (1 << 0)
}
return account.network.request(Api.functions.payments.resolveStarGiftOffer(flags: flags, offerMsgId: messageId.id))
|> mapError { _ -> ResolveStarGiftOfferError in
return .generic
}
|> mapToSignal { updates -> Signal<Never, ResolveStarGiftOfferError> in
account.stateManager.addUpdates(updates)
return .complete()
}
|> ignoreValues
}
public enum SendStarGiftOfferError {
case generic
}
func _internal_sendStarGiftOffer(account: Account, peerId: EnginePeer.Id, slug: String, amount: CurrencyAmount, duration: Int32, allowPaidStars: Int64?) -> Signal<Never, SendStarGiftOfferError> {
var flags: Int32 = 0
if let _ = allowPaidStars {
flags |= (1 << 0)
}
return account.postbox.transaction { transaction in
return transaction.getPeer(peerId).flatMap(apiInputPeer)
}
|> castError(SendStarGiftOfferError.self)
|> mapToSignal { inputPeer -> Signal<Never, SendStarGiftOfferError> in
guard let inputPeer else {
return .fail(.generic)
}
return account.network.request(Api.functions.payments.sendStarGiftOffer(flags: flags, peer: inputPeer, slug: slug, price: amount.apiAmount, duration: duration, randomId: Int64.random(in: .min ..< .max), allowPaidStars: allowPaidStars))
|> mapError { _ -> SendStarGiftOfferError in
return .generic
}
|> mapToSignal { updates -> Signal<Never, SendStarGiftOfferError> in
account.stateManager.addUpdates(updates)
return .complete()
}
}
|> ignoreValues
}

View file

@ -735,6 +735,9 @@ private extension StarsContext.State.Transaction {
if (apiFlags & (1 << 28)) != 0 {
flags.insert(.isStarGiftAuctionBid)
}
if (apiFlags & (1 << 29)) != 0 {
flags.insert(.isStarGiftOffer)
}
let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
@ -793,6 +796,7 @@ public final class StarsContext {
public static let isStarGiftDropOriginalDetails = Flags(rawValue: 1 << 12)
public static let isStarGiftAuctionBid = Flags(rawValue: 1 << 13)
public static let isLiveStreamPaidMessage = Flags(rawValue: 1 << 14)
public static let isStarGiftOffer = Flags(rawValue: 1 << 15)
}
public enum Peer: Equatable {
@ -1640,7 +1644,7 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
case .giftCode, .stars, .starsGift, .starsChatSubscription, .starGift, .starGiftUpgrade, .starGiftTransfer, .premiumGift, .starGiftResale, .starGiftPrepaidUpgrade, .starGiftDropOriginalDetails, .starGiftAuctionBid:
receiptMessageId = nil
}
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _) = action.action, case let .Id(messageId) = message.id {
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _, _) = action.action, case let .Id(messageId) = message.id {
let reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)
@ -1667,7 +1671,8 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
collectionIds: nil,
prepaidUpgradeHash: nil,
upgradeSeparate: false,
dropOriginalDetailsStars: dropOriginalDetailsStars
dropOriginalDetailsStars: dropOriginalDetailsStars,
number: nil
)
}
}

View file

@ -180,6 +180,18 @@ public extension TelegramEngine {
public func getStarsTransaction(reference: StarsTransactionReference) -> Signal<StarsContext.State.Transaction?, NoError> {
return _internal_getStarsTransaction(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, transactionReference: reference)
}
public func resolveStarGiftOffer(messageId: EngineMessage.Id, accept: Bool) -> Signal<Never, ResolveStarGiftOfferError> {
return _internal_resolveStarGiftOffer(account: self.account, messageId: messageId, accept: accept)
}
public func sendStarGiftOffer(peerId: EnginePeer.Id, slug: String, amount: CurrencyAmount, duration: Int32, allowPaidStars: Int64?) -> Signal<Never, SendStarGiftOfferError> {
return _internal_sendStarGiftOffer(account: self.account, peerId: peerId, slug: slug, amount: amount, duration: duration, allowPaidStars: allowPaidStars)
}
public func getStarGiftUpgradeAttributes(giftId: Int64) -> Signal<[StarGift.UniqueGift.Attribute]?, NoError> {
return _internal_getStarGiftUpgradeAttributes(account: self.account, giftId: giftId)
}
}
}

View file

@ -1171,7 +1171,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = mutableString
case .prizeStars:
attributedString = NSAttributedString(string: strings.Notification_StarsPrize, font: titleFont, textColor: primaryTextColor)
case let .starGift(gift, _, text, entities, _, _, _, _, _, upgradeStars, _, isPrepaidUpgrade, _, peerId, senderId, _, _, _, upgradeSeparate, isAuctionAcquired, _):
case let .starGift(gift, _, text, entities, _, _, _, _, _, upgradeStars, _, isPrepaidUpgrade, _, peerId, senderId, _, _, _, upgradeSeparate, isAuctionAcquired, _, _):
if !forAdditionalServiceMessage {
if let text {
let mutableAttributedString = NSMutableAttributedString(attributedString: stringWithAppliedEntities(text, entities: entities ?? [], baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false, message: message._asMessage()))
@ -1262,7 +1262,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Sent(authorName, starsPrice)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
}
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, isPrepaidUpgrade, peerId, senderId, _, resaleStars, _, _, _, assigned):
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, isPrepaidUpgrade, peerId, senderId, _, resaleStars, _, _, _, assigned, fromOffer):
if case let .unique(gift) = gift {
if !forAdditionalServiceMessage && !"".isEmpty {
attributedString = NSAttributedString(string: "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))", font: titleFont, textColor: primaryTextColor)
@ -1290,7 +1290,33 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
}
}
} else {
if message.id.peerId == accountPeerId && assigned {
if fromOffer, let resaleStars {
let starsString: String
switch resaleStars.currency {
case .stars:
starsString = strings.Notification_StarsGiftOffer_Accepted_Stars(Int32(clamping: resaleStars.amount.value))
case .ton:
starsString = formatTonAmountText(resaleStars.amount.value, dateTimeFormat: dateTimeFormat) + " TON"
}
let giftTitle = "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))"
var peerName = ""
if let name = message.peers[message.id.peerId].flatMap(EnginePeer.init)?.compactDisplayTitle {
peerName = name
}
if message.author?.id == accountPeerId {
let peerIds: [(Int, EnginePeer.Id?)] = [(1, message.id.peerId)]
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[0] = boldAttributes
attributes[2] = boldAttributes
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_AcceptedYou(giftTitle, peerName, starsString)._tuple, body: bodyAttributes, argumentAttributes: attributes)
} else {
let peerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)]
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[1] = boldAttributes
attributes[2] = boldAttributes
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_Accepted(peerName, giftTitle, starsString)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
} else if message.id.peerId == accountPeerId && assigned {
let attributes: [Int: MarkdownAttributeSet] = [0: boldAttributes]
let giftTitle = "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))"
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Assigned(giftTitle)._tuple, body: bodyAttributes, argumentAttributes: attributes)
@ -1616,6 +1642,103 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Sent(authorName, price)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
}
case let .starGiftPurchaseOffer(gift, amount, _, _, _):
let peerName = message.peers[message.id.peerId].flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
let giftTitle: String
if case let .unique(gift) = gift {
giftTitle = "\(gift.title) #\(formatCollectibleNumber(gift.number, dateTimeFormat: dateTimeFormat))"
} else {
giftTitle = ""
}
let peerIds: [(Int, EnginePeer.Id?)] = [(0, message.id.peerId)]
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[1] = boldAttributes
attributes[2] = boldAttributes
if message.author?.id == accountPeerId {
let priceString: String
switch amount.currency {
case .stars:
priceString = strings.Notification_StarsGiftOffer_OfferYou_Stars(Int32(clamping: amount.amount.value))
case .ton:
priceString = "\(amount.amount) TON"
}
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_OfferYou(peerName, priceString, giftTitle)._tuple, body: bodyAttributes, argumentAttributes: attributes)
} else {
let priceString: String
switch amount.currency {
case .stars:
priceString = strings.Notification_StarsGiftOffer_Offer_Stars(Int32(clamping: amount.amount.value))
case .ton:
priceString = "\(amount.amount) TON"
}
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_Offer(peerName, priceString, giftTitle)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
case let .starGiftPurchaseOfferDeclined(gift, amount, hasExpired):
let peerName = message.peers[message.id.peerId].flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
let peerIds: [(Int, EnginePeer.Id?)] = [(0, message.id.peerId)]
let giftTitle: String
if case let .unique(gift) = gift {
giftTitle = "\(gift.title) #\(formatCollectibleNumber(gift.number, dateTimeFormat: dateTimeFormat))"
} else {
giftTitle = ""
}
if hasExpired {
if message.author?.id == accountPeerId {
let priceString: String
switch amount.currency {
case .stars:
priceString = strings.Notification_StarsGiftOffer_ExpiredYou_Stars(Int32(clamping: amount.amount.value))
case .ton:
priceString = "\(amount.amount) TON"
}
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[1] = boldAttributes
attributes[2] = boldAttributes
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_ExpiredYou(peerName, giftTitle, priceString)._tuple, body: bodyAttributes, argumentAttributes: attributes)
} else {
let priceString: String
switch amount.currency {
case .stars:
priceString = strings.Notification_StarsGiftOffer_Expired_Stars(Int32(clamping: amount.amount.value))
case .ton:
priceString = "\(amount.amount) TON"
}
let timeString = "[TODO]"
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[1] = boldAttributes
attributes[2] = boldAttributes
attributes[3] = boldAttributes
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_Expired(peerName, giftTitle, timeString, priceString)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
} else {
if message.author?.id == accountPeerId {
let attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_RejectedYou(peerName)._tuple, body: bodyAttributes, argumentAttributes: attributes)
} else {
let priceString: String
switch amount.currency {
case .stars:
priceString = strings.Notification_StarsGiftOffer_Rejected_Stars(Int32(clamping: amount.amount.value))
case .ton:
priceString = "\(amount.amount) TON"
}
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
attributes[1] = boldAttributes
attributes[2] = boldAttributes
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGiftOffer_Rejected(peerName, giftTitle, priceString)._tuple, body: bodyAttributes, argumentAttributes: attributes)
}
}
case .unknown:
attributedString = nil
}

View file

@ -402,6 +402,7 @@ swift_library(
"//submodules/TelegramUI/Components/Chat/ChatMessageUnsupportedBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageWallpaperBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageGiftBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageGiftOfferBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageGiveawayBubbleContentNode",
"//submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode",
"//submodules/TelegramUI/Components/Chat/ChatRecentActionsController",
@ -497,6 +498,8 @@ swift_library(
"//submodules/TelegramUI/Components/AttachmentFileController",
"//submodules/TelegramUI/Components/Contacts/NewContactScreen",
"//submodules/TelegramUI/Components/Chat/ChatSendAsContextMenu",
"//submodules/TelegramUI/Components/Settings/PasskeysScreen",
"//submodules/TelegramUI/Components/Gifts/GiftDemoScreen",
] + select({
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
"//build-system:ios_sim_arm64": [],

View file

@ -108,6 +108,7 @@ final class AdminUserActionsPeerComponent: Component {
private weak var state: EmptyComponentState?
public var customUpdateIsHighlighted: ((Bool) -> Void)?
public var enumerateSiblings: (((UIView) -> Void) -> Void)?
public var separatorInset: CGFloat = 0.0
override init(frame: CGRect) {

Some files were not shown because too many files have changed in this diff Show more