diff --git a/frontend/src/services/Android/index.ts b/frontend/src/services/Android/index.ts index f33b702a..973c1ff9 100644 --- a/frontend/src/services/Android/index.ts +++ b/frontend/src/services/Android/index.ts @@ -11,17 +11,41 @@ interface AndroidAppRobosats { } class AndroidRobosats { - private promises: Record) => void> = {}; + private promises: Record< + string, + { + resolve: (value: string | PromiseLike) => void; + reject: (reason?: string) => void; + } + > = {}; public storePromise: ( uuid: string, - promise: (value: string | PromiseLike) => void, - ) => void = (uuid, promise) => { - this.promises[uuid] = promise; + resolve: (value: string | PromiseLike) => void, + reject?: (reason?: string) => void, + ) => void = (uuid, resolve, reject) => { + this.promises[uuid] = { + resolve, + reject: reject || ((error) => console.error('Promise rejected:', error)), + }; }; - public onResolvePromise: (uuid: string, response: string) => void = (uuid, respone) => { - this.promises[uuid](respone); + public onResolvePromise: (uuid: string, response: string) => void = (uuid, response) => { + if (this.promises[uuid]) { + this.promises[uuid].resolve(response); + delete this.promises[uuid]; // Clean up after resolving + } else { + console.warn(`No promise found for UUID: ${uuid}`); + } + }; + + public onRejectPromise: (uuid: string, error: string) => void = (uuid, error) => { + if (this.promises[uuid]) { + this.promises[uuid].reject(error); + delete this.promises[uuid]; // Clean up after rejecting + } else { + console.warn(`No promise found for UUID: ${uuid}`); + } }; } diff --git a/frontend/src/services/Roboidentities/RoboidentitiesAndroidClient/index.ts b/frontend/src/services/Roboidentities/RoboidentitiesAndroidClient/index.ts index 12cdbd83..4fab857d 100644 --- a/frontend/src/services/Roboidentities/RoboidentitiesAndroidClient/index.ts +++ b/frontend/src/services/Roboidentities/RoboidentitiesAndroidClient/index.ts @@ -9,15 +9,19 @@ class RoboidentitiesAndroidClient implements RoboidentitiesClient { if (this.robonames[initialString]) { return this.robonames[initialString]; } else { - const result = await new Promise((resolve) => { - const uuid: string = uuidv4(); - window.AndroidAppRobosats?.generateRoboname(uuid, initialString); - window.AndroidRobosats?.storePromise(uuid, resolve); - }); + try { + const result = await new Promise((resolve, reject) => { + const uuid: string = uuidv4(); + window.AndroidAppRobosats?.generateRoboname(uuid, initialString); + window.AndroidRobosats?.storePromise(uuid, resolve, reject); + }); - this.robonames[initialString] = result; - - return result; + this.robonames[initialString] = result; + return result; + } catch (error) { + console.error('Error generating roboname:', error); + return ''; + } } }; diff --git a/mobile_new/app/build.gradle.kts b/mobile_new/app/build.gradle.kts index 51013fc6..02f8fb5f 100644 --- a/mobile_new/app/build.gradle.kts +++ b/mobile_new/app/build.gradle.kts @@ -60,7 +60,7 @@ android { } } - fun Packaging.() { + packaging { jniLibs.useLegacyPackaging = true } } diff --git a/mobile_new/app/src/main/java/com/koalasat/robosats/MainActivity.kt b/mobile_new/app/src/main/java/com/koalasat/robosats/MainActivity.kt index e250eb89..1aefaf08 100644 --- a/mobile_new/app/src/main/java/com/koalasat/robosats/MainActivity.kt +++ b/mobile_new/app/src/main/java/com/koalasat/robosats/MainActivity.kt @@ -6,7 +6,7 @@ import android.os.Bundle import android.util.Log import android.webkit.* import androidx.appcompat.app.AppCompatActivity -import com.koalasat.robosats.tor.WebAppInterface +import com.koalasat.robosats.WebAppInterface import com.robosats.tor.TorKmp import com.robosats.tor.TorKmpManager import java.net.InetSocketAddress diff --git a/mobile_new/app/src/main/java/com/koalasat/robosats/RoboIdentities.kt b/mobile_new/app/src/main/java/com/koalasat/robosats/RoboIdentities.kt new file mode 100644 index 00000000..578c8a0c --- /dev/null +++ b/mobile_new/app/src/main/java/com/koalasat/robosats/RoboIdentities.kt @@ -0,0 +1,58 @@ +package com.koalasat.robosats + +import android.util.Log + +class RoboIdentities { + companion object { + private const val TAG = "RoboIdentities" + private var librariesLoaded = false + + init { + try { + System.loadLibrary("robonames") + System.loadLibrary("robohash") + librariesLoaded = true + Log.d(TAG, "Native libraries loaded successfully") + } catch (e: UnsatisfiedLinkError) { + Log.e(TAG, "Failed to load native libraries: ${e.message}", e) + librariesLoaded = false + } catch (e: Exception) { + Log.e(TAG, "Unexpected error loading native libraries: ${e.message}", e) + librariesLoaded = false + } + } + + fun areLibrariesLoaded(): Boolean { + return librariesLoaded + } + } + + fun generateRoboname(initial_string: String?): String? { + return try { + if (!areLibrariesLoaded()) { + Log.e(TAG, "Cannot generate roboname: Native libraries not loaded") + "" } + nativeGenerateRoboname(initial_string) + } catch (e: Exception) { + Log.e(TAG, "Error generating roboname: ${e.message}", e) + "" + } + } + + fun generateRobohash(initial_string: String?): String? { + return try { + if (!areLibrariesLoaded()) { + Log.e(TAG, "Cannot generate robohash: Native libraries not loaded") + return "" + } + nativeGenerateRobohash(initial_string) + } catch (e: Exception) { + Log.e(TAG, "Error generating robohash: ${e.message}", e) + "" + } + } + + // Native functions implemented in Rust. + private external fun nativeGenerateRoboname(initial_string: String?): String? + private external fun nativeGenerateRobohash(initial_string: String?): String? +} diff --git a/mobile_new/app/src/main/java/com/koalasat/robosats/WebAppInterface.kt b/mobile_new/app/src/main/java/com/koalasat/robosats/WebAppInterface.kt new file mode 100644 index 00000000..160c5c56 --- /dev/null +++ b/mobile_new/app/src/main/java/com/koalasat/robosats/WebAppInterface.kt @@ -0,0 +1,46 @@ +package com.koalasat.robosats + +import android.content.Context +import android.util.Log +import android.webkit.JavascriptInterface +import android.webkit.WebView +import android.widget.Toast + +class WebAppInterface(private val context: Context, private val webView: WebView) { + private val TAG = "WebAppInterface" + private val roboIdentities = RoboIdentities() + + init { + // Check if libraries are loaded and show a toast notification if there's an issue + if (!RoboIdentities.areLibrariesLoaded()) { + Log.w(TAG, "Native libraries for RoboIdentities are not loaded - fallback names will be used") + Toast.makeText( + context, + "Warning: Robot name generator is using fallback mode", + Toast.LENGTH_LONG + ).show() + } + } + + @JavascriptInterface + fun generateRoboname(uuid: String, message: String) { + try { + val roboname = roboIdentities.generateRoboname(message) + Log.d(TAG, "Generated roboname: $roboname for message: $message") + + webView.post { + webView.evaluateJavascript("javascript:window.AndroidRobosats.onResolvePromise('${uuid}', '${roboname}')", null) + } + } catch (e: Exception) { + Log.e(TAG, "Error in generateRoboname: ${e.message}", e) + + // Handle error gracefully by returning a fallback value + webView.post { + webView.evaluateJavascript( + "javascript:window.AndroidRobosats.onRejectPromise('${uuid}', 'Error generating robot name')", + null + ) + } + } + } +} diff --git a/mobile_new/app/src/main/java/com/koalasat/robosats/tor/WebAppInterface.kt b/mobile_new/app/src/main/java/com/koalasat/robosats/tor/WebAppInterface.kt deleted file mode 100644 index f9c685f7..00000000 --- a/mobile_new/app/src/main/java/com/koalasat/robosats/tor/WebAppInterface.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.koalasat.robosats.tor - -import android.content.Context -import android.webkit.JavascriptInterface -import android.webkit.WebView -import android.widget.Toast - -class WebAppInterface(private val context: Context, private val webView: WebView) { - @JavascriptInterface - fun generateRoboname(uuid: String, message: String) { - // Handle the message received from JavaScript - Toast.makeText(context, message, Toast.LENGTH_SHORT).show() - - webView.post { - webView.evaluateJavascript("javascript:window.AndroidRobosats.onResolvePromise('${uuid}', '${message}')", null) - } - } -} diff --git a/mobile_new/app/src/main/jniLibs/arm64-v8a/librobohash.so b/mobile_new/app/src/main/jniLibs/arm64-v8a/librobohash.so new file mode 100755 index 00000000..bbff4071 Binary files /dev/null and b/mobile_new/app/src/main/jniLibs/arm64-v8a/librobohash.so differ diff --git a/mobile_new/app/src/main/jniLibs/arm64-v8a/librobonames.so b/mobile_new/app/src/main/jniLibs/arm64-v8a/librobonames.so new file mode 100755 index 00000000..56655ed8 Binary files /dev/null and b/mobile_new/app/src/main/jniLibs/arm64-v8a/librobonames.so differ diff --git a/mobile_new/app/src/main/jniLibs/armeabi-v7a/librobohash.so b/mobile_new/app/src/main/jniLibs/armeabi-v7a/librobohash.so new file mode 100755 index 00000000..373f2b99 Binary files /dev/null and b/mobile_new/app/src/main/jniLibs/armeabi-v7a/librobohash.so differ diff --git a/mobile_new/app/src/main/jniLibs/armeabi-v7a/librobonames.so b/mobile_new/app/src/main/jniLibs/armeabi-v7a/librobonames.so new file mode 100755 index 00000000..3f42760d Binary files /dev/null and b/mobile_new/app/src/main/jniLibs/armeabi-v7a/librobonames.so differ diff --git a/mobile_new/app/src/main/jniLibs/x86_64/librobohash.so b/mobile_new/app/src/main/jniLibs/x86_64/librobohash.so new file mode 100755 index 00000000..1e26077b Binary files /dev/null and b/mobile_new/app/src/main/jniLibs/x86_64/librobohash.so differ diff --git a/mobile_new/app/src/main/jniLibs/x86_64/librobonames.so b/mobile_new/app/src/main/jniLibs/x86_64/librobonames.so new file mode 100755 index 00000000..d6e1df92 Binary files /dev/null and b/mobile_new/app/src/main/jniLibs/x86_64/librobonames.so differ