mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-11-10 18:26:46 +01:00
Merge pull request #1493 from greenart7c3/main
Show a dialog to select a signer when using multiple signers
This commit is contained in:
@@ -23,12 +23,39 @@ package com.vitorpamplona.amethyst.ui.screen.loggedOff.login
|
||||
import android.app.Activity
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import coil3.compose.rememberAsyncImagePainter
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.DefaultSignerPermissions
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size0dp
|
||||
@@ -37,6 +64,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size40dp
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.PubKeyResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.client.ExternalSignerLogin
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.client.getExternalSignersInstalled
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -44,6 +72,9 @@ import kotlinx.coroutines.launch
|
||||
@Composable
|
||||
fun ExternalSignerButton(loginViewModel: LoginViewModel) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
val installedSigners = getExternalSignersInstalled(context)
|
||||
var shouldSelectSigner by remember { mutableStateOf(false) }
|
||||
|
||||
val launcher =
|
||||
rememberLauncherForActivityResult(
|
||||
@@ -63,6 +94,81 @@ fun ExternalSignerButton(loginViewModel: LoginViewModel) {
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSelectSigner) {
|
||||
Dialog(
|
||||
onDismissRequest = {
|
||||
shouldSelectSigner = false
|
||||
},
|
||||
content = {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(4.dp),
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
text = stringResource(R.string.select_signer),
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
)
|
||||
Spacer(Modifier.height(4.dp))
|
||||
LazyColumn {
|
||||
items(installedSigners) {
|
||||
val appName = it.loadLabel(context.packageManager).toString()
|
||||
val appIcon = it.loadIcon(context.packageManager)
|
||||
val iconBitmap = appIcon.toBitmap()
|
||||
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp, end = 16.dp, bottom = 8.dp, top = 8.dp)
|
||||
.clickable {
|
||||
if (!loginViewModel.acceptedTerms) {
|
||||
loginViewModel.termsAcceptanceIsRequiredError = true
|
||||
} else {
|
||||
try {
|
||||
launcher.launch(ExternalSignerLogin.createIntent(DefaultSignerPermissions, it.activityInfo.packageName))
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.e("ExternalSigner", "Error opening Signer app", e)
|
||||
loginViewModel.errorManager.error(R.string.error_opening_external_signer)
|
||||
} finally {
|
||||
shouldSelectSigner = false
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
val painter =
|
||||
rememberAsyncImagePainter(
|
||||
iconBitmap,
|
||||
)
|
||||
|
||||
Image(
|
||||
painter = painter,
|
||||
contentDescription = appName,
|
||||
modifier =
|
||||
Modifier
|
||||
.size(48.dp)
|
||||
.padding(end = 16.dp),
|
||||
)
|
||||
Column {
|
||||
Text(appName)
|
||||
Text(
|
||||
it.activityInfo.packageName,
|
||||
fontSize = 14.sp,
|
||||
color = Color.Gray,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.padding(Size40dp, Size20dp, Size40dp, Size0dp)) {
|
||||
LoginWithAmberButton(
|
||||
enabled = loginViewModel.acceptedTerms,
|
||||
@@ -71,7 +177,11 @@ fun ExternalSignerButton(loginViewModel: LoginViewModel) {
|
||||
loginViewModel.termsAcceptanceIsRequiredError = true
|
||||
} else {
|
||||
try {
|
||||
launcher.launch(ExternalSignerLogin.createIntent(DefaultSignerPermissions))
|
||||
if (installedSigners.size == 1) {
|
||||
launcher.launch(ExternalSignerLogin.createIntent(DefaultSignerPermissions))
|
||||
} else {
|
||||
shouldSelectSigner = true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException) throw e
|
||||
Log.e("ExternalSigner", "Error opening Signer app", e)
|
||||
|
||||
@@ -1289,4 +1289,5 @@
|
||||
<string name="would_you_like_to_send_the_recent_crash_report_to_amethyst_in_a_dm_no_personal_information_will_be_shared">Would you like to send the recent crash report to Amethyst in a DM? No personal information will be shared</string>
|
||||
<string name="crashreport_found_send">Send it</string>
|
||||
<string name="this_message_will_disappear_in_days">This message will disappear in %1$d days</string>
|
||||
<string name="select_signer">Select Signer</string>
|
||||
</resources>
|
||||
|
||||
@@ -29,9 +29,15 @@ import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.result
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.permission.Permission
|
||||
|
||||
object ExternalSignerLogin {
|
||||
fun createIntent(permissions: List<Permission> = LoginRequest.DefaultPermissions): Intent {
|
||||
fun createIntent(
|
||||
permissions: List<Permission> = LoginRequest.DefaultPermissions,
|
||||
packageName: String = "",
|
||||
): Intent {
|
||||
val intent = LoginRequest.assemble(permissions)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
if (packageName.isNotBlank()) {
|
||||
intent.`package` = packageName
|
||||
}
|
||||
return intent
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ package com.vitorpamplona.quartz.nip55AndroidSigner.client
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ResolveInfo
|
||||
import androidx.core.net.toUri
|
||||
|
||||
@SuppressLint("QueryPermissionsNeeded")
|
||||
@@ -35,3 +36,14 @@ fun isExternalSignerInstalled(context: Context): Boolean =
|
||||
},
|
||||
0,
|
||||
).isNotEmpty()
|
||||
|
||||
@SuppressLint("QueryPermissionsNeeded")
|
||||
fun getExternalSignersInstalled(context: Context): List<ResolveInfo> =
|
||||
context.packageManager
|
||||
.queryIntentActivities(
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
data = "nostrsigner:".toUri()
|
||||
},
|
||||
0,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user