diff --git a/app/build.gradle b/app/build.gradle index 1087944a..29d53278 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,8 +29,8 @@ android { buildTypes { release { - // minifyEnabled false - // proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), 'proguard-rules.pro' + minifyEnabled true resValue "string", "app_name", "@string/app_name_release" } debug { diff --git a/app/play/release/baselineProfiles/0/app-play-arm64-v8a-release.dm b/app/play/release/baselineProfiles/0/app-play-arm64-v8a-release.dm index 02599f46..200e244d 100644 Binary files a/app/play/release/baselineProfiles/0/app-play-arm64-v8a-release.dm and b/app/play/release/baselineProfiles/0/app-play-arm64-v8a-release.dm differ diff --git a/app/play/release/baselineProfiles/0/app-play-armeabi-v7a-release.dm b/app/play/release/baselineProfiles/0/app-play-armeabi-v7a-release.dm index 02599f46..200e244d 100644 Binary files a/app/play/release/baselineProfiles/0/app-play-armeabi-v7a-release.dm and b/app/play/release/baselineProfiles/0/app-play-armeabi-v7a-release.dm differ diff --git a/app/play/release/baselineProfiles/0/app-play-universal-release.dm b/app/play/release/baselineProfiles/0/app-play-universal-release.dm index 02599f46..200e244d 100644 Binary files a/app/play/release/baselineProfiles/0/app-play-universal-release.dm and b/app/play/release/baselineProfiles/0/app-play-universal-release.dm differ diff --git a/app/play/release/baselineProfiles/0/app-play-x86-release.dm b/app/play/release/baselineProfiles/0/app-play-x86-release.dm index 02599f46..200e244d 100644 Binary files a/app/play/release/baselineProfiles/0/app-play-x86-release.dm and b/app/play/release/baselineProfiles/0/app-play-x86-release.dm differ diff --git a/app/play/release/baselineProfiles/0/app-play-x86_64-release.dm b/app/play/release/baselineProfiles/0/app-play-x86_64-release.dm index 02599f46..200e244d 100644 Binary files a/app/play/release/baselineProfiles/0/app-play-x86_64-release.dm and b/app/play/release/baselineProfiles/0/app-play-x86_64-release.dm differ diff --git a/app/play/release/baselineProfiles/1/app-play-arm64-v8a-release.dm b/app/play/release/baselineProfiles/1/app-play-arm64-v8a-release.dm index 34cf77aa..71af37c1 100644 Binary files a/app/play/release/baselineProfiles/1/app-play-arm64-v8a-release.dm and b/app/play/release/baselineProfiles/1/app-play-arm64-v8a-release.dm differ diff --git a/app/play/release/baselineProfiles/1/app-play-armeabi-v7a-release.dm b/app/play/release/baselineProfiles/1/app-play-armeabi-v7a-release.dm index 34cf77aa..71af37c1 100644 Binary files a/app/play/release/baselineProfiles/1/app-play-armeabi-v7a-release.dm and b/app/play/release/baselineProfiles/1/app-play-armeabi-v7a-release.dm differ diff --git a/app/play/release/baselineProfiles/1/app-play-universal-release.dm b/app/play/release/baselineProfiles/1/app-play-universal-release.dm index 34cf77aa..71af37c1 100644 Binary files a/app/play/release/baselineProfiles/1/app-play-universal-release.dm and b/app/play/release/baselineProfiles/1/app-play-universal-release.dm differ diff --git a/app/play/release/baselineProfiles/1/app-play-x86-release.dm b/app/play/release/baselineProfiles/1/app-play-x86-release.dm index 34cf77aa..71af37c1 100644 Binary files a/app/play/release/baselineProfiles/1/app-play-x86-release.dm and b/app/play/release/baselineProfiles/1/app-play-x86-release.dm differ diff --git a/app/play/release/baselineProfiles/1/app-play-x86_64-release.dm b/app/play/release/baselineProfiles/1/app-play-x86_64-release.dm index 34cf77aa..71af37c1 100644 Binary files a/app/play/release/baselineProfiles/1/app-play-x86_64-release.dm and b/app/play/release/baselineProfiles/1/app-play-x86_64-release.dm differ diff --git a/app/play/release/output-metadata.json b/app/play/release/output-metadata.json index c0a6deed..e0e7bf39 100644 --- a/app/play/release/output-metadata.json +++ b/app/play/release/output-metadata.json @@ -11,7 +11,7 @@ "type": "UNIVERSAL", "filters": [], "attributes": [], - "versionCode": 51, + "versionCode": 60, "versionName": "1.0.0", "outputFile": "app-play-universal-release.apk" }, @@ -24,23 +24,10 @@ } ], "attributes": [], - "versionCode": 51, + "versionCode": 60, "versionName": "1.0.0", "outputFile": "app-play-armeabi-v7a-release.apk" }, - { - "type": "ONE_OF_MANY", - "filters": [ - { - "filterType": "ABI", - "value": "x86" - } - ], - "attributes": [], - "versionCode": 51, - "versionName": "1.0.0", - "outputFile": "app-play-x86-release.apk" - }, { "type": "ONE_OF_MANY", "filters": [ @@ -50,7 +37,7 @@ } ], "attributes": [], - "versionCode": 51, + "versionCode": 60, "versionName": "1.0.0", "outputFile": "app-play-arm64-v8a-release.apk" }, @@ -63,9 +50,22 @@ } ], "attributes": [], - "versionCode": 51, + "versionCode": 60, "versionName": "1.0.0", "outputFile": "app-play-x86_64-release.apk" + }, + { + "type": "ONE_OF_MANY", + "filters": [ + { + "filterType": "ABI", + "value": "x86" + } + ], + "attributes": [], + "versionCode": 60, + "versionName": "1.0.0", + "outputFile": "app-play-x86-release.apk" } ], "elementType": "File", @@ -76,9 +76,9 @@ "baselineProfiles": [ "baselineProfiles/1/app-play-universal-release.dm", "baselineProfiles/1/app-play-armeabi-v7a-release.dm", - "baselineProfiles/1/app-play-x86-release.dm", "baselineProfiles/1/app-play-arm64-v8a-release.dm", - "baselineProfiles/1/app-play-x86_64-release.dm" + "baselineProfiles/1/app-play-x86_64-release.dm", + "baselineProfiles/1/app-play-x86-release.dm" ] }, { @@ -87,9 +87,9 @@ "baselineProfiles": [ "baselineProfiles/0/app-play-universal-release.dm", "baselineProfiles/0/app-play-armeabi-v7a-release.dm", - "baselineProfiles/0/app-play-x86-release.dm", "baselineProfiles/0/app-play-arm64-v8a-release.dm", - "baselineProfiles/0/app-play-x86_64-release.dm" + "baselineProfiles/0/app-play-x86_64-release.dm", + "baselineProfiles/0/app-play-x86-release.dm" ] } ], diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 97496bbf..81576c83 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -33,6 +33,11 @@ # JNA For Libsodium -keep class com.goterl.lazysodium.** { *; } +# libscrypt +-keep class com.lambdaworks.codec.** { *; } +-keep class com.lambdaworks.crypto.** { *; } +-keep class com.lambdaworks.jni.** { *; } + # JNA also requires AWT, which Android does not have. So the classes are broken down to filter AWT out -keep class com.sun.jna.ToNativeConverter { *; } -keep class com.sun.jna.NativeMapped { *; } @@ -58,3 +63,11 @@ -keep class com.vitorpamplona.quartz.events.** { *; } -keep class com.vitorpamplona.amethyst.model.** { *; } -keep class com.vitorpamplona.amethyst.service.** { *; } +-keep class com.greenart7c3.nostrsigner.models.** { *; } +-keep class com.greenart7c3.nostrsigner.service.** { *; } + +-dontwarn edu.umd.cs.findbugs.annotations.NonNull +-dontwarn edu.umd.cs.findbugs.annotations.Nullable +-dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings +-dontwarn java.lang.instrument.ClassDefinition +-dontwarn java.lang.instrument.UnmodifiableClassException diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/MainActivity.kt b/app/src/main/java/com/greenart7c3/nostrsigner/MainActivity.kt index 95ae51f9..cc247bb0 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/MainActivity.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/MainActivity.kt @@ -2,9 +2,6 @@ package com.greenart7c3.nostrsigner import android.content.Intent import android.net.ConnectivityManager -import android.net.Network -import android.net.NetworkCapabilities -import android.net.Uri import android.os.Bundle import android.util.Log import androidx.activity.compose.setContent @@ -12,35 +9,19 @@ import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface -import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.Modifier import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.WindowCompat import androidx.lifecycle.viewmodel.compose.viewModel -import com.greenart7c3.nostrsigner.models.IntentData -import com.greenart7c3.nostrsigner.service.HttpClientManager -import com.greenart7c3.nostrsigner.service.IntentUtils -import com.greenart7c3.nostrsigner.service.NotificationDataSource import com.greenart7c3.nostrsigner.ui.AccountScreen import com.greenart7c3.nostrsigner.ui.AccountStateViewModel -import com.greenart7c3.nostrsigner.ui.navigation.Route import com.greenart7c3.nostrsigner.ui.theme.NostrSignerTheme -import com.vitorpamplona.quartz.encoders.toNpub -import fr.acinq.secp256k1.Hex -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.launch fun Intent.isLaunchFromHistory(): Boolean = this.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY class MainActivity : AppCompatActivity() { - private val intents = MutableStateFlow>(listOf()) - val isOnMobileDataState = mutableStateOf(false) - private val isOnWifiDataState = mutableStateOf(false) + private val mainViewModel = MainViewModel() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -67,167 +48,42 @@ class MainActivity : AppCompatActivity() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background, ) { - val npub = intent.getStringExtra("current_user") ?: getAccount() + val npub = intent.getStringExtra("current_user") ?: mainViewModel.getAccount() val accountStateViewModel: AccountStateViewModel = viewModel { AccountStateViewModel(npub) } - AccountScreen(accountStateViewModel, intent, packageName, appName, intents) + AccountScreen(accountStateViewModel, intent, packageName, appName, mainViewModel.intents) } } } } - fun getAccount(): String? { - val pubKeys = - intents.value.mapNotNull { - it.event?.pubKey - } - - if (pubKeys.isEmpty()) return null - return Hex.decode(pubKeys.first()).toNpub() - } - - @OptIn(DelicateCoroutinesApi::class) override fun onResume() { - val requests = - IntentUtils.bunkerRequests.map { - it.value.copy() - } - - GlobalScope.launch(Dispatchers.IO) { - val account = LocalPreferences.loadFromEncryptedStorage() - account?.let { acc -> - requests.forEach { - val contentIntent = - Intent(applicationContext, MainActivity::class.java).apply { - data = Uri.parse("nostrsigner:") - } - contentIntent.putExtra("bunker", it.toJson()) - contentIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) - IntentUtils.getIntentData(contentIntent, callingPackage, Route.Home.route, acc) { intentData -> - if (intentData != null) { - if (intents.value.none { item -> item.id == intentData.id }) { - intents.value += listOf(intentData) - } - } - } - } - } - - IntentUtils.bunkerRequests.clear() - } + mainViewModel.showBunkerRequests(callingPackage) if (BuildConfig.FLAVOR != "offline") { val connectivityManager = (getSystemService(ConnectivityManager::class.java) as ConnectivityManager) - connectivityManager.registerDefaultNetworkCallback(networkCallback) + connectivityManager.registerDefaultNetworkCallback(mainViewModel.networkCallback) connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)?.let { - updateNetworkCapabilities(it) + mainViewModel.updateNetworkCapabilities(it) } } super.onResume() } - @OptIn(DelicateCoroutinesApi::class) override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - GlobalScope.launch(Dispatchers.IO) { - val account = LocalPreferences.loadFromEncryptedStorage() - account?.let { acc -> - IntentUtils.getIntentData(intent, callingPackage, intent.getStringExtra("route"), acc) { intentData -> - if (intentData != null) { - if (intents.value.none { item -> item.id == intentData.id }) { - intents.value += listOf(intentData) - } - intents.value = - intents.value.map { - it.copy() - }.toMutableList() - } - } - } - } + mainViewModel.onNewIntent(intent, callingPackage) } override fun onDestroy() { - intents.value = emptyList() + mainViewModel.intents.value = emptyList() super.onDestroy() } - - fun updateNetworkCapabilities(networkCapabilities: NetworkCapabilities): Boolean { - val isOnMobileData = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) - val isOnWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) - - var changedNetwork = false - - if (isOnMobileDataState.value != isOnMobileData) { - isOnMobileDataState.value = isOnMobileData - - changedNetwork = true - } - - if (isOnWifiDataState.value != isOnWifi) { - isOnWifiDataState.value = isOnWifi - - changedNetwork = true - } - - if (changedNetwork) { - if (isOnMobileData) { - HttpClientManager.setDefaultTimeout(HttpClientManager.DEFAULT_TIMEOUT_ON_MOBILE) - } else { - HttpClientManager.setDefaultTimeout(HttpClientManager.DEFAULT_TIMEOUT_ON_WIFI) - } - } - - return changedNetwork - } - - @OptIn(DelicateCoroutinesApi::class) - private val networkCallback = - object : ConnectivityManager.NetworkCallback() { - var lastNetwork: Network? = null - - override fun onAvailable(network: Network) { - super.onAvailable(network) - if (BuildConfig.FLAVOR == "offline") return - - if (lastNetwork != null && lastNetwork != network) { - GlobalScope.launch(Dispatchers.IO) { - NotificationDataSource.stopSync() - delay(1000) - NotificationDataSource.start() - } - } - - lastNetwork = network - } - - // Network capabilities have changed for the network - override fun onCapabilitiesChanged( - network: Network, - networkCapabilities: NetworkCapabilities, - ) { - super.onCapabilitiesChanged(network, networkCapabilities) - - if (BuildConfig.FLAVOR == "offline") return - - GlobalScope.launch(Dispatchers.IO) { - Log.d( - "ServiceManager NetworkCallback", - "onCapabilitiesChanged: ${network.networkHandle} hasMobileData ${isOnMobileDataState.value} hasWifi ${isOnWifiDataState.value}", - ) - if (updateNetworkCapabilities(networkCapabilities)) { - NotificationDataSource.stopSync() - delay(1000) - NotificationDataSource.start() - } - } - } - } } diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/MainViewModel.kt b/app/src/main/java/com/greenart7c3/nostrsigner/MainViewModel.kt new file mode 100644 index 00000000..ff750a68 --- /dev/null +++ b/app/src/main/java/com/greenart7c3/nostrsigner/MainViewModel.kt @@ -0,0 +1,162 @@ +package com.greenart7c3.nostrsigner + +import android.content.Intent +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import android.net.Uri +import android.util.Log +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.greenart7c3.nostrsigner.models.IntentData +import com.greenart7c3.nostrsigner.service.HttpClientManager +import com.greenart7c3.nostrsigner.service.IntentUtils +import com.greenart7c3.nostrsigner.service.NotificationDataSource +import com.greenart7c3.nostrsigner.ui.NotificationType +import com.greenart7c3.nostrsigner.ui.navigation.Route +import com.vitorpamplona.quartz.encoders.toNpub +import fr.acinq.secp256k1.Hex +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch + +class MainViewModel : ViewModel() { + val intents = MutableStateFlow>(listOf()) + val isOnMobileDataState = mutableStateOf(false) + val isOnWifiDataState = mutableStateOf(false) + + val networkCallback = + object : ConnectivityManager.NetworkCallback() { + var lastNetwork: Network? = null + + override fun onAvailable(network: Network) { + super.onAvailable(network) + if (BuildConfig.FLAVOR == "offline") return + + if (lastNetwork != null && lastNetwork != network && LocalPreferences.getNotificationType() == NotificationType.DIRECT) { + viewModelScope.launch(Dispatchers.IO) { + NotificationDataSource.stopSync() + delay(1000) + NotificationDataSource.start() + } + } + + lastNetwork = network + } + + // Network capabilities have changed for the network + override fun onCapabilitiesChanged( + network: Network, + networkCapabilities: NetworkCapabilities, + ) { + super.onCapabilitiesChanged(network, networkCapabilities) + + if (BuildConfig.FLAVOR == "offline") return + + viewModelScope.launch(Dispatchers.IO) { + Log.d( + "ServiceManager NetworkCallback", + "onCapabilitiesChanged: ${network.networkHandle} hasMobileData ${isOnMobileDataState.value} hasWifi ${isOnWifiDataState.value}", + ) + if (updateNetworkCapabilities(networkCapabilities) && LocalPreferences.getNotificationType() == NotificationType.DIRECT) { + NotificationDataSource.stopSync() + delay(1000) + NotificationDataSource.start() + } + } + } + } + + fun getAccount(): String? { + val pubKeys = + intents.value.mapNotNull { + it.event?.pubKey + } + + if (pubKeys.isEmpty()) return null + return Hex.decode(pubKeys.first()).toNpub() + } + + fun showBunkerRequests(callingPackage: String?) { + val requests = + IntentUtils.bunkerRequests.map { + it.value.copy() + } + + viewModelScope.launch(Dispatchers.IO) { + val account = LocalPreferences.loadFromEncryptedStorage() + account?.let { acc -> + requests.forEach { + val contentIntent = + Intent(NostrSigner.instance, MainActivity::class.java).apply { + data = Uri.parse("nostrsigner:") + } + contentIntent.putExtra("bunker", it.toJson()) + contentIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) + IntentUtils.getIntentData(contentIntent, callingPackage, Route.Home.route, acc) { intentData -> + if (intentData != null) { + if (intents.value.none { item -> item.id == intentData.id }) { + intents.value += listOf(intentData) + } + } + } + } + } + + IntentUtils.bunkerRequests.clear() + } + } + + fun onNewIntent( + intent: Intent, + callingPackage: String?, + ) { + viewModelScope.launch(Dispatchers.IO) { + val account = LocalPreferences.loadFromEncryptedStorage() + account?.let { acc -> + IntentUtils.getIntentData(intent, callingPackage, intent.getStringExtra("route"), acc) { intentData -> + if (intentData != null) { + if (intents.value.none { item -> item.id == intentData.id }) { + intents.value += listOf(intentData) + } + intents.value = + intents.value.map { + it.copy() + }.toMutableList() + } + } + } + } + } + + fun updateNetworkCapabilities(networkCapabilities: NetworkCapabilities): Boolean { + val isOnMobileData = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) + val isOnWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + + var changedNetwork = false + + if (isOnMobileDataState.value != isOnMobileData) { + isOnMobileDataState.value = isOnMobileData + + changedNetwork = true + } + + if (isOnWifiDataState.value != isOnWifi) { + isOnWifiDataState.value = isOnWifi + + changedNetwork = true + } + + if (changedNetwork) { + if (isOnMobileData) { + HttpClientManager.setDefaultTimeout(HttpClientManager.DEFAULT_TIMEOUT_ON_MOBILE) + } else { + HttpClientManager.setDefaultTimeout(HttpClientManager.DEFAULT_TIMEOUT_ON_WIFI) + } + } + + return changedNetwork + } +} diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/models/BunkerRequest.kt b/app/src/main/java/com/greenart7c3/nostrsigner/models/BunkerRequest.kt new file mode 100644 index 00000000..e39b28fb --- /dev/null +++ b/app/src/main/java/com/greenart7c3/nostrsigner/models/BunkerRequest.kt @@ -0,0 +1,87 @@ +package com.greenart7c3.nostrsigner.models + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import com.fasterxml.jackson.databind.module.SimpleModule +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper + +data class BunkerRequest( + val id: String, + val method: String, + val params: Array, + var localKey: String, + var relays: List, + var secret: String, + var currentAccount: String, +) { + fun toJson(): String { + return mapper.writeValueAsString(this) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as BunkerRequest + + if (id != other.id) return false + if (method != other.method) return false + if (!params.contentEquals(other.params)) return false + if (localKey != other.localKey) return false + if (relays != other.relays) return false + if (secret != other.secret) return false + + return true + } + + override fun hashCode(): Int { + var result = id.hashCode() + result = 31 * result + method.hashCode() + result = 31 * result + params.contentHashCode() + result = 31 * result + localKey.hashCode() + result = 31 * result + relays.hashCode() + result = 31 * result + secret.hashCode() + return result + } + + companion object { + val mapper: ObjectMapper = + jacksonObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .registerModule( + SimpleModule() + .addDeserializer(BunkerRequest::class.java, BunkerRequestDeserializer()), + ) + + fun fromJson(jsonObject: JsonNode): BunkerRequest { + return BunkerRequest( + id = jsonObject.get("id").asText().intern(), + method = jsonObject.get("method").asText().intern(), + params = + jsonObject.get("params").asIterable().toList().map { + it.asText().intern() + }.toTypedArray(), + localKey = jsonObject.get("localKey")?.asText()?.intern() ?: "", + relays = + jsonObject.get("relays")?.asIterable()?.toList()?.map { + it.asText().intern() + } ?: listOf(), + secret = jsonObject.get("secret")?.asText()?.intern() ?: "", + currentAccount = jsonObject.get("currentAccount")?.asText()?.intern() ?: "", + ) + } + + private class BunkerRequestDeserializer : StdDeserializer(BunkerRequest::class.java) { + override fun deserialize( + jp: JsonParser, + ctxt: DeserializationContext, + ): BunkerRequest { + return fromJson(jp.codec.readTree(jp)) + } + } + } +} diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/models/BunkerResponse.kt b/app/src/main/java/com/greenart7c3/nostrsigner/models/BunkerResponse.kt new file mode 100644 index 00000000..05091da2 --- /dev/null +++ b/app/src/main/java/com/greenart7c3/nostrsigner/models/BunkerResponse.kt @@ -0,0 +1,7 @@ +package com.greenart7c3.nostrsigner.models + +data class BunkerResponse( + val id: String, + val result: String, + val error: String?, +) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/models/IntentData.kt b/app/src/main/java/com/greenart7c3/nostrsigner/models/IntentData.kt index 039d0883..74876f5f 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/models/IntentData.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/models/IntentData.kt @@ -1,7 +1,6 @@ package com.greenart7c3.nostrsigner.models import androidx.compose.runtime.MutableState -import com.greenart7c3.nostrsigner.service.BunkerRequest import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.events.Event 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 2e85e2e2..ccb4de6d 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/AmberUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/AmberUtils.kt @@ -7,10 +7,11 @@ import com.greenart7c3.nostrsigner.database.ApplicationEntity import com.greenart7c3.nostrsigner.database.ApplicationPermissionsEntity import com.greenart7c3.nostrsigner.database.ApplicationWithPermissions import com.greenart7c3.nostrsigner.models.Account +import com.greenart7c3.nostrsigner.models.BunkerRequest +import com.greenart7c3.nostrsigner.models.BunkerResponse import com.greenart7c3.nostrsigner.models.IntentData import com.greenart7c3.nostrsigner.models.SignerType import com.greenart7c3.nostrsigner.relays.Relay -import com.greenart7c3.nostrsigner.ui.BunkerResponse import com.vitorpamplona.quartz.crypto.CryptoUtils import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.hexToByteArray diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/ConnectivityService.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/ConnectivityService.kt index 57f25790..c0355861 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/ConnectivityService.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/ConnectivityService.kt @@ -49,7 +49,7 @@ class ConnectivityService : Service() { override fun onCreate() { startForeground(1, createNotification()) - timer.scheduleAtFixedRate( + timer.schedule( object : TimerTask() { override fun run() { if (LocalPreferences.getNotificationType() == NotificationType.PUSH) return 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 b50e693f..79ec3212 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt @@ -27,109 +27,25 @@ import android.util.Log import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.toLowerCase import androidx.core.content.ContextCompat -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.fasterxml.jackson.databind.module.SimpleModule -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.greenart7c3.nostrsigner.BuildConfig import com.greenart7c3.nostrsigner.LocalPreferences import com.greenart7c3.nostrsigner.NostrSigner import com.greenart7c3.nostrsigner.database.ApplicationWithPermissions import com.greenart7c3.nostrsigner.database.NotificationEntity import com.greenart7c3.nostrsigner.models.Account +import com.greenart7c3.nostrsigner.models.BunkerRequest +import com.greenart7c3.nostrsigner.models.BunkerResponse import com.greenart7c3.nostrsigner.models.Permission import com.greenart7c3.nostrsigner.models.SignerType import com.greenart7c3.nostrsigner.relays.Relay import com.greenart7c3.nostrsigner.service.NotificationUtils.sendNotification import com.greenart7c3.nostrsigner.service.model.AmberEvent -import com.greenart7c3.nostrsigner.ui.BunkerResponse import com.greenart7c3.nostrsigner.ui.NotificationType import com.vitorpamplona.quartz.encoders.toNpub import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.GiftWrapEvent import com.vitorpamplona.quartz.events.SealedGossipEvent -data class BunkerRequest( - val id: String, - val method: String, - val params: Array, - var localKey: String, - var relays: List, - var secret: String, - var currentAccount: String, -) { - fun toJson(): String { - return mapper.writeValueAsString(this) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as BunkerRequest - - if (id != other.id) return false - if (method != other.method) return false - if (!params.contentEquals(other.params)) return false - if (localKey != other.localKey) return false - if (relays != other.relays) return false - if (secret != other.secret) return false - - return true - } - - override fun hashCode(): Int { - var result = id.hashCode() - result = 31 * result + method.hashCode() - result = 31 * result + params.contentHashCode() - result = 31 * result + localKey.hashCode() - result = 31 * result + relays.hashCode() - result = 31 * result + secret.hashCode() - return result - } - - companion object { - val mapper: ObjectMapper = - jacksonObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .registerModule( - SimpleModule() - .addDeserializer(BunkerRequest::class.java, BunkerRequestDeserializer()), - ) - - fun fromJson(jsonObject: JsonNode): BunkerRequest { - return BunkerRequest( - id = jsonObject.get("id").asText().intern(), - method = jsonObject.get("method").asText().intern(), - params = - jsonObject.get("params").asIterable().toList().map { - it.asText().intern() - }.toTypedArray(), - localKey = jsonObject.get("localKey")?.asText()?.intern() ?: "", - relays = - jsonObject.get("relays")?.asIterable()?.toList()?.map { - it.asText().intern() - } ?: listOf(), - secret = jsonObject.get("secret")?.asText()?.intern() ?: "", - currentAccount = jsonObject.get("currentAccount")?.asText()?.intern() ?: "", - ) - } - - private class BunkerRequestDeserializer : StdDeserializer(BunkerRequest::class.java) { - override fun deserialize( - jp: JsonParser, - ctxt: DeserializationContext, - ): BunkerRequest { - return fromJson(jp.codec.readTree(jp)) - } - } - } -} - class EventNotificationConsumer(private val applicationContext: Context) { private val groupKey = "com.greenart7c3.nostrsigner.DM_NOTIFICATION" 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 2ce0078d..a888dee3 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt @@ -15,6 +15,8 @@ import com.google.gson.reflect.TypeToken import com.greenart7c3.nostrsigner.LocalPreferences import com.greenart7c3.nostrsigner.NostrSigner import com.greenart7c3.nostrsigner.models.Account +import com.greenart7c3.nostrsigner.models.BunkerRequest +import com.greenart7c3.nostrsigner.models.BunkerResponse import com.greenart7c3.nostrsigner.models.CompressionType import com.greenart7c3.nostrsigner.models.IntentData import com.greenart7c3.nostrsigner.models.Permission @@ -25,7 +27,6 @@ import com.greenart7c3.nostrsigner.relays.Client import com.greenart7c3.nostrsigner.relays.Relay import com.greenart7c3.nostrsigner.relays.RelayPool import com.greenart7c3.nostrsigner.service.model.AmberEvent -import com.greenart7c3.nostrsigner.ui.BunkerResponse import com.greenart7c3.nostrsigner.ui.NotificationType import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.encoders.toNpub 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 c456ecb0..4c922780 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationUtils.kt @@ -32,6 +32,7 @@ import android.service.notification.StatusBarNotification import androidx.core.app.NotificationCompat import com.greenart7c3.nostrsigner.MainActivity import com.greenart7c3.nostrsigner.R +import com.greenart7c3.nostrsigner.models.BunkerRequest import com.greenart7c3.nostrsigner.ui.navigation.Route object NotificationUtils { 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 e90266ed..1742c943 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt @@ -86,6 +86,7 @@ import com.greenart7c3.nostrsigner.database.ApplicationEntity import com.greenart7c3.nostrsigner.database.ApplicationPermissionsEntity import com.greenart7c3.nostrsigner.database.ApplicationWithPermissions import com.greenart7c3.nostrsigner.models.Account +import com.greenart7c3.nostrsigner.models.BunkerResponse import com.greenart7c3.nostrsigner.models.CompressionType import com.greenart7c3.nostrsigner.models.IntentData import com.greenart7c3.nostrsigner.models.Permission @@ -113,12 +114,6 @@ import java.util.Base64 import java.util.UUID import java.util.zip.GZIPOutputStream -data class BunkerResponse( - val id: String, - val result: String, - val error: String?, -) - @OptIn(DelicateCoroutinesApi::class) fun sendResult( context: Context, 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 540bf309..dddc3696 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 @@ -48,6 +48,7 @@ import com.greenart7c3.nostrsigner.NostrSigner import com.greenart7c3.nostrsigner.R import com.greenart7c3.nostrsigner.database.AppDatabase import com.greenart7c3.nostrsigner.models.Account +import com.greenart7c3.nostrsigner.models.BunkerResponse import com.greenart7c3.nostrsigner.models.IntentData import com.greenart7c3.nostrsigner.models.Permission import com.greenart7c3.nostrsigner.models.SignerType @@ -62,7 +63,6 @@ import com.greenart7c3.nostrsigner.service.RelayDisconnectService import com.greenart7c3.nostrsigner.service.getAppCompatActivity import com.greenart7c3.nostrsigner.service.model.AmberEvent import com.greenart7c3.nostrsigner.service.toShortenHex -import com.greenart7c3.nostrsigner.ui.BunkerResponse import com.greenart7c3.nostrsigner.ui.Result import com.greenart7c3.nostrsigner.ui.theme.ButtonBorder import com.vitorpamplona.quartz.events.LnZapRequestEvent