From cc5f18beec5198036b89dce571ebc1c8a6301932 Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 23 Aug 2025 17:27:06 +0200 Subject: [PATCH] Quote when composing --- .../mastodon/activities/ComposeActivity.java | 16 ++++++--- .../endpoints/MastodonStatusesService.java | 2 ++ .../client/entities/api/ScheduledStatus.java | 2 ++ .../mastodon/client/entities/api/Source.java | 4 +++ .../mastodon/client/entities/api/Status.java | 3 ++ .../entities/api/params/StatusParams.java | 5 +++ .../mastodon/helper/MastodonHelper.java | 16 +++++++++ .../android/mastodon/jobs/ComposeWorker.java | 4 ++- .../mastodon/ui/drawer/ComposeAdapter.java | 35 ++++++++++++++++--- .../viewmodel/mastodon/StatusesVM.java | 3 +- .../peertube/activities/PeertubeActivity.java | 4 +-- 11 files changed, 80 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/app/fedilab/android/mastodon/activities/ComposeActivity.java b/app/src/main/java/app/fedilab/android/mastodon/activities/ComposeActivity.java index bfd204e7..c95fce1b 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/activities/ComposeActivity.java +++ b/app/src/main/java/app/fedilab/android/mastodon/activities/ComposeActivity.java @@ -156,6 +156,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana private Uri photoFileUri; private ScheduledStatus scheduledStatus; private String visibility; + private String quote_approval_policy; private Account accountMention; private String statusReplyId; private Account mentionBooster; @@ -287,7 +288,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana statusList.addAll(0, context.ancestors); statusList.add(initialStatus); statusList.add(statusDraft.statusDraftList.get(0)); - composeAdapter = new ComposeAdapter(statusList, context.ancestors.size(), account, accountMention, visibility, editMessageId); + composeAdapter = new ComposeAdapter(statusList, context.ancestors.size(), account, accountMention, visibility, quote_approval_policy, editMessageId); composeAdapter.mediaDescriptionCallBack = this; composeAdapter.promptDraftListener = this; composeAdapter.manageDrafts = this; @@ -526,6 +527,10 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana } else if (visibility == null && Helper.getCurrentAccount(ComposeActivity.this) != null && Helper.getCurrentAccount(ComposeActivity.this).mastodon_account != null && Helper.getCurrentAccount(ComposeActivity.this).mastodon_account.source != null) { visibility = Helper.getCurrentAccount(ComposeActivity.this).mastodon_account.source.privacy; } + if (quote_approval_policy == null && Helper.getCurrentAccount(ComposeActivity.this) != null && Helper.getCurrentAccount(ComposeActivity.this).mastodon_account != null && Helper.getCurrentAccount(ComposeActivity.this).mastodon_account.source != null) { + quote_approval_policy = Helper.getCurrentAccount(ComposeActivity.this).mastodon_account.source.quote_authorizations; + } + if(setMentionBooster) { mentionBooster = (Account) b.getSerializable(Helper.ARG_MENTION_BOOSTER); } else { @@ -569,6 +574,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana status.sensitive = scheduledStatus.params.sensitive; status.spoiler_text = scheduledStatus.params.spoiler_text; status.visibility = scheduledStatus.params.visibility; + status.quote_approval_policy = scheduledStatus.params.quote_approval_policy; statuses.add(status); statusDraft.statusDraftList = statuses; } @@ -636,7 +642,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana } int statusCount = statusList.size(); statusList.addAll(statusDraft.statusDraftList); - composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility, editMessageId); + composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility, quote_approval_policy, editMessageId); composeAdapter.mediaDescriptionCallBack = this; composeAdapter.manageDrafts = this; composeAdapter.promptDraftListener = this; @@ -709,7 +715,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana } //StatusDraftList at this point should only have one element statusList.addAll(statusDraftList); - composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility, editMessageId); + composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility, quote_approval_policy, editMessageId); composeAdapter.mediaDescriptionCallBack = this; composeAdapter.manageDrafts = this; composeAdapter.promptDraftListener = this; @@ -724,7 +730,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana 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 = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility, quote_approval_policy, editMessageId); composeAdapter.mediaDescriptionCallBack = this; composeAdapter.manageDrafts = this; composeAdapter.promptDraftListener = this; @@ -734,7 +740,7 @@ public class ComposeActivity extends BaseActivity implements ComposeAdapter.Mana } else { //Compose without replying statusList.addAll(statusDraftList); - composeAdapter = new ComposeAdapter(statusList, 0, account, accountMention, visibility, editMessageId); + composeAdapter = new ComposeAdapter(statusList, 0, account, accountMention, visibility,quote_approval_policy, editMessageId); composeAdapter.mediaDescriptionCallBack = this; composeAdapter.manageDrafts = this; composeAdapter.promptDraftListener = this; diff --git a/app/src/main/java/app/fedilab/android/mastodon/client/endpoints/MastodonStatusesService.java b/app/src/main/java/app/fedilab/android/mastodon/client/endpoints/MastodonStatusesService.java index 0095aea5..87afd568 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/client/endpoints/MastodonStatusesService.java +++ b/app/src/main/java/app/fedilab/android/mastodon/client/endpoints/MastodonStatusesService.java @@ -64,6 +64,8 @@ public interface MastodonStatusesService { @Field("spoiler_text") String spoiler_text, @Field("visibility") String visibility, @Field("language") String language, + @Field("quote_approval_policy") String quote_approval_policy, + @Field("quoted_status_id") String quoted_status_id, @Field("quote_id") String quote_id, @Field("content_type") String content_type, @Field("local_only") Boolean local_only diff --git a/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/ScheduledStatus.java b/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/ScheduledStatus.java index 12e12e5c..de93ddb6 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/ScheduledStatus.java +++ b/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/ScheduledStatus.java @@ -42,6 +42,8 @@ public class ScheduledStatus implements Serializable { public String spoiler_text; @SerializedName("visibility") public String visibility; + @SerializedName("quote_approval_policy") + public String quote_approval_policy; @SerializedName("scheduled_at") public Date scheduled_at; @SerializedName("poll") diff --git a/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/Source.java b/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/Source.java index 6702f815..c7cd1f30 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/Source.java +++ b/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/Source.java @@ -22,6 +22,8 @@ import java.util.List; public class Source implements Serializable { @SerializedName("privacy") public String privacy; + @SerializedName("quote_authorizations") + public String quote_authorizations; @SerializedName("sensitive") public boolean sensitive; @SerializedName("language") @@ -36,6 +38,8 @@ public class Source implements Serializable { public static class SourceParams implements Serializable { @SerializedName("privacy") public String privacy; + @SerializedName("quote_authorizations") + public String quote_authorizations; @SerializedName("sensitive") public boolean sensitive; @SerializedName("language") diff --git a/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/Status.java b/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/Status.java index 251fe42e..6cb1e933 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/Status.java +++ b/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/Status.java @@ -55,10 +55,13 @@ public class Status implements Serializable, Cloneable { public String text; @SerializedName("quote_id") public String quote_id; + @SerializedName("content_type") public String content_type; @SerializedName("visibility") public String visibility; + @SerializedName("quote_approval_policy") + public String quote_approval_policy; @SerializedName("language") public String language; @SerializedName("uri") diff --git a/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/params/StatusParams.java b/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/params/StatusParams.java index 5057f0e2..c8e0e5fc 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/params/StatusParams.java +++ b/app/src/main/java/app/fedilab/android/mastodon/client/entities/api/params/StatusParams.java @@ -33,10 +33,15 @@ public class StatusParams implements Serializable { public String in_reply_to_id; @SerializedName("sensitive") public Boolean sensitive; + @SerializedName("spoiler_text") public String spoiler_text; @SerializedName("visibility") public String visibility; + @SerializedName("quote_approval_policy") + public String quote_approval_policy; + @SerializedName("quoted_status_id") + public String quoted_status_id; @SerializedName("language") public String language; @SerializedName("media_attributes") diff --git a/app/src/main/java/app/fedilab/android/mastodon/helper/MastodonHelper.java b/app/src/main/java/app/fedilab/android/mastodon/helper/MastodonHelper.java index fa744575..c7f84f8f 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/helper/MastodonHelper.java +++ b/app/src/main/java/app/fedilab/android/mastodon/helper/MastodonHelper.java @@ -572,6 +572,22 @@ public class MastodonHelper { HEADER } + public enum quote_visibility { + @SerializedName("PUBLIC") + PUBLIC("public"), + @SerializedName("FOLLOWERS") + FOLLOWERS("followers"), + @SerializedName("NOBODY") + NOBODY("nobody"); + private final String value; + quote_visibility(String value) { + this.value = value; + } + public String getValue() { + return value; + } + } + public enum visibility { @SerializedName("PUBLIC") PUBLIC("public"), diff --git a/app/src/main/java/app/fedilab/android/mastodon/jobs/ComposeWorker.java b/app/src/main/java/app/fedilab/android/mastodon/jobs/ComposeWorker.java index ebcb2416..325f603d 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/jobs/ComposeWorker.java +++ b/app/src/main/java/app/fedilab/android/mastodon/jobs/ComposeWorker.java @@ -261,7 +261,7 @@ 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, 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(), statuses.get(i).language, statuses.get(i).quote_id, statuses.get(i).content_type, statuses.get(i).local_only); + 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(), statuses.get(i).language, statuses.get(i).quote_approval_policy.toLowerCase(), statuses.get(i).quote_id, statuses.get(i).quote_id, statuses.get(i).content_type, statuses.get(i).local_only); } else { //Status is edited StatusParams statusParams = new StatusParams(); statusParams.status = statuses.get(i).text; @@ -277,6 +277,8 @@ public class ComposeWorker extends Worker { statusParams.sensitive = statuses.get(i).sensitive; statusParams.spoiler_text = statuses.get(i).spoilerChecked ? statuses.get(i).spoiler_text : null; statusParams.visibility = statuses.get(i).visibility.toLowerCase(); + statusParams.quoted_status_id = statuses.get(i).quote_id.toLowerCase(); + statusParams.quote_approval_policy = statuses.get(i).quote_approval_policy.toLowerCase(); statusParams.language = statuses.get(i).language; statusParams.media_attributes = media_attributes; statusCall = mastodonStatusesService.updateStatus(null, dataPost.token, diff --git a/app/src/main/java/app/fedilab/android/mastodon/ui/drawer/ComposeAdapter.java b/app/src/main/java/app/fedilab/android/mastodon/ui/drawer/ComposeAdapter.java index b9667b8c..3017c6b6 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/ui/drawer/ComposeAdapter.java +++ b/app/src/main/java/app/fedilab/android/mastodon/ui/drawer/ComposeAdapter.java @@ -167,6 +167,7 @@ public class ComposeAdapter extends RecyclerView.Adapter statusList, int statusCount, BaseAccount account, Account mentionedAccount, String visibility, String editMessageId) { + public ComposeAdapter(List statusList, int statusCount, BaseAccount account, Account mentionedAccount, String visibility, String quote_approval_policy, String editMessageId) { this.statusList = statusList; this.statusCount = statusCount; this.account = account; this.mentionedAccount = mentionedAccount; this.visibility = visibility; + this.quote_approval_policy = quote_approval_policy; this.editMessageId = editMessageId; } @@ -1624,6 +1626,9 @@ public class ComposeAdapter extends RecyclerView.Adapter 0) { @@ -1639,7 +1644,9 @@ public class ComposeAdapter extends RecyclerView.Adapter 0 && position == statusCount && unlistedReplies && statusDraft.visibility.equalsIgnoreCase("public") && statusList.size() > 1) { statusDraft.visibility = "unlisted"; } - + if( statusDraft.quote_approval_policy == null) { //Set a default value + statusDraft.quote_approval_policy = MastodonHelper.quote_visibility.PUBLIC.name(); + } switch (statusDraft.visibility.toLowerCase()) { case "public" -> { holder.binding.buttonVisibility.setIconResource(R.drawable.ic_compose_visibility_public); @@ -1663,6 +1670,24 @@ public class ComposeAdapter extends RecyclerView.Adapter { + holder.binding.buttonQuoteApprovalPolicy.setIconResource(R.drawable.ic_compose_visibility_public); + statusDraft.quote_approval_policy = MastodonHelper.quote_visibility.PUBLIC.name(); + } + case "followers" -> { + holder.binding.buttonQuoteApprovalPolicy.setIconResource(R.drawable.ic_baseline_people_alt_24); + statusDraft.quote_approval_policy = MastodonHelper.quote_visibility.FOLLOWERS.name(); + } + case "nobody" -> { + holder.binding.buttonQuoteApprovalPolicy.setIconResource(R.drawable.ic_baseline_block_24); + statusDraft.quote_approval_policy = MastodonHelper.quote_visibility.NOBODY.name(); + } + } + + + holder.binding.visibilityPanel.setOnTouchListener((view, motionEvent) -> true); holder.binding.buttonCloseAttachmentPanel.setOnClickListener(v -> holder.binding.attachmentChoicesPanel.setVisibility(View.GONE)); holder.binding.buttonVisibility.setOnClickListener(v -> { @@ -1706,17 +1731,17 @@ public class ComposeAdapter extends RecyclerView.Adapter { holder.binding.quoteApprovalPolicyPanel.setVisibility(View.GONE); holder.binding.buttonQuoteApprovalPolicy.setIconResource(R.drawable.ic_baseline_block_24); - // Todo: statusDraft.visibility = nobody + statusDraft.quote_approval_policy = MastodonHelper.quote_visibility.NOBODY.name(); }); holder.binding.buttonQuoteApprovalPolicyFollowersOnly.setOnClickListener(v -> { holder.binding.quoteApprovalPolicyPanel.setVisibility(View.GONE); holder.binding.buttonQuoteApprovalPolicy.setIconResource(R.drawable.ic_baseline_people_alt_24); - // Todo: statusDraft.visibility = followers + statusDraft.quote_approval_policy = MastodonHelper.quote_visibility.FOLLOWERS.name(); }); holder.binding.buttonQuoteApprovalPolicyAnyone.setOnClickListener(v -> { holder.binding.quoteApprovalPolicyPanel.setVisibility(View.GONE); holder.binding.buttonQuoteApprovalPolicy.setIconResource(R.drawable.ic_compose_visibility_public); - // Todo: statusDraft.visibility = public + statusDraft.quote_approval_policy = MastodonHelper.quote_visibility.PUBLIC.name(); }); if (statusDraft.spoilerChecked || statusDraft.spoiler_text != null && !statusDraft.spoiler_text.trim().isEmpty()) { diff --git a/app/src/main/java/app/fedilab/android/mastodon/viewmodel/mastodon/StatusesVM.java b/app/src/main/java/app/fedilab/android/mastodon/viewmodel/mastodon/StatusesVM.java index 29e81627..6ebb3894 100644 --- a/app/src/main/java/app/fedilab/android/mastodon/viewmodel/mastodon/StatusesVM.java +++ b/app/src/main/java/app/fedilab/android/mastodon/viewmodel/mastodon/StatusesVM.java @@ -188,6 +188,7 @@ public class StatusesVM extends AndroidViewModel { String spoiler_text, String visibility, String language, + String quote_approval_policy, String quote_id, String content_type, Boolean local_only) { @@ -195,7 +196,7 @@ public class StatusesVM extends AndroidViewModel { 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, quote_id, content_type, local_only); + poll_multiple, poll_hide_totals, in_reply_to_id, sensitive, spoiler_text, visibility, language, quote_approval_policy, quote_id, quote_id, content_type, local_only); Status status = null; if (statusCall != null) { try { diff --git a/app/src/main/java/app/fedilab/android/peertube/activities/PeertubeActivity.java b/app/src/main/java/app/fedilab/android/peertube/activities/PeertubeActivity.java index 8ee0d0f5..582d1a51 100644 --- a/app/src/main/java/app/fedilab/android/peertube/activities/PeertubeActivity.java +++ b/app/src/main/java/app/fedilab/android/peertube/activities/PeertubeActivity.java @@ -2046,7 +2046,7 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis viewModelComment.comment(ADD_COMMENT, peertube.getId(), null, commentStr).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(ADD_COMMENT, 0, apiResponse1)); } else {//Remote account is posting a message StatusesVM statusesVM = new ViewModelProvider(PeertubeActivity.this).get(StatusesVM.class); - statusesVM.postStatus(currentInstance, currentToken, null, commentStr, null, null, null, null, null, status.id, false, null, "public", null, null, null, null).observe(PeertubeActivity.this, this::manageVIewPostActionsMastodon); + statusesVM.postStatus(currentInstance, currentToken, null, commentStr, null, null, null, null, null, status.id, false, null, "public", null, null, null, null, null).observe(PeertubeActivity.this, this::manageVIewPostActionsMastodon); } binding.addCommentWrite.setText(""); } @@ -2058,7 +2058,7 @@ public class PeertubeActivity extends BasePeertubeActivity implements CommentLis viewModelComment.comment(REPLY, peertube.getId(), comment.getId(), commentView).observe(PeertubeActivity.this, apiResponse1 -> manageVIewPostActions(REPLY, position, apiResponse1)); } else {//Remote account is posting a message StatusesVM statusesVM = new ViewModelProvider(PeertubeActivity.this).get(StatusesVM.class); - statusesVM.postStatus(currentInstance, currentToken, null, commentView, null, null, null, null, null, status.id, false, null, "public", null, null, null, null).observe(PeertubeActivity.this, this::manageVIewPostActionsMastodon); + statusesVM.postStatus(currentInstance, currentToken, null, commentView, null, null, null, null, null, status.id, false, null, "public", null, null, null, null, null).observe(PeertubeActivity.this, this::manageVIewPostActionsMastodon); } binding.addCommentWrite.setText(""); }