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"; "ChatList.CloseAction" = "Close";
"Channel.EditAdmin.PermissionManageTopics" = "Manage Topics"; "Channel.EditAdmin.PermissionManageTopics" = "Manage Topics";
"Channel.EditAdmin.PermissionCreateTopics" = "Create Topics";
"ChatList.Search.FilterTopics" = "Topics"; "ChatList.Search.FilterTopics" = "Topics";
"DialogList.SearchSectionTopics" = "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.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_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.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_1" = "There is [1 topic]() that is listed as exception.";
"PeerInfo.TopicNotificationExceptions_any" = "There are [%d topics]() that are listed as exceptions."; "PeerInfo.TopicNotificationExceptions_any" = "There are [%d topics]() that are listed as exceptions.";

View File

@ -10,6 +10,7 @@ import HorizontalPeerItem
import ListSectionHeaderNode import ListSectionHeaderNode
import ContextUI import ContextUI
import AccountContext import AccountContext
import Postbox
private func calculateItemCustomWidth(width: CGFloat) -> CGFloat { private func calculateItemCustomWidth(width: CGFloat) -> CGFloat {
let itemInsets = UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 6.0) let itemInsets = UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 6.0)
@ -155,51 +156,51 @@ public final class ChatListSearchRecentPeersNode: ASDisplayNode {
} }
|> mapToSignal { recent in |> mapToSignal { recent in
switch recent { switch recent {
case .disabled: case .disabled:
return .single(([], [:], [:])) return .single(([], [:], [:]))
case let .peers(peers): case let .peers(peers):
return combineLatest(queue: .mainQueue(), return combineLatest(queue: .mainQueue(),
peers.filter { peers.filter {
!$0.isDeleted !$0.isDeleted
}.map { }.map {
context.account.postbox.peerView(id: $0.id) context.account.postbox.peerView(id: $0.id)
} }
) )
|> mapToSignal { peerViews -> Signal<([EnginePeer], [EnginePeer.Id: (Int32, Bool)], [EnginePeer.Id: EnginePeer.Presence]), NoError> in |> mapToSignal { peerViews -> Signal<([EnginePeer], [EnginePeer.Id: (Int32, Bool)], [EnginePeer.Id: EnginePeer.Presence]), NoError> in
return context.account.postbox.unreadMessageCountsView(items: peerViews.map { return context.account.postbox.unreadMessageCountsView(items: peerViews.map { item -> UnreadMessageCountsItem in
.peer($0.peerId) return UnreadMessageCountsItem.peer(id: item.peerId, handleThreads: true)
}) })
|> map { values in |> map { values in
var peers: [EnginePeer] = [] var peers: [EnginePeer] = []
var unread: [EnginePeer.Id: (Int32, Bool)] = [:] var unread: [EnginePeer.Id: (Int32, Bool)] = [:]
var presences: [EnginePeer.Id: EnginePeer.Presence] = [:] var presences: [EnginePeer.Id: EnginePeer.Presence] = [:]
for peerView in peerViews { for peerView in peerViews {
if let peer = peerViewMainPeer(peerView) { if let peer = peerViewMainPeer(peerView) {
var isMuted: Bool = false var isMuted: Bool = false
if let notificationSettings = peerView.notificationSettings as? TelegramPeerNotificationSettings { if let notificationSettings = peerView.notificationSettings as? TelegramPeerNotificationSettings {
switch notificationSettings.muteState { switch notificationSettings.muteState {
case .muted: case .muted:
isMuted = true isMuted = true
default: default:
break break
}
} }
let unreadCount = values.count(for: .peer(peerView.peerId))
if let unreadCount = unreadCount, unreadCount > 0 {
unread[peerView.peerId] = (unreadCount, isMuted)
}
if let presence = peerView.peerPresences[peer.id] {
presences[peer.id] = EnginePeer.Presence(presence)
}
peers.append(EnginePeer(peer))
} }
let unreadCount = values.count(for: .peer(id: peerView.peerId, handleThreads: true))
if let unreadCount = unreadCount, unreadCount > 0 {
unread[peerView.peerId] = (unreadCount, isMuted)
}
if let presence = peerView.peerPresences[peer.id] {
presences[peer.id] = EnginePeer.Presence(presence)
}
peers.append(EnginePeer(peer))
} }
return (peers, unread, presences)
} }
return (peers, unread, presences)
} }
}
} }
} }

View File

@ -1030,9 +1030,9 @@ public final class ChatListNode: ListView {
} }
self?.setCurrentRemovingPeerId(nil) self?.setCurrentRemovingPeerId(nil)
}) })
}, setPeerThreadMuted: { [weak self] peerId, threadId, _ in }, setPeerThreadMuted: { [weak self] peerId, threadId, value in
//self?.setCurrentRemovingPeerId(peerId) //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: { |> deliverOnMainQueue).start(completed: {
self?.updateState { state in self?.updateState { state in
var state = state var state = state

View File

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

View File

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

View File

@ -610,11 +610,16 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
hasTimer = true hasTimer = true
} }
var hasSchedule = true
if controller.chatLocation?.threadId != nil {
hasSchedule = false
}
self.openingMedia = true self.openingMedia = true
let reversed = controller.collection == nil let reversed = controller.collection == nil
let index = reversed ? fetchResult.count - index - 1 : index 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)) self?.hiddenMediaId.set(.single(id))
}, initialLayout: layout, transitionHostView: { [weak self] in }, initialLayout: layout, transitionHostView: { [weak self] in
return self?.gridNode.view return self?.gridNode.view

View File

@ -15,6 +15,7 @@ import PresentationDataUtils
import ItemListPeerItem import ItemListPeerItem
import ItemListPeerActionItem import ItemListPeerActionItem
import ChatListFilterSettingsHeaderItem import ChatListFilterSettingsHeaderItem
import UndoUI
private final class ChannelDiscussionGroupSetupControllerArguments { private final class ChannelDiscussionGroupSetupControllerArguments {
let context: AccountContext let context: AccountContext
@ -314,6 +315,13 @@ public func channelDiscussionGroupSetupController(context: AccountContext, updat
} }
let presentationData = context.sharedContext.currentPresentationData.with { $0 } 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) let actionSheet = ActionSheetController(presentationData: presentationData)
actionSheet.setItemGroups([ActionSheetItemGroup(items: [ actionSheet.setItemGroups([ActionSheetItemGroup(items: [
ChannelDiscussionGroupActionSheetItem(context: context, channelPeer: channelPeer._asPeer(), groupPeer: groupPeer._asPeer(), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder), 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) { } else if right.contains(.banPinMessages) {
return strings.Channel_EditAdmin_PermissionPinMessages return strings.Channel_EditAdmin_PermissionPinMessages
} else if right.contains(.banManageTopics) { } else if right.contains(.banManageTopics) {
return strings.Channel_EditAdmin_PermissionManageTopics return strings.Channel_EditAdmin_PermissionCreateTopics
} else { } else {
return "" return ""
} }

View File

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

View File

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

View File

@ -194,7 +194,7 @@ public extension TelegramEngine.EngineData.Item {
} }
var key: PostboxViewKey { var key: PostboxViewKey {
return .unreadCounts(items: [.peer(self.id)]) return .unreadCounts(items: [.peer(id: self.id, handleThreads: true)])
} }
public init(id: EnginePeer.Id) { public init(id: EnginePeer.Id) {
@ -206,7 +206,7 @@ public extension TelegramEngine.EngineData.Item {
preconditionFailure() 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?) { func _internal_updatePeerMuteSetting(account: Account, transaction: Transaction, peerId: PeerId, threadId: Int64?, muteInterval: Int32?) {
if let peer = transaction.getPeer(peerId) { if let peer = transaction.getPeer(peerId) {
if let threadId = threadId { 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) { if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings let previousSettings: TelegramPeerNotificationSettings = data.notificationSettings
let muteState: PeerMuteState var muteState: PeerMuteState
if let muteInterval = muteInterval { if let muteInterval = muteInterval {
if muteInterval == 0 { if muteInterval == 0 {
muteState = .unmuted muteState = .unmuted
@ -88,6 +90,9 @@ func _internal_updatePeerMuteSetting(account: Account, transaction: Transaction,
muteState = .muted(until: absoluteUntil) muteState = .muted(until: absoluteUntil)
} }
} else { } else {
muteState = .unmuted
}
if peerSettings.muteState == muteState {
muteState = .default muteState = .default
} }

View File

@ -46,7 +46,7 @@ func _internal_recentlySearchedPeers(postbox: Postbox) -> Signal<[RecentlySearch
} }
} }
var keys: [PostboxViewKey] = [] 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(unreadCountsKey)
keys.append(contentsOf: peerIds.map({ .peer(peerId: $0, components: .all) })) 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> { public func chatLocationUnreadCount(for location: ChatLocation, contextHolder: Atomic<ChatLocationContextHolder?>) -> Signal<Int, NoError> {
switch location { switch location {
case let .peer(peerId): 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]) return self.account.postbox.combinedView(keys: [unreadCountsKey])
|> map { views in |> map { views in
var unreadCount: Int32 = 0 var unreadCount: Int32 = 0
if let view = views.views[unreadCountsKey] as? UnreadMessageCountsView { 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 unreadCount = count
} }
} }

View File

@ -1618,18 +1618,20 @@ final class ChatMediaInputNode: ChatInputNode {
}))) })))
} }
menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in if interfaceState.chatLocation.threadId == nil {
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in
}, action: { _, f in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor)
if let strongSelf = self, let peekController = strongSelf.peekController { }, action: { _, f in
if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { if let strongSelf = self, let peekController = strongSelf.peekController {
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil, []) if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode {
} else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil, [])
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode {
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil, [])
}
} }
} f(.default)
f(.default) })))
}))) }
} }
} }
} }
@ -1770,18 +1772,20 @@ final class ChatMediaInputNode: ChatInputNode {
}))) })))
} }
menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in if interfaceState.chatLocation.threadId == nil {
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor) menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in
}, action: { _, f in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor)
if let strongSelf = self, let peekController = strongSelf.peekController { }, action: { _, f in
if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { if let strongSelf = self, let peekController = strongSelf.peekController {
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil, []) if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode {
} else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil, [])
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil, []) } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode {
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil, [])
}
} }
} f(.default)
f(.default) })))
}))) }
} }
} }
} }

View File

@ -1397,7 +1397,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
authorRank = attributes.rank 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 { if let topicAuthorId = item.associatedData.topicAuthorId, topicAuthorId == message.author?.id {
authorRank = .custom(item.presentationData.strings.Chat_Message_TopicAuthorBadge) authorRank = .custom(item.presentationData.strings.Chat_Message_TopicAuthorBadge)
} }

View File

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