diff --git a/app/src/main/java/app/pachli/components/conversation/ConversationsFragment.kt b/app/src/main/java/app/pachli/components/conversation/ConversationsFragment.kt index 8e8fad59b..ad71027c3 100644 --- a/app/src/main/java/app/pachli/components/conversation/ConversationsFragment.kt +++ b/app/src/main/java/app/pachli/components/conversation/ConversationsFragment.kt @@ -55,6 +55,7 @@ import app.pachli.fragment.SFragment import app.pachli.interfaces.ActionButtonActivity import app.pachli.interfaces.ReselectableFragment import app.pachli.interfaces.StatusActionListener +import app.pachli.util.ListStatusAccessibilityDelegate import app.pachli.util.StatusDisplayOptionsRepository import at.connyduck.sparkbutton.helpers.Utils import com.google.android.material.color.MaterialColors @@ -220,6 +221,15 @@ class ConversationsFragment : } private fun setupRecyclerView() { + binding.recyclerView.setAccessibilityDelegateCompat( + ListStatusAccessibilityDelegate(binding.recyclerView, this) { pos -> + if (pos in 0 until adapter.itemCount) { + adapter.peek(pos) + } else { + null + } + }, + ) binding.recyclerView.setHasFixedSize(true) binding.recyclerView.layoutManager = LinearLayoutManager(context) diff --git a/app/src/main/java/app/pachli/components/notifications/NotificationsFragment.kt b/app/src/main/java/app/pachli/components/notifications/NotificationsFragment.kt index 8e55a03e7..2eb10226c 100644 --- a/app/src/main/java/app/pachli/components/notifications/NotificationsFragment.kt +++ b/app/src/main/java/app/pachli/components/notifications/NotificationsFragment.kt @@ -26,8 +26,10 @@ import android.view.MenuInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup +import android.view.accessibility.AccessibilityManager import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog +import androidx.core.content.ContextCompat import androidx.core.view.MenuProvider import androidx.core.view.isVisible import androidx.fragment.app.DialogFragment @@ -106,6 +108,8 @@ class NotificationsFragment : private lateinit var layoutManager: LinearLayoutManager + private var talkBackWasEnabled = false + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -149,7 +153,11 @@ class NotificationsFragment : binding.recyclerView.layoutManager = layoutManager binding.recyclerView.setAccessibilityDelegateCompat( ListStatusAccessibilityDelegate(binding.recyclerView, this) { pos: Int -> - adapter.snapshot().getOrNull(pos) + if (pos in 0 until adapter.itemCount) { + adapter.peek(pos) + } else { + null + } }, ) binding.recyclerView.addItemDecoration( @@ -502,6 +510,14 @@ class NotificationsFragment : override fun onResume() { super.onResume() + + val a11yManager = ContextCompat.getSystemService(requireContext(), AccessibilityManager::class.java) + val wasEnabled = talkBackWasEnabled + talkBackWasEnabled = a11yManager?.isEnabled == true + if (talkBackWasEnabled && !wasEnabled) { + adapter.notifyItemRangeChanged(0, adapter.itemCount) + } + clearNotificationsForAccount(requireContext(), viewModel.account) } diff --git a/app/src/main/java/app/pachli/util/ListStatusAccessibilityDelegate.kt b/app/src/main/java/app/pachli/util/ListStatusAccessibilityDelegate.kt index b3b92f1d0..ca10b2996 100644 --- a/app/src/main/java/app/pachli/util/ListStatusAccessibilityDelegate.kt +++ b/app/src/main/java/app/pachli/util/ListStatusAccessibilityDelegate.kt @@ -49,51 +49,50 @@ class ListStatusAccessibilityDelegate( val pos = recyclerView.getChildAdapterPosition(host) val status = statusProvider.getStatus(pos) ?: return - if (status is StatusViewData) { - if (status.spoilerText.isNotEmpty()) { - info.addAction(if (status.isExpanded) collapseCwAction else expandCwAction) - } - info.addAction(replyAction) - - val actionable = status.actionable - if (actionable.rebloggingAllowed()) { - info.addAction(if (actionable.reblogged) unreblogAction else reblogAction) - } - info.addAction(if (actionable.favourited) unfavouriteAction else favouriteAction) - info.addAction(if (actionable.bookmarked) unbookmarkAction else bookmarkAction) - - val mediaActions = intArrayOf( - R.id.action_open_media_1, - R.id.action_open_media_2, - R.id.action_open_media_3, - R.id.action_open_media_4, - ) - val attachmentCount = min(actionable.attachments.size, MAX_MEDIA_ATTACHMENTS) - for (i in 0 until attachmentCount) { - info.addAction( - AccessibilityActionCompat( - mediaActions[i], - context.getString(R.string.action_open_media_n, i + 1), - ), - ) - } - - info.addAction(openProfileAction) - if (getLinks(status).any()) info.addAction(linksAction) - - val mentions = actionable.mentions - if (mentions.isNotEmpty()) info.addAction(mentionsAction) - - if (getHashtags(status).any()) info.addAction(hashtagsAction) - if (!status.status.reblog?.account?.username.isNullOrEmpty()) { - info.addAction(openRebloggerAction) - } - if (actionable.reblogsCount > 0) info.addAction(openRebloggedByAction) - if (actionable.favouritesCount > 0) info.addAction(openFavsAction) - - info.addAction(moreAction) + if (status.spoilerText.isNotEmpty()) { + info.addAction(if (status.isExpanded) collapseCwAction else expandCwAction) } + + info.addAction(replyAction) + + val actionable = status.actionable + if (actionable.rebloggingAllowed()) { + info.addAction(if (actionable.reblogged) unreblogAction else reblogAction) + } + info.addAction(if (actionable.favourited) unfavouriteAction else favouriteAction) + info.addAction(if (actionable.bookmarked) unbookmarkAction else bookmarkAction) + + val mediaActions = intArrayOf( + R.id.action_open_media_1, + R.id.action_open_media_2, + R.id.action_open_media_3, + R.id.action_open_media_4, + ) + val attachmentCount = min(actionable.attachments.size, MAX_MEDIA_ATTACHMENTS) + for (i in 0 until attachmentCount) { + info.addAction( + AccessibilityActionCompat( + mediaActions[i], + context.getString(R.string.action_open_media_n, i + 1), + ), + ) + } + + info.addAction(openProfileAction) + if (getLinks(status).any()) info.addAction(linksAction) + + val mentions = actionable.mentions + if (mentions.isNotEmpty()) info.addAction(mentionsAction) + + if (getHashtags(status).any()) info.addAction(hashtagsAction) + if (!status.status.reblog?.account?.username.isNullOrEmpty()) { + info.addAction(openRebloggerAction) + } + if (actionable.reblogsCount > 0) info.addAction(openRebloggedByAction) + if (actionable.favouritesCount > 0) info.addAction(openFavsAction) + + info.addAction(moreAction) } override fun performAccessibilityAction( @@ -230,7 +229,7 @@ class ListStatusAccessibilityDelegate( } } - private fun getLinks(status: StatusViewData): Sequence { + private fun getLinks(status: IStatusViewData): Sequence { val content = status.content return if (content is Spannable) { content.getSpans(0, content.length, URLSpan::class.java) @@ -248,7 +247,7 @@ class ListStatusAccessibilityDelegate( } } - private fun getHashtags(status: StatusViewData): Sequence { + private fun getHashtags(status: IStatusViewData): Sequence { val content = status.content return content.getSpans(0, content.length, Object::class.java) .asSequence()