Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2020-05-29 16:37:46 +03:00
commit de4c1aa89d
9 changed files with 2518 additions and 2432 deletions

View File

@ -5502,8 +5502,10 @@ Any member of this group will be able to see messages in the channel.";
"Widget.ApplicationStartRequired" = "Open the app to use the widget";
"ChatList.Context.AddToFolder" = "Add to Folder";
"ChatList.Context.RemoveFromFolder" = "Remove from Folder";
"ChatList.Context.Back" = "Back";
"ChatList.AddedToFolderTooltip" = "%1$@ has been added to folder %2$@";
"ChatList.RemovedFromFolderTooltip" = "%1$@ has been removed from folder %2$@";
"OwnershipTransfer.Transfer" = "Transfer";

View File

@ -127,98 +127,122 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
let isContact = transaction.isPeerContact(peerId: peerId)
if case .chatList = source {
var hasFolders = false
updateChatListFiltersInteractively(transaction: transaction, { filters in
for filter in filters {
let predicate = chatListFilterPredicate(filter: filter.data)
if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) {
continue
}
var data = filter.data
if data.addIncludePeer(peerId: peerId) {
hasFolders = true
break
}
}
return filters
})
if hasFolders {
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Folder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
let _ = (context.account.postbox.transaction { transaction -> [ContextMenuItem] in
var updatedItems: [ContextMenuItem] = []
if case let .chatList(currentFilter) = source {
if let currentFilter = currentFilter {
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_RemoveFromFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/RemoveFromFolder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
let _ = (context.account.postbox.transaction { transaction -> Void in
updateChatListFiltersInteractively(transaction: transaction, { filters in
for filter in filters {
let predicate = chatListFilterPredicate(filter: filter.data)
if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) {
continue
var filters = filters
for i in 0 ..< filters.count {
if filters[i].id == currentFilter.id {
let _ = filters[i].data.addExcludePeer(peerId: peer.id)
break
}
var data = filter.data
if !data.addIncludePeer(peerId: peerId) {
continue
}
let filterType = chatListFilterType(filter)
updatedItems.append(.action(ContextMenuActionItem(text: filter.title, icon: { theme in
let imageName: String
switch filterType {
case .generic:
imageName = "Chat/Context Menu/List"
case .unmuted:
imageName = "Chat/Context Menu/Unmute"
case .unread:
imageName = "Chat/Context Menu/MarkAsUnread"
case .channels:
imageName = "Chat/Context Menu/Channels"
case .groups:
imageName = "Chat/Context Menu/Groups"
case .bots:
imageName = "Chat/Context Menu/Bots"
case .contacts:
imageName = "Chat/Context Menu/User"
case .nonContacts:
imageName = "Chat/Context Menu/UnknownUser"
}
return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor)
}, action: { c, f in
c.dismiss(completion: {
let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in
var filters = filters
for i in 0 ..< filters.count {
if filters[i].id == filter.id {
let _ = filters[i].data.addIncludePeer(peerId: peerId)
break
}
}
return filters
})).start()
chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatAddedToFolder(chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: filter.title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
return false
}), in: .current)
})
})))
}
return filters
})
updatedItems.append(.separator)
updatedItems.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Back, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor)
}, action: { c, _ in
c.setItems(chatContextMenuItems(context: context, peerId: peerId, promoInfo: promoInfo, source: source, chatListController: chatListController))
})))
return updatedItems
}
|> deliverOnMainQueue).start(next: { updatedItems in
c.setItems(.single(updatedItems))
|> deliverOnMainQueue).start(completed: {
c.dismiss(completion: {
chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatRemovedFromFolder(chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: currentFilter.title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
return false
}), in: .current)
})
})
})))
} else {
var hasFolders = false
updateChatListFiltersInteractively(transaction: transaction, { filters in
for filter in filters {
let predicate = chatListFilterPredicate(filter: filter.data)
if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) {
continue
}
var data = filter.data
if data.addIncludePeer(peerId: peer.id) {
hasFolders = true
break
}
}
return filters
})
if hasFolders {
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_AddToFolder, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Folder"), color: theme.contextMenu.primaryColor) }, action: { c, _ in
let _ = (context.account.postbox.transaction { transaction -> [ContextMenuItem] in
var updatedItems: [ContextMenuItem] = []
updateChatListFiltersInteractively(transaction: transaction, { filters in
for filter in filters {
let predicate = chatListFilterPredicate(filter: filter.data)
if predicate.includes(peer: peer, groupId: .root, isRemovedFromTotalUnreadCount: isMuted, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: false) {
continue
}
var data = filter.data
if !data.addIncludePeer(peerId: peer.id) {
continue
}
let filterType = chatListFilterType(filter)
updatedItems.append(.action(ContextMenuActionItem(text: filter.title, icon: { theme in
let imageName: String
switch filterType {
case .generic:
imageName = "Chat/Context Menu/List"
case .unmuted:
imageName = "Chat/Context Menu/Unmute"
case .unread:
imageName = "Chat/Context Menu/MarkAsUnread"
case .channels:
imageName = "Chat/Context Menu/Channels"
case .groups:
imageName = "Chat/Context Menu/Groups"
case .bots:
imageName = "Chat/Context Menu/Bots"
case .contacts:
imageName = "Chat/Context Menu/User"
case .nonContacts:
imageName = "Chat/Context Menu/UnknownUser"
}
return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor)
}, action: { c, f in
c.dismiss(completion: {
let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in
var filters = filters
for i in 0 ..< filters.count {
if filters[i].id == filter.id {
let _ = filters[i].data.addIncludePeer(peerId: peer.id)
break
}
}
return filters
})).start()
chatListController?.present(UndoOverlayController(presentationData: presentationData, content: .chatAddedToFolder(chatTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), folderTitle: filter.title), elevatedLayout: false, animateInAsReplacement: true, action: { _ in
return false
}), in: .current)
})
})))
}
return filters
})
updatedItems.append(.separator)
updatedItems.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Back, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor)
}, action: { c, _ in
c.setItems(chatContextMenuItems(context: context, peerId: peerId, promoInfo: promoInfo, source: source, chatListController: chatListController))
})))
return updatedItems
}
|> deliverOnMainQueue).start(next: { updatedItems in
c.setItems(.single(updatedItems))
})
})))
}
}
if isUnread {

View File

@ -155,6 +155,19 @@ public struct ChatListFilterIncludePeers: Equatable, Hashable {
return true
}
public mutating func removePeer(_ peerId: PeerId) -> Bool {
var found = false
if let index = self.pinnedPeers.firstIndex(of: peerId) {
self.pinnedPeers.remove(at: index)
found = true
}
if let index = self.peers.firstIndex(of: peerId) {
self.peers.remove(at: index)
found = true
}
return found
}
public mutating func setPeers(_ peers: [PeerId]) {
self.peers = peers
self.pinnedPeers = self.pinnedPeers.filter { peers.contains($0) }
@ -203,6 +216,20 @@ public struct ChatListFilterData: Equatable, Hashable {
return false
}
}
public mutating func addExcludePeer(peerId: PeerId) -> Bool {
if self.excludePeers.contains(peerId) {
return false
}
if self.excludePeers.count >= 100 {
return false
}
let _ = self.includePeers.removePeer(peerId)
self.excludePeers.append(peerId)
return true
}
}
public struct ChatListFilter: PostboxCoding, Equatable {

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "ic_removefromfolder.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -19,6 +19,7 @@ public enum UndoOverlayContent {
case stickersModified(title: String, text: String, undo: Bool, info: StickerPackCollectionInfo, topItem: ItemCollectionItem?, account: Account)
case dice(dice: TelegramMediaDice, account: Account, text: String, action: String?)
case chatAddedToFolder(chatTitle: String, folderTitle: String)
case chatRemovedFromFolder(chatTitle: String, folderTitle: String)
}
public enum UndoOverlayAction {

View File

@ -181,6 +181,22 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
string.addAttribute(.font, value: Font.regular(14.0), range: range)
}
self.textNode.attributedText = string
displayUndo = false
self.originalRemainingSeconds = 5
case let .chatRemovedFromFolder(chatTitle, folderTitle):
self.iconNode = nil
self.iconCheckNode = nil
self.animationNode = AnimationNode(animation: "anim_success", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0)
self.animatedStickerNode = nil
let (rawString, attributes) = presentationData.strings.ChatList_RemovedFromFolderTooltip(chatTitle, folderTitle)
let string = NSMutableAttributedString(attributedString: NSAttributedString(string: rawString, font: Font.regular(14.0), textColor: .white))
for (_, range) in attributes {
string.addAttribute(.font, value: Font.regular(14.0), range: range)
}
self.textNode.attributedText = string
displayUndo = false
self.originalRemainingSeconds = 5
@ -368,7 +384,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
switch content {
case .removedChat:
self.panelWrapperNode.addSubnode(self.timerTextNode)
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder:
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply, .actionSucceeded, .stickersModified, .chatAddedToFolder, .chatRemovedFromFolder:
break
case .dice:
self.panelWrapperNode.clipsToBounds = true