diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt index b14af9f..c7e5ef3 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/FlwtchWorker.kt @@ -36,18 +36,156 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : NotificationManager override suspend fun doWork(): Result { - val appDir = inputData.getString(KEY_APP_DIR) + val method = inputData.getString(KEY_METHOD) ?: return Result.failure() - val torPath = inputData.getString(KEY_TOR_PATH) + val args = inputData.getString(KEY_ARGS) ?: return Result.failure() + Log.i("FlwtchWorker.kt", "got call $method with args $args") // Mark the Worker as important val progress = "Trying to do a Flwtch" setForeground(createForegroundInfo(progress)) - download(appDir, torPath) + handleCwtch(method, args) return Result.success() } - private suspend fun download(appDir: String, torPath: String) { + private suspend fun handleCwtch(method: String, args: String) { + var a = JSONObject(args); + when (method) { + "Start" -> { + Log.i("FlwtchWorker.kt", "handleAppInfo Start") + val appDir = (a.get("appDir") as? String) ?: ""; + val torPath = (a.get("torPath") as? String) ?: "tor"; + Log.i("FlwtchWorker.kt", " appDir: '" + appDir + "' torPath: '" + torPath + "'") + + Cwtch.startCwtch(appDir, torPath) + + // infinite coroutine :) + while(true) { + val evt = MainActivity.AppbusEvent(Cwtch.getAppBusEvent()) + Log.i("FlwtchWorker.kt", "got appbusEvent: " + evt) + if (isStopped) { + Log.i("FlwtchWorker.kt", "COROUTINEWORKER DOT ISSTOPPED TRUE OH MY") + } + //todo: this elides evt.EventID which may be needed at some point? + val data = Data.Builder().putString("EventType", evt.EventType).putString("Data", evt.Data).build() + setProgress(data) + Thread.sleep(200) + } + } + "SelectProfile" -> { + val onion = (a.get("profile") as? String) ?: ""; + Cwtch.selectProfile(onion) + } + "CreateProfile" -> { + val nick = (a.get("nick") as? String) ?: ""; + val pass = (a.get("pass") as? String) ?: ""; + Cwtch.createProfile(nick, pass) + } + "LoadProfiles" -> { + val pass = (a.get("pass") as? String) ?: ""; + Cwtch.loadProfiles(pass) + } + "GetProfiles" -> Result.success(Data.Builder().putString("result", Cwtch.getProfiles()).build()) + // "ACNEvents" -> result.success(Cwtch.acnEvents()) + "ContactEvents" -> Result.success(Data.Builder().putString("result", Cwtch.contactEvents()).build()) + "NumMessages" -> { + val profile = (a.get("profile") as? String) ?: ""; + val handle = (a.get("contact") as? String) ?: ""; + Result.success(Data.Builder().putLong("result", Cwtch.numMessages(profile, handle)).build()) + } + "GetMessage" -> { + //Log.i("MainActivivity.kt", (a.get("index"))); + +// var args : HashMap = a.gets(); +// Log.i("FlwtchWorker.kt", args); + + + val profile = (a.get("profile") as? String) ?: ""; + val handle = (a.get("contact") as? String) ?: ""; + val indexI = a.getInt("index") ?: 0; + Log.i("FlwtchWorker.kt", "indexI = " + indexI) + Result.success(Data.Builder().putString("result", Cwtch.getMessage(profile, handle, indexI.toLong())).build()) + } + "GetMessages" -> { + val profile = (a.get("profile") as? String) ?: ""; + val handle = (a.get("contact") as? String) ?: ""; + val start = (a.get("start") as? Long) ?: 0; + val end = (a.get("end") as? Long) ?: 0; + Result.success(Data.Builder().putString("result", Cwtch.getMessages(profile, handle, start, end)).build()) + } + "AcceptContact" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val handle = (a.get("handle") as? String) ?: ""; + Cwtch.acceptContact(profile, handle); + } + "BlockContact" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val handle = (a.get("handle") as? String) ?: ""; + Cwtch.blockContact(profile, handle); + } + "DebugResetContact" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val handle = (a.get("handle") as? String) ?: ""; + Cwtch.debugResetContact(profile, handle); + } + "SendMessage" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val handle = (a.get("handle") as? String) ?: ""; + val message = (a.get("message") as? String) ?: ""; + Cwtch.sendMessage(profile, handle, message); + } + "SendInvitation" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val handle = (a.get("handle") as? String) ?: ""; + val target = (a.get("target") as? String) ?: ""; + Cwtch.sendInvitation(profile, handle, target); + } + "SendProfileEvent" -> { + val onion = (a.get("onion") as? String) ?: ""; + val jsonEvent = (a.get("jsonEvent") as? String) ?: ""; + Cwtch.sendProfileEvent(onion, jsonEvent); + } + "SendAppEvent" -> { + val jsonEvent = (a.get("jsonEvent") as? String) ?: ""; + Cwtch.sendAppEvent(jsonEvent); + } + "ResetTor" -> { + Cwtch.resetTor(); + } + "ImportBundle" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val bundle = (a.get("bundle") as? String) ?: ""; + Cwtch.importBundle(profile, bundle); + } + "SetGroupAttribute" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val groupHandle = (a.get("groupHandle") as? String) ?: ""; + val key = (a.get("key") as? String) ?: ""; + val value = (a.get("value") as? String) ?: ""; + Cwtch.setGroupAttribute(profile, groupHandle, key, value); + } + "CreateGroup" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val server = (a.get("server") as? String) ?: ""; + val groupName = (a.get("groupname") as? String) ?: ""; + Cwtch.createGroup(profile, server, groupName); + } + "LeaveGroup" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val groupHandle = (a.get("groupHandle") as? String) ?: ""; + Log.i("FlwtchWorker.kt", "LeaveGroup: need to recompile aar and uncomment this line")//todo + //Cwtch.leaveGroup(profile, groupHandle); + } + "RejectInvite" -> { + val profile = (a.get("ProfileOnion") as? String) ?: ""; + val groupHandle = (a.get("groupHandle") as? String) ?: ""; + Cwtch.rejectInvite(profile, groupHandle); + } + else -> Result.failure() + } + } + + private suspend fun launchCwtch(appDir: String, torPath: String) { Cwtch.startCwtch(appDir, torPath) // seperate coroutine to poll event bus and send to dart //Log.i("FlwtchWorker.kt", "got event chan: " + eventbus_chan + " launching corouting...") @@ -103,15 +241,15 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) : private fun createNotificationChannel(channelId: String, channelName: String): String{ val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE) - chan.lightColor = Color.BLUE + chan.lightColor = Color.MAGENTA chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE notificationManager.createNotificationChannel(chan) return channelId } companion object { - const val KEY_APP_DIR = "KEY_APP_DIR" - const val KEY_TOR_PATH = "KEY_TOR_PATH" + const val KEY_METHOD = "KEY_METHOD" + const val KEY_ARGS = "KEY_ARGS" } class AppbusEvent(json: String) : JSONObject(json) { diff --git a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt index e1aa843..e2dccaf 100644 --- a/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt +++ b/android/app/src/main/kotlin/im/cwtch/flwtch/MainActivity.kt @@ -6,11 +6,8 @@ import android.content.pm.PackageManager import android.os.Bundle import android.os.Looper import android.util.Log - -import androidx.work.Data -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.WorkManager -import androidx.work.WorkRequest +import androidx.lifecycle.Observer +import androidx.work.* import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -67,141 +64,40 @@ class MainActivity: FlutterActivity() { } private fun handleCwtch(@NonNull call: MethodCall, @NonNull result: Result) { - when (call.method) { - "Start" -> { - Log.i("MainActivity.kt", "handleAppInfo Start") - val appDir = (call.argument("appDir") as? String) ?: ""; - val torPath = (call.argument("torPath") as? String) ?: "tor"; - Log.i("MainActivity.kt", " appDir: '" + appDir + "' torPath: '" + torPath + "'") + val argmap: Map = call.arguments as Map + val data: Data = Data.Builder().putString(FlwtchWorker.KEY_METHOD, call.method).putString(FlwtchWorker.KEY_ARGS, JSONObject(argmap).toString()).build() + var tag = "" + if (call.method == "Start") { + tag = "cwtchEventBus" + } + val workRequest: WorkRequest = OneTimeWorkRequestBuilder().setInputData(data).addTag(tag).build() + WorkManager.getInstance(this).enqueue(workRequest) + if (call.method == "Start") { + val eventbus_chan = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS) + WorkManager.getInstance(applicationContext) + // requestId is the WorkRequest id + .getWorkInfosByTagLiveData("cwtchEventBus") + .observeForever(Observer> { listOfWorkInfo -> + if (listOfWorkInfo.isNullOrEmpty()) { + return@Observer + } - //Cwtch.startCwtch(appDir, torPath)// todo - val data: Data = Data.Builder().putString(FlwtchWorker.KEY_APP_DIR, appDir).putString(FlwtchWorker.KEY_TOR_PATH, torPath).build() - val uploadWorkRequest: WorkRequest = OneTimeWorkRequestBuilder().setInputData(data).build() - WorkManager.getInstance(this).enqueue(uploadWorkRequest) - - // seperate coroutine to poll event bus and send to dart -// val eventbus_chan = MethodChannel(flutterEngine?.dartExecutor?.binaryMessenger, CWTCH_EVENTBUS) -// Log.i("MainActivity.kt", "got event chan: " + eventbus_chan + " launching corouting...") -// GlobalScope.launch(Dispatchers.IO) { -// while(true) { -// val evt = AppbusEvent(Cwtch.getAppBusEvent()) -// Log.i("MainActivity.kt", "got appbusEvent: " + evt) -// launch(Dispatchers.Main) { -// //todo: this elides evt.EventID which may be needed at some point? -// eventbus_chan.invokeMethod(evt.EventType, evt.Data) -// } -// } -// } - } - "SelectProfile" -> { - val onion = (call.argument("profile") as? String) ?: ""; - Cwtch.selectProfile(onion) - } - "CreateProfile" -> { - val nick = (call.argument("nick") as? String) ?: ""; - val pass = (call.argument("pass") as? String) ?: ""; - Cwtch.createProfile(nick, pass) - } - "LoadProfiles" -> { - val pass = (call.argument("pass") as? String) ?: ""; - Cwtch.loadProfiles(pass) - } - "GetProfiles" -> result.success(Cwtch.getProfiles()) - // "ACNEvents" -> result.success(Cwtch.acnEvents()) - "ContactEvents" -> result.success(Cwtch.contactEvents()) - "NumMessages" -> { - val profile = (call.argument("profile") as? String) ?: ""; - val handle = (call.argument("contact") as? String) ?: ""; - result.success(Cwtch.numMessages(profile, handle)) - } - "GetMessage" -> { - //Log.i("MainActivivity.kt", (call.argument("index"))); - -// var args : HashMap = call.arguments(); -// Log.i("MainActivity.kt", args); - - - val profile = (call.argument("profile") as? String) ?: ""; - val handle = (call.argument("contact") as? String) ?: ""; - val indexI = call.argument("index") ?: 0; - Log.i("MainActivity.kt", "indexI = " + indexI) - result.success(Cwtch.getMessage(profile, handle, indexI.toLong())) - } - "GetMessages" -> { - val profile = (call.argument("profile") as? String) ?: ""; - val handle = (call.argument("contact") as? String) ?: ""; - val start = (call.argument("start") as? Long) ?: 0; - val end = (call.argument("end") as? Long) ?: 0; - result.success(Cwtch.getMessages(profile, handle, start, end)) - } - "AcceptContact" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val handle = (call.argument("handle") as? String) ?: ""; - Cwtch.acceptContact(profile, handle); - } - "BlockContact" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val handle = (call.argument("handle") as? String) ?: ""; - Cwtch.blockContact(profile, handle); - } - "DebugResetContact" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val handle = (call.argument("handle") as? String) ?: ""; - Cwtch.debugResetContact(profile, handle); - } - "SendMessage" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val handle = (call.argument("handle") as? String) ?: ""; - val message = (call.argument("message") as? String) ?: ""; - Cwtch.sendMessage(profile, handle, message); - } - "SendInvitation" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val handle = (call.argument("handle") as? String) ?: ""; - val target = (call.argument("target") as? String) ?: ""; - Cwtch.sendInvitation(profile, handle, target); - } - "SendProfileEvent" -> { - val onion = (call.argument("onion") as? String) ?: ""; - val jsonEvent = (call.argument("jsonEvent") as? String) ?: ""; - Cwtch.sendProfileEvent(onion, jsonEvent); - } - "SendAppEvent" -> { - val jsonEvent = (call.argument("jsonEvent") as? String) ?: ""; - Cwtch.sendAppEvent(jsonEvent); - } - "ResetTor" -> { - Cwtch.resetTor(); - } - "ImportBundle" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val bundle = (call.argument("bundle") as? String) ?: ""; - Cwtch.importBundle(profile, bundle); - } - "SetGroupAttribute" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val groupHandle = (call.argument("groupHandle") as? String) ?: ""; - val key = (call.argument("key") as? String) ?: ""; - val value = (call.argument("value") as? String) ?: ""; - Cwtch.setGroupAttribute(profile, groupHandle, key, value); - } - "CreateGroup" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val server = (call.argument("server") as? String) ?: ""; - val groupName = (call.argument("groupname") as? String) ?: ""; - Cwtch.createGroup(profile, server, groupName); - } - "LeaveGroup" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val groupHandle = (call.argument("groupHandle") as? String) ?: ""; - Cwtch.leaveGroup(profile, groupHandle); - } - "RejectInvite" -> { - val profile = (call.argument("ProfileOnion") as? String) ?: ""; - val groupHandle = (call.argument("groupHandle") as? String) ?: ""; - Cwtch.rejectInvite(profile, groupHandle); - } - else -> result.notImplemented() + for (workInfo in listOfWorkInfo) { + if (workInfo != null) { + val progress = workInfo.progress + val eventType = progress.getString("EventType") ?: "" + val eventData = progress.getString("Data") + Log.i("MainActivity.kt", "got event $progress $eventType $eventData") + try { + eventbus_chan.invokeMethod(eventType, eventData) + } catch (e: Exception) { + Log.i("MainActivity.kt", "event bus exception") + } + } else { + Log.i("MainActivity.kt", "got null workInfo") + } + } + }) } } diff --git a/android/build.gradle b/android/build.gradle index 361fb7a..5685ae0 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -27,6 +27,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { - delete rootProject.buildDir -} +//task clean(type: Delete) { +// delete rootProject.buildDir +//} diff --git a/pubspec.lock b/pubspec.lock index c7f8be5..58bca12 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -105,7 +105,7 @@ packages: name: file url: "https://pub.dartlang.org" source: hosted - version: "6.1.1" + version: "6.1.0" flutter: dependency: "direct main" description: flutter