Merge pull request #2781 from mstrofnone/fix/selectable-error-messages
fix(desktop): make error messages selectable so users can copy them
This commit is contained in:
+13
@@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@@ -66,6 +67,11 @@ fun LoadingState(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A centered empty state with title, optional description, and optional refresh action.
|
* A centered empty state with title, optional description, and optional refresh action.
|
||||||
|
*
|
||||||
|
* The optional `description` is wrapped in a [SelectionContainer] so users can
|
||||||
|
* select and copy it. `EmptyState` is reused as the in-feed error renderer
|
||||||
|
* (e.g. "Error loading feed" with the underlying error in `description`), so
|
||||||
|
* making the description selectable lets users copy error text for reporting.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun EmptyState(
|
fun EmptyState(
|
||||||
@@ -89,12 +95,14 @@ fun EmptyState(
|
|||||||
)
|
)
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
|
SelectionContainer {
|
||||||
Text(
|
Text(
|
||||||
description,
|
description,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
|
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (onRefresh != null) {
|
if (onRefresh != null) {
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
OutlinedButton(onClick = onRefresh) {
|
OutlinedButton(onClick = onRefresh) {
|
||||||
@@ -106,6 +114,9 @@ fun EmptyState(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A centered error state with message and optional retry action.
|
* A centered error state with message and optional retry action.
|
||||||
|
*
|
||||||
|
* The error `message` is wrapped in a [SelectionContainer] so users can select
|
||||||
|
* and copy it — useful for reporting bugs or pasting error text into a search.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun ErrorState(
|
fun ErrorState(
|
||||||
@@ -121,11 +132,13 @@ fun ErrorState(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
) {
|
) {
|
||||||
|
SelectionContainer {
|
||||||
Text(
|
Text(
|
||||||
message,
|
message,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = MaterialTheme.colorScheme.error,
|
color = MaterialTheme.colorScheme.error,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
if (onRetry != null) {
|
if (onRetry != null) {
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
Button(onClick = onRetry) {
|
Button(onClick = onRetry) {
|
||||||
|
|||||||
+5
@@ -31,6 +31,7 @@ import androidx.compose.foundation.layout.height
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@@ -251,21 +252,25 @@ fun ComposeNoteDialog(
|
|||||||
|
|
||||||
errorMessage?.let { error ->
|
errorMessage?.let { error ->
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
|
SelectionContainer {
|
||||||
Text(
|
Text(
|
||||||
error,
|
error,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.error,
|
color = MaterialTheme.colorScheme.error,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uploadState.error?.let { error ->
|
uploadState.error?.let { error ->
|
||||||
Spacer(Modifier.height(4.dp))
|
Spacer(Modifier.height(4.dp))
|
||||||
|
SelectionContainer {
|
||||||
Text(
|
Text(
|
||||||
"Upload error: $error",
|
"Upload error: $error",
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.error,
|
color = MaterialTheme.colorScheme.error,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.desktop.ui.auth
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
@@ -85,7 +86,11 @@ fun KeyInputField(
|
|||||||
isError = errorMessage != null,
|
isError = errorMessage != null,
|
||||||
supportingText =
|
supportingText =
|
||||||
errorMessage?.let {
|
errorMessage?.let {
|
||||||
{ Text(it, color = MaterialTheme.colorScheme.error) }
|
{
|
||||||
|
SelectionContainer {
|
||||||
|
Text(it, color = MaterialTheme.colorScheme.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
@@ -254,11 +255,13 @@ private fun NostrConnectContent(
|
|||||||
val clipboardManager = LocalClipboard.current
|
val clipboardManager = LocalClipboard.current
|
||||||
|
|
||||||
if (errorMessage != null) {
|
if (errorMessage != null) {
|
||||||
|
SelectionContainer {
|
||||||
Text(
|
Text(
|
||||||
errorMessage!!,
|
errorMessage!!,
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.error,
|
color = MaterialTheme.colorScheme.error,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
Spacer(Modifier.height(12.dp))
|
Spacer(Modifier.height(12.dp))
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
errorMessage = null
|
errorMessage = null
|
||||||
|
|||||||
Reference in New Issue
Block a user