mirror of
https://github.com/pachli/pachli-android.git
synced 2025-02-02 18:37:00 +01:00
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:
parent
7ef692c2c8
commit
6b55d107c1
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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">مُصفّى: <b>%1$s</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>
|
||||
|
@ -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">Адфільтрована: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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">پالوده: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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é : <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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">Dh’fhàillig leis an luchdadh suas: %s</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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ð: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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">フィルタ済み: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -546,7 +546,7 @@
|
||||
<string name="ui_success_accepted_follow_request">Demanda d’abonament acceptada</string>
|
||||
<string name="ui_success_rejected_follow_request">Demanda d’abonament 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 : <b>%1$s</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>
|
||||
|
@ -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): <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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">Відфільтровано: <b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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">已过滤:<b>%1$s</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>
|
||||
|
@ -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: <b>%1$s</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>
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user