/*
* Copyright 2015 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.nimingban.ui.fragment;
import android.app.Activity;
import android.app.Dialog;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.support.v7.widget.Toolbar;
import android.text.Layout;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.webkit.MimeTypeMap;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.hippo.app.ProgressDialogBuilder;
import com.hippo.easyrecyclerview.EasyRecyclerView;
import com.hippo.easyrecyclerview.SimpleHolder;
import com.hippo.io.UriInputStreamPipe;
import com.hippo.nimingban.Constants;
import com.hippo.nimingban.Emoji;
import com.hippo.nimingban.NMBAppConfig;
import com.hippo.nimingban.NMBApplication;
import com.hippo.nimingban.R;
import com.hippo.nimingban.client.NMBClient;
import com.hippo.nimingban.client.NMBRequest;
import com.hippo.nimingban.client.ac.ACUrl;
import com.hippo.nimingban.client.ac.data.ACPostStruct;
import com.hippo.nimingban.client.ac.data.ACReplyStruct;
import com.hippo.nimingban.client.data.ACSite;
import com.hippo.nimingban.client.data.DisplayForum;
import com.hippo.nimingban.client.data.Site;
import com.hippo.nimingban.drawable.RoundSideDrawable;
import com.hippo.nimingban.network.SimpleCookieStore;
import com.hippo.nimingban.ui.DoodleActivity;
import com.hippo.nimingban.ui.DraftActivity;
import com.hippo.nimingban.ui.GalleryActivity2;
import com.hippo.nimingban.util.BitmapUtils;
import com.hippo.nimingban.util.DB;
import com.hippo.nimingban.util.ReadableTime;
import com.hippo.nimingban.util.Settings;
import com.hippo.nimingban.widget.NMBEditText;
import com.hippo.nimingban.widget.FontTextView;
import com.hippo.ripple.Ripple;
import com.hippo.util.DrawableManager;
import com.hippo.util.ExceptionUtils;
import com.hippo.widget.SimpleImageView;
import com.hippo.yorozuya.FileUtils;
import com.hippo.yorozuya.IOUtils;
import com.hippo.yorozuya.LayoutUtils;
import com.hippo.yorozuya.Messenger;
import com.hippo.yorozuya.ResourcesUtils;
import com.hippo.yorozuya.SimpleHandler;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
public final class TypeSendFragment extends BaseFragment implements View.OnClickListener {
private static final String TAG = TypeSendFragment.class.getSimpleName();
@IntDef({METHOD_REPLY, METHOD_CREATE_POST})
@Retention(RetentionPolicy.SOURCE)
private @interface Method {}
public static final String ACTION_REPLY = "com.hippo.nimingban.ui.TypeSendActivity.action.REPLY";
public static final String ACTION_CREATE_POST = "com.hippo.nimingban.ui.TypeSendActivity.action.CREATE_POST";
public static final String ACTION_REPORT = "com.hippo.nimingban.ui.TypeSendActivity.action.REPORT";
public static final String KEY_ACTION = "action";
public static final String KEY_TYPE = "type";
public static final String KEY_SITE = "site";
public static final String KEY_ID = "id";
public static final String KEY_TEXT = "text";
public static final String KEY_EXTRA_TEXT = Intent.EXTRA_TEXT;
public static final String KEY_EXTRA_STREAM = Intent.EXTRA_STREAM;
public static final int REQUEST_CODE_SELECT_IMAGE = 0;
public static final int REQUEST_CODE_DRAFT = 1;
public static final int REQUEST_CODE_DOODLE = 2;
public static final int REQUEST_CODE_CAMERA = 3;
public static final int METHOD_REPLY = 0;
public static final int METHOD_CREATE_POST = 1;
private List<DisplayForum> mForums;
private CharSequence[] mForumNames;
private boolean mReport;
@Method
private int mMethod = METHOD_CREATE_POST;
private Site mSite;
private String mId;
private String mTitleText;
private String mPresetText;
private Uri mSeletedImageUri;
private String mSeletedImageType;
private Bitmap mSeletedImageBitmap;
private Uri mCameraImageUri;
private NMBClient mNMBClient;
private NMBEditText mEditText;
private SimpleImageView mEmoji;
private View mImage;
private View mDraw;
private View mDraft;
private View mSend;
private View mImagePreview;
private ImageView mPreview;
private View mDelete;
private ImageView mIndicator;
private View mWritableItem;
private EditText mName;
private EditText mEmail;
private EditText mTitle;
private CheckBox mWatermark;
private TextView mForumText;
private EasyRecyclerView mEmojiKeyboard;
private Drawable mEmojiOff;
private Drawable mEmojiOn;
private Dialog mProgressDialog;
private NMBRequest mNMBRequest;
private Callback mCallback;
public void setCallback(Callback callback) {
mCallback = callback;
}
private boolean handleArgs(Bundle args) {
if (args == null) {
return false;
}
boolean share = false;
mReport = false;
String action = args.getString(KEY_ACTION);
String type = args.getString(KEY_TYPE);
if (ACTION_REPLY.equals(action)) {
mMethod = METHOD_REPLY;
mTitleText = getString(R.string.reply);
} else if (ACTION_CREATE_POST.equals(action)) {
mMethod = METHOD_CREATE_POST;
mTitleText = getString(R.string.create_post);
} else if (ACTION_REPORT.equals(action)) {
mMethod = METHOD_CREATE_POST;
mTitleText = getString(R.string.report);
mReport = true;
} else if (Intent.ACTION_SEND.equals(action) && type != null) {
mMethod = METHOD_CREATE_POST;
mTitleText = getString(R.string.create_post);
share = true;
} else {
return false;
}
if (share && type != null) {
// Share
// TODO for other site
mSite = ACSite.getInstance();
if ("text/plain".equals(type)) {
mPresetText = args.getString(KEY_EXTRA_TEXT);
return true;
} else if (type.startsWith("image/")) {
mSeletedImageUri = args.getParcelable(KEY_EXTRA_STREAM);
return true;
}
} else {
int site = args.getInt(KEY_SITE, -1);
String id = args.getString(KEY_ID);
mPresetText = args.getString(KEY_TEXT);
if (Site.isValid(site) && id != null) {
mSite = Site.fromId(site);
mId = id;
return true;
}
}
return false;
}
private void prepareForCreatePost() {
// Get all forums
mForums = DB.getACForums(false);
if (mForums.size() == 0) {
// TODO error
} else {
int n = mForums.size();
mForumNames = new CharSequence[n];
for (int i = 0; i < n; i++) {
mForumNames[i] = mForums.get(i).getNMBDisplayname();
}
}
// If no id, use first forum
if (mId == null) {
mId = mForums.get(0).id;
}
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNMBClient = NMBApplication.getNMBClient(getContext());
if (!handleArgs(getArguments())) {
mMethod = METHOD_CREATE_POST;
mSite = ACSite.getInstance();
mId = null;
mTitleText = getString(R.string.create_post);
mPresetText = null;
mSeletedImageUri = null;
}
// Show toast when report
if (mReport) {
Toast.makeText(getContext(), R.string.report_tip, Toast.LENGTH_SHORT).show();
}
// Prepare for create post
if (METHOD_CREATE_POST == mMethod) {
prepareForCreatePost();
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.activity_toolbar, container, false);
ViewGroup contentPanel = (ViewGroup) view.findViewById(R.id.content_panel);
ViewGroup contentView = (ViewGroup) inflater.inflate(R.layout.fragment_type_send, contentPanel, true);
view.setId(R.id.type_send);
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
toolbar.setTitle(mTitleText);
toolbar.setNavigationIcon(DrawableManager.getDrawable(getContext(), R.drawable.v_arrow_left_dark_x24));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCallback.onClickBack(TypeSendFragment.this);
}
});
mEditText = (NMBEditText) contentView.findViewById(R.id.edit_text);
mEmoji = (SimpleImageView) contentView.findViewById(R.id.emoji);
mImage = contentView.findViewById(R.id.image);
mDraw = contentView.findViewById(R.id.draw);
mDraft = contentView.findViewById(R.id.draft);
mSend = contentView.findViewById(R.id.send);
mImagePreview = contentView.findViewById(R.id.image_preview);
mPreview = (ImageView) mImagePreview.findViewById(R.id.preview);
mDelete = mImagePreview.findViewById(R.id.delete);
mWatermark = (CheckBox) mImagePreview.findViewById(R.id.watermark);
mIndicator = (ImageView) contentView.findViewById(R.id.indicator);
TextView moreWritableItemsText = (TextView) contentView.findViewById(R.id.more_writable_items_text);
View selectForum = contentView.findViewById(R.id.select_forum);
mForumText = (TextView) selectForum.findViewById(R.id.forum_text);
mWritableItem = contentView.findViewById(R.id.writable_item);
mName = (EditText) mWritableItem.findViewById(R.id.name);
mEmail = (EditText) mWritableItem.findViewById(R.id.email);
mTitle = (EditText) mWritableItem.findViewById(R.id.title);
mEmojiOff = DrawableManager.getDrawable(getContext(), R.drawable.v_emoji_off_dark);
mEmojiOn = DrawableManager.getDrawable(getContext(), R.drawable.v_emoji_on_dark);
mEmoji.setDrawable(mEmojiOff);
if (Settings.getFixEmojiDisplay()) {
mEditText.useCustomTypeface();
} else {
mEditText.useOriginalTypeface();
}
mEditText.requestFocus();
mEditText.requestFocusFromTouch();
// Show ime
SimpleHandler.getInstance().postDelayed(new Runnable() {
@Override
public void run() {
if (TypeSendFragment.this.isAdded()) {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Service.INPUT_METHOD_SERVICE);
imm.showSoftInput(mEditText, 0);
}
}
}, 300);
Ripple.addRipple(mEmoji, true);
Ripple.addRipple(mImage, true);
Ripple.addRipple(mDraw, true);
Ripple.addRipple(mDraft, true);
Ripple.addRipple(mSend, true);
Ripple.addRipple(mIndicator, ResourcesUtils.getAttrBoolean(getContext(), R.attr.dark));
mEmoji.setOnClickListener(this);
mImage.setOnClickListener(this);
mDraw.setOnClickListener(this);
mDraft.setOnClickListener(this);
mSend.setOnClickListener(this);
mDelete.setOnClickListener(this);
mIndicator.setOnClickListener(this);
mPreview.setOnClickListener(this);
// TODO Use AnimatedVectorDrawable
StateListDrawable drawable = new StateListDrawable();
drawable.addState(new int[]{android.R.attr.state_activated}, DrawableManager.getDrawable(getContext(), R.drawable.v_chevron_up_x24));
drawable.addState(new int[]{}, DrawableManager.getDrawable(getContext(), R.drawable.v_chevron_down_x24));
mIndicator.setImageDrawable(drawable);
mWatermark.setChecked(Settings.getWatermark());
if (METHOD_CREATE_POST == mMethod) {
moreWritableItemsText.setVisibility(View.GONE);
selectForum.setVisibility(View.VISIBLE);
mForumText.setBackgroundDrawable(new RoundSideDrawable(
ResourcesUtils.getAttrColor(getContext(), R.attr.colorRoundSide)));
int index = -1;
for (int i = 0, length = mForums.size(); i < length; i++) {
if (mId.equals(mForums.get(i).id)) {
index = i;
break;
}
}
if (index == -1) {
Toast.makeText(getContext(), getString(R.string.cant_find_the_forum, mId), Toast.LENGTH_SHORT).show();
setForum(0);
} else {
setForum(index);
}
// Can't select forum if you want report
if (!mReport) {
mForumText.setOnClickListener(this);
}
} else {
moreWritableItemsText.setVisibility(View.VISIBLE);
selectForum.setVisibility(View.GONE);
}
// Append preset text
if (!TextUtils.isEmpty(mPresetText)) {
mEditText.append(mPresetText);
}
handleSelectedImageUri(mSeletedImageUri);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (mPreview != null && mImagePreview != null && mEditText != null) {
clearImagePreview();
}
if (mNMBRequest != null) {
mNMBRequest.cancel();
mNMBRequest = null;
}
// Hide ime keyboard
View view = getActivity().getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
// Cancel FLAG_ALT_FOCUSABLE_IM
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
}
/**
* @return True for finish now, false for wait
*/
public boolean checkBeforeFinish() {
if (isEmojiKeyboardShown()) {
hideEmojiKeyboard();
return false;
}
final String text = mEditText.getText().toString().trim();
if (!text.isEmpty()) {
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
DB.addDraft(mEditText.getText().toString());
getFragmentHost().finishFragment(TypeSendFragment.this);
} else if (which == DialogInterface.BUTTON_NEUTRAL) {
getFragmentHost().finishFragment(TypeSendFragment.this);
}
}
};
AlertDialog dialog = new AlertDialog.Builder(getContext()).setMessage(R.string.save_text_draft)
.setPositiveButton(R.string.save, listener)
.setNegativeButton(android.R.string.cancel, null)
.setNeutralButton(R.string.dont_save, listener)
.show();
Button button = dialog.getButton(DialogInterface.BUTTON_NEUTRAL);
button.setTextColor(getResources().getColor(R.color.red_500));
return false;
} else {
return true;
}
}
private class EmojiKeyboardHelper extends RecyclerView.Adapter<SimpleHolder>
implements EasyRecyclerView.OnItemClickListener {
@Override
public SimpleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
SimpleHolder holder = new SimpleHolder(
getActivity().getLayoutInflater().inflate(R.layout.item_emoji, parent, false));
if (Settings.getFixEmojiDisplay()) {
((FontTextView) holder.itemView).useCustomTypeface();
} else {
((FontTextView) holder.itemView).useOriginalTypeface();
}
return holder;
}
@Override
public void onBindViewHolder(SimpleHolder holder, int position) {
((TextView) holder.itemView).setText(Emoji.EMOJI_NAME[position]);
}
@Override
public int getItemCount() {
return Emoji.COUNT;
}
@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
EditText editText = mEditText;
String emoji = Emoji.EMOJI_VALUE[position];
int start = Math.max(editText.getSelectionStart(), 0);
int end = Math.max(editText.getSelectionEnd(), 0);
editText.getText().replace(Math.min(start, end), Math.max(start, end),
emoji, 0, emoji.length());
return true;
}
}
private boolean isEmojiKeyboardShown() {
return mEmojiKeyboard != null && mEmojiKeyboard.getVisibility() == View.VISIBLE;
}
private void showEmojiKeyboard() {
mEmoji.setDrawable(mEmojiOn);
// Hide ime keyboard
View view = getActivity().getCurrentFocus();
if (view != null) {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
// Add FLAG_ALT_FOCUSABLE_IM
getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
view = getView();
if (view == null) {
return;
}
if (mEmojiKeyboard == null) {
ViewStub stub = (ViewStub) view.findViewById(R.id.stub);
mEmojiKeyboard = (EasyRecyclerView) stub.inflate();
EmojiKeyboardHelper helper = new EmojiKeyboardHelper();
mEmojiKeyboard.setAdapter(helper);
mEmojiKeyboard.setLayoutManager(new StaggeredGridLayoutManager(
3, StaggeredGridLayoutManager.VERTICAL));// TODO adjust by view width
mEmojiKeyboard.setSelector(Ripple.generateRippleDrawable(
getContext(), ResourcesUtils.getAttrBoolean(getContext(), R.attr.dark)));
mEmojiKeyboard.setOnItemClickListener(helper);
}
mEmojiKeyboard.setVisibility(View.VISIBLE);
// Show a stub dialog to make FLAG_ALT_FOCUSABLE_IM work
final Dialog dialog = new Dialog(getContext(), R.style.Theme_Dialog_DoNotDim);
dialog.show();
SimpleHandler.getInstance().post(new Runnable() {
@Override
public void run() {
dialog.dismiss();
}
});
}
private void hideEmojiKeyboard() {
mEmoji.setDrawable(mEmojiOff);
// Clear FLAG_ALT_FOCUSABLE_IM
getActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
// Show ime keyboard
SimpleHandler.getInstance().post(new Runnable() {
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Service.INPUT_METHOD_SERVICE);
imm.showSoftInput(mEditText, 0);
}
});
mEmojiKeyboard.setVisibility(View.GONE);
}
@Override
public void onClick(View v) {
if (mSend == v) {
if (mProgressDialog != null || mNMBRequest != null) {
return;
}
if (hasACCookies()) {
doAction();
} else {
tryGettingCookies();
}
} else if (mEmoji == v) {
if (isEmojiKeyboardShown()) {
hideEmojiKeyboard();
} else {
showEmojiKeyboard();
}
} else if (mImage == v) {
showImageDialog();
} else if (mDraft == v) {
Intent intent = new Intent(getActivity(), DraftActivity.class);
startActivityForResult(intent, REQUEST_CODE_DRAFT);
} else if (mDraw == v) {
Intent intent = new Intent(getActivity(), DoodleActivity.class);
startActivityForResult(intent, REQUEST_CODE_DOODLE);
} else if (mDelete == v) {
clearImagePreview();
} else if (mIndicator == v) {
if (mWritableItem.getVisibility() == View.VISIBLE) {
mWritableItem.setVisibility(View.GONE);
v.setActivated(false);
} else {
mWritableItem.setVisibility(View.VISIBLE);
v.setActivated(true);
}
} else if (v == mForumText) {
showForumDialog();
} else if (v == mPreview) {
if (mSeletedImageUri != null) {
Intent intent = new Intent(getActivity(), GalleryActivity2.class);
intent.setAction(GalleryActivity2.ACTION_IMAGE_FILE);
intent.putExtra(GalleryActivity2.KEY_UNI_FILE_URI, mSeletedImageUri);
startActivity(intent);
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if ((requestCode == REQUEST_CODE_SELECT_IMAGE || requestCode == REQUEST_CODE_DOODLE)
&& resultCode == Activity.RESULT_OK) {
handleSelectedImageUri(data.getData());
} else if (requestCode == REQUEST_CODE_CAMERA && resultCode == Activity.RESULT_OK) {
handleSelectedImageUri(mCameraImageUri);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void setForum(int position) {
DisplayForum forum = mForums.get(position);
mId = forum.getNMBId();
mForumText.setText(forum.getNMBDisplayname());
}
private boolean hasACCookies() {
SimpleCookieStore cookieStore = NMBApplication.getSimpleCookieStore(getContext());
URL url;
try {
url = new URL(ACUrl.HOST);
} catch (MalformedURLException e) {
// WTF ?
return true;
}
return cookieStore.contain(url, "userhash");
}
private void doAction() {
if (mMethod == METHOD_REPLY) {
doReply();
} else if (mMethod == METHOD_CREATE_POST) {
doCreatePost();
} else {
Log.d(TAG, "WTF?, an unknown method in TypeSendActivity " + mMethod);
}
}
private void showProgressDialog(int resId) {
if (mProgressDialog != null) {
return;
}
DialogInterface.OnClickListener clicklistener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (mNMBRequest != null) {
mNMBRequest.cancel();
mNMBRequest = null;
}
}
};
DialogInterface.OnDismissListener dismissListener = new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
mProgressDialog = null;
}
};
mProgressDialog = new ProgressDialogBuilder(getContext())
.setTitle(R.string.please_wait)
.setMessage(resId)
.setCancelable(false)
.setNegativeButton(android.R.string.cancel, clicklistener)
.setOnDismissListener(dismissListener)
.show();
}
private void doReply() {
ACReplyStruct struct = new ACReplyStruct();
struct.name = mName.getText().toString();
struct.email = mEmail.getText().toString();
struct.title = mTitle.getText().toString();
struct.content = mEditText.getText().toString();
struct.resto = mId;
struct.image = mSeletedImageUri != null ? new UriInputStreamPipe(
getContext().getApplicationContext(), mSeletedImageUri) : null;
struct.imageType = mSeletedImageType;
struct.water = mWatermark.isChecked();
NMBRequest request = new NMBRequest();
request.setSite(mSite);
request.setMethod(NMBClient.METHOD_REPLY);
request.setArgs(struct);
request.setCallback(new ActionListener(getContext(), mMethod, mId, struct.content, mSeletedImageBitmap));
mNMBClient.execute(request);
SimpleHandler.getInstance().post(new Runnable() {
@Override
public void run() {
getFragmentHost().finishFragment(TypeSendFragment.this);
}
});
}
private void doCreatePost() {
ACPostStruct struct = new ACPostStruct();
struct.name = mName.getText().toString();
struct.email = mEmail.getText().toString();
struct.title = mTitle.getText().toString();
struct.content = mEditText.getText().toString();
struct.fid = mId;
struct.image = mSeletedImageUri != null ? new UriInputStreamPipe(
getContext().getApplicationContext(), mSeletedImageUri) : null;
struct.imageType = mSeletedImageType;
struct.water = mWatermark.isChecked();
NMBRequest request = new NMBRequest();
request.setSite(mSite);
request.setMethod(NMBClient.METHOD_CREATE_POST);
request.setArgs(struct);
request.setCallback(new ActionListener(getContext(), mMethod, mId, struct.content, mSeletedImageBitmap));
mNMBClient.execute(request);
SimpleHandler.getInstance().post(new Runnable() {
@Override
public void run() {
getFragmentHost().finishFragment(TypeSendFragment.this);
}
});
}
private void getCookies() {
showProgressDialog(R.string.getting_cookies);
NMBRequest request = new NMBRequest();
mNMBRequest = request;
request.setSite(mSite);
request.setMethod(NMBClient.METHOD_GET_COOKIE);
request.setCallback(new GetCookieListener());
mNMBClient.execute(request);
}
private void tryGettingCookies() {
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
getCookies();
break;
case DialogInterface.BUTTON_NEUTRAL:
doAction();
break;
}
}
};
new AlertDialog.Builder(getContext()).setTitle(R.string.no_cookies)
.setMessage(R.string.no_cookies_ac)
.setPositiveButton(android.R.string.ok, listener)
.setNegativeButton(android.R.string.cancel, listener)
.setNeutralButton(R.string.i_dont_care, listener).show();
}
private void showImageDialog() {
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent;
switch (which) {
case 0:
intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,
getString(R.string.select_picture)), REQUEST_CODE_SELECT_IMAGE);
break;
case 1:
if (TextUtils.isEmpty(mEditText.getText().toString()) || mProgressDialog != null) {
break;
}
showProgressDialog(R.string.converting);
new AsyncTask<Void, Void, Uri>() {
@Override
protected Uri doInBackground(Void... params) {
return saveEditTextToImage();
}
@Override
protected void onPostExecute(Uri uri) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
if (uri != null) {
handleSelectedImageUri(uri);
} else {
Toast.makeText(getContext(), R.string.cant_create_image_file, Toast.LENGTH_SHORT).show();
}
}
}.execute();
break;
case 2:
File dir = NMBAppConfig.getPhotoDir();
if (dir == null)
break;
File temp = new File(dir, ReadableTime.getFilenamableTime(System.currentTimeMillis()) + ".jpg");
mCameraImageUri = Uri.fromFile(temp);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraImageUri);
startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA);
break;
}
}
};
new AlertDialog.Builder(getContext()).setItems(R.array.image_dialog, listener).show();
}
private void showForumDialog() {
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setForum(which);
}
};
new AlertDialog.Builder(getContext()).setItems(mForumNames, listener).show();
}
private void clearImagePreview() {
mSeletedImageUri = null;
mSeletedImageType = null;
mSeletedImageBitmap = null;
mPreview.setImageDrawable(null);
mImagePreview.setVisibility(View.GONE);
ViewGroup.LayoutParams lp = mEditText.getLayoutParams();
if (lp == null) {
lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
} else{
lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
}
mEditText.setLayoutParams(lp);
}
private void setImagePreview(Uri uri, String type, Bitmap bitmap) {
mSeletedImageUri = uri;
mSeletedImageType = type;
mSeletedImageBitmap = bitmap;
mPreview.setImageBitmap(bitmap);
mImagePreview.setVisibility(View.VISIBLE);
ViewGroup.LayoutParams lp = mEditText.getLayoutParams();
if (lp == null) {
lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
} else{
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
}
mEditText.setLayoutParams(lp);
}
// TODO do not do it in UI thread
private boolean handleSelectedImageUri(Uri uri) {
if (uri == null) {
return false;
}
ContentResolver resolver = getContext().getContentResolver();
String type = resolver.getType(uri);
if (type == null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
FileUtils.getExtensionFromFilename(uri.toString()));
}
int maxSize = LayoutUtils.dp2pix(getContext(), 256);
Bitmap bitmap = BitmapUtils.decodeStream(new UriInputStreamPipe(getContext(), uri), maxSize, maxSize);
if (bitmap != null) {
setImagePreview(uri, type, bitmap);
return true;
}
return false;
}
private Uri saveEditTextToImage() {
EditText v = mEditText;
Layout layout = v.getLayout();
if (layout == null) {
return null;
}
int padding = LayoutUtils.dp2pix(getContext(), 16);
Bitmap bitmap;
try {
bitmap = Bitmap.createBitmap(layout.getWidth() + (2 * padding),
layout.getHeight() + (2 * padding), Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError e) {
return null;
}
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(ResourcesUtils.getAttrColor(getContext(), R.attr.colorPure));
canvas.translate(padding, padding);
layout.draw(canvas);
File file = NMBAppConfig.createTempFile("png");
if (file == null) {
return null;
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
return Uri.fromFile(file);
} catch (IOException e) {
return null;
} finally {
IOUtils.closeQuietly(fos);
}
}
private static class ActionListener implements NMBClient.Callback<Void> {
private Context mContext;
@Method
private int mMethod;
private String mId;
private String mContent;
private Bitmap mImage;
public ActionListener(Context context, @Method int method, String id, String content, Bitmap image) {
mContext = context.getApplicationContext();
mMethod = method;
mId = id;
mContent = content;
mImage = image;
Toast.makeText(context, method == METHOD_REPLY ? R.string.start_reply : R.string.start_creating_post, Toast.LENGTH_SHORT).show();
}
private void addToRecord(String image) {
int type;
String recordid = null;
String postid;
String content = mContent;
if (mMethod == METHOD_REPLY) {
type = DB.AC_RECORD_REPLY;
postid = mId;
} else {
type = DB.AC_RECORD_POST;
postid = null;
}
DB.addACRecord(type, recordid, postid, content, image);
// Notify RecordActivity
Messenger.getInstance().notify(Constants.MESSENGER_ID_UPDATE_RECORD, null);
}
@Override
public void onSuccess(Void result) {
if (mImage != null) {
// Save image file in new thread
// TODO looks ugly
new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void[] params) {
String image = null;
if (mImage != null) {
File imageFile = NMBAppConfig.createRecordImageFile();
if (imageFile != null) {
try {
mImage.compress(Bitmap.CompressFormat.PNG,
100, new FileOutputStream(imageFile));
image = imageFile.getPath();
} catch (FileNotFoundException e) {
// Ignore
}
}
mImage = null;
}
return image;
}
@Override
protected void onPostExecute(String image) {
addToRecord(image);
}
}.execute();
} else {
addToRecord(null);
}
SimpleHandler.getInstance().postDelayed(new Runnable() {
@Override
public void run() {
Toast.makeText(mContext, mMethod == METHOD_REPLY ? R.string.reply_successfully :
R.string.create_post_successfully, Toast.LENGTH_SHORT).show();
Messenger.getInstance().notify(METHOD_REPLY == mMethod ? Constants.MESSENGER_ID_REPLY : Constants.MESSENGER_ID_CREATE_POST, mId);
}
}, 1000); // Wait a seconds to make sure the server has done with the post
}
@Override
public void onFailure(final Exception e) {
mImage = null;
if (!TextUtils.isEmpty(mContent)) {
DB.addDraft(mContent);
}
SimpleHandler.getInstance().postDelayed(new Runnable() {
@Override
public void run() {
Context context = mContext;
Toast.makeText(context, context.getString(mMethod == METHOD_REPLY ? R.string.reply_failed :
R.string.create_post_failed) + "\n" +
ExceptionUtils.getReadableString(context, e), Toast.LENGTH_SHORT).show();
Messenger.getInstance().notify(METHOD_REPLY == mMethod ?
Constants.MESSENGER_ID_REPLY : Constants.MESSENGER_ID_CREATE_POST, mId);
}
}, 1000); // Wait a seconds to make sure the server has done with the post
}
@Override
public void onCancel() {
mImage = null;
Log.d(TAG, "ActionListener onCancel");
}
}
private class GetCookieListener implements NMBClient.Callback<Boolean> {
@Override
public void onSuccess(Boolean result) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
mNMBRequest = null;
Toast.makeText(getContext(), R.string.got_cookies, Toast.LENGTH_SHORT).show();
doAction();
}
@Override
public void onFailure(Exception e) {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
mNMBRequest = null;
Toast.makeText(getContext(), getString(R.string.cant_get_cookies) + "\n" +
ExceptionUtils.getReadableString(getContext(), e), Toast.LENGTH_SHORT).show();
}
@Override
public void onCancel() {
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
mNMBRequest = null;
Log.d(TAG, "GetCookieListener onCancel");
}
}
public interface Callback {
void onClickBack(TypeSendFragment fragment);
}
}