More design changes

This commit is contained in:
greenart7c3
2024-11-13 11:06:48 -03:00
parent 0d85fa1878
commit 4a24c7724e
29 changed files with 712 additions and 734 deletions
@@ -27,7 +27,6 @@ import com.vitorpamplona.ammolite.relays.RelaySetupInfoToConnect
import com.vitorpamplona.ammolite.relays.TypedFilter
import com.vitorpamplona.ammolite.relays.filters.SincePerRelayFilter
import com.vitorpamplona.ammolite.service.HttpClientManager
import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.encoders.toNpub
import com.vitorpamplona.quartz.events.Event
import com.vitorpamplona.quartz.events.EventInterface
@@ -255,7 +254,7 @@ class NostrSigner : Application() {
types = COMMON_FEED_TYPES,
filter = SincePerRelayFilter(
kinds = listOf(MetadataEvent.KIND),
authors = listOf(account.signer.keyPair.pubKey.toHexKey()),
authors = listOf("7579076d9aff0a4cfdefa7e2045f2486c7e5d8bc63bfc6b45397233e1bbfcb19"),
limit = 1,
),
),
@@ -0,0 +1,8 @@
package com.greenart7c3.nostrsigner.service
import com.greenart7c3.nostrsigner.models.IntentData
object MultiEventScreenIntents {
var intents = listOf<IntentData>()
var appName = ""
}
@@ -3,14 +3,21 @@ package com.greenart7c3.nostrsigner.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun CenterCircularProgressIndicator(modifier: Modifier) {
fun CenterCircularProgressIndicator(
modifier: Modifier,
text: String? = null,
) {
Box(
modifier,
) {
@@ -19,6 +26,10 @@ fun CenterCircularProgressIndicator(modifier: Modifier) {
Arrangement.Center,
Alignment.CenterHorizontally,
) {
text?.let {
Text(it)
Spacer(Modifier.height(8.dp))
}
CircularProgressIndicator()
}
}
@@ -250,9 +250,7 @@ fun EditConfigurationScreen(
}
}
},
content = {
Text(stringResource(R.string.update))
},
text = stringResource(R.string.update),
)
AmberButton(
@@ -276,12 +274,8 @@ fun EditConfigurationScreen(
}
}
},
content = {
Text(
stringResource(R.string.delete_application),
color = Color.White,
)
},
text = stringResource(R.string.delete_application),
textColor = Color.White,
)
}
}
@@ -2,6 +2,7 @@ package com.greenart7c3.nostrsigner.ui
import android.annotation.SuppressLint
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -35,12 +36,12 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.toLowerCase
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -68,7 +69,6 @@ fun EditPermission(
navController: NavController,
database: AppDatabase,
) {
val uriHandler = LocalUriHandler.current
val clipboardManager = LocalClipboardManager.current
val context = LocalContext.current
val permissions = remember {
@@ -119,13 +119,14 @@ fun EditPermission(
}
Column(
modifier = modifier.verticalScroll(rememberScrollState()),
modifier = modifier
.verticalScroll(rememberScrollState()),
) {
if (!applicationData.isConnected) {
Text(
bunkerUri,
Modifier
.padding(8.dp),
.padding(bottom = 8.dp),
textAlign = TextAlign.Start,
fontSize = 18.sp,
)
@@ -136,9 +137,7 @@ fun EditPermission(
onClick = {
clipboardManager.setText(AnnotatedString(bunkerUri))
},
content = {
Text(stringResource(R.string.copy_to_clipboard))
},
text = stringResource(R.string.copy_to_clipboard),
)
Spacer(Modifier.height(12.dp))
@@ -149,9 +148,7 @@ fun EditPermission(
onClick = {
navController.navigate("Activity/${applicationData.key}")
},
content = {
Text(stringResource(R.string.activity))
},
text = stringResource(R.string.activity),
)
AmberButton(
@@ -159,15 +156,12 @@ fun EditPermission(
onClick = {
navController.navigate("EditConfiguration/${applicationData.key}")
},
content = {
Text(stringResource(R.string.edit_configuration))
},
text = stringResource(R.string.edit_configuration),
)
Text(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.padding(bottom = 20.dp),
text = stringResource(R.string.edit_permissions_description),
)
@@ -188,7 +182,7 @@ fun EditPermission(
Card(
modifier = Modifier
.padding(4.dp)
.padding(vertical = 4.dp)
.fillMaxWidth(),
border = BorderStroke(1.dp, Color.LightGray),
colors = CardDefaults.cardColors().copy(
@@ -219,7 +213,9 @@ fun EditPermission(
}
permissions.clear()
permissions.addAll(localPermissions)
database.applicationDao().insertPermissions(localPermissions)
database
.applicationDao()
.insertPermissions(localPermissions)
}
},
) {
@@ -269,20 +265,58 @@ fun EditPermission(
if (permissions.isNotEmpty()) {
AmberButton(
modifier = Modifier.padding(top = 60.dp, bottom = 20.dp),
colors = ButtonDefaults.buttonColors().copy(
containerColor = orange,
),
modifier = Modifier.padding(bottom = 20.dp),
onClick = {
wantsToRemovePermissions = true
},
content = {
Text(
stringResource(R.string.remove_all_permissions),
color = Color.White,
)
},
text = stringResource(R.string.remove_all_permissions),
textColor = Color.White,
)
}
}
}
@Composable
fun RelayCard(
modifier: Modifier = Modifier,
relay: String,
onClick: () -> Unit,
) {
Card(
Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
border = BorderStroke(1.dp, Color.LightGray),
colors = CardDefaults.cardColors().copy(
containerColor = MaterialTheme.colorScheme.background,
),
) {
Row(
modifier
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Text(
relay,
Modifier
.weight(0.9f)
.padding(8.dp)
.padding(start = 8.dp),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
IconButton(
onClick = onClick,
) {
Icon(
ImageVector.vectorResource(R.drawable.delete),
stringResource(R.string.delete),
)
}
}
}
}
@@ -21,6 +21,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.NostrSigner
import com.greenart7c3.nostrsigner.R
@@ -42,6 +43,7 @@ fun IncomingRequestScreen(
applicationName: String?,
account: Account,
database: AppDatabase,
navController: NavController,
) {
var loading by remember { mutableStateOf(false) }
val context = LocalContext.current
@@ -101,6 +103,7 @@ fun IncomingRequestScreen(
intents,
packageName,
account,
navController,
) {
loading = it
}
@@ -138,9 +138,8 @@ fun MainPage(
state.animateScrollToPage(1)
}
},
) {
Text(text = stringResource(R.string.add_a_key))
}
text = stringResource(R.string.add_a_key),
)
AmberButton(
onClick = {
@@ -148,9 +147,8 @@ fun MainPage(
state.animateScrollToPage(2)
}
},
) {
Text(stringResource(R.string.generate_a_new_key))
}
text = stringResource(R.string.sign_policy),
)
}
}
}
@@ -349,9 +347,7 @@ fun OrbotPage(
pageState.animateScrollToPage(2)
}
},
content = {
Text(text = stringResource(R.string.next))
},
text = stringResource(R.string.next),
)
}
}
@@ -477,9 +473,8 @@ fun SignPolicyScreen(
)
}
},
) {
Text(text = stringResource(R.string.finish))
}
text = stringResource(R.string.finish),
)
}
}
}
@@ -786,9 +781,7 @@ fun LoginPage(accountViewModel: AccountStateViewModel) {
Spacer(modifier = Modifier.height(10.dp))
AmberButton(
content = {
Text(text = stringResource(R.string.next))
},
text = stringResource(R.string.next),
onClick = {
if (key.value.text.isBlank()) {
errorMessage = context.getString(R.string.key_is_required)
@@ -96,11 +96,7 @@ fun LogsScreen(
NostrSigner.getInstance().getDatabase(account.signer.keyPair.pubKey.toNpub()).applicationDao().clearLogs()
}
},
content = {
Text(
text = stringResource(R.string.clear_logs),
)
},
text = stringResource(R.string.clear_logs),
)
}
}
@@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -57,6 +58,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.ClipboardManager
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@@ -103,7 +105,6 @@ import com.greenart7c3.nostrsigner.ui.actions.RelayLogScreen
import com.greenart7c3.nostrsigner.ui.components.IconRow
import com.greenart7c3.nostrsigner.ui.navigation.Route
import com.greenart7c3.nostrsigner.ui.navigation.routes
import com.greenart7c3.nostrsigner.ui.theme.defaultPadding
import com.vitorpamplona.quartz.encoders.toHexKey
import java.io.ByteArrayOutputStream
import java.util.Base64
@@ -372,6 +373,7 @@ fun PermissionsFloatingActionButton(
Icons.Default.Add,
contentDescription = stringResource(R.string.connect_app),
tint = Color.Black,
modifier = Modifier.size(48.dp),
)
}
}
@@ -427,7 +429,10 @@ fun MainScreen(
val scope = rememberCoroutineScope()
val context = LocalContext.current
var profileUrl by remember { mutableStateOf<String?>(null) }
val configuration = LocalConfiguration.current
val screenHeightDp = configuration.screenHeightDp.dp
val percentage = (screenHeightDp * 0.97f)
val verticalPadding = (screenHeightDp - percentage)
val requestPermissionLauncher =
rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission(),
@@ -613,8 +618,8 @@ fun MainScreen(
.clip(
RoundedCornerShape(50),
)
.height(24.dp)
.width(24.dp),
.height(28.dp)
.width(28.dp),
)
} else {
Icon(
@@ -695,12 +700,14 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
intents,
packageName,
appName,
account,
database,
navController,
)
},
)
@@ -712,7 +719,8 @@ fun MainScreen(
modifier = Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
account = account,
navController = navController,
database = database,
@@ -727,7 +735,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
accountStateViewModel,
account,
navController,
@@ -742,7 +751,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
account,
)
},
@@ -758,7 +768,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
account = account,
selectedPackage = packageName,
navController = navController,
@@ -776,7 +787,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
account = account,
)
},
@@ -791,7 +803,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
)
},
)
@@ -804,7 +817,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
account = account,
)
},
@@ -818,7 +832,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
accountStateViewModel = accountStateViewModel,
account = account,
)
@@ -833,7 +848,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
account = account,
navController = navController,
)
@@ -848,7 +864,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
navController = navController,
)
},
@@ -865,7 +882,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
)
},
)
@@ -882,7 +900,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
)
},
)
@@ -900,7 +919,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
)
}
},
@@ -918,7 +938,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
)
}
},
@@ -936,7 +957,8 @@ fun MainScreen(
Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
)
}
},
@@ -951,7 +973,8 @@ fun MainScreen(
modifier = Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
database = database,
key = key,
accountStateViewModel = accountStateViewModel,
@@ -969,7 +992,8 @@ fun MainScreen(
modifier = Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
navController = navController,
)
},
@@ -984,7 +1008,8 @@ fun MainScreen(
modifier = Modifier
.fillMaxSize()
.padding(padding)
.padding(defaultPadding),
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
accountStateViewModel = accountStateViewModel,
pin = pin,
navController = navController,
@@ -992,6 +1017,19 @@ fun MainScreen(
}
},
)
composable(
Route.SeeDetails.route,
content = {
SeeDetailsScreen(
modifier = Modifier
.fillMaxSize()
.padding(padding)
.padding(horizontal = verticalPadding)
.padding(top = verticalPadding * 1.5f),
)
},
)
}
}
}
@@ -12,7 +12,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
@@ -91,12 +90,7 @@ fun NewApplicationScreen(
context.getAppCompatActivity()?.startActivity(intent)
accountStateViewModel.switchUser(account.signer.keyPair.pubKey.toNpub(), Route.IncomingRequest.route)
},
content = {
Text(
text = stringResource(R.string.paste_from_clipboard),
Modifier.scale(1.25f),
)
},
text = stringResource(R.string.paste_from_clipboard),
)
Text(
@@ -108,12 +102,7 @@ fun NewApplicationScreen(
onClick = {
dialogOpen = true
},
content = {
Text(
text = stringResource(R.string.scan_qr_code),
Modifier.scale(1.25f),
)
},
text = stringResource(R.string.scan_qr_code),
)
Text(
@@ -125,12 +114,7 @@ fun NewApplicationScreen(
onClick = {
navController.navigate(Route.NewNsecBunker.route)
},
content = {
Text(
text = stringResource(R.string.add_a_nsecbunker),
Modifier.scale(1.25f),
)
},
text = stringResource(R.string.add_a_nsecbunker),
)
Text(
@@ -8,12 +8,10 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
@@ -30,7 +28,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.platform.LocalClipboardManager
@@ -40,7 +37,6 @@ import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
@@ -93,7 +89,8 @@ fun NewNsecBunkerScreen(
if (isLoading.value) {
CenterCircularProgressIndicator(
modifier = Modifier.fillMaxSize(),
modifier = Modifier,
text = "Testing the relay...",
)
} else {
Column(
@@ -181,47 +178,18 @@ fun NewNsecBunkerScreen(
Spacer(modifier = Modifier.height(16.dp))
LazyColumn(
Modifier
.padding(bottom = 20.dp),
) {
items(relays.size) {
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Text(
relays[it].url,
Modifier
.weight(0.9f)
.padding(8.dp),
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
IconButton(
onClick = {
relays.removeAt(it)
},
) {
Icon(
Icons.Default.Delete,
stringResource(R.string.delete),
)
}
}
}
relays.forEachIndexed { index, relay ->
RelayCard(
relay = relay.url,
onClick = {
relays.removeAt(index)
},
)
}
AmberButton(
content = {
Text(
text = stringResource(R.string.create),
Modifier.scale(1.25f),
)
},
Modifier.padding(top = 20.dp),
text = stringResource(R.string.create),
onClick = {
if (relays.isEmpty()) {
accountStateViewModel.toast(
@@ -335,12 +303,7 @@ fun NewNsecBunkerCreatedScreen(
onClick = {
clipboardManager.setText(AnnotatedString(bunkerUri))
},
content = {
Text(
text = stringResource(R.string.copy_to_clipboard),
Modifier.scale(1.25f),
)
},
text = stringResource(R.string.copy_to_clipboard),
)
}
}
@@ -52,33 +52,8 @@ fun PermissionsScreen(
} else {
LazyColumn(
Modifier
.fillMaxSize()
.padding(8.dp),
.fillMaxSize(),
) {
// item {
// Row(
// Modifier
// .fillMaxWidth()
// .padding(8.dp)
// .clickable {
//
// },
// horizontalArrangement = Arrangement.End,
// ) {
// Icon(
// Icons.AutoMirrored.Filled.Sort,
// null,
// modifier = Modifier.size(22.dp),
// tint = MaterialTheme.colorScheme.onBackground,
// )
// Text(
// modifier = Modifier.padding(start = 16.dp),
// text = "Sort by $sortBy",
// maxLines = 1,
// overflow = TextOverflow.Ellipsis,
// )
// }
// }
itemsIndexed(applications.value) { _, applicationWithHistory ->
Row(
modifier = Modifier
@@ -142,11 +142,7 @@ fun SecurityScreen(
}
}
},
content = {
Text(
text = stringResource(R.string.save),
)
},
text = stringResource(R.string.save),
)
}
}
@@ -0,0 +1,145 @@
package com.greenart7c3.nostrsigner.ui
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
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.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.toLowerCase
import androidx.compose.ui.unit.dp
import com.greenart7c3.nostrsigner.R
import com.greenart7c3.nostrsigner.models.Permission
import com.greenart7c3.nostrsigner.models.SignerType
import com.greenart7c3.nostrsigner.service.MultiEventScreenIntents
import com.greenart7c3.nostrsigner.service.model.AmberEvent
@Composable
fun SeeDetailsScreen(
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
Column(
modifier = modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState()),
) {
var rememberMyChoice by remember { mutableStateOf(MultiEventScreenIntents.intents.first().rememberMyChoice.value) }
val first = MultiEventScreenIntents.intents.first()
val permission = if (first.type == SignerType.SIGN_EVENT) {
Permission("sign_event", first.event!!.kind)
} else {
Permission(first.type.toString().toLowerCase(Locale.current), null)
}
val message = if (first.type == SignerType.CONNECT) {
stringResource(R.string.connect)
} else {
permission.toLocalizedString(context)
}
Text(
stringResource(R.string.is_requiring_to_sign_these_events_related_to_permission, MultiEventScreenIntents.appName, message),
Modifier
.fillMaxWidth()
.padding(bottom = 20.dp),
)
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(vertical = 8.dp)
.clickable {
rememberMyChoice = !rememberMyChoice
MultiEventScreenIntents.intents.forEach { intent ->
intent.rememberMyChoice.value = rememberMyChoice
}
},
) {
Switch(
modifier = Modifier.scale(0.85f),
checked = rememberMyChoice,
onCheckedChange = {
rememberMyChoice = !rememberMyChoice
MultiEventScreenIntents.intents.forEach { intent ->
intent.rememberMyChoice.value = rememberMyChoice
}
},
)
Text(
modifier = Modifier
.weight(1f)
.padding(start = 8.dp),
text = stringResource(R.string.always_approve_this_permission),
)
}
MultiEventScreenIntents.intents.forEach { intent ->
Card(
Modifier
.padding(4.dp),
colors = CardDefaults.cardColors().copy(
containerColor = MaterialTheme.colorScheme.background,
),
border = BorderStroke(1.dp, Color.Gray),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clickable {
intent.checked.value = !intent.checked.value
},
) {
Checkbox(
checked = intent.checked.value,
onCheckedChange = { _ ->
intent.checked.value = !intent.checked.value
},
colors = CheckboxDefaults.colors().copy(
uncheckedBorderColor = Color.Gray,
),
)
val data = if (intent.type == SignerType.SIGN_EVENT) {
val event = intent.event!!
if (event.kind == 22242) AmberEvent.relay(event) else event.content
} else {
intent.encryptedData ?: intent.data
}
Text(
modifier = Modifier
.weight(1f)
.padding(vertical = 8.dp),
text = data.ifBlank { message },
color = if (intent.checked.value) Color.Unspecified else Color.Gray,
)
}
}
}
}
}
@@ -100,7 +100,7 @@ fun SettingsScreen(
) {
Box(
Modifier
.padding(vertical = 8.dp),
.padding(bottom = 8.dp),
) {
IconRow(
title = stringResource(R.string.security),
@@ -121,11 +121,7 @@ fun SignPolicySettingsScreen(
}
}
},
content = {
Text(
text = stringResource(R.string.save),
)
},
text = stringResource(R.string.save),
)
}
}
@@ -176,9 +176,7 @@ fun AccountBackupScreen(
},
)
},
content = {
Text(text = stringResource(R.string.show_seed_words))
},
text = stringResource(R.string.show_seed_words),
)
}
NSecCopyButton(account)
@@ -324,11 +322,7 @@ private fun NSecQrButton(account: Account) {
},
)
},
content = {
Text(
stringResource(id = R.string.show_qr_code),
)
},
text = stringResource(id = R.string.show_qr_code),
)
}
@@ -411,9 +405,7 @@ private fun NSecCopyButton(account: Account) {
},
)
},
content = {
Text(stringResource(id = R.string.copy_my_secret_key))
},
text = stringResource(id = R.string.copy_my_secret_key),
)
}
@@ -471,13 +463,9 @@ private fun EncryptNSecCopyButton(
)
},
enabled = password.value.text.isNotBlank(),
content = {
Text(
stringResource(id = R.string.encrypt_and_copy_my_secret_key),
maxLines = 1,
textAlign = TextAlign.Center,
)
},
text = stringResource(id = R.string.encrypt_and_copy_my_secret_key),
maxLines = 1,
textAlign = TextAlign.Center,
)
}
@@ -528,11 +516,7 @@ private fun EncryptNSecQRButton(
)
},
enabled = password.value.text.isNotBlank(),
content = {
Text(
stringResource(id = R.string.show_qr_code),
)
},
text = stringResource(id = R.string.show_qr_code),
)
}
@@ -124,7 +124,7 @@ fun ActivityScreen(
if (activity.accepted) Icons.Default.Check else Icons.Default.Close,
contentDescription = if (activity.accepted) stringResource(R.string.accepted) else stringResource(R.string.rejected),
tint = if (activity.accepted) Color(0xFF1D8802) else Color(0xFFFF6B00),
modifier = Modifier.padding(top = 4.dp, bottom = 16.dp),
modifier = Modifier.padding(start = 10.dp, top = 4.dp, bottom = 16.dp),
)
}
Spacer(Modifier.weight(1f))
@@ -15,11 +15,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
@@ -37,7 +33,6 @@ 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.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.TextFieldValue
@@ -57,6 +52,7 @@ 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.RelayCard
import com.greenart7c3.nostrsigner.ui.components.AmberButton
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.ammolite.relays.Client
@@ -108,7 +104,10 @@ fun DefaultRelaysScreen(
.fillMaxSize(),
) {
if (isLoading.value) {
CenterCircularProgressIndicator(Modifier)
CenterCircularProgressIndicator(
Modifier,
text = "Testing relay...",
)
} else {
Column(
modifier = Modifier
@@ -117,8 +116,7 @@ fun DefaultRelaysScreen(
) {
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
.fillMaxWidth(),
value = textFieldRelay.value.text,
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.None,
@@ -168,8 +166,7 @@ fun DefaultRelaysScreen(
AmberButton(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
.fillMaxWidth(),
onClick = {
scope.launch(Dispatchers.IO) {
onAddRelay(
@@ -202,9 +199,7 @@ fun DefaultRelaysScreen(
)
}
},
content = {
Text(stringResource(R.string.add))
},
text = stringResource(R.string.add),
)
LazyColumn(
@@ -212,47 +207,29 @@ fun DefaultRelaysScreen(
.weight(1f),
) {
items(relays2.size) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Text(
relays2[it].url,
Modifier
.weight(0.9f)
.padding(16.dp),
fontWeight = FontWeight.Bold,
fontSize = 18.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
IconButton(
onClick = {
isLoading.value = true
relays2.removeAt(it)
NostrSigner.getInstance().settings = NostrSigner.getInstance().settings.copy(
defaultRelays = relays2,
)
LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
scope.launch(Dispatchers.IO) {
@Suppress("KotlinConstantConditions")
if (BuildConfig.FLAVOR != "offline") {
NostrSigner.getInstance().checkForNewRelays()
NotificationDataSource.stop()
delay(2000)
NotificationDataSource.start()
isLoading.value = false
} else {
isLoading.value = false
}
}
},
) {
Icon(
Icons.Default.Delete,
stringResource(R.string.delete),
RelayCard(
relay = relays2[it].url,
onClick = {
isLoading.value = true
relays2.removeAt(it)
NostrSigner.getInstance().settings = NostrSigner.getInstance().settings.copy(
defaultRelays = relays2,
)
}
}
LocalPreferences.saveSettingsToEncryptedStorage(NostrSigner.getInstance().settings)
scope.launch(Dispatchers.IO) {
@Suppress("KotlinConstantConditions")
if (BuildConfig.FLAVOR != "offline") {
NostrSigner.getInstance().checkForNewRelays()
NotificationDataSource.stop()
delay(2000)
NotificationDataSource.start()
isLoading.value = false
} else {
isLoading.value = false
}
}
},
)
}
}
}
@@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -27,17 +26,16 @@ fun AcceptRejectButtons(
AmberButton(
modifier = Modifier.fillMaxWidth(),
onClick = onAccept,
) {
Text(stringResource(R.string.accept))
}
text = stringResource(R.string.accept),
)
Spacer(modifier = Modifier.width(20.dp))
AmberButton(
onClick = onReject,
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFFFF6B00),
),
) {
Text(stringResource(R.string.reject))
}
text = stringResource(R.string.reject),
)
}
}
@@ -10,9 +10,12 @@ import androidx.compose.material3.Button
import androidx.compose.material3.ButtonColors
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@Composable
@@ -23,7 +26,10 @@ fun AmberButton(
colors: ButtonColors = ButtonDefaults.buttonColors().copy(
contentColor = Color.Black,
),
content: @Composable () -> Unit,
textColor: Color = Color.Unspecified,
text: String,
textAlign: TextAlign? = null,
maxLines: Int = Int.MAX_VALUE,
) {
Row(
modifier.fillMaxWidth(),
@@ -39,7 +45,13 @@ fun AmberButton(
.padding(vertical = 6.dp),
contentPadding = PaddingValues(vertical = 14.dp),
) {
content()
Text(
text = text,
color = textColor,
modifier = Modifier.scale(1.50f),
textAlign = textAlign,
maxLines = maxLines,
)
}
}
}
@@ -49,7 +61,10 @@ fun AmberElevatedButton(
modifier: Modifier = Modifier,
onClick: () -> Unit,
enabled: Boolean = true,
content: @Composable () -> Unit,
textColor: Color = Color.Unspecified,
text: String,
textAlign: TextAlign? = null,
maxLines: Int = Int.MAX_VALUE,
) {
Row(
modifier.fillMaxWidth(),
@@ -64,7 +79,13 @@ fun AmberElevatedButton(
.padding(vertical = 6.dp),
contentPadding = PaddingValues(vertical = 14.dp),
) {
content()
Text(
text = text,
color = textColor,
modifier = Modifier.scale(1.50f),
textAlign = textAlign,
maxLines = maxLines,
)
}
}
}
@@ -40,7 +40,7 @@ fun IconRow(
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 15.dp, horizontal = 25.dp),
.padding(vertical = 15.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = if (center) Arrangement.Center else Arrangement.Start,
) {
@@ -81,7 +81,7 @@ fun IconRow(
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 15.dp, horizontal = 25.dp),
.padding(vertical = 15.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
@@ -224,9 +224,7 @@ fun LoginWithPubKey(
onClick = {
onAccept(localPermissions, selectedOption)
},
content = {
Text(stringResource(R.string.grant_permissions))
},
text = stringResource(R.string.grant_permissions),
)
AmberButton(
@@ -235,9 +233,7 @@ fun LoginWithPubKey(
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFFFF6B00),
),
content = {
Text(stringResource(R.string.reject))
},
text = stringResource(R.string.reject),
)
}
}
@@ -5,6 +5,7 @@ import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -14,17 +15,12 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CheckboxDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -36,12 +32,9 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.LinkAnnotation
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextLinkStyles
@@ -52,8 +45,7 @@ import androidx.compose.ui.text.toLowerCase
import androidx.compose.ui.text.withLink
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.navigation.NavController
import com.google.gson.GsonBuilder
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.NostrSigner
@@ -71,8 +63,8 @@ import com.greenart7c3.nostrsigner.service.AmberUtils
import com.greenart7c3.nostrsigner.service.ApplicationNameCache
import com.greenart7c3.nostrsigner.service.EventNotificationConsumer
import com.greenart7c3.nostrsigner.service.IntentUtils
import com.greenart7c3.nostrsigner.service.MultiEventScreenIntents
import com.greenart7c3.nostrsigner.service.getAppCompatActivity
import com.greenart7c3.nostrsigner.service.model.AmberEvent
import com.greenart7c3.nostrsigner.service.toShortenHex
import com.greenart7c3.nostrsigner.ui.Result
import com.greenart7c3.nostrsigner.ui.navigation.Route
@@ -84,19 +76,18 @@ import com.vitorpamplona.quartz.events.LnZapRequestEvent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MultiEventHomeScreen(
intents: List<IntentData>,
packageName: String?,
accountParam: Account,
navController: NavController,
onLoading: (Boolean) -> Unit,
) {
val coroutineScope = rememberCoroutineScope()
val context = LocalContext.current
val grouped = intents.groupBy { it.type }.filter { it.key != SignerType.SIGN_EVENT }
val grouped2 = intents.filter { it.type == SignerType.SIGN_EVENT }.groupBy { it.event?.kind }
var intentsDialog by remember { mutableStateOf<List<IntentData>?>(null) }
val acceptEventsGroup1 = grouped.map {
remember {
mutableStateOf(true)
@@ -121,453 +112,318 @@ fun MultiEventHomeScreen(
val appName = ApplicationNameCache.names["$localAccount-$key"] ?: key.toShortenHex()
if (intentsDialog != null) {
Dialog(
properties = DialogProperties(
usePlatformDefaultWidth = false,
),
onDismissRequest = {
intentsDialog = null
},
) {
Scaffold(
bottomBar = {
BottomAppBar {
IconRow(
center = true,
title = stringResource(R.string.back_to, Route.IncomingRequest.title),
icon = ImageVector.vectorResource(R.drawable.back),
onClick = {
intentsDialog = null
},
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
Column(
Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState()),
) {
Text(
stringResource(R.string.is_requiring_some_permissions_please_review_them, appName),
Modifier
.fillMaxWidth()
.padding(bottom = 20.dp),
)
grouped.toList().forEachIndexed { index, it ->
PermissionCard(
context = context,
acceptEventsGroup = acceptEventsGroup1,
index = index,
item = it,
onDetailsClick = {
MultiEventScreenIntents.intents = it
MultiEventScreenIntents.appName = appName
navController.navigate(Route.SeeDetails.route)
},
topBar = {
CenterAlignedTopAppBar(
title = {
Text(Route.IncomingRequest.title)
},
)
)
}
grouped2.toList().forEachIndexed { index, it ->
PermissionCard(
context = context,
acceptEventsGroup = acceptEventsGroup2,
index = index,
item = it,
onDetailsClick = {
MultiEventScreenIntents.intents = it
MultiEventScreenIntents.appName = appName
navController.navigate(Route.SeeDetails.route)
},
) {
Column(
modifier = Modifier
.padding(it)
.padding(40.dp),
) {
var rememberMyChoice by remember { mutableStateOf(intentsDialog!!.first().rememberMyChoice.value) }
val first = intentsDialog!!.first()
val permission = if (first.type == SignerType.SIGN_EVENT) {
Permission("sign_event", first.event!!.kind)
} else {
Permission(first.type.toString().toLowerCase(Locale.current), null)
}
)
}
val message = if (first.type == SignerType.CONNECT) {
stringResource(R.string.connect)
} else {
permission.toLocalizedString(context)
}
Text(
stringResource(R.string.is_requiring_to_sign_these_events_related_to_permission, appName, message),
Modifier
.fillMaxWidth()
.padding(bottom = 20.dp),
)
AmberButton(
Modifier.padding(vertical = 20.dp),
text = stringResource(R.string.approve_selected),
onClick = {
onLoading(true)
coroutineScope.launch(Dispatchers.IO) {
try {
val activity = context.getAppCompatActivity()
val results = mutableListOf<Result>()
reconnectToRelays(intents)
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.padding(vertical = 8.dp)
.clickable {
rememberMyChoice = !rememberMyChoice
intentsDialog?.forEach { intent ->
intent.rememberMyChoice.value = rememberMyChoice
for (intentData in intents) {
val localAccount =
if (intentData.currentAccount.isNotBlank()) {
LocalPreferences.loadFromEncryptedStorage(
context,
intentData.currentAccount,
)
} else {
accountParam
} ?: continue
val key = intentData.bunkerRequest?.localKey ?: packageName ?: continue
val database = NostrSigner.getInstance().getDatabase(localAccount.signer.keyPair.pubKey.toNpub())
val application =
database
.applicationDao()
.getByKey(key) ?: ApplicationWithPermissions(
application = ApplicationEntity(
key,
"",
listOf(),
"",
"",
"",
localAccount.signer.keyPair.pubKey.toHexKey(),
true,
intentData.bunkerRequest?.secret ?: "",
intentData.bunkerRequest?.secret != null,
localAccount.signPolicy,
),
permissions = mutableListOf(),
)
if (intentData.type == SignerType.SIGN_EVENT) {
val localEvent = intentData.event!!
if (intentData.rememberMyChoice.value && intentData.checked.value) {
AmberUtils.acceptOrRejectPermission(
application,
key,
intentData,
localEvent.kind,
intentData.rememberMyChoice.value,
database,
)
}
},
) {
Switch(
modifier = Modifier.scale(0.85f),
checked = rememberMyChoice,
onCheckedChange = {
rememberMyChoice = !rememberMyChoice
intentsDialog?.forEach { intent ->
intent.rememberMyChoice.value = rememberMyChoice
}
},
)
Text(
modifier = Modifier
.weight(1f)
.padding(start = 8.dp),
text = stringResource(R.string.always_approve_this_permission),
)
}
intentsDialog?.forEach { intent ->
Card(
Modifier
.padding(4.dp),
colors = CardDefaults.cardColors().copy(
containerColor = MaterialTheme.colorScheme.background,
),
border = BorderStroke(1.dp, Color.Gray),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clickable {
intent.checked.value = !intent.checked.value
},
) {
Checkbox(
checked = intent.checked.value,
onCheckedChange = { _ ->
intent.checked.value = !intent.checked.value
},
colors = CheckboxDefaults.colors().copy(
uncheckedBorderColor = Color.Gray,
database.applicationDao().insertApplicationWithPermissions(application)
database.applicationDao().addHistory(
HistoryEntity(
0,
key,
intentData.type.toString(),
localEvent.kind,
TimeUtils.now(),
intentData.checked.value,
),
)
val data = if (intent.type == SignerType.SIGN_EVENT) {
val event = intent.event!!
if (event.kind == 22242) AmberEvent.relay(event) else event.content
if (intentData.bunkerRequest != null) {
if (intentData.checked.value) {
IntentUtils.sendBunkerResponse(
context,
localAccount,
intentData.bunkerRequest,
BunkerResponse(intentData.bunkerRequest.id, localEvent.toJson(), null),
application.application.relays,
onLoading = {},
onDone = {},
)
} else {
AmberUtils.sendBunkerError(
localAccount,
intentData.bunkerRequest,
relays = application.application.relays,
context = context,
onLoading = {},
)
}
} else {
intent.encryptedData ?: intent.data
if (intentData.checked.value) {
results.add(
Result(
null,
signature = if (localEvent is LnZapRequestEvent &&
localEvent.tags.any { tag ->
tag.any { t -> t == "anon" }
}
) {
localEvent.toJson()
} else {
localEvent.sig
},
result = if (localEvent is LnZapRequestEvent &&
localEvent.tags.any { tag ->
tag.any { t -> t == "anon" }
}
) {
localEvent.toJson()
} else {
localEvent.sig
},
id = intentData.id,
),
)
}
}
} else if (intentData.type == SignerType.SIGN_MESSAGE) {
if (intentData.rememberMyChoice.value && intentData.checked.value) {
AmberUtils.acceptOrRejectPermission(
application,
key,
intentData,
null,
intentData.rememberMyChoice.value,
database,
)
}
Text(
modifier = Modifier
.weight(1f)
.padding(vertical = 8.dp),
text = data,
color = if (intent.checked.value) Color.Unspecified else Color.Gray,
database.applicationDao().insertApplicationWithPermissions(application)
database.applicationDao().addHistory(
HistoryEntity(
0,
key,
intentData.type.toString(),
null,
TimeUtils.now(),
intentData.checked.value,
),
)
val signedMessage = CryptoUtils.signString(intentData.data, localAccount.signer.keyPair.privKey!!).toHexKey()
if (intentData.bunkerRequest != null) {
if (intentData.checked.value) {
IntentUtils.sendBunkerResponse(
context,
localAccount,
intentData.bunkerRequest,
BunkerResponse(intentData.bunkerRequest.id, signedMessage, null),
application.application.relays,
onLoading = {},
onDone = {},
)
} else {
AmberUtils.sendBunkerError(
localAccount,
intentData.bunkerRequest,
relays = application.application.relays,
context = context,
onLoading = {},
)
}
} else {
if (intentData.checked.value) {
results.add(
Result(
null,
signature = signedMessage,
result = signedMessage,
id = intentData.id,
),
)
}
}
} else {
if (intentData.rememberMyChoice.value && intentData.checked.value) {
AmberUtils.acceptOrRejectPermission(
application,
key,
intentData,
null,
intentData.rememberMyChoice.value,
database,
)
}
database.applicationDao().insertApplicationWithPermissions(application)
database.applicationDao().addHistory(
HistoryEntity(
0,
key,
intentData.type.toString(),
null,
TimeUtils.now(),
intentData.checked.value,
),
)
val signature = intentData.encryptedData ?: continue
if (intentData.bunkerRequest != null) {
if (intentData.checked.value) {
IntentUtils.sendBunkerResponse(
context,
localAccount,
intentData.bunkerRequest,
BunkerResponse(intentData.bunkerRequest.id, signature, null),
application.application.relays,
onLoading = {},
onDone = {},
)
} else {
AmberUtils.sendBunkerError(
localAccount,
intentData.bunkerRequest,
relays = application.application.relays,
context = context,
onLoading = {},
)
}
} else {
if (intentData.checked.value) {
results.add(
Result(
null,
signature = signature,
result = signature,
id = intentData.id,
),
)
}
}
}
}
if (results.isNotEmpty()) {
sendResultIntent(results, activity)
}
if (intents.any { it.bunkerRequest != null }) {
EventNotificationConsumer(context).notificationManager().cancelAll()
finishActivity(activity)
} else {
finishActivity(activity)
}
} finally {
onLoading(false)
}
}
}
}
} else {
Column(
Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState()),
) {
Text(
stringResource(R.string.is_requiring_some_permissions_please_review_them, appName),
Modifier
.fillMaxWidth()
.padding(bottom = 20.dp),
)
},
)
grouped.toList().forEachIndexed { index, it ->
PermissionCard(
context = context,
acceptEventsGroup = acceptEventsGroup1,
index = index,
item = it,
onDetailsClick = {
intentsDialog = it
},
)
}
grouped2.toList().forEachIndexed { index, it ->
PermissionCard(
context = context,
acceptEventsGroup = acceptEventsGroup2,
index = index,
item = it,
onDetailsClick = {
intentsDialog = it
},
)
}
AmberButton(
Modifier.padding(vertical = 20.dp),
content = {
Text(stringResource(R.string.approve_selected))
},
onClick = {
onLoading(true)
coroutineScope.launch(Dispatchers.IO) {
try {
val activity = context.getAppCompatActivity()
val results = mutableListOf<Result>()
reconnectToRelays(intents)
for (intentData in intents) {
val localAccount =
if (intentData.currentAccount.isNotBlank()) {
LocalPreferences.loadFromEncryptedStorage(
context,
intentData.currentAccount,
)
} else {
accountParam
} ?: continue
val key = intentData.bunkerRequest?.localKey ?: packageName ?: continue
val database = NostrSigner.getInstance().getDatabase(localAccount.signer.keyPair.pubKey.toNpub())
val application =
database
.applicationDao()
.getByKey(key) ?: ApplicationWithPermissions(
application = ApplicationEntity(
key,
"",
listOf(),
"",
"",
"",
localAccount.signer.keyPair.pubKey.toHexKey(),
true,
intentData.bunkerRequest?.secret ?: "",
intentData.bunkerRequest?.secret != null,
localAccount.signPolicy,
),
permissions = mutableListOf(),
)
if (intentData.type == SignerType.SIGN_EVENT) {
val localEvent = intentData.event!!
if (intentData.rememberMyChoice.value && intentData.checked.value) {
AmberUtils.acceptOrRejectPermission(
application,
key,
intentData,
localEvent.kind,
intentData.rememberMyChoice.value,
database,
)
}
database.applicationDao().insertApplicationWithPermissions(application)
database.applicationDao().addHistory(
HistoryEntity(
0,
key,
intentData.type.toString(),
localEvent.kind,
TimeUtils.now(),
intentData.checked.value,
),
)
if (intentData.bunkerRequest != null) {
if (intentData.checked.value) {
IntentUtils.sendBunkerResponse(
context,
localAccount,
intentData.bunkerRequest,
BunkerResponse(intentData.bunkerRequest.id, localEvent.toJson(), null),
application.application.relays,
onLoading = {},
onDone = {},
)
} else {
AmberUtils.sendBunkerError(
localAccount,
intentData.bunkerRequest,
relays = application.application.relays,
context = context,
onLoading = {},
)
}
} else {
if (intentData.checked.value) {
results.add(
Result(
null,
signature = if (localEvent is LnZapRequestEvent &&
localEvent.tags.any { tag ->
tag.any { t -> t == "anon" }
}
) {
localEvent.toJson()
} else {
localEvent.sig
},
result = if (localEvent is LnZapRequestEvent &&
localEvent.tags.any { tag ->
tag.any { t -> t == "anon" }
}
) {
localEvent.toJson()
} else {
localEvent.sig
},
id = intentData.id,
),
)
}
}
} else if (intentData.type == SignerType.SIGN_MESSAGE) {
if (intentData.rememberMyChoice.value && intentData.checked.value) {
AmberUtils.acceptOrRejectPermission(
application,
key,
intentData,
null,
intentData.rememberMyChoice.value,
database,
)
}
database.applicationDao().insertApplicationWithPermissions(application)
database.applicationDao().addHistory(
HistoryEntity(
0,
key,
intentData.type.toString(),
null,
TimeUtils.now(),
intentData.checked.value,
),
)
val signedMessage = CryptoUtils.signString(intentData.data, localAccount.signer.keyPair.privKey!!).toHexKey()
if (intentData.bunkerRequest != null) {
if (intentData.checked.value) {
IntentUtils.sendBunkerResponse(
context,
localAccount,
intentData.bunkerRequest,
BunkerResponse(intentData.bunkerRequest.id, signedMessage, null),
application.application.relays,
onLoading = {},
onDone = {},
)
} else {
AmberUtils.sendBunkerError(
localAccount,
intentData.bunkerRequest,
relays = application.application.relays,
context = context,
onLoading = {},
)
}
} else {
if (intentData.checked.value) {
results.add(
Result(
null,
signature = signedMessage,
result = signedMessage,
id = intentData.id,
),
)
}
}
} else {
if (intentData.rememberMyChoice.value && intentData.checked.value) {
AmberUtils.acceptOrRejectPermission(
application,
key,
intentData,
null,
intentData.rememberMyChoice.value,
database,
)
}
database.applicationDao().insertApplicationWithPermissions(application)
database.applicationDao().addHistory(
HistoryEntity(
0,
key,
intentData.type.toString(),
null,
TimeUtils.now(),
intentData.checked.value,
),
)
val signature = intentData.encryptedData ?: continue
if (intentData.bunkerRequest != null) {
if (intentData.checked.value) {
IntentUtils.sendBunkerResponse(
context,
localAccount,
intentData.bunkerRequest,
BunkerResponse(intentData.bunkerRequest.id, signature, null),
application.application.relays,
onLoading = {},
onDone = {},
)
} else {
AmberUtils.sendBunkerError(
localAccount,
intentData.bunkerRequest,
relays = application.application.relays,
context = context,
onLoading = {},
)
}
} else {
if (intentData.checked.value) {
results.add(
Result(
null,
signature = signature,
result = signature,
id = intentData.id,
),
)
}
}
}
}
if (results.isNotEmpty()) {
sendResultIntent(results, activity)
}
if (intents.any { it.bunkerRequest != null }) {
EventNotificationConsumer(context).notificationManager().cancelAll()
finishActivity(activity)
} else {
finishActivity(activity)
}
} finally {
onLoading(false)
}
}
},
)
AmberButton(
Modifier.padding(vertical = 20.dp),
colors = ButtonDefaults.buttonColors().copy(
containerColor = orange,
),
onClick = {
val activity = context.getAppCompatActivity()
if (intents.any { it.bunkerRequest != null }) {
EventNotificationConsumer(context).notificationManager().cancelAll()
finishActivity(activity)
} else {
finishActivity(activity)
}
},
content = {
Text(stringResource(R.string.discard_all_requests))
},
)
}
AmberButton(
Modifier.padding(vertical = 20.dp),
colors = ButtonDefaults.buttonColors().copy(
containerColor = orange,
),
onClick = {
val activity = context.getAppCompatActivity()
if (intents.any { it.bunkerRequest != null }) {
EventNotificationConsumer(context).notificationManager().cancelAll()
finishActivity(activity)
} else {
finishActivity(activity)
}
},
text = stringResource(R.string.discard_all_requests),
)
}
}
@@ -29,6 +29,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
@@ -123,7 +124,11 @@ fun RandomPinInput(
},
modifier = Modifier.padding(8.dp),
) {
Text(number.toString(), color = Color.Black)
Text(
number.toString(),
color = Color.Black,
modifier = Modifier.scale(1.50f),
)
}
}
@@ -155,7 +160,11 @@ fun RandomPinInput(
},
modifier = Modifier.weight(1f).padding(8.dp),
) {
Text(randomNumbers.last().toString(), color = Color.Black)
Text(
randomNumbers.last().toString(),
color = Color.Black,
modifier = Modifier.scale(1.50f),
)
}
}
@@ -88,8 +88,7 @@ fun RawJson(
}
}
},
) {
Text(stringResource(R.string.copy) + label)
}
text = (stringResource(R.string.copy) + label),
)
}
}
@@ -61,9 +61,7 @@ fun SeedWordsPage(
onClick = {
clipboardManager.setText(AnnotatedString(seedWords.joinToString(" ")))
},
content = {
Text(text = stringResource(R.string.copy_to_clipboard))
},
text = stringResource(R.string.copy_to_clipboard),
)
Row(
@@ -127,9 +125,7 @@ fun SeedWordsPage(
if (showNextButton) {
AmberButton(
onClick = onNextPage,
content = {
Text(text = stringResource(R.string.next))
},
text = stringResource(R.string.next),
)
}
}
@@ -151,6 +151,13 @@ sealed class Route(
icon = R.drawable.settings,
selectedIcon = R.drawable.settings,
)
data object SeeDetails : Route(
title = NostrSigner.getInstance().getString(R.string.incoming_request),
route = "SeeDetails",
icon = R.drawable.settings,
selectedIcon = R.drawable.settings,
)
}
val routes = listOf(
@@ -174,4 +181,5 @@ val routes = listOf(
Route.EditConfiguration,
Route.SetupPin,
Route.ConfirmPin,
Route.SeeDetails,
)
@@ -36,8 +36,7 @@ val primaryColor = Color(0xFFFFCA62)
val primaryVariant = Color(0xFFC8541A)
val secondaryColor = Color(0xFFFFCA62)
val orange = Color(0xFFFF6B00)
val defaultPadding = 40.dp
val defaultPadding = 35.dp
val RichTextDefaults = RichTextStyle().resolveDefaults()
private val DarkColorPalette =