@apollohg/react-native-prose-editor 0.5.16 → 0.5.18
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.
- package/android/src/main/java/com/apollohg/editor/EditorEditText.kt +2440 -275
- package/android/src/main/java/com/apollohg/editor/EditorInputConnection.kt +783 -64
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoView.kt +1767 -81
- package/android/src/main/java/com/apollohg/editor/NativeEditorModule.kt +209 -87
- package/android/src/main/java/com/apollohg/editor/PositionBridge.kt +27 -0
- package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +58 -9
- package/dist/NativeEditorBridge.d.ts +34 -1
- package/dist/NativeEditorBridge.js +243 -83
- package/dist/NativeRichTextEditor.js +998 -137
- package/dist/addons.d.ts +7 -0
- package/ios/EditorCore.xcframework/Info.plist +5 -5
- package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
- package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
- package/ios/NativeEditorExpoView.swift +830 -17
- package/ios/NativeEditorModule.swift +304 -108
- package/ios/PositionBridge.swift +24 -1
- package/ios/RichTextEditorView.swift +912 -89
- package/package.json +2 -1
- package/rust/android/arm64-v8a/libeditor_core.so +0 -0
- package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
- package/rust/android/x86_64/libeditor_core.so +0 -0
|
@@ -4,151 +4,223 @@ import expo.modules.kotlin.modules.Module
|
|
|
4
4
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
5
5
|
import uniffi.editor_core.*
|
|
6
6
|
|
|
7
|
+
internal fun nativeULong(value: Int): ULong? =
|
|
8
|
+
if (value >= 0) value.toULong() else null
|
|
9
|
+
|
|
10
|
+
internal fun nativeUInt(value: Int): UInt? =
|
|
11
|
+
if (value >= 0) value.toUInt() else null
|
|
12
|
+
|
|
13
|
+
internal fun nativeArgumentError(field: String): String =
|
|
14
|
+
"{\"error\":\"invalid $field\"}"
|
|
15
|
+
|
|
7
16
|
class NativeEditorModule : Module() {
|
|
8
17
|
override fun definition() = ModuleDefinition {
|
|
9
18
|
Name("NativeEditor")
|
|
10
19
|
|
|
11
20
|
Function("editorCreate") { configJson: String ->
|
|
12
|
-
editorCreate(configJson).toLong()
|
|
21
|
+
editorCreate(configJson).toLong().also { id ->
|
|
22
|
+
NativeEditorViewRegistry.markEditorCreated(id)
|
|
23
|
+
}
|
|
13
24
|
}
|
|
14
25
|
Function("editorDestroy") { id: Int ->
|
|
15
|
-
|
|
26
|
+
val editorId = nativeULong(id) ?: return@Function
|
|
27
|
+
NativeEditorViewRegistry.invalidateDestroyedEditor(id.toLong())
|
|
28
|
+
editorDestroy(editorId)
|
|
29
|
+
}
|
|
30
|
+
Function("editorPrepareForCommand") { id: Int ->
|
|
31
|
+
nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
32
|
+
NativeEditorViewRegistry.prepareForCommandJSON(id.toLong())
|
|
16
33
|
}
|
|
17
34
|
Function("collaborationSessionCreate") { configJson: String ->
|
|
18
35
|
collaborationSessionCreate(configJson).toLong()
|
|
19
36
|
}
|
|
20
37
|
Function("collaborationSessionDestroy") { id: Int ->
|
|
21
|
-
|
|
38
|
+
val sessionId = nativeULong(id) ?: return@Function
|
|
39
|
+
collaborationSessionDestroy(sessionId)
|
|
22
40
|
}
|
|
23
41
|
Function("collaborationSessionGetDocumentJson") { id: Int ->
|
|
24
|
-
|
|
42
|
+
val sessionId = nativeULong(id) ?: return@Function "{}"
|
|
43
|
+
collaborationSessionGetDocumentJson(sessionId)
|
|
25
44
|
}
|
|
26
45
|
Function("collaborationSessionGetEncodedState") { id: Int ->
|
|
27
|
-
|
|
46
|
+
val sessionId = nativeULong(id) ?: return@Function "[]"
|
|
47
|
+
collaborationSessionGetEncodedState(sessionId)
|
|
28
48
|
}
|
|
29
49
|
Function("collaborationSessionGetPeersJson") { id: Int ->
|
|
30
|
-
|
|
50
|
+
val sessionId = nativeULong(id) ?: return@Function "[]"
|
|
51
|
+
collaborationSessionGetPeersJson(sessionId)
|
|
31
52
|
}
|
|
32
53
|
Function("collaborationSessionStart") { id: Int ->
|
|
33
|
-
|
|
54
|
+
val sessionId = nativeULong(id) ?: return@Function nativeArgumentError("session id")
|
|
55
|
+
collaborationSessionStart(sessionId)
|
|
34
56
|
}
|
|
35
57
|
Function("collaborationSessionApplyLocalDocumentJson") { id: Int, json: String ->
|
|
36
|
-
|
|
58
|
+
val sessionId = nativeULong(id) ?: return@Function nativeArgumentError("session id")
|
|
59
|
+
collaborationSessionApplyLocalDocumentJson(sessionId, json)
|
|
37
60
|
}
|
|
38
61
|
Function("collaborationSessionApplyEncodedState") { id: Int, encodedStateJson: String ->
|
|
39
|
-
|
|
62
|
+
val sessionId = nativeULong(id) ?: return@Function nativeArgumentError("session id")
|
|
63
|
+
collaborationSessionApplyEncodedState(sessionId, encodedStateJson)
|
|
40
64
|
}
|
|
41
65
|
Function("collaborationSessionReplaceEncodedState") { id: Int, encodedStateJson: String ->
|
|
42
|
-
|
|
66
|
+
val sessionId = nativeULong(id) ?: return@Function nativeArgumentError("session id")
|
|
67
|
+
collaborationSessionReplaceEncodedState(sessionId, encodedStateJson)
|
|
43
68
|
}
|
|
44
69
|
Function("collaborationSessionHandleMessage") { id: Int, messageJson: String ->
|
|
45
|
-
|
|
70
|
+
val sessionId = nativeULong(id) ?: return@Function nativeArgumentError("session id")
|
|
71
|
+
collaborationSessionHandleMessage(sessionId, messageJson)
|
|
46
72
|
}
|
|
47
73
|
Function("collaborationSessionSetLocalAwareness") { id: Int, awarenessJson: String ->
|
|
48
|
-
|
|
74
|
+
val sessionId = nativeULong(id) ?: return@Function nativeArgumentError("session id")
|
|
75
|
+
collaborationSessionSetLocalAwareness(sessionId, awarenessJson)
|
|
49
76
|
}
|
|
50
77
|
Function("collaborationSessionClearLocalAwareness") { id: Int ->
|
|
51
|
-
|
|
78
|
+
val sessionId = nativeULong(id) ?: return@Function nativeArgumentError("session id")
|
|
79
|
+
collaborationSessionClearLocalAwareness(sessionId)
|
|
52
80
|
}
|
|
53
81
|
|
|
54
82
|
Function("editorSetHtml") { id: Int, html: String ->
|
|
55
|
-
|
|
83
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
84
|
+
editorSetHtml(editorId, html)
|
|
56
85
|
}
|
|
57
86
|
Function("editorGetHtml") { id: Int ->
|
|
58
|
-
|
|
87
|
+
val editorId = nativeULong(id) ?: return@Function ""
|
|
88
|
+
editorGetHtml(editorId)
|
|
59
89
|
}
|
|
60
90
|
Function("editorSetJson") { id: Int, json: String ->
|
|
61
|
-
|
|
91
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
92
|
+
editorSetJson(editorId, json)
|
|
62
93
|
}
|
|
63
94
|
Function("editorGetJson") { id: Int ->
|
|
64
|
-
|
|
95
|
+
val editorId = nativeULong(id) ?: return@Function "{}"
|
|
96
|
+
editorGetJson(editorId)
|
|
65
97
|
}
|
|
66
98
|
Function("editorGetContentSnapshot") { id: Int ->
|
|
67
|
-
|
|
99
|
+
val editorId = nativeULong(id) ?: return@Function "{\"html\":\"\",\"json\":{}}"
|
|
100
|
+
editorGetContentSnapshot(editorId)
|
|
68
101
|
}
|
|
69
102
|
|
|
70
103
|
Function("editorInsertText") { id: Int, pos: Int, text: String ->
|
|
71
|
-
|
|
104
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
105
|
+
val position = nativeUInt(pos) ?: return@Function nativeArgumentError("position")
|
|
106
|
+
editorInsertText(editorId, position, text)
|
|
72
107
|
}
|
|
73
108
|
Function("editorReplaceSelectionText") { id: Int, text: String ->
|
|
74
|
-
|
|
109
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
110
|
+
editorReplaceSelectionText(editorId, text)
|
|
75
111
|
}
|
|
76
112
|
Function("editorDeleteRange") { id: Int, from: Int, to: Int ->
|
|
77
|
-
|
|
113
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
114
|
+
val fromPosition = nativeUInt(from) ?: return@Function nativeArgumentError("position")
|
|
115
|
+
val toPosition = nativeUInt(to) ?: return@Function nativeArgumentError("position")
|
|
116
|
+
editorDeleteRange(editorId, fromPosition, toPosition)
|
|
78
117
|
}
|
|
79
118
|
Function("editorSplitBlock") { id: Int, pos: Int ->
|
|
80
|
-
|
|
119
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
120
|
+
val position = nativeUInt(pos) ?: return@Function nativeArgumentError("position")
|
|
121
|
+
editorSplitBlock(editorId, position)
|
|
81
122
|
}
|
|
82
123
|
Function("editorInsertContentHtml") { id: Int, html: String ->
|
|
83
|
-
|
|
124
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
125
|
+
editorInsertContentHtml(editorId, html)
|
|
84
126
|
}
|
|
85
127
|
Function("editorReplaceHtml") { id: Int, html: String ->
|
|
86
|
-
|
|
128
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
129
|
+
editorReplaceHtml(editorId, html)
|
|
87
130
|
}
|
|
88
131
|
Function("editorReplaceJson") { id: Int, json: String ->
|
|
89
|
-
|
|
132
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
133
|
+
editorReplaceJson(editorId, json)
|
|
90
134
|
}
|
|
91
135
|
Function("editorInsertContentJson") { id: Int, json: String ->
|
|
92
|
-
|
|
136
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
137
|
+
editorInsertContentJson(editorId, json)
|
|
93
138
|
}
|
|
94
139
|
Function(
|
|
95
140
|
"editorInsertContentJsonAtSelectionScalar"
|
|
96
141
|
) { id: Int, scalarAnchor: Int, scalarHead: Int, json: String ->
|
|
142
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
143
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
144
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
97
145
|
editorInsertContentJsonAtSelectionScalar(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
146
|
+
editorId,
|
|
147
|
+
anchor,
|
|
148
|
+
head,
|
|
101
149
|
json
|
|
102
150
|
)
|
|
103
151
|
}
|
|
104
152
|
Function("editorWrapInList") { id: Int, listType: String ->
|
|
105
|
-
|
|
153
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
154
|
+
editorWrapInList(editorId, listType)
|
|
106
155
|
}
|
|
107
156
|
Function("editorUnwrapFromList") { id: Int ->
|
|
108
|
-
|
|
157
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
158
|
+
editorUnwrapFromList(editorId)
|
|
109
159
|
}
|
|
110
160
|
Function("editorIndentListItem") { id: Int ->
|
|
111
|
-
|
|
161
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
162
|
+
editorIndentListItem(editorId)
|
|
112
163
|
}
|
|
113
164
|
Function("editorOutdentListItem") { id: Int ->
|
|
114
|
-
|
|
165
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
166
|
+
editorOutdentListItem(editorId)
|
|
115
167
|
}
|
|
116
168
|
Function("editorInsertNode") { id: Int, nodeType: String ->
|
|
117
|
-
|
|
169
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
170
|
+
editorInsertNode(editorId, nodeType)
|
|
118
171
|
}
|
|
119
172
|
|
|
120
173
|
Function("editorInsertTextScalar") { id: Int, scalarPos: Int, text: String ->
|
|
121
|
-
|
|
174
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
175
|
+
val position = nativeUInt(scalarPos) ?: return@Function nativeArgumentError("position")
|
|
176
|
+
editorInsertTextScalar(editorId, position, text)
|
|
122
177
|
}
|
|
123
178
|
Function("editorDeleteScalarRange") { id: Int, scalarFrom: Int, scalarTo: Int ->
|
|
124
|
-
|
|
179
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
180
|
+
val fromPosition = nativeUInt(scalarFrom) ?: return@Function nativeArgumentError("position")
|
|
181
|
+
val toPosition = nativeUInt(scalarTo) ?: return@Function nativeArgumentError("position")
|
|
182
|
+
editorDeleteScalarRange(editorId, fromPosition, toPosition)
|
|
125
183
|
}
|
|
126
184
|
Function("editorReplaceTextScalar") { id: Int, scalarFrom: Int, scalarTo: Int, text: String ->
|
|
127
|
-
|
|
185
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
186
|
+
val fromPosition = nativeUInt(scalarFrom) ?: return@Function nativeArgumentError("position")
|
|
187
|
+
val toPosition = nativeUInt(scalarTo) ?: return@Function nativeArgumentError("position")
|
|
188
|
+
editorReplaceTextScalar(editorId, fromPosition, toPosition, text)
|
|
128
189
|
}
|
|
129
190
|
Function("editorSplitBlockScalar") { id: Int, scalarPos: Int ->
|
|
130
|
-
|
|
191
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
192
|
+
val position = nativeUInt(scalarPos) ?: return@Function nativeArgumentError("position")
|
|
193
|
+
editorSplitBlockScalar(editorId, position)
|
|
131
194
|
}
|
|
132
195
|
Function("editorDeleteAndSplitScalar") { id: Int, scalarFrom: Int, scalarTo: Int ->
|
|
133
|
-
|
|
196
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
197
|
+
val fromPosition = nativeUInt(scalarFrom) ?: return@Function nativeArgumentError("position")
|
|
198
|
+
val toPosition = nativeUInt(scalarTo) ?: return@Function nativeArgumentError("position")
|
|
199
|
+
editorDeleteAndSplitScalar(editorId, fromPosition, toPosition)
|
|
134
200
|
}
|
|
135
201
|
Function(
|
|
136
202
|
"editorToggleMarkAtSelectionScalar"
|
|
137
203
|
) { id: Int, scalarAnchor: Int, scalarHead: Int, markName: String ->
|
|
204
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
205
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
206
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
138
207
|
editorToggleMarkAtSelectionScalar(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
208
|
+
editorId,
|
|
209
|
+
anchor,
|
|
210
|
+
head,
|
|
142
211
|
markName
|
|
143
212
|
)
|
|
144
213
|
}
|
|
145
214
|
Function(
|
|
146
215
|
"editorSetMarkAtSelectionScalar"
|
|
147
216
|
) { id: Int, scalarAnchor: Int, scalarHead: Int, markName: String, attrsJson: String ->
|
|
217
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
218
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
219
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
148
220
|
editorSetMarkAtSelectionScalar(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
221
|
+
editorId,
|
|
222
|
+
anchor,
|
|
223
|
+
head,
|
|
152
224
|
markName,
|
|
153
225
|
attrsJson
|
|
154
226
|
)
|
|
@@ -156,136 +228,182 @@ class NativeEditorModule : Module() {
|
|
|
156
228
|
Function(
|
|
157
229
|
"editorUnsetMarkAtSelectionScalar"
|
|
158
230
|
) { id: Int, scalarAnchor: Int, scalarHead: Int, markName: String ->
|
|
231
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
232
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
233
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
159
234
|
editorUnsetMarkAtSelectionScalar(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
235
|
+
editorId,
|
|
236
|
+
anchor,
|
|
237
|
+
head,
|
|
163
238
|
markName
|
|
164
239
|
)
|
|
165
240
|
}
|
|
166
241
|
Function(
|
|
167
242
|
"editorToggleBlockquoteAtSelectionScalar"
|
|
168
243
|
) { id: Int, scalarAnchor: Int, scalarHead: Int ->
|
|
244
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
245
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
246
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
169
247
|
editorToggleBlockquoteAtSelectionScalar(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
248
|
+
editorId,
|
|
249
|
+
anchor,
|
|
250
|
+
head
|
|
173
251
|
)
|
|
174
252
|
}
|
|
175
253
|
Function(
|
|
176
254
|
"editorToggleHeadingAtSelectionScalar"
|
|
177
255
|
) { id: Int, scalarAnchor: Int, scalarHead: Int, level: Int ->
|
|
256
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
257
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
258
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
178
259
|
if (level !in 1..6) {
|
|
179
260
|
return@Function "{\"error\":\"invalid heading level\"}"
|
|
180
261
|
}
|
|
181
262
|
editorToggleHeadingAtSelectionScalar(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
263
|
+
editorId,
|
|
264
|
+
anchor,
|
|
265
|
+
head,
|
|
185
266
|
level.toUByte()
|
|
186
267
|
)
|
|
187
268
|
}
|
|
188
269
|
Function(
|
|
189
270
|
"editorWrapInListAtSelectionScalar"
|
|
190
271
|
) { id: Int, scalarAnchor: Int, scalarHead: Int, listType: String ->
|
|
272
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
273
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
274
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
191
275
|
editorWrapInListAtSelectionScalar(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
276
|
+
editorId,
|
|
277
|
+
anchor,
|
|
278
|
+
head,
|
|
195
279
|
listType
|
|
196
280
|
)
|
|
197
281
|
}
|
|
198
282
|
Function(
|
|
199
283
|
"editorUnwrapFromListAtSelectionScalar"
|
|
200
284
|
) { id: Int, scalarAnchor: Int, scalarHead: Int ->
|
|
285
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
286
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
287
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
201
288
|
editorUnwrapFromListAtSelectionScalar(
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
289
|
+
editorId,
|
|
290
|
+
anchor,
|
|
291
|
+
head
|
|
205
292
|
)
|
|
206
293
|
}
|
|
207
294
|
Function(
|
|
208
295
|
"editorIndentListItemAtSelectionScalar"
|
|
209
296
|
) { id: Int, scalarAnchor: Int, scalarHead: Int ->
|
|
297
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
298
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
299
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
210
300
|
editorIndentListItemAtSelectionScalar(
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
301
|
+
editorId,
|
|
302
|
+
anchor,
|
|
303
|
+
head
|
|
214
304
|
)
|
|
215
305
|
}
|
|
216
306
|
Function(
|
|
217
307
|
"editorOutdentListItemAtSelectionScalar"
|
|
218
308
|
) { id: Int, scalarAnchor: Int, scalarHead: Int ->
|
|
309
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
310
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
311
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
219
312
|
editorOutdentListItemAtSelectionScalar(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
313
|
+
editorId,
|
|
314
|
+
anchor,
|
|
315
|
+
head
|
|
223
316
|
)
|
|
224
317
|
}
|
|
225
318
|
Function(
|
|
226
319
|
"editorInsertNodeAtSelectionScalar"
|
|
227
320
|
) { id: Int, scalarAnchor: Int, scalarHead: Int, nodeType: String ->
|
|
321
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
322
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function nativeArgumentError("position")
|
|
323
|
+
val head = nativeUInt(scalarHead) ?: return@Function nativeArgumentError("position")
|
|
228
324
|
editorInsertNodeAtSelectionScalar(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
325
|
+
editorId,
|
|
326
|
+
anchor,
|
|
327
|
+
head,
|
|
232
328
|
nodeType
|
|
233
329
|
)
|
|
234
330
|
}
|
|
235
331
|
|
|
236
332
|
Function("editorToggleMark") { id: Int, markName: String ->
|
|
237
|
-
|
|
333
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
334
|
+
editorToggleMark(editorId, markName)
|
|
238
335
|
}
|
|
239
336
|
Function("editorSetMark") { id: Int, markName: String, attrsJson: String ->
|
|
240
|
-
|
|
337
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
338
|
+
editorSetMark(editorId, markName, attrsJson)
|
|
241
339
|
}
|
|
242
340
|
Function("editorUnsetMark") { id: Int, markName: String ->
|
|
243
|
-
|
|
341
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
342
|
+
editorUnsetMark(editorId, markName)
|
|
244
343
|
}
|
|
245
344
|
Function("editorToggleBlockquote") { id: Int ->
|
|
246
|
-
|
|
345
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
346
|
+
editorToggleBlockquote(editorId)
|
|
247
347
|
}
|
|
248
348
|
Function("editorToggleHeading") { id: Int, level: Int ->
|
|
349
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
249
350
|
if (level !in 1..6) {
|
|
250
351
|
return@Function "{\"error\":\"invalid heading level\"}"
|
|
251
352
|
}
|
|
252
|
-
editorToggleHeading(
|
|
353
|
+
editorToggleHeading(editorId, level.toUByte())
|
|
253
354
|
}
|
|
254
355
|
|
|
255
356
|
Function("editorSetSelection") { id: Int, anchor: Int, head: Int ->
|
|
256
|
-
|
|
357
|
+
val editorId = nativeULong(id) ?: return@Function
|
|
358
|
+
val anchorPosition = nativeUInt(anchor) ?: return@Function
|
|
359
|
+
val headPosition = nativeUInt(head) ?: return@Function
|
|
360
|
+
editorSetSelection(editorId, anchorPosition, headPosition)
|
|
257
361
|
}
|
|
258
362
|
Function("editorSetSelectionScalar") { id: Int, scalarAnchor: Int, scalarHead: Int ->
|
|
259
|
-
|
|
363
|
+
val editorId = nativeULong(id) ?: return@Function
|
|
364
|
+
val anchor = nativeUInt(scalarAnchor) ?: return@Function
|
|
365
|
+
val head = nativeUInt(scalarHead) ?: return@Function
|
|
366
|
+
editorSetSelectionScalar(editorId, anchor, head)
|
|
260
367
|
}
|
|
261
368
|
Function("editorGetSelection") { id: Int ->
|
|
262
|
-
|
|
369
|
+
val editorId = nativeULong(id) ?: return@Function "{\"type\":\"text\",\"anchor\":0,\"head\":0}"
|
|
370
|
+
editorGetSelection(editorId)
|
|
263
371
|
}
|
|
264
372
|
Function("editorGetSelectionState") { id: Int ->
|
|
265
|
-
|
|
373
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
374
|
+
editorGetSelectionState(editorId)
|
|
266
375
|
}
|
|
267
376
|
Function("editorDocToScalar") { id: Int, docPos: Int ->
|
|
268
|
-
|
|
377
|
+
val editorId = nativeULong(id) ?: return@Function 0
|
|
378
|
+
val position = nativeUInt(docPos) ?: return@Function 0
|
|
379
|
+
editorDocToScalar(editorId, position).toInt()
|
|
269
380
|
}
|
|
270
381
|
Function("editorScalarToDoc") { id: Int, scalar: Int ->
|
|
271
|
-
|
|
382
|
+
val editorId = nativeULong(id) ?: return@Function 0
|
|
383
|
+
val position = nativeUInt(scalar) ?: return@Function 0
|
|
384
|
+
editorScalarToDoc(editorId, position).toInt()
|
|
272
385
|
}
|
|
273
386
|
|
|
274
387
|
Function("editorGetCurrentState") { id: Int ->
|
|
275
|
-
|
|
388
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
389
|
+
editorGetCurrentState(editorId)
|
|
276
390
|
}
|
|
277
391
|
|
|
278
392
|
Function("editorUndo") { id: Int ->
|
|
279
|
-
|
|
393
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
394
|
+
editorUndo(editorId)
|
|
280
395
|
}
|
|
281
396
|
Function("editorRedo") { id: Int ->
|
|
282
|
-
|
|
397
|
+
val editorId = nativeULong(id) ?: return@Function nativeArgumentError("editor id")
|
|
398
|
+
editorRedo(editorId)
|
|
283
399
|
}
|
|
284
400
|
Function("editorCanUndo") { id: Int ->
|
|
285
|
-
|
|
401
|
+
val editorId = nativeULong(id) ?: return@Function false
|
|
402
|
+
editorCanUndo(editorId)
|
|
286
403
|
}
|
|
287
404
|
Function("editorCanRedo") { id: Int ->
|
|
288
|
-
|
|
405
|
+
val editorId = nativeULong(id) ?: return@Function false
|
|
406
|
+
editorCanRedo(editorId)
|
|
289
407
|
}
|
|
290
408
|
Function("renderDocumentJson") { configJson: String, json: String ->
|
|
291
409
|
val editorId = editorCreate(configJson)
|
|
@@ -320,15 +438,16 @@ class NativeEditorModule : Module() {
|
|
|
320
438
|
"onSelectionChange",
|
|
321
439
|
"onFocusChange",
|
|
322
440
|
"onContentHeightChange",
|
|
441
|
+
"onEditorReady",
|
|
323
442
|
"onToolbarAction",
|
|
324
443
|
"onAddonEvent"
|
|
325
444
|
)
|
|
326
445
|
|
|
327
446
|
Prop("editorId") { view: NativeEditorExpoView, id: Int ->
|
|
328
|
-
view.setEditorId(id
|
|
447
|
+
view.setEditorId(nativeULong(id)?.toLong() ?: 0L)
|
|
329
448
|
}
|
|
330
449
|
Prop("editable") { view: NativeEditorExpoView, editable: Boolean ->
|
|
331
|
-
view.
|
|
450
|
+
view.setEditable(editable)
|
|
332
451
|
}
|
|
333
452
|
Prop("placeholder") { view: NativeEditorExpoView, placeholder: String ->
|
|
334
453
|
view.richTextView.editorEditText.placeholderText = placeholder
|
|
@@ -375,6 +494,9 @@ class NativeEditorModule : Module() {
|
|
|
375
494
|
Prop("editorUpdateJson") { view: NativeEditorExpoView, editorUpdateJson: String? ->
|
|
376
495
|
view.setPendingEditorUpdateJson(editorUpdateJson)
|
|
377
496
|
}
|
|
497
|
+
Prop("editorUpdateEditorId") { view: NativeEditorExpoView, editorUpdateEditorId: Int? ->
|
|
498
|
+
view.setPendingEditorUpdateEditorId(editorUpdateEditorId?.let { nativeULong(it)?.toLong() })
|
|
499
|
+
}
|
|
378
500
|
Prop("editorUpdateRevision") { view: NativeEditorExpoView, editorUpdateRevision: Int ->
|
|
379
501
|
view.setPendingEditorUpdateRevision(editorUpdateRevision)
|
|
380
502
|
}
|
|
@@ -61,6 +61,33 @@ object PositionBridge {
|
|
|
61
61
|
return if (nextBoundary == BreakIterator.DONE) text.length else nextBoundary
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Snaps a UTF-16 offset out of the middle of a surrogate pair without
|
|
66
|
+
* applying full grapheme-cluster expansion.
|
|
67
|
+
*/
|
|
68
|
+
fun snapToScalarBoundary(
|
|
69
|
+
utf16Offset: Int,
|
|
70
|
+
text: String,
|
|
71
|
+
biasForward: Boolean
|
|
72
|
+
): Int {
|
|
73
|
+
val clampedOffset = utf16Offset.coerceIn(0, text.length)
|
|
74
|
+
if (clampedOffset <= 0 || clampedOffset >= text.length) return clampedOffset
|
|
75
|
+
|
|
76
|
+
val previous = text[clampedOffset - 1]
|
|
77
|
+
val current = text[clampedOffset]
|
|
78
|
+
if (Character.isHighSurrogate(previous) && Character.isLowSurrogate(current)) {
|
|
79
|
+
return if (biasForward) clampedOffset + 1 else clampedOffset - 1
|
|
80
|
+
}
|
|
81
|
+
return clampedOffset
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fun snapRangeToScalarBoundaries(start: Int, end: Int, text: String): Pair<Int, Int> {
|
|
85
|
+
val lower = minOf(start, end).coerceIn(0, text.length)
|
|
86
|
+
val upper = maxOf(start, end).coerceIn(0, text.length)
|
|
87
|
+
return snapToScalarBoundary(lower, text, biasForward = false) to
|
|
88
|
+
snapToScalarBoundary(upper, text, biasForward = true)
|
|
89
|
+
}
|
|
90
|
+
|
|
64
91
|
private fun conversionTableFor(text: String): ConversionTable {
|
|
65
92
|
val lastText = cachedText
|
|
66
93
|
val lastTable = cachedTable
|
|
@@ -56,16 +56,15 @@ class RichTextEditorView @JvmOverloads constructor(
|
|
|
56
56
|
internal var appliedCornerRadiusPx: Float = 0f
|
|
57
57
|
internal var appliedBackgroundColorForTesting: Int = Color.WHITE
|
|
58
58
|
|
|
59
|
+
private var currentEditorId: Long = 0
|
|
60
|
+
private var deferEditorUnbindOnDetach = false
|
|
61
|
+
internal var onBeforeDetachedFromWindow: (() -> Unit)? = null
|
|
62
|
+
|
|
59
63
|
/** Binds or unbinds the Rust editor instance. */
|
|
60
|
-
var editorId: Long
|
|
64
|
+
var editorId: Long
|
|
65
|
+
get() = currentEditorId
|
|
61
66
|
set(value) {
|
|
62
|
-
|
|
63
|
-
if (value != 0L) {
|
|
64
|
-
editorEditText.bindEditor(value)
|
|
65
|
-
} else {
|
|
66
|
-
editorEditText.unbindEditor()
|
|
67
|
-
}
|
|
68
|
-
refreshOverlays()
|
|
67
|
+
setEditorId(value, bindEditor = true)
|
|
69
68
|
}
|
|
70
69
|
|
|
71
70
|
init {
|
|
@@ -178,6 +177,8 @@ class RichTextEditorView @JvmOverloads constructor(
|
|
|
178
177
|
requestLayout()
|
|
179
178
|
}
|
|
180
179
|
|
|
180
|
+
internal fun viewportBottomInsetPxForTesting(): Int = viewportBottomInsetPx
|
|
181
|
+
|
|
181
182
|
fun setRemoteSelections(selections: List<RemoteSelectionDecoration>) {
|
|
182
183
|
remoteSelectionOverlayView.setRemoteSelections(selections)
|
|
183
184
|
}
|
|
@@ -217,9 +218,57 @@ class RichTextEditorView @JvmOverloads constructor(
|
|
|
217
218
|
editorEditText.applyUpdateJSON(editorGetCurrentState(editorId.toULong()), notifyListener = false)
|
|
218
219
|
}
|
|
219
220
|
|
|
221
|
+
internal fun rebindEditorIfNeeded(notifyListener: Boolean = true) {
|
|
222
|
+
if (editorId != 0L && editorEditText.editorId != editorId) {
|
|
223
|
+
setEditorId(editorId, bindEditor = true, notifyListener = notifyListener)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
internal fun setEditorIdWhileDetached(value: Long) {
|
|
228
|
+
setEditorId(value, bindEditor = false)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
internal fun deferEditorUnbindOnNextDetach() {
|
|
232
|
+
deferEditorUnbindOnDetach = true
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
internal fun clearDeferredEditorUnbind() {
|
|
236
|
+
deferEditorUnbindOnDetach = false
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
internal fun unbindEditorForDetachedViewIfNeeded() {
|
|
240
|
+
if (isAttachedToWindow) return
|
|
241
|
+
deferEditorUnbindOnDetach = false
|
|
242
|
+
if (editorId != 0L) {
|
|
243
|
+
editorEditText.unbindEditor()
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
private fun setEditorId(value: Long, bindEditor: Boolean, notifyListener: Boolean = true) {
|
|
248
|
+
val targetBoundEditorId = if (bindEditor) value else 0L
|
|
249
|
+
if (currentEditorId == value && editorEditText.editorId == targetBoundEditorId) return
|
|
250
|
+
if (currentEditorId != value || editorEditText.editorId != targetBoundEditorId) {
|
|
251
|
+
editorEditText.discardTransientNativeInputForEditorRebind()
|
|
252
|
+
}
|
|
253
|
+
currentEditorId = value
|
|
254
|
+
if (bindEditor && value != 0L) {
|
|
255
|
+
editorEditText.bindEditor(value, notifyListener = notifyListener)
|
|
256
|
+
} else {
|
|
257
|
+
editorEditText.unbindEditor()
|
|
258
|
+
}
|
|
259
|
+
refreshOverlays()
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
override fun onAttachedToWindow() {
|
|
263
|
+
super.onAttachedToWindow()
|
|
264
|
+
clearDeferredEditorUnbind()
|
|
265
|
+
rebindEditorIfNeeded()
|
|
266
|
+
}
|
|
267
|
+
|
|
220
268
|
override fun onDetachedFromWindow() {
|
|
269
|
+
onBeforeDetachedFromWindow?.invoke()
|
|
221
270
|
super.onDetachedFromWindow()
|
|
222
|
-
if (editorId != 0L) {
|
|
271
|
+
if (editorId != 0L && !deferEditorUnbindOnDetach) {
|
|
223
272
|
editorEditText.unbindEditor()
|
|
224
273
|
}
|
|
225
274
|
}
|