improve default post privacy to work like web mastodon, add default post privacy option

main
Conny Duck 7 years ago
parent b239c2eef5
commit 679ab52ea4
  1. 222
      app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java
  2. 10
      app/src/main/java/com/keylesspalace/tusky/entity/Status.java
  3. 6
      app/src/main/res/values/donottranslate.xml
  4. 13
      app/src/main/res/values/strings.xml
  5. 11
      app/src/main/res/xml/preferences.xml

@ -35,6 +35,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.NonNull;
@ -134,7 +135,6 @@ public final class ComposeActivity extends BaseActivity
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 final String REMEMBERED_VISIBILITY_PREF = "rememberedVisibilityNum";
private static TootDao tootDao = TuskyApplication.getDB().tootDao();
private TextView replyTextView;
@ -198,42 +198,12 @@ public final class ComposeActivity extends BaseActivity
}
// Setup the interface buttons.
floatingBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onSendClicked();
}
});
floatingBtn.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return saveDraft();
}
});
pickButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openPickDialog();
}
});
visibilityBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showComposeOptions();
}
});
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
saveDraft();
}
});
hideMediaToggle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleHideMedia();
}
});
floatingBtn.setOnClickListener(v -> onSendClicked());
floatingBtn.setOnLongClickListener(v -> saveDraft());
pickButton.setOnClickListener(v -> openPickDialog());
visibilityBtn.setOnClickListener(v -> showComposeOptions());
saveButton.setOnClickListener(v -> saveDraft());
hideMediaToggle.setOnClickListener(v -> toggleHideMedia());
//fix a bug with autocomplete and some keyboards
int newInputType = textEditor.getInputType() & (textEditor.getInputType() ^ InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
@ -241,9 +211,7 @@ public final class ComposeActivity extends BaseActivity
/* Initialise all the state, or restore it from a previous run, to determine a "starting"
* state. */
SharedPreferences preferences = getPrivatePreferences();
Status.Visibility startingVisibility;
Status.Visibility startingVisibility = Status.Visibility.UNKNOWN;
boolean startingHideText;
String startingContentWarning = null;
ArrayList<SavedQueuedMedia> savedMediaQueued = null;
@ -267,10 +235,6 @@ public final class ComposeActivity extends BaseActivity
photoUploadUri = savedInstanceState.getParcelable("photoUploadUri");
} else {
showMarkSensitive = false;
startingVisibility = Status.Visibility.byNum(
preferences.getInt(REMEMBERED_VISIBILITY_PREF,
Status.Visibility.UNKNOWN.getNum())
);
statusMarkSensitive = false;
startingHideText = false;
photoUploadUri = null;
@ -283,12 +247,23 @@ public final class ComposeActivity extends BaseActivity
String[] mentionedUsernames = null;
ArrayList<String> loadedDraftMediaUris = null;
inReplyToId = null;
Status.Visibility replyVisibility = Status.Visibility.UNKNOWN;
if (intent != null) {
if(startingVisibility == Status.Visibility.UNKNOWN) {
Status.Visibility replyVisibility = Status.Visibility.byNum(
intent.getIntExtra(REPLY_VISIBILITY_EXTRA, Status.Visibility.UNKNOWN.getNum()));
if(replyVisibility != Status.Visibility.UNKNOWN) {
startingVisibility = replyVisibility;
} else {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
startingVisibility = Status.Visibility.byString(
preferences.getString("defaultPostPrivacy",
Status.Visibility.PUBLIC.serverString()));
}
}
inReplyToId = intent.getStringExtra(IN_REPLY_TO_ID_EXTRA);
replyVisibility = Status.Visibility.byNum(
intent.getIntExtra(REPLY_VISIBILITY_EXTRA, Status.Visibility.UNKNOWN.getNum())
);
mentionedUsernames = intent.getStringArrayExtra(MENTIONED_USERNAMES_EXTRA);
@ -323,14 +298,11 @@ public final class ComposeActivity extends BaseActivity
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);
}
replyTextView.setOnClickListener(v -> {
if (replyContentTextView.getVisibility() != View.VISIBLE) {
replyContentTextView.setVisibility(View.VISIBLE);
} else {
replyContentTextView.setVisibility(View.GONE);
}
});
}
@ -340,11 +312,8 @@ public final class ComposeActivity extends BaseActivity
}
}
Status.Visibility pickedVisibility = pickVisibility(startingVisibility, replyVisibility,
preferences.getBoolean("loggedInAccountLocked", false));
// After the starting state is finalised, the interface can be set to reflect this state.
setStatusVisibility(pickedVisibility);
setStatusVisibility(startingVisibility);
postProgress.setVisibility(View.INVISIBLE);
updateHideMediaToggleColor();
@ -496,6 +465,7 @@ public final class ComposeActivity extends BaseActivity
currentInputContentInfo = null;
currentFlags = 0;
outState.putParcelable("photoUploadUri", photoUploadUri);
outState.putInt("statusVisibility", statusVisibility.getNum());
super.onSaveInstanceState(outState);
}
@ -822,28 +792,12 @@ public final class ComposeActivity extends BaseActivity
readyStatus(statusVisibility, statusMarkSensitive);
}
@Override
protected void onStop() {
super.onStop();
// 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.
if (inReplyToId == null) {
getPrivatePreferences().edit()
.putInt(REMEMBERED_VISIBILITY_PREF, statusVisibility.getNum())
.apply();
}
}
private void setEditTextMimeTypes() {
final String[] mimeTypes = new String[]{"image/*"};
textEditor.setMimeTypes(mimeTypes, new InputConnectionCompat.OnCommitContentListener() {
@Override
public boolean onCommitContent(InputContentInfoCompat inputContentInfo,
int flags, Bundle opts) {
return ComposeActivity.this.onCommitContent(inputContentInfo, flags,
mimeTypes);
}
});
textEditor.setMimeTypes(mimeTypes,
(inputContentInfo, flags, opts) ->
ComposeActivity.this.onCommitContent(inputContentInfo, flags,
mimeTypes));
}
private boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags,
@ -963,13 +917,10 @@ public final class ComposeActivity extends BaseActivity
if (response != null && inReplyToId != null && response.code() == 404) {
new AlertDialog.Builder(this)
.setMessage(R.string.dialog_reply_not_found)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
inReplyToId = null;
replyContentTextView.setVisibility(View.GONE);
replyTextView.setVisibility(View.GONE);
}
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
inReplyToId = null;
replyContentTextView.setVisibility(View.GONE);
replyTextView.setVisibility(View.GONE);
})
.setNegativeButton(android.R.string.cancel, null)
.show();
@ -1013,14 +964,11 @@ public final class ComposeActivity extends BaseActivity
super.onCancelled();
}
};
finishingUploadDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
/* Generating an interrupt by passing true here is important because an interrupt
* exception is the only thing that will kick the latch out of its waiting loop
* early. */
waitForMediaTask.cancel(true);
}
finishingUploadDialog.setOnCancelListener(dialog -> {
/* Generating an interrupt by passing true here is important because an interrupt
* exception is the only thing that will kick the latch out of its waiting loop
* early. */
waitForMediaTask.cancel(true);
});
waitForMediaTask.execute();
}
@ -1048,12 +996,7 @@ public final class ComposeActivity extends BaseActivity
private void onReadyFailure(final Status.Visibility visibility, final boolean sensitive) {
doErrorDialog(R.string.error_media_upload_sending, R.string.action_retry,
new View.OnClickListener() {
@Override
public void onClick(View v) {
readyStatus(visibility, sensitive);
}
});
v -> readyStatus(visibility, sensitive));
setStateToNotReadying();
}
@ -1063,18 +1006,15 @@ public final class ComposeActivity extends BaseActivity
CharSequence[] choices = new CharSequence[2];
choices[CHOICE_TAKE] = getString(R.string.action_photo_take);
choices[CHOICE_PICK] = getString(R.string.action_photo_pick);
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case CHOICE_TAKE: {
initiateCameraApp();
break;
}
case CHOICE_PICK: {
onMediaPick();
break;
}
DialogInterface.OnClickListener listener = (dialog, which) -> {
switch (which) {
case CHOICE_TAKE: {
initiateCameraApp();
break;
}
case CHOICE_PICK: {
onMediaPick();
break;
}
}
};
@ -1106,12 +1046,7 @@ public final class ComposeActivity extends BaseActivity
initiateMediaPicking();
} else {
doErrorDialog(R.string.error_media_upload_permission, R.string.action_retry,
new View.OnClickListener() {
@Override
public void onClick(View v) {
onMediaPick();
}
});
v -> onMediaPick());
}
break;
}
@ -1193,12 +1128,7 @@ public final class ComposeActivity extends BaseActivity
view.setLayoutParams(layoutParams);
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setImageBitmap(preview);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
removeMediaFromQueue(item);
}
});
view.setOnClickListener(v -> removeMediaFromQueue(item));
view.setContentDescription(getString(R.string.action_delete));
mediaPreviewBar.addView(view);
mediaQueued.add(item);
@ -1334,12 +1264,7 @@ public final class ComposeActivity extends BaseActivity
@Override
public void onProgressUpdate(final int percentage) {
if (percentage != lastProgress) {
runOnUiThread(new Runnable() {
@Override
public void run() {
item.preview.setProgress(percentage);
}
});
runOnUiThread(() -> item.preview.setProgress(percentage));
}
lastProgress = percentage;
}
@ -1607,41 +1532,6 @@ public final class ComposeActivity extends BaseActivity
}
}
/**
* Function to decide which visibility should be used for posting a status
*
* @return {@code PRIVATE} if account is locked, {@code PUBLIC} if both start and reply
* visibilities are unknown or minimal known visibility of two of them.
*/
private static Status.Visibility pickVisibility(final Status.Visibility startVisibility,
final Status.Visibility replyVisibility,
boolean isAccountLocked) {
// If the currently logged in account is locked, its posts should default to private.
// This should override even the reply settings.
if (isAccountLocked) {
return Status.Visibility.PRIVATE;
}
if (startVisibility == Status.Visibility.UNKNOWN &&
replyVisibility == Status.Visibility.UNKNOWN) {
return Status.Visibility.PUBLIC;
}
if (replyVisibility == Status.Visibility.UNKNOWN) {
return startVisibility;
}
if (startVisibility == Status.Visibility.UNKNOWN) {
return replyVisibility;
}
if (startVisibility.getNum() > replyVisibility.getNum()) {
return startVisibility;
} else {
return replyVisibility;
}
}
@SuppressWarnings("WeakerAccess")
public static final class IntentBuilder {
@Nullable

@ -80,6 +80,16 @@ public class Status {
}
}
public static Visibility byString(String s) {
switch (s) {
case "public": return PUBLIC;
case "unlisted": return UNLISTED;
case "private": return PRIVATE;
case "direct": return DIRECT;
case "unknown": default: return UNKNOWN;
}
}
public String serverString() {
switch (this) {
case PUBLIC: return "public";

@ -16,4 +16,10 @@
<item>60</item>
<item>120</item>
</string-array>
<string-array name="post_privacy_values" inputType="integer">
<item>public</item>
<item>unlisted</item>
<item>private</item>
</string-array>
</resources>

@ -107,7 +107,7 @@
<string name="download_image">Downloading %1$s</string>
<string name="action_copy_link">Copy the link</string>
<string name="send_status_link_to">Share toot URL to…</string>
<string name="send_status_content_to">Share toot to…</string>
@ -146,7 +146,6 @@
<string name="dialog_download_image">Download</string>
<string name="dialog_message_follow_request">Follow request pending: awaiting their response</string>
<string name="dialog_unfollow_warning">Unfollow this account?</string>
<string name="dialog_reply_not_found">Couldn\'t post this status. The status you\'re replying to might not be available. Remove reply info?</string>
<string name="visibility_public">Public: Post to public timelines</string>
<string name="visibility_unlisted">Unlisted: Do not show in public timelines</string>
@ -187,6 +186,15 @@
<item>2 hours</item>
</string-array>
<string name="pref_default_post_privacy">Default post privacy</string>
<string name="pref_publishing">Publishing</string>
<string-array name="post_privacy_names" inputType="integer">
<item>Public</item>
<item>Unlisted</item>
<item>Followers-only</item>
</string-array>
<string name="notification_channel_mention_name">New Mentions</string>
<string name="notification_channel_mention_descriptions">Notifications about new mentions</string>
<string name="notification_channel_follow_name">New Followers</string>
@ -250,4 +258,5 @@
<string name="replying_to">Replying to @%s</string>
<string name="load_more_placeholder_text">load more</string>
</resources>

@ -25,6 +25,17 @@
android:title="@string/pref_title_alway_show_sensitive_media" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_publishing">
<ListPreference
android:defaultValue="public"
android:entries="@array/post_privacy_names"
android:entryValues="@array/post_privacy_values"
android:key="defaultPostPrivacy"
android:summary="%s"
android:title="@string/pref_default_post_privacy" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/pref_title_browser_settings">
<CheckBoxPreference
android:defaultValue="false"

Loading…
Cancel
Save