From 130c9264e1ee1654f719524ae9627a1d9732b497 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 7 Nov 2022 18:47:20 +0400 Subject: [PATCH 1/2] Topic improvements --- .../Sources/ChatListController.swift | 4 +- .../Sources/ChatListControllerNode.swift | 9 ++- submodules/Postbox/Sources/Postbox.swift | 10 ++-- .../Sources/ApiUtils/TelegramChannel.swift | 8 +-- .../Sources/State/AccountViewTracker.swift | 3 +- .../ChatTitleView/Sources/ChatTitleView.swift | 4 +- .../TelegramUI/Sources/ChatController.swift | 57 ++++++++++++++++--- .../Sources/ChatHistoryEntriesForView.swift | 2 +- .../ChatInterfaceStateInputPanels.swift | 4 +- .../Sources/ChatMessageBubbleItemNode.swift | 4 +- .../Sources/PeerInfo/PeerInfoData.swift | 4 +- 11 files changed, 76 insertions(+), 33 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index e8c19ebc81..6ad45c6e87 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -524,9 +524,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController default: let actionTitle: String if channel.flags.contains(.requestToJoin) { - actionTitle = strongSelf.presentationData.strings.Channel_JoinChannel - } else { actionTitle = strongSelf.presentationData.strings.Group_ApplyToJoin + } else { + actionTitle = strongSelf.presentationData.strings.Channel_JoinChannel } strongSelf.setToolbar(Toolbar(leftAction: nil, rightAction: nil, middleAction: ToolbarAction(title: actionTitle, isEnabled: true)), transition: .animated(duration: 0.4, curve: .spring)) } diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 7d359f0160..be384f910c 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -1257,6 +1257,7 @@ final class ChatListControllerNode: ASDisplayNode { insets.top += navigationBarHeight insets.left += layout.safeInsets.left insets.right += layout.safeInsets.right + var additionalPanelInset: CGFloat = 0.0 if let toolbar = self.toolbar { var tabBarHeight: CGFloat @@ -1268,9 +1269,11 @@ final class ChatListControllerNode: ASDisplayNode { if !layout.safeInsets.left.isZero { tabBarHeight = 34.0 + bottomInset insets.bottom += 34.0 + additionalPanelInset += 34.0 } else { tabBarHeight = 49.0 + bottomInset insets.bottom += 49.0 + additionalPanelInset += 49.0 } let tabBarFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - tabBarHeight), size: CGSize(width: layout.size.width, height: tabBarHeight)) @@ -1302,11 +1305,13 @@ final class ChatListControllerNode: ASDisplayNode { } var childrenLayout = layout - childrenLayout.intrinsicInsets = UIEdgeInsets(top: visualNavigationHeight, left: childrenLayout.intrinsicInsets.left, bottom: childrenLayout.intrinsicInsets.bottom, right: childrenLayout.intrinsicInsets.right) + childrenLayout.intrinsicInsets = UIEdgeInsets(top: visualNavigationHeight, left: childrenLayout.intrinsicInsets.left, bottom: childrenLayout.intrinsicInsets.bottom + additionalPanelInset, right: childrenLayout.intrinsicInsets.right) self.controller?.presentationContext.containerLayoutUpdated(childrenLayout, transition: transition) transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - self.containerNode.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: self.isReorderingFilters, isEditing: self.isEditing, transition: transition) + var containerLayout = layout + containerLayout.intrinsicInsets.bottom += additionalPanelInset + self.containerNode.update(layout: containerLayout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: self.isReorderingFilters, isEditing: self.isEditing, transition: transition) transition.updateFrame(node: self.inlineTabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - layout.intrinsicInsets.bottom - 8.0 - 40.0), size: CGSize(width: layout.size.width, height: 40.0))) diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 601f085004..486dab2967 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -1210,7 +1210,7 @@ public enum PostboxResult { case error } -func debugSaveState(basePath:String, name: String) { +func debugSaveState(basePath: String, name: String) { let path = basePath + name let _ = try? FileManager.default.removeItem(atPath: path) do { @@ -1220,7 +1220,7 @@ func debugSaveState(basePath:String, name: String) { } } -func debugRestoreState(basePath:String, name: String) { +func debugRestoreState(basePath: String, name: String) { let path = basePath + name if FileManager.default.fileExists(atPath: path) { let _ = try? FileManager.default.removeItem(atPath: basePath) @@ -1272,8 +1272,8 @@ public func openPostbox(basePath: String, seedConfiguration: SeedConfiguration, } #if DEBUG - //debugSaveState(basePath: basePath, name: "previous1") - //debugRestoreState(basePath: basePath, name: "previous1") + //debugSaveState(basePath: basePath + "/db", name: "previous1") + debugRestoreState(basePath: basePath + "/db", name: "previous1") #endif let startTime = CFAbsoluteTimeGetCurrent() @@ -2438,6 +2438,8 @@ final class PostboxImpl { for id in messageIds { if self.messageHistoryIndexTable.exists(id) { filteredIds.insert(id) + } else { + assert(true) } } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramChannel.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramChannel.swift index fafb10a228..2aa010ea94 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramChannel.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramChannel.swift @@ -78,13 +78,7 @@ public extension TelegramChannel { if let adminRights = self.adminRights, adminRights.rights.contains(.canManageTopics) { return true } - if let bannedRights = self.bannedRights, bannedRights.flags.contains(.banManageTopics) { - return false - } - if let defaultBannedRights = self.defaultBannedRights, defaultBannedRights.flags.contains(.banManageTopics) { - return false - } - return true + return false case .createTopics: if self.flags.contains(.isCreator) { return true diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index 3f6babaeae..35b78402c4 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -1729,7 +1729,8 @@ public final class AccountViewTracker { tagMask: tagMask, appendMessagesFromTheSameGroup: false, namespaces: .not(Namespaces.Message.allScheduled), - orderStatistics: orderStatistics + orderStatistics: orderStatistics, + additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData) ) } diff --git a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift index 71ce323559..387eb30741 100644 --- a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift @@ -728,12 +728,12 @@ public final class ChatTitleView: UIView, NavigationBarTitleView { titleTransition = .immediate } - let titleSideInset: CGFloat = 3.0 + let titleSideInset: CGFloat = 6.0 var titleFrame: CGRect if size.height > 40.0 { var titleSize = self.titleTextNode.updateLayout(size: CGSize(width: clearBounds.width - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0, height: size.height), animated: titleTransition.isAnimated) titleSize.width += credibilityIconWidth - let activitySize = self.activityNode.updateLayout(clearBounds.size, alignment: .center) + let activitySize = self.activityNode.updateLayout(CGSize(width: clearBounds.size.width - titleSideInset * 2.0, height: clearBounds.size.height), alignment: .center) let titleInfoSpacing: CGFloat = 0.0 if activitySize.height.isZero { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index d276c26b59..2624561041 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -4924,7 +4924,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let avatarContent: EmojiStatusComponent.Content if let fileId = threadInfo.icon { - avatarContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 48.0, height: 48.0), placeholderColor: strongSelf.presentationData.theme.list.mediaPlaceholderColor, themeColor: strongSelf.presentationData.theme.list.itemAccentColor, loopMode: .count(2)) + avatarContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 48.0, height: 48.0), placeholderColor: strongSelf.presentationData.theme.list.mediaPlaceholderColor, themeColor: strongSelf.presentationData.theme.list.itemAccentColor, loopMode: .count(1)) } else { avatarContent = .topic(title: String(threadInfo.title.prefix(1)), color: threadInfo.iconColor, size: CGSize(width: 32.0, height: 32.0)) } @@ -4933,7 +4933,37 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatTitleView?.titleContent = .replyThread(type: replyThreadType, count: count) } + var wasGroupChannel: Bool? + if let previousPeerView = strongSelf.peerView, let info = (previousPeerView.peers[previousPeerView.peerId] as? TelegramChannel)?.info { + if case .group = info { + wasGroupChannel = true + } else { + wasGroupChannel = false + } + } + var isGroupChannel: Bool? + if let info = (peerView.peers[peerView.peerId] as? TelegramChannel)?.info { + if case .group = info { + isGroupChannel = true + } else { + isGroupChannel = false + } + } let firstTime = strongSelf.peerView == nil + + if wasGroupChannel != isGroupChannel { + if let isGroupChannel = isGroupChannel, isGroupChannel { + let (recentDisposable, _) = strongSelf.context.peerChannelMemberCategoriesContextsManager.recent(engine: strongSelf.context.engine, postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) + let (adminsDisposable, _) = strongSelf.context.peerChannelMemberCategoriesContextsManager.admins(engine: strongSelf.context.engine, postbox: strongSelf.context.account.postbox, network: strongSelf.context.account.network, accountPeerId: context.account.peerId, peerId: peerView.peerId, updated: { _ in }) + let disposable = DisposableSet() + disposable.add(recentDisposable) + disposable.add(adminsDisposable) + strongSelf.chatAdditionalDataDisposable.set(disposable) + } else { + strongSelf.chatAdditionalDataDisposable.set(nil) + } + } + strongSelf.peerView = peerView strongSelf.threadInfo = messageAndTopic.threadData?.info @@ -5679,6 +5709,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G struct ReferenceMessage { var id: MessageId + var minId: MessageId var isScrolled: Bool } @@ -5692,18 +5723,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.chatDisplayNode.historyNode.topVisibleMessageRange.get() ) |> map { scrolledToMessageId, topVisibleMessageRange -> ReferenceMessage? in - let topVisibleMessage: MessageId? - topVisibleMessage = topVisibleMessageRange?.upperBound.id + let bottomVisibleMessage = topVisibleMessageRange?.lowerBound.id + let topVisibleMessage = topVisibleMessageRange?.upperBound.id if let scrolledToMessageId = scrolledToMessageId { - if let topVisibleMessage = topVisibleMessage { + if let topVisibleMessage, let bottomVisibleMessage { if scrolledToMessageId.allowedReplacementDirection.contains(.up) && topVisibleMessage < scrolledToMessageId.id { - return ReferenceMessage(id: topVisibleMessage, isScrolled: false) + return ReferenceMessage(id: topVisibleMessage, minId: bottomVisibleMessage, isScrolled: false) } } - return ReferenceMessage(id: scrolledToMessageId.id, isScrolled: true) - } else if let topVisibleMessage = topVisibleMessage { - return ReferenceMessage(id: topVisibleMessage, isScrolled: false) + return ReferenceMessage(id: scrolledToMessageId.id, minId: scrolledToMessageId.id, isScrolled: true) + } else if let topVisibleMessage, let bottomVisibleMessage { + return ReferenceMessage(id: topVisibleMessage, minId: bottomVisibleMessage, isScrolled: false) } else { return nil } @@ -5917,6 +5948,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } + if threadId != nil { + if referenceMessage.minId <= topMessage.message.id { + return nil + } + } return ChatPinnedMessage(message: topMessage.message, index: index, totalCount: pinnedMessages.totalCount, topMessageId: topMessageId) } @@ -5940,6 +5976,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G matches = true } if matches { + if threadId != nil, let referenceMessage { + if referenceMessage.minId <= entry.message.id { + continue + } + } message = ChatPinnedMessage(message: entry.message, index: entry.index, totalCount: pinnedMessages.totalCount, topMessageId: topMessageId) } } diff --git a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift index e8845b4aa9..953eaae337 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift @@ -35,7 +35,7 @@ func chatHistoryEntriesForView( var adminRanks: [PeerId: CachedChannelAdminRank] = [:] var stickersEnabled = true var channelPeer: Peer? - if case let .peer(peerId) = location, peerId.namespace == Namespaces.Peer.CloudChannel { + if let peerId = location.peerId, peerId.namespace == Namespaces.Peer.CloudChannel { for additionalEntry in view.additionalData { if case let .cacheEntry(id, data) = additionalEntry { if id == cachedChannelAdminRanksEntryId(peerId: peerId), let data = data?.get(CachedChannelAdminRanks.self) { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift index 2bb9fa07dd..83ad6c6d73 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift @@ -151,8 +151,8 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState case .member: isMember = true case .left: - if case .replyThread = chatPresentationInterfaceState.chatLocation { - if !channel.flags.contains(.joinToSend) { + if case let .replyThread(message) = chatPresentationInterfaceState.chatLocation { + if !message.isForumPost && !channel.flags.contains(.joinToSend) { isMember = true } } diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 130feae189..54286842d9 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -1398,8 +1398,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode } var enableAutoRank = false - if let authorRank = authorRank, case .admin = authorRank { - enableAutoRank = true + if case .admin = authorRank { + } else if case .owner = authorRank { } else if authorRank == nil { enableAutoRank = true } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift index 08f846138d..e6626ea776 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift @@ -1211,10 +1211,10 @@ func peerInfoCanEdit(peer: Peer?, threadData: MessageHistoryThreadData?, cachedD } return true } else if let peer = peer as? TelegramChannel { - if peer.flags.contains(.isForum) { + if peer.flags.contains(.isForum), let threadData = threadData { if peer.flags.contains(.isCreator) { return true - } else if let threadData = threadData, threadData.isOwnedByMe { + } else if threadData.isOwnedByMe { return true } else if peer.hasPermission(.manageTopics) { return true From dbb4dc8e123def7939bfac30aa5f40e3b7c3cee6 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 7 Nov 2022 20:12:03 +0400 Subject: [PATCH 2/2] More resilient logs --- .../TelegramVoip/Sources/OngoingCallContext.swift | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/submodules/TelegramVoip/Sources/OngoingCallContext.swift b/submodules/TelegramVoip/Sources/OngoingCallContext.swift index 776b3d71c2..7d5dfdb24b 100644 --- a/submodules/TelegramVoip/Sources/OngoingCallContext.swift +++ b/submodules/TelegramVoip/Sources/OngoingCallContext.swift @@ -741,7 +741,6 @@ public final class OngoingCallContext { return OngoingCallThreadLocalContext.maxLayer() } - private let tempLogFile: EngineTempBoxFile private let tempStatsLogFile: EngineTempBoxFile private var signalingConnectionManager: QueueLocalObject? @@ -774,8 +773,8 @@ public final class OngoingCallContext { self.callSessionManager = callSessionManager self.logPath = logName.isEmpty ? "" : callLogsPath(account: self.account) + "/" + logName + ".log" let logPath = self.logPath - self.tempLogFile = EngineTempBox.shared.tempFile(fileName: "CallLog.txt") - let tempLogPath = self.tempLogFile.path + + let _ = try? FileManager.default.createDirectory(atPath: callLogsPath(account: account), withIntermediateDirectories: true, attributes: nil) self.tempStatsLogFile = EngineTempBox.shared.tempFile(fileName: "CallStats.json") let tempStatsLogPath = self.tempStatsLogFile.path @@ -880,7 +879,7 @@ public final class OngoingCallContext { } } - let context = OngoingCallThreadLocalContextWebrtc(version: version, queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: Data(), key: key, isOutgoing: isOutgoing, connections: filteredConnections, maxLayer: maxLayer, allowP2P: allowP2P, allowTCP: enableTCP, enableStunMarking: enableStunMarking, logPath: tempLogPath, statsLogPath: tempStatsLogPath, sendSignalingData: { [weak callSessionManager] data in + let context = OngoingCallThreadLocalContextWebrtc(version: version, queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtc(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtc(dataSaving), derivedState: Data(), key: key, isOutgoing: isOutgoing, connections: filteredConnections, maxLayer: maxLayer, allowP2P: allowP2P, allowTCP: enableTCP, enableStunMarking: enableStunMarking, logPath: logPath, statsLogPath: tempStatsLogPath, sendSignalingData: { [weak callSessionManager] data in queue.async { guard let strongSelf = self else { return @@ -1068,7 +1067,6 @@ public final class OngoingCallContext { if !logPath.isEmpty { statsLogPath = logPath + ".json" } - let tempLogPath = self.tempLogFile.path let tempStatsLogPath = self.tempStatsLogFile.path self.withContextThenDeallocate { context in @@ -1082,12 +1080,6 @@ public final class OngoingCallContext { outgoing: bytesSentWifi)) updateAccountNetworkUsageStats(account: self.account, category: .call, delta: delta) - if !logPath.isEmpty { - let logsPath = callLogsPath(account: account) - let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil) - let _ = try? FileManager.default.moveItem(atPath: tempLogPath, toPath: logPath) - } - if !statsLogPath.isEmpty { let logsPath = callLogsPath(account: account) let _ = try? FileManager.default.createDirectory(atPath: logsPath, withIntermediateDirectories: true, attributes: nil)