mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-05 19:08:23 +00:00
created history screen
This commit is contained in:
@@ -4,7 +4,10 @@ import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.greenart7c3.nostrsigner.models.Account
|
||||
import com.greenart7c3.nostrsigner.models.History
|
||||
import com.greenart7c3.nostrsigner.service.KeyPair
|
||||
import com.vitorpamplona.quartz.encoders.hexToByteArray
|
||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||
@@ -25,6 +28,7 @@ private object PrefKeys {
|
||||
const val NOSTR_PRIVKEY = "nostr_privkey"
|
||||
const val NOSTR_PUBKEY = "nostr_pubkey"
|
||||
const val REMEMBER_APPS = "remember_apps"
|
||||
const val HISTORY = "history"
|
||||
const val ACCOUNT_NAME = "account_name"
|
||||
}
|
||||
|
||||
@@ -185,6 +189,8 @@ object LocalPreferences {
|
||||
val jsonObject = JSONObject(account.savedApps.toMap())
|
||||
putString(PrefKeys.REMEMBER_APPS, jsonObject.toString())
|
||||
putString(PrefKeys.ACCOUNT_NAME, account.name)
|
||||
val historyObject = Gson().toJson(account.history)
|
||||
putString(PrefKeys.HISTORY, historyObject)
|
||||
}.apply()
|
||||
}
|
||||
|
||||
@@ -204,6 +210,14 @@ object LocalPreferences {
|
||||
}
|
||||
}
|
||||
|
||||
fun loadHistory(npub: String?): MutableList<History> {
|
||||
encryptedPreferences(npub).apply {
|
||||
val historyJson = getString(PrefKeys.HISTORY, "[]") ?: "[]"
|
||||
val listType = object : TypeToken<List<History>>() {}.type
|
||||
return Gson().fromJson<List<History>>(historyJson, listType).toMutableList()
|
||||
}
|
||||
}
|
||||
|
||||
fun loadFromEncryptedStorage(npub: String?): Account? {
|
||||
encryptedPreferences(npub).apply {
|
||||
val pubKey = getString(PrefKeys.NOSTR_PUBKEY, null) ?: return null
|
||||
@@ -222,10 +236,15 @@ object LocalPreferences {
|
||||
}
|
||||
val name = getString(PrefKeys.ACCOUNT_NAME, "") ?: ""
|
||||
|
||||
val historyJson = getString(PrefKeys.HISTORY, "[]") ?: "[]"
|
||||
val listType = object : TypeToken<List<History>>() {}.type
|
||||
val history = Gson().fromJson<List<History>>(historyJson, listType).toMutableList()
|
||||
|
||||
return Account(
|
||||
keyPair = KeyPair(privKey = privKey?.hexToByteArray(), pubKey = pubKey.hexToByteArray()),
|
||||
name = name,
|
||||
savedApps = outputMap
|
||||
savedApps = outputMap,
|
||||
history = history
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ import android.content.ContentValues
|
||||
import android.database.Cursor
|
||||
import android.database.MatrixCursor
|
||||
import android.net.Uri
|
||||
import com.greenart7c3.nostrsigner.models.History
|
||||
import com.greenart7c3.nostrsigner.models.SignerType
|
||||
import com.greenart7c3.nostrsigner.models.TimeUtils
|
||||
import com.greenart7c3.nostrsigner.service.AmberUtils
|
||||
import com.greenart7c3.nostrsigner.service.model.AmberEvent
|
||||
import com.vitorpamplona.quartz.encoders.toNpub
|
||||
@@ -61,6 +63,10 @@ class SignerProvider : ContentProvider() {
|
||||
AmberEvent.fromJson(json),
|
||||
account.keyPair.privKey
|
||||
)
|
||||
|
||||
account.history.add(History(packageName, "SIGN_EVENT", TimeUtils.now()))
|
||||
LocalPreferences.saveToEncryptedStorage(account)
|
||||
|
||||
val cursor = MatrixCursor(arrayOf("signature", "event"))
|
||||
cursor.addRow(arrayOf(signedEvent.sig, signedEvent.toJson()))
|
||||
return cursor
|
||||
@@ -99,6 +105,10 @@ class SignerProvider : ContentProvider() {
|
||||
} catch (e: Exception) {
|
||||
"Could not decrypt the message"
|
||||
}
|
||||
|
||||
account.history.add(History(packageName, stringType, TimeUtils.now()))
|
||||
LocalPreferences.saveToEncryptedStorage(account)
|
||||
|
||||
if (type == SignerType.NIP04_ENCRYPT && result == "Could not decrypt the message") {
|
||||
return null
|
||||
} else {
|
||||
@@ -115,6 +125,9 @@ class SignerProvider : ContentProvider() {
|
||||
val isRemembered = account.savedApps[key] ?: false
|
||||
if (!isRemembered) return null
|
||||
|
||||
account.history.add(History(packageName, "GET_PUBLIC_KEY", TimeUtils.now()))
|
||||
LocalPreferences.saveToEncryptedStorage(account)
|
||||
|
||||
val cursor = MatrixCursor(arrayOf("signature"))
|
||||
cursor.addRow(arrayOf<Any>(account.keyPair.pubKey.toNpub()))
|
||||
return cursor
|
||||
|
||||
@@ -5,11 +5,18 @@ import androidx.compose.runtime.Stable
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.greenart7c3.nostrsigner.service.KeyPair
|
||||
|
||||
class History(
|
||||
val appName: String,
|
||||
val type: String,
|
||||
val time: Long
|
||||
)
|
||||
|
||||
@Stable
|
||||
class Account(
|
||||
val keyPair: KeyPair,
|
||||
var name: String,
|
||||
var savedApps: MutableMap<String, Boolean>
|
||||
var savedApps: MutableMap<String, Boolean>,
|
||||
var history: MutableList<History> = mutableListOf()
|
||||
) {
|
||||
val saveable: AccountLiveData = AccountLiveData(this)
|
||||
}
|
||||
|
||||
@@ -82,7 +82,8 @@ fun HomeScreen(
|
||||
sig,
|
||||
"",
|
||||
sig,
|
||||
it.callBackUrl
|
||||
it.callBackUrl,
|
||||
it.type
|
||||
)
|
||||
}
|
||||
return@LoginWithPubKey
|
||||
@@ -157,7 +158,8 @@ fun HomeScreen(
|
||||
result,
|
||||
it.id,
|
||||
result,
|
||||
it.callBackUrl
|
||||
it.callBackUrl,
|
||||
it.type
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -247,7 +249,8 @@ fun HomeScreen(
|
||||
resultEvent.toJson(),
|
||||
it.id,
|
||||
resultEvent.toJson(),
|
||||
it.callBackUrl
|
||||
it.callBackUrl,
|
||||
it.type
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -267,7 +270,8 @@ fun HomeScreen(
|
||||
signedEvent.toJson(),
|
||||
it.id,
|
||||
signedEvent.sig,
|
||||
it.callBackUrl
|
||||
it.callBackUrl,
|
||||
it.type
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,22 @@ import android.app.Activity.RESULT_OK
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.text.format.DateUtils
|
||||
import android.widget.Toast
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
@@ -35,6 +40,8 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.ClipboardManager
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.intl.Locale
|
||||
import androidx.compose.ui.text.toLowerCase
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
@@ -45,7 +52,10 @@ import androidx.navigation.navArgument
|
||||
import com.greenart7c3.nostrsigner.LocalPreferences
|
||||
import com.greenart7c3.nostrsigner.R
|
||||
import com.greenart7c3.nostrsigner.models.Account
|
||||
import com.greenart7c3.nostrsigner.models.History
|
||||
import com.greenart7c3.nostrsigner.models.IntentData
|
||||
import com.greenart7c3.nostrsigner.models.SignerType
|
||||
import com.greenart7c3.nostrsigner.models.TimeUtils
|
||||
import com.greenart7c3.nostrsigner.service.getAppCompatActivity
|
||||
import com.greenart7c3.nostrsigner.service.toShortenHex
|
||||
import com.greenart7c3.nostrsigner.ui.actions.AccountsBottomSheet
|
||||
@@ -66,13 +76,15 @@ fun sendResult(
|
||||
event: String,
|
||||
id: String,
|
||||
value: String,
|
||||
callBackUrl: String?
|
||||
callBackUrl: String?,
|
||||
type: SignerType
|
||||
) {
|
||||
val activity = context.getAppCompatActivity()
|
||||
if (packageName != null) {
|
||||
if (rememberChoice) {
|
||||
account.savedApps[key] = rememberChoice
|
||||
}
|
||||
account.history.add(History(packageName, type.toString(), TimeUtils.now()))
|
||||
LocalPreferences.saveToEncryptedStorage(account)
|
||||
val intent = Intent()
|
||||
intent.putExtra("signature", value)
|
||||
@@ -114,7 +126,7 @@ fun MainScreen(
|
||||
) {
|
||||
val navController = rememberNavController()
|
||||
val navBackStackEntry by navController.currentBackStackEntryAsState()
|
||||
val items = listOf(Route.Home, Route.Permissions, Route.Settings)
|
||||
val items = listOf(Route.Home, Route.Permissions, Route.History, Route.Settings)
|
||||
var shouldShowBottomSheet by remember { mutableStateOf(false) }
|
||||
|
||||
val sheetState = rememberModalBottomSheetState(
|
||||
@@ -237,6 +249,37 @@ fun MainScreen(
|
||||
}
|
||||
)
|
||||
|
||||
composable(
|
||||
Route.History.route,
|
||||
content = {
|
||||
val history = LocalPreferences.loadHistory(account.keyPair.pubKey.toNpub())
|
||||
LazyColumn(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(padding)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
items(history.size) {
|
||||
Card(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(4.dp)
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(8.dp)
|
||||
) {
|
||||
Text(history[it].appName)
|
||||
Text(history[it].type.toLowerCase(Locale.current))
|
||||
Text(timeAgoShort(history[it].time, "now"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
composable(
|
||||
Route.Permission.route,
|
||||
arguments = listOf(navArgument("packageName") { type = NavType.StringType }),
|
||||
@@ -255,3 +298,19 @@ fun MainScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun timeAgoShort(mills: Long?, stringForNow: String): String {
|
||||
if (mills == null) return " "
|
||||
|
||||
var humanReadable = DateUtils.getRelativeTimeSpanString(
|
||||
mills * 1000,
|
||||
System.currentTimeMillis(),
|
||||
DateUtils.MINUTE_IN_MILLIS,
|
||||
DateUtils.FORMAT_ABBREV_ALL
|
||||
).toString()
|
||||
if (humanReadable.startsWith("In") || humanReadable.startsWith("0")) {
|
||||
humanReadable = stringForNow
|
||||
}
|
||||
|
||||
return humanReadable
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.greenart7c3.nostrsigner.ui.navigation
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.History
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material.icons.filled.ViewList
|
||||
import androidx.compose.material.icons.outlined.History
|
||||
import androidx.compose.material.icons.outlined.Home
|
||||
import androidx.compose.material.icons.outlined.Settings
|
||||
import androidx.compose.material.icons.outlined.ViewList
|
||||
@@ -39,4 +41,10 @@ sealed class Route(
|
||||
icon = Icons.Outlined.ViewList,
|
||||
selectedIcon = Icons.Default.ViewList
|
||||
)
|
||||
|
||||
data object History : Route(
|
||||
route = "History",
|
||||
icon = Icons.Outlined.History,
|
||||
selectedIcon = Icons.Default.History
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user