diff --git a/app/build.gradle b/app/build.gradle
index 6a13d285..c0dd3625 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,7 +4,6 @@ plugins {
alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsKotlinAndroid)
alias(libs.plugins.gradle.ktlint) version(libs.versions.ktlint)
- alias(libs.plugins.google.gms) version(libs.versions.gms)
alias(libs.plugins.kotlin.ksp) version(libs.versions.ksp)
alias(libs.plugins.jetbrainsComposeCompiler)
}
@@ -58,7 +57,6 @@ android {
'ku-rTR',
'lt-rLT',
'ne-rNP',
- 'night',
'nl',
'nl-rBE',
'pcm-rNG',
@@ -131,11 +129,8 @@ android {
flavorDimensions += "version"
productFlavors {
- create("play") {
- getIsDefault().set(true)
- dimension = "version"
- }
create("free") {
+ getIsDefault().set(true)
dimension = "version"
}
create("offline") {
@@ -241,12 +236,8 @@ dependencies {
// Biometrics
implementation libs.biometric.ktx
- playImplementation platform(libs.firebase.bom)
- playImplementation(libs.firebase.messaging)
- freeImplementation(libs.unfiedpush)
ksp(libs.room.compiler)
implementation(libs.room.ktx)
freeImplementation(libs.okhttp)
- playImplementation(libs.okhttp)
}
diff --git a/app/google-services.json b/app/google-services.json
deleted file mode 100644
index 1afad829..00000000
--- a/app/google-services.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
- "project_info": {
- "project_number": "575711686692",
- "project_id": "amber-c362b",
- "storage_bucket": "amber-c362b.appspot.com"
- },
- "client": [
- {
- "client_info": {
- "mobilesdk_app_id": "1:575711686692:android:11451e08365ea86f6ce8b1",
- "android_client_info": {
- "package_name": "com.greenart7c3.nostrsigner"
- }
- },
- "oauth_client": [],
- "api_key": [
- {
- "current_key": "AIzaSyDB2tmjxGmFx_Oz25YhtKkheWbdb_NlnfU"
- }
- ],
- "services": {
- "appinvite_service": {
- "other_platform_oauth_client": []
- }
- }
- },
- {
- "client_info": {
- "mobilesdk_app_id": "1:575711686692:android:fb6ef62b68245d696ce8b1",
- "android_client_info": {
- "package_name": "com.greenart7c3.nostrsigner.debug"
- }
- },
- "oauth_client": [],
- "api_key": [
- {
- "current_key": "AIzaSyDB2tmjxGmFx_Oz25YhtKkheWbdb_NlnfU"
- }
- ],
- "services": {
- "appinvite_service": {
- "other_platform_oauth_client": []
- }
- }
- }
- ],
- "configuration_version": "1"
-}
\ No newline at end of file
diff --git a/app/src/free/AndroidManifest.xml b/app/src/free/AndroidManifest.xml
index 7f803246..208539d7 100644
--- a/app/src/free/AndroidManifest.xml
+++ b/app/src/free/AndroidManifest.xml
@@ -26,19 +26,6 @@
/>
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/free/java/com/greenart7c3/nostrsigner/service/PushDistributorHandler.kt b/app/src/free/java/com/greenart7c3/nostrsigner/service/PushDistributorHandler.kt
deleted file mode 100644
index 02e09067..00000000
--- a/app/src/free/java/com/greenart7c3/nostrsigner/service/PushDistributorHandler.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * Copyright (c) 2024 Vitor Pamplona
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
- * Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-package com.greenart7c3.nostrsigner.service
-
-import android.content.Context
-import android.content.pm.PackageManager
-import android.os.Build
-import android.util.Log
-import com.greenart7c3.nostrsigner.LocalPreferences
-import com.greenart7c3.nostrsigner.NostrSigner
-import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-import org.unifiedpush.android.connector.UnifiedPush
-
-interface PushDistributorActions {
- fun getSavedDistributor(): String
-
- fun getInstalledDistributors(): List
-
- fun saveDistributor(distributor: String)
-
- fun removeSavedDistributor()
-}
-
-object PushDistributorHandler : PushDistributorActions {
- private val appContext = NostrSigner.getInstance().applicationContext
- private val unifiedPush: UnifiedPush = UnifiedPush
-
- private var endpointInternal = NostrSigner.getInstance().settings.endpoint
-
- fun getSavedEndpoint() = endpointInternal
-
- @OptIn(DelicateCoroutinesApi::class)
- fun setEndpoint(newEndpoint: String) {
- endpointInternal = newEndpoint
- GlobalScope.launch(Dispatchers.IO) {
- NostrSigner.getInstance().settings = NostrSigner.getInstance().settings.copy(endpoint = newEndpoint)
- LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
- }
- Log.d("PushHandler", "New endpoint saved : $endpointInternal")
- }
-
- @OptIn(DelicateCoroutinesApi::class)
- fun removeEndpoint() {
- endpointInternal = ""
- GlobalScope.launch(Dispatchers.IO) {
- NostrSigner.getInstance().settings = NostrSigner.getInstance().settings.copy(endpoint = "")
- LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
- }
- }
-
- override fun getSavedDistributor(): String {
- return unifiedPush.getSavedDistributor(appContext) ?: ""
- }
-
- fun savedDistributorExists(): Boolean = getSavedDistributor().isNotEmpty()
-
- override fun getInstalledDistributors(): List {
- return unifiedPush.getDistributors(appContext)
- }
-
- fun formattedDistributorNames(): List {
- val distributorsArray = getInstalledDistributors().toTypedArray()
- val distributorsNameArray =
- distributorsArray
- .map {
- try {
- val ai =
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- appContext.packageManager.getApplicationInfo(
- it,
- PackageManager.ApplicationInfoFlags.of(
- PackageManager.GET_META_DATA.toLong(),
- ),
- )
- } else {
- appContext.packageManager.getApplicationInfo(it, 0)
- }
- appContext.packageManager.getApplicationLabel(ai)
- } catch (e: PackageManager.NameNotFoundException) {
- it
- }
- as String
- }
- .toTypedArray()
- return distributorsNameArray.toList()
- }
-
- override fun saveDistributor(distributor: String) {
- unifiedPush.saveDistributor(appContext, distributor)
- unifiedPush.registerApp(appContext)
- }
-
- override fun removeSavedDistributor() {
- unifiedPush.safeRemoveDistributor(appContext)
- }
-
- fun forceRemoveDistributor(context: Context) {
- unifiedPush.forceRemoveDistributor(context)
- }
-}
diff --git a/app/src/free/java/com/greenart7c3/nostrsigner/service/PushMessageReceiver.kt b/app/src/free/java/com/greenart7c3/nostrsigner/service/PushMessageReceiver.kt
deleted file mode 100644
index c4bdc89d..00000000
--- a/app/src/free/java/com/greenart7c3/nostrsigner/service/PushMessageReceiver.kt
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * Copyright (c) 2024 Vitor Pamplona
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
- * Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-package com.greenart7c3.nostrsigner.service
-
-import android.content.Context
-import android.util.Log
-import android.util.LruCache
-import com.greenart7c3.nostrsigner.LocalPreferences
-import com.greenart7c3.nostrsigner.NostrSigner
-import com.greenart7c3.nostrsigner.database.LogEntity
-import com.vitorpamplona.quartz.events.Event
-import com.vitorpamplona.quartz.events.GiftWrapEvent
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.launch
-import org.unifiedpush.android.connector.MessagingReceiver
-
-class PushMessageReceiver : MessagingReceiver() {
- companion object {
- private val TAG = "Amber-OSSPushReceiver"
- }
-
- private val appContext = NostrSigner.getInstance().applicationContext
- private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
- private val eventCache = LruCache(100)
- private val pushHandler = PushDistributorHandler
-
- override fun onMessage(
- context: Context,
- message: ByteArray,
- instance: String,
- ) {
- val messageStr = message.decodeToString()
- Log.d(TAG, "New message $messageStr for Instance: $instance")
- scope.launch {
- try {
- parseMessage(messageStr)?.let { receiveIfNew(it) }
- } catch (e: Exception) {
- if (e is CancellationException) throw e
- Log.d(TAG, "Message could not be parsed: ${e.message}")
- }
- }
- }
-
- private suspend fun parseMessage(message: String): GiftWrapEvent? {
- (Event.fromJson(message) as? GiftWrapEvent)?.let {
- return it
- }
- return null
- }
-
- private suspend fun receiveIfNew(event: GiftWrapEvent) {
- if (eventCache.get(event.id) == null) {
- eventCache.put(event.id, event.id)
- EventNotificationConsumer(appContext).consume(event)
- }
- }
-
- override fun onNewEndpoint(
- context: Context,
- endpoint: String,
- instance: String,
- ) {
- Log.d(TAG, "New endpoint provided:- $endpoint for Instance: $instance")
- val sanitizedEndpoint = if (endpoint.endsWith("?up=1")) endpoint.dropLast(5) else endpoint
- if (pushHandler.getSavedEndpoint() == sanitizedEndpoint) {
- Log.d(TAG, "Endpoint already saved. ")
- return
- }
- pushHandler.setEndpoint(sanitizedEndpoint)
- scope.launch(Dispatchers.IO) {
- RegisterAccounts(LocalPreferences.allSavedAccounts(context)).go(sanitizedEndpoint)
- NotificationUtils.getOrCreateDMChannel(appContext)
- }
- }
-
- override fun onRegistrationFailed(
- context: Context,
- instance: String,
- ) {
- Log.d(TAG, "Registration failed for Instance: $instance")
-
- LocalPreferences.allSavedAccounts(context).forEach {
- NostrSigner.getInstance().getDatabase(it.npub).applicationDao().insertLog(
- LogEntity(
- 0,
- "Push server",
- "Push server",
- "Registration failed for Instance: $instance",
- System.currentTimeMillis(),
- ),
- )
- }
-
- scope.cancel()
- pushHandler.forceRemoveDistributor(context)
- }
-
- override fun onUnregistered(
- context: Context,
- instance: String,
- ) {
- val removedEndpoint = pushHandler.getSavedEndpoint()
- Log.d(TAG, "Endpoint: $removedEndpoint removed for Instance: $instance")
- Log.d(TAG, "App is unregistered. ")
- pushHandler.forceRemoveDistributor(context)
- pushHandler.removeEndpoint()
- }
-}
diff --git a/app/src/free/java/com/greenart7c3/nostrsigner/service/PushNotificationUtils.kt b/app/src/free/java/com/greenart7c3/nostrsigner/service/PushNotificationUtils.kt
deleted file mode 100644
index 784854e4..00000000
--- a/app/src/free/java/com/greenart7c3/nostrsigner/service/PushNotificationUtils.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * Copyright (c) 2024 Vitor Pamplona
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
- * Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-package com.greenart7c3.nostrsigner.service
-
-import android.content.Intent
-import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
-import android.net.Uri
-import android.util.Log
-import com.greenart7c3.nostrsigner.AccountInfo
-import com.greenart7c3.nostrsigner.LocalPreferences
-import com.greenart7c3.nostrsigner.NostrSigner
-import com.greenart7c3.nostrsigner.R
-import com.greenart7c3.nostrsigner.database.LogEntity
-import com.greenart7c3.nostrsigner.ui.AccountStateViewModel
-import com.greenart7c3.nostrsigner.ui.NotificationType
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-
-object PushNotificationUtils {
- var hasInit: Boolean = false
- private val pushHandler = PushDistributorHandler
- var accountState: AccountStateViewModel? = null
-
- @OptIn(DelicateCoroutinesApi::class)
- suspend fun init(accounts: List) {
- if (hasInit || NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
- return
- }
-
- val savedDistributor = pushHandler.getSavedDistributor()
- if (savedDistributor.isBlank()) {
- val distributions = pushHandler.getInstalledDistributors()
- if (distributions.isNotEmpty()) {
- distributions.firstOrNull { it.isNotBlank() }?.let {
- pushHandler.saveDistributor(it)
- }
- } else {
- accounts.forEach {
- NostrSigner.getInstance().getDatabase(it.npub).applicationDao().insertLog(
- LogEntity(
- 0,
- "Push server",
- "Push server",
- "No distributors found for push notifications",
- System.currentTimeMillis(),
- ),
- )
- }
- if (!NostrSigner.getInstance().settings.pushServerMessage && NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT) {
- accountState?.toast(
- title = NostrSigner.getInstance().getString(R.string.push_server),
- message = NostrSigner.getInstance().getString(R.string.no_distributors_found),
- onOk = {
- GlobalScope.launch(Dispatchers.IO) {
- NostrSigner.getInstance().settings = NostrSigner.getInstance().settings.copy(pushServerMessage = true)
- LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
- }
-
- val intent = Intent(Intent.ACTION_VIEW)
- intent.data = Uri.parse("https://ntfy.sh/")
- intent.flags = FLAG_ACTIVITY_NEW_TASK
- NostrSigner.getInstance().startActivity(intent)
- },
- )
- }
- }
- }
- try {
- if (pushHandler.savedDistributorExists()) {
- val endpoint = pushHandler.getSavedEndpoint()
- if (endpoint.isBlank()) {
- pushHandler.saveDistributor(pushHandler.getSavedDistributor())
- }
-
- RegisterAccounts(accounts).go(pushHandler.getSavedEndpoint())
- }
- } catch (e: Exception) {
- if (e is CancellationException) throw e
- Log.d("Amber-OSSPushUtils", "Failed to get endpoint.")
- accounts.forEach {
- NostrSigner.getInstance().getDatabase(it.npub).applicationDao().insertLog(
- LogEntity(
- 0,
- "Push server",
- "Push server",
- "Failed to get endpoint. ${e.message}",
- System.currentTimeMillis(),
- ),
- )
- }
- }
- }
-}
diff --git a/app/src/free/java/com/greenart7c3/nostrsigner/ui/SelectNotificationProvider.kt b/app/src/free/java/com/greenart7c3/nostrsigner/ui/SelectNotificationProvider.kt
deleted file mode 100644
index 012790e9..00000000
--- a/app/src/free/java/com/greenart7c3/nostrsigner/ui/SelectNotificationProvider.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * Copyright (c) 2024 Vitor Pamplona
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
- * Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-package com.greenart7c3.nostrsigner.ui
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.stringResource
-import com.greenart7c3.nostrsigner.R
-import com.greenart7c3.nostrsigner.service.PushDistributorHandler
-import com.greenart7c3.nostrsigner.ui.components.TitleExplainer
-import kotlinx.collections.immutable.ImmutableList
-import kotlinx.collections.immutable.toImmutableList
-
-@Composable
-fun LoadDistributors(onInner: @Composable (String, ImmutableList, ImmutableList) -> Unit) {
- val currentDistributor = PushDistributorHandler.getSavedDistributor().ifBlank { null } ?: "None"
-
- val list =
- remember {
- PushDistributorHandler.getInstalledDistributors().plus("None").toImmutableList()
- }
-
- val readableListWithExplainer =
- PushDistributorHandler
- .formattedDistributorNames()
- .mapIndexed { index, name ->
- TitleExplainer(
- name,
- stringResource(id = R.string.push_server_uses_app_explainer, list[index]),
- )
- }.plus(
- TitleExplainer(
- stringResource(id = R.string.push_server_none),
- stringResource(id = R.string.push_server_none_explainer),
- ),
- )
- .toImmutableList()
-
- onInner(
- currentDistributor,
- list,
- readableListWithExplainer,
- )
-}
-
-@Composable
-fun PushNotificationSettingsRow() {
- val context = LocalContext.current
- LoadDistributors { currentDistributor, list, readableListWithExplainer ->
- SettingsRow(
- R.string.push_server_title,
- R.string.push_server_explainer,
- selectedItems = readableListWithExplainer,
- selectedIndex = list.indexOf(currentDistributor),
- ) { index ->
- if (list[index] == "None") {
- PushDistributorHandler.forceRemoveDistributor(context)
- } else {
- PushDistributorHandler.saveDistributor(list[index])
- }
- }
- }
-}
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt b/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt
index b7c27c6d..896b32df 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt
@@ -11,7 +11,6 @@ import com.greenart7c3.nostrsigner.database.ApplicationPermissionsEntity
import com.greenart7c3.nostrsigner.models.Account
import com.greenart7c3.nostrsigner.models.AmberSettings
import com.greenart7c3.nostrsigner.ui.parseBiometricsTimeType
-import com.greenart7c3.nostrsigner.ui.parseNotificationType
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.ammolite.relays.RelaySetupInfo
import com.vitorpamplona.ammolite.service.HttpClientManager
@@ -116,7 +115,6 @@ object LocalPreferences {
putStringSet(PrefKeys.DEFAULT_RELAYS, settings.defaultRelays.map { it.url }.toSet())
putLong(PrefKeys.LAST_BIOMETRICS_TIME, settings.lastBiometricsTime)
putBoolean(PrefKeys.USE_AUTH, settings.useAuth)
- putInt(PrefKeys.NOTIFICATION_TYPE, settings.notificationType.screenCode)
putInt(PrefKeys.BIOMETRICS_TYPE, settings.biometricsTimeType.screenCode)
putBoolean(PrefKeys.USE_PIN, settings.usePin)
}.apply()
@@ -156,7 +154,6 @@ object LocalPreferences {
} ?: listOf(RelaySetupInfo("wss://relay.nsec.app", read = true, write = true, feedTypes = COMMON_FEED_TYPES)),
lastBiometricsTime = getLong(PrefKeys.LAST_BIOMETRICS_TIME, 0),
useAuth = getBoolean(PrefKeys.USE_AUTH, false),
- notificationType = parseNotificationType(getInt(PrefKeys.NOTIFICATION_TYPE, 1)),
biometricsTimeType = parseBiometricsTimeType(getInt(PrefKeys.BIOMETRICS_TYPE, 0)),
usePin = getBoolean(PrefKeys.USE_PIN, false),
)
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/NostrSigner.kt b/app/src/main/java/com/greenart7c3/nostrsigner/NostrSigner.kt
index 93ee2751..90ba7e3f 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/NostrSigner.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/NostrSigner.kt
@@ -12,9 +12,7 @@ import com.greenart7c3.nostrsigner.database.AppDatabase
import com.greenart7c3.nostrsigner.models.AmberSettings
import com.greenart7c3.nostrsigner.service.ConnectivityService
import com.greenart7c3.nostrsigner.service.RelayDisconnectService
-import com.greenart7c3.nostrsigner.ui.NotificationType
import com.vitorpamplona.ammolite.relays.Client
-import com.vitorpamplona.ammolite.relays.Relay
import com.vitorpamplona.ammolite.relays.RelayPool
import com.vitorpamplona.ammolite.relays.RelaySetupInfo
import com.vitorpamplona.ammolite.relays.RelaySetupInfoToConnect
@@ -122,28 +120,11 @@ class NostrSigner : Application() {
LocalPreferences.loadFromEncryptedStorage(this, it.npub)?.useProxy ?: false
}
- if (settings.notificationType != NotificationType.DIRECT) {
- RelayPool.register(Client)
- savedRelays.forEach { setupInfo ->
- if (RelayPool.getRelay(setupInfo.url) == null) {
- RelayPool.addRelay(
- Relay(
- setupInfo.url,
- setupInfo.read,
- setupInfo.write,
- if (isPrivateIp(setupInfo.url)) false else useProxy,
- setupInfo.feedTypes,
- ),
- )
- }
- }
- }
-
if (shouldReconnect) {
checkIfRelaysAreConnected()
}
@Suppress("KotlinConstantConditions")
- if (settings.notificationType == NotificationType.DIRECT && BuildConfig.FLAVOR != "offline" && savedRelays.isNotEmpty()) {
+ if (BuildConfig.FLAVOR != "offline" && savedRelays.isNotEmpty()) {
Client.reconnect(
savedRelays.map { RelaySetupInfoToConnect(it.url, if (isPrivateIp(it.url)) false else useProxy, it.read, it.write, it.feedTypes) }.toTypedArray(),
true,
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 83cba61c..bd002945 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/ApplicationDao.kt
@@ -26,6 +26,9 @@ interface ApplicationDao {
@Query("SELECT * FROM application where pubKey = :pubKey order by name")
fun getAll(pubKey: String): List
+ @Query("SELECT * FROM application where pubKey = :pubKey order by name")
+ fun getAllFlow(pubKey: String): Flow>
+
@Query("SELECT * FROM application WHERE `key` = :key")
@Transaction
fun getByKey(key: String): ApplicationWithPermissions?
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/models/AmberSettings.kt b/app/src/main/java/com/greenart7c3/nostrsigner/models/AmberSettings.kt
index 16836a6c..2e6a6c57 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/models/AmberSettings.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/models/AmberSettings.kt
@@ -1,7 +1,6 @@
package com.greenart7c3.nostrsigner.models
import com.greenart7c3.nostrsigner.ui.BiometricsTimeType
-import com.greenart7c3.nostrsigner.ui.NotificationType
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.ammolite.relays.RelaySetupInfo
@@ -11,7 +10,6 @@ data class AmberSettings(
val defaultRelays: List = listOf(RelaySetupInfo("wss://relay.nsec.app", read = true, write = true, feedTypes = COMMON_FEED_TYPES)),
val lastBiometricsTime: Long = 0,
val useAuth: Boolean = false,
- val notificationType: NotificationType = NotificationType.DIRECT,
val biometricsTimeType: BiometricsTimeType = BiometricsTimeType.EVERY_TIME,
val usePin: Boolean = false,
)
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 1cafcc7f..8b7855ea 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/service/ConnectivityService.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/ConnectivityService.kt
@@ -13,10 +13,8 @@ import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import com.greenart7c3.nostrsigner.BuildConfig
-import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.NostrSigner
import com.greenart7c3.nostrsigner.R
-import com.greenart7c3.nostrsigner.ui.NotificationType
import com.vitorpamplona.ammolite.relays.RelayPool
import java.util.Timer
import java.util.TimerTask
@@ -40,7 +38,7 @@ class ConnectivityService : Service() {
@Suppress("KotlinConstantConditions")
if (BuildConfig.FLAVOR == "offline") return
- if (lastNetwork != null && lastNetwork != network && NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
+ if (lastNetwork != null && lastNetwork != network) {
scope.launch(Dispatchers.IO) {
NotificationDataSource.stopSync()
delay(1000)
@@ -66,7 +64,7 @@ class ConnectivityService : Service() {
"ServiceManager NetworkCallback",
"onCapabilitiesChanged: ${network.networkHandle} hasMobileData ${NostrSigner.getInstance().isOnMobileDataState.value} hasWifi ${NostrSigner.getInstance().isOnWifiDataState.value}",
)
- if (NostrSigner.getInstance().updateNetworkCapabilities(networkCapabilities) && NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
+ if (NostrSigner.getInstance().updateNetworkCapabilities(networkCapabilities)) {
NotificationDataSource.stopSync()
delay(1000)
NotificationDataSource.start()
@@ -101,11 +99,6 @@ class ConnectivityService : Service() {
isStarted = true
startForeground(1, createNotification())
- scope.launch(Dispatchers.IO) {
- PushNotificationUtils.hasInit = false
- PushNotificationUtils.init(LocalPreferences.allSavedAccounts(this@ConnectivityService))
- }
-
@Suppress("KotlinConstantConditions")
if (BuildConfig.FLAVOR != "offline") {
val connectivityManager =
@@ -119,9 +112,11 @@ class ConnectivityService : Service() {
timer.schedule(
object : TimerTask() {
override fun run() {
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.PUSH) return
+ @Suppress("KotlinConstantConditions")
+ if (BuildConfig.FLAVOR == "offline") {
+ return
+ }
- Log.d("ConnectivityService", "Checking connectivity...")
RelayPool.getAll().forEach {
if (!it.isConnected()) {
Log.d(
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 51fa1522..f38688ad 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt
@@ -42,13 +42,10 @@ import com.greenart7c3.nostrsigner.models.Permission
import com.greenart7c3.nostrsigner.models.SignerType
import com.greenart7c3.nostrsigner.service.NotificationUtils.sendNotification
import com.greenart7c3.nostrsigner.service.model.AmberEvent
-import com.greenart7c3.nostrsigner.ui.NotificationType
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 com.vitorpamplona.quartz.events.GiftWrapEvent
-import com.vitorpamplona.quartz.events.SealedGossipEvent
class EventNotificationConsumer(private val applicationContext: Context) {
@@ -64,61 +61,6 @@ class EventNotificationConsumer(private val applicationContext: Context) {
}
}
- fun consume(event: GiftWrapEvent) {
- if (!notificationManager().areNotificationsEnabled()) return
- if (!event.hasCorrectIDHash()) return
- if (!event.hasVerifiedSignature()) return
-
- // PushNotification Wraps don't include a receiver.
- // Test with all logged in accounts
- LocalPreferences.allSavedAccounts(applicationContext).forEach {
- if (it.hasPrivKey) {
- LocalPreferences.loadFromEncryptedStorage(applicationContext, it.npub)?.let { acc ->
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.PUSH) {
- consumeIfMatchesAccount(event, acc)
- }
- }
- }
- }
- }
-
- private fun consumeIfMatchesAccount(
- pushWrappedEvent: GiftWrapEvent,
- account: Account,
- ) {
- pushWrappedEvent.unwrap(account.signer) { notificationEvent ->
- unwrapAndConsume(notificationEvent, account) { innerEvent ->
- if (innerEvent.kind == 24133) {
- if (innerEvent.hasCorrectIDHash()) {
- if (innerEvent.hasVerifiedSignature()) {
- notify(innerEvent, account)
- }
- }
- }
- }
- }
- }
-
- private fun unwrapAndConsume(
- event: Event,
- account: Account,
- onReady: (Event) -> Unit,
- ) {
- when (event) {
- is GiftWrapEvent -> {
- event.unwrap(account.signer) { unwrapAndConsume(it, account, onReady) }
- }
- is SealedGossipEvent -> {
- event.unseal(account.signer) {
- onReady(it)
- }
- }
- else -> {
- onReady(event)
- }
- }
- }
-
private fun notify(
event: Event,
acc: Account,
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 7d88c09a..e20b6cf1 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt
@@ -34,7 +34,6 @@ import com.greenart7c3.nostrsigner.models.TimeUtils
import com.greenart7c3.nostrsigner.models.containsNip
import com.greenart7c3.nostrsigner.relays.AmberListenerSingleton
import com.greenart7c3.nostrsigner.service.model.AmberEvent
-import com.greenart7c3.nostrsigner.ui.NotificationType
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.ammolite.relays.Client
import com.vitorpamplona.ammolite.relays.RelayPool
@@ -388,15 +387,11 @@ object IntentUtils {
GlobalScope.launch(Dispatchers.IO) {
if (RelayPool.getAll().any { !it.isConnected() }) {
NostrSigner.getInstance().checkForNewRelays(
- NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT,
newRelays = relays.toSet(),
)
}
val success = Client.sendAndWaitForResponse(it, relayList = relays)
- if (NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT) {
- RelayPool.unregister(Client)
- }
if (success) {
onDone()
}
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 a0ae9a17..84fdc07a 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationDataSource.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/NotificationDataSource.kt
@@ -25,7 +25,6 @@ import com.greenart7c3.nostrsigner.NostrSigner
import com.greenart7c3.nostrsigner.checkNotInMainThread
import com.greenart7c3.nostrsigner.database.LogEntity
import com.greenart7c3.nostrsigner.models.TimeUtils
-import com.greenart7c3.nostrsigner.ui.NotificationType
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.ammolite.relays.Client
import com.vitorpamplona.ammolite.relays.NostrDataSource
@@ -143,9 +142,7 @@ object NotificationDataSource : NostrDataSource("AccountData") {
init {
scope.launch {
LocalPreferences.loadSettingsFromEncryptedStorage()
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
- Client.subscribe(clientListener)
- }
+ Client.subscribe(clientListener)
}
}
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/RegisterAccounts.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/RegisterAccounts.kt
deleted file mode 100644
index b12fb200..00000000
--- a/app/src/main/java/com/greenart7c3/nostrsigner/service/RegisterAccounts.kt
+++ /dev/null
@@ -1,228 +0,0 @@
-/**
- * Copyright (c) 2024 Vitor Pamplona
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
- * Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-package com.greenart7c3.nostrsigner.service
-
-import android.util.Log
-import com.greenart7c3.nostrsigner.AccountInfo
-import com.greenart7c3.nostrsigner.BuildConfig
-import com.greenart7c3.nostrsigner.LocalPreferences
-import com.greenart7c3.nostrsigner.NostrSigner
-import com.greenart7c3.nostrsigner.database.LogEntity
-import com.greenart7c3.nostrsigner.models.Account
-import com.vitorpamplona.ammolite.service.HttpClientManager
-import com.vitorpamplona.quartz.encoders.toHexKey
-import com.vitorpamplona.quartz.encoders.toNpub
-import com.vitorpamplona.quartz.events.RelayAuthEvent
-import java.net.URL
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withContext
-import okhttp3.MediaType.Companion.toMediaType
-import okhttp3.Request
-import okhttp3.RequestBody.Companion.toRequestBody
-
-class RegisterAccounts(
- private val accounts: List,
-) {
- private fun recursiveAuthCreation(
- notificationToken: String,
- remainingTos: List>,
- output: MutableList,
- onReady: (List) -> Unit,
- ) {
- if (remainingTos.isEmpty()) {
- onReady(output)
- return
- }
-
- val next = remainingTos.first()
-
- next.first.createAuthEvent(next.second, notificationToken) {
- output.add(it)
- recursiveAuthCreation(notificationToken, remainingTos.filter { remainingTo -> next != remainingTo }, output, onReady)
- }
- }
-
- private fun isSupportedUrl(url: String): Boolean {
- return url.isNotBlank() &&
- !url.contains("brb.io") && // no broken relays
- !url.contains("echo.websocket.org") && // test relay
- !url.contains("127.0") && // no local relays
- !url.contains("umbrel.local") && // no local relays
- !url.contains("192.168.") && // no local relays
- !url.contains(".onion") && // we are not running on Tor
- !url.contains("https://") && // not a websocket
- !url.contains("http://") && // not a websocket
- !url.contains("www://") && // not a websocket
- !url.contains("https//") && // not a websocket
- !url.contains("http//") && // not a websocket
- !url.contains("www//") && // not a websocket
- !url.contains("npub1") && // does not allow custom uris
- !url.contains("was://") && // common mispellings
- !url.contains("ws://umbrel:") && // local domain
- !url.contains("\t") && // tab is not allowed
- !url.contains(" ") && // space is not allowed
- isValidUrl(url)
- }
-
- private fun isValidUrl(url: String): Boolean {
- try {
- URL(url.replace("wss://", "https://").replace("ws://", "http://"))
- return true
- } catch (e: Exception) {
- return false
- }
- }
-
- // creates proof that it controls all accounts
- private fun signEventsToProveControlOfAccounts(
- accounts: List,
- notificationToken: String,
- onReady: (List) -> Unit,
- ) {
- val readyToSend: MutableSet> = mutableSetOf()
- accounts.forEach {
- val acc = LocalPreferences.loadFromEncryptedStorage(NostrSigner.getInstance(), it.npub)
- if (acc != null) {
- val permissions =
- NostrSigner.getInstance().getDatabase(
- acc.signer.keyPair.pubKey.toNpub(),
- ).applicationDao().getAll(acc.signer.keyPair.pubKey.toHexKey())
- permissions.forEach { permission ->
- permission.relays.forEach { relay ->
- if (isSupportedUrl(relay.url)) {
- readyToSend.add(
- Pair(acc, relay.url),
- )
- }
- }
- }
-
- runBlocking {
- LocalPreferences.loadSettingsFromEncryptedStorage()
- }
- val defaultRelays = NostrSigner.getInstance().settings.defaultRelays
- defaultRelays.forEach { relay ->
- if (isSupportedUrl(relay.url)) {
- readyToSend.add(
- Pair(acc, relay.url),
- )
- }
- }
- }
- }
-
- val listOfAuthEvents = mutableListOf()
- recursiveAuthCreation(
- notificationToken,
- readyToSend.toList(),
- listOfAuthEvents,
- onReady,
- )
- }
-
- private fun postRegistrationEvent(events: List, notificationToken: String) {
- if (notificationToken.isBlank()) {
- Log.d("FirebaseMsgService", "No notification token to register with push server")
- return
- }
- try {
- val jsonObject =
- """{
- "events": [ ${events.joinToString(", ") { it.toJson() }} ]
- }
- """
-
- val mediaType = "application/json; charset=utf-8".toMediaType()
- val body = jsonObject.toRequestBody(mediaType)
-
- val request =
- Request.Builder()
- .header("User-Agent", "Amber/${BuildConfig.VERSION_NAME}")
- .url("https://push.greenart7c3.com/register")
- .post(body)
- .build()
-
- val useProxy = accounts.any {
- val account = LocalPreferences.loadFromEncryptedStorage(context = NostrSigner.getInstance(), npub = it.npub)
- val useProxy = account?.useProxy ?: false
-
- if (useProxy) {
- HttpClientManager.setDefaultProxyOnPort(account?.proxyPort ?: 9050)
- }
-
- useProxy
- }
-
- val client = HttpClientManager.getHttpClient(useProxy)
- var isSuccess = client.newCall(request).execute().use {
- it.isSuccessful
- }
- var tries = 0
- while (!isSuccess && tries < 3) {
- Log.d("FirebaseMsgService", "Failed to register with push server, retrying...")
- isSuccess = client.newCall(request).execute().use {
- it.isSuccessful
- }
- tries++
- }
- if (isSuccess) {
- Log.d("FirebaseMsgService", "Successfully registered with push server")
- } else {
- accounts.forEach {
- NostrSigner.getInstance().getDatabase(it.npub).applicationDao().insertLog(
- LogEntity(
- 0,
- "Push server",
- "Push server",
- "Failed to register with push server",
- System.currentTimeMillis(),
- ),
- )
- }
- }
- } catch (e: java.lang.Exception) {
- if (e is CancellationException) throw e
- val tag = "FirebaseMsgService"
-
- Log.e(tag, "Unable to register with push server", e)
- accounts.forEach {
- NostrSigner.getInstance().getDatabase(it.npub).applicationDao().insertLog(
- LogEntity(
- 0,
- "Push server",
- "Push server",
- "Unable to register with push server: ${e.message}",
- System.currentTimeMillis(),
- ),
- )
- }
- }
- }
-
- suspend fun go(notificationToken: String) =
- withContext(Dispatchers.IO) {
- signEventsToProveControlOfAccounts(accounts, notificationToken) { postRegistrationEvent(it, notificationToken) }
-
- PushNotificationUtils.hasInit = true
- }
-}
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountScreen.kt
index 7608c6d2..b0f36662 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountScreen.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/AccountScreen.kt
@@ -9,8 +9,6 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
@@ -19,10 +17,7 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults
-import androidx.compose.material3.CenterAlignedTopAppBar
-import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
-import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -49,14 +44,12 @@ import com.greenart7c3.nostrsigner.relays.AmberListenerSingleton
import com.greenart7c3.nostrsigner.service.ConnectivityService
import com.greenart7c3.nostrsigner.service.IntentUtils
import com.greenart7c3.nostrsigner.service.NotificationDataSource
-import com.greenart7c3.nostrsigner.service.PushNotificationUtils
import com.vitorpamplona.quartz.encoders.toNpub
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
-@OptIn(ExperimentalMaterial3Api::class)
@SuppressLint("StateFlowValueCalledInComposition", "UnrememberedMutableState")
@Composable
fun AccountScreen(
@@ -82,115 +75,69 @@ fun AccountScreen(
MainLoginPage(accountStateViewModel)
}
is AccountState.LoggedIn -> {
- var isLoading by remember { mutableStateOf(true) }
- var isNotificationsConfigured by remember {
- mutableStateOf(false)
+ var intentData by remember {
+ mutableStateOf(null)
}
- LaunchedEffect(Unit) {
- launch(Dispatchers.IO) {
- isNotificationsConfigured = LocalPreferences.isNotificationTypeConfigured()
- isLoading = false
+ LaunchedEffect(intent, intents) {
+ IntentUtils.getIntentData(context, intent, packageName, intent.getStringExtra("route"), state.account) {
+ intentData = it
+ }
+ val data =
+ intents.firstOrNull {
+ it.currentAccount.isNotBlank()
+ }
+
+ data?.bunkerRequest?.let {
+ if (it.currentAccount.isNotBlank()) {
+ if (LocalPreferences.currentAccount(context) != it.currentAccount) {
+ accountStateViewModel.switchUser(it.currentAccount, null)
+ }
+ }
}
}
- if (isLoading) {
- Scaffold { innerPadding ->
- CenterCircularProgressIndicator(
- Modifier
- .fillMaxSize()
- .padding(innerPadding),
- )
+ if (intentData != null) {
+ if (intents.none { item -> item.id == intentData!!.id }) {
+ val oldIntents = intents.toMutableList()
+ oldIntents.add(intentData!!)
+ flow.value = oldIntents
}
- } else {
- if (isNotificationsConfigured) {
- var intentData by remember {
- mutableStateOf(null)
+ }
+
+ val newIntents =
+ intents.ifEmpty {
+ if (intentData == null) {
+ listOf()
+ } else {
+ listOf(intentData)
}
- LaunchedEffect(intent, intents) {
- IntentUtils.getIntentData(context, intent, packageName, intent.getStringExtra("route"), state.account) {
- intentData = it
- }
- val data =
- intents.firstOrNull {
- it.currentAccount.isNotBlank()
- }
+ }.mapNotNull { it }
+ val database = NostrSigner.getInstance().getDatabase(state.account.signer.keyPair.pubKey.toNpub())
+ val localRoute = mutableStateOf(newIntents.firstNotNullOfOrNull { it.route } ?: state.route)
- data?.bunkerRequest?.let {
- if (it.currentAccount.isNotBlank()) {
- if (LocalPreferences.currentAccount(context) != it.currentAccount) {
- accountStateViewModel.switchUser(it.currentAccount, null)
- }
- }
- }
- }
-
- if (intentData != null) {
- if (intents.none { item -> item.id == intentData!!.id }) {
- val oldIntents = intents.toMutableList()
- oldIntents.add(intentData!!)
- flow.value = oldIntents
- }
- }
-
- val newIntents =
- intents.ifEmpty {
- if (intentData == null) {
- listOf()
- } else {
- listOf(intentData)
- }
- }.mapNotNull { it }
- val database = NostrSigner.getInstance().getDatabase(state.account.signer.keyPair.pubKey.toNpub())
- val localRoute = mutableStateOf(newIntents.firstNotNullOfOrNull { it.route } ?: state.route)
-
- SideEffect {
- NostrSigner.getInstance().applicationIOScope.launch(Dispatchers.IO) {
- PushNotificationUtils.accountState = accountStateViewModel
- try {
- NostrSigner.getInstance().applicationContext.startForegroundService(
- Intent(NostrSigner.getInstance().applicationContext, ConnectivityService::class.java),
- )
- } catch (e: Exception) {
- Log.d("NostrSigner", "Failed to start ConnectivityService", e)
- }
-
- @Suppress("KotlinConstantConditions")
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT && BuildConfig.FLAVOR != "offline") {
- NostrSigner.getInstance().checkForNewRelays()
- NotificationDataSource.start()
- delay(5000)
- }
- }
- }
-
- AmberListenerSingleton.accountStateViewModel = accountStateViewModel
-
- DisplayErrorMessages(accountStateViewModel)
- MainScreen(state.account, accountStateViewModel, newIntents, packageName, appName, localRoute, database, navController)
- } else {
- AmberListenerSingleton.accountStateViewModel = accountStateViewModel
- DisplayErrorMessages(accountStateViewModel)
- Scaffold(
- topBar = {
- CenterAlignedTopAppBar(
- title = {
- Text(stringResource(R.string.notification_type))
- },
- )
- },
- ) { innerPadding ->
- NotificationTypeScreen(
- Modifier
- .fillMaxSize()
- .padding(innerPadding)
- .padding(40.dp),
- onDone = {
- isNotificationsConfigured = true
- },
+ SideEffect {
+ NostrSigner.getInstance().applicationIOScope.launch(Dispatchers.IO) {
+ try {
+ NostrSigner.getInstance().applicationContext.startForegroundService(
+ Intent(NostrSigner.getInstance().applicationContext, ConnectivityService::class.java),
)
+ } catch (e: Exception) {
+ Log.d("NostrSigner", "Failed to start ConnectivityService", e)
+ }
+
+ @Suppress("KotlinConstantConditions")
+ if (BuildConfig.FLAVOR != "offline") {
+ NostrSigner.getInstance().checkForNewRelays()
+ NotificationDataSource.start()
+ delay(5000)
}
}
}
+
+ AmberListenerSingleton.accountStateViewModel = accountStateViewModel
+
+ DisplayErrorMessages(accountStateViewModel)
+ MainScreen(state.account, accountStateViewModel, newIntents, packageName, appName, localRoute, database, navController)
}
}
}
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/EditConfigurationScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/EditConfigurationScreen.kt
index 25915684..08db35ff 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/EditConfigurationScreen.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/EditConfigurationScreen.kt
@@ -162,9 +162,8 @@ fun EditConfigurationScreen(
it.permissions,
),
)
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
- NostrSigner.getInstance().checkForNewRelays()
- }
+
+ NostrSigner.getInstance().checkForNewRelays()
}
}
},
@@ -203,9 +202,7 @@ fun EditConfigurationScreen(
it.permissions,
),
)
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
- NostrSigner.getInstance().checkForNewRelays()
- }
+ NostrSigner.getInstance().checkForNewRelays()
}
}
},
@@ -255,9 +252,7 @@ fun EditConfigurationScreen(
it.permissions,
),
)
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
- NostrSigner.getInstance().checkForNewRelays()
- }
+ NostrSigner.getInstance().checkForNewRelays()
}
}
},
@@ -280,9 +275,7 @@ fun EditConfigurationScreen(
scope.launch(Dispatchers.IO) {
database.applicationDao().delete(it.application)
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
- NostrSigner.getInstance().checkForNewRelays()
- }
+ NostrSigner.getInstance().checkForNewRelays()
scope.launch(Dispatchers.Main) {
navController.navigate(Route.Applications.route) {
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 63c6a09b..3946a486 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/MainScreen.kt
@@ -86,7 +86,6 @@ import com.greenart7c3.nostrsigner.models.TimeUtils
import com.greenart7c3.nostrsigner.models.basicPermissions
import com.greenart7c3.nostrsigner.service.EventNotificationConsumer
import com.greenart7c3.nostrsigner.service.IntentUtils
-import com.greenart7c3.nostrsigner.service.PushNotificationUtils
import com.greenart7c3.nostrsigner.service.getAppCompatActivity
import com.greenart7c3.nostrsigner.ui.actions.AccountBackupScreen
import com.greenart7c3.nostrsigner.ui.actions.AccountsBottomSheet
@@ -131,8 +130,7 @@ fun sendResult(
val relays = savedApplication?.application?.relays?.ifEmpty { defaultRelays } ?: (intentData.bunkerRequest?.relays?.ifEmpty { defaultRelays } ?: defaultRelays)
if (intentData.bunkerRequest != null) {
NostrSigner.getInstance().checkForNewRelays(
- NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT,
- relays.toSet(),
+ newRelays = relays.toSet(),
)
}
@@ -259,10 +257,6 @@ fun sendResult(
true,
),
)
- PushNotificationUtils.hasInit = false
- GlobalScope.launch(Dispatchers.IO) {
- PushNotificationUtils.init(LocalPreferences.allSavedAccounts(context))
- }
EventNotificationConsumer(context).notificationManager().cancelAll()
activity?.intent = null
@@ -375,9 +369,6 @@ private suspend fun askNotificationPermission(
onShouldShowRequestPermissionRationale: () -> Unit,
) {
if (ContextCompat.checkSelfPermission(context, "android.permission.POST_NOTIFICATIONS") == PackageManager.PERMISSION_GRANTED) {
- initNotifications(
- context = context,
- )
return
}
@@ -398,11 +389,6 @@ private suspend fun askNotificationPermission(
}
}
-private suspend fun initNotifications(context: Context) {
- PushNotificationUtils.hasInit = false
- PushNotificationUtils.init(LocalPreferences.allSavedAccounts(context))
-}
-
fun Color.Companion.fromHex(colorString: String) = try {
Color(android.graphics.Color.parseColor("#$colorString"))
} catch (e: Exception) {
@@ -431,13 +417,7 @@ fun MainScreen(
rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission(),
) { isGranted: Boolean ->
- if (isGranted) {
- scope.launch(Dispatchers.IO) {
- initNotifications(
- context = context,
- )
- }
- } else {
+ if (!isGranted) {
if (LocalPreferences.shouldShowRationale(context) == null) {
LocalPreferences.updateShouldShowRationale(context, true)
}
@@ -682,7 +662,6 @@ fun MainScreen(
.padding(padding)
.padding(24.dp),
account = account,
- accountStateViewModel = accountStateViewModel,
navController = navController,
database = database,
)
@@ -779,22 +758,6 @@ fun MainScreen(
},
)
- composable(
- Route.NotificationType.route,
- content = {
- NotificationTypeScreen(
- modifier =
- Modifier
- .fillMaxSize()
- .padding(padding)
- .padding(40.dp),
- onDone = {
- navController.navigateUp()
- },
- )
- },
- )
-
composable(
Route.DefaultRelays.route,
content = {
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/NotificationTypeScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/NotificationTypeScreen.kt
deleted file mode 100644
index d748be56..00000000
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/NotificationTypeScreen.kt
+++ /dev/null
@@ -1,133 +0,0 @@
-package com.greenart7c3.nostrsigner.ui
-
-import android.content.Intent
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableIntStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
-import com.greenart7c3.nostrsigner.BuildConfig
-import com.greenart7c3.nostrsigner.LocalPreferences
-import com.greenart7c3.nostrsigner.NostrSigner
-import com.greenart7c3.nostrsigner.R
-import com.greenart7c3.nostrsigner.relays.AmberListenerSingleton
-import com.greenart7c3.nostrsigner.service.ConnectivityService
-import com.greenart7c3.nostrsigner.service.NotificationDataSource
-import com.greenart7c3.nostrsigner.service.PushNotificationUtils
-import com.greenart7c3.nostrsigner.ui.components.AmberButton
-import com.greenart7c3.nostrsigner.ui.components.TitleExplainer
-import com.vitorpamplona.ammolite.relays.RelayPool
-import kotlinx.collections.immutable.persistentListOf
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-
-@Composable
-fun NotificationTypeScreen(
- modifier: Modifier = Modifier,
- onDone: () -> Unit,
-) {
- val context = LocalContext.current
-
- LaunchedEffect(Unit) {
- launch(Dispatchers.IO) {
- if (!LocalPreferences.isNotificationTypeConfigured()) {
- AmberListenerSingleton.accountStateViewModel?.toast(
- context.getString(R.string.notification_settings),
- context.getString(R.string.please_configure_your_notification_settings_before_continuing),
- )
- }
- }
- }
-
- val scope = rememberCoroutineScope()
- var notificationItemsIndex by remember {
- mutableIntStateOf(NostrSigner.getInstance().settings.notificationType.screenCode)
- }
- val notificationItems =
- persistentListOf(
- TitleExplainer(
- stringResource(NotificationType.PUSH.resourceId),
- stringResource(R.string.push_notifications_explainer),
- ),
- TitleExplainer(
- stringResource(NotificationType.DIRECT.resourceId),
- stringResource(R.string.direct_notifications_explainer),
- ),
- )
- Column(
- modifier = modifier
- .fillMaxSize(),
- ) {
- Column(
- Modifier.weight(1f),
- ) {
- Box(
- Modifier
- .padding(8.dp),
- ) {
- SettingsRow(
- R.string.notification_type,
- R.string.select_the_type_of_notification_you_want_to_receive,
- notificationItems,
- notificationItemsIndex,
- ) {
- notificationItemsIndex = it
- }
- }
-
- @Suppress("KotlinConstantConditions")
- if (BuildConfig.FLAVOR == "free") {
- Box(
- Modifier
- .padding(8.dp),
- ) {
- PushNotificationSettingsRow()
- }
- }
- }
- AmberButton(
- onClick = {
- scope.launch(Dispatchers.IO) {
- NostrSigner.getInstance().settings = NostrSigner.getInstance().settings.copy(
- notificationType = parseNotificationType(notificationItemsIndex),
- )
- LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
- PushNotificationUtils.hasInit = false
- PushNotificationUtils.init(LocalPreferences.allSavedAccounts(context))
- if (notificationItemsIndex == 0) {
- NotificationDataSource.stopSync()
- RelayPool.disconnect()
- } else {
- NostrSigner.getInstance().checkForNewRelays()
- NotificationDataSource.start()
- }
- NostrSigner.getInstance().applicationContext.startForegroundService(
- Intent(
- NostrSigner.getInstance().applicationContext,
- ConnectivityService::class.java,
- ),
- )
- scope.launch(Dispatchers.Main) {
- onDone()
- }
- }
- },
- content = {
- Text(
- text = stringResource(R.string.save),
- )
- },
- )
- }
-}
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/PermissionsScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/PermissionsScreen.kt
index f8dfa983..dd7ddbcb 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/PermissionsScreen.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/PermissionsScreen.kt
@@ -12,57 +12,35 @@ import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
-import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.R
import com.greenart7c3.nostrsigner.database.AppDatabase
-import com.greenart7c3.nostrsigner.database.ApplicationEntity
import com.greenart7c3.nostrsigner.models.Account
import com.greenart7c3.nostrsigner.service.toShortenHex
import com.vitorpamplona.quartz.encoders.toHexKey
-import com.vitorpamplona.quartz.encoders.toNpub
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
@Composable
fun PermissionsScreen(
modifier: Modifier,
account: Account,
- accountStateViewModel: AccountStateViewModel,
navController: NavController,
database: AppDatabase,
) {
- val lifecycleEvent = rememberLifecycleEvent()
- val context = LocalContext.current
- val localAccount = LocalPreferences.loadFromEncryptedStorage(context, account.signer.keyPair.pubKey.toNpub())!!
- val applications =
- remember {
- mutableListOf()
- }
- val scope = rememberCoroutineScope()
- // val sortBy by remember { mutableStateOf("name") }
-
- LaunchedEffect(lifecycleEvent) {
- scope.launch(Dispatchers.IO) {
- applications.clear()
- applications.addAll(database.applicationDao().getAll(localAccount.signer.keyPair.pubKey.toHexKey()))
- }
- }
+ val applications = database.applicationDao().getAllFlow(account.signer.keyPair.pubKey.toHexKey()).collectAsStateWithLifecycle(emptyList())
Column(
modifier,
) {
- if (applications.isEmpty()) {
+ if (applications.value.isEmpty()) {
Column(
Modifier.fillMaxSize(),
Arrangement.Center,
@@ -100,13 +78,13 @@ fun PermissionsScreen(
// )
// }
// }
- items(applications.size) {
+ items(applications.value.size) {
Row(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 4.dp)
.clickable {
- navController.navigate("Permission/${applications.elementAt(it).key}")
+ navController.navigate("Permission/${applications.value.elementAt(it).key}")
},
verticalAlignment = Alignment.CenterVertically,
) {
@@ -115,7 +93,7 @@ fun PermissionsScreen(
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
) {
- val localPermission = applications.elementAt(it)
+ val localPermission = applications.value.elementAt(it)
Text(
modifier = Modifier.padding(top = 16.dp),
text = localPermission.name.ifBlank { localPermission.key.toShortenHex() },
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/SettingsScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/SettingsScreen.kt
index acfbcfa5..dc1a3046 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/SettingsScreen.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/SettingsScreen.kt
@@ -18,7 +18,6 @@ import androidx.compose.material.icons.filled.FilterList
import androidx.compose.material.icons.filled.Hub
import androidx.compose.material.icons.filled.Key
import androidx.compose.material.icons.filled.Language
-import androidx.compose.material.icons.filled.Notifications
import androidx.compose.material.icons.filled.Security
import androidx.compose.material.icons.filled.SurroundSound
import androidx.compose.material3.AlertDialog
@@ -61,7 +60,6 @@ import com.greenart7c3.nostrsigner.ui.components.IconRow
import com.greenart7c3.nostrsigner.ui.components.TextSpinner
import com.greenart7c3.nostrsigner.ui.components.TitleExplainer
import com.greenart7c3.nostrsigner.ui.navigation.Route
-import com.vitorpamplona.ammolite.relays.RelayPool
import com.vitorpamplona.quartz.encoders.toNpub
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.Dispatchers
@@ -144,20 +142,6 @@ fun SettingsScreen(
@Suppress("KotlinConstantConditions")
if (BuildConfig.FLAVOR != "offline") {
- Box(
- Modifier
- .padding(8.dp),
- ) {
- IconRow(
- title = stringResource(R.string.notification_type),
- icon = Icons.Default.Notifications,
- tint = MaterialTheme.colorScheme.onBackground,
- onClick = {
- navController.navigate(Route.NotificationType.route)
- },
- )
- }
-
Box(
Modifier
.padding(8.dp),
@@ -182,43 +166,43 @@ fun SettingsScreen(
},
)
}
- }
- Box(
- Modifier
- .padding(8.dp),
- ) {
- IconRow(
- title = stringResource(R.string.default_relays),
- icon = Icons.Default.Hub,
- tint = MaterialTheme.colorScheme.onBackground,
- onClick = {
- navController.navigate(Route.DefaultRelays.route)
- },
- )
- }
+ Box(
+ Modifier
+ .padding(8.dp),
+ ) {
+ IconRow(
+ title = stringResource(R.string.default_relays),
+ icon = Icons.Default.Hub,
+ tint = MaterialTheme.colorScheme.onBackground,
+ onClick = {
+ navController.navigate(Route.DefaultRelays.route)
+ },
+ )
+ }
- Box(
- Modifier
- .padding(8.dp),
- ) {
- IconRow(
- title = if (allowNewConnections) stringResource(R.string.disable_listening_for_new_connections) else stringResource(R.string.enable_listening_for_new_connections),
- icon = Icons.Default.SurroundSound,
- tint = MaterialTheme.colorScheme.onBackground,
- onClick = {
- allowNewConnections = !allowNewConnections
- account.allowNewConnections = allowNewConnections
- LocalPreferences.saveToEncryptedStorage(context, account)
- },
- onLongClick = {
- Toast.makeText(
- context,
- if (allowNewConnections) context.getString(R.string.disable_listening_for_new_connections) else context.getString(R.string.enable_listening_for_new_connections),
- Toast.LENGTH_LONG,
- ).show()
- },
- )
+ Box(
+ Modifier
+ .padding(8.dp),
+ ) {
+ IconRow(
+ title = if (allowNewConnections) stringResource(R.string.disable_listening_for_new_connections) else stringResource(R.string.enable_listening_for_new_connections),
+ icon = Icons.Default.SurroundSound,
+ tint = MaterialTheme.colorScheme.onBackground,
+ onClick = {
+ allowNewConnections = !allowNewConnections
+ account.allowNewConnections = allowNewConnections
+ LocalPreferences.saveToEncryptedStorage(context, account)
+ },
+ onLongClick = {
+ Toast.makeText(
+ context,
+ if (allowNewConnections) context.getString(R.string.disable_listening_for_new_connections) else context.getString(R.string.enable_listening_for_new_connections),
+ Toast.LENGTH_LONG,
+ ).show()
+ },
+ )
+ }
}
Box(
@@ -307,12 +291,8 @@ fun SettingsScreen(
LocalPreferences.updateProxy(context, true, proxyPort.value.toInt())
scope.launch(Dispatchers.IO) {
NotificationDataSource.stopSync()
- if (NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT) {
- RelayPool.disconnect()
- } else {
- NostrSigner.getInstance().checkForNewRelays()
- NotificationDataSource.start()
- }
+ NostrSigner.getInstance().checkForNewRelays()
+ NotificationDataSource.start()
}
},
onError = {
@@ -341,12 +321,8 @@ fun SettingsScreen(
LocalPreferences.updateProxy(context, false, proxyPort.value.toInt())
scope.launch(Dispatchers.IO) {
NotificationDataSource.stopSync()
- if (NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT) {
- RelayPool.disconnect()
- } else {
- NostrSigner.getInstance().checkForNewRelays()
- NotificationDataSource.start()
- }
+ NostrSigner.getInstance().checkForNewRelays()
+ NotificationDataSource.start()
}
},
) {
@@ -406,11 +382,6 @@ fun SettingsRow(
}
}
-enum class NotificationType(val screenCode: Int, val resourceId: Int) {
- PUSH(0, R.string.push_notifications),
- DIRECT(1, R.string.direct_connection),
-}
-
enum class BiometricsTimeType(val screenCode: Int, val resourceId: Int) {
EVERY_TIME(0, R.string.every_time),
ONE_MINUTE(1, R.string.one_minute),
@@ -428,13 +399,3 @@ fun parseBiometricsTimeType(screenCode: Int): BiometricsTimeType {
}
}
}
-
-fun parseNotificationType(screenCode: Int): NotificationType {
- return when (screenCode) {
- NotificationType.PUSH.screenCode -> NotificationType.PUSH
- NotificationType.DIRECT.screenCode -> NotificationType.DIRECT
- else -> {
- NotificationType.PUSH
- }
- }
-}
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/actions/EditRelaysDialog.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/actions/EditRelaysDialog.kt
index 88ba459b..c9c9064f 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/actions/EditRelaysDialog.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/actions/EditRelaysDialog.kt
@@ -60,7 +60,6 @@ import com.greenart7c3.nostrsigner.service.Nip11Retriever
import com.greenart7c3.nostrsigner.service.NotificationDataSource
import com.greenart7c3.nostrsigner.ui.AccountStateViewModel
import com.greenart7c3.nostrsigner.ui.CenterCircularProgressIndicator
-import com.greenart7c3.nostrsigner.ui.NotificationType
import com.greenart7c3.nostrsigner.ui.components.AmberButton
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.ammolite.relays.Client
@@ -149,7 +148,7 @@ fun DefaultRelaysScreen(
LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
scope.launch(Dispatchers.IO) {
@Suppress("KotlinConstantConditions")
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT && BuildConfig.FLAVOR != "offline") {
+ if (BuildConfig.FLAVOR != "offline") {
NostrSigner.getInstance().checkForNewRelays()
NotificationDataSource.stop()
delay(2000)
@@ -191,7 +190,7 @@ fun DefaultRelaysScreen(
LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
scope.launch(Dispatchers.IO) {
@Suppress("KotlinConstantConditions")
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT && BuildConfig.FLAVOR != "offline") {
+ if (BuildConfig.FLAVOR != "offline") {
NostrSigner.getInstance().checkForNewRelays()
NotificationDataSource.stop()
delay(2000)
@@ -238,7 +237,7 @@ fun DefaultRelaysScreen(
LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
scope.launch(Dispatchers.IO) {
@Suppress("KotlinConstantConditions")
- if (NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT && BuildConfig.FLAVOR != "offline") {
+ if (BuildConfig.FLAVOR != "offline") {
NostrSigner.getInstance().checkForNewRelays()
NotificationDataSource.stop()
delay(2000)
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 a2278132..707352f9 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
@@ -61,7 +61,6 @@ import com.greenart7c3.nostrsigner.service.IntentUtils
import com.greenart7c3.nostrsigner.service.getAppCompatActivity
import com.greenart7c3.nostrsigner.service.model.AmberEvent
import com.greenart7c3.nostrsigner.service.toShortenHex
-import com.greenart7c3.nostrsigner.ui.NotificationType
import com.greenart7c3.nostrsigner.ui.Result
import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.encoders.toHexKey
@@ -577,7 +576,7 @@ private fun sendResultIntent(
private suspend fun reconnectToRelays(intents: List) {
if (!intents.any { it.bunkerRequest != null }) return
- NostrSigner.getInstance().checkForNewRelays(NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT)
+ NostrSigner.getInstance().checkForNewRelays()
}
@Composable
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/SingleEventHomeScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/SingleEventHomeScreen.kt
index 21c0d732..6c55ec27 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/SingleEventHomeScreen.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/components/SingleEventHomeScreen.kt
@@ -36,7 +36,6 @@ import com.greenart7c3.nostrsigner.models.kindToNip
import com.greenart7c3.nostrsigner.service.AmberUtils
import com.greenart7c3.nostrsigner.service.getAppCompatActivity
import com.greenart7c3.nostrsigner.service.toShortenHex
-import com.greenart7c3.nostrsigner.ui.NotificationType
import com.greenart7c3.nostrsigner.ui.sendResult
import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.encoders.bechToBytes
@@ -138,8 +137,7 @@ fun SingleEventHomeScreen(
val relays = savedApplication?.application?.relays?.ifEmpty { defaultRelays } ?: intentData.bunkerRequest.relays.ifEmpty { defaultRelays }
NostrSigner.getInstance().checkForNewRelays(
- NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT,
- relays.toSet(),
+ newRelays = relays.toSet(),
)
AmberUtils.sendBunkerError(
@@ -242,8 +240,7 @@ fun SingleEventHomeScreen(
if (intentData.bunkerRequest != null) {
NostrSigner.getInstance().checkForNewRelays(
- NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT,
- relays.toSet(),
+ newRelays = relays.toSet(),
)
}
@@ -378,8 +375,7 @@ fun SingleEventHomeScreen(
if (intentData.bunkerRequest != null) {
NostrSigner.getInstance().checkForNewRelays(
- NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT,
- relays.toSet(),
+ newRelays = relays.toSet(),
)
}
@@ -528,8 +524,7 @@ fun SingleEventHomeScreen(
if (intentData.bunkerRequest != null) {
NostrSigner.getInstance().checkForNewRelays(
- NostrSigner.getInstance().settings.notificationType != NotificationType.DIRECT,
- relays.toSet(),
+ newRelays = relays.toSet(),
)
}
diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/navigation/Route.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/navigation/Route.kt
index f245df01..6c841bce 100644
--- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/navigation/Route.kt
+++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/navigation/Route.kt
@@ -81,13 +81,6 @@ sealed class Route(
selectedIcon = Icons.Default.Settings,
)
- data object NotificationType : Route(
- title = NostrSigner.getInstance().getString(R.string.notification_type),
- route = "NotificationType",
- icon = Icons.Outlined.Settings,
- selectedIcon = Icons.Default.Settings,
- )
-
data object DefaultRelays : Route(
title = NostrSigner.getInstance().getString(R.string.default_relays),
route = "DefaultRelays",
@@ -182,7 +175,6 @@ val routes = listOf(
Route.Logs,
Route.ActiveRelays,
Route.Language,
- Route.NotificationType,
Route.DefaultRelays,
Route.SignPolicy,
Route.Security,
diff --git a/app/src/play/AndroidManifest.xml b/app/src/play/AndroidManifest.xml
deleted file mode 100644
index 6d815c94..00000000
--- a/app/src/play/AndroidManifest.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/play/java/com/greenart7c3/nostrsigner/service/Notifications.kt b/app/src/play/java/com/greenart7c3/nostrsigner/service/Notifications.kt
deleted file mode 100644
index 9b1b1b5a..00000000
--- a/app/src/play/java/com/greenart7c3/nostrsigner/service/Notifications.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.greenart7c3.nostrsigner.service
-
-import android.content.Intent
-import android.util.Log
-import android.util.LruCache
-import com.google.firebase.messaging.FirebaseMessagingService
-import com.google.firebase.messaging.RemoteMessage
-import com.greenart7c3.nostrsigner.LocalPreferences
-import com.greenart7c3.nostrsigner.service.NotificationUtils.getOrCreateDMChannel
-import com.vitorpamplona.quartz.events.Event
-import com.vitorpamplona.quartz.events.GiftWrapEvent
-import kotlin.time.measureTimedValue
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.launch
-
-class Notifications : FirebaseMessagingService() {
- private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
- private val eventCache = LruCache(100)
-
- override fun getStartCommandIntent(originalIntent: Intent?): Intent {
- return super.getStartCommandIntent(originalIntent)
- }
-
- override fun handleIntent(intent: Intent?) {
- Log.d("Time", "Intent received $intent")
- super.handleIntent(intent)
- }
-
- override fun onMessageReceived(remoteMessage: RemoteMessage) {
- scope.launch(Dispatchers.IO) {
- val (_, elapsed) =
- measureTimedValue { parseMessage(remoteMessage.data)?.let { receiveIfNew(it) } }
- Log.d("Time", "Notification processed in $elapsed")
- }
- super.onMessageReceived(remoteMessage)
- }
-
- private fun parseMessage(params: Map): GiftWrapEvent? {
- params["encryptedEvent"]?.let { eventStr ->
- (Event.fromJson(eventStr) as? GiftWrapEvent)?.let {
- return it
- }
- }
- return null
- }
-
- private suspend fun receiveIfNew(event: GiftWrapEvent) {
- if (eventCache.get(event.id) == null) {
- eventCache.put(event.id, event.id)
- getOrCreateDMChannel(applicationContext)
- EventNotificationConsumer(applicationContext).consume(event)
- }
- }
-
- override fun onNewToken(token: String) {
- scope.launch(Dispatchers.IO) {
- RegisterAccounts(LocalPreferences.allSavedAccounts(applicationContext)).go(token)
- }
- super.onNewToken(token)
- }
-
- override fun onDestroy() {
- Log.d("Lifetime Event", "PushNotificationReceiverService.onDestroy")
-
- scope.cancel()
- super.onDestroy()
- }
-}
diff --git a/app/src/play/java/com/greenart7c3/nostrsigner/service/PushNotificationUtils.kt b/app/src/play/java/com/greenart7c3/nostrsigner/service/PushNotificationUtils.kt
deleted file mode 100644
index bb7cd105..00000000
--- a/app/src/play/java/com/greenart7c3/nostrsigner/service/PushNotificationUtils.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (c) 2024 Vitor Pamplona
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
- * Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-package com.greenart7c3.nostrsigner.service
-
-import android.util.Log
-import com.google.firebase.messaging.FirebaseMessaging
-import com.greenart7c3.nostrsigner.AccountInfo
-import com.greenart7c3.nostrsigner.NostrSigner
-import com.greenart7c3.nostrsigner.ui.AccountStateViewModel
-import com.greenart7c3.nostrsigner.ui.NotificationType
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.tasks.await
-
-object PushNotificationUtils {
- var hasInit: Boolean = false
- var accountState: AccountStateViewModel? = null
-
- suspend fun init(accounts: List) =
- with(Dispatchers.IO) {
- if (hasInit || NostrSigner.getInstance().settings.notificationType == NotificationType.DIRECT) {
- return@with
- }
- // get user notification token provided by firebase
- try {
- RegisterAccounts(accounts).go(FirebaseMessaging.getInstance().token.await())
- } catch (e: Exception) {
- if (e is CancellationException) throw e
- Log.e("Firebase token", "failed to get firebase token", e)
- }
- }
-}
diff --git a/app/src/play/java/com/greenart7c3/nostrsigner/ui/SelectNotificationProvider.kt b/app/src/play/java/com/greenart7c3/nostrsigner/ui/SelectNotificationProvider.kt
deleted file mode 100644
index 76ff05b8..00000000
--- a/app/src/play/java/com/greenart7c3/nostrsigner/ui/SelectNotificationProvider.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.greenart7c3.nostrsigner.ui
-
-import androidx.compose.runtime.Composable
-
-@Composable
-fun PushNotificationSettingsRow() {}
diff --git a/build.gradle b/build.gradle
index 406fbf1c..d24d34eb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -6,7 +6,6 @@ plugins {
alias(libs.plugins.androidLibrary) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
alias(libs.plugins.serialization) apply false
- alias(libs.plugins.google.gms) version(libs.versions.gms) apply false
alias(libs.plugins.kotlin.ksp) version(libs.versions.ksp) apply false
alias(libs.plugins.gradle.ktlint) version(libs.versions.ktlint) apply false
}
diff --git a/build.sh b/build.sh
index 6e3bede5..0ca2adb8 100755
--- a/build.sh
+++ b/build.sh
@@ -10,15 +10,13 @@ appName=$2
./gradlew clean bundleRelease --stacktrace
./gradlew assembleRelease --stacktrace
-rm ~/release/amber-*
-rm ~/release/citrine-*
-rm ~/release/manifest-*
-mv app/build/outputs/bundle/playRelease/app-play-release.aab ~/release/
+rm -rf ~/release/amber-*
+rm -rf ~/release/citrine-*
+rm -rf ~/release/manifest-*
mv app/build/outputs/bundle/offlineRelease/app-offline-release.aab ~/release/
mv app/build/outputs/bundle/freeRelease/app-free-release.aab ~/release/
mv app/build/outputs/apk/offline/release/app-offline-* ~/release/
mv app/build/outputs/apk/free/release/app-free-* ~/release/
-mv app/build/outputs/apk/play/release/app-play-* ~/release/
./gradlew --stop
cd ~/release
./generate_manifest.sh ${version} ${appName}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 6e518b9e..07e2d5fa 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,6 +1,5 @@
[versions]
activityCompose = "1.9.3"
-unfiedpush = "2.4.0"
appcompat = "1.7.0"
biometricKtx = "1.2.0-alpha05"
converterGson = "2.11.0"
@@ -8,8 +7,6 @@ core = "3.5.3"
coreKtx = "1.13.1"
coreSplashscreen = "1.0.1"
espressoCore = "3.6.1"
-firebaseBom = "33.5.1"
-firebaseMessaging = "24.0.3"
jna = "5.14.0"
junit = "4.13.2"
junitVersion = "1.2.1"
@@ -33,7 +30,6 @@ ksp = "2.0.20-1.0.24"
[libraries]
activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }
-unfiedpush = { module = "com.github.UnifiedPush:android-connector", version.ref = "unfiedpush" }
appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
biometric-ktx = { module = "androidx.biometric:biometric-ktx", version.ref = "biometricKtx" }
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" }
@@ -42,8 +38,6 @@ core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
core-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "coreSplashscreen" }
espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espressoCore" }
ext-junit = { module = "androidx.test.ext:junit", version.ref = "junitVersion" }
-firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebaseBom" }
-firebase-messaging = { module = "com.google.firebase:firebase-messaging", version.ref = "firebaseMessaging" }
jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
junit = { module = "junit:junit", version.ref = "junit" }
lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle_version" }
@@ -76,7 +70,6 @@ jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "k
androidLibrary = { id = "com.android.library", version.ref = "agp" }
androidApplication = { id = "com.android.application", version.ref = "agp" }
gradle_ktlint = { id = "org.jlleitschuh.gradle.ktlint", version = "ktlint" }
-google_gms = { id = "com.google.gms.google-services", version = "gms" }
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlin_ksp = { id = "com.google.devtools.ksp", version = "ksp" }
jetbrainsComposeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }