gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-android] 04/05: [wallet] Make observability log atomic and


From: gnunet
Subject: [taler-taler-android] 04/05: [wallet] Make observability log atomic and improve dialog UI
Date: Mon, 01 Apr 2024 14:34:29 +0200

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a commit to branch master
in repository taler-android.

commit e33bc723687328eec69e7580dd3e5698d4679167
Author: Iván Ávalos <avalos@disroot.org>
AuthorDate: Thu Mar 28 13:23:44 2024 -0600

    [wallet] Make observability log atomic and improve dialog UI
    
    bug 0008509
---
 .../main/java/net/taler/wallet/MainViewModel.kt    | 26 ++++++---
 .../net/taler/wallet/events/ObservabilityDialog.kt | 61 ++++++++++++++--------
 .../net/taler/wallet/events/ObservabilityEvent.kt  |  3 ++
 3 files changed, 61 insertions(+), 29 deletions(-)

diff --git a/wallet/src/main/java/net/taler/wallet/MainViewModel.kt 
b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
index b4da875..4b53d15 100644
--- a/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
+++ b/wallet/src/main/java/net/taler/wallet/MainViewModel.kt
@@ -24,6 +24,9 @@ import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.viewModelScope
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.getAndUpdate
 import kotlinx.coroutines.launch
 import kotlinx.serialization.encodeToString
 import net.taler.common.Amount
@@ -57,6 +60,11 @@ private val transactionNotifications = listOf(
     "transaction-state-transition",
 )
 
+private val observabilityNotifications = listOf(
+    "task-observability-event",
+    "request-observability-event",
+)
+
 class MainViewModel(
     app: Application,
 ) : AndroidViewModel(app), VersionReceiver, NotificationReceiver {
@@ -89,8 +97,8 @@ class MainViewModel(
     private val mTransactionsEvent = MutableLiveData<Event<ScopeInfo>>()
     val transactionsEvent: LiveData<Event<ScopeInfo>> = mTransactionsEvent
 
-    private val mObservabilityLog = 
MutableLiveData<List<ObservabilityEvent>>(emptyList())
-    val observabilityLog: LiveData<List<ObservabilityEvent>> = 
mObservabilityLog
+    private val mObservabilityLog = 
MutableStateFlow<List<ObservabilityEvent>>(emptyList())
+    val observabilityLog: StateFlow<List<ObservabilityEvent>> = 
mObservabilityLog
 
     private val mScanCodeEvent = MutableLiveData<Event<Boolean>>()
     val scanCodeEvent: LiveData<Event<Boolean>> = mScanCodeEvent
@@ -113,14 +121,16 @@ class MainViewModel(
             balanceManager.loadBalances()
         }
 
-        if (payload.type == "task-observability-event"
+        if (payload.type in observabilityNotifications
             && payload.event != null
             && devMode.value == true) {
-            val logs = mObservabilityLog.value
-                ?.takeLast(OBSERVABILITY_LIMIT)
-                ?.toMutableList() ?: mutableListOf()
-            logs.add(payload.event)
-            mObservabilityLog.postValue(logs)
+            mObservabilityLog.getAndUpdate { logs ->
+                logs.takeLast(OBSERVABILITY_LIMIT)
+                    .toMutableList().apply {
+                        add(payload.event)
+                    }
+
+            }
         }
 
         if (payload.type in transactionNotifications) 
viewModelScope.launch(Dispatchers.Main) {
diff --git 
a/wallet/src/main/java/net/taler/wallet/events/ObservabilityDialog.kt 
b/wallet/src/main/java/net/taler/wallet/events/ObservabilityDialog.kt
index eae5758..91733c3 100644
--- a/wallet/src/main/java/net/taler/wallet/events/ObservabilityDialog.kt
+++ b/wallet/src/main/java/net/taler/wallet/events/ObservabilityDialog.kt
@@ -20,31 +20,34 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ContentCopy
 import androidx.compose.material3.AlertDialog
 import androidx.compose.material3.Button
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
+import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.ListItem
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.material3.TextButton
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
-import androidx.compose.runtime.livedata.observeAsState
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.ComposeView
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.unit.dp
 import androidx.fragment.app.DialogFragment
 import androidx.fragment.app.activityViewModels
 import kotlinx.serialization.ExperimentalSerializationApi
@@ -52,8 +55,10 @@ import kotlinx.serialization.encodeToString
 import kotlinx.serialization.json.Json
 import net.taler.wallet.MainViewModel
 import net.taler.wallet.R
-import net.taler.wallet.compose.copyToClipBoard
+import net.taler.wallet.compose.CopyToClipboardButton
 import net.taler.wallet.events.ObservabilityDialog.Companion.json
+import java.time.format.DateTimeFormatter
+import java.time.format.FormatStyle
 
 class ObservabilityDialog: DialogFragment() {
     private val model: MainViewModel by activityViewModels()
@@ -64,8 +69,8 @@ class ObservabilityDialog: DialogFragment() {
         savedInstanceState: Bundle?
     ): View = ComposeView(requireContext()).apply {
         setContent {
-            val events by model.observabilityLog.observeAsState()
-            ObservabilityComposable(events?.reversed() ?: emptyList()) {
+            val events by model.observabilityLog.collectAsState()
+            ObservabilityComposable(events.reversed()) {
                 dismiss()
             }
         }
@@ -122,24 +127,38 @@ fun ObservabilityItem(
     val context = LocalContext.current
     val title = event.getTitle(context)
     val body = json.encodeToString(event.body)
+    val timestamp = DateTimeFormatter
+        .ofLocalizedDateTime(FormatStyle.MEDIUM)
+        .format(event.timestamp)
 
     ListItem(
         modifier = Modifier.fillMaxWidth(),
         headlineContent = { Text(title) },
+        overlineContent = { Text(timestamp) },
         supportingContent = if (!showJson) null else { ->
-            Text(
-                text = body,
-                fontFamily = FontFamily.Monospace,
-                style = MaterialTheme.typography.bodySmall,
-            )
-        },
-        trailingContent = if(!showJson) null else { ->
-            IconButton(onClick = {
-                copyToClipBoard(context, "Event", body)
-            }) {
-                Icon(
-                    Icons.Default.ContentCopy,
-                    contentDescription = stringResource(R.string.copy),
+            Column(
+                horizontalAlignment = Alignment.CenterHorizontally,
+            ) {
+                Box(
+                    modifier = Modifier.background(
+                        MaterialTheme.colorScheme.secondaryContainer,
+                        shape = MaterialTheme.shapes.small,
+                    )
+                ) {
+                    Text(
+                        modifier = Modifier
+                            .padding(10.dp)
+                            .fillMaxWidth(),
+                        text = body,
+                        fontFamily = FontFamily.Monospace,
+                        style = MaterialTheme.typography.bodySmall,
+                    )
+                }
+
+                CopyToClipboardButton(
+                    label = "Event",
+                    content = body,
+                    colors = ButtonDefaults.textButtonColors(),
                 )
             }
         },
diff --git a/wallet/src/main/java/net/taler/wallet/events/ObservabilityEvent.kt 
b/wallet/src/main/java/net/taler/wallet/events/ObservabilityEvent.kt
index cb710f7..a726045 100644
--- a/wallet/src/main/java/net/taler/wallet/events/ObservabilityEvent.kt
+++ b/wallet/src/main/java/net/taler/wallet/events/ObservabilityEvent.kt
@@ -28,11 +28,13 @@ import kotlinx.serialization.json.JsonObject
 import kotlinx.serialization.json.jsonObject
 import kotlinx.serialization.json.jsonPrimitive
 import net.taler.wallet.R
+import java.time.LocalDateTime
 
 
 @Serializable(with = ObservabilityEventSerializer::class)
 class ObservabilityEvent(
     val body: JsonObject,
+    val timestamp: LocalDateTime,
     val type: String,
 ) {
 
@@ -78,6 +80,7 @@ class ObservabilityEventSerializer: 
KSerializer<ObservabilityEvent> {
 
         return ObservabilityEvent(
             body = jsonObject,
+            timestamp = LocalDateTime.now(),
             type = type,
         )
     }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]