From 12b24d4474eb42713dbee86ac76296db676c3f64 Mon Sep 17 00:00:00 2001 From: siepra Date: Tue, 23 Apr 2024 11:04:50 +0200 Subject: [PATCH] fix: use callback on react app init --- .../com/quietmobile/Backend/BackendWorker.kt | 44 +++---------------- .../Communication/CommunicationModule.java | 20 ++++++++- .../java/com/quietmobile/MainApplication.kt | 19 ++++++++ .../main/java/com/quietmobile/Utils/Const.kt | 3 -- .../main/java/com/quietmobile/Utils/Utils.kt | 2 + packages/mobile/src/App.tsx | 6 ++- packages/state-manager/src/constants.ts | 1 + 7 files changed, 51 insertions(+), 44 deletions(-) diff --git a/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/BackendWorker.kt b/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/BackendWorker.kt index acc28c1c89..57ea48a0ee 100644 --- a/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/BackendWorker.kt +++ b/packages/mobile/android/app/src/main/java/com/quietmobile/Backend/BackendWorker.kt @@ -9,14 +9,12 @@ import androidx.core.app.NotificationCompat import androidx.work.CoroutineWorker import androidx.work.ForegroundInfo import androidx.work.WorkerParameters -import com.google.gson.Gson import com.quietmobile.BuildConfig import com.quietmobile.Communication.CommunicationModule +import com.quietmobile.MainApplication import com.quietmobile.Notification.NotificationHandler import com.quietmobile.R -import com.quietmobile.Scheme.WebsocketConnectionPayload import com.quietmobile.Utils.Const -import com.quietmobile.Utils.Const.WEBSOCKET_CONNECTION_DELAY import com.quietmobile.Utils.Utils import com.quietmobile.Utils.isAppOnForeground import io.socket.client.IO @@ -98,9 +96,12 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters withContext(Dispatchers.IO) { // Get and store data port for usage in methods across the app - val dataPort = Utils.getOpenPort(11000) + val socketPort = Utils.getOpenPort(11000) val socketIOSecret = Utils.generateRandomString(20) + (applicationContext as MainApplication).setSocketPort(socketPort) + (applicationContext as MainApplication).setSocketIOSecret(socketIOSecret) + // Init nodejs project launch { nodeProject.init() @@ -108,25 +109,7 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters launch { notificationHandler = NotificationHandler(context) - subscribePushNotifications(dataPort, socketIOSecret) - } - - launch { - /* - * Wait for CommunicationModule to be initialized with reactContext - * (there's no callback we can use for that purpose). - * - * Code featured below suspends nothing but the websocket connection - * and it doesn't affect anything besides that. - * - * In any case, websocket won't connect until data server starts listening - */ - val intervals: Array = arrayOf(30000) - - for (interval in intervals) { - delay(interval) - startWebsocketConnection(dataPort, socketIOSecret) - } + subscribePushNotifications(socketPort, socketIOSecret) } val dataPath = Utils.createDirectory(context) @@ -143,7 +126,7 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters * https://github.com/TryQuiet/quiet/issues/2214 */ delay(500) - startNodeProjectWithArguments("bundle.cjs --torBinary $torBinary --dataPath $dataPath --dataPort $dataPort --platform $platform --socketIOSecret $socketIOSecret") + startNodeProjectWithArguments("bundle.cjs --torBinary $torBinary --dataPath $dataPath --dataPort $socketPort --platform $platform --socketIOSecret $socketIOSecret") } } @@ -159,8 +142,6 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters return Result.success() } - private external fun sendMessageToNodeChannel(channelName: String, message: String): Void - private external fun startNodeWithArguments( arguments: Array?, modulesPath: String? @@ -218,17 +199,6 @@ class BackendWorker(private val context: Context, workerParams: WorkerParameters notificationHandler.notify(message, username) } - private fun startWebsocketConnection(port: Int, socketIOSecret: String) { - Log.d("WEBSOCKET CONNECTION", "Starting on $port") - // Proceed only if data port is defined - val websocketConnectionPayload = WebsocketConnectionPayload(port, socketIOSecret) - CommunicationModule.handleIncomingEvents( - CommunicationModule.WEBSOCKET_CONNECTION_CHANNEL, - Gson().toJson(websocketConnectionPayload), - "" // Empty extras - ) - } - fun handleNodeMessages(channelName: String, msg: String?) { print("handle node message - channel name $channelName") print("handle node message - msg $msg") diff --git a/packages/mobile/android/app/src/main/java/com/quietmobile/Communication/CommunicationModule.java b/packages/mobile/android/app/src/main/java/com/quietmobile/Communication/CommunicationModule.java index e51ee1f125..ff186756b6 100644 --- a/packages/mobile/android/app/src/main/java/com/quietmobile/Communication/CommunicationModule.java +++ b/packages/mobile/android/app/src/main/java/com/quietmobile/Communication/CommunicationModule.java @@ -10,7 +10,10 @@ import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.core.RCTNativeAppEventEmitter; +import com.google.gson.Gson; +import com.quietmobile.MainApplication; import com.quietmobile.Notification.NotificationHandler; +import com.quietmobile.Scheme.WebsocketConnectionPayload; import androidx.annotation.NonNull; @@ -24,6 +27,8 @@ public class CommunicationModule extends ReactContextBaseJavaModule { + public static final String APP_READY_CHANNEL = "_APP_READY_"; + public static final String PUSH_NOTIFICATION_CHANNEL = "_PUSH_NOTIFICATION_"; public static final String WEBSOCKET_CONNECTION_CHANNEL = "_WEBSOCKET_CONNECTION_"; public static final String INIT_CHECK_CHANNEL = "_INIT_CHECK_"; @@ -48,14 +53,16 @@ public CommunicationModule(ReactApplicationContext reactContext) { } @ReactMethod - public static void handleIncomingEvents(String event, String payload, String extra) { + public static void handleIncomingEvents(String event, @Nullable String payload, @Nullable String extra) { switch (event) { + case APP_READY_CHANNEL: + startWebsocketConnection(); + break; case PUSH_NOTIFICATION_CHANNEL: String message = payload; String username = extra; notificationHandler.notify(message, username); break; - case WEBSOCKET_CONNECTION_CHANNEL: case INIT_CHECK_CHANNEL: case BACKEND_CLOSED_CHANNEL: passDataToReact(event, payload); @@ -88,6 +95,15 @@ private static void sendEvent(@Nullable WritableMap params) { } } + private static void startWebsocketConnection() { + Context context = reactContext.getApplicationContext(); + int port = ((MainApplication) context).getSocketPort(); + String socketIOSecret = ((MainApplication) context).getSocketIOSecret(); + + WebsocketConnectionPayload websocketConnectionPayload = new WebsocketConnectionPayload(port, socketIOSecret); + passDataToReact(WEBSOCKET_CONNECTION_CHANNEL, new Gson().toJson(websocketConnectionPayload)); + } + @ReactMethod private static void deleteBackendData() { Context context = reactContext.getApplicationContext(); diff --git a/packages/mobile/android/app/src/main/java/com/quietmobile/MainApplication.kt b/packages/mobile/android/app/src/main/java/com/quietmobile/MainApplication.kt index 901a31de38..6b29a6d01a 100644 --- a/packages/mobile/android/app/src/main/java/com/quietmobile/MainApplication.kt +++ b/packages/mobile/android/app/src/main/java/com/quietmobile/MainApplication.kt @@ -52,6 +52,25 @@ class MainApplication : Application(), ReactApplication { createNotificationChannel() } + private var socketPort: Int = 0 + private var socketIOSecret: String = "" + + fun getSocketPort(): Int { + return socketPort + } + + fun setSocketPort(value: Int) { + this.socketPort = value + } + + fun getSocketIOSecret(): String { + return socketIOSecret + } + + fun setSocketIOSecret(value: String) { + this.socketIOSecret = value + } + private fun createForegroundServiceNotificationChannel() { // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library diff --git a/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Const.kt b/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Const.kt index 2a73ae6a99..7254e6a0dc 100644 --- a/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Const.kt +++ b/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Const.kt @@ -22,7 +22,4 @@ object Const { const val NODEJS_PROJECT_DIR = "nodejs-project" const val NODEJS_BUILTIN_NATIVE_ASSETS_PREFIX = "nodejs-native-assets-" const val NODEJS_TRASH_DIR = "nodejs-project-trash" - - // Websocket - const val WEBSOCKET_CONNECTION_DELAY: Long = 5000 } diff --git a/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Utils.kt b/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Utils.kt index 29491191a0..7d38d92c2a 100644 --- a/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Utils.kt +++ b/packages/mobile/android/app/src/main/java/com/quietmobile/Utils/Utils.kt @@ -30,6 +30,7 @@ object Utils { return dataDirectory.absolutePath } + @JvmStatic fun generateRandomString(length: Int): String { val CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" val secureRandom = SecureRandom() @@ -43,6 +44,7 @@ object Utils { return randomString.toString() } + @JvmStatic suspend fun getOpenPort(starting: Int) = suspendCoroutine { continuation -> val port = checkPort(starting) continuation.resume(port) diff --git a/packages/mobile/src/App.tsx b/packages/mobile/src/App.tsx index f5128ddc39..9944888ea9 100644 --- a/packages/mobile/src/App.tsx +++ b/packages/mobile/src/App.tsx @@ -1,7 +1,9 @@ import React, { useEffect } from 'react' import { useDispatch } from 'react-redux' -import { LogBox, StatusBar } from 'react-native' +import { LogBox, NativeModules, StatusBar } from 'react-native' + +import { APP_READY_CHANNEL } from '@quiet/state-manager' import WebviewCrypto from 'react-native-webview-crypto' @@ -28,7 +30,6 @@ import { NavigationContainer } from '@react-navigation/native' import { createNativeStackNavigator } from '@react-navigation/native-stack' import { navigationRef } from './RootNavigation' -import { initActions } from './store/init/init.slice' import { navigationActions } from './store/navigation/navigation.slice' import { rootSaga } from './store/root.saga' @@ -76,6 +77,7 @@ function App(): JSX.Element { useEffect(() => { console.log('LAUNCHED APPLICATION: ', (Math.random() + 1).toString(36).substring(7)) + NativeModules.CommunicationModule.handleIncomingEvents(APP_READY_CHANNEL, null, null) }, []) return ( diff --git a/packages/state-manager/src/constants.ts b/packages/state-manager/src/constants.ts index a8f9ac9130..848b3409ca 100644 --- a/packages/state-manager/src/constants.ts +++ b/packages/state-manager/src/constants.ts @@ -1,5 +1,6 @@ export const AUTODOWNLOAD_SIZE_LIMIT = 20971520 // 20 MB +export const APP_READY_CHANNEL = '_APP_READY_' export const PUSH_NOTIFICATION_CHANNEL = '_PUSH_NOTIFICATION_' export const WEBSOCKET_CONNECTION_CHANNEL = '_WEBSOCKET_CONNECTION_' export const INIT_CHECK_CHANNEL = '_INIT_CHECK_'