diff --git a/apps/android/app/build.gradle b/apps/android/app/build.gradle index 082294a40..2b2cfe5d3 100644 --- a/apps/android/app/build.gradle +++ b/apps/android/app/build.gradle @@ -67,6 +67,7 @@ dependencies { implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' implementation 'androidx.activity:activity-compose:1.3.1' + implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.3.2' implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' diff --git a/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt index b6efb56ff..35893e846 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/SimplexApp.kt @@ -30,10 +30,12 @@ external fun chatRecvMsg(ctrl: ChatCtrl) : String class SimplexApp: Application() { private lateinit var controller: ChatController + lateinit var chatModel: ChatModel override fun onCreate() { super.onCreate() controller = ChatController(chatInit(applicationContext.filesDir.toString())) + chatModel = controller.chatModel GlobalScope.launch { withContext(Dispatchers.Main) { var user = controller.apiGetActiveUser() @@ -42,13 +44,6 @@ class SimplexApp: Application() { } } - val chatModel by lazy { - val m = ChatModel(controller) - controller.setModel(m) - controller.startReceiver() - m - } - companion object { lateinit var weakActivity: WeakReference init { diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index 2fd3de45f..306a4e8b6 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -1,8 +1,8 @@ package chat.simplex.app.model import androidx.compose.runtime.* +import kotlinx.datetime.* import kotlinx.serialization.* -import java.util.* class ChatModel(val controller: ChatController) { var currentUser = mutableStateOf(null) @@ -155,8 +155,7 @@ class Contact( val profile: Profile, val activeConn: Connection, val viaGroup: Long? = null, -// no serializer for type Date? -// val createdAt: Date + val createdAt: Instant ): SomeChat, NamedChat { override val chatType get() = ChatType.Direct override val id get() = "@$contactId" @@ -170,8 +169,8 @@ class Contact( contactId = 1, localDisplayName = "alice", profile = Profile.sampleData, - activeConn = Connection.sampleData -// createdAt = Date() + activeConn = Connection.sampleData, + createdAt = Clock.System.now() ) } } @@ -201,7 +200,7 @@ class GroupInfo ( val groupId: Long, override val localDisplayName: String, val groupProfile: GroupProfile, -// var createdAt: Date + val createdAt: Instant ): SomeChat, NamedChat { override val chatType get() = ChatType.Group override val id get() = "#$groupId" @@ -215,7 +214,7 @@ class GroupInfo ( groupId = 1, localDisplayName = "team", groupProfile = GroupProfile.sampleData, -// createdAt: Date() + createdAt = Clock.System.now() ) } } @@ -261,8 +260,8 @@ class GroupMember ( class UserContactRequest ( val contactRequestId: Long, override val localDisplayName: String, - val profile: Profile -// val createdAt: Date + val profile: Profile, + val createdAt: Instant ): SomeChat, NamedChat { override val chatType get() = ChatType.ContactRequest override val id get() = "<@$contactRequestId" @@ -276,7 +275,7 @@ class UserContactRequest ( contactRequestId = 1, localDisplayName = "alice", profile = Profile.sampleData, -// createdAt: Date() + createdAt = Clock.System.now() ) } } @@ -298,7 +297,7 @@ class ChatItem ( val isRcvNew: Boolean get() = meta.itemStatus is CIStatus.RcvNew companion object { - fun getSampleData(id: Long, dir: CIDirection, ts: Date, text: String,status: CIStatus = CIStatus.SndNew()) = + fun getSampleData(id: Long, dir: CIDirection, ts: Instant, text: String,status: CIStatus = CIStatus.SndNew()) = ChatItem( chatDir = dir, meta = CIMeta.getSample(id, ts, text, status), @@ -335,27 +334,27 @@ sealed class CIDirection { @Serializable class CIMeta ( val itemId: Long, -// val itemTs: Date, + val itemTs: Instant, val itemText: String, val itemStatus: CIStatus, -// val createdAt: Date + val createdAt: Instant ) { // val timestampText: String get() = getTimestampText(itemTs) companion object { - fun getSample(id: Long, ts: Date, text: String, status: CIStatus = CIStatus.SndNew()): CIMeta = + fun getSample(id: Long, ts: Instant, text: String, status: CIStatus = CIStatus.SndNew()): CIMeta = CIMeta( itemId = id, -// itemTs = ts, + itemTs = ts, itemText = text, itemStatus = status, -// createdAt = ts + createdAt = ts ) } } // TODO -fun getTimestampText(d: Date): String = "" +fun getTimestampText(d: Instant): String = "" @Serializable sealed class CIStatus { diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index 72b4f048a..d7ff0be22 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -18,20 +18,20 @@ import kotlin.concurrent.thread typealias ChatCtrl = Long open class ChatController(val ctrl: ChatCtrl) { - private var chatModel: ChatModel? = null - private val callbacks = mutableMapOf Unit>() + var chatModel: ChatModel - fun setModel(m: ChatModel) { - chatModel = m + init { + chatModel = ChatModel(this) } suspend fun startChat(u: User) { - chatModel!!.currentUser = mutableStateOf(u) + chatModel.currentUser = mutableStateOf(u) Log.d("SIMPLEX (user)", u.toString()) - apiStartChat() try { + apiStartChat() + chatModel.chats.addAll(apiGetChats()) + startReceiver() Log.d("SIMPLEX", "started chat") - chatModel!!.chats = apiGetChats().toMutableStateList() } catch(e: Error) { Log.d("SIMPLEX", "failed starting chat $e") throw e @@ -45,11 +45,7 @@ open class ChatController(val ctrl: ChatCtrl) { val json = chatRecvMsg(ctrl) Log.d("SIMPLEX chatRecvMsg: ", 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(System.currentTimeMillis(), r.resp)) + chatModel.terminalItems.add(TerminalItem.resp(r.resp)) } } } @@ -57,13 +53,15 @@ open class ChatController(val ctrl: ChatCtrl) { suspend fun sendCmd(cmd: CC): CR { return withContext(Dispatchers.IO) { val c = cmd.cmdString - chatModel?.terminalItems?.add(TerminalItem.Cmd(System.currentTimeMillis(), cmd)) + chatModel.terminalItems.add(TerminalItem.cmd(cmd)) val json = chatSendCmd(ctrl, c) Log.d("SIMPLEX", "sendCmd: ${cmd.cmdType}") - Log.d("SIMPLEX", "sendCmd response json $json") val r = APIResponse.decodeStr(json) Log.d("SIMPLEX", "sendCmd response type ${r.resp.responseType}") - chatModel?.terminalItems?.add(TerminalItem.Resp(System.currentTimeMillis(), r.resp)) + if (r.resp is CR.Response || r.resp is CR.Invalid) { + Log.d("SIMPLEX", "sendCmd response json $json") + } + chatModel.terminalItems.add(TerminalItem.resp(r.resp)) r.resp } } @@ -276,5 +274,8 @@ abstract class TerminalItem { TerminalItem.Cmd(0, CC.ShowActiveUser()), TerminalItem.Resp(1, CR.ActiveUser(User.sampleData)) ) + + fun cmd(c: CC) = TerminalItem.Cmd(System.currentTimeMillis(), c) + fun resp(r: CR) = TerminalItem.Resp(System.currentTimeMillis(), r) } }