Reply improvements (#432)

* Refactor ComposeActivity intent. Fix bug with URLs

When user saved toot link was removed from the text field itself,
not only from the text to be saved.

* Show what you reply to

Closes #119
This commit is contained in:
Ivan Kupalov 2017-11-01 21:59:29 +02:00 committed by Konrad Pozniak
commit 62f4837135
10 changed files with 260 additions and 78 deletions

View file

@ -59,6 +59,7 @@ import com.squareup.picasso.Picasso;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import retrofit2.Call;
@ -650,8 +651,10 @@ public class AccountActivity extends BaseActivity implements ActionButtonActivit
// If the account isn't loaded yet, eat the input.
return false;
}
Intent intent = new Intent(this, ComposeActivity.class);
intent.putExtra("mentioned_usernames", new String[] { loadedAccount.username });
Intent intent = new ComposeActivity.IntentBuilder()
.mentionedUsernames(Collections.singleton(loadedAccount.username))
.build(this);
startActivity(intent);
startActivity(intent);
return true;
}

View file

@ -37,6 +37,7 @@ import android.os.Bundle;
import android.os.Environment;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.support.annotation.AttrRes;
import android.support.annotation.LayoutRes;
@ -110,6 +111,7 @@ import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@ -121,7 +123,7 @@ import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ComposeActivity extends BaseActivity implements ComposeOptionsFragment.Listener {
public final class ComposeActivity extends BaseActivity implements ComposeOptionsFragment.Listener {
private static final String TAG = "ComposeActivity"; // logging tag
private static final int STATUS_CHARACTER_LIMIT = 500;
private static final int STATUS_MEDIA_SIZE_LIMIT = 8388608; // 8MiB
@ -130,8 +132,20 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
private static final int PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1;
private static final int COMPOSE_SUCCESS = -1;
private static final int THUMBNAIL_SIZE = 128; // pixels
private static final String SAVED_TOOT_UID_EXTRA = "saved_toot_uid";
private static final String SAVED_TOOT_TEXT_EXTRA = "saved_toot_text";
private static final String SAVED_JSON_URLS_EXTRA = "saved_json_urls";
private static final String IN_REPLY_TO_ID_EXTRA = "in_reply_to_id";
private static final String REPLY_VISIBILITY_EXTRA = "reply_visibilty";
private static final String CONTENT_WARNING_EXTRA = "content_warning";
private static final String MENTIONED_USERNAMES_EXTRA = "netnioned_usernames";
private static final String REPLYING_STATUS_AUTHOR_USERNAME_EXTRA = "replying_author_nickname_extra";
private static final String REPLYING_STATUS_CONTENT_EXTRA = "replying_status_content";
private static TootDao tootDao = TuskyApplication.getDB().tootDao();
private TextView replyTextView;
private TextView replyContentTextView;
private EditTextTyped textEditor;
private LinearLayout mediaPreviewBar;
private View contentWarningBar;
@ -169,6 +183,8 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_compose);
replyTextView = findViewById(R.id.reply_tv);
replyContentTextView = findViewById(R.id.reply_content_tv);
textEditor = findViewById(R.id.compose_edit_field);
mediaPreviewBar = findViewById(R.id.compose_media_preview_bar);
contentWarningBar = findViewById(R.id.compose_content_warning_bar);
@ -275,8 +291,8 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
ArrayList<String> loadedDraftMediaUris = null;
inReplyToId = null;
if (intent != null) {
inReplyToId = intent.getStringExtra("in_reply_to_id");
String replyVisibility = intent.getStringExtra("reply_visibility");
inReplyToId = intent.getStringExtra(IN_REPLY_TO_ID_EXTRA);
String replyVisibility = intent.getStringExtra(REPLY_VISIBILITY_EXTRA);
if (replyVisibility != null && startingVisibility != null) {
// Lowest possible visibility setting in response
@ -291,15 +307,15 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
}
}
mentionedUsernames = intent.getStringArrayExtra("mentioned_usernames");
mentionedUsernames = intent.getStringArrayExtra(MENTIONED_USERNAMES_EXTRA);
if (inReplyToId != null) {
startingHideText = !intent.getStringExtra("content_warning").equals("");
startingHideText = !intent.getStringExtra(CONTENT_WARNING_EXTRA).equals("");
if (startingHideText) {
startingContentWarning = intent.getStringExtra("content_warning");
startingContentWarning = intent.getStringExtra(CONTENT_WARNING_EXTRA);
}
} else {
String contentWarning = intent.getStringExtra("saved_toot_content_warning");
String contentWarning = intent.getStringExtra(CONTENT_WARNING_EXTRA);
if (contentWarning != null) {
startingHideText = !contentWarning.isEmpty();
if (startingHideText) {
@ -309,12 +325,12 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
}
// If come from SavedTootActivity
String savedTootText = intent.getStringExtra("saved_toot_text");
String savedTootText = intent.getStringExtra(SAVED_TOOT_TEXT_EXTRA);
if (!TextUtils.isEmpty(savedTootText)) {
textEditor.append(savedTootText);
}
String savedJsonUrls = intent.getStringExtra("saved_json_urls");
String savedJsonUrls = intent.getStringExtra(SAVED_JSON_URLS_EXTRA);
if (!TextUtils.isEmpty(savedJsonUrls)) {
// try to redo a list of media
loadedDraftMediaUris = new Gson().fromJson(savedJsonUrls,
@ -322,10 +338,30 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
}.getType());
}
int savedTootUid = intent.getIntExtra("saved_toot_uid", 0);
int savedTootUid = intent.getIntExtra(SAVED_TOOT_UID_EXTRA, 0);
if (savedTootUid != 0) {
this.savedTootUid = savedTootUid;
}
if (intent.hasExtra(REPLYING_STATUS_AUTHOR_USERNAME_EXTRA)) {
replyTextView.setVisibility(View.VISIBLE);
String username = intent.getStringExtra(REPLYING_STATUS_AUTHOR_USERNAME_EXTRA);
replyTextView.setText(getString(R.string.replying_to, username));
replyTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (replyContentTextView.getVisibility() != View.VISIBLE) {
replyContentTextView.setVisibility(View.VISIBLE);
} else {
replyContentTextView.setVisibility(View.GONE);
}
}
});
}
if (intent.hasExtra(REPLYING_STATUS_CONTENT_EXTRA)) {
replyContentTextView.setText(intent.getStringExtra(REPLYING_STATUS_CONTENT_EXTRA));
}
}
/* If the currently logged in account is locked, its posts should default to private. This
@ -460,6 +496,8 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
}
}
}
}
@Override
@ -533,19 +571,20 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
if (statusHideText) {
contentWarning = contentWarningEditor.getText().toString();
}
Editable textToSave = textEditor.getEditableText();
/* Discard any upload URLs embedded in the text because they'll be re-uploaded when
* the draft is loaded and replaced with new URLs. */
if (mediaQueued != null) {
for (QueuedMedia item : mediaQueued) {
removeUrlFromEditable(textEditor.getEditableText(), item.uploadUrl);
textToSave = removeUrlFromEditable(textToSave, item.uploadUrl);
}
}
boolean b = saveTheToot(textEditor.getText().toString(), contentWarning);
if (b) {
boolean didSaveSuccessfully = saveTheToot(textToSave.toString(), contentWarning);
if (didSaveSuccessfully) {
Toast.makeText(ComposeActivity.this, R.string.action_save_one_toot, Toast.LENGTH_SHORT)
.show();
}
return b;
return didSaveSuccessfully;
}
private static boolean copyToFile(ContentResolver contentResolver, Uri uri, File file) {
@ -1228,15 +1267,17 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
}
}
private static void removeUrlFromEditable(Editable editable, @Nullable URLSpan urlSpan) {
private static Editable removeUrlFromEditable(Editable editable, @Nullable URLSpan urlSpan) {
if (urlSpan == null) {
return;
return editable;
}
int start = editable.getSpanStart(urlSpan);
int end = editable.getSpanEnd(urlSpan);
SpannableStringBuilder builder = new SpannableStringBuilder(editable);
int start = builder.getSpanStart(urlSpan);
int end = builder.getSpanEnd(urlSpan);
if (start != -1 && end != -1) {
editable.delete(start, end);
builder.delete(start, end);
}
return builder;
}
private void downsizeMedia(final QueuedMedia item) {
@ -1710,4 +1751,105 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFragm
return view;
}
}
public static final class IntentBuilder {
@Nullable
private Integer savedTootUid;
@Nullable
private String savedTootText;
@Nullable
private String savedJsonUrls;
@Nullable
private Collection<String> mentionedUsernames;
@Nullable
private String inReplyToId;
@Nullable
private String replyVisibility;
@Nullable
private String contentWarning;
@Nullable
private Account replyingStatusAuthor;
@Nullable
private String replyingStatusContent;
public IntentBuilder savedTootUid(int uid) {
this.savedTootUid = uid;
return this;
}
public IntentBuilder savedTootText(String savedTootText) {
this.savedTootText = savedTootText;
return this;
}
public IntentBuilder savedJsonUrls(String jsonUrls) {
this.savedJsonUrls = jsonUrls;
return this;
}
public IntentBuilder mentionedUsernames(Collection<String> mentionedUsernames) {
this.mentionedUsernames = mentionedUsernames;
return this;
}
public IntentBuilder inReplyToId(String inReplyToId) {
this.inReplyToId = inReplyToId;
return this;
}
public IntentBuilder replyVisibility(String replyVisibility) {
this.replyVisibility = replyVisibility;
return this;
}
public IntentBuilder contentWarning(String contentWarning) {
this.contentWarning = contentWarning;
return this;
}
public IntentBuilder repyingStatusAuthor(Account author) {
this.replyingStatusAuthor = author;
return this;
}
public IntentBuilder replyingStatusContent(String content) {
this.replyingStatusContent = content;
return this;
}
public Intent build(Context context) {
Intent intent = new Intent(context, ComposeActivity.class);
if (savedTootUid != null) {
intent.putExtra(SAVED_TOOT_UID_EXTRA, (int) savedTootUid);
}
if (savedTootText != null) {
intent.putExtra(SAVED_TOOT_TEXT_EXTRA, savedTootText);
}
if (savedJsonUrls != null) {
intent.putExtra(SAVED_JSON_URLS_EXTRA, savedJsonUrls);
}
if (mentionedUsernames != null) {
String[] usernames = mentionedUsernames.toArray(new String[0]);
intent.putExtra(MENTIONED_USERNAMES_EXTRA, usernames);
}
if (inReplyToId != null) {
intent.putExtra(IN_REPLY_TO_ID_EXTRA, inReplyToId);
}
if (replyVisibility != null) {
intent.putExtra(REPLY_VISIBILITY_EXTRA, replyVisibility);
}
if (contentWarning != null) {
intent.putExtra(CONTENT_WARNING_EXTRA, contentWarning);
}
if (replyingStatusContent != null) {
intent.putExtra(REPLYING_STATUS_CONTENT_EXTRA, replyingStatusContent);
}
if (replyingStatusAuthor != null) {
intent.putExtra(REPLYING_STATUS_AUTHOR_USERNAME_EXTRA,
replyingStatusAuthor.localUsername);
}
return intent;
}
}
}

View file

@ -150,11 +150,12 @@ public class SavedTootActivity extends BaseActivity implements SavedTootAdapter.
@Override
public void click(int position, TootEntity item) {
Intent intent = new Intent(this, ComposeActivity.class);
intent.putExtra("saved_toot_uid", item.getUid());
intent.putExtra("saved_toot_text", item.getText());
intent.putExtra("saved_toot_content_warning", item.getContentWarning());
intent.putExtra("saved_json_urls", item.getUrls());
Intent intent = new ComposeActivity.IntentBuilder()
.savedTootUid(item.getUid())
.savedTootText(item.getText())
.contentWarning(item.getContentWarning())
.savedJsonUrls(item.getUrls())
.build(this);
startActivity(intent);
}
}

View file

@ -26,9 +26,7 @@ import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.text.Spanned;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
@ -103,11 +101,14 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov
mentionedUsernames.add(mention.username);
}
mentionedUsernames.remove(loggedInUsername);
Intent intent = new Intent(getContext(), ComposeActivity.class);
intent.putExtra("in_reply_to_id", inReplyToId);
intent.putExtra("reply_visibility", replyVisibility);
intent.putExtra("content_warning", contentWarning);
intent.putExtra("mentioned_usernames", mentionedUsernames.toArray(new String[0]));
Intent intent = new ComposeActivity.IntentBuilder()
.inReplyToId(inReplyToId)
.replyVisibility(replyVisibility)
.contentWarning(contentWarning)
.mentionedUsernames(mentionedUsernames)
.repyingStatusAuthor(actionableStatus.account)
.replyingStatusContent(actionableStatus.content.toString())
.build(getContext());
startActivityForResult(intent, COMPOSE_RESULT);
}