no message

This commit is contained in:
Peter Iakovlev 2018-01-12 17:30:17 +04:00
parent 15be8bb5e6
commit d04264c127
11 changed files with 219 additions and 41 deletions

View File

@ -1157,6 +1157,8 @@ private func resolveAssociatedMessages(account: Account, state: AccountMutableSt
return (messages, chats, users) return (messages, chats, users)
case let .channelMessages(_, _, _, messages, chats, users): case let .channelMessages(_, _, _, messages, chats, users):
return (messages, chats, users) return (messages, chats, users)
case .messagesNotModified:
return ([], [], [])
} }
} |> `catch` { _ in } |> `catch` { _ in
return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], [])) return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], []))

View File

@ -77,6 +77,10 @@ private func fetchWebpage(account: Account, messageId: MessageId) -> Signal<Void
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case .messagesNotModified:
messages = []
chats = []
users = []
} }
return account.postbox.modify { modifier -> Void in return account.postbox.modify { modifier -> Void in

View File

@ -108,7 +108,7 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? {
case .chat, .chatEmpty, .chatForbidden, .channelForbidden: case .chat, .chatEmpty, .chatForbidden, .channelForbidden:
return parseTelegramGroupOrChannel(chat: rhs) return parseTelegramGroupOrChannel(chat: rhs)
case let .channel(flags, _, accessHash, title, username, photo, date, version, restrictionReason, adminRights, bannedRights, _, feedId): case let .channel(flags, _, accessHash, title, username, photo, date, version, restrictionReason, adminRights, bannedRights, _, feedId):
if let _ = accessHash { if accessHash != nil && (flags & (1 << 12)) == 0 {
return parseTelegramGroupOrChannel(chat: rhs) return parseTelegramGroupOrChannel(chat: rhs)
} else if let lhs = lhs as? TelegramChannel { } else if let lhs = lhs as? TelegramChannel {
var channelFlags = lhs.flags var channelFlags = lhs.flags
@ -128,7 +128,7 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? {
} }
info = .group(TelegramChannelGroupInfo(flags: infoFlags)) info = .group(TelegramChannelGroupInfo(flags: infoFlags))
} }
return TelegramChannel(id: lhs.id, accessHash: lhs.accessHash, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: lhs.creationDate, version: lhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: lhs.restrictionInfo, adminRights: lhs.adminRights, bannedRights: lhs.bannedRights, peerGroupId: feedId.flatMap { PeerGroupId(rawValue: $0) }) return TelegramChannel(id: lhs.id, accessHash: lhs.accessHash, title: title, username: username, photo: imageRepresentationsForApiChatPhoto(photo), creationDate: lhs.creationDate, version: lhs.version, participationStatus: lhs.participationStatus, info: info, flags: channelFlags, restrictionInfo: lhs.restrictionInfo, adminRights: lhs.adminRights, bannedRights: lhs.bannedRights, peerGroupId: lhs.peerGroupId)
} else { } else {
return nil return nil
} }

View File

@ -61,7 +61,7 @@ final class HistoryViewChannelStateValidationContexts {
if ranges.isEmpty { if ranges.isEmpty {
ranges = [[id]] ranges = [[id]]
} else { } else {
ranges[rangesToInvalidate.count - 1].append(id) ranges[ranges.count - 1].append(id)
} }
} }
@ -122,6 +122,8 @@ final class HistoryViewChannelStateValidationContexts {
var addedRanges: [[MessageId]] = [] var addedRanges: [[MessageId]] = []
for messages in rangesToInvalidate { for messages in rangesToInvalidate {
for id in messages { for id in messages {
invalidatedMessageIds.insert(id)
if context.batchReferences[id] != nil { if context.batchReferences[id] != nil {
addRangeBreak(&addedRanges) addRangeBreak(&addedRanges)
} else { } else {
@ -141,7 +143,7 @@ final class HistoryViewChannelStateValidationContexts {
context.batchReferences[messageId] = batch context.batchReferences[messageId] = batch
} }
disposable.set((validateBatch(postbox: self.postbox, network: self.network, messageIds: messages) disposable.set((validateBatch(postbox: self.postbox, network: self.network, messageIds: messages, validatePts: invalidatedPts)
|> deliverOn(self.queue)).start(completed: { [weak self, weak batch] in |> deliverOn(self.queue)).start(completed: { [weak self, weak batch] in
if let strongSelf = self, let context = strongSelf.contexts[id], let batch = batch { if let strongSelf = self, let context = strongSelf.contexts[id], let batch = batch {
var completedMessageIds: [MessageId] = [] var completedMessageIds: [MessageId] = []
@ -215,8 +217,10 @@ final class HistoryViewChannelStateValidationContexts {
private func hashForMessages(_ messages: [Message]) -> Int32 { private func hashForMessages(_ messages: [Message]) -> Int32 {
var acc: UInt32 = 0 var acc: UInt32 = 0
for message in messages { let sorted = messages.sorted(by: { $0.id > $1.id })
acc = (acc &* 20261) &+ message.id.id
for message in sorted {
acc = (acc &* 20261) &+ UInt32(message.id.id)
var timestamp = message.timestamp var timestamp = message.timestamp
inner: for attribute in message.attributes { inner: for attribute in message.attributes {
if let attribute = attribute as? EditedMessageAttribute { if let attribute = attribute as? EditedMessageAttribute {
@ -224,35 +228,169 @@ private func hashForMessages(_ messages: [Message]) -> Int32 {
break inner break inner
} }
} }
acc = (acc &* 20261) &+ timestamp acc = (acc &* 20261) &+ UInt32(timestamp)
} }
return Int32(bitPattern: acc & UInt32(0x7FFFFFFF)) return Int32(bitPattern: acc & UInt32(0x7FFFFFFF))
} }
private func validateBatch(postbox: Postbox, network: Network, messageIds: [MessageId]) -> Signal<Void, NoError> { private func hashForMessages(_ messages: [StoreMessage]) -> Int32 {
var acc: UInt32 = 0
for message in messages {
if case let .Id(id) = message.id {
acc = (acc &* 20261) &+ UInt32(id.id)
var timestamp = message.timestamp
inner: for attribute in message.attributes {
if let attribute = attribute as? EditedMessageAttribute {
timestamp = attribute.date
break inner
}
}
acc = (acc &* 20261) &+ UInt32(timestamp)
}
}
return Int32(bitPattern: acc & UInt32(0x7FFFFFFF))
}
private func validateBatch(postbox: Postbox, network: Network, messageIds: [MessageId], validatePts: Int32) -> Signal<Void, NoError> {
guard let peerId = messageIds.first?.peerId else { guard let peerId = messageIds.first?.peerId else {
return .never() return .never()
} }
return postbox.modify { modifier -> Signal<Void, NoError> in return postbox.modify { modifier -> Signal<Void, NoError> in
if let peer = modifier.getPeer(peerId), let inputPeer = apiInputPeer(peer) { if let peer = modifier.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
var messages: [Message] = [] var messages: [Message] = []
var previous: [MessageId: Message] = [:]
for messageId in messageIds { for messageId in messageIds {
if let message = modifier.getMessage(messageId) { if let message = modifier.getMessage(messageId) {
messages.append(message) messages.append(message)
previous[message.id] = message
} }
} }
let hash = hashForMessages(messages) let hash = hashForMessages(messages)
return network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: messageIds[messageIds.count - 1].id, offsetDate: 0, addOffset: 0, limit: 100, maxId: messageIds[messageIds.cout - 1].id, minId: messageIds[0].id, hash: hash)) return network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: messageIds[messageIds.count - 1].id + 1, offsetDate: 0, addOffset: 0, limit: Int32(messageIds.count), maxId: messageIds[messageIds.count - 1].id + 1, minId: messageIds[0].id - 1, hash: hash))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in |> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
return .single(nil) return .single(nil)
} }
|> mapToSignal { result -> Signal<Void, NoError> in |> mapToSignal { result -> Signal<Void, NoError> in
return postbox.modify { modifier -> Void in return postbox.modify { modifier -> Void in
if let result = result { if let result = result {
let messages: [Api.Message]
let chats: [Api.Chat]
let users: [Api.User]
var channelPts: Int32?
switch result { switch result {
case let .messages(messages: apiMessages, chats: apiChats, users: apiUsers):
messages = apiMessages
chats = apiChats
users = apiUsers
case let .messagesSlice(_, messages: apiMessages, chats: apiChats, users: apiUsers):
messages = apiMessages
chats = apiChats
users = apiUsers
case let .channelMessages(_, pts, _, apiMessages, apiChats, apiUsers):
messages = apiMessages
chats = apiChats
users = apiUsers
channelPts = pts
case .messagesNotModified: case .messagesNotModified:
break for id in previous.keys {
modifier.updateMessage(id, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature)
}
var attributes = currentMessage.attributes
/*if let channelPts = channelPts {
for i in 0 ..< attributes.count {
if let _ = attributes[i] as? ChannelMessageStateVersionAttribute {
attributes.remove(at: i)
break
}
}
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
}*/
for i in 0 ..< attributes.count {
if let _ = attributes[i] as? ChannelMessageStateVersionAttribute {
attributes.remove(at: i)
break
}
}
attributes.append(ChannelMessageStateVersionAttribute(pts: validatePts))
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: [.Failed], tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
})
}
return
}
var storeMessages: [StoreMessage] = []
for message in messages {
if let storeMessage = StoreMessage(apiMessage: message) {
if let channelPts = channelPts {
var attributes = storeMessage.attributes
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
storeMessages.append(storeMessage.withUpdatedAttributes(attributes))
} else {
storeMessages.append(storeMessage)
}
}
}
//let updatedHash = hashForMessages(storeMessages)
var validMessageIds = Set<MessageId>()
for message in storeMessages {
if case let .Id(id) = message.id {
validMessageIds.insert(id)
if let previousMessage = previous[id] {
var updatedTimestamp = message.timestamp
inner: for attribute in message.attributes {
if let attribute = attribute as? EditedMessageAttribute {
updatedTimestamp = attribute.date
break inner
}
}
var timestamp = previousMessage.timestamp
inner: for attribute in previousMessage.attributes {
if let attribute = attribute as? EditedMessageAttribute {
timestamp = attribute.date
break inner
}
}
modifier.updateMessage(id, update: { currentMessage in
if updatedTimestamp != timestamp {
return .update(message)
} else {
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature)
}
var attributes = currentMessage.attributes
if let channelPts = channelPts {
for i in 0 ..< attributes.count {
if let _ = attributes[i] as? ChannelMessageStateVersionAttribute {
attributes.remove(at: i)
break
}
}
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
}
return .update(StoreMessage(id: message.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: [.Failed], tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
}
})
}
}
}
for id in previous.keys {
if !validMessageIds.contains(id) {
modifier.deleteMessages([id])
}
} }
} }
} }

View File

@ -183,6 +183,10 @@ func fetchMessageHistoryHole(source: FetchMessageHistoryHoleSource, postbox: Pos
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
channelPts = pts channelPts = pts
case .messagesNotModified:
messages = []
chats = []
users = []
} }
var updatedMaxIndex: MessageIndex? var updatedMaxIndex: MessageIndex?
if let maxIndexResult = maxIndexResult { if let maxIndexResult = maxIndexResult {
@ -194,6 +198,8 @@ func fetchMessageHistoryHole(source: FetchMessageHistoryHoleSource, postbox: Pos
maxIndexMessages = apiMessages maxIndexMessages = apiMessages
case let .channelMessages(_, _, _, apiMessages, _, _): case let .channelMessages(_, _, _, apiMessages, _, _):
maxIndexMessages = apiMessages maxIndexMessages = apiMessages
case .messagesNotModified:
maxIndexMessages = []
} }
if !maxIndexMessages.isEmpty { if !maxIndexMessages.isEmpty {
assert(maxIndexMessages.count == 1) assert(maxIndexMessages.count == 1)
@ -520,6 +526,10 @@ func fetchCallListHole(network: Network, postbox: Postbox, holeIndex: MessageInd
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case .messagesNotModified:
messages = []
chats = []
users = []
} }
return postbox.modify { modifier -> Void in return postbox.modify { modifier -> Void in
var storeMessages: [StoreMessage] = [] var storeMessages: [StoreMessage] = []

View File

@ -60,12 +60,14 @@ public func getMessagesLoadIfNecessary(_ messageIds:[MessageId], postbox:Postbox
if let signal = signal { if let signal = signal {
signals.append(signal |> map { result in signals.append(signal |> map { result in
switch result { switch result {
case let .messages(messages, chats, users): case let .messages(messages, chats, users):
return (messages, chats, users) return (messages, chats, users)
case let .messagesSlice(_, messages, chats, users): case let .messagesSlice(_, messages, chats, users):
return (messages, chats, users) return (messages, chats, users)
case let .channelMessages(_, _, _, messages, chats, users): case let .channelMessages(_, _, _, messages, chats, users):
return (messages, chats, users) return (messages, chats, users)
case .messagesNotModified:
return ([], [], [])
} }
} |> `catch` { _ in } |> `catch` { _ in
return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], [])) return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], []))

View File

@ -43,6 +43,8 @@ public func loadedPeerFromMessage(account: Account, peerId: PeerId, messageId: M
apiUsers = users apiUsers = users
case let .channelMessages(_, _, _, _, _, users): case let .channelMessages(_, _, _, _, _, users):
apiUsers = users apiUsers = users
case .messagesNotModified:
apiUsers = []
} }
for user in apiUsers { for user in apiUsers {

View File

@ -75,18 +75,22 @@ public func requestPeerPhotos(account:Account, peerId:PeerId) -> Signal<[Telegra
let chats: [Api.Chat] let chats: [Api.Chat]
let users: [Api.User] let users: [Api.User]
switch result { switch result {
case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers): case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers):
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case let .messages(apiMessages, apiChats, apiUsers): case let .messages(apiMessages, apiChats, apiUsers):
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case let.messagesSlice(_, apiMessages, apiChats, apiUsers): case let.messagesSlice(_, apiMessages, apiChats, apiUsers):
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case .messagesNotModified:
messages = []
chats = []
users = []
} }
return account.postbox.modify { modifier -> [Message] in return account.postbox.modify { modifier -> [Message] in

View File

@ -117,6 +117,10 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case .messagesNotModified:
messages = []
chats = []
users = []
} }
return account.postbox.modify { modifier -> [Message] in return account.postbox.modify { modifier -> [Message] in
@ -183,18 +187,22 @@ public func downloadMessage(account: Account, messageId: MessageId) -> Signal<Me
let chats: [Api.Chat] let chats: [Api.Chat]
let users: [Api.User] let users: [Api.User]
switch result { switch result {
case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers): case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers):
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case let .messages(apiMessages, apiChats, apiUsers): case let .messages(apiMessages, apiChats, apiUsers):
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case let.messagesSlice(_, apiMessages, apiChats, apiUsers): case let.messagesSlice(_, apiMessages, apiChats, apiUsers):
messages = apiMessages messages = apiMessages
chats = apiChats chats = apiChats
users = apiUsers users = apiUsers
case .messagesNotModified:
messages = []
chats = []
users = []
} }
let postboxSignal = account.postbox.modify { modifier -> Message? in let postboxSignal = account.postbox.modify { modifier -> Message? in
@ -249,6 +257,8 @@ public func searchMessageIdByTimestamp(account: Account, peerId: PeerId, timesta
messages = apiMessages messages = apiMessages
case let.messagesSlice(_, apiMessages, _, _): case let.messagesSlice(_, apiMessages, _, _):
messages = apiMessages messages = apiMessages
case .messagesNotModified:
messages = []
} }
for message in messages { for message in messages {
if let message = StoreMessage(apiMessage: message), case let .Id(id) = message.id { if let message = StoreMessage(apiMessage: message), case let .Id(id) = message.id {

View File

@ -64,6 +64,10 @@ private func fetchMessage(modifier: Modifier, account: Account, messageId: Messa
apiMessages = messages apiMessages = messages
apiChats = chats apiChats = chats
apiUsers = users apiUsers = users
case .messagesNotModified:
apiMessages = []
apiChats = []
apiUsers = []
} }
var peers: [PeerId: Peer] = [:] var peers: [PeerId: Peer] = [:]

View File

@ -53,6 +53,8 @@ private func dialogTopMessage(network: Network, postbox: Postbox, peerId: PeerId
apiMessages = messages apiMessages = messages
case let .messagesSlice(_, messages, _, _): case let .messagesSlice(_, messages, _, _):
apiMessages = messages apiMessages = messages
case .messagesNotModified:
apiMessages = []
} }
if let message = apiMessages.first, let timestamp = message.timestamp { if let message = apiMessages.first, let timestamp = message.timestamp {
return .single((message.rawId, timestamp)) return .single((message.rawId, timestamp))