mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Topic-related fixes
This commit is contained in:
parent
cd949e0542
commit
a28ed6a7dc
@ -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 can’t 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.";
|
||||
|
@ -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)
|
||||
@ -155,51 +156,51 @@ public final class ChatListSearchRecentPeersNode: ASDisplayNode {
|
||||
}
|
||||
|> mapToSignal { recent in
|
||||
switch recent {
|
||||
case .disabled:
|
||||
return .single(([], [:], [:]))
|
||||
case let .peers(peers):
|
||||
return combineLatest(queue: .mainQueue(),
|
||||
peers.filter {
|
||||
!$0.isDeleted
|
||||
}.map {
|
||||
context.account.postbox.peerView(id: $0.id)
|
||||
}
|
||||
)
|
||||
|> 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)
|
||||
})
|
||||
|> map { values in
|
||||
var peers: [EnginePeer] = []
|
||||
var unread: [EnginePeer.Id: (Int32, Bool)] = [:]
|
||||
var presences: [EnginePeer.Id: EnginePeer.Presence] = [:]
|
||||
for peerView in peerViews {
|
||||
if let peer = peerViewMainPeer(peerView) {
|
||||
var isMuted: Bool = false
|
||||
if let notificationSettings = peerView.notificationSettings as? TelegramPeerNotificationSettings {
|
||||
switch notificationSettings.muteState {
|
||||
case .muted:
|
||||
isMuted = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
case .disabled:
|
||||
return .single(([], [:], [:]))
|
||||
case let .peers(peers):
|
||||
return combineLatest(queue: .mainQueue(),
|
||||
peers.filter {
|
||||
!$0.isDeleted
|
||||
}.map {
|
||||
context.account.postbox.peerView(id: $0.id)
|
||||
}
|
||||
)
|
||||
|> mapToSignal { peerViews -> Signal<([EnginePeer], [EnginePeer.Id: (Int32, Bool)], [EnginePeer.Id: EnginePeer.Presence]), NoError> in
|
||||
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] = []
|
||||
var unread: [EnginePeer.Id: (Int32, Bool)] = [:]
|
||||
var presences: [EnginePeer.Id: EnginePeer.Presence] = [:]
|
||||
for peerView in peerViews {
|
||||
if let peer = peerViewMainPeer(peerView) {
|
||||
var isMuted: Bool = false
|
||||
if let notificationSettings = peerView.notificationSettings as? TelegramPeerNotificationSettings {
|
||||
switch notificationSettings.muteState {
|
||||
case .muted:
|
||||
isMuted = true
|
||||
default:
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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 ""
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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) }))
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -1618,18 +1618,20 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
})))
|
||||
}
|
||||
|
||||
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
|
||||
if let strongSelf = self, let peekController = strongSelf.peekController {
|
||||
if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode {
|
||||
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.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, [])
|
||||
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
|
||||
if let strongSelf = self, let peekController = strongSelf.peekController {
|
||||
if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode {
|
||||
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.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
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Menu/ScheduleIcon"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
if let strongSelf = self, let peekController = strongSelf.peekController {
|
||||
if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode {
|
||||
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.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, [])
|
||||
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
|
||||
if let strongSelf = self, let peekController = strongSelf.peekController {
|
||||
if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode {
|
||||
let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, animationNode.view, animationNode.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)
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user