Various Improvements

This commit is contained in:
Ilya Laktyushin 2021-12-21 18:36:44 +04:00
parent 50060d9da2
commit 6035a52fd3
8 changed files with 286 additions and 26 deletions

View File

@ -1786,11 +1786,13 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
strongSelf.inputActivitiesNode.alpha = 1.0
strongSelf.textNode.alpha = 0.0
strongSelf.authorNode.alpha = 0.0
strongSelf.dustNode?.alpha = 0.0
if animated || animateContent {
strongSelf.inputActivitiesNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
strongSelf.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15)
strongSelf.authorNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15)
strongSelf.dustNode?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15)
}
}
} else {
@ -1798,6 +1800,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
strongSelf.inputActivitiesNode.alpha = 0.0
strongSelf.textNode.alpha = 1.0
strongSelf.authorNode.alpha = 1.0
strongSelf.dustNode?.alpha = 1.0
if animated || animateContent {
strongSelf.inputActivitiesNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, completion: { value in
if let strongSelf = self, value {
@ -1806,6 +1809,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
})
strongSelf.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
strongSelf.authorNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
strongSelf.dustNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
} else {
strongSelf.inputActivitiesNode.removeFromSupernode()
}
@ -2016,6 +2020,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
textFrame.origin.x = contentRect.origin.x
transition.updateFrameAdditive(node: self.textNode, frame: textFrame)
if let dustNode = self.dustNode {
transition.updateFrameAdditive(node: dustNode, frame: textFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0))
}
var mediaPreviewOffsetX = textFrame.origin.x + 1.0
let contentImageSpacing: CGFloat = 2.0
for (_, media, mediaSize) in self.currentMediaPreviewSpecs {

View File

@ -92,6 +92,7 @@ swift_library(
"//submodules/DebugSettingsUI:DebugSettingsUI",
"//submodules/WallpaperBackgroundNode:WallpaperBackgroundNode",
"//submodules/WebPBinding:WebPBinding",
"//submodules/Translate:Translate",
],
visibility = [
"//visibility:public",

View File

@ -15,6 +15,7 @@ import SearchBarNode
import SearchUI
import UndoUI
import TelegramUIPreferences
import Translate
private enum LanguageListSection: ItemListSectionId {
case translate
@ -432,8 +433,20 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
var existingIds = Set<String>()
var showTranslate = true
var ignoredLanguages: [String] = []
if let translationSettings = sharedData.entries[ApplicationSpecificSharedDataKeys.translationSettings]?.get(TranslationSettings.self) {
showTranslate = translationSettings.showTranslate
if let languages = translationSettings.ignoredLanguages {
ignoredLanguages = languages
} else {
if let activeLanguageCode = activeLanguageCode, supportedTranslationLanguages.contains(activeLanguageCode) {
ignoredLanguages = [activeLanguageCode]
}
}
} else {
if let activeLanguageCode = activeLanguageCode, supportedTranslationLanguages.contains(activeLanguageCode) {
ignoredLanguages = [activeLanguageCode]
}
}
let localizationListState = (view.views[preferencesKey] as? PreferencesView)?.values[PreferencesKeys.localizationListState]?.get(LocalizationListState.self)
@ -444,8 +457,18 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
entries.append(.translateTitle(text: presentationData.strings.Localization_TranslateMessages.uppercased()))
entries.append(.translate(text: presentationData.strings.Localization_ShowTranslate, value: showTranslate))
if showTranslate {
entries.append(.doNotTranslate(text: presentationData.strings.Localization_DoNotTranslate, value: ""))
entries.append(.translateInfo(text: presentationData.strings.Localization_DoNotTranslateInfo))
var value = ""
if ignoredLanguages.count > 1 {
value = ignoredLanguages.joined(separator: ", ")
} else if let code = ignoredLanguages.first {
let enLocale = Locale(identifier: "en")
if let title = enLocale.localizedString(forLanguageCode: code) {
value = title
}
}
entries.append(.doNotTranslate(text: presentationData.strings.Localization_DoNotTranslate, value: value))
entries.append(.translateInfo(text: ignoredLanguages.count > 1 ? presentationData.strings.Localization_DoNotTranslateManyInfo : presentationData.strings.Localization_DoNotTranslateInfo))
} else {
entries.append(.translateInfo(text: presentationData.strings.Localization_ShowTranslateInfo))
}

View File

@ -15,6 +15,8 @@ import AnimatedCountLabelNode
import AnimatedNavigationStripeNode
import ContextUI
import RadialStatusNode
import InvisibleInkDustNode
import TextFormat
private enum PinnedMessageAnimation {
case slideToTop
@ -50,6 +52,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
private let lineNode: AnimatedNavigationStripeNode
private let titleNode: AnimatedCountLabelNode
private let textNode: TextNode
private var dustNode: InvisibleInkDustNode?
private let imageNode: TransformImageNode
private let imageNodeContainer: ASDisplayNode
@ -451,7 +454,25 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
}
let (titleLayout, titleApply) = makeTitleLayout(CGSize(width: width - textLineInset - contentLeftInset - rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude), titleStrings)
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: foldLineBreaks(descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId).0), font: Font.regular(15.0), textColor: message.media.isEmpty || message.media.first is TelegramMediaWebpage ? theme.chat.inputPanel.primaryTextColor : theme.chat.inputPanel.secondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - textLineInset - contentLeftInset - rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 0.0, bottom: 2.0, right: 0.0)))
let (textString, _, isText) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId)
let messageText: NSAttributedString
let textFont = Font.regular(15.0)
if isText {
let entities = (message.textEntitiesAttribute?.entities ?? []).filter { entity in
if case .Spoiler = entity.type {
return true
} else {
return false
}
}
let textColor = theme.chat.inputPanel.primaryTextColor
messageText = stringWithAppliedEntities(message.text, entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false)
} else {
messageText = NSAttributedString(string: foldLineBreaks(textString), font: textFont, textColor: message.media.isEmpty || message.media.first is TelegramMediaWebpage ? theme.chat.inputPanel.primaryTextColor : theme.chat.inputPanel.secondaryTextColor)
}
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: messageText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - textLineInset - contentLeftInset - rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 0.0, bottom: 2.0, right: 0.0)))
Queue.mainQueue().async {
if let strongSelf = self {
@ -463,7 +484,26 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
animationTransition.updateFrameAdditive(node: strongSelf.contentTextContainer, frame: CGRect(origin: CGPoint(x: contentLeftInset + textLineInset, y: 0.0), size: CGSize()))
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 5.0), size: titleLayout.size)
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 23.0), size: textLayout.size)
let textFrame = CGRect(origin: CGPoint(x: 0.0, y: 23.0), size: textLayout.size)
strongSelf.textNode.frame = textFrame
if !textLayout.spoilers.isEmpty {
let dustNode: InvisibleInkDustNode
if let current = strongSelf.dustNode {
dustNode = current
} else {
dustNode = InvisibleInkDustNode(textNode: nil)
dustNode.isUserInteractionEnabled = false
strongSelf.dustNode = dustNode
strongSelf.contentTextContainer.insertSubnode(dustNode, aboveSubnode: strongSelf.textNode)
}
dustNode.frame = textFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0)
dustNode.update(size: dustNode.frame.size, color: theme.chat.inputPanel.primaryTextColor, rects: textLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) })
} else if let dustNode = strongSelf.dustNode {
dustNode.removeFromSupernode()
strongSelf.dustNode = nil
}
let lineFrame = CGRect(origin: CGPoint(x: contentLeftInset, y: 0.0), size: CGSize(width: 2.0, height: panelHeight))
animationTransition.updateFrame(node: strongSelf.lineNode, frame: lineFrame)

View File

@ -27,11 +27,11 @@ final class ChatTextInputMenu {
UIMenuController.shared.menuItems = []
case .format:
UIMenuController.shared.menuItems = [
UIMenuItem(title: self.stringSpoiler, action: Selector(("formatAttributesSpoiler:"))),
UIMenuItem(title: self.stringBold, action: Selector(("formatAttributesBold:"))),
UIMenuItem(title: self.stringItalic, action: Selector(("formatAttributesItalic:"))),
UIMenuItem(title: self.stringMonospace, action: Selector(("formatAttributesMonospace:"))),
UIMenuItem(title: self.stringLink, action: Selector(("formatAttributesLink:"))),
UIMenuItem(title: self.stringSpoiler, action: Selector(("formatAttributesSpoiler:"))),
UIMenuItem(title: self.stringStrikethrough, action: Selector(("formatAttributesStrikethrough:"))),
UIMenuItem(title: self.stringUnderline, action: Selector(("formatAttributesUnderline:")))
]

View File

@ -352,7 +352,10 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
}
}
private var currentState: ChatTextInputState?
func updateInputTextState(_ state: ChatTextInputState, keepSendButtonEnabled: Bool, extendedSearchLayout: Bool, accessoryItems: [ChatTextInputAccessoryItem], animated: Bool) {
self.currentState = state
if state.inputText.length != 0 && self.textInputNode == nil {
self.loadTextInputNode()
}
@ -713,6 +716,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
}
textInputNode.frame = CGRect(origin: CGPoint(x: self.textInputViewInternalInsets.left, y: self.textInputViewInternalInsets.top), size: CGSize(width: textInputFrame.size.width - (self.textInputViewInternalInsets.left + self.textInputViewInternalInsets.right), height: textInputFrame.size.height - self.textInputViewInternalInsets.top - self.textInputViewInternalInsets.bottom))
textInputNode.view.layoutIfNeeded()
self.updateSpoiler()
}
self.textInputBackgroundNode.isUserInteractionEnabled = false
@ -1793,10 +1798,143 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
}
private func updateSpoiler() {
guard let textInputNode = self.textInputNode, let presentationInterfaceState = self.presentationInterfaceState else {
return
}
let textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
var rects: [CGRect] = []
if let attributedText = textInputNode.attributedText {
let beginning = textInputNode.textView.beginningOfDocument
attributedText.enumerateAttributes(in: NSMakeRange(0, attributedText.length), options: [], using: { attributes, range, _ in
if let _ = attributes[ChatTextInputAttributes.spoiler] {
func addSpoiler(startIndex: Int, endIndex: Int) {
if let start = textInputNode.textView.position(from: beginning, offset: startIndex), let end = textInputNode.textView.position(from: start, offset: endIndex - startIndex), let textRange = textInputNode.textView.textRange(from: start, to: end) {
let textRects = textInputNode.textView.selectionRects(for: textRange)
for textRect in textRects {
rects.append(textRect.rect.insetBy(dx: 1.0, dy: 1.0).offsetBy(dx: 0.0, dy: 1.0))
}
}
}
var startIndex: Int?
var currentIndex: Int?
let nsString = (attributedText.string as NSString)
nsString.enumerateSubstrings(in: range, options: .byComposedCharacterSequences) { substring, range, _, _ in
if let substring = substring, substring.rangeOfCharacter(from: .whitespacesAndNewlines) != nil {
if let currentStartIndex = startIndex {
startIndex = nil
let endIndex = range.location
addSpoiler(startIndex: currentStartIndex, endIndex: endIndex)
}
} else if startIndex == nil {
startIndex = range.location
}
currentIndex = range.location + range.length
}
if let currentStartIndex = startIndex, let currentIndex = currentIndex {
startIndex = nil
let endIndex = currentIndex
addSpoiler(startIndex: currentStartIndex, endIndex: endIndex)
}
}
})
}
if !rects.isEmpty {
let dustNode: InvisibleInkDustNode
if let current = self.dustNode {
dustNode = current
} else {
dustNode = InvisibleInkDustNode(textNode: nil)
dustNode.alpha = self.spoilersRevealed ? 0.0 : 1.0
dustNode.isUserInteractionEnabled = false
textInputNode.textView.addSubview(dustNode.view)
self.dustNode = dustNode
}
dustNode.frame = CGRect(origin: CGPoint(), size: textInputNode.textView.contentSize)
dustNode.update(size: textInputNode.textView.contentSize, color: textColor, rects: rects)
} else if let dustNode = self.dustNode {
dustNode.removeFromSupernode()
self.dustNode = nil
}
}
private func updateSpoilersRevealed() {
guard let textInputNode = self.textInputNode else {
return
}
print(textInputNode.attributedText?.description ?? "")
let selectionRange = textInputNode.textView.selectedRange
var revealed = false
if let attributedText = textInputNode.attributedText {
attributedText.enumerateAttributes(in: NSMakeRange(0, attributedText.length), options: [], using: { attributes, range, _ in
if let _ = attributes[ChatTextInputAttributes.spoiler] {
if let _ = selectionRange.intersection(range) {
revealed = true
}
}
})
}
guard self.spoilersRevealed != revealed else {
return
}
self.spoilersRevealed = revealed
if revealed {
self.updateInternalSpoilersRevealed(true)
} else {
Queue.mainQueue().after(1.5, {
self.updateInternalSpoilersRevealed(false)
})
}
}
private func updateInternalSpoilersRevealed(_ revealed: Bool) {
guard self.spoilersRevealed == revealed, let textInputNode = self.textInputNode, let presentationInterfaceState = self.presentationInterfaceState else {
return
}
let textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor
let accentTextColor = presentationInterfaceState.theme.chat.inputPanel.panelControlAccentColor
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
refreshChatTextInputAttributes(textInputNode, theme: presentationInterfaceState.theme, baseFontSize: baseFontSize, spoilersRevealed: self.spoilersRevealed)
if let state = self.currentState {
textInputNode.attributedText = textAttributedStringForStateText(state.inputText, fontSize: baseFontSize, textColor: textColor, accentTextColor: accentTextColor, writingDirection: nil, spoilersRevealed: self.spoilersRevealed)
}
if textInputNode.textView.subviews.count > 1 {
let containerView = textInputNode.textView.subviews[1]
if let canvasView = containerView.subviews.first {
if let snapshotView = canvasView.snapshotView(afterScreenUpdates: false) {
textInputNode.view.insertSubview(snapshotView, at: 0)
canvasView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
})
}
}
}
if revealed {
let transition = ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear)
if let dustNode = self.dustNode {
transition.updateAlpha(node: dustNode, alpha: 0.0)
}
} else {
let transition = ContainedViewLayoutTransition.animated(duration: 0.3, curve: .linear)
if let dustNode = self.dustNode {
transition.updateAlpha(node: dustNode, alpha: 1.0)
}
}
}
private func updateCounterTextNode(transition: ContainedViewLayoutTransition) {
@ -2069,6 +2207,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
let baseFontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize)
refreshChatTextInputTypingAttributes(textInputNode, theme: presentationInterfaceState.theme, baseFontSize: baseFontSize)
self.updateSpoilersRevealed()
}
}
@ -2193,6 +2333,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
self.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
return (chatTextInputAddFormattingAttribute(current, attribute: ChatTextInputAttributes.spoiler), inputMode)
}
self.updateSpoilersRevealed()
}
@objc func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

View File

@ -11,6 +11,8 @@ import AccountContext
import LocalizedPeerData
import PhotoResources
import TelegramStringFormatting
import InvisibleInkDustNode
import TextFormat
final class ReplyAccessoryPanelNode: AccessoryPanelNode {
private let messageDisposable = MetaDisposable()
@ -23,6 +25,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
let iconNode: ASImageNode
let titleNode: ImmediateTextNode
let textNode: ImmediateTextNode
var dustNode: InvisibleInkDustNode?
let imageNode: TransformImageNode
private let actionArea: AccessibilityAreaNode
@ -96,6 +99,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
var authorName = ""
var text = ""
var isText = true
if let forwardInfo = message?.forwardInfo, forwardInfo.flags.contains(.isImported) {
if let author = forwardInfo.author {
authorName = EnginePeer(author).displayTitle(strings: strings, displayOrder: nameDisplayOrder)
@ -105,8 +109,34 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
} else if let author = message?.effectiveAuthor {
authorName = EnginePeer(author).displayTitle(strings: strings, displayOrder: nameDisplayOrder)
}
let isMedia: Bool
if let message = message {
(text, _, _) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId)
switch messageContentKind(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId) {
case .text:
isMedia = false
default:
isMedia = true
}
(text, _, isText) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId)
} else {
isMedia = false
}
let textFont = Font.regular(14.0)
let messageText: NSAttributedString
if isText, let message = message {
let entities = (message.textEntitiesAttribute?.entities ?? []).filter { entity in
if case .Spoiler = entity.type {
return true
} else {
return false
}
}
let textColor = strongSelf.theme.chat.inputPanel.primaryTextColor
messageText = stringWithAppliedEntities(message.text, entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false)
} else {
messageText = NSAttributedString(string: text, font: textFont, textColor: isMedia ? strongSelf.theme.chat.inputPanel.secondaryTextColor : strongSelf.theme.chat.inputPanel.primaryTextColor)
}
var updatedMediaReference: AnyMediaReference?
@ -169,22 +199,10 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
updateImageSignal = .single({ _ in return nil })
}
}
let isMedia: Bool
if let message = message {
switch messageContentKind(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId) {
case .text:
isMedia = false
default:
isMedia = true
}
} else {
isMedia = false
}
strongSelf.titleNode.attributedText = NSAttributedString(string: strongSelf.strings.Conversation_ReplyMessagePanelTitle(authorName).string, font: Font.medium(14.0), textColor: strongSelf.theme.chat.inputPanel.panelControlAccentColor)
strongSelf.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: isMedia ? strongSelf.theme.chat.inputPanel.secondaryTextColor : strongSelf.theme.chat.inputPanel.primaryTextColor)
strongSelf.textNode.attributedText = messageText
let headerString: String
if let message = message, message.flags.contains(.Incoming), let author = message.author {
headerString = "Reply to message. From: \(EnginePeer(author).displayTitle(strings: strings, displayOrder: nameDisplayOrder))"
@ -295,8 +313,25 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
}
let textSize = self.textNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
let textFrame = CGRect(origin: CGPoint(x: leftInset + textLineInset + imageTextInset - self.textNode.insets.left, y: 25.0 - self.textNode.insets.top), size: textSize)
if self.textNode.supernode == self {
self.textNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset + imageTextInset - self.textNode.insets.left, y: 25.0 - self.textNode.insets.top), size: textSize)
self.textNode.frame = textFrame
}
if let textLayout = self.textNode.cachedLayout, !textLayout.spoilers.isEmpty {
if self.dustNode == nil {
let dustNode = InvisibleInkDustNode(textNode: nil)
self.dustNode = dustNode
self.textNode.supernode?.insertSubnode(dustNode, aboveSubnode: self.textNode)
}
if let dustNode = self.dustNode {
dustNode.update(size: textFrame.size, color: self.theme.chat.inputPanel.primaryTextColor, rects: textLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) })
dustNode.frame = textFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 3.0)
}
} else if let dustNode = self.dustNode {
self.dustNode = nil
dustNode.removeFromSupernode()
}
}

View File

@ -86,7 +86,11 @@ public func textAttributedStringForStateText(_ stateText: NSAttributedString, fo
result.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue as NSNumber, range: range)
} else if key == ChatTextInputAttributes.spoiler {
result.addAttribute(key, value: value, range: range)
result.addAttribute(NSAttributedString.Key.backgroundColor, value: textColor.withAlphaComponent(0.15), range: range)
if spoilersRevealed {
result.addAttribute(NSAttributedString.Key.backgroundColor, value: textColor.withAlphaComponent(0.15), range: range)
} else {
result.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
}
}
}
@ -472,7 +476,11 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue as NSNumber, range: range)
} else if key == ChatTextInputAttributes.spoiler {
textNode.textView.textStorage.addAttribute(key, value: value, range: range)
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.backgroundColor, value: theme.chat.inputPanel.primaryTextColor.withAlphaComponent(0.15), range: range)
if spoilersRevealed {
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.backgroundColor, value: theme.chat.inputPanel.primaryTextColor.withAlphaComponent(0.15), range: range)
} else {
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
}
}
}
@ -564,7 +572,11 @@ public func refreshGenericTextInputAttributes(_ textNode: ASEditableTextNode, th
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.underlineStyle, value: NSUnderlineStyle.single.rawValue as NSNumber, range: range)
} else if key == ChatTextInputAttributes.spoiler {
textNode.textView.textStorage.addAttribute(key, value: value, range: range)
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.backgroundColor, value: UIColor.clear, range: range)
if spoilersRevealed {
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.backgroundColor, value: theme.chat.inputPanel.primaryTextColor.withAlphaComponent(0.15), range: range)
} else {
textNode.textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
}
}
}