enable multiple hashtags in one hashtag tab (#1790)

* enable multiple hashtags in one hashtag tab

* add comment explaining the code in TabAdapter

* delete unused drawables

* add padding to EditText in dialog
This commit is contained in:
Konrad Pozniak 2020-05-15 22:10:29 +02:00 committed by GitHub
parent 2fc7ad13bb
commit df8dc3a198
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 105 additions and 121 deletions

View File

@ -45,7 +45,7 @@ fun createTabDataFromId(id: String, arguments: List<String> = emptyList()): TabD
LOCAL -> TabData(LOCAL, R.string.title_public_local, R.drawable.ic_local_24dp, { TimelineFragment.newInstance(TimelineFragment.Kind.PUBLIC_LOCAL) }) LOCAL -> TabData(LOCAL, R.string.title_public_local, R.drawable.ic_local_24dp, { TimelineFragment.newInstance(TimelineFragment.Kind.PUBLIC_LOCAL) })
FEDERATED -> TabData(FEDERATED, R.string.title_public_federated, R.drawable.ic_public_24dp, { TimelineFragment.newInstance(TimelineFragment.Kind.PUBLIC_FEDERATED) }) FEDERATED -> TabData(FEDERATED, R.string.title_public_federated, R.drawable.ic_public_24dp, { TimelineFragment.newInstance(TimelineFragment.Kind.PUBLIC_FEDERATED) })
DIRECT -> TabData(DIRECT, R.string.title_direct_messages, R.drawable.ic_reblog_direct_24dp, { ConversationsFragment.newInstance() }) DIRECT -> TabData(DIRECT, R.string.title_direct_messages, R.drawable.ic_reblog_direct_24dp, { ConversationsFragment.newInstance() })
HASHTAG -> TabData(HASHTAG, R.string.hashtag, R.drawable.ic_hashtag, { args -> TimelineFragment.newInstance(TimelineFragment.Kind.TAG, args.getOrNull(0).orEmpty()) }, arguments) HASHTAG -> TabData(HASHTAG, R.string.hashtags, R.drawable.ic_hashtag, { args -> TimelineFragment.newHashtagInstance(args) }, arguments)
LIST -> TabData(LIST, R.string.list, R.drawable.ic_list, { args -> TimelineFragment.newInstance(TimelineFragment.Kind.LIST, args.getOrNull(0).orEmpty()) }, arguments) LIST -> TabData(LIST, R.string.list, R.drawable.ic_list, { args -> TimelineFragment.newInstance(TimelineFragment.Kind.LIST, args.getOrNull(0).orEmpty()) }, arguments)
else -> throw IllegalArgumentException("unknown tab type") else -> throw IllegalArgumentException("unknown tab type")
} }

View File

@ -18,13 +18,16 @@ package com.keylesspalace.tusky
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.MenuItem import android.view.MenuItem
import android.widget.FrameLayout
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatEditText import androidx.appcompat.widget.AppCompatEditText
import androidx.core.view.updatePadding
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import at.connyduck.sparkbutton.helpers.Utils
import com.keylesspalace.tusky.adapter.ItemInteractionListener import com.keylesspalace.tusky.adapter.ItemInteractionListener
import com.keylesspalace.tusky.adapter.ListSelectionAdapter import com.keylesspalace.tusky.adapter.ListSelectionAdapter
import com.keylesspalace.tusky.adapter.TabAdapter import com.keylesspalace.tusky.adapter.TabAdapter
@ -150,7 +153,7 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
actionButton.isExpanded = false actionButton.isExpanded = false
if (tab.id == HASHTAG) { if (tab.id == HASHTAG) {
showEditHashtagDialog() showAddHashtagDialog()
return return
} }
@ -173,19 +176,32 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
} }
override fun onActionChipClicked(tab: TabData) { override fun onActionChipClicked(tab: TabData) {
showEditHashtagDialog(tab) showAddHashtagDialog(tab)
} }
private fun showEditHashtagDialog(tab: TabData? = null) { override fun onChipClicked(tab: TabData, chipPosition: Int) {
val newArguments = tab.arguments.filterIndexed { i, _ -> i != chipPosition }
val newTab = tab.copy(arguments = newArguments)
val position = currentTabs.indexOf(tab)
currentTabs[position] = newTab
currentTabsAdapter.notifyItemChanged(position)
}
private fun showAddHashtagDialog(tab: TabData? = null) {
val frameLayout = FrameLayout(this)
val padding = Utils.dpToPx(this, 8)
frameLayout.updatePadding(left = padding, right = padding)
val editText = AppCompatEditText(this) val editText = AppCompatEditText(this)
editText.setHint(R.string.edit_hashtag_hint) editText.setHint(R.string.edit_hashtag_hint)
editText.setText("") editText.setText("")
editText.append(tab?.arguments?.first().orEmpty()) frameLayout.addView(editText)
val dialog = AlertDialog.Builder(this) val dialog = AlertDialog.Builder(this)
.setTitle(R.string.edit_hashtag_title) .setTitle(R.string.add_hashtag_title)
.setView(editText) .setView(frameLayout)
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(R.string.action_save) { _, _ -> .setPositiveButton(R.string.action_save) { _, _ ->
val input = editText.text.toString().trim() val input = editText.text.toString().trim()
@ -194,7 +210,7 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
currentTabs.add(newTab) currentTabs.add(newTab)
currentTabsAdapter.notifyItemInserted(currentTabs.size - 1) currentTabsAdapter.notifyItemInserted(currentTabs.size - 1)
} else { } else {
val newTab = tab.copy(arguments = listOf(input)) val newTab = tab.copy(arguments = tab.arguments + input)
val position = currentTabs.indexOf(tab) val position = currentTabs.indexOf(tab)
currentTabs[position] = newTab currentTabs[position] = newTab

View File

@ -28,6 +28,8 @@ import androidx.fragment.app.FragmentTransaction;
import com.keylesspalace.tusky.fragment.TimelineFragment; import com.keylesspalace.tusky.fragment.TimelineFragment;
import java.util.Collections;
import javax.inject.Inject; import javax.inject.Inject;
import dagger.android.AndroidInjector; import dagger.android.AndroidInjector;
@ -65,7 +67,7 @@ public class ViewTagActivity extends BottomSheetActivity implements HasAndroidIn
} }
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
Fragment fragment = TimelineFragment.newInstance(TimelineFragment.Kind.TAG, hashtag); Fragment fragment = TimelineFragment.newHashtagInstance(Collections.singletonList(hashtag));
fragmentTransaction.replace(R.id.fragment_container, fragment); fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.commit(); fragmentTransaction.commit();
} }

View File

@ -19,7 +19,9 @@ import android.view.LayoutInflater
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.size
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.chip.Chip
import com.keylesspalace.tusky.HASHTAG import com.keylesspalace.tusky.HASHTAG
import com.keylesspalace.tusky.LIST import com.keylesspalace.tusky.LIST
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
@ -29,13 +31,13 @@ import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import kotlinx.android.synthetic.main.item_tab_preference.view.* import kotlinx.android.synthetic.main.item_tab_preference.view.*
interface ItemInteractionListener { interface ItemInteractionListener {
fun onTabAdded(tab: TabData) fun onTabAdded(tab: TabData)
fun onTabRemoved(position: Int) fun onTabRemoved(position: Int)
fun onStartDelete(viewHolder: RecyclerView.ViewHolder) fun onStartDelete(viewHolder: RecyclerView.ViewHolder)
fun onStartDrag(viewHolder: RecyclerView.ViewHolder) fun onStartDrag(viewHolder: RecyclerView.ViewHolder)
fun onActionChipClicked(tab: TabData) fun onActionChipClicked(tab: TabData)
fun onChipClicked(tab: TabData, chipPosition: Int)
} }
class TabAdapter(private var data: List<TabData>, class TabAdapter(private var data: List<TabData>,
@ -86,9 +88,9 @@ class TabAdapter(private var data: List<TabData>,
if (holder.itemView.removeButton != null) { if (holder.itemView.removeButton != null) {
holder.itemView.removeButton.isEnabled = removeButtonEnabled holder.itemView.removeButton.isEnabled = removeButtonEnabled
ThemeUtils.setDrawableTint( ThemeUtils.setDrawableTint(
holder.itemView.context, holder.itemView.context,
holder.itemView.removeButton.drawable, holder.itemView.removeButton.drawable,
(if (removeButtonEnabled) android.R.attr.textColorTertiary else R.attr.textColorDisabled) (if (removeButtonEnabled) android.R.attr.textColorTertiary else R.attr.textColorDisabled)
) )
} }
@ -96,11 +98,38 @@ class TabAdapter(private var data: List<TabData>,
if (data[position].id == HASHTAG) { if (data[position].id == HASHTAG) {
holder.itemView.chipGroup.show() holder.itemView.chipGroup.show()
holder.itemView.actionChip.text = data[position].arguments[0]
holder.itemView.actionChip.setChipIconResource(R.drawable.ic_edit_chip) /*
* The chip group will always contain the actionChip (it is defined in the xml layout).
* The other dynamic chips are inserted in front of the actionChip.
* This code tries to reuse already added chips to reduce the number of Views created.
*/
data[position].arguments.forEachIndexed { i, arg ->
val chip = holder.itemView.chipGroup.getChildAt(i).takeUnless { it.id == R.id.actionChip } as Chip?
?: Chip(context).apply {
text = arg
holder.itemView.chipGroup.addView(this, holder.itemView.chipGroup.size - 1)
}
chip.text = arg
if(data[position].arguments.size <= 1) {
chip.chipIcon = null
chip.setOnClickListener(null)
} else {
val cancelIcon = ThemeUtils.getTintedDrawable(context, R.drawable.ic_cancel_24dp, android.R.attr.textColorPrimary)
chip.chipIcon = cancelIcon
chip.setOnClickListener {
listener.onChipClicked(data[position], i)
}
}
}
while(holder.itemView.chipGroup.size - 1 > data[position].arguments.size) {
holder.itemView.chipGroup.removeViewAt(data[position].arguments.size - 1)
}
holder.itemView.actionChip.chipIcon = context.getDrawable(R.drawable.ic_edit_chip)
holder.itemView.actionChip.setOnClickListener { holder.itemView.actionChip.setOnClickListener {
listener.onActionChipClicked(data[position]) listener.onActionChipClicked(data[position])
} }

View File

@ -88,11 +88,11 @@ import com.keylesspalace.tusky.view.EndlessOnScrollListener;
import com.keylesspalace.tusky.viewdata.StatusViewData; import com.keylesspalace.tusky.viewdata.StatusViewData;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Objects;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.inject.Inject; import javax.inject.Inject;
@ -116,7 +116,8 @@ public class TimelineFragment extends SFragment implements
Injectable, ReselectableFragment, RefreshableFragment { Injectable, ReselectableFragment, RefreshableFragment {
private static final String TAG = "TimelineF"; // logging tag private static final String TAG = "TimelineF"; // logging tag
private static final String KIND_ARG = "kind"; private static final String KIND_ARG = "kind";
private static final String HASHTAG_OR_ID_ARG = "hashtag_or_id"; private static final String ID_ARG = "id";
private static final String HASHTAGS_ARG = "hastags";
private static final String ARG_ENABLE_SWIPE_TO_REFRESH = "arg.enable.swipe.to.refresh"; private static final String ARG_ENABLE_SWIPE_TO_REFRESH = "arg.enable.swipe.to.refresh";
private static final int LOAD_AT_ONCE = 30; private static final int LOAD_AT_ONCE = 30;
@ -160,7 +161,8 @@ public class TimelineFragment extends SFragment implements
private TimelineAdapter adapter; private TimelineAdapter adapter;
private Kind kind; private Kind kind;
private String hashtagOrId; private String id;
private List<String> tags;
private LinearLayoutManager layoutManager; private LinearLayoutManager layoutManager;
private EndlessOnScrollListener scrollListener; private EndlessOnScrollListener scrollListener;
private boolean filterRemoveReplies; private boolean filterRemoveReplies;
@ -201,25 +203,37 @@ public class TimelineFragment extends SFragment implements
public static TimelineFragment newInstance(Kind kind, @Nullable String hashtagOrId, boolean enableSwipeToRefresh) { public static TimelineFragment newInstance(Kind kind, @Nullable String hashtagOrId, boolean enableSwipeToRefresh) {
TimelineFragment fragment = new TimelineFragment(); TimelineFragment fragment = new TimelineFragment();
Bundle arguments = new Bundle(); Bundle arguments = new Bundle(3);
arguments.putString(KIND_ARG, kind.name()); arguments.putString(KIND_ARG, kind.name());
arguments.putString(HASHTAG_OR_ID_ARG, hashtagOrId); arguments.putString(ID_ARG, hashtagOrId);
arguments.putBoolean(ARG_ENABLE_SWIPE_TO_REFRESH, enableSwipeToRefresh); arguments.putBoolean(ARG_ENABLE_SWIPE_TO_REFRESH, enableSwipeToRefresh);
fragment.setArguments(arguments); fragment.setArguments(arguments);
return fragment; return fragment;
} }
public static TimelineFragment newHashtagInstance(@NonNull List<String> hashtags) {
TimelineFragment fragment = new TimelineFragment();
Bundle arguments = new Bundle(3);
arguments.putString(KIND_ARG, Kind.TAG.name());
arguments.putStringArrayList(HASHTAGS_ARG, new ArrayList<>(hashtags));
arguments.putBoolean(ARG_ENABLE_SWIPE_TO_REFRESH, true);
fragment.setArguments(arguments);
return fragment;
}
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Bundle arguments = requireArguments(); Bundle arguments = requireArguments();
kind = Kind.valueOf(arguments.getString(KIND_ARG)); kind = Kind.valueOf(arguments.getString(KIND_ARG));
if (kind == Kind.TAG if (kind == Kind.USER
|| kind == Kind.USER
|| kind == Kind.USER_PINNED || kind == Kind.USER_PINNED
|| kind == Kind.USER_WITH_REPLIES || kind == Kind.USER_WITH_REPLIES
|| kind == Kind.LIST) { || kind == Kind.LIST) {
hashtagOrId = arguments.getString(HASHTAG_OR_ID_ARG); id = arguments.getString(ID_ARG);
}
if(kind == Kind.TAG) {
tags = arguments.getStringArrayList(HASHTAGS_ARG);
} }
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
@ -822,7 +836,7 @@ public class TimelineFragment extends SFragment implements
@Override @Override
public void onViewTag(String tag) { public void onViewTag(String tag) {
if (kind == Kind.TAG && hashtagOrId.equals(tag)) { if (kind == Kind.TAG && tags.size() == 1 && tags.contains(tag)) {
// If already viewing a tag page, then ignore any request to view that tag again. // If already viewing a tag page, then ignore any request to view that tag again.
return; return;
} }
@ -831,7 +845,7 @@ public class TimelineFragment extends SFragment implements
@Override @Override
public void onViewAccount(String id) { public void onViewAccount(String id) {
if ((kind == Kind.USER || kind == Kind.USER_WITH_REPLIES) && hashtagOrId.equals(id)) { if ((kind == Kind.USER || kind == Kind.USER_WITH_REPLIES) && this.id.equals(id)) {
/* If already viewing an account page, then any requests to view that account page /* If already viewing an account page, then any requests to view that account page
* should be ignored. */ * should be ignored. */
return; return;
@ -981,8 +995,7 @@ public class TimelineFragment extends SFragment implements
} }
} }
private Call<List<Status>> getFetchCallByTimelineType(Kind kind, String tagOrId, String fromId, private Call<List<Status>> getFetchCallByTimelineType(String fromId, String uptoId) {
String uptoId) {
MastodonApi api = mastodonApi; MastodonApi api = mastodonApi;
switch (kind) { switch (kind) {
default: default:
@ -993,19 +1006,21 @@ public class TimelineFragment extends SFragment implements
case PUBLIC_LOCAL: case PUBLIC_LOCAL:
return api.publicTimeline(true, fromId, uptoId, LOAD_AT_ONCE); return api.publicTimeline(true, fromId, uptoId, LOAD_AT_ONCE);
case TAG: case TAG:
return api.hashtagTimeline(tagOrId, null, fromId, uptoId, LOAD_AT_ONCE); String firstHashtag = tags.get(0);
List<String> additionalHashtags = tags.subList(1, tags.size());
return api.hashtagTimeline(firstHashtag, additionalHashtags, null, fromId, uptoId, LOAD_AT_ONCE);
case USER: case USER:
return api.accountStatuses(tagOrId, fromId, uptoId, LOAD_AT_ONCE, true, null, null); return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, true, null, null);
case USER_PINNED: case USER_PINNED:
return api.accountStatuses(tagOrId, fromId, uptoId, LOAD_AT_ONCE, null, null, true); return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, null, null, true);
case USER_WITH_REPLIES: case USER_WITH_REPLIES:
return api.accountStatuses(tagOrId, fromId, uptoId, LOAD_AT_ONCE, null, null, null); return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, null, null, null);
case FAVOURITES: case FAVOURITES:
return api.favourites(fromId, uptoId, LOAD_AT_ONCE); return api.favourites(fromId, uptoId, LOAD_AT_ONCE);
case BOOKMARKS: case BOOKMARKS:
return api.bookmarks(fromId, uptoId, LOAD_AT_ONCE); return api.bookmarks(fromId, uptoId, LOAD_AT_ONCE);
case LIST: case LIST:
return api.listTimeline(tagOrId, fromId, uptoId, LOAD_AT_ONCE); return api.listTimeline(id, fromId, uptoId, LOAD_AT_ONCE);
} }
} }
@ -1047,7 +1062,7 @@ public class TimelineFragment extends SFragment implements
} }
}; };
Call<List<Status>> listCall = getFetchCallByTimelineType(kind, hashtagOrId, maxId, sinceId); Call<List<Status>> listCall = getFetchCallByTimelineType(maxId, sinceId);
callList.add(listCall); callList.add(listCall);
listCall.enqueue(callback); listCall.enqueue(callback);
} }
@ -1330,7 +1345,7 @@ public class TimelineFragment extends SFragment implements
break; break;
case USER: case USER:
case USER_WITH_REPLIES: case USER_WITH_REPLIES:
if (status.getAccount().getId().equals(hashtagOrId)) { if (status.getAccount().getId().equals(id)) {
break; break;
} else { } else {
return; return;

View File

@ -76,6 +76,7 @@ interface MastodonApi {
@GET("api/v1/timelines/tag/{hashtag}") @GET("api/v1/timelines/tag/{hashtag}")
fun hashtagTimeline( fun hashtagTimeline(
@Path("hashtag") hashtag: String, @Path("hashtag") hashtag: String,
@Query("any[]") any: List<String>?,
@Query("local") local: Boolean?, @Query("local") local: Boolean?,
@Query("max_id") maxId: String?, @Query("max_id") maxId: String?,
@Query("since_id") sinceId: String?, @Query("since_id") sinceId: String?,

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="24dp"
android:layout_height="24dp">
<background android:drawable="@color/tusky_blue" />
<foreground>
<inset
android:drawable="@drawable/ic_create_24dp"
android:inset="30%" />
</foreground>
</adaptive-icon>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:attr/textColorPrimary"
android:pathData="m4.5088,16.3703v3.1209H7.6297L16.8342,10.2866 13.7134,7.1658ZM19.2477,7.8732c0.3246,-0.3246 0.3246,-0.8489 0,-1.1735l-1.9474,-1.9474c-0.3246,-0.3246 -0.8489,-0.3246 -1.1735,0l-1.523,1.523 3.1209,3.1209z" />
</vector>

View File

@ -26,10 +26,10 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:layout_weight="1" android:layout_weight="1"
android:drawablePadding="12dp" android:drawablePadding="12dp"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:textSize="?attr/status_text_large" android:textSize="?attr/status_text_large"
app:layout_constraintBottom_toTopOf="@id/chipGroup" app:layout_constraintBottom_toTopOf="@id/chipGroup"
@ -57,9 +57,7 @@
android:id="@+id/chipGroup" android:id="@+id/chipGroup"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:paddingTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"> app:layout_constraintBottom_toBottomOf="parent">
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
@ -68,7 +66,9 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checkable="false" android:checkable="false"
tools:text="add hashtag" /> android:text="@string/add_hashtag_title"
app:chipIcon="@drawable/ic_plus_24dp"
app:chipSurfaceColor="@color/tusky_blue" />
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>

View File

@ -342,9 +342,7 @@
<string name="downloading_media">جارٍ تنزيل الوسائط</string> <string name="downloading_media">جارٍ تنزيل الوسائط</string>
<string name="dialog_redraft_toot_warning">هل تريد حذف وإعادة صياغة هذا التبويق؟</string> <string name="dialog_redraft_toot_warning">هل تريد حذف وإعادة صياغة هذا التبويق؟</string>
<string name="description_status_favourited">تم تفضيله</string> <string name="description_status_favourited">تم تفضيله</string>
<string name="edit_hashtag_title">تعديل الوسم</string>
<string name="edit_hashtag_hint">وسم بدون #</string> <string name="edit_hashtag_hint">وسم بدون #</string>
<string name="hashtag">الوسم</string>
<string name="notifications_clear">مسح</string> <string name="notifications_clear">مسح</string>
<string name="notifications_apply_filter">عامل تصفية</string> <string name="notifications_apply_filter">عامل تصفية</string>
<string name="filter_apply">طَبِّق</string> <string name="filter_apply">طَبِّق</string>

View File

@ -416,9 +416,7 @@
<string name="hint_list_name">নামের তালিকা</string> <string name="hint_list_name">নামের তালিকা</string>
<string name="edit_hashtag_title">হ্যাশট্যাগ সম্পাদনা করুন</string>
<string name="edit_hashtag_hint"># ছাড়া হ্যাশট্যাগ</string> <string name="edit_hashtag_hint"># ছাড়া হ্যাশট্যাগ</string>
<string name="hashtag">হ্যাশট্যাগ</string>
<string name="notifications_clear">পরিষ্কার</string> <string name="notifications_clear">পরিষ্কার</string>
<string name="notifications_apply_filter">ফিল্টার</string> <string name="notifications_apply_filter">ফিল্টার</string>
<string name="filter_apply">প্রয়োগ</string> <string name="filter_apply">প্রয়োগ</string>

View File

@ -420,9 +420,7 @@
<string name="description_visiblity_direct">Directe</string> <string name="description_visiblity_direct">Directe</string>
<string name="hint_list_name">Nom de la llista</string> <string name="hint_list_name">Nom de la llista</string>
<string name="edit_hashtag_title">Modificar el hashtag</string>
<string name="edit_hashtag_hint">Hashtag sense #</string> <string name="edit_hashtag_hint">Hashtag sense #</string>
<string name="hashtag">Hashtag</string>
<string name="notifications_clear">Netejar</string> <string name="notifications_clear">Netejar</string>
<string name="notifications_apply_filter">Filtrar</string> <string name="notifications_apply_filter">Filtrar</string>
<string name="filter_apply">Aplicar</string> <string name="filter_apply">Aplicar</string>

View File

@ -364,9 +364,7 @@
<string name="description_visiblity_direct"> Přímý <string name="description_visiblity_direct"> Přímý
</string> </string>
<string name="hint_list_name">Název seznamu</string> <string name="hint_list_name">Název seznamu</string>
<string name="edit_hashtag_title">Upravit hashtag</string>
<string name="edit_hashtag_hint">Hashtag bez #</string> <string name="edit_hashtag_hint">Hashtag bez #</string>
<string name="hashtag">Hashtag</string>
<string name="compose_shortcut_long_label">Napsat toot</string> <string name="compose_shortcut_long_label">Napsat toot</string>
<string name="compose_shortcut_short_label">Napsat</string> <string name="compose_shortcut_short_label">Napsat</string>

View File

@ -329,9 +329,7 @@
<string name="error_delete_list">Liste konnte nicht gelöscht werden</string> <string name="error_delete_list">Liste konnte nicht gelöscht werden</string>
<string name="hint_search_people_list">Suche nach Leuten denen du folgst</string> <string name="hint_search_people_list">Suche nach Leuten denen du folgst</string>
<string name="action_remove_from_list">Von der Liste entfernen</string> <string name="action_remove_from_list">Von der Liste entfernen</string>
<string name="edit_hashtag_title">Hashtag bearbeiten</string>
<string name="edit_hashtag_hint">Hashtag ohne #</string> <string name="edit_hashtag_hint">Hashtag ohne #</string>
<string name="hashtag">Hashtag</string>
<string name="action_open_reblogger">Öffne Autor des geteilten Beitrages</string> <string name="action_open_reblogger">Öffne Autor des geteilten Beitrages</string>
<string name="pref_title_public_filter_keywords">Öffentliche Zeitleisten</string> <string name="pref_title_public_filter_keywords">Öffentliche Zeitleisten</string>
<plurals name="favs"> <plurals name="favs">

View File

@ -367,10 +367,7 @@
<string name="notification_poll_name">Enketoj</string> <string name="notification_poll_name">Enketoj</string>
<string name="notification_poll_description">Sciigoj pri enketoj kiuj finiĝis</string> <string name="notification_poll_description">Sciigoj pri enketoj kiuj finiĝis</string>
<string name="edit_hashtag_title">Redakti kradvorton</string>
<string name="edit_hashtag_hint">Kradvortoj sen #</string> <string name="edit_hashtag_hint">Kradvortoj sen #</string>
<string name="hashtag">Kradvorto</string>
<string name="notifications_clear">Viŝi</string> <string name="notifications_clear">Viŝi</string>
<string name="notifications_apply_filter">Filtri</string> <string name="notifications_apply_filter">Filtri</string>
<string name="filter_apply">Apliki</string> <string name="filter_apply">Apliki</string>

View File

@ -381,9 +381,7 @@
<string name="description_visiblity_unlisted">Sin listar</string> <string name="description_visiblity_unlisted">Sin listar</string>
<string name="description_visiblity_direct">Directo</string> <string name="description_visiblity_direct">Directo</string>
<string name="hint_list_name">Nombre de la lista</string> <string name="hint_list_name">Nombre de la lista</string>
<string name="edit_hashtag_title">Editar etiqueta</string>
<string name="edit_hashtag_hint">Etiqueta sin #</string> <string name="edit_hashtag_hint">Etiqueta sin #</string>
<string name="hashtag">Etiqueta</string>
<string name="notifications_clear">Limpiar</string> <string name="notifications_clear">Limpiar</string>
<string name="notifications_apply_filter">Filtro</string> <string name="notifications_apply_filter">Filtro</string>
<string name="compose_shortcut_long_label">Componer toot</string> <string name="compose_shortcut_long_label">Componer toot</string>

View File

@ -373,9 +373,7 @@
<string name="description_visiblity_direct">Zuzena</string> <string name="description_visiblity_direct">Zuzena</string>
<string name="description_poll">Inkestatu aukerekin: %1$s, %2$s, %3$s, %4$s; %5$s</string> <string name="description_poll">Inkestatu aukerekin: %1$s, %2$s, %3$s, %4$s; %5$s</string>
<string name="hint_list_name">Zerrendaren izena</string> <string name="hint_list_name">Zerrendaren izena</string>
<string name="edit_hashtag_title">Editatu traola</string>
<string name="edit_hashtag_hint">Traola # gabe</string> <string name="edit_hashtag_hint">Traola # gabe</string>
<string name="hashtag">Traola</string>
<string name="notifications_clear">Garbitu</string> <string name="notifications_clear">Garbitu</string>
<string name="notifications_apply_filter">Iragazi</string> <string name="notifications_apply_filter">Iragazi</string>
<string name="filter_apply">Aplikatu</string> <string name="filter_apply">Aplikatu</string>

View File

@ -364,9 +364,7 @@
<string name="description_visiblity_direct">مستقیم</string> <string name="description_visiblity_direct">مستقیم</string>
<string name="description_poll">نظرسنجی با انتخاب‌ها: %1$s، %2$s، %3$s، %4$s؛ %5$s</string> <string name="description_poll">نظرسنجی با انتخاب‌ها: %1$s، %2$s، %3$s، %4$s؛ %5$s</string>
<string name="hint_list_name">نام فهرست</string> <string name="hint_list_name">نام فهرست</string>
<string name="edit_hashtag_title">ویرایش برچسب</string>
<string name="edit_hashtag_hint">برچسب بدون #</string> <string name="edit_hashtag_hint">برچسب بدون #</string>
<string name="hashtag">برچسب</string>
<string name="notifications_clear">پاک‌سازی</string> <string name="notifications_clear">پاک‌سازی</string>
<string name="notifications_apply_filter">پالایش</string> <string name="notifications_apply_filter">پالایش</string>
<string name="filter_apply">اعمال</string> <string name="filter_apply">اعمال</string>

View File

@ -362,9 +362,7 @@
<string name="description_visiblity_direct"> Direct <string name="description_visiblity_direct"> Direct
</string> </string>
<string name="hint_list_name">Nom de la liste</string> <string name="hint_list_name">Nom de la liste</string>
<string name="edit_hashtag_title">Édition des hashtags</string>
<string name="edit_hashtag_hint">Hashtags sans #</string> <string name="edit_hashtag_hint">Hashtags sans #</string>
<string name="hashtag">Hashtag</string>
<string name="notifications_clear">Effacer</string> <string name="notifications_clear">Effacer</string>
<string name="notifications_apply_filter">Filtrer</string> <string name="notifications_apply_filter">Filtrer</string>
<string name="filter_apply">Appliquer</string> <string name="filter_apply">Appliquer</string>

View File

@ -390,9 +390,7 @@
<string name="hint_list_name">Lista neve</string> <string name="hint_list_name">Lista neve</string>
<string name="edit_hashtag_title">Hashtag szerkesztése</string>
<string name="edit_hashtag_hint">Hashtag # nélkül</string> <string name="edit_hashtag_hint">Hashtag # nélkül</string>
<string name="hashtag">Hashtag</string>
<string name="notifications_clear">Törlés</string> <string name="notifications_clear">Törlés</string>
<string name="notifications_apply_filter">Szűrés</string> <string name="notifications_apply_filter">Szűrés</string>
<string name="filter_apply">Alkalmaz</string> <string name="filter_apply">Alkalmaz</string>

View File

@ -428,9 +428,7 @@
<string name="hint_list_name">Heiti á lista</string> <string name="hint_list_name">Heiti á lista</string>
<string name="edit_hashtag_title">Breyta myllumerki</string>
<string name="edit_hashtag_hint">Myllumerki án #</string> <string name="edit_hashtag_hint">Myllumerki án #</string>
<string name="hashtag">Myllumerki</string>
<string name="select_list_title">Veldu lista</string> <string name="select_list_title">Veldu lista</string>
<string name="list">Listi</string> <string name="list">Listi</string>
<string name="notifications_clear">Hreinsa</string> <string name="notifications_clear">Hreinsa</string>

View File

@ -359,9 +359,7 @@
<string name="download_media">Scarica media</string> <string name="download_media">Scarica media</string>
<string name="downloading_media">Scaricando media</string> <string name="downloading_media">Scaricando media</string>
<string name="edit_hashtag_title">Modifica hashtag</string>
<string name="edit_hashtag_hint">Hashtag senza #</string> <string name="edit_hashtag_hint">Hashtag senza #</string>
<string name="hashtag">Hashtag</string>
<string name="compose_shortcut_long_label">Componi Toot</string> <string name="compose_shortcut_long_label">Componi Toot</string>

View File

@ -398,8 +398,6 @@
<string name="pref_title_public_filter_keywords">公開タイムライン</string> <string name="pref_title_public_filter_keywords">公開タイムライン</string>
<string name="description_status_cw">閲覧注意:%s</string> <string name="description_status_cw">閲覧注意:%s</string>
<string name="edit_hashtag_title">ハッシュタグの編集</string>
<string name="hashtag">ハッシュタグ</string>
<string name="filter_apply">適用</string> <string name="filter_apply">適用</string>
<string name="poll_info_closed">投票終了</string> <string name="poll_info_closed">投票終了</string>

View File

@ -368,9 +368,7 @@
<string name="description_visiblity_direct">다이렉트</string> <string name="description_visiblity_direct">다이렉트</string>
<string name="description_poll">투표 선택지: %1$s, %2$s, %3$s, %4$s, %5$s</string> <string name="description_poll">투표 선택지: %1$s, %2$s, %3$s, %4$s, %5$s</string>
<string name="hint_list_name">리스트 이름</string> <string name="hint_list_name">리스트 이름</string>
<string name="edit_hashtag_title">해시태그 편집</string>
<string name="edit_hashtag_hint">#를 제외한 해시태그</string> <string name="edit_hashtag_hint">#를 제외한 해시태그</string>
<string name="hashtag">해시태그</string>
<string name="notifications_clear">알림 지우기</string> <string name="notifications_clear">알림 지우기</string>
<string name="notifications_apply_filter">필터</string> <string name="notifications_apply_filter">필터</string>
<string name="filter_apply">적용</string> <string name="filter_apply">적용</string>

View File

@ -356,9 +356,7 @@
<string name="action_add_to_list">Account aan de lijst toevoegen</string> <string name="action_add_to_list">Account aan de lijst toevoegen</string>
<string name="action_remove_from_list">Account uit de lijst verwijderen</string> <string name="action_remove_from_list">Account uit de lijst verwijderen</string>
<string name="hint_list_name">Naam van lijst</string> <string name="hint_list_name">Naam van lijst</string>
<string name="edit_hashtag_title">Hashtag bewerken</string>
<string name="edit_hashtag_hint">Hashtag zonder #</string> <string name="edit_hashtag_hint">Hashtag zonder #</string>
<string name="hashtag">Hashtag</string>
<string name="action_delete_and_redraft">Verwijderen en herschrijven</string> <string name="action_delete_and_redraft">Verwijderen en herschrijven</string>
<string name="dialog_redraft_toot_warning">Deze toot verwijderen en herschrijven\?</string> <string name="dialog_redraft_toot_warning">Deze toot verwijderen en herschrijven\?</string>
<string name="notifications_clear">Leegmaken</string> <string name="notifications_clear">Leegmaken</string>

View File

@ -328,9 +328,7 @@
<string name="description_visiblity_private">Følgere</string> <string name="description_visiblity_private">Følgere</string>
<string name="description_visiblity_direct">Direkte</string> <string name="description_visiblity_direct">Direkte</string>
<string name="hint_list_name">Listenavn</string> <string name="hint_list_name">Listenavn</string>
<string name="edit_hashtag_title">Endre emneord</string>
<string name="edit_hashtag_hint">Emneord uten #</string> <string name="edit_hashtag_hint">Emneord uten #</string>
<string name="hashtag">Emneord</string>
<string name="notifications_clear">Slett</string> <string name="notifications_clear">Slett</string>
<string name="notifications_apply_filter">Filter</string> <string name="notifications_apply_filter">Filter</string>
<string name="filter_apply">Bruk</string> <string name="filter_apply">Bruk</string>

View File

@ -351,9 +351,7 @@
<string name="description_visiblity_private">Seguidors</string> <string name="description_visiblity_private">Seguidors</string>
<string name="description_visiblity_direct">Dirècte</string> <string name="description_visiblity_direct">Dirècte</string>
<string name="hint_list_name">Nom de la lista</string> <string name="hint_list_name">Nom de la lista</string>
<string name="edit_hashtag_title">Modificar las etiquetas</string>
<string name="edit_hashtag_hint">Etiquetas sens #</string> <string name="edit_hashtag_hint">Etiquetas sens #</string>
<string name="hashtag">Etiqueta</string>
<string name="compose_shortcut_long_label">Escriure un tut</string> <string name="compose_shortcut_long_label">Escriure un tut</string>
<string name="compose_shortcut_short_label">Escriure</string> <string name="compose_shortcut_short_label">Escriure</string>
<string name="action_delete_and_redraft">Suprimir e reformular</string> <string name="action_delete_and_redraft">Suprimir e reformular</string>

View File

@ -373,9 +373,7 @@
<string name="description_visiblity_direct">Bezpośrednio</string> <string name="description_visiblity_direct">Bezpośrednio</string>
<string name="description_poll">Głosowanie z opcjami: %1$s, %2$s, %3$s, %4$s; %5$s</string> <string name="description_poll">Głosowanie z opcjami: %1$s, %2$s, %3$s, %4$s; %5$s</string>
<string name="hint_list_name">Nazwa listy</string> <string name="hint_list_name">Nazwa listy</string>
<string name="edit_hashtag_title">Edytuj hashtag</string>
<string name="edit_hashtag_hint">Hashtag bez #</string> <string name="edit_hashtag_hint">Hashtag bez #</string>
<string name="hashtag">Hashtag</string>
<string name="notifications_clear">Wyczyść</string> <string name="notifications_clear">Wyczyść</string>
<string name="notifications_apply_filter">Filtr</string> <string name="notifications_apply_filter">Filtr</string>
<string name="filter_apply">Zastosuj</string> <string name="filter_apply">Zastosuj</string>

View File

@ -356,9 +356,7 @@
<string name="description_visiblity_unlisted">Não-listado</string> <string name="description_visiblity_unlisted">Não-listado</string>
<string name="description_visiblity_direct">Direta</string> <string name="description_visiblity_direct">Direta</string>
<string name="hint_list_name">Nome da lista</string> <string name="hint_list_name">Nome da lista</string>
<string name="edit_hashtag_title">Editar hashtag</string>
<string name="edit_hashtag_hint">Hashtag sem #</string> <string name="edit_hashtag_hint">Hashtag sem #</string>
<string name="hashtag">Hashtag</string>
<string name="notifications_clear">Limpar</string> <string name="notifications_clear">Limpar</string>
<string name="notifications_apply_filter">Filtro</string> <string name="notifications_apply_filter">Filtro</string>
<string name="filter_apply">Salvar</string> <string name="filter_apply">Salvar</string>

View File

@ -394,9 +394,7 @@
Для упомянутых Для упомянутых
</string> </string>
<string name="hint_list_name">Название списка</string> <string name="hint_list_name">Название списка</string>
<string name="edit_hashtag_title">Изм. хэштег</string>
<string name="edit_hashtag_hint">Хэштег без #</string> <string name="edit_hashtag_hint">Хэштег без #</string>
<string name="hashtag">Хэштег</string>
<string name="notifications_clear">Очистить</string> <string name="notifications_clear">Очистить</string>
<string name="notifications_apply_filter">Фильтр</string> <string name="notifications_apply_filter">Фильтр</string>
<string name="filter_apply">Применить</string> <string name="filter_apply">Применить</string>

View File

@ -332,9 +332,7 @@
<string name="description_visiblity_private">Sledilci</string> <string name="description_visiblity_private">Sledilci</string>
<string name="description_visiblity_direct">Neposredno</string> <string name="description_visiblity_direct">Neposredno</string>
<string name="hint_list_name">Ime seznama</string> <string name="hint_list_name">Ime seznama</string>
<string name="edit_hashtag_title">Uredi ključnik</string>
<string name="edit_hashtag_hint">Ključnik brez #</string> <string name="edit_hashtag_hint">Ključnik brez #</string>
<string name="hashtag">Ključnik</string>
<string name="notifications_clear">Počisti</string> <string name="notifications_clear">Počisti</string>
<string name="notifications_apply_filter">Filter</string> <string name="notifications_apply_filter">Filter</string>
<string name="filter_apply">Uporabi</string> <string name="filter_apply">Uporabi</string>

View File

@ -358,9 +358,7 @@
<string name="hint_list_name">Listnamn</string> <string name="hint_list_name">Listnamn</string>
<string name="download_media">Ladda ned media</string> <string name="download_media">Ladda ned media</string>
<string name="downloading_media">Laddar ned media</string> <string name="downloading_media">Laddar ned media</string>
<string name="edit_hashtag_title">Redigera hashtag</string>
<string name="edit_hashtag_hint">Hashtag utan #</string> <string name="edit_hashtag_hint">Hashtag utan #</string>
<string name="hashtag">Hashtag</string>
<string name="compose_shortcut_long_label">Skriv toot</string> <string name="compose_shortcut_long_label">Skriv toot</string>
<string name="compose_shortcut_short_label">Skriv</string> <string name="compose_shortcut_short_label">Skriv</string>
<string name="notifications_clear">Rensa</string> <string name="notifications_clear">Rensa</string>

View File

@ -351,9 +351,7 @@
<string name="description_visiblity_direct">Direkt</string> <string name="description_visiblity_direct">Direkt</string>
<string name="description_poll">Seçenekli anket: %1$s, %2$s, %3$s, %4$s; %5$s</string> <string name="description_poll">Seçenekli anket: %1$s, %2$s, %3$s, %4$s; %5$s</string>
<string name="hint_list_name">Liste adı</string> <string name="hint_list_name">Liste adı</string>
<string name="edit_hashtag_title">Hashtag\'i düzenle</string>
<string name="edit_hashtag_hint"># olmadan hashtag</string> <string name="edit_hashtag_hint"># olmadan hashtag</string>
<string name="hashtag">Hashtag</string>
<string name="notifications_clear">Temizle</string> <string name="notifications_clear">Temizle</string>
<string name="notifications_apply_filter">Filtre</string> <string name="notifications_apply_filter">Filtre</string>
<string name="filter_apply">Uygula</string> <string name="filter_apply">Uygula</string>

View File

@ -370,9 +370,7 @@
私信 私信
</string> </string>
<string name="hint_list_name">列表名</string> <string name="hint_list_name">列表名</string>
<string name="edit_hashtag_title">编辑话题</string>
<string name="edit_hashtag_hint">话题名(不含前面的 # 号)</string> <string name="edit_hashtag_hint">话题名(不含前面的 # 号)</string>
<string name="hashtag">话题</string>
<string name="notifications_clear">清空</string> <string name="notifications_clear">清空</string>
<string name="notifications_apply_filter">分类</string> <string name="notifications_apply_filter">分类</string>
<string name="filter_apply">应用</string> <string name="filter_apply">应用</string>

View File

@ -366,9 +366,7 @@
私信 私信
</string> </string>
<string name="hint_list_name">列表名</string> <string name="hint_list_name">列表名</string>
<string name="edit_hashtag_title">編輯話題</string>
<string name="edit_hashtag_hint">話題名(不含前面的 # 號)</string> <string name="edit_hashtag_hint">話題名(不含前面的 # 號)</string>
<string name="hashtag">話題</string>
<string name="notifications_clear">清空</string> <string name="notifications_clear">清空</string>
<string name="notifications_apply_filter">分類</string> <string name="notifications_apply_filter">分類</string>
<string name="filter_apply">應用</string> <string name="filter_apply">應用</string>

View File

@ -366,9 +366,7 @@
私信 私信
</string> </string>
<string name="hint_list_name">列表名</string> <string name="hint_list_name">列表名</string>
<string name="edit_hashtag_title">編輯話題</string>
<string name="edit_hashtag_hint">話題名(不含前面的 # 號)</string> <string name="edit_hashtag_hint">話題名(不含前面的 # 號)</string>
<string name="hashtag">話題</string>
<string name="notifications_clear">清空</string> <string name="notifications_clear">清空</string>
<string name="notifications_apply_filter">分類</string> <string name="notifications_apply_filter">分類</string>
<string name="filter_apply">應用</string> <string name="filter_apply">應用</string>

View File

@ -434,9 +434,7 @@
<string name="hint_list_name">列表名</string> <string name="hint_list_name">列表名</string>
<string name="edit_hashtag_title">编辑话题</string>
<string name="edit_hashtag_hint">话题名(不含前面的 # 号)</string> <string name="edit_hashtag_hint">话题名(不含前面的 # 号)</string>
<string name="hashtag">话题</string>
<string name="notifications_clear">清空</string> <string name="notifications_clear">清空</string>
<string name="notifications_apply_filter">分类</string> <string name="notifications_apply_filter">分类</string>
<string name="filter_apply">应用</string> <string name="filter_apply">应用</string>

View File

@ -366,9 +366,7 @@
私信 私信
</string> </string>
<string name="hint_list_name">列表名</string> <string name="hint_list_name">列表名</string>
<string name="edit_hashtag_title">編輯話題</string>
<string name="edit_hashtag_hint">話題名(不含前面的 # 號)</string> <string name="edit_hashtag_hint">話題名(不含前面的 # 號)</string>
<string name="hashtag">話題</string>
<string name="notifications_clear">清空</string> <string name="notifications_clear">清空</string>
<string name="notifications_apply_filter">分類</string> <string name="notifications_apply_filter">分類</string>
<string name="filter_apply">應用</string> <string name="filter_apply">應用</string>

View File

@ -474,9 +474,9 @@
<string name="hint_list_name">List name</string> <string name="hint_list_name">List name</string>
<string name="edit_hashtag_title">Edit hashtag</string> <string name="add_hashtag_title">Add hashtag</string>
<string name="edit_hashtag_hint">Hashtag without #</string> <string name="edit_hashtag_hint">Hashtag without #</string>
<string name="hashtag">Hashtag</string> <string name="hashtags">Hashtags</string>
<string name="select_list_title">Select list</string> <string name="select_list_title">Select list</string>
<string name="list">List</string> <string name="list">List</string>
<string name="notifications_clear">Clear</string> <string name="notifications_clear">Clear</string>