react-native-advanced-text 0.1.9 → 0.1.10
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.
|
@@ -9,11 +9,9 @@ import android.text.TextPaint
|
|
|
9
9
|
import android.text.method.LinkMovementMethod
|
|
10
10
|
import android.text.style.ClickableSpan
|
|
11
11
|
import android.text.style.BackgroundColorSpan
|
|
12
|
-
import android.text.style.ForegroundColorSpan
|
|
13
12
|
import android.util.AttributeSet
|
|
14
13
|
import android.util.Log
|
|
15
|
-
import android.view.
|
|
16
|
-
import android.view.Menu
|
|
14
|
+
import android.view.ContextMenu
|
|
17
15
|
import android.view.MenuItem
|
|
18
16
|
import android.view.View
|
|
19
17
|
import android.widget.TextView
|
|
@@ -22,7 +20,7 @@ import com.facebook.react.bridge.ReactContext
|
|
|
22
20
|
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
23
21
|
import android.text.Selection
|
|
24
22
|
|
|
25
|
-
class AdvancedTextView : TextView {
|
|
23
|
+
class AdvancedTextView : TextView, View.OnCreateContextMenuListener {
|
|
26
24
|
|
|
27
25
|
private val TAG = "AdvancedTextView"
|
|
28
26
|
|
|
@@ -30,7 +28,7 @@ class AdvancedTextView : TextView {
|
|
|
30
28
|
private var menuOptions: List<String> = emptyList()
|
|
31
29
|
private var indicatorWordIndex: Int = -1
|
|
32
30
|
private var lastSelectedText: String = ""
|
|
33
|
-
private var
|
|
31
|
+
private var isSelectionEnabled: Boolean = true
|
|
34
32
|
|
|
35
33
|
constructor(context: Context?) : super(context) { init() }
|
|
36
34
|
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) { init() }
|
|
@@ -39,65 +37,24 @@ class AdvancedTextView : TextView {
|
|
|
39
37
|
private fun init() {
|
|
40
38
|
Log.d(TAG, "AdvancedTextView initialized")
|
|
41
39
|
|
|
42
|
-
// Set default text appearance
|
|
40
|
+
// Set default text appearance
|
|
41
|
+
setTextColor(Color.BLACK)
|
|
43
42
|
textSize = 16f
|
|
44
43
|
setPadding(16, 16, 16, 16)
|
|
45
44
|
|
|
46
45
|
movementMethod = LinkMovementMethod.getInstance()
|
|
47
46
|
setTextIsSelectable(true)
|
|
47
|
+
setOnCreateContextMenuListener(this)
|
|
48
48
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
|
52
|
-
Log.d(TAG, "onCreateActionMode triggered")
|
|
53
|
-
customActionMode = mode
|
|
54
|
-
return true
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
|
58
|
-
Log.d(TAG, "onPrepareActionMode triggered")
|
|
59
|
-
menu?.clear()
|
|
60
|
-
|
|
61
|
-
val selectionStart = selectionStart
|
|
62
|
-
val selectionEnd = selectionEnd
|
|
63
|
-
|
|
64
|
-
if (selectionStart >= 0 && selectionEnd >= 0 && selectionStart != selectionEnd) {
|
|
65
|
-
lastSelectedText = text.subSequence(selectionStart, selectionEnd).toString()
|
|
66
|
-
Log.d(TAG, "User selected text: '$lastSelectedText'")
|
|
67
|
-
Log.d(TAG, "Menu options available: $menuOptions")
|
|
68
|
-
|
|
69
|
-
menuOptions.forEachIndexed { index, option ->
|
|
70
|
-
menu?.add(0, index, index, option)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
sendSelectionEvent(lastSelectedText, "selection")
|
|
74
|
-
return true
|
|
75
|
-
}
|
|
76
|
-
return false
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
|
|
80
|
-
item?.let {
|
|
81
|
-
val menuItemText = it.title.toString()
|
|
82
|
-
Log.d(TAG, "Menu item clicked: $menuItemText")
|
|
83
|
-
sendSelectionEvent(lastSelectedText, menuItemText)
|
|
84
|
-
mode?.finish()
|
|
85
|
-
return true
|
|
86
|
-
}
|
|
87
|
-
return false
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
91
|
-
Log.d(TAG, "onDestroyActionMode")
|
|
92
|
-
customActionMode = null
|
|
93
|
-
}
|
|
94
|
-
}
|
|
49
|
+
// Ensure minimum height for visibility during debugging
|
|
50
|
+
minHeight = 100
|
|
95
51
|
}
|
|
96
52
|
|
|
97
53
|
fun setAdvancedText(text: String) {
|
|
98
54
|
Log.d(TAG, "setAdvancedText: $text (length=${text.length})")
|
|
99
55
|
this.text = text
|
|
100
56
|
updateTextWithHighlights()
|
|
57
|
+
// Force layout update
|
|
101
58
|
requestLayout()
|
|
102
59
|
invalidate()
|
|
103
60
|
}
|
|
@@ -161,16 +118,16 @@ class AdvancedTextView : TextView {
|
|
|
161
118
|
|
|
162
119
|
if (wordIndex == indicatorWordIndex) {
|
|
163
120
|
Log.d(TAG, "Applying indicator span to word '$word' at index $wordIndex")
|
|
164
|
-
|
|
121
|
+
|
|
165
122
|
spannableString.setSpan(
|
|
166
|
-
|
|
123
|
+
IndicatorSpan(),
|
|
167
124
|
wordStart,
|
|
168
125
|
wordEnd,
|
|
169
126
|
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
|
170
127
|
)
|
|
171
128
|
}
|
|
172
129
|
|
|
173
|
-
//
|
|
130
|
+
// clickable span
|
|
174
131
|
spannableString.setSpan(
|
|
175
132
|
WordClickableSpan(wordIndex, word),
|
|
176
133
|
wordStart,
|
|
@@ -187,6 +144,39 @@ class AdvancedTextView : TextView {
|
|
|
187
144
|
Log.d(TAG, "Text updated with spans")
|
|
188
145
|
}
|
|
189
146
|
|
|
147
|
+
override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
|
|
148
|
+
val selectionStart = selectionStart
|
|
149
|
+
val selectionEnd = selectionEnd
|
|
150
|
+
|
|
151
|
+
Log.d(TAG, "onCreateContextMenu triggered. selectionStart=$selectionStart selectionEnd=$selectionEnd")
|
|
152
|
+
|
|
153
|
+
if (selectionStart >= 0 && selectionEnd >= 0 && selectionStart != selectionEnd) {
|
|
154
|
+
lastSelectedText = text.subSequence(selectionStart, selectionEnd).toString()
|
|
155
|
+
|
|
156
|
+
Log.d(TAG, "User selected text: '$lastSelectedText'")
|
|
157
|
+
Log.d(TAG, "Menu options available: $menuOptions")
|
|
158
|
+
|
|
159
|
+
menu?.clear()
|
|
160
|
+
|
|
161
|
+
menuOptions.forEachIndexed { index, option ->
|
|
162
|
+
menu?.add(0, index, index, option)?.setOnMenuItemClickListener {
|
|
163
|
+
Log.d(TAG, "Menu item clicked: $option")
|
|
164
|
+
onMenuItemClick(it, lastSelectedText)
|
|
165
|
+
true
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
sendSelectionEvent(lastSelectedText, "selection")
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private fun onMenuItemClick(item: MenuItem, selectedText: String): Boolean {
|
|
174
|
+
val menuItemText = menuOptions[item.itemId]
|
|
175
|
+
Log.d(TAG, "onMenuItemClick: menuOption='$menuItemText', selectedText='$selectedText'")
|
|
176
|
+
sendSelectionEvent(selectedText, menuItemText)
|
|
177
|
+
return true
|
|
178
|
+
}
|
|
179
|
+
|
|
190
180
|
private fun sendSelectionEvent(selectedText: String, eventType: String) {
|
|
191
181
|
Log.d(TAG, "sendSelectionEvent -> eventType='$eventType' selectedText='$selectedText'")
|
|
192
182
|
|
|
@@ -211,17 +201,24 @@ class AdvancedTextView : TextView {
|
|
|
211
201
|
|
|
212
202
|
override fun onClick(widget: View) {
|
|
213
203
|
Log.d(TAG, "Word clicked: '$word' (index=$wordIndex)")
|
|
214
|
-
// Clear any selection first to prevent interference
|
|
215
|
-
val spannable = widget as? TextView
|
|
216
|
-
spannable?.let {
|
|
217
|
-
Selection.removeSelection(it.text as? android.text.Spannable)
|
|
218
|
-
}
|
|
219
204
|
sendWordPressEvent(word, wordIndex)
|
|
220
205
|
}
|
|
221
206
|
|
|
222
207
|
override fun updateDrawState(ds: TextPaint) {
|
|
223
208
|
super.updateDrawState(ds)
|
|
224
|
-
|
|
209
|
+
ds.color = currentTextColor
|
|
210
|
+
ds.isUnderlineText = false
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private inner class IndicatorSpan : ClickableSpan() {
|
|
215
|
+
override fun onClick(widget: View) {
|
|
216
|
+
Log.d(TAG, "IndicatorSpan clicked (shouldn't trigger action)")
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
override fun updateDrawState(ds: TextPaint) {
|
|
220
|
+
ds.color = Color.RED
|
|
221
|
+
ds.isFakeBoldText = true
|
|
225
222
|
ds.isUnderlineText = false
|
|
226
223
|
}
|
|
227
224
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// File: AdvancedTextViewManager.kt
|
|
2
|
+
// This should be the ONLY content in this file
|
|
2
3
|
package com.advancedtext
|
|
3
4
|
|
|
4
|
-
import android.graphics.Color
|
|
5
5
|
import android.view.ViewGroup
|
|
6
6
|
import com.facebook.react.bridge.ReadableArray
|
|
7
7
|
import com.facebook.react.module.annotations.ReactModule
|
|
@@ -31,10 +31,10 @@ class AdvancedTextViewManager : SimpleViewManager<AdvancedTextView>(),
|
|
|
31
31
|
|
|
32
32
|
public override fun createViewInstance(context: ThemedReactContext): AdvancedTextView {
|
|
33
33
|
val view = AdvancedTextView(context)
|
|
34
|
-
// Set layout params
|
|
34
|
+
// Set default layout params to ensure the view is visible
|
|
35
35
|
view.layoutParams = ViewGroup.LayoutParams(
|
|
36
36
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
37
|
-
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
37
|
+
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
38
38
|
)
|
|
39
39
|
return view
|
|
40
40
|
}
|
|
@@ -81,15 +81,7 @@ class AdvancedTextViewManager : SimpleViewManager<AdvancedTextView>(),
|
|
|
81
81
|
view?.setIndicatorWordIndex(index)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
//
|
|
85
|
-
@ReactProp(name = "color", customType = "Color")
|
|
86
|
-
fun setColor(view: AdvancedTextView?, color: Int?) {
|
|
87
|
-
color?.let {
|
|
88
|
-
view?.setTextColor(it)
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Register custom events
|
|
84
|
+
// Add this method to register custom events
|
|
93
85
|
override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
|
|
94
86
|
return mapOf(
|
|
95
87
|
"onWordPress" to mapOf("registrationName" to "onWordPress"),
|
package/package.json
CHANGED