Skip to content

Commit

Permalink
feat: android debounce backup state events to react native
Browse files Browse the repository at this point in the history
Also fixes the numeric representation of backup state timestamps. Apparently doubles are ok, but integers not. Before this fix the RN side would get wrong timestamp like `"lastQueued": -86628891`
  • Loading branch information
ovitrif committed Mar 1, 2024
1 parent 0254c3a commit 882c160
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 16 deletions.
41 changes: 40 additions & 1 deletion lib/android/src/main/java/com/reactnativeldk/Helpers.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package com.reactnativeldk
import android.os.Handler
import android.os.Looper
import com.facebook.react.bridge.*
import org.json.JSONObject
import org.ldk.enums.Currency
Expand All @@ -8,6 +10,7 @@ import java.io.File
import java.io.FileOutputStream
import java.net.URL
import java.nio.channels.Channels
import java.util.Date

fun handleResolve(promise: Promise, res: LdkCallbackResponses) {
if (res != LdkCallbackResponses.log_write_success) {
Expand Down Expand Up @@ -204,6 +207,22 @@ fun WritableMap.putHexString(key: String, bytes: ByteArray?) {
}
}

/**
* Adds a Date object into the map.
* If the date is not null, it is converted to a double representing the unix timestamp.
* If it's null, a null value is added to the map.
*
* @param key The key under which the date will be stored in the map.
* @param date The date to be stored in the map. Can be null.
*/
fun WritableMap.putDateOrNull(key: String, date: Date?) {
if (date != null) {
putDouble(key, date.time.toDouble())
} else {
putNull(key)
}
}

fun WritableArray.pushHexString(bytes: ByteArray) {
pushString(bytes.hexEncodedString())
}
Expand Down Expand Up @@ -502,4 +521,24 @@ fun mergeObj(obj1: JSONObject, obj2: HashMap<String, Any>): HashMap<String, Any>
}

return newObj
}
}

object UiThreadDebouncer {
private val pending = hashMapOf<String, Runnable>()
private val handler = Handler(Looper.getMainLooper())

/**
* Used to debounce an [action] function call to be executed after a delay on the main thread
*
* @param interval The delay in milliseconds after which the action will be executed. Default value is 250ms.
* @param key The unique identifier for the action to be debounced. If an action with the same key is already pending, it will be cancelled.
* @param action The function to be executed after the interval.
*/
fun debounce(interval: Long = 250, key: String, action: () -> Unit) {
pending[key]?.let { handler.removeCallbacks(it) }
val runnable = Runnable(action)
pending[key] = runnable

handler.postDelayed(runnable, interval)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.reactnativeldk.classes

import com.facebook.react.bridge.Arguments
import com.facebook.react.bridge.WritableMap
import com.reactnativeldk.UiThreadDebouncer
import com.reactnativeldk.EventTypes
import com.reactnativeldk.LdkEventEmitter
import com.reactnativeldk.hexEncodedString
import com.reactnativeldk.hexa
import com.reactnativeldk.putDateOrNull
import org.json.JSONObject
import org.ldk.structs.Result_StrSecp256k1ErrorZ.Result_StrSecp256k1ErrorZ_OK
import org.ldk.structs.UtilMethods
Expand Down Expand Up @@ -61,17 +64,9 @@ data class BackupFileState(
val encoded: WritableMap
get() {
val body = Arguments.createMap()
body.putInt("lastQueued", lastQueued.time.toInt())
if (lastPersisted != null) {
body.putInt("lastPersisted", lastPersisted!!.time.toInt())
} else {
body.putNull("lastPersisted")
}
if (lastFailed != null) {
body.putInt("lastFailed", lastFailed!!.time.toInt())
} else {
body.putNull("lastFailed")
}
body.putDouble("lastQueued", lastQueued.time.toDouble())
body.putDateOrNull("lastPersisted", lastPersisted)
body.putDateOrNull("lastFailed", lastFailed)
if (lastErrorMessage != null) {
body.putString("lastErrorMessage", lastErrorMessage)
} else {
Expand Down Expand Up @@ -592,10 +587,9 @@ class BackupClient {
body.putMap(key, state.encoded)
}

LdkEventEmitter.send(
EventTypes.backup_state_update,
body
)
UiThreadDebouncer.debounce(interval = 250, key = "backupStateUpdate") {
LdkEventEmitter.send(EventTypes.backup_state_update, body)
}

backupStateLock.unlock()
}
Expand Down

0 comments on commit 882c160

Please sign in to comment.