diff --git a/app/src/main/java/com/koalasat/pokey/models/EncryptedStorage.kt b/app/src/main/java/com/koalasat/pokey/models/EncryptedStorage.kt index fd13ddc..1b3c039 100644 --- a/app/src/main/java/com/koalasat/pokey/models/EncryptedStorage.kt +++ b/app/src/main/java/com/koalasat/pokey/models/EncryptedStorage.kt @@ -14,7 +14,6 @@ object PrefKeys { } object DefaultKeys { const val BROADCAST = true - const val EXTERNAL_SIGNER = "com.greenart7c3.nostrsigner" } object EncryptedStorage { @@ -28,9 +27,6 @@ object EncryptedStorage { private val _broadcast = MutableLiveData().apply { DefaultKeys.BROADCAST } val broadcast: LiveData get() = _broadcast - private val _externalSigner = MutableLiveData().apply { DefaultKeys.EXTERNAL_SIGNER } - val externalSigner: LiveData get() = _externalSigner - fun init(context: Context) { val masterKey: MasterKey = MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS) @@ -46,15 +42,9 @@ object EncryptedStorage { ) as EncryptedSharedPreferences _broadcast.postValue(sharedPreferences.getBoolean(PrefKeys.NOSTR_BROADCAST, DefaultKeys.BROADCAST)) - _externalSigner.postValue(sharedPreferences.getString(PrefKeys.EXTERNAL_SIGNER, DefaultKeys.EXTERNAL_SIGNER) ?: DefaultKeys.EXTERNAL_SIGNER) _inboxPubKey.postValue(sharedPreferences.getString(PrefKeys.INBOX_PUBKEY, "")) } - fun updateExternalSigner(newValue: String) { - sharedPreferences.edit().putString(PrefKeys.EXTERNAL_SIGNER, newValue).apply() - _externalSigner.postValue(newValue) - } - fun updateBroadcast(newValue: Boolean) { sharedPreferences.edit().putBoolean(PrefKeys.NOSTR_BROADCAST, newValue).apply() _broadcast.postValue(newValue) diff --git a/app/src/main/java/com/koalasat/pokey/models/ExternalSigner.kt b/app/src/main/java/com/koalasat/pokey/models/ExternalSigner.kt index 4d283b1..81c8378 100644 --- a/app/src/main/java/com/koalasat/pokey/models/ExternalSigner.kt +++ b/app/src/main/java/com/koalasat/pokey/models/ExternalSigner.kt @@ -15,12 +15,15 @@ import com.vitorpamplona.quartz.signers.ExternalSignerLauncher import com.vitorpamplona.quartz.signers.SignerType import com.vitorpamplona.quartz.utils.TimeUtils import java.util.UUID +import java.util.concurrent.ConcurrentHashMap +import kotlin.collections.get import kotlin.coroutines.cancellation.CancellationException import kotlinx.coroutines.launch object ExternalSigner { + const val EXTERNAL_SIGNER = "com.greenart7c3.nostrsigner" private lateinit var nostrSignerLauncher: ActivityResultLauncher - private lateinit var externalSignerLauncher: ExternalSignerLauncher + private var externalSignerLaunchers = ConcurrentHashMap() fun init(activity: AppCompatActivity) { nostrSignerLauncher = activity.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> @@ -28,17 +31,18 @@ object ExternalSigner { Log.e("Pokey", "ExternalSigner result error: ${result.resultCode}") Toast.makeText(activity, activity.getString(R.string.amber_not_found), Toast.LENGTH_SHORT).show() } else { - result.data?.let { externalSignerLauncher.newResult(it) } + result.data?.let { + var externalSignerLauncher = externalSignerLaunchers[""] + externalSignerLauncher?.newResult(it) + } } } - - EncryptedStorage.inboxPubKey.observeForever { - startLauncher(it) - } + startLauncher("") } fun savePubKey(onReady: (pubKey: String) -> Unit) { - externalSignerLauncher.openSignerApp( + var externalSignerLauncher = externalSignerLaunchers[""] + externalSignerLauncher?.openSignerApp( "", SignerType.GET_PUBLIC_KEY, "", @@ -47,17 +51,15 @@ object ExternalSigner { val split = result.split("-") val pubkey = split.first() if (split.first().isNotEmpty()) { - if (split.size > 1) { - EncryptedStorage.updateExternalSigner(split[1]) - } - startLauncher(pubkey) - onReady(pubkey) + val hexPub = NostrClient.parseNpub(pubkey.toString()).toString() + startLauncher(hexPub) + onReady(hexPub) } } } fun auth(hexKey: String, relayUrl: String, challenge: String, onReady: (Event) -> Unit) { - if (!::externalSignerLauncher.isInitialized) return + var externalSignerLauncher = externalSignerLaunchers[hexKey] val createdAt = TimeUtils.now() val kind = 22242 @@ -78,7 +80,7 @@ object ExternalSigner { content = content, sig = "", ) - externalSignerLauncher.openSigner( + externalSignerLauncher?.openSigner( event, ) { onReady( @@ -96,28 +98,26 @@ object ExternalSigner { } fun sign(event: Event, onReady: (String) -> Unit) { - externalSignerLauncher.openSigner( + var externalSignerLauncher = externalSignerLaunchers[event.pubKey] + externalSignerLauncher?.openSigner( event, onReady, ) } private fun startLauncher(pubKey: String) { - var externalSignerPackage = EncryptedStorage.externalSigner.value - - if (pubKey.isNotEmpty() == true && externalSignerPackage?.isNotEmpty() == true) { - externalSignerLauncher = ExternalSignerLauncher(pubKey, signerPackageName = externalSignerPackage) - externalSignerLauncher.registerLauncher( - launcher = { - try { - nostrSignerLauncher.launch(it) - } catch (e: Exception) { - if (e is CancellationException) throw e - Log.e("Pokey", "Error opening Signer app", e) - } - }, - contentResolver = { Pokey.getInstance().contentResolverFn() }, - ) - } + val externalSignerLauncher = ExternalSignerLauncher(pubKey, signerPackageName = EXTERNAL_SIGNER) + externalSignerLauncher.registerLauncher( + launcher = { + try { + nostrSignerLauncher.launch(it) + } catch (e: Exception) { + if (e is CancellationException) throw e + Log.e("Pokey", "Error opening Signer app", e) + } + }, + contentResolver = { Pokey.getInstance().contentResolverFn() }, + ) + externalSignerLaunchers.put(pubKey, externalSignerLauncher) } } diff --git a/app/src/main/java/com/koalasat/pokey/models/NostrClient.kt b/app/src/main/java/com/koalasat/pokey/models/NostrClient.kt index d83b6c4..75ed2fe 100644 --- a/app/src/main/java/com/koalasat/pokey/models/NostrClient.kt +++ b/app/src/main/java/com/koalasat/pokey/models/NostrClient.kt @@ -17,6 +17,8 @@ import com.vitorpamplona.ammolite.relays.RelayPool import com.vitorpamplona.ammolite.relays.TypedFilter import com.vitorpamplona.ammolite.relays.filters.EOSETime import com.vitorpamplona.ammolite.relays.filters.SincePerRelayFilter +import com.vitorpamplona.quartz.encoders.Nip19Bech32 +import com.vitorpamplona.quartz.encoders.Nip19Bech32.uriToRoute import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.utils.TimeUtils @@ -303,6 +305,20 @@ object NostrClient { } } + fun parseNpub(value: String): String? { + if (value.isEmpty()) return null + + val parseReturn = uriToRoute(value) + + when (val parsed = parseReturn?.entity) { + is Nip19Bech32.NPub -> { + return parsed.hex + } + } + + return null + } + private fun getInboxLists(context: Context) { val db = AppDatabase.getDatabase(context, "common") val users = db.applicationDao().getUsers() diff --git a/app/src/main/java/com/koalasat/pokey/ui/home/HomeFragment.kt b/app/src/main/java/com/koalasat/pokey/ui/home/HomeFragment.kt index 45964fc..8f54f2a 100644 --- a/app/src/main/java/com/koalasat/pokey/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/koalasat/pokey/ui/home/HomeFragment.kt @@ -35,12 +35,11 @@ import com.koalasat.pokey.utils.images.CircleTransform import com.koalasat.pokey.utils.isDarkThemeEnabled import com.squareup.picasso.Picasso import com.vitorpamplona.quartz.encoders.Hex -import com.vitorpamplona.quartz.encoders.Nip19Bech32 -import com.vitorpamplona.quartz.encoders.Nip19Bech32.uriToRoute import com.vitorpamplona.quartz.encoders.toNpub import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.json.JSONException class HomeFragment : Fragment() { @@ -59,7 +58,7 @@ class HomeFragment : Fragment() { ViewModelProvider(this)[HomeViewModel::class.java] homeViewModel.accountList.observeForever { value -> - if (binding != null) { + if (_binding != null) { if (binding.accountList.size > 1) { binding.accountList.removeViews(0, binding.accountList.size - 1) } @@ -126,7 +125,17 @@ class HomeFragment : Fragment() { } binding.serviceStart.setOnClickListener { - viewModel.updateServiceStart(!viewModel.serviceStart.value!!) + CoroutineScope(Dispatchers.IO).launch { + val dao = AppDatabase.getDatabase(requireContext(), "common").applicationDao() + val users = dao.getUsers() + if (users.isNotEmpty()) { + viewModel.updateServiceStart(!viewModel.serviceStart.value!!) + } else { + withContext(Dispatchers.Main) { + Toast.makeText(requireContext(), getString(R.string.addUsersToStart), Toast.LENGTH_SHORT).show() + } + } + } } Pokey.isEnabled.observe(viewLifecycleOwner) { @@ -174,12 +183,13 @@ class HomeFragment : Fragment() { buttonAmber.setOnClickListener { ExternalSigner.savePubKey { dialog.hide() - createUser(it, 1) + val hexPub = NostrClient.parseNpub(it.toString()) + createUser(hexPub, 1) } } buttonSubmitAccount.setOnClickListener { - val hexPub = parseNpubInput(npubInput.text.toString()) + val hexPub = NostrClient.parseNpub(npubInput.text.toString()) if (hexPub?.isNotEmpty() == true) { npubInput.error = null dialog.hide() @@ -193,20 +203,6 @@ class HomeFragment : Fragment() { } } - private fun parseNpubInput(value: String): String? { - if (value.isEmpty()) return null - - val parseReturn = uriToRoute(value) - - when (val parsed = parseReturn?.entity) { - is Nip19Bech32.NPub -> { - return parsed.hex - } - } - - return null - } - private fun loadAvatar(avatar: String?, imageView: ImageView) { if (avatar?.isNotEmpty() != true) return @@ -257,11 +253,10 @@ class HomeFragment : Fragment() { CoroutineScope(Dispatchers.IO).launch { val dao = context?.let { AppDatabase.getDatabase(it, "common").applicationDao() } dao?.deleteUser(user) - if (EncryptedStorage.inboxPubKey.value == user.hexPub) { - var nextUser = dao?.getUsers()?.first() - if (nextUser != null) { - EncryptedStorage.updateInboxPubKey(nextUser.hexPub) - } + var users = dao?.getUsers() + if (users?.size!! > 0 && EncryptedStorage.inboxPubKey.value == user.hexPub) { + var nextUser = users.first() + EncryptedStorage.updateInboxPubKey(nextUser.hexPub) } viewModel.loadAccounts() } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7e4cbf9..94315df 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -54,4 +54,5 @@ Select Delete "Stop Pokey to perform this action " + Add at least one user to start Pokey.