feat: Edit a matching filter directly from the timeline (#819)

Previously, if a status was filtered with "WARN" and was shown in the
timeline with the name of the filter, and the user then decided to
change
that filter, they had to:

1. Open the left navigation menu
2. Navigate to "Account preferences"
3. Open "Filters"
4. Find the filter they want to edit, tap it
5. Make the change, and save
6. "Back" to the list of filters
7. "Back" to "Account preferences"
8. "Back" to the timeline

That's a lot of clicks for a simple action.

Change this. Now the filtered status includes an "Edit filter" button
that takes the user directly to step 5, and when they press "Back" they
return directly to the timeline.

To do this create a new filter action, `onEditFilterById`. Update the
listeners to launch `EditFilterActivity` if appropriate.

Modify `item_status_filtered.xml` to show the new button.

Update the accessibility delegate to show just the "Show anyway" and
"Edit filter" actions. Modify `FilterableStatusViewHolder` to expose
the information it needs to do this.
This commit is contained in:
Nik Clayton 2024-07-19 13:45:24 +02:00 committed by GitHub
parent 7ef692c2c8
commit 6b55d107c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 185 additions and 93 deletions

View File

@ -18,6 +18,7 @@
package app.pachli.adapter
import android.view.View
import androidx.core.text.HtmlCompat
import app.pachli.R
import app.pachli.core.data.model.StatusDisplayOptions
import app.pachli.core.network.model.Filter
@ -28,6 +29,8 @@ import app.pachli.viewdata.IStatusViewData
open class FilterableStatusViewHolder<T : IStatusViewData>(
private val binding: ItemStatusWrapperBinding,
) : StatusViewHolder<T>(binding.statusContainer, binding.root) {
/** The filter that matched the status, null if the status is not being filtered. */
var matchedFilter: Filter? = null
override fun setupWithStatus(
viewData: T,
@ -44,42 +47,38 @@ open class FilterableStatusViewHolder<T : IStatusViewData>(
listener: StatusActionListener<T>,
) {
if (status.filterAction !== Filter.Action.WARN) {
showFilteredPlaceholder(false)
matchedFilter = null
setPlaceholderVisibility(false)
return
}
// Shouldn't be necessary given the previous test against getFilterAction(),
// but guards against a possible NPE. See the TODO in StatusViewData.filterAction
// for more details.
val filterResults = status.actionable.filtered
if (filterResults.isNullOrEmpty()) {
showFilteredPlaceholder(false)
return
}
var matchedFilter: Filter? = null
for ((filter) in filterResults) {
if (filter.action === Filter.Action.WARN) {
matchedFilter = filter
break
status.actionable.filtered?.find { it.filter.action === Filter.Action.WARN }?.let { result ->
this.matchedFilter = result.filter
setPlaceholderVisibility(true)
val label = HtmlCompat.fromHtml(
context.getString(
R.string.status_filter_placeholder_label_format,
result.filter.title,
),
HtmlCompat.FROM_HTML_MODE_LEGACY,
)
binding.root.contentDescription = label
binding.statusFilteredPlaceholder.statusFilterLabel.text = label
binding.statusFilteredPlaceholder.statusFilterShowAnyway.setOnClickListener {
listener.clearWarningAction(status)
}
}
// Guard against a possible NPE
if (matchedFilter == null) {
showFilteredPlaceholder(false)
return
}
showFilteredPlaceholder(true)
binding.statusFilteredPlaceholder.statusFilterLabel.text = context.getString(
R.string.status_filter_placeholder_label_format,
matchedFilter.title,
)
binding.statusFilteredPlaceholder.statusFilterShowAnyway.setOnClickListener {
listener.clearWarningAction(status)
binding.statusFilteredPlaceholder.statusFilterEditFilter.setOnClickListener {
listener.onEditFilterById(result.filter.id)
}
} ?: {
matchedFilter = null
setPlaceholderVisibility(false)
}
}
private fun showFilteredPlaceholder(show: Boolean) {
private fun setPlaceholderVisibility(show: Boolean) {
binding.statusContainer.root.visibility = if (show) View.GONE else View.VISIBLE
binding.statusFilteredPlaceholder.root.visibility = if (show) View.VISIBLE else View.GONE
}

View File

@ -11,7 +11,6 @@ import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.content.res.AppCompatResources
@ -100,7 +99,7 @@ abstract class StatusBaseViewHolder<T : IStatusViewData> protected constructor(i
private val contentWarningDescription: TextView = itemView.findViewById(R.id.status_content_warning_description)
private val pollView: PollView = itemView.findViewById(R.id.status_poll)
private val cardView: PreviewCardView? = itemView.findViewById(R.id.status_card_view)
private val filteredPlaceholder: LinearLayout? = itemView.findViewById(R.id.status_filtered_placeholder)
private val filteredPlaceholder: ConstraintLayout? = itemView.findViewById(R.id.status_filtered_placeholder)
private val filteredPlaceholderLabel: TextView? = itemView.findViewById(R.id.status_filter_label)
private val filteredPlaceholderShowButton: Button? = itemView.findViewById(R.id.status_filter_show_anyway)
private val statusContainer: ConstraintLayout? = itemView.findViewById(R.id.status_container)

View File

@ -346,6 +346,9 @@ class ConversationsFragment :
override fun clearWarningAction(viewData: ConversationViewData) {
}
// Filters don't apply in conversations
override fun onEditFilterById(filterId: String) {}
override fun onReselect() {
if (isAdded) {
binding.recyclerView.layoutManager?.scrollToPosition(0)

View File

@ -49,11 +49,14 @@ import app.pachli.R
import app.pachli.adapter.StatusBaseViewHolder
import app.pachli.components.timeline.TimelineLoadStateAdapter
import app.pachli.core.activity.ReselectableFragment
import app.pachli.core.activity.extensions.TransitionKind
import app.pachli.core.activity.extensions.startActivityWithTransition
import app.pachli.core.activity.openLink
import app.pachli.core.common.extensions.hide
import app.pachli.core.common.extensions.show
import app.pachli.core.common.extensions.viewBinding
import app.pachli.core.navigation.AttachmentViewData.Companion.list
import app.pachli.core.navigation.EditFilterActivityIntent
import app.pachli.core.network.model.Filter
import app.pachli.core.network.model.Notification
import app.pachli.core.network.model.Poll
@ -589,6 +592,13 @@ class NotificationsFragment :
}
}
override fun onEditFilterById(filterId: String) {
requireActivity().startActivityWithTransition(
EditFilterActivityIntent.edit(requireContext(), filterId),
TransitionKind.SLIDE_FROM_END,
)
}
override fun onNotificationContentCollapsedChange(
isCollapsed: Boolean,
viewData: NotificationViewData,

View File

@ -40,13 +40,16 @@ import app.pachli.R
import app.pachli.components.search.adapter.SearchStatusesAdapter
import app.pachli.core.activity.AccountSelectionListener
import app.pachli.core.activity.BaseActivity
import app.pachli.core.activity.extensions.TransitionKind
import app.pachli.core.activity.extensions.startActivityWithDefaultTransition
import app.pachli.core.activity.extensions.startActivityWithTransition
import app.pachli.core.activity.openLink
import app.pachli.core.data.repository.StatusDisplayOptionsRepository
import app.pachli.core.database.model.AccountEntity
import app.pachli.core.navigation.AttachmentViewData
import app.pachli.core.navigation.ComposeActivityIntent
import app.pachli.core.navigation.ComposeActivityIntent.ComposeOptions
import app.pachli.core.navigation.EditFilterActivityIntent
import app.pachli.core.navigation.ReportActivityIntent
import app.pachli.core.navigation.ViewMediaActivityIntent
import app.pachli.core.network.model.Attachment
@ -162,6 +165,13 @@ class SearchStatusesFragment : SearchFragment<StatusViewData>(), StatusActionLis
viewModel.reblog(viewData, reblog)
}
override fun onEditFilterById(filterId: String) {
requireActivity().startActivityWithTransition(
EditFilterActivityIntent.edit(requireContext(), filterId),
TransitionKind.SLIDE_FROM_END,
)
}
companion object {
fun newInstance() = SearchStatusesFragment()
}

View File

@ -51,7 +51,9 @@ import app.pachli.components.timeline.viewmodel.TimelineViewModel
import app.pachli.components.timeline.viewmodel.UiSuccess
import app.pachli.core.activity.RefreshableFragment
import app.pachli.core.activity.ReselectableFragment
import app.pachli.core.activity.extensions.TransitionKind
import app.pachli.core.activity.extensions.startActivityWithDefaultTransition
import app.pachli.core.activity.extensions.startActivityWithTransition
import app.pachli.core.common.extensions.hide
import app.pachli.core.common.extensions.show
import app.pachli.core.common.extensions.viewBinding
@ -59,6 +61,7 @@ import app.pachli.core.database.model.TranslationState
import app.pachli.core.model.Timeline
import app.pachli.core.navigation.AccountListActivityIntent
import app.pachli.core.navigation.AttachmentViewData
import app.pachli.core.navigation.EditFilterActivityIntent
import app.pachli.core.network.model.Poll
import app.pachli.core.network.model.Status
import app.pachli.core.ui.ActionButtonScrollListener
@ -615,6 +618,13 @@ class TimelineFragment :
viewModel.clearWarning(viewData)
}
override fun onEditFilterById(filterId: String) {
requireActivity().startActivityWithTransition(
EditFilterActivityIntent.edit(requireContext(), filterId),
TransitionKind.SLIDE_FROM_END,
)
}
override fun onMore(view: View, viewData: StatusViewData) {
super.more(view, viewData)
}

View File

@ -33,7 +33,9 @@ import androidx.recyclerview.widget.SimpleItemAnimator
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
import app.pachli.R
import app.pachli.components.viewthread.edits.ViewEditsFragment
import app.pachli.core.activity.extensions.TransitionKind
import app.pachli.core.activity.extensions.startActivityWithDefaultTransition
import app.pachli.core.activity.extensions.startActivityWithTransition
import app.pachli.core.activity.openLink
import app.pachli.core.common.extensions.hide
import app.pachli.core.common.extensions.show
@ -41,6 +43,7 @@ import app.pachli.core.common.extensions.viewBinding
import app.pachli.core.designsystem.R as DR
import app.pachli.core.navigation.AccountListActivityIntent
import app.pachli.core.navigation.AttachmentViewData.Companion.list
import app.pachli.core.navigation.EditFilterActivityIntent
import app.pachli.core.network.model.Poll
import app.pachli.core.network.model.Status
import app.pachli.core.ui.extensions.getErrorString
@ -323,6 +326,13 @@ class ViewThreadFragment :
// there are no reblogs in threads
}
override fun onEditFilterById(filterId: String) {
requireActivity().startActivityWithTransition(
EditFilterActivityIntent.edit(requireContext(), filterId),
TransitionKind.SLIDE_FROM_END,
)
}
override fun onExpandedChange(viewData: StatusViewData, expanded: Boolean) {
viewModel.changeExpanded(expanded, viewData)
}

View File

@ -59,4 +59,7 @@ interface StatusActionListener<T : IStatusViewData> : LinkListener {
fun onVoteInPoll(viewData: T, poll: Poll, choices: List<Int>)
fun onShowEdits(statusId: String) {}
fun clearWarningAction(viewData: T)
/** Edit the filter that matched this status. */
fun onEditFilterById(filterId: String)
}

View File

@ -15,6 +15,7 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.Accessibilit
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
@ -48,6 +49,13 @@ class ListStatusAccessibilityDelegate<T : IStatusViewData>(
) {
super.onInitializeAccessibilityNodeInfo(host, info)
val viewHolder = recyclerView.findContainingViewHolder(host)
if (viewHolder is FilterableStatusViewHolder<*> && viewHolder.matchedFilter != null) {
info.addAction(showAnywayAction)
info.addAction(editFilterAction)
return
}
val pos = recyclerView.getChildAdapterPosition(host)
val status = statusProvider.getStatus(pos) ?: return
@ -183,6 +191,14 @@ class ListStatusAccessibilityDelegate<T : IStatusViewData>(
app.pachli.core.ui.R.id.action_more -> {
statusActionListener.onMore(host, status)
}
app.pachli.core.ui.R.id.action_show_anyway -> statusActionListener.clearWarningAction(status)
app.pachli.core.ui.R.id.action_edit_filter -> {
(recyclerView.findContainingViewHolder(host) as? FilterableStatusViewHolder<*>)?.matchedFilter?.let {
statusActionListener.onEditFilterById(it.id)
return@let true
} ?: false
}
else -> return super.performAccessibilityAction(host, action, args)
}
return true
@ -378,5 +394,15 @@ class ListStatusAccessibilityDelegate<T : IStatusViewData>(
context.getString(app.pachli.core.ui.R.string.action_more),
)
private val showAnywayAction = AccessibilityActionCompat(
app.pachli.core.ui.R.id.action_show_anyway,
context.getString(R.string.status_filtered_show_anyway),
)
private val editFilterAction = AccessibilityActionCompat(
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)
}

View File

@ -1,33 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/status_filtered_placeholder"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
android:paddingStart="14dp"
android:paddingEnd="14dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:minHeight="48dp">
<TextView
android:id="@+id/status_filter_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAccessibility="no"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:layout_marginBottom="0dp"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
android:textAlignment="center"
android:textIsSelectable="false"
tools:text="Filter: MyFilter"
/>
tools:text="Filter: MyFilter" />
<Button
android:id="@+id/status_filter_edit_filter"
style="@style/AppButton.TextButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:importantForAccessibility="no"
android:text="@string/filter_edit_title"
android:textSize="?attr/status_text_medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/status_filter_show_anyway"
app:layout_constraintTop_toTopOf="@+id/status_filter_show_anyway" />
<Button
android:id="@+id/status_filter_show_anyway"
android:layout_width="match_parent"
style="@style/AppButton.Outlined"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
style="@style/AppButton.TextButton"
android:textStyle="bold"
android:textSize="?attr/status_text_medium"
android:importantForAccessibility="no"
android:layout_marginTop="8dp"
android:text="@string/status_filtered_show_anyway"
/>
</LinearLayout>
android:textSize="?attr/status_text_medium"
app:layout_constraintStart_toEndOf="@id/status_filter_edit_filter"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_filter_label" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -587,7 +587,7 @@
<string name="filter_action_warn">تحذير</string>
<string name="title_public_trending_links">الروابط الشائعة</string>
<string name="title_tab_public_trending_links">الروابط</string>
<string name="status_filter_placeholder_label_format">مُصفّى: %s</string>
<string name="status_filter_placeholder_label_format">مُصفّى: &lt;b>%1$s&lt;/b></string>
<string name="update_dialog_neutral">لا تذكرني بهذه النسخة</string>
<string name="ui_error_reject_follow_request">فشل رفض طلب المتابعة: %s</string>
<string name="reaction_name_and_count">%1$s %2$d</string>
@ -642,4 +642,4 @@
<string name="pref_summary_timeline_filters">خادمك الخاص لا يدعم عوامل التصفية</string>
<string name="load_newest_statuses">تحميل أحدث المنشورات</string>
<string name="announcement_date_updated">(%1$s :تم تحديثه)</string>
</resources>
</resources>

View File

@ -551,7 +551,7 @@
<string name="description_login">Працуе амаль заўсёды. Даныя не ўцякаюць у іншыя праграмы.</string>
<string name="notification_unknown_name">Невядома</string>
<string name="status_filtered_show_anyway">Усё роўна паказаць</string>
<string name="status_filter_placeholder_label_format">Адфільтрована: %s</string>
<string name="status_filter_placeholder_label_format">Адфільтрована: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Профілі</string>
<string name="title_public_trending_hashtags">Папулярныя хэштэгі</string>
<string name="description_browser_login">Можа падтрымліваць дадатковыя метады праверкі сапраўднасці, але для гэтага патрэбны адпаведны браузер.</string>
@ -581,4 +581,4 @@
<string name="filter_keyword_display_format">%s (цэлае слова)</string>
<string name="filter_keyword_addition_title">Дадаць ключавое слова</string>
<string name="filter_edit_keyword_title">Змяніць ключавое слова</string>
</resources>
</resources>

View File

@ -537,8 +537,8 @@
<string name="dialog_follow_hashtag_title">Segueix hashtag</string>
<string name="dialog_follow_hashtag_hint">#hashtag</string>
<string name="notification_unknown_name">Desconegut</string>
<string name="status_filter_placeholder_label_format">Filtrat: %s</string>
<string name="status_filter_placeholder_label_format">Filtrat: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Perfils</string>
<string name="status_filtered_show_anyway">Mostra de totes maneres</string>
<string name="socket_timeout_exception">El contacte amb el teu servidor ha trigat massa</string>
</resources>
</resources>

View File

@ -585,7 +585,7 @@
<string name="dialog_follow_hashtag_hint">#hashnod</string>
<string name="notification_unknown_name">Anhysbys</string>
<string name="status_filtered_show_anyway">Dangos beth bynnag</string>
<string name="status_filter_placeholder_label_format">Hidlwyd: %s</string>
<string name="status_filter_placeholder_label_format">Hidlwyd: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Proffiliau</string>
<string name="socket_timeout_exception">Cymrodd hi\'n rhy hir i gysylltu â\'ch gweinydd</string>
<string name="ui_error_bookmark_fmt">Methodd tudalnodi\'r neges: %1$s</string>
@ -634,4 +634,4 @@
<string name="error_media_playback">Methodd chwarae: %s</string>
<string name="dialog_delete_filter_positive_action">Dileu</string>
<string name="dialog_delete_filter_text">Dileu\'r hidlydd \'%1$s\'\?</string>
</resources>
</resources>

View File

@ -554,7 +554,7 @@
<string name="notification_unknown_name">Unbekannt</string>
<string name="ui_error_clear_notifications">Löschen der Benachrichtigungen schlug fehl: %s</string>
<string name="ui_error_reject_follow_request">Ablehnen der Folgeanfrage schlug fehl: %s</string>
<string name="status_filter_placeholder_label_format">Gefiltert: %s</string>
<string name="status_filter_placeholder_label_format">Gefiltert: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Profile</string>
<string name="hint_filter_title">Mein Filter</string>
<string name="label_filter_title">Titel</string>
@ -621,4 +621,4 @@
<string name="reaction_name_and_count">%1$s %2$d</string>
<string name="announcement_date">%1$s %2$s</string>
<string name="announcement_date_updated">(Aktualisiert: %1$s)</string>
</resources>
</resources>

View File

@ -554,7 +554,7 @@
<string name="pref_title_account_filter_keywords">Perfiles</string>
<string name="notification_unknown_name">Desconocido</string>
<string name="status_filtered_show_anyway">Mostrar de todas formas</string>
<string name="status_filter_placeholder_label_format">Filtrado: %s</string>
<string name="status_filter_placeholder_label_format">Filtrado: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_show_stat_inline">Mostrar estadísticas de la entrada en la línea de tiempo</string>
<string name="socket_timeout_exception">Contactar con tu servidor ha tardado demasiado tiempo</string>
<string name="select_list_empty">Todavía no tienes listas</string>
@ -680,4 +680,4 @@
<string name="error_prepare_media_content_resolver_unsupported_scheme_fmt">el agente de resolución de contenido tiene un esquema no compatible: %1$s</string>
<string name="error_prepare_media_file_is_too_large_fmt">el tamaño del archivo es %1$s, el máximo permitido es %2$s</string>
<string name="error_prepare_media_io_fmt">%1$s</string>
</resources>
</resources>

View File

@ -551,7 +551,7 @@
<string name="ui_error_reblog_fmt">%1$s: تقویت فرسته شکست خورد</string>
<string name="ui_error_reject_follow_request">رد کردن درخواست پی‌گیری شکست خورد: %s</string>
<string name="status_filtered_show_anyway">نمایش به هر روی</string>
<string name="status_filter_placeholder_label_format">پالوده: %s</string>
<string name="status_filter_placeholder_label_format">پالوده: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">نمایه‌ها</string>
<string name="hint_filter_title">پالایه‌ام</string>
<string name="label_filter_title">عنوان</string>
@ -590,4 +590,4 @@
<string name="error_media_playback">پخش شکست خورد: %s</string>
<string name="dialog_delete_filter_positive_action">حذف</string>
<string name="dialog_delete_filter_text">«%1$s» حذف پالایهٔ ؟</string>
</resources>
</resources>

View File

@ -364,7 +364,7 @@
<string name="send_post_notification_error_title">Julkaisun lähettäminen epäonnistui</string>
<string name="pref_title_notification_filter_follow_requests">seuraamista pyydetty</string>
<string name="pref_title_notification_filters">Ilmoita kun</string>
<string name="status_filter_placeholder_label_format">Suodatettu: %s</string>
<string name="status_filter_placeholder_label_format">Suodatettu: &lt;b>%1$s&lt;/b></string>
<string name="pref_main_nav_position_option_bottom">Alareuna</string>
<string name="pref_title_notification_filter_poll">päättyneet äänestykset</string>
<string name="abbreviated_in_seconds">%ds</string>
@ -661,4 +661,4 @@
<string name="action_open_link">Avaa linkki</string>
<string name="error_prepare_media_unknown_file_size">tiedoston kokoa ei voitu määrittää</string>
<string name="error_prepare_media_unsupported_mime_type_fmt">palvelin ei tue tidostomuotoa: %1$s</string>
</resources>
</resources>

View File

@ -528,7 +528,7 @@
<string name="pref_title_notification_filter_reports">il y a un nouveau signalement</string>
<string name="pref_title_account_filter_keywords">Profils</string>
<string name="status_filtered_show_anyway">Montrer quand même</string>
<string name="status_filter_placeholder_label_format">Caché : %s</string>
<string name="status_filter_placeholder_label_format">Caché : &lt;b>%1$s&lt;/b></string>
<string name="title_public_trending_hashtags">Hashtags tendance</string>
<string name="send_account_username_to">Partager le nom du compte avec…</string>
<string name="status_created_at_now">maintenant</string>
@ -625,4 +625,4 @@
<string name="notification_notification_worker">Récupération des notifications </string>
<string name="notification_prune_cache">Maintenance du cache </string>
<string name="announcement_date">%1$s %2$s</string>
</resources>
</resources>

View File

@ -569,7 +569,7 @@
<string name="select_list_empty">Chan eil liosta agad fhathast</string>
<string name="error_list_load">Mearachd a luchdadh nan liostaichean</string>
<string name="status_filtered_show_anyway">Seall e co-dhiù</string>
<string name="status_filter_placeholder_label_format">Criathraichte: %s</string>
<string name="status_filter_placeholder_label_format">Criathraichte: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Pròifilean</string>
<string name="hint_filter_title">A chriathrag agam</string>
<string name="filter_description_warn">Falaich le rabhadh</string>
@ -602,4 +602,4 @@
<string name="notification_notification_worker">A faighinn nam brathan…</string>
<string name="notification_prune_cache">Obair-ghlèidhidh air an tasgadan…</string>
<string name="error_media_upload_sending_fmt">Dhfhàillig leis an luchdadh suas: %s</string>
</resources>
</resources>

View File

@ -550,7 +550,7 @@
<string name="ui_success_accepted_follow_request">Aceptado o seguimento</string>
<string name="ui_success_rejected_follow_request">Bloqueada a solicitude de seguimento</string>
<string name="status_filtered_show_anyway">Mostrar igualmente</string>
<string name="status_filter_placeholder_label_format">Filtrado: %s</string>
<string name="status_filter_placeholder_label_format">Filtrado: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Perfís</string>
<string name="label_filter_title">Título</string>
<string name="filter_action_warn">Aviso</string>
@ -582,4 +582,4 @@
<string name="error_media_upload_sending_fmt">Fallou a subida: %s</string>
<string name="dialog_delete_filter_positive_action">Eliminar</string>
<string name="dialog_delete_filter_text">Eliminar o filtro \'%1$s\'\?</string>
</resources>
</resources>

View File

@ -545,7 +545,7 @@
<string name="ui_error_vote_fmt">Szavazat leadása a szavazásba sikertelen: %1$s</string>
<string name="ui_error_accept_follow_request">Követési kérelem elfogadása sikertelen: %s</string>
<string name="status_filtered_show_anyway">Mutatás mindenképpen</string>
<string name="status_filter_placeholder_label_format">Szűrve: %s</string>
<string name="status_filter_placeholder_label_format">Szűrve: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Profil</string>
<string name="socket_timeout_exception">A kapcsolatfelvétel a kiszolgálóddal túl sokáig tartott</string>
<string name="ui_error_bookmark_fmt">Bejegyzés könyvjelzőzése sikertelen: %1$s</string>
@ -586,4 +586,4 @@
<string name="error_missing_edits">A kiszolgálód tudja, hogy ezt a bejegyzést szerkesztették, de erről nincs másolata, így ezt nem tudjuk neked megmutatni.
\n
\nEz egy <a href="https://github.com/mastodon/mastodon/issues/25398">Mastodon hiba #25398</a>.</string>
</resources>
</resources>

View File

@ -534,7 +534,7 @@
<string name="dialog_follow_hashtag_hint">#myllumerki</string>
<string name="notification_unknown_name">Óþekkt</string>
<string name="status_filtered_show_anyway">Birta samt</string>
<string name="status_filter_placeholder_label_format">Síað: %s</string>
<string name="status_filter_placeholder_label_format">Síað: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Notendasnið</string>
<string name="pref_title_show_stat_inline">Sýna tölfræði færslu í tímalínu</string>
<string name="ui_error_favourite_fmt">Mistókst að setja færslu í eftirlæti: %1$s</string>
@ -579,4 +579,4 @@
<string name="error_missing_edits">Þjónninn þinn veit að þessari færslu hefur verið breytt, en er hins vegar ekki með afrit af breytingunum, þannig að ekki er hægt að sýna þér þær.
\n
\nÞetta er <a href="https://github.com/mastodon/mastodon/issues/25398">Mastodon verkbeiðni #25398</a>.</string>
</resources>
</resources>

View File

@ -593,7 +593,7 @@
<string name="select_list_manage">Gestisci liste</string>
<string name="error_list_load">Errore nel caricamento delle liste</string>
<string name="status_filtered_show_anyway">Mostra comunque</string>
<string name="status_filter_placeholder_label_format">Filtrato: %s</string>
<string name="status_filter_placeholder_label_format">Filtrato: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Profili</string>
<string name="hint_filter_title">I miei filtri</string>
<string name="action_add">Aggiungi</string>
@ -629,4 +629,4 @@
<string name="title_tab_public_trending_statuses">Post</string>
<string name="pref_update_notification_frequency_once_per_version">Una volta per versione</string>
<string name="update_dialog_title">Un aggiornamento è disponibile</string>
</resources>
</resources>

View File

@ -595,7 +595,7 @@
<string name="pref_title_font_family">フォント</string>
<string name="description_poll">選択肢付きの投票: %1$s, %2$s, %3$s, %4$s; %5$s</string>
<string name="label_image">画像</string>
<string name="status_filter_placeholder_label_format">フィルタ済み: %s</string>
<string name="status_filter_placeholder_label_format">フィルタ済み: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_show_self_boosts_description">自分の投稿をブーストすること</string>
<string name="confirmation_hashtag_unmuted">%s を非表示にしました</string>
<string name="pref_title_show_self_boosts">セルフブーストを表示</string>
@ -613,4 +613,4 @@
<string name="action_translate">翻訳</string>
<string name="update_dialog_title">アップデート可能です</string>
<string name="action_translate_undo">翻訳を元に戻す</string>
</resources>
</resources>

View File

@ -564,7 +564,7 @@
<string name="account_username_copied">Brukernavn kopiert</string>
<string name="error_status_source_load">Kunne ikke laste status fra tjeneren.</string>
<string name="status_filtered_show_anyway">Vis allikevel</string>
<string name="status_filter_placeholder_label_format">Filtrert: %s</string>
<string name="status_filter_placeholder_label_format">Filtrert: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Profiler</string>
<string name="action_add">Legg til</string>
<string name="filter_keyword_display_format">%s (helt ord)</string>
@ -652,4 +652,4 @@
<string name="error_filter_missing_context">Minst én filterkontekst kreves</string>
<string name="error_filter_missing_title">Tittel kreves</string>
<string name="load_newest_statuses">Last inn de nyeste innleggene</string>
</resources>
</resources>

View File

@ -543,7 +543,7 @@
<string name="select_list_manage">Lijsten beheren</string>
<string name="pref_title_account_filter_keywords">Profielen</string>
<string name="status_filtered_show_anyway">Toch tonen</string>
<string name="status_filter_placeholder_label_format">Gefilterd: %s</string>
<string name="status_filter_placeholder_label_format">Gefilterd: &lt;b>%1$s&lt;/b></string>
<string name="hint_filter_title">Mijn filter</string>
<string name="label_filter_action">Filteractie</string>
<string name="filter_action_warn">Waarschuwen</string>
@ -626,4 +626,4 @@
<string name="pref_update_check_no_updates">Er zijn geen updates beschikbaar</string>
<string name="pref_update_next_scheduled_check">Volgende geplande controle: %1$s</string>
<string name="pref_summary_timeline_filters">Je server ondersteund geen filters</string>
</resources>
</resources>

View File

@ -546,7 +546,7 @@
<string name="ui_success_accepted_follow_request">Demanda dabonament acceptada</string>
<string name="ui_success_rejected_follow_request">Demanda dabonament blocada</string>
<string name="status_filtered_show_anyway">Afichar ça que la</string>
<string name="status_filter_placeholder_label_format">Filtrat : %s</string>
<string name="status_filter_placeholder_label_format">Filtrat : &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Perfils</string>
<string name="hint_filter_title">Mon filtre</string>
<string name="label_filter_title">Títol</string>
@ -587,4 +587,4 @@
<string name="notification_notification_worker">Recuperacion de las notificacions…</string>
<string name="notification_prune_cache">Manteniment del cache…</string>
<string name="error_media_upload_sending_fmt">Fracàs del mandadís: %s</string>
</resources>
</resources>

View File

@ -531,7 +531,7 @@
<string name="title_public_trending_links">URL em alta</string>
<string name="title_tab_public_trending_links">URL</string>
<string name="title_public_trending_hashtags">Hashtags em alta</string>
<string name="status_filter_placeholder_label_format">Filtrado(s): %s</string>
<string name="status_filter_placeholder_label_format">Filtrado(s): &lt;b>%1$s&lt;/b></string>
<string name="confirmation_hashtag_unfollowed">#%s deixado de seguir</string>
<string name="ui_error_vote_fmt">Votar na enquete falhou: %1$s</string>
<string name="update_dialog_neutral">Não me lembre desta versão</string>
@ -632,4 +632,4 @@
<string name="load_newest_notifications">Carregar notificações mais recentes</string>
<string name="action_discard">Descartar mudanças</string>
<string name="pref_ui_text_size">Tamanho do texto da UI</string>
</resources>
</resources>

View File

@ -556,7 +556,7 @@
<string name="select_list_manage">Hantera listor</string>
<string name="select_list_empty">Du har inga listor, än</string>
<string name="status_filtered_show_anyway">Visa allafall</string>
<string name="status_filter_placeholder_label_format">Filtrerad: %s</string>
<string name="status_filter_placeholder_label_format">Filtrerad: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Profiler</string>
<string name="label_filter_action">Filteråtgärd</string>
<string name="label_filter_keywords">Nyckelord eller fraser att filtrera</string>
@ -629,4 +629,4 @@
<string name="action_translate_undo">Ångra översättning</string>
<string name="server_repository_error">Kunde inte hämta serverinformation för %1$s: %2$s</string>
<string name="pref_summary_timeline_filters">Din server stöder inte filter</string>
</resources>
</resources>

View File

@ -568,7 +568,7 @@
<string name="filter_action_hide">Gizle</string>
<string name="filter_description_warn">Bir uyarı ile gizle</string>
<string name="status_filtered_show_anyway">Yine de göster</string>
<string name="status_filter_placeholder_label_format">Süzgeçlendi: %s</string>
<string name="status_filter_placeholder_label_format">Süzgeçlendi: &lt;b>%1$s&lt;/b></string>
<string name="filter_edit_keyword_title">Anahtar kelimeyi düzenle</string>
<string name="filter_description_format">%s: %s</string>
<string name="pref_title_show_stat_inline">Gönderi istatistiklerini sğ akışında göster</string>
@ -588,4 +588,4 @@
\nBu <a href="https://github.com/mastodon/mastodon/issues/25398">Mastodon sorununu #25398</a>.</string>
<string name="error_media_upload_sending_fmt">Yükleme başarısız oldu: %s</string>
<string name="error_media_playback">Oynatma başarısız oldu: %s</string>
</resources>
</resources>

View File

@ -566,7 +566,7 @@
<string name="ui_success_accepted_follow_request">Запит на стеження погоджено</string>
<string name="ui_success_rejected_follow_request">Запит на стеження заблоковано</string>
<string name="status_filtered_show_anyway">Усе одно показати</string>
<string name="status_filter_placeholder_label_format">Відфільтровано: %s</string>
<string name="status_filter_placeholder_label_format">Відфільтровано: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Профілі</string>
<string name="label_filter_title">Заголовок</string>
<string name="filter_action_warn">Попередження</string>
@ -602,4 +602,4 @@
\n
\nЦе <a href="https://github.com/mastodon/mastodon/issues/25398">помилка #25398 у Mastodon</a>.</string>
<string name="error_media_upload_sending_fmt">Не вдалося вивантажити: %s</string>
</resources>
</resources>

View File

@ -534,7 +534,7 @@
<string name="ui_success_accepted_follow_request">Đã chấp nhận yêu cầu theo dõi</string>
<string name="ui_success_rejected_follow_request">Đã từ chối yêu cầu theo dõi</string>
<string name="status_filtered_show_anyway">Vẫn hiện</string>
<string name="status_filter_placeholder_label_format">Đã lọc: %s</string>
<string name="status_filter_placeholder_label_format">Đã lọc: &lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">Người</string>
<string name="hint_filter_title">Bộ lọc của tôi</string>
<string name="label_filter_title">Tên bộ lọc</string>
@ -573,4 +573,4 @@
<string name="error_media_playback">Không thể phát: %s</string>
<string name="dialog_delete_filter_text">Xóa bộ lọc \'%1$s\'\?</string>
<string name="dialog_delete_filter_positive_action">Xóa</string>
</resources>
</resources>

View File

@ -548,7 +548,7 @@
<string name="ui_success_accepted_follow_request">关注请求被接受</string>
<string name="ui_success_rejected_follow_request">关注请求被拦截</string>
<string name="status_filtered_show_anyway">仍要显示</string>
<string name="status_filter_placeholder_label_format">已过滤:%s</string>
<string name="status_filter_placeholder_label_format">已过滤:&lt;b>%1$s&lt;/b></string>
<string name="pref_title_account_filter_keywords">个人资料</string>
<string name="hint_filter_title">我的筛选器</string>
<string name="label_filter_title">标题</string>
@ -587,4 +587,4 @@
<string name="error_media_playback">播放失败了:%s</string>
<string name="dialog_delete_filter_text">删除筛选器\'%1$s\'吗?</string>
<string name="dialog_delete_filter_positive_action">删除</string>
</resources>
</resources>

View File

@ -357,7 +357,7 @@
<string name="status_count_one_plus">1+</string>
<string name="status_created_at_now">now</string>
<string name="status_filtered_show_anyway">Show anyway</string>
<string name="status_filter_placeholder_label_format">Filtered: %s</string>
<string name="status_filter_placeholder_label_format">Filtered: &lt;b>%1$s&lt;/b></string>
<string name="state_follow_requested">Follow requested</string>
<!--These are for timestamps on posts. For example: "16s" or "2d"-->
<string name="abbreviated_in_years">in %dy</string>

View File

@ -49,4 +49,7 @@
<item name="action_dismiss_follow_suggestion" type="id" />
<item name="action_follow_account" type="id" />
<item name="action_show_anyway" type="id" />
<item name="action_edit_filter" type="id" />
</resources>