@chaitrabhairappa/react-native-rich-text-editor 3.5.0 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -145,10 +145,7 @@ class RichTextEditorView(context: Context) : androidx.appcompat.widget.AppCompat
|
|
|
145
145
|
calculatedHeight = 0f
|
|
146
146
|
bottomBorderPaint.strokeWidth = density
|
|
147
147
|
|
|
148
|
-
|
|
149
|
-
val paddingVertical = (10 * density).toInt()
|
|
150
|
-
|
|
151
|
-
setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical)
|
|
148
|
+
setPadding(0, 0, 0, 0)
|
|
152
149
|
textSize = 16f
|
|
153
150
|
setLineSpacing(0f, 1.3f) // Consistent line height multiplier
|
|
154
151
|
setTextColor(Color.BLACK)
|
|
@@ -1302,6 +1299,7 @@ class RichTextEditorView(context: Context) : androidx.appcompat.widget.AppCompat
|
|
|
1302
1299
|
setSelection(spannable.length)
|
|
1303
1300
|
}
|
|
1304
1301
|
isInternalChange = false
|
|
1302
|
+
detectAllLinks(spannable)
|
|
1305
1303
|
if (numberOfLinesValue > 0 && !isEditable) {
|
|
1306
1304
|
scrollTo(0, 0)
|
|
1307
1305
|
applyEllipsisIfNeeded()
|
|
@@ -1314,6 +1312,32 @@ class RichTextEditorView(context: Context) : androidx.appcompat.widget.AppCompat
|
|
|
1314
1312
|
}
|
|
1315
1313
|
}
|
|
1316
1314
|
|
|
1315
|
+
private fun detectAllLinks(spannable: SpannableStringBuilder) {
|
|
1316
|
+
val text = spannable.toString()
|
|
1317
|
+
if (text.isEmpty()) return
|
|
1318
|
+
val matcher = android.util.Patterns.WEB_URL.matcher(text)
|
|
1319
|
+
var changed = false
|
|
1320
|
+
while (matcher.find()) {
|
|
1321
|
+
val start = matcher.start()
|
|
1322
|
+
val end = matcher.end()
|
|
1323
|
+
val existingLinks = spannable.getSpans(start, end, android.text.style.URLSpan::class.java)
|
|
1324
|
+
if (existingLinks.isNotEmpty()) continue
|
|
1325
|
+
var url = matcher.group()
|
|
1326
|
+
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
1327
|
+
url = "https://$url"
|
|
1328
|
+
}
|
|
1329
|
+
spannable.setSpan(android.text.style.URLSpan(url), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
1330
|
+
spannable.setSpan(android.text.style.ForegroundColorSpan(Color.parseColor("#2196F3")), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
1331
|
+
spannable.setSpan(UnderlineSpan(), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
1332
|
+
changed = true
|
|
1333
|
+
}
|
|
1334
|
+
if (changed) {
|
|
1335
|
+
isInternalChange = true
|
|
1336
|
+
setText(spannable)
|
|
1337
|
+
isInternalChange = false
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1317
1341
|
fun getTextContent(): String = text.toString()
|
|
1318
1342
|
|
|
1319
1343
|
// Fabric command response methods
|
|
@@ -500,7 +500,7 @@ class RichTextEditorView: UIView, UITextViewDelegate, UIGestureRecognizerDelegat
|
|
|
500
500
|
private let textView: RichTextView = {
|
|
501
501
|
let tv = RichTextView()
|
|
502
502
|
tv.font = UIFont.systemFont(ofSize: 16)
|
|
503
|
-
tv.textContainerInset = UIEdgeInsets(top:
|
|
503
|
+
tv.textContainerInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
|
|
504
504
|
tv.translatesAutoresizingMaskIntoConstraints = false
|
|
505
505
|
tv.backgroundColor = .clear
|
|
506
506
|
|
|
@@ -2833,6 +2833,7 @@ class RichTextEditorView: UIView, UITextViewDelegate, UIGestureRecognizerDelegat
|
|
|
2833
2833
|
placeholderLabel.isHidden = !textView.text.isEmpty
|
|
2834
2834
|
isInternalChange = false
|
|
2835
2835
|
applyListIndentation()
|
|
2836
|
+
detectAllLinks()
|
|
2836
2837
|
|
|
2837
2838
|
let endPosition = textView.text?.count ?? 0
|
|
2838
2839
|
textView.selectedRange = NSRange(location: endPosition, length: 0)
|
|
@@ -2846,6 +2847,31 @@ class RichTextEditorView: UIView, UITextViewDelegate, UIGestureRecognizerDelegat
|
|
|
2846
2847
|
}
|
|
2847
2848
|
}
|
|
2848
2849
|
|
|
2850
|
+
private func detectAllLinks() {
|
|
2851
|
+
guard let text = textView.text, !text.isEmpty else { return }
|
|
2852
|
+
let nsText = text as NSString
|
|
2853
|
+
let fullRange = NSRange(location: 0, length: nsText.length)
|
|
2854
|
+
guard let detector = try? NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue) else { return }
|
|
2855
|
+
let matches = detector.matches(in: text, range: fullRange)
|
|
2856
|
+
guard !matches.isEmpty else { return }
|
|
2857
|
+
let mutable = NSMutableAttributedString(attributedString: textView.attributedText)
|
|
2858
|
+
var changed = false
|
|
2859
|
+
for match in matches {
|
|
2860
|
+
guard let url = match.url else { continue }
|
|
2861
|
+
let existingLink = mutable.attribute(.link, at: match.range.location, effectiveRange: nil)
|
|
2862
|
+
if existingLink != nil { continue }
|
|
2863
|
+
mutable.addAttribute(.link, value: url.absoluteString, range: match.range)
|
|
2864
|
+
mutable.addAttribute(.foregroundColor, value: UIColor.systemBlue, range: match.range)
|
|
2865
|
+
mutable.addAttribute(.underlineStyle, value: NSUnderlineStyle.single.rawValue, range: match.range)
|
|
2866
|
+
changed = true
|
|
2867
|
+
}
|
|
2868
|
+
if changed {
|
|
2869
|
+
isInternalChange = true
|
|
2870
|
+
textView.attributedText = mutable
|
|
2871
|
+
isInternalChange = false
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2849
2875
|
func getText() -> String {
|
|
2850
2876
|
return textView.text ?? ""
|
|
2851
2877
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chaitrabhairappa/react-native-rich-text-editor",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.1",
|
|
4
4
|
"description": "A high-performance native rich text editor for React Native (New Architecture / Fabric only)",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|