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

This commit is contained in:
Ilya Laktyushin 2021-02-19 09:54:03 +04:00
commit 70dd6ed1f2
18 changed files with 292 additions and 49 deletions

View File

@ -358,6 +358,7 @@ plist_fragment(
name = "TelegramEntitlements", name = "TelegramEntitlements",
extension = "entitlements", extension = "entitlements",
template = "".join([ template = "".join([
aps_fragment,
app_groups_fragment, app_groups_fragment,
siri_fragment, siri_fragment,
associated_domains_fragment, associated_domains_fragment,
@ -1338,13 +1339,23 @@ swift_intent_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
filegroup(
name = "IntentsAssets",
srcs = glob(["SiriIntents/IntentsImages.xcassets/**"]),
visibility = ["//visibility:public"],
)
swift_library( swift_library(
name = "IntentsExtensionLib", name = "IntentsExtensionLib",
module_name = "IntentsExtensionLib", module_name = "IntentsExtensionLib",
srcs = glob([ srcs = glob([
"SiriIntents/**/*.swift", "SiriIntents/**/*.swift",
]), ]),
data = glob(["SiriIntents/*.lproj/Intents.intentdefinition"]), data = glob([
"SiriIntents/*.lproj/Intents.intentdefinition"
]) + [
":IntentsAssets"
],
deps = [ deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/Postbox:Postbox", "//submodules/Postbox:Postbox",

View File

@ -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, *) @available(iOSApplicationExtension 14.0, iOS 14.0, *)
private func mapPeersToFriends(accountId: AccountRecordId, accountPeerId: PeerId, mediaBox: MediaBox, peers: [Peer]) -> [Friend] { private func mapPeersToFriends(accountId: AccountRecordId, accountPeerId: PeerId, mediaBox: MediaBox, peers: [Peer]) -> [Friend] {
var items: [Friend] = [] var items: [Friend] = []
@ -1231,7 +1299,26 @@ private func mapPeersToFriends(accountId: AccountRecordId, accountPeerId: PeerId
autoreleasepool { autoreleasepool {
var profileImage: INImage? 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) let cachedPath = mediaBox.cachedRepresentationPathForId(resource.id.uniqueId, representationId: "intents.png", keepDuration: .shortLived)
if let _ = fileSize(cachedPath) { if let _ = fileSize(cachedPath) {
do { 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 return items

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,9 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"provides-namespace" : true
}
}

View File

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

View File

@ -92,10 +92,77 @@ private func avatarViewLettersImage(size: CGSize, peerId: Int64, accountPeerId:
return image 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) private let avatarSize = CGSize(width: 50.0, height: 50.0)
func avatarImage(accountPeerId: Int64?, peer: WidgetDataPeer?, size: CGSize) -> UIImage { 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 return roundImage
} else { } else {
return avatarViewLettersImage(size: size, peerId: peer?.id ?? 1, accountPeerId: accountPeerId ?? 1, letters: peer?.letters ?? [" "])! return avatarViewLettersImage(size: size, peerId: peer?.id ?? 1, accountPeerId: accountPeerId ?? 1, letters: peer?.letters ?? [" "])!

View File

@ -316,7 +316,9 @@ struct WidgetView: View {
dateText = "" dateText = ""
} }
var formattedName = peer.peer.name 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)") formattedName.append(" \(lastName)")
} }
chatTitle = AnyView(Text(formattedName) chatTitle = AnyView(Text(formattedName)
@ -575,10 +577,15 @@ struct WidgetView: View {
content = .placeholder content = .placeholder
} }
let avatarView: AvatarItemView
avatarView = AvatarItemView(peer: peers?.peers[index], itemSize: 54.0, placeholderColor: getPlaceholderColor())
return AnyView( return AnyView(
Link(destination: url, label: { Link(destination: url, label: {
HStack(alignment: .center, spacing: 0.0, content: { 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)) chatContent(content).frame(maxWidth: .infinity).padding(EdgeInsets(top: 0.0, leading: 0.0, bottom: 0.0, trailing: 10.0))
}) })
}) })

View File

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

View File

@ -1510,11 +1510,18 @@ public protocol ContextExtractedContentSource: class {
var keepInPlace: Bool { get } var keepInPlace: Bool { get }
var ignoreContentTouches: Bool { get } var ignoreContentTouches: Bool { get }
var blurBackground: Bool { get } var blurBackground: Bool { get }
var shouldBeDismissed: Signal<Bool, NoError> { get }
func takeView() -> ContextControllerTakeViewInfo? func takeView() -> ContextControllerTakeViewInfo?
func putBack() -> ContextControllerPutBackViewInfo? func putBack() -> ContextControllerPutBackViewInfo?
} }
public extension ContextExtractedContentSource {
var shouldBeDismissed: Signal<Bool, NoError> {
return .single(false)
}
}
public protocol ContextControllerContentSource: class { public protocol ContextControllerContentSource: class {
var controller: ViewController { get } var controller: ViewController { get }
var navigationController: NavigationController? { get } var navigationController: NavigationController? { get }
@ -1555,6 +1562,8 @@ public final class ContextController: ViewController, StandalonePresentableContr
public var reactionSelected: ((ReactionContextItem.Reaction) -> Void)? 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) { 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.account = account
self.presentationData = presentationData self.presentationData = presentationData
@ -1567,8 +1576,19 @@ public final class ContextController: ViewController, StandalonePresentableContr
super.init(navigationBarPresentationData: nil) super.init(navigationBarPresentationData: nil)
if case let .extracted(extractedSource) = source, !extractedSource.blurBackground { if case let .extracted(extractedSource) = source {
self.statusBar.statusBarStyle = .Ignore 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 { } else {
self.statusBar.statusBarStyle = .Hide self.statusBar.statusBarStyle = .Hide
} }
@ -1579,6 +1599,10 @@ public final class ContextController: ViewController, StandalonePresentableContr
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
deinit {
self.shouldBeDismissedDisposable?.dispose()
}
override public func loadDisplayNode() { 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.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) self?.dismiss(result: result, completion: nil)

View File

@ -463,6 +463,7 @@ public class GalleryController: ViewController, StandalonePresentableController
} }
} }
} }
|> take(1)
let semaphore: DispatchSemaphore? let semaphore: DispatchSemaphore?
if synchronousLoad { if synchronousLoad {
@ -486,23 +487,6 @@ public class GalleryController: ViewController, StandalonePresentableController
strongSelf.configuration = configuration strongSelf.configuration = configuration
let entries = view.entries 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? var centralEntryStableId: UInt32?
loop: for i in 0 ..< entries.count { loop: for i in 0 ..< entries.count {
let message = entries[i].message let message = entries[i].message
@ -531,16 +515,14 @@ public class GalleryController: ViewController, StandalonePresentableController
strongSelf.entries = entries.reversed() strongSelf.entries = entries.reversed()
strongSelf.hasLeftEntries = view.hasLater strongSelf.hasLeftEntries = view.hasLater
strongSelf.hasRightEntries = view.hasEarlier strongSelf.hasRightEntries = view.hasEarlier
if strongSelf.centralEntryStableId == nil, let centralEntryStableId = centralEntryStableId { if let centralEntryStableId = centralEntryStableId {
strongSelf.centralEntryStableId = centralEntryStableId strongSelf.centralEntryStableId = centralEntryStableId
} }
} else { } else {
strongSelf.entries = entries strongSelf.entries = entries
strongSelf.hasLeftEntries = view.hasEarlier strongSelf.hasLeftEntries = view.hasEarlier
strongSelf.hasRightEntries = view.hasLater strongSelf.hasRightEntries = view.hasLater
if strongSelf.centralEntryStableId == nil { strongSelf.centralEntryStableId = centralEntryStableId
strongSelf.centralEntryStableId = centralEntryStableId
}
} }
if strongSelf.isViewLoaded { if strongSelf.isViewLoaded {
var items: [GalleryItem] = [] var items: [GalleryItem] = []
@ -565,17 +547,13 @@ public class GalleryController: ViewController, StandalonePresentableController
strongSelf.galleryNode.pager.replaceItems(items, centralItemIndex: centralItemIndex) strongSelf.galleryNode.pager.replaceItems(items, centralItemIndex: centralItemIndex)
if strongSelf.temporaryDoNotWaitForReady { if strongSelf.temporaryDoNotWaitForReady {
if !strongSelf.didSetReady { strongSelf.didSetReady = true
strongSelf.didSetReady = true strongSelf._ready.set(.single(true))
strongSelf._ready.set(.single(true))
}
} else { } else {
if !strongSelf.didSetReady { let ready = strongSelf.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak strongSelf] _ in
let ready = strongSelf.galleryNode.pager.ready() |> timeout(2.0, queue: Queue.mainQueue(), alternate: .single(Void())) |> afterNext { [weak strongSelf] _ in strongSelf?.didSetReady = true
strongSelf?.didSetReady = true
}
strongSelf._ready.set(ready |> map { true })
} }
strongSelf._ready.set(ready |> map { true })
} }
} }
} }
@ -590,7 +568,7 @@ public class GalleryController: ViewController, StandalonePresentableController
return (true, nil) return (true, nil)
} }
semaphore?.signal() semaphore?.signal()
if process || true { if process {
Queue.mainQueue().async { Queue.mainQueue().async {
f() f()
} }

View File

@ -121,7 +121,7 @@ private func peerAutoremoveSetupEntries(peer: Peer?, presentationData: Presentat
24 * 60 * 60 * 7 24 * 60 * 60 * 7
] ]
if isDebug || true { if isDebug || true {
availableValues[1] = 60 availableValues[1] = 5
availableValues[2] = 5 * 60 availableValues[2] = 5 * 60
} }
entries.append(.timeValue(resolvedValue, availableValues)) entries.append(.timeValue(resolvedValue, availableValues))

View File

@ -298,6 +298,8 @@ public final class SqliteValueBox: ValueBox {
preconditionFailure("Couldn't open database") preconditionFailure("Couldn't open database")
} }
sqlite3_busy_timeout(database.handle, 1000 * 10000)
var resultCode: Bool = true var resultCode: Bool = true
resultCode = database.execute("PRAGMA cipher_plaintext_header_size=32") 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") //database.execute("PRAGMA cache_size=-2097152")
resultCode = database.execute("PRAGMA mmap_size=0") resultCode = database.execute("PRAGMA mmap_size=0")
assert(resultCode) assert(resultCode)

View File

@ -844,7 +844,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let _ = ApplicationSpecificNotice.incrementChatTextSelectionTips(accountManager: strongSelf.context.sharedContext.accountManager).start() 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 strongSelf.currentContextController = controller
controller.reactionSelected = { [weak controller] value in controller.reactionSelected = { [weak controller] value in
guard let strongSelf = self, let message = updatedMessages.first else { 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.currentContextController = controller
strongSelf.forEachController({ controller in strongSelf.forEachController({ controller in
if let controller = controller as? TooltipScreen { if let controller = controller as? TooltipScreen {
@ -1947,7 +1947,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
f(.dismissWithoutContent) 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.currentContextController = controller
strongSelf.forEachController({ controller in strongSelf.forEachController({ controller in
if let controller = controller as? TooltipScreen { if let controller = controller as? TooltipScreen {

View File

@ -3,6 +3,7 @@ import UIKit
import Display import Display
import ContextUI import ContextUI
import Postbox import Postbox
import SwiftSignalKit
final class ChatMessageContextExtractedContentSource: ContextExtractedContentSource { final class ChatMessageContextExtractedContentSource: ContextExtractedContentSource {
let keepInPlace: Bool = false let keepInPlace: Bool = false
@ -10,11 +11,29 @@ final class ChatMessageContextExtractedContentSource: ContextExtractedContentSou
let blurBackground: Bool = true let blurBackground: Bool = true
private weak var chatNode: ChatControllerNode? private weak var chatNode: ChatControllerNode?
private let postbox: Postbox
private let message: Message private let message: Message
private let selectAll: Bool private let selectAll: Bool
init(chatNode: ChatControllerNode, message: Message, selectAll: Bool) { var shouldBeDismissed: Signal<Bool, NoError> {
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.chatNode = chatNode
self.postbox = postbox
self.message = message self.message = message
self.selectAll = selectAll self.selectAll = selectAll
} }

View File

@ -277,7 +277,8 @@ final class WidgetDataContext {
autodeleteTimerUpdated: presentationData.strings.Widget_MessageAutoremoveTimerUpdated, autodeleteTimerUpdated: presentationData.strings.Widget_MessageAutoremoveTimerUpdated,
autodeleteTimerRemoved: presentationData.strings.Widget_MessageAutoremoveTimerRemoved, autodeleteTimerRemoved: presentationData.strings.Widget_MessageAutoremoveTimerRemoved,
generalLockedTitle: presentationData.strings.Intents_ErrorLockedTitle, 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 |> distinctUntilChanged).start(next: { value in

View File

@ -300,6 +300,8 @@ public struct WidgetPresentationData: Codable, Equatable {
public var generalLockedTitle: String public var generalLockedTitle: String
public var generalLockedText: String public var generalLockedText: String
public var chatSavedMessages: String
public init( public init(
widgetChatsGalleryTitle: String, widgetChatsGalleryTitle: String,
widgetChatsGalleryDescription: String, widgetChatsGalleryDescription: String,
@ -321,7 +323,8 @@ public struct WidgetPresentationData: Codable, Equatable {
autodeleteTimerUpdated: String, autodeleteTimerUpdated: String,
autodeleteTimerRemoved: String, autodeleteTimerRemoved: String,
generalLockedTitle: String, generalLockedTitle: String,
generalLockedText: String generalLockedText: String,
chatSavedMessages: String
) { ) {
self.widgetChatsGalleryTitle = widgetChatsGalleryTitle self.widgetChatsGalleryTitle = widgetChatsGalleryTitle
self.widgetChatsGalleryDescription = widgetChatsGalleryDescription self.widgetChatsGalleryDescription = widgetChatsGalleryDescription
@ -344,6 +347,7 @@ public struct WidgetPresentationData: Codable, Equatable {
self.autodeleteTimerRemoved = autodeleteTimerRemoved self.autodeleteTimerRemoved = autodeleteTimerRemoved
self.generalLockedTitle = generalLockedTitle self.generalLockedTitle = generalLockedTitle
self.generalLockedText = generalLockedText self.generalLockedText = generalLockedText
self.chatSavedMessages = chatSavedMessages
} }
public static func getForExtension() -> WidgetPresentationData { public static func getForExtension() -> WidgetPresentationData {
@ -392,7 +396,8 @@ public extension WidgetPresentationData {
autodeleteTimerUpdated: "Auto-delete timer updated", autodeleteTimerUpdated: "Auto-delete timer updated",
autodeleteTimerRemoved: "Auto-delete timer disabled", autodeleteTimerRemoved: "Auto-delete timer disabled",
generalLockedTitle: "Locked", generalLockedTitle: "Locked",
generalLockedText: "Open Telegram and enter passcode to edit widget." generalLockedText: "Open Telegram and enter passcode to edit widget.",
chatSavedMessages: "Saved Messages"
) )
} }