package net.coding.program.project.detail.topic;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AlertDialog;
import android.text.Html;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import com.loopj.android.http.RequestParams;
import net.coding.program.FootUpdate;
import net.coding.program.R;
import net.coding.program.common.ClickSmallImage;
import net.coding.program.common.Global;
import net.coding.program.common.MyImageGetter;
import net.coding.program.common.PhotoOperate;
import net.coding.program.common.StartActivity;
import net.coding.program.common.TextWatcherAt;
import net.coding.program.common.base.MyJsonResponse;
import net.coding.program.common.enter.EnterLayout;
import net.coding.program.common.enter.ImageCommentLayout;
import net.coding.program.common.photopick.ImageInfo;
import net.coding.program.common.ui.BackActivity;
import net.coding.program.common.umeng.UmengEvent;
import net.coding.program.maopao.BaseUsersArea;
import net.coding.program.maopao.item.ImageCommentHolder;
import net.coding.program.model.AttachmentFileObject;
import net.coding.program.model.TopicLabelObject;
import net.coding.program.model.TopicObject;
import net.coding.program.model.UserObject;
import net.coding.program.model.request.Project;
import net.coding.program.project.detail.TopicAddActivity_;
import net.coding.program.project.detail.TopicLabelActivity;
import net.coding.program.project.detail.TopicLabelActivity_;
import net.coding.program.project.detail.TopicLabelBar;
import net.coding.program.third.EmojiFilter;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.Extra;
import org.androidannotations.annotations.InstanceState;
import org.androidannotations.annotations.OnActivityResult;
import org.androidannotations.annotations.OptionsItem;
import org.androidannotations.annotations.ViewById;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@EActivity(R.layout.activity_topic_list_detail)
public class TopicListDetailActivity extends BackActivity implements StartActivity, SwipeRefreshLayout.OnRefreshListener, FootUpdate.LoadMore {
private static final String TAG_TOPIC_COMMENTS = "TAG_TOPIC_COMMENTS";
final int RESULT_AT = 1;
final int RESULT_EDIT = 2;
final int RESULT_LABEL = 3;
private static final int RESULT_MODIFY_WATCHER = 4;
final String TAG_DELETE_TOPIC_COMMENT = "TAG_DELETE_TOPIC_COMMENT";
final String TAG_DELETE_TOPIC = "TAG_DELETE_TOPIC";
private final String HOST_COMMENT_SEND = Global.HOST_API + "/project/%s/topic?parent=%s";
private final ClickSmallImage onClickImage = new ClickSmallImage(this);
@InstanceState
protected boolean saveTopicWhenLoaded;
@Extra
TopicObject topicObject;
@Extra
TopicDetailParam mJumpParam;
@ViewById
ListView listView;
private WatchHelp watchHelp;
private CommentHelp commentHelp;
@ViewById
SwipeRefreshLayout swipeRefreshLayout;
// EnterLayout mEnterLayout;
ImageCommentLayout mEnterComment;
String owerGlobar = "";
String urlCommentSend = HOST_COMMENT_SEND;
String URI_DELETE_TOPIC_LABEL = Global.HOST_API + "/topic/%s/label/%s";
String urlTopic = "";
ArrayList<TopicObject> mData = new ArrayList<>();
Intent mResultData = new Intent();
View mListHead;
String tagUrlCommentPhoto = "";
HashMap<String, String> mSendedImages = new HashMap<>();
View.OnClickListener mOnClickSend = v -> sendCommentAll();
View.OnClickListener onClickComment = v -> {
final TopicObject comment = (TopicObject) v.getTag();
if (comment.isMy()) {
new AlertDialog.Builder(TopicListDetailActivity.this)
.setTitle("删除评论")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String url = String.format(Global.HOST_API + "/project/%s/topic/%s/comment/%s", topicObject.project.getId(), topicObject.id, comment.id);
deleteNetwork(url, TAG_DELETE_TOPIC_COMMENT, comment.id);
}
})
.setNegativeButton("取消", null)
.show();
} else {
EnterLayout enterLayout = mEnterComment.getEnterLayout();
EditText message = enterLayout.content;
message.setHint("回复 " + comment.owner.name);
message.setTag(comment);
enterLayout.popKeyboard();
enterLayout.restoreLoad(comment);
}
};
MyImageGetter myImageGetter = new MyImageGetter(this);
BaseAdapter baseAdapter = new BaseAdapter() {
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageCommentHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.activity_task_comment_much_image_divide, parent, false);
holder = new ImageCommentHolder(convertView, onClickComment, myImageGetter, getImageLoad(), mOnClickUser, onClickImage);
convertView.setTag(R.id.layout, holder);
} else {
holder = (ImageCommentHolder) convertView.getTag(R.id.layout);
}
TopicObject data = (TopicObject) getItem(position);
holder.setContent(data);
// convertView.findViewById(R.id.customDivide)
loadMore();
return convertView;
}
};
private TopicLabelBar labelBar;
private int currentLabelId;
private TextView textViewCommentCount;
@AfterViews
protected final void initTopicListDetailActivity() {
swipeRefreshLayout.setOnRefreshListener(this);
swipeRefreshLayout.setColorSchemeResources(R.color.green);
mFootUpdate.init(listView, mInflater, this);
loadData();
mEnterComment = new ImageCommentLayout(this, mOnClickSend, getImageLoad());
prepareComment();
}
@Override
public void onRefresh() {
loadData();
}
@Override
public void loadMore() {
getNextPageNetwork(topicObject.getHttpComments(), TAG_TOPIC_COMMENTS);
}
private void loadData() {
if (mJumpParam != null) {
urlTopic = String.format(Global.HOST_API + "/topic/%s?", mJumpParam.mTopic);
getNetwork(urlTopic, urlTopic);
} else if (topicObject != null) {
owerGlobar = topicObject.owner.global_key;
setActionBarTitle(topicObject.project.name);
urlTopic = String.format(Global.HOST_API + "/topic/%s?", topicObject.id);
getNetwork(urlTopic, urlTopic);
} else {
finish();
}
}
private void initData() {
setActionBarTitle(topicObject.project.name);
updateHeadData();
if (saveTopicWhenLoaded) {
saveTopicWhenLoaded = false;
mResultData.putExtra("topic", topicObject);
}
urlCommentSend = String.format(urlCommentSend, topicObject.project_id, topicObject.id);
loadMore();
}
@OnActivityResult(RESULT_AT)
void onResultAt(int requestCode, Intent data) {
if (requestCode == Activity.RESULT_OK) {
String name = data.getStringExtra("name");
mEnterComment.getEnterLayout().insertText(name);
mEnterComment.getEnterLayout().popKeyboard();
}
}
@OnActivityResult(RESULT_EDIT)
void onResultEdit() {
// 分支情况太多,如编辑状态下可进入标签管理删掉目前用的标签,
// 回到编辑后又重复进入修改名字或者继续添加删除,最后还可以不保存返回
// 除非一直把全局labels的所有状态通过intents传递,否则原状态难以维持,这里只好直接重新刷新了,
// 会慢一些但状态肯定是对的,可能影响回复列表页数
saveTopicWhenLoaded = true;
onRefresh();
}
@OnActivityResult(RESULT_LABEL)
void onResultLabel(int code, @OnActivityResult.Extra ArrayList<TopicLabelObject> labels) {
if (code == RESULT_OK) {
topicObject.labels = labels;
updateLabels(topicObject.labels);
mResultData.putExtra("topic", topicObject);
}
}
@OnActivityResult(ImageCommentLayout.RESULT_REQUEST_COMMENT_IMAGE)
protected final void commentImage(int result, Intent data) {
if (result == RESULT_OK) {
mEnterComment.onActivityResult(
ImageCommentLayout.RESULT_REQUEST_COMMENT_IMAGE,
data);
}
}
@OnActivityResult(ImageCommentLayout.RESULT_REQUEST_COMMENT_IMAGE_DETAIL)
protected final void commentImageDetail(int result, Intent data) {
if (result == RESULT_OK) {
mEnterComment.onActivityResult(
ImageCommentLayout.RESULT_REQUEST_COMMENT_IMAGE_DETAIL,
data);
}
}
@OnActivityResult(RESULT_MODIFY_WATCHER)
void onResultModifyWatcher(int code, @OnActivityResult.Extra ArrayList<UserObject> resultData) {
if (code == RESULT_OK) {
watchers = resultData;
watchHelp.setData(this.watchers);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (topicObject != null) {
int menuRes;
if (topicObject.isMy()) {
menuRes = R.menu.topic_detail_modify;
} else {
menuRes = R.menu.common_more_copy_link;
}
getMenuInflater().inflate(menuRes, menu);
}
return super.onCreateOptionsMenu(menu);
}
@OptionsItem
void action_edit() {
TopicAddActivity_.intent(this).projectObject(topicObject.project).topicObject(topicObject).startForResult(RESULT_EDIT);
}
@Override
public void onBackPressed() {
if (mResultData.getExtras() == null) {
setResult(Activity.RESULT_CANCELED);
} else {
setResult(Activity.RESULT_OK, mResultData);
}
super.onBackPressed();
}
@OptionsItem
void action_delete() {
showDialog("讨论", "删除讨论?", (dialog, which) -> deleteNetwork(String.format(Global.HOST_API + "/topic/%s", topicObject.id), TAG_DELETE_TOPIC));
}
@OptionsItem
protected final void action_copy() {
final String urlTemplate = Global.HOST + "/u/%s/p/%s/topic/%d";
String url = String.format(urlTemplate, topicObject.project.owner_user_name, topicObject.project.name, topicObject.id);
Global.copy(this, url);
showButtomToast("已复制 " + url);
}
void updateDisplayCommentCount() {
String commentCount = String.format("%s 条评论", topicObject.child_count);
textViewCommentCount.setText(commentCount);
}
private void updateHeadData() {
mEnterComment.getEnterLayout().content.addTextChangedListener(new TextWatcherAt(this, this, RESULT_AT, topicObject.project));
if (mListHead == null) {
mListHead = mInflater.inflate(R.layout.activity_project_topic_comment_list_head, listView, false);
listView.addHeaderView(mListHead);
watchHelp = new WatchHelp(mListHead);
commentHelp = new CommentHelp(mListHead);
}
ImageView icon = (ImageView) mListHead.findViewById(R.id.icon);
iconfromNetwork(icon, topicObject.owner.avatar);
icon.setTag(topicObject.owner.global_key);
icon.setOnClickListener(mOnClickUser);
TextView topicTitleTextView = ((TextView) mListHead.findViewById(R.id.title));
topicTitleTextView.setText(topicObject.title);
final String format = "<font color='#3bbd79'>%s</font> 发布于%s";
String timeString = String.format(format, topicObject.owner.name, Global.dayToNow(topicObject.updated_at));
((TextView) mListHead.findViewById(R.id.time)).setText(Html.fromHtml(timeString));
((TextView) mListHead.findViewById(R.id.referenceId)).setText(topicObject.getRefId());
updateLabels(topicObject.labels);
WebView webView = (WebView) mListHead.findViewById(R.id.comment);
Global.setWebViewContent(webView, "topic-android.html", topicObject.content);
textViewCommentCount = (TextView) mListHead.findViewById(R.id.commentCount);
updateDisplayCommentCount();
Spinner spinner = (Spinner) mListHead.findViewById(R.id.spinner);
spinner.setAdapter(new TopicSortAdapter(this));
spinner.setSelection(0, true); // 一定要写,否则会自动调用一次 onItemSelected
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
topicObject.setSortOld(TopicObject.SORT_OLD);
} else {
topicObject.setSortOld(TopicObject.SORT_NEW);
}
initSetting();
loadMore();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
mListHead.setOnClickListener(v -> {
prepareComment();
mEnterComment.getEnterLayout().popKeyboard();
});
listView.setAdapter(baseAdapter);
}
private void updateLabels(List<TopicLabelObject> labels) {
if (labelBar == null) {
labelBar = (TopicLabelBar) mListHead.findViewById(R.id.labelBar);
}
labelBar.bind(labels, new TopicLabelBar.Controller() {
@Override
public boolean canShowLabels() {
return true;
}
@Override
public boolean canEditLabels() {
return true;
}
@Override
public void onEditLabels(TopicLabelBar view) {
TopicLabelActivity_.intent(TopicListDetailActivity.this)
.labelType(TopicLabelActivity.LabelType.Topic)
.projectPath(topicObject.project.getProjectPath())
.id(topicObject.id)
.checkedLabels(topicObject.labels)
.startForResult(RESULT_LABEL);
}
@Override
public void onRemoveLabel(TopicLabelBar view, int labelId) {
currentLabelId = labelId;
String url = String.format(URI_DELETE_TOPIC_LABEL, topicObject.id, labelId);
deleteNetwork(url, URI_DELETE_TOPIC_LABEL);
}
});
}
private ArrayList<UserObject> watchers = new ArrayList<>(0);
private void updateWatchFromNetwork() {
if (topicObject == null) {
return;
}
Project.topicWatchList(this, topicObject.project.getId(), topicObject.id, new MyJsonResponse(this) {
@Override
public void onMySuccess(JSONObject response) {
super.onMySuccess(response);
watchers.clear();
JSONArray jsonArray = response.optJSONObject("data").optJSONArray("list");
for (int i = 0; i < jsonArray.length(); ++i) {
UserObject user = new UserObject(jsonArray.optJSONObject(i));
watchers.add(user);
}
watchHelp.setData(watchers);
}
@Override
public void onMyFailure(JSONObject response) {
super.onMyFailure(response);
}
});
}
private void prepareComment() {
EditText message = mEnterComment.getEnterLayout().content;
message.setHint("发表评论");
message.setTag(topicObject);
mEnterComment.getEnterLayout().restoreLoad(topicObject);
}
private void sendCommentAll() {
showProgressBar(true);
ArrayList<ImageInfo> photos = mEnterComment.getPickPhotos();
for (ImageInfo item : photos) {
String imagePath = item.path;
if (!mSendedImages.containsKey(imagePath)) {
try {
String url = topicObject.project.getHttpUploadPhoto();
RequestParams params = new RequestParams();
params.put("dir", 0);
File fileImage = new File(imagePath);
if (!Global.isGifByFile(fileImage)) {
Uri uri = Uri.parse(imagePath);
fileImage = new PhotoOperate(this).scal(uri);
}
params.put("file", fileImage);
tagUrlCommentPhoto = imagePath; // tag必须不同,否则无法调用下一次
postNetwork(url, params, tagUrlCommentPhoto, 0, imagePath);
showProgressBar(true);
} catch (Exception e) {
showProgressBar(false);
}
return;
}
}
String send = mEnterComment.getEnterLayout().getContent();
for (ImageInfo item : photos) {
send += mSendedImages.get(item.path);
}
sendComment(send);
}
private void sendComment(String send) {
if (urlCommentSend.equals(HOST_COMMENT_SEND)) {
return;
}
String input = send;
if (EmojiFilter.containsEmptyEmoji(this, input)) {
showProgressBar(false);
return;
}
RequestParams params = new RequestParams();
TopicObject comment = (TopicObject) mEnterComment.getEnterLayout().content.getTag();
if (comment != null && comment.parent_id != 0) {
input = Global.encodeInput(comment.owner.name, input);
} else {
input = Global.encodeInput("", input);
}
params.put("content", input);
postNetwork(urlCommentSend, params, urlCommentSend, 0, comment);
showProgressBar(R.string.sending_comment);
}
@Override
public void parseJson(int code, JSONObject respanse, String tag, int pos, Object data) throws JSONException {
if (tag.equals(TAG_TOPIC_COMMENTS)) {
if (code == 0) {
if (isLoadingFirstPage(tag)) {
mData.clear();
}
JSONArray jsonArray = respanse.optJSONObject("data").optJSONArray("list");
for (int i = 0; i < jsonArray.length(); ++i) {
TopicObject commnet = new TopicObject(jsonArray.getJSONObject(i));
mData.add(commnet);
}
} else {
showErrorMsg(code, respanse);
}
commentHelp.update();
baseAdapter.notifyDataSetChanged();
mFootUpdate.updateState(code, isLoadingLastPage(tag), mData.size());
} else if (tag.equals(urlCommentSend)) {
showProgressBar(false);
if (code == 0) {
umengEvent(UmengEvent.TOPIC, "新建讨论评论");
JSONObject jsonObject = respanse.getJSONObject("data");
++topicObject.child_count;
mResultData.putExtra("child_count", topicObject.child_count);
mResultData.putExtra("topic_id", topicObject.id);
updateDisplayCommentCount();
mData.add(new TopicObject(jsonObject));
EnterLayout enterLayout = mEnterComment.getEnterLayout();
enterLayout.restoreDelete(data);
mEnterComment.clearContent();
baseAdapter.notifyDataSetChanged();
showButtomToast("发送评论成功");
commentHelp.update();
} else {
showErrorMsg(code, respanse);
baseAdapter.notifyDataSetChanged();
}
} else if (tag.equals(urlTopic)) {
swipeRefreshLayout.setRefreshing(false);
if (code == 0) {
topicObject = new TopicObject(respanse.getJSONObject("data"));
initData();
updateWatchFromNetwork();
invalidateOptionsMenu();
} else {
showErrorMsg(code, respanse);
}
} else if (tag.equals(TAG_DELETE_TOPIC_COMMENT)) {
int itemId = (int) data;
if (code == 0) {
umengEvent(UmengEvent.TOPIC, "删除讨论评论");
for (int i = 0; i < mData.size(); ++i) {
if (itemId == mData.get(i).id) {
mData.remove(i);
--topicObject.child_count;
mResultData.putExtra("child_count", topicObject.child_count);
mResultData.putExtra("topic_id", topicObject.id);
updateDisplayCommentCount();
baseAdapter.notifyDataSetChanged();
break;
}
}
commentHelp.update();
} else {
showButtomToast(R.string.delete_fail);
}
} else if (tag.equals(TAG_DELETE_TOPIC)) {
if (code == 0) {
umengEvent(UmengEvent.TOPIC, "删除讨论");
mResultData.putExtra("id", topicObject.id);
setResult(RESULT_OK, mResultData);
finish();
} else {
showButtomToast("删除讨论失败");
}
} else if (tag.equals(tagUrlCommentPhoto)) {
if (code == 0) {
String fileUri;
if (topicObject.project.isPublic()) {
fileUri = respanse.optString("data", "");
} else {
AttachmentFileObject fileObject = new AttachmentFileObject(respanse.optJSONObject("data"));
fileUri = fileObject.owner_preview;
}
String mdPhotoUri = String.format("\n![图片](%s)", fileUri);
mSendedImages.put((String) data, mdPhotoUri);
sendCommentAll();
} else {
showErrorMsg(code, respanse);
showProgressBar(false);
}
} else if (URI_DELETE_TOPIC_LABEL.equals(tag)) {
if (code == 0) {
umengEvent(UmengEvent.PROJECT, "删除标签");
labelBar.removeLabel(currentLabelId);
if (topicObject.labels != null) {
for (TopicLabelObject item : topicObject.labels) {
if (item.id == currentLabelId) {
topicObject.labels.remove(item);
break;
}
}
}
mResultData.putExtra("topic", topicObject);
} else {
currentLabelId = -1;
showErrorMsg(code, respanse);
showProgressBar(false);
}
}
}
private class WatchHelp {
View emptyWatchLayout;
View watchUsersLayout;
TextView watchCount;
LinearLayout watchUsers;
BaseUsersArea userArea;
public WatchHelp(View headView) {
emptyWatchLayout = (View) headView.findViewById(R.id.emptyWatchLayout);
TextView emptyWatchAdd = (TextView) headView.findViewById(R.id.emptyWatchAdd);
emptyWatchAdd.setText(Html.fromHtml("尚未添加任何关注者, <font color='#3bbd79'>去添加</font>"));
emptyWatchAdd.setOnClickListener(clickAddWatch);
watchUsersLayout = (View) headView.findViewById(R.id.watchUsersLayout);
watchCount = (TextView) headView.findViewById(R.id.watchCount);
View watchListAdd = (View) headView.findViewById(R.id.watchListAdd);
watchListAdd.setOnClickListener(clickAddWatch);
watchUsers = (LinearLayout) headView.findViewById(R.id.watchUsers);
userArea = new BaseUsersArea(watchUsers, null, TopicListDetailActivity.this, mOnClickUser, getImageLoad());
}
public void setData(List<UserObject> watches) {
if (watches.isEmpty()) {
emptyWatchLayout.setVisibility(View.VISIBLE);
watchUsersLayout.setVisibility(View.GONE);
} else {
emptyWatchLayout.setVisibility(View.GONE);
watchUsersLayout.setVisibility(View.VISIBLE);
watchCount.setText(String.format("%s 人关注", watches.size()));
watchUsers.setTag(watches);
userArea.displayLikeUser();
}
}
}
private class CommentHelp {
View commentButton;
View commentSort;
public CommentHelp(View v) {
commentButton = v.findViewById(R.id.topicCommentButton);
commentSort = v.findViewById(R.id.spinner);
commentButton.setOnClickListener(v1 -> {
prepareComment();
mEnterComment.getEnterLayout().popKeyboard();
});
}
public void update() {
if (mData.isEmpty()) {
commentButton.setVisibility(View.VISIBLE);
commentSort.setVisibility(View.GONE);
} else {
commentButton.setVisibility(View.GONE);
commentSort.setVisibility(View.VISIBLE);
}
}
}
View.OnClickListener clickAddWatch = v -> {
WatcherListActivity_.intent(TopicListDetailActivity.this)
.mProjectObjectId(topicObject.project.getId())
.topicId(topicObject.id)
.watchers(watchers)
.startForResult(RESULT_MODIFY_WATCHER);
};
public static class TopicDetailParam implements Serializable {
public String mUser;
public String mProject;
public String mTopic;
public TopicDetailParam(String mUser, String mProject, String mTopic) {
this.mUser = mUser;
this.mProject = mProject;
this.mTopic = mTopic;
}
}
}