expo-paste-input 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.
- package/android/build/.transforms/04cfbef6d6438014a0f56f30321e9943/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/pasteinput/ExpoPasteInputView$createActionModeCallback$1.dex +0 -0
- package/android/build/.transforms/04cfbef6d6438014a0f56f30321e9943/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/pasteinput/ExpoPasteInputView.dex +0 -0
- package/android/build/.transforms/61052c0b101cc72f1be04cd5637e14e3/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/pasteinput/ExpoPasteInputView$createActionModeCallback$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/pasteinput/ExpoPasteInputView.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +1 -1
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/pasteinput/ExpoPasteInputView$createActionModeCallback$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/pasteinput/ExpoPasteInputView.class +0 -0
- package/android/src/main/java/expo/modules/pasteinput/ExpoPasteInputView.kt +46 -30
- package/ios/ExpoPasteInputView.swift +6 -39
- package/package.json +1 -1
- package/android/build/.transforms/04cfbef6d6438014a0f56f30321e9943/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/expo/modules/pasteinput/ExpoPasteInputView$enhanceOnTextContextMenuItem$callback$1.dex +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/expo/modules/pasteinput/ExpoPasteInputView$enhanceOnTextContextMenuItem$callback$1.class +0 -0
- package/android/build/tmp/kotlin-classes/debug/expo/modules/pasteinput/ExpoPasteInputView$enhanceOnTextContextMenuItem$callback$1.class +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
6
|
|
2
2
|
0
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream
CHANGED
|
Binary file
|
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len
CHANGED
|
Binary file
|
package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/android/build/tmp/kotlin-classes/debug/expo/modules/pasteinput/ExpoPasteInputView.class
CHANGED
|
Binary file
|
|
@@ -184,52 +184,56 @@ class ExpoPasteInputView(context: Context, appContext: AppContext) : ExpoView(co
|
|
|
184
184
|
originalInsertionActionModeCallback = editText.customInsertionActionModeCallback
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// Set up
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
// Set up custom callbacks to intercept paste from both selection and insertion menus.
|
|
188
|
+
customSelectionActionModeCallback = createActionModeCallback(
|
|
189
|
+
editText = editText,
|
|
190
|
+
originalCallback = originalSelectionActionModeCallback
|
|
191
|
+
)
|
|
192
|
+
editText.customSelectionActionModeCallback = customSelectionActionModeCallback
|
|
193
|
+
|
|
194
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
195
|
+
customInsertionActionModeCallback = createActionModeCallback(
|
|
196
|
+
editText = editText,
|
|
197
|
+
originalCallback = originalInsertionActionModeCallback
|
|
198
|
+
)
|
|
199
|
+
editText.customInsertionActionModeCallback = customInsertionActionModeCallback
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
} catch (e: Exception) {
|
|
203
|
+
// If ActionMode.Callback approach fails, we'll rely on OnReceiveContentListener
|
|
204
|
+
// which should still work but may show the toast briefly
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private fun createActionModeCallback(
|
|
209
|
+
editText: EditText,
|
|
210
|
+
originalCallback: ActionMode.Callback?
|
|
211
|
+
): ActionMode.Callback {
|
|
212
|
+
return object : ActionMode.Callback {
|
|
190
213
|
override fun onCreateActionMode(mode: ActionMode?, menu: android.view.Menu?): Boolean {
|
|
191
214
|
// Delegate to original callback if it exists
|
|
192
|
-
return
|
|
215
|
+
return originalCallback?.onCreateActionMode(mode, menu) ?: true
|
|
193
216
|
}
|
|
194
217
|
|
|
195
218
|
override fun onPrepareActionMode(mode: ActionMode?, menu: android.view.Menu?): Boolean {
|
|
196
219
|
// Delegate to original callback if it exists
|
|
197
|
-
return
|
|
220
|
+
return originalCallback?.onPrepareActionMode(mode, menu) ?: false
|
|
198
221
|
}
|
|
199
222
|
|
|
200
223
|
override fun onActionItemClicked(mode: ActionMode?, item: android.view.MenuItem?): Boolean {
|
|
201
224
|
if (item?.itemId == android.R.id.paste) {
|
|
202
|
-
return handlePasteFromActionMode(editText, mode, item,
|
|
225
|
+
return handlePasteFromActionMode(editText, mode, item, originalCallback)
|
|
203
226
|
}
|
|
204
227
|
|
|
205
228
|
// For other actions, delegate to original callback or return false
|
|
206
|
-
return
|
|
229
|
+
return originalCallback?.onActionItemClicked(mode, item) ?: false
|
|
207
230
|
}
|
|
208
231
|
|
|
209
232
|
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
210
233
|
// Delegate to original callback if it exists
|
|
211
|
-
|
|
234
|
+
originalCallback?.onDestroyActionMode(mode)
|
|
212
235
|
}
|
|
213
236
|
}
|
|
214
|
-
|
|
215
|
-
customSelectionActionModeCallback = callback
|
|
216
|
-
editText.customSelectionActionModeCallback = customSelectionActionModeCallback
|
|
217
|
-
|
|
218
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
219
|
-
customInsertionActionModeCallback = callback
|
|
220
|
-
editText.customInsertionActionModeCallback = customInsertionActionModeCallback
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
} catch (e: Exception) {
|
|
224
|
-
// If ActionMode.Callback approach fails, we'll rely on OnReceiveContentListener
|
|
225
|
-
// which should still work but may show the toast briefly
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
private fun getOriginalActionModeCallback(): ActionMode.Callback? {
|
|
230
|
-
// Cursor/insertion menu and selection menu can use different callbacks.
|
|
231
|
-
// Prefer insertion callback first for insertion-mode paste.
|
|
232
|
-
return originalInsertionActionModeCallback ?: originalSelectionActionModeCallback
|
|
233
237
|
}
|
|
234
238
|
|
|
235
239
|
private fun handlePasteFromActionMode(
|
|
@@ -298,6 +302,8 @@ class ExpoPasteInputView(context: Context, appContext: AppContext) : ExpoView(co
|
|
|
298
302
|
} else {
|
|
299
303
|
imageUris.add(uri)
|
|
300
304
|
}
|
|
305
|
+
} else if (isLikelyGifUri(uri)) {
|
|
306
|
+
gifUris.add(uri)
|
|
301
307
|
} else if (isLikelyImageUri(uri)) {
|
|
302
308
|
imageUris.add(uri)
|
|
303
309
|
}
|
|
@@ -323,12 +329,16 @@ class ExpoPasteInputView(context: Context, appContext: AppContext) : ExpoView(co
|
|
|
323
329
|
return fileName.endsWith(".png") ||
|
|
324
330
|
fileName.endsWith(".jpg") ||
|
|
325
331
|
fileName.endsWith(".jpeg") ||
|
|
326
|
-
fileName.endsWith(".gif") ||
|
|
327
332
|
fileName.endsWith(".webp") ||
|
|
328
333
|
fileName.endsWith(".heic") ||
|
|
329
334
|
fileName.endsWith(".heif")
|
|
330
335
|
}
|
|
331
336
|
|
|
337
|
+
private fun isLikelyGifUri(uri: Uri): Boolean {
|
|
338
|
+
val fileName = uri.lastPathSegment?.lowercase() ?: return false
|
|
339
|
+
return fileName.endsWith(".gif")
|
|
340
|
+
}
|
|
341
|
+
|
|
332
342
|
private fun markSuppressOnReceiveContent() {
|
|
333
343
|
suppressOnReceiveContentUntilMs = SystemClock.elapsedRealtime() + 500L
|
|
334
344
|
}
|
|
@@ -404,12 +414,18 @@ class ExpoPasteInputView(context: Context, appContext: AppContext) : ExpoView(co
|
|
|
404
414
|
|
|
405
415
|
// Save to cache directory
|
|
406
416
|
val cacheDir = context.cacheDir
|
|
417
|
+
val usePng = bitmap.hasAlpha()
|
|
418
|
+
val fileExtension = if (usePng) "png" else "jpg"
|
|
407
419
|
// Use UUID-like approach for better uniqueness: timestamp + counter
|
|
408
|
-
val fileName = "${System.currentTimeMillis()}_${filePaths.size}
|
|
420
|
+
val fileName = "${System.currentTimeMillis()}_${filePaths.size}.$fileExtension"
|
|
409
421
|
val file = File(cacheDir, fileName)
|
|
410
422
|
|
|
411
423
|
FileOutputStream(file).use { outputStream ->
|
|
412
|
-
|
|
424
|
+
if (usePng) {
|
|
425
|
+
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
|
|
426
|
+
} else {
|
|
427
|
+
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream)
|
|
428
|
+
}
|
|
413
429
|
outputStream.flush()
|
|
414
430
|
}
|
|
415
431
|
|
|
@@ -151,10 +151,12 @@ class ExpoPasteInputView: ExpoView {
|
|
|
151
151
|
let wrapper = weakWrapper.value {
|
|
152
152
|
// Only process if this is our wrapped text input
|
|
153
153
|
if action == #selector(UIResponderStandardEditActions.paste(_:)) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
// IMPORTANT:
|
|
155
|
+
// Do not read UIPasteboard content here. iOS may show the
|
|
156
|
+
// "App would like to paste" privacy prompt on menu-open checks.
|
|
157
|
+
// We allow paste action visibility and read the pasteboard only
|
|
158
|
+
// when the user explicitly taps Paste in `paste(_:)`.
|
|
159
|
+
return true
|
|
158
160
|
}
|
|
159
161
|
}
|
|
160
162
|
|
|
@@ -607,41 +609,6 @@ class ExpoPasteInputView: ExpoView {
|
|
|
607
609
|
stopMonitoring()
|
|
608
610
|
}
|
|
609
611
|
|
|
610
|
-
private func hasSupportedImageContent(in pasteboard: UIPasteboard) -> Bool {
|
|
611
|
-
if pasteboard.hasImages {
|
|
612
|
-
return true
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
if hasPasteboardData(forAnyTypeIn: gifTypes.union(webpTypes), pasteboard: pasteboard) {
|
|
616
|
-
return true
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
for item in pasteboard.items {
|
|
620
|
-
for (key, value) in item {
|
|
621
|
-
let lowercasedKey = key.lowercased()
|
|
622
|
-
let isImageLikeType = lowercasedKey.contains("image") ||
|
|
623
|
-
lowercasedKey.contains("png") ||
|
|
624
|
-
lowercasedKey.contains("jpeg") ||
|
|
625
|
-
lowercasedKey.contains("jpg") ||
|
|
626
|
-
lowercasedKey.contains("tiff") ||
|
|
627
|
-
lowercasedKey.contains("heic") ||
|
|
628
|
-
lowercasedKey.contains("heif") ||
|
|
629
|
-
lowercasedKey.contains("gif") ||
|
|
630
|
-
lowercasedKey.contains("webp")
|
|
631
|
-
|
|
632
|
-
if isImageLikeType && (value is Data || value is UIImage) {
|
|
633
|
-
return true
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
if value is UIImage {
|
|
637
|
-
return true
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
return false
|
|
643
|
-
}
|
|
644
|
-
|
|
645
612
|
private func hasPasteboardData(forAnyTypeIn types: Set<String>, pasteboard: UIPasteboard) -> Bool {
|
|
646
613
|
for type in types {
|
|
647
614
|
if let data = pasteboard.data(forPasteboardType: type), !data.isEmpty {
|
package/package.json
CHANGED