wip
This commit is contained in:
+237
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Created by sweetbread
|
||||
* Copyright (c) 2025. All rights reserved.
|
||||
*/
|
||||
|
||||
package ru.risdeveau.pixeldragon.api
|
||||
|
||||
import android.util.Log
|
||||
import io.ktor.client.request.bearerAuth
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.client.request.parameter
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.contentType
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import org.json.JSONObject
|
||||
import ru.risdeveau.pixeldragon.AccountData.syncLastBatch
|
||||
import ru.risdeveau.pixeldragon.baseUrl
|
||||
import ru.risdeveau.pixeldragon.client
|
||||
import ru.risdeveau.pixeldragon.db.isConnected
|
||||
import ru.risdeveau.pixeldragon.token
|
||||
import ru.risdeveau.pixeldragon.ui.activity.ME
|
||||
import splitties.init.appCtx
|
||||
import java.io.File
|
||||
|
||||
|
||||
class MatrixSyncService {
|
||||
private val _syncState = MutableStateFlow<SyncState>(SyncState.Idle)
|
||||
val syncState: StateFlow<SyncState> = _syncState.asStateFlow()
|
||||
|
||||
private var syncJob: Job? = null
|
||||
// private var isInitialized = false
|
||||
//
|
||||
// fun initialize() {
|
||||
// isInitialized = true
|
||||
// }
|
||||
|
||||
fun startSync() {
|
||||
// if (!isInitialized)
|
||||
// throw IllegalStateException("Sync service not initialized")
|
||||
|
||||
if (syncJob?.isActive == true) return
|
||||
|
||||
syncJob = CoroutineScope(Dispatchers.IO).launch {
|
||||
if (syncLastBatch == "") {
|
||||
_syncState.value = SyncState.Syncing
|
||||
try {
|
||||
processSyncResponse(initialSync())
|
||||
_syncState.value = SyncState.Idle
|
||||
} catch (e: Exception) {
|
||||
_syncState.value = SyncState.Error(e.message)
|
||||
}
|
||||
}
|
||||
|
||||
// while (isActive) {
|
||||
// try {
|
||||
// val response = sync (
|
||||
// timeout = 30000,
|
||||
// filter = getFilter()
|
||||
// )
|
||||
//
|
||||
// processSyncResponse(response)
|
||||
//
|
||||
// } catch (e: Exception) {
|
||||
// Log.w("sync", e.message.toString())
|
||||
// delay(5000) // Wait before retry
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun stopSync() {
|
||||
syncJob?.cancel()
|
||||
_syncState.value = SyncState.Idle
|
||||
}
|
||||
|
||||
fun pauseSync() {
|
||||
// Called when app goes to background
|
||||
syncJob?.cancel()
|
||||
}
|
||||
|
||||
fun resumeSync() {
|
||||
// Called when app comes to foreground
|
||||
if (!isSyncActive()) {
|
||||
startSync()
|
||||
}
|
||||
}
|
||||
|
||||
fun isSyncActive(): Boolean = syncJob?.isActive == true
|
||||
|
||||
private suspend fun processSyncResponse(response: JSONObject) {
|
||||
// Log.d("syncResponse", response.toString(2))
|
||||
// val newMessages = mutableListOf<Message>()
|
||||
// val roomUpdates = mutableListOf<RoomUpdate>()
|
||||
//
|
||||
// response.rooms?.join?.forEach { (roomId, roomData) ->
|
||||
// // Process timeline events (messages)
|
||||
// roomData.timeline?.events?.forEach { event ->
|
||||
// val message = event.toMessage(roomId)
|
||||
// database.messageDao().insertMessage(message)
|
||||
// newMessages.add(message)
|
||||
// }
|
||||
//
|
||||
// // Process room state updates
|
||||
// roomData.state?.events?.forEach { event ->
|
||||
// when (event.type) {
|
||||
// "m.room.name", "m.room.avatar" -> {
|
||||
// roomUpdates.add(RoomUpdate(roomId, event.type, event.content))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Process ephemeral events (typing, receipts)
|
||||
// roomData.ephemeral?.events?.forEach { event ->
|
||||
// when (event.type) {
|
||||
// "m.typing" -> handleTypingEvent(roomId, event)
|
||||
// "m.receipt" -> handleReceiptEvent(roomId, event)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Notify the app about new data
|
||||
// if (newMessages.isNotEmpty()) {
|
||||
// _newMessages.emit(newMessages)
|
||||
// }
|
||||
// if (roomUpdates.isNotEmpty()) {
|
||||
// _roomUpdates.emit(roomUpdates)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
sealed class SyncState {
|
||||
object Idle : SyncState()
|
||||
object Syncing : SyncState()
|
||||
object Success : SyncState()
|
||||
data class Error(val message: String?) : SyncState()
|
||||
}
|
||||
|
||||
suspend fun sync(): JSONObject {
|
||||
|
||||
return JSONObject()
|
||||
|
||||
}
|
||||
|
||||
suspend fun initialSync(): JSONObject {
|
||||
val initialFilter = """
|
||||
{
|
||||
"room": {
|
||||
"state": {
|
||||
"types": [
|
||||
"m.room.name",
|
||||
"m.room.avatar",
|
||||
"m.room.canonical_alias",
|
||||
"m.room.encryption",
|
||||
"m.room.tombstone",
|
||||
"m.room.power_levels",
|
||||
"m.room.member"
|
||||
],
|
||||
"lazy_load_members": true,
|
||||
"not_types": []
|
||||
},
|
||||
"timeline": {
|
||||
"limit": 10,
|
||||
"types": ["m.room.message"],
|
||||
"not_types": [
|
||||
"m.room.name",
|
||||
"m.room.avatar",
|
||||
"m.room.canonical_alias",
|
||||
"m.room.encryption",
|
||||
"m.room.tombstone",
|
||||
"m.room.power_levels",
|
||||
"m.room.member",
|
||||
"m.call.*"
|
||||
]
|
||||
},
|
||||
"ephemeral": {
|
||||
"types": [],
|
||||
"not_types": ["m.typing", "m.receipt"]
|
||||
},
|
||||
"include_leave": false
|
||||
},
|
||||
"presence": {
|
||||
"types": [],
|
||||
"not_types": ["*"]
|
||||
},
|
||||
"event_format": "client",
|
||||
"event_fields": [
|
||||
"type",
|
||||
"content",
|
||||
"sender",
|
||||
"state_key",
|
||||
"room_id",
|
||||
"origin_server_ts"
|
||||
]
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
var r = client.post("$baseUrl/user/${ME!!.userId}/filter") {
|
||||
setBody(initialFilter)
|
||||
contentType(ContentType.Application.Json)
|
||||
bearerAuth(token)
|
||||
}
|
||||
|
||||
if (r.status != HttpStatusCode.OK)
|
||||
throw IllegalStateException("Failed to create a filter")
|
||||
val filterId = JSONObject(r.bodyAsText()).getString("filter_id")
|
||||
// val filterId = "vmNk"
|
||||
|
||||
/*val*/ r = client.get("$baseUrl/sync") {
|
||||
bearerAuth(token)
|
||||
url {
|
||||
parameter("filter", filterId)
|
||||
}
|
||||
}
|
||||
|
||||
if (r.status != HttpStatusCode.OK)
|
||||
throw IllegalStateException("Failed to sync")
|
||||
Log.d("initialSync", "Response size: ${r.bodyAsText().length}")
|
||||
|
||||
val json = JSONObject(r.bodyAsText())
|
||||
syncLastBatch = json.getString("next_batch")
|
||||
|
||||
return json
|
||||
}
|
||||
Reference in New Issue
Block a user