diff options
author | Thomas <tschneider.ac@gmail.com> | 2022-12-30 18:12:09 +0100 |
---|---|---|
committer | Thomas <tschneider.ac@gmail.com> | 2022-12-30 18:12:09 +0100 |
commit | c3006080bacfc1548e3435837d387dc7cd0ae014 (patch) | |
tree | 442428a233fea48c2cc61bf506b84ddb0887b107 | |
parent | 5766bfce32665a4467952a9dba0cff99fbb6e423 (diff) | |
parent | 12fae6059a860fc4cb770185c7cdd8b6c51a3870 (diff) |
Merge branch 'develop'3.13.3
44 files changed, 927 insertions, 199 deletions
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,5 +1,10 @@ [ { + "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", "note": "Changed:\n- Hidden media smaller with preview images\n\nFixed:\n- Issue with Media for Android 11+\n- Crash when not setting a translation key\n- Fix DeepL for API pro\n- Crash when visiting a profile with a lot of media\n- Home muted accounts not working without filters\n- Animated custom emoji not displayed" 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<app.fedilab.android.client.entities.api.Account> accountCall = mastodonAccountsService.verify_credentials(MainActivity.currentToken); + if (accountCall != null) { + try { + retrofit2.Response<app.fedilab.android.client.entities.api.Account> 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<Status> 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<Status> 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<Status> statusResponse = statusCall.execute(); @@ -285,7 +285,7 @@ public class ComposeWorker extends Worker { } } else { Call<ScheduledStatus> 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<ScheduledStatus> 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<RecyclerView.ViewHolder Status statusDraft = statusList.get(position); ComposeViewHolder holder = (ComposeViewHolder) viewHolder; + boolean extraFeatures = sharedpreferences.getBoolean(context.getString(R.string.SET_EXTAND_EXTRA_FEATURES) + MainActivity.currentUserID + MainActivity.currentInstance, false); holder.binding.buttonEmojiOne.setVisibility(View.VISIBLE); + if (extraFeatures) { + holder.binding.buttonTextFormat.setVisibility(View.VISIBLE); + holder.binding.buttonTextFormat.setOnClickListener(v -> { + 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<RecyclerView.ViewHolder } else { holder.binding.contentSpoiler.setVisibility(View.GONE); } + holder.binding.buttonSensitive.setChecked(statusDraft.spoilerChecked); holder.binding.buttonSensitive.setOnClickListener(v -> { 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<ReactionAdapter.Reacti holder.binding.reactionCount.setText(String.valueOf(reaction.count)); if (reaction.me) { holder.binding.reactionContainer.setBackgroundResource(R.drawable.reaction_voted); + holder.binding.reactionCount.setTextColor(ThemeHelper.getAttColor(context, R.attr.colorOnPrimary)); } else { holder.binding.reactionContainer.setBackgroundResource(R.drawable.reaction_border); } diff --git a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java index be9a5c3d3..8d9661394 100644 --- a/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +++ b/app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java @@ -392,10 +392,13 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 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 (rem |