-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Custom Fields] Read-only mode for JSON values #12708
Changes from 9 commits
f5f29ea
0b8c68c
cb89d47
341eb47
f98c8aa
ed234c1
1563eca
b585623
2c7bd7b
dbcf0be
c5eb9e5
f3b515e
5b2cae4
8452fc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ package com.woocommerce.android.ui.customfields.list | |
import android.content.res.Configuration | ||
import androidx.activity.compose.BackHandler | ||
import androidx.compose.foundation.clickable | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Box | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Row | ||
|
@@ -20,9 +21,11 @@ import androidx.compose.material.ExperimentalMaterialApi | |
import androidx.compose.material.FloatingActionButton | ||
import androidx.compose.material.Icon | ||
import androidx.compose.material.MaterialTheme | ||
import androidx.compose.material.OutlinedTextField | ||
import androidx.compose.material.Scaffold | ||
import androidx.compose.material.SnackbarHost | ||
import androidx.compose.material.SnackbarHostState | ||
import androidx.compose.material.Surface | ||
import androidx.compose.material.Text | ||
import androidx.compose.material.icons.Icons | ||
import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos | ||
|
@@ -46,17 +49,21 @@ import androidx.compose.ui.text.style.TextOverflow | |
import androidx.compose.ui.text.withStyle | ||
import androidx.compose.ui.tooling.preview.Preview | ||
import androidx.compose.ui.unit.dp | ||
import androidx.compose.ui.window.Dialog | ||
import com.woocommerce.android.R | ||
import com.woocommerce.android.ui.compose.component.DiscardChangesDialog | ||
import com.woocommerce.android.ui.compose.component.ExpandableTopBanner | ||
import com.woocommerce.android.ui.compose.component.ProgressDialog | ||
import com.woocommerce.android.ui.compose.component.Toolbar | ||
import com.woocommerce.android.ui.compose.component.WCColoredButton | ||
import com.woocommerce.android.ui.compose.component.WCTextButton | ||
import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews | ||
import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground | ||
import com.woocommerce.android.ui.customfields.CustomField | ||
import com.woocommerce.android.ui.customfields.CustomFieldContentType | ||
import com.woocommerce.android.ui.customfields.CustomFieldUiModel | ||
import org.json.JSONArray | ||
import org.json.JSONObject | ||
|
||
@Composable | ||
fun CustomFieldsScreen( | ||
|
@@ -75,6 +82,13 @@ fun CustomFieldsScreen( | |
snackbarHostState = snackbarHostState | ||
) | ||
} | ||
|
||
viewModel.overlayedField.observeAsState().value?.let { overlayedField -> | ||
JsonCustomFieldViewer( | ||
customField = overlayedField, | ||
onDismiss = viewModel::onOverlayedFieldDismissed | ||
) | ||
} | ||
} | ||
|
||
@OptIn(ExperimentalMaterialApi::class) | ||
|
@@ -243,6 +257,56 @@ private fun CustomFieldItem( | |
} | ||
} | ||
|
||
@Composable | ||
private fun JsonCustomFieldViewer( | ||
customField: CustomFieldUiModel, | ||
onDismiss: () -> Unit | ||
) { | ||
Dialog(onDismissRequest = onDismiss) { | ||
Surface( | ||
shape = MaterialTheme.shapes.medium, | ||
) { | ||
val jsonFormatted = remember(customField.value) { | ||
runCatching { | ||
if (customField.value.trimStart().startsWith("[")) { | ||
JSONArray(customField.value).toString(4) | ||
} else { | ||
JSONObject(customField.value).toString(4) | ||
} | ||
}.getOrDefault(customField.value) | ||
} | ||
|
||
Column( | ||
verticalArrangement = Arrangement.spacedBy(8.dp), | ||
modifier = Modifier.padding(16.dp) | ||
) { | ||
OutlinedTextField( | ||
value = customField.key, | ||
onValueChange = {}, | ||
label = { Text(text = stringResource(id = R.string.custom_fields_editor_key_label)) }, | ||
readOnly = true, | ||
modifier = Modifier | ||
) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I used read-only text fields for displaying the custom field's content because it has built-in support for selection and allowing copy/paste. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call! Just a minor nitpick. From a UX point of view, having the edit text fields focusable (highlighted with the purple border) when they are not editable seems confusing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point here @JorgeMucientes, I made some updates to disable the focus of the fields, I didn't use With this commit, and the other UI updates suggested below, the result looks like this now: Screen_recording_20241001_130945.mp4 |
||
|
||
OutlinedTextField( | ||
value = jsonFormatted, | ||
onValueChange = {}, | ||
label = { Text(text = stringResource(id = R.string.custom_fields_editor_value_label)) }, | ||
readOnly = true, | ||
modifier = Modifier.weight(1f, fill = false) | ||
) | ||
|
||
WCColoredButton( | ||
onClick = onDismiss, | ||
modifier = Modifier.align(Alignment.CenterHorizontally) | ||
) { | ||
Text(text = stringResource(id = R.string.close)) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
@LightDarkThemePreviews | ||
@Preview | ||
@Composable | ||
|
@@ -274,3 +338,21 @@ private fun CustomFieldsScreenPreview() { | |
) | ||
} | ||
} | ||
|
||
@LightDarkThemePreviews | ||
@Preview | ||
@Composable | ||
private fun JsonCustomFieldViewerPreview() { | ||
WooThemeWithBackground { | ||
JsonCustomFieldViewer( | ||
customField = CustomFieldUiModel( | ||
CustomField( | ||
id = 0, | ||
key = "key1", | ||
value = "[{\"key\": \"value\"}]" | ||
) | ||
), | ||
onDismiss = {} | ||
) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't add this formatting logic to the ViewModel because it's UI only, and uses an Android specific class
org.json.*
, let me know if you have some concerns with this approach.