Files
GLEGram-iOS/submodules/TelegramUI/Sources/Chat/ChatControllerPaidMessage.swift
T
Leeksov 4647310322 GLEGram 12.5 — Initial public release
Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
2026-04-06 09:48:12 +03:00

141 lines
7.2 KiB
Swift

import Foundation
import UIKit
import SwiftSignalKit
import Postbox
import TelegramCore
import AsyncDisplayKit
import Display
import ContextUI
import UndoUI
import AccountContext
import ChatControllerInteraction
import AnimatedTextComponent
import ChatMessagePaymentAlertController
import TelegramPresentationData
import TelegramNotices
extension ChatControllerImpl {
func presentPaidMessageAlertIfNeeded(count: Int32 = 1, forceDark: Bool = false, alwaysAsk: Bool = false, completion: @escaping (Bool) -> Void) {
guard let peer = self.presentationInterfaceState.renderedPeer?.peer.flatMap(EnginePeer.init) else {
completion(false)
return
}
guard let renderedPeer = self.presentationInterfaceState.renderedPeer.flatMap(EngineRenderedPeer.init) else {
return
}
if let sendPaidMessageStars = self.presentationInterfaceState.sendPaidMessageStars, self.presentationInterfaceState.interfaceState.editMessage == nil {
let totalAmount = sendPaidMessageStars.value * Int64(count)
let _ = (ApplicationSpecificNotice.dismissedPaidMessageWarningNamespace(accountManager: self.context.sharedContext.accountManager, peerId: peer.id)
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] dismissedAmount in
guard let self, let starsContext = self.context.starsContext else {
return
}
if !alwaysAsk, let dismissedAmount, dismissedAmount == sendPaidMessageStars.value, let currentState = starsContext.currentState, currentState.balance.value > totalAmount {
if count < 3 && totalAmount < 100 {
completion(false)
} else {
completion(true)
self.displayPaidMessageUndo(count: count, amount: sendPaidMessageStars)
}
} else {
var presentationData = self.presentationData
if forceDark {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
var peer = peer
var renderedPeer = renderedPeer
if let peerDiscussionId = self.presentationInterfaceState.peerDiscussionId, let channel = self.contentData?.state.peerView?.peers[peerDiscussionId] {
peer = EnginePeer(channel)
renderedPeer = EngineRenderedPeer(peer: peer)
}
let controller = chatMessagePaymentAlertController(
context: self.context,
presentationData: presentationData,
updatedPresentationData: nil,
peers: [renderedPeer],
count: count,
amount: sendPaidMessageStars,
totalAmount: nil,
hasCheck: !alwaysAsk,
navigationController: self.navigationController as? NavigationController,
completion: { [weak self] dontAskAgain in
guard let self else {
return
}
if dontAskAgain {
let _ = ApplicationSpecificNotice.setDismissedPaidMessageWarningNamespace(accountManager: self.context.sharedContext.accountManager, peerId: peer.id, amount: sendPaidMessageStars.value).start()
}
if let currentState = starsContext.currentState, currentState.balance.value < totalAmount {
let _ = (self.context.engine.payments.starsTopUpOptions()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { [weak self] options in
guard let self else {
return
}
let controller = self.context.sharedContext.makeStarsPurchaseScreen(context: self.context, starsContext: starsContext, options: options, purpose: .sendMessage(peerId: peer.id, requiredStars: totalAmount), targetPeerId: nil, customTheme: nil, completion: { stars in
starsContext.add(balance: StarsAmount(value: stars, nanos: 0))
let _ = (starsContext.onUpdate
|> deliverOnMainQueue).start(next: {
completion(false)
})
})
self.push(controller)
})
} else {
completion(false)
}
}
)
self.present(controller, in: .window(.root))
}
})
} else {
completion(false)
}
}
func displayPaidMessageUndo(count: Int32, amount: StarsAmount) {
guard let peerId = self.chatLocation.peerId else {
return
}
if let current = self.currentPaidMessageUndoController {
self.currentPaidMessageUndoController = nil
current.dismiss()
self.context.engine.messages.forceSendPostponedPaidMessage(peerId: peerId)
}
let title = self.presentationData.strings.Chat_PaidMessage_Sent_Title(count)
let text = self.presentationData.strings.Chat_PaidMessage_Sent_Text(self.presentationData.strings.Chat_PaidMessage_Sent_Text_Stars(Int32(clamping: amount.value * Int64(count)))).string
let textItems: [AnimatedTextComponent.Item] = [
AnimatedTextComponent.Item(id: 0, content: .text(text))
]
let controller = UndoOverlayController(presentationData: self.presentationData, content: .starsSent(context: self.context, title: title, text: textItems, hasUndo: true), elevatedLayout: false, position: .top, action: { [weak self] action in
guard let self else {
return false
}
if case .undo = action {
var messageIds: [MessageId] = []
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemNodeProtocol {
for message in itemNode.messages() {
if message.id.namespace == Namespaces.Message.Local {
messageIds.append(message.id)
}
}
}
}
let _ = self.context.engine.messages.deleteMessagesInteractively(messageIds: messageIds, type: .forLocalPeer).startStandalone()
}
return false
})
self.currentPaidMessageUndoController = controller
self.present(controller, in: .current)
}
}