mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-11 11:13:29 +00:00
Merge commit '8d5dc7ff600836a88d23777def61e556d15eb7cd'
This commit is contained in:
commit
0d2cffb033
@ -14700,6 +14700,9 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"AccessDenied.AgeVerificationCamera" = "Telegram needs access to your camera for age verification.\n\nOpen your device's Settings > Privacy > Camera and set Telegram to ON.";
|
"AccessDenied.AgeVerificationCamera" = "Telegram needs access to your camera for age verification.\n\nOpen your device's Settings > Privacy > Camera and set Telegram to ON.";
|
||||||
|
|
||||||
|
"PeerInfo.Gifts.Collections.All" = "All Gifts";
|
||||||
|
"PeerInfo.Gifts.Collections.Add" = "Add Collection";
|
||||||
|
|
||||||
"PeerInfo.Gifts.AddGiftsButton" = "Add Gifts";
|
"PeerInfo.Gifts.AddGiftsButton" = "Add Gifts";
|
||||||
|
|
||||||
"PeerInfo.Gifts.AddCollection" = "Add Collection";
|
"PeerInfo.Gifts.AddCollection" = "Add Collection";
|
||||||
@ -14728,6 +14731,12 @@ Sorry for the inconvenience.";
|
|||||||
"PeerInfo.Gifts.EmptyCollection.Text" = "Add some gifts to this collection.";
|
"PeerInfo.Gifts.EmptyCollection.Text" = "Add some gifts to this collection.";
|
||||||
"PeerInfo.Gifts.EmptyCollection.Action" = "Add to Collection";
|
"PeerInfo.Gifts.EmptyCollection.Action" = "Add to Collection";
|
||||||
|
|
||||||
|
"PeerInfo.Gifts.AddedToCollection" = "The gift has been added to **%@**.";
|
||||||
|
"PeerInfo.Gifts.RemovedFromCollection" = "The gift has been removed from **%@**.";
|
||||||
|
|
||||||
|
"PeerInfo.Gifts.AddedToCollectionUnique" = "**%1$@** has been added to **%2$@**.";
|
||||||
|
"PeerInfo.Gifts.RemovedFromCollectionUnique" = "**%1$@** has been removed from **%2$@**.";
|
||||||
|
|
||||||
"AddGifts.Title" = "Add Gifts";
|
"AddGifts.Title" = "Add Gifts";
|
||||||
"AddGifts.AddGifts_1" = "Add %@ Gift";
|
"AddGifts.AddGifts_1" = "Add %@ Gift";
|
||||||
"AddGifts.AddGifts_any" = "Add %@ Gifts";
|
"AddGifts.AddGifts_any" = "Add %@ Gifts";
|
||||||
@ -14736,10 +14745,13 @@ Sorry for the inconvenience.";
|
|||||||
"Gift.Options.Gift.BuyLimitReached_any" = "You've already sent %@ of these gifts, and it's the limit.";
|
"Gift.Options.Gift.BuyLimitReached_any" = "You've already sent %@ of these gifts, and it's the limit.";
|
||||||
|
|
||||||
"AgeVerification.Title" = "Age Verification";
|
"AgeVerification.Title" = "Age Verification";
|
||||||
"AgeVerification.Text" = "To access this content, you must confirm you are at least **18** years old as required by UK law.\n\nThis is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
"AgeVerification.Text" = "To access this content, you must confirm you are at least **18** years old.\n\nThis is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
||||||
"AgeVerification.Text.gb" = "To access this content, you must confirm you are at least **18** years old as required by UK law.\n\nThis is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
"AgeVerification.Text.GB" = "To access this content, you must confirm you are at least **18** years old as required by UK law.\n\nThis is a one-time process using your phone's camera. Your selfie will not be stored by Telegram.";
|
||||||
"AgeVerification.Verify" = "Verify My Age";
|
"AgeVerification.Verify" = "Verify My Age";
|
||||||
|
|
||||||
|
"AgeVerification.Unavailable.Title" = "18+";
|
||||||
|
"AgeVerification.Unavailable.Text" = "This media may contain sensitive content suitable only for adults.";
|
||||||
|
|
||||||
"AgeVerification.Success.Title" = "Age check passed!";
|
"AgeVerification.Success.Title" = "Age check passed!";
|
||||||
"AgeVerification.Success.Text" = "You can now view this content.";
|
"AgeVerification.Success.Text" = "You can now view this content.";
|
||||||
|
|
||||||
|
|||||||
@ -1296,7 +1296,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
|
|
||||||
func makeIncomingMessagePrivacyScreen(context: AccountContext, value: GlobalPrivacySettings.NonContactChatsPrivacy, exceptions: SelectivePrivacySettings, update: @escaping (GlobalPrivacySettings.NonContactChatsPrivacy) -> Void) -> 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?)
|
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 makeAffiliateProgramSetupScreenInitialData(context: AccountContext, peerId: EnginePeer.Id, mode: AffiliateProgramSetupScreenMode) -> Signal<AffiliateProgramSetupScreenInitialData, NoError>
|
||||||
func makeAffiliateProgramSetupScreen(context: AccountContext, initialData: AffiliateProgramSetupScreenInitialData) -> ViewController
|
func makeAffiliateProgramSetupScreen(context: AccountContext, initialData: AffiliateProgramSetupScreenInitialData) -> ViewController
|
||||||
|
|||||||
@ -12,6 +12,7 @@ public final class BotCheckoutController: ViewController {
|
|||||||
public enum FetchError {
|
public enum FetchError {
|
||||||
case generic
|
case generic
|
||||||
case disallowedStarGifts
|
case disallowedStarGifts
|
||||||
|
case starGiftsUserLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
public let form: BotPaymentForm
|
public let form: BotPaymentForm
|
||||||
@ -58,6 +59,8 @@ public final class BotCheckoutController: ViewController {
|
|||||||
switch error {
|
switch error {
|
||||||
case .disallowedStarGift:
|
case .disallowedStarGift:
|
||||||
return .disallowedStarGifts
|
return .disallowedStarGifts
|
||||||
|
case .starGiftUserLimit:
|
||||||
|
return .starGiftsUserLimit
|
||||||
default:
|
default:
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1250,7 +1250,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
simple: true,
|
simple: true,
|
||||||
source: .generic,
|
source: .generic,
|
||||||
skipTermsOfService: true,
|
skipTermsOfService: true,
|
||||||
payload: nil
|
payload: nil,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3282,7 +3282,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
simple: true,
|
simple: true,
|
||||||
source: .generic,
|
source: .generic,
|
||||||
skipTermsOfService: true,
|
skipTermsOfService: true,
|
||||||
payload: nil
|
payload: nil,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
)
|
)
|
||||||
interaction.dismissSearch()
|
interaction.dismissSearch()
|
||||||
}
|
}
|
||||||
@ -4268,7 +4269,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
simple: true,
|
simple: true,
|
||||||
source: .generic,
|
source: .generic,
|
||||||
skipTermsOfService: true,
|
skipTermsOfService: true,
|
||||||
payload: nil
|
payload: nil,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4287,7 +4289,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
simple: true,
|
simple: true,
|
||||||
source: .generic,
|
source: .generic,
|
||||||
skipTermsOfService: true,
|
skipTermsOfService: true,
|
||||||
payload: nil
|
payload: nil,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
)
|
)
|
||||||
interaction.dismissSearch()
|
interaction.dismissSearch()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -871,7 +871,7 @@
|
|||||||
|
|
||||||
if (_intent == TGMediaAssetsControllerSendMediaIntent && _selectionContext.allowGrouping)
|
if (_intent == TGMediaAssetsControllerSendMediaIntent && _selectionContext.allowGrouping)
|
||||||
[[NSUserDefaults standardUserDefaults] setObject:@(!_selectionContext.grouping) forKey:@"TG_mediaGroupingDisabled_v0"];
|
[[NSUserDefaults standardUserDefaults] setObject:@(!_selectionContext.grouping) forKey:@"TG_mediaGroupingDisabled_v0"];
|
||||||
|
|
||||||
return [TGMediaAssetsController resultSignalsForSelectionContext:_selectionContext editingContext:_editingContext intent:_intent currentItem:currentItem storeAssets:storeAssets convertToJpeg:false descriptionGenerator:descriptionGenerator saveEditedPhotos:_saveEditedPhotos];
|
return [TGMediaAssetsController resultSignalsForSelectionContext:_selectionContext editingContext:_editingContext intent:_intent currentItem:currentItem storeAssets:storeAssets convertToJpeg:false descriptionGenerator:descriptionGenerator saveEditedPhotos:_saveEditedPhotos];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -889,6 +889,9 @@
|
|||||||
if (selectedItems.count == 0 && currentItem != nil)
|
if (selectedItems.count == 0 && currentItem != nil)
|
||||||
[selectedItems addObject:currentItem];
|
[selectedItems addObject:currentItem];
|
||||||
|
|
||||||
|
if (intent == TGMediaAssetsControllerSendMediaIntent)
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:@(editingContext.isHighQualityPhoto) forKey:@"TG_photoHighQuality_v0"];
|
||||||
|
|
||||||
if (saveEditedPhotos && storeAssets && editingContext != nil)
|
if (saveEditedPhotos && storeAssets && editingContext != nil)
|
||||||
{
|
{
|
||||||
NSMutableArray *fullSizeSignals = [[NSMutableArray alloc] init];
|
NSMutableArray *fullSizeSignals = [[NSMutableArray alloc] init];
|
||||||
|
|||||||
@ -2159,6 +2159,12 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
|||||||
strongSelf.controllerNode.dismissInput()
|
strongSelf.controllerNode.dismissInput()
|
||||||
}
|
}
|
||||||
}, selectionState: selectionContext, editingState: editingContext ?? TGMediaEditingContext())
|
}, selectionState: selectionContext, editingState: editingContext ?? TGMediaEditingContext())
|
||||||
|
|
||||||
|
let highQualityPhoto = UserDefaults.standard.bool(forKey: "TG_photoHighQuality_v0")
|
||||||
|
if highQualityPhoto {
|
||||||
|
self.interaction?.editingState.setHighQualityPhoto(highQualityPhoto)
|
||||||
|
}
|
||||||
|
|
||||||
self.interaction?.selectionState?.grouping = true
|
self.interaction?.selectionState?.grouping = true
|
||||||
|
|
||||||
self.interaction?.editingState.sendPaidMessageStars = sendPaidMessageStars ?? 0
|
self.interaction?.editingState.sendPaidMessageStars = sendPaidMessageStars ?? 0
|
||||||
|
|||||||
@ -220,10 +220,10 @@ private func indexToRoman(_ index: Int) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func chatInputStateString(attributedString: NSAttributedString) -> NSAttributedString? {
|
private func chatInputStateString(attributedString: NSAttributedString) -> NSAttributedString? {
|
||||||
let preprocessedString = preprocessLists(attributedString: attributedString)
|
//let preprocessedString = preprocessLists(attributedString: attributedString)
|
||||||
|
|
||||||
let string = NSMutableAttributedString(string: preprocessedString.string)
|
let string = NSMutableAttributedString(string: attributedString.string)
|
||||||
preprocessedString.enumerateAttributes(in: NSRange(location: 0, length: attributedString.length), options: [], using: { attributes, range, _ in
|
attributedString.enumerateAttributes(in: NSRange(location: 0, length: attributedString.length), options: [], using: { attributes, range, _ in
|
||||||
if let value = attributes[.link], let url = (value as? URL)?.absoluteString {
|
if let value = attributes[.link], let url = (value as? URL)?.absoluteString {
|
||||||
string.addAttribute(ChatTextInputAttributes.textUrl, value: ChatTextInputTextUrlAttribute(url: url), range: range)
|
string.addAttribute(ChatTextInputAttributes.textUrl, value: ChatTextInputTextUrlAttribute(url: url), range: range)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3096,13 +3096,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
|||||||
products.append(PremiumProduct(option: option, storeProduct: product))
|
products.append(PremiumProduct(option: option, storeProduct: product))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:release
|
|
||||||
if let product = availableProducts.first(where: { $0.id.hasSuffix(".annual") }) {
|
|
||||||
let (currency, price) = product.priceCurrencyAndAmount
|
|
||||||
products.insert(PremiumProduct(option: PremiumPromoConfiguration.PremiumProductOption(isCurrent: false, months: 24, currency: currency, amount: price * 2, botUrl: "", transactionId: nil, availableForUpgrade: true, storeProductId: "org.telegram.telegramPremium.biannual"), storeProduct: product), at: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.products = products
|
strongSelf.products = products
|
||||||
strongSelf.isPremium = forceHasPremium || isPremium
|
strongSelf.isPremium = forceHasPremium || isPremium
|
||||||
strongSelf.otherPeerName = otherPeerName
|
strongSelf.otherPeerName = otherPeerName
|
||||||
|
|||||||
@ -912,12 +912,6 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
updateSensitiveContentDisposable.set(updateRemoteContentSettingsConfiguration(postbox: context.account.postbox, network: context.account.network, sensitiveContentEnabled: value).start())
|
updateSensitiveContentDisposable.set(updateRemoteContentSettingsConfiguration(postbox: context.account.postbox, network: context.account.network, sensitiveContentEnabled: value).start())
|
||||||
|
|
||||||
if !value {
|
|
||||||
let _ = updateAgeVerificationState(engine: context.engine, { _ in
|
|
||||||
return AgeVerificationState(verificationPassed: false)
|
|
||||||
}).start()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if value {
|
if value {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|||||||
@ -46,7 +46,7 @@ func confirmRevenueWithdrawalController(context: AccountContext, updatedPresenta
|
|||||||
}
|
}
|
||||||
contentNode.updateIsChecking(true)
|
contentNode.updateIsChecking(true)
|
||||||
|
|
||||||
let signal = context.engine.peers.requestStarsRevenueWithdrawalUrl(peerId: peerId, ton: false, amount: nil, password: contentNode.password)
|
let signal = context.engine.peers.requestStarsRevenueWithdrawalUrl(peerId: peerId, ton: true, amount: nil, password: contentNode.password)
|
||||||
disposable.set((signal |> deliverOnMainQueue).start(next: { url in
|
disposable.set((signal |> deliverOnMainQueue).start(next: { url in
|
||||||
dismissImpl?()
|
dismissImpl?()
|
||||||
completion(url)
|
completion(url)
|
||||||
|
|||||||
@ -388,7 +388,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-625298705] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftStars($0) }
|
dict[-625298705] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftStars($0) }
|
||||||
dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) }
|
dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) }
|
||||||
dict[-396206446] = { return Api.InputInvoice.parse_inputInvoiceStarGift($0) }
|
dict[-396206446] = { return Api.InputInvoice.parse_inputInvoiceStarGift($0) }
|
||||||
dict[1674298252] = { return Api.InputInvoice.parse_inputInvoiceStarGiftResale($0) }
|
dict[-1012968668] = { return Api.InputInvoice.parse_inputInvoiceStarGiftResale($0) }
|
||||||
dict[1247763417] = { return Api.InputInvoice.parse_inputInvoiceStarGiftTransfer($0) }
|
dict[1247763417] = { return Api.InputInvoice.parse_inputInvoiceStarGiftTransfer($0) }
|
||||||
dict[1300335965] = { return Api.InputInvoice.parse_inputInvoiceStarGiftUpgrade($0) }
|
dict[1300335965] = { return Api.InputInvoice.parse_inputInvoiceStarGiftUpgrade($0) }
|
||||||
dict[1710230755] = { return Api.InputInvoice.parse_inputInvoiceStars($0) }
|
dict[1710230755] = { return Api.InputInvoice.parse_inputInvoiceStars($0) }
|
||||||
@ -603,7 +603,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1348510708] = { return Api.MessageAction.parse_messageActionSetChatWallPaper($0) }
|
dict[1348510708] = { return Api.MessageAction.parse_messageActionSetChatWallPaper($0) }
|
||||||
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
|
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
|
||||||
dict[1192749220] = { return Api.MessageAction.parse_messageActionStarGift($0) }
|
dict[1192749220] = { return Api.MessageAction.parse_messageActionStarGift($0) }
|
||||||
dict[775611918] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
|
dict[888627955] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
|
||||||
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
|
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
|
||||||
dict[-293988970] = { return Api.MessageAction.parse_messageActionSuggestedPostApproval($0) }
|
dict[-293988970] = { return Api.MessageAction.parse_messageActionSuggestedPostApproval($0) }
|
||||||
dict[1777932024] = { return Api.MessageAction.parse_messageActionSuggestedPostRefund($0) }
|
dict[1777932024] = { return Api.MessageAction.parse_messageActionSuggestedPostRefund($0) }
|
||||||
@ -944,7 +944,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
||||||
dict[-963180333] = { return Api.SponsoredPeer.parse_sponsoredPeer($0) }
|
dict[-963180333] = { return Api.SponsoredPeer.parse_sponsoredPeer($0) }
|
||||||
dict[12386139] = { return Api.StarGift.parse_starGift($0) }
|
dict[12386139] = { return Api.StarGift.parse_starGift($0) }
|
||||||
dict[-164136786] = { return Api.StarGift.parse_starGiftUnique($0) }
|
dict[975654224] = { return Api.StarGift.parse_starGiftUnique($0) }
|
||||||
dict[-650279524] = { return Api.StarGiftAttribute.parse_starGiftAttributeBackdrop($0) }
|
dict[-650279524] = { return Api.StarGiftAttribute.parse_starGiftAttributeBackdrop($0) }
|
||||||
dict[970559507] = { return Api.StarGiftAttribute.parse_starGiftAttributeModel($0) }
|
dict[970559507] = { return Api.StarGiftAttribute.parse_starGiftAttributeModel($0) }
|
||||||
dict[-524291476] = { return Api.StarGiftAttribute.parse_starGiftAttributeOriginalDetails($0) }
|
dict[-524291476] = { return Api.StarGiftAttribute.parse_starGiftAttributeOriginalDetails($0) }
|
||||||
@ -992,8 +992,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[872932635] = { return Api.StickerSetCovered.parse_stickerSetMultiCovered($0) }
|
dict[872932635] = { return Api.StickerSetCovered.parse_stickerSetMultiCovered($0) }
|
||||||
dict[2008112412] = { return Api.StickerSetCovered.parse_stickerSetNoCovered($0) }
|
dict[2008112412] = { return Api.StickerSetCovered.parse_stickerSetNoCovered($0) }
|
||||||
dict[1898850301] = { return Api.StoriesStealthMode.parse_storiesStealthMode($0) }
|
dict[1898850301] = { return Api.StoriesStealthMode.parse_storiesStealthMode($0) }
|
||||||
|
dict[-1826262950] = { return Api.StoryAlbum.parse_storyAlbum($0) }
|
||||||
dict[-1205411504] = { return Api.StoryFwdHeader.parse_storyFwdHeader($0) }
|
dict[-1205411504] = { return Api.StoryFwdHeader.parse_storyFwdHeader($0) }
|
||||||
dict[2041735716] = { return Api.StoryItem.parse_storyItem($0) }
|
dict[-302947087] = { return Api.StoryItem.parse_storyItem($0) }
|
||||||
dict[1374088783] = { return Api.StoryItem.parse_storyItemDeleted($0) }
|
dict[1374088783] = { return Api.StoryItem.parse_storyItemDeleted($0) }
|
||||||
dict[-5388013] = { return Api.StoryItem.parse_storyItemSkipped($0) }
|
dict[-5388013] = { return Api.StoryItem.parse_storyItemSkipped($0) }
|
||||||
dict[1620104917] = { return Api.StoryReaction.parse_storyReaction($0) }
|
dict[1620104917] = { return Api.StoryReaction.parse_storyReaction($0) }
|
||||||
@ -1476,6 +1477,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[172975040] = { return Api.storage.FileType.parse_filePng($0) }
|
dict[172975040] = { return Api.storage.FileType.parse_filePng($0) }
|
||||||
dict[-1432995067] = { return Api.storage.FileType.parse_fileUnknown($0) }
|
dict[-1432995067] = { return Api.storage.FileType.parse_fileUnknown($0) }
|
||||||
dict[276907596] = { return Api.storage.FileType.parse_fileWebp($0) }
|
dict[276907596] = { return Api.storage.FileType.parse_fileWebp($0) }
|
||||||
|
dict[-1013417414] = { return Api.stories.Albums.parse_albums($0) }
|
||||||
|
dict[1448008427] = { return Api.stories.Albums.parse_albumsNotModified($0) }
|
||||||
dict[1862033025] = { return Api.stories.AllStories.parse_allStories($0) }
|
dict[1862033025] = { return Api.stories.AllStories.parse_allStories($0) }
|
||||||
dict[291044926] = { return Api.stories.AllStories.parse_allStoriesNotModified($0) }
|
dict[291044926] = { return Api.stories.AllStories.parse_allStoriesNotModified($0) }
|
||||||
dict[-1014513586] = { return Api.stories.CanSendStoryCount.parse_canSendStoryCount($0) }
|
dict[-1014513586] = { return Api.stories.CanSendStoryCount.parse_canSendStoryCount($0) }
|
||||||
@ -2196,6 +2199,8 @@ public extension Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.StoriesStealthMode:
|
case let _1 as Api.StoriesStealthMode:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.StoryAlbum:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.StoryFwdHeader:
|
case let _1 as Api.StoryFwdHeader:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.StoryItem:
|
case let _1 as Api.StoryItem:
|
||||||
@ -2614,6 +2619,8 @@ public extension Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.storage.FileType:
|
case let _1 as Api.storage.FileType:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
case let _1 as Api.stories.Albums:
|
||||||
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.stories.AllStories:
|
case let _1 as Api.stories.AllStories:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.stories.CanSendStoryCount:
|
case let _1 as Api.stories.CanSendStoryCount:
|
||||||
|
|||||||
@ -255,7 +255,7 @@ public extension Api {
|
|||||||
case inputInvoicePremiumGiftStars(flags: Int32, userId: Api.InputUser, months: Int32, message: Api.TextWithEntities?)
|
case inputInvoicePremiumGiftStars(flags: Int32, userId: Api.InputUser, months: Int32, message: Api.TextWithEntities?)
|
||||||
case inputInvoiceSlug(slug: String)
|
case inputInvoiceSlug(slug: String)
|
||||||
case inputInvoiceStarGift(flags: Int32, peer: Api.InputPeer, giftId: Int64, message: Api.TextWithEntities?)
|
case inputInvoiceStarGift(flags: Int32, peer: Api.InputPeer, giftId: Int64, message: Api.TextWithEntities?)
|
||||||
case inputInvoiceStarGiftResale(slug: String, toId: Api.InputPeer)
|
case inputInvoiceStarGiftResale(flags: Int32, slug: String, toId: Api.InputPeer)
|
||||||
case inputInvoiceStarGiftTransfer(stargift: Api.InputSavedStarGift, toId: Api.InputPeer)
|
case inputInvoiceStarGiftTransfer(stargift: Api.InputSavedStarGift, toId: Api.InputPeer)
|
||||||
case inputInvoiceStarGiftUpgrade(flags: Int32, stargift: Api.InputSavedStarGift)
|
case inputInvoiceStarGiftUpgrade(flags: Int32, stargift: Api.InputSavedStarGift)
|
||||||
case inputInvoiceStars(purpose: Api.InputStorePaymentPurpose)
|
case inputInvoiceStars(purpose: Api.InputStorePaymentPurpose)
|
||||||
@ -313,10 +313,11 @@ public extension Api {
|
|||||||
serializeInt64(giftId, buffer: buffer, boxed: false)
|
serializeInt64(giftId, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 1) != 0 {message!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 1) != 0 {message!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
case .inputInvoiceStarGiftResale(let slug, let toId):
|
case .inputInvoiceStarGiftResale(let flags, let slug, let toId):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(1674298252)
|
buffer.appendInt32(-1012968668)
|
||||||
}
|
}
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeString(slug, buffer: buffer, boxed: false)
|
serializeString(slug, buffer: buffer, boxed: false)
|
||||||
toId.serialize(buffer, true)
|
toId.serialize(buffer, true)
|
||||||
break
|
break
|
||||||
@ -359,8 +360,8 @@ public extension Api {
|
|||||||
return ("inputInvoiceSlug", [("slug", slug as Any)])
|
return ("inputInvoiceSlug", [("slug", slug as Any)])
|
||||||
case .inputInvoiceStarGift(let flags, let peer, let giftId, let message):
|
case .inputInvoiceStarGift(let flags, let peer, let giftId, let message):
|
||||||
return ("inputInvoiceStarGift", [("flags", flags as Any), ("peer", peer as Any), ("giftId", giftId as Any), ("message", message as Any)])
|
return ("inputInvoiceStarGift", [("flags", flags as Any), ("peer", peer as Any), ("giftId", giftId as Any), ("message", message as Any)])
|
||||||
case .inputInvoiceStarGiftResale(let slug, let toId):
|
case .inputInvoiceStarGiftResale(let flags, let slug, let toId):
|
||||||
return ("inputInvoiceStarGiftResale", [("slug", slug as Any), ("toId", toId as Any)])
|
return ("inputInvoiceStarGiftResale", [("flags", flags as Any), ("slug", slug as Any), ("toId", toId as Any)])
|
||||||
case .inputInvoiceStarGiftTransfer(let stargift, let toId):
|
case .inputInvoiceStarGiftTransfer(let stargift, let toId):
|
||||||
return ("inputInvoiceStarGiftTransfer", [("stargift", stargift as Any), ("toId", toId as Any)])
|
return ("inputInvoiceStarGiftTransfer", [("stargift", stargift as Any), ("toId", toId as Any)])
|
||||||
case .inputInvoiceStarGiftUpgrade(let flags, let stargift):
|
case .inputInvoiceStarGiftUpgrade(let flags, let stargift):
|
||||||
@ -491,16 +492,19 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static func parse_inputInvoiceStarGiftResale(_ reader: BufferReader) -> InputInvoice? {
|
public static func parse_inputInvoiceStarGiftResale(_ reader: BufferReader) -> InputInvoice? {
|
||||||
var _1: String?
|
var _1: Int32?
|
||||||
_1 = parseString(reader)
|
_1 = reader.readInt32()
|
||||||
var _2: Api.InputPeer?
|
var _2: String?
|
||||||
|
_2 = parseString(reader)
|
||||||
|
var _3: Api.InputPeer?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
_2 = Api.parse(reader, signature: signature) as? Api.InputPeer
|
_3 = Api.parse(reader, signature: signature) as? Api.InputPeer
|
||||||
}
|
}
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
if _c1 && _c2 {
|
let _c3 = _3 != nil
|
||||||
return Api.InputInvoice.inputInvoiceStarGiftResale(slug: _1!, toId: _2!)
|
if _c1 && _c2 && _c3 {
|
||||||
|
return Api.InputInvoice.inputInvoiceStarGiftResale(flags: _1!, slug: _2!, toId: _3!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -394,7 +394,7 @@ public extension Api {
|
|||||||
case messageActionSetChatWallPaper(flags: Int32, wallpaper: Api.WallPaper)
|
case messageActionSetChatWallPaper(flags: Int32, wallpaper: Api.WallPaper)
|
||||||
case messageActionSetMessagesTTL(flags: Int32, period: Int32, autoSettingFrom: Int64?)
|
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?)
|
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeMsgId: Int32?, upgradeStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?)
|
||||||
case messageActionStarGiftUnique(flags: Int32, gift: Api.StarGift, canExportAt: Int32?, transferStars: Int64?, fromId: Api.Peer?, peer: Api.Peer?, savedId: Int64?, resaleStars: Int64?, canTransferAt: Int32?, canResellAt: Int32?)
|
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?)
|
||||||
case messageActionSuggestProfilePhoto(photo: Api.Photo)
|
case messageActionSuggestProfilePhoto(photo: Api.Photo)
|
||||||
case messageActionSuggestedPostApproval(flags: Int32, rejectComment: String?, scheduleDate: Int32?, price: Api.StarsAmount?)
|
case messageActionSuggestedPostApproval(flags: Int32, rejectComment: String?, scheduleDate: Int32?, price: Api.StarsAmount?)
|
||||||
case messageActionSuggestedPostRefund(flags: Int32)
|
case messageActionSuggestedPostRefund(flags: Int32)
|
||||||
@ -797,9 +797,9 @@ public extension Api {
|
|||||||
if Int(flags) & Int(1 << 12) != 0 {peer!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 12) != 0 {peer!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 12) != 0 {serializeInt64(savedId!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 12) != 0 {serializeInt64(savedId!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars, let fromId, let peer, let savedId, let resaleStars, let canTransferAt, let canResellAt):
|
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars, let fromId, let peer, let savedId, let resaleAmount, let canTransferAt, let canResellAt):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(775611918)
|
buffer.appendInt32(888627955)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
gift.serialize(buffer, true)
|
gift.serialize(buffer, true)
|
||||||
@ -808,7 +808,7 @@ public extension Api {
|
|||||||
if Int(flags) & Int(1 << 6) != 0 {fromId!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 6) != 0 {fromId!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 7) != 0 {peer!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 7) != 0 {peer!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 7) != 0 {serializeInt64(savedId!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 7) != 0 {serializeInt64(savedId!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 8) != 0 {serializeInt64(resaleStars!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 8) != 0 {resaleAmount!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 9) != 0 {serializeInt32(canTransferAt!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 9) != 0 {serializeInt32(canTransferAt!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 10) != 0 {serializeInt32(canResellAt!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 10) != 0 {serializeInt32(canResellAt!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
@ -993,8 +993,8 @@ public extension Api {
|
|||||||
return ("messageActionSetMessagesTTL", [("flags", flags as Any), ("period", period as Any), ("autoSettingFrom", autoSettingFrom as Any)])
|
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):
|
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars, let fromId, let peer, let savedId):
|
||||||
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)])
|
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)])
|
||||||
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars, let fromId, let peer, let savedId, let resaleStars, let canTransferAt, let canResellAt):
|
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars, let fromId, let peer, let savedId, let resaleAmount, let canTransferAt, let canResellAt):
|
||||||
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), ("resaleStars", resaleStars as Any), ("canTransferAt", canTransferAt as Any), ("canResellAt", canResellAt as Any)])
|
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)])
|
||||||
case .messageActionSuggestProfilePhoto(let photo):
|
case .messageActionSuggestProfilePhoto(let photo):
|
||||||
return ("messageActionSuggestProfilePhoto", [("photo", photo as Any)])
|
return ("messageActionSuggestProfilePhoto", [("photo", photo as Any)])
|
||||||
case .messageActionSuggestedPostApproval(let flags, let rejectComment, let scheduleDate, let price):
|
case .messageActionSuggestedPostApproval(let flags, let rejectComment, let scheduleDate, let price):
|
||||||
@ -1792,8 +1792,10 @@ public extension Api {
|
|||||||
} }
|
} }
|
||||||
var _7: Int64?
|
var _7: Int64?
|
||||||
if Int(_1!) & Int(1 << 7) != 0 {_7 = reader.readInt64() }
|
if Int(_1!) & Int(1 << 7) != 0 {_7 = reader.readInt64() }
|
||||||
var _8: Int64?
|
var _8: Api.StarsAmount?
|
||||||
if Int(_1!) & Int(1 << 8) != 0 {_8 = reader.readInt64() }
|
if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() {
|
||||||
|
_8 = Api.parse(reader, signature: signature) as? Api.StarsAmount
|
||||||
|
} }
|
||||||
var _9: Int32?
|
var _9: Int32?
|
||||||
if Int(_1!) & Int(1 << 9) != 0 {_9 = reader.readInt32() }
|
if Int(_1!) & Int(1 << 9) != 0 {_9 = reader.readInt32() }
|
||||||
var _10: Int32?
|
var _10: Int32?
|
||||||
@ -1809,7 +1811,7 @@ public extension Api {
|
|||||||
let _c9 = (Int(_1!) & Int(1 << 9) == 0) || _9 != nil
|
let _c9 = (Int(_1!) & Int(1 << 9) == 0) || _9 != nil
|
||||||
let _c10 = (Int(_1!) & Int(1 << 10) == 0) || _10 != nil
|
let _c10 = (Int(_1!) & Int(1 << 10) == 0) || _10 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
|
||||||
return Api.MessageAction.messageActionStarGiftUnique(flags: _1!, gift: _2!, canExportAt: _3, transferStars: _4, fromId: _5, peer: _6, savedId: _7, resaleStars: _8, canTransferAt: _9, canResellAt: _10)
|
return Api.MessageAction.messageActionStarGiftUnique(flags: _1!, gift: _2!, canExportAt: _3, transferStars: _4, fromId: _5, peer: _6, savedId: _7, resaleAmount: _8, canTransferAt: _9, canResellAt: _10)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -637,7 +637,7 @@ public extension Api {
|
|||||||
public extension Api {
|
public extension Api {
|
||||||
enum StarGift: TypeConstructorDescription {
|
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?)
|
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?)
|
||||||
case starGiftUnique(flags: Int32, id: Int64, title: String, slug: String, num: Int32, ownerId: Api.Peer?, ownerName: String?, ownerAddress: String?, attributes: [Api.StarGiftAttribute], availabilityIssued: Int32, availabilityTotal: Int32, giftAddress: String?, resellStars: Int64?, releasedBy: Api.Peer?)
|
case starGiftUnique(flags: Int32, id: 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?)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -662,9 +662,9 @@ public extension Api {
|
|||||||
if Int(flags) & Int(1 << 8) != 0 {serializeInt32(perUserTotal!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 8) != 0 {serializeInt32(perUserTotal!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 8) != 0 {serializeInt32(perUserRemains!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 8) != 0 {serializeInt32(perUserRemains!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .starGiftUnique(let flags, let id, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellStars, let releasedBy):
|
case .starGiftUnique(let flags, let id, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-164136786)
|
buffer.appendInt32(975654224)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt64(id, buffer: buffer, boxed: false)
|
serializeInt64(id, buffer: buffer, boxed: false)
|
||||||
@ -682,7 +682,11 @@ public extension Api {
|
|||||||
serializeInt32(availabilityIssued, buffer: buffer, boxed: false)
|
serializeInt32(availabilityIssued, buffer: buffer, boxed: false)
|
||||||
serializeInt32(availabilityTotal, buffer: buffer, boxed: false)
|
serializeInt32(availabilityTotal, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 3) != 0 {serializeString(giftAddress!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 3) != 0 {serializeString(giftAddress!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 4) != 0 {serializeInt64(resellStars!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(resellAmount!.count))
|
||||||
|
for item in resellAmount! {
|
||||||
|
item.serialize(buffer, true)
|
||||||
|
}}
|
||||||
if Int(flags) & Int(1 << 5) != 0 {releasedBy!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 5) != 0 {releasedBy!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -692,8 +696,8 @@ public extension Api {
|
|||||||
switch self {
|
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):
|
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):
|
||||||
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)])
|
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)])
|
||||||
case .starGiftUnique(let flags, let id, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellStars, let releasedBy):
|
case .starGiftUnique(let flags, let id, let title, let slug, let num, let ownerId, let ownerName, let ownerAddress, let attributes, let availabilityIssued, let availabilityTotal, let giftAddress, let resellAmount, let releasedBy):
|
||||||
return ("starGiftUnique", [("flags", flags as Any), ("id", id 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), ("resellStars", resellStars as Any), ("releasedBy", releasedBy as Any)])
|
return ("starGiftUnique", [("flags", flags as Any), ("id", id 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)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,8 +790,10 @@ public extension Api {
|
|||||||
_11 = reader.readInt32()
|
_11 = reader.readInt32()
|
||||||
var _12: String?
|
var _12: String?
|
||||||
if Int(_1!) & Int(1 << 3) != 0 {_12 = parseString(reader) }
|
if Int(_1!) & Int(1 << 3) != 0 {_12 = parseString(reader) }
|
||||||
var _13: Int64?
|
var _13: [Api.StarsAmount]?
|
||||||
if Int(_1!) & Int(1 << 4) != 0 {_13 = reader.readInt64() }
|
if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() {
|
||||||
|
_13 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsAmount.self)
|
||||||
|
} }
|
||||||
var _14: Api.Peer?
|
var _14: Api.Peer?
|
||||||
if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() {
|
||||||
_14 = Api.parse(reader, signature: signature) as? Api.Peer
|
_14 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||||
@ -807,7 +813,7 @@ public extension Api {
|
|||||||
let _c13 = (Int(_1!) & Int(1 << 4) == 0) || _13 != nil
|
let _c13 = (Int(_1!) & Int(1 << 4) == 0) || _13 != nil
|
||||||
let _c14 = (Int(_1!) & Int(1 << 5) == 0) || _14 != nil
|
let _c14 = (Int(_1!) & Int(1 << 5) == 0) || _14 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 {
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 {
|
||||||
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, title: _3!, slug: _4!, num: _5!, ownerId: _6, ownerName: _7, ownerAddress: _8, attributes: _9!, availabilityIssued: _10!, availabilityTotal: _11!, giftAddress: _12, resellStars: _13, releasedBy: _14)
|
return Api.StarGift.starGiftUnique(flags: _1!, id: _2!, title: _3!, slug: _4!, num: _5!, ownerId: _6, ownerName: _7, ownerAddress: _8, attributes: _9!, availabilityIssued: _10!, availabilityTotal: _11!, giftAddress: _12, resellAmount: _13, releasedBy: _14)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -324,6 +324,62 @@ 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 {
|
public extension Api {
|
||||||
enum StoryFwdHeader: TypeConstructorDescription {
|
enum StoryFwdHeader: TypeConstructorDescription {
|
||||||
case storyFwdHeader(flags: Int32, from: Api.Peer?, fromName: String?, storyId: Int32?)
|
case storyFwdHeader(flags: Int32, from: Api.Peer?, fromName: String?, storyId: Int32?)
|
||||||
@ -376,15 +432,15 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
indirect enum StoryItem: TypeConstructorDescription {
|
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?)
|
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 storyItemDeleted(id: Int32)
|
||||||
case storyItemSkipped(flags: Int32, id: Int32, date: Int32, expireDate: Int32)
|
case storyItemSkipped(flags: Int32, id: Int32, date: Int32, expireDate: Int32)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
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):
|
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 {
|
if boxed {
|
||||||
buffer.appendInt32(2041735716)
|
buffer.appendInt32(-302947087)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt32(id, buffer: buffer, boxed: false)
|
serializeInt32(id, buffer: buffer, boxed: false)
|
||||||
@ -411,6 +467,11 @@ public extension Api {
|
|||||||
}}
|
}}
|
||||||
if Int(flags) & Int(1 << 3) != 0 {views!.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 << 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
|
break
|
||||||
case .storyItemDeleted(let id):
|
case .storyItemDeleted(let id):
|
||||||
if boxed {
|
if boxed {
|
||||||
@ -432,8 +493,8 @@ public extension Api {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
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):
|
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)])
|
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):
|
case .storyItemDeleted(let id):
|
||||||
return ("storyItemDeleted", [("id", id as Any)])
|
return ("storyItemDeleted", [("id", id as Any)])
|
||||||
case .storyItemSkipped(let flags, let id, let date, let expireDate):
|
case .storyItemSkipped(let flags, let id, let date, let expireDate):
|
||||||
@ -484,6 +545,10 @@ public extension Api {
|
|||||||
if Int(_1!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() {
|
||||||
_13 = Api.parse(reader, signature: signature) as? Api.Reaction
|
_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 _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = _3 != nil
|
let _c3 = _3 != nil
|
||||||
@ -497,8 +562,9 @@ public extension Api {
|
|||||||
let _c11 = (Int(_1!) & Int(1 << 2) == 0) || _11 != nil
|
let _c11 = (Int(_1!) & Int(1 << 2) == 0) || _11 != nil
|
||||||
let _c12 = (Int(_1!) & Int(1 << 3) == 0) || _12 != nil
|
let _c12 = (Int(_1!) & Int(1 << 3) == 0) || _12 != nil
|
||||||
let _c13 = (Int(_1!) & Int(1 << 15) == 0) || _13 != nil
|
let _c13 = (Int(_1!) & Int(1 << 15) == 0) || _13 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 {
|
let _c14 = (Int(_1!) & Int(1 << 19) == 0) || _14 != nil
|
||||||
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)
|
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 {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -482,6 +482,64 @@ public extension Api.storage {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.stories {
|
||||||
|
enum Albums: TypeConstructorDescription {
|
||||||
|
case albums(hash: Int64, albums: [Api.StoryAlbum])
|
||||||
|
case albumsNotModified
|
||||||
|
|
||||||
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
|
switch self {
|
||||||
|
case .albums(let hash, let albums):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1013417414)
|
||||||
|
}
|
||||||
|
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(albums.count))
|
||||||
|
for item in albums {
|
||||||
|
item.serialize(buffer, true)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case .albumsNotModified:
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(1448008427)
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
|
switch self {
|
||||||
|
case .albums(let hash, let albums):
|
||||||
|
return ("albums", [("hash", hash as Any), ("albums", albums as Any)])
|
||||||
|
case .albumsNotModified:
|
||||||
|
return ("albumsNotModified", [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func parse_albums(_ reader: BufferReader) -> Albums? {
|
||||||
|
var _1: Int64?
|
||||||
|
_1 = reader.readInt64()
|
||||||
|
var _2: [Api.StoryAlbum]?
|
||||||
|
if let _ = reader.readInt32() {
|
||||||
|
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryAlbum.self)
|
||||||
|
}
|
||||||
|
let _c1 = _1 != nil
|
||||||
|
let _c2 = _2 != nil
|
||||||
|
if _c1 && _c2 {
|
||||||
|
return Api.stories.Albums.albums(hash: _1!, albums: _2!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static func parse_albumsNotModified(_ reader: BufferReader) -> Albums? {
|
||||||
|
return Api.stories.Albums.albumsNotModified
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.stories {
|
public extension Api.stories {
|
||||||
enum AllStories: TypeConstructorDescription {
|
enum AllStories: TypeConstructorDescription {
|
||||||
case allStories(flags: Int32, count: Int32, state: String, peerStories: [Api.PeerStories], chats: [Api.Chat], users: [Api.User], stealthMode: Api.StoriesStealthMode)
|
case allStories(flags: Int32, count: Int32, state: String, peerStories: [Api.PeerStories], chats: [Api.Chat], users: [Api.User], stealthMode: Api.StoriesStealthMode)
|
||||||
@ -1428,55 +1486,3 @@ public extension Api.updates {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.updates {
|
|
||||||
enum State: TypeConstructorDescription {
|
|
||||||
case state(pts: Int32, qts: Int32, date: Int32, seq: Int32, unreadCount: Int32)
|
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
|
||||||
switch self {
|
|
||||||
case .state(let pts, let qts, let date, let seq, let unreadCount):
|
|
||||||
if boxed {
|
|
||||||
buffer.appendInt32(-1519637954)
|
|
||||||
}
|
|
||||||
serializeInt32(pts, buffer: buffer, boxed: false)
|
|
||||||
serializeInt32(qts, buffer: buffer, boxed: false)
|
|
||||||
serializeInt32(date, buffer: buffer, boxed: false)
|
|
||||||
serializeInt32(seq, buffer: buffer, boxed: false)
|
|
||||||
serializeInt32(unreadCount, buffer: buffer, boxed: false)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
|
||||||
switch self {
|
|
||||||
case .state(let pts, let qts, let date, let seq, let unreadCount):
|
|
||||||
return ("state", [("pts", pts as Any), ("qts", qts as Any), ("date", date as Any), ("seq", seq as Any), ("unreadCount", unreadCount as Any)])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static func parse_state(_ reader: BufferReader) -> State? {
|
|
||||||
var _1: Int32?
|
|
||||||
_1 = reader.readInt32()
|
|
||||||
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.updates.State.state(pts: _1!, qts: _2!, date: _3!, seq: _4!, unreadCount: _5!)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,3 +1,55 @@
|
|||||||
|
public extension Api.updates {
|
||||||
|
enum State: TypeConstructorDescription {
|
||||||
|
case state(pts: Int32, qts: Int32, date: Int32, seq: Int32, unreadCount: Int32)
|
||||||
|
|
||||||
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
|
switch self {
|
||||||
|
case .state(let pts, let qts, let date, let seq, let unreadCount):
|
||||||
|
if boxed {
|
||||||
|
buffer.appendInt32(-1519637954)
|
||||||
|
}
|
||||||
|
serializeInt32(pts, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(qts, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(date, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(seq, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(unreadCount, buffer: buffer, boxed: false)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
|
switch self {
|
||||||
|
case .state(let pts, let qts, let date, let seq, let unreadCount):
|
||||||
|
return ("state", [("pts", pts as Any), ("qts", qts as Any), ("date", date as Any), ("seq", seq as Any), ("unreadCount", unreadCount as Any)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func parse_state(_ reader: BufferReader) -> State? {
|
||||||
|
var _1: Int32?
|
||||||
|
_1 = reader.readInt32()
|
||||||
|
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.updates.State.state(pts: _1!, qts: _2!, date: _3!, seq: _4!, unreadCount: _5!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.upload {
|
public extension Api.upload {
|
||||||
enum CdnFile: TypeConstructorDescription {
|
enum CdnFile: TypeConstructorDescription {
|
||||||
case cdnFile(bytes: Buffer)
|
case cdnFile(bytes: Buffer)
|
||||||
|
|||||||
@ -10058,12 +10058,12 @@ public extension Api.functions.payments {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.payments {
|
public extension Api.functions.payments {
|
||||||
static func updateStarGiftPrice(stargift: Api.InputSavedStarGift, resellStars: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
static func updateStarGiftPrice(stargift: Api.InputSavedStarGift, resellAmount: Api.StarsAmount) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(1001301217)
|
buffer.appendInt32(-306287413)
|
||||||
stargift.serialize(buffer, true)
|
stargift.serialize(buffer, true)
|
||||||
serializeInt64(resellStars, buffer: buffer, boxed: false)
|
resellAmount.serialize(buffer, true)
|
||||||
return (FunctionDescription(name: "payments.updateStarGiftPrice", parameters: [("stargift", String(describing: stargift)), ("resellStars", String(describing: resellStars))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
return (FunctionDescription(name: "payments.updateStarGiftPrice", parameters: [("stargift", String(describing: stargift)), ("resellAmount", String(describing: resellAmount))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Updates?
|
var result: Api.Updates?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
@ -11371,6 +11371,43 @@ public extension Api.functions.stories {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.stories {
|
||||||
|
static func createAlbum(peer: Api.InputPeer, title: String, stories: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.StoryAlbum>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-1553754395)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
serializeString(title, buffer: buffer, boxed: false)
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(stories.count))
|
||||||
|
for item in stories {
|
||||||
|
serializeInt32(item, buffer: buffer, boxed: false)
|
||||||
|
}
|
||||||
|
return (FunctionDescription(name: "stories.createAlbum", parameters: [("peer", String(describing: peer)), ("title", String(describing: title)), ("stories", String(describing: stories))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StoryAlbum? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.StoryAlbum?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.StoryAlbum
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public extension Api.functions.stories {
|
||||||
|
static func deleteAlbum(peer: Api.InputPeer, albumId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-1925949744)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
serializeInt32(albumId, buffer: buffer, boxed: false)
|
||||||
|
return (FunctionDescription(name: "stories.deleteAlbum", parameters: [("peer", String(describing: peer)), ("albumId", String(describing: albumId))]), 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.stories {
|
public extension Api.functions.stories {
|
||||||
static func deleteStories(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) {
|
static func deleteStories(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Int32]>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
@ -11441,6 +11478,40 @@ public extension Api.functions.stories {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.stories {
|
||||||
|
static func getAlbumStories(peer: Api.InputPeer, albumId: Int32, offset: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.stories.Stories>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-1400869535)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
serializeInt32(albumId, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(offset, buffer: buffer, boxed: false)
|
||||||
|
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||||
|
return (FunctionDescription(name: "stories.getAlbumStories", parameters: [("peer", String(describing: peer)), ("albumId", String(describing: albumId)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stories.Stories? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.stories.Stories?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.stories.Stories
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public extension Api.functions.stories {
|
||||||
|
static func getAlbums(peer: Api.InputPeer, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.stories.Albums>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(632548039)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||||
|
return (FunctionDescription(name: "stories.getAlbums", parameters: [("peer", String(describing: peer)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.stories.Albums? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.stories.Albums?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.stories.Albums
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.functions.stories {
|
public extension Api.functions.stories {
|
||||||
static func getAllReadPeerStories() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
static func getAllReadPeerStories() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
@ -11671,6 +11742,26 @@ public extension Api.functions.stories {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.stories {
|
||||||
|
static func reorderAlbums(peer: Api.InputPeer, order: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-2060059687)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(order.count))
|
||||||
|
for item in order {
|
||||||
|
serializeInt32(item, buffer: buffer, boxed: false)
|
||||||
|
}
|
||||||
|
return (FunctionDescription(name: "stories.reorderAlbums", parameters: [("peer", String(describing: peer)), ("order", String(describing: order))]), 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.stories {
|
public extension Api.functions.stories {
|
||||||
static func report(peer: Api.InputPeer, id: [Int32], option: Buffer, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ReportResult>) {
|
static func report(peer: Api.InputPeer, id: [Int32], option: Buffer, message: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ReportResult>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
@ -11732,9 +11823,9 @@ public extension Api.functions.stories {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.stories {
|
public extension Api.functions.stories {
|
||||||
static func sendStory(flags: Int32, peer: Api.InputPeer, media: Api.InputMedia, mediaAreas: [Api.MediaArea]?, caption: String?, entities: [Api.MessageEntity]?, privacyRules: [Api.InputPrivacyRule], randomId: Int64, period: Int32?, fwdFromId: Api.InputPeer?, fwdFromStory: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
static func sendStory(flags: Int32, peer: Api.InputPeer, media: Api.InputMedia, mediaAreas: [Api.MediaArea]?, caption: String?, entities: [Api.MessageEntity]?, privacyRules: [Api.InputPrivacyRule], randomId: Int64, period: Int32?, fwdFromId: Api.InputPeer?, fwdFromStory: Int32?, albums: [Int32]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(-454661813)
|
buffer.appendInt32(1937752812)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
media.serialize(buffer, true)
|
media.serialize(buffer, true)
|
||||||
@ -11758,7 +11849,12 @@ public extension Api.functions.stories {
|
|||||||
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(period!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(period!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 6) != 0 {fwdFromId!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 6) != 0 {fwdFromId!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 6) != 0 {serializeInt32(fwdFromStory!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 6) != 0 {serializeInt32(fwdFromStory!, buffer: buffer, boxed: false)}
|
||||||
return (FunctionDescription(name: "stories.sendStory", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("media", String(describing: media)), ("mediaAreas", String(describing: mediaAreas)), ("caption", String(describing: caption)), ("entities", String(describing: entities)), ("privacyRules", String(describing: privacyRules)), ("randomId", String(describing: randomId)), ("period", String(describing: period)), ("fwdFromId", String(describing: fwdFromId)), ("fwdFromStory", String(describing: fwdFromStory))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
if Int(flags) & Int(1 << 8) != 0 {buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(albums!.count))
|
||||||
|
for item in albums! {
|
||||||
|
serializeInt32(item, buffer: buffer, boxed: false)
|
||||||
|
}}
|
||||||
|
return (FunctionDescription(name: "stories.sendStory", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("media", String(describing: media)), ("mediaAreas", String(describing: mediaAreas)), ("caption", String(describing: caption)), ("entities", String(describing: entities)), ("privacyRules", String(describing: privacyRules)), ("randomId", String(describing: randomId)), ("period", String(describing: period)), ("fwdFromId", String(describing: fwdFromId)), ("fwdFromStory", String(describing: fwdFromStory)), ("albums", String(describing: albums))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.Updates?
|
var result: Api.Updates?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
@ -11840,6 +11936,39 @@ public extension Api.functions.stories {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.stories {
|
||||||
|
static func updateAlbum(flags: Int32, peer: Api.InputPeer, albumId: Int32, title: String?, deleteStories: [Int32]?, addStories: [Int32]?, order: [Int32]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.StoryAlbum>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(1582455222)
|
||||||
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
|
peer.serialize(buffer, true)
|
||||||
|
serializeInt32(albumId, buffer: buffer, boxed: false)
|
||||||
|
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||||
|
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(deleteStories!.count))
|
||||||
|
for item in deleteStories! {
|
||||||
|
serializeInt32(item, buffer: buffer, boxed: false)
|
||||||
|
}}
|
||||||
|
if Int(flags) & Int(1 << 2) != 0 {buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(addStories!.count))
|
||||||
|
for item in addStories! {
|
||||||
|
serializeInt32(item, buffer: buffer, boxed: false)
|
||||||
|
}}
|
||||||
|
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(order!.count))
|
||||||
|
for item in order! {
|
||||||
|
serializeInt32(item, buffer: buffer, boxed: false)
|
||||||
|
}}
|
||||||
|
return (FunctionDescription(name: "stories.updateAlbum", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("albumId", String(describing: albumId)), ("title", String(describing: title)), ("deleteStories", String(describing: deleteStories)), ("addStories", String(describing: addStories)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StoryAlbum? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.StoryAlbum?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.StoryAlbum
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.functions.updates {
|
public extension Api.functions.updates {
|
||||||
static func getChannelDifference(flags: Int32, channel: Api.InputChannel, filter: Api.ChannelMessagesFilter, pts: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.updates.ChannelDifference>) {
|
static func getChannelDifference(flags: Int32, channel: Api.InputChannel, filter: Api.ChannelMessagesFilter, pts: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.updates.ChannelDifference>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
|
|||||||
@ -192,11 +192,11 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
|||||||
return nil
|
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, upgradeMessageId: upgradeMessageId, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId))
|
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, upgradeMessageId: upgradeMessageId, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId))
|
||||||
case let .messageActionStarGiftUnique(flags, apiGift, canExportAt, transferStars, fromId, peer, savedId, resaleStars, canTransferDate, canResaleDate):
|
case let .messageActionStarGiftUnique(flags, apiGift, canExportAt, transferStars, fromId, peer, savedId, resaleAmount, canTransferDate, canResaleDate):
|
||||||
guard let gift = StarGift(apiStarGift: apiGift) else {
|
guard let gift = StarGift(apiStarGift: apiGift) else {
|
||||||
return nil
|
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, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, resaleStars: resaleStars, canTransferDate: canTransferDate, canResaleDate: canResaleDate))
|
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, peerId: peer?.peerId, senderId: fromId?.peerId, savedId: savedId, resaleAmount: resaleAmount.flatMap { CurrencyAmount(apiAmount: $0) }, canTransferDate: canTransferDate, canResaleDate: canResaleDate))
|
||||||
case let .messageActionPaidMessagesRefunded(count, stars):
|
case let .messageActionPaidMessagesRefunded(count, stars):
|
||||||
return TelegramMediaAction(action: .paidMessagesRefunded(count: count, stars: stars))
|
return TelegramMediaAction(action: .paidMessagesRefunded(count: count, stars: stars))
|
||||||
case let .messageActionPaidMessagesPrice(flags, stars):
|
case let .messageActionPaidMessagesPrice(flags, stars):
|
||||||
|
|||||||
@ -10,6 +10,13 @@ public struct AppUpdateInfo: Equatable {
|
|||||||
public let version: String
|
public let version: String
|
||||||
public let text: String
|
public let text: String
|
||||||
public let entities: [MessageTextEntity]
|
public let entities: [MessageTextEntity]
|
||||||
|
|
||||||
|
public init(blocking: Bool, version: String, text: String, entities: [MessageTextEntity]) {
|
||||||
|
self.blocking = blocking
|
||||||
|
self.version = version
|
||||||
|
self.text = text
|
||||||
|
self.entities = entities
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppUpdateInfo {
|
extension AppUpdateInfo {
|
||||||
|
|||||||
@ -354,7 +354,8 @@ func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Ne
|
|||||||
],
|
],
|
||||||
availability: StarGift.UniqueGift.Availability(issued: 0, total: 0),
|
availability: StarGift.UniqueGift.Availability(issued: 0, total: 0),
|
||||||
giftAddress: nil,
|
giftAddress: nil,
|
||||||
resellStars: nil,
|
resellAmounts: nil,
|
||||||
|
resellForTonOnly: false,
|
||||||
releasedBy: nil
|
releasedBy: nil
|
||||||
)
|
)
|
||||||
if let entry = CodableEntry(RecentStarGiftItem(gift)) {
|
if let entry = CodableEntry(RecentStarGiftItem(gift)) {
|
||||||
|
|||||||
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
|||||||
|
|
||||||
public class Serialization: NSObject, MTSerialization {
|
public class Serialization: NSObject, MTSerialization {
|
||||||
public func currentLayer() -> UInt {
|
public func currentLayer() -> UInt {
|
||||||
return 210
|
return 211
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parseMessage(_ data: Data!) -> Any! {
|
public func parseMessage(_ data: Data!) -> Any! {
|
||||||
|
|||||||
@ -244,7 +244,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
case giftStars(currency: String, amount: Int64, count: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, 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 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, upgradeMessageId: Int32?, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?)
|
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, isRefunded: Bool, upgradeMessageId: Int32?, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?)
|
||||||
case starGiftUnique(gift: StarGift, isUpgrade: Bool, isTransferred: Bool, savedToProfile: Bool, canExportDate: Int32?, transferStars: Int64?, isRefunded: Bool, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, resaleStars: Int64?, canTransferDate: Int32?, canResaleDate: Int32?)
|
case starGiftUnique(gift: StarGift, isUpgrade: Bool, isTransferred: Bool, savedToProfile: Bool, canExportDate: Int32?, transferStars: Int64?, isRefunded: Bool, peerId: EnginePeer.Id?, senderId: EnginePeer.Id?, savedId: Int64?, resaleAmount: CurrencyAmount?, canTransferDate: Int32?, canResaleDate: Int32?)
|
||||||
case paidMessagesRefunded(count: Int32, stars: Int64)
|
case paidMessagesRefunded(count: Int32, stars: Int64)
|
||||||
case paidMessagesPriceEdited(stars: Int64, broadcastMessagesAllowed: Bool)
|
case paidMessagesPriceEdited(stars: Int64, broadcastMessagesAllowed: Bool)
|
||||||
case conferenceCall(ConferenceCall)
|
case conferenceCall(ConferenceCall)
|
||||||
@ -377,7 +377,13 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
case 44:
|
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), upgradeMessageId: decoder.decodeOptionalInt32ForKey("upgradeMessageId"), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"))
|
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), upgradeMessageId: decoder.decodeOptionalInt32ForKey("upgradeMessageId"), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"))
|
||||||
case 45:
|
case 45:
|
||||||
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), peerId: decoder.decodeOptionalInt64ForKey("peerId").flatMap { EnginePeer.Id($0) }, senderId: decoder.decodeOptionalInt64ForKey("senderId").flatMap { EnginePeer.Id($0) }, savedId: decoder.decodeOptionalInt64ForKey("savedId"), resaleStars: decoder.decodeOptionalInt64ForKey("resaleStars"), canTransferDate: decoder.decodeOptionalInt32ForKey("canTransferDate"), canResaleDate: decoder.decodeOptionalInt32ForKey("canResaleDate"))
|
var resaleAmount: CurrencyAmount?
|
||||||
|
if let amount = decoder.decodeCodable(CurrencyAmount.self, forKey: "resaleAmount") {
|
||||||
|
resaleAmount = amount
|
||||||
|
} 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), 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"))
|
||||||
case 46:
|
case 46:
|
||||||
self = .paidMessagesRefunded(count: decoder.decodeInt32ForKey("count", orElse: 0), stars: decoder.decodeInt64ForKey("stars", orElse: 0))
|
self = .paidMessagesRefunded(count: decoder.decodeInt32ForKey("count", orElse: 0), stars: decoder.decodeInt64ForKey("stars", orElse: 0))
|
||||||
case 47:
|
case 47:
|
||||||
@ -745,7 +751,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "savedId")
|
encoder.encodeNil(forKey: "savedId")
|
||||||
}
|
}
|
||||||
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, peerId, senderId, savedId, resaleStars, canTransferDate, canResaleDate):
|
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded, peerId, senderId, savedId, resaleAmount, canTransferDate, canResaleDate):
|
||||||
encoder.encodeInt32(45, forKey: "_rawValue")
|
encoder.encodeInt32(45, forKey: "_rawValue")
|
||||||
encoder.encodeObject(gift, forKey: "gift")
|
encoder.encodeObject(gift, forKey: "gift")
|
||||||
encoder.encodeBool(isUpgrade, forKey: "isUpgrade")
|
encoder.encodeBool(isUpgrade, forKey: "isUpgrade")
|
||||||
@ -777,10 +783,10 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "savedId")
|
encoder.encodeNil(forKey: "savedId")
|
||||||
}
|
}
|
||||||
if let resaleStars {
|
if let resaleAmount {
|
||||||
encoder.encodeInt64(resaleStars, forKey: "resaleStars")
|
encoder.encodeCodable(resaleAmount, forKey: "resaleAmount")
|
||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "resaleStars")
|
encoder.encodeNil(forKey: "resaleAmount")
|
||||||
}
|
}
|
||||||
if let canTransferDate {
|
if let canTransferDate {
|
||||||
encoder.encodeInt32(canTransferDate, forKey: "canTransferDate")
|
encoder.encodeInt32(canTransferDate, forKey: "canTransferDate")
|
||||||
|
|||||||
@ -1235,7 +1235,8 @@ func _internal_uploadStoryImpl(
|
|||||||
randomId: randomId,
|
randomId: randomId,
|
||||||
period: Int32(period),
|
period: Int32(period),
|
||||||
fwdFromId: fwdFromId,
|
fwdFromId: fwdFromId,
|
||||||
fwdFromStory: fwdFromStory
|
fwdFromStory: fwdFromStory,
|
||||||
|
albums: nil
|
||||||
))
|
))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||||
@ -1259,7 +1260,7 @@ func _internal_uploadStoryImpl(
|
|||||||
for update in updates.allUpdates {
|
for update in updates.allUpdates {
|
||||||
if case let .updateStory(_, story) = update {
|
if case let .updateStory(_, story) = update {
|
||||||
switch story {
|
switch story {
|
||||||
case let .storyItem(_, idValue, _, fromId, _, _, _, _, media, _, _, _, _):
|
case let .storyItem(_, idValue, _, fromId, _, _, _, _, media, _, _, _, _, _):
|
||||||
if let parsedStory = Stories.StoredItem(apiStoryItem: story, peerId: toPeerId, transaction: transaction) {
|
if let parsedStory = Stories.StoredItem(apiStoryItem: story, peerId: toPeerId, transaction: transaction) {
|
||||||
var items = transaction.getStoryItems(peerId: toPeerId)
|
var items = transaction.getStoryItems(peerId: toPeerId)
|
||||||
var updatedItems: [Stories.Item] = []
|
var updatedItems: [Stories.Item] = []
|
||||||
@ -1648,7 +1649,7 @@ func _internal_editStory(account: Account, peerId: PeerId, id: Int32, media: Eng
|
|||||||
for update in updates.allUpdates {
|
for update in updates.allUpdates {
|
||||||
if case let .updateStory(_, story) = update {
|
if case let .updateStory(_, story) = update {
|
||||||
switch story {
|
switch story {
|
||||||
case let .storyItem(_, _, _, _, _, _, _, _, media, _, _, _, _):
|
case let .storyItem(_, _, _, _, _, _, _, _, media, _, _, _, _, _):
|
||||||
let parsedMedia = textMediaAndExpirationTimerFromApiMedia(media, account.peerId).media
|
let parsedMedia = textMediaAndExpirationTimerFromApiMedia(media, account.peerId).media
|
||||||
if let parsedMedia = parsedMedia, let originalMedia = originalMedia {
|
if let parsedMedia = parsedMedia, let originalMedia = originalMedia {
|
||||||
applyMediaResourceChanges(from: originalMedia, to: parsedMedia, postbox: account.postbox, force: false, skipPreviews: updatingCoverTime)
|
applyMediaResourceChanges(from: originalMedia, to: parsedMedia, postbox: account.postbox, force: false, skipPreviews: updatingCoverTime)
|
||||||
@ -2009,7 +2010,7 @@ func _internal_updatePinnedToTopStories(account: Account, peerId: PeerId, ids: [
|
|||||||
extension Api.StoryItem {
|
extension Api.StoryItem {
|
||||||
var id: Int32 {
|
var id: Int32 {
|
||||||
switch self {
|
switch self {
|
||||||
case let .storyItem(_, id, _, _, _, _, _, _, _, _, _, _, _):
|
case let .storyItem(_, id, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||||
return id
|
return id
|
||||||
case let .storyItemDeleted(id):
|
case let .storyItemDeleted(id):
|
||||||
return id
|
return id
|
||||||
@ -2072,7 +2073,7 @@ extension Stories.Item.ForwardInfo {
|
|||||||
extension Stories.StoredItem {
|
extension Stories.StoredItem {
|
||||||
init?(apiStoryItem: Api.StoryItem, existingItem: Stories.Item? = nil, peerId: PeerId, transaction: Transaction) {
|
init?(apiStoryItem: Api.StoryItem, existingItem: Stories.Item? = nil, peerId: PeerId, transaction: Transaction) {
|
||||||
switch apiStoryItem {
|
switch apiStoryItem {
|
||||||
case let .storyItem(flags, id, date, fromId, forwardFrom, expireDate, caption, entities, media, mediaAreas, privacy, views, sentReaction):
|
case let .storyItem(flags, id, date, fromId, forwardFrom, expireDate, caption, entities, media, mediaAreas, privacy, views, sentReaction, _):
|
||||||
let parsedMedia = textMediaAndExpirationTimerFromApiMedia(media, peerId).media
|
let parsedMedia = textMediaAndExpirationTimerFromApiMedia(media, peerId).media
|
||||||
if let parsedMedia = parsedMedia {
|
if let parsedMedia = parsedMedia {
|
||||||
var parsedPrivacy: Stories.Item.Privacy?
|
var parsedPrivacy: Stories.Item.Privacy?
|
||||||
|
|||||||
@ -17,7 +17,7 @@ public enum BotPaymentInvoiceSource {
|
|||||||
case starGiftUpgrade(keepOriginalInfo: Bool, reference: StarGiftReference)
|
case starGiftUpgrade(keepOriginalInfo: Bool, reference: StarGiftReference)
|
||||||
case starGiftTransfer(reference: StarGiftReference, toPeerId: EnginePeer.Id)
|
case starGiftTransfer(reference: StarGiftReference, toPeerId: EnginePeer.Id)
|
||||||
case premiumGift(peerId: EnginePeer.Id, option: CachedPremiumGiftOption, text: String?, entities: [MessageTextEntity]?)
|
case premiumGift(peerId: EnginePeer.Id, option: CachedPremiumGiftOption, text: String?, entities: [MessageTextEntity]?)
|
||||||
case starGiftResale(slug: String, toPeerId: EnginePeer.Id)
|
case starGiftResale(slug: String, toPeerId: EnginePeer.Id, ton: Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct BotPaymentInvoiceFields: OptionSet {
|
public struct BotPaymentInvoiceFields: OptionSet {
|
||||||
@ -180,6 +180,7 @@ public enum BotPaymentFormRequestError {
|
|||||||
case noPaymentNeeded
|
case noPaymentNeeded
|
||||||
case disallowedStarGift
|
case disallowedStarGift
|
||||||
case starGiftResellTooEarly(Int32)
|
case starGiftResellTooEarly(Int32)
|
||||||
|
case starGiftUserLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
extension BotPaymentInvoice {
|
extension BotPaymentInvoice {
|
||||||
@ -402,11 +403,15 @@ func _internal_parseInputInvoice(transaction: Transaction, source: BotPaymentInv
|
|||||||
message = .textWithEntities(text: text, entities: entities.flatMap { apiEntitiesFromMessageTextEntities($0, associatedPeers: SimpleDictionary()) } ?? [])
|
message = .textWithEntities(text: text, entities: entities.flatMap { apiEntitiesFromMessageTextEntities($0, associatedPeers: SimpleDictionary()) } ?? [])
|
||||||
}
|
}
|
||||||
return .inputInvoicePremiumGiftStars(flags: flags, userId: inputUser, months: option.months, message: message)
|
return .inputInvoicePremiumGiftStars(flags: flags, userId: inputUser, months: option.months, message: message)
|
||||||
case let .starGiftResale(slug, toPeerId):
|
case let .starGiftResale(slug, toPeerId, ton):
|
||||||
guard let peer = transaction.getPeer(toPeerId), let inputPeer = apiInputPeer(peer) else {
|
guard let peer = transaction.getPeer(toPeerId), let inputPeer = apiInputPeer(peer) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return .inputInvoiceStarGiftResale(slug: slug, toId: inputPeer)
|
var flags: Int32 = 0
|
||||||
|
if ton {
|
||||||
|
flags |= 1 << 0
|
||||||
|
}
|
||||||
|
return .inputInvoiceStarGiftResale(flags: flags, slug: slug, toId: inputPeer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,6 +493,8 @@ func _internal_fetchBotPaymentForm(accountPeerId: PeerId, postbox: Postbox, netw
|
|||||||
if let value = Int32(timeout) {
|
if let value = Int32(timeout) {
|
||||||
return .fail(.starGiftResellTooEarly(value))
|
return .fail(.starGiftResellTooEarly(value))
|
||||||
}
|
}
|
||||||
|
} else if error.errorDescription == "STARGIFT_USER_USAGE_LIMITED" {
|
||||||
|
return .fail(.starGiftUserLimit)
|
||||||
}
|
}
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
@ -651,6 +658,7 @@ public enum SendBotPaymentFormError {
|
|||||||
case alreadyPaid
|
case alreadyPaid
|
||||||
case starGiftOutOfStock
|
case starGiftOutOfStock
|
||||||
case disallowedStarGift
|
case disallowedStarGift
|
||||||
|
case starGiftUserLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SendBotPaymentResult {
|
public enum SendBotPaymentResult {
|
||||||
|
|||||||
@ -301,6 +301,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
case availability
|
case availability
|
||||||
case giftAddress
|
case giftAddress
|
||||||
case resellStars
|
case resellStars
|
||||||
|
case resellAmounts
|
||||||
|
case resellForTonOnly
|
||||||
case releasedBy
|
case releasedBy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,10 +556,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
public let attributes: [Attribute]
|
public let attributes: [Attribute]
|
||||||
public let availability: Availability
|
public let availability: Availability
|
||||||
public let giftAddress: String?
|
public let giftAddress: String?
|
||||||
public let resellStars: Int64?
|
public let resellAmounts: [CurrencyAmount]?
|
||||||
|
public let resellForTonOnly: Bool
|
||||||
public let releasedBy: EnginePeer.Id?
|
public let releasedBy: EnginePeer.Id?
|
||||||
|
|
||||||
public init(id: Int64, title: String, number: Int32, slug: String, owner: Owner, attributes: [Attribute], availability: Availability, giftAddress: String?, resellStars: Int64?, releasedBy: EnginePeer.Id?) {
|
public init(id: Int64, title: String, number: Int32, slug: String, owner: Owner, attributes: [Attribute], availability: Availability, giftAddress: String?, resellAmounts: [CurrencyAmount]?, resellForTonOnly: Bool, releasedBy: EnginePeer.Id?) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.title = title
|
self.title = title
|
||||||
self.number = number
|
self.number = number
|
||||||
@ -566,7 +569,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
self.attributes = attributes
|
self.attributes = attributes
|
||||||
self.availability = availability
|
self.availability = availability
|
||||||
self.giftAddress = giftAddress
|
self.giftAddress = giftAddress
|
||||||
self.resellStars = resellStars
|
self.resellAmounts = resellAmounts
|
||||||
|
self.resellForTonOnly = resellForTonOnly
|
||||||
self.releasedBy = releasedBy
|
self.releasedBy = releasedBy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,7 +592,14 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
self.attributes = try container.decode([UniqueGift.Attribute].self, forKey: .attributes)
|
self.attributes = try container.decode([UniqueGift.Attribute].self, forKey: .attributes)
|
||||||
self.availability = try container.decode(UniqueGift.Availability.self, forKey: .availability)
|
self.availability = try container.decode(UniqueGift.Availability.self, forKey: .availability)
|
||||||
self.giftAddress = try container.decodeIfPresent(String.self, forKey: .giftAddress)
|
self.giftAddress = try container.decodeIfPresent(String.self, forKey: .giftAddress)
|
||||||
self.resellStars = try container.decodeIfPresent(Int64.self, forKey: .resellStars)
|
if let resellAmounts = try container.decodeIfPresent([CurrencyAmount].self, forKey: .resellAmounts) {
|
||||||
|
self.resellAmounts = resellAmounts
|
||||||
|
} else if let resellStars = try container.decodeIfPresent(Int64.self, forKey: .resellStars) {
|
||||||
|
self.resellAmounts = [CurrencyAmount(amount: StarsAmount(value: resellStars, nanos: 0), currency: .stars)]
|
||||||
|
} else {
|
||||||
|
self.resellAmounts = []
|
||||||
|
}
|
||||||
|
self.resellForTonOnly = try container.decodeIfPresent(Bool.self, forKey: .resellForTonOnly) ?? false
|
||||||
self.releasedBy = try container.decodeIfPresent(EnginePeer.Id.self, forKey: .releasedBy)
|
self.releasedBy = try container.decodeIfPresent(EnginePeer.Id.self, forKey: .releasedBy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,7 +620,14 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
self.attributes = (try? decoder.decodeObjectArrayWithCustomDecoderForKey(CodingKeys.attributes.rawValue, decoder: { UniqueGift.Attribute(decoder: $0) })) ?? []
|
self.attributes = (try? decoder.decodeObjectArrayWithCustomDecoderForKey(CodingKeys.attributes.rawValue, decoder: { UniqueGift.Attribute(decoder: $0) })) ?? []
|
||||||
self.availability = decoder.decodeObjectForKey(CodingKeys.availability.rawValue, decoder: { UniqueGift.Availability(decoder: $0) }) as! UniqueGift.Availability
|
self.availability = decoder.decodeObjectForKey(CodingKeys.availability.rawValue, decoder: { UniqueGift.Availability(decoder: $0) }) as! UniqueGift.Availability
|
||||||
self.giftAddress = decoder.decodeOptionalStringForKey(CodingKeys.giftAddress.rawValue)
|
self.giftAddress = decoder.decodeOptionalStringForKey(CodingKeys.giftAddress.rawValue)
|
||||||
self.resellStars = decoder.decodeOptionalInt64ForKey(CodingKeys.resellStars.rawValue)
|
if let resellAmounts = decoder.decodeCodable([CurrencyAmount].self, forKey: CodingKeys.resellAmounts.rawValue) {
|
||||||
|
self.resellAmounts = resellAmounts
|
||||||
|
} else if let resellStars = decoder.decodeOptionalInt64ForKey(CodingKeys.resellStars.rawValue) {
|
||||||
|
self.resellAmounts = [CurrencyAmount(amount: StarsAmount(value: resellStars, nanos: 0), currency: .stars)]
|
||||||
|
} else {
|
||||||
|
self.resellAmounts = nil
|
||||||
|
}
|
||||||
|
self.resellForTonOnly = decoder.decodeBoolForKey(CodingKeys.resellForTonOnly.rawValue, orElse: false)
|
||||||
self.releasedBy = decoder.decodeOptionalInt64ForKey(CodingKeys.releasedBy.rawValue).flatMap { EnginePeer.Id($0) }
|
self.releasedBy = decoder.decodeOptionalInt64ForKey(CodingKeys.releasedBy.rawValue).flatMap { EnginePeer.Id($0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -630,7 +648,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
try container.encode(self.attributes, forKey: .attributes)
|
try container.encode(self.attributes, forKey: .attributes)
|
||||||
try container.encode(self.availability, forKey: .availability)
|
try container.encode(self.availability, forKey: .availability)
|
||||||
try container.encodeIfPresent(self.giftAddress, forKey: .giftAddress)
|
try container.encodeIfPresent(self.giftAddress, forKey: .giftAddress)
|
||||||
try container.encodeIfPresent(self.resellStars, forKey: .resellStars)
|
try container.encodeIfPresent(self.resellAmounts, forKey: .resellAmounts)
|
||||||
|
try container.encode(self.resellForTonOnly, forKey: .resellForTonOnly)
|
||||||
try container.encodeIfPresent(self.releasedBy, forKey: .releasedBy)
|
try container.encodeIfPresent(self.releasedBy, forKey: .releasedBy)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -654,11 +673,12 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: CodingKeys.giftAddress.rawValue)
|
encoder.encodeNil(forKey: CodingKeys.giftAddress.rawValue)
|
||||||
}
|
}
|
||||||
if let resellStars = self.resellStars {
|
if let resellAmounts = self.resellAmounts {
|
||||||
encoder.encodeInt64(resellStars, forKey: CodingKeys.resellStars.rawValue)
|
encoder.encodeCodable(resellAmounts, forKey: CodingKeys.resellAmounts.rawValue)
|
||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: CodingKeys.resellStars.rawValue)
|
encoder.encodeNil(forKey: CodingKeys.resellAmounts.rawValue)
|
||||||
}
|
}
|
||||||
|
encoder.encodeBool(self.resellForTonOnly, forKey: CodingKeys.resellForTonOnly.rawValue)
|
||||||
if let releasedBy = self.releasedBy {
|
if let releasedBy = self.releasedBy {
|
||||||
encoder.encodeInt64(releasedBy.toInt64(), forKey: CodingKeys.releasedBy.rawValue)
|
encoder.encodeInt64(releasedBy.toInt64(), forKey: CodingKeys.releasedBy.rawValue)
|
||||||
} else {
|
} else {
|
||||||
@ -666,7 +686,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func withResellStars(_ resellStars: Int64?) -> UniqueGift {
|
public func withResellAmounts(_ resellAmounts: [CurrencyAmount]?) -> UniqueGift {
|
||||||
return UniqueGift(
|
return UniqueGift(
|
||||||
id: self.id,
|
id: self.id,
|
||||||
title: self.title,
|
title: self.title,
|
||||||
@ -676,7 +696,8 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
|||||||
attributes: self.attributes,
|
attributes: self.attributes,
|
||||||
availability: self.availability,
|
availability: self.availability,
|
||||||
giftAddress: self.giftAddress,
|
giftAddress: self.giftAddress,
|
||||||
resellStars: resellStars,
|
resellAmounts: resellAmounts,
|
||||||
|
resellForTonOnly: self.resellForTonOnly,
|
||||||
releasedBy: self.releasedBy
|
releasedBy: self.releasedBy
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -787,7 +808,7 @@ extension StarGift {
|
|||||||
return nil
|
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))
|
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))
|
||||||
case let .starGiftUnique(_, id, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellStars, releasedBy):
|
case let .starGiftUnique(flags, id, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellAmounts, releasedBy):
|
||||||
let owner: StarGift.UniqueGift.Owner
|
let owner: StarGift.UniqueGift.Owner
|
||||||
if let ownerAddress {
|
if let ownerAddress {
|
||||||
owner = .address(ownerAddress)
|
owner = .address(ownerAddress)
|
||||||
@ -798,7 +819,8 @@ extension StarGift {
|
|||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
self = .unique(StarGift.UniqueGift(id: id, title: title, number: num, slug: slug, owner: owner, attributes: attributes.compactMap { UniqueGift.Attribute(apiAttribute: $0) }, availability: UniqueGift.Availability(issued: availabilityIssued, total: availabilityTotal), giftAddress: giftAddress, resellStars: resellStars, releasedBy: releasedBy?.peerId))
|
let resellAmounts = resellAmounts?.compactMap { CurrencyAmount(apiAmount: $0) }
|
||||||
|
self = .unique(StarGift.UniqueGift(id: id, 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: (flags & (1 << 7)) != 0, releasedBy: releasedBy?.peerId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -948,8 +970,8 @@ public enum UpgradeStarGiftError {
|
|||||||
case generic
|
case generic
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_buyStarGift(account: Account, slug: String, peerId: EnginePeer.Id, price: Int64?) -> Signal<Never, BuyStarGiftError> {
|
func _internal_buyStarGift(account: Account, slug: String, peerId: EnginePeer.Id, price: CurrencyAmount?) -> Signal<Never, BuyStarGiftError> {
|
||||||
let source: BotPaymentInvoiceSource = .starGiftResale(slug: slug, toPeerId: peerId)
|
let source: BotPaymentInvoiceSource = .starGiftResale(slug: slug, toPeerId: peerId, ton: price?.currency == .ton)
|
||||||
return _internal_fetchBotPaymentForm(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, source: source, themeParams: nil)
|
return _internal_fetchBotPaymentForm(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, source: source, themeParams: nil)
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { error -> Signal<BotPaymentForm?, BuyStarGiftError> in
|
|> `catch` { error -> Signal<BotPaymentForm?, BuyStarGiftError> in
|
||||||
@ -960,7 +982,7 @@ func _internal_buyStarGift(account: Account, slug: String, peerId: EnginePeer.Id
|
|||||||
}
|
}
|
||||||
|> mapToSignal { paymentForm in
|
|> mapToSignal { paymentForm in
|
||||||
if let paymentForm {
|
if let paymentForm {
|
||||||
if let paymentPrice = paymentForm.invoice.prices.first?.amount, let price, paymentPrice > price {
|
if let paymentPrice = paymentForm.invoice.prices.first?.amount, let price, paymentPrice > price.amount.value {
|
||||||
return .fail(.priceChanged(paymentPrice))
|
return .fail(.priceChanged(paymentPrice))
|
||||||
}
|
}
|
||||||
return _internal_sendStarsPaymentForm(account: account, formId: paymentForm.id, source: source)
|
return _internal_sendStarsPaymentForm(account: account, formId: paymentForm.id, source: source)
|
||||||
@ -1594,15 +1616,15 @@ private final class ProfileGiftsContextImpl {
|
|||||||
return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId)
|
return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64?) -> Signal<Never, BuyStarGiftError> {
|
func buyStarGift(slug: String, peerId: EnginePeer.Id, price: CurrencyAmount?) -> Signal<Never, BuyStarGiftError> {
|
||||||
var listingPrice: Int64?
|
var listingPrice: CurrencyAmount?
|
||||||
if let gift = self.gifts.first(where: { gift in
|
if let gift = self.gifts.first(where: { gift in
|
||||||
if case let .unique(uniqueGift) = gift.gift, uniqueGift.slug == slug {
|
if case let .unique(uniqueGift) = gift.gift, uniqueGift.slug == slug {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}), case let .unique(uniqueGift) = gift.gift {
|
}), case let .unique(uniqueGift) = gift.gift {
|
||||||
listingPrice = uniqueGift.resellStars
|
listingPrice = uniqueGift.resellAmounts?.first(where: { $0.currency == .stars })
|
||||||
}
|
}
|
||||||
|
|
||||||
if listingPrice == nil {
|
if listingPrice == nil {
|
||||||
@ -1612,7 +1634,7 @@ private final class ProfileGiftsContextImpl {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}), case let .unique(uniqueGift) = gift.gift {
|
}), case let .unique(uniqueGift) = gift.gift {
|
||||||
listingPrice = uniqueGift.resellStars
|
listingPrice = uniqueGift.resellAmounts?.first(where: { $0.currency == .stars })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1776,7 +1798,7 @@ private final class ProfileGiftsContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateStarGiftResellPrice(reference: StarGiftReference, price: Int64?, id: Int64?) -> Signal<Never, UpdateStarGiftPriceError> {
|
func updateStarGiftResellPrice(reference: StarGiftReference, price: CurrencyAmount?, id: Int64?) -> Signal<Never, UpdateStarGiftPriceError> {
|
||||||
return Signal { [weak self] subscriber in
|
return Signal { [weak self] subscriber in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return EmptyDisposable
|
return EmptyDisposable
|
||||||
@ -1806,7 +1828,7 @@ private final class ProfileGiftsContextImpl {
|
|||||||
return false
|
return false
|
||||||
}) {
|
}) {
|
||||||
if case let .unique(uniqueGift) = self.gifts[index].gift {
|
if case let .unique(uniqueGift) = self.gifts[index].gift {
|
||||||
let updatedUniqueGift = uniqueGift.withResellStars(price)
|
let updatedUniqueGift = uniqueGift.withResellAmounts(price.flatMap { [$0] })
|
||||||
let updatedGift = self.gifts[index].withGift(.unique(updatedUniqueGift))
|
let updatedGift = self.gifts[index].withGift(.unique(updatedUniqueGift))
|
||||||
self.gifts[index] = updatedGift
|
self.gifts[index] = updatedGift
|
||||||
}
|
}
|
||||||
@ -1829,7 +1851,7 @@ private final class ProfileGiftsContextImpl {
|
|||||||
return false
|
return false
|
||||||
}) {
|
}) {
|
||||||
if case let .unique(uniqueGift) = self.filteredGifts[index].gift {
|
if case let .unique(uniqueGift) = self.filteredGifts[index].gift {
|
||||||
let updatedUniqueGift = uniqueGift.withResellStars(price)
|
let updatedUniqueGift = uniqueGift.withResellAmounts(price.flatMap { [$0] })
|
||||||
let updatedGift = self.filteredGifts[index].withGift(.unique(updatedUniqueGift))
|
let updatedGift = self.filteredGifts[index].withGift(.unique(updatedUniqueGift))
|
||||||
self.filteredGifts[index] = updatedGift
|
self.filteredGifts[index] = updatedGift
|
||||||
}
|
}
|
||||||
@ -2143,6 +2165,28 @@ public final class ProfileGiftsContext {
|
|||||||
collectionIds: self.collectionIds
|
collectionIds: self.collectionIds
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func withCollectionIds(_ collectionIds: [Int32]?) -> StarGift {
|
||||||
|
return StarGift(
|
||||||
|
gift: self.gift,
|
||||||
|
reference: self.reference,
|
||||||
|
fromPeer: self.fromPeer,
|
||||||
|
date: self.date,
|
||||||
|
text: self.text,
|
||||||
|
entities: self.entities,
|
||||||
|
nameHidden: self.nameHidden,
|
||||||
|
savedToProfile: self.savedToProfile,
|
||||||
|
pinnedToTop: self.pinnedToTop,
|
||||||
|
convertStars: self.convertStars,
|
||||||
|
canUpgrade: self.canUpgrade,
|
||||||
|
canExportDate: self.canExportDate,
|
||||||
|
upgradeStars: self.upgradeStars,
|
||||||
|
transferStars: self.transferStars,
|
||||||
|
canTransferDate: self.canTransferDate,
|
||||||
|
canResaleDate: self.canResaleDate,
|
||||||
|
collectionIds: collectionIds
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DataState: Equatable {
|
public enum DataState: Equatable {
|
||||||
@ -2232,7 +2276,7 @@ public final class ProfileGiftsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64? = nil) -> Signal<Never, BuyStarGiftError> {
|
public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: CurrencyAmount? = nil) -> Signal<Never, BuyStarGiftError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
let disposable = MetaDisposable()
|
let disposable = MetaDisposable()
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
@ -2300,7 +2344,7 @@ public final class ProfileGiftsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateStarGiftResellPrice(reference: StarGiftReference, price: Int64?, id: Int64? = nil) -> Signal<Never, UpdateStarGiftPriceError> {
|
public func updateStarGiftResellPrice(reference: StarGiftReference, price: CurrencyAmount?, id: Int64? = nil) -> Signal<Never, UpdateStarGiftPriceError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
let disposable = MetaDisposable()
|
let disposable = MetaDisposable()
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
@ -2646,7 +2690,7 @@ func _internal_toggleStarGiftsNotifications(account: Account, peerId: EnginePeer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_updateStarGiftResalePrice(account: Account, reference: StarGiftReference, price: Int64?) -> Signal<Never, UpdateStarGiftPriceError> {
|
func _internal_updateStarGiftResalePrice(account: Account, reference: StarGiftReference, price: CurrencyAmount?) -> Signal<Never, UpdateStarGiftPriceError> {
|
||||||
return account.postbox.transaction { transaction in
|
return account.postbox.transaction { transaction in
|
||||||
return reference.apiStarGiftReference(transaction: transaction)
|
return reference.apiStarGiftReference(transaction: transaction)
|
||||||
}
|
}
|
||||||
@ -2655,7 +2699,8 @@ func _internal_updateStarGiftResalePrice(account: Account, reference: StarGiftRe
|
|||||||
guard let starGift else {
|
guard let starGift else {
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
return account.network.request(Api.functions.payments.updateStarGiftPrice(stargift: starGift, resellStars: price ?? 0))
|
let apiAmount = (price ?? CurrencyAmount(amount: .zero, currency: .stars)).apiAmount
|
||||||
|
return account.network.request(Api.functions.payments.updateStarGiftPrice(stargift: starGift, resellAmount: apiAmount))
|
||||||
|> mapError { error -> UpdateStarGiftPriceError in
|
|> mapError { error -> UpdateStarGiftPriceError in
|
||||||
if error.errorDescription.hasPrefix("STARGIFT_RESELL_TOO_EARLY_") {
|
if error.errorDescription.hasPrefix("STARGIFT_RESELL_TOO_EARLY_") {
|
||||||
let timeout = String(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "STARGIFT_RESELL_TOO_EARLY_".count)...])
|
let timeout = String(error.errorDescription[error.errorDescription.index(error.errorDescription.startIndex, offsetBy: "STARGIFT_RESELL_TOO_EARLY_".count)...])
|
||||||
@ -2818,7 +2863,7 @@ private final class ResaleGiftsContextImpl {
|
|||||||
|
|
||||||
var mappedGifts: [StarGift] = []
|
var mappedGifts: [StarGift] = []
|
||||||
for gift in gifts {
|
for gift in gifts {
|
||||||
if let mappedGift = StarGift(apiStarGift: gift), case let .unique(uniqueGift) = mappedGift, let resellStars = uniqueGift.resellStars, resellStars > 0 {
|
if let mappedGift = StarGift(apiStarGift: gift), case let .unique(uniqueGift) = mappedGift, let resellAmount = uniqueGift.resellAmounts?.first, resellAmount.amount.value > 0 {
|
||||||
mappedGifts.append(mappedGift)
|
mappedGifts.append(mappedGift)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2882,15 +2927,15 @@ private final class ResaleGiftsContextImpl {
|
|||||||
self.loadMore()
|
self.loadMore()
|
||||||
}
|
}
|
||||||
|
|
||||||
func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64?) -> Signal<Never, BuyStarGiftError> {
|
func buyStarGift(slug: String, peerId: EnginePeer.Id, price: CurrencyAmount?) -> Signal<Never, BuyStarGiftError> {
|
||||||
var listingPrice: Int64?
|
var listingPrice: CurrencyAmount?
|
||||||
if let gift = self.gifts.first(where: { gift in
|
if let gift = self.gifts.first(where: { gift in
|
||||||
if case let .unique(uniqueGift) = gift, uniqueGift.slug == slug {
|
if case let .unique(uniqueGift) = gift, uniqueGift.slug == slug {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}), case let .unique(uniqueGift) = gift {
|
}), case let .unique(uniqueGift) = gift {
|
||||||
listingPrice = uniqueGift.resellStars
|
listingPrice = uniqueGift.resellAmounts?.first(where: { $0.currency == .stars })
|
||||||
}
|
}
|
||||||
|
|
||||||
return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId, price: price ?? listingPrice)
|
return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId, price: price ?? listingPrice)
|
||||||
@ -2913,7 +2958,7 @@ private final class ResaleGiftsContextImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateStarGiftResellPrice(slug: String, price: Int64?) -> Signal<Never, UpdateStarGiftPriceError> {
|
func updateStarGiftResellPrice(slug: String, price: CurrencyAmount?) -> Signal<Never, UpdateStarGiftPriceError> {
|
||||||
return Signal { [weak self] subscriber in
|
return Signal { [weak self] subscriber in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return EmptyDisposable
|
return EmptyDisposable
|
||||||
@ -2936,7 +2981,7 @@ private final class ResaleGiftsContextImpl {
|
|||||||
}) {
|
}) {
|
||||||
if let price {
|
if let price {
|
||||||
if case let .unique(uniqueGift) = self.gifts[index] {
|
if case let .unique(uniqueGift) = self.gifts[index] {
|
||||||
self.gifts[index] = .unique(uniqueGift.withResellStars(price))
|
self.gifts[index] = .unique(uniqueGift.withResellAmounts([price]))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.gifts.remove(at: index)
|
self.gifts.remove(at: index)
|
||||||
@ -3040,7 +3085,7 @@ public final class ResaleGiftsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64? = nil) -> Signal<Never, BuyStarGiftError> {
|
public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: CurrencyAmount? = nil) -> Signal<Never, BuyStarGiftError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
let disposable = MetaDisposable()
|
let disposable = MetaDisposable()
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
@ -3054,7 +3099,7 @@ public final class ResaleGiftsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateStarGiftResellPrice(slug: String, price: Int64?) -> Signal<Never, UpdateStarGiftPriceError> {
|
public func updateStarGiftResellPrice(slug: String, price: CurrencyAmount?) -> Signal<Never, UpdateStarGiftPriceError> {
|
||||||
return Signal { subscriber in
|
return Signal { subscriber in
|
||||||
let disposable = MetaDisposable()
|
let disposable = MetaDisposable()
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
|
|||||||
@ -190,10 +190,15 @@ private func _internal_reorderStarGiftCollections(account: Account, peerId: Engi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func _internal_updateStarGiftCollection(account: Account, peerId: EnginePeer.Id, collectionId: Int32, giftsContext: ProfileGiftsContext?, actions: [ProfileGiftsCollectionsContext.UpdateAction]) -> Signal<StarGiftCollection?, NoError> {
|
private func _internal_updateStarGiftCollection(account: Account, peerId: EnginePeer.Id, collectionId: Int32, giftsContext: ProfileGiftsContext?, allGiftsContext: ProfileGiftsContext?, actions: [ProfileGiftsCollectionsContext.UpdateAction]) -> Signal<StarGiftCollection?, NoError> {
|
||||||
for action in actions {
|
for action in actions {
|
||||||
switch action {
|
switch action {
|
||||||
case let .addGifts(gifts):
|
case let .addGifts(gifts):
|
||||||
|
let gifts = gifts.map { gift in
|
||||||
|
var collectionIds = gift.collectionIds ?? []
|
||||||
|
collectionIds.append(collectionId)
|
||||||
|
return gift.withCollectionIds(collectionIds)
|
||||||
|
}
|
||||||
giftsContext?.insertStarGifts(gifts: gifts)
|
giftsContext?.insertStarGifts(gifts: gifts)
|
||||||
case let .removeGifts(gifts):
|
case let .removeGifts(gifts):
|
||||||
giftsContext?.removeStarGifts(references: gifts)
|
giftsContext?.removeStarGifts(references: gifts)
|
||||||
@ -294,6 +299,7 @@ public final class ProfileGiftsCollectionsContext {
|
|||||||
private let queue: Queue = .mainQueue()
|
private let queue: Queue = .mainQueue()
|
||||||
private let account: Account
|
private let account: Account
|
||||||
private let peerId: EnginePeer.Id
|
private let peerId: EnginePeer.Id
|
||||||
|
private weak var allGiftsContext: ProfileGiftsContext?
|
||||||
|
|
||||||
private let disposable = MetaDisposable()
|
private let disposable = MetaDisposable()
|
||||||
|
|
||||||
@ -306,9 +312,10 @@ public final class ProfileGiftsCollectionsContext {
|
|||||||
return self.stateValue.get()
|
return self.stateValue.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(account: Account, peerId: EnginePeer.Id) {
|
public init(account: Account, peerId: EnginePeer.Id, allGiftsContext: ProfileGiftsContext?) {
|
||||||
self.account = account
|
self.account = account
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
|
self.allGiftsContext = allGiftsContext
|
||||||
|
|
||||||
self.reload()
|
self.reload()
|
||||||
}
|
}
|
||||||
@ -362,7 +369,7 @@ public final class ProfileGiftsCollectionsContext {
|
|||||||
|
|
||||||
public func updateCollection(id: Int32, actions: [UpdateAction]) -> Signal<StarGiftCollection?, NoError> {
|
public func updateCollection(id: Int32, actions: [UpdateAction]) -> Signal<StarGiftCollection?, NoError> {
|
||||||
let giftsContext = self.giftsContextForCollection(id: id)
|
let giftsContext = self.giftsContextForCollection(id: id)
|
||||||
return _internal_updateStarGiftCollection(account: self.account, peerId: self.peerId, collectionId: id, giftsContext: giftsContext, actions: actions)
|
return _internal_updateStarGiftCollection(account: self.account, peerId: self.peerId, collectionId: id, giftsContext: giftsContext, allGiftsContext: self.allGiftsContext, actions: actions)
|
||||||
|> deliverOn(self.queue)
|
|> deliverOn(self.queue)
|
||||||
|> afterNext { [weak self] collection in
|
|> afterNext { [weak self] collection in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
|
|||||||
@ -129,7 +129,7 @@ public extension TelegramEngine {
|
|||||||
return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId)
|
return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: Int64?) -> Signal<Never, BuyStarGiftError> {
|
public func buyStarGift(slug: String, peerId: EnginePeer.Id, price: CurrencyAmount?) -> Signal<Never, BuyStarGiftError> {
|
||||||
return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId, price: price)
|
return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId, price: price)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ public extension TelegramEngine {
|
|||||||
return _internal_toggleStarGiftsNotifications(account: self.account, peerId: peerId, enabled: enabled)
|
return _internal_toggleStarGiftsNotifications(account: self.account, peerId: peerId, enabled: enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateStarGiftResalePrice(reference: StarGiftReference, price: Int64?) -> Signal<Never, UpdateStarGiftPriceError> {
|
public func updateStarGiftResalePrice(reference: StarGiftReference, price: CurrencyAmount?) -> Signal<Never, UpdateStarGiftPriceError> {
|
||||||
return _internal_updateStarGiftResalePrice(account: self.account, reference: reference, price: price)
|
return _internal_updateStarGiftResalePrice(account: self.account, reference: reference, price: price)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1204,7 +1204,14 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
attributedString = NSAttributedString(string: strings.Notification_StarsGift_SentSomeone, font: titleFont, textColor: primaryTextColor)
|
attributedString = NSAttributedString(string: strings.Notification_StarsGift_SentSomeone, font: titleFont, textColor: primaryTextColor)
|
||||||
} else if message.author?.id == accountPeerId {
|
} else if message.author?.id == accountPeerId {
|
||||||
if let resaleStars {
|
if let resaleStars {
|
||||||
let starsString = strings.Notification_StarsGift_Bought_Stars(Int32(resaleStars))
|
let starsString: String
|
||||||
|
switch resaleStars.currency {
|
||||||
|
case .stars:
|
||||||
|
starsString = strings.Notification_StarsGift_Bought_Stars(Int32(resaleStars.amount.value))
|
||||||
|
case .ton:
|
||||||
|
//TODO:localize
|
||||||
|
starsString = "\(Int32(resaleStars.amount.value)) TON"
|
||||||
|
}
|
||||||
if message.id.peerId == accountPeerId {
|
if message.id.peerId == accountPeerId {
|
||||||
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_BoughtForYouself(starsString)._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_BoughtForYouself(starsString)._tuple, body: bodyAttributes, argumentAttributes: [0: boldAttributes])
|
||||||
} else {
|
} else {
|
||||||
@ -1237,7 +1244,14 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
} else {
|
} else {
|
||||||
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
|
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: peerIds)
|
||||||
if let resaleStars {
|
if let resaleStars {
|
||||||
let starsString = strings.Notification_StarsGift_Bought_Stars(Int32(resaleStars))
|
let starsString: String
|
||||||
|
switch resaleStars.currency {
|
||||||
|
case .stars:
|
||||||
|
starsString = strings.Notification_StarsGift_Bought_Stars(Int32(resaleStars.amount.value))
|
||||||
|
case .ton:
|
||||||
|
//TODO:localize
|
||||||
|
starsString = "\(Int32(resaleStars.amount.value)) TON"
|
||||||
|
}
|
||||||
let giftTitle = "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))"
|
let giftTitle = "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))"
|
||||||
attributes[1] = boldAttributes
|
attributes[1] = boldAttributes
|
||||||
attributes[2] = boldAttributes
|
attributes[2] = boldAttributes
|
||||||
|
|||||||
@ -398,72 +398,92 @@ func generateCloseButtonImage(backgroundColor: UIColor, foregroundColor: UIColor
|
|||||||
|
|
||||||
public func presentAgeVerification(context: AccountContext, parentController: ViewController, completion: @escaping () -> Void) {
|
public func presentAgeVerification(context: AccountContext, parentController: ViewController, completion: @escaping () -> Void) {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let _ = (context.engine.data.get(
|
let _ = (contentSettingsConfiguration(network: context.account.network)
|
||||||
TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: ApplicationSpecificPreferencesKeys.ageVerificationState)
|
|> deliverOnMainQueue).start(next: { [weak parentController] settings in
|
||||||
) |> deliverOnMainQueue).start(next: { [weak parentController] ageVerificationStatePreference in
|
if !settings.canAdjustSensitiveContent {
|
||||||
let state = ageVerificationStatePreference?.get(AgeVerificationState.self) ?? AgeVerificationState.default
|
let alertController = textAlertController(
|
||||||
if state.verificationPassed {
|
context: context,
|
||||||
completion()
|
title: presentationData.strings.AgeVerification_Unavailable_Title,
|
||||||
} else {
|
text: presentationData.strings.AgeVerification_Unavailable_Text,
|
||||||
let infoScreen = AgeVerificationScreen(context: context, completion: { [weak parentController] check, availability in
|
actions: []
|
||||||
if check {
|
)
|
||||||
let scanScreen = FaceScanScreen(context: context, availability: availability, completion: { [weak parentController] passed in
|
parentController?.present(alertController, in: .window(.root))
|
||||||
if passed {
|
return
|
||||||
let _ = updateAgeVerificationState(engine: context.engine, { _ in
|
}
|
||||||
return AgeVerificationState(verificationPassed: passed)
|
let miniappPromise = Promise<EnginePeer?>(nil)
|
||||||
}).start()
|
var useVerifyAgeBot = false
|
||||||
completion()
|
if let value = context.currentAppConfiguration.with({ $0 }).data?["force_verify_age_bot"] as? Bool, value {
|
||||||
|
useVerifyAgeBot = value
|
||||||
let navigationController = parentController?.navigationController
|
}
|
||||||
Queue.mainQueue().after(2.0) {
|
if useVerifyAgeBot, let verifyAgeBotUsername = context.currentAppConfiguration.with({ $0 }).data?["verify_age_bot_username"] as? String {
|
||||||
let controller = UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.AgeVerification_Success_Title, text: presentationData.strings.AgeVerification_Success_Text, cancel: nil, destructive: false), action: { _ in return true })
|
miniappPromise.set(context.engine.peers.resolvePeerByName(name: verifyAgeBotUsername, referrer: nil)
|
||||||
(navigationController?.viewControllers.last as? ViewController)?.present(controller, in: .window(.root))
|
|> mapToSignal { result in
|
||||||
}
|
if case let .result(peer) = result {
|
||||||
} else {
|
return .single(peer)
|
||||||
let controller = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_banned", scale: 0.066, colors: [:], title: presentationData.strings.AgeVerification_Fail_Title, text: presentationData.strings.AgeVerification_Fail_Text, customUndoText: nil, timeout: nil), action: { _ in return true })
|
|
||||||
parentController?.present(controller, in: .window(.root))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
parentController?.push(scanScreen)
|
|
||||||
}
|
}
|
||||||
|
return .complete()
|
||||||
})
|
})
|
||||||
parentController?.push(infoScreen)
|
|
||||||
}
|
}
|
||||||
|
let infoScreen = AgeVerificationScreen(context: context, completion: { [weak parentController] check, availability in
|
||||||
|
if check {
|
||||||
|
var requiredAge = 18
|
||||||
|
if let value = context.currentAppConfiguration.with({ $0 }).data?["verify_age_min"] as? Double {
|
||||||
|
requiredAge = Int(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
let success = { [weak parentController] in
|
||||||
|
completion()
|
||||||
|
|
||||||
|
let navigationController = parentController?.navigationController
|
||||||
|
Queue.mainQueue().after(2.0) {
|
||||||
|
let controller = UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: presentationData.strings.AgeVerification_Success_Title, text: presentationData.strings.AgeVerification_Success_Text, cancel: nil, destructive: false), action: { _ in return true })
|
||||||
|
(navigationController?.viewControllers.last as? ViewController)?.present(controller, in: .current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let failure = { [weak parentController] in
|
||||||
|
let controller = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_banned", scale: 0.066, colors: [:], title: presentationData.strings.AgeVerification_Fail_Title, text: presentationData.strings.AgeVerification_Fail_Text, customUndoText: nil, timeout: nil), action: { _ in return true })
|
||||||
|
parentController?.present(controller, in: .current)
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = (miniappPromise.get()
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
|
if let peer, let parentController {
|
||||||
|
context.sharedContext.openWebApp(
|
||||||
|
context: context,
|
||||||
|
parentController: parentController,
|
||||||
|
updatedPresentationData: nil,
|
||||||
|
botPeer: peer,
|
||||||
|
chatPeer: nil,
|
||||||
|
threadId: nil,
|
||||||
|
buttonText: "",
|
||||||
|
url: "",
|
||||||
|
simple: true,
|
||||||
|
source: .generic,
|
||||||
|
skipTermsOfService: true,
|
||||||
|
payload: nil,
|
||||||
|
verifyAgeCompletion: { age in
|
||||||
|
if age >= requiredAge {
|
||||||
|
success()
|
||||||
|
} else {
|
||||||
|
failure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
let scanScreen = FaceScanScreen(context: context, availability: availability, completion: { age in
|
||||||
|
if age >= requiredAge {
|
||||||
|
success()
|
||||||
|
} else {
|
||||||
|
failure()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
parentController?.push(scanScreen)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
parentController?.push(infoScreen)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateAgeVerificationState(engine: TelegramEngine, _ f: @escaping (AgeVerificationState) -> AgeVerificationState) -> Signal<Never, NoError> {
|
|
||||||
return engine.preferences.update(id: ApplicationSpecificPreferencesKeys.ageVerificationState, { entry in
|
|
||||||
let currentSettings: AgeVerificationState
|
|
||||||
if let entry = entry?.get(AgeVerificationState.self) {
|
|
||||||
currentSettings = entry
|
|
||||||
} else {
|
|
||||||
currentSettings = .default
|
|
||||||
}
|
|
||||||
return SharedPreferencesEntry(f(currentSettings))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct AgeVerificationState: Equatable, Codable {
|
|
||||||
public var verificationPassed: Bool
|
|
||||||
|
|
||||||
public static var `default`: AgeVerificationState {
|
|
||||||
return AgeVerificationState(verificationPassed: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(verificationPassed: Bool) {
|
|
||||||
self.verificationPassed = verificationPassed
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
|
||||||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
|
||||||
|
|
||||||
self.verificationPassed = (try container.decode(Int32.self, forKey: "verificationPassed")) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
|
||||||
var container = encoder.container(keyedBy: StringCodingKey.self)
|
|
||||||
|
|
||||||
try container.encode((self.verificationPassed ? 1 : 0) as Int32, forKey: "verificationPassed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -20,8 +20,6 @@ import ZipArchive
|
|||||||
import PlainButtonComponent
|
import PlainButtonComponent
|
||||||
import MultilineTextComponent
|
import MultilineTextComponent
|
||||||
|
|
||||||
private let requiredAge = 18
|
|
||||||
|
|
||||||
final class FaceScanScreenComponent: Component {
|
final class FaceScanScreenComponent: Component {
|
||||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
@ -109,7 +107,7 @@ final class FaceScanScreenComponent: Component {
|
|||||||
|
|
||||||
self.backgroundColor = .black
|
self.backgroundColor = .black
|
||||||
|
|
||||||
self.previewLayer.backgroundColor = UIColor.red.cgColor
|
//self.previewLayer.backgroundColor = UIColor.red.cgColor
|
||||||
self.previewLayer.videoGravity = .resizeAspectFill
|
self.previewLayer.videoGravity = .resizeAspectFill
|
||||||
self.layer.addSublayer(previewLayer)
|
self.layer.addSublayer(previewLayer)
|
||||||
|
|
||||||
@ -240,7 +238,7 @@ final class FaceScanScreenComponent: Component {
|
|||||||
let targetCenter = CGPoint(x: 0.5, y: 0.5)
|
let targetCenter = CGPoint(x: 0.5, y: 0.5)
|
||||||
let distance = sqrt(pow(faceCenter.x - targetCenter.x, 2) + pow(faceCenter.y - targetCenter.y, 2))
|
let distance = sqrt(pow(faceCenter.x - targetCenter.x, 2) + pow(faceCenter.y - targetCenter.y, 2))
|
||||||
|
|
||||||
if distance < 0.35 {
|
if distance < 0.24 {
|
||||||
switch processState {
|
switch processState {
|
||||||
case .waitingForFace:
|
case .waitingForFace:
|
||||||
self.processState = .positioning
|
self.processState = .positioning
|
||||||
@ -320,7 +318,7 @@ final class FaceScanScreenComponent: Component {
|
|||||||
if !self.ages.isEmpty {
|
if !self.ages.isEmpty {
|
||||||
let averageAge = self.ages.reduce(0, +) / Double(self.ages.count)
|
let averageAge = self.ages.reduce(0, +) / Double(self.ages.count)
|
||||||
if let environment = self.environment, let controller = environment.controller() as? FaceScanScreen {
|
if let environment = self.environment, let controller = environment.controller() as? FaceScanScreen {
|
||||||
controller.completion(averageAge >= Double(requiredAge))
|
controller.completion(Int(averageAge))
|
||||||
controller.dismiss(animated: true)
|
controller.dismiss(animated: true)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -436,7 +434,7 @@ final class FaceScanScreenComponent: Component {
|
|||||||
|
|
||||||
let center = CGPoint(x: availableSize.width / 2, y: environment.statusBarHeight + 10.0 + widthRadius * 1.3)
|
let center = CGPoint(x: availableSize.width / 2, y: environment.statusBarHeight + 10.0 + widthRadius * 1.3)
|
||||||
|
|
||||||
var previewScale = 1.0
|
var previewScale = 0.85
|
||||||
if self.processState == .tracking || self.processState == .readyToStart || self.processState == .completed || self.transitioningToViewFinder {
|
if self.processState == .tracking || self.processState == .readyToStart || self.processState == .completed || self.transitioningToViewFinder {
|
||||||
let circlePath = CGPath(roundedRect: CGRect(x: center.x - radius, y: center.y - radius, width: radius * 2, height: radius * 2), cornerWidth: radius, cornerHeight: radius, transform: nil)
|
let circlePath = CGPath(roundedRect: CGRect(x: center.x - radius, y: center.y - radius, width: radius * 2, height: radius * 2), cornerWidth: radius, cornerHeight: radius, transform: nil)
|
||||||
path.addPath(circlePath)
|
path.addPath(circlePath)
|
||||||
@ -457,7 +455,6 @@ final class FaceScanScreenComponent: Component {
|
|||||||
self.frameView.frame = frameViewFrame
|
self.frameView.frame = frameViewFrame
|
||||||
self.frameView.update(size: frameViewFrame.size)
|
self.frameView.update(size: frameViewFrame.size)
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
var instructionString = environment.strings.FaceScan_Instruction_Position
|
var instructionString = environment.strings.FaceScan_Instruction_Position
|
||||||
switch self.processState {
|
switch self.processState {
|
||||||
case .waitingForFace, .positioning:
|
case .waitingForFace, .positioning:
|
||||||
@ -545,12 +542,12 @@ final class FaceScanScreenComponent: Component {
|
|||||||
|
|
||||||
public final class FaceScanScreen: ViewControllerComponentContainer {
|
public final class FaceScanScreen: ViewControllerComponentContainer {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
fileprivate let completion: (Bool) -> Void
|
fileprivate let completion: (Int) -> Void
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
availability: Signal<AgeVerificationAvailability, NoError>,
|
availability: Signal<AgeVerificationAvailability, NoError>,
|
||||||
completion: @escaping (Bool) -> Void
|
completion: @escaping (Int) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
|
|||||||
@ -363,6 +363,8 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
let entities = generateChatInputTextEntities(self.textInputState.text)
|
let entities = generateChatInputTextEntities(self.textInputState.text)
|
||||||
|
|
||||||
var finalPrice: Int64
|
var finalPrice: Int64
|
||||||
|
var perUserLimit: Int32?
|
||||||
|
var giftFile: TelegramMediaFile?
|
||||||
let source: BotPaymentInvoiceSource
|
let source: BotPaymentInvoiceSource
|
||||||
switch component.subject {
|
switch component.subject {
|
||||||
case let .premium(product):
|
case let .premium(product):
|
||||||
@ -377,6 +379,8 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
if self.includeUpgrade, let upgradeStars = starGift.upgradeStars {
|
if self.includeUpgrade, let upgradeStars = starGift.upgradeStars {
|
||||||
finalPrice += upgradeStars
|
finalPrice += upgradeStars
|
||||||
}
|
}
|
||||||
|
perUserLimit = starGift.perUserLimit?.total
|
||||||
|
giftFile = starGift.file
|
||||||
source = .starGift(hideName: self.hideName, includeUpgrade: self.includeUpgrade, peerId: peerId, giftId: starGift.id, text: self.textInputState.text.string, entities: entities)
|
source = .starGift(hideName: self.hideName, includeUpgrade: self.includeUpgrade, peerId: peerId, giftId: starGift.id, text: self.textInputState.text.string, entities: entities)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +399,8 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
switch error {
|
switch error {
|
||||||
case .disallowedStarGifts:
|
case .disallowedStarGifts:
|
||||||
return .fail(.disallowedStarGift)
|
return .fail(.disallowedStarGift)
|
||||||
|
case .starGiftsUserLimit:
|
||||||
|
return .fail(.starGiftUserLimit)
|
||||||
default:
|
default:
|
||||||
return .fail(.generic)
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
@ -468,6 +474,14 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
|
|
||||||
var errorText: String?
|
var errorText: String?
|
||||||
switch error {
|
switch error {
|
||||||
|
case .starGiftUserLimit:
|
||||||
|
if let perUserLimit, let giftFile {
|
||||||
|
let text = presentationData.strings.Gift_Options_Gift_BuyLimitReached(perUserLimit)
|
||||||
|
let undoController = UndoOverlayController(presentationData: presentationData, content: .sticker(context: component.context, file: giftFile, loop: true, title: nil, text: text, undoText: nil, customAction: nil), action: { _ in return false })
|
||||||
|
controller.present(undoController, in: .current)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
case .starGiftOutOfStock:
|
case .starGiftOutOfStock:
|
||||||
errorText = presentationData.strings.Gift_Send_ErrorOutOfStock
|
errorText = presentationData.strings.Gift_Send_ErrorOutOfStock
|
||||||
case .disallowedStarGift:
|
case .disallowedStarGift:
|
||||||
|
|||||||
@ -233,7 +233,8 @@ final class GiftStoreScreenComponent: Component {
|
|||||||
color: ribbonColor
|
color: ribbonColor
|
||||||
)
|
)
|
||||||
|
|
||||||
let subject: GiftItemComponent.Subject = .uniqueGift(gift: uniqueGift, price: "# \(presentationStringsFormattedNumber(Int32(uniqueGift.resellStars ?? 0), environment.dateTimeFormat.groupingSeparator))")
|
//TODO:release
|
||||||
|
let subject: GiftItemComponent.Subject = .uniqueGift(gift: uniqueGift, price: "# \(presentationStringsFormattedNumber(Int32(uniqueGift.resellAmounts?.first(where: { $0.currency == .stars })?.amount.value ?? 0), environment.dateTimeFormat.groupingSeparator))")
|
||||||
let _ = visibleItem.update(
|
let _ = visibleItem.update(
|
||||||
transition: itemTransition,
|
transition: itemTransition,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
|
|||||||
@ -176,8 +176,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let _ = arguments.resellStars {
|
if let _ = arguments.resellAmounts {
|
||||||
self.buyFormDisposable = (context.engine.payments.fetchBotPaymentForm(source: .starGiftResale(slug: gift.slug, toPeerId: context.account.peerId), themeParams: nil)
|
self.buyFormDisposable = (context.engine.payments.fetchBotPaymentForm(source: .starGiftResale(slug: gift.slug, toPeerId: context.account.peerId, ton: false), themeParams: nil)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] paymentForm in
|
|> deliverOnMainQueue).start(next: { [weak self] paymentForm in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -288,11 +288,14 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var minRequiredAmount = StarsAmount(value: 100, nanos: 0)
|
var minRequiredAmount = StarsAmount(value: 100, nanos: 0)
|
||||||
if let resellStars = self.subject.arguments?.resellStars {
|
var canUpgrade = false
|
||||||
minRequiredAmount = StarsAmount(value: resellStars, nanos: 0)
|
if let resellStars = self.subject.arguments?.resellAmounts?.first(where: { $0.currency == .stars }) {
|
||||||
|
minRequiredAmount = resellStars.amount
|
||||||
|
} else if let arguments = self.subject.arguments, arguments.canUpgrade && arguments.upgradeStars == nil {
|
||||||
|
canUpgrade = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if let starsContext = context.starsContext, let state = starsContext.currentState, state.balance < minRequiredAmount {
|
if let starsContext = context.starsContext, let state = starsContext.currentState, state.balance < minRequiredAmount || canUpgrade {
|
||||||
self.optionsDisposable = (context.engine.payments.starsTopUpOptions()
|
self.optionsDisposable = (context.engine.payments.starsTopUpOptions()
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] options in
|
|> deliverOnMainQueue).start(next: { [weak self] options in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -813,7 +816,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
let giftTitle = "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, presentationData.dateTimeFormat.groupingSeparator))"
|
let giftTitle = "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, presentationData.dateTimeFormat.groupingSeparator))"
|
||||||
let reference = arguments.reference ?? .slug(slug: gift.slug)
|
let reference = arguments.reference ?? .slug(slug: gift.slug)
|
||||||
|
|
||||||
if let resellStars = gift.resellStars, resellStars > 0, !update {
|
if let resellStars = gift.resellAmounts?.first, resellStars.amount.value > 0, !update {
|
||||||
let alertController = textAlertController(
|
let alertController = textAlertController(
|
||||||
context: context,
|
context: context,
|
||||||
title: presentationData.strings.Gift_View_Resale_Unlist_Title,
|
title: presentationData.strings.Gift_View_Resale_Unlist_Title,
|
||||||
@ -832,9 +835,9 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
switch self.subject {
|
switch self.subject {
|
||||||
case let .profileGift(peerId, currentSubject):
|
case let .profileGift(peerId, currentSubject):
|
||||||
self.subject = .profileGift(peerId, currentSubject.withGift(.unique(gift.withResellStars(nil))))
|
self.subject = .profileGift(peerId, currentSubject.withGift(.unique(gift.withResellAmounts(nil))))
|
||||||
case let .uniqueGift(_, recipientPeerId):
|
case let .uniqueGift(_, recipientPeerId):
|
||||||
self.subject = .uniqueGift(gift.withResellStars(nil), recipientPeerId)
|
self.subject = .uniqueGift(gift.withResellAmounts(nil), recipientPeerId)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -873,6 +876,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let price = CurrencyAmount(amount: StarsAmount(value: price, nanos: 0), currency: .stars)
|
||||||
|
|
||||||
let _ = ((controller.updateResellStars?(price) ?? context.engine.payments.updateStarGiftResalePrice(reference: reference, price: price))
|
let _ = ((controller.updateResellStars?(price) ?? context.engine.payments.updateStarGiftResalePrice(reference: reference, price: price))
|
||||||
|> deliverOnMainQueue).startStandalone(error: { [weak self, weak controller] error in
|
|> deliverOnMainQueue).startStandalone(error: { [weak self, weak controller] error in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -908,9 +913,9 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
switch self.subject {
|
switch self.subject {
|
||||||
case let .profileGift(peerId, currentSubject):
|
case let .profileGift(peerId, currentSubject):
|
||||||
self.subject = .profileGift(peerId, currentSubject.withGift(.unique(gift.withResellStars(price))))
|
self.subject = .profileGift(peerId, currentSubject.withGift(.unique(gift.withResellAmounts([price]))))
|
||||||
case let .uniqueGift(_, recipientPeerId):
|
case let .uniqueGift(_, recipientPeerId):
|
||||||
self.subject = .uniqueGift(gift.withResellStars(price), recipientPeerId)
|
self.subject = .uniqueGift(gift.withResellAmounts([price]), recipientPeerId)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -918,7 +923,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
var text = presentationData.strings.Gift_View_Resale_List_Success(giftTitle).string
|
var text = presentationData.strings.Gift_View_Resale_List_Success(giftTitle).string
|
||||||
if update {
|
if update {
|
||||||
let starsString = presentationData.strings.Gift_View_Resale_Relist_Success_Stars(Int32(price))
|
let starsString = presentationData.strings.Gift_View_Resale_Relist_Success_Stars(Int32(price.amount.value))
|
||||||
text = presentationData.strings.Gift_View_Resale_Relist_Success(giftTitle, starsString).string
|
text = presentationData.strings.Gift_View_Resale_Relist_Success(giftTitle, starsString).string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,7 +1024,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .unique(gift) = arguments.gift, let resellStars = gift.resellStars, resellStars > 0 {
|
if case let .unique(gift) = arguments.gift, let resellAmount = gift.resellAmounts?.first, resellAmount.amount.value > 0 {
|
||||||
if arguments.reference != nil || gift.owner.peerId == context.account.peerId {
|
if arguments.reference != nil || gift.owner.peerId == context.account.peerId {
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_View_Context_ChangePrice, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_View_Context_ChangePrice, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/PriceTag"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/PriceTag"), color: theme.contextMenu.primaryColor)
|
||||||
@ -1063,7 +1068,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let _ = arguments.resellStars, case let .uniqueGift(uniqueGift, recipientPeerId) = subject, let _ = recipientPeerId {
|
if let _ = arguments.resellAmounts, case let .uniqueGift(uniqueGift, recipientPeerId) = subject, let _ = recipientPeerId {
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_View_Context_ViewInProfile, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Gift_View_Context_ViewInProfile, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Peer Info/ShowIcon"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Peer Info/ShowIcon"), color: theme.contextMenu.primaryColor)
|
||||||
}, action: { [weak self] c, _ in
|
}, action: { [weak self] c, _ in
|
||||||
@ -1160,8 +1165,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func commitBuy(acceptedPrice: Int64? = nil, skipConfirmation: Bool = false) {
|
func commitBuy(acceptedPrice: CurrencyAmount? = nil, skipConfirmation: Bool = false) {
|
||||||
guard let resellStars = self.subject.arguments?.resellStars, let starsContext = self.context.starsContext, let starsState = starsContext.currentState, case let .unique(uniqueGift) = self.subject.arguments?.gift else {
|
guard let resellAmount = self.subject.arguments?.resellAmounts?.first, let starsContext = self.context.starsContext, let starsState = starsContext.currentState, case let .unique(uniqueGift) = self.subject.arguments?.gift else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1198,7 +1203,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
self.inProgress = true
|
self.inProgress = true
|
||||||
self.updated()
|
self.updated()
|
||||||
|
|
||||||
let buyGiftImpl: ((String, EnginePeer.Id, Int64?) -> Signal<Never, BuyStarGiftError>)
|
let buyGiftImpl: ((String, EnginePeer.Id, CurrencyAmount?) -> Signal<Never, BuyStarGiftError>)
|
||||||
if let buyGift = controller.buyGift {
|
if let buyGift = controller.buyGift {
|
||||||
buyGiftImpl = { slug, peerId, price in
|
buyGiftImpl = { slug, peerId, price in
|
||||||
return buyGift(slug, peerId, price)
|
return buyGift(slug, peerId, price)
|
||||||
@ -1215,7 +1220,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.buyDisposable = (buyGiftImpl(uniqueGift.slug, recipientPeerId, acceptedPrice ?? resellStars)
|
self.buyDisposable = (buyGiftImpl(uniqueGift.slug, recipientPeerId, acceptedPrice ?? resellAmount)
|
||||||
|> deliverOnMainQueue).start(
|
|> deliverOnMainQueue).start(
|
||||||
error: { [weak self] error in
|
error: { [weak self] error in
|
||||||
guard let self, let controller = self.getController() else {
|
guard let self, let controller = self.getController() else {
|
||||||
@ -1227,8 +1232,9 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
switch error {
|
switch error {
|
||||||
case let .priceChanged(newPrice):
|
case let .priceChanged(newPrice):
|
||||||
|
//TODO:release
|
||||||
let errorTitle = presentationData.strings.Gift_Buy_ErrorPriceChanged_Title
|
let errorTitle = presentationData.strings.Gift_Buy_ErrorPriceChanged_Title
|
||||||
let originalPriceString = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text_Stars(Int32(resellStars))
|
let originalPriceString = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text_Stars(Int32(resellAmount.amount.value))
|
||||||
let newPriceString = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text_Stars(Int32(newPrice))
|
let newPriceString = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text_Stars(Int32(newPrice))
|
||||||
let errorText = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text(originalPriceString, newPriceString).string
|
let errorText = presentationData.strings.Gift_Buy_ErrorPriceChanged_Text(originalPriceString, newPriceString).string
|
||||||
|
|
||||||
@ -1241,7 +1247,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.commitBuy(acceptedPrice: newPrice, skipConfirmation: true)
|
//TODO:release
|
||||||
|
self.commitBuy(acceptedPrice: CurrencyAmount(amount: StarsAmount(value: newPrice, nanos: 0), currency: .ton), skipConfirmation: true)
|
||||||
}),
|
}),
|
||||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||||
})
|
})
|
||||||
@ -1395,7 +1402,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let text: String
|
let text: String
|
||||||
let starsString = presentationData.strings.Gift_Buy_Confirm_Text_Stars(Int32(resellStars))
|
//TODO:release
|
||||||
|
let starsString = presentationData.strings.Gift_Buy_Confirm_Text_Stars(Int32(resellAmount.amount.value))
|
||||||
|
|
||||||
if recipientPeerId == self.context.account.peerId {
|
if recipientPeerId == self.context.account.peerId {
|
||||||
text = presentationData.strings.Gift_Buy_Confirm_Text(giftTitle, starsString).string
|
text = presentationData.strings.Gift_Buy_Confirm_Text(giftTitle, starsString).string
|
||||||
@ -1407,7 +1415,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
title: presentationData.strings.Gift_Buy_Confirm_Title,
|
title: presentationData.strings.Gift_Buy_Confirm_Title,
|
||||||
text: text,
|
text: text,
|
||||||
actions: [
|
actions: [
|
||||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Gift_Buy_Confirm_BuyFor(Int32(resellStars)), action: {
|
TextAlertAction(type: .defaultAction, title: presentationData.strings.Gift_Buy_Confirm_BuyFor(Int32(resellAmount.amount.value)), action: {
|
||||||
action()
|
action()
|
||||||
}),
|
}),
|
||||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||||
@ -2763,8 +2771,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component: PlainButtonComponent(
|
component: PlainButtonComponent(
|
||||||
content: AnyComponent(
|
content: AnyComponent(
|
||||||
HeaderButtonComponent(
|
HeaderButtonComponent(
|
||||||
title: uniqueGift.resellStars == nil ? strings.Gift_View_Sell : strings.Gift_View_Unlist,
|
title: uniqueGift.resellAmounts == nil ? strings.Gift_View_Sell : strings.Gift_View_Unlist,
|
||||||
iconName: uniqueGift.resellStars == nil ? "Premium/Collectible/Sell" : "Premium/Collectible/Unlist"
|
iconName: uniqueGift.resellAmounts == nil ? "Premium/Collectible/Sell" : "Premium/Collectible/Unlist"
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
effectAlignment: .center,
|
effectAlignment: .center,
|
||||||
@ -3128,17 +3136,18 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
originY += table.size.height + 23.0
|
originY += table.size.height + 23.0
|
||||||
}
|
}
|
||||||
|
|
||||||
var resellStars: Int64?
|
var resellStars: CurrencyAmount?
|
||||||
var selling = false
|
var selling = false
|
||||||
if let uniqueGift {
|
if let uniqueGift {
|
||||||
resellStars = uniqueGift.resellStars
|
//TODO:release
|
||||||
|
resellStars = uniqueGift.resellAmounts?.first(where: { $0.currency == .ton })
|
||||||
|
|
||||||
if let resellStars {
|
if let resellStars {
|
||||||
if incoming || ownerPeerId == component.context.account.peerId {
|
if incoming || ownerPeerId == component.context.account.peerId {
|
||||||
let priceButton = priceButton.update(
|
let priceButton = priceButton.update(
|
||||||
component: PlainButtonComponent(
|
component: PlainButtonComponent(
|
||||||
content: AnyComponent(
|
content: AnyComponent(
|
||||||
PriceButtonComponent(price: presentationStringsFormattedNumber(Int32(resellStars), environment.dateTimeFormat.groupingSeparator))
|
PriceButtonComponent(price: presentationStringsFormattedNumber(Int32(resellStars.amount.value), environment.dateTimeFormat.groupingSeparator))
|
||||||
),
|
),
|
||||||
effectAlignment: .center,
|
effectAlignment: .center,
|
||||||
action: { [weak state] in
|
action: { [weak state] in
|
||||||
@ -3473,10 +3482,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
if state.cachedStarImage == nil || state.cachedStarImage?.1 !== theme {
|
if state.cachedStarImage == nil || state.cachedStarImage?.1 !== theme {
|
||||||
state.cachedStarImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: theme.list.itemCheckColors.foregroundColor)!, theme)
|
state.cachedStarImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: theme.list.itemCheckColors.foregroundColor)!, theme)
|
||||||
}
|
}
|
||||||
var upgradeString = strings.Gift_View_BuyFor
|
var buyString = strings.Gift_View_BuyFor
|
||||||
upgradeString += " # \(presentationStringsFormattedNumber(Int32(resellStars), environment.dateTimeFormat.groupingSeparator))"
|
//TODO:release
|
||||||
|
buyString += " # \(presentationStringsFormattedNumber(Int32(resellStars.amount.value), environment.dateTimeFormat.groupingSeparator))"
|
||||||
|
|
||||||
let buttonTitle = subject.arguments?.upgradeStars != nil ? strings.Gift_Upgrade_Confirm : upgradeString
|
let buttonTitle = subject.arguments?.upgradeStars != nil ? strings.Gift_Upgrade_Confirm : buyString
|
||||||
let buttonAttributedString = NSMutableAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
let buttonAttributedString = NSMutableAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
||||||
if let range = buttonAttributedString.string.range(of: "#"), let starImage = state.cachedStarImage?.0 {
|
if let range = buttonAttributedString.string.range(of: "#"), let starImage = state.cachedStarImage?.0 {
|
||||||
buttonAttributedString.addAttribute(.attachment, value: starImage, range: NSRange(range, in: buttonAttributedString.string))
|
buttonAttributedString.addAttribute(.attachment, value: starImage, range: NSRange(range, in: buttonAttributedString.string))
|
||||||
@ -3656,7 +3666,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
case upgradePreview([StarGift.UniqueGift.Attribute], String)
|
case upgradePreview([StarGift.UniqueGift.Attribute], String)
|
||||||
case wearPreview(StarGift.UniqueGift)
|
case wearPreview(StarGift.UniqueGift)
|
||||||
|
|
||||||
var arguments: (peerId: EnginePeer.Id?, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, reference: StarGiftReference?, incoming: Bool, gift: StarGift, date: Int32, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, pinnedToTop: Bool?, converted: Bool, upgraded: Bool, refunded: Bool, canUpgrade: Bool, upgradeStars: Int64?, transferStars: Int64?, resellStars: Int64?, canExportDate: Int32?, upgradeMessageId: Int32?, canTransferDate: Int32?, canResaleDate: Int32?)? {
|
var arguments: (peerId: EnginePeer.Id?, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, reference: StarGiftReference?, incoming: Bool, gift: StarGift, date: Int32, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, pinnedToTop: Bool?, converted: Bool, upgraded: Bool, refunded: Bool, canUpgrade: Bool, upgradeStars: Int64?, transferStars: Int64?, resellAmounts: [CurrencyAmount]?, canExportDate: Int32?, upgradeMessageId: Int32?, canTransferDate: Int32?, canResaleDate: Int32?)? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .message(message):
|
case let .message(message):
|
||||||
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
|
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
|
||||||
@ -3689,27 +3699,27 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
incoming = message.flags.contains(.Incoming)
|
incoming = message.flags.contains(.Incoming)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resellStars: Int64?
|
var resellAmounts: [CurrencyAmount]?
|
||||||
if case let .unique(uniqueGift) = gift {
|
if case let .unique(uniqueGift) = gift {
|
||||||
resellStars = uniqueGift.resellStars
|
resellAmounts = uniqueGift.resellAmounts
|
||||||
}
|
}
|
||||||
return (message.id.peerId, senderId ?? message.author?.id, message.author?.compactDisplayTitle, message.id, reference, incoming, gift, message.timestamp, nil, nil, nil, false, savedToProfile, nil, false, false, false, false, nil, transferStars, resellStars, canExportDate, nil, canTransferDate, canResaleDate)
|
return (message.id.peerId, senderId ?? message.author?.id, message.author?.compactDisplayTitle, message.id, reference, incoming, gift, message.timestamp, nil, nil, nil, false, savedToProfile, nil, false, false, false, false, nil, transferStars, resellAmounts, canExportDate, nil, canTransferDate, canResaleDate)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .uniqueGift(gift, _), let .wearPreview(gift):
|
case let .uniqueGift(gift, _), let .wearPreview(gift):
|
||||||
return (nil, nil, nil, nil, nil, false, .unique(gift), 0, nil, nil, nil, false, false, nil, false, false, false, false, nil, nil, gift.resellStars, nil, nil, nil, nil)
|
return (nil, nil, nil, nil, nil, false, .unique(gift), 0, nil, nil, nil, false, false, nil, false, false, false, false, nil, nil, gift.resellAmounts, nil, nil, nil, nil)
|
||||||
case let .profileGift(peerId, gift):
|
case let .profileGift(peerId, gift):
|
||||||
var messageId: EngineMessage.Id?
|
var messageId: EngineMessage.Id?
|
||||||
if case let .message(messageIdValue) = gift.reference {
|
if case let .message(messageIdValue) = gift.reference {
|
||||||
messageId = messageIdValue
|
messageId = messageIdValue
|
||||||
}
|
}
|
||||||
var resellStars: Int64?
|
var resellAmounts: [CurrencyAmount]?
|
||||||
if case let .unique(uniqueGift) = gift.gift {
|
if case let .unique(uniqueGift) = gift.gift {
|
||||||
resellStars = uniqueGift.resellStars
|
resellAmounts = uniqueGift.resellAmounts
|
||||||
}
|
}
|
||||||
return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, messageId, gift.reference, false, gift.gift, gift.date, gift.convertStars, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, gift.pinnedToTop, false, false, false, gift.canUpgrade, gift.upgradeStars, gift.transferStars, resellStars, gift.canExportDate, nil, gift.canTransferDate, gift.canResaleDate)
|
return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, messageId, gift.reference, false, gift.gift, gift.date, gift.convertStars, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, gift.pinnedToTop, false, false, false, gift.canUpgrade, gift.upgradeStars, gift.transferStars, resellAmounts, gift.canExportDate, nil, gift.canTransferDate, gift.canResaleDate)
|
||||||
case .soldOutGift:
|
case .soldOutGift:
|
||||||
return nil
|
return nil
|
||||||
case .upgradePreview:
|
case .upgradePreview:
|
||||||
@ -3733,8 +3743,8 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
fileprivate let convertToStars: (() -> Void)?
|
fileprivate let convertToStars: (() -> Void)?
|
||||||
fileprivate let transferGift: ((Bool, EnginePeer.Id) -> Signal<Never, TransferStarGiftError>)?
|
fileprivate let transferGift: ((Bool, EnginePeer.Id) -> Signal<Never, TransferStarGiftError>)?
|
||||||
fileprivate let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)?
|
fileprivate let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)?
|
||||||
fileprivate let buyGift: ((String, EnginePeer.Id, Int64?) -> Signal<Never, BuyStarGiftError>)?
|
fileprivate let buyGift: ((String, EnginePeer.Id, CurrencyAmount?) -> Signal<Never, BuyStarGiftError>)?
|
||||||
fileprivate let updateResellStars: ((Int64?) -> Signal<Never, UpdateStarGiftPriceError>)?
|
fileprivate let updateResellStars: ((CurrencyAmount?) -> Signal<Never, UpdateStarGiftPriceError>)?
|
||||||
fileprivate let togglePinnedToTop: ((Bool) -> Bool)?
|
fileprivate let togglePinnedToTop: ((Bool) -> Bool)?
|
||||||
fileprivate let shareStory: ((StarGift.UniqueGift) -> Void)?
|
fileprivate let shareStory: ((StarGift.UniqueGift) -> Void)?
|
||||||
|
|
||||||
@ -3750,8 +3760,8 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
convertToStars: (() -> Void)? = nil,
|
convertToStars: (() -> Void)? = nil,
|
||||||
transferGift: ((Bool, EnginePeer.Id) -> Signal<Never, TransferStarGiftError>)? = nil,
|
transferGift: ((Bool, EnginePeer.Id) -> Signal<Never, TransferStarGiftError>)? = nil,
|
||||||
upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)? = nil,
|
upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)? = nil,
|
||||||
buyGift: ((String, EnginePeer.Id, Int64?) -> Signal<Never, BuyStarGiftError>)? = nil,
|
buyGift: ((String, EnginePeer.Id, CurrencyAmount?) -> Signal<Never, BuyStarGiftError>)? = nil,
|
||||||
updateResellStars: ((Int64?) -> Signal<Never, UpdateStarGiftPriceError>)? = nil,
|
updateResellStars: ((CurrencyAmount?) -> Signal<Never, UpdateStarGiftPriceError>)? = nil,
|
||||||
togglePinnedToTop: ((Bool) -> Bool)? = nil,
|
togglePinnedToTop: ((Bool) -> Bool)? = nil,
|
||||||
shareStory: ((StarGift.UniqueGift) -> Void)? = nil
|
shareStory: ((StarGift.UniqueGift) -> Void)? = nil
|
||||||
) {
|
) {
|
||||||
@ -3810,7 +3820,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
|
|
||||||
self.view.disablesInteractiveModalDismiss = true
|
self.view.disablesInteractiveModalDismiss = true
|
||||||
|
|
||||||
if let arguments = self.subject.arguments, let _ = self.subject.arguments?.resellStars {
|
if let arguments = self.subject.arguments, let _ = self.subject.arguments?.resellAmounts {
|
||||||
if case let .unique(uniqueGift) = arguments.gift, case .peerId(self.context.account.peerId) = uniqueGift.owner {
|
if case let .unique(uniqueGift) = arguments.gift, case .peerId(self.context.account.peerId) = uniqueGift.owner {
|
||||||
} else {
|
} else {
|
||||||
self.showBalance = true
|
self.showBalance = true
|
||||||
|
|||||||
@ -3729,7 +3729,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
|
|||||||
}
|
}
|
||||||
} else if case let .gift(gift) = subject {
|
} else if case let .gift(gift) = subject {
|
||||||
isGift = true
|
isGift = true
|
||||||
let media: [Media] = [TelegramMediaAction(action: .starGiftUnique(gift: .unique(gift), isUpgrade: false, isTransferred: false, savedToProfile: false, canExportDate: nil, transferStars: nil, isRefunded: false, peerId: nil, senderId: nil, savedId: nil, resaleStars: nil, canTransferDate: nil, canResaleDate: nil))]
|
let media: [Media] = [TelegramMediaAction(action: .starGiftUnique(gift: .unique(gift), isUpgrade: false, isTransferred: false, savedToProfile: false, canExportDate: nil, transferStars: nil, isRefunded: false, peerId: nil, senderId: nil, savedId: nil, resaleAmount: nil, canTransferDate: nil, canResaleDate: nil))]
|
||||||
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: self.context.account.peerId, namespace: Namespaces.Message.Cloud, id: -1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: media, peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: self.context.account.peerId, namespace: Namespaces.Message.Cloud, id: -1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: media, peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||||
messages = .single([message])
|
messages = .single([message])
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1257,7 +1257,8 @@ final class AffiliateProgramSetupScreenComponent: Component {
|
|||||||
simple: true,
|
simple: true,
|
||||||
source: .generic,
|
source: .generic,
|
||||||
skipTermsOfService: true,
|
skipTermsOfService: true,
|
||||||
payload: nil
|
payload: nil,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
)
|
)
|
||||||
} else if let navigationController = controller.navigationController as? NavigationController {
|
} else if let navigationController = controller.navigationController as? NavigationController {
|
||||||
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(item.peer), subject: nil, keepStack: .always, animated: true, pushController: { [weak navigationController] chatController, animated, completion in
|
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(item.peer), subject: nil, keepStack: .always, animated: true, pushController: { [weak navigationController] chatController, animated, completion in
|
||||||
|
|||||||
@ -1082,7 +1082,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
if case .user = kind {
|
if case .user = kind {
|
||||||
if isMyProfile || userPeerId != context.account.peerId {
|
if isMyProfile || userPeerId != context.account.peerId {
|
||||||
profileGiftsContext = existingProfileGiftsContext ?? ProfileGiftsContext(account: context.account, peerId: userPeerId)
|
profileGiftsContext = existingProfileGiftsContext ?? ProfileGiftsContext(account: context.account, peerId: userPeerId)
|
||||||
profileGiftsCollectionsContext = existingProfileGiftsCollectionsContext ?? ProfileGiftsCollectionsContext(account: context.account, peerId: userPeerId)
|
profileGiftsCollectionsContext = existingProfileGiftsCollectionsContext ?? ProfileGiftsCollectionsContext(account: context.account, peerId: userPeerId, allGiftsContext: profileGiftsContext)
|
||||||
} else {
|
} else {
|
||||||
profileGiftsContext = nil
|
profileGiftsContext = nil
|
||||||
profileGiftsCollectionsContext = nil
|
profileGiftsCollectionsContext = nil
|
||||||
@ -1629,7 +1629,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
}
|
}
|
||||||
|
|
||||||
let profileGiftsContext = ProfileGiftsContext(account: context.account, peerId: peerId)
|
let profileGiftsContext = ProfileGiftsContext(account: context.account, peerId: peerId)
|
||||||
let profileGiftsCollectionsContext = ProfileGiftsCollectionsContext(account: context.account, peerId: peerId)
|
let profileGiftsCollectionsContext = ProfileGiftsCollectionsContext(account: context.account, peerId: peerId, allGiftsContext: profileGiftsContext)
|
||||||
|
|
||||||
let personalChannel = peerInfoPersonalOrLinkedChannel(context: context, peerId: peerId, isSettings: false)
|
let personalChannel = peerInfoPersonalOrLinkedChannel(context: context, peerId: peerId, isSettings: false)
|
||||||
|
|
||||||
|
|||||||
@ -1451,7 +1451,8 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||||||
simple: true,
|
simple: true,
|
||||||
source: .generic,
|
source: .generic,
|
||||||
skipTermsOfService: true,
|
skipTermsOfService: true,
|
||||||
payload: nil
|
payload: nil,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -11363,7 +11364,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
let canReorderEquals = lhs.2 == rhs.2
|
let canReorderEquals = lhs.2 == rhs.2
|
||||||
return filterEquals && sortingEquals && canReorderEquals
|
return filterEquals && sortingEquals && canReorderEquals
|
||||||
})
|
})
|
||||||
|> map { [weak self, weak pane, weak giftsContext] filter, sorting, canReorder -> ContextController.Items in
|
|> map { [weak pane, weak giftsContext] filter, sorting, canReorder -> ContextController.Items in
|
||||||
var items: [ContextMenuItem] = []
|
var items: [ContextMenuItem] = []
|
||||||
|
|
||||||
if hasVisibility {
|
if hasVisibility {
|
||||||
@ -11388,13 +11389,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
|
// items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
|
// return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
|
||||||
}, action: { [weak self] _, f in
|
// }, action: { [weak self] _, f in
|
||||||
f(.default)
|
// f(.default)
|
||||||
//TODO:release
|
// self?.openShareLink(url: "https://t.me/")
|
||||||
self?.openShareLink(url: "https://t.me/")
|
// })))
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if canReorder {
|
if canReorder {
|
||||||
@ -11426,15 +11426,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
items.append(.separator)
|
items.append(.separator)
|
||||||
}
|
}
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: sorting == .date ? strings.PeerInfo_Gifts_SortByValue : strings.PeerInfo_Gifts_SortByDate, icon: { theme in
|
if let pane, case .all = pane.currentCollection {
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: sorting == .date ? "Peer Info/SortValue" : "Peer Info/SortDate"), color: theme.contextMenu.primaryColor)
|
items.append(.action(ContextMenuActionItem(text: sorting == .date ? strings.PeerInfo_Gifts_SortByValue : strings.PeerInfo_Gifts_SortByDate, icon: { theme in
|
||||||
}, action: { [weak giftsContext] _, f in
|
return generateTintedImage(image: UIImage(bundleImageName: sorting == .date ? "Peer Info/SortValue" : "Peer Info/SortDate"), color: theme.contextMenu.primaryColor)
|
||||||
f(.default)
|
}, action: { [weak giftsContext] _, f in
|
||||||
|
f(.default)
|
||||||
giftsContext?.updateSorting(sorting == .date ? .value : .date)
|
|
||||||
})))
|
giftsContext?.updateSorting(sorting == .date ? .value : .date)
|
||||||
|
})))
|
||||||
|
|
||||||
items.append(.separator)
|
items.append(.separator)
|
||||||
|
}
|
||||||
|
|
||||||
let toggleFilter: (ProfileGiftsContext.Filters) -> Void = { [weak giftsContext] value in
|
let toggleFilter: (ProfileGiftsContext.Filters) -> Void = { [weak giftsContext] value in
|
||||||
var updatedFilter = filter
|
var updatedFilter = filter
|
||||||
|
|||||||
@ -23,17 +23,20 @@ final class AddGiftsScreenComponent: Component {
|
|||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let peerId: EnginePeer.Id
|
let peerId: EnginePeer.Id
|
||||||
let collectionId: Int32
|
let collectionId: Int32
|
||||||
|
let remainingCount: Int32
|
||||||
let profileGifts: ProfileGiftsContext
|
let profileGifts: ProfileGiftsContext
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
peerId: EnginePeer.Id,
|
peerId: EnginePeer.Id,
|
||||||
collectionId: Int32,
|
collectionId: Int32,
|
||||||
|
remainingCount: Int32,
|
||||||
profileGifts: ProfileGiftsContext
|
profileGifts: ProfileGiftsContext
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.collectionId = collectionId
|
self.collectionId = collectionId
|
||||||
|
self.remainingCount = remainingCount
|
||||||
self.profileGifts = profileGifts
|
self.profileGifts = profileGifts
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,10 +101,10 @@ final class AddGiftsScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
self.updateScrolling(transition: .immediate)
|
self.updateScrolling(interactive: true, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateScrolling(transition: ComponentTransition) {
|
private func updateScrolling(interactive: Bool = false, transition: ComponentTransition) {
|
||||||
guard let environment = self.environment, let giftsListView = self.giftsListView else {
|
guard let environment = self.environment, let giftsListView = self.giftsListView else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -111,11 +114,17 @@ final class AddGiftsScreenComponent: Component {
|
|||||||
var contentSize = CGSize(width: self.scrollView.bounds.width, height: contentHeight)
|
var contentSize = CGSize(width: self.scrollView.bounds.width, height: contentHeight)
|
||||||
contentSize.height += environment.safeInsets.bottom
|
contentSize.height += environment.safeInsets.bottom
|
||||||
contentSize.height = max(contentSize.height, self.scrollView.bounds.size.height)
|
contentSize.height = max(contentSize.height, self.scrollView.bounds.size.height)
|
||||||
|
contentSize.height += 50.0 + 24.0
|
||||||
transition.setFrame(view: giftsListView, frame: CGRect(origin: CGPoint(), size: contentSize))
|
transition.setFrame(view: giftsListView, frame: CGRect(origin: CGPoint(), size: contentSize))
|
||||||
|
|
||||||
if self.scrollView.contentSize != contentSize {
|
if self.scrollView.contentSize != contentSize {
|
||||||
self.scrollView.contentSize = contentSize
|
self.scrollView.contentSize = contentSize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let bottomContentOffset = max(0.0, self.scrollView.contentSize.height - self.scrollView.contentOffset.y - self.scrollView.frame.height)
|
||||||
|
if interactive, bottomContentOffset < 200.0 {
|
||||||
|
self.giftsListView?.loadMore()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(component: AddGiftsScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
|
func update(component: AddGiftsScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
|
||||||
@ -128,7 +137,13 @@ final class AddGiftsScreenComponent: Component {
|
|||||||
if let current = self.giftsListView {
|
if let current = self.giftsListView {
|
||||||
giftsListView = current
|
giftsListView = current
|
||||||
} else {
|
} else {
|
||||||
giftsListView = GiftsListView(context: component.context, peerId: component.peerId, profileGifts: component.profileGifts, giftsCollections: nil, canSelect: true, ignoreCollection: component.collectionId)
|
giftsListView = GiftsListView(context: component.context, peerId: component.peerId, profileGifts: component.profileGifts, giftsCollections: nil, canSelect: true, ignoreCollection: component.collectionId, remainingSelectionCount: component.remainingCount)
|
||||||
|
giftsListView.onContentUpdated = { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.state?.updated(transition: .immediate)
|
||||||
|
}
|
||||||
giftsListView.selectionUpdated = { [weak self] in
|
giftsListView.selectionUpdated = { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -248,6 +263,7 @@ public final class AddGiftsScreen: ViewControllerComponentContainer {
|
|||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
peerId: EnginePeer.Id,
|
peerId: EnginePeer.Id,
|
||||||
collectionId: Int32,
|
collectionId: Int32,
|
||||||
|
remainingCount: Int32,
|
||||||
completion: @escaping ([ProfileGiftsContext.State.StarGift]) -> Void
|
completion: @escaping ([ProfileGiftsContext.State.StarGift]) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -264,10 +280,10 @@ public final class AddGiftsScreen: ViewControllerComponentContainer {
|
|||||||
context: context,
|
context: context,
|
||||||
peerId: peerId,
|
peerId: peerId,
|
||||||
collectionId: collectionId,
|
collectionId: collectionId,
|
||||||
|
remainingCount: remainingCount,
|
||||||
profileGifts: self.profileGifts
|
profileGifts: self.profileGifts
|
||||||
), navigationBarAppearance: .default, theme: .default, updatedPresentationData: nil)
|
), navigationBarAppearance: .default, theme: .default, updatedPresentationData: nil)
|
||||||
|
|
||||||
|
|
||||||
self.title = presentationData.strings.AddGifts_Title
|
self.title = presentationData.strings.AddGifts_Title
|
||||||
self.navigationPresentation = .modal
|
self.navigationPresentation = .modal
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,7 @@ final class GiftsListView: UIView {
|
|||||||
|
|
||||||
private let canSelect: Bool
|
private let canSelect: Bool
|
||||||
private let ignoreCollection: Int32?
|
private let ignoreCollection: Int32?
|
||||||
|
private let remainingSelectionCount: Int32
|
||||||
|
|
||||||
private var dataDisposable: Disposable?
|
private var dataDisposable: Disposable?
|
||||||
|
|
||||||
@ -124,13 +125,14 @@ final class GiftsListView: UIView {
|
|||||||
var contextAction: ((ProfileGiftsContext.State.StarGift, UIView, ContextGesture) -> Void)?
|
var contextAction: ((ProfileGiftsContext.State.StarGift, UIView, ContextGesture) -> Void)?
|
||||||
var addToCollection: (() -> Void)?
|
var addToCollection: (() -> Void)?
|
||||||
|
|
||||||
init(context: AccountContext, peerId: PeerId, profileGifts: ProfileGiftsContext, giftsCollections: ProfileGiftsCollectionsContext?, canSelect: Bool, ignoreCollection: Int32? = nil) {
|
init(context: AccountContext, peerId: PeerId, profileGifts: ProfileGiftsContext, giftsCollections: ProfileGiftsCollectionsContext?, canSelect: Bool, ignoreCollection: Int32? = nil, remainingSelectionCount: Int32 = 0) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.profileGifts = profileGifts
|
self.profileGifts = profileGifts
|
||||||
self.giftsCollections = giftsCollections
|
self.giftsCollections = giftsCollections
|
||||||
self.canSelect = canSelect
|
self.canSelect = canSelect
|
||||||
self.ignoreCollection = ignoreCollection
|
self.ignoreCollection = ignoreCollection
|
||||||
|
self.remainingSelectionCount = remainingSelectionCount
|
||||||
|
|
||||||
if let value = context.currentAppConfiguration.with({ $0 }).data?["stargifts_pinned_to_top_limit"] as? Double {
|
if let value = context.currentAppConfiguration.with({ $0 }).data?["stargifts_pinned_to_top_limit"] as? Double {
|
||||||
self.maxPinnedCount = Int(value)
|
self.maxPinnedCount = Int(value)
|
||||||
@ -406,6 +408,13 @@ final class GiftsListView: UIView {
|
|||||||
}
|
}
|
||||||
return self.updateScrolling(interactive: interactive, topInset: topInset, visibleBounds: visibleBounds, transition: transition)
|
return self.updateScrolling(interactive: interactive, topInset: topInset, visibleBounds: visibleBounds, transition: transition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||||||
|
if let topInset = self.topInset, point.y < topInset {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return super.point(inside: point, with: event)
|
||||||
|
}
|
||||||
|
|
||||||
func updateScrolling(interactive: Bool = false, topInset: CGFloat, visibleBounds: CGRect, transition: ComponentTransition) -> CGFloat {
|
func updateScrolling(interactive: Bool = false, topInset: CGFloat, visibleBounds: CGRect, transition: ComponentTransition) -> CGFloat {
|
||||||
self.topInset = topInset
|
self.topInset = topInset
|
||||||
@ -474,7 +483,7 @@ final class GiftsListView: UIView {
|
|||||||
|
|
||||||
let peer: GiftItemComponent.Peer?
|
let peer: GiftItemComponent.Peer?
|
||||||
let subject: GiftItemComponent.Subject
|
let subject: GiftItemComponent.Subject
|
||||||
var resellPrice: Int64?
|
var resellAmount: CurrencyAmount?
|
||||||
|
|
||||||
switch product.gift {
|
switch product.gift {
|
||||||
case let .generic(gift):
|
case let .generic(gift):
|
||||||
@ -489,9 +498,9 @@ final class GiftsListView: UIView {
|
|||||||
case let .unique(gift):
|
case let .unique(gift):
|
||||||
subject = .uniqueGift(gift: gift, price: nil)
|
subject = .uniqueGift(gift: gift, price: nil)
|
||||||
peer = nil
|
peer = nil
|
||||||
resellPrice = gift.resellStars
|
resellAmount = gift.resellAmounts?.first
|
||||||
|
|
||||||
if let _ = resellPrice {
|
if let _ = resellAmount {
|
||||||
ribbonText = params.presentationData.strings.PeerInfo_Gifts_Sale
|
ribbonText = params.presentationData.strings.PeerInfo_Gifts_Sale
|
||||||
ribbonFont = .larger
|
ribbonFont = .larger
|
||||||
ribbonColor = .green
|
ribbonColor = .green
|
||||||
@ -524,6 +533,7 @@ final class GiftsListView: UIView {
|
|||||||
itemAlpha = 0.3
|
itemAlpha = 0.3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO:release
|
||||||
let _ = visibleItem.update(
|
let _ = visibleItem.update(
|
||||||
transition: itemTransition,
|
transition: itemTransition,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
@ -534,7 +544,7 @@ final class GiftsListView: UIView {
|
|||||||
peer: peer,
|
peer: peer,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
ribbon: ribbonText.flatMap { GiftItemComponent.Ribbon(text: $0, font: ribbonFont, color: ribbonColor, outline: ribbonOutline) },
|
ribbon: ribbonText.flatMap { GiftItemComponent.Ribbon(text: $0, font: ribbonFont, color: ribbonColor, outline: ribbonOutline) },
|
||||||
resellPrice: resellPrice,
|
resellPrice: resellAmount?.amount.value,
|
||||||
isHidden: !product.savedToProfile,
|
isHidden: !product.savedToProfile,
|
||||||
isSelected: self.selectedItemIds.contains(itemReferenceId),
|
isSelected: self.selectedItemIds.contains(itemReferenceId),
|
||||||
isPinned: !self.canSelect && product.pinnedToTop,
|
isPinned: !self.canSelect && product.pinnedToTop,
|
||||||
@ -548,8 +558,10 @@ final class GiftsListView: UIView {
|
|||||||
if self.selectedItemIds.contains(itemReferenceId) {
|
if self.selectedItemIds.contains(itemReferenceId) {
|
||||||
self.selectedItemIds.remove(itemReferenceId)
|
self.selectedItemIds.remove(itemReferenceId)
|
||||||
} else {
|
} else {
|
||||||
self.selectedItemIds.insert(itemReferenceId)
|
if self.selectedItemIds.count < self.remainingSelectionCount {
|
||||||
self.selectedItemsMap[itemReferenceId] = product
|
self.selectedItemIds.insert(itemReferenceId)
|
||||||
|
self.selectedItemsMap[itemReferenceId] = product
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.selectionUpdated()
|
self.selectionUpdated()
|
||||||
self.updateScrolling(transition: .easeInOut(duration: 0.25))
|
self.updateScrolling(transition: .easeInOut(duration: 0.25))
|
||||||
|
|||||||
@ -151,6 +151,15 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
self.giftsListView.onContentUpdated = { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let params = self.currentParams {
|
||||||
|
self.update(size: params.size, topInset: params.topInset, sideInset: params.sideInset, bottomInset: params.bottomInset, deviceMetrics: params.deviceMetrics, visibleHeight: params.visibleHeight, isScrollingLockedAtTop: params.isScrollingLockedAtTop, expandProgress: params.expandProgress, navigationHeight: params.navigationHeight, presentationData: params.presentationData, synchronous: true, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.addSubnode(self.backgroundNode)
|
self.addSubnode(self.backgroundNode)
|
||||||
self.addSubnode(self.scrollNode)
|
self.addSubnode(self.scrollNode)
|
||||||
|
|
||||||
@ -184,7 +193,11 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
self.scrollNode.view.contentInsetAdjustmentBehavior = .never
|
self.scrollNode.view.contentInsetAdjustmentBehavior = .never
|
||||||
self.scrollNode.view.delegate = self
|
self.scrollNode.view.delegate = self
|
||||||
|
|
||||||
self.scrollNode.view.insertSubview(self.giftsListView, at: 0)
|
if let tabSelectorView = self.tabSelector.view {
|
||||||
|
self.scrollNode.view.insertSubview(self.giftsListView, aboveSubview: tabSelectorView)
|
||||||
|
} else {
|
||||||
|
self.scrollNode.view.insertSubview(self.giftsListView, at: 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func item(at point: CGPoint) -> (AnyHashable, ComponentView<Empty>)? {
|
private func item(at point: CGPoint) -> (AnyHashable, ComponentView<Empty>)? {
|
||||||
@ -201,7 +214,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let promptController = promptController(sharedContext: self.context.sharedContext, updatedPresentationData: nil, text: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Title, titleFont: .bold, subtitle: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Text, value: "", placeholder: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Placeholder, characterLimit: 20, displayCharacterLimit: true, apply: { [weak self] value in
|
let promptController = promptController(sharedContext: self.context.sharedContext, updatedPresentationData: nil, text: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Title, titleFont: .bold, subtitle: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Text, value: "", placeholder: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Placeholder, characterLimit: 12, displayCharacterLimit: true, apply: { [weak self] value in
|
||||||
guard let self, let value else {
|
guard let self, let value else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -211,6 +224,10 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
}
|
}
|
||||||
if let collection {
|
if let collection {
|
||||||
self.setCurrentCollection(collection: .collection(collection.id))
|
self.setCurrentCollection(collection: .collection(collection.id))
|
||||||
|
|
||||||
|
if let tabSelectorView = self.tabSelector.view as? TabSelectorComponent.View {
|
||||||
|
tabSelectorView.scrollToEnd()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -230,6 +247,10 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
|
|
||||||
self?.setCurrentCollection(collection: .all)
|
self?.setCurrentCollection(collection: .all)
|
||||||
let _ = self?.profileGiftsCollections.deleteCollection(id: id).start()
|
let _ = self?.profileGiftsCollections.deleteCollection(id: id).start()
|
||||||
|
|
||||||
|
if let tabSelectorView = self?.tabSelector.view as? TabSelectorComponent.View {
|
||||||
|
tabSelectorView.scrollToStart()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
]),
|
]),
|
||||||
ActionSheetItemGroup(items: [
|
ActionSheetItemGroup(items: [
|
||||||
@ -242,7 +263,15 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func addGiftsToCollection(id: Int32) {
|
public func addGiftsToCollection(id: Int32) {
|
||||||
let screen = AddGiftsScreen(context: self.context, peerId: self.peerId, collectionId: id, completion: { [weak self] gifts in
|
var collectionGiftsMaxCount: Int32 = 1000
|
||||||
|
if let value = self.context.currentAppConfiguration.with({ $0 }).data?["stargifts_collection_gifts_limit"] as? Double {
|
||||||
|
collectionGiftsMaxCount = Int32(value)
|
||||||
|
}
|
||||||
|
var remainingCount = collectionGiftsMaxCount
|
||||||
|
if let currentCount = self.giftsListView.profileGifts.currentState?.count {
|
||||||
|
remainingCount = max(0, collectionGiftsMaxCount - currentCount)
|
||||||
|
}
|
||||||
|
let screen = AddGiftsScreen(context: self.context, peerId: self.peerId, collectionId: id, remainingCount: remainingCount, completion: { [weak self] gifts in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -256,7 +285,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let promptController = promptController(sharedContext: self.context.sharedContext, updatedPresentationData: nil, text: params.presentationData.strings.PeerInfo_Gifts_RenameCollection_Title, titleFont: .bold, value: collection.title, placeholder: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Placeholder, characterLimit: 20, displayCharacterLimit: true, apply: { [weak self] value in
|
let promptController = promptController(sharedContext: self.context.sharedContext, updatedPresentationData: nil, text: params.presentationData.strings.PeerInfo_Gifts_RenameCollection_Title, titleFont: .bold, value: collection.title, placeholder: params.presentationData.strings.PeerInfo_Gifts_CreateCollection_Placeholder, characterLimit: 12, displayCharacterLimit: true, apply: { [weak self] value in
|
||||||
guard let self, let value else {
|
guard let self, let value else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -460,20 +489,21 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
}
|
}
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
self.renameCollection(id: id)
|
Queue.mainQueue().after(0.15) {
|
||||||
|
self.renameCollection(id: id)
|
||||||
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
|
// items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_ShareCollection, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.actionSheet.primaryTextColor)
|
// return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, action: { [weak self] _, f in
|
// }, action: { [weak self] _, f in
|
||||||
guard let self else {
|
// guard let self else {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
f(.default)
|
// f(.default)
|
||||||
|
//
|
||||||
//TODO:release
|
// let _ = self
|
||||||
let _ = self
|
// })))
|
||||||
})))
|
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_Reorder, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_Reorder, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/ReorderItems"), color: theme.actionSheet.primaryTextColor)
|
||||||
@ -494,7 +524,9 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
}
|
}
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
self.deleteCollection(id: id)
|
Queue.mainQueue().after(0.15) {
|
||||||
|
self.deleteCollection(id: id)
|
||||||
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
let contextController = ContextController(
|
let contextController = ContextController(
|
||||||
@ -506,8 +538,6 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
)
|
)
|
||||||
self.parentController?.presentInGlobalOverlay(contextController)
|
self.parentController?.presentInGlobalOverlay(contextController)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func updateScrolling(interactive: Bool = false, transition: ComponentTransition) {
|
func updateScrolling(interactive: Bool = false, transition: ComponentTransition) {
|
||||||
if let params = self.currentParams {
|
if let params = self.currentParams {
|
||||||
@ -515,13 +545,19 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
|
|
||||||
var topInset: CGFloat = 60.0
|
var topInset: CGFloat = 60.0
|
||||||
|
|
||||||
if let collections = self.collections, !collections.isEmpty {
|
var canEditCollections = false
|
||||||
|
if self.peerId == self.context.account.peerId || self.canManage {
|
||||||
|
canEditCollections = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasNonEmptyCollections = self.collections?.contains(where: { $0.count > 0 }) ?? false
|
||||||
|
if let collections = self.collections, !collections.isEmpty && (hasNonEmptyCollections || canEditCollections) {
|
||||||
var tabSelectorItems: [TabSelectorComponent.Item] = []
|
var tabSelectorItems: [TabSelectorComponent.Item] = []
|
||||||
tabSelectorItems.append(TabSelectorComponent.Item(
|
tabSelectorItems.append(TabSelectorComponent.Item(
|
||||||
id: AnyHashable(GiftCollection.all.rawValue),
|
id: AnyHashable(GiftCollection.all.rawValue),
|
||||||
title: "All Gifts"
|
title: params.presentationData.strings.PeerInfo_Gifts_Collections_All
|
||||||
))
|
))
|
||||||
|
|
||||||
var effectiveCollections: [StarGiftCollection] = collections
|
var effectiveCollections: [StarGiftCollection] = collections
|
||||||
if let reorderedCollectionIds = self.reorderedCollectionIds {
|
if let reorderedCollectionIds = self.reorderedCollectionIds {
|
||||||
var collectionMap: [Int32: StarGiftCollection] = [:]
|
var collectionMap: [Int32: StarGiftCollection] = [:]
|
||||||
@ -538,6 +574,9 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
}
|
}
|
||||||
|
|
||||||
for collection in effectiveCollections {
|
for collection in effectiveCollections {
|
||||||
|
if !canEditCollections && collection.count == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
tabSelectorItems.append(TabSelectorComponent.Item(
|
tabSelectorItems.append(TabSelectorComponent.Item(
|
||||||
id: AnyHashable(GiftCollection.collection(collection.id).rawValue),
|
id: AnyHashable(GiftCollection.collection(collection.id).rawValue),
|
||||||
content: .component(AnyComponent(
|
content: .component(AnyComponent(
|
||||||
@ -549,27 +588,29 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
)
|
)
|
||||||
)),
|
)),
|
||||||
isReorderable: collections.count > 1,
|
isReorderable: collections.count > 1,
|
||||||
contextAction: { [weak self] sourceNode, gesture in
|
contextAction: canEditCollections ? { [weak self] sourceNode, gesture in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.openCollectionContextMenu(id: collection.id, sourceNode: sourceNode, gesture: gesture)
|
self.openCollectionContextMenu(id: collection.id, sourceNode: sourceNode, gesture: gesture)
|
||||||
}
|
} : nil
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
if canEditCollections {
|
||||||
|
tabSelectorItems.append(TabSelectorComponent.Item(
|
||||||
|
id: AnyHashable(GiftCollection.create.rawValue),
|
||||||
|
content: .component(AnyComponent(
|
||||||
|
CollectionTabItemComponent(
|
||||||
|
context: self.context,
|
||||||
|
icon: .add,
|
||||||
|
title: params.presentationData.strings.PeerInfo_Gifts_Collections_Add,
|
||||||
|
theme: params.presentationData.theme
|
||||||
|
)
|
||||||
|
)),
|
||||||
|
isReorderable: false
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
tabSelectorItems.append(TabSelectorComponent.Item(
|
|
||||||
id: AnyHashable(GiftCollection.create.rawValue),
|
|
||||||
content: .component(AnyComponent(
|
|
||||||
CollectionTabItemComponent(
|
|
||||||
context: self.context,
|
|
||||||
icon: .add,
|
|
||||||
title: "Add Collection",
|
|
||||||
theme: params.presentationData.theme
|
|
||||||
)
|
|
||||||
)),
|
|
||||||
isReorderable: false
|
|
||||||
))
|
|
||||||
|
|
||||||
let tabSelectorSize = self.tabSelector.update(
|
let tabSelectorSize = self.tabSelector.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
@ -621,7 +662,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
if let tabSelectorView = self.tabSelector.view {
|
if let tabSelectorView = self.tabSelector.view {
|
||||||
if tabSelectorView.superview == nil {
|
if tabSelectorView.superview == nil {
|
||||||
tabSelectorView.alpha = 1.0
|
tabSelectorView.alpha = 1.0
|
||||||
self.scrollNode.view.addSubview(tabSelectorView)
|
self.scrollNode.view.insertSubview(tabSelectorView, at: 0)
|
||||||
|
|
||||||
if !transition.animation.isImmediate {
|
if !transition.animation.isImmediate {
|
||||||
tabSelectorView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
tabSelectorView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||||
@ -938,10 +979,53 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
}, iconPosition: collection.icon == nil ? .left : .right, action: { [weak self] _, f in
|
}, iconPosition: collection.icon == nil ? .left : .right, action: { [weak self] _, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if isAdded, let giftReference = gift.reference {
|
if isAdded, let giftReference = gift.reference {
|
||||||
let _ = self?.profileGiftsCollections.removeGifts(id: collection.id, gifts: [giftReference]).start()
|
let _ = self.profileGiftsCollections.removeGifts(id: collection.id, gifts: [giftReference]).start()
|
||||||
} else {
|
} else {
|
||||||
let _ = self?.profileGiftsCollections.addGifts(id: collection.id, gifts: [gift]).start()
|
let _ = self.profileGiftsCollections.addGifts(id: collection.id, gifts: [gift]).start()
|
||||||
|
}
|
||||||
|
|
||||||
|
var giftFile: TelegramMediaFile?
|
||||||
|
var giftTitle: String?
|
||||||
|
switch gift.gift {
|
||||||
|
case let .generic(gift):
|
||||||
|
giftFile = gift.file
|
||||||
|
case let .unique(uniqueGift):
|
||||||
|
giftTitle = uniqueGift.title + " #\(presentationStringsFormattedNumber(uniqueGift.number, currentParams.presentationData.dateTimeFormat.groupingSeparator))"
|
||||||
|
for attribute in uniqueGift.attributes {
|
||||||
|
if case let .model(_, file, _) = attribute {
|
||||||
|
giftFile = file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let giftFile {
|
||||||
|
let text: String
|
||||||
|
if let giftTitle {
|
||||||
|
if isAdded {
|
||||||
|
text = currentParams.presentationData.strings.PeerInfo_Gifts_RemovedFromCollectionUnique(giftTitle, collection.title).string
|
||||||
|
} else {
|
||||||
|
text = currentParams.presentationData.strings.PeerInfo_Gifts_AddedToCollectionUnique(giftTitle, collection.title).string
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if isAdded {
|
||||||
|
text = currentParams.presentationData.strings.PeerInfo_Gifts_RemovedFromCollection(collection.title).string
|
||||||
|
} else {
|
||||||
|
text = currentParams.presentationData.strings.PeerInfo_Gifts_AddedToCollection(collection.title).string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let undoController = UndoOverlayController(
|
||||||
|
presentationData: currentParams.presentationData,
|
||||||
|
content: .sticker(context: self.context, file: giftFile, loop: false, title: nil, text: text, undoText: nil, customAction: nil),
|
||||||
|
elevatedLayout: true,
|
||||||
|
action: { _ in return true }
|
||||||
|
)
|
||||||
|
self.parentController?.present(undoController, in: .current)
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
@ -1213,12 +1297,47 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if case let .collection(id) = self.currentCollection {
|
if canManage, case let .collection(id) = self.currentCollection {
|
||||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Context_RemoveFromCollection, textColor: .destructive, textLayout: .twoLinesMax, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/RemoveFromCollection"), color: theme.contextMenu.destructiveColor) }, action: { [weak self] c, f in
|
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Context_RemoveFromCollection, textColor: .destructive, textLayout: .twoLinesMax, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Peer Info/Gifts/RemoveFromCollection"), color: theme.contextMenu.destructiveColor) }, action: { [weak self] c, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if let reference = gift.reference {
|
if let reference = gift.reference {
|
||||||
let _ = self?.profileGiftsCollections.removeGifts(id: id, gifts: [reference]).start()
|
let _ = self.profileGiftsCollections.removeGifts(id: id, gifts: [reference]).start()
|
||||||
|
}
|
||||||
|
|
||||||
|
var giftFile: TelegramMediaFile?
|
||||||
|
var giftTitle: String?
|
||||||
|
switch gift.gift {
|
||||||
|
case let .generic(gift):
|
||||||
|
giftFile = gift.file
|
||||||
|
case let .unique(uniqueGift):
|
||||||
|
giftTitle = uniqueGift.title + " #\(presentationStringsFormattedNumber(uniqueGift.number, currentParams.presentationData.dateTimeFormat.groupingSeparator))"
|
||||||
|
for attribute in uniqueGift.attributes {
|
||||||
|
if case let .model(_, file, _) = attribute {
|
||||||
|
giftFile = file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let giftFile, let collection = self.collections?.first(where: { $0.id == id }) {
|
||||||
|
let text: String
|
||||||
|
if let giftTitle {
|
||||||
|
text = currentParams.presentationData.strings.PeerInfo_Gifts_RemovedFromCollectionUnique(giftTitle, collection.title).string
|
||||||
|
} else {
|
||||||
|
text = currentParams.presentationData.strings.PeerInfo_Gifts_RemovedFromCollection(collection.title).string
|
||||||
|
}
|
||||||
|
|
||||||
|
let undoController = UndoOverlayController(
|
||||||
|
presentationData: currentParams.presentationData,
|
||||||
|
content: .sticker(context: self.context, file: giftFile, loop: false, title: nil, text: text, undoText: nil, customAction: nil),
|
||||||
|
elevatedLayout: true,
|
||||||
|
action: { _ in return true }
|
||||||
|
)
|
||||||
|
self.parentController?.present(undoController, in: .current)
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
@ -1351,14 +1470,12 @@ private final class CollectionTabItemComponent: Component {
|
|||||||
let titleSize = self.title.update(
|
let titleSize = self.title.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextComponent(
|
component: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(string: component.title, font: Font.semibold(14.0), textColor: .white))
|
text: .plain(NSAttributedString(string: component.title, font: Font.semibold(14.0), textColor: component.theme.list.itemSecondaryTextColor))
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
containerSize: CGSize(width: availableSize.width, height: 100.0)
|
||||||
)
|
)
|
||||||
|
|
||||||
let tintColor = component.theme.list.itemSecondaryTextColor
|
|
||||||
|
|
||||||
var iconOffset: CGFloat = 0.0
|
var iconOffset: CGFloat = 0.0
|
||||||
var iconSize = CGSize()
|
var iconSize = CGSize()
|
||||||
if let icon = component.icon {
|
if let icon = component.icon {
|
||||||
@ -1392,7 +1509,7 @@ private final class CollectionTabItemComponent: Component {
|
|||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(BundleIconComponent(
|
component: AnyComponent(BundleIconComponent(
|
||||||
name: "Chat/Input/Media/PanelBadgeAdd",
|
name: "Chat/Input/Media/PanelBadgeAdd",
|
||||||
tintColor: tintColor
|
tintColor: component.theme.list.itemSecondaryTextColor
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: 100.0, height: 100.0)
|
containerSize: CGSize(width: 100.0, height: 100.0)
|
||||||
@ -1428,8 +1545,6 @@ private final class CollectionTabItemComponent: Component {
|
|||||||
self.addSubview(titleView)
|
self.addSubview(titleView)
|
||||||
}
|
}
|
||||||
titleView.frame = titleFrame
|
titleView.frame = titleFrame
|
||||||
|
|
||||||
transition.setTintColor(layer: titleView.layer, color: tintColor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let size: CGSize
|
let size: CGSize
|
||||||
|
|||||||
@ -460,7 +460,8 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
],
|
],
|
||||||
availability: StarGift.UniqueGift.Availability(issued: 0, total: 0),
|
availability: StarGift.UniqueGift.Availability(issued: 0, total: 0),
|
||||||
giftAddress: nil,
|
giftAddress: nil,
|
||||||
resellStars: nil,
|
resellAmounts: nil,
|
||||||
|
resellForTonOnly: false,
|
||||||
releasedBy: nil
|
releasedBy: nil
|
||||||
)
|
)
|
||||||
signal = component.context.engine.accountData.setStarGiftStatus(starGift: gift, expirationDate: emojiStatus.expirationDate)
|
signal = component.context.engine.accountData.setStarGiftStatus(starGift: gift, expirationDate: emojiStatus.expirationDate)
|
||||||
|
|||||||
@ -942,8 +942,8 @@ private final class SheetContent: CombinedComponent {
|
|||||||
|
|
||||||
if case let .starGiftResell(giftToMatch, update, _) = self.mode {
|
if case let .starGiftResell(giftToMatch, update, _) = self.mode {
|
||||||
if update {
|
if update {
|
||||||
if let resellStars = giftToMatch.resellStars {
|
if let resellStars = giftToMatch.resellAmounts?.first(where: { $0.currency == .stars }) {
|
||||||
self.amount = StarsAmount(value: resellStars, nanos: 0)
|
self.amount = resellStars.amount
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let _ = (context.engine.payments.cachedStarGifts()
|
let _ = (context.engine.payments.cachedStarGifts()
|
||||||
|
|||||||
@ -483,6 +483,14 @@ public final class TabSelectorComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func scrollToStart() {
|
||||||
|
self.setContentOffset(.zero, animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func scrollToEnd() {
|
||||||
|
self.setContentOffset(CGPoint(x: self.contentSize.width - self.bounds.width, y: 0.0), animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
func update(component: TabSelectorComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
func update(component: TabSelectorComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
let selectionColorUpdated = component.colors.selection != self.component?.colors.selection
|
let selectionColorUpdated = component.colors.selection != self.component?.colors.selection
|
||||||
|
|
||||||
|
|||||||
@ -900,7 +900,21 @@ final class AuthorizedApplicationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if openAppIfAny, case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.hasWebApp), let parentController = self.rootController.viewControllers.last as? ViewController {
|
if openAppIfAny, case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.hasWebApp), let parentController = self.rootController.viewControllers.last as? ViewController {
|
||||||
self.context.sharedContext.openWebApp(context: self.context, parentController: parentController, updatedPresentationData: nil, botPeer: peer, chatPeer: nil, threadId: nil, buttonText: "", url: "", simple: true, source: .generic, skipTermsOfService: true, payload: nil)
|
self.context.sharedContext.openWebApp(
|
||||||
|
context: self.context,
|
||||||
|
parentController: parentController,
|
||||||
|
updatedPresentationData: nil,
|
||||||
|
botPeer: peer,
|
||||||
|
chatPeer: nil,
|
||||||
|
threadId: nil,
|
||||||
|
buttonText: "",
|
||||||
|
url: "",
|
||||||
|
simple: true,
|
||||||
|
source: .generic,
|
||||||
|
skipTermsOfService: true,
|
||||||
|
payload: nil,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: chatLocation, subject: alwaysKeepMessageId || isOutgoingMessage ? messageId.flatMap { .message(id: .id($0), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false) } : nil, activateInput: activateInput ? .text : nil))
|
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: chatLocation, subject: alwaysKeepMessageId || isOutgoingMessage ? messageId.flatMap { .message(id: .id($0), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil, setupReply: false) } : nil, activateInput: activateInput ? .text : nil))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,8 +128,7 @@ extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if "".isEmpty {
|
if canReplyInChat(self.presentationInterfaceState, accountPeerId: self.context.account.peerId) {
|
||||||
//TODO:release
|
|
||||||
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Todo_ReplyToItem, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Todo_ReplyToItem, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, action: { [weak self] c, _ in
|
}, action: { [weak self] c, _ in
|
||||||
|
|||||||
@ -27,7 +27,8 @@ func openWebAppImpl(
|
|||||||
simple: Bool,
|
simple: Bool,
|
||||||
source: ChatOpenWebViewSource,
|
source: ChatOpenWebViewSource,
|
||||||
skipTermsOfService: Bool,
|
skipTermsOfService: Bool,
|
||||||
payload: String?
|
payload: String?,
|
||||||
|
verifyAgeCompletion: ((Int) -> Void)?
|
||||||
) {
|
) {
|
||||||
if context.isFrozen {
|
if context.isFrozen {
|
||||||
parentController.push(context.sharedContext.makeAccountFreezeInfoScreen(context: context))
|
parentController.push(context.sharedContext.makeAccountFreezeInfoScreen(context: context))
|
||||||
@ -246,7 +247,7 @@ func openWebAppImpl(
|
|||||||
navigationController = parentController.effectiveNavigationController
|
navigationController = parentController.effectiveNavigationController
|
||||||
}
|
}
|
||||||
return navigationController ?? (context.sharedContext.mainWindow?.viewController as? NavigationController)
|
return navigationController ?? (context.sharedContext.mainWindow?.viewController as? NavigationController)
|
||||||
})
|
}, verifyAgeCompletion: verifyAgeCompletion)
|
||||||
controller.navigationPresentation = .flatModal
|
controller.navigationPresentation = .flatModal
|
||||||
parentController.push(controller)
|
parentController.push(controller)
|
||||||
|
|
||||||
@ -351,7 +352,21 @@ public extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
self.chatDisplayNode.dismissInput()
|
self.chatDisplayNode.dismissInput()
|
||||||
|
|
||||||
self.context.sharedContext.openWebApp(context: self.context, parentController: self, updatedPresentationData: self.updatedPresentationData, botPeer: EnginePeer(peer), chatPeer: EnginePeer(peer), threadId: self.chatLocation.threadId, buttonText: buttonText, url: url, simple: simple, source: source, skipTermsOfService: false, payload: nil)
|
self.context.sharedContext.openWebApp(
|
||||||
|
context: self.context,
|
||||||
|
parentController: self,
|
||||||
|
updatedPresentationData: self.updatedPresentationData,
|
||||||
|
botPeer: EnginePeer(peer),
|
||||||
|
chatPeer: EnginePeer(peer),
|
||||||
|
threadId: self.chatLocation.threadId,
|
||||||
|
buttonText: buttonText,
|
||||||
|
url: url,
|
||||||
|
simple: simple,
|
||||||
|
source: source,
|
||||||
|
skipTermsOfService: false,
|
||||||
|
payload: nil,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate static func botRequestSwitchInline(context: AccountContext, controller: ChatControllerImpl?, peerId: EnginePeer.Id, botAddress: String, query: String, chatTypes: [ReplyMarkupButtonRequestPeerType]?, completion: @escaping () -> Void) -> Void {
|
fileprivate static func botRequestSwitchInline(context: AccountContext, controller: ChatControllerImpl?, peerId: EnginePeer.Id, botAddress: String, query: String, chatTypes: [ReplyMarkupButtonRequestPeerType]?, completion: @escaping () -> Void) -> Void {
|
||||||
@ -616,7 +631,21 @@ public extension ChatControllerImpl {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
context.sharedContext.openWebApp(context: context, parentController: parentController, updatedPresentationData: updatedPresentationData, botPeer: botPeer, chatPeer: nil, threadId: nil, buttonText: "", url: "", simple: true, source: .generic, skipTermsOfService: false, payload: payload)
|
context.sharedContext.openWebApp(
|
||||||
|
context: context,
|
||||||
|
parentController: parentController,
|
||||||
|
updatedPresentationData: updatedPresentationData,
|
||||||
|
botPeer: botPeer,
|
||||||
|
chatPeer: nil,
|
||||||
|
threadId: nil,
|
||||||
|
buttonText: "",
|
||||||
|
url: "",
|
||||||
|
simple: true,
|
||||||
|
source: .generic,
|
||||||
|
skipTermsOfService: false,
|
||||||
|
payload: payload,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8907,7 +8907,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
commit()
|
commit()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
self.context.sharedContext.openWebApp(context: self.context, parentController: self, updatedPresentationData: self.updatedPresentationData, botPeer: peer, chatPeer: nil, threadId: nil, buttonText: "", url: "", simple: true, source: .generic, skipTermsOfService: false, payload: botAppStart.payload)
|
self.context.sharedContext.openWebApp(
|
||||||
|
context: self.context,
|
||||||
|
parentController: self,
|
||||||
|
updatedPresentationData: self.updatedPresentationData,
|
||||||
|
botPeer: peer,
|
||||||
|
chatPeer: nil,
|
||||||
|
threadId: nil,
|
||||||
|
buttonText: "",
|
||||||
|
url: "",
|
||||||
|
simple: true,
|
||||||
|
source: .generic,
|
||||||
|
skipTermsOfService: false,
|
||||||
|
payload: botAppStart.payload,
|
||||||
|
verifyAgeCompletion: nil
|
||||||
|
)
|
||||||
commit()
|
commit()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -3882,8 +3882,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return incomingMessagePrivacyScreen(context: context, value: value, exceptions: exceptions, update: update)
|
return incomingMessagePrivacyScreen(context: context, value: value, exceptions: exceptions, update: update)
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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?) {
|
public 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)?) {
|
||||||
openWebAppImpl(context: context, parentController: parentController, updatedPresentationData: updatedPresentationData, botPeer: botPeer, chatPeer: chatPeer, threadId: threadId, buttonText: buttonText, url: url, simple: simple, source: source, skipTermsOfService: skipTermsOfService, payload: payload)
|
openWebAppImpl(context: context, parentController: parentController, updatedPresentationData: updatedPresentationData, botPeer: botPeer, chatPeer: chatPeer, threadId: threadId, buttonText: buttonText, url: url, simple: simple, source: source, skipTermsOfService: skipTermsOfService, payload: payload, verifyAgeCompletion: verifyAgeCompletion)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeAffiliateProgramSetupScreenInitialData(context: AccountContext, peerId: EnginePeer.Id, mode: AffiliateProgramSetupScreenMode) -> Signal<AffiliateProgramSetupScreenInitialData, NoError> {
|
public func makeAffiliateProgramSetupScreenInitialData(context: AccountContext, peerId: EnginePeer.Id, mode: AffiliateProgramSetupScreenMode) -> Signal<AffiliateProgramSetupScreenInitialData, NoError> {
|
||||||
|
|||||||
@ -31,7 +31,6 @@ import PeerInfoScreen
|
|||||||
import PeerInfoStoryGridScreen
|
import PeerInfoStoryGridScreen
|
||||||
import ShareWithPeersScreen
|
import ShareWithPeersScreen
|
||||||
import ChatEmptyNode
|
import ChatEmptyNode
|
||||||
//import FaceScanScreen
|
|
||||||
import UndoUI
|
import UndoUI
|
||||||
|
|
||||||
private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceholderNode {
|
private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceholderNode {
|
||||||
@ -237,22 +236,6 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
|||||||
self.accountSettingsController = accountSettingsController
|
self.accountSettingsController = accountSettingsController
|
||||||
self.rootTabController = tabBarController
|
self.rootTabController = tabBarController
|
||||||
self.pushViewController(tabBarController, animated: false)
|
self.pushViewController(tabBarController, animated: false)
|
||||||
|
|
||||||
// Queue.mainQueue().after(1.0) {
|
|
||||||
// let context = self.context
|
|
||||||
// let infoScreen = AgeVerificationScreen(context: context, completion: { [weak chatListController] proceed in
|
|
||||||
// if proceed {
|
|
||||||
// let scanScreen = FaceScanScreen(context: context, completion: { success in
|
|
||||||
// let controller = UndoOverlayController(presentationData: self.presentationData, content: .actionSucceeded(title: "Age check passed!", text: "You can now view this content.", cancel: nil, destructive: false), elevatedLayout: true, action: { _ in return true })
|
|
||||||
// Queue.mainQueue().after(0.1) {
|
|
||||||
// chatListController?.present(controller, in: .window(.root))
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// chatListController?.push(scanScreen)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// chatListController.push(infoScreen)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateRootControllers(showCallsTab: Bool) {
|
public func updateRootControllers(showCallsTab: Bool) {
|
||||||
|
|||||||
@ -90,6 +90,21 @@ private func updateInfoControllerEntries(theme: PresentationTheme, strings: Pres
|
|||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class UpdateInfoController: ItemListController {
|
||||||
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
|
self.view.layer.animatePosition(from: CGPoint(x: self.view.layer.position.x, y: self.view.layer.position.y + self.view.layer.bounds.size.height), to: self.view.layer.position, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, completion: { _ in
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func animateOut(completion: (() -> Void)? = nil) {
|
||||||
|
self.view.layer.animatePosition(from: self.view.layer.position, to: CGPoint(x: self.view.layer.position.x, y: self.view.layer.position.y + self.view.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
|
||||||
|
completion?()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func updateInfoController(context: AccountContext, appUpdateInfo: AppUpdateInfo) -> ViewController {
|
public func updateInfoController(context: AccountContext, appUpdateInfo: AppUpdateInfo) -> ViewController {
|
||||||
var dismissImpl: (() -> Void)?
|
var dismissImpl: (() -> Void)?
|
||||||
var linkActionImpl: ((TextLinkItemActionType, TextLinkItem) -> Void)?
|
var linkActionImpl: ((TextLinkItemActionType, TextLinkItem) -> Void)?
|
||||||
@ -128,16 +143,16 @@ public func updateInfoController(context: AccountContext, appUpdateInfo: AppUpda
|
|||||||
actionsDisposable.dispose()
|
actionsDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
let controller = ItemListController(sharedContext: context.sharedContext, state: signal)
|
let controller = UpdateInfoController(sharedContext: context.sharedContext, state: signal)
|
||||||
controller.navigationPresentation = .modal
|
|
||||||
linkActionImpl = { [weak controller, weak context] action, itemLink in
|
linkActionImpl = { [weak controller, weak context] action, itemLink in
|
||||||
if let strongController = controller, let context = context {
|
if let strongController = controller, let context = context {
|
||||||
context.sharedContext.handleTextLinkAction(context: context, peerId: nil, navigateDisposable: navigateDisposable, controller: strongController, action: action, itemLink: itemLink)
|
context.sharedContext.handleTextLinkAction(context: context, peerId: nil, navigateDisposable: navigateDisposable, controller: strongController, action: action, itemLink: itemLink)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dismissImpl = { [weak controller] in
|
dismissImpl = { [weak controller] in
|
||||||
controller?.view.endEditing(true)
|
controller?.animateOut(completion: { [weak controller] in
|
||||||
controller?.presentingViewController?.dismiss(animated: true, completion: nil)
|
controller?.dismiss()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,6 +102,7 @@ class UpdateInfoItemNode: ListViewItemNode {
|
|||||||
private let bottomStripeNode: ASDisplayNode
|
private let bottomStripeNode: ASDisplayNode
|
||||||
private let highlightedBackgroundNode: ASDisplayNode
|
private let highlightedBackgroundNode: ASDisplayNode
|
||||||
private var linkHighlightingNode: LinkHighlightingNode?
|
private var linkHighlightingNode: LinkHighlightingNode?
|
||||||
|
private let maskNode: ASImageNode
|
||||||
|
|
||||||
private let iconNode: ASImageNode
|
private let iconNode: ASImageNode
|
||||||
private let overlayNode: ASImageNode
|
private let overlayNode: ASImageNode
|
||||||
@ -127,6 +128,9 @@ class UpdateInfoItemNode: ListViewItemNode {
|
|||||||
self.bottomStripeNode = ASDisplayNode()
|
self.bottomStripeNode = ASDisplayNode()
|
||||||
self.bottomStripeNode.isLayerBacked = true
|
self.bottomStripeNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.maskNode = ASImageNode()
|
||||||
|
self.maskNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
self.iconNode = ASImageNode()
|
self.iconNode = ASImageNode()
|
||||||
self.iconNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 62.0, height: 62.0))
|
self.iconNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 62.0, height: 62.0))
|
||||||
self.iconNode.isLayerBacked = true
|
self.iconNode.isLayerBacked = true
|
||||||
@ -198,6 +202,7 @@ class UpdateInfoItemNode: ListViewItemNode {
|
|||||||
let inset: CGFloat
|
let inset: CGFloat
|
||||||
let itemBackgroundColor: UIColor
|
let itemBackgroundColor: UIColor
|
||||||
let itemSeparatorColor: UIColor
|
let itemSeparatorColor: UIColor
|
||||||
|
let verticalInset: CGFloat = 14.0
|
||||||
|
|
||||||
switch item.style {
|
switch item.style {
|
||||||
case .plain:
|
case .plain:
|
||||||
@ -221,10 +226,10 @@ class UpdateInfoItemNode: ListViewItemNode {
|
|||||||
|
|
||||||
switch item.style {
|
switch item.style {
|
||||||
case .plain:
|
case .plain:
|
||||||
contentSize = CGSize(width: params.width, height: 88.0 + textLayout.size.height + inset)
|
contentSize = CGSize(width: params.width, height: 88.0 + textLayout.size.height + verticalInset * 2.0)
|
||||||
insets = itemListNeighborsPlainInsets(neighbors)
|
insets = itemListNeighborsPlainInsets(neighbors)
|
||||||
case .blocks:
|
case .blocks:
|
||||||
contentSize = CGSize(width: params.width, height: 88.0 + textLayout.size.height + inset)
|
contentSize = CGSize(width: params.width, height: 88.0 + textLayout.size.height + verticalInset * 2.0)
|
||||||
insets = itemListNeighborsGroupedInsets(neighbors, params)
|
insets = itemListNeighborsGroupedInsets(neighbors, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,11 +294,19 @@ class UpdateInfoItemNode: ListViewItemNode {
|
|||||||
if strongSelf.bottomStripeNode.supernode == nil {
|
if strongSelf.bottomStripeNode.supernode == nil {
|
||||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||||
}
|
}
|
||||||
|
if strongSelf.maskNode.supernode == nil {
|
||||||
|
strongSelf.addSubnode(strongSelf.maskNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||||
|
var hasTopCorners = false
|
||||||
|
var hasBottomCorners = false
|
||||||
switch neighbors.top {
|
switch neighbors.top {
|
||||||
case .sameSection(false):
|
case .sameSection(false):
|
||||||
strongSelf.topStripeNode.isHidden = true
|
strongSelf.topStripeNode.isHidden = true
|
||||||
default:
|
default:
|
||||||
strongSelf.topStripeNode.isHidden = false
|
hasTopCorners = true
|
||||||
|
strongSelf.topStripeNode.isHidden = hasCorners
|
||||||
}
|
}
|
||||||
let bottomStripeInset: CGFloat
|
let bottomStripeInset: CGFloat
|
||||||
let bottomStripeOffset: CGFloat
|
let bottomStripeOffset: CGFloat
|
||||||
@ -305,13 +318,19 @@ class UpdateInfoItemNode: ListViewItemNode {
|
|||||||
default:
|
default:
|
||||||
bottomStripeInset = 0.0
|
bottomStripeInset = 0.0
|
||||||
bottomStripeOffset = 0.0
|
bottomStripeOffset = 0.0
|
||||||
|
hasBottomCorners = true
|
||||||
|
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||||
|
|
||||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||||
|
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))
|
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))
|
||||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))
|
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))
|
||||||
}
|
}
|
||||||
|
|
||||||
let iconFrame = CGRect(origin: CGPoint(x: inset, y: inset), size: CGSize(width: 62.0, height: 62.0))
|
let iconFrame = CGRect(origin: CGPoint(x: inset, y: verticalInset), size: CGSize(width: 62.0, height: 62.0))
|
||||||
strongSelf.iconNode.frame = iconFrame
|
strongSelf.iconNode.frame = iconFrame
|
||||||
strongSelf.overlayNode.frame = iconFrame
|
strongSelf.overlayNode.frame = iconFrame
|
||||||
|
|
||||||
|
|||||||
@ -653,10 +653,14 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
self.animateTransitionIn()
|
self.animateTransitionIn()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOSApplicationExtension 15.0, iOS 15.0, *)
|
@available(iOSApplicationExtension 15.0, iOS 15.0, *)
|
||||||
func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) {
|
func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) {
|
||||||
decisionHandler(.prompt)
|
if self.controller?.isVerifyAgeBot == true && type == .camera {
|
||||||
|
decisionHandler(.grant)
|
||||||
|
} else {
|
||||||
|
decisionHandler(.prompt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
|
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
|
||||||
@ -1756,6 +1760,12 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
case "web_app_hide_keyboard":
|
case "web_app_hide_keyboard":
|
||||||
self.view.window?.endEditing(true)
|
self.view.window?.endEditing(true)
|
||||||
|
case "web_app_verify_age":
|
||||||
|
if let json, self.controller?.isVerifyAgeBot == true {
|
||||||
|
if let ageValue = json["age"] as? Double {
|
||||||
|
self.controller?.verifyAgeCompletion?(Int(ageValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -3281,6 +3291,8 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
public var completion: () -> Void = {}
|
public var completion: () -> Void = {}
|
||||||
public var requestSwitchInline: (String, [ReplyMarkupButtonRequestPeerType]?, @escaping () -> Void) -> Void = { _, _, _ in }
|
public var requestSwitchInline: (String, [ReplyMarkupButtonRequestPeerType]?, @escaping () -> Void) -> Void = { _, _, _ in }
|
||||||
|
|
||||||
|
public var verifyAgeCompletion: ((Int) -> Void)?
|
||||||
|
|
||||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, params: WebAppParameters, replyToMessageId: MessageId?, threadId: Int64?) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, params: WebAppParameters, replyToMessageId: MessageId?, threadId: Int64?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.source = params.source
|
self.source = params.source
|
||||||
@ -3323,16 +3335,20 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
self.navigationItem.leftBarButtonItem?.action = #selector(self.cancelPressed)
|
self.navigationItem.leftBarButtonItem?.action = #selector(self.cancelPressed)
|
||||||
self.navigationItem.leftBarButtonItem?.target = self
|
self.navigationItem.leftBarButtonItem?.target = self
|
||||||
|
|
||||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customDisplayNode: self.moreButtonNode)
|
if !self.isVerifyAgeBot {
|
||||||
self.navigationItem.rightBarButtonItem?.action = #selector(self.moreButtonPressed)
|
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customDisplayNode: self.moreButtonNode)
|
||||||
self.navigationItem.rightBarButtonItem?.target = self
|
self.navigationItem.rightBarButtonItem?.action = #selector(self.moreButtonPressed)
|
||||||
|
self.navigationItem.rightBarButtonItem?.target = self
|
||||||
|
}
|
||||||
|
|
||||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||||
|
|
||||||
let titleView = WebAppTitleView(context: self.context, theme: self.presentationData.theme)
|
if !self.isVerifyAgeBot {
|
||||||
titleView.title = WebAppTitle(title: params.botName, counter: self.presentationData.strings.WebApp_Miniapp, isVerified: params.botVerified)
|
let titleView = WebAppTitleView(context: self.context, theme: self.presentationData.theme)
|
||||||
self.navigationItem.titleView = titleView
|
titleView.title = WebAppTitle(title: params.botName, counter: self.presentationData.strings.WebApp_Miniapp, isVerified: params.botVerified)
|
||||||
self.titleView = titleView
|
self.navigationItem.titleView = titleView
|
||||||
|
self.titleView = titleView
|
||||||
|
}
|
||||||
|
|
||||||
self.moreButtonNode.action = { [weak self] _, gesture in
|
self.moreButtonNode.action = { [weak self] _, gesture in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@ -3387,6 +3403,13 @@ public final class WebAppController: ViewController, AttachmentContainable {
|
|||||||
self.presentationDataDisposable?.dispose()
|
self.presentationDataDisposable?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var isVerifyAgeBot: Bool {
|
||||||
|
if let ageBotUsername = self.context.currentAppConfiguration.with({ $0 }).data?["verify_age_bot_username"] as? String {
|
||||||
|
return self.botAddress == ageBotUsername
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
public func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void) {
|
public func beforeMaximize(navigationController: NavigationController, completion: @escaping () -> Void) {
|
||||||
switch self.source {
|
switch self.source {
|
||||||
case .generic, .settings:
|
case .generic, .settings:
|
||||||
@ -3857,7 +3880,8 @@ public func standaloneWebAppController(
|
|||||||
willDismiss: @escaping () -> Void = {},
|
willDismiss: @escaping () -> Void = {},
|
||||||
didDismiss: @escaping () -> Void = {},
|
didDismiss: @escaping () -> Void = {},
|
||||||
getNavigationController: @escaping () -> NavigationController? = { return nil },
|
getNavigationController: @escaping () -> NavigationController? = { return nil },
|
||||||
getSourceRect: (() -> CGRect?)? = nil
|
getSourceRect: (() -> CGRect?)? = nil,
|
||||||
|
verifyAgeCompletion: ((Int) -> Void)? = nil
|
||||||
) -> ViewController {
|
) -> ViewController {
|
||||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: params.peerId), buttons: [.standalone], initialButton: .standalone, fromMenu: params.source == .menu, hasTextInput: false, isFullSize: params.fullSize, makeEntityInputView: {
|
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: params.peerId), buttons: [.standalone], initialButton: .standalone, fromMenu: params.source == .menu, hasTextInput: false, isFullSize: params.fullSize, makeEntityInputView: {
|
||||||
return nil
|
return nil
|
||||||
@ -3868,6 +3892,7 @@ public func standaloneWebAppController(
|
|||||||
webAppController.completion = completion
|
webAppController.completion = completion
|
||||||
webAppController.getNavigationController = getNavigationController
|
webAppController.getNavigationController = getNavigationController
|
||||||
webAppController.requestSwitchInline = requestSwitchInline
|
webAppController.requestSwitchInline = requestSwitchInline
|
||||||
|
webAppController.verifyAgeCompletion = verifyAgeCompletion
|
||||||
present(webAppController, webAppController.mediaPickerContext)
|
present(webAppController, webAppController.mediaPickerContext)
|
||||||
}
|
}
|
||||||
controller.willDismiss = willDismiss
|
controller.willDismiss = willDismiss
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "11.14",
|
"app": "11.13.4",
|
||||||
"xcode": "16.2",
|
"xcode": "16.2",
|
||||||
"bazel": "8.2.1:22ff65b05869f6160e5157b1b425a14a62085d71d8baef571f462b8fe5a703a3",
|
"bazel": "8.2.1:22ff65b05869f6160e5157b1b425a14a62085d71d8baef571f462b8fe5a703a3",
|
||||||
"macos": "15"
|
"macos": "15"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user