diff --git a/patches/expo-translate-text+0.1.0.patch b/patches/expo-translate-text+0.1.0.patch new file mode 100644 index 0000000000..92e966d29f --- /dev/null +++ b/patches/expo-translate-text+0.1.0.patch @@ -0,0 +1,211 @@ +diff --git a/node_modules/expo-translate-text/android/src/main/java/expo/modules/translatetext/ExpoTranslateTextModule.kt b/node_modules/expo-translate-text/android/src/main/java/expo/modules/translatetext/ExpoTranslateTextModule.kt +index 7db10a2..368f3d8 100644 +--- a/node_modules/expo-translate-text/android/src/main/java/expo/modules/translatetext/ExpoTranslateTextModule.kt ++++ b/node_modules/expo-translate-text/android/src/main/java/expo/modules/translatetext/ExpoTranslateTextModule.kt +@@ -11,32 +11,24 @@ import expo.modules.kotlin.Promise + import expo.modules.kotlin.exception.CodedException + import expo.modules.kotlin.modules.Module + import expo.modules.kotlin.modules.ModuleDefinition ++import org.json.JSONArray ++import org.json.JSONObject ++import org.json.JSONTokener + import java.util.concurrent.atomic.AtomicInteger + + class ExpoTranslateTextModule : Module() { + override fun definition() = ModuleDefinition { + Name("ExpoTranslateText") + +- AsyncFunction("translateTask") { params: Map, promise: Promise -> +- translateTask(params, promise) ++ AsyncFunction("translateTask") { inputJson: String, targetLangCode: String, sourceLangCode: String?, requiresWifi: Boolean, requireCharging: Boolean, promise: Promise -> ++ translateTask(inputJson, targetLangCode, sourceLangCode, requiresWifi, requireCharging, promise) + } + } + +- private fun translateTask(params: Map, promise: Promise) { ++ private fun translateTask(inputJson: String, targetLangCode: String, sourceLangCode: String?, requiresWifi: Boolean, requireCharging: Boolean, promise: Promise) { + try { +- val textsInput = params["input"] ?: throw CodedException( +- code = "INVALID_PARAMETER", +- message = "No texts provided", +- cause = null +- ) ++ val textsInput = JSONTokener(inputJson).nextValue() + +- // 2) Validate the target language +- val targetLangCode = params["targetLangCode"] as? String +- ?: throw CodedException( +- code = "INVALID_PARAMETER", +- message = "Target language code is missing", +- cause = null +- ) + val targetLanguage = TranslateLanguage.fromLanguageTag(targetLangCode) + ?: throw CodedException( + code = "INVALID_PARAMETER", +@@ -44,8 +36,6 @@ class ExpoTranslateTextModule : Module() { + cause = null + ) + +- // 3) Optional source language (could be "auto") +- val sourceLangCode = params["sourceLangCode"] as? String + val fixedSourceLanguage: String? = if (sourceLangCode != null && sourceLangCode != "auto") { + TranslateLanguage.fromLanguageTag(sourceLangCode) + ?: throw CodedException( +@@ -55,10 +45,6 @@ class ExpoTranslateTextModule : Module() { + ) + } else null + +- // 4) Configure download conditions +- val requiresWifi = params["requiresWifi"] as? Boolean ?: false +- val requireCharging = params["requireCharging"] as? Boolean ?: false +- + val conditionsBuilder = DownloadConditions.Builder() + if (requiresWifi) { + conditionsBuilder.requireWifi() +@@ -90,8 +76,8 @@ class ExpoTranslateTextModule : Module() { + // 10) Figure out the total steps for concurrency + val totalStringCount = textsMap.values.sumOf { it.size } + val pendingCountValue = if (fixedSourceLanguage != null) { +- // 1 (download) + N (translations) +- totalStringCount + 1 ++ // 1 (initial download) + N (download in translateText) + N (translations) = 1 + 2N ++ totalStringCount * 2 + 1 + } else { + // For each string: 1 detection + 1 download + 1 translation = 3 + totalStringCount * 3 +@@ -311,25 +297,35 @@ class ExpoTranslateTextModule : Module() { + private fun extractTexts(input: Any): Map> { + return when (input) { + is String -> { +- // Single string => one map entry "0" => listOf(thatString) + mapOf("0" to listOf(input)) + } +- is List<*> -> { +- // If top-level is an array, store everything under "0" +- val stringList = input.filterIsInstance() ++ is JSONArray -> { ++ val stringList = mutableListOf() ++ for (i in 0 until input.length()) { ++ stringList.add(input.getString(i)) ++ } + mapOf("0" to stringList) + } +- is Map<*, *> -> { +- // If top-level is an object, each value can be string or string[] +- input.entries.associate { (k, v) -> +- val key = k.toString() +- val listOfStrings: List = when (v) { +- is String -> listOf(v) +- is List<*> -> v.filterIsInstance() ++ is JSONObject -> { ++ val result = mutableMapOf>() ++ val keys = input.keys() ++ while (keys.hasNext()) { ++ val key = keys.next() ++ val value = input.get(key) ++ val listOfStrings: List = when (value) { ++ is String -> listOf(value) ++ is JSONArray -> { ++ val arr = mutableListOf() ++ for (i in 0 until value.length()) { ++ arr.add(value.getString(i)) ++ } ++ arr ++ } + else -> emptyList() + } +- key to listOfStrings ++ result[key] = listOfStrings + } ++ result + } + else -> emptyMap() + } +@@ -346,16 +342,18 @@ class ExpoTranslateTextModule : Module() { + is String -> { + "" + } +- is List<*> -> { ++ is JSONArray -> { + mutableListOf() + } +- is Map<*, *> -> { ++ is JSONObject -> { + val outputMap = mutableMapOf() +- for ((k, v) in input) { +- val key = k.toString() +- when (v) { ++ val keys = input.keys() ++ while (keys.hasNext()) { ++ val key = keys.next() ++ val value = input.get(key) ++ when (value) { + is String -> outputMap[key] = "" +- is List<*> -> outputMap[key] = mutableListOf() ++ is JSONArray -> outputMap[key] = mutableListOf() + else -> outputMap[key] = "" + } + } +diff --git a/node_modules/expo-translate-text/build/ExpoTranslateTextModule.js b/node_modules/expo-translate-text/build/ExpoTranslateTextModule.js +index 74510b7..e978ee2 100644 +--- a/node_modules/expo-translate-text/build/ExpoTranslateTextModule.js ++++ b/node_modules/expo-translate-text/build/ExpoTranslateTextModule.js +@@ -1,4 +1,5 @@ + import { requireNativeModule } from 'expo-modules-core'; ++import { Platform } from 'react-native'; + export class TranslationError extends Error { + code; + constructor(message, code) { +@@ -7,7 +8,12 @@ export class TranslationError extends Error { + this.code = code; + } + } +-const ExpoIosTranslate = requireNativeModule('ExpoTranslateText'); +-export const translateTask = ExpoIosTranslate.translateTask; +-export const translateSheet = ExpoIosTranslate.translateSheet; ++const ExpoTranslateText = requireNativeModule('ExpoTranslateText'); ++export const translateTask = (params) => { ++ if (Platform.OS === 'android') { ++ return ExpoTranslateText.translateTask(JSON.stringify(params.input), params.targetLangCode ?? '', params.sourceLangCode ?? null, params.requiresWifi ?? false, params.requireCharging ?? false); ++ } ++ return ExpoTranslateText.translateTask(params); ++}; ++export const translateSheet = ExpoTranslateText.translateSheet; + //# sourceMappingURL=ExpoTranslateTextModule.js.map +\ No newline at end of file +diff --git a/node_modules/expo-translate-text/src/ExpoTranslateTextModule.ts b/node_modules/expo-translate-text/src/ExpoTranslateTextModule.ts +index 439a7d6..cd0bae1 100644 +--- a/node_modules/expo-translate-text/src/ExpoTranslateTextModule.ts ++++ b/node_modules/expo-translate-text/src/ExpoTranslateTextModule.ts +@@ -1,5 +1,6 @@ + import { requireNativeModule } from 'expo-modules-core'; +-import { ExpoTranslateTextModule } from './ExpoTranslateText.types'; ++import { ExpoTranslateTextModule, TranslationTaskRequest } from './ExpoTranslateText.types'; ++import { Platform } from 'react-native'; + + export class TranslationError extends Error { + code?: number; +@@ -11,7 +12,20 @@ export class TranslationError extends Error { + } + } + +-const ExpoIosTranslate = requireNativeModule('ExpoTranslateText'); ++const ExpoTranslateText = requireNativeModule('ExpoTranslateText'); + +-export const translateTask = ExpoIosTranslate.translateTask; +-export const translateSheet = ExpoIosTranslate.translateSheet; ++export const translateTask = (params: TranslationTaskRequest) => { ++ if (Platform.OS === 'android') { ++ // Android native module accepts individual typed params to avoid ++ // Expo Modules bridge serialization issues with Map ++ return (ExpoTranslateText as any).translateTask( ++ JSON.stringify(params.input), ++ params.targetLangCode ?? '', ++ params.sourceLangCode ?? null, ++ params.requiresWifi ?? false, ++ params.requireCharging ?? false, ++ ); ++ } ++ return ExpoTranslateText.translateTask(params); ++}; ++export const translateSheet = ExpoTranslateText.translateSheet;