From 6986c8892ceb5c38b186848fc63b95e5c786dd33 Mon Sep 17 00:00:00 2001 From: Aleksey Ivanovsky Date: Wed, 4 Dec 2024 21:25:02 +0100 Subject: [PATCH] Add accessibility tags --- .../presentation/core/compose/Accessibility.kt | 16 ++++++++++++++++ .../presentation/core/widget/MaterialEditText.kt | 16 ++++++++++++++++ .../serverLogin/ServerLoginScreen.kt | 5 +++++ .../main/res/layout/dialog_change_password.xml | 3 +++ .../main/res/layout/group_editor_fragment.xml | 5 ++++- app/src/main/res/layout/groups_fragment.xml | 1 + .../main/res/layout/new_database_fragment.xml | 5 ++++- .../res/layout/password_generator_fragment.xml | 1 + .../res/layout/widget_material_edit_text.xml | 3 ++- app/src/main/res/layout/widget_unlock_view.xml | 3 ++- app/src/main/res/values/attrs.xml | 1 + app/src/main/res/values/strings.xml | 5 +++++ 12 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 app/src/main/kotlin/com/ivanovsky/passnotes/presentation/core/compose/Accessibility.kt diff --git a/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/core/compose/Accessibility.kt b/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/core/compose/Accessibility.kt new file mode 100644 index 00000000..cf5fe6dc --- /dev/null +++ b/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/core/compose/Accessibility.kt @@ -0,0 +1,16 @@ +package com.ivanovsky.passnotes.presentation.core.compose + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics + +@Composable +fun contentDescription(description: String): Modifier { + return remember { + Modifier.semantics { + contentDescription = description + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/core/widget/MaterialEditText.kt b/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/core/widget/MaterialEditText.kt index 83996dcb..dd13f15a 100644 --- a/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/core/widget/MaterialEditText.kt +++ b/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/core/widget/MaterialEditText.kt @@ -143,6 +143,11 @@ class MaterialEditText( this.hint = hint } + val description = params.getString(R.styleable.MaterialEditText_description) + if (description != null) { + binding.textInput.contentDescription = description + } + val isEyeButtonEnabled = params.getBoolean( R.styleable.MaterialEditText_isEyeButtonEnabled, false @@ -157,10 +162,12 @@ class MaterialEditText( isEyeButtonEnabled && isClearButtonEnabled -> { throw IllegalStateException() } + isEyeButtonEnabled -> { actionButton = ActionButton.EYE isTextVisible = false } + isClearButtonEnabled -> { actionButton = ActionButton.CLEAR } @@ -272,6 +279,7 @@ class MaterialEditText( InputType.TYPE_CLASS_TEXT + InputType.TYPE_TEXT_VARIATION_PASSWORD } } + TextInputType.DIGITS -> { if (isTextVisible) { InputType.TYPE_CLASS_NUMBER @@ -279,12 +287,15 @@ class MaterialEditText( InputType.TYPE_CLASS_NUMBER + InputType.TYPE_NUMBER_VARIATION_PASSWORD } } + TextInputType.TEXT_CAP_SENTENCES -> { InputType.TYPE_CLASS_TEXT + InputType.TYPE_TEXT_FLAG_CAP_SENTENCES } + TextInputType.URL -> { InputType.TYPE_CLASS_TEXT + InputType.TYPE_TEXT_VARIATION_URI } + TextInputType.EMAIL -> { InputType.TYPE_CLASS_TEXT + InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS } @@ -300,11 +311,13 @@ class MaterialEditText( binding.textInput.maxLines = 1 binding.textInput.isSingleLine = true } + TextInputLines.MULTIPLE_LINES -> { binding.textInput.isSingleLine = false binding.textInput.minLines = 1 binding.textInput.maxLines = 25 } + else -> {} } setTextVisibleInternal(isTextVisible) @@ -316,9 +329,11 @@ class MaterialEditText( ImeOptions.ACTION_DONE -> { binding.textInput.imeOptions = EditorInfo.IME_ACTION_DONE } + ImeOptions.ACTION_NEXT -> { binding.textInput.imeOptions = EditorInfo.IME_ACTION_NEXT } + else -> {} } } @@ -353,6 +368,7 @@ class MaterialEditText( } binding.editTextActionButton.setImageResource(getEyeIcon(isTextVisible)) } + ActionButton.CLEAR -> { binding.editTextActionButton.setImageResource(R.drawable.ic_close_24dp) } diff --git a/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/serverLogin/ServerLoginScreen.kt b/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/serverLogin/ServerLoginScreen.kt index 9a520575..d740aa24 100644 --- a/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/serverLogin/ServerLoginScreen.kt +++ b/app/src/main/kotlin/com/ivanovsky/passnotes/presentation/serverLogin/ServerLoginScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.tooling.preview.Preview import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ivanovsky.passnotes.R @@ -27,6 +28,7 @@ import com.ivanovsky.passnotes.presentation.core.compose.PrimaryTextStyle import com.ivanovsky.passnotes.presentation.core.compose.ProgressIndicator import com.ivanovsky.passnotes.presentation.core.compose.ThemedScreenPreview import com.ivanovsky.passnotes.presentation.core.compose.cells.ui.InfoCell +import com.ivanovsky.passnotes.presentation.core.compose.contentDescription import com.ivanovsky.passnotes.presentation.core.compose.model.InputType import com.ivanovsky.passnotes.presentation.serverLogin.model.LoginType import com.ivanovsky.passnotes.presentation.serverLogin.model.ServerLoginIntent.OnIgnoreSslValidationStateChanged @@ -225,6 +227,7 @@ private fun UrlTextField( end = dimensionResource(R.dimen.element_margin), top = dimensionResource(R.dimen.element_margin) ) + .then(contentDescription(stringResource(R.string.url))) ) } @@ -302,6 +305,7 @@ private fun UsernameTextField( end = dimensionResource(R.dimen.element_margin), top = dimensionResource(R.dimen.element_margin) ) + .then(contentDescription(stringResource(R.string.username))) ) } @@ -332,6 +336,7 @@ private fun PasswordTextField( end = dimensionResource(R.dimen.element_margin), top = dimensionResource(R.dimen.element_margin) ) + .then(contentDescription(stringResource(R.string.password))) ) } diff --git a/app/src/main/res/layout/dialog_change_password.xml b/app/src/main/res/layout/dialog_change_password.xml index 5a5b7b96..19aae001 100644 --- a/app/src/main/res/layout/dialog_change_password.xml +++ b/app/src/main/res/layout/dialog_change_password.xml @@ -35,6 +35,7 @@ android:layout_marginStart="@dimen/element_margin" android:layout_marginTop="@dimen/group_margin" android:layout_marginEnd="@dimen/element_margin" + app:description="@string/password" app:hint="@string/password" app:isEyeButtonEnabled="true" app:layout_constraintBottom_toTopOf="@id/newPassword" @@ -52,6 +53,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="@dimen/element_margin" + app:description="@string/new_password" app:hint="@string/new_password" app:isEyeButtonEnabled="true" app:layout_constraintBottom_toTopOf="@id/confirmation" @@ -68,6 +70,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="@dimen/element_margin" + app:description="@string/confirm_password" app:hint="@string/confirm_password" app:isEyeButtonEnabled="true" app:layout_constraintBottom_toTopOf="@id/applyButton" diff --git a/app/src/main/res/layout/group_editor_fragment.xml b/app/src/main/res/layout/group_editor_fragment.xml index 93c4de9f..2868036f 100644 --- a/app/src/main/res/layout/group_editor_fragment.xml +++ b/app/src/main/res/layout/group_editor_fragment.xml @@ -28,7 +28,9 @@ android:layout_width="match_parent" android:layout_height="match_parent" app:screenState="@{viewModel.screenState}" - app:screenStateHandler="@{viewModel.screenStateHandler}" /> + app:screenStateHandler="@{viewModel.screenStateHandler}" + tools:layout_editor_absoluteX="0dp" + tools:layout_editor_absoluteY="0dp" /> + app:tint="?attr/kpIconPrimaryColor" /> diff --git a/app/src/main/res/layout/widget_material_edit_text.xml b/app/src/main/res/layout/widget_material_edit_text.xml index 37d8a2b4..182d574f 100644 --- a/app/src/main/res/layout/widget_material_edit_text.xml +++ b/app/src/main/res/layout/widget_material_edit_text.xml @@ -16,9 +16,9 @@ @@ -30,6 +30,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/small_margin" + android:contentDescription="@string/eye_icon" android:focusable="false" android:focusableInTouchMode="false" android:visibility="gone" diff --git a/app/src/main/res/layout/widget_unlock_view.xml b/app/src/main/res/layout/widget_unlock_view.xml index 64629b0f..5a37d6b9 100644 --- a/app/src/main/res/layout/widget_unlock_view.xml +++ b/app/src/main/res/layout/widget_unlock_view.xml @@ -23,6 +23,7 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/half_margin" android:layout_marginEnd="@dimen/half_margin" + app:description="@string/password" app:hint="@string/password" app:isEyeButtonEnabled="true" app:layout_constraintEnd_toStartOf="@id/unlockButton" @@ -34,9 +35,9 @@ android:layout_width="wrap_content" android:layout_height="0dp" android:layout_marginTop="@dimen/small_margin" + android:contentDescription="@string/unlock_button" android:foreground="?attr/selectableItemBackground" android:minWidth="@dimen/unlock_button_size" - android:contentDescription="unlockButton" app:layout_constraintBottom_toBottomOf="@id/password" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@id/password" /> diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 8bb150fa..276b023c 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -8,5 +8,6 @@ + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9920b016..2ea773bb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,6 +44,11 @@ Synchronize with source Details + + URL + Unlock button + Eye icon + Quick Lock Button to lock opened database