Merge pull request #3834 from element-hq/feature/fga/design_system_text_field
Design system : implement new TextField
This commit is contained in:
commit
cffd2da10b
188 changed files with 817 additions and 901 deletions
|
|
@ -23,7 +23,6 @@ import androidx.compose.foundation.selection.selectableGroup
|
|||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -36,16 +35,17 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.features.createroom.impl.R
|
||||
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtom
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.RoundedIconAtomSize
|
||||
import io.element.android.libraries.designsystem.components.LabelledTextField
|
||||
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||
import io.element.android.libraries.designsystem.modifiers.clearFocusOnTap
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight
|
||||
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
|
|
@ -217,7 +217,7 @@ private fun RoomNameWithAvatar(
|
|||
modifier = Modifier.clickable(onClick = onAvatarClick),
|
||||
)
|
||||
|
||||
LabelledTextField(
|
||||
TextField(
|
||||
label = stringResource(R.string.screen_create_room_room_name_label),
|
||||
value = roomName,
|
||||
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
|
||||
|
|
@ -233,7 +233,7 @@ private fun RoomTopic(
|
|||
onTopicChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
LabelledTextField(
|
||||
TextField(
|
||||
modifier = modifier,
|
||||
label = stringResource(R.string.screen_create_room_topic_label),
|
||||
value = topic,
|
||||
|
|
@ -322,51 +322,43 @@ private fun RoomAddressField(
|
|||
onAddressChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
text = stringResource(R.string.screen_create_room_room_address_section_title),
|
||||
)
|
||||
|
||||
TextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = address.value,
|
||||
leadingIcon = {
|
||||
Text(
|
||||
text = "#",
|
||||
style = ElementTheme.typography.fontBodyLgMedium,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
Text(
|
||||
text = homeserverName,
|
||||
style = ElementTheme.typography.fontBodyLgMedium,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
modifier = Modifier.padding(end = 16.dp)
|
||||
)
|
||||
},
|
||||
supportingText = {
|
||||
Text(
|
||||
text = stringResource(R.string.screen_create_room_room_address_section_footer),
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
)
|
||||
},
|
||||
onValueChange = onAddressChange,
|
||||
singleLine = true,
|
||||
)
|
||||
}
|
||||
TextField(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
value = address.value,
|
||||
label = stringResource(R.string.screen_create_room_room_address_section_title),
|
||||
leadingIcon = {
|
||||
Text(
|
||||
text = "#",
|
||||
style = ElementTheme.typography.fontBodyLgMedium,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
Text(
|
||||
text = homeserverName,
|
||||
style = ElementTheme.typography.fontBodyLgMedium,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
)
|
||||
},
|
||||
supportingText = stringResource(R.string.screen_create_room_room_address_section_footer),
|
||||
onValueChange = onAddressChange,
|
||||
singleLine = true,
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@PreviewWithLargeHeight
|
||||
@Composable
|
||||
internal fun ConfigureRoomViewPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) = ElementPreview {
|
||||
internal fun ConfigureRoomViewLightPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) =
|
||||
ElementPreviewLight { ContentToPreview(state) }
|
||||
|
||||
@PreviewWithLargeHeight
|
||||
@Composable
|
||||
internal fun ConfigureRoomViewDarkPreview(@PreviewParameter(ConfigureRoomStateProvider::class) state: ConfigureRoomState) =
|
||||
ElementPreviewDark { ContentToPreview(state) }
|
||||
|
||||
@ExcludeFromCoverage
|
||||
@Composable
|
||||
private fun ContentToPreview(state: ConfigureRoomState) {
|
||||
ConfigureRoomView(
|
||||
state = state,
|
||||
onBackClick = {},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
|
||||
package io.element.android.features.logout.impl
|
||||
|
||||
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.ColumnScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
|
|
@ -52,19 +54,18 @@ import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrgani
|
|||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.components.list.SwitchListItem
|
||||
import io.element.android.libraries.designsystem.modifiers.autofill
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.text.buildAnnotatedStringWithStyledPart
|
||||
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.theme.components.autofill
|
||||
import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -257,26 +258,21 @@ private fun Content(
|
|||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(CommonStrings.action_confirm_password),
|
||||
style = ElementTheme.typography.fontBodySmMedium,
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
)
|
||||
var passwordVisible by remember { mutableStateOf(false) }
|
||||
if (isLoading) {
|
||||
// Ensure password is hidden when user submits the form
|
||||
passwordVisible = false
|
||||
}
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
value = passwordFieldState,
|
||||
label = stringResource(CommonStrings.action_confirm_password),
|
||||
readOnly = isLoading,
|
||||
modifier = Modifier
|
||||
.padding(top = 8.dp)
|
||||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(focusManager)
|
||||
.testTag(TestTags.loginPassword)
|
||||
|
|
@ -293,9 +289,7 @@ private fun Content(
|
|||
passwordFieldState = sanitized
|
||||
eventSink(AccountDeactivationEvents.SetPassword(sanitized))
|
||||
},
|
||||
placeholder = {
|
||||
Text(text = stringResource(CommonStrings.common_password))
|
||||
},
|
||||
placeholder = stringResource(CommonStrings.common_password),
|
||||
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
||||
trailingIcon = {
|
||||
val image =
|
||||
|
|
@ -303,7 +297,7 @@ private fun Content(
|
|||
val description =
|
||||
if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password)
|
||||
|
||||
IconButton(onClick = { passwordVisible = !passwordVisible }) {
|
||||
Box(modifier = Modifier.clickable { passwordVisible = !passwordVisible }) {
|
||||
Icon(imageVector = image, description)
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
|||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.ButtonSize
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedButton
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||
import io.element.android.libraries.matrix.api.room.RoomType
|
||||
|
|
@ -390,19 +390,13 @@ private fun DefaultLoadedContent(
|
|||
)
|
||||
} else if (contentState.joinAuthorisationStatus is JoinAuthorisationStatus.CanKnock) {
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
value = knockMessage,
|
||||
onValueChange = onKnockMessageUpdate,
|
||||
maxLines = 3,
|
||||
minLines = 3,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.screen_join_room_knock_message_description),
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
color = ElementTheme.colors.textPlaceholder,
|
||||
textAlign = TextAlign.Start,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
supportingText = stringResource(R.string.screen_join_room_knock_message_description)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
package io.element.android.features.login.impl.screens.loginpassword
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
|
|
@ -52,17 +53,15 @@ import io.element.android.libraries.designsystem.components.BigIcon
|
|||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.modifiers.autofill
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.theme.components.autofill
|
||||
import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -101,12 +100,12 @@ fun LoginPasswordView(
|
|||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.imePadding()
|
||||
.padding(padding)
|
||||
.consumeWindowInsets(padding)
|
||||
.verticalScroll(state = scrollState)
|
||||
.padding(start = 20.dp, end = 20.dp, bottom = 20.dp),
|
||||
.fillMaxSize()
|
||||
.imePadding()
|
||||
.padding(padding)
|
||||
.consumeWindowInsets(padding)
|
||||
.verticalScroll(state = scrollState)
|
||||
.padding(start = 20.dp, end = 20.dp, bottom = 20.dp),
|
||||
) {
|
||||
// Title
|
||||
IconTitleSubtitleMolecule(
|
||||
|
|
@ -140,8 +139,8 @@ fun LoginPasswordView(
|
|||
onClick = ::submit,
|
||||
enabled = state.submitEnabled || isLoading,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.loginContinue)
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.loginContinue)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(48.dp))
|
||||
}
|
||||
|
|
@ -170,16 +169,10 @@ private fun LoginForm(
|
|||
val eventSink = state.eventSink
|
||||
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(R.string.screen_login_form_header),
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
label = stringResource(R.string.screen_login_form_header),
|
||||
value = loginFieldState,
|
||||
readOnly = isLoading,
|
||||
enabled = !isLoading,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(focusManager)
|
||||
|
|
@ -192,9 +185,7 @@ private fun LoginForm(
|
|||
eventSink(LoginPasswordEvents.SetLogin(sanitized))
|
||||
}
|
||||
),
|
||||
placeholder = {
|
||||
Text(text = stringResource(CommonStrings.common_username))
|
||||
},
|
||||
placeholder = stringResource(CommonStrings.common_username),
|
||||
onValueChange = {
|
||||
val sanitized = it.sanitize()
|
||||
loginFieldState = sanitized
|
||||
|
|
@ -210,10 +201,14 @@ private fun LoginForm(
|
|||
singleLine = true,
|
||||
trailingIcon = if (loginFieldState.isNotEmpty()) {
|
||||
{
|
||||
IconButton(onClick = {
|
||||
Box(Modifier.clickable {
|
||||
loginFieldState = ""
|
||||
}) {
|
||||
Icon(imageVector = CompoundIcons.Close(), contentDescription = stringResource(CommonStrings.action_clear))
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Close(),
|
||||
contentDescription = stringResource(CommonStrings.action_clear),
|
||||
tint = ElementTheme.colors.iconSecondary
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -226,9 +221,9 @@ private fun LoginForm(
|
|||
passwordVisible = false
|
||||
}
|
||||
Spacer(Modifier.height(20.dp))
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
value = passwordFieldState,
|
||||
readOnly = isLoading,
|
||||
enabled = !isLoading,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(focusManager)
|
||||
|
|
@ -246,18 +241,18 @@ private fun LoginForm(
|
|||
passwordFieldState = sanitized
|
||||
eventSink(LoginPasswordEvents.SetPassword(sanitized))
|
||||
},
|
||||
placeholder = {
|
||||
Text(text = stringResource(CommonStrings.common_password))
|
||||
},
|
||||
placeholder = stringResource(CommonStrings.common_password),
|
||||
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
||||
trailingIcon = {
|
||||
val image =
|
||||
if (passwordVisible) CompoundIcons.VisibilityOn() else CompoundIcons.VisibilityOff()
|
||||
val description =
|
||||
if (passwordVisible) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password)
|
||||
|
||||
IconButton(onClick = { passwordVisible = !passwordVisible }) {
|
||||
Icon(imageVector = image, description)
|
||||
Box(Modifier.clickable { passwordVisible = !passwordVisible }) {
|
||||
Icon(
|
||||
imageVector = image,
|
||||
contentDescription = description,
|
||||
)
|
||||
}
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
package io.element.android.features.login.impl.screens.searchaccountprovider
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||
|
|
@ -23,7 +24,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -51,14 +51,12 @@ import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubti
|
|||
import io.element.android.libraries.designsystem.components.BigIcon
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -86,10 +84,10 @@ fun SearchAccountProviderView(
|
|||
) { padding ->
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.imePadding()
|
||||
.padding(padding)
|
||||
.consumeWindowInsets(padding)
|
||||
.fillMaxSize()
|
||||
.imePadding()
|
||||
.padding(padding)
|
||||
.consumeWindowInsets(padding)
|
||||
) {
|
||||
LazyColumn(modifier = Modifier.fillMaxWidth(), state = rememberLazyListState()) {
|
||||
item {
|
||||
|
|
@ -104,7 +102,7 @@ fun SearchAccountProviderView(
|
|||
// TextInput
|
||||
var userInputState by textFieldState(stateValue = state.userInput)
|
||||
val focusManager = LocalFocusManager.current
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
value = userInputState,
|
||||
// readOnly = isLoading,
|
||||
modifier = Modifier
|
||||
|
|
@ -126,7 +124,7 @@ fun SearchAccountProviderView(
|
|||
singleLine = true,
|
||||
trailingIcon = if (userInputState.isNotEmpty()) {
|
||||
{
|
||||
IconButton(onClick = {
|
||||
Box(Modifier.clickable {
|
||||
userInputState = ""
|
||||
eventSink(SearchAccountProviderEvents.UserInput(""))
|
||||
}) {
|
||||
|
|
@ -139,9 +137,7 @@ fun SearchAccountProviderView(
|
|||
} else {
|
||||
null
|
||||
},
|
||||
supportingText = {
|
||||
Text(text = stringResource(id = R.string.screen_account_provider_form_notice), color = MaterialTheme.colorScheme.secondary)
|
||||
}
|
||||
supportingText = stringResource(id = R.string.screen_account_provider_form_notice),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
|
|
@ -39,9 +38,9 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
|
|||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
|
|
@ -89,21 +88,16 @@ fun ReportMessageView(
|
|||
) {
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
value = state.reason,
|
||||
onValueChange = { state.eventSink(ReportMessageEvents.UpdateReason(it)) },
|
||||
placeholder = { Text(stringResource(R.string.screen_report_content_hint)) },
|
||||
placeholder = stringResource(R.string.screen_report_content_hint),
|
||||
minLines = 3,
|
||||
enabled = !isSending,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 90.dp)
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.screen_report_content_explanation),
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
textAlign = TextAlign.Start,
|
||||
modifier = Modifier.padding(top = 4.dp, bottom = 24.dp, start = 16.dp, end = 16.dp)
|
||||
.heightIn(min = 90.dp),
|
||||
supportingText = stringResource(R.string.screen_report_content_explanation),
|
||||
)
|
||||
|
||||
Row(
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.features.poll.impl.R
|
||||
|
|
@ -48,10 +47,10 @@ import io.element.android.libraries.designsystem.theme.components.Icon
|
|||
import io.element.android.libraries.designsystem.theme.components.IconSource
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItem
|
||||
import io.element.android.libraries.designsystem.theme.components.ListItemStyle
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.matrix.api.poll.PollKind
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -109,14 +108,10 @@ fun CreatePollView(
|
|||
) {
|
||||
item {
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_create_poll_question_desc),
|
||||
modifier = Modifier.padding(start = 32.dp),
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
)
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
label = stringResource(id = R.string.screen_create_poll_question_desc),
|
||||
value = state.question,
|
||||
onValueChange = {
|
||||
state.eventSink(CreatePollEvents.SetQuestion(it))
|
||||
|
|
@ -124,9 +119,7 @@ fun CreatePollView(
|
|||
modifier = Modifier
|
||||
.focusRequester(questionFocusRequester)
|
||||
.fillMaxWidth(),
|
||||
placeholder = {
|
||||
Text(text = stringResource(id = R.string.screen_create_poll_question_hint))
|
||||
},
|
||||
placeholder = stringResource(id = R.string.screen_create_poll_question_hint),
|
||||
keyboardOptions = keyboardOptions,
|
||||
)
|
||||
}
|
||||
|
|
@ -137,7 +130,7 @@ fun CreatePollView(
|
|||
val isLastItem = index == state.answers.size - 1
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
value = answer.text,
|
||||
onValueChange = {
|
||||
state.eventSink(CreatePollEvents.SetAnswer(index, it))
|
||||
|
|
@ -145,9 +138,7 @@ fun CreatePollView(
|
|||
modifier = Modifier
|
||||
.then(if (isLastItem) Modifier.focusRequester(answerFocusRequester) else Modifier)
|
||||
.fillMaxWidth(),
|
||||
placeholder = {
|
||||
Text(text = stringResource(id = R.string.screen_create_poll_answer_hint, index + 1))
|
||||
},
|
||||
placeholder = stringResource(id = R.string.screen_create_poll_answer_hint, index + 1),
|
||||
keyboardOptions = keyboardOptions,
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.features.preferences.impl.R
|
||||
import io.element.android.libraries.designsystem.components.LabelledOutlinedTextField
|
||||
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
|
|
@ -41,6 +40,7 @@ import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
|||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
|
||||
import io.element.android.libraries.matrix.ui.components.EditableAvatarView
|
||||
|
|
@ -112,7 +112,7 @@ fun EditUserProfileView(
|
|||
textAlign = TextAlign.Center,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(40.dp))
|
||||
LabelledOutlinedTextField(
|
||||
TextField(
|
||||
label = stringResource(R.string.screen_edit_profile_display_name),
|
||||
value = state.displayName,
|
||||
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
|
||||
|
|
|
|||
|
|
@ -39,13 +39,12 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen
|
|||
import io.element.android.libraries.designsystem.components.preferences.PreferenceRow
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
|
|
@ -70,17 +69,14 @@ fun BugReportView(
|
|||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
PreferenceRow {
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
value = descriptionFieldState,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(LocalFocusManager.current),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(LocalFocusManager.current),
|
||||
enabled = isFormEnabled,
|
||||
label = {
|
||||
Text(text = stringResource(id = R.string.screen_bug_report_editor_placeholder))
|
||||
},
|
||||
supportingText = {
|
||||
Text(text = stringResource(id = R.string.screen_bug_report_editor_description))
|
||||
},
|
||||
placeholder = stringResource(id = R.string.screen_bug_report_editor_placeholder),
|
||||
supportingText = stringResource(id = R.string.screen_bug_report_editor_description),
|
||||
onValueChange = {
|
||||
descriptionFieldState = it
|
||||
eventSink(BugReportEvents.SetDescription(it))
|
||||
|
|
@ -152,8 +148,8 @@ fun BugReportView(
|
|||
enabled = state.submitEnabled,
|
||||
showProgress = state.sending.isLoading(),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 24.dp, bottom = 16.dp)
|
||||
.fillMaxWidth()
|
||||
.padding(top = 24.dp, bottom = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
package io.element.android.features.roomdetails.impl.edit
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
|
@ -21,7 +20,6 @@ import androidx.compose.foundation.rememberScrollState
|
|||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -33,7 +31,6 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.features.roomdetails.impl.R
|
||||
import io.element.android.libraries.designsystem.components.LabelledTextField
|
||||
import io.element.android.libraries.designsystem.components.async.AsyncActionView
|
||||
import io.element.android.libraries.designsystem.components.async.AsyncActionViewDefaults
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
|
|
@ -45,6 +42,7 @@ import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
|||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.matrix.ui.components.AvatarActionBottomSheet
|
||||
import io.element.android.libraries.matrix.ui.components.EditableAvatarView
|
||||
|
|
@ -110,40 +108,28 @@ fun RoomDetailsEditView(
|
|||
)
|
||||
Spacer(modifier = Modifier.height(60.dp))
|
||||
|
||||
if (state.canChangeName) {
|
||||
LabelledTextField(
|
||||
label = stringResource(id = R.string.screen_room_details_room_name_label),
|
||||
value = state.roomRawName,
|
||||
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
|
||||
singleLine = true,
|
||||
onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomName(it)) },
|
||||
)
|
||||
} else {
|
||||
LabelledReadOnlyField(
|
||||
title = stringResource(R.string.screen_room_details_room_name_label),
|
||||
value = state.roomRawName
|
||||
)
|
||||
}
|
||||
TextField(
|
||||
label = stringResource(id = R.string.screen_room_details_room_name_label),
|
||||
value = state.roomRawName,
|
||||
placeholder = stringResource(CommonStrings.common_room_name_placeholder),
|
||||
singleLine = true,
|
||||
readOnly = !state.canChangeName,
|
||||
onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomName(it)) },
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(28.dp))
|
||||
|
||||
if (state.canChangeTopic) {
|
||||
LabelledTextField(
|
||||
label = stringResource(CommonStrings.common_topic),
|
||||
value = state.roomTopic,
|
||||
placeholder = stringResource(CommonStrings.common_topic_placeholder),
|
||||
maxLines = 10,
|
||||
onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(it)) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
capitalization = KeyboardCapitalization.Sentences,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
LabelledReadOnlyField(
|
||||
title = stringResource(R.string.screen_room_details_topic_title),
|
||||
value = state.roomTopic
|
||||
)
|
||||
}
|
||||
TextField(
|
||||
label = stringResource(CommonStrings.common_topic),
|
||||
value = state.roomTopic,
|
||||
placeholder = stringResource(CommonStrings.common_topic_placeholder),
|
||||
maxLines = 10,
|
||||
readOnly = !state.canChangeTopic,
|
||||
onValueChange = { state.eventSink(RoomDetailsEditEvents.UpdateRoomTopic(it)) },
|
||||
keyboardOptions = KeyboardOptions(
|
||||
capitalization = KeyboardCapitalization.Sentences,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,30 +157,6 @@ fun RoomDetailsEditView(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LabelledReadOnlyField(
|
||||
title: String,
|
||||
value: String,
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
text = title,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 12.dp),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
text = value,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun RoomDetailsEditViewPreview(@PreviewParameter(RoomDetailsEditStateProvider::class) state: RoomDetailsEditState) = ElementPreview {
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ package io.element.android.features.roomdetails.edit
|
|||
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.ui.test.assertHasClickAction
|
||||
import androidx.compose.ui.test.assertHasNoClickAction
|
||||
import androidx.compose.ui.test.assert
|
||||
import androidx.compose.ui.test.hasTestTag
|
||||
import androidx.compose.ui.test.isEditable
|
||||
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
|
|
@ -78,7 +78,6 @@ class RoomDetailsEditViewTest {
|
|||
roomRawName = "Marketing",
|
||||
),
|
||||
)
|
||||
rule.onNodeWithText("Marketing").assertHasClickAction()
|
||||
rule.onNodeWithText("Marketing").performTextInput("A")
|
||||
eventsRecorder.assertSingle(RoomDetailsEditEvents.UpdateRoomName("AMarketing"))
|
||||
}
|
||||
|
|
@ -93,7 +92,7 @@ class RoomDetailsEditViewTest {
|
|||
canChangeName = false,
|
||||
),
|
||||
)
|
||||
rule.onNodeWithText("Marketing").assertHasNoClickAction()
|
||||
rule.onNodeWithText("Marketing").assert(!isEditable())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -105,7 +104,6 @@ class RoomDetailsEditViewTest {
|
|||
roomTopic = "My Topic",
|
||||
),
|
||||
)
|
||||
rule.onNodeWithText("My Topic").assertHasClickAction()
|
||||
rule.onNodeWithText("My Topic").performTextInput("A")
|
||||
eventsRecorder.assertSingle(RoomDetailsEditEvents.UpdateRoomTopic("AMy Topic"))
|
||||
}
|
||||
|
|
@ -120,7 +118,7 @@ class RoomDetailsEditViewTest {
|
|||
canChangeTopic = false,
|
||||
),
|
||||
)
|
||||
rule.onNodeWithText("My Topic").assertHasNoClickAction()
|
||||
rule.onNodeWithText("My Topic").assert(!isEditable())
|
||||
}
|
||||
|
||||
@Ignore("This test is failing because the bottom sheet does not open")
|
||||
|
|
|
|||
|
|
@ -45,11 +45,11 @@ import io.element.android.libraries.designsystem.preview.ElementPreview
|
|||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.aliasScreenTitle
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.FilledTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -194,7 +194,7 @@ private fun SearchTextField(
|
|||
),
|
||||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
TextField(
|
||||
FilledTextField(
|
||||
modifier = modifier.testTag(TestTags.searchTextField.value),
|
||||
textStyle = ElementTheme.typography.fontBodyLgRegular,
|
||||
singleLine = true,
|
||||
|
|
|
|||
|
|
@ -49,11 +49,11 @@ import io.element.android.libraries.designsystem.modifiers.applyIf
|
|||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.ButtonSize
|
||||
import io.element.android.libraries.designsystem.theme.components.FilledTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.copy
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
|
@ -130,7 +130,7 @@ private fun RoomListSearchContent(
|
|||
title = {
|
||||
val filter = state.query
|
||||
val focusRequester = FocusRequester()
|
||||
TextField(
|
||||
FilledTextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.focusRequester(focusRequester),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
package io.element.android.features.securebackup.impl.reset.password
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
|
|
@ -25,14 +27,12 @@ import io.element.android.libraries.designsystem.atomic.pages.FlowStepPage
|
|||
import io.element.android.libraries.designsystem.components.BigIcon
|
||||
import io.element.android.libraries.designsystem.components.ProgressDialog
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.modifiers.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.onTabOrEnterKeyFocusNext
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
|
|
@ -80,14 +80,13 @@ fun ResetIdentityPasswordView(
|
|||
@Composable
|
||||
private fun Content(text: String, onTextChange: (String) -> Unit, hasError: Boolean) {
|
||||
var showPassword by remember { mutableStateOf(false) }
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.onTabOrEnterKeyFocusNext(LocalFocusManager.current),
|
||||
value = text,
|
||||
onValueChange = onTextChange,
|
||||
label = { Text(stringResource(CommonStrings.common_password)) },
|
||||
placeholder = { Text(stringResource(R.string.screen_reset_encryption_password_placeholder)) },
|
||||
placeholder = stringResource(CommonStrings.common_password),
|
||||
singleLine = true,
|
||||
visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(),
|
||||
trailingIcon = {
|
||||
|
|
@ -96,13 +95,13 @@ private fun Content(text: String, onTextChange: (String) -> Unit, hasError: Bool
|
|||
val description =
|
||||
if (showPassword) stringResource(CommonStrings.a11y_hide_password) else stringResource(CommonStrings.a11y_show_password)
|
||||
|
||||
IconButton(onClick = { showPassword = !showPassword }) {
|
||||
Box(Modifier.clickable { showPassword = !showPassword }) {
|
||||
Icon(imageVector = image, description)
|
||||
}
|
||||
},
|
||||
isError = hasError,
|
||||
supportingText = if (hasError) {
|
||||
{ Text(stringResource(R.string.screen_reset_encryption_password_error)) }
|
||||
stringResource(R.string.screen_reset_encryption_password_error)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,14 +36,14 @@ import io.element.android.compound.theme.ElementTheme
|
|||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.features.securebackup.impl.R
|
||||
import io.element.android.features.securebackup.impl.tools.RecoveryKeyVisualTransformation
|
||||
import io.element.android.libraries.designsystem.modifiers.autofill
|
||||
import io.element.android.libraries.designsystem.modifiers.clickableIfNotNull
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.autofill
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
|
@ -62,7 +62,6 @@ internal fun RecoveryKeyView(
|
|||
) {
|
||||
Text(
|
||||
text = stringResource(id = CommonStrings.common_recovery_key),
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
)
|
||||
RecoveryKeyContent(state, onClick, onChange, onSubmit)
|
||||
|
|
@ -159,7 +158,7 @@ private fun RecoveryKeyFormContent(
|
|||
// Do not apply a visual transformation if the key has spaces, to let user enter passphrase
|
||||
if (keyHasSpace) VisualTransformation.None else RecoveryKeyVisualTransformation()
|
||||
}
|
||||
OutlinedTextField(
|
||||
TextField(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.recoveryKey)
|
||||
|
|
@ -179,7 +178,7 @@ private fun RecoveryKeyFormContent(
|
|||
keyboardActions = KeyboardActions(
|
||||
onDone = { onSubmit() }
|
||||
),
|
||||
label = { Text(text = stringResource(id = R.string.screen_recovery_key_confirm_key_placeholder)) }
|
||||
placeholder = stringResource(id = R.string.screen_recovery_key_confirm_key_placeholder),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -198,14 +197,12 @@ private fun RecoveryKeyFooter(state: RecoveryKeyViewState) {
|
|||
}
|
||||
),
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_recovery_key_save_key_description),
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
)
|
||||
}
|
||||
|
|
@ -214,7 +211,6 @@ private fun RecoveryKeyFooter(state: RecoveryKeyViewState) {
|
|||
Text(
|
||||
text = stringResource(id = R.string.screen_recovery_key_confirm_key_description),
|
||||
color = ElementTheme.colors.textSecondary,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
@Composable
|
||||
fun LabelledOutlinedTextField(
|
||||
label: String,
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
placeholder: String? = null,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
text = label
|
||||
)
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = value,
|
||||
placeholder = placeholder?.let { { Text(placeholder) } },
|
||||
onValueChange = onValueChange,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
keyboardOptions = keyboardOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun LabelledOutlinedTextFieldPreview() = ElementPreview {
|
||||
Column {
|
||||
LabelledOutlinedTextField(
|
||||
label = "Room name",
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
placeholder = "e.g. Product Sprint",
|
||||
)
|
||||
LabelledOutlinedTextField(
|
||||
label = "Room name",
|
||||
value = "a room name",
|
||||
onValueChange = {},
|
||||
placeholder = "e.g. Product Sprint",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.components
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
|
||||
@Composable
|
||||
fun LabelledTextField(
|
||||
label: String,
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
placeholder: String? = null,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
text = label
|
||||
)
|
||||
|
||||
TextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = value,
|
||||
placeholder = placeholder?.let { { Text(placeholder) } },
|
||||
onValueChange = onValueChange,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
keyboardOptions = keyboardOptions,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun LabelledTextFieldPreview() = ElementPreview {
|
||||
Column {
|
||||
LabelledTextField(
|
||||
label = "Room name",
|
||||
value = "",
|
||||
onValueChange = {},
|
||||
placeholder = "e.g. Product Sprint",
|
||||
)
|
||||
LabelledTextField(
|
||||
label = "Room name",
|
||||
value = "a room name",
|
||||
onValueChange = {},
|
||||
placeholder = "e.g. Product Sprint",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ package io.element.android.libraries.designsystem.components.list
|
|||
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -18,7 +19,6 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.modifiers
|
||||
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.autofill.AutofillNode
|
||||
import androidx.compose.ui.autofill.AutofillType
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.layout.boundsInWindow
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalAutofill
|
||||
import androidx.compose.ui.platform.LocalAutofillTree
|
||||
|
||||
@Suppress("ModifierComposed")
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
fun Modifier.autofill(autofillTypes: List<AutofillType>, onFill: (String) -> Unit) = composed {
|
||||
val autofillNode = AutofillNode(autofillTypes, onFill = onFill)
|
||||
LocalAutofillTree.current += autofillNode
|
||||
|
||||
val autofill = LocalAutofill.current
|
||||
|
||||
this
|
||||
.onGloballyPositioned {
|
||||
// Inform autofill framework of where our composable is so it can show the popup in the right place
|
||||
autofillNode.boundingBox = it.boundsInWindow()
|
||||
}
|
||||
.onFocusChanged {
|
||||
autofill?.run {
|
||||
if (it.isFocused) {
|
||||
requestAutofillForNode(autofillNode)
|
||||
} else {
|
||||
cancelAutofillForNode(autofillNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
* Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.modifiers
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
import androidx.compose.ui.focus.FocusManager
|
||||
import androidx.compose.ui.input.key.Key
|
||||
import androidx.compose.ui.input.key.KeyEventType
|
||||
import androidx.compose.ui.input.key.key
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.input.key.type
|
||||
|
||||
fun Modifier.onTabOrEnterKeyFocusNext(focusManager: FocusManager): Modifier = onPreviewKeyEvent { event ->
|
||||
if (event.key == Key.Tab || event.key == Key.Enter) {
|
||||
if (event.type == KeyEventType.KeyUp) {
|
||||
focusManager.moveFocus(FocusDirection.Down)
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -15,25 +15,19 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.OutlinedTextFieldDefaults
|
||||
import androidx.compose.material3.TextFieldColors
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
import androidx.compose.ui.focus.FocusManager
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.input.key.Key
|
||||
import androidx.compose.ui.input.key.KeyEventType
|
||||
import androidx.compose.ui.input.key.key
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.input.key.type
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
|
@ -42,7 +36,7 @@ import io.element.android.libraries.designsystem.utils.allBooleans
|
|||
import io.element.android.libraries.designsystem.utils.asInt
|
||||
|
||||
@Composable
|
||||
fun OutlinedTextField(
|
||||
fun FilledTextField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -60,12 +54,16 @@ fun OutlinedTextField(
|
|||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
||||
minLines: Int = 1,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = OutlinedTextFieldDefaults.shape,
|
||||
colors: TextFieldColors = OutlinedTextFieldDefaults.colors()
|
||||
shape: Shape = TextFieldDefaults.shape,
|
||||
colors: TextFieldColors = TextFieldDefaults.colors(
|
||||
unfocusedContainerColor = ElementTheme.colors.bgSubtleSecondary,
|
||||
focusedContainerColor = ElementTheme.colors.bgSubtleSecondary,
|
||||
disabledContainerColor = ElementTheme.colors.bgSubtleSecondary,
|
||||
errorContainerColor = ElementTheme.colors.bgSubtleSecondary,
|
||||
)
|
||||
) {
|
||||
androidx.compose.material3.OutlinedTextField(
|
||||
androidx.compose.material3.TextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
|
|
@ -83,7 +81,6 @@ fun OutlinedTextField(
|
|||
keyboardActions = keyboardActions,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
minLines = minLines,
|
||||
interactionSource = interactionSource,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
|
|
@ -91,7 +88,7 @@ fun OutlinedTextField(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun OutlinedTextField(
|
||||
fun FilledTextField(
|
||||
value: TextFieldValue,
|
||||
onValueChange: (TextFieldValue) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -108,12 +105,12 @@ fun OutlinedTextField(
|
|||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = OutlinedTextFieldDefaults.shape,
|
||||
colors: TextFieldColors = OutlinedTextFieldDefaults.colors()
|
||||
shape: Shape = TextFieldDefaults.shape,
|
||||
colors: TextFieldColors = TextFieldDefaults.colors()
|
||||
) {
|
||||
androidx.compose.material3.OutlinedTextField(
|
||||
androidx.compose.material3.TextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
|
|
@ -137,37 +134,62 @@ fun OutlinedTextField(
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
fun Modifier.onTabOrEnterKeyFocusNext(focusManager: FocusManager): Modifier = onPreviewKeyEvent { event ->
|
||||
if (event.key == Key.Tab || event.key == Key.Enter) {
|
||||
if (event.type == KeyEventType.KeyUp) {
|
||||
focusManager.moveFocus(FocusDirection.Down)
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun FilledTextFieldLightPreview() =
|
||||
ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun OutlinedTextFieldsPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
internal fun FilledTextFieldDarkPreview() =
|
||||
ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun OutlinedTextFieldsDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
@ExcludeFromCoverage
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column(modifier = Modifier.padding(4.dp)) {
|
||||
allBooleans.forEach { isError ->
|
||||
allBooleans.forEach { enabled ->
|
||||
allBooleans.forEach { readonly ->
|
||||
OutlinedTextField(
|
||||
FilledTextField(
|
||||
value = "Hello er=${isError.asInt()}, en=${enabled.asInt()}, ro=${readonly.asInt()}",
|
||||
onValueChange = {},
|
||||
label = { Text(text = "label") },
|
||||
isError = isError,
|
||||
enabled = enabled,
|
||||
readOnly = readonly,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun FilledTextFieldValueLightPreview() =
|
||||
ElementPreviewLight { FilledTextFieldValueContentToPreview() }
|
||||
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun FilledTextFieldValueTextFieldDarkPreview() =
|
||||
ElementPreviewDark { FilledTextFieldValueContentToPreview() }
|
||||
|
||||
@ExcludeFromCoverage
|
||||
@Composable
|
||||
private fun FilledTextFieldValueContentToPreview() {
|
||||
Column(modifier = Modifier.padding(4.dp)) {
|
||||
allBooleans.forEach { isError ->
|
||||
allBooleans.forEach { enabled ->
|
||||
allBooleans.forEach { readonly ->
|
||||
FilledTextField(
|
||||
value = TextFieldValue(
|
||||
text = "Hello er=${isError.asInt()}, en=${enabled.asInt()}, ro=${readonly.asInt()}",
|
||||
selection = TextRange(0, "Hello".length),
|
||||
),
|
||||
onValueChange = {},
|
||||
label = { Text(text = "label") },
|
||||
value = "Hello er=${isError.asInt()}, en=${enabled.asInt()}, ro=${readonly.asInt()}",
|
||||
isError = isError,
|
||||
enabled = enabled,
|
||||
readOnly = readonly,
|
||||
|
|
@ -7,36 +7,37 @@
|
|||
|
||||
package io.element.android.libraries.designsystem.theme.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
|
||||
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.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.TextFieldColors
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.autofill.AutofillNode
|
||||
import androidx.compose.ui.autofill.AutofillType
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.layout.boundsInWindow
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalAutofill
|
||||
import androidx.compose.ui.platform.LocalAutofillTree
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.text.TextLayoutResult
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||
import io.element.android.libraries.architecture.coverage.ExcludeFromCoverage
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
|
@ -44,56 +45,63 @@ import io.element.android.libraries.designsystem.preview.PreviewGroup
|
|||
import io.element.android.libraries.designsystem.utils.allBooleans
|
||||
import io.element.android.libraries.designsystem.utils.asInt
|
||||
|
||||
/**
|
||||
* https://www.figma.com/design/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?node-id=2008-37137
|
||||
*/
|
||||
@Composable
|
||||
fun TextField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
readOnly: Boolean = false,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
label: @Composable (() -> Unit)? = null,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
label: String? = null,
|
||||
supportingText: String? = null,
|
||||
placeholder: String? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
supportingText: @Composable (() -> Unit)? = null,
|
||||
isError: Boolean = false,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
enabled: Boolean = true,
|
||||
readOnly: Boolean = false,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
||||
minLines: Int = 1,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = TextFieldDefaults.shape,
|
||||
colors: TextFieldColors = TextFieldDefaults.colors(
|
||||
unfocusedContainerColor = ElementTheme.colors.bgSubtleSecondary,
|
||||
focusedContainerColor = ElementTheme.colors.bgSubtleSecondary,
|
||||
disabledContainerColor = ElementTheme.colors.bgSubtleSecondary,
|
||||
errorContainerColor = ElementTheme.colors.bgSubtleSecondary,
|
||||
)
|
||||
onTextLayout: (TextLayoutResult) -> Unit = {},
|
||||
) {
|
||||
androidx.compose.material3.TextField(
|
||||
val isFocused by interactionSource.collectIsFocusedAsState()
|
||||
BasicTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
textStyle = textFieldStyle(enabled),
|
||||
interactionSource = interactionSource,
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = textStyle,
|
||||
label = label,
|
||||
placeholder = placeholder,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
supportingText = supportingText,
|
||||
isError = isError,
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
interactionSource = interactionSource,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
)
|
||||
minLines = minLines,
|
||||
readOnly = readOnly,
|
||||
cursorBrush = SolidColor(ElementTheme.colors.textPrimary),
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
visualTransformation = visualTransformation,
|
||||
onTextLayout = onTextLayout,
|
||||
) { innerTextField ->
|
||||
DecorationBox(
|
||||
label = label,
|
||||
readOnly = readOnly,
|
||||
enabled = enabled,
|
||||
isFocused = isFocused,
|
||||
isError = isError,
|
||||
leadingIcon = leadingIcon,
|
||||
placeholder = placeholder,
|
||||
isTextEmpty = value.isEmpty(),
|
||||
innerTextField = innerTextField,
|
||||
trailingIcon = trailingIcon,
|
||||
supportingText = supportingText
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -101,69 +109,200 @@ fun TextField(
|
|||
value: TextFieldValue,
|
||||
onValueChange: (TextFieldValue) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
readOnly: Boolean = false,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
label: @Composable (() -> Unit)? = null,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
label: String? = null,
|
||||
supportingText: String? = null,
|
||||
placeholder: String? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
supportingText: @Composable (() -> Unit)? = null,
|
||||
isError: Boolean = false,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
enabled: Boolean = true,
|
||||
readOnly: Boolean = false,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
|
||||
minLines: Int = 1,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = TextFieldDefaults.shape,
|
||||
colors: TextFieldColors = TextFieldDefaults.colors()
|
||||
onTextLayout: (TextLayoutResult) -> Unit = {},
|
||||
) {
|
||||
androidx.compose.material3.TextField(
|
||||
val isFocused by interactionSource.collectIsFocusedAsState()
|
||||
BasicTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
textStyle = textFieldStyle(enabled),
|
||||
interactionSource = interactionSource,
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = textStyle,
|
||||
label = label,
|
||||
placeholder = placeholder,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
supportingText = supportingText,
|
||||
isError = isError,
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
interactionSource = interactionSource,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
minLines = minLines,
|
||||
readOnly = readOnly,
|
||||
cursorBrush = SolidColor(ElementTheme.colors.textPrimary),
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
visualTransformation = visualTransformation,
|
||||
onTextLayout = onTextLayout,
|
||||
) { innerTextField ->
|
||||
DecorationBox(
|
||||
label = label,
|
||||
readOnly = readOnly,
|
||||
enabled = enabled,
|
||||
isFocused = isFocused,
|
||||
isError = isError,
|
||||
leadingIcon = leadingIcon,
|
||||
placeholder = placeholder,
|
||||
isTextEmpty = value.text.isEmpty(),
|
||||
innerTextField = innerTextField,
|
||||
trailingIcon = trailingIcon,
|
||||
supportingText = supportingText
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DecorationBox(
|
||||
label: String?,
|
||||
enabled: Boolean,
|
||||
readOnly: Boolean,
|
||||
isFocused: Boolean,
|
||||
isError: Boolean,
|
||||
placeholder: String?,
|
||||
isTextEmpty: Boolean,
|
||||
supportingText: String?,
|
||||
leadingIcon: @Composable (() -> Unit)?,
|
||||
trailingIcon: @Composable (() -> Unit)?,
|
||||
innerTextField: @Composable () -> Unit,
|
||||
) {
|
||||
Column {
|
||||
if (label != null) {
|
||||
Text(
|
||||
text = label,
|
||||
color = ElementTheme.colors.textPrimary,
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
TextFieldContainer(
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
isFocused = isFocused,
|
||||
isError = isError
|
||||
) {
|
||||
Row(modifier = Modifier.padding(16.dp)) {
|
||||
if (leadingIcon != null) {
|
||||
CompositionLocalProvider(LocalContentColor provides ElementTheme.colors.iconSecondary) {
|
||||
leadingIcon()
|
||||
}
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
Box(modifier = Modifier.weight(1f)) {
|
||||
if (placeholder != null && isTextEmpty) {
|
||||
Text(
|
||||
text = placeholder,
|
||||
color = ElementTheme.colors.textPlaceholder,
|
||||
style = ElementTheme.typography.fontBodyLgRegular,
|
||||
)
|
||||
}
|
||||
innerTextField()
|
||||
}
|
||||
if (trailingIcon != null) {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
CompositionLocalProvider(LocalContentColor provides ElementTheme.colors.iconSecondary) {
|
||||
trailingIcon()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (supportingText != null) {
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
SupportingTextLayout(isError, supportingText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TextFieldContainer(
|
||||
enabled: Boolean,
|
||||
readOnly: Boolean,
|
||||
isFocused: Boolean,
|
||||
isError: Boolean,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(4.dp),
|
||||
border = if (readOnly) {
|
||||
null
|
||||
} else {
|
||||
BorderStroke(
|
||||
width = if (isFocused) 2.dp else 1.dp,
|
||||
color = when {
|
||||
!enabled -> ElementTheme.colors.borderDisabled
|
||||
isError -> ElementTheme.colors.borderCriticalPrimary
|
||||
isFocused -> ElementTheme.colors.borderInteractiveHovered
|
||||
else -> ElementTheme.colors.borderInteractiveSecondary
|
||||
}
|
||||
)
|
||||
},
|
||||
color = when {
|
||||
readOnly -> ElementTheme.colors.bgSubtleSecondary
|
||||
!enabled -> ElementTheme.colors.bgCanvasDisabled
|
||||
else -> ElementTheme.colors.bgCanvasDefault
|
||||
},
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SupportingTextLayout(isError: Boolean, supportingText: String) {
|
||||
Row(horizontalArrangement = spacedBy(4.dp)) {
|
||||
if (isError) {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.Error(),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = ElementTheme.colors.iconCriticalPrimary
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = supportingText,
|
||||
color = if (isError) ElementTheme.colors.textCriticalPrimary else ElementTheme.colors.textSecondary,
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun textFieldStyle(enabled: Boolean): TextStyle {
|
||||
return ElementTheme.typography.fontBodyLgRegular.copy(
|
||||
color = if (enabled) {
|
||||
ElementTheme.colors.textPrimary
|
||||
} else {
|
||||
ElementTheme.colors.textSecondary
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun TextFieldLightPreview() =
|
||||
ElementPreviewLight { ContentToPreview() }
|
||||
internal fun TextFieldsLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun TextFieldDarkPreview() =
|
||||
ElementPreviewDark { ContentToPreview() }
|
||||
internal fun TextFieldsDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@ExcludeFromCoverage
|
||||
@Composable
|
||||
@ExcludeFromCoverage
|
||||
private fun ContentToPreview() {
|
||||
Column(modifier = Modifier.padding(4.dp)) {
|
||||
allBooleans.forEach { isError ->
|
||||
allBooleans.forEach { enabled ->
|
||||
allBooleans.forEach { readonly ->
|
||||
TextField(
|
||||
onValueChange = {},
|
||||
label = "Label",
|
||||
value = "Hello er=${isError.asInt()}, en=${enabled.asInt()}, ro=${readonly.asInt()}",
|
||||
onValueChange = {},
|
||||
label = { Text(text = "label") },
|
||||
supportingText = "Supporting text",
|
||||
isError = isError,
|
||||
enabled = enabled,
|
||||
readOnly = readonly,
|
||||
|
|
@ -174,62 +313,3 @@ private fun ContentToPreview() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun TextFieldValueLightPreview() =
|
||||
ElementPreviewLight { TextFieldValueContentToPreview() }
|
||||
|
||||
@Preview(group = PreviewGroup.TextFields)
|
||||
@Composable
|
||||
internal fun TextFieldValueTextFieldDarkPreview() =
|
||||
ElementPreviewDark { TextFieldValueContentToPreview() }
|
||||
|
||||
@ExcludeFromCoverage
|
||||
@Composable
|
||||
private fun TextFieldValueContentToPreview() {
|
||||
Column(modifier = Modifier.padding(4.dp)) {
|
||||
allBooleans.forEach { isError ->
|
||||
allBooleans.forEach { enabled ->
|
||||
allBooleans.forEach { readonly ->
|
||||
TextField(
|
||||
value = TextFieldValue(
|
||||
text = "Hello er=${isError.asInt()}, en=${enabled.asInt()}, ro=${readonly.asInt()}",
|
||||
selection = TextRange(0, "Hello".length),
|
||||
),
|
||||
onValueChange = {},
|
||||
label = { Text(text = "label") },
|
||||
isError = isError,
|
||||
enabled = enabled,
|
||||
readOnly = readonly,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("ModifierComposed")
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
fun Modifier.autofill(autofillTypes: List<AutofillType>, onFill: (String) -> Unit) = composed {
|
||||
val autofillNode = AutofillNode(autofillTypes, onFill = onFill)
|
||||
LocalAutofillTree.current += autofillNode
|
||||
|
||||
val autofill = LocalAutofill.current
|
||||
|
||||
this
|
||||
.onGloballyPositioned {
|
||||
// Inform autofill framework of where our composable is so it can show the popup in the right place
|
||||
autofillNode.boundingBox = it.boundsInWindow()
|
||||
}
|
||||
.onFocusChanged {
|
||||
autofill?.run {
|
||||
if (it.isFocused) {
|
||||
requestAutofillForNode(autofillNode)
|
||||
} else {
|
||||
cancelAutofillForNode(autofillNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c94e5e7c3b044017e6cb98985671875c7ab6103533e2a5e15aed17a01a52576b
|
||||
size 30470
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5053e8716e3bfe5703f6d00e304101bbbf6cdebaf5eb5088a6043171a1f34e47
|
||||
size 41328
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e6270f3b7935c47da76ce4e81aa7e8eac13a9340e7ccb198f8cd6956d746dfa8
|
||||
size 59452
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f6a98ba9f5edc21b8781e84ccaf6f93c3608a4aa64464494304962d8cb62a102
|
||||
size 31477
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:150b375f3fa9c180ec221b3fcc3ed0397b75920cb760e25e327fd6be46370618
|
||||
size 41954
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c3b02b0bc0d557bac4d5aa945daf04d5d58dab44d9e4284d030804e6b5ed6a49
|
||||
size 60703
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e7de44cc8f686264788aa79cde24b9896c6ca4dabc49b246abbd1d3dd0311e25
|
||||
size 57891
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2df49a9c82438dbf1ba0ba0670cadd8e7bb47a7e25de27793fd756760cf7c5f2
|
||||
size 79562
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2df49a9c82438dbf1ba0ba0670cadd8e7bb47a7e25de27793fd756760cf7c5f2
|
||||
size 79562
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c754daf307554dc0c83ba0f89c38f5fa7f5c2edff82907b0826c2b781498dbcb
|
||||
size 56047
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b6e43161abdccacbede4a8c4b4ff446026035df4be0894a55c6364681458bb2f
|
||||
size 78805
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b6e43161abdccacbede4a8c4b4ff446026035df4be0894a55c6364681458bb2f
|
||||
size 78805
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:74f12ea2c5114363b809fcf4d897487cb87ecfab361952471c05d22898d0048f
|
||||
size 130010
|
||||
oid sha256:a9d0338485aabe5296754868ce2fcd5097d914eea28298ec11c16f7161ae2341
|
||||
size 111617
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6950f5e0824c964936077ecda4ff7edb8c8c6796b5a4ae304e6027e57a83cb55
|
||||
size 116382
|
||||
oid sha256:88584b1d4a4876e68e2972f9bbd03156127ee9b552de1ec20a9057d8f6cb1828
|
||||
size 101296
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:afa896a21369e764e32b1dd4858a34708ddf38426a4a8aaa724761e76a90fed7
|
||||
size 35316
|
||||
oid sha256:91cdcd831bc82480a130093a2f561bde8f0c3f0f2b9e7251628763202fc7bc39
|
||||
size 35249
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2dc060e53c33a7a06895e1be02f45f7f7e52b287d87b41c76d3321a71184f525
|
||||
size 36501
|
||||
oid sha256:971e260530cfd5b25cce035272820cb067c7e4a4a34fa6992526e5176913ea2d
|
||||
size 36617
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1cdff1f6e189eff691125330b0f2c733ffd16fca324a5f2faee3dd15c9b7bc90
|
||||
size 27119
|
||||
oid sha256:56fde0cdb5a5196c277c43a1b9909401f40a4e7ef8bfe2e4d80592f0768fe5d5
|
||||
size 27306
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:60e85a3e25fd112009111634ddc59a6ae7d884e26ea29e0598c1af10818abcb5
|
||||
size 34285
|
||||
oid sha256:2db3dad746069968a83693752e985c25b72ca31be11b5c65d7da234f96d377d3
|
||||
size 34055
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9b518aa920d7183d740be4358dcc495e7df1c2d40c866addb728c7af8e273dbe
|
||||
size 35502
|
||||
oid sha256:61739bd834ee18df778b4737f38f656d4342397135d518791ff4518d8fdea96d
|
||||
size 35173
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a96833c5ba2508d77e1b8a1f885df78fb979fcb530223c4591076120729559e4
|
||||
size 25080
|
||||
oid sha256:ae8a729e91657959dbac49ef1c0f41fe37c296923eef6c22bdc9692d389ca346
|
||||
size 25207
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4054b601d6afc38467b632a19a5e12540b21dccbd67a885bcc13f8ad8a86636e
|
||||
size 23532
|
||||
oid sha256:a5419be4719399829da9684e6635873168f274120738e43c0b101603d8499da1
|
||||
size 23562
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:99fae3f838aa948b77391ef87d71ef56f2ac68b734bfdbd9c2b1868793dba192
|
||||
size 51583
|
||||
oid sha256:cd128a94f904caabcd0557b2d7742e743fe80ad8618d96148dc469d7c0f3a006
|
||||
size 51651
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2426456773a27afb8daedb3d4ce8d03901d5b4c5a92c034537a79cd0ed018b0b
|
||||
size 23067
|
||||
oid sha256:d27d44214d8f083ee8ecbda76e060167af26f00052c9c0acb43b77e87432ae54
|
||||
size 23084
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b929faac1dc1e016ae59333941612231fdc56ceeba56515b28d7e768e7fce4e2
|
||||
size 50630
|
||||
oid sha256:ecd37beb7a097aadda38238b36327dc5da809834f489c583146b9189d4e8a628
|
||||
size 50563
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:de520c3c0cf2133c2f862e061055b24d11a9fd7b54644b7aaaa989a8ecbe466f
|
||||
size 76719
|
||||
oid sha256:d8a8e7035c518edf069c9860e9fe4a894d144420541d6397066ec5ee7742df57
|
||||
size 77584
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0ac8095520e4a80826f34733f90d1cb3d56601f194edbd890508a6fc6f31eadf
|
||||
size 75246
|
||||
oid sha256:2fc2fd1c67088e29a3d8e2dc633b411cd8256d821243d5d2f96bcf6b8e5ab6cc
|
||||
size 75979
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a9d2f18ee31a3370c08ba437ac21173538117b8fcdfeb45665677746c9fdd335
|
||||
size 60790
|
||||
oid sha256:cd29b3483f20da49930f1bc65c04c25a5ba045a8cf7557ca65df26be3663d94a
|
||||
size 61388
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:59af9b4f6e390612464e8e83a1fbc0657a4bbd8c954c160e10c05bc6d48442fc
|
||||
size 55191
|
||||
oid sha256:e26369765383ad4e9d22dc0c0a2945fc28ebfcdc5f8f387dcebcc3db859de544
|
||||
size 55677
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d244fa646c87a6379d14eab9fa182652479473b5c77559e4631f3ffa19c0e1c4
|
||||
size 52134
|
||||
oid sha256:cf8e762edb7915238e9f2dc3b71b32d44659a02e031b169d004eb15b497e45c4
|
||||
size 52747
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:babfe5dd3b5eaff3cddeb3a09b6cc72c86241510311bad2322d3938919dd6e01
|
||||
size 74907
|
||||
oid sha256:d8bcd7f9287d275ee4fe2d9c8d6ef39715644696c8ddeaf84db7eb5877cce4c7
|
||||
size 75645
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cca5bcbc56dcd6b47e4608682a0a343eb612a0185332e245ca0025336a09bcd0
|
||||
size 73344
|
||||
oid sha256:1cc6acf5ef063b3bf4d101afe0c65435e2c4a68990ab3e860f57ad0bc18b32ec
|
||||
size 74073
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:88e989abce89da86ef8a7e2a4e036ac3ff9b41e38270edc3be9959a18cd4c86c
|
||||
size 57191
|
||||
oid sha256:d5fdc298a5f3320d57d5709f8d979b13712351d2b29e01be88f1ad43b9bb04bf
|
||||
size 57856
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9264c3aab735dc4546e9a12eb7698ad4572c911489906310044c8a5c65336a56
|
||||
size 52219
|
||||
oid sha256:f32a16cdf84a60cc3d74fb86201355dbcae8ec3dbb4b95c1999e0106752299f9
|
||||
size 52817
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c7e9d33860371dd2a280175f9482e43589aeaf92f443e3d7cb7ab487cdef1dfb
|
||||
size 48737
|
||||
oid sha256:2132cd35e731279fba539e10b2843b1ae012d1db7e01653e2f0ec60c054e9061
|
||||
size 49369
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:85690981c628723b7ae353fe82277967dfda763953d0fca91e2575e3d8d84c25
|
||||
size 43788
|
||||
oid sha256:24d232b144ff5664fecbd3c83fc04533eef8b3e82e4984b93f4156d996ad33e2
|
||||
size 43569
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d57f594ecf21d414ed0c301b30aa400ad3d04ca4aacae647899ae7550db7521a
|
||||
size 45012
|
||||
oid sha256:741ad1b881c9598c42c91603e84166768b5dc5a713ec191dc1c34c05360dbb92
|
||||
size 44908
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f81c06c3cbc14d8f9528a36f46ea9b39510f6eb9b1f93e731d4a182ed2a9dba8
|
||||
size 44549
|
||||
oid sha256:0da11f0f4d9c191218e0d45caa37620db92311bbf126788a1ac1d84ca03b63a5
|
||||
size 44444
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4fba92eab1bbfc9338db2581f8375c3edf09b3130e7997c1016cf0dcf782284c
|
||||
size 43209
|
||||
oid sha256:cc14af0383a159fbba7dc643e0d925db9ff8c4b22c2e38afcda20b504fd53d93
|
||||
size 44165
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fc2bdf0c222a688693e3df942b1c359f0e53799e1a81288f2a04a73bb53929c4
|
||||
size 34245
|
||||
oid sha256:e96f672af0dd6a622deb18bfccea861cb51b63c3355e85ee8a8db6543e3de05c
|
||||
size 33803
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f81c06c3cbc14d8f9528a36f46ea9b39510f6eb9b1f93e731d4a182ed2a9dba8
|
||||
size 44549
|
||||
oid sha256:0da11f0f4d9c191218e0d45caa37620db92311bbf126788a1ac1d84ca03b63a5
|
||||
size 44444
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f2801aecec234fa032e060262f030aebbf39cd23c9d4bfa014caddd422e93ffb
|
||||
size 42482
|
||||
oid sha256:31e50bed6ff94d2e20bb8cb0b9c35154de4c148c56a37518b0721fe463d7078b
|
||||
size 42242
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d0b38c4e39ce03f0fbdcb51425872a3ed096d58b5c16d05ced11bea882053c58
|
||||
size 43652
|
||||
oid sha256:ca3973d21ea5575ab0921f78c4443c69c21f1f3f07ca78612c57bfe58b261002
|
||||
size 43748
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a26fb7c853e0dd27b48a5d9ef247067f6bd8f8668695949be592dca1e54d3634
|
||||
size 43311
|
||||
oid sha256:f46c2d027a11f6dfca7edabc3d12ca7feed43c9688007c7cac9b654fb6fd6710
|
||||
size 43411
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c79d8c292de4b8dab500345a737274d84580f3d8c886652988c004363f975597
|
||||
size 42179
|
||||
oid sha256:4b5219d31af9590df4e78041af6cf217cfadd7cbe67753b22e919758e4a31f53
|
||||
size 42608
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:02826a3e3870f8c64a91a1ef0662cf2aa17818481e1c1d5f6ac3512eadb614a5
|
||||
size 32041
|
||||
oid sha256:85e3ccef2770f569ad2b062b9d7b86438b95e7235bf4d511621fa21dc2086f3e
|
||||
size 31504
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a26fb7c853e0dd27b48a5d9ef247067f6bd8f8668695949be592dca1e54d3634
|
||||
size 43311
|
||||
oid sha256:f46c2d027a11f6dfca7edabc3d12ca7feed43c9688007c7cac9b654fb6fd6710
|
||||
size 43411
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1dfe32bea70bff2eb009cde05441a8476701366d34341468a96101c336630c3d
|
||||
size 32242
|
||||
oid sha256:88fbd2415816962033bc3a5798c2e75d3e6fffe2e2886072b67f9acb8643d1e2
|
||||
size 31586
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c34faf032e7f38b49d9bb7e99c8688f9e1c7fd821d951a26c52b2bb4bc9cf24d
|
||||
size 36637
|
||||
oid sha256:d1d455bd313f90002307e23823e14189bf53ebd0f0b1cfa4478514d2bb8ab7d0
|
||||
size 36440
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5199a5d1f36ee96a30c81dd328dee7c07fc96fd5eab8a4b93f2fe33ccef4405d
|
||||
size 38989
|
||||
oid sha256:470d70f74c6c5560f5324874b2cedd0458614e3bdf6c65356879eb42ff337bb2
|
||||
size 38892
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3153a4e0b95bc3c6cd7c1424e864c9e1aadee95eee6a66fa03e760e9cd7cb10f
|
||||
size 44462
|
||||
oid sha256:cc85c3e76d57bc1b46a427ecee9ca64c238c419a346a43cd52d3a6e9f4199ed4
|
||||
size 43958
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:85a96fa375f9c77754feb70676a7aeb23803f9688bf3de6e61ebdf39062f42f1
|
||||
size 27219
|
||||
oid sha256:3399b98bd9f8d3ba2175125656db8871ba14ec98f80595d7be95bf8438a33219
|
||||
size 26803
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:df844f42580ca97e481656b04056ab0ae02b32c83bb6d46411c9d60040b5cf86
|
||||
size 117912
|
||||
oid sha256:d59fb94b1c8430065b7e40b413d250e631511acfac88cb01c24cf63e3d354cc1
|
||||
size 117561
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:96d2015cfd86eec443b94263da66c769df35135e8319d19bcab137a2b363d51a
|
||||
size 32781
|
||||
oid sha256:dd2845e9385c972347a1200ae3edb4d6a2bc866a4f4f34f07eaf9f96d0407405
|
||||
size 32270
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7af8a815fbdf00bc72ee8bdadfeb2d328b28d0f5a25d845f195889af8abba25e
|
||||
size 32770
|
||||
oid sha256:98a74b997bf3c1e1365abf1c944453b15f1f8eb4ee48e24d91dda05c0a602b2a
|
||||
size 33245
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:16d14b57d5299dba1cec83f416d6283065281ab5a50f7cb72286d7cea3d2dff5
|
||||
size 31067
|
||||
oid sha256:ed0cba1b78f970ab1ef5bfc277da6fcfbad8e07d3d3d796daab43948b0423f41
|
||||
size 30639
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:18713df330ee3b81cd015e09151e4b4a4739ddd3201a15f8d2e1286ee16b2d1e
|
||||
size 35436
|
||||
oid sha256:921d30810d6e1b6abfbd24bc7cef4b90916db0b41dccfd7de2298f81882fb5c7
|
||||
size 35224
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fef21564c727e0937748abcff1cd9ca45a54bfafe70176d7110f5321de9e7acf
|
||||
size 36436
|
||||
oid sha256:a07d6cc47b853a2f51aa8250290a5d618d702a40150bbae221bee9f2588828f9
|
||||
size 36271
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a218321a53ef189108aa19985bead154eb33afd4be5adf364ad0c0569bf003bf
|
||||
size 43054
|
||||
oid sha256:fe35cfe537168054a634faeb6c10519b2d13b694d532b152728df588c2f3649a
|
||||
size 42636
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fe01f18063cdaddfaa8f3d9c3395d5dba73c1726908b28e60a945d40a83c5978
|
||||
size 26468
|
||||
oid sha256:58a98bf2a38cb65d90f8e6181b70b673078830182d9f506598df5bda75cfdfd7
|
||||
size 26089
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d7dccaaf3da114e97fdaf89b000fe62d1b8235402edd3d4027e970746057f154
|
||||
size 114209
|
||||
oid sha256:4af7eec8cb1d89c71a9b2fe1efb28dbb956bac465e215ba7414432d7a37c272f
|
||||
size 113942
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0885f4af4e3e8afd56aaeb44f517b75eb087d9f21e1095da2c8a3590715a8672
|
||||
size 31669
|
||||
oid sha256:b5b1e6dbf5d662f0e4255dd0328bbe969ae6d309e4c9a5dbb6977671b940d428
|
||||
size 31310
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cf1b3633e2a946b3a63c326cdad8ab14dfb4d1d5b41c06754924a696cde47ea5
|
||||
size 30290
|
||||
oid sha256:31940f629ceaec427e44e1c4576d489550e40c652da5894bcca6da3f0642c5ff
|
||||
size 30708
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f1c5669f63f761311a49a7d82475ccd7463bdb5051db9add2875e13514272690
|
||||
size 20189
|
||||
oid sha256:4362307104a54c1e65ffe79765b54ce9b11ea482f1965d6ec2a8642b023110a6
|
||||
size 20108
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fe8c7f7de0d56bfc60af6771fd076104687e1f123ced09dfdedc625c03431458
|
||||
size 20361
|
||||
oid sha256:221e75077d503dc234772e3d3352055311e08290539f104e02c8a21463f03369
|
||||
size 20239
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b1a27216d9fb2e6d28109f6f414c0a06598103c69d182cdf5e926c930ac0a6b0
|
||||
size 69545
|
||||
oid sha256:c19217fdb11145af9a2e86bbdb9fa203ac717e8e94ca61798b4861392bb396e1
|
||||
size 69416
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:97ddd11519803c8d042e593c0d231051bc9518b4fbe2f63d80792ea34319442f
|
||||
size 87044
|
||||
oid sha256:cf191b543c1b87e0c33965c215b842f05e0f07ab86a4fbc2b2acbd577dc4df17
|
||||
size 108891
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f6fd4487ae63d2116b70a31b5ee8d18135cf735f6257134afd6572b0dbe1ac5b
|
||||
size 63216
|
||||
oid sha256:905112d921f655c9a122261b4a1d1980ed16079611be0b20066d976780ea8c5c
|
||||
size 66019
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b1a27216d9fb2e6d28109f6f414c0a06598103c69d182cdf5e926c930ac0a6b0
|
||||
size 69545
|
||||
oid sha256:c19217fdb11145af9a2e86bbdb9fa203ac717e8e94ca61798b4861392bb396e1
|
||||
size 69416
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1c2cd5fc3c6bef3f6cfc9f1d61bee2e2e41829ae3e77a3d8de31cf2168c25f61
|
||||
size 52908
|
||||
oid sha256:c86dd4d1ababe8df2d373aa1b47c14bf71e4744de78bff3efdab2f9fcb5034da
|
||||
size 49211
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ca62ad16aa94477303c61f1796d6fff8262fde99c3b31184538f6ae9234dc950
|
||||
size 67807
|
||||
oid sha256:1f7c6104e319a7246c04dcc4749c01e7147b412e6905e1fec70b7331632cf1a2
|
||||
size 67441
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f625b162bbd3172e953676219de6ba00e0cb34f0acbcda5ff6847359e7b867e3
|
||||
size 85035
|
||||
oid sha256:2497fd0b7d7ae2e8da0a69e36a34c0dd7f7c8abb52b95005cd961b3c5c4b8734
|
||||
size 106454
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:23f505a91ebe3438f52c65f53362fc2d5cca57a8959e5459722217541ec24fc9
|
||||
size 62030
|
||||
oid sha256:d84ab79382862503da8f18a54d05578a560f515f9062af5fd6c922fe830ca84a
|
||||
size 63656
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ca62ad16aa94477303c61f1796d6fff8262fde99c3b31184538f6ae9234dc950
|
||||
size 67807
|
||||
oid sha256:1f7c6104e319a7246c04dcc4749c01e7147b412e6905e1fec70b7331632cf1a2
|
||||
size 67441
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bbe73e23b4217cf10f3a5d50483bcd4d1fdc956b35129e66133c1c9ee26595bd
|
||||
size 49536
|
||||
oid sha256:3afd2de9146b6d29dec8e6249acbf771cc602d27f5783523da844f24f24c8daf
|
||||
size 45984
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e534ca2cc96a4b7a0e840eb18d153479f9e641348216fb4237c431dc8ef727d4
|
||||
size 27831
|
||||
oid sha256:2450f444e0e4c7a0f354ff8a38225df5b0255280924996b0d4d40b72fdf0438f
|
||||
size 27737
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:31f588a58c0e79c37edbdcc72748fb1cd69e15e2313f48c5800fcf7f473d1f57
|
||||
size 21509
|
||||
oid sha256:2633d18f133660a2daff4ba902abe0450cf233714d43f5de8897379784f082c5
|
||||
size 21375
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1e085b1745cd0445b7954af882a73b50bbd4dea74ec6def5d49562f6839c6095
|
||||
size 29353
|
||||
oid sha256:4dbe0286f64a876af3bc4570141e26881462d8ca17485632e2fc599ae9eed563
|
||||
size 29037
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:54f82d574bca5f68787bc239ecd58cfcae94f1e6dd2f760e48dd033aba784df9
|
||||
size 53535
|
||||
oid sha256:09f520d47af8427aa51e0a1938adab74c3433952a68c248e090a8f99454e39bf
|
||||
size 53466
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue