From 96d9444e0bbad7574a47b1ef131da7e6cf162a30 Mon Sep 17 00:00:00 2001 From: Vavassor Date: Sun, 5 Mar 2017 19:58:36 -0500 Subject: [PATCH] Fixes crash due to unexpected GIFV attachments. Also when composing a reply it defaults the visibility to the status being replied to. Also, public timeline visibility is no longer in the options list when replying, it never had an effect and was just erroneously left there. --- .../keylesspalace/tusky/ComposeActivity.java | 16 ++++++++++++++-- .../tusky/ComposeOptionsFragment.java | 16 ++++++++++++++-- .../com/keylesspalace/tusky/SFragment.java | 7 +++++++ .../java/com/keylesspalace/tusky/Status.java | 19 +++++++++++++++++-- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java index 5f45a59e1..1d4ad15c3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java @@ -89,6 +89,7 @@ import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Random; @@ -345,6 +346,12 @@ public class ComposeActivity extends BaseActivity { String[] mentionedUsernames = null; if (intent != null) { inReplyToId = intent.getStringExtra("in_reply_to_id"); + String replyVisibility = intent.getStringExtra("reply_visibility"); + if (replyVisibility != null) { + /* Override any remembered visibilty and instead adopt the visibility of the status + * to which this replies. */ + statusVisibility = replyVisibility; + } mentionedUsernames = intent.getStringArrayExtra("mentioned_usernames"); } @@ -363,7 +370,7 @@ public class ComposeActivity extends BaseActivity { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { int left = STATUS_CHARACTER_LIMIT - s.length(); - charactersLeft.setText(Integer.toString(left)); + charactersLeft.setText(String.format(Locale.getDefault(), "%d", left)); } @Override @@ -435,7 +442,7 @@ public class ComposeActivity extends BaseActivity { public void onClick(View v) { ComposeOptionsFragment fragment = ComposeOptionsFragment.newInstance( statusVisibility, statusMarkSensitive, statusHideText, - showMarkSensitive, + showMarkSensitive, inReplyToId != null, new ComposeOptionsFragment.Listener() { @Override public int describeContents() { @@ -498,6 +505,11 @@ public class ComposeActivity extends BaseActivity { @Override protected void onPause() { super.onPause(); + if (inReplyToId != null) { + /* Don't save the visibility setting for replies because they adopt the visibility of + * the status they reply to and that behaviour needs to be kept separate. */ + return; + } SharedPreferences preferences = getSharedPreferences( getString(R.string.preferences_file_key), Context.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeOptionsFragment.java b/app/src/main/java/com/keylesspalace/tusky/ComposeOptionsFragment.java index ca78a8c33..fe9edfdc5 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeOptionsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeOptionsFragment.java @@ -9,6 +9,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.CompoundButton; +import android.widget.RadioButton; import android.widget.RadioGroup; public class ComposeOptionsFragment extends BottomSheetDialogFragment { @@ -21,7 +22,7 @@ public class ComposeOptionsFragment extends BottomSheetDialogFragment { private Listener listener; public static ComposeOptionsFragment newInstance(String visibility, boolean markSensitive, - boolean hideText, boolean showMarkSensitive, Listener listener) { + boolean hideText, boolean showMarkSensitive, boolean isReply, Listener listener) { Bundle arguments = new Bundle(); ComposeOptionsFragment fragment = new ComposeOptionsFragment(); arguments.putParcelable("listener", listener); @@ -29,6 +30,7 @@ public class ComposeOptionsFragment extends BottomSheetDialogFragment { arguments.putBoolean("markSensitive", markSensitive); arguments.putBoolean("hideText", hideText); arguments.putBoolean("showMarkSensitive", showMarkSensitive); + arguments.putBoolean("isReply", isReply); fragment.setArguments(arguments); return fragment; } @@ -45,9 +47,15 @@ public class ComposeOptionsFragment extends BottomSheetDialogFragment { boolean statusMarkSensitive = arguments.getBoolean("markSensitive"); boolean statusHideText = arguments.getBoolean("hideText"); boolean showMarkSensitive = arguments.getBoolean("showMarkSensitive"); + boolean isReply = arguments.getBoolean("isReply"); RadioGroup radio = (RadioGroup) rootView.findViewById(R.id.radio_visibility); - int radioCheckedId = R.id.radio_public; + int radioCheckedId; + if (!isReply) { + radioCheckedId = R.id.radio_public; + } else { + radioCheckedId = R.id.radio_unlisted; + } if (statusVisibility != null) { if (statusVisibility.equals("unlisted")) { radioCheckedId = R.id.radio_unlisted; @@ -78,6 +86,10 @@ public class ComposeOptionsFragment extends BottomSheetDialogFragment { listener.onVisibilityChanged(visibility); } }); + if (isReply) { + RadioButton publicButton = (RadioButton) rootView.findViewById(R.id.radio_public); + publicButton.setEnabled(false); + } CheckBox markSensitive = (CheckBox) rootView.findViewById(R.id.compose_mark_sensitive); if (showMarkSensitive) { diff --git a/app/src/main/java/com/keylesspalace/tusky/SFragment.java b/app/src/main/java/com/keylesspalace/tusky/SFragment.java index 549356acc..112fdae1e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/SFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/SFragment.java @@ -121,6 +121,7 @@ public class SFragment extends Fragment { mentionedUsernames.remove(loggedInUsername); Intent intent = new Intent(getContext(), ComposeActivity.class); intent.putExtra("in_reply_to_id", inReplyToId); + intent.putExtra("reply_visibility", status.getVisibility().toString().toLowerCase()); intent.putExtra("mentioned_usernames", mentionedUsernames.toArray(new String[0])); startActivity(intent); } @@ -252,6 +253,12 @@ public class SFragment extends Fragment { startActivity(intent); break; } + case UNKNOWN: { + /* Intentionally do nothing. This case is here is to handle when new attachment + * types are added to the API before code is added here to handle them. So, the + * best fallback is to just show the preview and ignore requests to view them. */ + break; + } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/Status.java b/app/src/main/java/com/keylesspalace/tusky/Status.java index 34c8ba64e..7e21ebddb 100644 --- a/app/src/main/java/com/keylesspalace/tusky/Status.java +++ b/app/src/main/java/com/keylesspalace/tusky/Status.java @@ -15,6 +15,7 @@ package com.keylesspalace.tusky; +import android.support.annotation.Nullable; import android.text.Spanned; import org.json.JSONArray; @@ -177,6 +178,8 @@ public class Status { return status.id.equals(this.id); } + @SuppressWarnings("SimpleDateFormat") // UTC needs to not specify a Locale + @Nullable private static Date parseDate(String dateTime) { Date date; String s = dateTime.replace("Z", "+00:00"); @@ -190,6 +193,18 @@ public class Status { return date; } + private static MediaAttachment.Type parseMediaType(@Nullable String type) { + if (type == null) { + return MediaAttachment.Type.UNKNOWN; + } + switch (type.toUpperCase()) { + case "IMAGE": return MediaAttachment.Type.IMAGE; + case "GIFV": + case "VIDEO": return MediaAttachment.Type.VIDEO; + default: return MediaAttachment.Type.UNKNOWN; + } + } + public static Status parse(JSONObject object, boolean isReblog) throws JSONException { String id = object.getString("id"); String content = object.getString("content"); @@ -239,8 +254,7 @@ public class Status { String url = attachment.getString("url"); String previewUrl = attachment.getString("preview_url"); String type = attachment.getString("type"); - attachments[i] = new MediaAttachment(url, previewUrl, - MediaAttachment.Type.valueOf(type.toUpperCase())); + attachments[i] = new MediaAttachment(url, previewUrl, parseMediaType(type)); } } @@ -289,6 +303,7 @@ public class Status { enum Type { IMAGE, VIDEO, + UNKNOWN, } private String url;