diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 66860712c4..8c93517f1e 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -2512,9 +2512,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController }, action: { action in action.dismissWithResult(.default) - let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: "Topic#\(Int.random(in: 0 ..< 100000)) very long title to fill two lines", iconFileId: nil) + let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: "Topic#\(Int.random(in: 0 ..< 100000))", iconColor: 0, iconFileId: nil) |> deliverOnMainQueue).start(next: { topicId in - let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "First Message", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(topicId)), localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() + let _ = topicId + //let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "First Message", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(topicId)), localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start() }) }))) diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 12996f06d1..cb1f1d70ce 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -1928,10 +1928,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } let avatarIconContent: EmojiStatusComponent.Content - if let fileId = threadInfo.info.icon { + if let fileId = threadInfo.info.icon, fileId != 0 { avatarIconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 40.0, height: 40.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: nil, loopMode: .forever) } else { - avatarIconContent = .topic(title: String(threadInfo.info.title.prefix(1)), colorIndex: Int(clamping: abs(threadInfo.id))) + avatarIconContent = .topic(title: String(threadInfo.info.title.prefix(1)), colorIndex: Int(abs(threadInfo.info.iconColor))) } let avatarIconComponent = EmojiStatusComponent( diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 8a3f3f04d6..c9ece079d2 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -222,7 +222,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-207944868] = { return Api.FileHash.parse_fileHash($0) } dict[-11252123] = { return Api.Folder.parse_folder($0) } dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) } - dict[792599046] = { return Api.ForumTopic.parse_forumTopic($0) } + dict[413771876] = { return Api.ForumTopic.parse_forumTopic($0) } dict[-1107729093] = { return Api.Game.parse_game($0) } dict[-1297942941] = { return Api.GeoPoint.parse_geoPoint($0) } dict[286776671] = { return Api.GeoPoint.parse_geoPointEmpty($0) } @@ -446,9 +446,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[455635795] = { return Api.MessageAction.parse_messageActionSecureValuesSentMe($0) } dict[-1434950843] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) } dict[-1441072131] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) } - dict[1873254060] = { return Api.MessageAction.parse_messageActionTopicCreate($0) } - dict[-2113245653] = { return Api.MessageAction.parse_messageActionTopicEditIcon($0) } - dict[-838130739] = { return Api.MessageAction.parse_messageActionTopicEditTitle($0) } + dict[228168278] = { return Api.MessageAction.parse_messageActionTopicCreate($0) } + dict[-1323849227] = { return Api.MessageAction.parse_messageActionTopicEdit($0) } dict[-1262252875] = { return Api.MessageAction.parse_messageActionWebViewDataSent($0) } dict[1205698681] = { return Api.MessageAction.parse_messageActionWebViewDataSentMe($0) } dict[546203849] = { return Api.MessageEntity.parse_inputMessageEntityMentionName($0) } diff --git a/submodules/TelegramApi/Sources/Api11.swift b/submodules/TelegramApi/Sources/Api11.swift index b6366ce19f..cc64b39a7b 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -1019,9 +1019,8 @@ public extension Api { case messageActionSecureValuesSentMe(values: [Api.SecureValue], credentials: Api.SecureCredentialsEncrypted) case messageActionSetChatTheme(emoticon: String) case messageActionSetMessagesTTL(period: Int32) - case messageActionTopicCreate(flags: Int32, title: String, iconEmojiId: Int64?) - case messageActionTopicEditIcon(emojiDocumentId: Int64) - case messageActionTopicEditTitle(title: String) + case messageActionTopicCreate(flags: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?) + case messageActionTopicEdit(flags: Int32, title: String?, iconEmojiId: Int64?) case messageActionWebViewDataSent(text: String) case messageActionWebViewDataSentMe(text: String, data: String) @@ -1257,25 +1256,22 @@ public extension Api { } serializeInt32(period, buffer: buffer, boxed: false) break - case .messageActionTopicCreate(let flags, let title, let iconEmojiId): + case .messageActionTopicCreate(let flags, let title, let iconColor, let iconEmojiId): if boxed { - buffer.appendInt32(1873254060) + buffer.appendInt32(228168278) } serializeInt32(flags, buffer: buffer, boxed: false) serializeString(title, buffer: buffer, boxed: false) + serializeInt32(iconColor, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {serializeInt64(iconEmojiId!, buffer: buffer, boxed: false)} break - case .messageActionTopicEditIcon(let emojiDocumentId): + case .messageActionTopicEdit(let flags, let title, let iconEmojiId): if boxed { - buffer.appendInt32(-2113245653) + buffer.appendInt32(-1323849227) } - serializeInt64(emojiDocumentId, buffer: buffer, boxed: false) - break - case .messageActionTopicEditTitle(let title): - if boxed { - buffer.appendInt32(-838130739) - } - serializeString(title, buffer: buffer, boxed: false) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt64(iconEmojiId!, buffer: buffer, boxed: false)} break case .messageActionWebViewDataSent(let text): if boxed { @@ -1357,12 +1353,10 @@ public extension Api { return ("messageActionSetChatTheme", [("emoticon", String(describing: emoticon))]) case .messageActionSetMessagesTTL(let period): return ("messageActionSetMessagesTTL", [("period", String(describing: period))]) - case .messageActionTopicCreate(let flags, let title, let iconEmojiId): - return ("messageActionTopicCreate", [("flags", String(describing: flags)), ("title", String(describing: title)), ("iconEmojiId", String(describing: iconEmojiId))]) - case .messageActionTopicEditIcon(let emojiDocumentId): - return ("messageActionTopicEditIcon", [("emojiDocumentId", String(describing: emojiDocumentId))]) - case .messageActionTopicEditTitle(let title): - return ("messageActionTopicEditTitle", [("title", String(describing: title))]) + case .messageActionTopicCreate(let flags, let title, let iconColor, let iconEmojiId): + return ("messageActionTopicCreate", [("flags", String(describing: flags)), ("title", String(describing: title)), ("iconColor", String(describing: iconColor)), ("iconEmojiId", String(describing: iconEmojiId))]) + case .messageActionTopicEdit(let flags, let title, let iconEmojiId): + return ("messageActionTopicEdit", [("flags", String(describing: flags)), ("title", String(describing: title)), ("iconEmojiId", String(describing: iconEmojiId))]) case .messageActionWebViewDataSent(let text): return ("messageActionWebViewDataSent", [("text", String(describing: text))]) case .messageActionWebViewDataSentMe(let text, let data): @@ -1762,35 +1756,33 @@ public extension Api { _1 = reader.readInt32() var _2: String? _2 = parseString(reader) - var _3: Int64? - if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt64() } + var _3: Int32? + _3 = reader.readInt32() + var _4: Int64? + if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt64() } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.MessageAction.messageActionTopicCreate(flags: _1!, title: _2!, iconColor: _3!, iconEmojiId: _4) + } + else { + return nil + } + } + public static func parse_messageActionTopicEdit(_ reader: BufferReader) -> MessageAction? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } + var _3: Int64? + if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt64() } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil if _c1 && _c2 && _c3 { - return Api.MessageAction.messageActionTopicCreate(flags: _1!, title: _2!, iconEmojiId: _3) - } - else { - return nil - } - } - public static func parse_messageActionTopicEditIcon(_ reader: BufferReader) -> MessageAction? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionTopicEditIcon(emojiDocumentId: _1!) - } - else { - return nil - } - } - public static func parse_messageActionTopicEditTitle(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.MessageAction.messageActionTopicEditTitle(title: _1!) + return Api.MessageAction.messageActionTopicEdit(flags: _1!, title: _2, iconEmojiId: _3) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api29.swift b/submodules/TelegramApi/Sources/Api29.swift index d3ad69554b..2232c9c612 100644 --- a/submodules/TelegramApi/Sources/Api29.swift +++ b/submodules/TelegramApi/Sources/Api29.swift @@ -1854,16 +1854,17 @@ public extension Api.functions.channels { } } public extension Api.functions.channels { - static func createForumTopic(flags: Int32, channel: Api.InputChannel, title: String, iconEmojiId: Int64?, randomId: Int64, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func createForumTopic(flags: Int32, channel: Api.InputChannel, title: String, iconColor: Int32?, iconEmojiId: Int64?, randomId: Int64, sendAs: Api.InputPeer?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(1623145417) + buffer.appendInt32(-200539612) serializeInt32(flags, buffer: buffer, boxed: false) channel.serialize(buffer, true) serializeString(title, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(iconColor!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 3) != 0 {serializeInt64(iconEmojiId!, buffer: buffer, boxed: false)} serializeInt64(randomId, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 2) != 0 {sendAs!.serialize(buffer, true)} - return (FunctionDescription(name: "channels.createForumTopic", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("title", String(describing: title)), ("iconEmojiId", String(describing: iconEmojiId)), ("randomId", String(describing: randomId)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + return (FunctionDescription(name: "channels.createForumTopic", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("title", String(describing: title)), ("iconColor", String(describing: iconColor)), ("iconEmojiId", String(describing: iconEmojiId)), ("randomId", String(describing: randomId)), ("sendAs", String(describing: sendAs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in let reader = BufferReader(buffer) var result: Api.Updates? if let signature = reader.readInt32() { @@ -1941,6 +1942,22 @@ public extension Api.functions.channels { }) } } +public extension Api.functions.channels { + static func deleteTopicHistory(channel: Api.InputChannel, topMsgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(876830509) + channel.serialize(buffer, true) + serializeInt32(topMsgId, buffer: buffer, boxed: false) + return (FunctionDescription(name: "channels.deleteTopicHistory", parameters: [("channel", String(describing: channel)), ("topMsgId", String(describing: topMsgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.AffectedHistory? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedHistory? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory + } + return result + }) + } +} public extension Api.functions.channels { static func editAdmin(channel: Api.InputChannel, userId: Api.InputUser, adminRights: Api.ChatAdminRights, rank: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -1994,30 +2011,15 @@ public extension Api.functions.channels { } } public extension Api.functions.channels { - static func editForumIcon(channel: Api.InputChannel, topicId: Int32, emojiDocumentId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func editForumTopic(flags: Int32, channel: Api.InputChannel, topicId: Int32, title: String?, iconEmojiId: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(1439605469) + buffer.appendInt32(-1971370421) + serializeInt32(flags, buffer: buffer, boxed: false) channel.serialize(buffer, true) serializeInt32(topicId, buffer: buffer, boxed: false) - serializeInt64(emojiDocumentId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.editForumIcon", parameters: [("channel", String(describing: channel)), ("topicId", String(describing: topicId)), ("emojiDocumentId", String(describing: emojiDocumentId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in - let reader = BufferReader(buffer) - var result: Api.Updates? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.Updates - } - return result - }) - } -} -public extension Api.functions.channels { - static func editForumTitle(channel: Api.InputChannel, topicId: Int32, title: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { - let buffer = Buffer() - buffer.appendInt32(-2004764239) - channel.serialize(buffer, true) - serializeInt32(topicId, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - return (FunctionDescription(name: "channels.editForumTitle", parameters: [("channel", String(describing: channel)), ("topicId", String(describing: topicId)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 1) != 0 {serializeInt64(iconEmojiId!, buffer: buffer, boxed: false)} + return (FunctionDescription(name: "channels.editForumTopic", parameters: [("flags", String(describing: flags)), ("channel", String(describing: channel)), ("topicId", String(describing: topicId)), ("title", String(describing: title)), ("iconEmojiId", String(describing: iconEmojiId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in let reader = BufferReader(buffer) var result: Api.Updates? if let signature = reader.readInt32() { diff --git a/submodules/TelegramApi/Sources/Api5.swift b/submodules/TelegramApi/Sources/Api5.swift index ab3f199352..f88470e925 100644 --- a/submodules/TelegramApi/Sources/Api5.swift +++ b/submodules/TelegramApi/Sources/Api5.swift @@ -1094,18 +1094,19 @@ public extension Api { } public extension Api { enum ForumTopic: TypeConstructorDescription { - case forumTopic(flags: Int32, id: Int32, date: Int32, title: String, iconEmojiId: Int64?, topMessage: Int32, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, unreadMentionsCount: Int32, unreadReactionsCount: Int32) + case forumTopic(flags: Int32, id: Int32, date: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?, topMessage: Int32, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, unreadMentionsCount: Int32, unreadReactionsCount: Int32, fromId: Api.Peer) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .forumTopic(let flags, let id, let date, let title, let iconEmojiId, let topMessage, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let unreadMentionsCount, let unreadReactionsCount): + case .forumTopic(let flags, let id, let date, let title, let iconColor, let iconEmojiId, let topMessage, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let unreadMentionsCount, let unreadReactionsCount, let fromId): if boxed { - buffer.appendInt32(792599046) + buffer.appendInt32(413771876) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(id, buffer: buffer, boxed: false) serializeInt32(date, buffer: buffer, boxed: false) serializeString(title, buffer: buffer, boxed: false) + serializeInt32(iconColor, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {serializeInt64(iconEmojiId!, buffer: buffer, boxed: false)} serializeInt32(topMessage, buffer: buffer, boxed: false) serializeInt32(readInboxMaxId, buffer: buffer, boxed: false) @@ -1113,14 +1114,15 @@ public extension Api { serializeInt32(unreadCount, buffer: buffer, boxed: false) serializeInt32(unreadMentionsCount, buffer: buffer, boxed: false) serializeInt32(unreadReactionsCount, buffer: buffer, boxed: false) + fromId.serialize(buffer, true) break } } public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .forumTopic(let flags, let id, let date, let title, let iconEmojiId, let topMessage, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let unreadMentionsCount, let unreadReactionsCount): - return ("forumTopic", [("flags", String(describing: flags)), ("id", String(describing: id)), ("date", String(describing: date)), ("title", String(describing: title)), ("iconEmojiId", String(describing: iconEmojiId)), ("topMessage", String(describing: topMessage)), ("readInboxMaxId", String(describing: readInboxMaxId)), ("readOutboxMaxId", String(describing: readOutboxMaxId)), ("unreadCount", String(describing: unreadCount)), ("unreadMentionsCount", String(describing: unreadMentionsCount)), ("unreadReactionsCount", String(describing: unreadReactionsCount))]) + case .forumTopic(let flags, let id, let date, let title, let iconColor, let iconEmojiId, let topMessage, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let unreadMentionsCount, let unreadReactionsCount, let fromId): + return ("forumTopic", [("flags", String(describing: flags)), ("id", String(describing: id)), ("date", String(describing: date)), ("title", String(describing: title)), ("iconColor", String(describing: iconColor)), ("iconEmojiId", String(describing: iconEmojiId)), ("topMessage", String(describing: topMessage)), ("readInboxMaxId", String(describing: readInboxMaxId)), ("readOutboxMaxId", String(describing: readOutboxMaxId)), ("unreadCount", String(describing: unreadCount)), ("unreadMentionsCount", String(describing: unreadMentionsCount)), ("unreadReactionsCount", String(describing: unreadReactionsCount)), ("fromId", String(describing: fromId))]) } } @@ -1133,10 +1135,10 @@ public extension Api { _3 = reader.readInt32() var _4: String? _4 = parseString(reader) - var _5: Int64? - if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt64() } - var _6: Int32? - _6 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Int64? + if Int(_1!) & Int(1 << 0) != 0 {_6 = reader.readInt64() } var _7: Int32? _7 = reader.readInt32() var _8: Int32? @@ -1147,19 +1149,27 @@ public extension Api { _10 = reader.readInt32() var _11: Int32? _11 = reader.readInt32() + var _12: Int32? + _12 = reader.readInt32() + var _13: Api.Peer? + if let signature = reader.readInt32() { + _13 = Api.parse(reader, signature: signature) as? Api.Peer + } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - let _c6 = _6 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil let _c7 = _7 != nil let _c8 = _8 != nil let _c9 = _9 != nil let _c10 = _10 != nil let _c11 = _11 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 { - return Api.ForumTopic.forumTopic(flags: _1!, id: _2!, date: _3!, title: _4!, iconEmojiId: _5, topMessage: _6!, readInboxMaxId: _7!, readOutboxMaxId: _8!, unreadCount: _9!, unreadMentionsCount: _10!, unreadReactionsCount: _11!) + let _c12 = _12 != nil + let _c13 = _13 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 { + return Api.ForumTopic.forumTopic(flags: _1!, id: _2!, date: _3!, title: _4!, iconColor: _5!, iconEmojiId: _6, topMessage: _7!, readInboxMaxId: _8!, readOutboxMaxId: _9!, unreadCount: _10!, unreadMentionsCount: _11!, unreadReactionsCount: _12!, fromId: _13!) } else { return nil diff --git a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index 5a35ab8c71..2aac2e13c8 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift @@ -201,7 +201,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] { } switch action { - case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionTopicCreate, .messageActionTopicEditTitle, .messageActionTopicEditIcon: + case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction, .messageActionBotAllowed, .messageActionSecureValuesSent, .messageActionSecureValuesSentMe, .messageActionContactSignUp, .messageActionGroupCall, .messageActionSetMessagesTTL, .messageActionGroupCallScheduled, .messageActionSetChatTheme, .messageActionChatJoinedByRequest, .messageActionWebViewDataSent, .messageActionWebViewDataSentMe, .messageActionGiftPremium, .messageActionTopicCreate, .messageActionTopicEdit: break case let .messageActionChannelMigrateFrom(_, chatId): result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(chatId))) @@ -680,6 +680,13 @@ extension StoreMessage { } attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId)) } + } else { + switch action { + case .messageActionTopicCreate: + threadId = Int64(id) + default: + break + } } if (flags & (1 << 17)) != 0 { diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift index cd63d4a567..2b85f99fd5 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift @@ -87,12 +87,18 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe return TelegramMediaAction(action: .webViewData(text)) case let .messageActionGiftPremium(currency, amount, months): return TelegramMediaAction(action: .giftPremium(currency: currency, amount: amount, months: months)) - case let .messageActionTopicCreate(_, title, iconEmojiId): - return TelegramMediaAction(action: .topicCreated(title: title, iconFileId: iconEmojiId)) - case let .messageActionTopicEditTitle(title): - return TelegramMediaAction(action: .topicEditTitle(title: title)) - case let .messageActionTopicEditIcon(fileId): - return TelegramMediaAction(action: .topicEditIcon(fileId: fileId == 0 ? nil : fileId)) + case let .messageActionTopicCreate(_, title, iconColor, iconEmojiId): + return TelegramMediaAction(action: .topicCreated(title: title, iconColor: iconColor, iconFileId: iconEmojiId)) + case let .messageActionTopicEdit(_, title, iconEmojiId): + var componenents: [TelegramMediaActionType.ForumTopicEditComponent] = [] + //messageActionTopicEdit#b117a9f5 flags:# title:flags.0?string icon_emoji_id:flags.1?long = MessageAction; + if let title { + componenents.append(.title(title)) + } + if let iconEmojiId { + componenents.append(.iconFileId(iconEmojiId == 0 ? nil : iconEmojiId)) + } + return TelegramMediaAction(action: .topicEdited(components: componenents)) } } diff --git a/submodules/TelegramCore/Sources/ForumChannels.swift b/submodules/TelegramCore/Sources/ForumChannels.swift index 796270697a..3b725b6de3 100644 --- a/submodules/TelegramCore/Sources/ForumChannels.swift +++ b/submodules/TelegramCore/Sources/ForumChannels.swift @@ -8,29 +8,35 @@ public extension EngineMessageHistoryThread { private enum CodingKeys: String, CodingKey { case title case icon + case iconColor } public let title: String public let icon: Int64? + public let iconColor: Int32 public init( title: String, - icon: Int64? + icon: Int64?, + iconColor: Int32 ) { self.title = title self.icon = icon + self.iconColor = iconColor } public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.title = try container.decode(String.self, forKey: .title) self.icon = try container.decodeIfPresent(Int64.self, forKey: .icon) + self.iconColor = try container.decodeIfPresent(Int32.self, forKey: .iconColor) ?? 0 } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(self.title, forKey: .title) try container.encodeIfPresent(self.icon, forKey: .icon) + try container.encode(self.iconColor, forKey: .iconColor) } public static func ==(lhs: Info, rhs: Info) -> Bool { @@ -40,24 +46,31 @@ public extension EngineMessageHistoryThread { if lhs.icon != rhs.icon { return false } + if lhs.iconColor != rhs.iconColor { + return false + } return true } } } -public struct MessageHistoryThreadData: Codable { +public struct MessageHistoryThreadData: Codable, Equatable { + public var creationDate: Int32 + public var author: PeerId public var info: EngineMessageHistoryThread.Info public var incomingUnreadCount: Int32 public var maxIncomingReadId: Int32 public var maxKnownMessageId: Int32 public var maxOutgoingReadId: Int32 + public var unreadMentionCount: Int32 + public var unreadReactionCount: Int32 } public enum CreateForumChannelTopicError { case generic } -func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title: String, iconFileId: Int64?) -> Signal { +func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title: String, iconColor: Int32, iconFileId: Int64?) -> Signal { return account.postbox.transaction { transaction -> Api.InputChannel? in return transaction.getPeer(peerId).flatMap(apiInputChannel) } @@ -70,10 +83,12 @@ func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title: if iconFileId != nil { flags |= (1 << 3) } + flags |= (1 << 0) return account.network.request(Api.functions.channels.createForumTopic( flags: flags, channel: inputChannel, title: title, + iconColor: iconColor, iconEmojiId: iconFileId, randomId: Int64.random(in: Int64.min ..< Int64.max), sendAs: nil @@ -193,16 +208,21 @@ func _internal_loadMessageHistoryThreads(account: Account, peerId: PeerId) -> Si for topic in topics { switch topic { - case let .forumTopic(_, id, _, title, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _, _): + case let .forumTopic(_, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId): let data = MessageHistoryThreadData( + creationDate: date, + author: fromId.peerId, info: EngineMessageHistoryThread.Info( title: title, - icon: iconEmojiId + icon: iconEmojiId == 0 ? nil : iconEmojiId, + iconColor: iconColor ), incomingUnreadCount: unreadCount, maxIncomingReadId: readInboxMaxId, maxKnownMessageId: topMessage, - maxOutgoingReadId: readOutboxMaxId + maxOutgoingReadId: readOutboxMaxId, + unreadMentionCount: unreadMentionsCount, + unreadReactionCount: unreadReactionsCount ) guard let info = CodableEntry(data) else { continue diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 20ac73dd48..0c5d856d68 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1694,17 +1694,26 @@ func resolveForumThreads(postbox: Postbox, network: Network, state: AccountMutab for topic in topics { switch topic { - case let .forumTopic(_, id, _, title, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _, _): - state.operations.append(.ResetForumTopic(topicId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), data: MessageHistoryThreadData( - info: EngineMessageHistoryThread.Info( - title: title, - icon: iconEmojiId + case let .forumTopic(_, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId): + state.operations.append(.ResetForumTopic( + topicId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), + data: MessageHistoryThreadData( + creationDate: date, + author: fromId.peerId, + info: EngineMessageHistoryThread.Info( + title: title, + icon: iconEmojiId == 0 ? nil : iconEmojiId, + iconColor: iconColor + ), + incomingUnreadCount: unreadCount, + maxIncomingReadId: readInboxMaxId, + maxKnownMessageId: topMessage, + maxOutgoingReadId: readOutboxMaxId, + unreadMentionCount: unreadMentionsCount, + unreadReactionCount: unreadReactionsCount ), - incomingUnreadCount: unreadCount, - maxIncomingReadId: readInboxMaxId, - maxKnownMessageId: topMessage, - maxOutgoingReadId: readOutboxMaxId - ), pts: pts)) + pts: pts + )) } } } @@ -1786,16 +1795,21 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe for topic in topics { switch topic { - case let .forumTopic(_, id, _, title, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, _, _): + case let .forumTopic(_, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId): fetchedChatList.threadInfos[MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)] = MessageHistoryThreadData( + creationDate: date, + author: fromId.peerId, info: EngineMessageHistoryThread.Info( title: title, - icon: iconEmojiId + icon: iconEmojiId == 0 ? nil : iconEmojiId, + iconColor: iconColor ), incomingUnreadCount: unreadCount, maxIncomingReadId: readInboxMaxId, maxKnownMessageId: topMessage, - maxOutgoingReadId: readOutboxMaxId + maxOutgoingReadId: readOutboxMaxId, + unreadMentionCount: unreadMentionsCount, + unreadReactionCount: unreadReactionsCount ) } } @@ -2864,18 +2878,23 @@ func replayFinalState( for media in message.media { if let action = media as? TelegramMediaAction { switch action.action { - case let .topicEditTitle(title): - if var data = transaction.getMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) { - data.info = EngineMessageHistoryThread.Info(title: title, icon: data.info.icon) - if let entry = CodableEntry(data) { - transaction.setMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId, info: entry) + case let .topicEdited(components): + if let initialData = transaction.getMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) { + var data = initialData + + for component in components { + switch component { + case let .title(title): + data.info = EngineMessageHistoryThread.Info(title: title, icon: data.info.icon, iconColor: data.info.iconColor) + case let .iconFileId(fileId): + data.info = EngineMessageHistoryThread.Info(title: data.info.title, icon: fileId == 0 ? nil : fileId, iconColor: data.info.iconColor) + } } - } - case let .topicEditIcon(fileId): - if var data = transaction.getMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) { - data.info = EngineMessageHistoryThread.Info(title: data.info.title, icon: fileId == 0 ? nil : fileId) - if let entry = CodableEntry(data) { - transaction.setMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId, info: entry) + + if data != initialData { + if let entry = CodableEntry(data) { + transaction.setMessageHistoryThreadInfo(peerId: id.peerId, threadId: threadId, info: entry) + } } } default: diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift index e7e371272f..34f05f42ef 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift @@ -24,6 +24,38 @@ public enum SentSecureValueType: Int32 { } public enum TelegramMediaActionType: PostboxCoding, Equatable { + public enum ForumTopicEditComponent: PostboxCoding, Equatable { + case title(String) + case iconFileId(Int64?) + + public init(decoder: PostboxDecoder) { + switch decoder.decodeInt32ForKey("_t", orElse: 0) { + case 0: + self = .title(decoder.decodeStringForKey("title", orElse: "")) + case 1: + self = .iconFileId(decoder.decodeOptionalInt64ForKey("fileId")) + default: + assertionFailure() + self = .title("") + } + } + + public func encode(_ encoder: PostboxEncoder) { + switch self { + case let .title(title): + encoder.encodeInt32(0, forKey: "_t") + encoder.encodeString(title, forKey: "title") + case let .iconFileId(fileId): + encoder.encodeInt32(1, forKey: "_t") + if let fileId = fileId { + encoder.encodeInt64(fileId, forKey: "fileId") + } else { + encoder.encodeNil(forKey: "fileId") + } + } + } + } + case unknown case groupCreated(title: String) case addedMembers(peerIds: [PeerId]) @@ -52,9 +84,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { case joinedByRequest case webViewData(String) case giftPremium(currency: String, amount: Int64, months: Int32) - case topicCreated(title: String, iconFileId: Int64?) - case topicEditTitle(title: String) - case topicEditIcon(fileId: Int64?) + case topicCreated(title: String, iconColor: Int32, iconFileId: Int64?) + case topicEdited(components: [ForumTopicEditComponent]) public init(decoder: PostboxDecoder) { let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0) @@ -126,11 +157,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { case 27: self = .giftPremium(currency: decoder.decodeStringForKey("currency", orElse: ""), amount: decoder.decodeInt64ForKey("amount", orElse: 0), months: decoder.decodeInt32ForKey("months", orElse: 0)) case 28: - self = .topicCreated(title: decoder.decodeStringForKey("t", orElse: ""), iconFileId: decoder.decodeOptionalInt64ForKey("fid")) + self = .topicCreated(title: decoder.decodeStringForKey("title", orElse: ""), iconColor: decoder.decodeInt32ForKey("iconColor", orElse: 0), iconFileId: decoder.decodeOptionalInt64ForKey("iconFileId")) case 29: - self = .topicEditTitle(title: decoder.decodeStringForKey("t", orElse: "")) - case 30: - self = .topicEditIcon(fileId: decoder.decodeOptionalInt64ForKey("fid")) + self = .topicEdited(components: decoder.decodeObjectArrayWithDecoderForKey("components")) default: self = .unknown } @@ -260,24 +289,18 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { encoder.encodeString(currency, forKey: "currency") encoder.encodeInt64(amount, forKey: "amount") encoder.encodeInt32(months, forKey: "months") - case let .topicCreated(title, iconFileId): + case let .topicCreated(title, iconColor, iconFileId): encoder.encodeInt32(28, forKey: "_rawValue") - encoder.encodeString(title, forKey: "t") - if let fileId = iconFileId { - encoder.encodeInt64(fileId, forKey: "fid") + encoder.encodeString(title, forKey: "title") + encoder.encodeInt32(iconColor, forKey: "iconColor") + if let iconFileId = iconFileId { + encoder.encodeInt64(iconFileId, forKey: "iconFileId") } else { - encoder.encodeNil(forKey: "fid") + encoder.encodeNil(forKey: "iconFileId") } - case let .topicEditTitle(title): + case let .topicEdited(components): encoder.encodeInt32(29, forKey: "_rawValue") - encoder.encodeString(title, forKey: "t") - case let .topicEditIcon(fileId): - encoder.encodeInt32(30, forKey: "_rawValue") - if let fileId = fileId { - encoder.encodeInt64(fileId, forKey: "fid") - } else { - encoder.encodeNil(forKey: "fid") - } + encoder.encodeObjectArray(components, forKey: "components") } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index 9ff693db20..63258f9f9e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -802,8 +802,8 @@ public extension TelegramEngine { return _internal_setChannelForumMode(account: self.account, peerId: id, isForum: isForum) } - public func createForumChannelTopic(id: EnginePeer.Id, title: String, iconFileId: Int64?) -> Signal { - return _internal_createForumChannelTopic(account: self.account, peerId: id, title: title, iconFileId: iconFileId) + public func createForumChannelTopic(id: EnginePeer.Id, title: String, iconColor: Int32, iconFileId: Int64?) -> Signal { + return _internal_createForumChannelTopic(account: self.account, peerId: id, title: title, iconColor: iconColor, iconFileId: iconFileId) } } } diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 534b2a7727..aa7f0e7d11 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -682,13 +682,29 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, case .topicCreated: //TODO:localize attributedString = NSAttributedString(string: "Topic created", font: titleFont, textColor: primaryTextColor) - case let .topicEditTitle(title): + case let .topicEdited(components): //TODO:localize - attributedString = NSAttributedString(string: "Topic renamed to \"\(title)\"", font: titleFont, textColor: primaryTextColor) - case let .topicEditIcon(fileId): - let _ = fileId - //TODO:localize - attributedString = NSAttributedString(string: "Topic icon changed", font: titleFont, textColor: primaryTextColor) + if let title = components.compactMap({ item -> String? in + switch item { + case let .title(title): + return title + default: + return nil + } + }).first { + attributedString = NSAttributedString(string: "Topic renamed to \"\(title)\"", font: titleFont, textColor: primaryTextColor) + } else if let maybeFileId = components.compactMap({ item -> Int64? in + switch item { + case let .iconFileId(id): + return id ?? 0 + default: + return nil + } + }).first { + let _ = maybeFileId + //TODO:localize + attributedString = NSAttributedString(string: "Topic icon changed", font: titleFont, textColor: primaryTextColor) + } case .unknown: attributedString = nil } diff --git a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift index 024a0d8225..2c98f904ce 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift @@ -202,7 +202,7 @@ func chatHistoryEntriesForView( } var addedThreadHead = false - if case let .replyThread(replyThreadMessage) = location, view.earlierId == nil, !view.holeEarlier, !view.isLoading { + if case let .replyThread(replyThreadMessage) = location, !replyThreadMessage.isForumPost, view.earlierId == nil, !view.holeEarlier, !view.isLoading { loop: for entry in view.additionalData { switch entry { case let .message(id, messages) where id == replyThreadMessage.effectiveTopId: