diff --git a/Telegram/BUILD b/Telegram/BUILD index 5893fd8821..d9af42bf74 100644 --- a/Telegram/BUILD +++ b/Telegram/BUILD @@ -358,6 +358,7 @@ plist_fragment( name = "TelegramEntitlements", extension = "entitlements", template = "".join([ + aps_fragment, app_groups_fragment, siri_fragment, associated_domains_fragment, @@ -1338,13 +1339,23 @@ swift_intent_library( visibility = ["//visibility:public"], ) +filegroup( + name = "IntentsAssets", + srcs = glob(["SiriIntents/IntentsImages.xcassets/**"]), + visibility = ["//visibility:public"], +) + swift_library( name = "IntentsExtensionLib", module_name = "IntentsExtensionLib", srcs = glob([ "SiriIntents/**/*.swift", ]), - data = glob(["SiriIntents/*.lproj/Intents.intentdefinition"]), + data = glob([ + "SiriIntents/*.lproj/Intents.intentdefinition" + ]) + [ + ":IntentsAssets" + ], deps = [ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/Postbox:Postbox", diff --git a/Telegram/SiriIntents/IntentHandler.swift b/Telegram/SiriIntents/IntentHandler.swift index d8b6dc86e5..2d833a6c71 100644 --- a/Telegram/SiriIntents/IntentHandler.swift +++ b/Telegram/SiriIntents/IntentHandler.swift @@ -1224,6 +1224,74 @@ private func avatarImage(path: String?, peerId: Int64, accountPeerId: Int64, let } } +private func generateTintedImage(image: UIImage?, color: UIColor, backgroundColor: UIColor? = nil) -> UIImage? { + guard let image = image else { + return nil + } + + let imageSize = image.size + + UIGraphicsBeginImageContextWithOptions(imageSize, backgroundColor != nil, image.scale) + if let context = UIGraphicsGetCurrentContext() { + if let backgroundColor = backgroundColor { + context.setFillColor(backgroundColor.cgColor) + context.fill(CGRect(origin: CGPoint(), size: imageSize)) + } + + let imageRect = CGRect(origin: CGPoint(), size: imageSize) + context.saveGState() + context.translateBy(x: imageRect.midX, y: imageRect.midY) + context.scaleBy(x: 1.0, y: -1.0) + context.translateBy(x: -imageRect.midX, y: -imageRect.midY) + context.clip(to: imageRect, mask: image.cgImage!) + context.setFillColor(color.cgColor) + context.fill(imageRect) + context.restoreGState() + } + + let tintedImage = UIGraphicsGetImageFromCurrentImageContext()! + UIGraphicsEndImageContext() + + return tintedImage +} + +private let savedMessagesColors: NSArray = [ + UIColor(rgb: 0x2a9ef1).cgColor, UIColor(rgb: 0x72d5fd).cgColor +] + +private func savedMessagesImage(size: CGSize) -> UIImage? { + guard let icon = generateTintedImage(image: UIImage(named: "Intents/SavedMessages"), color: .white) else { + return nil + } + UIGraphicsBeginImageContextWithOptions(size, false, 0.0) + let context = UIGraphicsGetCurrentContext() + + context?.beginPath() + context?.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)) + context?.clip() + + let colorsArray = savedMessagesColors + var locations: [CGFloat] = [1.0, 0.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray, locations: &locations)! + + context?.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) + + context?.setBlendMode(.normal) + + let factor = size.width / 60.0 + context?.translateBy(x: size.width / 2.0, y: size.height / 2.0) + context?.scaleBy(x: factor, y: -factor) + context?.translateBy(x: -size.width / 2.0, y: -size.height / 2.0) + + if let context = context { + context.draw(icon.cgImage!, in: CGRect(origin: CGPoint(x: floor((size.width - icon.size.width) / 2.0), y: floor((size.height - icon.size.height) / 2.0)), size: icon.size)) + } + + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return image +} + @available(iOSApplicationExtension 14.0, iOS 14.0, *) private func mapPeersToFriends(accountId: AccountRecordId, accountPeerId: PeerId, mediaBox: MediaBox, peers: [Peer]) -> [Friend] { var items: [Friend] = [] @@ -1231,7 +1299,26 @@ private func mapPeersToFriends(accountId: AccountRecordId, accountPeerId: PeerId autoreleasepool { var profileImage: INImage? - if let resource = smallestImageRepresentation(peer.profileImageRepresentations)?.resource, let path = mediaBox.completedResourcePath(resource) { + if peer.id == accountPeerId { + let cachedPath = mediaBox.cachedRepresentationPathForId("savedMessagesAvatar50x50", representationId: "intents.png", keepDuration: .shortLived) + if let _ = fileSize(cachedPath) { + do { + let data = try Data(contentsOf: URL(fileURLWithPath: cachedPath), options: .alwaysMapped) + profileImage = INImage(imageData: data) + } catch { + } + } else { + let image = savedMessagesImage(size: CGSize(width: 50.0, height: 50.0)) + if let data = image?.pngData() { + let _ = try? data.write(to: URL(fileURLWithPath: cachedPath), options: .atomic) + } + do { + let data = try Data(contentsOf: URL(fileURLWithPath: cachedPath), options: .alwaysMapped) + profileImage = INImage(imageData: data) + } catch { + } + } + } else if let resource = smallestImageRepresentation(peer.profileImageRepresentations)?.resource, let path = mediaBox.completedResourcePath(resource) { let cachedPath = mediaBox.cachedRepresentationPathForId(resource.id.uniqueId, representationId: "intents.png", keepDuration: .shortLived) if let _ = fileSize(cachedPath) { do { @@ -1272,7 +1359,12 @@ private func mapPeersToFriends(accountId: AccountRecordId, accountPeerId: PeerId } } - items.append(Friend(identifier: "\(accountId.int64):\(peer.id.toInt64())", display: peer.debugDisplayTitle, subtitle: nil, image: profileImage)) + var displayTitle = peer.debugDisplayTitle + if peer.id == accountPeerId { + displayTitle = WidgetPresentationData.getForExtension().chatSavedMessages + } + + items.append(Friend(identifier: "\(accountId.int64):\(peer.id.toInt64())", display: displayTitle, subtitle: nil, image: profileImage)) } } return items diff --git a/Telegram/SiriIntents/IntentsImages.xcassets/Contents.json b/Telegram/SiriIntents/IntentsImages.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/Telegram/SiriIntents/IntentsImages.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Telegram/SiriIntents/IntentsImages.xcassets/Intents/Contents.json b/Telegram/SiriIntents/IntentsImages.xcassets/Intents/Contents.json new file mode 100644 index 0000000000..6e965652df --- /dev/null +++ b/Telegram/SiriIntents/IntentsImages.xcassets/Intents/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/Telegram/SiriIntents/IntentsImages.xcassets/Intents/SavedMessages.imageset/Contents.json b/Telegram/SiriIntents/IntentsImages.xcassets/Intents/SavedMessages.imageset/Contents.json new file mode 100644 index 0000000000..2265cbc0ac --- /dev/null +++ b/Telegram/SiriIntents/IntentsImages.xcassets/Intents/SavedMessages.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_av_savedmessages (2).pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Telegram/SiriIntents/IntentsImages.xcassets/Intents/SavedMessages.imageset/ic_av_savedmessages (2).pdf b/Telegram/SiriIntents/IntentsImages.xcassets/Intents/SavedMessages.imageset/ic_av_savedmessages (2).pdf new file mode 100644 index 0000000000..6199cc1152 Binary files /dev/null and b/Telegram/SiriIntents/IntentsImages.xcassets/Intents/SavedMessages.imageset/ic_av_savedmessages (2).pdf differ diff --git a/Telegram/WidgetKitWidget/PeerNode.swift b/Telegram/WidgetKitWidget/PeerNode.swift index 97cd9ba502..7308b76090 100644 --- a/Telegram/WidgetKitWidget/PeerNode.swift +++ b/Telegram/WidgetKitWidget/PeerNode.swift @@ -92,10 +92,77 @@ private func avatarViewLettersImage(size: CGSize, peerId: Int64, accountPeerId: return image } +private func generateTintedImage(image: UIImage?, color: UIColor, backgroundColor: UIColor? = nil) -> UIImage? { + guard let image = image else { + return nil + } + + let imageSize = image.size + + UIGraphicsBeginImageContextWithOptions(imageSize, backgroundColor != nil, image.scale) + if let context = UIGraphicsGetCurrentContext() { + if let backgroundColor = backgroundColor { + context.setFillColor(backgroundColor.cgColor) + context.fill(CGRect(origin: CGPoint(), size: imageSize)) + } + + let imageRect = CGRect(origin: CGPoint(), size: imageSize) + context.saveGState() + context.translateBy(x: imageRect.midX, y: imageRect.midY) + context.scaleBy(x: 1.0, y: -1.0) + context.translateBy(x: -imageRect.midX, y: -imageRect.midY) + context.clip(to: imageRect, mask: image.cgImage!) + context.setFillColor(color.cgColor) + context.fill(imageRect) + context.restoreGState() + } + + let tintedImage = UIGraphicsGetImageFromCurrentImageContext()! + UIGraphicsEndImageContext() + + return tintedImage +} + +private let savedMessagesColors: NSArray = [ + UIColor(rgb: 0x2a9ef1).cgColor, UIColor(rgb: 0x72d5fd).cgColor +] + +private func savedMessagesImage(size: CGSize) -> UIImage? { + UIGraphicsBeginImageContextWithOptions(size, false, 0.0) + let context = UIGraphicsGetCurrentContext() + + context?.beginPath() + context?.addEllipse(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)) + context?.clip() + + let colorsArray = savedMessagesColors + var locations: [CGFloat] = [1.0, 0.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray, locations: &locations)! + + context?.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions()) + + context?.setBlendMode(.normal) + + let factor = size.width / 60.0 + context?.translateBy(x: size.width / 2.0, y: size.height / 2.0) + context?.scaleBy(x: factor, y: -factor) + context?.translateBy(x: -size.width / 2.0, y: -size.height / 2.0) + + if let context = context, let icon = generateTintedImage(image: UIImage(named: "Widget/SavedMessages"), color: .white) { + context.draw(icon.cgImage!, in: CGRect(origin: CGPoint(x: floor((size.width - icon.size.width) / 2.0), y: floor((size.height - icon.size.height) / 2.0)), size: icon.size)) + } + + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return image +} + private let avatarSize = CGSize(width: 50.0, height: 50.0) func avatarImage(accountPeerId: Int64?, peer: WidgetDataPeer?, size: CGSize) -> UIImage { - if let path = peer?.avatarPath, let image = UIImage(contentsOfFile: path), let roundImage = avatarRoundImage(size: size, source: image) { + if let peer = peer, let accountPeerId = accountPeerId, peer.id == accountPeerId { + return savedMessagesImage(size: size)! + } else if let path = peer?.avatarPath, let image = UIImage(contentsOfFile: path), let roundImage = avatarRoundImage(size: size, source: image) { return roundImage } else { return avatarViewLettersImage(size: size, peerId: peer?.id ?? 1, accountPeerId: accountPeerId ?? 1, letters: peer?.letters ?? [" "])! diff --git a/Telegram/WidgetKitWidget/TodayViewController.swift b/Telegram/WidgetKitWidget/TodayViewController.swift index b459177fcf..efa8b4798f 100644 --- a/Telegram/WidgetKitWidget/TodayViewController.swift +++ b/Telegram/WidgetKitWidget/TodayViewController.swift @@ -316,7 +316,9 @@ struct WidgetView: View { dateText = "" } var formattedName = peer.peer.name - if let lastName = peer.peer.lastName { + if peer.accountPeerId == peer.peer.id { + formattedName = self.presentationData.chatSavedMessages + } else if let lastName = peer.peer.lastName { formattedName.append(" \(lastName)") } chatTitle = AnyView(Text(formattedName) @@ -575,10 +577,15 @@ struct WidgetView: View { content = .placeholder } + let avatarView: AvatarItemView + avatarView = AvatarItemView(peer: peers?.peers[index], itemSize: 54.0, placeholderColor: getPlaceholderColor()) + return AnyView( Link(destination: url, label: { HStack(alignment: .center, spacing: 0.0, content: { - AvatarItemView(peer: peers?.peers[index], itemSize: 54.0, placeholderColor: getPlaceholderColor()).frame(width: 54.0, height: 54.0, alignment: .leading).padding(EdgeInsets(top: 0.0, leading: 10.0, bottom: 0.0, trailing: 10.0)) + avatarView + .frame(width: 54.0, height: 54.0, alignment: .leading) + .padding(EdgeInsets(top: 0.0, leading: 10.0, bottom: 0.0, trailing: 10.0)) chatContent(content).frame(maxWidth: .infinity).padding(EdgeInsets(top: 0.0, leading: 0.0, bottom: 0.0, trailing: 10.0)) }) }) diff --git a/Telegram/WidgetKitWidget/WidgetImages.xcassets/Widget/SavedMessages.imageset/Contents.json b/Telegram/WidgetKitWidget/WidgetImages.xcassets/Widget/SavedMessages.imageset/Contents.json new file mode 100644 index 0000000000..2265cbc0ac --- /dev/null +++ b/Telegram/WidgetKitWidget/WidgetImages.xcassets/Widget/SavedMessages.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_av_savedmessages (2).pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Telegram/WidgetKitWidget/WidgetImages.xcassets/Widget/SavedMessages.imageset/ic_av_savedmessages (2).pdf b/Telegram/WidgetKitWidget/WidgetImages.xcassets/Widget/SavedMessages.imageset/ic_av_savedmessages (2).pdf new file mode 100644 index 0000000000..6199cc1152 Binary files /dev/null and b/Telegram/WidgetKitWidget/WidgetImages.xcassets/Widget/SavedMessages.imageset/ic_av_savedmessages (2).pdf differ diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index a40ea194b5..9d3b6f94b8 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -1510,11 +1510,18 @@ public protocol ContextExtractedContentSource: class { var keepInPlace: Bool { get } var ignoreContentTouches: Bool { get } var blurBackground: Bool { get } + var shouldBeDismissed: Signal { get } func takeView() -> ContextControllerTakeViewInfo? func putBack() -> ContextControllerPutBackViewInfo? } +public extension ContextExtractedContentSource { + var shouldBeDismissed: Signal { + return .single(false) + } +} + public protocol ContextControllerContentSource: class { var controller: ViewController { get } var navigationController: NavigationController? { get } @@ -1555,6 +1562,8 @@ public final class ContextController: ViewController, StandalonePresentableContr public var reactionSelected: ((ReactionContextItem.Reaction) -> Void)? + private var shouldBeDismissedDisposable: Disposable? + public init(account: Account, presentationData: PresentationData, source: ContextContentSource, items: Signal<[ContextMenuItem], NoError>, reactionItems: [ReactionContextItem], recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil, displayTextSelectionTip: Bool = false) { self.account = account self.presentationData = presentationData @@ -1567,8 +1576,19 @@ public final class ContextController: ViewController, StandalonePresentableContr super.init(navigationBarPresentationData: nil) - if case let .extracted(extractedSource) = source, !extractedSource.blurBackground { - self.statusBar.statusBarStyle = .Ignore + if case let .extracted(extractedSource) = source { + if !extractedSource.blurBackground { + self.statusBar.statusBarStyle = .Ignore + } + self.shouldBeDismissedDisposable = (extractedSource.shouldBeDismissed + |> filter { $0 } + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] _ in + guard let strongSelf = self else { + return + } + strongSelf.dismiss(result: .default, completion: {}) + }) } else { self.statusBar.statusBarStyle = .Hide } @@ -1579,6 +1599,10 @@ public final class ContextController: ViewController, StandalonePresentableContr fatalError("init(coder:) has not been implemented") } + deinit { + self.shouldBeDismissedDisposable?.dispose() + } + override public func loadDisplayNode() { self.displayNode = ContextControllerNode(account: self.account, controller: self, presentationData: self.presentationData, source: self.source, items: self.items, reactionItems: self.reactionItems, beginDismiss: { [weak self] result in self?.dismiss(result: result, completion: nil) diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index ab2d04e0f5..9f07705918 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -463,6 +463,7 @@ public class GalleryController: ViewController, StandalonePresentableController } } } + |> take(1) let semaphore: DispatchSemaphore? if synchronousLoad { @@ -486,23 +487,6 @@ public class GalleryController: ViewController, StandalonePresentableController strongSelf.configuration = configuration let entries = view.entries - - if let centralEntryStableId = strongSelf.centralEntryStableId { - var found = false - for i in 0 ..< entries.count { - let message = entries[i].message - if message.stableId == centralEntryStableId { - found = true - break - } - } - - if !found { - strongSelf.dismiss(forceAway: true) - return - } - } - var centralEntryStableId: UInt32? loop: for i in 0 ..< entries.count { let message = entries[i].message @@ -531,16 +515,14 @@ public class GalleryController: ViewController, StandalonePresentableController strongSelf.entries = entries.reversed() strongSelf.hasLeftEntries = view.hasLater strongSelf.hasRightEntries = view.hasEarlier - if strongSelf.centralEntryStableId == nil, let centralEntryStableId = centralEntryStableId { + if let centralEntryStableId = centralEntryStableId { strongSelf.centralEntryStableId = centralEntryStableId } } else { strongSelf.entries = entries strongSelf.hasLeftEntries = view.hasEarlier strongSelf.hasRightEntries = view.hasLater - if strongSelf.centralEntryStableId == nil { - strongSelf.centralEntryStableId = centralEntryStableId - } + strongSelf.centralEntryStableId = centralEntryStableId } if strongSelf.isViewLoaded { var items: [GalleryItem] = [] @@ -565,17 +547,13 @@ public class GalleryController: ViewController, StandalonePresentableController strongSelf.galleryNode.pager.replaceItems(items, centralItemIndex: centralItemIndex) if strongSelf.temporaryDoNotWaitForReady { - if !strongSelf.didSetReady { - strongSelf.didSetReady = true - strongSelf._ready.set(.single(true)) - } + strongSelf.didSetReady = true + strongSelf._ready.set(.single(true)) } else { - if !strongSelf.didSetReady { - let ready = strongSelf.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak strongSelf] _ in - strongSelf?.didSetReady = true - } - strongSelf._ready.set(ready |> map { true }) + let ready = strongSelf.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak strongSelf] _ in + strongSelf?.didSetReady = true } + strongSelf._ready.set(ready |> map { true }) } } } @@ -590,7 +568,7 @@ public class GalleryController: ViewController, StandalonePresentableController return (true, nil) } semaphore?.signal() - if process || true { + if process { Queue.mainQueue().async { f() } diff --git a/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift b/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift index f2fcf945ef..99ffac0867 100644 --- a/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift +++ b/submodules/PeerInfoUI/Sources/PeerAutoremoveSetupScreen.swift @@ -121,7 +121,7 @@ private func peerAutoremoveSetupEntries(peer: Peer?, presentationData: Presentat 24 * 60 * 60 * 7 ] if isDebug || true { - availableValues[1] = 60 + availableValues[1] = 5 availableValues[2] = 5 * 60 } entries.append(.timeValue(resolvedValue, availableValues)) diff --git a/submodules/Postbox/Sources/SqliteValueBox.swift b/submodules/Postbox/Sources/SqliteValueBox.swift index 177517a796..0ae732a92a 100644 --- a/submodules/Postbox/Sources/SqliteValueBox.swift +++ b/submodules/Postbox/Sources/SqliteValueBox.swift @@ -298,6 +298,8 @@ public final class SqliteValueBox: ValueBox { preconditionFailure("Couldn't open database") } + sqlite3_busy_timeout(database.handle, 1000 * 10000) + var resultCode: Bool = true resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32") @@ -408,8 +410,6 @@ public final class SqliteValueBox: ValueBox { } } - sqlite3_busy_timeout(database.handle, 1000 * 10000) - //database.execute("PRAGMA cache_size=-2097152") resultCode = database.execute("PRAGMA mmap_size=0") assert(resultCode) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index ae61cbfa6c..31f5ca6e77 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -844,7 +844,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let _ = ApplicationSpecificNotice.incrementChatTextSelectionTips(accountManager: strongSelf.context.sharedContext.accountManager).start() } - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message, selectAll: selectAll)), items: .single(actions), reactionItems: reactionItems, recognizer: recognizer, gesture: gesture, displayTextSelectionTip: displayTextSelectionTip) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, selectAll: selectAll)), items: .single(actions), reactionItems: reactionItems, recognizer: recognizer, gesture: gesture, displayTextSelectionTip: displayTextSelectionTip) strongSelf.currentContextController = controller controller.reactionSelected = { [weak controller] value in guard let strongSelf = self, let message = updatedMessages.first else { @@ -1870,7 +1870,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }))) - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message, selectAll: true)), items: .single(actions), reactionItems: [], recognizer: nil) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, selectAll: true)), items: .single(actions), reactionItems: [], recognizer: nil) strongSelf.currentContextController = controller strongSelf.forEachController({ controller in if let controller = controller as? TooltipScreen { @@ -1947,7 +1947,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G f(.dismissWithoutContent) }))) - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: topMessage, selectAll: true)), items: .single(actions), reactionItems: [], recognizer: nil) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: topMessage, selectAll: true)), items: .single(actions), reactionItems: [], recognizer: nil) strongSelf.currentContextController = controller strongSelf.forEachController({ controller in if let controller = controller as? TooltipScreen { diff --git a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift index 9740f7e645..20ea32ca77 100644 --- a/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift +++ b/submodules/TelegramUI/Sources/ChatMessageContextControllerContentSource.swift @@ -3,6 +3,7 @@ import UIKit import Display import ContextUI import Postbox +import SwiftSignalKit final class ChatMessageContextExtractedContentSource: ContextExtractedContentSource { let keepInPlace: Bool = false @@ -10,11 +11,29 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou let blurBackground: Bool = true private weak var chatNode: ChatControllerNode? + private let postbox: Postbox private let message: Message private let selectAll: Bool - init(chatNode: ChatControllerNode, message: Message, selectAll: Bool) { + var shouldBeDismissed: Signal { + let viewKey = PostboxViewKey.messages(Set([self.message.id])) + return self.postbox.combinedView(keys: [viewKey]) + |> map { views -> Bool in + guard let view = views.views[viewKey] as? MessagesView else { + return false + } + if view.messages.isEmpty { + return true + } else { + return false + } + } + |> distinctUntilChanged + } + + init(chatNode: ChatControllerNode, postbox: Postbox, message: Message, selectAll: Bool) { self.chatNode = chatNode + self.postbox = postbox self.message = message self.selectAll = selectAll } diff --git a/submodules/TelegramUI/Sources/WidgetDataContext.swift b/submodules/TelegramUI/Sources/WidgetDataContext.swift index d4c99d73f7..c21891bade 100644 --- a/submodules/TelegramUI/Sources/WidgetDataContext.swift +++ b/submodules/TelegramUI/Sources/WidgetDataContext.swift @@ -277,7 +277,8 @@ final class WidgetDataContext { autodeleteTimerUpdated: presentationData.strings.Widget_MessageAutoremoveTimerUpdated, autodeleteTimerRemoved: presentationData.strings.Widget_MessageAutoremoveTimerRemoved, generalLockedTitle: presentationData.strings.Intents_ErrorLockedTitle, - generalLockedText: presentationData.strings.Intents_ErrorLockedText + generalLockedText: presentationData.strings.Intents_ErrorLockedText, + chatSavedMessages: presentationData.strings.DialogList_SavedMessages ) } |> distinctUntilChanged).start(next: { value in diff --git a/submodules/WidgetItems/Sources/WidgetItems.swift b/submodules/WidgetItems/Sources/WidgetItems.swift index 5466b2c6b3..4cf5ea1328 100644 --- a/submodules/WidgetItems/Sources/WidgetItems.swift +++ b/submodules/WidgetItems/Sources/WidgetItems.swift @@ -300,6 +300,8 @@ public struct WidgetPresentationData: Codable, Equatable { public var generalLockedTitle: String public var generalLockedText: String + public var chatSavedMessages: String + public init( widgetChatsGalleryTitle: String, widgetChatsGalleryDescription: String, @@ -321,7 +323,8 @@ public struct WidgetPresentationData: Codable, Equatable { autodeleteTimerUpdated: String, autodeleteTimerRemoved: String, generalLockedTitle: String, - generalLockedText: String + generalLockedText: String, + chatSavedMessages: String ) { self.widgetChatsGalleryTitle = widgetChatsGalleryTitle self.widgetChatsGalleryDescription = widgetChatsGalleryDescription @@ -344,6 +347,7 @@ public struct WidgetPresentationData: Codable, Equatable { self.autodeleteTimerRemoved = autodeleteTimerRemoved self.generalLockedTitle = generalLockedTitle self.generalLockedText = generalLockedText + self.chatSavedMessages = chatSavedMessages } public static func getForExtension() -> WidgetPresentationData { @@ -392,7 +396,8 @@ public extension WidgetPresentationData { autodeleteTimerUpdated: "Auto-delete timer updated", autodeleteTimerRemoved: "Auto-delete timer disabled", generalLockedTitle: "Locked", - generalLockedText: "Open Telegram and enter passcode to edit widget." + generalLockedText: "Open Telegram and enter passcode to edit widget.", + chatSavedMessages: "Saved Messages" ) }