Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ extension ThreadDetailsViewController: ASTableDelegate, ASTableDataSource {
guard row > 1 + securityWarningBlockCount else {
if processedMessage.text.isHTMLString {
return ThreadDetailWebNode(
input: .init(message: processedMessage.text, quote: processedMessage.quote, index: messageIndex)
input: .init(
message: processedMessage.text,
quote: processedMessage.quote,
index: messageIndex,
isEncrypted: processedMessage.type == .encrypted
)
)
}
return MessageTextSubjectNode(
Expand Down
36 changes: 28 additions & 8 deletions FlowCryptCommon/Extensions/StringExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,35 @@ public extension String {
return "tag.fill"
}
}


/// A regex that finds an opening HTML tag and captures its name.
private static let htmlTagRegex: NSRegularExpression? = {
try? NSRegularExpression(
pattern: "<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>",
options: .caseInsensitive
)
}()

/// Returns `true` if this string contains at least one full HTML element
/// (an opening `<tag…>` **and** a matching `</tag>`).
/// Email‑style `<…@…>` or other angle‑bracketed text won’t count.
var isHTMLString: Bool {
do {
let regex = try NSRegularExpression(pattern: "<[a-z][\\s\\S]*>", options: .caseInsensitive)
let range = NSRange(startIndex..., in: self)
return regex.firstMatch(in: self, options: [], range: range) != nil
} catch {
return false
}
guard
let regex = Self.htmlTagRegex,
let match = regex.firstMatch(
in: self,
options: [],
range: NSRange(startIndex..<endIndex, in: self)
),
match.numberOfRanges > 1,
let nameRange = Range(match.range(at: 1), in: self)
else {
return false
}

// Extract the tag name and look for its closing tag
let tagName = String(self[nameRange])
return range(of: "</\(tagName)>", options: .caseInsensitive) != nil
}

func removingHtmlTags() -> String {
Expand Down
6 changes: 4 additions & 2 deletions FlowCryptUI/Cell Nodes/ThreadDetailWebNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ public final class ThreadDetailWebNode: CellNode {
let message: String?
let quote: String?
let index: Int
let isEncrypted: Bool

public init(message: String?, quote: String?, index: Int) {
public init(message: String?, quote: String?, index: Int, isEncrypted: Bool) {
self.message = message
self.quote = quote
self.index = index
self.isEncrypted = isEncrypted
}
}

Expand Down Expand Up @@ -50,7 +52,7 @@ public final class ThreadDetailWebNode: CellNode {
self.input = input

super.init()
addLeftBorder(width: .threadLeftBorderWidth, color: .plainTextBorder)
addLeftBorder(width: .threadLeftBorderWidth, color: input.isEncrypted ? .main : .plainTextBorder)
}

private func getFormattedHtml(html: String?) -> String {
Expand Down