mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Saved message tags improvements
This commit is contained in:
parent
d392e51aae
commit
4594df516e
@ -2673,9 +2673,22 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
previousTopItemVerticalOrigin = self.topItemVerticalOrigin()
|
||||
}
|
||||
|
||||
var previousApparentFrames: [(ListViewItemNode, CGRect)] = []
|
||||
struct PreviousApparentFrame {
|
||||
var frame: CGRect
|
||||
var insets: UIEdgeInsets
|
||||
|
||||
init(frame: CGRect, insets: UIEdgeInsets) {
|
||||
self.frame = frame
|
||||
self.insets = insets
|
||||
}
|
||||
}
|
||||
|
||||
var previousApparentFrames: [(ListViewItemNode, PreviousApparentFrame)] = []
|
||||
for itemNode in self.itemNodes {
|
||||
previousApparentFrames.append((itemNode, itemNode.apparentFrame))
|
||||
previousApparentFrames.append((itemNode, PreviousApparentFrame(
|
||||
frame: itemNode.apparentFrame,
|
||||
insets: itemNode.insets
|
||||
)))
|
||||
}
|
||||
|
||||
var takenPreviousNodes = Set<ListViewItemNode>()
|
||||
@ -2699,7 +2712,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
var previousFrame: CGRect?
|
||||
for (previousNode, frame) in previousApparentFrames {
|
||||
if previousNode === node {
|
||||
previousFrame = frame
|
||||
previousFrame = frame.frame
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -2764,7 +2777,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
|
||||
for (node, previousFrame) in previousApparentFrames {
|
||||
if node === referenceNode {
|
||||
height = previousFrame.size.height
|
||||
height = previousFrame.frame.size.height
|
||||
previousLayout = ListViewItemNodeLayout(contentSize: node.contentSize, insets: node.insets)
|
||||
break
|
||||
}
|
||||
@ -2830,7 +2843,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
for (previousNode, previousFrame) in previousApparentFrames {
|
||||
if previousNode === self.itemNodes[index] {
|
||||
removedPreviousNodes.insert(previousNode)
|
||||
self.itemNodes[index].frame = previousFrame
|
||||
self.itemNodes[index].frame = previousFrame.frame
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -3026,7 +3039,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
if let index = itemNode.index , index == stationaryItemIndex {
|
||||
for (previousNode, previousFrame) in previousApparentFrames {
|
||||
if previousNode === itemNode {
|
||||
let offset = previousFrame.minY - itemNode.frame.minY
|
||||
let offset = previousFrame.frame.minY - itemNode.frame.minY
|
||||
|
||||
if abs(offset) > CGFloat.ulpOfOne {
|
||||
for itemNode in self.itemNodes {
|
||||
@ -3294,7 +3307,18 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
if animateFullTransition {
|
||||
for (previousNode, previousFrame) in previousApparentFrames {
|
||||
if !takenPreviousNodes.contains(previousNode) && !removedPreviousNodes.contains(previousNode) {
|
||||
previousNode.layer.animatePosition(from: CGPoint(x: 0.0, y: previousFrame.minY - previousNode.frame.minY), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
if previousFrame.frame.maxY < self.insets.top || previousFrame.frame.minY > self.visibleSize.height - self.insets.bottom {
|
||||
previousNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||
previousNode.layer.animateScale(from: 0.7, to: 1.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
} else {
|
||||
let boundsOffset: CGFloat
|
||||
if self.rotated {
|
||||
boundsOffset = previousFrame.insets.bottom - previousNode.insets.bottom
|
||||
} else {
|
||||
boundsOffset = previousFrame.insets.top - previousNode.insets.top
|
||||
}
|
||||
previousNode.layer.animatePosition(from: CGPoint(x: 0.0, y: previousFrame.frame.minY - previousNode.frame.minY + boundsOffset), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3310,16 +3334,16 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
for (previousNode, previousFrame) in previousApparentFrames {
|
||||
if previousNode.supernode == nil {
|
||||
temporaryPreviousNodes.append(previousNode)
|
||||
previousNode.updateFrame(previousFrame, within: self.visibleSize)
|
||||
if previousUpperBound == nil || previousUpperBound! > previousFrame.minY {
|
||||
previousUpperBound = previousFrame.minY
|
||||
previousNode.updateFrame(previousFrame.frame, within: self.visibleSize)
|
||||
if previousUpperBound == nil || previousUpperBound! > previousFrame.frame.minY {
|
||||
previousUpperBound = previousFrame.frame.minY
|
||||
}
|
||||
if previousLowerBound == nil || previousLowerBound! < previousFrame.maxY {
|
||||
previousLowerBound = previousFrame.maxY
|
||||
if previousLowerBound == nil || previousLowerBound! < previousFrame.frame.maxY {
|
||||
previousLowerBound = previousFrame.frame.maxY
|
||||
}
|
||||
} else {
|
||||
if previousNode.canBeUsedAsScrollToItemAnchor {
|
||||
offset = previousNode.apparentFrame.minY - previousFrame.minY
|
||||
offset = previousNode.apparentFrame.minY - previousFrame.frame.minY
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -3328,16 +3352,16 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
for (previousNode, previousFrame) in previousApparentFrames {
|
||||
if previousNode.supernode == nil {
|
||||
temporaryPreviousNodes.append(previousNode)
|
||||
previousNode.updateFrame(previousFrame, within: self.visibleSize)
|
||||
if previousUpperBound == nil || previousUpperBound! > previousFrame.minY {
|
||||
previousUpperBound = previousFrame.minY
|
||||
previousNode.updateFrame(previousFrame.frame, within: self.visibleSize)
|
||||
if previousUpperBound == nil || previousUpperBound! > previousFrame.frame.minY {
|
||||
previousUpperBound = previousFrame.frame.minY
|
||||
}
|
||||
if previousLowerBound == nil || previousLowerBound! < previousFrame.maxY {
|
||||
previousLowerBound = previousFrame.maxY
|
||||
if previousLowerBound == nil || previousLowerBound! < previousFrame.frame.maxY {
|
||||
previousLowerBound = previousFrame.frame.maxY
|
||||
}
|
||||
} else {
|
||||
if previousNode.canBeUsedAsScrollToItemAnchor {
|
||||
offset = previousNode.apparentFrame.minY - previousFrame.minY
|
||||
offset = previousNode.apparentFrame.minY - previousFrame.frame.minY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1851,14 +1851,15 @@ public extension Api.functions.auth {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.auth {
|
||||
static func signUp(phoneNumber: String, phoneCodeHash: String, firstName: String, lastName: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.auth.Authorization>) {
|
||||
static func signUp(flags: Int32, phoneNumber: String, phoneCodeHash: String, firstName: String, lastName: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.auth.Authorization>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-2131827673)
|
||||
buffer.appendInt32(-1429752041)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(phoneNumber, buffer: buffer, boxed: false)
|
||||
serializeString(phoneCodeHash, buffer: buffer, boxed: false)
|
||||
serializeString(firstName, buffer: buffer, boxed: false)
|
||||
serializeString(lastName, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "auth.signUp", parameters: [("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in
|
||||
return (FunctionDescription(name: "auth.signUp", parameters: [("flags", String(describing: flags)), ("phoneNumber", String(describing: phoneNumber)), ("phoneCodeHash", String(describing: phoneCodeHash)), ("firstName", String(describing: firstName)), ("lastName", String(describing: lastName))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.auth.Authorization? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.auth.Authorization?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -5901,11 +5902,13 @@ public extension Api.functions.messages {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSavedReactionTags(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SavedReactionTags>) {
|
||||
static func getSavedReactionTags(flags: Int32, peer: Api.InputPeer?, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SavedReactionTags>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1981668047)
|
||||
buffer.appendInt32(909631579)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {peer!.serialize(buffer, true)}
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getSavedReactionTags", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SavedReactionTags? in
|
||||
return (FunctionDescription(name: "messages.getSavedReactionTags", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SavedReactionTags? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.SavedReactionTags?
|
||||
if let signature = reader.readInt32() {
|
||||
|
@ -1211,7 +1211,7 @@ public enum SignUpError {
|
||||
public func signUpWithName(accountManager: AccountManager<TelegramAccountManagerTypes>, account: UnauthorizedAccount, firstName: String, lastName: String, avatarData: Data?, avatarVideo: Signal<UploadedPeerPhotoData?, NoError>?, videoStartTimestamp: Double?, forcedPasswordSetupNotice: @escaping (Int32) -> (NoticeEntryKey, CodableEntry)?) -> Signal<Void, SignUpError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, SignUpError> in
|
||||
if let state = transaction.getState() as? UnauthorizedAccountState, case let .signUp(number, codeHash, _, _, _, syncContacts) = state.contents {
|
||||
return account.network.request(Api.functions.auth.signUp(phoneNumber: number, phoneCodeHash: codeHash, firstName: firstName, lastName: lastName))
|
||||
return account.network.request(Api.functions.auth.signUp(flags: 0, phoneNumber: number, phoneCodeHash: codeHash, firstName: firstName, lastName: lastName))
|
||||
|> mapError { error -> SignUpError in
|
||||
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
|
||||
return .limitExceeded
|
||||
|
@ -89,7 +89,6 @@ final class AccountTaskManager {
|
||||
tasks.add(managedSynchronizeEmojiKeywordsOperations(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedApplyPendingScheduledMessagesActions(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start())
|
||||
tasks.add(managedSynchronizeAvailableReactions(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
|
||||
tasks.add(managedSynchronizeSavedMessageTags(postbox: self.stateManager.postbox, network: self.stateManager.network, accountPeerId: self.stateManager.accountPeerId).start())
|
||||
tasks.add(managedSynchronizeEmojiSearchCategories(postbox: self.stateManager.postbox, network: self.stateManager.network, kind: .emoji).start())
|
||||
tasks.add(managedSynchronizeEmojiSearchCategories(postbox: self.stateManager.postbox, network: self.stateManager.network, kind: .status).start())
|
||||
tasks.add(managedSynchronizeEmojiSearchCategories(postbox: self.stateManager.postbox, network: self.stateManager.network, kind: .avatar).start())
|
||||
|
@ -3,7 +3,39 @@ import Postbox
|
||||
import SwiftSignalKit
|
||||
import TelegramApi
|
||||
import MtProtoKit
|
||||
import CryptoUtils
|
||||
|
||||
private struct Md5Hash: Hashable {
|
||||
public let data: Data
|
||||
|
||||
public init(data: Data) {
|
||||
precondition(data.count == 16)
|
||||
self.data = data
|
||||
}
|
||||
}
|
||||
|
||||
private func md5Hash(_ data: Data) -> Md5Hash {
|
||||
let hashData = data.withUnsafeBytes { bytes -> Data in
|
||||
return CryptoMD5(bytes.baseAddress!, Int32(bytes.count))
|
||||
}
|
||||
return Md5Hash(data: hashData)
|
||||
}
|
||||
|
||||
private func md5StringHash(_ string: String) -> UInt64 {
|
||||
guard let data = string.data(using: .utf8) else {
|
||||
return 0
|
||||
}
|
||||
let hash = md5Hash(data).data
|
||||
|
||||
return hash.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) -> UInt64 in
|
||||
let bytes = buffer.baseAddress!.assumingMemoryBound(to: UInt8.self)
|
||||
var result: UInt64 = 0
|
||||
for i in 0 ... 7 {
|
||||
result += UInt64(bitPattern: Int64(bytes[i])) << (56 - 8 * i)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private final class ManagedConsumePersonalMessagesActionsHelper {
|
||||
var operationDisposables: [MessageId: Disposable] = [:]
|
||||
@ -529,7 +561,7 @@ private func synchronizeMessageHistoryTagSummary(postbox: Postbox, network: Netw
|
||||
|> switchToLatest
|
||||
}
|
||||
|
||||
private func synchronizeSavedMessageTags(postbox: Postbox, network: Network, peerId: PeerId, threadId: Int64?) -> Signal<Never, NoError> {
|
||||
func synchronizeSavedMessageTags(postbox: Postbox, network: Network, peerId: PeerId, threadId: Int64?) -> Signal<Never, NoError> {
|
||||
let key: PostboxViewKey = .pendingMessageActions(type: .updateReaction)
|
||||
let waitForApplySignal: Signal<Never, NoError> = postbox.combinedView(keys: [key])
|
||||
|> map { views -> Bool in
|
||||
@ -549,15 +581,99 @@ private func synchronizeSavedMessageTags(postbox: Postbox, network: Network, pee
|
||||
|> take(1)
|
||||
|> ignoreValues
|
||||
|
||||
let updateSignal: Signal<Never, NoError> = (postbox.transaction { transaction -> Bool in
|
||||
return transaction.getPreferencesEntry(key: PreferencesKeys.didCacheSavedMessageTags(threadId: threadId)) != nil
|
||||
let updateSignal: Signal<Never, NoError> = (postbox.transaction { transaction -> (Bool, Peer?, Int64) in
|
||||
struct HashableTag {
|
||||
var titleId: UInt64?
|
||||
var count: Int
|
||||
var id: UInt64
|
||||
|
||||
init(titleId: UInt64?, count: Int, id: UInt64) {
|
||||
self.titleId = titleId
|
||||
self.count = count
|
||||
self.id = id
|
||||
}
|
||||
|> mapToSignal { alreadyCached -> Signal<Never, NoError> in
|
||||
}
|
||||
|
||||
let savedTags = _internal_savedMessageTags(transaction: transaction)
|
||||
|
||||
var hashableTags: [HashableTag] = []
|
||||
for tag in transaction.getMessageTagSummaryCustomTags(peerId: peerId, threadId: threadId, tagMask: [], namespace: Namespaces.Message.Cloud) {
|
||||
if let summary = transaction.getMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: tag), summary.count > 0 {
|
||||
guard let reaction = ReactionsMessageAttribute.reactionFromMessageTag(tag: tag) else {
|
||||
continue
|
||||
}
|
||||
|
||||
var tagTitle: String?
|
||||
if threadId == nil, let savedTags {
|
||||
if let value = savedTags.tags.first(where: { $0.reaction == reaction }) {
|
||||
tagTitle = value.title
|
||||
}
|
||||
}
|
||||
|
||||
let reactionId: UInt64
|
||||
switch reaction {
|
||||
case let .custom(id):
|
||||
reactionId = UInt64(bitPattern: id)
|
||||
case let .builtin(string):
|
||||
reactionId = md5StringHash(string)
|
||||
}
|
||||
|
||||
var titleId: UInt64?
|
||||
if let tagTitle {
|
||||
titleId = md5StringHash(tagTitle)
|
||||
}
|
||||
|
||||
hashableTags.append(HashableTag(
|
||||
titleId: titleId,
|
||||
count: Int(summary.count),
|
||||
id: reactionId
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
hashableTags.sort(by: { lhs, rhs in
|
||||
if lhs.count != rhs.count {
|
||||
return lhs.count > rhs.count
|
||||
}
|
||||
return lhs.id < rhs.id
|
||||
})
|
||||
|
||||
var hashIds: [UInt64] = []
|
||||
for tag in hashableTags {
|
||||
hashIds.append(tag.id)
|
||||
if let titleId = tag.titleId {
|
||||
hashIds.append(titleId)
|
||||
}
|
||||
hashIds.append(UInt64(tag.count))
|
||||
}
|
||||
|
||||
var hashAcc: UInt64 = 0
|
||||
for id in hashIds {
|
||||
combineInt64Hash(&hashAcc, with: id)
|
||||
}
|
||||
|
||||
return (
|
||||
transaction.getPreferencesEntry(key: PreferencesKeys.didCacheSavedMessageTags(threadId: threadId)) != nil,
|
||||
threadId.flatMap { transaction.getPeer(PeerId($0)) },
|
||||
Int64(bitPattern: hashAcc)
|
||||
)
|
||||
}
|
||||
|> mapToSignal { alreadyCached, subPeer, currentHash -> Signal<Never, NoError> in
|
||||
if alreadyCached {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
return network.request(Api.functions.messages.getSavedReactionTags(hash: 0))
|
||||
let inputSubPeer = subPeer.flatMap(apiInputPeer)
|
||||
if threadId != nil && inputSubPeer == nil {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
if inputSubPeer != nil {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
|
||||
return network.request(Api.functions.messages.getSavedReactionTags(flags: flags, peer: inputSubPeer, hash: currentHash))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.SavedReactionTags?, NoError> in
|
||||
return .single(nil)
|
||||
@ -569,7 +685,10 @@ private func synchronizeSavedMessageTags(postbox: Postbox, network: Network, pee
|
||||
|
||||
switch result {
|
||||
case .savedReactionTagsNotModified:
|
||||
return .complete()
|
||||
return postbox.transaction { transaction -> Void in
|
||||
transaction.setPreferencesEntry(key: PreferencesKeys.didCacheSavedMessageTags(threadId: threadId), value: PreferencesEntry(data: Data()))
|
||||
}
|
||||
|> ignoreValues
|
||||
case let .savedReactionTags(tags, _):
|
||||
var customFileIds: [Int64] = []
|
||||
var parsedTags: [SavedMessageTags.Tag] = []
|
||||
@ -591,10 +710,15 @@ private func synchronizeSavedMessageTags(postbox: Postbox, network: Network, pee
|
||||
}
|
||||
}
|
||||
|
||||
let _ = customFileIds
|
||||
|
||||
return postbox.transaction { transaction -> Void in
|
||||
let previousTags = transaction.getMessageTagSummaryCustomTags(peerId: peerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud)
|
||||
if threadId == nil {
|
||||
_internal_setSavedMessageTags(transaction: transaction, savedMessageTags: SavedMessageTags(
|
||||
hash: 0,
|
||||
tags: parsedTags
|
||||
))
|
||||
}
|
||||
|
||||
let previousTags = transaction.getMessageTagSummaryCustomTags(peerId: peerId, threadId: threadId, tagMask: [], namespace: Namespaces.Message.Cloud)
|
||||
|
||||
let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud)?.id ?? 1
|
||||
|
||||
@ -602,11 +726,11 @@ private func synchronizeSavedMessageTags(postbox: Postbox, network: Network, pee
|
||||
for tag in parsedTags {
|
||||
let customTag = ReactionsMessageAttribute.messageTag(reaction: tag.reaction)
|
||||
validTags.append(customTag)
|
||||
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: customTag, count: Int32(tag.count), maxId: topMessageId)
|
||||
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: customTag, count: Int32(tag.count), maxId: topMessageId)
|
||||
}
|
||||
for tag in previousTags {
|
||||
if !validTags.contains(tag) {
|
||||
transaction.replaceMessageTagSummary(peerId: peerId, threadId: nil, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: tag, count: 0, maxId: topMessageId)
|
||||
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: [], namespace: Namespaces.Message.Cloud, customTag: tag, count: 0, maxId: topMessageId)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,95 +132,6 @@ func _internal_setSavedMessageTags(transaction: Transaction, savedMessageTags: S
|
||||
}
|
||||
}
|
||||
|
||||
func managedSynchronizeSavedMessageTags(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Never, NoError> {
|
||||
let poll = Signal<Never, NoError> { subscriber in
|
||||
let key: PostboxViewKey = .pendingMessageActions(type: .updateReaction)
|
||||
let waitForApplySignal: Signal<Never, NoError> = postbox.combinedView(keys: [key])
|
||||
|> map { views -> Bool in
|
||||
guard let view = views.views[key] as? PendingMessageActionsView else {
|
||||
return false
|
||||
}
|
||||
|
||||
for entry in view.entries {
|
||||
if entry.id.peerId == accountPeerId {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
|> ignoreValues
|
||||
|
||||
let signal: Signal<Never, NoError> = _internal_savedMessageTags(postbox: postbox)
|
||||
|> mapToSignal { current in
|
||||
return (network.request(Api.functions.messages.getSavedReactionTags(hash: current?.hash ?? 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.SavedReactionTags?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||
guard let result = result else {
|
||||
return .complete()
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .savedReactionTagsNotModified:
|
||||
return .complete()
|
||||
case let .savedReactionTags(tags, hash):
|
||||
var customFileIds: [Int64] = []
|
||||
|
||||
var parsedTags: [SavedMessageTags.Tag] = []
|
||||
for tag in tags {
|
||||
switch tag {
|
||||
case let .savedReactionTag(_, reaction, title, count):
|
||||
guard let reaction = MessageReaction.Reaction(apiReaction: reaction) else {
|
||||
continue
|
||||
}
|
||||
parsedTags.append(SavedMessageTags.Tag(
|
||||
reaction: reaction,
|
||||
title: title,
|
||||
count: Int(count)
|
||||
))
|
||||
|
||||
if case let .custom(fileId) = reaction {
|
||||
customFileIds.append(fileId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let savedMessageTags = SavedMessageTags(
|
||||
hash: hash,
|
||||
tags: parsedTags
|
||||
)
|
||||
|
||||
return _internal_resolveInlineStickers(postbox: postbox, network: network, fileIds: customFileIds)
|
||||
|> mapToSignal { _ -> Signal<Never, NoError> in
|
||||
return postbox.transaction { transaction in
|
||||
_internal_setSavedMessageTags(transaction: transaction, savedMessageTags: savedMessageTags)
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (waitForApplySignal |> then(signal)).start(completed: {
|
||||
subscriber.putCompletion()
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
poll
|
||||
|> then(
|
||||
.complete()
|
||||
|> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue())
|
||||
)
|
||||
)
|
||||
|> restart
|
||||
}
|
||||
|
||||
func _internal_setSavedMessageTagTitle(account: Account, reaction: MessageReaction.Reaction, title: String?) -> Signal<Never, NoError> {
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
let value = _internal_savedMessageTags(transaction: transaction) ?? SavedMessageTags(hash: 0, tags: [])
|
||||
|
@ -146,8 +146,8 @@ public extension TelegramEngine {
|
||||
}
|
||||
}
|
||||
|
||||
public func refreshSavedMessageTags() -> Signal<Never, NoError> {
|
||||
return managedSynchronizeSavedMessageTags(postbox: self.account.postbox, network: self.account.network, accountPeerId: self.account.peerId)
|
||||
public func refreshSavedMessageTags(subPeerId: EnginePeer.Id?) -> Signal<Never, NoError> {
|
||||
return synchronizeSavedMessageTags(postbox: self.account.postbox, network: self.account.network, peerId: self.account.peerId, threadId: subPeerId?.toInt64())
|
||||
}
|
||||
|
||||
public func setSavedMessageTagTitle(reaction: MessageReaction.Reaction, title: String?) -> Signal<Never, NoError> {
|
||||
|
@ -305,6 +305,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
var sendAsPeersDisposable: Disposable?
|
||||
var preloadAttachBotIconsDisposables: DisposableSet?
|
||||
var keepMessageCountersSyncrhonizedDisposable: Disposable?
|
||||
var keepSavedMessagesSyncrhonizedDisposable: Disposable?
|
||||
var saveMediaDisposable: MetaDisposable?
|
||||
var giveawayStatusDisposable: MetaDisposable?
|
||||
var nameColorDisposable: Disposable?
|
||||
@ -6617,6 +6618,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.sendAsPeersDisposable?.dispose()
|
||||
self.preloadAttachBotIconsDisposables?.dispose()
|
||||
self.keepMessageCountersSyncrhonizedDisposable?.dispose()
|
||||
self.keepSavedMessagesSyncrhonizedDisposable?.dispose()
|
||||
self.translationStateDisposable?.dispose()
|
||||
self.premiumGiftSuggestionDisposable?.dispose()
|
||||
self.powerSavingMonitoringDisposable?.dispose()
|
||||
@ -11322,11 +11324,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if self.keepMessageCountersSyncrhonizedDisposable == nil {
|
||||
self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: message.peerId, threadId: message.threadId).startStrict()
|
||||
}
|
||||
} else if case .peer(self.context.account.peerId) = self.chatLocation {
|
||||
} else if self.chatLocation.peerId == self.context.account.peerId {
|
||||
if self.keepMessageCountersSyncrhonizedDisposable == nil {
|
||||
if let threadId = self.chatLocation.threadId {
|
||||
self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: self.context.account.peerId, threadId: threadId).startStrict()
|
||||
} else {
|
||||
self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: self.context.account.peerId).startStrict()
|
||||
}
|
||||
}
|
||||
if self.keepSavedMessagesSyncrhonizedDisposable == nil {
|
||||
self.keepSavedMessagesSyncrhonizedDisposable = self.context.engine.stickers.refreshSavedMessageTags(subPeerId: self.chatLocation.threadId.flatMap(PeerId.init)).startStrict()
|
||||
}
|
||||
}
|
||||
|
||||
if let scheduledActivateInput = scheduledActivateInput, case .text = scheduledActivateInput {
|
||||
self.scheduledActivateInput = nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user