Topic-related fixes

This commit is contained in:
Ali 2022-10-25 19:12:18 +04:00
parent cd949e0542
commit a28ed6a7dc
17 changed files with 149 additions and 94 deletions

View File

@ -8141,6 +8141,7 @@ Sorry for the inconvenience.";
"ChatList.CloseAction" = "Close";
"Channel.EditAdmin.PermissionManageTopics" = "Manage Topics";
"Channel.EditAdmin.PermissionCreateTopics" = "Create Topics";
"ChatList.Search.FilterTopics" = "Topics";
"DialogList.SearchSectionTopics" = "Topics";
@ -8211,7 +8212,7 @@ Sorry for the inconvenience.";
"PeerInfo.OptionTopicsText" = "The group chat will be divided into topics created by admins or users.";
"PeerInfo.TopicsLimitedParticipantCountText_1" = "Only groups with more than **%d member** can have topics enabled.";
"PeerInfo.TopicsLimitedParticipantCountText_any" = "Only groups with more than **%d members** can have topics enabled.";
"PeerInfo.TopicsLimitedDiscussionGroups" = "Topics are currently unavailable in groups connected to channels.";
"PeerInfo.TopicsLimitedDiscussionGroups" = "Topics cant be enabled in discussion groups at the moment.";
"PeerInfo.TopicNotificationExceptions_1" = "There is [1 topic]() that is listed as exception.";
"PeerInfo.TopicNotificationExceptions_any" = "There are [%d topics]() that are listed as exceptions.";

View File

@ -10,6 +10,7 @@ import HorizontalPeerItem
import ListSectionHeaderNode
import ContextUI
import AccountContext
import Postbox
private func calculateItemCustomWidth(width: CGFloat) -> CGFloat {
let itemInsets = UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 6.0)
@ -166,8 +167,8 @@ public final class ChatListSearchRecentPeersNode: ASDisplayNode {
}
)
|> mapToSignal { peerViews -> Signal<([EnginePeer], [EnginePeer.Id: (Int32, Bool)], [EnginePeer.Id: EnginePeer.Presence]), NoError> in
return context.account.postbox.unreadMessageCountsView(items: peerViews.map {
.peer($0.peerId)
return context.account.postbox.unreadMessageCountsView(items: peerViews.map { item -> UnreadMessageCountsItem in
return UnreadMessageCountsItem.peer(id: item.peerId, handleThreads: true)
})
|> map { values in
var peers: [EnginePeer] = []
@ -185,7 +186,7 @@ public final class ChatListSearchRecentPeersNode: ASDisplayNode {
}
}
let unreadCount = values.count(for: .peer(peerView.peerId))
let unreadCount = values.count(for: .peer(id: peerView.peerId, handleThreads: true))
if let unreadCount = unreadCount, unreadCount > 0 {
unread[peerView.peerId] = (unreadCount, isMuted)
}

View File

@ -1030,9 +1030,9 @@ public final class ChatListNode: ListView {
}
self?.setCurrentRemovingPeerId(nil)
})
}, setPeerThreadMuted: { [weak self] peerId, threadId, _ in
}, setPeerThreadMuted: { [weak self] peerId, threadId, value in
//self?.setCurrentRemovingPeerId(peerId)
let _ = (context.engine.peers.togglePeerMuted(peerId: peerId, threadId: threadId)
let _ = (context.engine.peers.updatePeerMuteSetting(peerId: peerId, threadId: threadId, muteInterval: value ? Int32.max : 0)
|> deliverOnMainQueue).start(completed: {
self?.updateState { state in
var state = state

View File

@ -203,11 +203,22 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
continue
}
let defaultPeerNotificationSettings: TelegramPeerNotificationSettings = (view.peerNotificationSettings as? TelegramPeerNotificationSettings) ?? .defaultSettings
var hasUnseenMentions = false
var isMuted = false
if case .muted = data.notificationSettings.muteState {
switch data.notificationSettings.muteState {
case .muted:
isMuted = true
case .unmuted:
isMuted = false
case .default:
if case .default = data.notificationSettings.muteState {
if case .muted = defaultPeerNotificationSettings.muteState {
isMuted = true
}
}
}
if let info = item.tagSummaryInfo[ChatListEntryMessageTagSummaryKey(

View File

@ -26,7 +26,7 @@ func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilt
}
if !additionalPeerIds.isEmpty {
for peerId in additionalPeerIds {
unreadCountItems.append(.peer(peerId))
unreadCountItems.append(.peer(id: peerId, handleThreads: true))
}
}
for groupId in additionalGroupIds {

View File

@ -610,11 +610,16 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
hasTimer = true
}
var hasSchedule = true
if controller.chatLocation?.threadId != nil {
hasSchedule = false
}
self.openingMedia = true
let reversed = controller.collection == nil
let index = reversed ? fetchResult.count - index - 1 : index
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index, reversed: reversed), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: true, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index, reversed: reversed), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: hasSchedule, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
self?.hiddenMediaId.set(.single(id))
}, initialLayout: layout, transitionHostView: { [weak self] in
return self?.gridNode.view

View File

@ -15,6 +15,7 @@ import PresentationDataUtils
import ItemListPeerItem
import ItemListPeerActionItem
import ChatListFilterSettingsHeaderItem
import UndoUI
private final class ChannelDiscussionGroupSetupControllerArguments {
let context: AccountContext
@ -314,6 +315,13 @@ public func channelDiscussionGroupSetupController(context: AccountContext, updat
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
if case let .channel(channel) = groupPeer, channel.flags.contains(.isForum) {
let text = presentationData.strings.PeerInfo_TopicsLimitedDiscussionGroups
presentControllerImpl?(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_topics", scale: 0.066, colors: [:], title: nil, text: text, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil)
return
}
let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ChannelDiscussionGroupActionSheetItem(context: context, channelPeer: channelPeer._asPeer(), groupPeer: groupPeer._asPeer(), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),

View File

@ -354,7 +354,7 @@ func stringForGroupPermission(strings: PresentationStrings, right: TelegramChatB
} else if right.contains(.banPinMessages) {
return strings.Channel_EditAdmin_PermissionPinMessages
} else if right.contains(.banManageTopics) {
return strings.Channel_EditAdmin_PermissionManageTopics
return strings.Channel_EditAdmin_PermissionCreateTopics
} else {
return ""
}

View File

@ -32,6 +32,7 @@ final class MutableMessageHistoryThreadIndexView: MutablePostboxView {
fileprivate let peerId: PeerId
fileprivate let summaryComponents: ChatListEntrySummaryComponents
fileprivate var peer: Peer?
fileprivate var peerNotificationSettings: PeerNotificationSettings?
fileprivate var items: [Item] = []
private var hole: ForumTopicListHolesEntry?
fileprivate var isLoading: Bool = false
@ -48,6 +49,8 @@ final class MutableMessageHistoryThreadIndexView: MutablePostboxView {
self.peer = postbox.peerTable.get(self.peerId)
self.peerNotificationSettings = postbox.peerNotificationSettingsTable.getEffective(self.peerId)
let validIndexBoundary = postbox.peerThreadCombinedStateTable.get(peerId: peerId)?.validIndexBoundary
self.isLoading = validIndexBoundary == nil
@ -128,7 +131,7 @@ final class MutableMessageHistoryThreadIndexView: MutablePostboxView {
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
var updated = false
if transaction.updatedMessageThreadPeerIds.contains(self.peerId) || transaction.updatedPinnedThreads.contains(self.peerId) || transaction.updatedPeerThreadCombinedStates.contains(self.peerId) || transaction.currentUpdatedMessageTagSummaries.contains(where: { $0.key.peerId == self.peerId }) || transaction.currentUpdatedMessageActionsSummaries.contains(where: { $0.key.peerId == self.peerId }) || transaction.currentUpdatedPeerChatListEmbeddedStates.contains(self.peerId) {
if transaction.updatedMessageThreadPeerIds.contains(self.peerId) || transaction.updatedPinnedThreads.contains(self.peerId) || transaction.updatedPeerThreadCombinedStates.contains(self.peerId) || transaction.currentUpdatedMessageTagSummaries.contains(where: { $0.key.peerId == self.peerId }) || transaction.currentUpdatedMessageActionsSummaries.contains(where: { $0.key.peerId == self.peerId }) || transaction.currentUpdatedPeerChatListEmbeddedStates.contains(self.peerId) || transaction.currentUpdatedPeerNotificationSettings[self.peerId] != nil {
self.reload(postbox: postbox)
updated = true
}
@ -216,11 +219,13 @@ public final class EngineMessageHistoryThread {
public final class MessageHistoryThreadIndexView: PostboxView {
public let peer: Peer?
public let peerNotificationSettings: PeerNotificationSettings?
public let items: [EngineMessageHistoryThread.Item]
public let isLoading: Bool
init(_ view: MutableMessageHistoryThreadIndexView) {
self.peer = view.peer
self.peerNotificationSettings = view.peerNotificationSettings
var items: [EngineMessageHistoryThread.Item] = []
for item in view.items {

View File

@ -3,13 +3,13 @@ import Foundation
public enum UnreadMessageCountsItem: Equatable {
case total(ValueBoxKey?)
case totalInGroup(PeerGroupId)
case peer(PeerId)
case peer(id: PeerId, handleThreads: Bool)
}
private enum MutableUnreadMessageCountsItemEntry: Equatable {
case total((ValueBoxKey, PreferencesEntry?)?, ChatListTotalUnreadState)
case totalInGroup(PeerGroupId, ChatListTotalUnreadState)
case peer(PeerId, CombinedPeerReadState?)
case peer(PeerId, Bool, CombinedPeerReadState?)
static func ==(lhs: MutableUnreadMessageCountsItemEntry, rhs: MutableUnreadMessageCountsItemEntry) -> Bool {
switch lhs {
@ -34,8 +34,8 @@ private enum MutableUnreadMessageCountsItemEntry: Equatable {
} else {
return false
}
case let .peer(peerId, readState):
if case .peer(peerId, readState) = rhs {
case let .peer(peerId, handleThreads, readState):
if case .peer(peerId, handleThreads, readState) = rhs {
return true
} else {
return false
@ -63,15 +63,15 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
return .total(preferencesKey.flatMap({ ($0, postbox.preferencesTable.get(key: $0)) }), postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: .root))
case let .totalInGroup(groupId):
return .totalInGroup(groupId, postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId))
case let .peer(peerId):
if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
case let .peer(peerId, handleThreads):
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
var count: Int32 = 0
if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) {
count = summary.effectiveUnreadCount
}
return .peer(peerId, CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: count, markedUnread: false))]))
return .peer(peerId, handleThreads, CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: count, markedUnread: false))]))
} else {
return .peer(peerId, postbox.readStateTable.getCombinedState(peerId))
return .peer(peerId, handleThreads, postbox.readStateTable.getCombinedState(peerId))
}
}
}
@ -112,19 +112,19 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
updated = true
}
}
case let .peer(peerId, _):
if let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
case let .peer(peerId, handleThreads, _):
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
if transaction.updatedPeerThreadsSummaries.contains(peerId) {
var count: Int32 = 0
if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) {
count = summary.effectiveUnreadCount
}
self.entries[i] = .peer(peerId, CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: count, markedUnread: false))]))
self.entries[i] = .peer(peerId, handleThreads, CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: count, markedUnread: false))]))
updated = true
}
} else {
if transaction.alteredInitialPeerCombinedReadStates[peerId] != nil {
self.entries[i] = .peer(peerId, postbox.readStateTable.getCombinedState(peerId))
self.entries[i] = .peer(peerId, handleThreads, postbox.readStateTable.getCombinedState(peerId))
updated = true
}
}
@ -142,8 +142,16 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
return .total(preferencesKey.flatMap({ ($0, postbox.preferencesTable.get(key: $0)) }), postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: .root))
case let .totalInGroup(groupId):
return .totalInGroup(groupId, postbox.messageHistoryMetadataTable.getTotalUnreadState(groupId: groupId))
case let .peer(peerId):
return .peer(peerId, postbox.readStateTable.getCombinedState(peerId))
case let .peer(peerId, handleThreads):
if handleThreads, let peer = postbox.peerTable.get(peerId), postbox.seedConfiguration.peerSummaryIsThreadBased(peer) {
var count: Int32 = 0
if let summary = postbox.peerThreadsSummaryTable.get(peerId: peerId) {
count = summary.effectiveUnreadCount
}
return .peer(peerId, handleThreads, CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: count, markedUnread: false))]))
} else {
return .peer(peerId, handleThreads, postbox.readStateTable.getCombinedState(peerId))
}
}
}
if self.entries != entries {
@ -169,7 +177,7 @@ public final class UnreadMessageCountsView: PostboxView {
return .total(keyAndValue?.1, state)
case let .totalInGroup(groupId, state):
return .totalInGroup(groupId, state)
case let .peer(peerId, count):
case let .peer(peerId, _, count):
return .peer(peerId, count)
}
}
@ -193,7 +201,7 @@ public final class UnreadMessageCountsView: PostboxView {
case .total, .totalInGroup:
break
case let .peer(peerId, state):
if case .peer(peerId) = item {
if case .peer(peerId, _) = item {
return state?.count ?? 0
}
}

View File

@ -194,7 +194,7 @@ public extension TelegramEngine.EngineData.Item {
}
var key: PostboxViewKey {
return .unreadCounts(items: [.peer(self.id)])
return .unreadCounts(items: [.peer(id: self.id, handleThreads: true)])
}
public init(id: EnginePeer.Id) {
@ -206,7 +206,7 @@ public extension TelegramEngine.EngineData.Item {
preconditionFailure()
}
return Int(view.count(for: .peer(self.id)) ?? 0)
return Int(view.count(for: .peer(id: self.id, handleThreads: true)) ?? 0)
}
}

View File

@ -71,10 +71,12 @@ func _internal_updatePeerMuteSetting(account: Account, peerId: PeerId, threadId:
func _internal_updatePeerMuteSetting(account: Account, transaction: Transaction, peerId: PeerId, threadId: Int64?, muteInterval: Int32?) {
if let peer = transaction.getPeer(peerId) {
if let threadId = threadId {
let peerSettings: TelegramPeerNotificationSettings = (transaction.getPeerNotificationSettings(id: peerId) as? TelegramPeerNotificationSettings) ?? .defaultSettings
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings
let muteState: PeerMuteState
var muteState: PeerMuteState
if let muteInterval = muteInterval {
if muteInterval == 0 {
muteState = .unmuted
@ -88,6 +90,9 @@ func _internal_updatePeerMuteSetting(account: Account, transaction: Transaction,
muteState = .muted(until: absoluteUntil)
}
} else {
muteState = .unmuted
}
if peerSettings.muteState == muteState {
muteState = .default
}

View File

@ -46,7 +46,7 @@ func _internal_recentlySearchedPeers(postbox: Postbox) -> Signal<[RecentlySearch
}
}
var keys: [PostboxViewKey] = []
let unreadCountsKey: PostboxViewKey = .unreadCounts(items: peerIds.map(UnreadMessageCountsItem.peer))
let unreadCountsKey: PostboxViewKey = .unreadCounts(items: peerIds.map { UnreadMessageCountsItem.peer(id: $0, handleThreads: true) })
keys.append(unreadCountsKey)
keys.append(contentsOf: peerIds.map({ .peer(peerId: $0, components: .all) }))

View File

@ -384,13 +384,13 @@ public final class AccountContextImpl: AccountContext {
public func chatLocationUnreadCount(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>) -> Signal<Int, NoError> {
switch location {
case let .peer(peerId):
let unreadCountsKey: PostboxViewKey = .unreadCounts(items: [.peer(peerId), .total(nil)])
let unreadCountsKey: PostboxViewKey = .unreadCounts(items: [.peer(id: peerId, handleThreads: false), .total(nil)])
return self.account.postbox.combinedView(keys: [unreadCountsKey])
|> map { views in
var unreadCount: Int32 = 0
if let view = views.views[unreadCountsKey] as? UnreadMessageCountsView {
if let count = view.count(for: .peer(peerId)) {
if let count = view.count(for: .peer(id: peerId, handleThreads: false)) {
unreadCount = count
}
}

View File

@ -1618,6 +1618,7 @@ final class ChatMediaInputNode: ChatInputNode {
})))
}
if interfaceState.chatLocation.threadId == nil {
menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
@ -1633,6 +1634,7 @@ final class ChatMediaInputNode: ChatInputNode {
}
}
}
}
menuItems.append(
.action(ContextMenuActionItem(text: isStarred ? strongSelf.strings.Stickers_RemoveFromFavorites : strongSelf.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
f(.default)
@ -1770,6 +1772,7 @@ final class ChatMediaInputNode: ChatInputNode {
})))
}
if interfaceState.chatLocation.threadId == nil {
menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
@ -1785,6 +1788,7 @@ final class ChatMediaInputNode: ChatInputNode {
}
}
}
}
menuItems.append(
.action(ContextMenuActionItem(text: isStarred ? strongSelf.strings.Stickers_RemoveFromFavorites : strongSelf.strings.Stickers_AddToFavorites, icon: { theme in generateTintedImage(image: isStarred ? UIImage(bundleImageName: "Chat/Context Menu/Unfave") : UIImage(bundleImageName: "Chat/Context Menu/Fave"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in

View File

@ -1397,7 +1397,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
authorRank = attributes.rank
}
if authorRank == nil {
var enableAutoRank = false
if let authorRank = authorRank, case .admin = authorRank {
enableAutoRank = true
} else if authorRank == nil {
enableAutoRank = true
}
if enableAutoRank {
if let topicAuthorId = item.associatedData.topicAuthorId, topicAuthorId == message.author?.id {
authorRank = .custom(item.presentationData.strings.Chat_Message_TopicAuthorBadge)
}

View File

@ -4,7 +4,8 @@ private let whitelistedHosts: Set<String> = Set([
"t.me",
"telegram.me",
"telegra.ph",
"telesco.pe"
"telesco.pe",
"fragment.com"
])
public func isConcealedUrlWhitelisted(_ url: URL) -> Bool {