Merge upstream

main
Alibek Omarov 5 years ago
commit f2d14a0f9b
  1. 9
      app/build.gradle
  2. 2
      app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt
  3. 106
      app/src/main/java/com/keylesspalace/tusky/EmojiPreference.java
  4. 39
      app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java
  5. 4
      app/src/main/java/com/keylesspalace/tusky/components/compose/ComposeViewModel.kt
  6. 5
      app/src/main/java/com/keylesspalace/tusky/components/compose/dialog/CaptionDialog.kt
  7. 2
      app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationEntity.kt
  8. 3
      app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsViewModel.kt
  9. 22
      app/src/main/java/com/keylesspalace/tusky/components/search/adapter/SearchDataSource.kt
  10. 4
      app/src/main/java/com/keylesspalace/tusky/entity/Account.kt
  11. 2
      app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java
  12. 9
      app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.kt
  13. 2
      app/src/main/java/com/keylesspalace/tusky/repository/TimelineRepository.kt
  14. 92
      app/src/main/java/com/keylesspalace/tusky/util/EmojiCompatFont.java
  15. 2
      app/src/main/res/drawable/status_divider.xml
  16. 4
      app/src/main/res/layout-sw640dp/fragment_timeline.xml
  17. 18
      app/src/main/res/layout/activity_license.xml
  18. 2
      app/src/main/res/layout/activity_main.xml
  19. 4
      app/src/main/res/layout/fragment_accounts_in_list.xml
  20. 3
      app/src/main/res/layout/fragment_timeline_notifications.xml
  21. 11
      app/src/main/res/values-de/strings.xml
  22. 2
      app/src/main/res/values-en-rAU/strings.xml
  23. 2
      app/src/main/res/values-en-rUS/strings.xml
  24. 12
      app/src/main/res/values-es/strings.xml
  25. 42
      app/src/main/res/values-fa/strings.xml
  26. 2
      app/src/main/res/values-fr-rBE/strings.xml
  27. 10
      app/src/main/res/values-fr/strings.xml
  28. 5
      app/src/main/res/values-is/strings.xml
  29. 192
      app/src/main/res/values-kab/strings.xml
  30. 2
      app/src/main/res/values-lb/strings.xml
  31. 3
      app/src/main/res/values-night/theme_colors.xml
  32. 28
      app/src/main/res/values-nl/strings.xml
  33. 8
      app/src/main/res/values-pl/strings.xml
  34. 4
      app/src/main/res/values-pt-rBR/strings.xml
  35. 1
      app/src/main/res/values-ru/strings.xml
  36. 84
      app/src/main/res/values-sk/strings.xml
  37. 6
      app/src/main/res/values-sv/strings.xml
  38. 6
      app/src/main/res/values-v27/styles.xml
  39. 1
      app/src/main/res/values/attrs.xml
  40. 1
      app/src/main/res/values/colors.xml
  41. 2
      app/src/main/res/values/dimens.xml
  42. 4
      app/src/main/res/values/donottranslate.xml
  43. 9
      app/src/main/res/values/styles.xml
  44. 3
      app/src/main/res/values/theme_colors.xml
  45. 3
      fastlane/metadata/android/ar/changelogs/68.txt
  46. 7
      fastlane/metadata/android/de/changelogs/61.txt
  47. 8
      fastlane/metadata/android/de/changelogs/70.txt
  48. 8
      fastlane/metadata/android/en-US/changelogs/70.txt
  49. BIN
      fastlane/metadata/android/en-US/images/phoneScreenshots/01_timeline.png
  50. BIN
      fastlane/metadata/android/en-US/images/phoneScreenshots/02_compose.png
  51. BIN
      fastlane/metadata/android/en-US/images/phoneScreenshots/04_favourites.png
  52. BIN
      fastlane/metadata/android/en-US/images/phoneScreenshots/05_reply.png
  53. 7
      fastlane/metadata/android/nl/changelogs/61.txt
  54. 9
      fastlane/metadata/android/nl/changelogs/67.txt
  55. 3
      fastlane/metadata/android/nl/changelogs/68.txt
  56. 1
      fastlane/metadata/android/nl/short_description.txt
  57. 1
      fastlane/metadata/android/nl/title.txt
  58. 9
      fastlane/metadata/android/sk/changelogs/67.txt
  59. 3
      fastlane/metadata/android/sk/changelogs/68.txt
  60. 1
      fastlane/metadata/android/sk/short_description.txt
  61. 2
      fastlane/metadata/android/sv/changelogs/61.txt
  62. 3
      fastlane/metadata/android/sv/changelogs/68.txt

@ -20,8 +20,8 @@ android {
applicationId APP_ID applicationId APP_ID
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode 68 versionCode 69
versionName "9.1" versionName "10.0 beta 1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@ -66,6 +66,9 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
androidExtensions {
experimental = true
}
testOptions { testOptions {
unitTests { unitTests {
returnDefaultValues = true returnDefaultValues = true
@ -98,7 +101,7 @@ project.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
ext.lifecycleVersion = "2.1.0" ext.lifecycleVersion = "2.1.0"
ext.roomVersion = '2.2.3' ext.roomVersion = '2.2.3'
ext.retrofitVersion = '2.6.0' ext.retrofitVersion = '2.6.0'
ext.okhttpVersion = '4.2.2' ext.okhttpVersion = '4.3.1'
ext.glideVersion = '4.10.0' ext.glideVersion = '4.10.0'
ext.daggerVersion = '2.25.3' ext.daggerVersion = '2.25.3'

@ -464,7 +464,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
loadAvatar(movedAccount.avatar, accountMovedAvatar, avatarRadius, animateAvatar) loadAvatar(movedAccount.avatar, accountMovedAvatar, avatarRadius, animateAvatar)
accountMovedText.text = getString(R.string.account_moved_description, movedAccount.displayName) accountMovedText.text = getString(R.string.account_moved_description, movedAccount.name)
// this is necessary because API 19 can't handle vector compound drawables // this is necessary because API 19 can't handle vector compound drawables
val movedIcon = ContextCompat.getDrawable(this, R.drawable.ic_briefcase)?.mutate() val movedIcon = ContextCompat.getDrawable(this, R.drawable.ic_briefcase)?.mutate()

@ -1,14 +1,10 @@
package com.keylesspalace.tusky; package com.keylesspalace.tusky;
import android.app.AlarmManager; import android.app.AlarmManager;
import androidx.appcompat.app.AlertDialog;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -20,6 +16,10 @@ import android.widget.RadioButton;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import com.keylesspalace.tusky.util.EmojiCompatFont; import com.keylesspalace.tusky.util.EmojiCompatFont;
import java.util.ArrayList; import java.util.ArrayList;
@ -44,7 +44,6 @@ public class EmojiPreference extends Preference {
private boolean updated, currentNeedsUpdate; private boolean updated, currentNeedsUpdate;
public EmojiPreference(Context context, AttributeSet attrs) { public EmojiPreference(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
@ -63,7 +62,7 @@ public class EmojiPreference extends Preference {
View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_emojicompat, null); View view = LayoutInflater.from(getContext()).inflate(R.layout.dialog_emojicompat, null);
for(int i = 0; i < viewIds.length; i++) { for (int i = 0; i < viewIds.length; i++) {
setupItem(view.findViewById(viewIds[i]), FONTS[i]); setupItem(view.findViewById(viewIds[i]), FONTS[i]);
} }
@ -96,13 +95,13 @@ public class EmojiPreference extends Preference {
// Set actions // Set actions
download.setOnClickListener((downloadButton) -> download.setOnClickListener((downloadButton) ->
startDownload(font, container)); startDownload(font, container));
cancel.setOnClickListener((cancelButton) -> cancel.setOnClickListener((cancelButton) ->
cancelDownload(font, container)); cancelDownload(font, container));
radio.setOnClickListener((radioButton) -> radio.setOnClickListener((radioButton) ->
select(font, (RadioButton) radioButton)); select(font, (RadioButton) radioButton));
container.setOnClickListener((containterView) -> container.setOnClickListener((containterView) ->
select(font, select(font,
@ -111,11 +110,11 @@ public class EmojiPreference extends Preference {
} }
private void startDownload(EmojiCompatFont font, View container) { private void startDownload(EmojiCompatFont font, View container) {
ImageButton download = container.findViewById(R.id.emojicompat_download); ImageButton download = container.findViewById(R.id.emojicompat_download);
TextView caption = container.findViewById(R.id.emojicompat_caption); TextView caption = container.findViewById(R.id.emojicompat_caption);
ProgressBar progressBar = container.findViewById(R.id.emojicompat_progress); ProgressBar progressBar = container.findViewById(R.id.emojicompat_progress);
ImageButton cancel = container.findViewById(R.id.emojicompat_download_cancel); ImageButton cancel = container.findViewById(R.id.emojicompat_download_cancel);
// Switch to downloading style // Switch to downloading style
download.setVisibility(View.GONE); download.setVisibility(View.GONE);
@ -136,8 +135,7 @@ public class EmojiPreference extends Preference {
progress *= progressBar.getMax(); progress *= progressBar.getMax();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
progressBar.setProgress((int) progress, true); progressBar.setProgress((int) progress, true);
} } else {
else {
progressBar.setProgress((int) progress); progressBar.setProgress((int) progress);
} }
} }
@ -167,14 +165,15 @@ public class EmojiPreference extends Preference {
/** /**
* Select a font both visually and logically * Select a font both visually and logically
* @param font The font to be selected *
* @param font The font to be selected
* @param radio The radio button associated with it's visual item * @param radio The radio button associated with it's visual item
*/ */
private void select(EmojiCompatFont font, RadioButton radio) { private void select(EmojiCompatFont font, RadioButton radio) {
selected = font; selected = font;
// Uncheck all the other buttons // Uncheck all the other buttons
for(RadioButton other : radioButtons) { for (RadioButton other : radioButtons) {
if(other != radio) { if (other != radio) {
other.setChecked(false); other.setChecked(false);
} }
} }
@ -183,31 +182,31 @@ public class EmojiPreference extends Preference {
/** /**
* Called when a "consistent" state is reached, i.e. it's not downloading the font * Called when a "consistent" state is reached, i.e. it's not downloading the font
* @param font The font to be displayed *
* @param font The font to be displayed
* @param container The ConstraintLayout containing the item * @param container The ConstraintLayout containing the item
*/ */
private void updateItem(EmojiCompatFont font, View container) { private void updateItem(EmojiCompatFont font, View container) {
// Assignments // Assignments
ImageButton download = container.findViewById(R.id.emojicompat_download); ImageButton download = container.findViewById(R.id.emojicompat_download);
TextView caption = container.findViewById(R.id.emojicompat_caption); TextView caption = container.findViewById(R.id.emojicompat_caption);
ProgressBar progress = container.findViewById(R.id.emojicompat_progress); ProgressBar progress = container.findViewById(R.id.emojicompat_progress);
ImageButton cancel = container.findViewById(R.id.emojicompat_download_cancel); ImageButton cancel = container.findViewById(R.id.emojicompat_download_cancel);
RadioButton radio = container.findViewById(R.id.emojicompat_radio); RadioButton radio = container.findViewById(R.id.emojicompat_radio);
// There's no download going on // There's no download going on
progress.setVisibility(View.GONE); progress.setVisibility(View.GONE);
cancel.setVisibility(View.GONE); cancel.setVisibility(View.GONE);
caption.setVisibility(View.VISIBLE); caption.setVisibility(View.VISIBLE);
if(font.isDownloaded(getContext())) { if (font.isDownloaded(getContext())) {
// Make it selectable // Make it selectable
download.setVisibility(View.GONE); download.setVisibility(View.GONE);
radio.setVisibility(View.VISIBLE); radio.setVisibility(View.VISIBLE);
container.setClickable(true); container.setClickable(true);
} } else {
else {
// Make it downloadable // Make it downloadable
download.setVisibility(View.VISIBLE); download.setVisibility(View.VISIBLE);
radio.setVisibility(View.GONE); radio.setVisibility(View.GONE);
@ -215,14 +214,13 @@ public class EmojiPreference extends Preference {
} }
// Select it if necessary // Select it if necessary
if(font == selected) { if (font == selected) {
radio.setChecked(true); radio.setChecked(true);
// Update available // Update available
if (!font.isDownloaded(getContext())) { if (!font.isDownloaded(getContext())) {
currentNeedsUpdate = true; currentNeedsUpdate = true;
} }
} } else {
else {
radio.setChecked(false); radio.setChecked(false);
} }
} }
@ -248,33 +246,33 @@ public class EmojiPreference extends Preference {
* That means, the selected font can be saved (if the user hit OK) * That means, the selected font can be saved (if the user hit OK)
*/ */
private void onDialogOk() { private void onDialogOk() {
saveSelectedFont(); saveSelectedFont();
if (selected != original || updated) { if (selected != original || updated) {
new AlertDialog.Builder(getContext()) new AlertDialog.Builder(getContext())
.setTitle(R.string.restart_required) .setTitle(R.string.restart_required)
.setMessage(R.string.restart_emoji) .setMessage(R.string.restart_emoji)
.setNegativeButton(R.string.later, null) .setNegativeButton(R.string.later, null)
.setPositiveButton(R.string.restart, ((dialog, which) -> { .setPositiveButton(R.string.restart, ((dialog, which) -> {
// Restart the app // Restart the app
// From https://stackoverflow.com/a/17166729/5070653 // From https://stackoverflow.com/a/17166729/5070653
Intent launchIntent = new Intent(getContext(), SplashActivity.class); Intent launchIntent = new Intent(getContext(), SplashActivity.class);
PendingIntent mPendingIntent = PendingIntent.getActivity( PendingIntent mPendingIntent = PendingIntent.getActivity(
getContext(), getContext(),
// This is the codepoint of the party face emoji :D // This is the codepoint of the party face emoji :D
0x1f973, 0x1f973,
launchIntent, launchIntent,
PendingIntent.FLAG_CANCEL_CURRENT); PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = AlarmManager mgr =
(AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
if (mgr != null) { if (mgr != null) {
mgr.set( mgr.set(
AlarmManager.RTC, AlarmManager.RTC,
System.currentTimeMillis() + 100, System.currentTimeMillis() + 100,
mPendingIntent); mPendingIntent);
} }
System.exit(0); System.exit(0);
})).show(); })).show();
} }
} }

@ -73,6 +73,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
private TextView sensitiveMediaWarning; private TextView sensitiveMediaWarning;
private View sensitiveMediaShow; private View sensitiveMediaShow;
protected TextView[] mediaLabels; protected TextView[] mediaLabels;
protected CharSequence[] mediaDescriptions;
private MaterialButton contentWarningButton; private MaterialButton contentWarningButton;
private ImageView avatarInset; private ImageView avatarInset;
@ -133,6 +134,7 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
itemView.findViewById(R.id.status_media_label_2), itemView.findViewById(R.id.status_media_label_2),
itemView.findViewById(R.id.status_media_label_3) itemView.findViewById(R.id.status_media_label_3)
}; };
mediaDescriptions = new CharSequence[mediaLabels.length];
contentWarningDescription = itemView.findViewById(R.id.status_content_warning_description); contentWarningDescription = itemView.findViewById(R.id.status_content_warning_description);
contentWarningButton = itemView.findViewById(R.id.status_content_warning_button); contentWarningButton = itemView.findViewById(R.id.status_content_warning_button);
avatarInset = itemView.findViewById(R.id.status_avatar_inset); avatarInset = itemView.findViewById(R.id.status_avatar_inset);
@ -181,11 +183,8 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
@Nullable PollViewData poll, @Nullable PollViewData poll,
@NonNull StatusDisplayOptions statusDisplayOptions, @NonNull StatusDisplayOptions statusDisplayOptions,
final StatusActionListener listener) { final StatusActionListener listener) {
if (TextUtils.isEmpty(spoilerText)) { boolean sensitive = !TextUtils.isEmpty(spoilerText);
contentWarningDescription.setVisibility(View.GONE); if (sensitive) {
contentWarningButton.setVisibility(View.GONE);
this.setTextVisible(true, content, mentions, emojis, poll, statusDisplayOptions, listener);
} else {
CharSequence emojiSpoiler = CustomEmojiHelper.emojifyString(spoilerText, emojis, contentWarningDescription); CharSequence emojiSpoiler = CustomEmojiHelper.emojifyString(spoilerText, emojis, contentWarningDescription);
contentWarningDescription.setText(emojiSpoiler); contentWarningDescription.setText(emojiSpoiler);
contentWarningDescription.setVisibility(View.VISIBLE); contentWarningDescription.setVisibility(View.VISIBLE);
@ -198,9 +197,13 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
} }
setContentWarningButtonText(!expanded); setContentWarningButtonText(!expanded);
this.setTextVisible(!expanded, content, mentions, emojis, poll, statusDisplayOptions, listener); this.setTextVisible(sensitive, !expanded, content, mentions, emojis, poll, statusDisplayOptions, listener);
}); });
this.setTextVisible(expanded, content, mentions, emojis, poll, statusDisplayOptions, listener); this.setTextVisible(sensitive, expanded, content, mentions, emojis, poll, statusDisplayOptions, listener);
} else {
contentWarningDescription.setVisibility(View.GONE);
contentWarningButton.setVisibility(View.GONE);
this.setTextVisible(sensitive, true, content, mentions, emojis, poll, statusDisplayOptions, listener);
} }
} }
@ -212,7 +215,8 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
} }
} }
private void setTextVisible(boolean expanded, private void setTextVisible(boolean sensitive,
boolean expanded,
Spanned content, Spanned content,
Status.Mention[] mentions, Status.Mention[] mentions,
List<Emoji> emojis, List<Emoji> emojis,
@ -222,6 +226,9 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
if (expanded) { if (expanded) {
Spanned emojifiedText = CustomEmojiHelper.emojifyText(content, emojis, this.content); Spanned emojifiedText = CustomEmojiHelper.emojifyText(content, emojis, this.content);
LinkHelper.setClickableText(this.content, emojifiedText, mentions, listener); LinkHelper.setClickableText(this.content, emojifiedText, mentions, listener);
for (int i = 0; i < mediaLabels.length; ++i) {
updateMediaLabel(i, sensitive, expanded);
}
if (poll != null) { if (poll != null) {
setupPoll(poll, emojis, statusDisplayOptions, listener); setupPoll(poll, emojis, statusDisplayOptions, listener);
} else { } else {
@ -519,6 +526,14 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
} }
} }
private void updateMediaLabel(int index, boolean sensitive, boolean showingContent) {
Context context = itemView.getContext();
CharSequence label = (sensitive && !showingContent) ?
context.getString(R.string.status_sensitive_media_title) :
mediaDescriptions[index];
mediaLabels[index].setText(label);
}
protected void setMediaLabel(List<Attachment> attachments, boolean sensitive, protected void setMediaLabel(List<Attachment> attachments, boolean sensitive,
final StatusActionListener listener, boolean showingContent) { final StatusActionListener listener, boolean showingContent) {
Context context = itemView.getContext(); Context context = itemView.getContext();
@ -527,12 +542,8 @@ public abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder {
if (i < attachments.size()) { if (i < attachments.size()) {
Attachment attachment = attachments.get(i); Attachment attachment = attachments.get(i);
mediaLabel.setVisibility(View.VISIBLE); mediaLabel.setVisibility(View.VISIBLE);
mediaDescriptions[i] = getAttachmentDescription(context, attachment);
if (sensitive && !showingContent) { updateMediaLabel(i, sensitive, showingContent);
mediaLabel.setText(R.string.status_sensitive_media_title);
} else {
mediaLabel.setText(getAttachmentDescription(context, attachment));
}
// Set the icon next to the label. // Set the icon next to the label.
int drawableId = getLabelIcon(attachments.get(0).getType()); int drawableId = getLabelIcon(attachments.get(0).getType());

@ -61,8 +61,8 @@ class ComposeViewModel
private var startingContentWarning: String = "" private var startingContentWarning: String = ""
private var inReplyToId: String? = null private var inReplyToId: String? = null
private var startingVisibility: Status.Visibility = Status.Visibility.UNKNOWN private var startingVisibility: Status.Visibility = Status.Visibility.UNKNOWN
private val instance: MutableLiveData<InstanceEntity?> = MutableLiveData() private val instance: MutableLiveData<InstanceEntity?> = MutableLiveData(null)
private val nodeinfo: MutableLiveData<NodeInfo?> = MutableLiveData() private val nodeinfo: MutableLiveData<NodeInfo?> = MutableLiveData(null)
public var markdownMode: Boolean = false public var markdownMode: Boolean = false
public var hasNoAttachmentLimits = false public var hasNoAttachmentLimits = false

@ -50,7 +50,10 @@ fun <T> T.makeCaptionDialog(existingDescription: String?,
dialogLayout.setPadding(padding, padding, padding, padding) dialogLayout.setPadding(padding, padding, padding, padding)
dialogLayout.orientation = LinearLayout.VERTICAL dialogLayout.orientation = LinearLayout.VERTICAL
val imageView = PhotoView(this) val imageView = PhotoView(this).apply {
// If it seems a lot, try opening an image of A4 format or similar
maximumScale = 6.0f
}
val displayMetrics = DisplayMetrics() val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics) windowManager.defaultDisplay.getMetrics(displayMetrics)

@ -166,7 +166,7 @@ fun Account.toEntity() =
ConversationAccountEntity( ConversationAccountEntity(
id, id,
username, username,
displayName, displayName.orEmpty(),
avatar, avatar,
emojis ?: emptyList() emojis ?: emptyList()
) )

@ -74,6 +74,7 @@ class ConversationsViewModel @Inject constructor(
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.doOnError { t -> Log.w("ConversationViewModel", "Failed to bookmark conversation", t) } .doOnError { t -> Log.w("ConversationViewModel", "Failed to bookmark conversation", t) }
.onErrorReturnItem(0)
.subscribe() .subscribe()
.autoDispose() .autoDispose()
} }
@ -127,7 +128,7 @@ class ConversationsViewModel @Inject constructor(
} }
fun remove(position: Int) { fun remove(position: Int) {
conversations.value?.getOrNull(position)?.let { conversation -> conversations.value?.getOrNull(position)?.let {
refresh() refresh()
} }
} }

@ -62,7 +62,7 @@ class SearchDataSource<T>(
resolve = true, resolve = true,
limit = params.requestedLoadSize, limit = params.requestedLoadSize,
offset = 0, offset = 0,
following =false) following = false)
.subscribe( .subscribe(
{ data -> { data ->
val res = parser(data) val res = parser(data)
@ -84,24 +84,30 @@ class SearchDataSource<T>(
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<T>) { override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<T>) {
networkState.postValue(NetworkState.LOADING) networkState.postValue(NetworkState.LOADING)
retry = null retry = null
if(source.exhausted) { if (source.exhausted) {
return callback.onResult(emptyList()) return callback.onResult(emptyList())
} }
mastodonApi.searchObservable(searchType.apiParameter, searchRequest, true, params.loadSize, params.startPosition, false) mastodonApi.searchObservable(
query = searchRequest,
type = searchType.apiParameter,
resolve = true,
limit = params.loadSize,
offset = params.startPosition,
following = false)
.subscribe( .subscribe(
{ data -> { data ->
// Working around Mastodon bug where exact match is returned no matter // Working around Mastodon bug where exact match is returned no matter
// which offset is requested (so if we seach for a full username, it's // which offset is requested (so if we search for a full username, it's
// infinite) // infinite)
// see https://github.com/tootsuite/mastodon/issues/11365 // see https://github.com/tootsuite/mastodon/issues/11365
val res = if (data.accounts.size == 1 // see https://github.com/tootsuite/mastodon/issues/13083
&& data.accounts[0].username val res = if ((data.accounts.size == 1 && data.accounts[0].username.equals(searchRequest, ignoreCase = true))
.equals(searchRequest, ignoreCase = true)) { || (data.statuses.size == 1 && data.statuses[0].url.equals(searchRequest))) {
listOf() listOf()
} else { } else {
parser(data) parser(data)
} }
if(res.isEmpty()) { if (res.isEmpty()) {
source.exhausted = true source.exhausted = true
} }
callback.onResult(res) callback.onResult(res)

@ -31,7 +31,7 @@ data class Account(
val id: String, val id: String,
@SerializedName("username") val localUsername: String, @SerializedName("username") val localUsername: String,
@SerializedName("acct") val username: String, @SerializedName("acct") val username: String,
@SerializedName("display_name") val displayName: String, @SerializedName("display_name") val displayName: String?, // should never be null per Api definition, but some servers break the contract
val note: @WriteWith<SpannedParceler>() Spanned, val note: @WriteWith<SpannedParceler>() Spanned,
val url: String, val url: String,
val avatar: String, val avatar: String,
@ -49,7 +49,7 @@ data class Account(
) : Parcelable { ) : Parcelable {
val name: String val name: String
get() = if (displayName.isEmpty()) { get() = if (displayName.isNullOrEmpty()) {
localUsername localUsername
} else displayName } else displayName

@ -332,7 +332,7 @@ public final class ViewThreadFragment extends SFragment implements
.setIsExpanded(expanded) .setIsExpanded(expanded)
.createStatusViewData(); .createStatusViewData();
statuses.setPairedItem(position, newViewData); statuses.setPairedItem(position, newViewData);
adapter.setItem(position, newViewData, false); adapter.setItem(position, newViewData, true);
updateRevealIcon(); updateRevealIcon();
} }

@ -458,16 +458,19 @@ interface MastodonApi {
@Query("limit") limit: Int @Query("limit") limit: Int
): Single<List<Account>> ): Single<List<Account>>
@DELETE("api/v1/lists/{listId}/accounts") @FormUrlEncoded
// @DELETE doesn't support fields
@HTTP(method = "DELETE", path = "api/v1/lists/{listId}/accounts", hasBody = true)
fun deleteAccountFromList( fun deleteAccountFromList(
@Path("listId") listId: String, @Path("listId") listId: String,
@Query("account_ids[]") accountIds: List<String> @Field("account_ids[]") accountIds: List<String>
): Completable ): Completable
@FormUrlEncoded
@POST("api/v1/lists/{listId}/accounts") @POST("api/v1/lists/{listId}/accounts")
fun addCountToList( fun addCountToList(
@Path("listId") listId: String, @Path("listId") listId: String,
@Query("account_ids[]") accountIds: List<String> @Field("account_ids[]") accountIds: List<String>
): Completable ): Completable
@GET("/api/v1/conversations") @GET("/api/v1/conversations")

@ -299,7 +299,7 @@ fun Account.toEntity(accountId: Long, gson: Gson): TimelineAccountEntity {
timelineUserId = accountId, timelineUserId = accountId,
localUsername = localUsername, localUsername = localUsername,
username = username, username = username,
displayName = displayName, displayName = displayName.orEmpty(),
url = url, url = url,
avatar = avatar, avatar = avatar,
emojis = gson.toJson(emojis), emojis = gson.toJson(emojis),

@ -27,6 +27,7 @@ import de.c1710.filemojicompat.FileEmojiCompatConfig;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSink; import okio.BufferedSink;
import okio.Okio; import okio.Okio;
import okio.Source; import okio.Source;
@ -81,7 +82,7 @@ public class EmojiCompatFont {
R.drawable.ic_notoemoji, R.drawable.ic_notoemoji,
"https://tusky.app/hosted/emoji/NotoEmojiCompat.ttf", "https://tusky.app/hosted/emoji/NotoEmojiCompat.ttf",
"11.0.0" "11.0.0"
); );
/** /**
* This array stores all available EmojiCompat fonts. * This array stores all available EmojiCompat fonts.
@ -109,14 +110,14 @@ public class EmojiCompatFont {
/** /**
* Returns the Emoji font associated with this ID * Returns the Emoji font associated with this ID
*
* @param id the ID of this font * @param id the ID of this font
* @return the corresponding font. Will default to SYSTEM_DEFAULT if not in range. * @return the corresponding font. Will default to SYSTEM_DEFAULT if not in range.
*/ */
public static EmojiCompatFont byId(int id) { public static EmojiCompatFont byId(int id) {
if(id >= 0 && id < FONTS.length) { if (id >= 0 && id < FONTS.length) {
return FONTS[id]; return FONTS[id];
} } else {
else {
return SYSTEM_DEFAULT; return SYSTEM_DEFAULT;
} }
} }
@ -157,15 +158,15 @@ public class EmojiCompatFont {
/** /**
* This method will return the actual font file (regardless of its existence) for * This method will return the actual font file (regardless of its existence) for
* the current version (not necessarily the latest!). * the current version (not necessarily the latest!).
*
* @return The font (TTF) file or null if called on SYSTEM_FONT * @return The font (TTF) file or null if called on SYSTEM_FONT
*/ */
@Nullable @Nullable
private File getFont(Context context) { private File getFont(Context context) {
if(this != SYSTEM_DEFAULT) { if (this != SYSTEM_DEFAULT) {
File directory = new File(context.getExternalFilesDir(null), DIRECTORY); File directory = new File(context.getExternalFilesDir(null), DIRECTORY);
return new File(directory, this.getName() + this.getVersion() + ".ttf"); return new File(directory, this.getName() + this.getVersion() + ".ttf");
} } else {
else {
return null; return null;
} }
} }
@ -185,6 +186,7 @@ public class EmojiCompatFont {
/** /**
* Checks whether there is already a font version that satisfies the current version, i.e. it * Checks whether there is already a font version that satisfies the current version, i.e. it
* has a higher or equal version code. * has a higher or equal version code.
*
* @param context The Context * @param context The Context
* @return Whether there is a font file with a higher or equal version code to the current * @return Whether there is a font file with a higher or equal version code to the current
*/ */
@ -199,10 +201,11 @@ public class EmojiCompatFont {
/** /**
* Downloads the TTF file for this font * Downloads the TTF file for this font
*
* @param listeners The listeners which will be notified when the download has been finished * @param listeners The listeners which will be notified when the download has been finished
*/ */
public void downloadFont(Context context, Downloader.EmojiDownloadListener... listeners) { public void downloadFont(Context context, Downloader.EmojiDownloadListener... listeners) {
if(this != SYSTEM_DEFAULT) { if (this != SYSTEM_DEFAULT) {
// Additionally run a cleanup process after the download has been successful. // Additionally run a cleanup process after the download has been successful.
Downloader.EmojiDownloadListener cleanup = font -> deleteOldVersions(context); Downloader.EmojiDownloadListener cleanup = font -> deleteOldVersions(context);
@ -216,9 +219,8 @@ public class EmojiCompatFont {
this, this,
allListeners.toArray(allListenersA)) allListeners.toArray(allListenersA))
.execute(getFont(context)); .execute(getFont(context));
} } else {
else { for (Downloader.EmojiDownloadListener listener : listeners) {
for(Downloader.EmojiDownloadListener listener: listeners) {
// The system emoji font is always downloaded... // The system emoji font is always downloaded...
listener.onDownloaded(this); listener.onDownloaded(this);
} }
@ -227,6 +229,7 @@ public class EmojiCompatFont {
/** /**
* Deletes any older version of a font * Deletes any older version of a font
*
* @param context The current Context * @param context The current Context
*/ */
private void deleteOldVersions(Context context) { private void deleteOldVersions(Context context) {
@ -236,11 +239,11 @@ public class EmojiCompatFont {
Log.d(TAG, String.format("deleteOldVersions: Found %d other font files", existingFontFiles.size())); Log.d(TAG, String.format("deleteOldVersions: Found %d other font files", existingFontFiles.size()));
for (Pair<File, int[]> fileExists : existingFontFiles) { for (Pair<File, int[]> fileExists : existingFontFiles) {
if (compareVersions(fileExists.second, getVersionCode()) < 0) { if (compareVersions(fileExists.second, getVersionCode()) < 0) {
File file = fileExists.first; File file = fileExists.first;
// Uses side effects! // Uses side effects!
Log.d(TAG, String.format("Deleted %s successfully: %s", file.getAbsolutePath(), Log.d(TAG, String.format("Deleted %s successfully: %s", file.getAbsolutePath(),
file.delete())); file.delete()));
} }
} }
} }
@ -250,6 +253,7 @@ public class EmojiCompatFont {
/** /**
* Loads all font files that are inside the files directory into an ArrayList with the information * Loads all font files that are inside the files directory into an ArrayList with the information
* on whether they are older than the currently available version or not. * on whether they are older than the currently available version or not.
*
* @param context The Context * @param context The Context
*/ */
private void loadExistingFontFiles(Context context) { private void loadExistingFontFiles(Context context) {
@ -274,7 +278,7 @@ public class EmojiCompatFont {
this.existingFontFiles = new ArrayList<>(existingFontFiles.length); this.existingFontFiles = new ArrayList<>(existingFontFiles.length);
for(File file : existingFontFiles) { for (File file : existingFontFiles) {
Matcher matcher = fontRegex.matcher(file.getName()); Matcher matcher = fontRegex.matcher(file.getName());
if (matcher.matches()) { if (matcher.matches()) {
String version = matcher.group(1); String version = matcher.group(1);
@ -294,6 +298,7 @@ public class EmojiCompatFont {
/** /**
* Returns the current or latest version of this font file (if there is any) * Returns the current or latest version of this font file (if there is any)
*
* @param context The Context * @param context The Context
* @return The file for this font with the current or (if not existent) highest version code or null if there is no file for this font. * @return The file for this font with the current or (if not existent) highest version code or null if there is no file for this font.
*/ */
@ -380,7 +385,7 @@ public class EmojiCompatFont {
* Stops downloading the font. If no one started a font download, nothing happens. * Stops downloading the font. If no one started a font download, nothing happens.
*/ */
public void cancelDownload() { public void cancelDownload() {
if(fontDownloader != null) { if (fontDownloader != null) {
fontDownloader.cancel(false); fontDownloader.cancel(false);
fontDownloader = null; fontDownloader = null;
} }
@ -407,7 +412,7 @@ public class EmojiCompatFont {
} }
@Override @Override
protected File doInBackground(File... files){ protected File doInBackground(File... files) {
// Only download to one file... // Only download to one file...
File downloadFile = files[0]; File downloadFile = files[0];
try { try {
@ -428,7 +433,7 @@ public class EmojiCompatFont {
// Download! // Download!
if (response.body() != null if (response.body() != null
&& response.isSuccessful() && response.isSuccessful()
&& (size = response.body().contentLength()) > 0) { && (size = networkResponseLength(response)) > 0) {
float progress = 0; float progress = 0;
source = response.body().source(); source = response.body().source();
try { try {
@ -448,14 +453,13 @@ public class EmojiCompatFont {
Log.e(TAG, "Status code: " + response.code()); Log.e(TAG, "Status code: " + response.code());
failed = true; failed = true;
} }
} } finally {
finally { if (source != null) {
if(source != null) {
source.close(); source.close();
} }
sink.close(); sink.close();
// This 'if' uses side effects to delete the File. // This 'if' uses side effects to delete the File.
if(isCancelled() && !downloadFile.delete()) { if (isCancelled() && !downloadFile.delete()) {
Log.e(TAG, "Could not delete file " + downloadFile); Log.e(TAG, "Could not delete file " + downloadFile);
} }
} }
@ -468,28 +472,27 @@ public class EmojiCompatFont {
@Override @Override
public void onProgressUpdate(Float... progress) { public void onProgressUpdate(Float... progress) {
for(EmojiDownloadListener listener: listeners) { for (EmojiDownloadListener listener : listeners) {
listener.onProgress(progress[0]); listener.onProgress(progress[0]);
} }
} }
@Override @Override
public void onPostExecute(File downloadedFile) { public void onPostExecute(File downloadedFile) {
if(!failed && downloadedFile.exists()) { if (!failed && downloadedFile.exists()) {
for (EmojiDownloadListener listener : listeners) { for (EmojiDownloadListener listener : listeners) {
listener.onDownloaded(font); listener.onDownloaded(font);
} }
} } else {
else {
fail(downloadedFile); fail(downloadedFile);
} }
} }
private void fail(File failedFile) { private void fail(File failedFile) {
if(failedFile.exists() && !failedFile.delete()) { if (failedFile.exists() && !failedFile.delete()) {
Log.e(TAG, "Could not delete file " + failedFile); Log.e(TAG, "Could not delete file " + failedFile);
} }
for(EmojiDownloadListener listener : listeners) { for (EmojiDownloadListener listener : listeners) {
listener.onFailed(); listener.onFailed();
} }
} }
@ -500,11 +503,13 @@ public class EmojiCompatFont {
public interface EmojiDownloadListener { public interface EmojiDownloadListener {
/** /**
* Called after successfully finishing a download. * Called after successfully finishing a download.
*
* @param font The font related to this download. This will help identifying the download * @param font The font related to this download. This will help identifying the download
*/ */
void onDownloaded(EmojiCompatFont font); void onDownloaded(EmojiCompatFont font);
// TODO: Add functionality // TODO: Add functionality
/** /**
* Called when something went wrong with the download. * Called when something went wrong with the download.
* This one won't be called when the download has been cancelled though. * This one won't be called when the download has been cancelled though.
@ -515,12 +520,39 @@ public class EmojiCompatFont {
/** /**
* Called whenever the progress changed * Called whenever the progress changed
*
* @param Progress A value between 0 and 1 representing the current progress * @param Progress A value between 0 and 1 representing the current progress
*/ */
default void onProgress(float Progress) { default void onProgress(float Progress) {
// ARE WE THERE YET? // ARE WE THERE YET?
} }
} }
/**
* This method is needed because when transparent compression is used OkHttp reports
* {@link ResponseBody#contentLength()} as -1. We try to get the header which server sent
* us manually here.
*
* @see <a href="https://github.com/square/okhttp/issues/259">OkHttp issue 259</a>
*/
private long networkResponseLength(Response response) {
Response networkResponse = response.networkResponse();
if (networkResponse == null) {
// In case it's a fully cached response
ResponseBody body = response.body();
return body == null ? -1 : body.contentLength();
}
String header = networkResponse.header("Content-Length");
if (header == null) {
return -1;
}
try {
return Integer.parseInt(header);
} catch (NumberFormatException e) {
return -1;
}
}
} }
@Override @Override

@ -2,5 +2,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android" <shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:shape="rectangle">
<size android:height="1dp" /> <size android:height="1dp" />
<solid android:color="?attr/colorBackgroundAccent" /> <solid android:color="?attr/dividerColor" />
</shape> </shape>

@ -3,8 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:background="?attr/windowBackgroundColor" android:layout_height="match_parent"
android:layout_height="match_parent"> android:background="?attr/windowBackgroundColor">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="640dp" android:layout_width="640dp"

@ -39,8 +39,8 @@
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
license:license="@string/license_apache_2" license:license="@string/license_apache_2"
license:link="https://developer.android.com/topic/libraries/support-library/" license:link="https://kotlinlang.org/"
license:name="Android Support Library" /> license:name="Kotlin" />
<com.keylesspalace.tusky.view.LicenseCard <com.keylesspalace.tusky.view.LicenseCard
android:layout_width="match_parent" android:layout_width="match_parent"
@ -49,8 +49,18 @@
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
license:license="@string/license_apache_2" license:license="@string/license_apache_2"
license:link="https://developer.android.com/topic/libraries/architecture/" license:link="https://developer.android.com/jetpack/androidx"
license:name="Android Architecture Components" /> license:name="AndroidX" />
<com.keylesspalace.tusky.view.LicenseCard
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="12dp"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
license:license="@string/license_apache_2"
license:link="https://github.com/material-components/material-components-android"
license:name="Material Components for Android" />
<com.keylesspalace.tusky.view.LicenseCard <com.keylesspalace.tusky.view.LicenseCard
android:layout_width="match_parent" android:layout_width="match_parent"

@ -36,7 +36,7 @@
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager" android:id="@+id/pager"
android:background="?android:windowBackground" android:background="?attr/windowBackgroundColor"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_below="@id/tab_layout" android:layout_below="@id/tab_layout"

@ -29,7 +29,6 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/searchView" /> app:layout_constraintTop_toBottomOf="@id/searchView" />
<com.keylesspalace.tusky.view.BackgroundMessageView <com.keylesspalace.tusky.view.BackgroundMessageView
android:id="@+id/messageView" android:id="@+id/messageView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -43,16 +42,15 @@
tools:src="@drawable/elephant_error" tools:src="@drawable/elephant_error"
tools:visibility="visible" /> tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/accountsSearchRecycler" android:id="@+id/accountsSearchRecycler"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:background="?android:attr/windowBackground"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/searchView" /> app:layout_constraintTop_toBottomOf="@id/searchView" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

@ -3,7 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:background="?android:attr/colorBackground">
<com.google.android.material.appbar.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarOptions" android:id="@+id/appBarOptions"

@ -257,10 +257,10 @@
<string name="action_lists">Listen</string> <string name="action_lists">Listen</string>
<string name="title_lists">Listen</string> <string name="title_lists">Listen</string>
<string name="title_list_timeline">Liste</string> <string name="title_list_timeline">Liste</string>
<string name="action_create_list">Eine Liste erstellen</string> <string name="action_create_list">Liste erstellen</string>
<string name="action_rename_list">Eine Liste umbenennen</string> <string name="action_rename_list">Liste umbenennen</string>
<string name="action_delete_list">Eine Liste löschen</string> <string name="action_delete_list">Liste löschen</string>
<string name="action_edit_list">Eine Liste bearbeiten</string> <string name="action_edit_list">Liste bearbeiten</string>
<string name="action_add_to_list">Ein Konto zu einer Liste hinzufügen</string> <string name="action_add_to_list">Ein Konto zu einer Liste hinzufügen</string>
<string name="compose_active_account_description">verfassen mit %1$s</string> <string name="compose_active_account_description">verfassen mit %1$s</string>
<string name="error_failed_set_caption">Fehler beim Speichern der Beschreibung</string> <string name="error_failed_set_caption">Fehler beim Speichern der Beschreibung</string>
@ -450,14 +450,13 @@
<string name="action_access_scheduled_toot">Geplante Beiträge</string> <string name="action_access_scheduled_toot">Geplante Beiträge</string>
<string name="action_schedule_toot">Plane Beitrag</string> <string name="action_schedule_toot">Plane Beitrag</string>
<string name="action_reset_schedule">Zurücksetzen</string> <string name="action_reset_schedule">Zurücksetzen</string>
<string name="abbreviated_in_years">Dies sind Zeitstempel für Status. Beispiele: \"16s\" oder \"2t\".</string>
<string name="error_audio_upload_size">Audiodateien müssen kleiner als 40MB sein.</string> <string name="error_audio_upload_size">Audiodateien müssen kleiner als 40MB sein.</string>
<string name="title_bookmarks">Lesezeichen</string> <string name="title_bookmarks">Lesezeichen</string>
<string name="action_bookmark">Lesezeichen</string> <string name="action_bookmark">Lesezeichen</string>
<string name="action_view_bookmarks">Lesezeichen</string> <string name="action_view_bookmarks">Lesezeichen</string>
<string name="gradient_for_media">Bunten Farbverlauf für versteckte Medien anzeigen</string> <string name="gradient_for_media">Bunten Farbverlauf für versteckte Medien anzeigen</string>
<string name="about_powered_by_tusky">Angetrieben durch Tusky</string> <string name="about_powered_by_tusky">Powered by Tusky</string>
<plurals name="reblogs"> <plurals name="reblogs">
<item quantity="one"><b>%s</b> Boost</item> <item quantity="one"><b>%s</b> Boost</item>
<item quantity="other"><b>%s</b> Boosts</item> <item quantity="other"><b>%s</b> Boosts</item>

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

@ -1,2 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources></resources>

@ -467,10 +467,16 @@
<string name="post_lookup_error_format">Error al buscar el post %s</string> <string name="post_lookup_error_format">Error al buscar el post %s</string>
<string name="about_powered_by_tusky">Potenciado por Tusky</string> <string name="about_powered_by_tusky">Potenciado por Tusky</string>
<string name="title_bookmarks">Favoritos</string> <string name="title_bookmarks">Marcadores</string>
<string name="action_bookmark">Favorito</string> <string name="action_bookmark">Favorito</string>
<string name="action_view_bookmarks">Favoritos</string> <string name="action_view_bookmarks">Marcadores</string>
<string name="description_status_bookmarked">Marcado como favorito</string> <string name="description_status_bookmarked">Marcado como favorito</string>
<string name="select_list_title">Seleccionar lista</string> <string name="select_list_title">Seleccionar lista</string>
<string name="list">Lista</string> <string name="list">Lista</string>
</resources> <string name="error_audio_upload_size">Los ficheros de audio deben ser menores de 40MB.</string>
<string name="gradient_for_media">Mostrar degradados coloridos para el contenido multimedia oculto.</string>
<string name="no_saved_status">No tienes ningún borrador.</string>
<string name="no_scheduled_status">No tienes ningún estado programado.</string>
</resources>

@ -23,10 +23,10 @@
<string name="title_public_local">محلی</string> <string name="title_public_local">محلی</string>
<string name="title_public_federated">همگانی</string> <string name="title_public_federated">همگانی</string>
<string name="title_view_thread">بوق</string> <string name="title_view_thread">بوق</string>
<string name="title_statuses">فرستهها</string> <string name="title_statuses">بوق</string>
<string name="title_statuses_with_replies">با پاسخ</string> <string name="title_statuses_with_replies">با پاسخ</string>
<string name="title_follows">پی میگیرد</string> <string name="title_follows">پی میگیرد</string>
<string name="title_followers">پیرو</string> <string name="title_followers">پیگیر</string>
<string name="title_favourites">پسندها</string> <string name="title_favourites">پسندها</string>
<string name="title_mutes">کاربران خموش</string> <string name="title_mutes">کاربران خموش</string>
<string name="title_blocks">کاربران مسدود</string> <string name="title_blocks">کاربران مسدود</string>
@ -34,7 +34,7 @@
<string name="title_edit_profile">ویرایش نمایهتان</string> <string name="title_edit_profile">ویرایش نمایهتان</string>
<string name="title_saved_toot">پیشنویسها</string> <string name="title_saved_toot">پیشنویسها</string>
<string name="title_licenses">پروانهها</string> <string name="title_licenses">پروانهها</string>
<string name="status_boosted_format">%s تقویت شد</string> <string name="status_boosted_format">%s تقویت کرد</string>
<string name="status_sensitive_media_title">محتوای حسّاس</string> <string name="status_sensitive_media_title">محتوای حسّاس</string>
<string name="status_media_hidden_title">رسانهٔ پنهان</string> <string name="status_media_hidden_title">رسانهٔ پنهان</string>
<string name="status_sensitive_media_directions">کلیک برای نمایش</string> <string name="status_sensitive_media_directions">کلیک برای نمایش</string>
@ -54,7 +54,7 @@
<string name="action_favourite">پسند</string> <string name="action_favourite">پسند</string>
<string name="action_more">بیشتر</string> <string name="action_more">بیشتر</string>
<string name="action_compose">ایجاد</string> <string name="action_compose">ایجاد</string>
<string name="action_login">ورود با ماستدون</string> <string name="action_login">ورود با ماستودون</string>
<string name="action_logout">خروج</string> <string name="action_logout">خروج</string>
<string name="action_logout_confirm">مطمئنید میخواهید از حساب %1s خارج شوید؟</string> <string name="action_logout_confirm">مطمئنید میخواهید از حساب %1s خارج شوید؟</string>
<string name="action_follow">پیگیری</string> <string name="action_follow">پیگیری</string>
@ -134,7 +134,7 @@
<string name="dialog_delete_toot_warning">حذف این بوق؟</string> <string name="dialog_delete_toot_warning">حذف این بوق؟</string>
<string name="visibility_public">عمومی: فرستادن به خط زمانیهای عمومی</string> <string name="visibility_public">عمومی: فرستادن به خط زمانیهای عمومی</string>
<string name="visibility_unlisted">فهرستنشده: نشان ندادن در خط زمانیهای عمومی</string> <string name="visibility_unlisted">فهرستنشده: نشان ندادن در خط زمانیهای عمومی</string>
<string name="visibility_private">فقط پیروان: فرستادن فقط به پیروان</string> <string name="visibility_private">فقط پیگیران: فرستادن فقط به پیگیران</string>
<string name="visibility_direct">مستقیم: فرستادن فقط برای کاربران مورد اشاره</string> <string name="visibility_direct">مستقیم: فرستادن فقط برای کاربران مورد اشاره</string>
<string name="pref_title_edit_notification_settings">آگاهیها</string> <string name="pref_title_edit_notification_settings">آگاهیها</string>
<string name="pref_title_notifications_enabled">آگاهیها</string> <string name="pref_title_notifications_enabled">آگاهیها</string>
@ -173,7 +173,7 @@
<string name="pref_failed_to_sync">شکست در همگامسازی تنظیمات</string> <string name="pref_failed_to_sync">شکست در همگامسازی تنظیمات</string>
<string name="post_privacy_public">عمومی</string> <string name="post_privacy_public">عمومی</string>
<string name="post_privacy_unlisted">فهرستنشده</string> <string name="post_privacy_unlisted">فهرستنشده</string>
<string name="post_privacy_followers_only">فقط پیروان</string> <string name="post_privacy_followers_only">فقط پیگیران</string>
<string name="pref_status_text_size">اندازهٔ متن وضعیت</string> <string name="pref_status_text_size">اندازهٔ متن وضعیت</string>
<string name="status_text_size_smallest">بسیار کوچک</string> <string name="status_text_size_smallest">بسیار کوچک</string>
<string name="status_text_size_small">کوچک</string> <string name="status_text_size_small">کوچک</string>
@ -182,8 +182,8 @@
<string name="status_text_size_largest">بسیار بزرگ</string> <string name="status_text_size_largest">بسیار بزرگ</string>
<string name="notification_mention_name">اشارههای جدید</string> <string name="notification_mention_name">اشارههای جدید</string>
<string name="notification_mention_descriptions">آگاهیها در مورد اشارههای جدید</string> <string name="notification_mention_descriptions">آگاهیها در مورد اشارههای جدید</string>
<string name="notification_follow_name">پیروان جدید</string> <string name="notification_follow_name">پیگیران جدید</string>
<string name="notification_follow_description">آگاهیها درمورد پیروان جدید</string> <string name="notification_follow_description">آگاهیها درمورد پیگیران جدید</string>
<string name="notification_boost_name">تقویتها</string> <string name="notification_boost_name">تقویتها</string>
<string name="notification_boost_description">آگاهیها هنگام تقویت بوقهایتان</string> <string name="notification_boost_description">آگاهیها هنگام تقویت بوقهایتان</string>
<string name="notification_favourite_name">پسندها</string> <string name="notification_favourite_name">پسندها</string>
@ -225,7 +225,7 @@
<string name="replying_to">در حال پاسخ به @%s</string> <string name="replying_to">در حال پاسخ به @%s</string>
<string name="load_more_placeholder_text">بارگیری بیشتر</string> <string name="load_more_placeholder_text">بارگیری بیشتر</string>
<string name="add_account_name">افزودن حساب</string> <string name="add_account_name">افزودن حساب</string>
<string name="add_account_description">افزودن حساب ماستدون جدید</string> <string name="add_account_description">افزودن حساب جدید ماستودون</string>
<string name="action_lists">فهرستها</string> <string name="action_lists">فهرستها</string>
<string name="title_lists">فهرستها</string> <string name="title_lists">فهرستها</string>
<string name="title_list_timeline">خط زمانی فهرست</string> <string name="title_list_timeline">خط زمانی فهرست</string>
@ -235,7 +235,7 @@
<string name="action_set_caption">تنظیم عنوان</string> <string name="action_set_caption">تنظیم عنوان</string>
<string name="action_remove">برداشتن</string> <string name="action_remove">برداشتن</string>
<string name="lock_account_label">قفل حساب</string> <string name="lock_account_label">قفل حساب</string>
<string name="lock_account_label_description">میگذارد پیروانتان را به صورت دستی تأیید کنید</string> <string name="lock_account_label_description">نیاز دارد پیگیرانتان را به صورت دستی تأیید کنید</string>
<string name="compose_save_draft">ذخیرهٔ پیشنویس؟</string> <string name="compose_save_draft">ذخیرهٔ پیشنویس؟</string>
<string name="send_toot_notification_title">در حال فرستادن بوق…</string> <string name="send_toot_notification_title">در حال فرستادن بوق…</string>
<string name="send_toot_notification_error_title">خطای فرستادن بوق</string> <string name="send_toot_notification_error_title">خطای فرستادن بوق</string>
@ -257,7 +257,7 @@
<string name="restart">شروع دوباره</string> <string name="restart">شروع دوباره</string>
<string name="caption_systememoji">مجموعهٔ اموجی پیشگزیدهٔ افزارهتان</string> <string name="caption_systememoji">مجموعهٔ اموجی پیشگزیدهٔ افزارهتان</string>
<string name="caption_blobmoji">اموجیهای اندروید ۴.۴ تا ۷.۱</string> <string name="caption_blobmoji">اموجیهای اندروید ۴.۴ تا ۷.۱</string>
<string name="caption_twemoji">مجموعهٔ اموجی استاندارد ماستدون</string> <string name="caption_twemoji">مجموعهٔ اموجی استاندارد ماستودون</string>
<string name="download_failed">شکست در بارگیری</string> <string name="download_failed">شکست در بارگیری</string>
<string name="profile_badge_bot_text">بات</string> <string name="profile_badge_bot_text">بات</string>
<string name="account_moved_description">%1$s منتقل شد به:</string> <string name="account_moved_description">%1$s منتقل شد به:</string>
@ -379,7 +379,7 @@
<string name="description_status_favourited">پسندیده</string> <string name="description_status_favourited">پسندیده</string>
<string name="description_visiblity_public">عمومی</string> <string name="description_visiblity_public">عمومی</string>
<string name="description_visiblity_unlisted">فهرستنشده</string> <string name="description_visiblity_unlisted">فهرستنشده</string>
<string name="description_visiblity_private">پیروان</string> <string name="description_visiblity_private">پیگیران</string>
<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>
@ -459,14 +459,26 @@
<string name="action_access_scheduled_toot">بوقهای زمانبندیشده</string> <string name="action_access_scheduled_toot">بوقهای زمانبندیشده</string>
<string name="action_schedule_toot">زمانبندی بوق</string> <string name="action_schedule_toot">زمانبندی بوق</string>
<string name="action_reset_schedule">بازنشانی</string> <string name="action_reset_schedule">بازنشانی</string>
<string name="mute_domain_warning">مطمئنید میخواهید تمام %s را مسدود کنید؟ محتوای آن دامنه را در هیچیک از خط زمانیها یا در آگاهیهایتان نخواهید دید. پیروانتان از آن دامنه، برداشته خواهند شد.</string> <string name="mute_domain_warning">مطمئنید میخواهید تمام %s را مسدود کنید؟ محتوای آن دامنه را در هیچیک از خط زمانیها یا در آگاهیهایتان نخواهید دید. پیگیرانتان از آن دامنه، برداشته خواهند شد.</string>
<string name="filter_dialog_whole_word_description">هنگامی که کلیدواژه یا عبارت، فقط حروفعددی باشد، فقط اگر با تمام واژه مطابق باشد، اعمال خواهد شد</string> <string name="filter_dialog_whole_word_description">هنگامی که کلیدواژه یا عبارت، فقط حروفعددی باشد، فقط اگر با تمام واژه مطابق باشد، اعمال خواهد شد</string>
<string name="filter_add_description">عبارت پالایش</string> <string name="filter_add_description">عبارت پالایش</string>
<string name="poll_info_format"> <!-- 15 votes • 1 hour left --> %1$s • %2$s</string> <string name="poll_info_format"> <!-- 15 votes • 1 hour left --> %1$s • %2$s</string>
<string name="report_description_1">گزارش به ناظمهای کارسازتان ارسال خواهد شد. میتوانید توضیحی در باب چرایی گزارش این حساب در زیر بنویسید:</string> <string name="report_description_1">گزارش به ناظر کارسازتان ارسال خواهد شد. میتوانید توضیحی در باب چرایی گزارش این حساب در زیر بنویسید:</string>
<string name="report_description_remote_instance">این حساب از کارسازی دیگر است. رونوشتی ناشناس از گزارش، به آنجا نیز ارسال شود؟</string> <string name="report_description_remote_instance">این حساب از کارسازی دیگر است. رونوشتی ناشناس از گزارش، به آنجا نیز ارسال شود؟</string>
<string name="post_lookup_error_format">خطا در یافتن فرستهٔ %s</string> <string name="post_lookup_error_format">خطا در یافتن فرستهٔ %s</string>
<string name="about_powered_by_tusky">قدرتگرفته از تاسکی</string> <string name="about_powered_by_tusky">قدرتگرفته از تاسکی</string>
</resources> <string name="error_audio_upload_size">پروندههای صوتی باید کمتر از ۴۰مب باشند.</string>
<string name="title_bookmarks">نشانکها</string>
<string name="action_bookmark">نشانک</string>
<string name="action_view_bookmarks">نشانکها</string>
<string name="gradient_for_media">نمایش گرادیان رنگی برای رسانهٔ نهفته</string>
<string name="description_status_bookmarked">نشانشده</string>
<string name="select_list_title">گزینش فهرست</string>
<string name="list">فهرست</string>
<string name="no_saved_status">هیچ پیشنویسی ندارید.</string>
<string name="no_scheduled_status">هیچ وضعیت زمانبستهای ندارید.</string>
</resources>

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

@ -331,9 +331,9 @@
<string name="unpin_action">Détacher</string> <string name="unpin_action">Détacher</string>
<string name="pin_action">Épingler</string> <string name="pin_action">Épingler</string>
<plurals name="favs"> <plurals name="favs">
<item quantity="one">&lt;b&gt;%1$s&lt;/b&gt; Favoris</item> <item quantity="one"><b>%1$s</b> Favori</item>
<item quantity="other">&lt;b&gt;%1$s&lt;/b&gt; Favoris</item> <item quantity="other"><b>%1$s</b> Favoris</item>
</plurals> </plurals>
<plurals name="reblogs"> <plurals name="reblogs">
<item quantity="one">&lt;b&gt;%s&lt;/b&gt; Boost</item> <item quantity="one">&lt;b&gt;%s&lt;/b&gt; Boost</item>
<item quantity="other">&lt;b&gt;%s&lt;/b&gt; Boosts</item> <item quantity="other">&lt;b&gt;%s&lt;/b&gt; Boosts</item>
@ -381,8 +381,8 @@
<string name="dialog_redraft_toot_warning">Effacer et ré-écrire ce pouet \?</string> <string name="dialog_redraft_toot_warning">Effacer et ré-écrire ce pouet \?</string>
<plurals name="poll_info_votes"> <plurals name="poll_info_votes">
<item quantity="one">%s vote</item> <item quantity="one">%s voix</item>
<item quantity="other">%s votes</item> <item quantity="other">%s voix</item>
</plurals> </plurals>
<string name="poll_info_time_relative">%s restant</string> <string name="poll_info_time_relative">%s restant</string>
<string name="poll_info_time_absolute">Termine à %s</string> <string name="poll_info_time_absolute">Termine à %s</string>

@ -23,7 +23,7 @@
<string name="error_retrieving_oauth_token">Mistókst að fá innskráningarteikn.</string> <string name="error_retrieving_oauth_token">Mistókst að fá innskráningarteikn.</string>
<string name="error_compose_character_limit">Stöðufærslan er of löng!</string> <string name="error_compose_character_limit">Stöðufærslan er of löng!</string>
<string name="error_image_upload_size">Skráin verður að vera minni en 8MB.</string> <string name="error_image_upload_size">Skráin verður að vera minni en 8MB.</string>
<string name="error_video_upload_size">Myndskeiðasskrár verða að vera minni en 40MB.</string> <string name="error_video_upload_size">Myndskeiðaskrár verða að vera minni en 40MB.</string>
<string name="error_media_upload_type">Þessa tegund skrár er ekki hægt að senda inn.</string> <string name="error_media_upload_type">Þessa tegund skrár er ekki hægt að senda inn.</string>
<string name="error_media_upload_opening">Ekki var hægt að opna skrána.</string> <string name="error_media_upload_opening">Ekki var hægt að opna skrána.</string>
<string name="error_media_upload_permission">Krafist er heimilda til að lesa gögn.</string> <string name="error_media_upload_permission">Krafist er heimilda til að lesa gögn.</string>
@ -507,4 +507,5 @@
<string name="no_saved_status">Þú ert ekki með nein drög.</string> <string name="no_saved_status">Þú ert ekki með nein drög.</string>
<string name="no_scheduled_status">Þú ert ekki með neinar áætlaðar stöðufærslur.</string> <string name="no_scheduled_status">Þú ert ekki með neinar áætlaðar stöðufærslur.</string>
</resources> <string name="error_audio_upload_size">Hljóðskrár verða að vera minni en 40MB.</string>
</resources>

@ -8,8 +8,8 @@
<string name="action_edit_profile">Ẓreg amaγnu</string> <string name="action_edit_profile">Ẓreg amaγnu</string>
<string name="action_search">Nadi</string> <string name="action_search">Nadi</string>
<string name="about_title_activity">Γef</string> <string name="about_title_activity">Γef</string>
<string name="action_lists">Tibdarin</string> <string name="action_lists">Umuγen</string>
<string name="title_lists">Tibdarin</string> <string name="title_lists">Umuγen</string>
<string name="error_compose_character_limit">Tijewwiqt-ik aṭas i γuzzifet!</string> <string name="error_compose_character_limit">Tijewwiqt-ik aṭas i γuzzifet!</string>
<string name="title_home">Agejdan</string> <string name="title_home">Agejdan</string>
<string name="title_tab_preferences">Iccaren</string> <string name="title_tab_preferences">Iccaren</string>
@ -49,5 +49,191 @@
<item quantity="other"><b>%1$s</b> n ismenyifen</item> <item quantity="other"><b>%1$s</b> n ismenyifen</item>
</plurals> </plurals>
<string name="no_saved_status">Ur teɛiḍ ara irewwayen.</string> <string name="no_saved_status">Ur tesɛiḍ ara irewwayen.</string>
<string name="error_generic">Tella-d tucḍa.</string>
<string name="title_notifications">Tilγa</string>
<string name="link_whats_an_instance">D acu i ttummant\?</string>
<string name="title_bookmarks">Ticraḍ</string>
<string name="action_bookmark">Rnu γer ticraḍ</string>
<string name="action_view_bookmarks">Ticraḍ</string>
<string name="action_mute_domain">Sgugem %s</string>
<string name="action_mention">Bder</string>
<string name="action_save">Sekles</string>
<string name="action_edit_own_profile">Ẓreg</string>
<string name="action_undo">Sefsex</string>
<string name="action_emoji_keyboard">Anasiw n imujiyen</string>
<string name="action_add_tab">Rnu iccer</string>
<string name="action_copy_link">Nγel aseγwen</string>
<string name="action_open_as">Ldi amzun d %s</string>
<string name="action_share_as">Bḍu amzun d…</string>
<string name="send_status_link_to">Bḍu aseγwen n tijewwiq s…</string>
<string name="send_status_content_to">Bḍu tijewwiqt d…</string>
<string name="hint_domain">Anta tummant\?</string>
<string name="hint_compose">d-acu i gellan d amaynut\?</string>
<string name="hint_search">Nadi…</string>
<string name="label_quick_reply">Tiririn…</string>
<string name="label_avatar">Tugna n umaγnu</string>
<string name="dialog_download_image">Sider</string>
<string name="dialog_delete_toot_warning">Kkes tijewwiqt-a\?</string>
<string name="pref_title_edit_notification_settings">Ẓreg tilγa</string>
<string name="pref_title_appearance_settings">Agrudem</string>
<string name="app_theme_light">Aceɛlal</string>
<string name="app_theme_black">Aberkan</string>
<string name="pref_title_language">Tutlayt</string>
<string name="pref_title_status_tabs">Iccaren</string>
<string name="pref_title_proxy_settings">Apṛuksi</string>
<string name="notification_summary_large">%1$s, %2$s, %3$s d %4$d nniḍen</string>
<string name="notification_summary_medium">%1$s, %2$s, akked %3$s</string>
<string name="notification_summary_small">%1$s akked %2$s</string>
<string name="about_tusky_version">Tusky %s</string>
<string name="about_tusky_account">Amaγnu n Tusky</string>
<string name="status_media_images">Tugniwin</string>
<string name="status_media_video">Tibidyutin</string>
<string name="follows_you">Yeṭafaṛ-ik-id</string>
<string name="filter_dialog_remove_button">Kkes</string>
<string name="filter_dialog_update_button">Lqem</string>
<string name="add_account_name">Rnu amiḍan</string>
<string name="add_account_description">Rnu yiwen umiḍan amaynut n Maṣṭudun</string>
<string name="action_compose_shortcut">Aru</string>
<string name="error_no_custom_emojis">Tummant-ik·im %s ur tesɛi ara imujiyen udmawanen</string>
<string name="action_open_toot">Ldi tijewwiqt</string>
<string name="license_cc_by_4">CC-BY 4.0</string>
<string name="license_cc_by_sa_4">CC-BY-SA 4.0</string>
<string name="pin_action">Senṭeḍ</string>
<string name="action_view_mutes">Imiḍanen yettwasgugmen</string>
<string name="action_view_blocks">Imiḍanen yettusḥebsen</string>
<string name="action_view_domain_mutes">Tiγula yettwaffren</string>
<string name="action_view_follow_requests">Isuturen n teḍfeṛt</string>
<string name="action_view_media">Taγwalt</string>
<string name="notifications_clear">Sfeḍ</string>
<string name="title_mutes">Imiḍanen yettwasgugmen</string>
<string name="title_blocks">Imiḍanen yettusḥebsen</string>
<string name="title_domain_mutes">Tiγula yettwaffren</string>
<string name="title_follow_requests">Isuturen n teḍfeṛt</string>
<string name="pref_title_notifications_enabled">Ẓreg tilγa</string>
<string name="title_media">Taγwalt</string>
<string name="action_remove">Kkes</string>
<string name="compose_shortcut_short_label">Azen</string>
<string name="edit_poll">Ẓreg</string>
<string name="title_statuses_pinned">Yettwanṭḍen</string>
<string name="action_add_media">Rnu amidya</string>
<string name="action_add_poll">Rnu assenqed</string>
<string name="action_photo_take">Ṭef tugna</string>
<string name="action_toggle_visibility">Timeẓriwt n tijewwaqt</string>
<string name="action_schedule_toot">Sγiwes tijewwaqt-a</string>
<string name="status_share_content">Bḍu agbur n tijewwiqt-a</string>
<string name="status_share_link">Bḍu aseγwen γer tijewwiqt</string>
<string name="filter_addition_dialog_title">Rnu amsizdeg</string>
<string name="filter_edit_dialog_title">Ẓreg amsizdeg</string>
<string name="action_create_list">Snulfu-d umuγ</string>
<string name="action_rename_list">Snifel isem n wumuγ</string>
<string name="action_delete_list">Kkes umuγ-a</string>
<string name="action_edit_list">Ẓreg umuγ-a</string>
<string name="action_add_to_list">Rnu yiwen umiḍan γer tabdert</string>
<string name="action_remove_from_list">Kkes amiḍan seg wumuγ</string>
<string name="profile_metadata_add">Rnu isefka</string>
<string name="hint_list_name">Isem n wumuγ</string>
<string name="select_list_title">Fren tabdart</string>
<string name="list">Umuγ</string>
<string name="notifications_apply_filter">Sizdeg</string>
<string name="title_accounts">Imiḍanen</string>
<string name="add_poll_choice">Rnu yiwen wefran</string>
<string name="report_username_format">Ccetki γef @%s</string>
<string name="action_report">Ccetki</string>
<string name="action_reject">Ggami</string>
<string name="download_image">Yessidired %1$s</string>
<string name="send_media_to">Bḍu tugna s…</string>
<string name="login_connection">itteqqen…</string>
<string name="dialog_message_uploading_media">Issalay…</string>
<string name="pref_title_notification_filter_poll">fukken kran n wadγaren</string>
<string name="pref_title_timeline_filters">Imzizdigen</string>
<string name="app_theme_auto">Akken yella yiṭij</string>
<string name="pref_title_browser_settings">Iminig</string>
<string name="pref_title_show_replies">Sken-ed tiririyin</string>
<string name="pref_title_http_proxy_settings">Apṛuksi HTTP</string>
<string name="pref_title_http_proxy_server">Tansa n upṛuksi HTTP</string>
<string name="notification_follow_name">Imeḍfaṛen imaynuten</string>
<string name="notification_poll_name">Adγaren</string>
<string name="notification_mention_format">Yuder-ik-id %s</string>
<string name="description_account_locked">Yettwargel umiḍan</string>
<string name="abbreviated_years_ago">%dis aya</string>
<string name="abbreviated_days_ago">%dus aya</string>
<string name="replying_to">Tettaraḍ-as i @%s</string>
<string name="load_more_placeholder_text">awid ugar</string>
<string name="pref_title_thread_filter_keywords">Idewenniyen</string>
<string name="lock_account_label">Rgel amiḍan</string>
<string name="performing_lookup_title">Yettnadi…</string>
<string name="restart">Ales tanekra</string>
<string name="download_failed">Tuccḍa n usider</string>
<string name="account_moved_description">Igujj %1$s γer:</string>
<string name="unpin_action">Kkes asenṭeḍ</string>
<string name="conversation_1_recipients">%1$s</string>
<string name="conversation_2_recipients">%1$s akked %2$s</string>
<string name="conversation_more_recipients">%1$s, %2$s akked %3$d nniḍen</string>
<string name="compose_shortcut_long_label">Aru tijewwiqt</string>
<string name="poll_info_format"> <!-- 15 n wadγaren • 1 n wesrag id yeqqimen --> %1$s • %2$s</string>
<plurals name="poll_info_votes">
<item quantity="one">%s wedγar</item>
<item quantity="other">%s n yedγaren</item>
</plurals>
<string name="poll_info_time_relative">%s id yugran</string>
<string name="poll_info_time_absolute">ad ifak deg %s</string>
<string name="poll_info_closed">ifuk</string>
<string name="poll_vote">Dγer</string>
<string name="poll_ended_voted">Ifuk, tura kan, yiwen wedγar t tteki-iḍ degs</string>
<string name="poll_ended_created">Ifukk yiwen wedγar id snulfaḍ</string>
<plurals name="poll_timespan_days">
<item quantity="one">%d n wass</item>
<item quantity="other">%d n wussan</item>
</plurals>
<plurals name="poll_timespan_hours">
<item quantity="one">%d wesrag</item>
<item quantity="other">%d n yisragen</item>
</plurals>
<plurals name="poll_timespan_minutes">
<item quantity="one">%d n tasdidt</item>
<item quantity="other">%d n tesdidin</item>
</plurals>
<string name="button_continue">Kemmel</string>
<string name="button_back">Uγal</string>
<string name="failed_report">Tella-d tuccḍa deg ccetki</string>
<string name="failed_search">Tucḍa n unadi</string>
<string name="create_poll_title">Assenqed</string>
<string name="poll_duration_5_min">5 n tasditin</string>
<string name="poll_duration_30_min">30 n tasditin</string>
<string name="poll_duration_1_hour">1 n wesrag</string>
<string name="poll_duration_6_hours">6 n wesragen</string>
<string name="poll_duration_1_day">1 n wass</string>
<string name="poll_duration_3_days">3 n wussan</string>
<string name="poll_duration_7_days">7 n wussan</string>
<string name="poll_new_choice_hint">Tafrant %d</string>
<string name="title_follows">Ig ṭafaṛ</string>
<string name="title_followers">Imeḍfaṛen</string>
<string name="hint_search_people_list">Nadi γef medden i teṭafareḍ</string>
<string name="description_visiblity_private">Imeḍfaṛen</string>
</resources> </resources>

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

@ -2,7 +2,7 @@
<resources> <resources>
<color name="colorSurface">@color/tusky_grey_30</color> <color name="colorSurface">@color/tusky_grey_30</color>
<color name="colorPrimaryDark">@color/tusky_grey_10</color> <color name="colorPrimaryDark">@color/tusky_grey_25</color>
<color name="colorBackground">@color/tusky_grey_20</color> <color name="colorBackground">@color/tusky_grey_20</color>
<color name="windowBackground">@color/tusky_grey_10</color> <color name="windowBackground">@color/tusky_grey_10</color>
@ -15,6 +15,7 @@
<color name="iconColor">@color/tusky_grey_70</color> <color name="iconColor">@color/tusky_grey_70</color>
<color name="colorBackgroundAccent">@color/tusky_grey_30</color> <color name="colorBackgroundAccent">@color/tusky_grey_30</color>
<color name="dividerColor">@color/tusky_grey_25</color>
<color name="favoriteButtonActiveColor">@color/tusky_orange</color> <color name="favoriteButtonActiveColor">@color/tusky_orange</color>

@ -441,7 +441,7 @@
<string name="report_remote_instance">Verder naar %s</string> <string name="report_remote_instance">Verder naar %s</string>
<string name="failed_report">Het rapporteren is mislukt</string> <string name="failed_report">Het rapporteren is mislukt</string>
<string name="failed_fetch_statuses">Het ophalen van toots is mislukt</string> <string name="failed_fetch_statuses">Het ophalen van toots is mislukt</string>
<string name="report_description_1">Deze rapportage wordt naar jouw servermoderator(en) gestuurd. Je kunt een uitleg geven over waarom je het account hieronder wilt rapporteren:</string> <string name="report_description_1">De rapportage wordt naar de moderator(en) van jouw server gestuurd. Je kunt hieronder een uitleg geven waarom je dit account rapporteert:</string>
<string name="report_description_remote_instance">Het account is van een andere server. Wil je ook een geanonimiseerde kopie van de rapportage daarnaartoe sturen\?</string> <string name="report_description_remote_instance">Het account is van een andere server. Wil je ook een geanonimiseerde kopie van de rapportage daarnaartoe sturen\?</string>
<string name="pref_title_show_notifications_filter">Meldingenfilter tonen</string> <string name="pref_title_show_notifications_filter">Meldingenfilter tonen</string>
@ -459,4 +459,30 @@
<string name="poll_new_choice_hint">Keuze %d</string> <string name="poll_new_choice_hint">Keuze %d</string>
<string name="edit_poll">Bewerk</string> <string name="edit_poll">Bewerk</string>
<string name="error_audio_upload_size">Geluidsbestanden moeten minder dan 40MB zijn.</string>
<string name="title_bookmarks">Bladwijzers</string>
<string name="title_scheduled_toot">Ingeplande toots</string>
<string name="action_bookmark">Bladwijzer</string>
<string name="action_edit">Bewerken</string>
<string name="action_view_bookmarks">Bladwijzers</string>
<string name="action_add_poll">Poll toevoegen</string>
<string name="action_access_scheduled_toot">Ingeplande toots</string>
<string name="action_schedule_toot">Ingeplande toot</string>
<string name="action_reset_schedule">Herstellen</string>
<string name="gradient_for_media">Wazige kleurovergangen voor verborgen media tonen</string>
<string name="about_powered_by_tusky">Powered by Tusky</string>
<string name="pref_title_alway_open_spoiler">Altijd toots met tekstwaarschuwingen uitklappen</string>
<string name="description_status_bookmarked">Als bladwijzer toegevoegd</string>
<string name="select_list_title">Kies een lijst</string>
<string name="list">Lijst</string>
<string name="title_accounts">Accounts</string>
<string name="failed_search">Zoeken mislukt</string>
<string name="create_poll_title">Poll</string>
<string name="post_lookup_error_format">Fout tijdens opzoeken toot %s</string>
<string name="no_saved_status">Je hebt nog geen concepten.</string>
<string name="no_scheduled_status">Je hebt nog geen ingeplande toots.</string>
</resources> </resources>

@ -492,4 +492,10 @@
<string name="description_status_bookmarked">Dodane do zakładek</string> <string name="description_status_bookmarked">Dodane do zakładek</string>
<string name="select_list_title">Wybierz listę</string> <string name="select_list_title">Wybierz listę</string>
<string name="list">Lista</string> <string name="list">Lista</string>
</resources> <string name="error_audio_upload_size">Pliki audio muszą być mniejsze niż 40MB.</string>
<string name="gradient_for_media">Pokaż kolorowe gradienty dla ukrytych mediów</string>
<string name="no_saved_status">Nie masz żadnych szkiców.</string>
<string name="no_scheduled_status">Nie masz żadnych zaplanowanych wpisów.</string>
</resources>

@ -484,4 +484,6 @@
<string name="no_scheduled_status">Sem toots agendados.</string> <string name="no_scheduled_status">Sem toots agendados.</string>
</resources> <string name="error_audio_upload_size">Áudios devem ser menores que 40MB.</string>
<string name="no_saved_status">Sem rascunhos.</string>
</resources>

@ -538,7 +538,6 @@
<string name="action_access_scheduled_toot">Отложенные записи</string> <string name="action_access_scheduled_toot">Отложенные записи</string>
<string name="action_schedule_toot">Отложить запись</string> <string name="action_schedule_toot">Отложить запись</string>
<string name="action_reset_schedule">Сброс</string> <string name="action_reset_schedule">Сброс</string>
<string name="post_lookup_error_format">Ошибка при поиске сообщения / ний</string>
<string name="title_bookmarks">Закладки</string> <string name="title_bookmarks">Закладки</string>
<string name="action_bookmark">Добавить в закладки</string> <string name="action_bookmark">Добавить в закладки</string>

@ -28,4 +28,88 @@
<string name="report_username_format">Nahlásiť používateľa @%s</string> <string name="report_username_format">Nahlásiť používateľa @%s</string>
<string name="action_quick_reply">Rýchla odpoveď</string> <string name="action_quick_reply">Rýchla odpoveď</string>
<string name="action_reply">Odpovedať</string> <string name="action_reply">Odpovedať</string>
<string name="link_whats_an_instance">Čo je server\?</string>
<string name="title_favourites">Obľúbené</string>
<string name="about_title_activity">O aplikácii</string>
<string name="error_network">Vyskytla sa chyba v sieti! Prosím skontrolujte svoje pripojenie a skúste to znova!</string>
<string name="error_empty">Toto nemôže byť prázdne.</string>
<string name="error_authorization_denied">Autorizácia bola zamietnutá.</string>
<string name="error_retrieving_oauth_token">Nepodarilo sa získať prihlasovací token.</string>
<string name="error_image_upload_size">Súbor musí byť menší ako 8 MB.</string>
<string name="error_video_upload_size">Videosúbory musia byť menšie ako 40 MB.</string>
<string name="error_audio_upload_size">Audio súbory musia byť menšie ako 40 MB.</string>
<string name="error_media_upload_opening">Súbor sa nepodarilo otvoriť.</string>
<string name="title_home">Domov</string>
<string name="title_tab_preferences">Panely</string>
<string name="action_bookmark">Vytvoriť záložku</string>
<string name="action_follow">Sledovať</string>
<string name="action_unfollow">Prestať sledovať</string>
<string name="action_block">Blokovať</string>
<string name="action_unblock">Odblokovať</string>
<string name="action_report">Nahlásiť</string>
<string name="action_edit">Upraviť</string>
<string name="action_delete">Vymazať</string>
<string name="action_delete_and_redraft">Vymazať a prepísať</string>
<string name="action_reset_schedule">Obnoviť</string>
<string name="action_links">Odkazy</string>
<string name="action_mentions">Zmienky</string>
<string name="action_hashtags">Hashtagy</string>
<string name="action_open_faved_by">Zobraziť obľúbené</string>
<string name="title_hashtags_dialog">Hashtagy</string>
<string name="title_mentions_dialog">Zmienky</string>
<string name="title_links_dialog">Odkazy</string>
<string name="action_open_media_n">Otvoriť médium #%d</string>
<string name="download_image">Sťahovanie %1$s</string>
<string name="action_copy_link">Kopírovať odkaz</string>
<string name="action_open_as">Otvoriť ako %s</string>
<string name="confirmation_reported">Odoslané!</string>
<string name="confirmation_unblocked">Používateľ bol odblokovaný</string>
<string name="status_sent">Odoslané!</string>
<string name="status_sent_long">Odpoveď bola úspešne odoslaná.</string>
<string name="hint_domain">Ktorý server\?</string>
<string name="hint_display_name">Zobrazované meno</string>
<string name="hint_note">O vás</string>
<string name="hint_search">Hľadať…</string>
<string name="search_no_results">Žiadne výsledky</string>
<string name="label_quick_reply">Odpovedať…</string>
<string name="dialog_message_uploading_media">Nahrávanie…</string>
<string name="dialog_download_image">Stiahnuť</string>
<string name="error_invalid_domain">Neplatná doména</string>
<string name="error_failed_app_registration">Autentizácia servru zlyhala.</string>
<string name="error_no_web_browser_found">Nepodarilo sa nájsť použiteľný webový prehliadač.</string>
<string name="error_authorization_unknown">Vyskytla sa neidentifikovaná chyba autorizácie.</string>
<string name="error_compose_character_limit">Toot je príliš dlhý!</string>
<string name="error_media_upload_type">Tento typ súboru nemôže byť nahraný.</string>
<string name="error_sender_account_gone">Chyba pri odosielaní tootu.</string>
<string name="title_view_thread">Toot</string>
<string name="notification_favourite_format">%s si obľúbil/a váš toot</string>
<string name="action_send">TOOT</string>
<string name="action_send_public">TOOT!</string>
<string name="action_toggle_visibility">Viditeľnosť tootu</string>
<string name="action_schedule_toot">Naplánovať toot</string>
<string name="dialog_delete_toot_warning">Vymazať tento toot\?</string>
<string name="dialog_redraft_toot_warning">Vymazať a prepísať tento toot\?</string>
<string name="status_share_content">Zdieľať obsah tootu</string>
<string name="status_share_link">Zdieľať odkaz tootu</string>
<string name="send_toot_notification_title">Odosielanie tootu…</string>
<string name="send_toot_notification_error_title">Chyba pri odosielaní tootu</string>
<string name="send_toot_notification_saved_content">Kópia vášho tootu bola uložená do konceptov</string>
<string name="action_open_toot">Otvoriť toot</string>
<string name="compose_shortcut_long_label">Napísať toot</string>
<string name="title_scheduled_toot">Plánované tooty</string>
<string name="action_access_scheduled_toot">Plánované tooty</string>
<string name="label_avatar">Avatar</string>
<string name="action_remove">Odstrániť</string>
<string name="lock_account_label">Uzamknúť účet</string>
<string name="compose_save_draft">Uložiť koncept\?</string>
<string name="send_toot_notification_channel_name">Odosielanie tootov</string>
<string name="send_toot_notification_cancel_title">Odosielanie bolo zrušené</string>
</resources> </resources>

@ -118,7 +118,7 @@
<string name="action_open_media_n">Öppna media #%d</string> <string name="action_open_media_n">Öppna media #%d</string>
<string name="download_image">Laddar ned %1$s</string> <string name="download_image">Laddar ned %1$s</string>
<string name="action_copy_link">Kopiera länk</string> <string name="action_copy_link">Kopiera länk</string>
<string name="action_open_as">Öppen som %s</string> <string name="action_open_as">Öppna med %s</string>
<string name="action_share_as">Dela som …</string> <string name="action_share_as">Dela som …</string>
<string name="send_status_link_to">Dela toot-URL till…</string> <string name="send_status_link_to">Dela toot-URL till…</string>
<string name="send_status_content_to">Dela toot till…</string> <string name="send_status_content_to">Dela toot till…</string>
@ -480,4 +480,6 @@
<string name="no_scheduled_status">Du har inga schemalagda statusar.</string> <string name="no_scheduled_status">Du har inga schemalagda statusar.</string>
</resources> <string name="error_audio_upload_size">Ljudfiler måste vara mindre än 40MB.</string>
<string name="no_saved_status">Du har inga utkast.</string>
</resources>

@ -7,20 +7,20 @@
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowLightNavigationBar">false</item> <item name="android:windowLightNavigationBar">false</item>
<item name="android:navigationBarColor">@color/tusky_grey_20</item> <item name="android:navigationBarColor">@color/tusky_grey_20</item>
<item name="android:navigationBarDividerColor">@color/tusky_grey_30</item> <item name="android:navigationBarDividerColor">@color/tusky_grey_25</item>
</style> </style>
<style name="TuskyTheme" parent="TuskyBaseTheme"> <style name="TuskyTheme" parent="TuskyBaseTheme">
<item name="android:windowLightNavigationBar">@bool/lightNavigationBar</item> <item name="android:windowLightNavigationBar">@bool/lightNavigationBar</item>
<item name="android:navigationBarColor">@color/colorBackground</item> <item name="android:navigationBarColor">@color/colorBackground</item>
<item name="android:navigationBarDividerColor">@color/colorBackgroundAccent</item> <item name="android:navigationBarDividerColor">?attr/dividerColor</item>
</style> </style>
<!--Black Application Theme Styles--> <!--Black Application Theme Styles-->
<style name="TuskyBlackTheme" parent="TuskyBlackThemeBase"> <style name="TuskyBlackTheme" parent="TuskyBlackThemeBase">
<item name="android:windowLightNavigationBar">false</item> <item name="android:windowLightNavigationBar">false</item>
<item name="android:navigationBarColor">@color/black</item> <item name="android:navigationBarColor">@color/black</item>
<item name="android:navigationBarDividerColor">@color/tusky_grey_05</item> <item name="android:navigationBarDividerColor">?attr/dividerColor</item>
</style> </style>
</resources> </resources>

@ -13,6 +13,7 @@
<attr name="textColorDisabled" format="reference|color" /> <attr name="textColorDisabled" format="reference|color" />
<attr name="iconColor" format="reference|color" /> <attr name="iconColor" format="reference|color" />
<attr name="windowBackgroundColor" format="reference|color" /> <attr name="windowBackgroundColor" format="reference|color" />
<attr name="dividerColor" format="reference|color" />
<attr name="status_text_small" format="dimension" /> <attr name="status_text_small" format="dimension" />
<attr name="status_text_medium" format="dimension" /> <attr name="status_text_medium" format="dimension" />

@ -15,6 +15,7 @@
<color name="tusky_grey_05">#070b14</color> <color name="tusky_grey_05">#070b14</color>
<color name="tusky_grey_10">#121a24</color> <!-- Pleroma Dark Background --> <color name="tusky_grey_10">#121a24</color> <!-- Pleroma Dark Background -->
<color name="tusky_grey_20">#182230</color> <!-- Pleroma Dark Foreground --> <color name="tusky_grey_20">#182230</color> <!-- Pleroma Dark Foreground -->
<color name="tusky_grey_25">#1f2836</color> <!-- calculated from gradient -->
<color name="tusky_grey_30">#252e3c</color> <!-- Pleroma Dark Foreground --> <color name="tusky_grey_30">#252e3c</color> <!-- Pleroma Dark Foreground -->
<color name="tusky_grey_40">#3f4855</color> <!-- calculated from gradient --> <color name="tusky_grey_40">#3f4855</color> <!-- calculated from gradient -->
<color name="tusky_grey_50">#666e7a</color> <!-- calculated from gradient --> <color name="tusky_grey_50">#666e7a</color> <!-- calculated from gradient -->

@ -9,7 +9,7 @@
<dimen name="compose_media_preview_size">120dp</dimen> <dimen name="compose_media_preview_size">120dp</dimen>
<dimen name="compose_options_margin">8dp</dimen> <dimen name="compose_options_margin">8dp</dimen>
<dimen name="account_avatar_margin">14dp</dimen> <dimen name="account_avatar_margin">14dp</dimen>
<dimen name="tab_page_margin">8dp</dimen> <dimen name="tab_page_margin">16dp</dimen>
<dimen name="status_line_margin_start">36dp</dimen> <dimen name="status_line_margin_start">36dp</dimen>
<dimen name="text_content_margin">16dp</dimen> <dimen name="text_content_margin">16dp</dimen>
<dimen name="status_sensitive_media_button_padding">5dp</dimen> <dimen name="status_sensitive_media_button_padding">5dp</dimen>

@ -46,6 +46,7 @@
<item>Español</item> <item>Español</item>
<item>Euskara</item> <item>Euskara</item>
<item>Français</item> <item>Français</item>
<item>íslenska</item>
<item>Italiano</item> <item>Italiano</item>
<item>Magyar</item> <item>Magyar</item>
<item>Nederlands</item> <item>Nederlands</item>
@ -59,6 +60,7 @@
<item>Türkçe</item> <item>Türkçe</item>
<item>Русский</item> <item>Русский</item>
<item>العربية</item> <item>العربية</item>
<item></item>
<item>فارسی</item> <item>فارسی</item>
<item>தமி</item> <item>தமி</item>
<item>한국어</item> <item>한국어</item>
@ -82,6 +84,7 @@
<item>es</item> <item>es</item>
<item>eu</item> <item>eu</item>
<item>fr</item> <item>fr</item>
<item>is</item>
<item>it</item> <item>it</item>
<item>hu</item> <item>hu</item>
<item>nl</item> <item>nl</item>
@ -95,6 +98,7 @@
<item>tr</item> <item>tr</item>
<item>ru</item> <item>ru</item>
<item>ar</item> <item>ar</item>
<item>bn-in</item>
<item>fa</item> <item>fa</item>
<item>ta</item> <item>ta</item>
<item>ko</item> <item>ko</item>

@ -63,6 +63,7 @@
<item name="iconColor">@color/iconColor</item> <item name="iconColor">@color/iconColor</item>
<item name="android:listDivider">@drawable/status_divider</item> <item name="android:listDivider">@drawable/status_divider</item>
<item name="dividerColor">@color/dividerColor</item>
<item name="textColorDisabled">@color/textColorDisabled</item> <item name="textColorDisabled">@color/textColorDisabled</item>
@ -71,7 +72,7 @@
<item name="material_drawer_primary_icon">@color/iconColor</item> <item name="material_drawer_primary_icon">@color/iconColor</item>
<item name="material_drawer_secondary_text">@color/textColorTertiary</item> <item name="material_drawer_secondary_text">@color/textColorTertiary</item>
<item name="material_drawer_hint_text">@color/textColorTertiary</item> <item name="material_drawer_hint_text">@color/textColorTertiary</item>
<item name="material_drawer_divider">@color/colorBackgroundAccent</item> <item name="material_drawer_divider">?attr/dividerColor</item>
<item name="material_drawer_header_selection_text">@color/white</item> <item name="material_drawer_header_selection_text">@color/white</item>
<item name="material_drawer_header_selection_subtext">@color/white</item> <item name="material_drawer_header_selection_subtext">@color/white</item>
@ -91,11 +92,12 @@
<style name="TuskyDialog" parent="@style/ThemeOverlay.MaterialComponents.Dialog.Alert"> <style name="TuskyDialog" parent="@style/ThemeOverlay.MaterialComponents.Dialog.Alert">
<item name="android:letterSpacing">0</item> <item name="android:letterSpacing">0</item>
<item name="dialogCornerRadius">8dp</item> <item name="dialogCornerRadius">8dp</item>
<item name="android:background">@color/colorBackground</item>
</style> </style>
<style name="TuskyDialogFragmentStyle" parent="@style/ThemeOverlay.MaterialComponents.Dialog"> <style name="TuskyDialogFragmentStyle" parent="@style/ThemeOverlay.MaterialComponents.Dialog">
<item name="dialogCornerRadius">8dp</item> <item name="dialogCornerRadius">8dp</item>
<item name="android:backgroundTint">?attr/windowBackgroundColor</item> <item name="android:backgroundTint">@color/colorBackground</item>
</style> </style>
<style name="TuskyTabAppearance" parent="Widget.MaterialComponents.TabLayout"> <style name="TuskyTabAppearance" parent="Widget.MaterialComponents.TabLayout">
@ -114,6 +116,7 @@
</style> </style>
<style name="TuskyButton.Outlined" parent="Widget.MaterialComponents.Button.OutlinedButton"> <style name="TuskyButton.Outlined" parent="Widget.MaterialComponents.Button.OutlinedButton">
<item name="strokeColor">?attr/colorBackgroundAccent</item>
<item name="android:letterSpacing">0</item> <item name="android:letterSpacing">0</item>
</style> </style>
@ -140,7 +143,7 @@
<item name="material_drawer_background">@color/black</item> <item name="material_drawer_background">@color/black</item>
<item name="material_drawer_primary_icon">@color/tusky_grey_80</item> <item name="material_drawer_primary_icon">@color/tusky_grey_80</item>
<item name="material_drawer_divider">@color/tusky_grey_40</item> <item name="dividerColor">@color/tusky_grey_40</item>
</style> </style>
<style name="TuskyBlackTheme" parent="TuskyBlackThemeBase" /> <style name="TuskyBlackTheme" parent="TuskyBlackThemeBase" />

@ -14,7 +14,8 @@
<color name="iconColor">@color/tusky_grey_50</color> <color name="iconColor">@color/tusky_grey_50</color>
<color name="colorBackgroundAccent">@color/tusky_grey_80</color> <color name="colorBackgroundAccent">@color/tusky_grey_70</color>
<color name="dividerColor">@color/tusky_grey_80</color>
<color name="favoriteButtonActiveColor">@color/tusky_orange_light</color> <color name="favoriteButtonActiveColor">@color/tusky_orange_light</color>

@ -0,0 +1,3 @@
Tusky v9.1
يكفل هذا التحديث التوافق مع ماستدون 3 ويحسن الأداء والاستقرار.

@ -0,0 +1,7 @@
Tusky v7.0
- Unterstützung für das Anzeigen von Umfragen, Abstimmen und Umfragebenachrichtigungen
- Neue Knöpfe um den Benachrichtigungstab zu filtern und alle Benachrichtigungen zu löschen
- Lösche & erstelle deine Toots neu
- es wird auf dem Profilbild angezeigt, ob es sich bei einem Account um einen Bot handelt (kann in den Einstellungen ausgeschaltet werden)
- Neue Übersetzungen: Norwegisch Bokmål und Slovenisch.

@ -0,0 +1,8 @@
Tusky v10.0
- Du kannst jetzt Lesezeichen hinzufügen und ansehen
- Du kannst jetzt Posts vorausplanen. Achtung, der geplante Zeitpunkt muss mindestens 5 Minuten in der Zukunft liegen!
- Du kannst jetzt Listen auf dem Hauptbildschirm anzeigen.
- Du kannst jetzt Audio-Anhänge versenden.
Und viele andere Verbesserungen und Fehlerkorrekturen!

@ -0,0 +1,8 @@
Tusky v10.0
- You can now bookmark statuses & list your bookmarks in Tusky.
- You can now schedule toots with Tusky. Note that the time you select has to be at least 5 minutes in the future.
- You can now add lists to the main screen.
- You can now post audio attachments with Tusky.
And a lot of other small improvements and bug fixes!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 KiB

After

Width:  |  Height:  |  Size: 976 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 KiB

After

Width:  |  Height:  |  Size: 926 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 KiB

After

Width:  |  Height:  |  Size: 326 KiB

@ -0,0 +1,7 @@
Tusky v7.0
- Support for displaying polls, voting and poll notifications
- New buttons to filter the notification tab and to delete all notifications
- delete & redraft your own toots
- new indicator that shows if an account is a bot on the profile image (can be turned off in the preferences)
- New translations: Norwegian Bokmål and Slovenian.

@ -0,0 +1,9 @@
Tusky v9.0
- You can now create Polls from Tusky
- Improved search
- New option in Account Preferences to always expand content warnings
- Avatars in the navigation drawer have now a rounded square shape
- It is now possible to report users even when they never posted a status
- Tusky will now refuse to connect over cleartext connections on Android 6+
- A lot of other small improvements and bug fixes

@ -0,0 +1,3 @@
Tusky v9.1
This release ensures compatibility with Mastodon 3 and improves performance and stability.

@ -0,0 +1 @@
Een multi-accountclient voor het sociale netwerk Mastodon

@ -0,0 +1,9 @@
Tusky v9.0
- Teraz z Tusky môžete vytvárať ankety
- Vylepšené vyhľadávanie
- Nová možnost v nastaveniach účtu umožňuje automaticky rozbaľovať varovania obsahu
- Avatary v navigačnom menu majú odteraz zaokrúhlené rohy
- Odteraz je možné nahlásiť používateľa aj keď ešte nenapísali žiadny príspevok
- Tusky bude odteraz odmietať nešifrované spojenie na Androidu 6+
- Veľa ďalších malých vylepšení a opráv

@ -0,0 +1,3 @@
Tusky v9.1
Toto vydanie zaisťuje kompatibilitu s Mastodon 3 a vylepšuje výkon a stabilitu.

@ -0,0 +1 @@
Viacúčtový klient pre sociálnu sieť Mastodon

@ -1,6 +1,6 @@
Tusky v7.0 Tusky v7.0
- Support för att visa undersökningar, rösta och notifikationer - Stöd för att visa undersökningar, rösta och notifikationer
- Nya knappar för ett filtrera notifikationsfliken och att ta bort alla notifieringar - Nya knappar för ett filtrera notifikationsfliken och att ta bort alla notifieringar
- Radera & skriv ny toot - Radera & skriv ny toot
- Ny indikator som visar om kontot är en bot vid profilbilden (kan stängas av under inställningar) - Ny indikator som visar om kontot är en bot vid profilbilden (kan stängas av under inställningar)

@ -0,0 +1,3 @@
Tusky v9.1
Denna release garanterar kompatibilitet med Mastodon 3 och ökar prestanda och stabilitet.
Loading…
Cancel
Save