diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt b/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt index db9173d..f62cd34 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/SignerProvider.kt @@ -17,8 +17,14 @@ import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.encoders.toNpub import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.LnZapRequestEvent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch class SignerProvider : ContentProvider() { + val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) + override fun delete( uri: Uri, selection: String?, @@ -68,16 +74,18 @@ class SignerProvider : ContentProvider() { ) val isRemembered = if (signPolicy == 2) true else permission?.acceptable ?: return null if (!isRemembered) { - database.applicationDao().addHistory( - HistoryEntity( - 0, - sortOrder ?: packageName, - uri.toString().replace("content://$appId.", ""), - null, - TimeUtils.now(), - false, - ), - ) + scope.launch { + database.applicationDao().addHistory( + HistoryEntity( + 0, + sortOrder ?: packageName, + uri.toString().replace("content://$appId.", ""), + null, + TimeUtils.now(), + false, + ), + ) + } val cursor = MatrixCursor(arrayOf("rejected")).also { it.addRow(arrayOf("true")) @@ -87,16 +95,18 @@ class SignerProvider : ContentProvider() { } val result = CryptoUtils.signString(message, account.signer.keyPair.privKey!!).toHexKey() - database.applicationDao().addHistory( - HistoryEntity( - 0, - sortOrder ?: packageName, - "SIGN_MESSAGE", - null, - TimeUtils.now(), - true, - ), - ) + scope.launch { + database.applicationDao().addHistory( + HistoryEntity( + 0, + sortOrder ?: packageName, + "SIGN_MESSAGE", + null, + TimeUtils.now(), + true, + ), + ) + } val localCursor = MatrixCursor(arrayOf("signature", "event", "result")).also { it.addRow(arrayOf(result, result, result)) @@ -145,16 +155,18 @@ class SignerProvider : ContentProvider() { val signPolicy = database.applicationDao().getSignPolicy(sortOrder ?: packageName) val isRemembered = if (signPolicy == 2) true else permission?.acceptable ?: return null if (!isRemembered) { - database.applicationDao().addHistory( - HistoryEntity( - 0, - sortOrder ?: packageName, - uri.toString().replace("content://$appId.", ""), - event.kind, - TimeUtils.now(), - false, - ), - ) + scope.launch { + database.applicationDao().addHistory( + HistoryEntity( + 0, + sortOrder ?: packageName, + uri.toString().replace("content://$appId.", ""), + event.kind, + TimeUtils.now(), + false, + ), + ) + } val cursor = MatrixCursor(arrayOf("rejected")).also { @@ -168,6 +180,22 @@ class SignerProvider : ContentProvider() { if (signedEvent == null) { Log.d("SignerProvider", "Failed to sign event from $packageName") + scope.launch { + database.applicationDao().addHistory( + HistoryEntity( + 0, + sortOrder ?: packageName, + "SIGN_EVENT", + event.kind, + TimeUtils.now(), + false, + ), + ) + } + return null + } + + scope.launch { database.applicationDao().addHistory( HistoryEntity( 0, @@ -175,23 +203,11 @@ class SignerProvider : ContentProvider() { "SIGN_EVENT", event.kind, TimeUtils.now(), - false, + true, ), ) - return null } - database.applicationDao().addHistory( - HistoryEntity( - 0, - sortOrder ?: packageName, - "SIGN_EVENT", - event.kind, - TimeUtils.now(), - true, - ), - ) - val cursor = MatrixCursor(arrayOf("signature", "event", "result")).also { val signature = @@ -254,16 +270,18 @@ class SignerProvider : ContentProvider() { val signPolicy = database.applicationDao().getSignPolicy(sortOrder ?: packageName) val isRemembered = if (signPolicy == 2) true else permission?.acceptable ?: return null if (!isRemembered) { - database.applicationDao().addHistory( - HistoryEntity( - 0, - sortOrder ?: packageName, - uri.toString().replace("content://$appId.", ""), - null, - TimeUtils.now(), - false, - ), - ) + scope.launch { + database.applicationDao().addHistory( + HistoryEntity( + 0, + sortOrder ?: packageName, + uri.toString().replace("content://$appId.", ""), + null, + TimeUtils.now(), + false, + ), + ) + } val cursor = MatrixCursor(arrayOf("rejected")).also { @@ -295,16 +313,18 @@ class SignerProvider : ContentProvider() { "Could not decrypt the message" } - database.applicationDao().addHistory( - HistoryEntity( - 0, - sortOrder ?: packageName, - uri.toString().replace("content://$appId.", ""), - null, - TimeUtils.now(), - true, - ), - ) + scope.launch { + database.applicationDao().addHistory( + HistoryEntity( + 0, + sortOrder ?: packageName, + uri.toString().replace("content://$appId.", ""), + null, + TimeUtils.now(), + true, + ), + ) + } val cursor = MatrixCursor(arrayOf("signature", "event", "result")) cursor.addRow(arrayOf(result, result, result)) @@ -326,6 +346,28 @@ class SignerProvider : ContentProvider() { val signPolicy = database.applicationDao().getSignPolicy(sortOrder ?: packageName) val isRemembered = if (signPolicy == 2) true else permission?.acceptable ?: return null if (!isRemembered) { + scope.launch { + database.applicationDao().addHistory( + HistoryEntity( + 0, + sortOrder ?: packageName, + uri.toString().replace("content://$appId.", ""), + null, + TimeUtils.now(), + false, + ), + ) + } + + val cursor = + MatrixCursor(arrayOf("rejected")).also { + it.addRow(arrayOf("true")) + } + + return cursor + } + + scope.launch { database.applicationDao().addHistory( HistoryEntity( 0, @@ -333,29 +375,11 @@ class SignerProvider : ContentProvider() { uri.toString().replace("content://$appId.", ""), null, TimeUtils.now(), - false, + true, ), ) - - val cursor = - MatrixCursor(arrayOf("rejected")).also { - it.addRow(arrayOf("true")) - } - - return cursor } - database.applicationDao().addHistory( - HistoryEntity( - 0, - sortOrder ?: packageName, - uri.toString().replace("content://$appId.", ""), - null, - TimeUtils.now(), - true, - ), - ) - val cursor = MatrixCursor(arrayOf("signature", "result")) val result = if (sortOrder == null) account.signer.keyPair.pubKey.toNpub() else account.signer.keyPair.pubKey.toHexKey() cursor.addRow(arrayOf(result, result)) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt index 187ce4d..13ad960 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt @@ -18,17 +18,17 @@ interface ApplicationDao { fun getLatestNotification(): Long? @Query("SELECT * FROM notification WHERE eventId = :eventId") - fun getNotification(eventId: String): NotificationEntity? + suspend fun getNotification(eventId: String): NotificationEntity? @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insertNotification(notificationEntity: NotificationEntity): Long? + suspend fun insertNotification(notificationEntity: NotificationEntity): Long? @Query("SELECT * FROM application where pubKey = :pubKey order by name") - fun getAll(pubKey: String): List + suspend fun getAll(pubKey: String): List @Query("SELECT * FROM application where isConnected = 0") @Transaction - fun getAllNotConnected(): List + suspend fun getAllNotConnected(): List @Query( """ @@ -44,14 +44,14 @@ interface ApplicationDao { @Query("SELECT * FROM application WHERE `key` = :key") @Transaction - fun getByKey(key: String): ApplicationWithPermissions? + suspend fun getByKey(key: String): ApplicationWithPermissions? @Query("SELECT * FROM application WHERE secret = :secret") @Transaction - fun getBySecret(secret: String): ApplicationWithPermissions? + suspend fun getBySecret(secret: String): ApplicationWithPermissions? @Query("SELECT * FROM applicationPermission WHERE pkKey = :key") - fun getAllByKey(key: String): List + suspend fun getAllByKey(key: String): List @Query("SELECT * FROM application") @Transaction @@ -71,17 +71,12 @@ interface ApplicationDao { ): ApplicationPermissionsEntity? @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insertApplication(event: ApplicationEntity): Long? - - @Query("UPDATE application SET name = :name WHERE `key` = :key") - fun changeApplicationName( - key: String, - name: String, - ) + @Transaction + suspend fun insertApplication(event: ApplicationEntity): Long? @Insert(onConflict = OnConflictStrategy.REPLACE) @Transaction - fun insertPermissions(permissions: List): List? { + suspend fun insertPermissions(permissions: List): List? { permissions.forEach { if (it.kind != null) { deletePermissions(it.pkKey, it.type, it.kind) @@ -94,22 +89,22 @@ interface ApplicationDao { @Insert(onConflict = OnConflictStrategy.IGNORE) @Transaction - fun insertPermissions2(permissions: List): List? + suspend fun insertPermissions2(permissions: List): List? @Query("DELETE FROM applicationPermission WHERE pkKey = :key") @Transaction - fun deletePermissions(key: String) + suspend fun deletePermissions(key: String) @Query("DELETE FROM applicationPermission WHERE pkKey = :key AND type = :type") @Transaction - fun deletePermissions( + suspend fun deletePermissions( key: String, type: String, ) @Query("DELETE FROM applicationPermission WHERE pkKey = :key AND type = :type and kind = :kind") @Transaction - fun deletePermissions( + suspend fun deletePermissions( key: String, type: String, kind: Int, @@ -117,7 +112,7 @@ interface ApplicationDao { @Insert(onConflict = OnConflictStrategy.IGNORE) @Transaction - fun insertApplicationWithPermissions(application: ApplicationWithPermissions) { + suspend fun insertApplicationWithPermissions(application: ApplicationWithPermissions) { deletePermissions(application.application.key) insertApplication(application.application)?.let { application.permissions.forEach { @@ -130,18 +125,19 @@ interface ApplicationDao { @Delete @Transaction - fun delete(entity: ApplicationEntity) + suspend fun delete(entity: ApplicationEntity) @Query("DELETE FROM application WHERE `key` = :key") @Transaction - fun delete(key: String) + suspend fun delete(key: String) @Insert(onConflict = OnConflictStrategy.REPLACE) - fun innerAddHistory(entity: HistoryEntity) + @Transaction + suspend fun innerAddHistory(entity: HistoryEntity) @Insert(onConflict = OnConflictStrategy.IGNORE) @Transaction - fun addHistory(entity: HistoryEntity) { + suspend fun addHistory(entity: HistoryEntity) { try { innerAddHistory(entity) } catch (e: Exception) { @@ -153,7 +149,8 @@ interface ApplicationDao { fun getAllHistory(pk: String): Flow> @Insert - fun insertLog(logEntity: LogEntity) + @Transaction + suspend fun insertLog(logEntity: LogEntity) @Query("SELECT * FROM amber_log ORDER BY time DESC") fun getLogs(): Flow> @@ -162,8 +159,10 @@ interface ApplicationDao { fun getLogsByUrl(url: String): Flow> @Query("DELETE FROM amber_log") - fun clearLogs() + @Transaction + suspend fun clearLogs() @Delete - fun deletePermission(permission: ApplicationPermissionsEntity) + @Transaction + suspend fun deletePermission(permission: ApplicationPermissionsEntity) } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/relays/AmberClientListener.kt b/app/src/main/java/com/greenart7c3/nostrsigner/relays/AmberClientListener.kt index e98b8e7..b42f6c2 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/relays/AmberClientListener.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/relays/AmberClientListener.kt @@ -10,6 +10,10 @@ import com.vitorpamplona.ammolite.relays.Client import com.vitorpamplona.ammolite.relays.Relay import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.EventInterface +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch @SuppressLint("StaticFieldLeak") object AmberListenerSingleton { @@ -32,45 +36,52 @@ class AmberClientListener( val context: Context, val accountStateViewModel: AccountStateViewModel?, ) : Client.Listener { + val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) override fun onAuth(relay: Relay, challenge: String) { - LocalPreferences.currentAccount(context)?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onAuth", - message = "Authenticating", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(context)?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onAuth", + message = "Authenticating", + time = System.currentTimeMillis(), + ), + ) + } } } override fun onBeforeSend(relay: Relay, event: EventInterface) { - LocalPreferences.currentAccount(context)?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onBeforeSend", - message = "Sending event ${event.id()}", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(context)?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onBeforeSend", + message = "Sending event ${event.id()}", + time = System.currentTimeMillis(), + ), + ) + } } } override fun onSend(relay: Relay, msg: String, success: Boolean) { - LocalPreferences.currentAccount(context)?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onSend", - message = "message: $msg success: $success", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(context)?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onSend", + message = "message: $msg success: $success", + time = System.currentTimeMillis(), + ), + ) + } } if (!success) { if (msg.isNotBlank()) { @@ -82,16 +93,18 @@ class AmberClientListener( } override fun onSendResponse(eventId: String, success: Boolean, message: String, relay: Relay) { - LocalPreferences.currentAccount(context)?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onSendResponse", - message = "Success: $success Message: $message", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(context)?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onSendResponse", + message = "Success: $success Message: $message", + time = System.currentTimeMillis(), + ), + ) + } } if (!success) { @@ -101,60 +114,68 @@ class AmberClientListener( override fun onError(error: Error, subscriptionId: String, relay: Relay) { if (error.message?.trim()?.equals("Relay sent notice:") == true) return - LocalPreferences.currentAccount(context)?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onError", - message = "${error.message}", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(context)?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onError", + message = "${error.message}", + time = System.currentTimeMillis(), + ), + ) + } } accountStateViewModel?.toast("Error", error.message ?: "Unknown error") } override fun onEvent(event: Event, subscriptionId: String, relay: Relay, afterEOSE: Boolean) { - LocalPreferences.currentAccount(context)?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onEvent", - message = "Received event ${event.id()} from subscription $subscriptionId afterEOSE: $afterEOSE", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(context)?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onEvent", + message = "Received event ${event.id()} from subscription $subscriptionId afterEOSE: $afterEOSE", + time = System.currentTimeMillis(), + ), + ) + } } } override fun onNotify(relay: Relay, description: String) { - LocalPreferences.currentAccount(context)?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onNotify", - message = description, - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(context)?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onNotify", + message = description, + time = System.currentTimeMillis(), + ), + ) + } } } override fun onRelayStateChange(type: Relay.StateType, relay: Relay, subscriptionId: String?) { - LocalPreferences.currentAccount(context)?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onRelayStateChange", - message = type.name, - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(context)?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onRelayStateChange", + message = type.name, + time = System.currentTimeMillis(), + ), + ) + } } } } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/AmberUtils.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/AmberUtils.kt index 9353211..3c9a5c1 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/AmberUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/AmberUtils.kt @@ -152,7 +152,7 @@ object AmberUtils { ) } - fun acceptOrRejectPermission( + suspend fun acceptOrRejectPermission( application: ApplicationWithPermissions, key: String, intentData: IntentData, 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 639738b..f15ebd8 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt @@ -23,7 +23,6 @@ package com.greenart7c3.nostrsigner.service import android.app.NotificationManager import android.content.Context import android.net.Uri -import android.util.Log import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.toLowerCase import androidx.core.content.ContextCompat @@ -33,6 +32,7 @@ import com.greenart7c3.nostrsigner.NostrSigner import com.greenart7c3.nostrsigner.R import com.greenart7c3.nostrsigner.database.ApplicationWithPermissions import com.greenart7c3.nostrsigner.database.HistoryEntity +import com.greenart7c3.nostrsigner.database.LogEntity import com.greenart7c3.nostrsigner.database.NotificationEntity import com.greenart7c3.nostrsigner.models.Account import com.greenart7c3.nostrsigner.models.BunkerRequest @@ -47,6 +47,7 @@ import com.vitorpamplona.quartz.crypto.nip04.Nip04 import com.vitorpamplona.quartz.encoders.Hex import com.vitorpamplona.quartz.encoders.toNpub import com.vitorpamplona.quartz.events.Event +import kotlinx.coroutines.launch class EventNotificationConsumer(private val applicationContext: Context) { @@ -69,16 +70,20 @@ class EventNotificationConsumer(private val applicationContext: Context) { if (event.content.isEmpty()) return if (Nip04.isNIP04(event.content)) { acc.signer.nip04Decrypt(event.content, event.pubKey) { - notify(event, acc, it, EncryptionType.NIP04) + NostrSigner.getInstance().applicationIOScope.launch { + notify(event, acc, it, EncryptionType.NIP04) + } } } else { acc.signer.nip44Decrypt(event.content, event.pubKey) { - notify(event, acc, it, EncryptionType.NIP44) + NostrSigner.getInstance().applicationIOScope.launch { + notify(event, acc, it, EncryptionType.NIP44) + } } } } - private fun notify( + private suspend fun notify( event: Event, acc: Account, request: String, @@ -88,11 +93,25 @@ class EventNotificationConsumer(private val applicationContext: Context) { val notification = dao.getNotification(event.id) if (notification != null) return dao.insertNotification(NotificationEntity(0, event.id(), event.createdAt)) + dao.insertLog( + LogEntity( + 0, + "nostrsigner", + "bunker request json", + event.toJson(), + TimeUtils.now(), + ), + ) - if (BuildConfig.DEBUG) { - Log.d("bunker", event.toJson()) - Log.d("bunker", request) - } + dao.insertLog( + LogEntity( + 0, + "nostrsigner", + "bunker request", + request, + TimeUtils.now(), + ), + ) val bunkerRequest = BunkerRequest.mapper.readValue(request, BunkerRequest::class.java) bunkerRequest.localKey = event.pubKey @@ -118,17 +137,19 @@ class EventNotificationConsumer(private val applicationContext: Context) { val permission = database.applicationDao().getByKey(bunkerRequest.localKey) if (permission != null && ((permission.application.secret != permission.application.key && permission.application.useSecret) || permission.application.isConnected) && type == SignerType.CONNECT) { - database.applicationDao() - .addHistory( - HistoryEntity( - 0, - permission.application.key, - type.toString().toLowerCase(Locale.current), - amberEvent?.kind, - TimeUtils.now(), - true, - ), - ) + NostrSigner.getInstance().applicationIOScope.launch { + database.applicationDao() + .addHistory( + HistoryEntity( + 0, + permission.application.key, + type.toString().toLowerCase(Locale.current), + amberEvent?.kind, + TimeUtils.now(), + true, + ), + ) + } IntentUtils.sendBunkerResponse( applicationContext, acc, 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 0fd16b4..33541eb 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt @@ -46,8 +46,6 @@ import java.net.URLDecoder import java.util.UUID import java.util.concurrent.ConcurrentHashMap import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.launch @@ -90,8 +88,8 @@ object IntentUtils { val state = Channel(Channel.CONFLATED) private val bunkerRequests = ConcurrentHashMap() - fun addRequest(key: String, request: BunkerRequest) { - bunkerRequests[key] = request + fun addRequest(request: BunkerRequest) { + bunkerRequests[request.id] = request state.trySend("") } @@ -100,6 +98,11 @@ object IntentUtils { state.trySend("") } + fun remove(id: String) { + bunkerRequests.remove(id) + state.trySend("") + } + fun getBunkerRequests(): Map { return bunkerRequests } @@ -397,7 +400,7 @@ object IntentUtils { arrayOf(arrayOf("p", localKey)), encryptedContent, ) { - GlobalScope.launch(Dispatchers.IO) { + NostrSigner.getInstance().applicationIOScope.launch { Log.d("IntentUtils", "Sending response to relays ${relays.map { it.url }} type ${bunkerRequest?.method}") if (RelayPool.getAll().any { !it.isConnected() }) { @@ -924,15 +927,17 @@ object IntentUtils { ) } catch (e: Exception) { Log.e("nostrconnect", e.message, e) - NostrSigner.getInstance().getDatabase(account.signer.keyPair.pubKey.toNpub()).applicationDao().insertLog( - LogEntity( - 0, - "nostrconnect", - "nostrconnect", - e.message ?: "", - System.currentTimeMillis(), - ), - ) + NostrSigner.getInstance().applicationIOScope.launch { + NostrSigner.getInstance().getDatabase(account.signer.keyPair.pubKey.toNpub()).applicationDao().insertLog( + LogEntity( + 0, + "nostrconnect", + "nostrconnect", + e.message ?: "", + System.currentTimeMillis(), + ), + ) + } onReady(null) } } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationDataSource.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationDataSource.kt index 84fdc07..431f3fc 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationDataSource.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationDataSource.kt @@ -52,16 +52,18 @@ object NotificationDataSource : NostrDataSource("AccountData") { relay: Relay, afterEOSE: Boolean, ) { - LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onEvent", - message = "Received event ${event.id()} from subscription $subscriptionId afterEOSE: $afterEOSE", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onEvent", + message = "Received event ${event.id()} from subscription $subscriptionId afterEOSE: $afterEOSE", + time = System.currentTimeMillis(), + ), + ) + } } } @@ -70,16 +72,18 @@ object NotificationDataSource : NostrDataSource("AccountData") { relay: Relay, subscriptionId: String?, ) { - LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onRelayStateChange", - message = type.name, - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onRelayStateChange", + message = type.name, + time = System.currentTimeMillis(), + ), + ) + } } } @@ -89,16 +93,18 @@ object NotificationDataSource : NostrDataSource("AccountData") { message: String, relay: Relay, ) { - LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onSendResponse", - message = "Success: $success Message: $message", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onSendResponse", + message = "Success: $success Message: $message", + time = System.currentTimeMillis(), + ), + ) + } } } @@ -106,16 +112,18 @@ object NotificationDataSource : NostrDataSource("AccountData") { relay: Relay, challenge: String, ) { - LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onAuth", - message = "Authenticating", - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onAuth", + message = "Authenticating", + time = System.currentTimeMillis(), + ), + ) + } } auth(relay, challenge) } @@ -124,16 +132,18 @@ object NotificationDataSource : NostrDataSource("AccountData") { relay: Relay, description: String, ) { - LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> - NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( - LogEntity( - id = 0, - url = relay.url, - type = "onNotify", - message = description, - time = System.currentTimeMillis(), - ), - ) + scope.launch { + LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account -> + NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog( + LogEntity( + id = 0, + url = relay.url, + type = "onNotify", + message = description, + time = System.currentTimeMillis(), + ), + ) + } } notify(relay, description) } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationUtils.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationUtils.kt index 586bb41..13a0a50 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationUtils.kt @@ -111,7 +111,7 @@ object NotificationUtils { PendingIntent.FLAG_MUTABLE, ) - IntentUtils.addRequest(notId.toString(), bunkerRequest) + IntentUtils.addRequest(bunkerRequest) // Build the notification val builderPublic = diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt index 8314ee8..a2a0180 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt @@ -143,7 +143,7 @@ fun sendResult( onRemoveIntentData: (IntentData, IntentResultType) -> Unit, ) { onLoading(true) - GlobalScope.launch(Dispatchers.IO) { + NostrSigner.getInstance().applicationIOScope.launch { val defaultRelays = NostrSigner.getInstance().settings.defaultRelays var savedApplication = database.applicationDao().getByKey(key) if (savedApplication == null && intentData.bunkerRequest?.secret != null) { @@ -302,24 +302,25 @@ fun sendResult( application.application.relays.ifEmpty { relays }, onLoading, onDone = { - if (!it) { - if (rememberChoice) { - if (intentData.type == SignerType.SIGN_EVENT) { - kind?.let { - database.applicationDao().deletePermissions(key, intentData.type.toString(), kind) + NostrSigner.getInstance().applicationIOScope.launch { + if (!it) { + if (rememberChoice) { + if (intentData.type == SignerType.SIGN_EVENT) { + kind?.let { + database.applicationDao().deletePermissions(key, intentData.type.toString(), kind) + } + } else { + database.applicationDao().deletePermissions(key, intentData.type.toString()) } - } else { - database.applicationDao().deletePermissions(key, intentData.type.toString()) } - } - onLoading(false) - IntentUtils.addRequest(localIntentData.bunkerRequest!!.id, localIntentData.bunkerRequest) -// onRemoveIntentData(localIntentData, IntentResultType.ADD) - } else { - activity?.intent = null - if (application.application.closeApplication) { - activity?.finish() + onLoading(false) + IntentUtils.addRequest(localIntentData.bunkerRequest!!) + } else { + activity?.intent = null + if (application.application.closeApplication) { + activity?.finish() + } } } }, diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MultiEventHomeScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MultiEventHomeScreen.kt index eb7d291..668fcf7 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MultiEventHomeScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/MultiEventHomeScreen.kt @@ -171,7 +171,7 @@ fun MultiEventHomeScreen( text = stringResource(R.string.approve_selected), onClick = { onLoading(true) - coroutineScope.launch(Dispatchers.IO) { + NostrSigner.getInstance().applicationIOScope.launch(Dispatchers.IO) { try { val activity = context.getAppCompatActivity() val results = mutableListOf() @@ -247,6 +247,7 @@ fun MultiEventHomeScreen( if (intentData.bunkerRequest != null) { val localIntentData = intentData.copy() onRemoveIntentData(intentData, IntentResultType.REMOVE) + IntentUtils.remove(intentData.bunkerRequest.id) if (intentData.checked.value) { IntentUtils.sendBunkerResponse( @@ -258,7 +259,7 @@ fun MultiEventHomeScreen( onLoading = {}, onDone = { if (!it) { - IntentUtils.addRequest(localIntentData.id, localIntentData.bunkerRequest!!) + IntentUtils.addRequest(localIntentData.bunkerRequest!!) } }, ) @@ -331,6 +332,7 @@ fun MultiEventHomeScreen( if (intentData.bunkerRequest != null) { val localIntentData = intentData.copy() onRemoveIntentData(intentData, IntentResultType.REMOVE) + IntentUtils.remove(intentData.bunkerRequest.id) if (intentData.checked.value) { IntentUtils.sendBunkerResponse( @@ -342,7 +344,7 @@ fun MultiEventHomeScreen( onLoading = {}, onDone = { if (!it) { - IntentUtils.addRequest(localIntentData.id, localIntentData.bunkerRequest!!) + IntentUtils.addRequest(localIntentData.bunkerRequest!!) } }, ) @@ -390,6 +392,7 @@ fun MultiEventHomeScreen( if (intentData.bunkerRequest != null) { val localIntentData = intentData.copy() onRemoveIntentData(intentData, IntentResultType.REMOVE) + IntentUtils.remove(intentData.bunkerRequest.id) if (intentData.checked.value) { IntentUtils.sendBunkerResponse( context, @@ -400,7 +403,7 @@ fun MultiEventHomeScreen( onLoading = {}, onDone = { if (!it) { - IntentUtils.addRequest(localIntentData.id, localIntentData.bunkerRequest!!) + IntentUtils.addRequest(localIntentData.bunkerRequest!!) } }, ) @@ -459,6 +462,7 @@ fun MultiEventHomeScreen( if (intentData.bunkerRequest != null) { val localIntentData = intentData.copy() onRemoveIntentData(intentData, IntentResultType.REMOVE) + IntentUtils.remove(intentData.bunkerRequest.id) if (intentData.checked.value) { IntentUtils.sendBunkerResponse( context, @@ -469,7 +473,7 @@ fun MultiEventHomeScreen( onLoading = {}, onDone = { if (!it) { - IntentUtils.addRequest(localIntentData.id, localIntentData.bunkerRequest!!) + IntentUtils.addRequest(localIntentData.bunkerRequest!!) } }, ) @@ -522,56 +526,58 @@ fun MultiEventHomeScreen( containerColor = orange, ), onClick = { - var closeApp = true - - for (intentData in intents) { - val localAccount = - if (intentData.currentAccount.isNotBlank()) { - LocalPreferences.loadFromEncryptedStorage( - context, - intentData.currentAccount, + NostrSigner.getInstance().applicationIOScope.launch { + var closeApp = true + + for (intentData in intents) { + val localAccount = + if (intentData.currentAccount.isNotBlank()) { + LocalPreferences.loadFromEncryptedStorage( + context, + intentData.currentAccount, + ) + } else { + accountParam + } ?: continue + + val key = intentData.bunkerRequest?.localKey ?: packageName ?: continue + + val database = NostrSigner.getInstance().getDatabase(localAccount.signer.keyPair.pubKey.toNpub()) + + val application = + database + .applicationDao() + .getByKey(key) ?: ApplicationWithPermissions( + application = ApplicationEntity( + key, + "", + listOf(), + "", + "", + "", + localAccount.signer.keyPair.pubKey.toHexKey(), + true, + intentData.bunkerRequest?.secret ?: "", + intentData.bunkerRequest?.secret != null, + localAccount.signPolicy, + intentData.bunkerRequest?.closeApplication ?: true, + ), + permissions = mutableListOf(), ) - } else { - accountParam - } ?: continue - - val key = intentData.bunkerRequest?.localKey ?: packageName ?: continue - - val database = NostrSigner.getInstance().getDatabase(localAccount.signer.keyPair.pubKey.toNpub()) - - val application = - database - .applicationDao() - .getByKey(key) ?: ApplicationWithPermissions( - application = ApplicationEntity( - key, - "", - listOf(), - "", - "", - "", - localAccount.signer.keyPair.pubKey.toHexKey(), - true, - intentData.bunkerRequest?.secret ?: "", - intentData.bunkerRequest?.secret != null, - localAccount.signPolicy, - intentData.bunkerRequest?.closeApplication ?: true, - ), - permissions = mutableListOf(), - ) - - if (!application.application.closeApplication) { - closeApp = false - break + + if (!application.application.closeApplication) { + closeApp = false + break + } } - } - val activity = context.getAppCompatActivity() - if (intents.any { it.bunkerRequest != null }) { - EventNotificationConsumer(context).notificationManager().cancelAll() - finishActivity(activity, closeApp) - } else { - finishActivity(activity, closeApp) + val activity = context.getAppCompatActivity() + if (intents.any { it.bunkerRequest != null }) { + EventNotificationConsumer(context).notificationManager().cancelAll() + finishActivity(activity, closeApp) + } else { + finishActivity(activity, closeApp) + } } }, text = stringResource(R.string.discard_all_requests),