no message

This commit is contained in:
Peter
2017-09-21 15:10:06 +03:00
parent 9645d068bc
commit d95f85e964
9 changed files with 267 additions and 64 deletions

View File

@@ -44,6 +44,15 @@ enum AccountStateUpdateStickerPacksOperation {
case sync
}
enum AccountStateNotificationSettingsSubject {
case peer(PeerId)
}
enum AccountStateGlobalNotificationSettingsSubject {
case privateChats
case groups
}
enum AccountStateMutationOperation {
case AddMessages([StoreMessage], AddMessagesLocation)
case DeleteMessagesWithGlobalIds([Int32])
@@ -56,7 +65,8 @@ enum AccountStateMutationOperation {
case ResetMessageTagSummary(PeerId, MessageId.Namespace, Int32, MessageHistoryTagNamespaceCountValidityRange)
case UpdateState(AuthorizedAccountState.State)
case UpdateChannelState(PeerId, ChannelState)
case UpdatePeerNotificationSettings(PeerId, PeerNotificationSettings)
case UpdateNotificationSettings(AccountStateNotificationSettingsSubject, PeerNotificationSettings)
case UpdateGlobalNotificationSettings(AccountStateGlobalNotificationSettingsSubject, MessageNotificationSettings)
case AddHole(MessageId)
case MergeApiChats([Api.Chat])
case UpdatePeer(PeerId, (Peer?) -> Peer?)
@@ -182,8 +192,12 @@ struct AccountMutableState {
self.addOperation(.UpdateChannelState(peerId, state))
}
mutating func updatePeerNotificationSettings(_ peerId: PeerId, notificationSettings: PeerNotificationSettings) {
self.addOperation(.UpdatePeerNotificationSettings(peerId, notificationSettings))
mutating func updateNotificationSettings(_ subject: AccountStateNotificationSettingsSubject, notificationSettings: PeerNotificationSettings) {
self.addOperation(.UpdateNotificationSettings(subject, notificationSettings))
}
mutating func updateGlobalNotificationSettings(_ subject: AccountStateGlobalNotificationSettingsSubject, notificationSettings: MessageNotificationSettings) {
self.addOperation(.UpdateGlobalNotificationSettings(subject, notificationSettings))
}
mutating func addHole(_ messageId: MessageId) {
@@ -284,8 +298,12 @@ struct AccountMutableState {
self.state = state
case let .UpdateChannelState(peerId, channelState):
self.channelStates[peerId] = channelState
case let .UpdatePeerNotificationSettings(peerId, notificationSettings):
self.peerNotificationSettings[peerId] = notificationSettings
case let .UpdateNotificationSettings(subject, notificationSettings):
if case let .peer(peerId) = subject {
self.peerNotificationSettings[peerId] = notificationSettings
}
case .UpdateGlobalNotificationSettings:
break
case let .MergeApiChats(chats):
for chat in chats {
if let groupOrChannel = mergeGroupOrChannel(lhs: peers[chat.peerId], rhs: chat) {

View File

@@ -812,11 +812,14 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState,
}
}
case let .updateNotifySettings(apiPeer, apiNotificationSettings):
let notificationSettings = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings)
switch apiPeer {
case let .notifyPeer(peer):
updatedState.updatePeerNotificationSettings(peer.peerId, notificationSettings: notificationSettings)
break
let notificationSettings = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings)
updatedState.updateNotificationSettings(.peer(peer.peerId), notificationSettings: notificationSettings)
case .notifyUsers:
updatedState.updateGlobalNotificationSettings(.privateChats, notificationSettings: MessageNotificationSettings(apiSettings: apiNotificationSettings))
case .notifyChats:
updatedState.updateGlobalNotificationSettings(.groups, notificationSettings: MessageNotificationSettings(apiSettings: apiNotificationSettings))
default:
break
}
@@ -1150,7 +1153,7 @@ private func resolveMissingPeerNotificationSettings(account: Account, state: Acc
var updatedState = state
for pair in peersAndSettings {
if let (peerId, settings) = pair {
updatedState.updatePeerNotificationSettings(peerId, notificationSettings: settings)
updatedState.updateNotificationSettings(.peer(peerId), notificationSettings: settings)
}
}
return updatedState
@@ -1283,6 +1286,42 @@ private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableSt
case let .updateDeleteChannelMessages(_, messages, _, _):
let peerId = peer.id
updatedState.deleteMessages(messages.map({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) }))
case let .updateEditChannelMessage(apiMessage, _, _):
if let message = StoreMessage(apiMessage: apiMessage), case let .Id(messageId) = message.id, messageId.peerId == peerId {
if let preCachedResources = apiMessage.preCachedResources {
for (resource, data) in preCachedResources {
updatedState.addPreCachedResource(resource, data: data)
}
}
var attributes = message.attributes
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
updatedState.editMessage(messageId, message: message.withUpdatedAttributes(attributes))
} else {
Logger.shared.log("State", "Invalid updateEditChannelMessage")
}
case let .updateChannelPinnedMessage(_, id):
updatedState.updateCachedPeerData(peer.id, { current in
let previous: CachedChannelData
if let current = current as? CachedChannelData {
previous = current
} else {
previous = CachedChannelData()
}
return previous.withUpdatedPinnedMessageId(id == 0 ? nil : MessageId(peerId: channelPeerId, namespace: Namespaces.Message.Cloud, id: id))
})
case let .updateChannelReadMessagesContents(_, messages):
updatedState.addReadMessagesContents(peer.id, messages)
case let .updateChannelMessageViews(_, id, views):
updatedState.addUpdateMessageImpressionCount(id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id), count: views)
case let .updateChannelWebPage(_, apiWebpage, _, _):
switch apiWebpage {
case let .webPageEmpty(id):
updatedState.updateMedia(MediaId(namespace: Namespaces.Media.CloudWebpage, id: id), media: nil)
default:
if let webpage = telegramMediaWebpageFromApiWebpage(apiWebpage) {
updatedState.updateMedia(webpage.webpageId, media: webpage)
}
}
default:
break
}
@@ -1433,7 +1472,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
var currentAddMessages: OptimizeAddMessagesState?
for operation in operations {
switch operation {
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ResetReadState, .ResetMessageTagSummary, .UpdatePeerNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack:
case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ResetReadState, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack:
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
}
@@ -1526,8 +1565,38 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, modifier: Modif
modifier.setState(currentState.changedState(state))
case let .UpdateChannelState(peerId, channelState):
modifier.setPeerChatState(peerId, state: channelState)
case let .UpdatePeerNotificationSettings(peerId, notificationSettings):
modifier.updateCurrentPeerNotificationSettings([peerId: notificationSettings])
case let .UpdateNotificationSettings(subject, notificationSettings):
switch subject {
case let .peer(peerId):
modifier.updateCurrentPeerNotificationSettings([peerId: notificationSettings])
}
case let .UpdateGlobalNotificationSettings(subject, notificationSettings):
switch subject {
case .privateChats:
modifier.updatePreferencesEntry(key: PreferencesKeys.globalNotifications, { current in
var previous: GlobalNotificationSettings
if let current = current as? GlobalNotificationSettings {
previous = current
} else {
previous = GlobalNotificationSettings.defaultSettings
}
return GlobalNotificationSettings(toBeSynchronized: previous.toBeSynchronized, remote: previous.remote.withUpdatedPrivateChats { _ in
return notificationSettings
})
})
case .groups:
modifier.updatePreferencesEntry(key: PreferencesKeys.globalNotifications, { current in
var previous: GlobalNotificationSettings
if let current = current as? GlobalNotificationSettings {
previous = current
} else {
previous = GlobalNotificationSettings.defaultSettings
}
return GlobalNotificationSettings(toBeSynchronized: previous.toBeSynchronized, remote: previous.remote.withUpdatedGroupChats { _ in
return notificationSettings
})
})
}
case let .AddHole(messageId):
modifier.addHole(messageId)
case let .MergeApiChats(chats):

View File

@@ -456,7 +456,7 @@ public final class AccountStateManager {
let signal = self.account.postbox.modify { modifier -> [Message] in
var messages: [Message] = []
for id in events.addedIncomingMessageIds {
let (message, notify) = messageForNotification(modifier: modifier, id: id, alwaysReturnMessage: false)
let (message, notify, _, _) = messageForNotification(modifier: modifier, id: id, alwaysReturnMessage: false)
if let message = message, notify {
messages.append(message)
}
@@ -680,12 +680,19 @@ public final class AccountStateManager {
}
}
public func messageForNotification(modifier: Modifier, id: MessageId, alwaysReturnMessage: Bool) -> (message: Message?, notify: Bool) {
public func messageForNotification(modifier: Modifier, id: MessageId, alwaysReturnMessage: Bool) -> (message: Message?, notify: Bool, sound: PeerMessageSound, displayContents: Bool) {
var notify = true
var sound: PeerMessageSound = .bundledModern(id: 0)
var displayContents = true
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
if let notificationSettings = modifier.getPeerNotificationSettings(id.peerId) as? TelegramPeerNotificationSettings {
var notificationPeerId = id.peerId
if let peer = modifier.getPeer(id.peerId), let associatedPeerId = peer.associatedPeerId {
notificationPeerId = associatedPeerId
}
if let notificationSettings = modifier.getPeerNotificationSettings(notificationPeerId) as? TelegramPeerNotificationSettings {
switch notificationSettings.muteState {
case let .muted(until):
if until >= timestamp {
@@ -694,8 +701,26 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu
case .unmuted:
break
}
var defaultSound: PeerMessageSound = .bundledModern(id: 0)
if let globalNotificationSettings = modifier.getPreferencesEntry(key: PreferencesKeys.globalNotifications) as? GlobalNotificationSettings {
if id.peerId.namespace == Namespaces.Peer.CloudUser {
defaultSound = globalNotificationSettings.effective.privateChats.sound
displayContents = globalNotificationSettings.effective.privateChats.displayPreviews
} else if id.peerId.namespace == Namespaces.Peer.SecretChat {
defaultSound = globalNotificationSettings.effective.privateChats.sound
displayContents = false
} else {
defaultSound = globalNotificationSettings.effective.groupChats.sound
displayContents = globalNotificationSettings.effective.groupChats.displayPreviews
}
}
if case .default = notificationSettings.messageSound {
sound = defaultSound
} else {
sound = notificationSettings.messageSound
}
} else {
Logger.shared.log("AccountStateManager", "notification settings for \(id.peerId) are undefined")
Logger.shared.log("AccountStateManager", "notification settings for \(notificationPeerId) are undefined")
}
let message = modifier.getMessage(id)
@@ -703,7 +728,7 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu
if let channel = message.peers[message.id.peerId] as? TelegramChannel {
switch channel.participationStatus {
case .kicked, .left:
return (nil, false)
return (nil, false, sound, false)
case .member:
break
}
@@ -723,14 +748,12 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu
}
if notify || message.personal {
return (message, isUnread)
return (message, isUnread, sound, displayContents)
} else {
return (alwaysReturnMessage ? message : nil, false)
return (alwaysReturnMessage ? message : nil, false, sound, displayContents)
}
} else {
Logger.shared.log("AccountStateManager", "notification message doesn't exist")
return (nil, false)
return (nil, false, .bundledModern(id: 0), false)
}
}

View File

@@ -35,6 +35,57 @@ public func togglePeerMuted(account: Account, peerId: PeerId) -> Signal<Void, No
}
}
public func mutePeer(account: Account, peerId: PeerId, for interval: Int32) -> Signal<Void, NoError> {
return account.postbox.modify { modifier -> Void in
if let peer = modifier.getPeer(peerId) {
var notificationPeerId = peerId
if let associatedPeerId = peer.associatedPeerId {
notificationPeerId = associatedPeerId
}
let currentSettings = modifier.getPeerNotificationSettings(notificationPeerId) as? TelegramPeerNotificationSettings
let previousSettings: TelegramPeerNotificationSettings
if let currentSettings = currentSettings {
previousSettings = currentSettings
} else {
previousSettings = TelegramPeerNotificationSettings.defaultSettings
}
let absoluteUntil: Int32
if interval == Int32.max {
absoluteUntil = Int32.max
} else {
absoluteUntil = Int32(Date().timeIntervalSince1970) + interval
}
let updatedSettings = previousSettings.withUpdatedMuteState(.muted(until: absoluteUntil))
modifier.updatePendingPeerNotificationSettings(peerId: peerId, settings: updatedSettings)
}
}
}
public func updatePeerNotificationSoundInteractive(account: Account, peerId: PeerId, sound: PeerMessageSound) -> Signal<Void, NoError> {
return account.postbox.modify { modifier -> Void in
if let peer = modifier.getPeer(peerId) {
var notificationPeerId = peerId
if let associatedPeerId = peer.associatedPeerId {
notificationPeerId = associatedPeerId
}
let currentSettings = modifier.getPeerNotificationSettings(notificationPeerId) as? TelegramPeerNotificationSettings
let previousSettings: TelegramPeerNotificationSettings
if let currentSettings = currentSettings {
previousSettings = currentSettings
} else {
previousSettings = TelegramPeerNotificationSettings.defaultSettings
}
let updatedSettings = previousSettings.withUpdatedMessageSound(sound)
modifier.updatePendingPeerNotificationSettings(peerId: peerId, settings: updatedSettings)
}
}
}
public func changePeerNotificationSettings(account: Account, peerId: PeerId, settings: TelegramPeerNotificationSettings) -> Signal<Void, NoError> {
return account.postbox.modify { modifier -> Void in
modifier.updatePendingPeerNotificationSettings(peerId: peerId, settings: settings)

View File

@@ -54,6 +54,9 @@ private func hashForCountAndIds(count: Int32, ids: [Int32]) -> Int32 {
}
func manageContacts(network: Network, postbox: Postbox) -> Signal<Void, NoError> {
#if DEBUG
return .never()
#endif
let initialContactPeerIdsHash = postbox.contactPeerIdsView()
|> take(1)
|> map { view -> Int32 in

View File

@@ -104,6 +104,8 @@ public struct GlobalNotificationSettings: PreferencesEntry, Equatable {
let toBeSynchronized: GlobalNotificationSettingsSet?
let remote: GlobalNotificationSettingsSet
public static var defaultSettings: GlobalNotificationSettings = GlobalNotificationSettings(toBeSynchronized: nil, remote: GlobalNotificationSettingsSet.defaultSettings)
public var effective: GlobalNotificationSettingsSet {
if let toBeSynchronized = self.toBeSynchronized {
return toBeSynchronized
@@ -149,3 +151,14 @@ public struct GlobalNotificationSettings: PreferencesEntry, Equatable {
}
}
}
extension MessageNotificationSettings {
init(apiSettings: Api.PeerNotifySettings) {
switch apiSettings {
case .peerNotifySettingsEmpty:
self = .defaultSettings
case let .peerNotifySettings(flags, muteUntil, sound):
self = MessageNotificationSettings(enabled: muteUntil == 0, displayPreviews: (flags & (1 << 0)) != 0, sound: PeerMessageSound(apiSound: sound))
}
}
}

View File

@@ -102,37 +102,23 @@ private func pushPeerNotificationSettings(postbox: Postbox, network: Network, pe
}
if let notificationPeer = modifier.getPeer(notificationPeerId), let inputPeer = apiInputPeer(notificationPeer), let settings = settings as? TelegramPeerNotificationSettings {
return network.request(Api.functions.account.getNotifySettings(peer: .inputNotifyPeer(peer: inputPeer)))
let muteUntil: Int32
switch settings.muteState {
case let .muted(until):
muteUntil = until
case .unmuted:
muteUntil = 0
}
let sound: String = settings.messageSound.apiSound
let inputSettings = Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: Int32(1 << 0), muteUntil: muteUntil, sound: sound)
return network.request(Api.functions.account.updateNotifySettings(peer: .inputNotifyPeer(peer: inputPeer), settings: inputSettings))
|> retryRequest
|> mapToSignal { result -> Signal<Void, NoError> in
let current = TelegramPeerNotificationSettings(apiSettings: result)
let muteUntil: Int32
switch settings.muteState {
case let .muted(until):
muteUntil = until
case .unmuted:
muteUntil = 0
}
let sound: String
switch current.messageSound {
case .none:
sound = ""
case let .bundledModern(id):
sound = "\(id)"
case let .bundledClassic(id):
sound = "\(id + 12)"
}
let inputSettings = Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: Int32(1 << 0), muteUntil: muteUntil, sound: sound)
return network.request(Api.functions.account.updateNotifySettings(peer: .inputNotifyPeer(peer: inputPeer), settings: inputSettings))
|> retryRequest
|> mapToSignal { result -> Signal<Void, NoError> in
return postbox.modify { modifier -> Void in
modifier.updateCurrentPeerNotificationSettings([notificationPeerId: settings])
if let pending = modifier.getPendingPeerNotificationSettings(peerId), pending.isEqual(to: settings) {
modifier.updatePendingPeerNotificationSettings(peerId: peerId, settings: nil)
}
}
return postbox.modify { modifier -> Void in
modifier.updateCurrentPeerNotificationSettings([notificationPeerId: settings])
if let pending = modifier.getPendingPeerNotificationSettings(peerId), pending.isEqual(to: settings) {
modifier.updatePendingPeerNotificationSettings(peerId: peerId, settings: nil)
}
}
}
} else {

View File

@@ -45,7 +45,28 @@ public func recentPeers(account: Account) -> Signal<[Peer], NoError> {
return .complete()
}
}
return cachedPeers |> then(updatedRemotePeers |> filter({ !$0.isEmpty }))
return cachedPeers |> then(updatedRemotePeers |> filter({ !$0.isEmpty }))
}
public func removeRecentPeer(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
return account.postbox.modify { modifier -> Signal<Void, NoError> in
var peerIds = modifier.getRecentPeerIds()
if let index = peerIds.index(of: peerId) {
peerIds.remove(at: index)
modifier.replaceRecentPeerIds(peerIds)
}
if let peer = modifier.getPeer(peerId), let apiPeer = apiInputPeer(peer) {
return account.network.request(Api.functions.contacts.resetTopPeerRating(category: .topPeerCategoryCorrespondents, peer: apiPeer))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)
}
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}
} else {
return .complete()
}
} |> switchToLatest
}
public func managedRecentlyUsedInlineBots(postbox: Postbox, network: Network) -> Signal<Void, NoError> {

View File

@@ -54,10 +54,12 @@ private enum PeerMessageSoundValue: Int32 {
case none
case bundledModern
case bundledClassic
case `default`
}
public enum PeerMessageSound: Equatable {
case none
case `default`
case bundledModern(id: Int32)
case bundledClassic(id: Int32)
@@ -69,6 +71,8 @@ public enum PeerMessageSound: Equatable {
return .bundledModern(id: decoder.decodeInt32ForKey("s.i", orElse: 0))
case PeerMessageSoundValue.bundledClassic.rawValue:
return .bundledClassic(id: decoder.decodeInt32ForKey("s.i", orElse: 0))
case PeerMessageSoundValue.default.rawValue:
return .default
default:
assertionFailure()
return .bundledModern(id: 0)
@@ -85,6 +89,8 @@ public enum PeerMessageSound: Equatable {
case let .bundledClassic(id):
encoder.encodeInt32(PeerMessageSoundValue.bundledClassic.rawValue, forKey: "s.v")
encoder.encodeInt32(id, forKey: "s.i")
case .default:
encoder.encodeInt32(PeerMessageSoundValue.default.rawValue, forKey: "s.v")
}
}
@@ -108,6 +114,12 @@ public enum PeerMessageSound: Equatable {
} else {
return false
}
case .default:
if case .default = rhs {
return true
} else {
return false
}
}
}
}
@@ -117,7 +129,7 @@ public final class TelegramPeerNotificationSettings: PeerNotificationSettings, E
public let messageSound: PeerMessageSound
public static var defaultSettings: TelegramPeerNotificationSettings {
return TelegramPeerNotificationSettings(muteState: .unmuted, messageSound: .bundledModern(id: 0))
return TelegramPeerNotificationSettings(muteState: .unmuted, messageSound: .default)
}
public var isRemovedFromTotalUnreadCount: Bool {
@@ -178,22 +190,27 @@ extension TelegramPeerNotificationSettings {
extension PeerMessageSound {
init(apiSound: String) {
var rawApiSound = apiSound
if let index = rawApiSound.index(of: ".") {
rawApiSound = String(rawApiSound[..<index])
}
let parsedSound: PeerMessageSound
if apiSound == "default" {
parsedSound = .bundledModern(id: 0)
} else if apiSound == "" || apiSound == "0" {
if rawApiSound == "default" {
parsedSound = .default
} else if rawApiSound == "" || rawApiSound == "0" {
parsedSound = .none
} else {
let soundId: Int32
if let id = Int32(apiSound) {
if let id = Int32(rawApiSound) {
soundId = id
} else {
soundId = 1
soundId = 100
}
if soundId >= 1 && soundId < 13 {
parsedSound = .bundledModern(id: soundId - 1)
} else if soundId >= 13 && soundId <= 20 {
parsedSound = .bundledClassic(id: soundId - 13)
if soundId >= 100 && soundId <= 111 {
parsedSound = .bundledModern(id: soundId - 100)
} else if soundId >= 2 && soundId <= 9 {
parsedSound = .bundledClassic(id: soundId - 2)
} else {
parsedSound = .bundledModern(id: 0)
}
@@ -205,14 +222,16 @@ extension PeerMessageSound {
switch self {
case .none:
return ""
case .default:
return "default"
case let .bundledModern(id):
if id == 0 {
return "default"
} else {
return "\(id + 1)"
return "\(id + 100)"
}
case let .bundledClassic(id):
return "\(id + 13)"
return "\(id + 2)"
}
}
}