implement deleting and re-drafting
This commit is contained in:
parent
273c841d9a
commit
3a4d13b1c6
|
@ -22,6 +22,7 @@ import android.text.Layout;
|
|||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
|
@ -53,6 +54,7 @@ import org.joinmastodon.android.MastodonApp;
|
|||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.ProgressListener;
|
||||
import org.joinmastodon.android.api.requests.statuses.CreateStatus;
|
||||
import org.joinmastodon.android.api.requests.statuses.GetStatusByID;
|
||||
import org.joinmastodon.android.api.requests.statuses.UploadAttachment;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
|
@ -83,9 +85,11 @@ import org.joinmastodon.android.ui.views.SizeListenerLinearLayout;
|
|||
import org.parceler.Parcel;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -174,6 +178,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
private Instance instance;
|
||||
private boolean attachmentsErrorShowing;
|
||||
|
||||
public static DraftMediaAttachment redraftAttachment(Attachment att) {
|
||||
DraftMediaAttachment draft=new DraftMediaAttachment();
|
||||
draft.serverAttachment=att;
|
||||
draft.description=att.description;
|
||||
draft.uri=Uri.parse(att.url);
|
||||
return draft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -286,11 +298,18 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
pollDurationView.setOnClickListener(v->showPollDurationMenu());
|
||||
|
||||
pollOptions.clear();
|
||||
if(savedInstanceState!=null && savedInstanceState.containsKey("pollOptions")){
|
||||
ArrayList<String> restoredPollOptions=(savedInstanceState!=null ? savedInstanceState : getArguments())
|
||||
.getStringArrayList("pollOptions");
|
||||
if(restoredPollOptions!=null){
|
||||
if(savedInstanceState==null){
|
||||
// restoring from arguments
|
||||
pollDuration=getArguments().getInt("pollDuration");
|
||||
pollDurationStr=DateUtils.formatElapsedTime(pollDuration); // getResources().getQuantityString(R.plurals.x_hours, pollDuration/3600);
|
||||
}
|
||||
pollBtn.setSelected(true);
|
||||
mediaBtn.setEnabled(false);
|
||||
pollWrap.setVisibility(View.VISIBLE);
|
||||
for(String oldText:savedInstanceState.getStringArrayList("pollOptions")){
|
||||
for(String oldText:restoredPollOptions){
|
||||
DraftPollOption opt=createDraftPollOption();
|
||||
opt.edit.setText(oldText);
|
||||
}
|
||||
|
@ -310,8 +329,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
spoilerBtn.setSelected(true);
|
||||
}
|
||||
|
||||
if(savedInstanceState!=null && savedInstanceState.containsKey("attachments")){
|
||||
ArrayList<Parcelable> serializedAttachments=savedInstanceState.getParcelableArrayList("attachments");
|
||||
ArrayList<Parcelable> serializedAttachments=(savedInstanceState!=null ? savedInstanceState : getArguments())
|
||||
.getParcelableArrayList("attachments");
|
||||
if(serializedAttachments!=null){
|
||||
for(Parcelable a:serializedAttachments){
|
||||
DraftMediaAttachment att=Parcels.unwrap(a);
|
||||
attachmentsView.addView(createMediaAttachmentView(att));
|
||||
|
@ -454,10 +474,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
mainEditText.setText(initialText);
|
||||
mainEditText.setSelection(mainEditText.length());
|
||||
if(!TextUtils.isEmpty(replyTo.spoilerText) && AccountSessionManager.getInstance().isSelf(accountID, replyTo.account)){
|
||||
hasSpoiler=true;
|
||||
spoilerEdit.setVisibility(View.VISIBLE);
|
||||
spoilerEdit.setText(replyTo.spoilerText);
|
||||
spoilerBtn.setSelected(true);
|
||||
insertSpoiler(replyTo.spoilerText);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
@ -470,6 +487,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
mainEditText.setSelection(mainEditText.length());
|
||||
initialText=prefilledText;
|
||||
}
|
||||
String spoilerText=getArguments().getString("spoilerText");
|
||||
if(!TextUtils.isEmpty(spoilerText)) insertSpoiler(spoilerText);
|
||||
ArrayList<Uri> mediaUris=getArguments().getParcelableArrayList("mediaAttachments");
|
||||
if(mediaUris!=null && !mediaUris.isEmpty()){
|
||||
for(Uri uri:mediaUris){
|
||||
|
@ -479,6 +498,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
}
|
||||
}
|
||||
|
||||
private void insertSpoiler(String text) {
|
||||
hasSpoiler=true;
|
||||
if (text!=null) spoilerEdit.setText(text);
|
||||
spoilerEdit.setVisibility(View.VISIBLE);
|
||||
spoilerBtn.setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
|
||||
publishButton=new Button(getActivity());
|
||||
|
@ -547,8 +573,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
if(opt.edit.length()>0)
|
||||
nonEmptyPollOptionsCount++;
|
||||
}
|
||||
publishButton.setEnabled((trimmedCharCount>0 || !attachments.isEmpty()) && charCount<=charLimit && uploadingAttachment==null && failedAttachments.isEmpty() && queuedAttachments.isEmpty()
|
||||
&& (pollOptions.isEmpty() || nonEmptyPollOptionsCount>1));
|
||||
if(publishButton!=null){
|
||||
publishButton.setEnabled((trimmedCharCount>0 || !attachments.isEmpty()) && charCount<=charLimit
|
||||
&& uploadingAttachment==null && failedAttachments.isEmpty() && queuedAttachments.isEmpty()
|
||||
&& (pollOptions.isEmpty() || nonEmptyPollOptionsCount>1));
|
||||
}
|
||||
}
|
||||
|
||||
private void onCustomEmojiClick(Emoji emoji){
|
||||
|
@ -635,8 +664,10 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||
boolean pollFieldsHaveContent=false;
|
||||
for(DraftPollOption opt:pollOptions)
|
||||
pollFieldsHaveContent|=opt.edit.length()>0;
|
||||
return (mainEditText.length()>0 && !mainEditText.getText().toString().equals(initialText)) || !attachments.isEmpty()
|
||||
|| uploadingAttachment!=null || !queuedAttachments.isEmpty() || !failedAttachments.isEmpty() || pollFieldsHaveContent;
|
||||
return getArguments().getBoolean("hasDraft", false)
|
||||
|| (mainEditText.length()>0 && !mainEditText.getText().toString().equals(initialText))
|
||||
|| !attachments.isEmpty() || uploadingAttachment!=null || !queuedAttachments.isEmpty()
|
||||
|| !failedAttachments.isEmpty() || pollFieldsHaveContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.joinmastodon.android.R;
|
|||
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.fragments.ComposeFragment;
|
||||
import org.joinmastodon.android.fragments.ProfileFragment;
|
||||
import org.joinmastodon.android.fragments.report.ReportReasonChoiceFragment;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
|
@ -139,13 +138,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||
if(id==R.id.delete){
|
||||
UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{});
|
||||
}else if(id==R.id.delete_and_redraft) {
|
||||
UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", item.parentFragment.getAccountID());
|
||||
args.putString("prefilledText", HtmlParser.parse(item.status.content, item.status.emojis, item.status.mentions, item.status.tags, item.parentFragment.getAccountID()).toString()); // demo
|
||||
// TODO: restore re-drafted text and attachments
|
||||
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
||||
});
|
||||
UiUtils.confirmDeleteAndRedraftPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{});
|
||||
}else if(id==R.id.mute){
|
||||
UiUtils.confirmToggleMuteUser(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), account, relationship!=null && relationship.muting, r->{});
|
||||
}else if(id==R.id.block){
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
|
@ -44,6 +45,8 @@ import org.joinmastodon.android.api.requests.statuses.DeleteStatus;
|
|||
import org.joinmastodon.android.api.requests.statuses.GetStatusByID;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.events.StatusDeletedEvent;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.fragments.ComposeFragment;
|
||||
import org.joinmastodon.android.fragments.HashtagTimelineFragment;
|
||||
import org.joinmastodon.android.fragments.ProfileFragment;
|
||||
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||
|
@ -53,6 +56,7 @@ import org.joinmastodon.android.model.Relationship;
|
|||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.text.CustomEmojiSpan;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.text.SpacerSpan;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
|
@ -62,6 +66,8 @@ import java.time.Instant;
|
|||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -352,6 +358,60 @@ public class UiUtils{
|
|||
});
|
||||
}
|
||||
|
||||
public static void confirmDeleteAndRedraftPost(Activity activity, String accountID, Status status, Consumer<Status> resultCallback){
|
||||
showConfirmationAlert(activity, R.string.confirm_delete_and_redraft_title, R.string.confirm_delete_and_redraft, R.string.delete_and_redraft, ()->{
|
||||
new DeleteStatus(status.id)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Status result){
|
||||
resultCallback.accept(result);
|
||||
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().deleteStatus(status.id);
|
||||
E.post(new StatusDeletedEvent(status.id, accountID));
|
||||
UiUtils.redraftStatus(status, accountID, activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
error.showToast(activity);
|
||||
}
|
||||
})
|
||||
.wrapProgress(activity, R.string.deleting, false)
|
||||
.exec(accountID);
|
||||
});
|
||||
}
|
||||
|
||||
public static void redraftStatus(Status status, String accountID, Activity activity) {
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putBoolean("hasDraft", true);
|
||||
args.putString("prefilledText", HtmlParser.parse(status.content, status.emojis, status.mentions, status.tags, accountID).toString());
|
||||
args.putString("spoilerText", status.spoilerText);
|
||||
if(status.poll!=null){
|
||||
args.putInt("pollDuration", (int)status.poll.expiresAt.minus(status.createdAt.getEpochSecond(), ChronoUnit.SECONDS).getEpochSecond());
|
||||
ArrayList<String> opts=status.poll.options.stream().map(o -> o.title).collect(Collectors.toCollection(ArrayList::new));
|
||||
args.putStringArrayList("pollOptions", opts);
|
||||
}
|
||||
if(!status.mediaAttachments.isEmpty()){
|
||||
ArrayList<Parcelable> serializedAttachments=status.mediaAttachments.stream()
|
||||
.map(att -> Parcels.wrap(ComposeFragment.redraftAttachment(att)))
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
args.putParcelableArrayList("attachments", serializedAttachments);
|
||||
}
|
||||
Callback<Status> cb=new Callback<>(){
|
||||
@Override public void onError(ErrorResponse error) {
|
||||
onSuccess(null);
|
||||
error.showToast(activity);
|
||||
}
|
||||
@Override public void onSuccess(Status status) {
|
||||
if (status!=null) args.putParcelable("replyTo", Parcels.wrap(status));
|
||||
Nav.go(activity, ComposeFragment.class, args);
|
||||
}
|
||||
};
|
||||
|
||||
if(status.inReplyToId!=null) new GetStatusByID(status.inReplyToId).setCallback(cb).exec(accountID);
|
||||
else cb.onSuccess(null);
|
||||
}
|
||||
|
||||
public static void setRelationshipToActionButton(Relationship relationship, Button button){
|
||||
boolean secondaryStyle;
|
||||
if(relationship.blocking){
|
||||
|
|
|
@ -332,4 +332,10 @@
|
|||
<item quantity="one">%,d Reblog</item>
|
||||
<item quantity="other">%,d Reblogs</item>
|
||||
</plurals>
|
||||
<string name="delete_and_redraft">Löschen und neu erstellen</string>
|
||||
<string name="delete_and_redraft">L</string>
|
||||
<string name="confirm_delete_and_redraft_title">Beitrag löschen und neu erstellen</string>
|
||||
<string name="confirm_delete_and_redraft_title">B</string>
|
||||
<string name="confirm_delete_and_redraft">Bist du dir sicher, dass du den Beitrag löschen und neu erstellen möchtest?</string>
|
||||
<string name="confirm_delete_and_redraft">Bist du dir sicher, dass du den Beitrag löschen möchtest?</string>
|
||||
</resources>
|
||||
|
|
|
@ -126,8 +126,11 @@
|
|||
<string name="action_vote">Vote</string>
|
||||
<string name="tap_to_reveal">Tap to reveal</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="delete_and_redraft">Delete and re-draft</string>
|
||||
<string name="confirm_delete_title">Delete Post</string>
|
||||
<string name="confirm_delete_and_redraft_title">Delete and re-draft Post</string>
|
||||
<string name="confirm_delete">Are you sure you want to delete this post?</string>
|
||||
<string name="confirm_delete_and_redraft">Are you sure you want to delete and re-draft this post?</string>
|
||||
<string name="deleting">Deleting…</string>
|
||||
<string name="notification_channel_audio_player">Audio playback</string>
|
||||
<string name="play">Play</string>
|
||||
|
|
Loading…
Reference in New Issue