mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-07 08:01:10 +00:00
Added recent stickers clearing Added sending logs via email Added forward recipient change on forward acccessory panel tap Tweaked undo panel design Various UI fixes
219 lines
9.3 KiB
Swift
219 lines
9.3 KiB
Swift
import Foundation
|
|
import AsyncDisplayKit
|
|
import TelegramCore
|
|
import Postbox
|
|
import SwiftSignalKit
|
|
import Display
|
|
|
|
func textStringForForwardedMessage(_ message: Message, strings: PresentationStrings) -> (String, Bool) {
|
|
for media in message.media {
|
|
switch media {
|
|
case _ as TelegramMediaImage:
|
|
return (strings.ForwardedPhotos(1), true)
|
|
case let file as TelegramMediaFile:
|
|
var fileName: String = strings.ForwardedFiles(1)
|
|
for attribute in file.attributes {
|
|
switch attribute {
|
|
case .Sticker:
|
|
return (strings.ForwardedStickers(1), true)
|
|
case let .FileName(name):
|
|
fileName = name
|
|
case let .Audio(isVoice, _, title, performer, _):
|
|
if isVoice {
|
|
return (strings.ForwardedAudios(1), true)
|
|
} else {
|
|
if let title = title, let performer = performer, !title.isEmpty, !performer.isEmpty {
|
|
return (title + " — " + performer, true)
|
|
} else if let title = title, !title.isEmpty {
|
|
return (title, true)
|
|
} else if let performer = performer, !performer.isEmpty {
|
|
return (performer, true)
|
|
} else {
|
|
return (strings.ForwardedAudios(1), true)
|
|
}
|
|
}
|
|
case .Video:
|
|
if file.isAnimated {
|
|
return (strings.ForwardedGifs(1), true)
|
|
} else {
|
|
return (strings.ForwardedVideos(1), true)
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
return (fileName, true)
|
|
case _ as TelegramMediaContact:
|
|
return (strings.ForwardedContacts(1), true)
|
|
case let game as TelegramMediaGame:
|
|
return (game.title, true)
|
|
case _ as TelegramMediaMap:
|
|
return (strings.ForwardedLocations(1), true)
|
|
case _ as TelegramMediaAction:
|
|
return ("", true)
|
|
case _ as TelegramMediaPoll:
|
|
return (strings.ForwardedPolls(1), true)
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
return (message.text, false)
|
|
}
|
|
|
|
final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
|
private let messageDisposable = MetaDisposable()
|
|
let messageIds: [MessageId]
|
|
|
|
let closeButton: ASButtonNode
|
|
let lineNode: ASImageNode
|
|
let titleNode: ImmediateTextNode
|
|
let textNode: ImmediateTextNode
|
|
|
|
private let actionArea: AccessibilityAreaNode
|
|
|
|
var theme: PresentationTheme
|
|
|
|
init(context: AccountContext, messageIds: [MessageId], theme: PresentationTheme, strings: PresentationStrings) {
|
|
self.messageIds = messageIds
|
|
self.theme = theme
|
|
|
|
self.closeButton = ASButtonNode()
|
|
self.closeButton.accessibilityLabel = "Discard"
|
|
self.closeButton.setImage(PresentationResourcesChat.chatInputPanelCloseIconImage(theme), for: [])
|
|
self.closeButton.hitTestSlop = UIEdgeInsetsMake(-8.0, -8.0, -8.0, -8.0)
|
|
self.closeButton.displaysAsynchronously = false
|
|
|
|
self.lineNode = ASImageNode()
|
|
self.lineNode.displayWithoutProcessing = true
|
|
self.lineNode.displaysAsynchronously = false
|
|
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
|
|
|
|
self.titleNode = ImmediateTextNode()
|
|
self.titleNode.maximumNumberOfLines = 1
|
|
self.titleNode.displaysAsynchronously = false
|
|
|
|
self.textNode = ImmediateTextNode()
|
|
self.textNode.maximumNumberOfLines = 1
|
|
self.textNode.displaysAsynchronously = false
|
|
|
|
self.actionArea = AccessibilityAreaNode()
|
|
|
|
super.init()
|
|
|
|
self.closeButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: [.touchUpInside])
|
|
self.addSubnode(self.closeButton)
|
|
|
|
self.addSubnode(self.lineNode)
|
|
self.addSubnode(self.titleNode)
|
|
self.addSubnode(self.textNode)
|
|
self.addSubnode(self.actionArea)
|
|
|
|
self.messageDisposable.set((context.account.postbox.messagesAtIds(messageIds)
|
|
|> deliverOnMainQueue).start(next: { [weak self] messages in
|
|
if let strongSelf = self {
|
|
var authors = ""
|
|
var uniquePeerIds = Set<PeerId>()
|
|
var text = ""
|
|
for message in messages {
|
|
if let author = message.author, !uniquePeerIds.contains(author.id) {
|
|
uniquePeerIds.insert(author.id)
|
|
if !authors.isEmpty {
|
|
authors.append(", ")
|
|
}
|
|
authors.append(author.compactDisplayTitle)
|
|
}
|
|
}
|
|
if messages.count == 1 {
|
|
let (string, _) = textStringForForwardedMessage(messages[0], strings: strings)
|
|
text = string
|
|
} else {
|
|
text = strings.ForwardedMessages(Int32(messages.count))
|
|
}
|
|
|
|
strongSelf.titleNode.attributedText = NSAttributedString(string: authors, font: Font.medium(15.0), textColor: strongSelf.theme.chat.inputPanel.panelControlAccentColor)
|
|
strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: strongSelf.theme.chat.inputPanel.secondaryTextColor)
|
|
|
|
let headerString: String
|
|
if messages.count == 1 {
|
|
headerString = "Forward message"
|
|
} else {
|
|
headerString = "Forward messages"
|
|
}
|
|
strongSelf.actionArea.accessibilityLabel = "\(headerString). From: \(authors).\n\(text)"
|
|
|
|
strongSelf.setNeedsLayout()
|
|
}
|
|
}))
|
|
}
|
|
|
|
deinit {
|
|
self.messageDisposable.dispose()
|
|
}
|
|
|
|
override func didLoad() {
|
|
super.didLoad()
|
|
|
|
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
|
}
|
|
|
|
override func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
|
if self.theme !== theme {
|
|
self.theme = theme
|
|
|
|
self.closeButton.setImage(PresentationResourcesChat.chatInputPanelCloseIconImage(theme), for: [])
|
|
|
|
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
|
|
|
|
if let text = self.titleNode.attributedText?.string {
|
|
self.titleNode.attributedText = NSAttributedString(string: text, font: Font.medium(15.0), textColor: self.theme.chat.inputPanel.panelControlAccentColor)
|
|
}
|
|
|
|
if let text = self.textNode.attributedText?.string {
|
|
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: self.theme.chat.inputPanel.primaryTextColor)
|
|
}
|
|
|
|
self.setNeedsLayout()
|
|
}
|
|
}
|
|
|
|
override func calculateSizeThatFits(_ constrainedSize: CGSize) -> CGSize {
|
|
return CGSize(width: constrainedSize.width, height: 45.0)
|
|
}
|
|
|
|
override func layout() {
|
|
super.layout()
|
|
|
|
let bounds = self.bounds
|
|
let leftInset: CGFloat = 55.0
|
|
let textLineInset: CGFloat = 10.0
|
|
let rightInset: CGFloat = 55.0
|
|
let textRightInset: CGFloat = 20.0
|
|
|
|
let closeButtonSize = CGSize(width: 44.0, height: bounds.height)
|
|
let closeButtonFrame = CGRect(origin: CGPoint(x: bounds.width - rightInset - closeButtonSize.width + 12.0, y: 2.0), size: closeButtonSize)
|
|
self.closeButton.frame = closeButtonFrame
|
|
|
|
self.actionArea.frame = CGRect(origin: CGPoint(x: leftInset, y: 2.0), size: CGSize(width: closeButtonFrame.minX - leftInset, height: bounds.height))
|
|
|
|
self.lineNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 8.0), size: CGSize(width: 2.0, height: bounds.size.height - 10.0))
|
|
|
|
let titleSize = self.titleNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
|
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset, y: 7.0), size: titleSize)
|
|
|
|
let textSize = self.textNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
|
self.textNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset, y: 25.0), size: textSize)
|
|
}
|
|
|
|
@objc func closePressed() {
|
|
if let dismiss = self.dismiss {
|
|
dismiss()
|
|
}
|
|
}
|
|
|
|
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
|
if case .ended = recognizer.state {
|
|
self.interfaceInteraction?.forwardCurrentForwardMessages()
|
|
}
|
|
}
|
|
}
|