Implement code highlight colors

This commit is contained in:
Ali 2023-11-02 20:19:24 +04:00
parent 6bddf8ac47
commit 5ab45be3c7
11 changed files with 141 additions and 55 deletions

View File

@ -289,7 +289,9 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
quote: ChatInputTextView.Theme.Quote(
background: mainColor.withMultipliedAlpha(0.1),
foreground: mainColor,
lineStyle: mappedLineStyle
lineStyle: mappedLineStyle,
codeBackground: mainColor.withMultipliedAlpha(0.1),
codeForeground: mainColor
)
)
}

View File

@ -78,13 +78,15 @@ public final class TextNodeBlockQuoteData: NSObject {
public let color: UIColor
public let secondaryColor: UIColor?
public let tertiaryColor: UIColor?
public let backgroundColor: UIColor
public init(kind: Kind, title: NSAttributedString?, color: UIColor, secondaryColor: UIColor?, tertiaryColor: UIColor?) {
public init(kind: Kind, title: NSAttributedString?, color: UIColor, secondaryColor: UIColor?, tertiaryColor: UIColor?, backgroundColor: UIColor) {
self.kind = kind
self.title = title
self.color = color
self.secondaryColor = secondaryColor
self.tertiaryColor = tertiaryColor
self.backgroundColor = backgroundColor
super.init()
}
@ -162,13 +164,15 @@ private final class TextNodeBlockQuote {
let tintColor: UIColor
let secondaryTintColor: UIColor?
let tertiaryTintColor: UIColor?
let backgroundColor: UIColor
init(frame: CGRect, data: TextNodeBlockQuoteData, tintColor: UIColor, secondaryTintColor: UIColor?, tertiaryTintColor: UIColor?) {
init(frame: CGRect, data: TextNodeBlockQuoteData, tintColor: UIColor, secondaryTintColor: UIColor?, tertiaryTintColor: UIColor?, backgroundColor: UIColor) {
self.frame = frame
self.data = data
self.tintColor = tintColor
self.secondaryTintColor = secondaryTintColor
self.tertiaryTintColor = tertiaryTintColor
self.backgroundColor = backgroundColor
}
}
@ -1554,7 +1558,7 @@ open class TextNode: ASDisplayNode {
}
if let blockQuote = segment.blockQuote, let tintColor = segment.tintColor {
blockQuotes.append(TextNodeBlockQuote(frame: CGRect(origin: CGPoint(x: 0.0, y: blockMinY - 2.0), size: CGSize(width: blockWidth, height: blockMaxY - (blockMinY - 2.0) + 4.0)), data: blockQuote, tintColor: tintColor, secondaryTintColor: segment.secondaryTintColor, tertiaryTintColor: segment.tertiaryTintColor))
blockQuotes.append(TextNodeBlockQuote(frame: CGRect(origin: CGPoint(x: 0.0, y: blockMinY - 2.0), size: CGSize(width: blockWidth, height: blockMaxY - (blockMinY - 2.0) + 4.0)), data: blockQuote, tintColor: tintColor, secondaryTintColor: segment.secondaryTintColor, tertiaryTintColor: segment.tertiaryTintColor, backgroundColor: blockQuote.backgroundColor))
}
}
@ -2223,7 +2227,7 @@ open class TextNode: ASDisplayNode {
blockFrame.size.width += 4.0
blockFrame.origin.x -= 2.0
context.setFillColor(blockQuote.tintColor.withMultipliedAlpha(0.1).cgColor)
context.setFillColor(blockQuote.backgroundColor.cgColor)
context.addPath(UIBezierPath(roundedRect: blockFrame, cornerRadius: radius).cgPath)
context.fillPath()
@ -2315,7 +2319,9 @@ open class TextNode: ASDisplayNode {
}
} else {
context.setFillColor(blockQuote.tintColor.cgColor)
context.setBlendMode(.copy)
context.fill(lineFrame)
context.setBlendMode(.normal)
}
context.resetClip()

View File

@ -278,15 +278,21 @@ public final class ChatInputTextView: ChatInputTextViewImpl, NSLayoutManagerDele
public let background: UIColor
public let foreground: UIColor
public let lineStyle: LineStyle
public let codeBackground: UIColor
public let codeForeground: UIColor
public init(
background: UIColor,
foreground: UIColor,
lineStyle: LineStyle
lineStyle: LineStyle,
codeBackground: UIColor,
codeForeground: UIColor
) {
self.background = background
self.foreground = foreground
self.lineStyle = lineStyle
self.codeBackground = codeBackground
self.codeForeground = codeForeground
}
public static func ==(lhs: Quote, rhs: Quote) -> Bool {
@ -299,6 +305,12 @@ public final class ChatInputTextView: ChatInputTextViewImpl, NSLayoutManagerDele
if lhs.lineStyle != rhs.lineStyle {
return false
}
if !lhs.codeBackground.isEqual(rhs.codeBackground) {
return false
}
if !lhs.codeForeground.isEqual(rhs.codeForeground) {
return false
}
return true
}
}
@ -830,6 +842,7 @@ private final class QuoteBackgroundView: UIView {
var primaryColor: UIColor
var secondaryColor: UIColor?
var tertiaryColor: UIColor?
let backgroundColor: UIColor?
switch value.kind {
case .quote:
@ -846,10 +859,13 @@ private final class QuoteBackgroundView: UIView {
secondaryColor = secondaryColorValue
tertiaryColor = tertiaryColorValue
}
backgroundColor = nil
case .code:
self.iconView.isHidden = true
primaryColor = .gray
primaryColor = theme.codeForeground
backgroundColor = theme.codeBackground
}
self.backgroundView.update(
@ -858,6 +874,7 @@ private final class QuoteBackgroundView: UIView {
primaryColor: primaryColor,
secondaryColor: secondaryColor,
thirdColor: tertiaryColor,
backgroundColor: backgroundColor,
pattern: nil,
animation: .None
)

View File

@ -869,13 +869,13 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
if let current = self.backgroundView {
backgroundView = current
animation.animator.updateFrame(layer: backgroundView.layer, frame: backgroundFrame, completion: nil)
backgroundView.update(size: backgroundFrame.size, isTransparent: false, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, pattern: nil, animation: animation)
backgroundView.update(size: backgroundFrame.size, isTransparent: false, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, backgroundColor: nil, pattern: nil, animation: animation)
} else {
backgroundView = MessageInlineBlockBackgroundView()
self.backgroundView = backgroundView
backgroundView.frame = backgroundFrame
self.transformContainer.view.insertSubview(backgroundView, at: 0)
backgroundView.update(size: backgroundFrame.size, isTransparent: false, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, pattern: nil, animation: .None)
backgroundView.update(size: backgroundFrame.size, isTransparent: false, primaryColor: mainColor, secondaryColor: secondaryColor, thirdColor: tertiaryColor, backgroundColor: nil, pattern: nil, animation: .None)
}
} else {
if let backgroundView = self.backgroundView {

View File

@ -809,6 +809,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
primaryColor: mainColor,
secondaryColor: secondaryColor,
thirdColor: tertiaryColor,
backgroundColor: nil,
pattern: pattern,
animation: animation
)

View File

@ -392,6 +392,9 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
var tertiaryColor: UIColor? = nil
let nameColors = author?.nameColor.flatMap { item.context.peerNameColors.get($0, dark: item.presentationData.theme.theme.overallDarkAppearance) }
let codeBlockTitleColor: UIColor
let codeBlockAccentColor: UIColor
let codeBlockBackgroundColor: UIColor
if !incoming {
mainColor = messageTheme.accentTextColor
if let _ = nameColors?.secondary {
@ -400,6 +403,16 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
if let _ = nameColors?.tertiary {
tertiaryColor = .clear
}
if item.presentationData.theme.theme.overallDarkAppearance {
codeBlockTitleColor = .white
codeBlockAccentColor = UIColor(white: 1.0, alpha: 0.5)
codeBlockBackgroundColor = UIColor(white: 0.0, alpha: 0.65)
} else {
codeBlockTitleColor = mainColor
codeBlockAccentColor = mainColor
codeBlockBackgroundColor = mainColor.withMultipliedAlpha(0.1)
}
} else {
let authorNameColor = nameColors?.main
secondaryColor = nameColors?.secondary
@ -410,10 +423,17 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
} else {
mainColor = messageTheme.accentTextColor
}
codeBlockTitleColor = mainColor
codeBlockAccentColor = mainColor
if item.presentationData.theme.theme.overallDarkAppearance {
codeBlockBackgroundColor = UIColor(white: 0.0, alpha: 0.65)
} else {
codeBlockBackgroundColor = UIColor(white: 0.0, alpha: 0.05)
}
}
let codeBlockColor = messageTheme.secondaryTextColor
codeHighlightSpecs = extractMessageSyntaxHighlightSpecs(text: rawText, entities: entities)
if !codeHighlightSpecs.isEmpty {
@ -426,7 +446,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
}
}
attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseQuoteTintColor: mainColor, baseQuoteSecondaryTintColor: secondaryColor, baseQuoteTertiaryTintColor: tertiaryColor, baseCodeBlockColor: codeBlockColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont, underlineLinks: underlineLinks, message: item.message, adjustQuoteFontSize: true, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight)
attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseQuoteTintColor: mainColor, baseQuoteSecondaryTintColor: secondaryColor, baseQuoteTertiaryTintColor: tertiaryColor, codeBlockTitleColor: codeBlockTitleColor, codeBlockAccentColor: codeBlockAccentColor, codeBlockBackgroundColor: codeBlockBackgroundColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont, underlineLinks: underlineLinks, message: item.message, adjustQuoteFontSize: true, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight)
} else if !rawText.isEmpty {
attributedText = NSAttributedString(string: rawText, font: textFont, textColor: messageTheme.primaryTextColor)
} else {

View File

@ -28,15 +28,15 @@ private func addRoundedRectPath(context: CGContext, rect: CGRect, radius: CGFloa
context.restoreGState()
}
private func generateBackgroundTemplateImage(addStripe: Bool, isTransparent: Bool) -> UIImage {
private func generateBackgroundTemplateImage(addStripe: Bool, backgroundAlpha: CGFloat) -> UIImage {
return generateImage(CGSize(width: radius * 2.0 + 4.0, height: radius * 2.0 + 8.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
addRoundedRectPath(context: context, rect: CGRect(origin: CGPoint(), size: size), radius: radius)
context.clip()
context.setFillColor(UIColor.white.withMultipliedAlpha(0.1).cgColor)
if !isTransparent {
if backgroundAlpha != 0.0 {
context.setFillColor(UIColor.white.withMultipliedAlpha(backgroundAlpha).cgColor)
context.fill(CGRect(origin: CGPoint(), size: size))
}
@ -71,19 +71,23 @@ private func generateProgressTemplateImage() -> UIImage {
}
private let backgroundSolidTemplateImage: UIImage = {
return generateBackgroundTemplateImage(addStripe: true, isTransparent: false)
return generateBackgroundTemplateImage(addStripe: true, backgroundAlpha: 0.1)
}()
private let backgroundDashTemplateImage: UIImage = {
return generateBackgroundTemplateImage(addStripe: false, isTransparent: false)
return generateBackgroundTemplateImage(addStripe: false, backgroundAlpha: 0.1)
}()
private let transparentBackgroundSolidTemplateImage: UIImage = {
return generateBackgroundTemplateImage(addStripe: true, isTransparent: true)
return generateBackgroundTemplateImage(addStripe: true, backgroundAlpha: 0.0)
}()
private let transparentBackgroundDashTemplateImage: UIImage = {
return generateBackgroundTemplateImage(addStripe: false, isTransparent: true)
return generateBackgroundTemplateImage(addStripe: false, backgroundAlpha: 0.0)
}()
private let solidBackgroundTemplateImage: UIImage = {
return generateBackgroundTemplateImage(addStripe: false, backgroundAlpha: 1.0)
}()
private func generateDashBackgroundTemplateImage() -> UIImage {
@ -450,6 +454,7 @@ public final class MessageInlineBlockBackgroundView: UIView {
var primaryColor: UIColor
var secondaryColor: UIColor?
var thirdColor: UIColor?
var backgroundColor: UIColor?
var pattern: Pattern?
var displayProgress: Bool
@ -459,6 +464,7 @@ public final class MessageInlineBlockBackgroundView: UIView {
primaryColor: UIColor,
secondaryColor: UIColor?,
thirdColor: UIColor?,
backgroundColor: UIColor?,
pattern: Pattern?,
displayProgress: Bool
) {
@ -467,6 +473,7 @@ public final class MessageInlineBlockBackgroundView: UIView {
self.primaryColor = primaryColor
self.secondaryColor = secondaryColor
self.thirdColor = thirdColor
self.backgroundColor = backgroundColor
self.pattern = pattern
self.displayProgress = displayProgress
}
@ -484,6 +491,7 @@ public final class MessageInlineBlockBackgroundView: UIView {
primaryColor: params.primaryColor,
secondaryColor: params.secondaryColor,
thirdColor: params.thirdColor,
backgroundColor: params.backgroundColor,
pattern: params.pattern,
animation: .None
)
@ -595,6 +603,7 @@ public final class MessageInlineBlockBackgroundView: UIView {
primaryColor: UIColor,
secondaryColor: UIColor?,
thirdColor: UIColor?,
backgroundColor: UIColor?,
pattern: Pattern?,
animation: ListViewItemUpdateAnimation
) {
@ -604,6 +613,7 @@ public final class MessageInlineBlockBackgroundView: UIView {
primaryColor: primaryColor,
secondaryColor: secondaryColor,
thirdColor: thirdColor,
backgroundColor: backgroundColor,
pattern: pattern,
displayProgress: self.displayProgress
)
@ -618,20 +628,25 @@ public final class MessageInlineBlockBackgroundView: UIView {
patternContentLayer.layerTintColor = primaryColor.cgColor
}
if params.isTransparent {
if params.secondaryColor != nil {
self.backgroundView.image = transparentBackgroundDashTemplateImage
} else {
self.backgroundView.image = transparentBackgroundSolidTemplateImage
}
if let backgroundColor = params.backgroundColor {
self.backgroundView.image = solidBackgroundTemplateImage
self.backgroundView.tintColor = backgroundColor
} else {
if params.secondaryColor != nil {
self.backgroundView.image = backgroundDashTemplateImage
if params.isTransparent {
if params.secondaryColor != nil {
self.backgroundView.image = transparentBackgroundDashTemplateImage
} else {
self.backgroundView.image = transparentBackgroundSolidTemplateImage
}
} else {
self.backgroundView.image = backgroundSolidTemplateImage
if params.secondaryColor != nil {
self.backgroundView.image = backgroundDashTemplateImage
} else {
self.backgroundView.image = backgroundSolidTemplateImage
}
}
self.backgroundView.tintColor = params.primaryColor
}
self.backgroundView.tintColor = params.primaryColor
}
if previousParams?.pattern != params.pattern {

View File

@ -500,12 +500,21 @@ private func makeTextInputTheme(context: AccountContext, interfaceState: ChatPre
lineStyle = .solid(color: interfaceState.theme.list.itemAccentColor)
authorNameColor = interfaceState.theme.list.itemAccentColor
}
let codeBackgroundColor: UIColor
if interfaceState.theme.overallDarkAppearance {
codeBackgroundColor = UIColor(white: 1.0, alpha: 0.05)
} else {
codeBackgroundColor = UIColor(white: 0.0, alpha: 0.05)
}
return ChatInputTextView.Theme(
quote: ChatInputTextView.Theme.Quote(
background: authorNameColor.withMultipliedAlpha(interfaceState.theme.overallDarkAppearance ? 0.2 : 0.1),
foreground: authorNameColor,
lineStyle: lineStyle
lineStyle: lineStyle,
codeBackground: codeBackgroundColor,
codeForeground: authorNameColor
)
)
}

View File

@ -148,8 +148,13 @@ public func textAttributedStringForStateText(_ stateText: NSAttributedString, fo
} else if key == ChatTextInputAttributes.customEmoji {
result.addAttribute(key, value: value, range: range)
result.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
} else if key == ChatTextInputAttributes.block {
fontAttributes.insert(.blockQuote)
} else if key == ChatTextInputAttributes.block, let value = value as? ChatTextInputTextQuoteAttribute {
switch value.kind {
case .quote:
fontAttributes.insert(.blockQuote)
case .code:
fontAttributes.insert(.monospace)
}
result.addAttribute(key, value: value, range: range)
}
}
@ -742,8 +747,13 @@ public func refreshChatTextInputAttributes(textView: UITextView, primaryTextColo
} else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute {
textView.textStorage.addAttribute(key, value: value, range: range)
textView.textStorage.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.clear, range: range)
} else if key == ChatTextInputAttributes.block {
fontAttributes.insert(.blockQuote)
} else if key == ChatTextInputAttributes.block, let value = value as? ChatTextInputTextQuoteAttribute {
switch value.kind {
case .quote:
fontAttributes.insert(.blockQuote)
case .code:
fontAttributes.insert(.monospace)
}
textView.textStorage.addAttribute(key, value: value, range: range)
}
}

View File

@ -61,7 +61,7 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M
private let syntaxHighlighter = Syntaxer()
public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], baseColor: UIColor, linkColor: UIColor, baseQuoteTintColor: UIColor? = nil, baseQuoteSecondaryTintColor: UIColor? = nil, baseQuoteTertiaryTintColor: UIColor? = nil, baseCodeBlockColor: UIColor? = nil, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: Message?, entityFiles: [MediaId: TelegramMediaFile] = [:], adjustQuoteFontSize: Bool = false, cachedMessageSyntaxHighlight: CachedMessageSyntaxHighlight? = nil) -> NSAttributedString {
public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], baseColor: UIColor, linkColor: UIColor, baseQuoteTintColor: UIColor? = nil, baseQuoteSecondaryTintColor: UIColor? = nil, baseQuoteTertiaryTintColor: UIColor? = nil, codeBlockTitleColor: UIColor? = nil, codeBlockAccentColor: UIColor? = nil, codeBlockBackgroundColor: UIColor? = nil, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: Message?, entityFiles: [MediaId: TelegramMediaFile] = [:], adjustQuoteFontSize: Bool = false, cachedMessageSyntaxHighlight: CachedMessageSyntaxHighlight? = nil) -> NSAttributedString {
let baseQuoteTintColor = baseQuoteTintColor ?? baseColor
var nsString: NSString?
@ -210,16 +210,19 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Code), value: nsString!.substring(with: range), range: range)
case let .Pre(language):
addFontAttributes(range, .monospace)
addFontAttributes(range, .blockQuote)
if nsString == nil {
nsString = text as NSString
}
if let baseCodeBlockColor {
string.addAttribute(NSAttributedString.Key(rawValue: "Attribute__Blockquote"), value: TextNodeBlockQuoteData(kind: .code(language: language), title: nil, color: baseCodeBlockColor, secondaryColor: nil, tertiaryColor: nil), range: range)
if let codeBlockTitleColor, let codeBlockAccentColor, let codeBlockBackgroundColor {
string.addAttribute(NSAttributedString.Key(rawValue: "Attribute__Blockquote"), value: TextNodeBlockQuoteData(kind: .code(language: language), title: language.flatMap {
NSAttributedString(string: $0.capitalized, font: boldFont.withSize(round(boldFont.pointSize * 0.8235294117647058)), textColor: codeBlockTitleColor)
}, color: codeBlockAccentColor, secondaryColor: nil, tertiaryColor: nil, backgroundColor: codeBlockBackgroundColor), range: range)
}
case .BlockQuote:
addFontAttributes(range, .blockQuote)
string.addAttribute(NSAttributedString.Key(rawValue: "Attribute__Blockquote"), value: TextNodeBlockQuoteData(kind: .quote, title: nil, color: baseQuoteTintColor, secondaryColor: baseQuoteSecondaryTintColor, tertiaryColor: baseQuoteTertiaryTintColor), range: range)
string.addAttribute(NSAttributedString.Key(rawValue: "Attribute__Blockquote"), value: TextNodeBlockQuoteData(kind: .quote, title: nil, color: baseQuoteTintColor, secondaryColor: baseQuoteSecondaryTintColor, tertiaryColor: baseQuoteTertiaryTintColor, backgroundColor: baseQuoteTintColor.withMultipliedAlpha(0.1)), range: range)
case .BankCard:
string.addAttribute(NSAttributedString.Key.foregroundColor, value: linkColor, range: range)
if underlineLinks && underlineAllLinks {

View File

@ -49,25 +49,28 @@ public:
std::string_view match(bool& success, size_t& pos, std::string_view text) const
{
boost::cmatch m;
auto flags = boost::regex_constants::match_not_dot_newline;
auto match = boost::regex_search(text.data() + pos, text.data() + text.size(), m, m_regex, flags);
if (match)
{
success = true;
pos += m.position();
if (m_lookbehind && m[1].matched)
try {
boost::cmatch m;
auto flags = boost::regex_constants::match_not_dot_newline;
auto match = boost::regex_search(text.data() + pos, text.data() + text.size(), m, m_regex, flags);
if (match)
{
// change the match to remove the text matched by the Prism lookbehind group
auto lookbehindLength = m[1].length();
pos += lookbehindLength;
return text.substr(pos, m[0].length() - lookbehindLength);
success = true;
pos += m.position();
if (m_lookbehind && m[1].matched)
{
// change the match to remove the text matched by the Prism lookbehind group
auto lookbehindLength = m[1].length();
pos += lookbehindLength;
return text.substr(pos, m[0].length() - lookbehindLength);
}
return text.substr(pos, m[0].length());
}
return text.substr(pos, m[0].length());
} catch(...) {
}
return {};