From 3a3059acb33109229e0e6702bd91434a906a9015 Mon Sep 17 00:00:00 2001 From: Emma Date: Tue, 28 Jan 2025 08:00:36 -0500 Subject: [PATCH] Replace jsCommunicator calls with new promise class (benefits): allows for more concise passing of JSON back to the js side --- .../freetubeapp/freetube/helpers/Promise.kt | 71 +++++++++++++++++++ .../javascript/FreeTubeJavaScriptInterface.kt | 17 +++-- 2 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 android/app/src/main/java/io/freetubeapp/freetube/helpers/Promise.kt diff --git a/android/app/src/main/java/io/freetubeapp/freetube/helpers/Promise.kt b/android/app/src/main/java/io/freetubeapp/freetube/helpers/Promise.kt new file mode 100644 index 0000000000000..c03c8814f30bc --- /dev/null +++ b/android/app/src/main/java/io/freetubeapp/freetube/helpers/Promise.kt @@ -0,0 +1,71 @@ +package io.freetubeapp.freetube.helpers + +import io.freetubeapp.freetube.javascript.AsyncJSCommunicator +import java.util.UUID.randomUUID +import java.util.concurrent.ThreadPoolExecutor + +class Promise { + private val successListeners: MutableList<(T) -> Unit> = mutableListOf() + private var successResult: T? = null + private val errorListeners: MutableList<(G) -> Unit> = mutableListOf() + private var errorResult: G? = null + private val id = "${randomUUID()}" + + constructor(executor: ThreadPoolExecutor, runnable: ((T) -> Unit, (G) -> Unit) -> Unit) { + executor.run { + runnable.invoke({ + result -> + notifySuccess(result) + }, { + result -> + notifyError(result) + }) + } + } + + fun addJsCommunicator(communicator: AsyncJSCommunicator) : String { + then { + communicator.resolve(id, "$it") + } + catch { + communicator.reject(id, "$it") + } + return id + } + + fun notifySuccess(result: T) { + successResult = result + successListeners.forEach { + listener -> + listener.invoke(result) + } + } + + fun notifyError(result: G) { + errorResult = result + errorListeners.forEach { + listener -> + listener.invoke(result) + } + } + + fun then(listener: (T) -> Unit): Promise { + if (successResult != null) { + // assume success result won't be unset + listener(successResult!!) + } else { + successListeners.add(listener) + } + return this + } + + fun catch(listener: (G) -> Unit): Promise { + if (errorResult != null) { + // assume success result won't be unset + listener(errorResult!!) + } else { + errorListeners.add(listener) + } + return this + } +} diff --git a/android/app/src/main/java/io/freetubeapp/freetube/javascript/FreeTubeJavaScriptInterface.kt b/android/app/src/main/java/io/freetubeapp/freetube/javascript/FreeTubeJavaScriptInterface.kt index bc2a1b438b7b7..492a6a74650d2 100644 --- a/android/app/src/main/java/io/freetubeapp/freetube/javascript/FreeTubeJavaScriptInterface.kt +++ b/android/app/src/main/java/io/freetubeapp/freetube/javascript/FreeTubeJavaScriptInterface.kt @@ -26,6 +26,8 @@ import androidx.documentfile.provider.DocumentFile import io.freetubeapp.freetube.MainActivity import io.freetubeapp.freetube.MediaControlsReceiver import io.freetubeapp.freetube.R +import io.freetubeapp.freetube.helpers.Promise +import org.json.JSONObject import java.io.File import java.io.FileInputStream import java.net.URL @@ -375,24 +377,25 @@ class FreeTubeJavaScriptInterface { */ @JavascriptInterface fun readFile(basedir: String, filename: String): String { - val promise = jsCommunicator.jsPromise() - context.threadPoolExecutor.execute { + val promise = Promise(context.threadPoolExecutor, { + resolve, + reject -> try { if (basedir.startsWith("content://")) { val stream = context.contentResolver.openInputStream(Uri.parse(basedir)) val content = String(stream!!.readBytes()) stream!!.close() - jsCommunicator.resolve(promise, content) + resolve(content) } else { val path = getDirectory(basedir) val file = File(path, filename) - jsCommunicator.resolve(promise, FileInputStream(file).bufferedReader().use { it.readText() }) + resolve(FileInputStream(file).bufferedReader().use { it.readText() }) } } catch (ex: Exception) { - jsCommunicator.reject(promise, ex.stackTraceToString()) + reject(ex.stackTraceToString()) } - } - return promise + }) + return promise.addJsCommunicator(jsCommunicator) } /**