diff --git a/app/schemas/com.greenart7c3.nostrsigner.database.HistoryDatabase/3.json b/app/schemas/com.greenart7c3.nostrsigner.database.HistoryDatabase/3.json new file mode 100644 index 00000000..3fb52b92 --- /dev/null +++ b/app/schemas/com.greenart7c3.nostrsigner.database.HistoryDatabase/3.json @@ -0,0 +1,111 @@ +{ + "formatVersion": 1, + "database": { + "version": 3, + "identityHash": "05375ac6ff0b7b2ab82afd950bea114c", + "entities": [ + { + "tableName": "history", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `pkKey` TEXT NOT NULL, `type` TEXT NOT NULL, `kind` INTEGER, `time` INTEGER NOT NULL, `accepted` INTEGER NOT NULL, `translatedPermission` TEXT NOT NULL, `content` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "pkKey", + "columnName": "pkKey", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "kind", + "columnName": "kind", + "affinity": "INTEGER" + }, + { + "fieldPath": "time", + "columnName": "time", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "accepted", + "columnName": "accepted", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "translatedPermission", + "columnName": "translatedPermission", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "content", + "columnName": "content", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [ + { + "name": "history_by_pk_key", + "unique": false, + "columnNames": [ + "pkKey" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `history_by_pk_key` ON `${TABLE_NAME}` (`pkKey`)" + }, + { + "name": "history_by_id", + "unique": false, + "columnNames": [ + "id" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `history_by_id` ON `${TABLE_NAME}` (`id`)" + }, + { + "name": "history_by_time", + "unique": false, + "columnNames": [ + "time" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `history_by_time` ON `${TABLE_NAME}` (`time`)" + }, + { + "name": "history_by_key_and_time", + "unique": false, + "columnNames": [ + "pkKey", + "time" + ], + "orders": [], + "createSql": "CREATE INDEX IF NOT EXISTS `history_by_key_and_time` ON `${TABLE_NAME}` (`pkKey`, `time`)" + } + ] + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '05375ac6ff0b7b2ab82afd950bea114c')" + ] + } +} \ No newline at end of file diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt b/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt index fb138b11..3c6eba50 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt @@ -111,6 +111,7 @@ class SignerProvider : ContentProvider() { null, TimeUtils.now(), false, + content = message, ), account.npub, ) @@ -133,6 +134,7 @@ class SignerProvider : ContentProvider() { null, TimeUtils.now(), true, + content = message, ), account.npub, ) @@ -209,6 +211,7 @@ class SignerProvider : ContentProvider() { event.kind, TimeUtils.now(), false, + content = event.toJson(), ), account.npub, ) @@ -233,6 +236,7 @@ class SignerProvider : ContentProvider() { event.kind, TimeUtils.now(), true, + content = signedEvent.toJson(), ), account.npub, ) @@ -309,6 +313,7 @@ class SignerProvider : ContentProvider() { null, TimeUtils.now(), false, + content = content, ), account.npub, ) @@ -366,6 +371,7 @@ class SignerProvider : ContentProvider() { null, TimeUtils.now(), true, + content = if (type == SignerType.NIP04_DECRYPT || type == SignerType.NIP44_DECRYPT || type == SignerType.DECRYPT_ZAP_EVENT) result else content, ), account.npub, ) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDatabase.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDatabase.kt index c8a4cd9e..f9909441 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDatabase.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDatabase.kt @@ -15,11 +15,17 @@ val migration_1_2 = object : Migration(1, 2) { } } +val migration_2_3 = object : Migration(2, 3) { + override fun migrate(db: SupportSQLiteDatabase) { + db.execSQL("ALTER TABLE history ADD COLUMN content TEXT NOT NULL DEFAULT ''") + } +} + @Database( entities = [ HistoryEntity::class, ], - version = 2, + version = 3, ) @TypeConverters(Converters::class) abstract class HistoryDatabase : RoomDatabase() { @@ -41,7 +47,7 @@ abstract class HistoryDatabase : RoomDatabase() { ) .setQueryExecutor(executor) .setTransactionExecutor(transactionExecutor) - .addMigrations(migration_1_2) + .addMigrations(migration_1_2, migration_2_3) .build() instance diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryEntity.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryEntity.kt index 40337fa2..f7ff9050 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryEntity.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryEntity.kt @@ -34,4 +34,5 @@ data class HistoryEntity( val time: Long, val accepted: Boolean, val translatedPermission: String = "", + val content: String = "", ) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/BunkerRequestUtils.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/BunkerRequestUtils.kt index ca792f06..243849b4 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/BunkerRequestUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/BunkerRequestUtils.kt @@ -364,6 +364,14 @@ object BunkerRequestUtils { kind, TimeUtils.now(), true, + content = when (type) { + SignerType.SIGN_EVENT, + SignerType.NIP04_DECRYPT, + SignerType.NIP44_DECRYPT, + SignerType.DECRYPT_ZAP_EVENT, + -> response + else -> getDataFromBunker(bunkerRequest.request) + }, ), account.npub, ) @@ -486,6 +494,7 @@ object BunkerRequestUtils { null, TimeUtils.now(), false, + content = getDataFromBunker(bunkerRequest.request), ), account.npub, ) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt index b02619be..992c3047 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt @@ -243,6 +243,7 @@ class EventNotificationConsumer(private val applicationContext: Context) { amberEvent?.kind, TimeUtils.now(), true, + content = amberEvent?.content ?: "", ), acc.npub, ) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt index 0d3403f1..cec35f36 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt @@ -766,6 +766,14 @@ object IntentUtils { kind, TimeUtils.now(), true, + content = when (intentData.type) { + SignerType.SIGN_EVENT -> event + SignerType.NIP04_DECRYPT, + SignerType.NIP44_DECRYPT, + SignerType.DECRYPT_ZAP_EVENT, + -> value + else -> intentData.data + }, ), account.npub, ) @@ -905,6 +913,7 @@ object IntentUtils { kind, TimeUtils.now(), false, + content = intentData.data, ), account.npub, ) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/ActivitiesScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/ActivitiesScreen.kt index b6cc67b7..1ee78b50 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/ActivitiesScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/ActivitiesScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.text.input.TextFieldState @@ -28,6 +29,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -43,14 +45,17 @@ import androidx.paging.PagingConfig import androidx.paging.compose.collectAsLazyPagingItems import com.greenart7c3.nostrsigner.Amber import com.greenart7c3.nostrsigner.R -import com.greenart7c3.nostrsigner.database.AppDatabase import com.greenart7c3.nostrsigner.database.HistoryEntity import com.greenart7c3.nostrsigner.models.Account import com.greenart7c3.nostrsigner.models.TimeUtils import com.greenart7c3.nostrsigner.models.supportedKindNumbers import com.greenart7c3.nostrsigner.service.ApplicationNameCache +import com.greenart7c3.nostrsigner.service.model.AmberEvent import com.greenart7c3.nostrsigner.service.toShortenHex +import com.greenart7c3.nostrsigner.ui.components.EventSection import com.greenart7c3.nostrsigner.ui.components.SimpleSearchBar +import com.greenart7c3.nostrsigner.ui.components.TagsSection +import com.greenart7c3.nostrsigner.ui.components.copyToClipboard import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -147,6 +152,15 @@ fun ActivitiesScreen( @Composable fun ActivityRow(activity: HistoryEntity, account: Account) { + val clipboard = LocalClipboard.current + val parsedEvent = remember(activity.content) { + if (activity.content.isBlank()) { + null + } else { + runCatching { AmberEvent.fromJson(activity.content).toEvent() }.getOrNull() + } + } + Column { Row( modifier = Modifier @@ -161,7 +175,6 @@ fun ActivityRow(activity: HistoryEntity, account: Account) { ApplicationName( key = activity.pkKey, accepted = activity.accepted, - database = Amber.instance.getDatabase(account.npub), account = account, ) @@ -172,6 +185,45 @@ fun ActivityRow(activity: HistoryEntity, account: Account) { color = if (activity.accepted) Color.Unspecified else Color.Gray, ) + if (parsedEvent != null) { + if (parsedEvent.content.isNotBlank()) { + Spacer(Modifier.height(4.dp)) + EventSection( + padding = 0.dp, + label = stringResource(R.string.content), + displayValue = parsedEvent.content, + onCopy = { copyToClipboard(clipboard, parsedEvent.content) }, + ) + } + if (parsedEvent.tags.isNotEmpty()) { + Spacer(Modifier.height(4.dp)) + TagsSection( + horizontalPadding = 0, + verticalPadding = 0, + label = stringResource(R.string.tags), + tags = parsedEvent.tags, + onCopy = { + copyToClipboard( + clipboard, + parsedEvent.tags.joinToString(separator = ", ") { + "[${it.joinToString(separator = ", ") { tag -> "\"$tag\"" }}]" + }, + ) + }, + ) + } + } else if (activity.content.isNotBlank()) { + Spacer(Modifier.height(4.dp)) + Text( + modifier = Modifier.padding(top = 2.dp), + text = activity.content, + maxLines = 3, + overflow = TextOverflow.Ellipsis, + fontSize = 14.sp, + color = if (activity.accepted) Color.Unspecified else Color.Gray, + ) + } + Text( modifier = Modifier.padding(top = 4.dp, bottom = 16.dp), text = TimeUtils.formatLongToCustomDateTimeWithSeconds(activity.time * 1000), @@ -197,7 +249,6 @@ fun ActivityRow(activity: HistoryEntity, account: Account) { fun ApplicationName( key: String, accepted: Boolean, - database: AppDatabase, account: Account, ) { var name by remember { mutableStateOf("") } @@ -205,7 +256,7 @@ fun ApplicationName( LaunchedEffect(Unit) { launch(Dispatchers.IO) { if (ApplicationNameCache.names["${account.npub.toShortenHex()}-$key"] == null) { - val app = database.dao().getByKey(key) + val app = Amber.instance.getDatabase(account.npub).dao().getByKey(key) app?.let { name = it.application.name ApplicationNameCache.names["${account.npub.toShortenHex()}-$key"] = it.application.name diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/BunkerMultiEventHomeScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/BunkerMultiEventHomeScreen.kt index 80b8965c..08f075f2 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/BunkerMultiEventHomeScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/BunkerMultiEventHomeScreen.kt @@ -397,6 +397,7 @@ fun BunkerMultiEventHomeScreen( kind = localEvent.kind, time = TimeUtils.now(), accepted = request.checked.value, + content = localEvent.toJson(), ), thisAccount.npub, ) @@ -450,6 +451,7 @@ fun BunkerMultiEventHomeScreen( null, TimeUtils.now(), request.checked.value, + content = request.request.params.first(), ), thisAccount.npub, ) @@ -494,6 +496,7 @@ fun BunkerMultiEventHomeScreen( null, TimeUtils.now(), request.checked.value, + content = "", ), thisAccount.npub, ) @@ -549,6 +552,11 @@ fun BunkerMultiEventHomeScreen( null, TimeUtils.now(), request.checked.value, + content = if (type == SignerType.NIP04_DECRYPT || type == SignerType.NIP44_DECRYPT || type == SignerType.DECRYPT_ZAP_EVENT) { + request.encryptedData?.result ?: "" + } else { + request.request.params.getOrElse(1) { "" } + }, ), thisAccount.npub, ) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/EventSection.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/EventSection.kt index 8e67d4dc..69b7eaba 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/EventSection.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/EventSection.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.greenart7c3.nostrsigner.R @@ -27,11 +28,12 @@ fun EventSection( label: String, displayValue: String, onCopy: () -> Unit, + padding: Dp = 16.dp, ) { Row( modifier = Modifier .fillMaxWidth() - .padding(16.dp), + .padding(padding), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.Top, ) { diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/IntentMultiEventHomeScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/IntentMultiEventHomeScreen.kt index 3cb6f8b9..7cbd77bb 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/IntentMultiEventHomeScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/IntentMultiEventHomeScreen.kt @@ -409,6 +409,7 @@ fun IntentMultiEventHomeScreen( localEvent.kind, TimeUtils.now(), intentData.checked.value, + content = localEvent.toJson(), ), thisAccount.npub, ) @@ -462,6 +463,7 @@ fun IntentMultiEventHomeScreen( null, TimeUtils.now(), intentData.checked.value, + content = intentData.data, ), thisAccount.npub, ) @@ -501,6 +503,11 @@ fun IntentMultiEventHomeScreen( null, TimeUtils.now(), intentData.checked.value, + content = if (intentData.type == SignerType.NIP04_DECRYPT || intentData.type == SignerType.NIP44_DECRYPT || intentData.type == SignerType.DECRYPT_ZAP_EVENT) { + intentData.encryptedData?.result ?: "" + } else { + intentData.data + }, ), thisAccount.npub, ) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/TagsSection.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/TagsSection.kt index fad62bf3..80d5cb6c 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/TagsSection.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/TagsSection.kt @@ -27,6 +27,8 @@ fun TagsSection( label: String, tags: Array>, onCopy: () -> Unit, + horizontalPadding: Int = 16, + verticalPadding: Int = 12, ) { val tagsToShow = tags.take(10) val moreCount = tags.size - 10 @@ -34,7 +36,7 @@ fun TagsSection( Row( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 12.dp), + .padding(horizontal = horizontalPadding.dp, vertical = verticalPadding.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.Top, ) {