diff --git a/app/build.gradle b/app/build.gradle index fcda7ec49..8aace30fe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { defaultConfig { minSdk 21 targetSdk 33 - versionCode 456 - versionName "3.13.2" + versionCode 457 + versionName "3.13.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } flavorDimensions "default" diff --git a/app/src/main/assets/release_notes/notes.json b/app/src/main/assets/release_notes/notes.json index b1e4195b8..24c9070a8 100644 --- a/app/src/main/assets/release_notes/notes.json +++ b/app/src/main/assets/release_notes/notes.json @@ -1,4 +1,9 @@ [ + { + "version": "3.13.3", + "code": "457", + "note": "Added:\n- Allow to enable extra features in Settings\n- Customizable settings for extra features\n- Support quotes, reactions with messages\n- Support text format (html, markdown, etc.) when composing\n\nFixed:\n- CW not working with media\n- Media not displayed for older instances\n- Some crashes\n" + }, { "version": "3.13.2", "code": "456", diff --git a/app/src/main/java/app/fedilab/android/BaseMainActivity.java b/app/src/main/java/app/fedilab/android/BaseMainActivity.java index 331add50b..a09a6ec54 100644 --- a/app/src/main/java/app/fedilab/android/BaseMainActivity.java +++ b/app/src/main/java/app/fedilab/android/BaseMainActivity.java @@ -122,6 +122,7 @@ import app.fedilab.android.activities.SuggestionActivity; import app.fedilab.android.activities.TrendsActivity; import app.fedilab.android.activities.admin.AdminActionActivity; import app.fedilab.android.broadcastreceiver.NetworkStateReceiver; +import app.fedilab.android.client.endpoints.MastodonAccountsService; import app.fedilab.android.client.entities.api.Emoji; import app.fedilab.android.client.entities.api.EmojiInstance; import app.fedilab.android.client.entities.api.Filter; @@ -159,6 +160,8 @@ import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; public abstract class BaseMainActivity extends BaseActivity implements NetworkStateReceiver.NetworkStateReceiverListener, FragmentMastodonTimeline.UpdateCounters, FragmentNotificationContainer.UpdateCounters, FragmentMastodonConversation.UpdateCounters { @@ -585,9 +588,35 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt } catch (DBException e) { e.printStackTrace(); } + //If the attached account is null, the app will fetch remote instance to get up-to-date values + if (currentAccount != null && currentAccount.mastodon_account == null) { + OkHttpClient okHttpClient = new OkHttpClient.Builder() + .readTimeout(60, TimeUnit.SECONDS) + .connectTimeout(60, TimeUnit.SECONDS) + .callTimeout(60, TimeUnit.SECONDS) + .proxy(Helper.getProxy(getApplication().getApplicationContext())) + .build(); + Retrofit retrofit = new Retrofit.Builder() + .baseUrl("https://" + MainActivity.currentInstance + "/api/v1/") + .addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder())) + .client(okHttpClient) + .build(); + MastodonAccountsService mastodonAccountsService = retrofit.create(MastodonAccountsService.class); + retrofit2.Call accountCall = mastodonAccountsService.verify_credentials(MainActivity.currentToken); + if (accountCall != null) { + try { + retrofit2.Response accountResponse = accountCall.execute(); + if (accountResponse.isSuccessful()) { + currentAccount.mastodon_account = accountResponse.body(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> { - if (currentAccount == null) { + if (currentAccount == null || currentAccount.mastodon_account == null) { //It is not, the user is redirected to the login page Intent myIntent = new Intent(BaseMainActivity.this, LoginActivity.class); startActivity(myIntent); diff --git a/app/src/main/java/app/fedilab/android/activities/ComposeActivity.java b/app/src/main/java/app/fedilab/android/activities/ComposeActivity.java index 88addf670..5ff370bac 100644 --- a/app/src/main/java/app/fedilab/android/activities/ComposeActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ComposeActivity.java @@ -104,7 +104,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana public static final int TAKE_PHOTO = 5600; private final Timer timer = new Timer(); private List statusList; - private Status statusReply, statusMention; + private Status statusReply, statusMention, statusQuoted; private StatusDraft statusDraft; private ComposeAdapter composeAdapter; private boolean promptSaveDraft; @@ -465,6 +465,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana Bundle b = getIntent().getExtras(); if (b != null) { statusReply = (Status) b.getSerializable(Helper.ARG_STATUS_REPLY); + statusQuoted = (Status) b.getSerializable(Helper.ARG_QUOTED_MESSAGE); statusDraft = (StatusDraft) b.getSerializable(Helper.ARG_STATUS_DRAFT); scheduledStatus = (ScheduledStatus) b.getSerializable(Helper.ARG_STATUS_SCHEDULED); statusReplyId = b.getString(Helper.ARG_STATUS_REPLY_ID); @@ -557,6 +558,9 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana List statusDraftList = new ArrayList<>(); Status status = new Status(); status.id = Helper.generateIdString(); + if (statusQuoted != null) { + status.quote_id = statusQuoted.id; + } statusDraftList.add(status); if (statusReplyId != null && statusDraft != null) {//Delete and redraft @@ -647,6 +651,18 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana binding.recyclerView.setAdapter(composeAdapter); statusesVM.getContext(currentInstance, BaseMainActivity.currentToken, statusReply.id) .observe(ComposeActivity.this, this::initializeContextView); + } else if (statusQuoted != null) { + statusList.add(statusQuoted); + int statusCount = statusList.size(); + statusDraftList.get(0).quote_id = statusQuoted.id; + //StatusDraftList at this point should only have one element + statusList.addAll(statusDraftList); + composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility, editMessageId); + composeAdapter.manageDrafts = this; + composeAdapter.promptDraftListener = this; + LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this); + binding.recyclerView.setLayoutManager(mLayoutManager); + binding.recyclerView.setAdapter(composeAdapter); } else { //Compose without replying statusList.addAll(statusDraftList); diff --git a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonStatusesService.java b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonStatusesService.java index cf8613b48..7ecb050ff 100644 --- a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonStatusesService.java +++ b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonStatusesService.java @@ -59,7 +59,9 @@ public interface MastodonStatusesService { @Field("sensitive") Boolean sensitive, @Field("spoiler_text") String spoiler_text, @Field("visibility") String visibility, - @Field("language") String language + @Field("language") String language, + @Field("quote_id") String quote_id, + @Field("content_type") String content_type ); @GET("statuses/{id}/source") diff --git a/app/src/main/java/app/fedilab/android/client/entities/api/Status.java b/app/src/main/java/app/fedilab/android/client/entities/api/Status.java index 585eccec2..e6a030745 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/api/Status.java +++ b/app/src/main/java/app/fedilab/android/client/entities/api/Status.java @@ -48,6 +48,10 @@ public class Status implements Serializable, Cloneable { public String spoiler_text; @SerializedName("text") public String text; + @SerializedName("quote_id") + public String quote_id; + @SerializedName("content_type") + public String content_type; @SerializedName("visibility") public String visibility; @SerializedName("language") @@ -76,6 +80,8 @@ public class Status implements Serializable, Cloneable { public String content; @SerializedName("reblog") public Status reblog; + @SerializedName("quote") + public Status quote; @SerializedName("application") public App application; @SerializedName("account") @@ -111,7 +117,7 @@ public class Status implements Serializable, Cloneable { public transient boolean setCursorToEnd = false; public transient int cursorPosition = 0; public transient boolean submitted = false; - public transient boolean spoilerChecked = false; + public boolean spoilerChecked = false; public Filter filteredByApp; public transient Spannable contentSpan; public transient Spannable contentSpoilerSpan; diff --git a/app/src/main/java/app/fedilab/android/helper/Helper.java b/app/src/main/java/app/fedilab/android/helper/Helper.java index dc415779c..cb02fdb93 100644 --- a/app/src/main/java/app/fedilab/android/helper/Helper.java +++ b/app/src/main/java/app/fedilab/android/helper/Helper.java @@ -226,6 +226,7 @@ public class Helper { public static final String ARG_STATUS_DRAFT_ID = "ARG_STATUS_DRAFT_ID"; public static final String ARG_STATUS_REPLY = "ARG_STATUS_REPLY"; public static final String ARG_MENTION_BOOSTER = "ARG_MENTION_BOOSTER"; + public static final String ARG_QUOTED_MESSAGE = "ARG_QUOTED_MESSAGE"; public static final String ARG_STATUS_REPLY_ID = "ARG_STATUS_REPLY_ID"; public static final String ARG_ACCOUNT = "ARG_ACCOUNT"; public static final String ARG_ACCOUNT_ID = "ARG_ACCOUNT_ID"; diff --git a/app/src/main/java/app/fedilab/android/helper/MediaHelper.java b/app/src/main/java/app/fedilab/android/helper/MediaHelper.java index 8a45fdb0b..352075b65 100644 --- a/app/src/main/java/app/fedilab/android/helper/MediaHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/MediaHelper.java @@ -432,6 +432,8 @@ public class MediaHelper { } int orientation = getImageOrientation(uri, context.getContentResolver()); int scaledImageSize = 1024; + final int maxRetry = 3; + int retry = 0; do { FileOutputStream outputStream = new FileOutputStream(targetedFile); decodeBitmapInputStream = context.getContentResolver().openInputStream(uri); @@ -452,7 +454,8 @@ public class MediaHelper { reorientedBitmap.compress(format, 100, outputStream); reorientedBitmap.recycle(); scaledImageSize /= 2; - } while (targetedFile.length() > getMaxSize(targetedFile.length())); + retry++; + } while (targetedFile.length() > getMaxSize(targetedFile.length()) && retry < maxRetry); } catch (Exception e) { e.printStackTrace(); if (decodeBitmapInputStream != null) { diff --git a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java index 49021fcc7..26cb125d9 100644 --- a/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/SpannableHelper.java @@ -52,6 +52,7 @@ import androidx.lifecycle.ViewModelStoreOwner; import androidx.preference.PreferenceManager; import com.bumptech.glide.Glide; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; @@ -289,10 +290,10 @@ public class SpannableHelper { @Override public void onLongClick(View view) { Context mContext = view.getContext(); - AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext); + MaterialAlertDialogBuilder materialAlertDialogBuilder = new MaterialAlertDialogBuilder(mContext); PopupLinksBinding popupLinksBinding = PopupLinksBinding.inflate(LayoutInflater.from(context)); - dialogBuilder.setView(popupLinksBinding.getRoot()); - AlertDialog alertDialog = dialogBuilder.create(); + materialAlertDialogBuilder.setView(popupLinksBinding.getRoot()); + AlertDialog alertDialog = materialAlertDialogBuilder.create(); alertDialog.show(); String finalURl = newURL; String uniqueUrl = newURL.endsWith("…") ? newURL : newURL + "…"; diff --git a/app/src/main/java/app/fedilab/android/jobs/ComposeWorker.java b/app/src/main/java/app/fedilab/android/jobs/ComposeWorker.java index de565b876..05ed092b9 100644 --- a/app/src/main/java/app/fedilab/android/jobs/ComposeWorker.java +++ b/app/src/main/java/app/fedilab/android/jobs/ComposeWorker.java @@ -221,10 +221,10 @@ public class ComposeWorker extends Worker { if (dataPost.scheduledDate == null) { if (dataPost.statusEditId == null) { statusCall = mastodonStatusesService.createStatus(null, dataPost.token, statuses.get(i).text, attachmentIds, poll_options, poll_expire_in, - poll_multiple, poll_hide_totals, in_reply_to_status, statuses.get(i).sensitive, statuses.get(i).spoilerChecked ? statuses.get(i).spoiler_text : null, statuses.get(i).visibility.toLowerCase(), language); + poll_multiple, poll_hide_totals, statuses.get(i).quote_id == null ? in_reply_to_status : null, statuses.get(i).sensitive, statuses.get(i).spoilerChecked ? statuses.get(i).spoiler_text : null, statuses.get(i).visibility.toLowerCase(), language, statuses.get(i).quote_id, statuses.get(i).content_type); } else { //Status is edited statusCall = mastodonStatusesService.updateStatus(null, dataPost.token, dataPost.statusEditId, statuses.get(i).text, attachmentIds, poll_options, poll_expire_in, - poll_multiple, poll_hide_totals, in_reply_to_status, statuses.get(i).sensitive, statuses.get(i).spoilerChecked ? statuses.get(i).spoiler_text : null, statuses.get(i).visibility.toLowerCase(), language); + poll_multiple, poll_hide_totals, statuses.get(i).quote_id == null ? in_reply_to_status : null, statuses.get(i).sensitive, statuses.get(i).spoilerChecked ? statuses.get(i).spoiler_text : null, statuses.get(i).visibility.toLowerCase(), language); } try { Response statusResponse = statusCall.execute(); @@ -285,7 +285,7 @@ public class ComposeWorker extends Worker { } } else { Call scheduledStatusCall = mastodonStatusesService.createScheduledStatus(null, dataPost.token, statuses.get(i).text, attachmentIds, poll_options, poll_expire_in, - poll_multiple, poll_hide_totals, in_reply_to_status, statuses.get(i).sensitive, statuses.get(i).spoilerChecked ? statuses.get(i).spoiler_text : null, statuses.get(i).visibility.toLowerCase(), dataPost.scheduledDate, statuses.get(i).language); + poll_multiple, poll_hide_totals, statuses.get(i).quote_id == null ? in_reply_to_status : null, statuses.get(i).sensitive, statuses.get(i).spoilerChecked ? statuses.get(i).spoiler_text : null, statuses.get(i).visibility.toLowerCase(), dataPost.scheduledDate, statuses.get(i).language); try { Response statusResponse = scheduledStatusCall.execute(); diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/ComposeAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/ComposeAdapter.java index 332bb58e0..0a6b23bac 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/ComposeAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/ComposeAdapter.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.Drawable; @@ -99,6 +100,7 @@ import java.util.regex.Pattern; import app.fedilab.android.BaseMainActivity; import app.fedilab.android.R; import app.fedilab.android.activities.ComposeActivity; +import app.fedilab.android.activities.MainActivity; import app.fedilab.android.client.entities.api.Attachment; import app.fedilab.android.client.entities.api.Emoji; import app.fedilab.android.client.entities.api.EmojiInstance; @@ -1273,9 +1275,40 @@ public class ComposeAdapter extends RecyclerView.Adapter { + AlertDialog.Builder builder = new AlertDialog.Builder(context, Helper.dialogStyle()); + builder.setTitle(context.getString(R.string.post_format)); + Resources res = context.getResources(); + String[] formatArr = res.getStringArray(R.array.SET_POST_FORMAT); + int selection = 0; + String defaultFormat = sharedpreferences.getString(context.getString(R.string.SET_POST_FORMAT) + account.user_id + account.instance, "text/plain"); + for (String format : formatArr) { + if (statusDraft.content_type != null && statusDraft.content_type.equalsIgnoreCase(format)) { + break; + } else if (statusDraft.content_type == null && defaultFormat.equalsIgnoreCase(format)) { + break; + } + selection++; + } + builder.setSingleChoiceItems(formatArr, selection, null); + builder.setPositiveButton(R.string.validate, (dialog, which) -> { + int selectedPosition = ((AlertDialog) dialog).getListView().getCheckedItemPosition(); + statusDraft.content_type = formatArr[selectedPosition]; + notifyItemChanged(holder.getLayoutPosition()); + dialog.dismiss(); + }); + builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); + builder.create().show(); + }); + } else { + holder.binding.buttonTextFormat.setVisibility(View.GONE); + } holder.binding.buttonEmojiOne.setOnClickListener(v -> { InputMethodManager imm = (InputMethodManager) context.getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(holder.binding.buttonEmojiOne.getWindowToken(), 0); @@ -1414,6 +1447,7 @@ public class ComposeAdapter extends RecyclerView.Adapter { if (holder.binding.contentSpoiler.getVisibility() == View.VISIBLE) { statusDraft.spoilerChecked = false; diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/ReactionAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/ReactionAdapter.java index 19bdec57a..91048d2db 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/ReactionAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/ReactionAdapter.java @@ -32,6 +32,7 @@ import app.fedilab.android.R; import app.fedilab.android.client.entities.api.Reaction; import app.fedilab.android.databinding.DrawerReactionBinding; import app.fedilab.android.helper.Helper; +import app.fedilab.android.helper.ThemeHelper; import app.fedilab.android.viewmodel.mastodon.AnnouncementsVM; import app.fedilab.android.viewmodel.pleroma.ActionsVM; @@ -74,6 +75,7 @@ public class ReactionAdapter extends RecyclerView.Adapter boolean confirmFav = sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_VALIDATION_FAV), false); boolean confirmBoost = sharedpreferences.getBoolean(context.getString(R.string.SET_NOTIF_VALIDATION), true); boolean fullAttachement = sharedpreferences.getBoolean(context.getString(R.string.SET_FULL_PREVIEW), false); - boolean displayBookmark = sharedpreferences.getBoolean(context.getString(R.string.SET_DISPLAY_BOOKMARK), true); - boolean displayTranslate = sharedpreferences.getBoolean(context.getString(R.string.SET_DISPLAY_TRANSLATE), false); + boolean displayBookmark = sharedpreferences.getBoolean(context.getString(R.string.SET_DISPLAY_BOOKMARK) + MainActivity.currentUserID + MainActivity.currentInstance, true); + boolean displayTranslate = sharedpreferences.getBoolean(context.getString(R.string.SET_DISPLAY_TRANSLATE) + MainActivity.currentUserID + MainActivity.currentInstance, false); boolean displayCounters = sharedpreferences.getBoolean(context.getString(R.string.SET_DISPLAY_COUNTER_FAV_BOOST), false); boolean removeLeftMargin = sharedpreferences.getBoolean(context.getString(R.string.SET_REMOVE_LEFT_MARGIN), false); + boolean extraFeatures = sharedpreferences.getBoolean(context.getString(R.string.SET_EXTAND_EXTRA_FEATURES) + MainActivity.currentUserID + MainActivity.currentInstance, false); + boolean displayQuote = sharedpreferences.getBoolean(context.getString(R.string.SET_DISPLAY_QUOTES) + MainActivity.currentUserID + MainActivity.currentInstance, true); + boolean displayReactions = sharedpreferences.getBoolean(context.getString(R.string.SET_DISPLAY_REACTIONS) + MainActivity.currentUserID + MainActivity.currentInstance, true); if (removeLeftMargin) { LinearLayoutCompat.MarginLayoutParams p = (LinearLayoutCompat.MarginLayoutParams) holder.binding.spoiler.getLayoutParams(); @@ -438,6 +441,60 @@ public class StatusAdapter extends RecyclerView.Adapter String loadMediaType = sharedpreferences.getString(context.getString(R.string.SET_LOAD_MEDIA_TYPE), "ALWAYS"); + if (statusToDeal.quote != null) { + holder.binding.quotedMessage.cardviewContainer.setCardElevation((int) Helper.convertDpToPixel(5, context)); + holder.binding.quotedMessage.dividerCard.setVisibility(View.GONE); + holder.binding.quotedMessage.cardviewContainer.setStrokeWidth((int) Helper.convertDpToPixel(1, context)); + holder.binding.quotedMessage.cardviewContainer.setOnClickListener(v -> holder.binding.quotedMessage.statusContent.callOnClick()); + holder.binding.quotedMessage.statusContent.setOnTouchListener((view, motionEvent) -> { + if (motionEvent.getAction() == MotionEvent.ACTION_UP && !view.hasFocus()) { + try { + view.requestFocus(); + } catch (Exception ignored) { + } + } + return false; + }); + holder.binding.quotedMessage.statusContent.setOnClickListener(v -> { + if (status.isFocused || v.getTag() == SpannableHelper.CLICKABLE_SPAN) { + if (v.getTag() == SpannableHelper.CLICKABLE_SPAN) { + v.setTag(null); + } + return; + } + Intent intent = new Intent(context, ContextActivity.class); + intent.putExtra(Helper.ARG_STATUS, statusToDeal.quote); + context.startActivity(intent); + }); + holder.binding.quotedMessage.cardviewContainer.setStrokeColor(ThemeHelper.getAttColor(context, R.attr.colorPrimary)); + holder.binding.quotedMessage.statusContent.setText( + statusToDeal.quote.getSpanContent(context, + new WeakReference<>(holder.binding.quotedMessage.statusContent), null), + TextView.BufferType.SPANNABLE); + MastodonHelper.loadPPMastodon(holder.binding.quotedMessage.avatar, statusToDeal.quote.account); + if (statusToDeal.quote.account != null) { + holder.binding.quotedMessage.displayName.setText( + statusToDeal.quote.account.getSpanDisplayName(context, + new WeakReference<>(holder.binding.quotedMessage.displayName)), + TextView.BufferType.SPANNABLE); + holder.binding.quotedMessage.username.setText(String.format("@%s", statusToDeal.quote.account.acct)); + } + + if (statusToDeal.quote.spoiler_text != null && !statusToDeal.quote.spoiler_text.trim().isEmpty()) { + holder.binding.quotedMessage.spoiler.setVisibility(View.VISIBLE); + holder.binding.quotedMessage.spoiler.setText( + statusToDeal.quote.getSpanSpoiler(context, + new WeakReference<>(holder.binding.quotedMessage.spoiler), null), + TextView.BufferType.SPANNABLE); + } else { + holder.binding.quotedMessage.spoiler.setVisibility(View.GONE); + holder.binding.quotedMessage.spoiler.setText(null); + } + holder.binding.quotedMessage.cardviewContainer.setVisibility(View.VISIBLE); + } else { + holder.binding.quotedMessage.cardviewContainer.setVisibility(View.GONE); + } + if (currentAccount != null && currentAccount.api == Account.API.PLEROMA) { if (status.pleroma != null && status.pleroma.emoji_reactions != null && status.pleroma.emoji_reactions.size() > 0) { holder.binding.layoutReactions.getRoot().setVisibility(View.VISIBLE); @@ -498,8 +555,7 @@ public class StatusAdapter extends RecyclerView.Adapter int paddingDp = (int) (paddingPixel * density); builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()); builder.setTitle(R.string.insert_emoji); - - if (emojis != null && emojis.size() > 0 && emojis.get(BaseMainActivity.currentInstance) != null) { + if (emojis != null && emojis.size() > 0) { GridView gridView = new GridView(context); gridView.setAdapter(new EmojiAdapter(emojis.get(BaseMainActivity.currentInstance))); gridView.setNumColumns(5); @@ -508,9 +564,6 @@ public class StatusAdapter extends RecyclerView.Adapter String url = emojis.get(BaseMainActivity.currentInstance).get(index).url; String static_url = emojis.get(BaseMainActivity.currentInstance).get(index).static_url; boolean alreadyAdded = false; - if (status.pleroma == null || status.pleroma.emoji_reactions == null) { - return; - } for (Reaction reaction : status.pleroma.emoji_reactions) { if (reaction.name.compareTo(emojiStr) == 0 && reaction.me) { alreadyAdded = true; @@ -553,9 +606,21 @@ public class StatusAdapter extends RecyclerView.Adapter int truncate_toots_size = sharedpreferences.getInt(context.getString(R.string.SET_TRUNCATE_TOOTS_SIZE), 0); - if (currentAccount != null && currentAccount.api == Account.API.PLEROMA) { - holder.binding.statusAddCustomEmoji.setVisibility(View.VISIBLE); - holder.binding.statusEmoji.setVisibility(View.VISIBLE); + if (extraFeatures) { + if (displayQuote) { + holder.binding.actionButtonQuote.setVisibility(View.VISIBLE); + } else { + holder.binding.actionButtonQuote.setVisibility(View.GONE); + } + if (displayReactions) { + holder.binding.statusAddCustomEmoji.setVisibility(View.VISIBLE); + holder.binding.statusEmoji.setVisibility(View.VISIBLE); + } else { + holder.binding.statusAddCustomEmoji.setVisibility(View.GONE); + holder.binding.statusEmoji.setVisibility(View.GONE); + } + + } holder.binding.actionButtonFavorite.pressOnTouch(false); @@ -611,7 +676,7 @@ public class StatusAdapter extends RecyclerView.Adapter } } - if (statusToDeal.card != null && (display_card || statusToDeal.isFocused)) { + if (statusToDeal.card != null && (display_card || statusToDeal.isFocused) && statusToDeal.quote_id == null) { if (statusToDeal.card.width > statusToDeal.card.height) { holder.binding.cardImageHorizontal.setVisibility(View.VISIBLE); holder.binding.cardImageVertical.setVisibility(View.GONE); @@ -951,6 +1016,11 @@ public class StatusAdapter extends RecyclerView.Adapter holder.binding.statusAddCustomEmoji.getLayoutParams().width = (int) (normalSize * scaleIcon); holder.binding.statusAddCustomEmoji.getLayoutParams().height = (int) (normalSize * scaleIcon); holder.binding.statusAddCustomEmoji.requestLayout(); + + holder.binding.actionButtonQuote.getLayoutParams().width = (int) (normalSize * scaleIcon); + holder.binding.actionButtonQuote.getLayoutParams().height = (int) (normalSize * scaleIcon); + holder.binding.actionButtonQuote.requestLayout(); + holder.binding.statusEmoji.getLayoutParams().width = (int) (normalSize * scaleIcon); holder.binding.statusEmoji.getLayoutParams().height = (int) (normalSize * scaleIcon); holder.binding.actionButtonMore.getLayoutParams().width = (int) (normalSize * scaleIcon); @@ -1172,7 +1242,7 @@ public class StatusAdapter extends RecyclerView.Adapter holder.binding.mediaContainer.setVisibility(View.GONE); } else { holder.binding.statusContent.setVisibility(View.VISIBLE); - if (statusToDeal.card != null && (display_card || statusToDeal.isFocused)) { + if (statusToDeal.card != null && statusToDeal.quote_id == null && (display_card || statusToDeal.isFocused)) { holder.binding.card.setVisibility(View.VISIBLE); } else { holder.binding.card.setVisibility(View.GONE); @@ -1903,6 +1973,11 @@ public class StatusAdapter extends RecyclerView.Adapter CrossActionHelper.doCrossAction(context, CrossActionHelper.TypeOfCrossAction.REPLY_ACTION, null, statusToDeal); return true; }); + holder.binding.actionButtonQuote.setOnClickListener(v -> { + Intent intent = new Intent(context, ComposeActivity.class); + intent.putExtra(Helper.ARG_QUOTED_MESSAGE, statusToDeal); + context.startActivity(intent); + }); holder.binding.actionButtonReply.setOnClickListener(v -> { if (remote) { Toasty.info(context, context.getString(R.string.retrieve_remote_status), Toasty.LENGTH_SHORT).show(); @@ -2286,6 +2361,7 @@ public class StatusAdapter extends RecyclerView.Adapter if (theme_icons_color != -1) { Helper.changeDrawableColor(context, holder.binding.actionButtonReply, theme_icons_color); Helper.changeDrawableColor(context, holder.binding.statusAddCustomEmoji, theme_icons_color); + Helper.changeDrawableColor(context, holder.binding.actionButtonQuote, theme_icons_color); Helper.changeDrawableColor(context, holder.binding.statusEmoji, theme_icons_color); Helper.changeDrawableColor(context, holder.binding.actionButtonMore, theme_icons_color); Helper.changeDrawableColor(context, R.drawable.ic_round_star_24, theme_icons_color); diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentExtraFeaturesSettings.java b/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentExtraFeaturesSettings.java new file mode 100644 index 000000000..985faf95e --- /dev/null +++ b/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentExtraFeaturesSettings.java @@ -0,0 +1,142 @@ +package app.fedilab.android.ui.fragment.settings; +/* Copyright 2022 Thomas Schneider + * + * This file is a part of Fedilab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Fedilab; if not, + * see . */ + +import android.content.SharedPreferences; +import android.os.Bundle; + +import androidx.preference.ListPreference; +import androidx.preference.PreferenceFragmentCompat; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreferenceCompat; + +import app.fedilab.android.R; +import app.fedilab.android.activities.MainActivity; +import app.fedilab.android.helper.Helper; + +public class FragmentExtraFeaturesSettings extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { + + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.pref_extra_features); + createPref(); + } + + private void createPref() { + + getPreferenceScreen().removeAll(); + addPreferencesFromResource(R.xml.pref_extra_features); + PreferenceScreen preferenceScreen = getPreferenceScreen(); + SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); + SwitchPreferenceCompat SET_EXTAND_EXTRA_FEATURES = findPreference(getString(R.string.SET_EXTAND_EXTRA_FEATURES)); + if (SET_EXTAND_EXTRA_FEATURES != null) { + boolean checked = sharedpreferences.getBoolean(getString(R.string.SET_EXTAND_EXTRA_FEATURES) + MainActivity.currentUserID + MainActivity.currentInstance, false); + SET_EXTAND_EXTRA_FEATURES.setChecked(checked); + } + SwitchPreferenceCompat SET_DISPLAY_BOOKMARK = findPreference(getString(R.string.SET_DISPLAY_BOOKMARK)); + if (SET_DISPLAY_BOOKMARK != null) { + boolean checked = sharedpreferences.getBoolean(getString(R.string.SET_DISPLAY_BOOKMARK) + MainActivity.currentUserID + MainActivity.currentInstance, true); + SET_DISPLAY_BOOKMARK.setChecked(checked); + } + SwitchPreferenceCompat SET_DISPLAY_TRANSLATE = findPreference(getString(R.string.SET_DISPLAY_TRANSLATE)); + if (SET_DISPLAY_TRANSLATE != null) { + boolean checked = sharedpreferences.getBoolean(getString(R.string.SET_DISPLAY_TRANSLATE) + MainActivity.currentUserID + MainActivity.currentInstance, false); + SET_DISPLAY_TRANSLATE.setChecked(checked); + } + + SwitchPreferenceCompat SET_DISPLAY_QUOTES = findPreference(getString(R.string.SET_DISPLAY_QUOTES)); + if (SET_DISPLAY_QUOTES != null) { + boolean checked = sharedpreferences.getBoolean(getString(R.string.SET_DISPLAY_QUOTES) + MainActivity.currentUserID + MainActivity.currentInstance, true); + SET_DISPLAY_QUOTES.setChecked(checked); + } + + SwitchPreferenceCompat SET_DISPLAY_REACTIONS = findPreference(getString(R.string.SET_DISPLAY_REACTIONS)); + if (SET_DISPLAY_REACTIONS != null) { + boolean checked = sharedpreferences.getBoolean(getString(R.string.SET_DISPLAY_REACTIONS) + MainActivity.currentUserID + MainActivity.currentInstance, true); + SET_DISPLAY_REACTIONS.setChecked(checked); + } + + ListPreference SET_POST_FORMAT = findPreference(getString(R.string.SET_POST_FORMAT)); + if (SET_POST_FORMAT != null) { + SET_POST_FORMAT.getContext().setTheme(Helper.dialogStyle()); + String format = sharedpreferences.getString(getString(R.string.SET_POST_FORMAT) + MainActivity.currentUserID + MainActivity.currentInstance, "text/plain"); + SET_POST_FORMAT.setValue(format); + } + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (getActivity() != null) { + SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); + SharedPreferences.Editor editor = sharedpreferences.edit(); + if (key.compareToIgnoreCase(getString(R.string.SET_EXTAND_EXTRA_FEATURES)) == 0) { + SwitchPreferenceCompat SET_EXTAND_EXTRA_FEATURES = findPreference(getString(R.string.SET_EXTAND_EXTRA_FEATURES)); + if (SET_EXTAND_EXTRA_FEATURES != null) { + editor.putBoolean(getString(R.string.SET_EXTAND_EXTRA_FEATURES) + MainActivity.currentUserID + MainActivity.currentInstance, SET_EXTAND_EXTRA_FEATURES.isChecked()); + } + } + if (key.compareToIgnoreCase(getString(R.string.SET_DISPLAY_BOOKMARK)) == 0) { + SwitchPreferenceCompat SET_DISPLAY_BOOKMARK = findPreference(getString(R.string.SET_DISPLAY_BOOKMARK)); + if (SET_DISPLAY_BOOKMARK != null) { + editor.putBoolean(getString(R.string.SET_DISPLAY_BOOKMARK) + MainActivity.currentUserID + MainActivity.currentInstance, SET_DISPLAY_BOOKMARK.isChecked()); + } + } + if (key.compareToIgnoreCase(getString(R.string.SET_DISPLAY_TRANSLATE)) == 0) { + SwitchPreferenceCompat SET_DISPLAY_TRANSLATE = findPreference(getString(R.string.SET_DISPLAY_TRANSLATE)); + if (SET_DISPLAY_TRANSLATE != null) { + editor.putBoolean(getString(R.string.SET_DISPLAY_TRANSLATE) + MainActivity.currentUserID + MainActivity.currentInstance, SET_DISPLAY_TRANSLATE.isChecked()); + } + } + if (key.compareToIgnoreCase(getString(R.string.SET_DISPLAY_QUOTES)) == 0) { + SwitchPreferenceCompat SET_DISPLAY_QUOTES = findPreference(getString(R.string.SET_DISPLAY_QUOTES)); + if (SET_DISPLAY_QUOTES != null) { + editor.putBoolean(getString(R.string.SET_DISPLAY_QUOTES) + MainActivity.currentUserID + MainActivity.currentInstance, SET_DISPLAY_QUOTES.isChecked()); + } + } + if (key.compareToIgnoreCase(getString(R.string.SET_DISPLAY_REACTIONS)) == 0) { + SwitchPreferenceCompat SET_DISPLAY_REACTIONS = findPreference(getString(R.string.SET_DISPLAY_REACTIONS)); + if (SET_DISPLAY_REACTIONS != null) { + editor.putBoolean(getString(R.string.SET_DISPLAY_REACTIONS) + MainActivity.currentUserID + MainActivity.currentInstance, SET_DISPLAY_REACTIONS.isChecked()); + } + } + if (key.compareToIgnoreCase(getString(R.string.SET_POST_FORMAT)) == 0) { + ListPreference SET_POST_FORMAT = findPreference(getString(R.string.SET_POST_FORMAT)); + if (SET_POST_FORMAT != null) { + editor.putString(getString(R.string.SET_POST_FORMAT) + MainActivity.currentUserID + MainActivity.currentInstance, SET_POST_FORMAT.getValue()); + } + } + editor.apply(); + } + } + + @Override + public void onResume() { + super.onResume(); + + getPreferenceScreen().getSharedPreferences() + .registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onPause() { + super.onPause(); + getPreferenceScreen().getSharedPreferences() + .unregisterOnSharedPreferenceChangeListener(this); + } + + +} diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentInterfaceSettings.java b/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentInterfaceSettings.java index fcffbfb5c..998db5779 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentInterfaceSettings.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentInterfaceSettings.java @@ -27,9 +27,11 @@ import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.preference.SeekBarPreference; +import androidx.preference.SwitchPreferenceCompat; import app.fedilab.android.BuildConfig; import app.fedilab.android.R; +import app.fedilab.android.activities.MainActivity; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.LogoHelper; import es.dmoral.toasty.Toasty; @@ -67,6 +69,12 @@ public class FragmentInterfaceSettings extends PreferenceFragmentCompat implemen SET_LOGO_LAUNCHER.getContext().setTheme(Helper.dialogStyle()); SET_LOGO_LAUNCHER.setIcon(LogoHelper.getDrawable(SET_LOGO_LAUNCHER.getValue())); } + SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); + SwitchPreferenceCompat SET_EXTAND_EXTRA_FEATURES = findPreference(getString(R.string.SET_EXTAND_EXTRA_FEATURES)); + if (SET_EXTAND_EXTRA_FEATURES != null) { + boolean checked = sharedpreferences.getBoolean(getString(R.string.SET_EXTAND_EXTRA_FEATURES) + MainActivity.currentUserID + MainActivity.currentInstance, false); + SET_EXTAND_EXTRA_FEATURES.setChecked(checked); + } recreate = false; } @@ -81,6 +89,7 @@ public class FragmentInterfaceSettings extends PreferenceFragmentCompat implemen editor.putFloat(getString(R.string.SET_FONT_SCALE), scale); recreate = true; } + if (key.compareToIgnoreCase(getString(R.string.SET_FONT_SCALE_ICON_INT)) == 0) { int progress = sharedPreferences.getInt(getString(R.string.SET_FONT_SCALE_ICON_INT), 110); float scale = (float) (progress) / 100.0f; @@ -94,6 +103,13 @@ public class FragmentInterfaceSettings extends PreferenceFragmentCompat implemen recreate = true; } + if (key.compareToIgnoreCase(getString(R.string.SET_EXTAND_EXTRA_FEATURES)) == 0) { + SwitchPreferenceCompat SET_EXTAND_EXTRA_FEATURES = findPreference(getString(R.string.SET_EXTAND_EXTRA_FEATURES)); + if (SET_EXTAND_EXTRA_FEATURES != null) { + editor.putBoolean(getString(R.string.SET_EXTAND_EXTRA_FEATURES) + MainActivity.currentUserID + MainActivity.currentInstance, SET_EXTAND_EXTRA_FEATURES.isChecked()); + } + recreate = true; + } if (key.compareToIgnoreCase(getString(R.string.SET_LOGO_LAUNCHER)) == 0) { ListPreference SET_LOGO_LAUNCHER = findPreference(getString(R.string.SET_LOGO_LAUNCHER)); if (SET_LOGO_LAUNCHER != null) { diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentSettingsCategories.java b/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentSettingsCategories.java index eb11a00ba..258e32b5a 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentSettingsCategories.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentSettingsCategories.java @@ -121,6 +121,16 @@ public class FragmentSettingsCategories extends PreferenceFragmentCompat { return false; }); } + + Preference pref_category_key_extra_features = findPreference(getString(R.string.pref_category_key_extra_features)); + if (pref_category_key_extra_features != null) { + pref_category_key_extra_features.setOnPreferenceClickListener(preference -> { + NavController navController = Navigation.findNavController(requireActivity(), R.id.fragment_container); + navController.navigate(FragmentSettingsCategoriesDirections.Companion.categoriesToExtraFeatures()); + return false; + }); + } + ActivityResultLauncher permissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { try { diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentTimelinesSettings.java b/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentTimelinesSettings.java index 04fd9e9f8..49867c7f4 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentTimelinesSettings.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/settings/FragmentTimelinesSettings.java @@ -22,8 +22,10 @@ import androidx.preference.ListPreference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreferenceCompat; import app.fedilab.android.R; +import app.fedilab.android.activities.MainActivity; import app.fedilab.android.helper.Helper; public class FragmentTimelinesSettings extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -37,6 +39,7 @@ public class FragmentTimelinesSettings extends PreferenceFragmentCompat implemen private void createPref() { getPreferenceScreen().removeAll(); + SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); addPreferencesFromResource(R.xml.pref_timelines); PreferenceScreen preferenceScreen = getPreferenceScreen(); ListPreference SET_LOAD_MEDIA_TYPE = findPreference(getString(R.string.SET_LOAD_MEDIA_TYPE)); @@ -60,6 +63,16 @@ public class FragmentTimelinesSettings extends PreferenceFragmentCompat implemen preferenceScreen.removePreferenceRecursively("SET_TRANSLATOR_VERSION"); } } + SwitchPreferenceCompat SET_DISPLAY_BOOKMARK = findPreference(getString(R.string.SET_DISPLAY_BOOKMARK)); + if (SET_DISPLAY_BOOKMARK != null) { + boolean checked = sharedpreferences.getBoolean(getString(R.string.SET_DISPLAY_BOOKMARK) + MainActivity.currentUserID + MainActivity.currentInstance, true); + SET_DISPLAY_BOOKMARK.setChecked(checked); + } + SwitchPreferenceCompat SET_DISPLAY_TRANSLATE = findPreference(getString(R.string.SET_DISPLAY_TRANSLATE)); + if (SET_DISPLAY_TRANSLATE != null) { + boolean checked = sharedpreferences.getBoolean(getString(R.string.SET_DISPLAY_TRANSLATE) + MainActivity.currentUserID + MainActivity.currentInstance, false); + SET_DISPLAY_TRANSLATE.setChecked(checked); + } } @Override @@ -67,10 +80,22 @@ public class FragmentTimelinesSettings extends PreferenceFragmentCompat implemen if (getActivity() != null) { SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity()); SharedPreferences.Editor editor = sharedpreferences.edit(); - editor.apply(); if (key.compareToIgnoreCase(getString(R.string.SET_TRANSLATOR)) == 0) { createPref(); } + if (key.compareToIgnoreCase(getString(R.string.SET_DISPLAY_BOOKMARK)) == 0) { + SwitchPreferenceCompat SET_DISPLAY_BOOKMARK = findPreference(getString(R.string.SET_DISPLAY_BOOKMARK)); + if (SET_DISPLAY_BOOKMARK != null) { + editor.putBoolean(getString(R.string.SET_DISPLAY_BOOKMARK) + MainActivity.currentUserID + MainActivity.currentInstance, SET_DISPLAY_BOOKMARK.isChecked()); + } + } + if (key.compareToIgnoreCase(getString(R.string.SET_DISPLAY_TRANSLATE)) == 0) { + SwitchPreferenceCompat SET_DISPLAY_TRANSLATE = findPreference(getString(R.string.SET_DISPLAY_TRANSLATE)); + if (SET_DISPLAY_TRANSLATE != null) { + editor.putBoolean(getString(R.string.SET_DISPLAY_TRANSLATE) + MainActivity.currentUserID + MainActivity.currentInstance, SET_DISPLAY_TRANSLATE.isChecked()); + } + } + editor.apply(); } } diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/StatusesVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/StatusesVM.java index 826283770..bb9c88cfc 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/StatusesVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/StatusesVM.java @@ -186,12 +186,14 @@ public class StatusesVM extends AndroidViewModel { Boolean sensitive, String spoiler_text, String visibility, - String language) { + String language, + String quote_id, + String content_type) { MastodonStatusesService mastodonStatusesService = init(instance); statusMutableLiveData = new MutableLiveData<>(); new Thread(() -> { Call statusCall = mastodonStatusesService.createStatus(idempotency_Key, token, text, media_ids, poll_options, poll_expire_in, - poll_multiple, poll_hide_totals, in_reply_to_id, sensitive, spoiler_text, visibility, language); + poll_multiple, poll_hide_totals, in_reply_to_id, sensitive, spoiler_text, visibility, language, quote_id, content_type); Status status = null; if (statusCall != null) { try { diff --git a/app/src/main/res/drawable/ic_baseline_extension_24.xml b/app/src/main/res/drawable/ic_baseline_extension_24.xml new file mode 100644 index 000000000..bc61292c5 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_extension_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_format_quote_24.xml b/app/src/main/res/drawable/ic_baseline_format_quote_24.xml new file mode 100644 index 000000000..3eb675282 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_format_quote_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_baseline_format_size_24.xml b/app/src/main/res/drawable/ic_baseline_format_size_24.xml new file mode 100644 index 000000000..cae03ba95 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_format_size_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_check_redirect.xml b/app/src/main/res/drawable/ic_check_redirect.xml new file mode 100644 index 000000000..f4ff88703 --- /dev/null +++ b/app/src/main/res/drawable/ic_check_redirect.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_copy_link.xml b/app/src/main/res/drawable/ic_copy_link.xml new file mode 100644 index 000000000..462788122 --- /dev/null +++ b/app/src/main/res/drawable/ic_copy_link.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_full_link.xml b/app/src/main/res/drawable/ic_full_link.xml new file mode 100644 index 000000000..16b494d32 --- /dev/null +++ b/app/src/main/res/drawable/ic_full_link.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_open_external.xml b/app/src/main/res/drawable/ic_open_external.xml new file mode 100644 index 000000000..f7aa3cbb8 --- /dev/null +++ b/app/src/main/res/drawable/ic_open_external.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_share_link.xml b/app/src/main/res/drawable/ic_share_link.xml new file mode 100644 index 000000000..21496e7ae --- /dev/null +++ b/app/src/main/res/drawable/ic_share_link.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/drawer_status.xml b/app/src/main/res/layout/drawer_status.xml index a265701af..7dcc0a61d 100644 --- a/app/src/main/res/layout/drawer_status.xml +++ b/app/src/main/res/layout/drawer_status.xml @@ -394,6 +394,12 @@ + + + + + + + + android:padding="12dp"> - + android:textAlignment="textStart" + app:icon="@drawable/ic_full_link" /> - + android:textAlignment="textStart" + app:icon="@drawable/ic_share_link" /> - + android:textAlignment="textStart" + app:icon="@drawable/ic_open_external" /> - + android:textAlignment="textStart" + app:icon="@drawable/ic_copy_link" /> - + android:textAlignment="textStart" + app:icon="@drawable/ic_check_redirect" /> + diff --git a/app/src/main/res/navigation/nav_graph_settings.xml b/app/src/main/res/navigation/nav_graph_settings.xml index 729f2caf4..4290ad790 100644 --- a/app/src/main/res/navigation/nav_graph_settings.xml +++ b/app/src/main/res/navigation/nav_graph_settings.xml @@ -68,6 +68,14 @@ app:exitAnim="@anim/exit" app:popEnterAnim="@anim/pop_enter" app:popExitAnim="@anim/pop_exit" /> + + + + Vyberte vše, co vyhovuje Odstranit levý okraj Odstranit v časových osách levý okraj, aby se zprávy zobrazovaly kompaktněji + Překladač + Překladač + Klíč pro API překladače + Verze + Verze překladače \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 35dd56bb6..99c71d98e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -18,7 +18,7 @@ E-Mail Konten Nachrichten - Schlagwörter (tags) + Hashtags Speichern Instanz Instanz: mastodon.social @@ -36,7 +36,7 @@ Bestätigen Medien Teilen mit - Geteilt von Fedilab + Geteilt mit Fedilab Antworten Benutzername Entwürfe @@ -61,10 +61,10 @@ Die folgenden Informationen könnten das Profil des Nutzers unvollständig wiedergeben. Emoji einfügen Die App verfügt derzeit nicht über benutzerdefinierte Emojis. - Sind Du sicher, dass Sie @%1$s@%2$s abmelden möchten\? + Bist Du sicher, dass Du Dich von @%1$s@%2$s abmelden möchtest\? Keine Nachrichten zum Anzeigen - Diese Nachricht deinen Favoriten hinzufügen\? + Diese Nachricht Deinen Favoriten hinzufügen\? Diese Nachricht aus Ihren Favoriten entfernen\? Diese Nachricht teilen\? Geteilte Nachricht zurückziehen\? @@ -75,7 +75,7 @@ Kopieren Teilen Erwähnen - Zeitlich begrenzt lautlos schalten + Zeitlich begrenzt stumm schalten Löschen & neu entwerfen Lautlosmodus für dieses Konto aktivieren? @@ -152,17 +152,19 @@ Keine geplanten Nachrichten vorhanden! Geplante Nachricht löschen\? Die Nachricht wurde geplant! - Der geplante Termin muss nach dem aktuellen Zeitpunkt liegen! + Der geplante Termin muss in der Zukunft liegen! - Die Dauer für den Lautlosmodus sollte mehr als eine Minute betragen. - %1$s wurde bis %2$s lautlos geschaltet.\n Du kannst den Lautlosmodus für diesen Nutzer beenden, indem du sein/ihr Profil besuchst. - %1$s ist bis %2$s lautlos geschaltet.\n Hier antippen, um den Lautlosmodus zu beenden. + Die Dauer für die Stummschaltung sollte mehr als eine Minute betragen. + %1$s wurde bis %2$s lautlos geschaltet. +\n Du kannst die Stummschaltung für diese Person beenden, indem Du ihr Profil besuchst. + %1$s ist bis %2$s stumm geschaltet. +\n Hier antippen, um die Stummschaltung zu beenden. Keine Benachrichtigungen hat dich erwähnt hat eine neue Nachricht geschrieben - hat deinen Beitrag geteilt - hat deinen Status favorisiert + hat Deinen Beitrag geteilt + hat Deinen Status favorisiert folgt dir fragte, dir zu folgen Entferne alle Benachrichtigungen? @@ -173,14 +175,14 @@ Fehler beim Laden der Client ID! Konto wurde gesperrt! Das Konto wurde entsperrt! - Nutzer wurde lautlos geschaltet! - Lautlosmodus für dieses Konto aufgehoben! + Nutzer wurde stumm geschaltet! + Stummschaltung für dieses Konto aufgehoben! Du folgst dem Nutzer! Du folgst dem Nutzer nicht mehr! Die Nachricht wurde geteilt! Die Nachricht wird nicht länger geteilt! - Die Nachricht wurde deinen Favoriten hinzugefügt! - Die Nachricht wurde aus deinen Favoriten entfernt! + Die Nachricht wurde Deinen Favoriten hinzugefügt! + Die Nachricht wurde aus Deinen Favoriten entfernt! Es ist ein Fehler aufgetreten! Ein Fehler ist aufgetreten! Die Instanz hat keinen Autorisierungscode gesendet! Der Name der Instanz scheint ungültig zu sein! @@ -191,12 +193,12 @@ Anzahl der Nachrichten pro Ladevorgang GIF Avatare deaktivieren - mir jemand folgt - jemand meinen Beitrag teilt - jemand meinen Beitrag favorisiert - ich erwähnt werde - Benachrichtigen, sobald eine Umfrage beendet ist - Benachrichtigung über neue Beiträge aktivieren + Benachrichtigung wenn mir jemand folgt + Benachrichtigung wenn jemand meinen Beitrag teilt + Benachrichtigung wenn jemand meinen Beitrag favorisiert + Benachrichtigung wenn ich erwähnt werde + Benachrichtigung wenn eine Umfrage beendet ist + Benachrichtigung über neue Beiträge Bestätigungsdialog vor dem Teilen anzeigen Bestätigungsdialog vor dem Favorisieren anzeigen Benachrichtigen? @@ -225,8 +227,8 @@ Folgen Nicht mehr blockieren - Lautlos - Lautlosmodus beenden + Stumm + Stummschaltung beenden Anfrage gesendet folgt dir Ersten Buchstaben bei Antworten groß schreiben @@ -252,7 +254,7 @@ Löschen Listen - Möchtest du diese Liste wirklich dauerhaft löschen? + Möchtest Du diese Liste wirklich dauerhaft löschen\? Zur Liste hinzufügen Liste löschen Neuer Listentitel @@ -260,7 +262,7 @@ Du hast noch keine Listen! %1$s wurde verschoben nach %2$s - Media wurde geladen. Hier klicken zum anzeigen. + Datei wurde geladen. Hier klicken zum Anzeigen. Proxy Proxy aktivieren? @@ -271,7 +273,7 @@ Nachricht-Details beim Teilen hinzufügen Unterstütze die app auf Liberapay Es gibt einen Fehler im regulären Ausdruck! - Es wurden keine Zeitleisten in dieser Instanz gefunden! + Es wurden keine Timelines in dieser Instanz gefunden! Folge Instanz Du folgst dieser Instanz bereits! Partnerschaften @@ -283,13 +285,13 @@ Filter Keine Filter vorhanden. Du kannst durch Klicken auf \"+\" neue Filter erstellen. Schlagwort oder Phrase - Lokale Zeitleiste - Öffentliche Zeitleiste + Startseite + Öffentliche Timeline Benachrichtigungen Unterhaltungen Wird unabhängig vom umgebenen Text oder Inhaltswarnung einer Nachricht verglichen Entfernen anstatt zu verstecken - Gefilterte Nachrichten werden unwiderruflich verschwinden, selbst wenn der Filter später entfernt wurde + Gefilterte Nachrichten werden unwiderruflich verschwinden, selbst wenn der Filter später entfernt wird Wenn das Schlüsselwort oder -phrase nur Buchstaben und Zahlen enthält, wird es nur angewendet werden, wenn es dem ganzen Wort entspricht Ganzes Wort Kontext filtern @@ -309,7 +311,9 @@ Medien Download Klingelton auswählen Zeitfenster aktivieren - Möchtest du %s wirklich sperren?\n\nEs werden keine Inhalte aus dieser Domain in einer öffentlichen Zeitleiste oder in deinen Benachrichtigungen angezeigt. Deine Follower aus dieser Domain werden entfernt. + Möchtest Du %s wirklich sperren\? +\n +\nEs werden keine Inhalte aus dieser Domain in einer öffentlichen Timeline oder in Deinen Benachrichtigungen angezeigt. Deine Follower aus dieser Domain werden entfernt. Blockiere Domäne Die Domäne ist blockiert Rufe entfernten Status ab @@ -323,7 +327,7 @@ Kürze Nachrichten mit mehr als x Zeilen. Null bedeutet deaktiviert. Mehr anzeigen Weniger anzeigen - Dieses Schlagwort existiert bereits! + Dieser Hashtag existiert bereits! Teilen des Beitrags planen Teilen geplant! Nichts geplant! @@ -354,8 +358,8 @@ Pixelfed-Instanz Mastodon-Instanz Irgendwelche davon - Alle von denen - Keine von denen + Alle davon + Keine davon Eines dieser Wörter (durch Leerzeichen getrennt) Alle diese Wörter (durch Leerzeichen getrennt) Wörter zum Filter hinzufügen (durch Leerzeichen getrennt) @@ -368,7 +372,7 @@ Teilen Nachrichten (Server) Nachrichten (Gerät) - Zeitleisten + Timelines Benutzeroberfläche Kontakte Bei der Auswahl der Sicherungsdatei ist ein Problem aufgetreten! @@ -378,8 +382,8 @@ Von der Anwendung blockierte HTTP-Aufrufe Liste der blockierten Aufrufe Senden - Zeitleiste mit Schlagwörtern filtern - Keine Schlagwörter + Timeline mit Hashtags filtern + Keine Hashtags Metadaten abrufen, wenn die URL von anderen Apps geteilt wird Umfrage erstellen @@ -388,22 +392,22 @@ Fertig endet um %s Abstimmen - Eine Umfrage, in der du abgestimmt hast, ist beendet + Eine Umfrage, in der Du abgestimmt hast, ist beendet Eine Ihrer Umfragen wurde beendet Kategorien - Zeitleiste verschieben - Zeitleiste ausblenden - Verwaltung von Zeitleisten + Timeline verschieben + Timeline ausblenden + Verwaltung der Timelines Liste endgültig gelöscht Gefolgte Instanz entfernt - Angeheftetes Schlagwort entfernt + Angehefteter Hashtag entfernt Widerrufen - Hauptzeitleisten können nur ausgeblendet werden! + Haupt-Timelines können nur ausgeblendet werden! Medien immer als sensibel kennzeichnen GNU-Instanz - Schlagwörter in Antworten übernehmen + Hashtags in Antworten übernehmen Lange Drücken, um Medien zu speichern - Schlagwörter verwalten + Hashtags verwalten Anzeigename Emoji Text @@ -445,12 +449,12 @@ Konto erstellt! Dein Konto wurde erfolgreich erstellt! \n -\nDenke daran, deine E-Mail-Adresse innerhalb der nächsten 48 Stunden zu bestätigen. +\nDenke daran, Deine E-Mail-Adresse innerhalb der nächsten 48 Stunden zu bestätigen. \n -\nDu kannst nun dein Konto verbinden, indem du %1$s in das erste Feld schreibst und auf die Schaltfläche Verbinden klickst. +\nDu kannst nun Dein Konto verbinden, indem Du %1$s in das erste Feld schreibst und auf die Schaltfläche Verbinden klickst. \n -\nWichtig: Wenn deine Instanz eine Bestätigung benötigt, erhältst du eine E-Mail, sobald sie geprüft wurde! - Möchtest du die Nachricht als Entwurf speichern? +\nWichtig: Wenn Deine Instanz eine Bestätigung benötigt, erhältst Du eine E-Mail, sobald sie geprüft wurde! + Möchtest Du die Nachricht als Entwurf speichern\? Verwaltung Berichte Ungelöst @@ -469,15 +473,15 @@ Unterbrechen widerrufen Die Anwendung benötigt Zugriff auf die Audioaufzeichnung Sprachnachricht - Innerhalb des Zeitfensters sendet die App Mitteilungen. Du kannst dieses Zeitfenster mit dem richtigen Drehwähler umkehren (d. h. leise). - Vorschauen in Zeitachsen werden nicht beschnitten - Automatisches Einfügen eines Zeilenumbruchs nach der Anweisung den ersten Buchstaben groß zu schreiben + Innerhalb des Zeitfensters sendet die App Benachrichtigungen. Du kannst dieses Zeitfenster mit dem rechten Schieber zurücksetzen (d. h. leise). + Vorschauen in den Timelines werden nicht beschnitten + Automatisches Einfügen eines Zeilenumbruchs nach einer Erwähnung, um den ersten Buchstaben groß zu schreiben Ermöglicht es Inhaltserstellern, den Status ihrer RSS-Feeds zu teilen Verfassen Auswählen Instanz hinzufügen Absturzberichte aktivieren - Wenn aktiviert, wird lokal ein Absturzbericht erstellt. Anschließend kannst du diesen teilen. + Wenn aktiviert, wird ein Absturzbericht erstellt. Anschließend kannst Du diesen teilen. Fedilab ist abgestürzt :( Du kannst mir den Fehlerreport per E-Mail senden. Dies hilft mir bei der Fehlerbehebung:)\n\nDu kannst weitere Inhalte hinzufügen. Danke! Sichtbarkeit @@ -503,37 +507,37 @@ Ihre Umfrage kann keine doppelten Optionen haben! Cache beim Verlassen löschen Der Cache (Medien, zwischengespeicherte Nachrichten, Daten aus dem eingebauten Browser) wird automatisch gelöscht, wenn die Anwendung verlassen wird. - Möchtest du diesem Konto nicht mehr folgen? - Bestätigungsdialog anzeigen, bevor nicht mehr gefolgt wird + Möchtest Du diesem Konto nicht mehr folgen\? + Bestätigungsdialog vor dem Entfolgen anzeigen Medium Nutze eine alternative Benutzeroberfläche für Medium Standard: scribe.rip - Verwenden Du ein Push-Benachrichtigungssystem, um Benachrichtigungen in Echtzeit zu erhalten. + Verwende ein Push-Benachrichtigungs-System, um Benachrichtigungen in Echtzeit zu erhalten. Notizen hinzufügen Notizen für das Konto Erlauben es, große Fotos in kleinere Bilder mit sehr weniger oder vernachlässigbaren Verlust der Qualität des Bildes zu komprimieren. Erlaube das Komprimieren von Videos während die Qualität erhalten bleibt. Sortieren nach Links - Ändern Du die Farbe der Links (URLs, Erwähnungen, Tags, etc.) in Nachrichten - Reblogs Titel + Ändert die Farbe der Links (URLs, Erwähnungen, Hashtags, etc.) in Nachrichten + Titelzeile des geteilten Beitrags Ändern der Farbe des Anzeigenamens oben in den Nachrichten Ändern der Farbe des Benutzernamens am Anfang von Nachrichten - Ändern der Farbe der Kopfzeile für Reblogs + Ändert die Farbe der Kopfzeile von geteilten Beiträgen Beiträge - Hintergrundfarbe der posts in den timelines + Hintergrundfarbe der Beiträge in den Timelines Farben zurücksetzen - Tippen Du hier, um alle Ihre benutzerdefinierten Farben zurückzusetzen + Tippe hier, um all Deine benutzerdefinierten Farben zurückzusetzen Zurücksetzen Symbole - Farbe der unteren Symbole in Zeitleisten + Farbe der unteren Symbole in den Timelines Logo der Instanz Profil bearbeiten Aktion ausführen Übersetzung Textfarbe Ändere die Textfarbe in Nachrichten - Verwenden Du ein benutzerdefiniertes Design + Verwende ein benutzerdefiniertes Design Farbschema Das Theme wurde exportiert Das Design wurde erfolgreich als CSV exportiert @@ -572,9 +576,9 @@ Automatisches Hinzufügen eines Wasserzeichens am unteren Rand von Bildern. Der Text kann für jedes Konto angepasst werden. Keine Dienste gefunden! Du benötigen einen Dienst, um Push-Benachrichtigungen zu erhalten. -\nWeitere Details finden Sie unter %1$s. +\nWeitere Details findest Du unter %1$s. \n -\nDu können Push-Benachrichtigungen auch in den Einstellungen deaktivieren, um diese Nachricht zu ignorieren. +\nDu kannst Push-Benachrichtigungen auch in den Einstellungen deaktivieren, um keine Benachrichtigungen zu erhalten. Dienstanbieter auswählen Fortfahren Diese Instanz scheint nicht gültig zu sein! @@ -589,9 +593,9 @@ Aufnahme anhalten Ich mag es nicht Es ist Spam - Die Nachricht wurde zu deinen Lesezeichen hinzugefügt! - Die Nachricht wurde von deinen Lesezeichen entfernt! - Anzahl der Konten pro Laden + Die Nachricht wurde zu Deinen Lesezeichen hinzugefügt! + Die Nachricht wurde von Deinen Lesezeichen entfernt! + Anzahl der Konten pro Ladevorgang Musik Dieses Feld kann nicht leer sein! YouTube @@ -605,15 +609,15 @@ Andere Anzeige Du willst das nicht sehen\? - Du bist dir bewusst, dass es gegen bestimmte Regeln verstößt + Du bist Dir bewusst, dass es gegen bestimmte Regeln verstößt Es verstößt gegen die Serverregeln Das Thema lässt sich nicht in andere Kategorien einordnen Es ist etwas anderes - Es ist nichts was du sehen möchtest + Es ist nichts was Du sehen möchtest Meldung %1$s Verfügbarkeit: %,.2f %% Zusätzliche Kommentare - Gibt es noch etwas, das wir deiner Meinung nach wissen sollten\? + Gibt es noch etwas, das wir Deiner Meinung nach wissen sollten\? Wähle alle zutreffenden Punkte aus Welche Regeln werden verletzt\? Gibt es Beiträge, die diesen Bericht belegen\? @@ -645,7 +649,7 @@ Benachrichtigungstöne Wähle die Art der Benachrichtigung Themen der Mitwirkenden - Zeitleisten anpassen + Timelines anpassen Ein Thema wählen Weitere Aktionen Wähle ein Thema, das von Mitwirkenden erstellt wurde @@ -654,7 +658,7 @@ Art der Umfrage: Unteres Menü Oberes Menü - Einstellungen zur Kontrolle dessen, was du auf Mastodon siehst: + Einstellungen zur Kontrolle dessen, was Du auf Mastodon siehst: Inhalt verbergen < Benutzerdefiniert Sende Nachricht %d/%d @@ -667,7 +671,7 @@ Sage uns, was es mit diesem Beitrag auf sich hat Stummschalten %1$s Blockieren %1$s - Hallo! Wir laden dich ein, dem Fediverse beizutreten. + Hallo! Wir laden Dich ein, dem Fediverse beizutreten. Bot-Konto Interaktionen Konto auffindbar @@ -675,7 +679,7 @@ Wähle, ob die Basis des Themas dunkel oder hell sein soll Arten der anzuzeigenden Benachrichtigungen Standardmäßige Sichtbarkeit der Nachrichten: - Anzahl an Benachrichtigungen pro Ladezyklus + Anzahl an Benachrichtigungen pro Ladevorgang Nutze eine alternative Benutzeroberfläche für Instagram Instagram Frontend Domain Nutze eine alternative Benutzeroberfläche für Reddit @@ -686,13 +690,13 @@ Das Konto stammt von einem anderen Server. Die anonymisierte Kopie des Berichts auch dorthin senden\? Wähle die beste Übereinstimmung Entfolge %1$s - Du folgst diesem Konto. Um die Beiträge nicht mehr in deiner Home-Timeline zu sehen, entfolge ihm. - Du wirst die Beiträge nicht mehr sehen. Du können dir immer noch folgen und deine Beiträge sehen und wissen nicht, dass sie stummgeschaltet sind. + Du folgst diesem Konto. Um die Beiträge nicht mehr auf Deiner Startseite zu sehen, entfolge ihm. + Du wirst ihre Beiträge nicht mehr sehen. Sie können Dir immer noch folgen und Deine Beiträge sehen und wissen nicht, dass sie stummgeschaltet sind. Du wirst ihre Beiträge nicht mehr sehen. Sie werden Deine Beiträge nicht sehen und Dir nicht mehr folgen können. Sie werden erkennen können, dass sie blockiert sind. - Boosten + Geteilte Beiträge Aktualisierungen Anderer Folgende - Auch geboostet von: + Auch geteilt von: Entfolgen bestätigen "Auch favorisiert von: " Ich bin ein Moderator @@ -729,8 +733,8 @@ Einstellungen exportieren Vorschaubilder für Medien laden Timelines anzeigen - Anzahl der neuen Nachrichten in der Timeline werden in einer Blase in der Registerkarte angezeigt - Position in der Timeline merken + Die Anzahl neuer Nachrichten in den Timelines wird in der Registerkarte angezeigt + Position in den Timelines merken Timelines werden zwischengespeichert, um die Anwendung zu beschleunigen. Zwischengespeicherte Nachricht Antwort @@ -765,7 +769,7 @@ Originalnachricht öffnen Benachrichtigungsabrufzeit Hole Benachrichtigungen - Wenn aktiv, hat die App nur eine einzelne Bar für die Timelines + Wenn aktiv, hat die App nur eine Anzeigeleiste für alle Timelines Datei konnte nicht hochgeladen werden! Hole Benachrichtigungen alle: Maximale Anzahl an Zeichen setzen @@ -773,15 +777,15 @@ Push-Dienst Die App konnte kein Token abrufen Nachricht bearbeiten - Angepinnte Zeitleisten löschen\? + Angepinnte Timelines löschen\? Bericht eingereicht Datenschutz-Bestimmungen - Die angepinnte Zeitleiste entfernen\? - Bist Du sicher, dass diese Zeitleiste nicht mehr angepinnt sein soll\? + Die angepinnte Timeline entfernen\? + Bist Du sicher, dass diese Timeline nicht mehr angepinnt sein soll\? Geblockte Domänen %1$s bearbeitet %2$s Domäne freigeben - Du hast keine geblockten Domänen + Du hast keine Domänen geblockt Sicher, dass Du %1$s wieder freigeben willst\? Vorschläge Nicht interessiert @@ -794,7 +798,7 @@ Konto abgelehnt Konto genehmigt Meldung - Medien in Benachrichtigungen für Reblogs und Favoriten werden angezeigt + Medien in Benachrichtigungen für geteilte Beiträge und Favoriten werden angezeigt Übersetzung in eine bestimmte Sprache erzwingen. Wähle den ersten Wert, um auf Geräteeinstellungen zurückzusetzen Nachrichten-Verlauf Bearbeitet am %1$s @@ -821,15 +825,15 @@ Konto stummgeschaltet App neu starten\? Neustart - Du solltest die App neu starten um die Änderungen anzuwenden. - Du folgst bisher keinen Tags! - Tag nicht mehr folgen - Bist Du sicher dass Du diesem Tag nicht mehr folgen willst\? + Du musst die App neu starten um die Änderungen anzuwenden. + Du folgst bisher keinen Hashtags! + Hashtag nicht mehr folgen + Bist Du sicher dass Du diesem Hashtag nicht mehr folgen willst\? Nicht mehr folgen - Tag folgen - Schreibe den Tag dem Du folgen willst - Gefolgte Tags - Tag folgen + Hashtag folgen + Schreibe den Hashtag, dem Du folgen möchtest + Gefolgten Hashtags + Hashtag folgen Falls aktiv wird die App alle zusammenhängenden Benachrichtigungen einklappen Liste bearbeiten Profile @@ -840,14 +844,14 @@ Mit Warnung verstecken Vollständig verstecken Den gefilterten Inhalt komplett verstecken und so verhalten als ob dieser nie existiert hätte - Start und Listen + Startseite und Listen Titel Schlagwort oder Satz Schlagwort löschen Schlagwort hinzufügen Gefiltert: %1$s Trotzdem anzeigen - Zeitleiste löschen + Timeline löschen Angemeldet Neue Registrierung Eine Benutzer hat sich registriert @@ -862,7 +866,7 @@ Neue Meldung Verstecke den gefilterten Inhalt hinter einer Warnung die den Titel des Filters enthält Aktion filtern - Wähle die Aktion aus die durchgeführt werden soll wenn ein Beitrag Deinem Filter entspricht + Wähle die Aktion aus die durchgeführt werden soll, wenn ein Beitrag dem Filter entspricht Hinzufügen des Kontos zur Liste fehlgeschlagen! Benachrichtigungen behalten Neue Meldung (Moderatoren) @@ -872,7 +876,7 @@ Anmeldestatus Sprachen in der Auswahl Erlaube die Liste der Sprachen in der Auswahl beim Verfassen einer Nachricht zu reduzieren. - Bezeichnung des Tags ist nicht zulässig! + Bezeichnung des Hashtags ist nicht zulässig! Schweregrad Medien ablehnen Mediendateien ablehnen @@ -893,45 +897,50 @@ Kommentiere die Domainbeschränkung für die Öffentlichkeit, wenn die Verteilung der Liste der Domainbeschränkunden aktiviert ist. Listen sortieren Bericht senden - Den Tag %1$s wirklich stummschalten\? - Maximaler Einzug in Threads + Den Hashtag %1$s wirklich stummschalten\? + Maximale Einzugtiefe in den Beiträgen Konto wieder aktiviert Status Ermöglicht benutzerdefinierte Farben für Designs. Dynamische Farben Farbton dem Farbschema des persönlichen Hintergrunds anpassen. - Standard helles Design - Standard dunkles Design + Helles Standard-Design + Dunkles Standard-Design Wähle den Modus für das Design Farben anpassen - Wenn aktiviert, sind die Beiträge in der Timeline schattiert und erhöht. - Helles Thema anpassen - Gestattet, einige Elemente des hellen Themas zu personalisieren. - Dunkles Thema anpassen - Gestattet, einige Elemente des dunklen Themas zu personalisieren. + Wenn aktiviert, werden Beiträge in der Timeline schattiert und erhaben dargestellt. + Helles Design anpassen + Gestattet, einige Elemente des hellen Designs zu personalisieren. + Dunkles Design anpassen + Gestattet, einige Elemente des dunklen Designs zu personalisieren. Eigene Farben auswählen Hell - Eigene Farben Dunkel - Eigene Farben Entfernte Konversation anzeigen Die Konversation begann auf Deiner Instanz! - Die Anwendung hat keine entfernten Nachrichten gefunden. - Tag stummschalten - Anpinnen des Tags aufheben - Stummschaltung des Tags aufheben + Die Anwendung hat die entfernte Nachricht nicht gefunden. + Hashtag stummschalten + Anpinnen des Hashtags aufheben + Stummschaltung des Hashtags aufheben Bitte später nochmal versuchen. - Tag anpinnen - Alle Konten werden in der Timeline der Startseite stumm geschaltet. + Hashtag anpinnen + Alle Konten auf der Startseite stumm schalten. Alle Benutzer auf der Startseite stummschalten Daten importieren - Gruppiere geteilte Nachrichten in der Timeline der Startseite + Gruppiere geteilte Beiträge auf der Startseite Alle stummschalten Konten verwalten Auf Startseite stummgeschaltete Nutzer - Tag entfolgen - Für Startseite stummschalten + Hashtag entfolgen + Auf der Startseite stummschalten Stummschaltung auf der Startseite aufheben - Entfernt den linken Rand in den Timelines, um die Nachricht kompakter zu machen + Entfernt den linken Rand in den Timelines, um Nachrichten kompakter darzustellen Übersetzungs-Knopf immer anzeigen Kartenansicht Entferne linken Rand + Version + Übersetzungsdienst API-Schlüssel + Übersetzungsdienst + Übersetzungsdienst-Version + Übersetzungsdienst \ No newline at end of file diff --git a/app/src/main/res/values-gd/strings.xml b/app/src/main/res/values-gd/strings.xml index 3ef98dd5a..5d2af3453 100644 --- a/app/src/main/res/values-gd/strings.xml +++ b/app/src/main/res/values-gd/strings.xml @@ -145,4 +145,51 @@ Chan eil teachdaireachd air an sgeideil ri sealltainn ann! A bheil thu airson an teachdaireachd sgeidealaichte a sguabadh às\? Chaidh an teachdaireachd a chur air an sgeideal! + Ìoc! Thachair mearachd! + A bheil thu airson gach brath a sguabadh às\? + Chaidh gach brath a sguabadh às! + Chan eil an cunntas ’ga bhacadh tuilleadh! + Chaidh an cunntas a mhùthadh! + Chan eil an cunntas ’ga mhùchadh tuilleadh! + Chaidh an cunntas a leantainn! + Chan eil an cunntas ’ga leantainn tuilleadh! + Àireamh de theachdaireachdan anns gach luchdadh + Àireamh de chunntasan anns gach luchdadh + Cuir avataran GIF à comas + A bheil thu airson brath fhaighinn\? + Brathan tostach + Crìoch-ùine na susbaint frionasaich (diogan, is ciall dha 0 gum bi e dheth) + Faigh brath nuair bhrosnaicheas cuideigin am post agad + Faigh brath nuair as annsa le cuideigin am post agad + Faigh brath nuair bheir cuideigin iomradh ort + Faigh brath nuair a thàinig cunntas-bheachd gu crìoch + Feumaidh ceann-latha an sgeideil a bhith nas anmoiche na an uair an-dràsta! + Feumaidh ùine a’ mhùchaidh a bhith nas fhaide na aon mhionaid. + Chaidh %1$s a mhùchadh gu ruige %2$s. +\n ’S urrainn dhut an cunntas seo a dhì-mhùchadh o dhuilleag na pròifil aca. + Chaidh %1$s a mùchadh gu ruige %2$s. +\n Thoir gnogag an-seo gus an cunntas a dhì-mhùchadh. + Chan eil brath ri shealltainn ann + Luchd-leantainn + Cha b’ urrainn dhuinn ID a’ chliant fhaighinn! + Chaidh an cunntas a bhacadh! + Chaidh an teachdaireachd a bhrosnachadh! + Chan eil an teachdaireachd ’ga brosnachadh tuilleadh! + Chaidh an teachdaireachd a chur ris na h-annsachdan agad! + Chaidh an teachdaireachd a thoirt air falbh o na h-annsachdan agad! + Chaidh an teachdaireachd a chur ris na comharran-lìn agad! + Chaidh an teachdaireachd a thoirt air falbh on na comharran-lìn agad! + Thachair mearachd! Cha do thill an t-ionstans còd dearbhaidh! + Tha coltas nach eil àrainn an ionstans dligheach! + Thachair mearachd a ghearradh leum o chunntas gu cunntas! + Thachair mearachd rè an luirg! + Cha ghabh gnìomh a ghabhail + Thachair mearachd rè an eadar-theangachaidh! + Àireamh de bhrathan anns gach luchdadh + Faigh brath nuair a lean cuideigin thu + Faigh brath airson postaichean ùra + Seall còmhradh dearbhaidh mus dèan thu brosnachadh + Seall còmhradh dearbhaidh mus cuir thu rud ris na h-annsachdan + Crìoch-ùine nan tuairisgeulan mheadhnan (diogan, is ciall dha 0 gum bi e dheth) + Co-roinneadh gnàthaichte \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index cb127f48d..2e549a744 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -66,7 +66,7 @@ Nenhuma mensagem para exibir Adicionar esta mensagem aos seus favoritos\? Remover esta mensagem dos seus favoritos\? - Dar boost\? + Dar boost nesta mensagem\? Desfazer boost\? Silenciar Bloquear @@ -93,9 +93,9 @@ Excluir este toot? Excluir & rascunhar este toot? - Favoritos - Adicionar aos favoritos - Remover dos favoritos + Salvos + Salvar + Remover dos Salvos Toot foi salvo! Toot foi removido dos Salvos! @@ -257,7 +257,7 @@ Remover Listas - Tem certeza de que deseja excluir permanentemente esta lista? + Você tem certeza que deseja excluir permanentemente esta lista\? Adicionar à lista Excluir lista Nome da nova lista @@ -314,9 +314,9 @@ Baixar mídia Selecionar toque Ativar definição de momento - Tem certeza que deseja bloquear %s\? + Você tem certeza que deseja bloquear %s\? \n -\nVocê não verá nenhum conteúdo dessa instância em nenhuma linha do tempo pública ou em suas notificações. Seus seguidores dessa instância serão removidos. +\nVocê não verá nenhum conteúdo dessa instância em nenhuma timeline pública ou em suas notificações. Seus seguidores dessa instância serão removidos. Bloquear instância Instância bloqueada Obtendo status remoto @@ -528,30 +528,30 @@ Alterar a cor do cabeçalho para reblogs Publicações Cor de fundo das publicações nas cronologias - Repor cores - Toque aqui para repor todas as suas cores personalizadas - Reset - Icons + Redefinir cores + Toque aqui para redefinir todas as suas cores personalizadas + Redefinir + Ícones Cor dos ícones inferiores nas linhas do tempo Logo da instância Editar Perfil Faça uma ação Tradução - Text color + Cor do texto Alterar a cor do texto nas mensagens Use um tema personalizado Personalização O tema foi exportado O tema foi exportado com sucesso em CSV - Import a theme + Importar um tema Toque aqui para importar um tema exportado previamente - Export the theme + Exportar o tema Toque aqui para exportar o tema atual Ocorreu um erro ao selecionar o arquivo do tema Número de usuários Número de status Número de instâncias - End in %s + Termina em %s Esta instância não está disponível em https://instances.social Exibir link completo Partilhar link @@ -664,4 +664,56 @@ Nova denúncia Mostrar mesmo assim Personalizar cores + Política de Privacidade + Carregar mais mensagens… + Quais regras estão sendo violadas\? + Traduzir Mensagens + Buscar notificações a cada: + Permite personalizar alguns elementos nas mensagens para o tema escuro. + É outra coisa + Bloquear %1$s + Comentários adicionais + Você deseja sair sem salvar a imagem\? + Sempre mostrar o botão de salvar + Idioma das mensagens + É spam + Viola as regras do servidor + Deixar de seguir %1$s + Exportar configurações + Você está ciente de que isso quebra regras específicas + Tempo de busca de notificações + Editar mensagem + Respostas não listadas + Limpar cache + Sempre mostrar o botão de traduzir + Tipo de enquete: + Duração da enquete: + A mensagem foi enviada! + Toque aqui para atualizar a enquete + Anúncio · %1$s - %2$s + Excluir cache + Usar o idioma padrão do sistema + Remover margem esquerda + Remova a margem esquerda nas linhas do tempo para tornar as mensagens mais compactas + Versão do tradutor + Definir cores personalizadas + Permite definir cores personalizadas para os temas. + Links maliciosos, engajamento falso ou respostas repetitivas + Aqui estão suas opções para controlar o que você vê no Mastodon: + Versão + Diz respeito apenas a respostas \"públicas\". Quando ativado, suas respostas terão automaticamente a visibilidade \"não listada\" em vez de \"pública\" + Você tem certeza que deseja excluir o cache\? Se você tiver rascunhos com mídia, a mídia anexada será perdida. + Importar configurações + \"O Mastodon não é um site único como o Twitter ou o Facebook, é uma rede de milhares de comunidades operadas por diferentes organizações e indivíduos que fornecem uma experiência de mídia social perfeita.\" + Remover timeline fixada\? + Você tem certeza que deseja desbloquear %1$s\? + Limpar todas as notificações + OIá! Convidamos você a se juntar ao Fediverso. + Não possui uma conta\? + Exibir todas as categorias + Você tem certeza que deseja excluir todas as notificações\? Essa ação não pode ser desfeita. + Marcar todas as notificações como lidas + Junte-se ao Fediverso + Você tem certeza que deseja desafixar essa timeline\? + Excluir as timelines fixadas\? \ No newline at end of file diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index ca7a283c2..712ab75be 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -937,4 +937,9 @@ Hesapları yönet Sol kenar boşluğunu kaldır Mesajları daha sıkı hale getirmek için zaman çizelgelerindeki sol kenar boşluğunu kaldır + Çevirmen + Çevirmen sürümü + Çevirmen + Çevirmen API anahtarı + Sürüm \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b04300af8..9e929584c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -761,6 +761,15 @@ BrainCrash Mastalab + + + text/plain + text/html + text/markdown + text/bbcode + text/x.misskeymarkdown + + Always Wifi only @@ -1419,7 +1428,12 @@ SET_FILTER_REGEX_PUBLIC SET_NOTIF_VALIDATION SET_DISPLAY_BOOKMARK + SET_DISPLAY_QUOTES + SET_DISPLAY_REACTIONS + SET_DISPLAY_TRANSLATE + SET_POST_FORMAT + SET_TRANSLATOR SET_TRANSLATOR_VERSION @@ -1429,6 +1443,7 @@ SET_NOTIF_VALIDATION_FAV SET_DISPLAY_COUNTER_FAV_BOOST SET_REMOVE_LEFT_MARGIN + SET_EXTAND_EXTRA_FEATURES SET_INNER_MARKER SET_NOTIF_SILENT @@ -1955,6 +1970,8 @@ pref_category_theming pref_category_administration pref_category_languages + pref_category_key_extra_features + pref_export_settings pref_import_settings Export settings @@ -2147,4 +2164,14 @@ Translator API key Version Translator version + Extra features + By enabling that option the app will display extra features. This feature is done for social softwares like Pleroma, Akkoma or Glitch Social + Icons visibility + You can safely hide these icons at the bottom to have more space. They are also in the submenu. + Post format + Post format + Icons for extra features + If your instance does not accept some extra features, you can hide these icons + Display the \"Quote\" button + Display \"Reactions\" buttons \ No newline at end of file diff --git a/app/src/main/res/xml/pref_categories.xml b/app/src/main/res/xml/pref_categories.xml index 3d2669c56..826f560c5 100644 --- a/app/src/main/res/xml/pref_categories.xml +++ b/app/src/main/res/xml/pref_categories.xml @@ -70,6 +70,13 @@ app:key="@string/pref_category_key_languages" /> + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/pref_interface.xml b/app/src/main/res/xml/pref_interface.xml index f00bf82e5..55b5f58ec 100644 --- a/app/src/main/res/xml/pref_interface.xml +++ b/app/src/main/res/xml/pref_interface.xml @@ -28,6 +28,7 @@ app:summary="@string/set_remove_left_margin" app:title="@string/set_remove_left_margin_title" /> +