From f531a90b41ae071373da2005529b9a9861ba8625 Mon Sep 17 00:00:00 2001 From: Grishka Date: Fri, 2 Sep 2022 11:21:28 +0300 Subject: [PATCH] Better editing --- mastodon/build.gradle | 6 +++- .../statuses/GetStatusSourceText.java | 18 ++++++++++++ .../android/fragments/ComposeFragment.java | 28 +++++++++++++++++-- .../displayitems/HeaderStatusDisplayItem.java | 24 ++++++++++++++-- 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/GetStatusSourceText.java diff --git a/mastodon/build.gradle b/mastodon/build.gradle index 26e6f2fd2..0691e1d5d 100644 --- a/mastodon/build.gradle +++ b/mastodon/build.gradle @@ -9,7 +9,7 @@ android { applicationId "org.joinmastodon.android" minSdk 23 targetSdk 31 - versionCode 39 + versionCode 40 versionName "1.1.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -47,6 +47,10 @@ android { setRoot "src/appcenter" } } + lintOptions{ + checkReleaseBuilds false + abortOnError false + } } dependencies { diff --git a/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/GetStatusSourceText.java b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/GetStatusSourceText.java new file mode 100644 index 000000000..f1dd895e3 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/api/requests/statuses/GetStatusSourceText.java @@ -0,0 +1,18 @@ +package org.joinmastodon.android.api.requests.statuses; + +import org.joinmastodon.android.api.AllFieldsAreRequired; +import org.joinmastodon.android.api.MastodonAPIRequest; +import org.joinmastodon.android.model.BaseModel; + +public class GetStatusSourceText extends MastodonAPIRequest{ + public GetStatusSourceText(String id){ + super(HttpMethod.GET, "/statuses/"+id+"/source", Response.class); + } + + @AllFieldsAreRequired + public static class Response extends BaseModel{ + public String id; + public String text; + public String spoilerText; + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ComposeFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ComposeFragment.java index 05c311997..5504f6a58 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ComposeFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ComposeFragment.java @@ -178,6 +178,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr private boolean attachmentsErrorShowing; private Status editingStatus; + private boolean pollChanged; + private boolean creatingView; @Override public void onCreate(Bundle savedInstanceState){ @@ -233,6 +235,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr @Override public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ + creatingView=true; emojiKeyboard=new CustomEmojiPopupKeyboard(getActivity(), customEmojis, instanceDomain); emojiKeyboard.setListener(this::onCustomEmojiClick); @@ -328,7 +331,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr spoilerBtn.setSelected(true); }else if(editingStatus!=null && !TextUtils.isEmpty(editingStatus.spoilerText)){ spoilerEdit.setVisibility(View.VISIBLE); - spoilerEdit.setText(editingStatus.spoilerText); + spoilerEdit.setText(getArguments().getString("sourceSpoiler", editingStatus.spoilerText)); spoilerBtn.setSelected(true); } @@ -354,6 +357,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr autocompleteView.setVisibility(View.GONE); mainEditTextWrap.addView(autocompleteView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(178), Gravity.TOP)); + creatingView=false; + return view; } @@ -488,7 +493,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr } if(savedInstanceState==null){ if(editingStatus!=null){ - mainEditText.setText(initialText=HtmlParser.strip(editingStatus.content)); + initialText=getArguments().getString("sourceText", ""); + mainEditText.setText(initialText); mainEditText.setSelection(mainEditText.length()); if(!editingStatus.mediaAttachments.isEmpty()){ attachmentsView.setVisibility(View.VISIBLE); @@ -596,6 +602,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr if(opt.edit.length()>0) nonEmptyPollOptionsCount++; } + if(publishButton==null) + return; publishButton.setEnabled((trimmedCharCount>0 || !attachments.isEmpty()) && charCount<=charLimit && uploadingAttachment==null && failedAttachments.isEmpty() && queuedAttachments.isEmpty() && (pollOptions.isEmpty() || nonEmptyPollOptionsCount>1)); } @@ -693,6 +701,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr } private boolean hasDraft(){ + if(editingStatus!=null){ + if(!mainEditText.getText().toString().equals(initialText)) + return true; + List existingMediaIDs=editingStatus.mediaAttachments.stream().map(a->a.id).collect(Collectors.toList()); + if(!existingMediaIDs.equals(attachments.stream().map(a->a.serverAttachment.id).collect(Collectors.toList()))) + return true; + return pollChanged; + } boolean pollFieldsHaveContent=false; for(DraftPollOption opt:pollOptions) pollFieldsHaveContent|=opt.edit.length()>0; @@ -1021,7 +1037,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr pollOptionsView.startDragging(option.view); return true; }); - option.edit.addTextChangedListener(new SimpleTextWatcher(e->updatePublishButtonState())); + option.edit.addTextChangedListener(new SimpleTextWatcher(e->{ + if(!creatingView) + pollChanged=true; + updatePublishButtonState(); + })); option.edit.setFilters(new InputFilter[]{new InputFilter.LengthFilter(instance.configuration!=null && instance.configuration.polls!=null && instance.configuration.polls.maxCharactersPerOption>0 ? instance.configuration.polls.maxCharactersPerOption : 50)}); pollOptionsView.addView(option.view); @@ -1041,6 +1061,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr private void onSwapPollOptions(int oldIndex, int newIndex){ pollOptions.add(newIndex, pollOptions.remove(oldIndex)); updatePollOptionHints(); + pollChanged=true; } private void showPollDurationMenu(){ @@ -1064,6 +1085,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr default -> throw new IllegalStateException("Unexpected value: "+item.getItemId()); }; pollDurationView.setText(getString(R.string.compose_poll_duration, pollDurationStr=item.getTitle().toString())); + pollChanged=true; return true; }); menu.show(); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java index 511109f2b..ad44a7b13 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/displayitems/HeaderStatusDisplayItem.java @@ -21,6 +21,7 @@ import android.widget.Toast; import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.R; import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships; +import org.joinmastodon.android.api.requests.statuses.GetStatusSourceText; import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.ComposeFragment; @@ -137,10 +138,29 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{ Account account=item.user; int id=menuItem.getItemId(); if(id==R.id.edit){ - Bundle args=new Bundle(); + final Bundle args=new Bundle(); args.putString("account", item.parentFragment.getAccountID()); args.putParcelable("editStatus", Parcels.wrap(item.status)); - Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args); + if(TextUtils.isEmpty(item.status.content) && TextUtils.isEmpty(item.status.spoilerText)){ + Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args); + }else{ + new GetStatusSourceText(item.status.id) + .setCallback(new Callback<>(){ + @Override + public void onSuccess(GetStatusSourceText.Response result){ + args.putString("sourceText", result.text); + args.putString("sourceSpoiler", result.spoilerText); + Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args); + } + + @Override + public void onError(ErrorResponse error){ + error.showToast(item.parentFragment.getActivity()); + } + }) + .wrapProgress(item.parentFragment.getActivity(), R.string.loading, true) + .exec(item.parentFragment.getAccountID()); + } }else if(id==R.id.delete){ UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{}); }else if(id==R.id.mute){