package com.ladjzero.uzlee;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewStub;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import com.alibaba.fastjson.JSON;
import com.daimajia.androidanimations.library.Techniques;
import com.daimajia.androidanimations.library.YoYo;
import com.joanzapata.iconify.IconDrawable;
import com.joanzapata.iconify.fonts.MaterialIcons;
import com.ladjzero.hipda.Post;
import com.ladjzero.uzlee.utils.Constants;
import com.ladjzero.uzlee.utils.EmojiUtils;
import com.ladjzero.uzlee.utils.Utils;
import com.nineoldandroids.animation.Animator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.orhanobut.logger.Logger;
import com.rey.material.app.Dialog;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
public class ActivityEdit extends ActivityHardSlide implements HttpClientCallback {
public static final int EDIT_SUCCESS = 10;
private static final int SELECT_PHOTO = 100;
int tid;
int pid;
int fid;
int uid;
int no;
boolean isNewThread, isReplyToOne, isReply, isEdit;
String content;
TextView subjectInput;
EditText mMessageInput;
Intent intent;
ArrayList<Integer> attachIds = new ArrayList<Integer>();
ArrayList<Integer> existedAttachIds = new ArrayList<Integer>();
Dialog progress;
boolean mSaveDraft = true;
private View mEmojiSelector;
private InputMethodManager mImeManager;
private boolean mIsAnimating = false;
private HttpApi mHttpApi;
private AsyncTask mImageTask, mParseTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit);
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
intent = getIntent();
tid = intent.getIntExtra("tid", 0);
pid = intent.getIntExtra("pid", 0);
fid = intent.getIntExtra("fid", 0);
uid = intent.getIntExtra("uid", 0);
no = intent.getIntExtra("no", 0);
isNewThread = (tid == 0 && pid == 0);
isReplyToOne = (tid != 0 && pid != 0 && fid == 0);
isReply = (tid != 0 && pid == 0 && fid == 0);
isEdit = (tid != 0 && pid != 0 && fid != 0);
String title = intent.getStringExtra("title");
if (title != null) setTitle(title);
progress = new Dialog(this)
.cancelable(false)
.contentView(R.layout.progress_circular)
.titleColor(Utils.getThemeColor(this, R.attr.colorText))
.backgroundColor(Utils.getThemeColor(this, android.R.attr.colorBackground));
mHttpApi = App.getInstance().getCore().getHttpApi();
mHttpApi.getExistedAttach(new HttpClientCallback() {
@Override
public void onSuccess(String response) {
String[] ids = App.getInstance().getCore().getPostsParser().parseExistedAttach(response);
for (String id : ids) {
if (id.length() > 0) existedAttachIds.add(Integer.valueOf(id));
}
}
@Override
public void onFailure(String reason) {
showToast(reason);
}
});
mImeManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
subjectInput = (TextView) findViewById(R.id.edit_title);
mMessageInput = (EditText) findViewById(R.id.edit_body);
String subject = intent.getStringExtra("subject");
String message = intent.getStringExtra("message");
if (subject != null) subjectInput.setText(subject);
if (message != null) mMessageInput.setText(message);
mMessageInput.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mEmojiSelector != null) mEmojiSelector.setVisibility(View.GONE);
}
});
if (isNewThread) {
subjectInput.setVisibility(View.VISIBLE);
} else {
if (uid != App.getInstance().getCore().getLocalApi().getUser().getId()) {
//reply
subjectInput.setVisibility(View.GONE);
} else if (no != 1) {
//edit non-top
subjectInput.setVisibility(View.GONE);
} else {
//edit top
subjectInput.setVisibility(View.VISIBLE);
}
}
// If subject and message have content.
// This activity may be revived from a draft.
if (isEdit && subjectInput.length() == 0 && mMessageInput.length() == 0) {
progress.setTitle("载入中");
progress.show();
mHttpApi.getEditBody(fid, tid, pid, new HttpClientCallback() {
@Override
public void onSuccess(String response) {
mParseTask = new AsyncTask<String, Object, Post>() {
@Override
protected Post doInBackground(String... strings) {
return App.getInstance().getCore().getPostsParser().parseEditablePost(strings[0]);
}
@Override
protected void onPostExecute(Post post) {
subjectInput.setText(post.getTitle());
mMessageInput.setText(post.getBody());
progress.dismiss();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, response);
}
@Override
public void onFailure(String reason) {
}
});
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_reply, menu);
int color = Utils.getThemeColor(this, R.attr.colorTextInverse);
menu.findItem(R.id.reply_send)
.setIcon(new IconDrawable(this, MaterialIcons.md_send)
.color(color)
.actionBarSize());
menu.findItem(R.id.reply_add_image)
.setIcon(new IconDrawable(this, MaterialIcons.md_image)
.color(color)
.actionBarSize());
menu.findItem(R.id.reply_add_emoji)
.setIcon(new IconDrawable(this, MaterialIcons.md_tag_faces)
.color(color)
.actionBarSize());
if (fid != 0 && tid != 0 && pid != 0 && no != 1)
menu.findItem(R.id.delete_post)
.setIcon(new IconDrawable(this, MaterialIcons.md_delete)
.color(color)
.actionBarSize());
else
menu.findItem(R.id.delete_post).setVisible(false);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.reply_send) {
String sig = setting.getBoolean("use_sig", false) ? "有只梨" : "";
String subject = subjectInput.getText().toString();
String message = mMessageInput.getText().toString();
if (isNewThread) {
if (subject.length() == 0) {
showToast("标题不能为空");
} else if (message.length() == 0) {
showToast("内容不能少于5字");
} else {
progress.setTitle("发送");
progress.show();
if (sig.length() > 0)
message += "\t\t\t[size=1][color=Gray]" + sig + "[/color][/size]";
mHttpApi.newThread(fid, subject, message, attachIds, this);
}
} else if (isEdit) {
if (no == 1 && subject.length() == 0) {
showToast("标题不能为空");
} else if (message.length() == 0) {
showToast("内容不能少于5字");
} else {
progress.setTitle("发送");
progress.show();
mHttpApi.editPost(fid, tid, pid, subject, message, attachIds, this);
}
} else if (isReplyToOne) {
progress.setTitle("发送");
progress.show();
message = "[b]回复 [url=http://www.hi-pda.com/forum/redirect.php?goto=findpost&pid=" + pid + "&ptid=" + tid + "]" + intent.getIntExtra("no", 0) + "#[/url] [i]" + intent.getStringExtra("userName") + "[/i] [/b]\n\n" + message;
message += "\t\t\t[size=1][color=Gray]" + sig + "[/color][/size]";
mHttpApi.sendReply(tid, message, attachIds, existedAttachIds, this);
} else if (isReply) {
progress.setTitle("发送");
progress.show();
message += "\t\t\t[size=1][color=Gray]" + sig + "[/color][/size]";
mHttpApi.sendReply(tid, message, attachIds, existedAttachIds, this);
}
} else if (id == R.id.reply_add_image) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
photoPickerIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(photoPickerIntent, SELECT_PHOTO);
} else if (id == R.id.delete_post) {
final Dialog mDialog = new Dialog(this);
mDialog
.title("删除该回复?(实验性)")
.canceledOnTouchOutside(true)
.positiveActionClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDialog.dismiss();
mHttpApi.deletePost(fid, tid, pid, ActivityEdit.this);
}
})
.negativeActionClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDialog.dismiss();
}
})
.negativeAction("取消")
.positiveAction("确认")
.titleColor(Utils.getThemeColor(this, R.attr.colorText))
.backgroundColor(Utils.getThemeColor(this, android.R.attr.colorBackground))
.show();
} else if (id == R.id.reply_add_emoji) {
if (mEmojiSelector == null) {
((ViewStub) findViewById(R.id.emoji_viewstub)).inflate();
mEmojiSelector = findViewById(R.id.emoji);
}
if (!mIsAnimating) {
if (mEmojiSelector.getVisibility() == View.GONE) {
YoYo.with(Techniques.SlideInUp)
.duration(200)
.withListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mEmojiSelector.setVisibility(View.VISIBLE);
mIsAnimating = true;
}
@Override
public void onAnimationEnd(Animator animation) {
mIsAnimating = false;
mImeManager.hideSoftInputFromWindow(mMessageInput.getWindowToken(), 0);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
})
.playOn(mEmojiSelector);
} else {
YoYo.with(Techniques.SlideOutDown)
.duration(200)
.withListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mIsAnimating = true;
}
@Override
public void onAnimationEnd(Animator animation) {
mEmojiSelector.setVisibility(View.GONE);
mIsAnimating = false;
mImeManager.showSoftInput(mMessageInput, 0);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
})
.playOn(mEmojiSelector);
}
}
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
if (imageReturnedIntent != null) {
Uri uri = imageReturnedIntent.getData();
File imageFile = new File(getRealPathFromURI(this, uri));
final Dialog mDialog = new Dialog(this);
mDialog.title("图片处理")
.cancelable(false)
.contentView(R.layout.progress_circular)
.titleColor(Utils.getThemeColor(this, R.attr.colorText))
.backgroundColor(Utils.getThemeColor(this, android.R.attr.colorBackground))
.show();
mImageTask = new AsyncTask<File, Void, File>() {
@Override
protected File doInBackground(File... params) {
return compressImage(params[0], (getSettings().getInt(Constants.PREF_KEY_IMG_SIZE, Constants.DEFAULT_IMAGE_UPLOAD_SIZE) - 1) * 1024);
}
@Override
protected void onPostExecute(File tempFile) {
if (tempFile == null || !tempFile.exists()) {
mDialog.dismiss();
showToast("图片处理失败");
} else {
mDialog.title("图片上传").show();
mHttpApi.uploadImage(tempFile, new HttpClientCallback() {
@Override
public void onSuccess(String response) {
if (response.startsWith("DISCUZUPLOAD")) {
int attachId = -1;
try {
attachId = Integer.valueOf(response.split("\\|")[2]);
} catch (Exception e) {
}
if (attachId != -1) {
attachIds.add(attachId);
mMessageInput.setText(mMessageInput.getText() + "[attachimg]" + attachId + "[/attachimg]");
}
} else {
showToast("图片长传失败: " + response);
}
mDialog.dismiss();
}
@Override
public void onFailure(String reason) {
showToast("图片上传失败");
mDialog.dismiss();
}
});
}
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, imageFile);
}
}
private String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = {MediaStore.Images.Media.DATA};
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
@Override
public void onSuccess(String response) {
mSaveDraft = false;
Intent returnIntent = new Intent();
returnIntent.putExtra("posts-json", App.getInstance().getApi().getPostsParser().parse(response));
setResult(EDIT_SUCCESS, returnIntent);
finish();
}
@Override
public void onFailure(String reason) {
showToast(reason);
}
public void addEmoji(View v) {
String emojiText = (String) v.getTag();
String emoji;
if (emojiText.startsWith("coolmonkey")) {
emoji = EmojiUtils.icons.get("images/smilies/coolmonkey/" + emojiText.substring(10) + ".gif");
} else if (emojiText.startsWith("grapeman")) {
emoji = EmojiUtils.icons.get("images/smilies/grapeman/" + emojiText.substring(8) + ".gif");
} else {
emoji = EmojiUtils.icons.get("images/smilies/default/" + emojiText + ".gif");
}
String temp = mMessageInput.getText().toString();
int start = mMessageInput.getSelectionStart();
int end = mMessageInput.getSelectionEnd();
temp = StringUtils.left(temp, start) + emoji + StringUtils.right(temp, temp.length() - end);
mMessageInput.setText(temp);
mMessageInput.setSelection(start + emoji.length());
}
@Override
protected void onDestroy() {
if (mSaveDraft && (subjectInput.length() > 0 || mMessageInput.length() > 0)) {
Draft draft = new Draft();
draft.activityTitle = getTitle().toString();
draft.subject = subjectInput.getText().toString();
draft.message = mMessageInput.getText().toString();
draft.fid = fid;
draft.tid = tid;
draft.pid = pid;
draft.uid = uid;
draft.no = no;
String json = JSON.toJSONString(draft);
getSettings().edit().putString("draft", json).commit();
}
if (mImageTask != null && !mImageTask.isCancelled()) {
mImageTask.cancel(true);
}
if (mParseTask != null && !mParseTask.isCancelled()) {
mParseTask.cancel(true);
}
super.onDestroy();
}
/**
* If the length of image file is less than maxSize, quality will not be applied, and
* image file will be returned directly.
*
* @param imageFile
* @param maxSize
* @param quality
* @return File
*/
private File lowerQuality(final File imageFile, int maxSize, int quality) {
long fileLength = imageFile.length();
File tempFile = null;
OutputStream os = null;
if (fileLength > maxSize) {
try {
Bitmap bitmap = ImageLoader.getInstance().loadImageSync(Uri.fromFile(imageFile).toString());
tempFile = File.createTempFile("uzlee-compress", ".jpg", this.getCacheDir());
os = new FileOutputStream(tempFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, os);
os.close();
fileLength = tempFile.length();
Logger.i("length: %d, quality: %d", fileLength, quality);
return fileLength > maxSize ? null : tempFile;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (tempFile != null) {
tempFile.deleteOnExit();
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} else {
return imageFile;
}
return null;
}
private File lowerQuality(final File imageFile, int maxSize) {
int worst = 60;
// Test the worst case.
File tempFile = lowerQuality(imageFile, maxSize, worst);
// Find a better one.
if (tempFile != null) {
int quality = 90;
do {
tempFile = lowerQuality(imageFile, maxSize, quality);
quality -= 15;
} while (tempFile == null && quality >= worst);
}
return tempFile;
}
private File scaleImage(final File imageFile) {
File tempFile = null;
OutputStream os = null;
try {
Bitmap bitmap;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageFile.getAbsolutePath(), options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
ImageSize imageSize;
if (imageWidth < 720 || imageHeight < 720) {
imageSize = new ImageSize(imageHeight, imageWidth);
} else {
if (imageWidth > imageHeight) {
imageSize = new ImageSize((int) (720f * imageWidth / imageHeight), 720);
} else {
imageSize = new ImageSize(720, (int) (720f * imageHeight / imageWidth));
}
}
bitmap = ImageLoader.getInstance().loadImageSync(Uri.fromFile(imageFile).toString(), imageSize);
tempFile = File.createTempFile("uzlee-compress", ".jpg", this.getCacheDir());
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, imageSize.getWidth(), imageSize.getHeight(), true);
os = new FileOutputStream(tempFile);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.close();
Logger.i("length: %d, height: %d, width: %d", tempFile.length(), imageSize.getWidth(), imageSize.getHeight());
return tempFile;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (tempFile != null) {
tempFile.deleteOnExit();
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* @param imageFile
* @param maxFileLength
* @return
*/
private File compressImage(File imageFile, int maxFileLength) {
File outImage;
if (imageFile.length() < maxFileLength) {
outImage = imageFile;
} else {
outImage = scaleImage(imageFile);
if (outImage.length() >= maxFileLength) {
outImage = lowerQuality(outImage, maxFileLength);
}
}
return outImage;
}
public static class Draft {
public String activityTitle;
public String subject;
public String message;
public int tid;
public int fid;
public int pid;
public int uid;
public int no;
}
}