Remove ReplacementSpan, display diffs using CharacterStyle (#3431)

Remove the use of ReplacementSpan. It turns out this span type is incompatible with spans that occupy more than one line, and the result is that a longer diff can run off the end of the screen. The alternative means that the diff'd text doesn't have additional padding and rounded corners, but it's better than not being visible.

Display the most recent version of the status with larger text. Again, consistent with the thread view.

Display the avatar, name, and username of the poster in a pinned header at the top of the screen, instead of duplicating the information on every edit. This reduces the amount of redundant information on the screen.
This commit is contained in:
Nik Clayton 2023-06-11 19:12:05 +02:00 committed by GitHub
parent 84486c7f13
commit 66a394245b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 266 additions and 223 deletions

View file

@ -1,8 +1,6 @@
package com.keylesspalace.tusky.components.viewthread.edits
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Typeface.DEFAULT_BOLD
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
@ -11,7 +9,9 @@ import android.text.Html
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.ReplacementSpan
import android.text.TextPaint
import android.text.style.CharacterStyle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -33,11 +33,9 @@ import com.keylesspalace.tusky.util.aspectRatios
import com.keylesspalace.tusky.util.decodeBlurHash
import com.keylesspalace.tusky.util.emojify
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.parseAsMastodonHtml
import com.keylesspalace.tusky.util.setClickableText
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.unicodeWrap
import com.keylesspalace.tusky.util.visible
import com.keylesspalace.tusky.viewdata.toViewData
import org.xml.sax.XMLReader
@ -52,13 +50,28 @@ class ViewEditsAdapter(
private val absoluteTimeFormatter = AbsoluteTimeFormatter()
/** Size of large text in this theme, in px */
var largeTextSizePx: Float = 0f
/** Size of medium text in this theme, in px */
var mediumTextSizePx: Float = 0f
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): BindingHolder<ItemStatusEditBinding> {
val binding = ItemStatusEditBinding.inflate(LayoutInflater.from(parent.context), parent, false)
binding.statusEditMediaPreview.clipToOutline = true
val typedValue = TypedValue()
val context = binding.root.context
val displayMetrics = context.resources.displayMetrics
context.theme.resolveAttribute(R.attr.status_text_large, typedValue, true)
largeTextSizePx = typedValue.getDimension(displayMetrics)
context.theme.resolveAttribute(R.attr.status_text_medium, typedValue, true)
mediumTextSizePx = typedValue.getDimension(displayMetrics)
return BindingHolder(binding)
}
@ -69,24 +82,26 @@ class ViewEditsAdapter(
val context = binding.root.context
val avatarRadius: Int = context.resources
.getDimensionPixelSize(R.dimen.avatar_radius_48dp)
loadAvatar(edit.account.avatar, binding.statusEditAvatar, avatarRadius, animateAvatars)
val infoStringRes = if (position == edits.size - 1) {
val infoStringRes = if (position == edits.lastIndex) {
R.string.status_created_info
} else {
R.string.status_edit_info
}
// Show the most recent version of the status using large text to make it clearer for
// the user, and for similarity with thread view.
val variableTextSize = if (position == edits.lastIndex) {
mediumTextSizePx
} else {
largeTextSizePx
}
binding.statusEditContentWarningDescription.setTextSize(TypedValue.COMPLEX_UNIT_PX, variableTextSize)
binding.statusEditContent.setTextSize(TypedValue.COMPLEX_UNIT_PX, variableTextSize)
binding.statusEditMediaSensitivity.setTextSize(TypedValue.COMPLEX_UNIT_PX, variableTextSize)
val timestamp = absoluteTimeFormatter.format(edit.createdAt, false)
binding.statusEditInfo.text = context.getString(
infoStringRes,
edit.account.name.unicodeWrap(),
timestamp
).emojify(edit.account.emojis, binding.statusEditInfo, animateEmojis)
binding.statusEditInfo.text = context.getString(infoStringRes, timestamp)
if (edit.spoilerText.isEmpty()) {
binding.statusEditContentWarningDescription.hide()
@ -198,6 +213,11 @@ class ViewEditsAdapter(
}
override fun getItemCount() = edits.size
companion object {
private const val VIEW_TYPE_EDITS_NEWEST = 0
private const val VIEW_TYPE_EDITS = 1
}
}
/**
@ -266,98 +286,31 @@ class TuskyTagHandler(val context: Context) : Html.TagHandler {
}
}
/**
* A span that draws text with additional padding at the start/end of the text. The padding
* is the width of [separator].
*
* Note: The separator string is not included in the final text, so it will not be included
* if the user cuts or copies the text.
*/
open class LRPaddedSpan(val separator: String = " ") : ReplacementSpan() {
/** The width of the separator string, used as padding */
var paddingWidth = 0f
/** Measured width of the span */
var spanWidth = 0f
override fun getSize(
paint: Paint,
text: CharSequence?,
start: Int,
end: Int,
fm: Paint.FontMetricsInt?
): Int {
paddingWidth = paint.measureText(separator, 0, separator.length)
spanWidth = (paddingWidth * 2) + paint.measureText(text, start, end)
return spanWidth.toInt()
}
override fun draw(
canvas: Canvas,
text: CharSequence?,
start: Int,
end: Int,
x: Float,
top: Int,
y: Int,
bottom: Int,
paint: Paint
) {
canvas.drawText(text?.subSequence(start, end).toString(), x + paddingWidth, y.toFloat(), paint)
}
}
/** Span that signifies deleted text */
class DeletedTextSpan(context: Context) : LRPaddedSpan() {
private val bgPaint = Paint()
val radius: Float
class DeletedTextSpan(context: Context) : CharacterStyle() {
private var bgColor: Int
init {
bgPaint.color = context.getColor(R.color.view_edits_background_delete)
radius = context.resources.getDimension(R.dimen.lrPaddedSpanRadius)
bgColor = context.getColor(R.color.view_edits_background_delete)
}
override fun draw(
canvas: Canvas,
text: CharSequence?,
start: Int,
end: Int,
x: Float,
top: Int,
y: Int,
bottom: Int,
paint: Paint
) {
canvas.drawRoundRect(x, top.toFloat(), x + spanWidth, bottom.toFloat(), radius, radius, bgPaint)
paint.isStrikeThruText = true
super.draw(canvas, text, start, end, x, top, y, bottom, paint)
override fun updateDrawState(tp: TextPaint) {
tp.bgColor = bgColor
tp.isStrikeThruText = true
}
}
/** Span that signifies inserted text */
class InsertedTextSpan(context: Context) : LRPaddedSpan() {
val bgPaint = Paint()
val radius: Float
class InsertedTextSpan(context: Context) : CharacterStyle() {
private var bgColor: Int
init {
bgPaint.color = context.getColor(R.color.view_edits_background_insert)
radius = context.resources.getDimension(R.dimen.lrPaddedSpanRadius)
bgColor = context.getColor(R.color.view_edits_background_insert)
}
override fun draw(
canvas: Canvas,
text: CharSequence?,
start: Int,
end: Int,
x: Float,
top: Int,
y: Int,
bottom: Int,
paint: Paint
) {
canvas.drawRoundRect(x, top.toFloat(), x + spanWidth, bottom.toFloat(), radius, radius, bgPaint)
paint.typeface = DEFAULT_BOLD
super.draw(canvas, text, start, end, x, top, y, bottom, paint)
override fun updateDrawState(tp: TextPaint) {
tp.bgColor = bgColor
tp.typeface = DEFAULT_BOLD
}
}

View file

@ -37,13 +37,16 @@ import com.keylesspalace.tusky.BottomSheetActivity
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.StatusListActivity
import com.keylesspalace.tusky.components.account.AccountActivity
import com.keylesspalace.tusky.databinding.FragmentViewThreadBinding
import com.keylesspalace.tusky.databinding.FragmentViewEditsBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.emojify
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.unicodeWrap
import com.keylesspalace.tusky.util.viewBinding
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
@ -54,7 +57,7 @@ import java.io.IOException
import javax.inject.Inject
class ViewEditsFragment :
Fragment(R.layout.fragment_view_thread),
Fragment(R.layout.fragment_view_edits),
LinkListener,
OnRefreshListener,
MenuProvider,
@ -65,7 +68,7 @@ class ViewEditsFragment :
private val viewModel: ViewEditsViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(FragmentViewThreadBinding::bind)
private val binding by viewBinding(FragmentViewEditsBinding::bind)
private lateinit var statusId: String
@ -88,6 +91,7 @@ class ViewEditsFragment :
val animateAvatars = preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false)
val animateEmojis = preferences.getBoolean(PrefKeys.ANIMATE_CUSTOM_EMOJIS, false)
val useBlurhash = preferences.getBoolean(PrefKeys.USE_BLURHASH, true)
val avatarRadius: Int = requireContext().resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp)
viewLifecycleOwner.lifecycleScope.launch {
viewModel.uiState.collect { uiState ->
@ -130,6 +134,15 @@ class ViewEditsFragment :
useBlurhash = useBlurhash,
listener = this@ViewEditsFragment
)
// Focus on the most recent version
(binding.recyclerView.layoutManager as LinearLayoutManager).scrollToPosition(0)
val account = uiState.edits.first().account
loadAvatar(account.avatar, binding.statusAvatar, avatarRadius, animateAvatars)
binding.statusDisplayName.text = account.name.unicodeWrap().emojify(account.emojis, binding.statusDisplayName, animateEmojis)
binding.statusUsername.text = account.username
}
}
}

View file

@ -98,10 +98,7 @@ class ViewEditsViewModel @Inject constructor(private val api: MastodonApi) : Vie
if (i < sortedEdits.size - 1) {
currentContent = previousContent
previousContent = loader.load(
sortedEdits[i + 1].content.replace(
"<br>",
"<br/>"
)
sortedEdits[i + 1].content.replace("<br>", "<br/>")
)
}
}

View file

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/status_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:contentDescription="@string/action_view_profile"
android:importantForAccessibility="no"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/avatar_default" />
<ImageView
android:id="@+id/status_avatar_inset"
android:layout_width="24dp"
android:layout_height="24dp"
android:contentDescription="@null"
android:importantForAccessibility="no"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="@id/status_avatar"
app:layout_constraintEnd_toEndOf="@id/status_avatar"
tools:src="#000"
tools:visibility="visible" />
<TextView
android:id="@+id/status_display_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:ellipsize="end"
android:importantForAccessibility="no"
android:maxLines="1"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_large"
android:textStyle="normal|bold"
app:layout_constrainedWidth="true"
app:layout_constraintStart_toEndOf="@id/status_avatar"
app:layout_constraintTop_toTopOf="@+id/status_avatar"
tools:text="Ente r the void you foooooo"
tools:ignore="SelectableText"/>
<TextView
android:id="@+id/status_username"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:importantForAccessibility="no"
android:maxLines="1"
android:textColor="?android:textColorSecondary"
android:textSize="?attr/status_text_medium"
app:layout_constraintStart_toStartOf="@+id/status_display_name"
app:layout_constraintTop_toBottomOf="@id/status_display_name"
tools:text="\@Entenhausen@birbsarecooooooooooool.site"
tools:ignore="SelectableText" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_weight="1"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/status_avatar"
app:layout_constraintVertical_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/colorBackground"
android:scrollbars="vertical" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
<ProgressBar
android:id="@+id/initialProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:indeterminate="true"
android:layout_gravity="center"
android:contentDescription="@string/a11y_label_loading_thread" />
<com.keylesspalace.tusky.view.BackgroundMessageView
android:id="@+id/statusView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" >
</com.keylesspalace.tusky.view.BackgroundMessageView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -6,33 +6,21 @@
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="6dp">
<ImageView
android:id="@+id/status_edit_avatar"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="14dp"
android:layout_marginTop="14dp"
android:contentDescription="@string/action_view_profile"
android:importantForAccessibility="no"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/avatar_default" />
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingBottom="8dp">
<TextView
android:id="@+id/status_edit_info"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="10dp"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_medium"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/status_edit_avatar"
app:layout_constraintTop_toTopOf="parent"
tools:text="\@Tusky edited 18th December 2022" />
@ -40,34 +28,27 @@
android:id="@+id/status_edit_content_warning_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_medium"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="@+id/status_edit_info"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_edit_avatar"
app:layout_constraintTop_toBottomOf="@+id/status_edit_info"
tools:text="content warning which is very long and it doesn't fit"
tools:visibility="visible" />
<View
android:id="@+id/status_edit_content_warning_separator"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="14dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="4dp"
android:background="?android:textColorPrimary"
android:importantForAccessibility="no"
android:paddingLeft="16dp"
android:paddingRight="16dp"
app:layout_constraintEnd_toEndOf="@+id/status_edit_content_warning_description"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_edit_content_warning_description" />
@ -75,62 +56,52 @@
android:id="@+id/status_edit_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="4dp"
android:focusable="true"
android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorPrimary"
android:textSize="?attr/status_text_medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="@+id/status_edit_info"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_edit_content_warning_separator"
tools:text="This is an edited status" />
<com.keylesspalace.tusky.view.MediaPreviewLayout
android:id="@+id/status_edit_media_preview"
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="@dimen/status_media_preview_margin_top"
android:layout_marginEnd="14dp"
android:layout_marginBottom="6dp"
android:layout_marginTop="4dp"
android:background="@drawable/media_preview_outline"
android:importantForAccessibility="noHideDescendants"
app:layout_constraintEnd_toEndOf="@id/status_edit_info"
app:layout_constraintStart_toStartOf="@+id/status_edit_content_warning_description"
app:layout_constraintTop_toBottomOf="@id/status_edit_content" />
<TextView
android:id="@+id/status_edit_media_sensitivity"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="6dp"
android:layout_marginTop="4dp"
android:text="@string/post_sensitive_media_title"
android:textColor="?android:attr/textColorTertiary"
android:textSize="?attr/status_text_medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="@+id/status_edit_info"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_edit_media_preview" />
<!-- hidden because as of Mastodon 4.0.2 we don't get this info via the api -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/status_edit_poll_options"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="14dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="14dp"
android:layout_marginBottom="4dp"
android:nestedScrollingEnabled="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="@+id/status_edit_info"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status_edit_media_sensitivity" />
<!-- hidden because as of Mastodon 4.0.2 we don't get this info via the api -->
<TextView
android:id="@+id/status_edit_poll_description"
android:layout_width="0dp"

View file

@ -577,8 +577,8 @@
<string name="no_lists">ليس لديك أي قوائم.</string>
<string name="post_edited">عدَّلَ %s</string>
<string name="notification_report_format">شكوى جديدة عن %s</string>
<string name="status_edit_info">عدّله %1$s في %2$s</string>
<string name="status_created_info">أنشأه %1$s في %2$s</string>
<string name="status_edit_info">عدّله %1$s</string>
<string name="status_created_info">أنشأه %1$s</string>
<string name="wellbeing_mode_notice">سيتم إخفاء بعض المعلومات التي قد تؤثر على صحتك العقلية. هذا يتضمن:
\n
\n- المفضلة/المشاركات/متابعة الاشعارات

View file

@ -572,8 +572,8 @@
<string name="account_date_joined">Далучыўся(-лася) %1$s</string>
<string name="account_note_saved">Захавана!</string>
<string name="dialog_push_notification_migration_other_accounts">Вы паўторна зайшлі ў бягучы ўліковы запіс, каб дазволіць Tusky падпісацца на push-апавяшчэнні. Але ў Вас яшчэ засталіся ўліковыя запісы, якія не мігрыравалі такім чынам. Пераключыцеся на іх і зайдзіце паўторна, каб уключыць падтрымку апавяшчэнняў праз UnifiedPush.</string>
<string name="status_edit_info">%1$s адрэдагаваў(-ла) %2$s</string>
<string name="status_created_info">%1$s стварыў(-ла) %2$s</string>
<string name="status_edit_info">%1$s адрэдагаваў(-ла)</string>
<string name="status_created_info">%1$s стварыў(-ла)</string>
<string name="pref_title_hide_top_toolbar">Схаваць загаловак верхняй панэлі інструментаў</string>
<string name="account_note_hint">Ваша асабістая нататка пра гэты ўліковы запіс</string>
<string name="pref_title_confirm_favourites">Патрабаваць пацвярджэнне перад упадабаннем</string>

View file

@ -617,12 +617,12 @@
<string name="dialog_push_notification_migration">Per utilitzar les notificacions push mitjançant UnifiedPush, Tusky necessita permís per subscriure\'s a les notificacions al vostre servidor Mastodon. Això requereix un nou inici de sessió per canviar els àmbits d\'OAuth concedits a Tusky. Si feu servir l\'opció de tornar a iniciar sessió aquí o a les preferències del compte, es conservaran tots els esborranys locals i la memòria cau.</string>
<string name="tips_push_notification_migration">Torneu a iniciar sessió a tots els comptes per activar el suport de notificacions push.</string>
<string name="description_post_edited">Editat</string>
<string name="status_edit_info">%1$s ha editat %2$s</string>
<string name="status_edit_info">%1$s ha editat</string>
<string name="action_subscribe_account">Subscriu-te</string>
<string name="action_unsubscribe_account">Cancel·la la subscripció</string>
<string name="instance_rule_title">%s regles</string>
<string name="mute_notifications_switch">Silencia les notificacions</string>
<string name="status_created_info">%1$s ha creat %2$s</string>
<string name="status_created_info">%1$s ha creat</string>
<string name="title_public_trending_hashtags">Hashtags populars</string>
<string name="accessibility_talking_about_tag">%1$d persones parlen del hashtag %2$s</string>
<string name="total_usage">Ús total</string>

View file

@ -636,8 +636,8 @@
<item quantity="other">Disgrifiwch y cynnwys ar gyfer pobl â nam ar eu golwg (terfyn nodau o %d)</item>
</plurals>
<string name="action_continue_edit">Parhau i olygu</string>
<string name="status_edit_info">Golygodd %1$s %2$s</string>
<string name="status_created_info">Creodd %1$s %2$s</string>
<string name="status_edit_info">Golygodd %1$s</string>
<string name="status_created_info">Creodd %1$s</string>
<string name="title_edits">Golygiadau</string>
<string name="post_media_alt">AMGEN</string>
<string name="action_discard">Hepgor newidiadau</string>

View file

@ -613,8 +613,8 @@
<string name="send_account_link_to">Profil-Link teilen an </string>
<string name="send_account_username_to">Profilname teilen an </string>
<string name="account_username_copied">Profilname kopiert</string>
<string name="status_edit_info">%1$s bearbeitete %2$s</string>
<string name="status_created_info">%1$s erstellte %2$s</string>
<string name="status_edit_info">%1$s bearbeitete</string>
<string name="status_created_info">%1$s erstellte</string>
<string name="notification_report_format">Neue Meldung über %s</string>
<string name="notification_report_description">Benachrichtigungen über Moderationsmeldungen</string>
<string name="pref_title_notification_filter_reports">es eine neue Meldung gibt</string>

View file

@ -621,8 +621,8 @@
<string name="pref_title_reading_order">Orden de lectura</string>
<string name="pref_reading_order_oldest_first">Más antiguas primero</string>
<string name="pref_reading_order_newest_first">Más recientes primero</string>
<string name="status_edit_info">%1$s ha editado %2$s</string>
<string name="status_created_info">%1$s ha editado %2$s</string>
<string name="status_edit_info">%1$s ha editado</string>
<string name="status_created_info">%1$s ha editado</string>
<string name="pref_summary_http_proxy_disabled">Desactivado</string>
<string name="pref_summary_http_proxy_missing">&lt;sin establecer&gt;</string>
<string name="pref_summary_http_proxy_invalid">&lt;inválido&gt;</string>

View file

@ -595,8 +595,8 @@
<string name="pref_summary_http_proxy_invalid">&lt;نامعتبر&gt;</string>
<string name="pref_title_reading_order">ترتیب خواندن</string>
<string name="pref_reading_order_newest_first">نخست جدیدترین</string>
<string name="status_edit_info">%1$s %2$s را ویراست</string>
<string name="status_created_info">%1$s %2$s را ایجاد کرد</string>
<string name="status_edit_info">%1$s را ویراست</string>
<string name="status_created_info">%1$s را ایجاد کرد</string>
<string name="action_post_failed">بارگذاری شکست خورد</string>
<string name="action_post_failed_show_drafts">نمایش پیش‌نویس‌ها</string>
<string name="action_post_failed_do_nothing">رد کردن</string>

View file

@ -626,8 +626,8 @@
<string name="pref_reading_order_newest_first">Les plus récents en premier</string>
<string name="action_unfollow_hashtag_format">Arrêter de suivre #%s \?</string>
<string name="failed_to_pin">Échec de l\'épinglage</string>
<string name="status_edit_info">Modification de %1$s le %2$s</string>
<string name="status_created_info">Création par %1$s le %2$s</string>
<string name="status_edit_info">Modification de %1$s</string>
<string name="status_created_info">Création par %1$s</string>
<string name="compose_save_draft_loses_media">Enregistrer comme brouillon \? (Les pièces jointes seront à nouveau téléchargées lorsque le brouillon sera réouvert.)</string>
<string name="no_lists">Vous n\'avez aucune liste.</string>
<string name="language_display_name_format">%s (%s)</string>

View file

@ -594,8 +594,8 @@
<string name="title_edits">Deasachaidhean</string>
<string name="status_created_at_now">an-dràsta</string>
<string name="pref_default_post_language">Cànan bunaiteach nam post</string>
<string name="status_created_info">Chruthaich %1$s %2$s</string>
<string name="status_edit_info">Dheasaich %1$s %2$s</string>
<string name="status_created_info">Chruthaich %1$s</string>
<string name="status_edit_info">Dheasaich %1$s</string>
<string name="no_lists">Chan eil liosta sam bith agad.</string>
<string name="language_display_name_format">%s (%s)</string>
<string name="pref_title_http_proxy_port_message">Bu chòir dhan phort a bhith eadar %d is %d</string>

View file

@ -584,8 +584,8 @@
<string name="a11y_label_loading_thread">Cargando fío</string>
<string name="mute_notifications_switch">Acalar notificacións</string>
<string name="title_edits">Edicións</string>
<string name="status_edit_info">Editado por %1$s o %2$s</string>
<string name="status_created_info">Creado por %1$s o %2$s</string>
<string name="status_edit_info">Editado por %1$s</string>
<string name="status_created_info">Creado por %1$s</string>
<string name="action_discard">Desbotar cambios</string>
<string name="action_continue_edit">Continuar a edición</string>
<string name="compose_unsaved_changes">Hai cambios non gardados.</string>

View file

@ -599,8 +599,8 @@
<string name="pref_summary_http_proxy_missing">&lt;nincs beállítva&gt;</string>
<string name="pref_summary_http_proxy_invalid">&lt;érvénytelen&gt;</string>
<string name="title_edits">Szerkesztések</string>
<string name="status_created_info">%1$s létrehozta %2$s</string>
<string name="status_edit_info">%1$s szerkesztette %2$s</string>
<string name="status_created_info">%1$s létrehozta</string>
<string name="status_edit_info">%1$s szerkesztette</string>
<string name="post_media_alt">ALT</string>
<string name="action_discard">Változtatások elvetése</string>
<string name="action_continue_edit">Szerkesztés folytatása</string>

View file

@ -589,8 +589,8 @@
<string name="pref_summary_http_proxy_missing">&lt;ekki stillt&gt;</string>
<string name="pref_summary_http_proxy_invalid">&lt;ógilt&gt;</string>
<string name="title_edits">Breytingar</string>
<string name="status_created_info">%1$s bjó til %2$s</string>
<string name="status_edit_info">%1$s breytti %2$s</string>
<string name="status_created_info">%1$s bjó til</string>
<string name="status_edit_info">%1$s breytti</string>
<string name="post_media_alt">AUKA</string>
<string name="action_discard">Henda breytingum</string>
<string name="action_continue_edit">Halda breytingum áfram</string>

View file

@ -610,8 +610,8 @@
<string name="mute_notifications_switch">Silenzia notifiche</string>
<string name="title_edits">Modifiche</string>
<string name="report_category_spam">Spam</string>
<string name="status_edit_info">%1$s ha modificato %2$s</string>
<string name="status_created_info">%1$s ha creato %2$s</string>
<string name="status_edit_info">%1$s ha modificato</string>
<string name="status_created_info">%1$s ha creato</string>
<string name="report_category_other">Altro</string>
<string name="action_unfollow_hashtag_format">Smettere di seguire #%s\?</string>
<string name="action_post_failed">Caricamento fallito</string>

View file

@ -587,8 +587,8 @@
<string name="set_focus_description">サムネイル画像で常に表示される中心点を設定するには、円をタップまたはドラッグして中してくだだい。</string>
<string name="mute_notifications_switch">通知のミュート</string>
<string name="account_date_joined">%1$s に参加</string>
<string name="status_edit_info">%1$s 編集 %2$s</string>
<string name="status_created_info">%1$s の投稿 %2$s</string>
<string name="status_edit_info">%1$s 編集</string>
<string name="status_created_info">%1$s の投稿</string>
<string name="post_lookup_error_format">投稿 %s の検索エラー</string>
<string name="follow_requests_info">アカウントがロックされていなかったとしても、%1$s のスタッフは以下のアカウントのフォローリクエストを確認した方がいいと判断しました。</string>
<string name="action_set_focus">中心点の設定</string>

View file

@ -514,7 +514,7 @@
</plurals>
<string name="pref_reading_order_oldest_first">Vecākos vispirms</string>
<string name="pref_reading_order_newest_first">Jaunākos vispirms</string>
<string name="status_created_info">%1$s izveidoja %2$s</string>
<string name="status_created_info">%1$s izveidoja</string>
<plurals name="poll_info_people">
<item quantity="zero">%s personas</item>
<item quantity="one">%s persona</item>
@ -544,7 +544,7 @@
<string name="action_post_failed_show_drafts">Rādīt melnrakstus</string>
<string name="action_post_failed_do_nothing">Aizvākt</string>
<string name="edit_hashtag_hint">Tēmturis bez #</string>
<string name="status_edit_info">%1$s laboja %2$s</string>
<string name="status_edit_info">%1$s laboja</string>
<string name="action_browser_login">Pieslēgties ar pārlūku</string>
<string name="description_login">Strādā vairumā gadījumu. Dati netiek nopludināti uz citām lietotnēm.</string>
<string name="poll_info_time_absolute">beidzas %s</string>

View file

@ -569,8 +569,8 @@
<string name="pref_default_post_language">Standaardtaal van berichten</string>
<string name="notification_report_name">Rapporten</string>
<string name="description_post_edited">Bewerkt</string>
<string name="status_edit_info">%1$s bewerkte %2$s</string>
<string name="status_created_info">%1$s maakte %2$s</string>
<string name="status_edit_info">%1$s bewerkte</string>
<string name="status_created_info">%1$s maakte</string>
<string name="instance_rule_info">Door in te loggen ben je het eens met de regels van %s.</string>
<string name="report_category_spam">Spam</string>
<string name="report_category_other">Overig</string>

View file

@ -590,9 +590,9 @@
<string name="description_post_edited">Modificada</string>
<string name="error_status_source_load">Fracàs del cargament de lestatut a partir del servidor.</string>
<string name="mute_notifications_switch">Amudir las notificacions</string>
<string name="status_created_info">%1$s creèt %2$s</string>
<string name="status_created_info">%1$s creèt</string>
<string name="title_edits">Modificacions</string>
<string name="status_edit_info">%1$s modifiquèt %2$s</string>
<string name="status_edit_info">%1$s modifiquèt</string>
<string name="post_media_alt">ALT</string>
<string name="action_discard">Ignorar las modificacions</string>
<string name="action_continue_edit">Téner de modificar</string>

View file

@ -602,8 +602,8 @@
<string name="pref_reading_order_newest_first">Najpierw najnowsze</string>
<string name="no_lists">Nie masz żadnych list.</string>
<string name="mute_notifications_switch">Wycisz powiadomienia</string>
<string name="status_edit_info">%1$s edytował %2$s</string>
<string name="status_created_info">%1$s stworzył %2$s</string>
<string name="status_edit_info">%1$s edytował</string>
<string name="status_created_info">%1$s stworzył</string>
<string name="title_edits">Edycje</string>
<string name="compose_unsaved_changes">Masz niezapisane zmiany.</string>
<string name="instance_rule_title">%s regulamin</string>

View file

@ -562,7 +562,7 @@
<string name="failed_to_unpin">Falha ao desafixar</string>
<string name="compose_save_draft_loses_media">Salvar rascunho\? (Os anexos serão reenviados assim que você restaurar o rascunho.)</string>
<string name="tips_push_notification_migration">Faça login novamente em todas as contas para habilitar o suporte de notificação push.</string>
<string name="status_created_info">%1$s publicou em %2$s</string>
<string name="status_created_info">%1$s publicou</string>
<string name="title_edits">Edições</string>
<string name="pref_default_post_language">Idioma padrão dos toots</string>
<string name="pref_title_notification_filter_reports">há uma nova denúncia</string>
@ -587,7 +587,7 @@
<string name="description_login">Funciona na maioria dos casos. Nenhum dado é vazado para outros aplicativos.</string>
<string name="description_browser_login">Pode oferecer suporte a métodos de autenticação adicionais, mas requer um navegador compatível.</string>
<string name="failed_to_remove_from_list">Falha ao remover a conta da lista</string>
<string name="status_edit_info">%1$s editou em %2$s</string>
<string name="status_edit_info">%1$s editou</string>
<string name="action_continue_edit">Continuar editando</string>
<string name="compose_unsaved_changes">Você tem alterações não salvas.</string>
<string name="description_post_edited">Editado</string>

View file

@ -540,8 +540,8 @@
<string name="a11y_label_loading_thread">Загрузка ветки</string>
<string name="pref_reading_order_newest_first">Сначала новые</string>
<string name="title_edits">Правки</string>
<string name="status_edit_info">%1$s отредактировали %2$s</string>
<string name="status_created_info">%1$s создали %2$s</string>
<string name="status_edit_info">%1$s отредактировали</string>
<string name="status_created_info">%1$s создали</string>
<string name="title_login">Войти</string>
<string name="action_browser_login">Вход через Браузер</string>
</resources>

View file

@ -508,8 +508,8 @@
<string name="action_post_failed_do_nothing">उत्सृज्यताम्</string>
<string name="action_post_failed_show_drafts">लेखविकर्षान् दर्शयतु</string>
<string name="description_post_edited">सम्पादनं कृतम्</string>
<string name="status_created_info">%1$s निर्मितम् %2$s</string>
<string name="status_edit_info">%1$s सम्पादितम् %2$s</string>
<string name="status_created_info">%1$s निर्मितम्</string>
<string name="status_edit_info">%1$s सम्पादितम्</string>
<string name="action_subscribe_account">ग्राहकता</string>
<string name="draft_deleted">प्रारूपं निष्कासितम्</string>
<string name="report_category_violation">नियम-उल्लङ्घनम्</string>

View file

@ -602,13 +602,13 @@
<string name="a11y_label_loading_thread">Laddar tråd</string>
<string name="mute_notifications_switch">Tysta notiser</string>
<string name="title_edits">Redigeringar</string>
<string name="status_edit_info">%1$s redigerade %2$s</string>
<string name="status_edit_info">%1$s redigerade</string>
<string name="action_share_account_link">Dela länk med konto</string>
<string name="action_share_account_username">Dela användarnamn för konto</string>
<string name="send_account_link_to">Dela konto-URL med…</string>
<string name="send_account_username_to">Dela kontots användarnamn med…</string>
<string name="account_username_copied">Kopierade användarnamn</string>
<string name="status_created_info">%1$s skapade %2$s</string>
<string name="status_created_info">%1$s skapade</string>
<string name="action_discard">Förkasta ändringar</string>
<string name="action_continue_edit">Fortsätt redigera</string>
<string name="compose_unsaved_changes">Du har ändringar som inte sparats.</string>

View file

@ -598,11 +598,11 @@
<string name="pref_summary_http_proxy_missing">&lt;ayarlanmadı&gt;</string>
<string name="pref_summary_http_proxy_invalid">&lt;geçersiz&gt;</string>
<string name="pref_summary_http_proxy_disabled">Etkisizleştirildi</string>
<string name="status_created_info">%1$s oluşturdu %2$s</string>
<string name="status_created_info">%1$s oluşturdu</string>
<string name="dialog_follow_hashtag_title">Etiketi takip et</string>
<string name="dialog_follow_hashtag_hint">#etiket</string>
<string name="compose_unsaved_changes">Kaydedilmemiş değişikliklerin var.</string>
<string name="status_edit_info">%1$s düzenledi %2$s</string>
<string name="status_edit_info">%1$s düzenledi</string>
<string name="action_refresh">Yenile</string>
<string name="title_edits">Düzenlemeler</string>
<string name="hint_description">ıklama</string>

View file

@ -610,8 +610,8 @@
<string name="action_continue_edit">Продовжити редагування</string>
<string name="mute_notifications_switch">Беззвучні сповіщення</string>
<string name="title_edits">Редагування</string>
<string name="status_edit_info">%1$s редагує %2$s</string>
<string name="status_created_info">%1$s створює %2$s</string>
<string name="status_edit_info">%1$s редагує</string>
<string name="status_created_info">%1$s створює</string>
<string name="a11y_label_loading_thread">Завантаження стрічки</string>
<string name="action_share_account_link">Поділитися посиланням на обліковий запис</string>
<string name="action_share_account_username">Поділитися іменем користувача облікового запису</string>

View file

@ -574,8 +574,8 @@
<string name="action_continue_edit">Tiếp tục sửa</string>
<string name="compose_unsaved_changes">Thay đổi chưa được lưu.</string>
<string name="mute_notifications_switch">Ẩn thông báo</string>
<string name="status_edit_info">%1$s sửa %2$s</string>
<string name="status_created_info">%1$s đăng %2$s</string>
<string name="status_edit_info">%1$s sửa</string>
<string name="status_created_info">%1$s đăng</string>
<string name="title_edits">Những lượt sửa tút</string>
<string name="a11y_label_loading_thread">Đang tải thảo luận</string>
<string name="action_share_account_link">Chia sẻ URL người dùng</string>

View file

@ -591,10 +591,10 @@
<string name="action_discard">放弃更改</string>
<string name="action_continue_edit">继续编辑</string>
<string name="compose_unsaved_changes">你有未保存的更改。</string>
<string name="status_created_info">%1$s 创建了 %2$s</string>
<string name="status_created_info">%1$s 创建了</string>
<string name="mute_notifications_switch">将通知静音</string>
<string name="title_edits">编辑</string>
<string name="status_edit_info">%1$s 编辑了 %2$s</string>
<string name="status_edit_info">%1$s 编辑了</string>
<string name="a11y_label_loading_thread">加载帖子</string>
<string name="action_share_account_link">分享账户链接</string>
<string name="action_share_account_username">分享账户用户名</string>

View file

@ -63,7 +63,4 @@
<dimen name="graph_line_thickness">1dp</dimen>
<dimen name="minimum_touch_target">48dp</dimen>
<dimen name="lrPaddedSpanRadius">4dp</dimen>
</resources>

View file

@ -764,9 +764,9 @@
<string name="pref_reading_order_newest_first">Newest first</string>
<!--@Tusky edited 19th December 2022 13:37 -->
<string name="status_edit_info">%1$s edited %2$s</string>
<string name="status_edit_info">Edited: %1$s</string>
<!--@Tusky created 19th December 2022 13:12 -->
<string name="status_created_info">%1$s created %2$s</string>
<string name="status_created_info">Created: %1$s</string>
<string name="a11y_label_loading_thread">Loading thread</string>
<!--@knossos@fosstodon.org created 2023-01-07 -->