Support clear history for groups and channels

This commit is contained in:
Ali 2021-02-15 19:54:00 +04:00
parent 5aca2dee08
commit 7ad76867b8
8 changed files with 5006 additions and 4669 deletions

View File

@ -6083,3 +6083,6 @@ Sorry for the inconvenience.";
"ChannelInfo.InviteLink.RevokeAlert.Text" = "Are you sure you want to revoke this link? Once you do, no one will be able to join the channel using it."; "ChannelInfo.InviteLink.RevokeAlert.Text" = "Are you sure you want to revoke this link? Once you do, no one will be able to join the channel using it.";
"Group.Info.Members" = "Members"; "Group.Info.Members" = "Members";
"Conversation.AlsoClearCacheTitle" = "You can use \"clear cache\" to remove unnecessary media — and re-downloaded files if you need them again.";
"Conversation.DeleteAllMessagesInChat" = "Are you sure you want to delete all messages in %@?";

View File

@ -2307,7 +2307,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: mainPeer, chatPeer: chatPeer, action: .clearHistory, strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder)) items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: mainPeer, chatPeer: chatPeer, action: .clearHistory(canClearCache: false), strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder))
if joined || mainPeer.isDeleted { if joined || mainPeer.isDeleted {
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Delete, color: .destructive, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Delete, color: .destructive, action: { [weak actionSheet] in

View File

@ -12,7 +12,7 @@ import AccountContext
public enum DeleteChatPeerAction { public enum DeleteChatPeerAction {
case delete case delete
case deleteAndLeave case deleteAndLeave
case clearHistory case clearHistory(canClearCache: Bool)
case clearCache case clearCache
case clearCacheSuggestion case clearCacheSuggestion
case removeFromGroup case removeFromGroup
@ -128,8 +128,18 @@ private final class DeleteChatPeerActionSheetItemNode: ActionSheetItemNode {
} else { } else {
text = strings.ChatList_DeleteChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder)) text = strings.ChatList_DeleteChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder))
} }
case .clearHistory: case let .clearHistory(canClearCache):
text = strings.ChatList_ClearChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder)) if peer.id == context.account.peerId {
text = (strings.ChatList_DeleteSavedMessagesConfirmation, [])
} else if peer is TelegramUser {
text = strings.ChatList_ClearChatConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder))
} else {
text = strings.Conversation_DeleteAllMessagesInChat(peer.displayTitle(strings: strings, displayOrder: nameOrder))
}
if canClearCache {
text?.0 += "\n\n\(strings.Conversation_AlsoClearCacheTitle)"
}
case .removeFromGroup: case .removeFromGroup:
text = strings.VoiceChat_RemovePeerConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder)) text = strings.VoiceChat_RemovePeerConfirmation(peer.displayTitle(strings: strings, displayOrder: nameOrder))
default: default:

View File

@ -7709,38 +7709,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } }) self.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState { $0.withoutSelectionState() } })
case .clearHistory: case .clearHistory:
if case let .peer(peerId) = self.chatLocation { if case let .peer(peerId) = self.chatLocation {
guard let peer = self.presentationInterfaceState.renderedPeer, let chatPeer = peer.peers[peer.peerId], let mainPeer = peer.chatMainPeer else {
return
}
var isClearCache = false
let text: String
if peerId == self.context.account.peerId {
text = self.presentationData.strings.Conversation_ClearSelfHistory
} else if peerId.namespace == Namespaces.Peer.SecretChat {
text = self.presentationData.strings.Conversation_ClearSecretHistory
} else if peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel {
if let channel = peer.peer as? TelegramChannel, case .broadcast = channel.info {
isClearCache = true
text = self.presentationData.strings.Conversation_ClearCache
} else {
text = self.presentationData.strings.Conversation_ClearGroupHistory
}
} else {
text = self.presentationData.strings.Conversation_ClearPrivateHistory
}
var canRemoveGlobally = false
let limitsConfiguration = self.context.currentLimitsConfiguration.with { $0 }
if peerId.namespace == Namespaces.Peer.CloudUser && peerId != self.context.account.peerId {
if limitsConfiguration.maxMessageRevokeIntervalInPrivateChats == LimitsConfiguration.timeIntervalForever {
canRemoveGlobally = true
}
}
if let user = chatPeer as? TelegramUser, user.botInfo != nil {
canRemoveGlobally = false
}
let account = self.context.account let account = self.context.account
let beginClear: (InteractiveHistoryClearingType) -> Void = { [weak self] type in let beginClear: (InteractiveHistoryClearingType) -> Void = { [weak self] type in
@ -7773,6 +7741,355 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}), in: .current) }), in: .current)
} }
let _ = (self.context.account.postbox.transaction { transaction -> Bool in
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let memberCount = cachedData.participantsSummary.memberCount {
if memberCount > 1000 {
return true
} else {
return false
}
} else {
return false
}
}
|> deliverOnMainQueue).start(next: { [weak self] isLargeGroupOrChannel in
guard let strongSelf = self else {
return
}
guard let peer = strongSelf.presentationInterfaceState.renderedPeer, let chatPeer = peer.peers[peer.peerId], let mainPeer = peer.chatMainPeer else {
return
}
enum ClearType {
case savedMessages
case secretChat
case group
case channel
case user
}
let canClearCache: Bool
let canClearForMyself: ClearType?
let canClearForEveryone: ClearType?
if peerId == strongSelf.context.account.peerId {
canClearCache = false
canClearForMyself = .savedMessages
canClearForEveryone = nil
} else if chatPeer is TelegramSecretChat {
canClearCache = false
canClearForMyself = .secretChat
canClearForEveryone = nil
} else if let group = chatPeer as? TelegramGroup {
canClearCache = false
switch group.role {
case .creator:
canClearForMyself = .group
canClearForEveryone = .group
case .admin, .member:
canClearForMyself = .group
canClearForEveryone = nil
}
} else if let channel = chatPeer as? TelegramChannel {
if let username = channel.username, !username.isEmpty {
if isLargeGroupOrChannel {
canClearCache = true
canClearForMyself = nil
canClearForEveryone = nil
} else {
canClearCache = true
canClearForMyself = nil
switch channel.info {
case .broadcast:
if channel.flags.contains(.isCreator) {
canClearForEveryone = .channel
} else {
canClearForEveryone = nil
}
case .group:
if channel.flags.contains(.isCreator) {
canClearForEveryone = .group
} else {
canClearForEveryone = nil
}
}
}
} else {
if isLargeGroupOrChannel {
switch channel.info {
case .broadcast:
canClearCache = true
canClearForMyself = .channel
canClearForEveryone = nil
case .group:
canClearCache = false
canClearForMyself = .channel
canClearForEveryone = nil
}
} else {
switch channel.info {
case .broadcast:
canClearCache = true
if channel.flags.contains(.isCreator) {
canClearForMyself = .channel
canClearForEveryone = .channel
} else {
canClearForMyself = .channel
canClearForEveryone = nil
}
case .group:
canClearCache = false
if channel.flags.contains(.isCreator) {
canClearForMyself = .group
canClearForEveryone = .group
} else {
canClearForMyself = .group
canClearForEveryone = nil
}
}
}
}
} else {
canClearCache = false
canClearForMyself = .user
if let user = chatPeer as? TelegramUser, user.botInfo != nil {
canClearForEveryone = nil
} else {
canClearForEveryone = .user
}
}
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
var items: [ActionSheetItem] = []
if case .scheduledMessages = strongSelf.presentationInterfaceState.subject {
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ScheduledMessages_ClearAllConfirmation, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
guard let strongSelf = self else {
return
}
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationTitle, text: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationText, actions: [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationAction, action: {
beginClear(.scheduledMessages)
})
], parseMarkdown: true), in: .window(.root))
}))
} else {
if let _ = canClearForMyself ?? canClearForEveryone {
items.append(DeleteChatPeerActionSheetItem(context: strongSelf.context, peer: mainPeer, chatPeer: chatPeer, action: .clearHistory(canClearCache: canClearCache), strings: strongSelf.presentationData.strings, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder))
if let canClearForEveryone = canClearForEveryone {
let text: String
let confirmationText: String
switch canClearForEveryone {
case .user:
text = strongSelf.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).0
confirmationText = strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationText
default:
text = strongSelf.presentationData.strings.Conversation_DeleteMessagesForEveryone
confirmationText = strongSelf.presentationData.strings.ChatList_DeleteForAllMembersConfirmationText
}
items.append(ActionSheetButtonItem(title: text, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
guard let strongSelf = self else {
return
}
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationTitle, text: confirmationText, actions: [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationAction, action: {
beginClear(.forEveryone)
})
], parseMarkdown: true), in: .window(.root))
}))
}
if let canClearForMyself = canClearForMyself {
let text: String
switch canClearForMyself {
case .savedMessages, .secretChat:
text = strongSelf.presentationData.strings.Conversation_ClearAll
default:
text = strongSelf.presentationData.strings.ChatList_DeleteForCurrentUser
}
items.append(ActionSheetButtonItem(title: text, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
beginClear(.forLocalPeer)
}))
}
}
if canClearCache {
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ClearCache, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
guard let strongSelf = self else {
return
}
strongSelf.navigationButtonAction(.clearCache)
}))
}
if chatPeer.canSetupAutoremoveTimeout(accountPeerId: strongSelf.context.account.peerId) {
//TODO:localize
items.append(ActionSheetButtonItem(title: strongSelf.presentationInterfaceState.autoremoveTimeout == nil ? "Enable Auto-Delete" : "Edit Auto-Delete Settings", color: .accent, action: { [weak actionSheet] in
guard let actionSheet = actionSheet else {
return
}
guard let strongSelf = self else {
return
}
actionSheet.dismissAnimated()
strongSelf.presentAutoremoveSetup()
}))
}
}
/*if case .scheduledMessages = self.presentationInterfaceState.subject {
} else if canRemoveGlobally {
items.append(DeleteChatPeerActionSheetItem(context: self.context, peer: mainPeer, chatPeer: chatPeer, action: .clearHistory, strings: self.presentationData.strings, nameDisplayOrder: self.presentationData.nameDisplayOrder))
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForCurrentUser, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
beginClear(.forLocalPeer)
}))
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).0, color: .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
guard let strongSelf = self else {
return
}
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationTitle, text: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationText, actions: [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationAction, action: {
beginClear(.forEveryone)
})
], parseMarkdown: true), in: .window(.root))
}))
} else {
if !isClearCache {
items.append(ActionSheetTextItem(title: text))
}
items.append(ActionSheetButtonItem(title: isClearCache ? self.presentationData.strings.Conversation_ClearCache : self.presentationData.strings.Conversation_ClearAll, color: isClearCache ? .accent : .destructive, action: { [weak self, weak actionSheet] in
actionSheet?.dismissAnimated()
guard let strongSelf = self else {
return
}
if isClearCache {
strongSelf.navigationButtonAction(.clearCache)
} else {
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationTitle, text: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationText, actions: [
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
}),
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationAction, action: {
beginClear(.forLocalPeer)
})
], parseMarkdown: true), in: .window(.root))
}
}))
}
if let peer = self.presentationInterfaceState.renderedPeer?.peer {
var currentAutoremoveTimeout: Int32? = self.presentationInterfaceState.autoremoveTimeout
var canSetupAutoremoveTimeout = false
if let _ = peer as? TelegramSecretChat {
} else if let group = peer as? TelegramGroup {
if case .creator = group.role {
canSetupAutoremoveTimeout = true
} else if case let .admin(rights, _) = group.role {
if rights.flags.contains(.canDeleteMessages) {
canSetupAutoremoveTimeout = true
}
}
} else if let user = self.presentationInterfaceState.renderedPeer?.peer as? TelegramUser {
if user.id != self.context.account.peerId && user.botInfo == nil {
canSetupAutoremoveTimeout = true
}
} else if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel {
if channel.hasPermission(.deleteAllMessages) {
canSetupAutoremoveTimeout = true
}
}
if canSetupAutoremoveTimeout {
}
}*/
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
})
])])
strongSelf.chatDisplayNode.dismissInput()
strongSelf.present(actionSheet, in: .window(.root))
})
/*if peerId == self.context.account.peerId {
text = self.presentationData.strings.Conversation_ClearSelfHistory
} else if peerId.namespace == Namespaces.Peer.SecretChat {
text = self.presentationData.strings.Conversation_ClearSecretHistory
} else if peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel {
if let channel = peer.peer as? TelegramChannel, case .broadcast = channel.info {
isClearCache = true
text = self.presentationData.strings.Conversation_ClearCache
} else {
text = self.presentationData.strings.Conversation_ClearGroupHistory
}
} else {
text = self.presentationData.strings.Conversation_ClearPrivateHistory
}
let text: String
if peerId == self.context.account.peerId {
text = self.presentationData.strings.Conversation_ClearSelfHistory
} else if peerId.namespace == Namespaces.Peer.SecretChat {
text = self.presentationData.strings.Conversation_ClearSecretHistory
} else if peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel {
if let channel = peer.peer as? TelegramChannel, case .broadcast = channel.info {
isClearCache = true
text = self.presentationData.strings.Conversation_ClearCache
} else {
text = self.presentationData.strings.Conversation_ClearGroupHistory
}
} else {
text = self.presentationData.strings.Conversation_ClearPrivateHistory
}
var canRemoveGlobally = false
let limitsConfiguration = self.context.currentLimitsConfiguration.with { $0 }
if peerId.namespace == Namespaces.Peer.CloudUser && peerId != self.context.account.peerId {
if limitsConfiguration.maxMessageRevokeIntervalInPrivateChats == LimitsConfiguration.timeIntervalForever {
canRemoveGlobally = true
}
}
if let user = chatPeer as? TelegramUser, user.botInfo != nil {
canRemoveGlobally = false
}
let actionSheet = ActionSheetController(presentationData: self.presentationData) let actionSheet = ActionSheetController(presentationData: self.presentationData)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
@ -7884,7 +8201,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
])]) ])])
self.chatDisplayNode.dismissInput() self.chatDisplayNode.dismissInput()
self.present(actionSheet, in: .window(.root)) self.present(actionSheet, in: .window(.root))*/
} }
case let .openChatInfo(expandAvatar): case let .openChatInfo(expandAvatar):
let _ = self.presentVoiceMessageDiscardAlert(action: { let _ = self.presentVoiceMessageDiscardAlert(action: {
@ -12151,6 +12468,6 @@ extension Peer {
} }
} }
return true return false
} }
} }

@ -1 +1 @@
Subproject commit 17d7e77771ba00e128b2755b6eac486190a5194d Subproject commit 5ab60bbb78f2a71c945cd8ea82810d22f95cf9cd

View File

@ -633,7 +633,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
snapshot?.removeFromSuperview() snapshot?.removeFromSuperview()
}) })
} }
self.timerTextNode.attributedText = NSAttributedString(string: "\(self.remainingSeconds)", font: Font.regular(16.0), textColor: .white) self.timerTextNode.attributedText = NSAttributedString(string: "\(Int(self.remainingSeconds))", font: Font.regular(16.0), textColor: .white)
if let validLayout = self.validLayout { if let validLayout = self.validLayout {
self.containerLayoutUpdated(layout: validLayout, transition: .immediate) self.containerLayoutUpdated(layout: validLayout, transition: .immediate)
} }