mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
update android api to call haskell off main thread (#320)
This commit is contained in:
committed by
GitHub
parent
f8951b44fc
commit
d743804b1d
@@ -4,6 +4,10 @@ import android.app.Application
|
||||
import android.net.LocalServerSocket
|
||||
import android.util.Log
|
||||
import chat.simplex.app.model.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.lang.ref.WeakReference
|
||||
@@ -28,17 +32,21 @@ class SimplexApp: Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
controller = ChatController(chatInit(applicationContext.filesDir.toString()))
|
||||
var user = controller.apiGetActiveUser()
|
||||
if (user == null) {
|
||||
GlobalScope.launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
var user = controller.apiGetActiveUser()
|
||||
if (user == null) {
|
||||
// user = controller.apiCreateActiveUser(Profile("android", "Android test"))
|
||||
}
|
||||
Log.d("SIMPLEX (user)", user.toString())
|
||||
try {
|
||||
controller.apiStartChat()
|
||||
Log.d("SIMPLEX", "started chat")
|
||||
} catch(e: Error) {
|
||||
Log.d("SIMPLEX", "failed starting chat $e")
|
||||
}
|
||||
Log.d("SIMPLEX (user)", user.toString())
|
||||
try {
|
||||
controller.apiStartChat()
|
||||
Log.d("SIMPLEX", "started chat")
|
||||
} catch(e: Error) {
|
||||
Log.d("SIMPLEX", "failed starting chat $e")
|
||||
// throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,18 +3,20 @@ package chat.simplex.app.model
|
||||
import android.util.Log
|
||||
import chat.simplex.app.chatRecvMsg
|
||||
import chat.simplex.app.chatSendCmd
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import java.lang.Exception
|
||||
import java.util.*
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
typealias Controller = Long
|
||||
typealias ChatCtrl = Long
|
||||
|
||||
open class ChatController(val ctrl: Controller) {
|
||||
open class ChatController(val ctrl: ChatCtrl) {
|
||||
private var chatModel: ChatModel? = null
|
||||
private val callbacks = mutableMapOf<String, (Error?, CR?) -> Unit>()
|
||||
|
||||
fun setModel(m: ChatModel) {
|
||||
chatModel = m
|
||||
@@ -26,34 +28,46 @@ open class ChatController(val ctrl: Controller) {
|
||||
while(true) {
|
||||
val json = chatRecvMsg(ctrl)
|
||||
Log.d("SIMPLEX chatRecvMsg: ", json)
|
||||
chatModel?.terminalItems?.add(TerminalItem.Resp(APIResponse.decodeStr(json)))
|
||||
val r = APIResponse.decodeStr(json)
|
||||
if (r.corr != null) {
|
||||
val cb = callbacks[r.corr]
|
||||
if (cb != null) cb(null, r.resp)
|
||||
}
|
||||
chatModel?.terminalItems?.add(TerminalItem.Resp(r.resp))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun sendCmd(cmd: CC): CR {
|
||||
val c = cmd.cmdString
|
||||
val json = chatSendCmd(ctrl, c)
|
||||
Log.d("SIMPLEX", "sendCmd: $c")
|
||||
Log.d("SIMPLEX", "sendCmd response $json")
|
||||
chatModel?.terminalItems?.add(TerminalItem.Resp(APIResponse.decodeStr(json)))
|
||||
return APIResponse.decodeStr(json)
|
||||
suspend fun sendCmd(cmd: CC): CR {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val c = cmd.cmdString
|
||||
chatModel?.terminalItems?.add(TerminalItem.Cmd(cmd))
|
||||
val json = chatSendCmd(ctrl, c)
|
||||
Log.d("SIMPLEX", "sendCmd: $c")
|
||||
Log.d("SIMPLEX", "sendCmd response $json")
|
||||
val r = APIResponse.decodeStr(json)
|
||||
chatModel?.terminalItems?.add(TerminalItem.Resp(r.resp))
|
||||
r.resp
|
||||
}
|
||||
}
|
||||
|
||||
fun apiGetActiveUser(): User? {
|
||||
suspend fun apiGetActiveUser(): User? {
|
||||
val r = sendCmd(CC.ShowActiveUser())
|
||||
return if (r is CR.ActiveUser) r.user else null
|
||||
if (r is CR.ActiveUser) return r.user
|
||||
Log.d("SIMPLEX", "apiGetActiveUser: ${r.toString()}")
|
||||
return null
|
||||
}
|
||||
|
||||
fun apiCreateActiveUser(p: Profile): User {
|
||||
suspend fun apiCreateActiveUser(p: Profile): User {
|
||||
val r = sendCmd(CC.CreateActiveUser(p))
|
||||
if (r is CR.ActiveUser) return r.user
|
||||
throw Error("failed creating user: ${r.toString()}")
|
||||
Log.d("SIMPLEX", "apiCreateActiveUser: ${r.toString()}")
|
||||
throw Error("user not created ${r.toString()}")
|
||||
}
|
||||
|
||||
fun apiStartChat() {
|
||||
suspend fun apiStartChat() {
|
||||
val r = sendCmd(CC.StartChat())
|
||||
if (r is CR.ChatStarted) return
|
||||
if (r is CR.ChatStarted ) return
|
||||
throw Error("failed starting chat: ${r.toString()}")
|
||||
}
|
||||
|
||||
@@ -101,17 +115,20 @@ val json = Json {
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class APIResponse(val resp: CR) {
|
||||
class APIResponse(val resp: CR, val corr: String? = null) {
|
||||
companion object {
|
||||
fun decodeStr(str: String): CR {
|
||||
fun decodeStr(str: String): APIResponse {
|
||||
try {
|
||||
return json.decodeFromString<APIResponse>(str).resp
|
||||
return json.decodeFromString(str)
|
||||
} catch(e: Exception) {
|
||||
try {
|
||||
val data = json.parseToJsonElement(str)
|
||||
return CR.Response(data.jsonObject["resp"]!!.jsonObject["type"]?.toString() ?: "invalid", json.encodeToString(data))
|
||||
val data = json.parseToJsonElement(str).jsonObject
|
||||
return APIResponse(
|
||||
resp = CR.Response(data["resp"]!!.jsonObject["type"]?.toString() ?: "invalid", json.encodeToString(data)),
|
||||
corr = data["corr"]?.toString()
|
||||
)
|
||||
} catch(e: Exception) {
|
||||
return CR.Invalid(str)
|
||||
return APIResponse(CR.Invalid(str))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,6 +162,13 @@ sealed class CR {
|
||||
override val details get() = contact.toString()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@SerialName("cmdAccepted")
|
||||
class CmdAccepted(val corr: String): CR() {
|
||||
override val responseType get() = "cmdAccepted"
|
||||
override val details get() = "corrId: $corr"
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class Response(val type: String, val json: String): CR() {
|
||||
override val responseType get() = "* $type"
|
||||
@@ -168,7 +192,7 @@ abstract class TerminalItem {
|
||||
abstract val details: String
|
||||
|
||||
class Cmd(val cmd: CC): TerminalItem() {
|
||||
override val label get() = "> ${cmd.cmdString.substring(0, 30)}"
|
||||
override val label get() = "> ${cmd.cmdString}"
|
||||
override val details get() = cmd.cmdString
|
||||
}
|
||||
|
||||
|
||||
@@ -8,15 +8,16 @@ import androidx.compose.material.Text
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.navigation.*
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import chat.simplex.app.model.*
|
||||
import chat.simplex.app.ui.theme.SimpleXTheme
|
||||
import chat.simplex.app.views.chat.SendMsgView
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Composable
|
||||
fun TerminalPage(chatModel: ChatModel) {
|
||||
@@ -30,7 +31,7 @@ fun TerminalPage(chatModel: ChatModel) {
|
||||
type = NavType.StringType
|
||||
}
|
||||
)
|
||||
) { entry -> DetailView( entry.arguments?.getString("_details"), navController)}
|
||||
) { entry -> DetailView( entry.arguments?.getString("_details"), navController) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +40,13 @@ fun TerminalView(chatModel: ChatModel, navController: NavController) {
|
||||
Column {
|
||||
TerminalLog(chatModel.terminalItems, navController)
|
||||
SendMsgView(sendMessage = { cmd ->
|
||||
chatModel.controller.sendCmd(CC.Console(cmd))
|
||||
GlobalScope.launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
// show "in progress"
|
||||
chatModel.controller.sendCmd(CC.Console(cmd))
|
||||
// hide "in progress"
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -50,7 +57,7 @@ fun TerminalLog(terminalItems: List<TerminalItem>, navController: NavController)
|
||||
items(terminalItems) { item ->
|
||||
ClickableText(
|
||||
AnnotatedString(item.label),
|
||||
onClick={navController.navigate("details/${item.details}")}
|
||||
onClick = { navController.navigate("details/${item.details}") }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -60,11 +67,8 @@ fun TerminalLog(terminalItems: List<TerminalItem>, navController: NavController)
|
||||
fun DetailView(details: String?, navController: NavController){
|
||||
Column {
|
||||
Text("$details")
|
||||
|
||||
Button(
|
||||
onClick={navController.popBackStack()}
|
||||
)
|
||||
{Text("Back")}
|
||||
Button(onClick = { navController.popBackStack() }) {
|
||||
Text("Back")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user