(ComposeActivity) clean up, automatique format and implementation of
- Share a link and extract the title, images, author's name #136
This commit is contained in:
parent
6dd2aba3c6
commit
b1bbcb39d5
1 changed files with 177 additions and 149 deletions
|
@ -24,7 +24,6 @@ import android.content.SharedPreferences;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
|
@ -39,10 +38,8 @@ import android.os.Environment;
|
|||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.support.annotation.AttrRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v13.view.inputmethod.InputConnectionCompat;
|
||||
|
@ -56,6 +53,7 @@ import android.support.v7.widget.Toolbar;
|
|||
import android.text.Editable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.style.URLSpan;
|
||||
import android.view.MenuItem;
|
||||
|
@ -72,15 +70,17 @@ import android.widget.TextView;
|
|||
import com.keylesspalace.tusky.entity.Media;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.keylesspalace.tusky.fragment.ComposeOptionsFragment;
|
||||
import com.keylesspalace.tusky.util.DownsizeImageTask;
|
||||
import com.keylesspalace.tusky.view.EditTextTyped;
|
||||
import com.keylesspalace.tusky.util.CountUpDownLatch;
|
||||
import com.keylesspalace.tusky.util.DownsizeImageTask;
|
||||
import com.keylesspalace.tusky.util.IOUtils;
|
||||
import com.keylesspalace.tusky.util.Log;
|
||||
import com.keylesspalace.tusky.util.MediaUtils;
|
||||
import com.keylesspalace.tusky.util.ParserUtils;
|
||||
import com.keylesspalace.tusky.util.SpanUtils;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
import com.keylesspalace.tusky.view.EditTextTyped;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
@ -92,7 +92,6 @@ import java.util.Date;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
@ -103,17 +102,43 @@ import retrofit2.Call;
|
|||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class ComposeActivity extends BaseActivity implements ComposeOptionsFragment.Listener {
|
||||
import static com.keylesspalace.tusky.util.MediaUtils.MEDIA_SIZE_UNKNOWN;
|
||||
import static com.keylesspalace.tusky.util.MediaUtils.getMediaSize;
|
||||
import static com.keylesspalace.tusky.util.MediaUtils.inputStreamGetBytes;
|
||||
import static com.keylesspalace.tusky.util.StringUtils.carriageReturn;
|
||||
import static com.keylesspalace.tusky.util.StringUtils.randomAlphanumericString;
|
||||
|
||||
public class ComposeActivity extends BaseActivity implements ComposeOptionsFragment.Listener, ParserUtils.ParserListener {
|
||||
private static final String TAG = "ComposeActivity"; // logging tag
|
||||
private static final int STATUS_CHARACTER_LIMIT = 500;
|
||||
private static final int STATUS_MEDIA_SIZE_LIMIT = 4000000; // 4MB
|
||||
private static final int MEDIA_PICK_RESULT = 1;
|
||||
private static final int MEDIA_TAKE_PHOTO_RESULT = 2;
|
||||
private static final int PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1;
|
||||
private static final int MEDIA_SIZE_UNKNOWN = -1;
|
||||
private static final int COMPOSE_SUCCESS = -1;
|
||||
private static final int THUMBNAIL_SIZE = 128; // pixels
|
||||
|
||||
@BindView(R.id.compose_edit_field)
|
||||
EditTextTyped textEditor;
|
||||
@BindView(R.id.compose_media_preview_bar)
|
||||
LinearLayout mediaPreviewBar;
|
||||
@BindView(R.id.compose_content_warning_bar)
|
||||
View contentWarningBar;
|
||||
@BindView(R.id.field_content_warning)
|
||||
EditText contentWarningEditor;
|
||||
@BindView(R.id.characters_left)
|
||||
TextView charactersLeft;
|
||||
@BindView(R.id.floating_btn)
|
||||
Button floatingBtn;
|
||||
@BindView(R.id.compose_photo_pick)
|
||||
ImageButton pickBtn;
|
||||
@BindView(R.id.compose_photo_take)
|
||||
ImageButton takeBtn;
|
||||
@BindView(R.id.action_toggle_nsfw)
|
||||
Button nsfwBtn;
|
||||
@BindView(R.id.postProgress)
|
||||
ProgressBar postProgress;
|
||||
@BindView(R.id.action_toggle_visibility)
|
||||
ImageButton visibilityBtn;
|
||||
private String inReplyToId;
|
||||
private ArrayList<QueuedMedia> mediaQueued;
|
||||
private CountUpDownLatch waitForMediaLatch;
|
||||
|
@ -127,93 +152,7 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
private Uri photoUploadUri;
|
||||
// this only exists when a status is trying to be sent, but uploads are still occurring
|
||||
private ProgressDialog finishingUploadDialog;
|
||||
@BindView(R.id.compose_edit_field)
|
||||
EditTextTyped textEditor;
|
||||
@BindView(R.id.compose_media_preview_bar) LinearLayout mediaPreviewBar;
|
||||
@BindView(R.id.compose_content_warning_bar) View contentWarningBar;
|
||||
@BindView(R.id.field_content_warning) EditText contentWarningEditor;
|
||||
@BindView(R.id.characters_left) TextView charactersLeft;
|
||||
@BindView(R.id.floating_btn) Button floatingBtn;
|
||||
@BindView(R.id.compose_photo_pick) ImageButton pickBtn;
|
||||
@BindView(R.id.compose_photo_take) ImageButton takeBtn;
|
||||
@BindView(R.id.action_toggle_nsfw) Button nsfwBtn;
|
||||
@BindView(R.id.postProgress) ProgressBar postProgress;
|
||||
@BindView(R.id.action_toggle_visibility) ImageButton visibilityBtn;
|
||||
|
||||
private static class QueuedMedia {
|
||||
enum Type {
|
||||
IMAGE,
|
||||
VIDEO
|
||||
}
|
||||
|
||||
enum ReadyStage {
|
||||
DOWNSIZING,
|
||||
UPLOADING
|
||||
}
|
||||
|
||||
Type type;
|
||||
ImageView preview;
|
||||
Uri uri;
|
||||
String id;
|
||||
Call<Media> uploadRequest;
|
||||
URLSpan uploadUrl;
|
||||
ReadyStage readyStage;
|
||||
byte[] content;
|
||||
long mediaSize;
|
||||
|
||||
QueuedMedia(Type type, Uri uri, ImageView preview, long mediaSize) {
|
||||
this.type = type;
|
||||
this.uri = uri;
|
||||
this.preview = preview;
|
||||
this.mediaSize = mediaSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**This saves enough information to re-enqueue an attachment when restoring the activity. */
|
||||
private static class SavedQueuedMedia implements Parcelable {
|
||||
QueuedMedia.Type type;
|
||||
Uri uri;
|
||||
Bitmap preview;
|
||||
long mediaSize;
|
||||
|
||||
SavedQueuedMedia(QueuedMedia.Type type, Uri uri, ImageView view, long mediaSize) {
|
||||
this.type = type;
|
||||
this.uri = uri;
|
||||
this.preview = ((BitmapDrawable) view.getDrawable()).getBitmap();
|
||||
this.mediaSize = mediaSize;
|
||||
}
|
||||
|
||||
SavedQueuedMedia(Parcel parcel) {
|
||||
type = (QueuedMedia.Type) parcel.readSerializable();
|
||||
uri = parcel.readParcelable(Uri.class.getClassLoader());
|
||||
preview = parcel.readParcelable(Bitmap.class.getClassLoader());
|
||||
mediaSize = parcel.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeSerializable(type);
|
||||
dest.writeParcelable(uri, flags);
|
||||
dest.writeParcelable(preview, flags);
|
||||
dest.writeLong(mediaSize);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<SavedQueuedMedia> CREATOR
|
||||
= new Parcelable.Creator<SavedQueuedMedia>() {
|
||||
public SavedQueuedMedia createFromParcel(Parcel in) {
|
||||
return new SavedQueuedMedia(in);
|
||||
}
|
||||
|
||||
public SavedQueuedMedia[] newArray(int size) {
|
||||
return new SavedQueuedMedia[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -337,6 +276,8 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
postProgress.setVisibility(View.INVISIBLE);
|
||||
updateNsfwButtonColor();
|
||||
|
||||
final ParserUtils parser = new ParserUtils(this);
|
||||
|
||||
// Setup the main text field.
|
||||
setEditTextMimeTypes(null); // new String[] { "image/gif", "image/webp" }
|
||||
final int mentionColour = ThemeUtils.getColor(this, R.attr.compose_mention_color);
|
||||
|
@ -348,7 +289,8 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
|
@ -356,6 +298,13 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
}
|
||||
});
|
||||
|
||||
textEditor.addOnPasteListener(new EditTextTyped.OnPasteListener() {
|
||||
@Override
|
||||
public void onPaste() {
|
||||
parser.getPastedURLText(ComposeActivity.this);
|
||||
}
|
||||
});
|
||||
|
||||
// Add any mentions to the text field when a reply is first composed.
|
||||
if (mentionedUsernames != null) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
@ -371,7 +320,8 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
// Initialise the content warning editor.
|
||||
contentWarningEditor.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
@ -379,10 +329,11 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
});
|
||||
showContentWarning(startingHideText);
|
||||
if(startingContentWarning != null){
|
||||
if (startingContentWarning != null) {
|
||||
contentWarningEditor.setText(startingContentWarning);
|
||||
}
|
||||
|
||||
|
@ -637,7 +588,7 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
}
|
||||
|
||||
private boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags,
|
||||
String[] mimeTypes) {
|
||||
String[] mimeTypes) {
|
||||
try {
|
||||
if (currentInputContentInfo != null) {
|
||||
currentInputContentInfo.releasePermission();
|
||||
|
@ -816,9 +767,9 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
private void onMediaPick() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN &&
|
||||
ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(this,
|
||||
new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
|
||||
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||
PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
|
||||
} else {
|
||||
initiateMediaPicking();
|
||||
|
@ -827,7 +778,7 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
|
||||
@NonNull int[] grantResults) {
|
||||
@NonNull int[] grantResults) {
|
||||
switch (requestCode) {
|
||||
case PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {
|
||||
if (grantResults.length > 0
|
||||
|
@ -888,7 +839,7 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
intent.setType("image/* video/*");
|
||||
} else {
|
||||
String[] mimeTypes = new String[] { "image/*", "video/*" };
|
||||
String[] mimeTypes = new String[]{"image/*", "video/*"};
|
||||
intent.setType("*/*");
|
||||
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
|
||||
}
|
||||
|
@ -986,7 +937,7 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
}
|
||||
|
||||
private void removeAllMediaFromQueue() {
|
||||
for (Iterator<QueuedMedia> it = mediaQueued.iterator(); it.hasNext();) {
|
||||
for (Iterator<QueuedMedia> it = mediaQueued.iterator(); it.hasNext(); ) {
|
||||
QueuedMedia item = it.next();
|
||||
it.remove();
|
||||
removeMediaFromQueue(item);
|
||||
|
@ -1008,7 +959,7 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
public void onFailure() {
|
||||
onMediaDownsizeFailure(item);
|
||||
}
|
||||
}).execute(item.uri);
|
||||
}).execute(item.uri);
|
||||
}
|
||||
|
||||
private void onMediaDownsizeFailure(QueuedMedia item) {
|
||||
|
@ -1016,32 +967,6 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
removeMediaFromQueue(item);
|
||||
}
|
||||
|
||||
private static String randomAlphanumericString(int count) {
|
||||
char[] chars = new char[count];
|
||||
Random random = new Random();
|
||||
final String POSSIBLE_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
for (int i = 0; i < count; i++) {
|
||||
chars[i] = POSSIBLE_CHARS.charAt(random.nextInt(POSSIBLE_CHARS.length()));
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static byte[] inputStreamGetBytes(InputStream stream) {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
int read;
|
||||
byte[] data = new byte[16384];
|
||||
try {
|
||||
while ((read = stream.read(data, 0, data.length)) != -1) {
|
||||
buffer.write(data, 0, read);
|
||||
}
|
||||
buffer.flush();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
private void uploadMedia(final QueuedMedia item) {
|
||||
item.readyStage = QueuedMedia.ReadyStage.UPLOADING;
|
||||
|
||||
|
@ -1136,20 +1061,6 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
}
|
||||
}
|
||||
|
||||
private static long getMediaSize(ContentResolver contentResolver, Uri uri) {
|
||||
long mediaSize;
|
||||
Cursor cursor = contentResolver.query(uri, null, null, null, null);
|
||||
if (cursor != null) {
|
||||
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
|
||||
cursor.moveToFirst();
|
||||
mediaSize = cursor.getLong(sizeIndex);
|
||||
cursor.close();
|
||||
} else {
|
||||
mediaSize = MEDIA_SIZE_UNKNOWN;
|
||||
}
|
||||
return mediaSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
@ -1228,12 +1139,12 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
void showMarkSensitive(boolean show) {
|
||||
showMarkSensitive = show;
|
||||
|
||||
if(!showMarkSensitive) {
|
||||
if (!showMarkSensitive) {
|
||||
statusMarkSensitive = false;
|
||||
nsfwBtn.setTextColor(ThemeUtils.getColor(this, R.attr.compose_nsfw_button_color));
|
||||
}
|
||||
|
||||
if(show) {
|
||||
if (show) {
|
||||
nsfwBtn.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
nsfwBtn.setVisibility(View.GONE);
|
||||
|
@ -1260,4 +1171,121 @@ public class ComposeActivity extends BaseActivity implements ComposeOptionsFrag
|
|||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveHeaderInfo(ParserUtils.HeaderInfo headerInfo) {
|
||||
if (!TextUtils.isEmpty(headerInfo.title)) {
|
||||
cleanBaseUrl(headerInfo);
|
||||
textEditor.append(headerInfo.title);
|
||||
textEditor.append(carriageReturn);
|
||||
textEditor.append(headerInfo.baseUrl);
|
||||
}
|
||||
if (!TextUtils.isEmpty(headerInfo.image)) {
|
||||
Picasso.with(this).load(headerInfo.image).into(MediaUtils.picassoImageTarget(getApplicationContext(), new MediaUtils.MediaListener() {
|
||||
@Override
|
||||
public void onCallback(final Uri headerInfo) {
|
||||
if (headerInfo != null) {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long mediaSize = getMediaSize(getContentResolver(), headerInfo);
|
||||
pickMedia(headerInfo, mediaSize);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// remove the precedent paste from the edit text
|
||||
private void cleanBaseUrl(ParserUtils.HeaderInfo headerInfo) {
|
||||
int lengthBaseUrl = headerInfo.baseUrl.length();
|
||||
int total = textEditor.getText().length();
|
||||
int indexSubString = total - lengthBaseUrl;
|
||||
String text = textEditor.getText().toString();
|
||||
text = text.substring(0, indexSubString);
|
||||
textEditor.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onErrorHeaderInfo() {
|
||||
displayTransientError(R.string.error_generic);
|
||||
}
|
||||
|
||||
private static class QueuedMedia {
|
||||
Type type;
|
||||
ImageView preview;
|
||||
Uri uri;
|
||||
String id;
|
||||
Call<Media> uploadRequest;
|
||||
URLSpan uploadUrl;
|
||||
ReadyStage readyStage;
|
||||
byte[] content;
|
||||
long mediaSize;
|
||||
|
||||
QueuedMedia(Type type, Uri uri, ImageView preview, long mediaSize) {
|
||||
this.type = type;
|
||||
this.uri = uri;
|
||||
this.preview = preview;
|
||||
this.mediaSize = mediaSize;
|
||||
}
|
||||
|
||||
enum Type {
|
||||
IMAGE,
|
||||
VIDEO
|
||||
}
|
||||
|
||||
enum ReadyStage {
|
||||
DOWNSIZING,
|
||||
UPLOADING
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This saves enough information to re-enqueue an attachment when restoring the activity.
|
||||
*/
|
||||
private static class SavedQueuedMedia implements Parcelable {
|
||||
public static final Parcelable.Creator<SavedQueuedMedia> CREATOR
|
||||
= new Parcelable.Creator<SavedQueuedMedia>() {
|
||||
public SavedQueuedMedia createFromParcel(Parcel in) {
|
||||
return new SavedQueuedMedia(in);
|
||||
}
|
||||
|
||||
public SavedQueuedMedia[] newArray(int size) {
|
||||
return new SavedQueuedMedia[size];
|
||||
}
|
||||
};
|
||||
QueuedMedia.Type type;
|
||||
Uri uri;
|
||||
Bitmap preview;
|
||||
long mediaSize;
|
||||
|
||||
SavedQueuedMedia(QueuedMedia.Type type, Uri uri, ImageView view, long mediaSize) {
|
||||
this.type = type;
|
||||
this.uri = uri;
|
||||
this.preview = ((BitmapDrawable) view.getDrawable()).getBitmap();
|
||||
this.mediaSize = mediaSize;
|
||||
}
|
||||
|
||||
SavedQueuedMedia(Parcel parcel) {
|
||||
type = (QueuedMedia.Type) parcel.readSerializable();
|
||||
uri = parcel.readParcelable(Uri.class.getClassLoader());
|
||||
preview = parcel.readParcelable(Bitmap.class.getClassLoader());
|
||||
mediaSize = parcel.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeSerializable(type);
|
||||
dest.writeParcelable(uri, flags);
|
||||
dest.writeParcelable(preview, flags);
|
||||
dest.writeLong(mediaSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue