diff options
Diffstat (limited to 'app/src/main/java')
16 files changed, 391 insertions, 26 deletions
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 (removeLeftMargin) { LinearLayoutCompat.MarginLayoutParams p = (LinearLayoutCompat.MarginLayoutParams) holder.binding.spoiler.getLayoutParams(); @@ -438,6 +441,60 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> 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<RecyclerView.ViewHolder> 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<RecyclerView.ViewHolder> 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<RecyclerView.ViewHolder> 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<RecyclerView.ViewHolder> } } - 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<RecyclerView.ViewHolder> 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<RecyclerView.ViewHolder> 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<RecyclerView.ViewHolder> 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<RecyclerView.ViewHolder> 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 <http://www.gnu.org/licenses>. */ + +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(); + } + + privat |