Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[a11y] 11.4.1.2 Name-role value #4454

Merged
merged 17 commits into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ ownCloud admins and users.
* Enhancement - Improved accessibility of information and relationships: [#4362](https://github.com/owncloud/android/issues/4362)
* Enhancement - Changed the color of some elements to improve accessibility: [#4364](https://github.com/owncloud/android/issues/4364)
* Enhancement - Improved SearchView accessibility: [#4365](https://github.com/owncloud/android/issues/4365)
* Enhancement - Roles added to some elements to improve accessibility: [#4373](https://github.com/owncloud/android/issues/4373)
* Enhancement - Hardware keyboard support: [#4438](https://github.com/owncloud/android/pull/4438)
* Enhancement - Hardware keyboard support for passcode view: [#4447](https://github.com/owncloud/android/issues/4447)

Expand Down Expand Up @@ -88,6 +89,14 @@ ownCloud admins and users.
https://github.com/owncloud/android/issues/4365
https://github.com/owncloud/android/pull/4433

* Enhancement - Roles added to some elements to improve accessibility: [#4373](https://github.com/owncloud/android/issues/4373)

Roles have been added to specific elements within the following views: Toolbar,
Spaces, Drawer Menu, Manage accounts and Floating Action Button.

https://github.com/owncloud/android/issues/4373
https://github.com/owncloud/android/pull/4454

* Enhancement - Hardware keyboard support: [#4438](https://github.com/owncloud/android/pull/4438)

Navigation via hardware keyboard has been improved so that now focus order has a
Expand Down
6 changes: 6 additions & 0 deletions changelog/unreleased/4454
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Roles added to some elements to improve accessibility

Roles have been added to specific elements within the following views: Toolbar, Spaces, Drawer Menu, Manage accounts and Floating Action Button.

https://github.com/owncloud/android/issues/4373
https://github.com/owncloud/android/pull/4454
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* ownCloud Android client application
*
* @author Aitor Ballesteros Pavón
*
* Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.owncloud.android.extensions

import android.view.View
import androidx.core.view.AccessibilityDelegateCompat
import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat

fun View.setAccessibilityRole(className: Class<*>? = null, roleDescription: String? = null) {
ViewCompat.setAccessibilityDelegate(this, object : AccessibilityDelegateCompat() {
override fun onInitializeAccessibilityNodeInfo(v: View, info: AccessibilityNodeInfoCompat) {
super.onInitializeAccessibilityNodeInfo(v, info)
className?.let { info.className = it.name }
roleDescription?.let { info.roleDescription = it }
}
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ import android.accounts.Account
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.recyclerview.widget.RecyclerView
import com.owncloud.android.R
import com.owncloud.android.databinding.AccountActionBinding
import com.owncloud.android.databinding.AccountItemBinding
import com.owncloud.android.extensions.setAccessibilityRole
import com.owncloud.android.lib.common.OwnCloudAccount
import com.owncloud.android.presentation.authentication.AccountUtils
import com.owncloud.android.presentation.avatar.AvatarUtils
Expand All @@ -46,6 +48,7 @@ class ManageAccountsAdapter(private val accountListener: AccountAdapterListener)
return if (viewType == AccountManagementRecyclerItemViewType.ITEM_VIEW_ACCOUNT.ordinal) {
val view = inflater.inflate(R.layout.account_item, parent, false)
view.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(parent.context)
view.setAccessibilityRole(className = Button::class.java)
AccountManagementViewHolder(view)
} else {
val view = inflater.inflate(R.layout.account_action, parent, false)
Expand Down Expand Up @@ -119,6 +122,7 @@ class ManageAccountsAdapter(private val accountListener: AccountAdapterListener)
is NewAccountViewHolder -> {
holder.binding.icon.setImageResource(R.drawable.ic_account_plus)
holder.binding.name.setText(R.string.prefs_add_account)
holder.binding.name.setAccessibilityRole(className = Button::class.java)

// bind action listener
holder.binding.constraintLayoutAction.setOnClickListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* ownCloud Android client application
*
* @author Abel García de Prada
* Copyright (C) 2020 ownCloud GmbH.
* @author Aitor Ballesteros Pavón
*
* Copyright (C) 2024 ownCloud GmbH.
* <p>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand All @@ -21,13 +23,20 @@ package com.owncloud.android.presentation.files
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.view.AccessibilityDelegateCompat
import androidx.core.view.ViewCompat
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import com.owncloud.android.R
import com.owncloud.android.data.providers.SharedPreferencesProvider
import com.owncloud.android.data.providers.implementation.OCSharedPreferencesProvider
import com.owncloud.android.databinding.SortOptionsLayoutBinding
import com.owncloud.android.extensions.setAccessibilityRole
import com.owncloud.android.presentation.files.SortOrder.Companion.PREF_FILE_LIST_SORT_ORDER
import com.owncloud.android.presentation.files.SortOrder.SORT_ORDER_ASCENDING
import com.owncloud.android.presentation.files.SortType.Companion.PREF_FILE_LIST_SORT_TYPE

class SortOptionsView @JvmOverloads constructor(
Expand Down Expand Up @@ -75,7 +84,7 @@ class SortOptionsView @JvmOverloads constructor(
// Select sort type and order according to preferences.
sortTypeSelected = SortType.values()[sharedPreferencesProvider.getInt(PREF_FILE_LIST_SORT_TYPE, SortType.SORT_TYPE_BY_NAME.ordinal)]
sortOrderSelected = SortOrder.values()[sharedPreferencesProvider.getInt(PREF_FILE_LIST_SORT_ORDER, SortOrder.SORT_ORDER_ASCENDING.ordinal)]

binding.sortTypeTitle.setAccessibilityRole(className = Button::class.java)
binding.sortTypeSelector.setOnClickListener {
onSortOptionsListener?.onSortTypeListener(
sortTypeSelected,
Expand All @@ -87,6 +96,18 @@ class SortOptionsView @JvmOverloads constructor(
viewTypeSelected.getOppositeViewType()
)
}
ViewCompat.setAccessibilityDelegate(binding.sortTypeSelector, object : AccessibilityDelegateCompat() {
override fun onInitializeAccessibilityNodeInfo(v: View, info: AccessibilityNodeInfoCompat) {
super.onInitializeAccessibilityNodeInfo(v, info)
val sortTitleText = binding.sortTypeTitle.text
if (sortOrderSelected == SORT_ORDER_ASCENDING) {
binding.sortTypeTitle.contentDescription = context.getString(R.string.content_description_sort_by_name_ascending, sortTitleText)
} else {
binding.sortTypeTitle.contentDescription = context.getString(R.string.content_description_sort_by_name_descending, sortTitleText)
}
}
})

}

fun selectAdditionalView(additionalView: AdditionalView) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ import android.accounts.Account
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
Expand Down Expand Up @@ -219,10 +219,6 @@ class FileDetailsFragment : FileFragment() {
fileDetailsViewModel.checkOnGoingTransfersWhenOpening()
}

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.file_actions_menu, menu)
}

override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
Expand All @@ -241,6 +237,20 @@ class FileDetailsFragment : FileFragment() {

val appRegistryProviders = fileDetailsViewModel.appRegistryMimeType.value?.appProviders
openInWebProviders = addOpenInWebMenuOptions(menu, openInWebProviders, appRegistryProviders)

setRolesAccessibilityToMenuItems(menu)
}

private fun setRolesAccessibilityToMenuItems(menu: Menu) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val roleAccessibilityDescription = getString(R.string.button_role_accessibility)
menu.findItem(R.id.action_rename_file).setContentDescription(
getString(R.string.common_rename) + roleAccessibilityDescription
)
menu.findItem(R.id.action_remove_file).setContentDescription(
getString(R.string.common_remove) + roleAccessibilityDescription
)
}
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
Expand Down Expand Up @@ -280,8 +281,7 @@ class MainFileListFragment : Fragment(),

showOrHideFab(requireArguments().getParcelable(ARG_FILE_LIST_OPTION)!!, requireArguments().getParcelable(ARG_INITIAL_FOLDER_TO_DISPLAY)!!)

binding.fabMain.findViewById<AddFloatingActionButton>(com.getbase.floatingactionbutton.R.id.fab_expand_menu_button).contentDescription =
getString(R.string.content_description_add_new_content)
setFabMainContentDescription()

setTextHintRootToolbar()
}
Expand Down Expand Up @@ -859,6 +859,11 @@ class MainFileListFragment : Fragment(),
fabMkdir.isFocusable = isFabExpanded()
fabNewfile.isFocusable = isFabExpanded()
fabNewshortcut.isFocusable = isFabExpanded()
if (fabMain.isExpanded) {
binding.fabMain.findViewById<AddFloatingActionButton>(com.getbase.floatingactionbutton.R.id.fab_expand_menu_button).contentDescription = getString(R.string.content_description_add_new_content_expanded)
} else {
setFabMainContentDescription()
}
}
}
}
Expand Down Expand Up @@ -918,6 +923,11 @@ class MainFileListFragment : Fragment(),

fun isFabExpanded() = binding.fabMain.isExpanded

fun setFabMainContentDescription() {
binding.fabMain.findViewById<AddFloatingActionButton>(com.getbase.floatingactionbutton.R.id.fab_expand_menu_button).contentDescription =
getString(R.string.content_description_add_new_content)
}

private fun openBottomSheetToUploadFiles() {
val uploadBottomSheet = layoutInflater.inflate(R.layout.upload_bottom_sheet_fragment, null)
val dialog = BottomSheetDialog(requireContext())
Expand Down Expand Up @@ -1411,10 +1421,30 @@ class MainFileListFragment : Fragment(),
openInWebProviders = emptyMap()
}
}
setRolesAccessibilityToMenuItems()

return true
}

private fun setRolesAccessibilityToMenuItems() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val roleAccessibilityDescription = getString(R.string.button_role_accessibility)
menu?.apply {
findItem(R.id.file_action_select_all)?.contentDescription = getString(R.string.actionbar_select_all) + roleAccessibilityDescription
findItem(R.id.action_select_inverse)?.contentDescription = getString(R.string.actionbar_select_inverse) + roleAccessibilityDescription
findItem(R.id.action_open_file_with)?.contentDescription = getString(R.string.actionbar_open_with) + roleAccessibilityDescription
findItem(R.id.action_rename_file)?.contentDescription = getString(R.string.common_rename) + roleAccessibilityDescription
findItem(R.id.action_move)?.contentDescription = getString(R.string.actionbar_move) + roleAccessibilityDescription
findItem(R.id.action_copy)?.contentDescription = getString(R.string.copy) + roleAccessibilityDescription
findItem(R.id.action_send_file)?.contentDescription = getString(R.string.actionbar_send_file) + roleAccessibilityDescription
findItem(R.id.action_set_available_offline)?.contentDescription = getString(R.string.set_available_offline) + roleAccessibilityDescription
findItem(R.id.action_unset_available_offline)?.contentDescription = getString(R.string.unset_available_offline) + roleAccessibilityDescription
findItem(R.id.action_see_details)?.contentDescription = getString(R.string.actionbar_see_details) + roleAccessibilityDescription
findItem(R.id.action_remove_file)?.contentDescription = getString(R.string.common_remove) + roleAccessibilityDescription
}
}
}

override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
return onFileActionChosen(item?.itemId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.CompoundButton
import android.widget.TextView
import androidx.appcompat.widget.SwitchCompat
Expand All @@ -55,6 +56,7 @@ import com.owncloud.android.domain.sharing.shares.model.OCShare
import com.owncloud.android.domain.utils.Event.EventObserver
import com.owncloud.android.extensions.avoidScreenshotsIfNeeded
import com.owncloud.android.extensions.parseError
import com.owncloud.android.extensions.setAccessibilityRole
import com.owncloud.android.extensions.showMessageInSnackbar
import com.owncloud.android.lib.resources.shares.RemoteShare
import com.owncloud.android.lib.resources.status.OwnCloudVersion
Expand Down Expand Up @@ -122,6 +124,7 @@ class PublicShareDialogFragment : DialogFragment() {
val expirationDateValueInMillis: Long
get() {
var publicLinkExpirationDateInMillis: Long = -1
binding.shareViaLinkExpirationValue.setAccessibilityRole(className = Button::class.java)
val expirationDate = binding.shareViaLinkExpirationValue.text.toString()
if (expirationDate.isNotEmpty()) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
*
* @author Juan Carlos Garrote Gascón
* @author Manuel Plazas Palacio
* @author Aitor Balleteros Pavón
*
* Copyright (C) 2023 ownCloud GmbH.
* Copyright (C) 2024 ownCloud GmbH.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand All @@ -23,6 +24,7 @@ package com.owncloud.android.presentation.spaces

import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Button
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
Expand All @@ -31,6 +33,7 @@ import coil.load
import com.owncloud.android.R
import com.owncloud.android.databinding.SpacesListItemBinding
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.extensions.setAccessibilityRole
import com.owncloud.android.presentation.thumbnails.ThumbnailsRequester
import com.owncloud.android.utils.PreferenceUtils

Expand All @@ -54,6 +57,7 @@ class SpacesListAdapter(
spacesListItemCard.setOnClickListener {
listener.onItemClick(space)
}
spacesListItemCard.setAccessibilityRole(className = Button::class.java)

if (space.isPersonal) {
spacesListItemName.text = holder.itemView.context.getString(R.string.bottom_nav_personal)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import com.owncloud.android.domain.utils.Event
import com.owncloud.android.extensions.goToUrl
import com.owncloud.android.extensions.openPrivacyPolicy
import com.owncloud.android.extensions.sendEmailOrOpenFeedbackDialogAction
import com.owncloud.android.extensions.setAccessibilityRole
import com.owncloud.android.lib.common.OwnCloudAccount
import com.owncloud.android.presentation.authentication.AccountUtils
import com.owncloud.android.presentation.avatar.AvatarUtils
Expand Down Expand Up @@ -112,10 +113,12 @@ abstract class DrawerActivity : ToolbarActivity() {
getDrawerLinkIcon()?.apply {
isVisible = true
setOnClickListener { openDrawerLink() }
setAccessibilityRole(roleDescription = context.getString(R.string.link_role_accessibility))
}
getDrawerLinkText()?.apply {
isVisible = true
setOnClickListener { openDrawerLink() }
setAccessibilityRole(roleDescription = context.getString(R.string.link_role_accessibility))
}
} else {
getDrawerLogo()?.setImageResource(R.drawable.drawer_logo)
Expand Down Expand Up @@ -189,6 +192,7 @@ abstract class DrawerActivity : ToolbarActivity() {
}
true
}
setRolesAccessibilityToMenuItems()
}

fun setCheckedItemAtBottomBar(checkedMenuItem: Int) {
Expand Down Expand Up @@ -415,6 +419,19 @@ abstract class DrawerActivity : ToolbarActivity() {
}, Handler(), false)
}

private fun setRolesAccessibilityToMenuItems() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val navViewMenu = getNavView()?.menu ?: return
val roleAccessibilityDescription = getString(R.string.button_role_accessibility)
navViewMenu.apply {
findItem(R.id.nav_settings)?.contentDescription = getString(R.string.actionbar_settings) + roleAccessibilityDescription
findItem(R.id.drawer_menu_feedback)?.contentDescription = getString(R.string.drawer_feedback) + roleAccessibilityDescription
findItem(R.id.drawer_menu_help)?.contentDescription = getString(R.string.prefs_help) + roleAccessibilityDescription
findItem(R.id.drawer_menu_privacy_policy)?.contentDescription = getString(R.string.prefs_privacy_policy) + roleAccessibilityDescription
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
Expand Down
Loading
Loading