Thread draft synchronization

This commit is contained in:
Ali 2022-10-16 17:06:30 +04:00
parent 8b84be981f
commit 7d62cee9f5
4 changed files with 61 additions and 16 deletions

View File

@ -93,7 +93,7 @@ func managedSynchronizeChatInputStateOperations(postbox: Postbox, network: Netwo
let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal<Void, NoError> in let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal<Void, NoError> in
if let entry = entry { if let entry = entry {
if let operation = entry.contents as? SynchronizeChatInputStateOperation { if let operation = entry.contents as? SynchronizeChatInputStateOperation {
return synchronizeChatInputState(transaction: transaction, postbox: postbox, network: network, peerId: entry.peerId, operation: operation) return synchronizeChatInputState(transaction: transaction, postbox: postbox, network: network, peerId: entry.peerId, threadId: operation.threadId, operation: operation)
} else { } else {
assertionFailure() assertionFailure()
} }
@ -125,9 +125,16 @@ func managedSynchronizeChatInputStateOperations(postbox: Postbox, network: Netwo
} }
} }
private func synchronizeChatInputState(transaction: Transaction, postbox: Postbox, network: Network, peerId: PeerId, operation: SynchronizeChatInputStateOperation) -> Signal<Void, NoError> { private func synchronizeChatInputState(transaction: Transaction, postbox: Postbox, network: Network, peerId: PeerId, threadId: Int64?, operation: SynchronizeChatInputStateOperation) -> Signal<Void, NoError> {
var inputState: SynchronizeableChatInputState? var inputState: SynchronizeableChatInputState?
if let peerChatInterfaceState = transaction.getPeerChatInterfaceState(peerId), let data = peerChatInterfaceState.data { let peerChatInterfaceState: StoredPeerChatInterfaceState?
if let threadId = threadId {
peerChatInterfaceState = transaction.getPeerChatThreadInterfaceState(peerId, threadId: threadId)
} else {
peerChatInterfaceState = transaction.getPeerChatInterfaceState(peerId)
}
if let peerChatInterfaceState = peerChatInterfaceState, let data = peerChatInterfaceState.data {
inputState = (try? AdaptedPostboxDecoder().decode(InternalChatInterfaceState.self, from: data))?.synchronizeableInputState inputState = (try? AdaptedPostboxDecoder().decode(InternalChatInterfaceState.self, from: data))?.synchronizeableInputState
} }
@ -141,7 +148,12 @@ private func synchronizeChatInputState(transaction: Transaction, postbox: Postbo
flags |= (1 << 3) flags |= (1 << 3)
} }
} }
return network.request(Api.functions.messages.saveDraft(flags: flags, replyToMsgId: inputState?.replyToMessageId?.id, topMsgId: nil, peer: inputPeer, message: inputState?.text ?? "", entities: apiEntitiesFromMessageTextEntities(inputState?.entities ?? [], associatedPeers: SimpleDictionary()))) var topMsgId: Int32?
if let threadId = threadId {
flags |= (1 << 2)
topMsgId = Int32(clamping: threadId)
}
return network.request(Api.functions.messages.saveDraft(flags: flags, replyToMsgId: inputState?.replyToMessageId?.id, topMsgId: topMsgId, peer: inputPeer, message: inputState?.text ?? "", entities: apiEntitiesFromMessageTextEntities(inputState?.entities ?? [], associatedPeers: SimpleDictionary())))
|> delay(2.0, queue: Queue.concurrentDefaultQueue()) |> delay(2.0, queue: Queue.concurrentDefaultQueue())
|> `catch` { _ -> Signal<Api.Bool, NoError> in |> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse) return .single(.boolFalse)

View File

@ -1,27 +1,41 @@
import Foundation import Foundation
import Postbox import Postbox
func addSynchronizeChatInputStateOperation(transaction: Transaction, peerId: PeerId) { func addSynchronizeChatInputStateOperation(transaction: Transaction, peerId: PeerId, threadId: Int64?) {
var updateLocalIndex: Int32? var removeLocalIndices: [Int32] = []
let tag: PeerOperationLogTag = OperationLogTags.SynchronizeChatInputStates let tag: PeerOperationLogTag = OperationLogTags.SynchronizeChatInputStates
var previousOperation: SynchronizeChatInputStateOperation? var previousOperation: SynchronizeChatInputStateOperation?
transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in transaction.operationLogEnumerateEntries(peerId: peerId, tag: tag, { entry in
updateLocalIndex = entry.tagLocalIndex
if let operation = entry.contents as? SynchronizeChatInputStateOperation { if let operation = entry.contents as? SynchronizeChatInputStateOperation {
previousOperation = operation if operation.threadId == threadId {
previousOperation = operation
removeLocalIndices.append(entry.tagLocalIndex)
return false
}
} else {
removeLocalIndices.append(entry.tagLocalIndex)
} }
return false return true
}) })
var previousState: SynchronizeableChatInputState? var previousState: SynchronizeableChatInputState?
if let previousOperation = previousOperation { if let previousOperation = previousOperation {
previousState = previousOperation.previousState previousState = previousOperation.previousState
} else if let peerChatInterfaceState = transaction.getPeerChatInterfaceState(peerId), let data = peerChatInterfaceState.data { } else {
previousState = (try? AdaptedPostboxDecoder().decode(InternalChatInterfaceState.self, from: data))?.synchronizeableInputState let peerChatInterfaceState: StoredPeerChatInterfaceState?
if let threadId = threadId {
peerChatInterfaceState = transaction.getPeerChatThreadInterfaceState(peerId, threadId: threadId)
} else {
peerChatInterfaceState = transaction.getPeerChatInterfaceState(peerId)
}
if let peerChatInterfaceState = peerChatInterfaceState, let data = peerChatInterfaceState.data {
previousState = (try? AdaptedPostboxDecoder().decode(InternalChatInterfaceState.self, from: data))?.synchronizeableInputState
}
} }
let operationContents = SynchronizeChatInputStateOperation(previousState: previousState) let operationContents = SynchronizeChatInputStateOperation(previousState: previousState, threadId: threadId)
if let updateLocalIndex = updateLocalIndex { for index in removeLocalIndices {
let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: updateLocalIndex) let _ = transaction.operationLogRemoveEntry(peerId: peerId, tag: tag, tagLocalIndex: index)
} }
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: operationContents) transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: operationContents)
} }

View File

@ -2,13 +2,16 @@ import Postbox
public final class SynchronizeChatInputStateOperation: PostboxCoding { public final class SynchronizeChatInputStateOperation: PostboxCoding {
public let previousState: SynchronizeableChatInputState? public let previousState: SynchronizeableChatInputState?
public let threadId: Int64?
public init(previousState: SynchronizeableChatInputState?) { public init(previousState: SynchronizeableChatInputState?, threadId: Int64?) {
self.previousState = previousState self.previousState = previousState
self.threadId = threadId
} }
public init(decoder: PostboxDecoder) { public init(decoder: PostboxDecoder) {
self.previousState = decoder.decode(SynchronizeableChatInputState.self, forKey: "p") self.previousState = decoder.decode(SynchronizeableChatInputState.self, forKey: "p")
self.threadId = decoder.decodeOptionalInt64ForKey("threadId")
} }
public func encode(_ encoder: PostboxEncoder) { public func encode(_ encoder: PostboxEncoder) {
@ -17,5 +20,10 @@ public final class SynchronizeChatInputStateOperation: PostboxCoding {
} else { } else {
encoder.encodeNil(forKey: "p") encoder.encodeNil(forKey: "p")
} }
if let threadId = self.threadId {
encoder.encodeInt64(threadId, forKey: "threadId")
} else {
encoder.encodeNil(forKey: "threadId")
}
} }
} }

View File

@ -689,6 +689,17 @@ public extension TelegramEngine {
) )
if let threadId = threadId { if let threadId = threadId {
var currentInputState: SynchronizeableChatInputState?
if let peerChatInterfaceState = transaction.getPeerChatThreadInterfaceState(peerId, threadId: threadId), let data = peerChatInterfaceState.data {
currentInputState = (try? AdaptedPostboxDecoder().decode(InternalChatInterfaceState.self, from: data))?.synchronizeableInputState
}
let updatedInputState = state.synchronizeableInputState
if currentInputState != updatedInputState {
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudChannel || peerId.namespace == Namespaces.Peer.CloudGroup {
addSynchronizeChatInputStateOperation(transaction: transaction, peerId: peerId, threadId: threadId)
}
}
transaction.setPeerChatThreadInterfaceState(peerId, threadId: threadId, state: storedState) transaction.setPeerChatThreadInterfaceState(peerId, threadId: threadId, state: storedState)
} else { } else {
var currentInputState: SynchronizeableChatInputState? var currentInputState: SynchronizeableChatInputState?
@ -699,7 +710,7 @@ public extension TelegramEngine {
if currentInputState != updatedInputState { if currentInputState != updatedInputState {
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudChannel || peerId.namespace == Namespaces.Peer.CloudGroup { if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudChannel || peerId.namespace == Namespaces.Peer.CloudGroup {
addSynchronizeChatInputStateOperation(transaction: transaction, peerId: peerId) addSynchronizeChatInputStateOperation(transaction: transaction, peerId: peerId, threadId: nil)
} }
} }
transaction.setPeerChatInterfaceState( transaction.setPeerChatInterfaceState(