From 9ffd89b666833cc29a10d0e8a9848d38f7347cf3 Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Wed, 20 Nov 2024 12:47:43 +0100 Subject: [PATCH] feat: Show extra a11y actions for trending links and suggested accounts (#1114) Extend the "suggested accounts" accessibility actions to include any mentions in the account's bio. Links, mentions, and hashtags are now shown with a button to easily copy them. Extend the "trending links" accessibility actions with a new "copy link" action. Consolidate common functionality in to the new `PachliRecyclerviewAccessibilityDelegate` base class. --- .../TrendingLinksAccessibilityDelegate.kt | 40 +++-- .../util/ListStatusAccessibilityDelegate.kt | 147 ++++-------------- app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-be/strings.xml | 1 - app/src/main/res/values-bg/strings.xml | 1 - app/src/main/res/values-bn-rBD/strings.xml | 1 - app/src/main/res/values-bn-rIN/strings.xml | 1 - app/src/main/res/values-ca/strings.xml | 3 +- app/src/main/res/values-ckb/strings.xml | 1 - app/src/main/res/values-cs/strings.xml | 3 +- app/src/main/res/values-cy/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-eo/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-eu/strings.xml | 1 - app/src/main/res/values-fa/strings.xml | 1 - app/src/main/res/values-fi/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-ga/strings.xml | 1 - app/src/main/res/values-gd/strings.xml | 1 - app/src/main/res/values-gl/strings.xml | 1 - app/src/main/res/values-hi/strings.xml | 1 - app/src/main/res/values-hu/strings.xml | 1 - app/src/main/res/values-in/strings.xml | 1 - app/src/main/res/values-is/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-ja/strings.xml | 1 - app/src/main/res/values-kab/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 1 - app/src/main/res/values-lv/strings.xml | 3 +- app/src/main/res/values-ml/strings.xml | 1 - app/src/main/res/values-nb-rNO/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-oc/strings.xml | 1 - app/src/main/res/values-pl/strings.xml | 3 +- app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-pt-rPT/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sa/strings.xml | 1 - app/src/main/res/values-si/strings.xml | 1 - app/src/main/res/values-sk/strings.xml | 1 - app/src/main/res/values-sl/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-th/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values-vi/strings.xml | 1 - app/src/main/res/values-zh-rCN/strings.xml | 1 - app/src/main/res/values-zh-rHK/strings.xml | 1 - app/src/main/res/values-zh-rMO/strings.xml | 1 - app/src/main/res/values-zh-rSG/strings.xml | 1 - app/src/main/res/values-zh-rTW/strings.xml | 3 +- app/src/main/res/values/strings.xml | 1 - .../ArrayAdapterWithCopyButton.kt | 3 +- ...PachliRecyclerViewAccessibilityDelegate.kt | 115 ++++++++++++++ core/ui/src/main/res/values-ar/strings.xml | 1 + core/ui/src/main/res/values-be/strings.xml | 1 + core/ui/src/main/res/values-bg/strings.xml | 1 + .../ui/src/main/res/values-bn-rBD/strings.xml | 1 + .../ui/src/main/res/values-bn-rIN/strings.xml | 1 + core/ui/src/main/res/values-ca/strings.xml | 1 + core/ui/src/main/res/values-ckb/strings.xml | 1 + core/ui/src/main/res/values-cs/strings.xml | 1 + core/ui/src/main/res/values-cy/strings.xml | 1 + core/ui/src/main/res/values-de/strings.xml | 1 + core/ui/src/main/res/values-eo/strings.xml | 1 + core/ui/src/main/res/values-es/strings.xml | 1 + core/ui/src/main/res/values-eu/strings.xml | 1 + core/ui/src/main/res/values-fa/strings.xml | 1 + core/ui/src/main/res/values-fi/strings.xml | 1 + core/ui/src/main/res/values-fr/strings.xml | 1 + core/ui/src/main/res/values-ga/strings.xml | 1 + core/ui/src/main/res/values-gd/strings.xml | 1 + core/ui/src/main/res/values-gl/strings.xml | 1 + core/ui/src/main/res/values-hi/strings.xml | 1 + core/ui/src/main/res/values-hu/strings.xml | 1 + core/ui/src/main/res/values-in/strings.xml | 1 + core/ui/src/main/res/values-is/strings.xml | 1 + core/ui/src/main/res/values-it/strings.xml | 1 + core/ui/src/main/res/values-ja/strings.xml | 1 + core/ui/src/main/res/values-kab/strings.xml | 1 + core/ui/src/main/res/values-ko/strings.xml | 1 + core/ui/src/main/res/values-lv/strings.xml | 1 + core/ui/src/main/res/values-ml/strings.xml | 1 + .../ui/src/main/res/values-nb-rNO/strings.xml | 1 + core/ui/src/main/res/values-nl/strings.xml | 1 + core/ui/src/main/res/values-oc/strings.xml | 1 + core/ui/src/main/res/values-pl/strings.xml | 1 + .../ui/src/main/res/values-pt-rBR/strings.xml | 1 + .../ui/src/main/res/values-pt-rPT/strings.xml | 1 + core/ui/src/main/res/values-ru/strings.xml | 1 + core/ui/src/main/res/values-sa/strings.xml | 1 + core/ui/src/main/res/values-si/strings.xml | 1 + core/ui/src/main/res/values-sk/strings.xml | 1 + core/ui/src/main/res/values-sl/strings.xml | 1 + core/ui/src/main/res/values-sv/strings.xml | 1 + core/ui/src/main/res/values-th/strings.xml | 1 + core/ui/src/main/res/values-tr/strings.xml | 1 + core/ui/src/main/res/values-uk/strings.xml | 1 + core/ui/src/main/res/values-vi/strings.xml | 1 + .../ui/src/main/res/values-zh-rCN/strings.xml | 1 + .../ui/src/main/res/values-zh-rHK/strings.xml | 3 +- .../ui/src/main/res/values-zh-rMO/strings.xml | 3 +- .../ui/src/main/res/values-zh-rSG/strings.xml | 1 + .../ui/src/main/res/values-zh-rTW/strings.xml | 3 +- core/ui/src/main/res/values/actions.xml | 4 + core/ui/src/main/res/values/strings.xml | 1 + .../SuggestionAccessibilityDelegate.kt | 131 ++++++---------- 108 files changed, 283 insertions(+), 275 deletions(-) rename core/ui/src/main/kotlin/app/pachli/core/ui/{ => accessibility}/ArrayAdapterWithCopyButton.kt (97%) create mode 100644 core/ui/src/main/kotlin/app/pachli/core/ui/accessibility/PachliRecyclerViewAccessibilityDelegate.kt diff --git a/app/src/main/java/app/pachli/components/trending/TrendingLinksAccessibilityDelegate.kt b/app/src/main/java/app/pachli/components/trending/TrendingLinksAccessibilityDelegate.kt index e3442d406..f480f75bb 100644 --- a/app/src/main/java/app/pachli/components/trending/TrendingLinksAccessibilityDelegate.kt +++ b/app/src/main/java/app/pachli/components/trending/TrendingLinksAccessibilityDelegate.kt @@ -17,16 +17,19 @@ package app.pachli.components.trending -import android.content.Context +import android.content.ClipData +import android.content.ClipboardManager +import android.os.Build import android.os.Bundle import android.view.View -import android.view.accessibility.AccessibilityManager +import android.widget.Toast +import androidx.core.content.ContextCompat import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate import app.pachli.R +import app.pachli.core.ui.accessibility.PachliRecyclerViewAccessibilityDelegate import app.pachli.view.PreviewCardView import app.pachli.view.PreviewCardView.Target @@ -40,17 +43,17 @@ import app.pachli.view.PreviewCardView.Target internal class TrendingLinksAccessibilityDelegate( private val recyclerView: RecyclerView, val listener: PreviewCardView.OnClickListener, -) : RecyclerViewAccessibilityDelegate(recyclerView) { - private val context = recyclerView.context - - private val a11yManager = context.getSystemService(Context.ACCESSIBILITY_SERVICE) - as AccessibilityManager - +) : PachliRecyclerViewAccessibilityDelegate(recyclerView) { private val openLinkAction = AccessibilityActionCompat( app.pachli.core.ui.R.id.action_open_link, context.getString(R.string.action_open_link), ) + private val copyLinkAction = AccessibilityActionCompat( + app.pachli.core.ui.R.id.action_copy_item, + context.getString(R.string.action_copy_link), + ) + private val openBylineAccountAction = AccessibilityActionCompat( app.pachli.core.ui.R.id.action_open_byline_account, context.getString(R.string.action_open_byline_account), @@ -64,6 +67,7 @@ internal class TrendingLinksAccessibilityDelegate( as TrendingLinkViewHolder info.addAction(openLinkAction) + info.addAction(copyLinkAction) viewHolder.link.authors?.firstOrNull()?.account?.let { info.addAction(openBylineAccountAction) @@ -80,6 +84,22 @@ internal class TrendingLinksAccessibilityDelegate( listener.onClick(viewHolder.link, Target.CARD) true } + app.pachli.core.ui.R.id.action_copy_item -> { + val clipboard = ContextCompat.getSystemService( + context, + ClipboardManager::class.java, + ) as ClipboardManager + val clip = ClipData.newPlainText("", viewHolder.link.url) + clipboard.setPrimaryClip(clip) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) { + Toast.makeText( + context, + context.getString(app.pachli.core.ui.R.string.item_copied), + Toast.LENGTH_SHORT, + ).show() + } + true + } app.pachli.core.ui.R.id.action_open_byline_account -> { interrupt() listener.onClick(viewHolder.link, Target.BYLINE) @@ -90,7 +110,5 @@ internal class TrendingLinksAccessibilityDelegate( } } - private fun interrupt() = a11yManager.interrupt() - override fun getItemDelegate(): AccessibilityDelegateCompat = delegate } diff --git a/app/src/main/java/app/pachli/util/ListStatusAccessibilityDelegate.kt b/app/src/main/java/app/pachli/util/ListStatusAccessibilityDelegate.kt index b6a8ffb39..eb0bc952b 100644 --- a/app/src/main/java/app/pachli/util/ListStatusAccessibilityDelegate.kt +++ b/app/src/main/java/app/pachli/util/ListStatusAccessibilityDelegate.kt @@ -1,24 +1,17 @@ package app.pachli.util -import android.content.Context import android.os.Bundle -import android.text.Spannable -import android.text.style.URLSpan import android.view.View -import android.view.accessibility.AccessibilityEvent -import android.view.accessibility.AccessibilityManager -import androidx.appcompat.app.AlertDialog import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate import app.pachli.R import app.pachli.adapter.FilterableStatusViewHolder import app.pachli.adapter.StatusBaseViewHolder import app.pachli.core.activity.openLink import app.pachli.core.network.model.Status.Companion.MAX_MEDIA_ATTACHMENTS -import app.pachli.core.ui.ArrayAdapterWithCopyButton +import app.pachli.core.ui.accessibility.PachliRecyclerViewAccessibilityDelegate import app.pachli.interfaces.StatusActionListener import app.pachli.viewdata.IStatusViewData import app.pachli.viewdata.NotificationViewData @@ -34,14 +27,9 @@ class ListStatusAccessibilityDelegate( private val recyclerView: RecyclerView, private val statusActionListener: StatusActionListener, private val statusProvider: StatusProvider, -) : RecyclerViewAccessibilityDelegate(recyclerView) { - private val a11yManager = context.getSystemService(Context.ACCESSIBILITY_SERVICE) - as AccessibilityManager - +) : PachliRecyclerViewAccessibilityDelegate(recyclerView) { override fun getItemDelegate(): AccessibilityDelegateCompat = itemDelegate - private val context: Context get() = recyclerView.context - private val itemDelegate = object : ItemDelegate(this) { override fun onInitializeAccessibilityNodeInfo( host: View, @@ -96,12 +84,12 @@ class ListStatusAccessibilityDelegate( } info.addAction(openProfileAction) - if (getLinks(status).any()) info.addAction(linksAction) + if (status.content.getLinks().any()) info.addAction(linksAction) val mentions = actionable.mentions if (mentions.isNotEmpty()) info.addAction(mentionsAction) - if (getHashtags(status).any()) info.addAction(hashtagsAction) + if (status.content.getHashtags().any()) info.addAction(hashtagsAction) if (!status.status.reblog?.account?.username.isNullOrEmpty()) { info.addAction(openRebloggerAction) } @@ -167,9 +155,31 @@ class ListStatusAccessibilityDelegate( statusActionListener.onExpandedChange(pachliAccountId, status, false) interrupt() } - app.pachli.core.ui.R.id.action_links -> showLinksDialog(host) - app.pachli.core.ui.R.id.action_mentions -> showMentionsDialog(host) - app.pachli.core.ui.R.id.action_hashtags -> showHashtagsDialog(host) + + app.pachli.core.ui.R.id.action_links -> { + val links = status.content.getLinks() + showA11yDialogWithCopyButton( + app.pachli.core.ui.R.string.title_links_dialog, + links.map { it.url }, + ) { context.openLink(links[it].url) } + } + + app.pachli.core.ui.R.id.action_mentions -> { + val mentions = status.actionable.mentions + showA11yDialogWithCopyButton( + app.pachli.core.ui.R.string.title_mentions_dialog, + mentions.map { "@${it.username}" }, + ) { statusActionListener.onViewAccount(mentions[it].id) } + } + + app.pachli.core.ui.R.id.action_hashtags -> { + val hashtags = status.content.getHashtags() + showA11yDialogWithCopyButton( + app.pachli.core.ui.R.string.title_hashtags_dialog, + hashtags.map { "#$it" }, + ) { statusActionListener.onViewTag(hashtags[it].toString()) } + } + app.pachli.core.ui.R.id.action_open_reblogger -> { interrupt() statusActionListener.onOpenReblog(status.status) @@ -204,108 +214,11 @@ class ListStatusAccessibilityDelegate( return true } - private fun showLinksDialog(host: View) { - val status = getStatus(host) as? IStatusViewData ?: return - val links = getLinks(status).toList() - val textLinks = links.map { item -> item.link } - AlertDialog.Builder(host.context) - .setTitle(app.pachli.core.ui.R.string.title_links_dialog) - .setAdapter( - ArrayAdapterWithCopyButton( - host.context, - textLinks, - ) { position -> host.context.openLink(links[position].link) }, - null, - ) - .show() - .let { forceFocus(it.listView) } - } - - private fun showMentionsDialog(host: View) { - val status = getStatus(host) as? IStatusViewData ?: return - val mentions = status.actionable.mentions - - // Ensure mentions have the leading "@" to make them more useful when - // copied. - val stringMentions = mentions.map { "@${it.username}" } - AlertDialog.Builder(host.context) - .setTitle(R.string.title_mentions_dialog) - .setAdapter( - ArrayAdapterWithCopyButton( - host.context, - stringMentions, - ) { position -> - statusActionListener.onViewAccount(mentions[position].id) - }, - null, - ) - .show() - .let { forceFocus(it.listView) } - } - - private fun showHashtagsDialog(host: View) { - val status = getStatus(host) as? IStatusViewData ?: return - val tags = getHashtags(status) - AlertDialog.Builder(host.context) - .setTitle(app.pachli.core.ui.R.string.title_hashtags_dialog) - .setAdapter( - ArrayAdapterWithCopyButton( - host.context, - tags, - ) { position -> - statusActionListener.onViewTag(tags[position].toString()) - }, - null, - ) - .show() - .let { forceFocus(it.listView) } - } - private fun getStatus(childView: View): T { return statusProvider.getStatus(recyclerView.getChildAdapterPosition(childView))!! } } - private fun getLinks(status: IStatusViewData): Sequence { - val content = status.content - return if (content is Spannable) { - content.getSpans(0, content.length, URLSpan::class.java) - .asSequence() - .map { span -> - val text = content.subSequence( - content.getSpanStart(span), - content.getSpanEnd(span), - ) - if (isHashtag(text)) null else LinkSpanInfo(text.toString(), span.url) - } - .filterNotNull() - } else { - emptySequence() - } - } - - private fun getHashtags(status: IStatusViewData): List { - val content = status.content - return content.getSpans(0, content.length, Object::class.java) - .map { span -> - content.subSequence(content.getSpanStart(span), content.getSpanEnd(span)).toString() - } - .filter(this::isHashtag) - } - - private fun forceFocus(host: View) { - interrupt() - host.post { - host.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) - } - } - - private fun interrupt() { - a11yManager.interrupt() - } - - private fun isHashtag(text: CharSequence) = text.startsWith("#") - private val collapseCwAction = AccessibilityActionCompat( app.pachli.core.ui.R.id.action_collapse_cw, context.getString(R.string.post_content_warning_show_less), @@ -405,6 +318,4 @@ class ListStatusAccessibilityDelegate( app.pachli.core.ui.R.id.action_edit_filter, context.getString(R.string.filter_edit_title), ) - - private data class LinkSpanInfo(val text: String, val link: String) } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 92d968412..2717b9ae6 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -91,7 +91,6 @@ إضافة لسان اعرض المشاركات اعرض المفضلات - الإشارات تنزيل %1$s إنسخ الرابط شاركه كـ… diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 5dfdfc45a..23253673e 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -81,7 +81,6 @@ Адкрыць аўтара пашырэння Паказаць пашырэнні Паказаць абраныя - Згадкі Адкрыць медыя #%d дадаць рэакцыю Спампоўка %1$s diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index fba248c92..503ce0fca 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -241,7 +241,6 @@ Копиране на връзката Изтегляне на %1$s Отваряне на мултимедия #%d - Споменавания Показване на любими Показване на споделяния Отваряне на споделилия автор diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index 5e192722a..80d153720 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -164,7 +164,6 @@ লিঙ্ক অনুলিপি করুন \'%1$s ডাউনলোড হচ্ছে\' মিডিয়া খুলুন #%d - উল্লেখসমূহ প্রিয়গুলি দেখান সমর্থন দেখান সমর্থক লেখক খুলুন diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml index 6b46de3eb..6804dd027 100644 --- a/app/src/main/res/values-bn-rIN/strings.xml +++ b/app/src/main/res/values-bn-rIN/strings.xml @@ -93,7 +93,6 @@ সমর্থক লেখক খুলুন সমর্থন দেখান প্রিয়গুলি দেখান - উল্লেখসমূহ মিডিয়া খুলুন #%d %1$s ডাউনলোড হচ্ছে লিঙ্ক অনুলিপি করুন diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index d52089a4a..29fd33378 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -176,7 +176,6 @@ Contingut sensible Afegir una pestanya Mostra els favorits - Mencions Comparteix com a… Baixa el fitxer Compartir la imatge a … @@ -525,4 +524,4 @@ Perfils Mostra de totes maneres El contacte amb el teu servidor ha trigat massa - \ No newline at end of file + diff --git a/app/src/main/res/values-ckb/strings.xml b/app/src/main/res/values-ckb/strings.xml index 7a3e79c17..487a10484 100644 --- a/app/src/main/res/values-ckb/strings.xml +++ b/app/src/main/res/values-ckb/strings.xml @@ -16,7 +16,6 @@ بەستەرەکە ڕوونوس بکە داگرتنی %1$s کردنەوەی میدیا #%d - ئاماژەکان پیشاندانی دڵخوازەکان پیشاندانی بەهێزکردنەکان پۆستکەرەوەکە ببینە diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index ab7c829aa..06e791e52 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -92,7 +92,6 @@ Otevřít autora boostu Zobrazit boosty Zobrazit oblíbení - Zmínky Otevřít médium #%d Stahuji %1$s Zkopírovat odkaz @@ -480,4 +479,4 @@ Smazat tuto konverzaci\? Požádáno o sledování Animovat vlastní emotikony - \ No newline at end of file + diff --git a/app/src/main/res/values-cy/strings.xml b/app/src/main/res/values-cy/strings.xml index 46eb2d318..4c63a572f 100644 --- a/app/src/main/res/values-cy/strings.xml +++ b/app/src/main/res/values-cy/strings.xml @@ -305,7 +305,6 @@ Methu golygu\'r ddelwedd. Hoffwyd Yn cadw drafft… - Crybwylliadau Agor cyfryngau #%d Rhannu fel … Yn llwytho cyfryngau diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 8a4f9fb1b..6caddc3e7 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -92,7 +92,6 @@ Tab hinzufügen Geteilte Beiträge anzeigen Favoriten anzeigen - Erwähnungen Datei #%d öffnen %1$s heruntergeladen Link kopieren diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index 55d7e8bd8..0234bed4b 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -92,7 +92,6 @@ Montri la aŭtoron de la diskonigo Montri diskonigojn Montri stelumojn - Mencioj Malfermi aŭdovidaĵon #%d Elŝutado de %1$s Kopii la ligilon diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index ee697181c..d6d670bb1 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -259,7 +259,6 @@ %1$s y %2$s %1$s, %2$s y %3$d más Mostrar favoritos - Menciones Descargar multimedia Idioma Dejar de impulsar diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index 5717d7b4d..c891bf09f 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -249,7 +249,6 @@ Kategoria gehitu Bultzadak erakutsi Gogokoak erakutsi - Aipamenak Ireki media #%d … bezala partekatu Media jaisten diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 7ed48dbe9..1c22ffecc 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -243,7 +243,6 @@ گشودن تقویت‌کنندهٔ بوق نمایش تقویت‌ها نمایش برگزیده‌ها - اشاره‌ها گشودن رسانه #%d هم‌رسانی به عنوان … بارگیری رسانه diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 3505de862..adb56270e 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -102,7 +102,6 @@ Vastaa… Hae… Kuvaus - Maininnat Nollaa Luonnokset Hae diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index ef8b8ed32..b8e16d9cd 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -92,7 +92,6 @@ Afficher l’auteur·rice du partage Afficher les partages Montrer les favoris - Mentions Ouvrir le média #%d Téléchargement de %1$s Copier le lien diff --git a/app/src/main/res/values-ga/strings.xml b/app/src/main/res/values-ga/strings.xml index a201a8ea9..33d2377b6 100644 --- a/app/src/main/res/values-ga/strings.xml +++ b/app/src/main/res/values-ga/strings.xml @@ -205,7 +205,6 @@ Taispeáin táscaire do róbónna Teanga Abhatár - Tráchtanna Athchraol Cealaigh athchraoladh Freagra diff --git a/app/src/main/res/values-gd/strings.xml b/app/src/main/res/values-gd/strings.xml index 40402edc2..611cea355 100644 --- a/app/src/main/res/values-gd/strings.xml +++ b/app/src/main/res/values-gd/strings.xml @@ -369,7 +369,6 @@ Dèan lethbhreac dhen cheangal A’ luchdadh a-nuas %1$s Fosgail meadhan #%d - Iomraidhean Seall na h-annsachdan Fosgail ùghdar a’ bhrosnachaidh Cuir taba ris diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index c8afd6248..3bf07f699 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -412,7 +412,6 @@ Copiar ligazón Descargando %1$s Abrir multimedia #%d - Mencións Mostrar favoritos Mostrar promocións Abrir autor da promoción diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 136af3953..7ac2aa109 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -107,7 +107,6 @@ मीडिया डाउनलोड करें लिंक कॉपी करें मीडिया खोलें #%d - ज़िक्र पसंदीदा दिखाएँ ऐड टैब अनुसूची टूट diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index e9abd7f87..6d81fca31 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -88,7 +88,6 @@ Emoji billentyűzet Fül hozzáadása Kedvencek megjelenítése - Említések %1$s letöltése Link másolása Megosztás mint … diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 4ef94cd85..d2a95f737 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -240,7 +240,6 @@ TOOT! Terjemah Batalkan terjemahan - Menyebutkan Bagikan URL akun ke… Bagikan nama pengguna akun ke… Gambar diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index ff30cf9c9..22845d771 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -105,7 +105,6 @@ Opna höfund endurbirtingar Sýna endurbirtingar Birta eftirlæti - Tilvísanir Opna myndefni #%d Sæki %1$s Afrita tengilinn diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index a13f9b01a..cd88914a4 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -98,7 +98,6 @@ Vai all\'autore della condivisione Mostra condivisioni Mostra preferiti - Menzioni Apri media #%d Scaricando %1$s Copia collegamento diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index af22a1363..a57d50bde 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -291,7 +291,6 @@ 投票の集計が完了したときの通知 スレッド 投票 - 返信 この投稿を削除し、下書きに戻しますか? 削除 更新 diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index ce401d692..a146f8d5e 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -177,7 +177,6 @@ Ig ṭṭafar Imeḍfaṛen Imeḍfaṛen - Tibdarin Yettwaceyyeɛ! Yettwaceyyaɛ! Ula d yiwen n ugmuḍ diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 9ce0ada50..6cef8621d 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -96,7 +96,6 @@ 부스트한 유저의 프로필로 이동 부스트 보이기 좋아요한 유저 보이기 - 멘션 미디어 #%d 열기 %1$s 다운로드 중 링크 복사 diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 4df840676..0179a97d3 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -64,7 +64,6 @@ Pievienot cilni Atiestatīt Lejupielādē %1$s - Pieminējumi Nosūtīts! Nokopēt saiti Lietotājs atbloķēts @@ -509,4 +508,4 @@ Paslēpt ar brīdinājumu Labot atslēgvārdu Pievienot atslēgvārdu - \ No newline at end of file + diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index b15e8b0e9..aff964b8a 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -109,7 +109,6 @@ ഫോട്ടോ എടുക്കുക തിരയുക… ചിത്രങ്ങൾ - സൂചനകൾ ബയോ %1$s സംഭാഷണങ്ങൾ diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 11aa17cef..8ac639cdb 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -92,7 +92,6 @@ Åpne delerens profil Vis delinger Vis favoritter - Nevnelser Åpne media #%d Laster ned %1$s Kopier lenken diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index d88814fc0..ac086bc41 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -92,7 +92,6 @@ Auteur van deze boost openen Boosts tonen Favorieten tonen - Vermeldingen Media #%d openen %1$s aan het downloaden Link kopiëren diff --git a/app/src/main/res/values-oc/strings.xml b/app/src/main/res/values-oc/strings.xml index cf787dbfb..622537c56 100644 --- a/app/src/main/res/values-oc/strings.xml +++ b/app/src/main/res/values-oc/strings.xml @@ -231,7 +231,6 @@ Dobrir l’autor del partatge Mostrar los retuts Mostrar los favorits - Mencions Dobrir lo mèdia #%d Partejar coma… Telecargar lo mèdia diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index e372cbe49..8e00c8ca6 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -228,7 +228,6 @@ Usuń i przeredaguj Ustawienia konta Pokaż ulubione - Wzmianki Udostępnij jako … Zakładki Ukryte domeny @@ -575,4 +574,4 @@ Edytuj słowo kluczowe Obraz Dodaj - \ No newline at end of file + diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index d764d5228..69ba5cc9e 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -87,7 +87,6 @@ Adicionar aba Mostrar Boosts Mostrar favoritos - Menções Baixando %1$s Copiar URL Compartilhar como… diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index f7f509555..5ba8cea14 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -128,7 +128,6 @@ Ver autor do boost Mostrar boosts Mostrar favoritos - Menções Abrir conteúdo multimédia #%d A descarregar %1$s Copiar a hiperligação diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 5b68314e0..3b9bb3512 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -93,7 +93,6 @@ Перейти к автору Показывать продвижения Показать избранное - Упоминания Открыть медиафайл #%d Загрузка %1$s Копировать ссылку diff --git a/app/src/main/res/values-sa/strings.xml b/app/src/main/res/values-sa/strings.xml index 3615618c5..cf99f3267 100644 --- a/app/src/main/res/values-sa/strings.xml +++ b/app/src/main/res/values-sa/strings.xml @@ -94,7 +94,6 @@ जालस्थलं प्रतिलिख्यताम् अवारोप्यमाणम् %1$s उद्घाट्यताम् #%d - उल्लेखाः प्रियाणि दृश्यन्ताम् प्रकाशनानि दृश्यन्ताम् प्रकाशनलेखकः उद्घाट्यताम् diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml index f8b15ca0a..df914a428 100644 --- a/app/src/main/res/values-si/strings.xml +++ b/app/src/main/res/values-si/strings.xml @@ -99,7 +99,6 @@ මාධ්‍ය බාගත වෙමින් මාධ්‍ය පෙරදසුන් බාගන්න බාගන්න - සඳැහුම් පිළිතුර දැනුම්දීම් පරිශීලක අනවහිර කෙරිණි diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index a35416e8e..1c8370013 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -37,7 +37,6 @@ Vymazať a prepísať Obnoviť Zobraziť obľúbené - Zmienky Otvoriť médium #%d Sťahovanie %1$s Kopírovať odkaz diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 283e48030..8818f8fbd 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -89,7 +89,6 @@ Odpri spodbujenega avtorja Prikaži spodbude Prikaži priljubljene - Omembe Odpri medij #%d Prejemanje %1$s Kopiraj povezavo diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 8942bd951..da9fa565a 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -92,7 +92,6 @@ Öppna knuff författare Visa knuffar Visa favoriter - Omnämnanden Öppna media #%d Laddar ned %1$s Kopiera länk diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 0c00db5d1..80054c552 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -254,7 +254,6 @@ คัดลอกลิงก์ กำลังดาวน์โหลด %1$s เปิดสื่อ #%d - โต้ตอบ ดูชื่นชอบ ดูบสต์ ดูต้นตอบูสต์ diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index a5d659f69..2741056a5 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -329,7 +329,6 @@ Hesap başka bir sunucudan. Raporun anonim bir kopyasını da oraya gönderilsin mi\? Gönderi yazanını aç Yeniden paylaşımları göster - Bahsedenler #%d medyayı aç Yer imleri Zamanlanmış yayınlar diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 1474eb358..08a64e848 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -38,7 +38,6 @@ Поділитися як … Копіювати посилання Завантаження %1$s - Згадки Показати, хто вподобав Попередження про вміст Заплановані дописи diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 66d9fc518..624841fc7 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -72,7 +72,6 @@ Chép URL Đang tải %1$s Mở tập tin #%d - Lượt nhắc tới Xem lượt thích Xem lượt đăng lại Xem lượt đăng lại diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index c91628b9d..0698516bf 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -93,7 +93,6 @@ 打开转嘟用户主页 显示转嘟 显示喜欢 - 提及 打开媒体文件 #%d 下载中 %1$s 复制链接 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index c126b6a6d..ad90a3433 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -93,7 +93,6 @@ 打開轉嘟用戶主頁 顯示轉嘟 顯示最愛 - 提及 打開媒體 #%d 正在下載 %1$s 複製連結 diff --git a/app/src/main/res/values-zh-rMO/strings.xml b/app/src/main/res/values-zh-rMO/strings.xml index ceb50f35c..7d7ab0d89 100644 --- a/app/src/main/res/values-zh-rMO/strings.xml +++ b/app/src/main/res/values-zh-rMO/strings.xml @@ -93,7 +93,6 @@ 打開轉嘟用戶主頁 顯示轉嘟 顯示收藏 - 提及 打開媒體 #%d 正在下載 %1$s 複製連結 diff --git a/app/src/main/res/values-zh-rSG/strings.xml b/app/src/main/res/values-zh-rSG/strings.xml index 8667667a1..12356aead 100644 --- a/app/src/main/res/values-zh-rSG/strings.xml +++ b/app/src/main/res/values-zh-rSG/strings.xml @@ -93,7 +93,6 @@ 打开转嘟用户主页 显示转嘟 显示喜欢 - 提及 打开媒体文件 #%d 正在下载 %1$s… 复制链接 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 67401b2fe..297a27543 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -93,7 +93,6 @@ 打開轉嘟用戶主頁 顯示轉嘟 顯示最愛 - 提及 打開媒體 #%d 正在下載 %1$s 複製連結 @@ -473,4 +472,4 @@ %s 已註冊 %s 編輯了他們的嘟文 這張圖片不能編輯。 - \ 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 71f93f3c2..ea48ac4e2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -186,7 +186,6 @@ Suggested accounts Translate Undo translate - Mentions Open media #%d Downloading %1$s Copy the link diff --git a/core/ui/src/main/kotlin/app/pachli/core/ui/ArrayAdapterWithCopyButton.kt b/core/ui/src/main/kotlin/app/pachli/core/ui/accessibility/ArrayAdapterWithCopyButton.kt similarity index 97% rename from core/ui/src/main/kotlin/app/pachli/core/ui/ArrayAdapterWithCopyButton.kt rename to core/ui/src/main/kotlin/app/pachli/core/ui/accessibility/ArrayAdapterWithCopyButton.kt index ae113b788..d88e94fa0 100644 --- a/core/ui/src/main/kotlin/app/pachli/core/ui/ArrayAdapterWithCopyButton.kt +++ b/core/ui/src/main/kotlin/app/pachli/core/ui/accessibility/ArrayAdapterWithCopyButton.kt @@ -15,7 +15,7 @@ * see . */ -package app.pachli.core.ui +package app.pachli.core.ui.accessibility import android.content.ClipData import android.content.ClipboardManager @@ -27,6 +27,7 @@ import android.view.ViewGroup import android.widget.ArrayAdapter import android.widget.Toast import androidx.core.content.ContextCompat +import app.pachli.core.ui.R import app.pachli.core.ui.databinding.SimpleListItem1CopyButtonBinding /** diff --git a/core/ui/src/main/kotlin/app/pachli/core/ui/accessibility/PachliRecyclerViewAccessibilityDelegate.kt b/core/ui/src/main/kotlin/app/pachli/core/ui/accessibility/PachliRecyclerViewAccessibilityDelegate.kt new file mode 100644 index 000000000..afae1d203 --- /dev/null +++ b/core/ui/src/main/kotlin/app/pachli/core/ui/accessibility/PachliRecyclerViewAccessibilityDelegate.kt @@ -0,0 +1,115 @@ +/* + * Copyright 2024 Pachli Association + * + * This file is a part of Pachli. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Pachli 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 Pachli; if not, + * see . + */ + +package app.pachli.core.ui.accessibility + +import android.content.Context +import android.text.Spannable +import android.text.Spanned +import android.text.style.CharacterStyle +import android.text.style.URLSpan +import android.view.View +import android.view.accessibility.AccessibilityEvent +import android.view.accessibility.AccessibilityManager +import androidx.annotation.StringRes +import androidx.appcompat.app.AlertDialog +import androidx.core.text.getSpans +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate + +/** Base class for Pachli-specific [RecyclerViewAccessibilityDelegate]s. */ +abstract class PachliRecyclerViewAccessibilityDelegate( + recyclerView: RecyclerView, +) : RecyclerViewAccessibilityDelegate(recyclerView) { + protected val context: Context = recyclerView.context + + private val a11yManager = context.getSystemService(Context.ACCESSIBILITY_SERVICE) + as AccessibilityManager + + /** + * Shows a dialog with [title] displaying a list of [items]. + * + * Each row in the list shows the item and a "Copy" button to make it easier + * for assistive technologies to copy the item. + * + * Focus is set to the list after showing the dialog. + * + * @param title String resource to use as the dialog's title. + * @param items Items to show in the dialog. + * @param listener Callback, called with the position of the clicked item. + */ + fun showA11yDialogWithCopyButton(@StringRes title: Int, items: List, listener: ArrayAdapterWithCopyButton.OnClickListener) { + AlertDialog.Builder(context) + .setTitle(title) + .setAdapter(ArrayAdapterWithCopyButton(context, items, listener), null) + .show() + .let { forceFocus(it.listView) } + } + + /** Interrupts the accessibility service and sets focus to [view]. */ + protected fun forceFocus(view: View) { + interrupt() + view.post { + view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) + } + } + + /** Requests feedback interruption from all accessibility services. */ + protected fun interrupt() = a11yManager.interrupt() + + companion object { + /** @return The text enclosed by [span]. */ + @JvmStatic + protected fun Spanned.subSequence(span: CharacterStyle) = + subSequence(getSpanStart(span), getSpanEnd(span)) + + /** @return Links, excluding any links that are hashtags or @-mentions. */ + @JvmStatic + protected fun Spanned.getLinks(): List { + if (this !is Spannable) return emptyList() + + return getSpans(0, length) + .mapNotNull { span -> + val text = subSequence(span) + if (text.isHashtag() || text.isMention()) null else span + } + } + + /** @return The text of the linked hashtags (without the leading '#'). */ + @JvmStatic + protected fun Spanned.getHashtags(): List = getSpans(0, length) + .map { span -> subSequence(span).toString() } + .filter { it.isHashtag() } + .map { it.removePrefix("\u2068").removePrefix("#") } + + /** + * @return True if this is a hashtag (starts with `#` or `#` preceded by + * the directional isolate added by [StringUtils.unicodeWrap]). + */ + @JvmStatic + protected fun CharSequence.isHashtag() = startsWith("#") || + startsWith("\u2068#") + + /** + * @return True if this is a mention (starts with `@` or `@` preceded by + * the directional isolate added by [StringUtils.unicodeWrap]). + */ + @JvmStatic + protected fun CharSequence.isMention() = startsWith("@") || + startsWith("\u2068@") + } +} diff --git a/core/ui/src/main/res/values-ar/strings.xml b/core/ui/src/main/res/values-ar/strings.xml index a5801a674..c174a7307 100644 --- a/core/ui/src/main/res/values-ar/strings.xml +++ b/core/ui/src/main/res/values-ar/strings.xml @@ -14,4 +14,5 @@ الوسوم الروابط الوسوم + الإشارات diff --git a/core/ui/src/main/res/values-be/strings.xml b/core/ui/src/main/res/values-be/strings.xml index b2739fc3b..13e5421cc 100644 --- a/core/ui/src/main/res/values-be/strings.xml +++ b/core/ui/src/main/res/values-be/strings.xml @@ -14,4 +14,5 @@ Хэштэгі Спасылкі Хэштэгі + Згадкі diff --git a/core/ui/src/main/res/values-bg/strings.xml b/core/ui/src/main/res/values-bg/strings.xml index 7997412b7..e9af1d9a6 100644 --- a/core/ui/src/main/res/values-bg/strings.xml +++ b/core/ui/src/main/res/values-bg/strings.xml @@ -12,4 +12,5 @@ Хаштагове Връзки Хаштагове + Споменавания diff --git a/core/ui/src/main/res/values-bn-rBD/strings.xml b/core/ui/src/main/res/values-bn-rBD/strings.xml index 01706bd3c..74b8ad7aa 100644 --- a/core/ui/src/main/res/values-bn-rBD/strings.xml +++ b/core/ui/src/main/res/values-bn-rBD/strings.xml @@ -12,4 +12,5 @@ হ্যাশট্যাগ লিংকসমূহ হ্যাশট্যাগ + উল্লেখসমূহ diff --git a/core/ui/src/main/res/values-bn-rIN/strings.xml b/core/ui/src/main/res/values-bn-rIN/strings.xml index 09f93dea4..694f187ae 100644 --- a/core/ui/src/main/res/values-bn-rIN/strings.xml +++ b/core/ui/src/main/res/values-bn-rIN/strings.xml @@ -12,4 +12,5 @@ হ্যাশট্যাগ লিংকসমূহ হ্যাশট্যাগ + উল্লেখসমূহ diff --git a/core/ui/src/main/res/values-ca/strings.xml b/core/ui/src/main/res/values-ca/strings.xml index 443fd0c89..913e28264 100644 --- a/core/ui/src/main/res/values-ca/strings.xml +++ b/core/ui/src/main/res/values-ca/strings.xml @@ -14,4 +14,5 @@ Hashtags Enllaç Hashtags + Mencions diff --git a/core/ui/src/main/res/values-ckb/strings.xml b/core/ui/src/main/res/values-ckb/strings.xml index 95cbe165b..11b5062f0 100644 --- a/core/ui/src/main/res/values-ckb/strings.xml +++ b/core/ui/src/main/res/values-ckb/strings.xml @@ -12,4 +12,5 @@ هاشتاگ بەستەرەکان هاشتاگی + ئاماژەکان diff --git a/core/ui/src/main/res/values-cs/strings.xml b/core/ui/src/main/res/values-cs/strings.xml index 902c0b2e1..0331240e7 100644 --- a/core/ui/src/main/res/values-cs/strings.xml +++ b/core/ui/src/main/res/values-cs/strings.xml @@ -13,4 +13,5 @@ Hashtagy Odkazy Hashtagy + Zmínky diff --git a/core/ui/src/main/res/values-cy/strings.xml b/core/ui/src/main/res/values-cy/strings.xml index 8cfb3043e..4f955c384 100644 --- a/core/ui/src/main/res/values-cy/strings.xml +++ b/core/ui/src/main/res/values-cy/strings.xml @@ -14,4 +14,5 @@ Hashnodau Dolenni Hashnodau + Crybwylliadau diff --git a/core/ui/src/main/res/values-de/strings.xml b/core/ui/src/main/res/values-de/strings.xml index 6cb3f1aa3..9016d1c87 100644 --- a/core/ui/src/main/res/values-de/strings.xml +++ b/core/ui/src/main/res/values-de/strings.xml @@ -14,4 +14,5 @@ Hashtags Links Hashtags + Erwähnungen diff --git a/core/ui/src/main/res/values-eo/strings.xml b/core/ui/src/main/res/values-eo/strings.xml index c6316302f..6bef006e0 100644 --- a/core/ui/src/main/res/values-eo/strings.xml +++ b/core/ui/src/main/res/values-eo/strings.xml @@ -13,4 +13,5 @@ Kradvortoj Ligiloj Kradvortoj + Mencioj diff --git a/core/ui/src/main/res/values-es/strings.xml b/core/ui/src/main/res/values-es/strings.xml index 5f6840edd..35bd59721 100644 --- a/core/ui/src/main/res/values-es/strings.xml +++ b/core/ui/src/main/res/values-es/strings.xml @@ -16,4 +16,5 @@ Etiquetas Texto copiado Copiar ítem + Menciones diff --git a/core/ui/src/main/res/values-eu/strings.xml b/core/ui/src/main/res/values-eu/strings.xml index c4ad3df20..a63f6c9af 100644 --- a/core/ui/src/main/res/values-eu/strings.xml +++ b/core/ui/src/main/res/values-eu/strings.xml @@ -12,4 +12,5 @@ Traolak Estekak Traolak + Aipamenak diff --git a/core/ui/src/main/res/values-fa/strings.xml b/core/ui/src/main/res/values-fa/strings.xml index 050e8cde1..7f9500b8e 100644 --- a/core/ui/src/main/res/values-fa/strings.xml +++ b/core/ui/src/main/res/values-fa/strings.xml @@ -14,4 +14,5 @@ برچسب‌ها پیوندها برچسب‌ها + اشاره‌ها diff --git a/core/ui/src/main/res/values-fi/strings.xml b/core/ui/src/main/res/values-fi/strings.xml index c641d4537..0653811de 100644 --- a/core/ui/src/main/res/values-fi/strings.xml +++ b/core/ui/src/main/res/values-fi/strings.xml @@ -16,4 +16,5 @@ Aihetunnisteet Teksti kopioitu Kopioi kohde + Maininnat diff --git a/core/ui/src/main/res/values-fr/strings.xml b/core/ui/src/main/res/values-fr/strings.xml index af5eadf7f..c7c3206ee 100644 --- a/core/ui/src/main/res/values-fr/strings.xml +++ b/core/ui/src/main/res/values-fr/strings.xml @@ -14,4 +14,5 @@ Hashtags Liens Hashtags + Mentions diff --git a/core/ui/src/main/res/values-ga/strings.xml b/core/ui/src/main/res/values-ga/strings.xml index bd5213b74..97a61c1b8 100644 --- a/core/ui/src/main/res/values-ga/strings.xml +++ b/core/ui/src/main/res/values-ga/strings.xml @@ -16,4 +16,5 @@ " (🔗 %s)" Cóipeáladh téacs Cóipeáil mír + Tráchtanna diff --git a/core/ui/src/main/res/values-gd/strings.xml b/core/ui/src/main/res/values-gd/strings.xml index cf94be4f3..913dd5f11 100644 --- a/core/ui/src/main/res/values-gd/strings.xml +++ b/core/ui/src/main/res/values-gd/strings.xml @@ -14,4 +14,5 @@ Tagaichean hais Ceanglaichean Tagaichean hais + Iomraidhean diff --git a/core/ui/src/main/res/values-gl/strings.xml b/core/ui/src/main/res/values-gl/strings.xml index cbc2d94d0..553e206bf 100644 --- a/core/ui/src/main/res/values-gl/strings.xml +++ b/core/ui/src/main/res/values-gl/strings.xml @@ -14,4 +14,5 @@ Cancelos Ligazóns Cancelos + Mencións diff --git a/core/ui/src/main/res/values-hi/strings.xml b/core/ui/src/main/res/values-hi/strings.xml index deb4c57ca..80da56a4e 100644 --- a/core/ui/src/main/res/values-hi/strings.xml +++ b/core/ui/src/main/res/values-hi/strings.xml @@ -11,4 +11,5 @@ हैशटैग लिंक हैशटैग + ज़िक्र diff --git a/core/ui/src/main/res/values-hu/strings.xml b/core/ui/src/main/res/values-hu/strings.xml index f578b37f1..7bac6a076 100644 --- a/core/ui/src/main/res/values-hu/strings.xml +++ b/core/ui/src/main/res/values-hu/strings.xml @@ -14,4 +14,5 @@ Hashtagek Linkek Hashtagek + Említések diff --git a/core/ui/src/main/res/values-in/strings.xml b/core/ui/src/main/res/values-in/strings.xml index 7aae1cb19..b6fe1b260 100644 --- a/core/ui/src/main/res/values-in/strings.xml +++ b/core/ui/src/main/res/values-in/strings.xml @@ -11,4 +11,5 @@ Hashtag Tautan Hashtag + Menyebutkan diff --git a/core/ui/src/main/res/values-is/strings.xml b/core/ui/src/main/res/values-is/strings.xml index 611d315cc..ec4ca536d 100644 --- a/core/ui/src/main/res/values-is/strings.xml +++ b/core/ui/src/main/res/values-is/strings.xml @@ -14,4 +14,5 @@ Myllumerki Tenglar Myllumerki + Tilvísanir diff --git a/core/ui/src/main/res/values-it/strings.xml b/core/ui/src/main/res/values-it/strings.xml index 72e849e58..aa6c97736 100644 --- a/core/ui/src/main/res/values-it/strings.xml +++ b/core/ui/src/main/res/values-it/strings.xml @@ -14,4 +14,5 @@ Hashtag Collegamenti Hashtag + Menzioni diff --git a/core/ui/src/main/res/values-ja/strings.xml b/core/ui/src/main/res/values-ja/strings.xml index 9b4373998..989b2f44f 100644 --- a/core/ui/src/main/res/values-ja/strings.xml +++ b/core/ui/src/main/res/values-ja/strings.xml @@ -14,4 +14,5 @@ ハッシュタグ リンク ハッシュタグ + 返信 diff --git a/core/ui/src/main/res/values-kab/strings.xml b/core/ui/src/main/res/values-kab/strings.xml index 4759025be..b0d10af9d 100644 --- a/core/ui/src/main/res/values-kab/strings.xml +++ b/core/ui/src/main/res/values-kab/strings.xml @@ -12,4 +12,5 @@ Ihacṭagen Iseɣwan Ihacṭagen + Tibdarin diff --git a/core/ui/src/main/res/values-ko/strings.xml b/core/ui/src/main/res/values-ko/strings.xml index 40b2da417..1c855881d 100644 --- a/core/ui/src/main/res/values-ko/strings.xml +++ b/core/ui/src/main/res/values-ko/strings.xml @@ -12,4 +12,5 @@ 해시태그 링크 해시태그 + 멘션 diff --git a/core/ui/src/main/res/values-lv/strings.xml b/core/ui/src/main/res/values-lv/strings.xml index 50260d48f..198ca6a01 100644 --- a/core/ui/src/main/res/values-lv/strings.xml +++ b/core/ui/src/main/res/values-lv/strings.xml @@ -14,4 +14,5 @@ Tēmturi Saites Tēmturi + Pieminējumi diff --git a/core/ui/src/main/res/values-ml/strings.xml b/core/ui/src/main/res/values-ml/strings.xml index bbf4c0185..49c0475cc 100644 --- a/core/ui/src/main/res/values-ml/strings.xml +++ b/core/ui/src/main/res/values-ml/strings.xml @@ -9,4 +9,5 @@ ലിങ്കുകൾ സൂചനകൾ ലിങ്കുകൾ + സൂചനകൾ diff --git a/core/ui/src/main/res/values-nb-rNO/strings.xml b/core/ui/src/main/res/values-nb-rNO/strings.xml index 35ff5cdb8..9b141cb96 100644 --- a/core/ui/src/main/res/values-nb-rNO/strings.xml +++ b/core/ui/src/main/res/values-nb-rNO/strings.xml @@ -14,4 +14,5 @@ Emneknagger Lenker Stikkord + Nevnelser diff --git a/core/ui/src/main/res/values-nl/strings.xml b/core/ui/src/main/res/values-nl/strings.xml index 7a2814a53..009a10713 100644 --- a/core/ui/src/main/res/values-nl/strings.xml +++ b/core/ui/src/main/res/values-nl/strings.xml @@ -14,4 +14,5 @@ Hashtags Links Hashtags + Vermeldingen diff --git a/core/ui/src/main/res/values-oc/strings.xml b/core/ui/src/main/res/values-oc/strings.xml index 87479d67a..b0226ac35 100644 --- a/core/ui/src/main/res/values-oc/strings.xml +++ b/core/ui/src/main/res/values-oc/strings.xml @@ -14,4 +14,5 @@ Etiquetas Ligams Etiquetas + Mencions diff --git a/core/ui/src/main/res/values-pl/strings.xml b/core/ui/src/main/res/values-pl/strings.xml index 06eda0f99..179e6ba87 100644 --- a/core/ui/src/main/res/values-pl/strings.xml +++ b/core/ui/src/main/res/values-pl/strings.xml @@ -14,4 +14,5 @@ Hashtagi Linki Hashtagi + Wzmianki diff --git a/core/ui/src/main/res/values-pt-rBR/strings.xml b/core/ui/src/main/res/values-pt-rBR/strings.xml index 6c45bd393..e9f8d71a8 100644 --- a/core/ui/src/main/res/values-pt-rBR/strings.xml +++ b/core/ui/src/main/res/values-pt-rBR/strings.xml @@ -14,4 +14,5 @@ Hashtags Links Hashtags + Menções diff --git a/core/ui/src/main/res/values-pt-rPT/strings.xml b/core/ui/src/main/res/values-pt-rPT/strings.xml index 5825d9cce..25c4c642d 100644 --- a/core/ui/src/main/res/values-pt-rPT/strings.xml +++ b/core/ui/src/main/res/values-pt-rPT/strings.xml @@ -13,4 +13,5 @@ Hashtags Hiperligações Hashtags + Menções diff --git a/core/ui/src/main/res/values-ru/strings.xml b/core/ui/src/main/res/values-ru/strings.xml index df3b8ddb2..f728ab97d 100644 --- a/core/ui/src/main/res/values-ru/strings.xml +++ b/core/ui/src/main/res/values-ru/strings.xml @@ -12,4 +12,5 @@ Хэштеги Ссылки Хэштеги + Упоминания diff --git a/core/ui/src/main/res/values-sa/strings.xml b/core/ui/src/main/res/values-sa/strings.xml index 5605fa0fb..f4e79681d 100644 --- a/core/ui/src/main/res/values-sa/strings.xml +++ b/core/ui/src/main/res/values-sa/strings.xml @@ -13,4 +13,5 @@ निश्रेणिचिह्नशीर्षकाः जालस्थलानि निश्रेणिचिह्नशीर्षकाः + उल्लेखाः diff --git a/core/ui/src/main/res/values-si/strings.xml b/core/ui/src/main/res/values-si/strings.xml index 2e613326c..49de0117a 100644 --- a/core/ui/src/main/res/values-si/strings.xml +++ b/core/ui/src/main/res/values-si/strings.xml @@ -8,4 +8,5 @@ සබැඳි සඳැහුම් සබැඳි + සඳැහුම් diff --git a/core/ui/src/main/res/values-sk/strings.xml b/core/ui/src/main/res/values-sk/strings.xml index 4b05540b9..1e475987f 100644 --- a/core/ui/src/main/res/values-sk/strings.xml +++ b/core/ui/src/main/res/values-sk/strings.xml @@ -7,4 +7,5 @@ Hashtagy Odkazy Hashtagy + Zmienky diff --git a/core/ui/src/main/res/values-sl/strings.xml b/core/ui/src/main/res/values-sl/strings.xml index 23d85ce3e..942adb4a4 100644 --- a/core/ui/src/main/res/values-sl/strings.xml +++ b/core/ui/src/main/res/values-sl/strings.xml @@ -12,4 +12,5 @@ Ključniki Povezave Ključniki + Omembe diff --git a/core/ui/src/main/res/values-sv/strings.xml b/core/ui/src/main/res/values-sv/strings.xml index d6f235c9b..8e231ff39 100644 --- a/core/ui/src/main/res/values-sv/strings.xml +++ b/core/ui/src/main/res/values-sv/strings.xml @@ -14,4 +14,5 @@ Hashtaggar Länkar Hashtaggar + Omnämnanden diff --git a/core/ui/src/main/res/values-th/strings.xml b/core/ui/src/main/res/values-th/strings.xml index 90b7ff8a4..411efefe0 100644 --- a/core/ui/src/main/res/values-th/strings.xml +++ b/core/ui/src/main/res/values-th/strings.xml @@ -12,4 +12,5 @@ แฮชแท็ก ลิงก์ แฮชแท็ก + โต้ตอบ diff --git a/core/ui/src/main/res/values-tr/strings.xml b/core/ui/src/main/res/values-tr/strings.xml index c40619bfa..96a8f564b 100644 --- a/core/ui/src/main/res/values-tr/strings.xml +++ b/core/ui/src/main/res/values-tr/strings.xml @@ -14,4 +14,5 @@ Etiketler Bağlantılar Etiketler + Bahsedenler diff --git a/core/ui/src/main/res/values-uk/strings.xml b/core/ui/src/main/res/values-uk/strings.xml index 70e4fc1f8..cde45a814 100644 --- a/core/ui/src/main/res/values-uk/strings.xml +++ b/core/ui/src/main/res/values-uk/strings.xml @@ -14,4 +14,5 @@ Хештеги Посилання Хештеги + Згадки diff --git a/core/ui/src/main/res/values-vi/strings.xml b/core/ui/src/main/res/values-vi/strings.xml index 8a85d4eb9..7e3bb2502 100644 --- a/core/ui/src/main/res/values-vi/strings.xml +++ b/core/ui/src/main/res/values-vi/strings.xml @@ -14,4 +14,5 @@ Hashtag Links Hashtag + Lượt nhắc tới diff --git a/core/ui/src/main/res/values-zh-rCN/strings.xml b/core/ui/src/main/res/values-zh-rCN/strings.xml index bac348d25..ac99b1cca 100644 --- a/core/ui/src/main/res/values-zh-rCN/strings.xml +++ b/core/ui/src/main/res/values-zh-rCN/strings.xml @@ -14,4 +14,5 @@ 话题 链接 话题 + 提及 diff --git a/core/ui/src/main/res/values-zh-rHK/strings.xml b/core/ui/src/main/res/values-zh-rHK/strings.xml index 72d8a414d..23c87708a 100644 --- a/core/ui/src/main/res/values-zh-rHK/strings.xml +++ b/core/ui/src/main/res/values-zh-rHK/strings.xml @@ -13,4 +13,5 @@ 連結 話題 重新整理 - \ No newline at end of file + 提及 + diff --git a/core/ui/src/main/res/values-zh-rMO/strings.xml b/core/ui/src/main/res/values-zh-rMO/strings.xml index e8c18e6de..2afb8f2f2 100644 --- a/core/ui/src/main/res/values-zh-rMO/strings.xml +++ b/core/ui/src/main/res/values-zh-rMO/strings.xml @@ -11,4 +11,5 @@ 話題 連結 話題 - \ No newline at end of file + 提及 + diff --git a/core/ui/src/main/res/values-zh-rSG/strings.xml b/core/ui/src/main/res/values-zh-rSG/strings.xml index 5047ef0b0..1afc5aab9 100644 --- a/core/ui/src/main/res/values-zh-rSG/strings.xml +++ b/core/ui/src/main/res/values-zh-rSG/strings.xml @@ -11,4 +11,5 @@ 话题 链接 话题 + 提及 diff --git a/core/ui/src/main/res/values-zh-rTW/strings.xml b/core/ui/src/main/res/values-zh-rTW/strings.xml index c70bc0b25..0c1cb2fdf 100644 --- a/core/ui/src/main/res/values-zh-rTW/strings.xml +++ b/core/ui/src/main/res/values-zh-rTW/strings.xml @@ -14,4 +14,5 @@ 連結 話題 重新整理 - \ No newline at end of file + 提及 + diff --git a/core/ui/src/main/res/values/actions.xml b/core/ui/src/main/res/values/actions.xml index 1cb109cca..05abc8279 100644 --- a/core/ui/src/main/res/values/actions.xml +++ b/core/ui/src/main/res/values/actions.xml @@ -42,9 +42,13 @@ + + + + diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index b6de9af80..a599c275d 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -16,4 +16,5 @@ Hashtags Text copied Copy item + Mentions diff --git a/feature/suggestions/src/main/kotlin/app/pachli/feature/suggestions/SuggestionAccessibilityDelegate.kt b/feature/suggestions/src/main/kotlin/app/pachli/feature/suggestions/SuggestionAccessibilityDelegate.kt index fcd878809..a0fb45529 100644 --- a/feature/suggestions/src/main/kotlin/app/pachli/feature/suggestions/SuggestionAccessibilityDelegate.kt +++ b/feature/suggestions/src/main/kotlin/app/pachli/feature/suggestions/SuggestionAccessibilityDelegate.kt @@ -17,19 +17,16 @@ package app.pachli.feature.suggestions -import android.content.Context import android.os.Bundle import android.text.Spannable +import android.text.Spanned import android.text.style.URLSpan import android.view.View -import android.view.accessibility.AccessibilityEvent -import android.view.accessibility.AccessibilityManager -import android.widget.ArrayAdapter -import androidx.appcompat.app.AlertDialog +import androidx.core.text.getSpans import androidx.core.view.AccessibilityDelegateCompat import androidx.core.view.accessibility.AccessibilityNodeInfoCompat import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate +import app.pachli.core.ui.accessibility.PachliRecyclerViewAccessibilityDelegate /** * Accessibility delegate for items in [SuggestionViewHolder]. @@ -40,18 +37,13 @@ import androidx.recyclerview.widget.RecyclerViewAccessibilityDelegate * - Dismiss the suggestion * - Follow the account * - * If the account's bio includes any links or hashtags then actions to show those - * in a dialog allowing the user to activate one are also included. + * If the account's bio includes any links, mentions, or hashtags then actions to + * show those in a dialog allowing the user to copy/activate one are also included. */ internal class SuggestionAccessibilityDelegate( private val recyclerView: RecyclerView, private val accept: (UiAction) -> Unit, -) : RecyclerViewAccessibilityDelegate(recyclerView) { - private val context = recyclerView.context - - private val a11yManager = context.getSystemService(Context.ACCESSIBILITY_SERVICE) - as AccessibilityManager - +) : PachliRecyclerViewAccessibilityDelegate(recyclerView) { private val openProfileAction = AccessibilityNodeInfoCompat.AccessibilityActionCompat( app.pachli.core.ui.R.id.action_open_profile, context.getString(app.pachli.core.ui.R.string.action_view_profile), @@ -72,11 +64,18 @@ internal class SuggestionAccessibilityDelegate( context.getString(app.pachli.core.ui.R.string.action_links), ) + private val mentionsAction = AccessibilityNodeInfoCompat.AccessibilityActionCompat( + app.pachli.core.ui.R.id.action_mentions, + context.getString(app.pachli.core.ui.R.string.action_mentions), + ) + private val hashtagsAction = AccessibilityNodeInfoCompat.AccessibilityActionCompat( app.pachli.core.ui.R.id.action_hashtags, context.getString(app.pachli.core.ui.R.string.action_hashtags), ) + override fun getItemDelegate(): AccessibilityDelegateCompat = delegate + private val delegate = object : ItemDelegate(this) { override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfoCompat) { super.onInitializeAccessibilityNodeInfo(host, info) @@ -89,22 +88,17 @@ internal class SuggestionAccessibilityDelegate( info.addAction(deleteSuggestionAction) info.addAction(followAccountAction) - val links = getLinks(viewHolder) + val text = viewHolder.binding.accountNote.text as Spannable - // Listed in the same order as ListStatusAccessibilityDelegate to - // ensure consistent order (links, mentions, hashtags). - if (links.containsKey(LinkType.Link)) info.addAction(linksAction) - - // Disabling support for mentions at the moment, as the API response - // doesn't break them out (https://github.com/mastodon/mastodon/issues/27745). - // if (links.containsKey(LinkType.Mention)) info.addAction(mentionsAction) - - if (links.containsKey(LinkType.HashTag)) info.addAction(hashtagsAction) + if (text.getLinks().any()) info.addAction(linksAction) + if (text.getUrlMentions().any()) info.addAction(mentionsAction) + if (text.getHashtags().any()) info.addAction(hashtagsAction) } override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean { val viewHolder = recyclerView.findContainingViewHolder(host) as? SuggestionViewHolder ?: return false val viewData = viewHolder.viewData + val text = viewHolder.binding.accountNote.text as Spannable if (!viewData.isEnabled) return false @@ -128,79 +122,44 @@ internal class SuggestionAccessibilityDelegate( } app.pachli.core.ui.R.id.action_links -> { - val links = getLinks(viewHolder)[LinkType.Link] ?: return true - showLinksDialog(host.context, links) + val links = (viewHolder.binding.accountNote.text as Spannable).getLinks() + showA11yDialogWithCopyButton( + app.pachli.core.ui.R.string.title_links_dialog, + links.map { it.url }, + ) { accept(UiAction.NavigationAction.ViewUrl(links[it].url)) } + true + } + + app.pachli.core.ui.R.id.action_mentions -> { + val mentions = text.getUrlMentions() + showA11yDialogWithCopyButton( + app.pachli.core.ui.R.string.title_mentions_dialog, + mentions.map { text.subSequence(it).toString() }, + ) { accept(UiAction.NavigationAction.ViewUrl(mentions[it].url)) } true } app.pachli.core.ui.R.id.action_hashtags -> { - val hashtags = getLinks(viewHolder)[LinkType.HashTag] ?: return true - showHashTagsDialog(host.context, hashtags) + val hashtags = text.getHashtags() + showA11yDialogWithCopyButton( + app.pachli.core.ui.R.string.title_hashtags_dialog, + hashtags.map { "#$it" }, + ) { accept(UiAction.NavigationAction.ViewHashtag(hashtags[it].toString())) } true } else -> super.performAccessibilityAction(host, action, args) } } - - private fun showLinksDialog(context: Context, links: List) = AlertDialog.Builder(context) - .setTitle(app.pachli.core.ui.R.string.title_links_dialog) - .setAdapter( - ArrayAdapter( - context, - android.R.layout.simple_list_item_1, - links.map { it.link }, - ), - ) { _, which -> accept(UiAction.NavigationAction.ViewUrl(links[which].link)) } - .show() - .let { forceFocus(it.listView) } - - private fun showHashTagsDialog(context: Context, hashtags: List) = AlertDialog.Builder(context) - .setTitle(app.pachli.core.ui.R.string.title_hashtags_dialog) - .setAdapter( - ArrayAdapter( - context, - android.R.layout.simple_list_item_1, - hashtags.map { it.text.subSequence(1, it.text.length) }, - ), - ) { _, which -> accept(UiAction.NavigationAction.ViewHashtag(hashtags[which].text)) } - .show() - .let { forceFocus(it.listView) } } - private fun forceFocus(view: View) { - interrupt() - view.post { - view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) - } + companion object { + // This is required because account notes don't break mentions out in to + // a separate `mentions` property or similar. See + // https://github.com/mastodon/mastodon/issues/27745 for the feature request. + /** @return [URLSpan]s that have anchor text that looks like an at-mention. */ + @JvmStatic + fun Spanned.getUrlMentions(): List = getSpans(0, length) + .filter { subSequence(it).isMention() } } - - private fun interrupt() = a11yManager.interrupt() - - override fun getItemDelegate(): AccessibilityDelegateCompat = delegate - - enum class LinkType { - Mention, - HashTag, - Link, - } - - private fun getLinks(viewHolder: SuggestionViewHolder): Map> { - val note = viewHolder.binding.accountNote.text - if (note !is Spannable) return emptyMap() - - return note.getSpans(0, note.length, URLSpan::class.java) - .map { - LinkSpanInfo(note.subSequence(note.getSpanStart(it), note.getSpanEnd(it)).toString(), it.url) - } - .groupBy { - when { - it.text.startsWith("@") -> LinkType.Mention - it.text.startsWith("#") -> LinkType.HashTag - else -> LinkType.Link - } - } - } - - private data class LinkSpanInfo(val text: String, val link: String) }