mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-07 08:01:10 +00:00
Merge commit 'f1753011e1e5ca79e4720288fd7a521344ef6373'
This commit is contained in:
commit
235482fea1
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/Gift12.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/Gift12.tgs
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Telegram/Telegram-iOS/Resources/Gift6.tgs
Normal file
BIN
Telegram/Telegram-iOS/Resources/Gift6.tgs
Normal file
Binary file not shown.
@ -7869,6 +7869,7 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Premium.AnimatedEmoji" = "Animated Emoji";
|
"Premium.AnimatedEmoji" = "Animated Emoji";
|
||||||
"Premium.AnimatedEmojiInfo" = "Include animated emoji from different emoji sets in any message you send.";
|
"Premium.AnimatedEmojiInfo" = "Include animated emoji from different emoji sets in any message you send.";
|
||||||
|
"Premium.AnimatedEmojiStandaloneInfo" = "Include animated emoji from different emoji sets in any message you send.";
|
||||||
|
|
||||||
"ChatContextMenu.EmojiSetSingle" = "This message contains\n#[%@]() emoji.";
|
"ChatContextMenu.EmojiSetSingle" = "This message contains\n#[%@]() emoji.";
|
||||||
"ChatContextMenu.EmojiSet_1" = "This message contains emoji from [%@ pack]().";
|
"ChatContextMenu.EmojiSet_1" = "This message contains emoji from [%@ pack]().";
|
||||||
@ -7886,6 +7887,12 @@ Sorry for the inconvenience.";
|
|||||||
"EmojiPackActionInfo.ArchivedTitle" = "Emoji Archived";
|
"EmojiPackActionInfo.ArchivedTitle" = "Emoji Archived";
|
||||||
"EmojiPackActionInfo.RemovedText" = "%@ is no longer in your emoji.";
|
"EmojiPackActionInfo.RemovedText" = "%@ is no longer in your emoji.";
|
||||||
|
|
||||||
|
"EmojiPackActionInfo.MultipleAddedText_1" = "%@ emoji pack has been added to your emoji.";
|
||||||
|
"EmojiPackActionInfo.MultipleAddedText_any" = "%@ emoji packs have been added to your emoji.";
|
||||||
|
|
||||||
|
"EmojiPackActionInfo.MultipleRemovedText_1" = "%@ emoji pack is no longer in your emoji.";
|
||||||
|
"EmojiPackActionInfo.MultipleRemovedText_any" = "%@ emoji packs are no longer in your emoji.";
|
||||||
|
|
||||||
"MaskPackActionInfo.RemovedTitle" = "Masks Removed";
|
"MaskPackActionInfo.RemovedTitle" = "Masks Removed";
|
||||||
"MaskPackActionInfo.ArchivedTitle" = "Masks Archived";
|
"MaskPackActionInfo.ArchivedTitle" = "Masks Archived";
|
||||||
"MaskPackActionInfo.RemovedText" = "%@ is no longer in your masks.";
|
"MaskPackActionInfo.RemovedText" = "%@ is no longer in your masks.";
|
||||||
@ -7911,6 +7918,9 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"StickerSettings.EmojiContextInfo" = "If you archive an emoji set, you can quickly restore it later from the Archived Emoji section.";
|
"StickerSettings.EmojiContextInfo" = "If you archive an emoji set, you can quickly restore it later from the Archived Emoji section.";
|
||||||
|
|
||||||
|
"StickerPack.CopyLinks" = "Copy Links";
|
||||||
|
"Conversation.LinksCopied" = "Links copied to clipboard";
|
||||||
|
|
||||||
"StickersList.EmojiItem" = "Custom Emoji";
|
"StickersList.EmojiItem" = "Custom Emoji";
|
||||||
"StickersList.ArchivedEmojiItem" = "Archived Emoji";
|
"StickersList.ArchivedEmojiItem" = "Archived Emoji";
|
||||||
|
|
||||||
|
@ -560,6 +560,8 @@ public protocol ChatController: ViewController {
|
|||||||
func beginMessageSearch(_ query: String)
|
func beginMessageSearch(_ query: String)
|
||||||
func displayPromoAnnouncement(text: String)
|
func displayPromoAnnouncement(text: String)
|
||||||
|
|
||||||
|
func hintPlayNextOutgoingGift()
|
||||||
|
|
||||||
var isSendButtonVisible: Bool { get }
|
var isSendButtonVisible: Bool { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,11 +481,13 @@ private func availablePaymentMethods(form: BotPaymentForm, current: BotCheckoutP
|
|||||||
methods.append(.applePay)
|
methods.append(.applePay)
|
||||||
hasApplePay = true
|
hasApplePay = true
|
||||||
}
|
}
|
||||||
if let savedCredentials = form.savedCredentials {
|
|
||||||
|
for savedCredentials in form.savedCredentials {
|
||||||
if !methods.contains(.savedCredentials(savedCredentials)) {
|
if !methods.contains(.savedCredentials(savedCredentials)) {
|
||||||
methods.append(.savedCredentials(savedCredentials))
|
methods.append(.savedCredentials(savedCredentials))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !form.additionalPaymentMethods.isEmpty {
|
if !form.additionalPaymentMethods.isEmpty {
|
||||||
methods.append(contentsOf: form.additionalPaymentMethods.map { .other($0) })
|
methods.append(contentsOf: form.additionalPaymentMethods.map { .other($0) })
|
||||||
}
|
}
|
||||||
@ -835,7 +837,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dismissImpl: (() -> Void)?
|
var dismissImpl: (() -> Void)?
|
||||||
let canSave = paymentForm.canSaveCredentials || paymentForm.passwordMissing
|
let canSave = customUrl == nil && (paymentForm.canSaveCredentials || paymentForm.passwordMissing)
|
||||||
let controller = BotCheckoutNativeCardEntryController(context: strongSelf.context, provider: .stripe(additionalFields: additionalFields, publishableKey: publishableKey), completion: { method in
|
let controller = BotCheckoutNativeCardEntryController(context: strongSelf.context, provider: .stripe(additionalFields: additionalFields, publishableKey: publishableKey), completion: { method in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -1106,7 +1108,7 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
|||||||
strongSelf.botPeerValue = formAndValidatedInfo.botPeer
|
strongSelf.botPeerValue = formAndValidatedInfo.botPeer
|
||||||
strongSelf.currentFormInfo = savedInfo
|
strongSelf.currentFormInfo = savedInfo
|
||||||
strongSelf.currentValidatedFormInfo = formAndValidatedInfo.validatedFormInfo
|
strongSelf.currentValidatedFormInfo = formAndValidatedInfo.validatedFormInfo
|
||||||
if let savedCredentials = formAndValidatedInfo.form.savedCredentials {
|
if let savedCredentials = formAndValidatedInfo.form.savedCredentials.first {
|
||||||
strongSelf.currentPaymentMethod = .savedCredentials(savedCredentials)
|
strongSelf.currentPaymentMethod = .savedCredentials(savedCredentials)
|
||||||
}
|
}
|
||||||
strongSelf.actionButton.isEnabled = true
|
strongSelf.actionButton.isEnabled = true
|
||||||
|
@ -471,7 +471,6 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
|||||||
if self.animateInputField {
|
if self.animateInputField {
|
||||||
self.fromMessageTextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
self.fromMessageTextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||||
self.toMessageTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, removeOnCompletion: false)
|
self.toMessageTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3, removeOnCompletion: false)
|
||||||
self.textInputNode.isHidden = true
|
|
||||||
} else {
|
} else {
|
||||||
self.messageBackgroundNode.isHidden = true
|
self.messageBackgroundNode.isHidden = true
|
||||||
self.fromMessageTextNode.isHidden = true
|
self.fromMessageTextNode.isHidden = true
|
||||||
@ -526,6 +525,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
|||||||
self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
|
self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
|
||||||
|
|
||||||
Queue.mainQueue().after(0.01, {
|
Queue.mainQueue().after(0.01, {
|
||||||
|
if self.animateInputField {
|
||||||
|
self.textInputNode.isHidden = true
|
||||||
|
}
|
||||||
self.updateTextContents()
|
self.updateTextContents()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -662,15 +662,18 @@ public class Window1 {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.forceBadgeHidden = hidden
|
self.forceBadgeHidden = hidden
|
||||||
self.updateBadgeVisibility(layout: self.windowLayout)
|
self.updateBadgeVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateBadgeVisibility(layout: WindowLayout) {
|
private func updateBadgeVisibility() {
|
||||||
let badgeIsHidden = !self.deviceMetrics.hasTopNotch || self.forceBadgeHidden || layout.size.width > layout.size.height
|
let badgeIsHidden = !self.deviceMetrics.hasTopNotch || self.forceBadgeHidden || self.windowLayout.size.width > self.windowLayout.size.height
|
||||||
if badgeIsHidden != self.badgeView.isHidden && !badgeIsHidden {
|
if badgeIsHidden != self.badgeView.isHidden && !badgeIsHidden {
|
||||||
Queue.mainQueue().after(0.3) {
|
Queue.mainQueue().after(0.4) {
|
||||||
|
let badgeShouldBeHidden = !self.deviceMetrics.hasTopNotch || self.forceBadgeHidden || self.windowLayout.size.width > self.windowLayout.size.height
|
||||||
|
if badgeShouldBeHidden == badgeIsHidden {
|
||||||
self.badgeView.isHidden = badgeIsHidden
|
self.badgeView.isHidden = badgeIsHidden
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.badgeView.isHidden = badgeIsHidden
|
self.badgeView.isHidden = badgeIsHidden
|
||||||
}
|
}
|
||||||
@ -1115,7 +1118,7 @@ public class Window1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let image = self.badgeView.image {
|
if let image = self.badgeView.image {
|
||||||
self.updateBadgeVisibility(layout: self.windowLayout)
|
self.updateBadgeVisibility()
|
||||||
self.badgeView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.windowLayout.size.width - image.size.width) / 2.0), y: 6.0), size: image.size)
|
self.badgeView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((self.windowLayout.size.width - image.size.width) / 2.0), y: 6.0), size: image.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,7 +474,8 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
let baseNavigationController = strongSelf.baseNavigationController()
|
let baseNavigationController = strongSelf.baseNavigationController()
|
||||||
baseNavigationController?.view.endEditing(true)
|
baseNavigationController?.view.endEditing(true)
|
||||||
let controller = StickerPackScreen(context: context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { info, items, action in
|
let controller = StickerPackScreen(context: context, mainStickerPack: packs[0], stickerPacks: packs, sendSticker: nil, actionPerformed: { actions in
|
||||||
|
if let (info, items, action) = actions.first {
|
||||||
let animateInAsReplacement = false
|
let animateInAsReplacement = false
|
||||||
switch action {
|
switch action {
|
||||||
case .add:
|
case .add:
|
||||||
@ -489,6 +490,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
return true
|
return true
|
||||||
}), in: .window(.root))
|
}), in: .window(.root))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
(baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
|
(baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil)
|
||||||
})
|
})
|
||||||
|
@ -2477,15 +2477,15 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
c.setItems(strongSelf.contextMenuSpeedItems() |> map { ContextController.Items(content: .list($0)) }, minHeight: nil)
|
c.setItems(strongSelf.contextMenuSpeedItems() |> map { ContextController.Items(content: .list($0)) }, minHeight: nil)
|
||||||
})))
|
})))
|
||||||
|
|
||||||
if #available(iOS 11.0, *) {
|
// if #available(iOS 11.0, *) {
|
||||||
items.append(.action(ContextMenuActionItem(text: "AirPlay", textColor: .primary, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/AirPlay"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
|
// items.append(.action(ContextMenuActionItem(text: "AirPlay", textColor: .primary, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/AirPlay"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
|
||||||
f(.default)
|
// f(.default)
|
||||||
guard let strongSelf = self else {
|
// guard let strongSelf = self else {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
strongSelf.beginAirPlaySetup()
|
// strongSelf.beginAirPlaySetup()
|
||||||
})))
|
// })))
|
||||||
}
|
// }
|
||||||
|
|
||||||
if let (message, _, _) = strongSelf.contentInfo() {
|
if let (message, _, _) = strongSelf.contentInfo() {
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
@ -2667,7 +2667,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
let baseNavigationController = strongSelf.baseNavigationController()
|
let baseNavigationController = strongSelf.baseNavigationController()
|
||||||
baseNavigationController?.view.endEditing(true)
|
baseNavigationController?.view.endEditing(true)
|
||||||
let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: Array(packs.prefix(1)), sendSticker: nil, actionPerformed: { info, items, action in
|
let controller = StickerPackScreen(context: strongSelf.context, mainStickerPack: packs[0], stickerPacks: Array(packs.prefix(1)), sendSticker: nil, actionPerformed: { actions in
|
||||||
|
if let (info, items, action) = actions.first {
|
||||||
let animateInAsReplacement = false
|
let animateInAsReplacement = false
|
||||||
switch action {
|
switch action {
|
||||||
case .add:
|
case .add:
|
||||||
@ -2682,6 +2683,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
return true
|
return true
|
||||||
}), in: .window(.root))
|
}), in: .window(.root))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}, dismissed: { [weak self] in
|
}, dismissed: { [weak self] in
|
||||||
self?.isInteractingPromise.set(false)
|
self?.isInteractingPromise.set(false)
|
||||||
})
|
})
|
||||||
|
@ -694,7 +694,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
|
|||||||
}
|
}
|
||||||
strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: firstItem ?? items.first, context: strongSelf.context), elevatedLayout: false, action: { action in
|
strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: firstItem ?? items.first, context: strongSelf.context), elevatedLayout: false, action: { action in
|
||||||
if case .info = action {
|
if case .info = action {
|
||||||
(navigationController?.viewControllers.last as? ViewController)?.present(StickerPackScreen(context: context, mode: .settings, mainStickerPack: .id(id: info.id.id, accessHash: info.accessHash), stickerPacks: [], parentNavigationController: navigationController, actionPerformed: { _, _, _ in
|
(navigationController?.viewControllers.last as? ViewController)?.present(StickerPackScreen(context: context, mode: .settings, mainStickerPack: .id(id: info.id.id, accessHash: info.accessHash), stickerPacks: [], parentNavigationController: navigationController, actionPerformed: { _ in
|
||||||
}), in: .window(.root))
|
}), in: .window(.root))
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 6.0 KiB |
@ -909,7 +909,7 @@ private final class DemoSheetContent: CombinedComponent {
|
|||||||
decoration: .emoji
|
decoration: .emoji
|
||||||
)),
|
)),
|
||||||
title: strings.Premium_AnimatedEmoji,
|
title: strings.Premium_AnimatedEmoji,
|
||||||
text: strings.Premium_AnimatedEmojiInfo,
|
text: isStandalone ? strings.Premium_AnimatedEmojiStandaloneInfo : strings.Premium_AnimatedEmojiInfo,
|
||||||
textColor: textColor
|
textColor: textColor
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -145,7 +145,7 @@ private final class ProductGroupComponent: Component {
|
|||||||
buttonView?.backgroundColor = component.selectionColor
|
buttonView?.backgroundColor = component.selectionColor
|
||||||
} else {
|
} else {
|
||||||
UIView.animate(withDuration: 0.3, animations: {
|
UIView.animate(withDuration: 0.3, animations: {
|
||||||
buttonView?.backgroundColor = nil
|
buttonView?.backgroundColor = component.backgroundColor
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,6 +299,8 @@ private final class GiftComponent: CombinedComponent {
|
|||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let discountSize: CGSize
|
||||||
|
if !component.discount.isEmpty {
|
||||||
let discount = discount.update(
|
let discount = discount.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
text: .plain(
|
text: .plain(
|
||||||
@ -314,7 +316,7 @@ private final class GiftComponent: CombinedComponent {
|
|||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
|
||||||
let discountSize = CGSize(width: discount.size.width + 6.0, height: 18.0)
|
discountSize = CGSize(width: discount.size.width + 6.0, height: 18.0)
|
||||||
|
|
||||||
let discountBackground = discountBackground.update(
|
let discountBackground = discountBackground.update(
|
||||||
component: RoundedRectangle(
|
component: RoundedRectangle(
|
||||||
@ -325,6 +327,17 @@ private final class GiftComponent: CombinedComponent {
|
|||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
|
||||||
|
context.add(discountBackground
|
||||||
|
.position(CGPoint(x: insets.left + discountSize.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0))
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add(discount
|
||||||
|
.position(CGPoint(x: insets.left + discountSize.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0))
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
discountSize = CGSize(width: 0.0, height: 18.0)
|
||||||
|
}
|
||||||
|
|
||||||
let subtitle = subtitle.update(
|
let subtitle = subtitle.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
text: .plain(
|
text: .plain(
|
||||||
@ -360,16 +373,8 @@ private final class GiftComponent: CombinedComponent {
|
|||||||
.position(CGPoint(x: insets.left + title.size.width / 2.0, y: insets.top + title.size.height / 2.0))
|
.position(CGPoint(x: insets.left + title.size.width / 2.0, y: insets.top + title.size.height / 2.0))
|
||||||
)
|
)
|
||||||
|
|
||||||
context.add(discountBackground
|
|
||||||
.position(CGPoint(x: insets.left + discountSize.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0))
|
|
||||||
)
|
|
||||||
|
|
||||||
context.add(discount
|
|
||||||
.position(CGPoint(x: insets.left + discountSize.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0))
|
|
||||||
)
|
|
||||||
|
|
||||||
context.add(subtitle
|
context.add(subtitle
|
||||||
.position(CGPoint(x: insets.left + discountSize.width + 7.0 + subtitle.size.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0))
|
.position(CGPoint(x: insets.left + (discountSize.width.isZero ? 0.0 : discountSize.width + 7.0) + subtitle.size.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0))
|
||||||
)
|
)
|
||||||
|
|
||||||
let size = CGSize(width: context.availableSize.width, height: insets.top + title.size.height + spacing + subtitle.size.height + insets.bottom)
|
let size = CGSize(width: context.availableSize.width, height: insets.top + title.size.height + spacing + subtitle.size.height + insets.bottom)
|
||||||
@ -510,13 +515,13 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let peer: EnginePeer?
|
let peer: EnginePeer?
|
||||||
let products: [InAppPurchaseManager.Product]?
|
let products: [PremiumGiftProduct]?
|
||||||
let selectedProductId: String?
|
let selectedProductId: String?
|
||||||
|
|
||||||
let present: (ViewController) -> Void
|
let present: (ViewController) -> Void
|
||||||
let selectProduct: (String) -> Void
|
let selectProduct: (String) -> Void
|
||||||
|
|
||||||
init(context: AccountContext, peer: EnginePeer?, products: [InAppPurchaseManager.Product]?, selectedProductId: String?, present: @escaping (ViewController) -> Void, selectProduct: @escaping (String) -> Void) {
|
init(context: AccountContext, peer: EnginePeer?, products: [PremiumGiftProduct]?, selectedProductId: String?, present: @escaping (ViewController) -> Void, selectProduct: @escaping (String) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.products = products
|
self.products = products
|
||||||
@ -629,26 +634,26 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
if let products = component.products {
|
if let products = component.products {
|
||||||
|
let shortestOptionPrice: Int64
|
||||||
|
if let product = products.last {
|
||||||
|
shortestOptionPrice = Int64(Float(product.storeProduct.priceCurrencyAndAmount.amount) / Float(product.months))
|
||||||
|
} else {
|
||||||
|
shortestOptionPrice = 1
|
||||||
|
}
|
||||||
|
|
||||||
for product in products {
|
for product in products {
|
||||||
let monthsCount: Int
|
|
||||||
let giftTitle: String
|
let giftTitle: String
|
||||||
let discount: String
|
if product.months == 12 {
|
||||||
switch product.id {
|
|
||||||
case "org.telegram.telegramPremium.twelveMonths":
|
|
||||||
giftTitle = strings.Premium_Gift_Years(1)
|
giftTitle = strings.Premium_Gift_Years(1)
|
||||||
monthsCount = 12
|
} else {
|
||||||
discount = "-15%"
|
giftTitle = strings.Premium_Gift_Months(product.months)
|
||||||
case "org.telegram.telegramPremium.sixMonths":
|
}
|
||||||
giftTitle = strings.Premium_Gift_Months(6)
|
|
||||||
monthsCount = 6
|
let discountValue = Int((1.0 - Float(product.storeProduct.priceCurrencyAndAmount.amount) / Float(product.months) / Float(shortestOptionPrice)) * 100.0)
|
||||||
discount = "-10%"
|
let discount: String
|
||||||
case "org.telegram.telegramPremium.threeMonths":
|
if discountValue > 0 {
|
||||||
giftTitle = strings.Premium_Gift_Months(3)
|
discount = "-\(discountValue)%"
|
||||||
monthsCount = 3
|
} else {
|
||||||
discount = "-7%"
|
|
||||||
default:
|
|
||||||
giftTitle = ""
|
|
||||||
monthsCount = 1
|
|
||||||
discount = ""
|
discount = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,7 +664,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
GiftComponent(
|
GiftComponent(
|
||||||
title: giftTitle,
|
title: giftTitle,
|
||||||
totalPrice: product.price,
|
totalPrice: product.price,
|
||||||
perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth(monthsCount)).string,
|
perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth).string,
|
||||||
discount: discount,
|
discount: discount,
|
||||||
selected: product.id == component.selectedProductId,
|
selected: product.id == component.selectedProductId,
|
||||||
primaryTextColor: textColor,
|
primaryTextColor: textColor,
|
||||||
@ -705,19 +710,42 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct PremiumGiftProduct: Equatable {
|
||||||
|
let giftOption: CachedPremiumGiftOption
|
||||||
|
let storeProduct: InAppPurchaseManager.Product
|
||||||
|
|
||||||
|
var id: String {
|
||||||
|
return self.storeProduct.id
|
||||||
|
}
|
||||||
|
|
||||||
|
var months: Int32 {
|
||||||
|
return self.giftOption.months
|
||||||
|
}
|
||||||
|
|
||||||
|
var price: String {
|
||||||
|
return self.storeProduct.price
|
||||||
|
}
|
||||||
|
|
||||||
|
var pricePerMonth: String {
|
||||||
|
return self.storeProduct.pricePerMonth(Int(self.months))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class PremiumGiftScreenComponent: CombinedComponent {
|
private final class PremiumGiftScreenComponent: CombinedComponent {
|
||||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let peerId: PeerId
|
let peerId: PeerId
|
||||||
|
let options: [CachedPremiumGiftOption]
|
||||||
let updateInProgress: (Bool) -> Void
|
let updateInProgress: (Bool) -> Void
|
||||||
let present: (ViewController) -> Void
|
let present: (ViewController) -> Void
|
||||||
let push: (ViewController) -> Void
|
let push: (ViewController) -> Void
|
||||||
let completion: (Int32) -> Void
|
let completion: (Int32) -> Void
|
||||||
|
|
||||||
init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) {
|
init(context: AccountContext, peerId: PeerId, options: [CachedPremiumGiftOption], updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
|
self.options = options
|
||||||
self.updateInProgress = updateInProgress
|
self.updateInProgress = updateInProgress
|
||||||
self.present = present
|
self.present = present
|
||||||
self.push = push
|
self.push = push
|
||||||
@ -731,12 +759,16 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
if lhs.peerId != rhs.peerId {
|
if lhs.peerId != rhs.peerId {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.options != rhs.options {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
final class State: ComponentState {
|
final class State: ComponentState {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
|
private let options: [CachedPremiumGiftOption]
|
||||||
private let updateInProgress: (Bool) -> Void
|
private let updateInProgress: (Bool) -> Void
|
||||||
private let present: (ViewController) -> Void
|
private let present: (ViewController) -> Void
|
||||||
private let completion: (Int32) -> Void
|
private let completion: (Int32) -> Void
|
||||||
@ -749,16 +781,17 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
var inProgress = false
|
var inProgress = false
|
||||||
|
|
||||||
var peer: EnginePeer?
|
var peer: EnginePeer?
|
||||||
var products: [InAppPurchaseManager.Product]?
|
var products: [PremiumGiftProduct]?
|
||||||
var selectedProductId: String?
|
var selectedProductId: String?
|
||||||
|
|
||||||
private var disposable: Disposable?
|
private var disposable: Disposable?
|
||||||
private var paymentDisposable = MetaDisposable()
|
private var paymentDisposable = MetaDisposable()
|
||||||
private var activationDisposable = MetaDisposable()
|
private var activationDisposable = MetaDisposable()
|
||||||
|
|
||||||
init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) {
|
init(context: AccountContext, peerId: PeerId, options: [CachedPremiumGiftOption], updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
|
self.options = options
|
||||||
self.updateInProgress = updateInProgress
|
self.updateInProgress = updateInProgress
|
||||||
self.present = present
|
self.present = present
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
@ -778,8 +811,18 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
||||||
).start(next: { [weak self] products, peer in
|
).start(next: { [weak self] products, peer in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.products = products.filter { !$0.isSubscription }.sorted(by: { $0.priceValue.compare($1.priceValue) == .orderedDescending })
|
|
||||||
|
var gifts: [PremiumGiftProduct] = []
|
||||||
|
for option in strongSelf.options {
|
||||||
|
if let product = products.first(where: { $0.id == option.storeProductId }), !product.isSubscription {
|
||||||
|
gifts.append(PremiumGiftProduct(giftOption: option, storeProduct: product))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.products = gifts
|
||||||
|
if strongSelf.selectedProductId == nil {
|
||||||
strongSelf.selectedProductId = strongSelf.products?.first?.id
|
strongSelf.selectedProductId = strongSelf.products?.first?.id
|
||||||
|
}
|
||||||
strongSelf.peer = peer
|
strongSelf.peer = peer
|
||||||
strongSelf.updated(transition: .immediate)
|
strongSelf.updated(transition: .immediate)
|
||||||
}
|
}
|
||||||
@ -805,19 +848,8 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
guard let product = self.products?.first(where: { $0.id == self.selectedProductId }) else {
|
guard let product = self.products?.first(where: { $0.id == self.selectedProductId }) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let (currency, amount) = product.priceCurrencyAndAmount
|
let (currency, amount) = product.storeProduct.priceCurrencyAndAmount
|
||||||
|
let duration = product.months
|
||||||
let duration: Int32
|
|
||||||
switch product.id {
|
|
||||||
case "org.telegram.telegramPremium.twelveMonths":
|
|
||||||
duration = 12
|
|
||||||
case "org.telegram.telegramPremium.sixMonths":
|
|
||||||
duration = 6
|
|
||||||
case "org.telegram.telegramPremium.threeMonths":
|
|
||||||
duration = 3
|
|
||||||
default:
|
|
||||||
duration = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// addAppLogEvent(postbox: self.context.account.postbox, type: "premium.promo_screen_accept")
|
// addAppLogEvent(postbox: self.context.account.postbox, type: "premium.promo_screen_accept")
|
||||||
|
|
||||||
@ -829,7 +861,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
|> deliverOnMainQueue).start(next: { [weak self] available in
|
|> deliverOnMainQueue).start(next: { [weak self] available in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
if available {
|
if available {
|
||||||
strongSelf.paymentDisposable.set((inAppPurchaseManager.buyProduct(product, targetPeerId: strongSelf.peerId)
|
strongSelf.paymentDisposable.set((inAppPurchaseManager.buyProduct(product.storeProduct, targetPeerId: strongSelf.peerId)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] status in
|
|> deliverOnMainQueue).start(next: { [weak self] status in
|
||||||
if let strongSelf = self, case .purchased = status {
|
if let strongSelf = self, case .purchased = status {
|
||||||
strongSelf.activationDisposable.set((strongSelf.context.account.postbox.peerView(id: strongSelf.context.account.peerId)
|
strongSelf.activationDisposable.set((strongSelf.context.account.postbox.peerView(id: strongSelf.context.account.peerId)
|
||||||
@ -852,7 +884,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
|
|
||||||
strongSelf.updated(transition: .immediate)
|
strongSelf.updated(transition: .immediate)
|
||||||
|
|
||||||
addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail")
|
// addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail")
|
||||||
|
|
||||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
|
let errorText = presentationData.strings.Premium_Purchase_ErrorUnknown
|
||||||
@ -896,7 +928,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let errorText = errorText {
|
if let errorText = errorText {
|
||||||
addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail")
|
// addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail")
|
||||||
|
|
||||||
let alertController = textAlertController(context: strongSelf.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
|
let alertController = textAlertController(context: strongSelf.context, title: nil, text: errorText, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])
|
||||||
strongSelf.present(alertController)
|
strongSelf.present(alertController)
|
||||||
@ -919,7 +951,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeState() -> State {
|
func makeState() -> State {
|
||||||
return State(context: self.context, peerId: self.peerId, updateInProgress: self.updateInProgress, present: self.present, completion: self.completion)
|
return State(context: self.context, peerId: self.peerId, options: self.options, updateInProgress: self.updateInProgress, present: self.present, completion: self.completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: Body {
|
static var body: Body {
|
||||||
@ -1242,6 +1274,7 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer {
|
|||||||
super.init(context: context, component: PremiumGiftScreenComponent(
|
super.init(context: context, component: PremiumGiftScreenComponent(
|
||||||
context: context,
|
context: context,
|
||||||
peerId: peerId,
|
peerId: peerId,
|
||||||
|
options: options,
|
||||||
updateInProgress: { inProgress in
|
updateInProgress: { inProgress in
|
||||||
updateInProgressImpl?(inProgress)
|
updateInProgressImpl?(inProgress)
|
||||||
},
|
},
|
||||||
@ -1278,6 +1311,12 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer {
|
|||||||
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
|
||||||
var controllers = navigationController.viewControllers
|
var controllers = navigationController.viewControllers
|
||||||
controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) }
|
controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) }
|
||||||
|
for controller in controllers.reversed() {
|
||||||
|
if let chatController = controller as? ChatController, case .peer(id: peerId) = chatController.chatLocation {
|
||||||
|
chatController.hintPlayNextOutgoingGift()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
navigationController.setViewControllers(controllers, animated: true)
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,7 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry {
|
|||||||
case let .privacyHeader(_, text):
|
case let .privacyHeader(_, text):
|
||||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||||
case let .blockedPeers(_, text, value):
|
case let .blockedPeers(_, text, value):
|
||||||
return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Chat/Stickers/Blocked")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
return ItemListDisclosureItem(presentationData: presentationData, icon: UIImage(bundleImageName: "Settings/Menu/Blocked")?.precomposed(), title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||||
arguments.openBlockedUsers()
|
arguments.openBlockedUsers()
|
||||||
})
|
})
|
||||||
case let .phoneNumberPrivacy(_, text, value):
|
case let .phoneNumberPrivacy(_, text, value):
|
||||||
|
@ -1267,7 +1267,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
packs.insert(packReference, at: 0)
|
packs.insert(packReference, at: 0)
|
||||||
}
|
}
|
||||||
if let mainStickerPack = mainStickerPack {
|
if let mainStickerPack = mainStickerPack {
|
||||||
presentControllerImpl?(StickerPackScreen(context: context, mode: .settings, mainStickerPack: mainStickerPack, stickerPacks: [mainStickerPack], parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { info, items, action in
|
presentControllerImpl?(StickerPackScreen(context: context, mode: .settings, mainStickerPack: mainStickerPack, stickerPacks: [mainStickerPack], parentNavigationController: controller?.navigationController as? NavigationController, actionPerformed: { actions in
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
var animateInAsReplacement = false
|
var animateInAsReplacement = false
|
||||||
if let navigationController = navigationControllerImpl?() {
|
if let navigationController = navigationControllerImpl?() {
|
||||||
@ -1278,6 +1278,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let (info, items, action) = actions.first {
|
||||||
switch action {
|
switch action {
|
||||||
case .add:
|
case .add:
|
||||||
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
navigationControllerImpl?()?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.StickerPackActionInfo_AddedTitle, text: presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in
|
||||||
@ -1304,6 +1305,7 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta
|
|||||||
return true
|
return true
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}), nil)
|
}), nil)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -192,7 +192,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
lockBackground.isUserInteractionEnabled = false
|
lockBackground.isUserInteractionEnabled = false
|
||||||
lockIconNode = ASImageNode()
|
lockIconNode = ASImageNode()
|
||||||
lockIconNode.displaysAsynchronously = false
|
lockIconNode.displaysAsynchronously = false
|
||||||
lockIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/Lock"), color: .white)
|
lockIconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white)
|
||||||
|
|
||||||
let lockTintView = UIView()
|
let lockTintView = UIView()
|
||||||
lockTintView.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.15)
|
lockTintView.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.15)
|
||||||
@ -321,8 +321,8 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let lockBackground = self.lockBackground, let lockTintView = self.lockTintView, let lockIconNode = self.lockIconNode {
|
if let lockBackground = self.lockBackground, let lockTintView = self.lockTintView, let lockIconNode = self.lockIconNode {
|
||||||
let lockSize = CGSize(width: 30.0, height: 30.0)
|
let lockSize = CGSize(width: 16.0, height: 16.0)
|
||||||
let lockBackgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((bounds.width - lockSize.width) / 2.0), y: bounds.height - lockSize.height - 6.0), size: lockSize)
|
let lockBackgroundFrame = CGRect(origin: CGPoint(x: bounds.width - lockSize.width, y: bounds.height - lockSize.height), size: lockSize)
|
||||||
lockBackground.frame = lockBackgroundFrame
|
lockBackground.frame = lockBackgroundFrame
|
||||||
lockBackground.layer.cornerRadius = lockSize.width / 2.0
|
lockBackground.layer.cornerRadius = lockSize.width / 2.0
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
@ -330,7 +330,8 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
|||||||
}
|
}
|
||||||
lockTintView.frame = CGRect(origin: CGPoint(), size: lockBackgroundFrame.size)
|
lockTintView.frame = CGRect(origin: CGPoint(), size: lockBackgroundFrame.size)
|
||||||
if let icon = lockIconNode.image {
|
if let icon = lockIconNode.image {
|
||||||
lockIconNode.frame = CGRect(origin: CGPoint(x: lockBackgroundFrame.minX + floorToScreenPixels((lockBackgroundFrame.width - icon.size.width) / 2.0), y: lockBackgroundFrame.minY + floorToScreenPixels((lockBackgroundFrame.height - icon.size.height) / 2.0)), size: icon.size)
|
let iconSize = CGSize(width: icon.size.width - 4.0, height: icon.size.height - 4.0)
|
||||||
|
lockIconNode.frame = CGRect(origin: CGPoint(x: lockBackgroundFrame.minX + floorToScreenPixels((lockBackgroundFrame.width - iconSize.width) / 2.0), y: lockBackgroundFrame.minY + floorToScreenPixels((lockBackgroundFrame.height - iconSize.height) / 2.0)), size: iconSize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -586,7 +586,10 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
strongSelf.controller?.present(shareController, in: .window(.root))
|
strongSelf.controller?.present(shareController, in: .window(.root))
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
items.append(.action(ContextMenuActionItem(text: strings.StickerPack_CopyLink, icon: { theme in
|
|
||||||
|
let copyTitle = self.currentStickerPacks.count > 1 ? strings.StickerPack_CopyLinks : strings.StickerPack_CopyLink
|
||||||
|
let copyText = self.currentStickerPacks.count > 1 ? strings.Conversation_LinksCopied : strings.Conversation_LinkCopied
|
||||||
|
items.append(.action(ContextMenuActionItem(text: copyTitle, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
|
||||||
}, action: { [weak self] _, f in
|
}, action: { [weak self] _, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
@ -595,7 +598,7 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
|
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.Conversation_LinkCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root))
|
strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: copyText), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root))
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
@ -629,14 +632,15 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
var installedPacks: [(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)] = []
|
||||||
for (info, items, isInstalled) in self.currentStickerPacks {
|
for (info, items, isInstalled) in self.currentStickerPacks {
|
||||||
if !isInstalled {
|
if !isInstalled {
|
||||||
|
installedPacks.append((info, items, .add))
|
||||||
let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start()
|
let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start()
|
||||||
// if dismissed {
|
|
||||||
// actionPerformed?(info, items, .add)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.controller?.actionPerformed?(installedPacks)
|
||||||
}
|
}
|
||||||
self.requestDismiss()
|
self.requestDismiss()
|
||||||
} else if let (info, items, installed) = self.currentStickerPack {
|
} else if let (info, items, installed) = self.currentStickerPack {
|
||||||
@ -657,13 +661,13 @@ private final class StickerPackContainer: ASDisplayNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dismissed {
|
if dismissed {
|
||||||
actionPerformed?(info, items, .remove(positionInList: positionInList))
|
actionPerformed?([(info, items, .remove(positionInList: positionInList))])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start()
|
let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start()
|
||||||
if dismissed {
|
if dismissed {
|
||||||
actionPerformed?(info, items, .add)
|
actionPerformed?([(info, items, .add)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1217,7 +1221,6 @@ private final class StickerPackScreenNode: ViewControllerTracingNode {
|
|||||||
super.didLoad()
|
super.didLoad()
|
||||||
|
|
||||||
self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimNodeTapGesture(_:))))
|
self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimNodeTapGesture(_:))))
|
||||||
self.containerContainingNode.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePresentationData(_ presentationData: PresentationData) {
|
func updatePresentationData(_ presentationData: PresentationData) {
|
||||||
@ -1235,11 +1238,7 @@ private final class StickerPackScreenNode: ViewControllerTracingNode {
|
|||||||
transition.updateFrame(node: self.containerContainingNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
transition.updateFrame(node: self.containerContainingNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||||
|
|
||||||
let expandProgress: CGFloat = 1.0
|
let expandProgress: CGFloat = 1.0
|
||||||
// if self.stickerPacks.count == 1 {
|
|
||||||
// expandProgress = 1.0
|
|
||||||
// } else {
|
|
||||||
// expandProgress = self.containers[self.selectedStickerPackIndex]?.expandProgress ?? 0.0
|
|
||||||
// }
|
|
||||||
let scaledInset: CGFloat = 12.0
|
let scaledInset: CGFloat = 12.0
|
||||||
let scaledDistance: CGFloat = 4.0
|
let scaledDistance: CGFloat = 4.0
|
||||||
let minScale = (layout.size.width - scaledInset * 2.0) / layout.size.width
|
let minScale = (layout.size.width - scaledInset * 2.0) / layout.size.width
|
||||||
@ -1247,7 +1246,6 @@ private final class StickerPackScreenNode: ViewControllerTracingNode {
|
|||||||
|
|
||||||
let containerVerticalOffset: CGFloat = (1.0 - expandProgress) * scaledInset * 2.0
|
let containerVerticalOffset: CGFloat = (1.0 - expandProgress) * scaledInset * 2.0
|
||||||
|
|
||||||
// for i in 0 ..< self.stickerPacks.count {
|
|
||||||
let i = 0
|
let i = 0
|
||||||
let indexOffset = i - self.selectedStickerPackIndex
|
let indexOffset = i - self.selectedStickerPackIndex
|
||||||
var scaledOffset: CGFloat = 0.0
|
var scaledOffset: CGFloat = 0.0
|
||||||
@ -1348,7 +1346,6 @@ private final class StickerPackScreenNode: ViewControllerTracingNode {
|
|||||||
self.containers.removeValue(forKey: i)
|
self.containers.removeValue(forKey: i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
if firstTime {
|
if firstTime {
|
||||||
if !self.containers.isEmpty {
|
if !self.containers.isEmpty {
|
||||||
@ -1512,7 +1509,7 @@ public final class StickerPackScreenImpl: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public var dismissed: (() -> Void)?
|
public var dismissed: (() -> Void)?
|
||||||
public var actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)?
|
public var actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)?
|
||||||
|
|
||||||
private let _ready = Promise<Bool>()
|
private let _ready = Promise<Bool>()
|
||||||
override public var ready: Promise<Bool> {
|
override public var ready: Promise<Bool> {
|
||||||
@ -1527,7 +1524,7 @@ public final class StickerPackScreenImpl: ViewController {
|
|||||||
let animationCache: AnimationCache
|
let animationCache: AnimationCache
|
||||||
let animationRenderer: MultiAnimationRenderer
|
let animationRenderer: MultiAnimationRenderer
|
||||||
|
|
||||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, stickerPacks: [StickerPackReference], selectedStickerPackIndex: Int = 0, parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? = nil) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, stickerPacks: [StickerPackReference], selectedStickerPackIndex: Int = 0, parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)? = nil) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
|
||||||
self.stickerPacks = stickerPacks
|
self.stickerPacks = stickerPacks
|
||||||
@ -1706,7 +1703,7 @@ public enum StickerPackScreenPerformedAction {
|
|||||||
case remove(positionInList: Int)
|
case remove(positionInList: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func StickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController {
|
public func StickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, mode: StickerPackPreviewControllerMode = .default, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], parentNavigationController: NavigationController? = nil, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)? = nil, actionPerformed: (([(StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction)]) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController {
|
||||||
//let stickerPacks = [mainStickerPack]
|
//let stickerPacks = [mainStickerPack]
|
||||||
let controller = StickerPackScreenImpl(context: context, stickerPacks: stickerPacks, selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0, parentNavigationController: parentNavigationController, sendSticker: sendSticker, actionPerformed: actionPerformed)
|
let controller = StickerPackScreenImpl(context: context, stickerPacks: stickerPacks, selectedStickerPackIndex: stickerPacks.firstIndex(of: mainStickerPack) ?? 0, parentNavigationController: parentNavigationController, sendSticker: sendSticker, actionPerformed: actionPerformed)
|
||||||
controller.dismissed = dismissed
|
controller.dismissed = dismissed
|
||||||
|
@ -1006,7 +1006,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
||||||
dict[1042605427] = { return Api.payments.BankCardData.parse_bankCardData($0) }
|
dict[1042605427] = { return Api.payments.BankCardData.parse_bankCardData($0) }
|
||||||
dict[-1362048039] = { return Api.payments.ExportedInvoice.parse_exportedInvoice($0) }
|
dict[-1362048039] = { return Api.payments.ExportedInvoice.parse_exportedInvoice($0) }
|
||||||
dict[1288001087] = { return Api.payments.PaymentForm.parse_paymentForm($0) }
|
dict[-1610250415] = { return Api.payments.PaymentForm.parse_paymentForm($0) }
|
||||||
dict[1891958275] = { return Api.payments.PaymentReceipt.parse_paymentReceipt($0) }
|
dict[1891958275] = { return Api.payments.PaymentReceipt.parse_paymentReceipt($0) }
|
||||||
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
|
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
|
||||||
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
|
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
|
||||||
|
@ -728,13 +728,13 @@ public extension Api.payments {
|
|||||||
}
|
}
|
||||||
public extension Api.payments {
|
public extension Api.payments {
|
||||||
enum PaymentForm: TypeConstructorDescription {
|
enum PaymentForm: TypeConstructorDescription {
|
||||||
case paymentForm(flags: Int32, formId: Int64, botId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, providerId: Int64, url: String, nativeProvider: String?, nativeParams: Api.DataJSON?, additionalMethods: [Api.PaymentFormMethod]?, savedInfo: Api.PaymentRequestedInfo?, savedCredentials: Api.PaymentSavedCredentials?, users: [Api.User])
|
case paymentForm(flags: Int32, formId: Int64, botId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, providerId: Int64, url: String, nativeProvider: String?, nativeParams: Api.DataJSON?, additionalMethods: [Api.PaymentFormMethod]?, savedInfo: Api.PaymentRequestedInfo?, savedCredentials: [Api.PaymentSavedCredentials]?, users: [Api.User])
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let additionalMethods, let savedInfo, let savedCredentials, let users):
|
case .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let additionalMethods, let savedInfo, let savedCredentials, let users):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(1288001087)
|
buffer.appendInt32(-1610250415)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt64(formId, buffer: buffer, boxed: false)
|
serializeInt64(formId, buffer: buffer, boxed: false)
|
||||||
@ -753,7 +753,11 @@ public extension Api.payments {
|
|||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
}}
|
}}
|
||||||
if Int(flags) & Int(1 << 0) != 0 {savedInfo!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 0) != 0 {savedInfo!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 1) != 0 {savedCredentials!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(savedCredentials!.count))
|
||||||
|
for item in savedCredentials! {
|
||||||
|
item.serialize(buffer, true)
|
||||||
|
}}
|
||||||
buffer.appendInt32(481674261)
|
buffer.appendInt32(481674261)
|
||||||
buffer.appendInt32(Int32(users.count))
|
buffer.appendInt32(Int32(users.count))
|
||||||
for item in users {
|
for item in users {
|
||||||
@ -807,9 +811,9 @@ public extension Api.payments {
|
|||||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||||
_13 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo
|
_13 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo
|
||||||
} }
|
} }
|
||||||
var _14: Api.PaymentSavedCredentials?
|
var _14: [Api.PaymentSavedCredentials]?
|
||||||
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
|
||||||
_14 = Api.parse(reader, signature: signature) as? Api.PaymentSavedCredentials
|
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PaymentSavedCredentials.self)
|
||||||
} }
|
} }
|
||||||
var _15: [Api.User]?
|
var _15: [Api.User]?
|
||||||
if let _ = reader.readInt32() {
|
if let _ = reader.readInt32() {
|
||||||
|
@ -64,7 +64,7 @@ private final class PendingUpdateMessageManagerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool) {
|
func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], disableUrlPreview: Bool) {
|
||||||
if let context = self.contexts[messageId] {
|
if let context = self.contexts[messageId] {
|
||||||
self.contexts.removeValue(forKey: messageId)
|
self.contexts.removeValue(forKey: messageId)
|
||||||
context.disposable.dispose()
|
context.disposable.dispose()
|
||||||
@ -163,7 +163,7 @@ public final class PendingUpdateMessageManager {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false) {
|
public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], disableUrlPreview: Bool = false) {
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
impl.add(messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview)
|
impl.add(messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview)
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,11 @@ public enum RequestEditMessageError {
|
|||||||
case invalidGrouping
|
case invalidGrouping
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
||||||
return requestEditMessage(postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
|
return requestEditMessage(postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestEditMessage(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool, scheduleTime: Int32?) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
func requestEditMessage(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], disableUrlPreview: Bool, scheduleTime: Int32?) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
||||||
return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: false)
|
return requestEditMessageInternal(postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime, forceReupload: false)
|
||||||
|> `catch` { error -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> in
|
|> `catch` { error -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> in
|
||||||
if case .invalidReference = error {
|
if case .invalidReference = error {
|
||||||
@ -50,7 +50,7 @@ func requestEditMessage(postbox: Postbox, network: Network, stateManager: Accoun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func requestEditMessageInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool, scheduleTime: Int32?, forceReupload: Bool) -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> {
|
private func requestEditMessageInternal(postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], disableUrlPreview: Bool, scheduleTime: Int32?, forceReupload: Bool) -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> {
|
||||||
let uploadedMedia: Signal<PendingMessageUploadedContentResult?, NoError>
|
let uploadedMedia: Signal<PendingMessageUploadedContentResult?, NoError>
|
||||||
switch media {
|
switch media {
|
||||||
case .keep:
|
case .keep:
|
||||||
|
@ -85,7 +85,7 @@ public extension TelegramEngine {
|
|||||||
return _internal_clearAuthorHistory(account: self.account, peerId: peerId, memberId: memberId)
|
return _internal_clearAuthorHistory(account: self.account, peerId: peerId, memberId: memberId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: TelegramMediaFile], disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], disableUrlPreview: Bool = false, scheduleTime: Int32? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
|
||||||
return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
|
return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, disableUrlPreview: disableUrlPreview, scheduleTime: scheduleTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ public struct BotPaymentForm : Equatable {
|
|||||||
public let url: String
|
public let url: String
|
||||||
public let nativeProvider: BotPaymentNativeProvider?
|
public let nativeProvider: BotPaymentNativeProvider?
|
||||||
public let savedInfo: BotPaymentRequestedInfo?
|
public let savedInfo: BotPaymentRequestedInfo?
|
||||||
public let savedCredentials: BotPaymentSavedCredentials?
|
public let savedCredentials: [BotPaymentSavedCredentials]
|
||||||
public let additionalPaymentMethods: [BotPaymentMethod]
|
public let additionalPaymentMethods: [BotPaymentMethod]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,13 +304,12 @@ func _internal_fetchBotPaymentForm(postbox: Postbox, network: Network, source: B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let parsedSavedInfo = savedInfo.flatMap(BotPaymentRequestedInfo.init)
|
let parsedSavedInfo = savedInfo.flatMap(BotPaymentRequestedInfo.init)
|
||||||
var parsedSavedCredentials: BotPaymentSavedCredentials?
|
let parsedSavedCredentials = savedCredentials?.map({ savedCredentials -> BotPaymentSavedCredentials in
|
||||||
if let savedCredentials = savedCredentials {
|
|
||||||
switch savedCredentials {
|
switch savedCredentials {
|
||||||
case let .paymentSavedCredentialsCard(id, title):
|
case let .paymentSavedCredentialsCard(id, title):
|
||||||
parsedSavedCredentials = .card(id: id, title: title)
|
return .card(id: id, title: title)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}) ?? []
|
||||||
|
|
||||||
let additionalPaymentMethods = additionalMethods?.map({ BotPaymentMethod(apiPaymentFormMethod: $0) }) ?? []
|
let additionalPaymentMethods = additionalMethods?.map({ BotPaymentMethod(apiPaymentFormMethod: $0) }) ?? []
|
||||||
return BotPaymentForm(id: id, canSaveCredentials: (flags & (1 << 2)) != 0, passwordMissing: (flags & (1 << 3)) != 0, invoice: parsedInvoice, paymentBotId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), providerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(providerId)), url: url, nativeProvider: parsedNativeProvider, savedInfo: parsedSavedInfo, savedCredentials: parsedSavedCredentials, additionalPaymentMethods: additionalPaymentMethods)
|
return BotPaymentForm(id: id, canSaveCredentials: (flags & (1 << 2)) != 0, passwordMissing: (flags & (1 << 3)) != 0, invoice: parsedInvoice, paymentBotId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), providerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(providerId)), url: url, nativeProvider: parsedNativeProvider, savedInfo: parsedSavedInfo, savedCredentials: parsedSavedCredentials, additionalPaymentMethods: additionalPaymentMethods)
|
||||||
|
@ -1093,7 +1093,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
var disableTransitionAnimations = false
|
var disableTransitionAnimations = false
|
||||||
var actionsSignal: Signal<ContextController.Items, NoError> = .single(actions)
|
var actionsSignal: Signal<ContextController.Items, NoError> = .single(actions)
|
||||||
if actions.tip == nil, let entitiesAttribute = message.textEntitiesAttribute {
|
if let entitiesAttribute = message.textEntitiesAttribute {
|
||||||
var emojiFileIds: [Int64] = []
|
var emojiFileIds: [Int64] = []
|
||||||
for entity in entitiesAttribute.entities {
|
for entity in entitiesAttribute.entities {
|
||||||
if case let .CustomEmoji(_, fileId) = entity.type {
|
if case let .CustomEmoji(_, fileId) = entity.type {
|
||||||
@ -1128,7 +1128,36 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.chatDisplayNode.dismissTextInput()
|
strongSelf.chatDisplayNode.dismissTextInput()
|
||||||
let controller = StickerPackScreen(context: context, updatedPresentationData: strongSelf.updatedPresentationData, mainStickerPack: packReference, stickerPacks: Array(packReferences), parentNavigationController: strongSelf.effectiveNavigationController)
|
|
||||||
|
let presentationData = strongSelf.presentationData
|
||||||
|
let controller = StickerPackScreen(context: context, updatedPresentationData: strongSelf.updatedPresentationData, mainStickerPack: packReference, stickerPacks: Array(packReferences), parentNavigationController: strongSelf.effectiveNavigationController, actionPerformed: { [weak self] actions in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if actions.count > 1, let first = actions.first {
|
||||||
|
if case .add = first.2 {
|
||||||
|
strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), undo: false, info: first.0, topItem: first.1.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in
|
||||||
|
return true
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} else if let (info, items, action) = actions.first {
|
||||||
|
let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks
|
||||||
|
|
||||||
|
switch action {
|
||||||
|
case .add:
|
||||||
|
strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedTitle : presentationData.strings.StickerPackActionInfo_AddedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_AddedText(info.title).string : presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in
|
||||||
|
return true
|
||||||
|
}))
|
||||||
|
case let .remove(positionInList):
|
||||||
|
strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedTitle : presentationData.strings.StickerPackActionInfo_RemovedTitle, text: isEmoji ? presentationData.strings.EmojiPackActionInfo_RemovedText(info.title).string : presentationData.strings.StickerPackActionInfo_RemovedText(info.title).string, undo: true, info: info, topItem: items.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { action in
|
||||||
|
if case .undo = action {
|
||||||
|
let _ = context.engine.stickers.addStickerPackInteractively(info: info, items: items, positionInList: positionInList).start()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
strongSelf.present(controller, in: .window(.root))
|
strongSelf.present(controller, in: .window(.root))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9412,7 +9441,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
} else {
|
} else {
|
||||||
canSendMedia = true
|
canSendMedia = true
|
||||||
}
|
}
|
||||||
if canSendMedia {
|
if canSendMedia && self.presentationInterfaceState.voiceMessagesAvailable {
|
||||||
let _ = (ApplicationSpecificNotice.getChatMediaMediaRecordingTips(accountManager: self.context.sharedContext.accountManager)
|
let _ = (ApplicationSpecificNotice.getChatMediaMediaRecordingTips(accountManager: self.context.sharedContext.accountManager)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] counter in
|
|> deliverOnMainQueue).start(next: { [weak self] counter in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
@ -16304,6 +16333,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func hintPlayNextOutgoingGift() {
|
||||||
|
self.controllerInteraction?.playNextOutgoingGift = true
|
||||||
|
}
|
||||||
|
|
||||||
private var effectiveNavigationController: NavigationController? {
|
private var effectiveNavigationController: NavigationController? {
|
||||||
if let navigationController = self.navigationController as? NavigationController {
|
if let navigationController = self.navigationController as? NavigationController {
|
||||||
return navigationController
|
return navigationController
|
||||||
|
@ -160,6 +160,7 @@ public final class ChatControllerInteraction {
|
|||||||
var currentMessageWithLoadingReplyThread: MessageId?
|
var currentMessageWithLoadingReplyThread: MessageId?
|
||||||
var updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
var updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
||||||
let presentationContext: ChatPresentationContext
|
let presentationContext: ChatPresentationContext
|
||||||
|
var playNextOutgoingGift: Bool = false
|
||||||
|
|
||||||
init(
|
init(
|
||||||
openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool,
|
openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool,
|
||||||
|
@ -214,6 +214,9 @@ class ChatMessageBubbleContentNode: ASDisplayNode {
|
|||||||
func applyAbsoluteOffsetSpring(value: CGFloat, duration: Double, damping: CGFloat) {
|
func applyAbsoluteOffsetSpring(value: CGFloat, duration: Double, damping: CGFloat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unreadMessageRangeUpdated() {
|
||||||
|
}
|
||||||
|
|
||||||
func reactionTargetView(value: String) -> UIView? {
|
func reactionTargetView(value: String) -> UIView? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -3975,6 +3975,12 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func unreadMessageRangeUpdated() {
|
||||||
|
for contentNode in self.contentNodes {
|
||||||
|
contentNode.unreadMessageRangeUpdated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func animateQuizInvalidOptionSelected() {
|
func animateQuizInvalidOptionSelected() {
|
||||||
if let supernode = self.supernode, let subnodes = supernode.subnodes {
|
if let supernode = self.supernode, let subnodes = supernode.subnodes {
|
||||||
for i in 0 ..< subnodes.count {
|
for i in 0 ..< subnodes.count {
|
||||||
|
@ -41,8 +41,6 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
private var absoluteRect: (CGRect, CGSize)?
|
private var absoluteRect: (CGRect, CGSize)?
|
||||||
|
|
||||||
private var isPlaying: Bool = false
|
private var isPlaying: Bool = false
|
||||||
private var wasPending: Bool = false
|
|
||||||
private var didChangeFromPendingToSent: Bool = false
|
|
||||||
|
|
||||||
override var visibility: ListViewItemNodeVisibility {
|
override var visibility: ListViewItemNodeVisibility {
|
||||||
didSet {
|
didSet {
|
||||||
@ -165,9 +163,9 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(item.presentationData.strings.Notification_PremiumGift_Months(months)).string
|
duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(item.presentationData.strings.Notification_PremiumGift_Months(months)).string
|
||||||
switch months {
|
switch months {
|
||||||
case 12:
|
case 12:
|
||||||
animationName = "Gift2"
|
animationName = "Gift12"
|
||||||
case 6:
|
case 6:
|
||||||
animationName = "Gift1"
|
animationName = "Gift6"
|
||||||
case 3:
|
case 3:
|
||||||
animationName = "Gift3"
|
animationName = "Gift3"
|
||||||
default:
|
default:
|
||||||
@ -228,12 +226,6 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
strongSelf.item = item
|
strongSelf.item = item
|
||||||
|
|
||||||
if item.message.id.namespace == Namespaces.Message.Local || item.message.id.namespace == Namespaces.Message.ScheduledLocal {
|
|
||||||
strongSelf.wasPending = true
|
|
||||||
}
|
|
||||||
if strongSelf.wasPending && (item.message.id.namespace != Namespaces.Message.Local && item.message.id.namespace != Namespaces.Message.ScheduledLocal) {
|
|
||||||
strongSelf.didChangeFromPendingToSent = true
|
|
||||||
}
|
|
||||||
strongSelf.updateVisibility()
|
strongSelf.updateVisibility()
|
||||||
|
|
||||||
strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper)
|
strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper)
|
||||||
@ -416,6 +408,10 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func unreadMessageRangeUpdated() {
|
||||||
|
self.updateVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
private func updateVisibility() {
|
private func updateVisibility() {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return
|
return
|
||||||
@ -430,12 +426,16 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
if isPlaying {
|
if isPlaying {
|
||||||
var alreadySeen = true
|
var alreadySeen = true
|
||||||
|
|
||||||
|
if item.message.flags.contains(.Incoming) {
|
||||||
if let unreadRange = item.controllerInteraction.unreadMessageRange[UnreadMessageRangeKey(peerId: item.message.id.peerId, namespace: item.message.id.namespace)] {
|
if let unreadRange = item.controllerInteraction.unreadMessageRange[UnreadMessageRangeKey(peerId: item.message.id.peerId, namespace: item.message.id.namespace)] {
|
||||||
if unreadRange.contains(item.message.id.id) {
|
if unreadRange.contains(item.message.id.id) {
|
||||||
if !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) {
|
|
||||||
alreadySeen = false
|
alreadySeen = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if item.controllerInteraction.playNextOutgoingGift && !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) {
|
||||||
|
alreadySeen = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) {
|
if !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) {
|
||||||
@ -444,8 +444,10 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !alreadySeen {
|
if !alreadySeen {
|
||||||
|
Queue.mainQueue().after(1.0) {
|
||||||
item.controllerInteraction.animateDiceSuccess(false, true)
|
item.controllerInteraction.animateDiceSuccess(false, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
@ -363,7 +363,7 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto
|
|||||||
let colorKeys = ["__allcolors__"]
|
let colorKeys = ["__allcolors__"]
|
||||||
var colors: [String: UIColor] = [:]
|
var colors: [String: UIColor] = [:]
|
||||||
for colorKey in colorKeys {
|
for colorKey in colorKeys {
|
||||||
colors[colorKey] = self.theme.chat.inputPanel.panelControlColor
|
colors[colorKey] = self.theme.chat.inputPanel.panelControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = animationView.update(
|
let _ = animationView.update(
|
||||||
@ -497,8 +497,11 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto
|
|||||||
micDecoration.isHidden = false
|
micDecoration.isHidden = false
|
||||||
micDecoration.startAnimating()
|
micDecoration.startAnimating()
|
||||||
|
|
||||||
self.animationView.view?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
let transition = ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut)
|
||||||
self.animationView.view?.layer.animateScale(from: 1.0, to: 0.3, duration: 0.15, removeOnCompletion: false)
|
if let layer = self.animationView.view?.layer {
|
||||||
|
transition.updateAlpha(layer: layer, alpha: 0.0)
|
||||||
|
transition.updateTransformScale(layer: layer, scale: 0.3)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func animateOut(_ toSmallSize: Bool) {
|
override func animateOut(_ toSmallSize: Bool) {
|
||||||
@ -510,8 +513,11 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto
|
|||||||
micDecoration.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.03, delay: 0.15, removeOnCompletion: false)
|
micDecoration.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.03, delay: 0.15, removeOnCompletion: false)
|
||||||
} else {
|
} else {
|
||||||
micDecoration.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false)
|
micDecoration.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false)
|
||||||
self.animationView.view?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, removeOnCompletion: false)
|
let transition = ContainedViewLayoutTransition.animated(duration: 0.15, curve: .easeInOut)
|
||||||
self.animationView.view?.layer.animateScale(from: 0.3, to: 1.0, duration: 0.15, removeOnCompletion: false)
|
if let layer = self.animationView.view?.layer {
|
||||||
|
transition.updateAlpha(layer: layer, alpha: 1.0)
|
||||||
|
transition.updateTransformScale(layer: layer, scale: 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,10 +78,18 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
params.navigationController?.pushViewController(controller)
|
params.navigationController?.pushViewController(controller)
|
||||||
return true
|
return true
|
||||||
case let .stickerPack(reference):
|
case let .stickerPack(reference):
|
||||||
let controller = StickerPackScreen(context: params.context, updatedPresentationData: params.updatedPresentationData, mainStickerPack: reference, stickerPacks: [reference], parentNavigationController: params.navigationController, sendSticker: params.sendSticker, actionPerformed: { info, items, action in
|
let controller = StickerPackScreen(context: params.context, updatedPresentationData: params.updatedPresentationData, mainStickerPack: reference, stickerPacks: [reference], parentNavigationController: params.navigationController, sendSticker: params.sendSticker, actionPerformed: { actions in
|
||||||
|
let presentationData = params.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
|
if actions.count > 1, let first = actions.first {
|
||||||
|
if case .add = first.2 {
|
||||||
|
params.navigationController?.presentOverlay(controller: UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), undo: false, info: first.0, topItem: first.1.first, context: params.context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in
|
||||||
|
return true
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} else if let (info, items, action) = actions.first {
|
||||||
let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks
|
let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks
|
||||||
|
|
||||||
let presentationData = params.context.sharedContext.currentPresentationData.with { $0 }
|
|
||||||
var animateInAsReplacement = false
|
var animateInAsReplacement = false
|
||||||
if let navigationController = params.navigationController {
|
if let navigationController = params.navigationController {
|
||||||
for controller in navigationController.overlayControllers {
|
for controller in navigationController.overlayControllers {
|
||||||
@ -104,6 +112,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
return true
|
return true
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
params.dismissInput()
|
params.dismissInput()
|
||||||
params.present(controller, nil)
|
params.present(controller, nil)
|
||||||
|
@ -166,7 +166,14 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
|||||||
case let .stickerPack(name, _):
|
case let .stickerPack(name, _):
|
||||||
dismissInput()
|
dismissInput()
|
||||||
|
|
||||||
let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker, actionPerformed: { info, items, action in
|
let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker, actionPerformed: { actions in
|
||||||
|
if actions.count > 1, let first = actions.first {
|
||||||
|
if case .add = first.2 {
|
||||||
|
present(UndoOverlayController(presentationData: presentationData, content: .stickersModified(title: presentationData.strings.EmojiPackActionInfo_AddedTitle, text: presentationData.strings.EmojiPackActionInfo_MultipleAddedText(Int32(actions.count)), undo: false, info: first.0, topItem: first.1.first, context: context), elevatedLayout: true, animateInAsReplacement: false, action: { _ in
|
||||||
|
return true
|
||||||
|
}), nil)
|
||||||
|
}
|
||||||
|
} else if let (info, items, action) = actions.first {
|
||||||
let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks
|
let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks
|
||||||
|
|
||||||
switch action {
|
switch action {
|
||||||
@ -182,6 +189,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
|||||||
return true
|
return true
|
||||||
}), nil)
|
}), nil)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
present(controller, nil)
|
present(controller, nil)
|
||||||
case let .instantView(webpage, anchor):
|
case let .instantView(webpage, anchor):
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "8.8.3",
|
"app": "8.9",
|
||||||
"bazel": "5.1.0",
|
"bazel": "5.1.0",
|
||||||
"xcode": "13.4.1"
|
"xcode": "13.4.1"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user