3488 improve profile list (#3507)

Fixes #3488 

Working with lists from a profile page and in the normal "lists view"
from the drawer now use the same fragment view code.

(also) RFC regarding joining different list lists


![grafik](https://user-images.githubusercontent.com/1618905/229463168-397bd943-82d8-4e05-a8bf-9fcf22f6c1f9.png)
This commit is contained in:
UlrichKu 2024-01-03 21:17:03 +01:00 committed by GitHub
parent 6494247301
commit 0698333665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 250 additions and 380 deletions

View File

@ -1,4 +1,4 @@
/* Copyright 2017 Andrew Dawson
/* Copyright Tusky contributors
*
* This file is a part of Tusky.
*
@ -23,9 +23,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.PopupMenu
import android.widget.TextView
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
@ -35,14 +33,14 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.color.MaterialColors
import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.databinding.ActivityListsBinding
import com.keylesspalace.tusky.databinding.DialogListBinding
import com.keylesspalace.tusky.databinding.ItemListBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.util.BindingHolder
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding
@ -54,18 +52,12 @@ import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.ERROR_OTHER
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.INITIAL
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADED
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADING
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import kotlinx.coroutines.launch
import javax.inject.Inject
/**
* Created by charlag on 1/4/18.
*/
// TODO use the ListSelectionFragment (and/or its adapter or binding) here; but keep the LoadingState from here (?)
class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
@ -214,9 +206,9 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
).show()
}
private fun onListSelected(listId: String, listTitle: String) {
private fun onListSelected(list: MastoList) {
startActivityWithSlideInAnimation(
StatusListActivity.newListIntent(this, listId, listTitle)
StatusListActivity.newListIntent(this, list.id, list.title)
)
}
@ -255,42 +247,28 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
}
private inner class ListsAdapter :
ListAdapter<MastoList, ListsAdapter.ListViewHolder>(ListsDiffer) {
ListAdapter<MastoList, BindingHolder<ItemListBinding>>(ListsDiffer) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
return LayoutInflater.from(parent.context).inflate(R.layout.item_list, parent, false)
.let(this::ListViewHolder)
.apply {
val iconColor = MaterialColors.getColor(nameTextView, android.R.attr.textColorTertiary)
val context = nameTextView.context
val icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_list).apply { sizeDp = 20; colorInt = iconColor }
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): BindingHolder<ItemListBinding> {
return BindingHolder(ItemListBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
nameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null)
override fun onBindViewHolder(holder: BindingHolder<ItemListBinding>, position: Int) {
val item = getItem(position)
holder.binding.listName.text = item.title
holder.binding.moreButton.apply {
visible(true)
setOnClickListener {
onMore(item, holder.binding.moreButton)
}
}
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
holder.nameTextView.text = getItem(position).title
}
private inner class ListViewHolder(view: View) :
RecyclerView.ViewHolder(view),
View.OnClickListener {
val nameTextView: TextView = view.findViewById(R.id.list_name_textview)
val moreButton: ImageButton = view.findViewById(R.id.editListButton)
init {
view.setOnClickListener(this)
moreButton.setOnClickListener(this)
}
override fun onClick(v: View) {
if (v == itemView) {
val list = getItem(bindingAdapterPosition)
onListSelected(list.id, list.title)
} else {
onMore(getItem(bindingAdapterPosition), v)
}
holder.itemView.setOnClickListener {
onListSelected(item)
}
}
}

View File

@ -15,18 +15,10 @@
package com.keylesspalace.tusky
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatEditText
@ -38,34 +30,29 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.transition.TransitionManager
import at.connyduck.calladapter.networkresult.fold
import at.connyduck.sparkbutton.helpers.Utils
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialArcMotion
import com.google.android.material.transition.MaterialContainerTransform
import com.keylesspalace.tusky.adapter.ItemInteractionListener
import com.keylesspalace.tusky.adapter.TabAdapter
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.MainTabsChangedEvent
import com.keylesspalace.tusky.components.account.list.ListSelectionFragment
import com.keylesspalace.tusky.databinding.ActivityTabPreferenceBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.getDimension
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.unsafeLazy
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible
import kotlinx.coroutines.CoroutineStart
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.regex.Pattern
import javax.inject.Inject
class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListener {
class TabPreferenceActivity : BaseActivity(), Injectable, HasAndroidInjector, ItemInteractionListener, ListSelectionFragment.ListSelectionListener {
@Inject
lateinit var mastodonApi: MastodonApi
@ -73,6 +60,9 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
@Inject
lateinit var eventHub: EventHub
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
private val binding by viewBinding(ActivityTabPreferenceBinding::inflate)
private lateinit var currentTabs: MutableList<TabData>
@ -267,81 +257,24 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
editText.requestFocus()
}
private var listSelectDialog: ListSelectionFragment? = null
private fun showSelectListDialog() {
val adapter = object : ArrayAdapter<MastoList>(this, android.R.layout.simple_list_item_1) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
getItem(position)?.let { item -> (view as TextView).text = item.title }
return view
}
}
listSelectDialog = ListSelectionFragment.newInstance(null)
listSelectDialog?.show(supportFragmentManager, null)
val statusLayout = LinearLayout(this)
statusLayout.gravity = Gravity.CENTER
val progress = ProgressBar(this)
val preferredPadding = getDimension(this, androidx.appcompat.R.attr.dialogPreferredPadding)
progress.setPadding(preferredPadding, 0, preferredPadding, 0)
progress.visible(false)
val noListsText = TextView(this)
noListsText.setPadding(preferredPadding, 0, preferredPadding, 0)
noListsText.text = getText(R.string.select_list_empty)
noListsText.visible(false)
statusLayout.addView(progress)
statusLayout.addView(noListsText)
val dialogBuilder = AlertDialog.Builder(this)
.setTitle(R.string.select_list_title)
.setNeutralButton(R.string.select_list_manage) { _, _ ->
val listIntent = Intent(applicationContext, ListsActivity::class.java)
startActivity(listIntent)
}
.setNegativeButton(android.R.string.cancel, null)
.setView(statusLayout)
.setAdapter(adapter) { _, position ->
adapter.getItem(position)?.let { item ->
val newTab = createTabDataFromId(LIST, listOf(item.id, item.title))
currentTabs.add(newTab)
currentTabsAdapter.notifyItemInserted(currentTabs.size - 1)
updateAvailableTabs()
saveTabs()
}
}
val showProgressBarJob = getProgressBarJob(progress, 500)
showProgressBarJob.start()
val dialog = dialogBuilder.show()
lifecycleScope.launch {
mastodonApi.getLists().fold(
{ lists ->
showProgressBarJob.cancel()
adapter.addAll(lists)
if (lists.isEmpty()) {
noListsText.show()
}
},
{ throwable ->
dialog.hide()
Log.e("TabPreferenceActivity", "failed to load lists", throwable)
Snackbar.make(binding.root, R.string.error_list_load, Snackbar.LENGTH_LONG).show()
}
)
}
return
}
private fun getProgressBarJob(progressView: View, delayMs: Long) = this.lifecycleScope.launch(
start = CoroutineStart.LAZY
) {
try {
delay(delayMs)
progressView.show()
awaitCancellation()
} finally {
progressView.hide()
}
override fun onListSelected(list: MastoList) {
listSelectDialog?.dismiss()
listSelectDialog = null
val newTab = createTabDataFromId(LIST, listOf(list.id, list.title))
currentTabs.add(newTab)
currentTabsAdapter.notifyItemInserted(currentTabs.size - 1)
updateAvailableTabs()
saveTabs()
}
private fun validateHashtag(input: CharSequence?): Boolean {
@ -419,6 +352,8 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
}
}
override fun androidInjector() = dispatchingAndroidInjector
companion object {
private const val MIN_TAB_COUNT = 2
}

View File

@ -66,7 +66,7 @@ import com.keylesspalace.tusky.EditProfileActivity
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.StatusListActivity
import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.components.account.list.ListsForAccountFragment
import com.keylesspalace.tusky.components.account.list.ListSelectionFragment
import com.keylesspalace.tusky.components.accountlist.AccountListActivity
import com.keylesspalace.tusky.components.compose.ComposeActivity
import com.keylesspalace.tusky.components.report.ReportActivity
@ -991,7 +991,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
return true
}
R.id.action_add_or_remove_from_list -> {
ListsForAccountFragment.newInstance(viewModel.accountId).show(supportFragmentManager, null)
ListSelectionFragment.newInstance(viewModel.accountId).show(supportFragmentManager, null)
return true
}
R.id.action_mute_domain -> {

View File

@ -1,4 +1,4 @@
/* Copyright 2022 kyori19
/* Copyright Tusky Contributors
*
* This file is a part of Tusky.
*
@ -16,79 +16,99 @@
package com.keylesspalace.tusky.components.account.list
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.ListsActivity
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.FragmentListsForAccountBinding
import com.keylesspalace.tusky.databinding.ItemAddOrRemoveFromListBinding
import com.keylesspalace.tusky.databinding.FragmentListsListBinding
import com.keylesspalace.tusky.databinding.ItemListBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.util.BindingHolder
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject
class ListsForAccountFragment : DialogFragment(), Injectable {
class ListSelectionFragment : DialogFragment(), Injectable {
interface ListSelectionListener {
fun onListSelected(list: MastoList)
}
@Inject
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ListsForAccountViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(FragmentListsForAccountBinding::bind)
private var _binding: FragmentListsListBinding? = null
// This property is only valid between onCreateDialog and onDestroyView
private val binding get() = _binding!!
private val adapter = Adapter()
private var selectListener: ListSelectionListener? = null
private var accountId: String? = null
override fun onAttach(context: Context) {
super.onAttach(context)
selectListener = context as? ListSelectionListener
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.TuskyDialogFragmentStyle)
viewModel.setup(requireArguments().getString(ARG_ACCOUNT_ID)!!)
accountId = requireArguments().getString(ARG_ACCOUNT_ID)
}
override fun onStart() {
super.onStart()
dialog?.apply {
window?.setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val context = requireContext()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_lists_for_account, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.listsView.layoutManager = LinearLayoutManager(view.context)
_binding = FragmentListsListBinding.inflate(layoutInflater)
binding.listsView.adapter = adapter
viewLifecycleOwner.lifecycleScope.launch {
val dialogBuilder = AlertDialog.Builder(context)
.setView(binding.root)
.setTitle(R.string.select_list_title)
.setNeutralButton(R.string.select_list_manage) { _, _ ->
val listIntent = Intent(context, ListsActivity::class.java)
startActivity(listIntent)
}
.setNegativeButton(if (accountId != null) R.string.button_done else android.R.string.cancel, null)
val dialog = dialogBuilder.create()
val showProgressBarJob = getProgressBarJob(binding.progressBar, 500)
showProgressBarJob.start()
// TODO change this to a (single) LoadState like elsewhere?
lifecycleScope.launch {
viewModel.states.collectLatest { states ->
binding.progressBar.hide()
showProgressBarJob.cancel()
if (states.isEmpty()) {
binding.messageView.show()
binding.messageView.setup(R.drawable.elephant_friend_empty, R.string.no_lists) {
load()
}
binding.messageView.setup(R.drawable.elephant_friend_empty, R.string.no_lists)
} else {
binding.listsView.show()
adapter.submitList(states)
@ -96,9 +116,11 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
}
}
viewLifecycleOwner.lifecycleScope.launch {
lifecycleScope.launch {
viewModel.loadError.collectLatest { error ->
Log.e(TAG, "failed to load lists", error)
binding.progressBar.hide()
showProgressBarJob.cancel()
binding.listsView.hide()
binding.messageView.apply {
show()
@ -107,20 +129,20 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
}
}
viewLifecycleOwner.lifecycleScope.launch {
lifecycleScope.launch {
viewModel.actionError.collectLatest { error ->
when (error.type) {
ActionError.Type.ADD -> {
Snackbar.make(binding.root, R.string.failed_to_add_to_list, Snackbar.LENGTH_LONG)
.setAction(R.string.action_retry) {
viewModel.addAccountToList(error.listId)
viewModel.addAccountToList(accountId!!, error.listId)
}
.show()
}
ActionError.Type.REMOVE -> {
Snackbar.make(binding.root, R.string.failed_to_remove_from_list, Snackbar.LENGTH_LONG)
.setAction(R.string.action_retry) {
viewModel.removeAccountFromList(error.listId)
viewModel.removeAccountFromList(accountId!!, error.listId)
}
.show()
}
@ -128,18 +150,35 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
}
}
binding.doneButton.setOnClickListener {
dismiss()
lifecycleScope.launch {
load()
}
load()
return dialog
}
private fun getProgressBarJob(progressView: View, delayMs: Long) = this.lifecycleScope.launch(
start = CoroutineStart.LAZY
) {
try {
delay(delayMs)
progressView.show()
awaitCancellation()
} finally {
progressView.hide()
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun load() {
binding.progressBar.show()
binding.listsView.hide()
binding.messageView.hide()
viewModel.load()
viewModel.load(accountId)
}
private object Differ : DiffUtil.ItemCallback<AccountListState>() {
@ -159,42 +198,55 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
}
inner class Adapter :
ListAdapter<AccountListState, BindingHolder<ItemAddOrRemoveFromListBinding>>(Differ) {
ListAdapter<AccountListState, BindingHolder<ItemListBinding>>(Differ) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): BindingHolder<ItemAddOrRemoveFromListBinding> {
val binding =
ItemAddOrRemoveFromListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BindingHolder(binding)
): BindingHolder<ItemListBinding> {
return BindingHolder(ItemListBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
override fun onBindViewHolder(holder: BindingHolder<ItemAddOrRemoveFromListBinding>, position: Int) {
override fun onBindViewHolder(holder: BindingHolder<ItemListBinding>, position: Int) {
val item = getItem(position)
holder.binding.listNameView.text = item.list.title
holder.binding.addButton.apply {
visible(!item.includesAccount)
setOnClickListener {
viewModel.addAccountToList(item.list.id)
holder.binding.listName.text = item.list.title
accountId?.let { accountId ->
holder.binding.addButton.apply {
visible(!item.includesAccount)
setOnClickListener {
viewModel.addAccountToList(accountId, item.list.id)
}
}
holder.binding.removeButton.apply {
visible(item.includesAccount)
setOnClickListener {
viewModel.removeAccountFromList(accountId, item.list.id)
}
}
}
holder.binding.removeButton.apply {
visible(item.includesAccount)
setOnClickListener {
viewModel.removeAccountFromList(item.list.id)
holder.itemView.setOnClickListener {
selectListener?.onListSelected(item.list)
accountId?.let { accountId ->
if (item.includesAccount) {
viewModel.removeAccountFromList(accountId, item.list.id)
} else {
viewModel.addAccountToList(accountId, item.list.id)
}
}
}
}
}
companion object {
private const val TAG = "ListsListFragment"
private const val ARG_ACCOUNT_ID = "accountId"
fun newInstance(accountId: String): ListsForAccountFragment {
fun newInstance(accountId: String?): ListSelectionFragment {
val args = Bundle().apply {
putString(ARG_ACCOUNT_ID, accountId)
}
return ListsForAccountFragment().apply { arguments = args }
return ListSelectionFragment().apply { arguments = args }
}
}
}

View File

@ -25,8 +25,6 @@ import at.connyduck.calladapter.networkresult.runCatching
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.network.MastodonApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.first
@ -54,8 +52,6 @@ class ListsForAccountViewModel @Inject constructor(
private val mastodonApi: MastodonApi
) : ViewModel() {
private lateinit var accountId: String
private val _states = MutableSharedFlow<List<AccountListState>>(1)
val states: SharedFlow<List<AccountListState>> = _states
@ -65,24 +61,21 @@ class ListsForAccountViewModel @Inject constructor(
private val _actionError = MutableSharedFlow<ActionError>(1)
val actionError: SharedFlow<ActionError> = _actionError
fun setup(accountId: String) {
this.accountId = accountId
}
fun load() {
fun load(accountId: String?) {
_loadError.resetReplayCache()
viewModelScope.launch {
runCatching {
val (all, includes) = listOf(
async { mastodonApi.getLists() },
async { mastodonApi.getListsIncludesAccount(accountId) }
).awaitAll()
val all = mastodonApi.getLists().getOrThrow()
var includes: List<MastoList> = emptyList()
if (accountId != null) {
includes = mastodonApi.getListsIncludesAccount(accountId).getOrThrow()
}
_states.emit(
all.getOrThrow().map { list ->
all.map { listState ->
AccountListState(
list = list,
includesAccount = includes.getOrThrow().any { it.id == list.id }
list = listState,
includesAccount = includes.any { it.id == listState.id }
)
}
)
@ -93,7 +86,9 @@ class ListsForAccountViewModel @Inject constructor(
}
}
fun addAccountToList(listId: String) {
// TODO there is no "progress" visible for these
fun addAccountToList(accountId: String, listId: String) {
_actionError.resetReplayCache()
viewModelScope.launch {
mastodonApi.addAccountToList(listId, listOf(accountId))
@ -114,7 +109,7 @@ class ListsForAccountViewModel @Inject constructor(
}
}
fun removeAccountFromList(listId: String) {
fun removeAccountFromList(accountId: String, listId: String) {
_actionError.resetReplayCache()
viewModelScope.launch {
mastodonApi.deleteAccountFromList(listId, listOf(accountId))

View File

@ -100,7 +100,7 @@ abstract class ActivitiesModule {
@ContributesAndroidInjector
abstract fun contributesLicenseActivity(): LicenseActivity
@ContributesAndroidInjector
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesTabPreferenceActivity(): TabPreferenceActivity
@ContributesAndroidInjector

View File

@ -16,7 +16,7 @@
package com.keylesspalace.tusky.di
import com.keylesspalace.tusky.AccountsInListFragment
import com.keylesspalace.tusky.components.account.list.ListsForAccountFragment
import com.keylesspalace.tusky.components.account.list.ListSelectionFragment
import com.keylesspalace.tusky.components.account.media.AccountMediaFragment
import com.keylesspalace.tusky.components.accountlist.AccountListFragment
import com.keylesspalace.tusky.components.conversation.ConversationsFragment
@ -97,7 +97,7 @@ abstract class FragmentBuildersModule {
abstract fun preferencesFragment(): PreferencesFragment
@ContributesAndroidInjector
abstract fun listsForAccountFragment(): ListsForAccountFragment
abstract fun listsForAccountFragment(): ListSelectionFragment
@ContributesAndroidInjector
abstract fun trendingTagsFragment(): TrendingTagsFragment

View File

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:animateLayoutChanges="true"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/listsView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
tools:visibility="visible" />
<com.keylesspalace.tusky.view.BackgroundMessageView
android:id="@+id/messageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:color/transparent"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/errorphant_error"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="@+id/doneButton"
style="@style/TuskyButton.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:text="@string/button_done" />
</LinearLayout>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="wrap_content">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_gravity="center"
tools:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/listsView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:visibility="gone"
tools:visibility="visible" />
<com.keylesspalace.tusky.view.BackgroundMessageView
android:id="@+id/messageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@android:color/transparent"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/errorphant_error"
tools:visibility="visible" />
</FrameLayout>

View File

@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<TextView
android:id="@+id/listNameView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawablePadding="8dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:textColor="?android:attr/textColorSecondary"
android:textSize="?attr/status_text_medium"
app:drawableStartCompat="@drawable/ic_list"
app:drawableTint="?android:attr/textColorSecondary"
tools:text="Example list" />
<ImageButton
android:id="@+id/addButton"
style="@style/TuskyImageButton"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="12dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/action_add_to_list"
android:padding="4dp"
android:src="@drawable/ic_plus_24dp" />
<ImageButton
android:id="@+id/removeButton"
style="@style/TuskyImageButton"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginStart="12dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/action_remove_from_list"
android:padding="4dp"
android:src="@drawable/ic_clear_24dp"
android:visibility="gone" />
</LinearLayout>

View File

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="?dialogPreferredPadding"
android:paddingRight="?dialogPreferredPadding"
android:gravity="center_vertical"
android:orientation="horizontal"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
@ -12,21 +15,47 @@
tools:ignore="Overdraw">
<TextView
android:id="@+id/list_name_textview"
android:id="@+id/list_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawablePadding="8dp"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
app:drawableStartCompat="@drawable/ic_list"
app:drawableTint="?android:attr/textColorSecondary"
tools:text="Example list" />
<ImageButton
android:id="@+id/editListButton"
android:id="@+id/more_button"
android:visibility="gone"
style="@style/TuskyImageButton"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/action_more"
android:layout_marginLeft="8dp"
android:src="@drawable/ic_more_horiz_24dp" />
<ImageButton
android:id="@+id/add_button"
android:visibility="gone"
style="@style/TuskyImageButton"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="?selectableItemBackgroundBorderless"
android:contentDescription="@string/action_more"
android:src="@drawable/ic_more_horiz_24dp" />
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/action_add_to_list"
android:layout_marginLeft="8dp"
android:src="@drawable/ic_plus_24dp" />
<ImageButton
android:id="@+id/remove_button"
android:visibility="gone"
style="@style/TuskyImageButton"
android:layout_width="32dp"
android:layout_height="32dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/action_remove_from_list"
android:layout_marginLeft="8dp"
android:src="@drawable/ic_clear_24dp" />
</LinearLayout>

View File

@ -675,9 +675,7 @@
<string name="dialog_save_profile_changes_message">هل تريد حفط التغييرات التي طرأت على ملفك التعريفي؟</string>
<string name="dialog_delete_filter_text">أتريد حذف عامل التصفية ”%1$s“؟</string>
<string name="dialog_delete_filter_positive_action">حذف</string>
<string name="select_list_empty">ليس لديك أية قائمة بعدُ</string>
<string name="select_list_manage">إدارة القوائم</string>
<string name="error_list_load">خطأ أثناء تحميل القوائم</string>
<string name="status_filtered_show_anyway">أظهره على أي حال</string>
<string name="filter_description_hide">إخفاء بالكامل</string>
<string name="ui_success_accepted_follow_request">تم قبول طلب المتابَعة</string>

View File

@ -636,9 +636,7 @@
<string name="description_browser_login">Можа падтрымліваць дадатковыя метады праверкі сапраўднасці, але для гэтага патрэбны адпаведны браузер.</string>
<string name="post_media_image">Відарыс</string>
<string name="action_refresh">Абнавіць</string>
<string name="select_list_empty">Яшчэ няма спісаў</string>
<string name="select_list_manage">Кіраванне спісамі</string>
<string name="error_list_load">Памылка загрузкі спісаў</string>
<string name="total_usage">Усяго выкарыстана</string>
<string name="total_accounts">Усяго ўліковых запісаў</string>
<string name="accessibility_talking_about_tag">%1$d людзей кажуць пра хэштэг %2$s</string>

View File

@ -557,7 +557,6 @@
<string name="error_following_hashtag_format">Грешка при последване на #%s</string>
<string name="error_unfollowing_hashtag_format">Грешка при отследване на #%s</string>
<string name="title_public_federated">Федерирани</string>
<string name="error_list_load">Грешка при зареждане на списъци</string>
<string name="select_list_manage">Управление на списъци</string>
<string name="notification_update_format">%s редактира публикацията си</string>
<string name="pref_title_account_filter_keywords">Профили</string>

View File

@ -692,9 +692,7 @@
<string name="filter_edit_keyword_title">Golygu allweddair</string>
<string name="filter_description_format">%s: %s</string>
<string name="post_media_image">Delwedd</string>
<string name="select_list_empty">Does gennyt ti ddim rhestrau, eto</string>
<string name="select_list_manage">Rheoli rhestrau</string>
<string name="error_list_load">Gwall wrth lwytho rhestrau</string>
<string name="help_empty_home">Dyma dy <b>ffrwd cartref</b>. Mae\'n dangos negeseuon diweddar y cyfrifon rwyt ti\'n eu dilyn.
\n
\nEr mwyn archwilio cyfrifon galli di ddod o hyd iddyn o fewn un o\'r ffrydiau eraill. Er enghraifft, ffrwd dy weinydd [iconics gmd_group]. Neu galli di eu chwilio yn ôl eu henw [iconics gmd_search]; er enghraifft, chwiliwch am Tusky i ddod o hyd ein cyfrif Mastodon.</string>
@ -751,3 +749,4 @@
<string name="pref_title_show_self_boosts">Dangos hunan-hybiau</string>
<string name="pref_title_show_self_boosts_description">Rhywun yn hybu ei neges ei hunan</string>
</resources>

View File

@ -421,9 +421,7 @@
<string name="about_powered_by_tusky">Unterstützt von Tusky</string>
<string name="description_post_bookmarked">Als Lesezeichen gespeichert</string>
<string name="select_list_title">Liste auswählen</string>
<string name="select_list_empty">Du hast noch keine Listen</string>
<string name="select_list_manage">Listen verwalten</string>
<string name="error_list_load">Fehler beim Laden der Listen</string>
<string name="list">Liste</string>
<string name="post_lookup_error_format">Fehler beim Nachschlagen von %s</string>
<string name="no_drafts">Du hast keine Entwürfe.</string>

View File

@ -647,13 +647,11 @@
<string name="pref_title_show_stat_inline">Mostrar estadísticas de la entrada en la línea de tiempo</string>
<string name="ui_error_unknown">razón desconocida</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>
<string name="help_empty_home">Esta es tu <b> cronología de inicio</b>. Muestra las publicaciones recientes de las cuentas que sigues.
\n
\nPara encontrar cuentas, puedes mirar en alguna de las otras cronologías. Por ejemplo, la cronología local de tu instancia [iconics gmd_group]. O puedes buscarlas por nombre [iconics gmd_search]; por ejemplo, busca Tusky para encontrar nuestra cuenta de Mastodon.</string>
<string name="ui_error_bookmark">Fallo al añadir a marcadores: %s</string>
<string name="select_list_manage">Gestionar listas</string>
<string name="error_list_load">Error al cargar listas</string>
<string name="ui_error_favourite">Fallo al favoritear publicación: %s</string>
<string name="ui_error_clear_notifications">Fallo al limpiar notificaciones: %s</string>
<string name="ui_error_accept_follow_request">Fallo al aceptar solicitud de seguimiento: %s</string>

View File

@ -652,9 +652,7 @@
\n
\nبرای کاوش حساب‌ها می‌توانید آن‌ها را در دیگر خط‌های زمانی (برای نمونه خط زمانی محلّی نمونه‌تان [iconics gmd_group]) یافته یا با نام (برای نمونه Tusky برای حساب ماستودونمان) بجوییدشان [iconics gmd_search].</string>
<string name="post_media_image">تصویر</string>
<string name="select_list_empty">هنوز هیچ سیاهه‌ای ندارید</string>
<string name="select_list_manage">مدیریت سیاهه‌ها</string>
<string name="error_list_load">خطا در بار کردن سیاهه‌ها</string>
<string name="load_newest_notifications">بار کردن جدیدترین آگاهی‌ها</string>
<string name="compose_delete_draft">حذف پیش‌نویس؟</string>
<string name="error_missing_edits">کارسازتان می‌داند که این فرسته ویرایش شده؛ ولی رونوشتی از ویرایش‌ها ندارد. پس نمی‌توانند نشانتان داده شوند.

View File

@ -647,9 +647,7 @@
<string name="mute_notifications_switch">Masquer les notifications</string>
<string name="compose_unsaved_changes">Il y a des modifications non enregistrées.</string>
<string name="description_post_edited">Modifié</string>
<string name="select_list_empty">Vous n\'avez pas encore de liste</string>
<string name="select_list_manage">Gérer les listes</string>
<string name="error_list_load">Erreur de chargement des listes</string>
<string name="report_category_violation">Règle enfreinte</string>
<string name="error_status_source_load">Le texte d\'origine du statut n\'a pas pu être chargé.</string>
<string name="ui_error_unknown">raison inconnue</string>

View File

@ -645,8 +645,6 @@
<string name="ui_success_accepted_follow_request">Chaidh gabhail ris an iarrtas leantainn</string>
<string name="ui_success_rejected_follow_request">Chaidh iarrtas leantainn a bhacadh</string>
<string name="select_list_manage">Stiùirich na liostaichean</string>
<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="pref_title_account_filter_keywords">Pròifilean</string>

View File

@ -645,9 +645,7 @@
<string name="pref_title_show_stat_inline">Mostrar estatísticas da publicación na cronoloxía</string>
<string name="filter_keyword_addition_title">Engadir palabra</string>
<string name="filter_edit_keyword_title">Editar palabra</string>
<string name="select_list_empty">Aínda non tes listas</string>
<string name="select_list_manage">Xestionar listas</string>
<string name="error_list_load">Erro ao cargar as listas</string>
<string name="error_missing_edits">O teu servidor sabe que a publicación foi editada, pero non ten unha copia das edición, polo que non pode mostrarchas.
\n
\nÉ un <a href="https://github.com/mastodon/mastodon/issues/25398">problema coñecido</a> en Mastodon.</string>

View File

@ -654,9 +654,7 @@
\n
\nMás fiókokat másik idővonalakon fedezhetsz fel. Például a példányod helyi idővonalán [iconics gmd_group]. Vagy megkeresheted őket név szerint [iconics gmd_search]; például keress rá a Tuskyra, hogy megtaláld a Mastodon-fiókunkat.</string>
<string name="post_media_image">Kép</string>
<string name="select_list_empty">Még nincsenek listáid</string>
<string name="select_list_manage">Listák kezelése</string>
<string name="error_list_load">Hiba a listák betöltése során</string>
<string name="pref_ui_text_size">UI betűméret</string>
<string name="notification_listenable_worker_name">Háttértevékenység</string>
<string name="notification_listenable_worker_description">Értesítések, amikor a Tusky a háttérben működik</string>

View File

@ -642,9 +642,7 @@
<string name="filter_edit_keyword_title">Breyta stikkorði</string>
<string name="filter_description_format">%s: %s</string>
<string name="post_media_image">Mynd</string>
<string name="select_list_empty">Þú ert ekki með neina lista</string>
<string name="select_list_manage">Sýsla með lista</string>
<string name="error_list_load">Villa við að hlaða inn listum</string>
<string name="help_empty_home">Þetta er <b>tímalínan þín</b>. Hún sýnir nýlegar færslur þeirra sem þú fylgist með.
\n
\nTil að skoða hvað aðrir eru að gera getur þú til dæmis uppgötvað viðkomandi í einni af hinum tímalínunum. Til dæmis á staðværu tímalínu netþjónsins þíns [iconics gmd_group]. Eða að þú leitar að þeim eftir nafni [iconics gmd_search]; til dæmis geturðu leitað að Tusky til að finna Mastodon-aðganginn okkar.</string>

View File

@ -652,9 +652,7 @@
<string name="ui_error_accept_follow_request">Accettazione richiesta di follow fallita: %s</string>
<string name="ui_success_accepted_follow_request">Richiesta di follow accettata</string>
<string name="ui_success_rejected_follow_request">Richiesta di follow bloccata</string>
<string name="select_list_empty">Non hai ancora alcuna lista</string>
<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="pref_title_account_filter_keywords">Profili</string>

View File

@ -607,7 +607,6 @@
<string name="post_media_image">画像</string>
<string name="notification_unknown_name">不明</string>
<string name="select_list_manage">リストを管理する</string>
<string name="select_list_empty">リストはまだありません</string>
<string name="status_filtered_show_anyway">とにかく表示する</string>
<string name="pref_title_account_filter_keywords">プロフィール</string>
<string name="title_public_trending_hashtags">トレンドのハッシュタグ</string>
@ -646,7 +645,6 @@
<string name="filter_description_format">%s: %s</string>
<string name="load_newest_notifications">最新の通知を読み込む</string>
<string name="compose_delete_draft">下書きを削除しますか?</string>
<string name="error_list_load">リストを読み込む際のエラー</string>
<string name="error_media_upload_sending_fmt">アップロードに失敗しました: %s</string>
<string name="error_missing_edits">あなたのサーバーは、この投稿が変更されたことを把握していますが、編集履歴のコピーを備えていないので、表示できません。
\n

View File

@ -592,7 +592,6 @@
<string name="post_privacy_followers_only">Tikai sekotājiem</string>
<string name="post_media_image">Attēls</string>
<string name="filter_description_hide">Paslēpt pilnībā</string>
<string name="select_list_empty">Tev vēl nav sarakstu</string>
<string name="select_list_manage">Pārvaldīt sarakstus</string>
<string name="filter_keyword_display_format">%s (viss vārds)</string>
<string name="pref_title_account_filter_keywords">Profili</string>

View File

@ -626,8 +626,6 @@
<string name="action_discard">Forkast endringer</string>
<string name="action_continue_edit">Fortsett endring</string>
<string name="compose_unsaved_changes">Du har ulagrede endringer.</string>
<string name="select_list_empty">Du har ingen lister, enda</string>
<string name="error_list_load">Feil under lading av lister</string>
<string name="select_list_manage">Forvalte lister</string>
<string name="ui_error_reblog">Deling av innlegget feilet: %s</string>
<string name="ui_error_unknown">ukjent grunn</string>

View File

@ -617,8 +617,6 @@
<string name="notification_unknown_name">Onbekend</string>
<string name="ui_error_clear_notifications">Wissen meldingen mislukt: %s</string>
<string name="ui_success_accepted_follow_request">Volgverzoek geaccepteerd</string>
<string name="error_list_load">Fout bij laden lijsten</string>
<string name="select_list_empty">Je hebt nog geen lijsten</string>
<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>

View File

@ -644,9 +644,7 @@
<string name="filter_description_format">%s : %s</string>
<string name="label_filter_keywords">Mots clau o frasas de filtrar</string>
<string name="post_media_image">Imatge</string>
<string name="select_list_empty">Avètz pas encara de lista</string>
<string name="select_list_manage">Gerir las listas</string>
<string name="error_list_load">Error en cargant las litas</string>
<string name="ui_error_favourite">Fracàs de la mes en favorit: %s</string>
<string name="ui_error_reblog">Fracàs en partejant: %s</string>
<string name="ui_error_vote">Fracàs del vòt: %s</string>

View File

@ -617,7 +617,6 @@
<string name="failed_to_add_to_list">Falha em adicionar a conta à lista</string>
<string name="failed_to_pin">Falha em afixar</string>
<string name="compose_save_draft_loses_media">Guardar rascunho\? (anexos serão carregados novamente quando recuperares o rascunho.)</string>
<string name="select_list_empty">Ainda não tens nenhuma lista</string>
<string name="select_list_manage">Gerir listas</string>
<string name="status_filter_placeholder_label_format">Filtrados: %s</string>
<string name="status_filtered_show_anyway">Mostrar à mesma</string>
@ -641,7 +640,6 @@
<string name="status_edit_info">Editado: %1$s</string>
<string name="status_created_info">Criado: %1$s</string>
<string name="pref_title_reading_order">Ordem de leitura</string>
<string name="error_list_load">Erro ao carregar listas</string>
<string name="report_category_violation">Violação de regra</string>
<string name="no_lists">Não tens nenhuma lista.</string>
<string name="socket_timeout_exception">A tentativa de contato com o teu servidor demorou demasiado temp0</string>

View File

@ -639,8 +639,6 @@
<string name="about_copy">Копирование версии и информации об устройстве</string>
<string name="about_copied">Версия и информация об устройстве скопировано</string>
<string name="action_add_reaction">добавить реакцию</string>
<string name="error_list_load">Ошибка при загрузке списков</string>
<string name="select_list_empty">У вас нет списков, пока что</string>
<string name="select_list_manage">Управлять списками</string>
<string name="ui_error_reject_follow_request">Отклонение запроса на подписку не удалось: %s</string>
<string name="ui_error_accept_follow_request">Принятие запроса на подписку не удалось: %s</string>

View File

@ -632,7 +632,6 @@
<string name="ui_success_accepted_follow_request">Följ begäran accepterad</string>
<string name="ui_success_rejected_follow_request">Följ begäran blockerad</string>
<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="pref_title_account_filter_keywords">Profiler</string>
@ -663,7 +662,6 @@
<string name="ui_error_bookmark">Att bokmärka inlägg misslyckades: %s</string>
<string name="ui_error_clear_notifications">Rensing av aviseringar misslyckades: %s</string>
<string name="ui_error_favourite">Att favoritmarkera inlägg misslyckades: %s</string>
<string name="error_list_load">Fel vid laddning av listor</string>
<string name="ui_error_reject_follow_request">Avacceptera följarförgrågan misslyckades: %s</string>
<string name="label_filter_context">Filtrera sammanhang</string>
<string name="title_public_trending_hashtags">Populära hashtaggar</string>

View File

@ -628,9 +628,7 @@
<string name="action_browser_login">Tarayıcı ile Giriş Yap</string>
<string name="description_login">Çoğu durumda çalışır. Diğer uygulamalara veri sızmaz.</string>
<string name="description_browser_login">Ek kimlik doğrulama yöntemlerini destekleyebilir ancak desteklenen bir tarayıcı gerektirir.</string>
<string name="select_list_empty">Henüz hiç listen yok</string>
<string name="select_list_manage">Listeleri yönet</string>
<string name="error_list_load">Listeler yüklenirken hata oluştu</string>
<string name="action_share_account_link">Hesaba bağlantı paylaş</string>
<string name="action_share_account_username">Hesap adını paylaş</string>
<string name="account_username_copied">Kullanıcı adı kopyalandı</string>

View File

@ -667,8 +667,6 @@
\n
\nЩоб переглянути облікові записи, ви можете знайти їх в одній з інших стрічок. Наприклад, на локальній стрічці вашого сервера [iconics gmd_group]. Або ви можете шукати їх за іменами [iconics gmd_search]; наприклад, шукайте Tusky, щоб знайти наш обліковий запис Mastodon.</string>
<string name="post_media_image">Зображення</string>
<string name="error_list_load">Помилка завантаження списків</string>
<string name="select_list_empty">У вас ще немає списків</string>
<string name="select_list_manage">Керувати списками</string>
<string name="pref_ui_text_size">Розмір шрифту інтерфейсу</string>
<string name="notification_listenable_worker_name">Фонова діяльність</string>

View File

@ -636,8 +636,6 @@
\nĐể khám phá mọi người, bạn có thể xem qua ở các bảng tin khác. Ví dụ: [iconics gmd_group] Bảng tin máy chủ của bạn. Hoặc bạn cũng có thể [iconics gmd_search] tìm theo tên người dùng; ví dụ như Tusky.</string>
<string name="post_media_image">Hình ảnh</string>
<string name="select_list_manage">Quản lý danh sách</string>
<string name="error_list_load">Xảy ra lỗi khi tải danh sách</string>
<string name="select_list_empty">Bạn chưa có danh sách</string>
<string name="load_newest_notifications">Tải những thông báo mới nhất</string>
<string name="compose_delete_draft">Xóa bản nháp\?</string>
<string name="error_missing_edits">Máy chủ của bạn biết tút đã được sửa, nhưng không có bản sao của lần sửa, nên nó không thể hiện.

View File

@ -650,8 +650,6 @@
\n要探索账户 你可以浏览其他时间线。比如,你的账户所在实例服务器的本地时间线 [iconics gmd_group]。你也可以按名称 [iconics gmd_search]进行搜索比如搜索Tusky 来寻找我们的 Mastodon 账户。</string>
<string name="post_media_image">图片</string>
<string name="select_list_manage">管理列表</string>
<string name="error_list_load">加载列表出错</string>
<string name="select_list_empty">你还没有列表</string>
<string name="load_newest_notifications">加载最新通知</string>
<string name="compose_delete_draft">删除草稿?</string>
<string name="error_missing_edits">你的服务器知晓这篇帖子被编辑,但没有编辑的副本,所以无法呈现给你。

View File

@ -608,9 +608,7 @@
<string name="edit_hashtag_hint">Hashtag without #</string>
<string name="hashtags">Hashtags</string>
<string name="select_list_title">Select list</string>
<string name="select_list_empty">You have no lists, yet</string>
<string name="select_list_manage">Manage lists</string>
<string name="error_list_load">Error loading lists</string>
<string name="list_exclusive_label">Hide from the home timeline</string>
<string name="list">List</string>
<string name="notifications_clear">Delete</string>