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;