Various improvements

This commit is contained in:
Ilya Laktyushin
2025-02-22 19:17:36 +04:00
parent eecb2ef5c0
commit 8d7f9bf372
122 changed files with 3454 additions and 1121 deletions

View File

@@ -89,4 +89,169 @@ func _internal_updateChannelPaidMessagesStars(account: Account, peerId: PeerId,
|> switchToLatest
}
public final class PostponeSendPaidMessageAction: PendingMessageActionData {
public let randomId: Int64
public init(randomId: Int64) {
self.randomId = randomId
}
public init(decoder: PostboxDecoder) {
self.randomId = decoder.decodeInt64ForKey("id", orElse: 0)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt64(self.randomId, forKey: "id")
}
public func isEqual(to: PendingMessageActionData) -> Bool {
if let other = to as? PostponeSendPaidMessageAction {
if self.randomId != other.randomId {
return false
}
return true
} else {
return false
}
}
}
private final class ManagedApplyPendingPaidMessageActionsHelper {
var operationDisposables: [MessageId: (PendingMessageActionData, Disposable)] = [:]
func update(entries: [PendingMessageActionsEntry]) -> (disposeOperations: [Disposable], beginOperations: [(PendingMessageActionsEntry, MetaDisposable)]) {
var disposeOperations: [Disposable] = []
var beginOperations: [(PendingMessageActionsEntry, MetaDisposable)] = []
var hasRunningOperationForPeerId = Set<PeerId>()
var validIds = Set<MessageId>()
for entry in entries {
if let current = self.operationDisposables[entry.id], !current.0.isEqual(to: entry.action) {
self.operationDisposables.removeValue(forKey: entry.id)
disposeOperations.append(current.1)
}
if !hasRunningOperationForPeerId.contains(entry.id.peerId) {
hasRunningOperationForPeerId.insert(entry.id.peerId)
validIds.insert(entry.id)
let disposable = MetaDisposable()
beginOperations.append((entry, disposable))
self.operationDisposables[entry.id] = (entry.action, disposable)
}
}
var removeMergedIds: [MessageId] = []
for (id, actionAndDisposable) in self.operationDisposables {
if !validIds.contains(id) {
removeMergedIds.append(id)
disposeOperations.append(actionAndDisposable.1)
}
}
for id in removeMergedIds {
self.operationDisposables.removeValue(forKey: id)
}
return (disposeOperations, beginOperations)
}
func reset() -> [Disposable] {
let disposables = Array(self.operationDisposables.values.map(\.1))
self.operationDisposables.removeAll()
return disposables
}
}
private func withTakenStarsAction(postbox: Postbox, type: PendingMessageActionType, id: MessageId, _ f: @escaping (Transaction, PendingMessageActionsEntry?) -> Signal<Never, NoError>) -> Signal<Never, NoError> {
return postbox.transaction { transaction -> Signal<Never, NoError> in
var result: PendingMessageActionsEntry?
if let action = transaction.getPendingMessageAction(type: type, id: id) as? PostponeSendPaidMessageAction {
result = PendingMessageActionsEntry(id: id, action: action)
}
return f(transaction, result)
}
|> switchToLatest
}
private func sendPostponedPaidMessage(transaction: Transaction, postbox: Postbox, network: Network, stateManager: AccountStateManager, id: MessageId) -> Signal<Never, NoError> {
stateManager.commitSendPendingPaidMessage(messageId: id)
return postbox.transaction { transaction -> Void in
transaction.setPendingMessageAction(type: .sendPostponedPaidMessage, id: id, action: nil)
}
|> ignoreValues
}
func managedApplyPendingPaidMessageActions(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
return Signal { _ in
let helper = Atomic<ManagedApplyPendingPaidMessageActionsHelper>(value: ManagedApplyPendingPaidMessageActionsHelper())
let actionsKey = PostboxViewKey.pendingMessageActions(type: .sendPostponedPaidMessage)
let disposable = postbox.combinedView(keys: [actionsKey]).start(next: { view in
var entries: [PendingMessageActionsEntry] = []
if let v = view.views[actionsKey] as? PendingMessageActionsView {
entries = v.entries
}
let (disposeOperations, beginOperations) = helper.with { helper -> (disposeOperations: [Disposable], beginOperations: [(PendingMessageActionsEntry, MetaDisposable)]) in
return helper.update(entries: entries)
}
for disposable in disposeOperations {
disposable.dispose()
}
for (entry, disposable) in beginOperations {
let signal = withTakenStarsAction(postbox: postbox, type: .sendPostponedPaidMessage, id: entry.id, { transaction, entry -> Signal<Never, NoError> in
if let entry = entry {
if let _ = entry.action as? PostponeSendPaidMessageAction {
let triggerSignal: Signal<Void, NoError> = stateManager.forceSendPendingPaidMessage
|> filter {
$0 == entry.id.peerId
}
|> map { _ -> Void in
return Void()
}
|> take(1)
|> timeout(5.0, queue: .mainQueue(), alternate: .single(Void()))
return triggerSignal
|> mapToSignal { _ -> Signal<Never, NoError> in
return sendPostponedPaidMessage(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, id: entry.id)
}
} else {
assertionFailure()
}
}
return .complete()
})
|> then(
postbox.transaction { transaction -> Void in
transaction.setPendingMessageAction(type: .sendPostponedPaidMessage, id: entry.id, action: nil)
}
|> ignoreValues
)
disposable.set(signal.start())
}
})
return ActionDisposable {
let disposables = helper.with { helper -> [Disposable] in
return helper.reset()
}
for disposable in disposables {
disposable.dispose()
}
disposable.dispose()
}
}
}
func _internal_forceSendPostponedPaidMessage(account: Account, peerId: PeerId) -> Signal<Never, NoError> {
account.stateManager.forceSendPendingPaidMessage(peerId: peerId)
return .complete()
}