package com.yaoyumeng.v2ex.ui.fragment;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import com.melnykov.fab.FloatingActionButton;
import com.melnykov.fab.ScrollDirectionListener;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.twotoasters.jazzylistview.effects.FadeEffect;
import com.twotoasters.jazzylistview.recyclerview.JazzyRecyclerViewScrollListener;
import com.yaoyumeng.v2ex.Application;
import com.yaoyumeng.v2ex.R;
import com.yaoyumeng.v2ex.api.HttpRequestHandler;
import com.yaoyumeng.v2ex.api.V2EXManager;
import com.yaoyumeng.v2ex.database.V2EXDataSource;
import com.yaoyumeng.v2ex.model.MemberModel;
import com.yaoyumeng.v2ex.model.NodeModel;
import com.yaoyumeng.v2ex.model.ReplyModel;
import com.yaoyumeng.v2ex.model.TopicModel;
import com.yaoyumeng.v2ex.model.TopicWithReplyListModel;
import com.yaoyumeng.v2ex.model.V2EXDateModel;
import com.yaoyumeng.v2ex.model.V2EXModel;
import com.yaoyumeng.v2ex.ui.BaseActivity;
import com.yaoyumeng.v2ex.ui.NodeActivity;
import com.yaoyumeng.v2ex.ui.TopicCommentActivity;
import com.yaoyumeng.v2ex.ui.UserActivity;
import com.yaoyumeng.v2ex.ui.adapter.HeaderViewRecyclerAdapter;
import com.yaoyumeng.v2ex.ui.adapter.ReplyAdapter;
import com.yaoyumeng.v2ex.ui.social.ShareHelper;
import com.yaoyumeng.v2ex.ui.widget.EnterLayout;
import com.yaoyumeng.v2ex.ui.widget.FootUpdate;
import com.yaoyumeng.v2ex.ui.widget.RichTextView;
import com.yaoyumeng.v2ex.utils.InputUtils;
import com.yaoyumeng.v2ex.utils.MessageUtils;
import com.yaoyumeng.v2ex.utils.OnScrollToBottomListener;
import java.util.ArrayList;
public class TopicFragment extends BaseFragment
implements HttpRequestHandler<ArrayList<ReplyModel>>, OnScrollToBottomListener {
public static final int REQUEST_COMMENT = 100;
RecyclerView mRecyclerView;
View mHeader;
ReplyAdapter mAdapter;
HeaderViewRecyclerAdapter mHeaderAdapter;
RecyclerView.LayoutManager mLayoutManager;
SwipeRefreshLayout mSwipeLayout;
FloatingActionButton mScrollTopButton;
TopicModel mTopic;
int mTopicId;
MenuItem mStarItem;
MenuItem mUnStarItem;
MenuItem mReplyItem;
EnterLayout mEnterLayout;
V2EXDataSource mDataSource = Application.getDataSource();
boolean mIsStarred;
int mPage = 1;
boolean mNoMore = true;
Application mApp = Application.getInstance();
View.OnClickListener onClickSend = new View.OnClickListener() {
@Override
public void onClick(View v) {
String content = mEnterLayout.getContent();
if (content.isEmpty()) {
MessageUtils.showToast(getActivity(), getString(R.string.topic_comment_not_empty));
return;
}
InputUtils.popSoftkeyboard(getActivity(), mEnterLayout.content, false);
((BaseActivity) getActivity()).showProgressBar(R.string.topic_comment_working);
V2EXManager.replyCreateWithTopicId(getActivity(), mTopicId, content, new CommentHelper());
}
};
ReplyAdapter.OnItemCommentClickListener onItemCommentClick = new ReplyAdapter.OnItemCommentClickListener() {
@Override
public void onItemCommentClick(ReplyModel replyObj) {
prepareAddComment(replyObj, true);
}
};
public TopicFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_topic, container, false);
mHeader = inflater.inflate(R.layout.item_topic_more, container, false);
mEnterLayout = new EnterLayout(getActivity(), rootView, onClickSend);
mEnterLayout.setDefaultHint(getString(R.string.topic_comment_default_hint));
mEnterLayout.hide();
mScrollTopButton = (FloatingActionButton)rootView.findViewById(R.id.scroll_top_button);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.list_replies);
mAdapter = new ReplyAdapter(getActivity(), onItemCommentClick, this);
RecyclerView.LayoutParams headerLayoutParams = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mHeader.setLayoutParams(headerLayoutParams);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mHeaderAdapter = new HeaderViewRecyclerAdapter(mAdapter);
mHeaderAdapter.addHeaderView(mHeader);
mRecyclerView.setAdapter(mHeaderAdapter);
mScrollTopButton.attachToRecyclerView(mRecyclerView, new ScrollDirectionListener() {
@Override
public void onScrollDown() {
mScrollTopButton.hide();
}
@Override
public void onScrollUp() {
if (mScrollTopButton.getVisibility() != View.VISIBLE)
mScrollTopButton.setVisibility(View.VISIBLE);
mScrollTopButton.show();
}
});
mScrollTopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRecyclerView.smoothScrollToPosition(0);
mScrollTopButton.hide();
}
});
if (mApp.isShowEffectFromCache()) {
JazzyRecyclerViewScrollListener scrollListener = new JazzyRecyclerViewScrollListener();
mRecyclerView.setOnScrollListener(scrollListener);
scrollListener.setTransitionEffect(new FadeEffect());
}
mFootUpdate.init(mHeaderAdapter, LayoutInflater.from(getActivity()), new FootUpdate.LoadMore() {
@Override
public void loadMore() {
requestRepliesOfNextPage();
}
});
mSwipeLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_container);
mSwipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
mPage = 1;
getTopicData(true);
}
});
mSwipeLayout.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
mSwipeLayout.setProgressViewOffset(false, 0,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (getArguments().containsKey("model")) {
mTopic = getArguments().getParcelable("model");
mTopicId = mTopic.id;
setupHeaderView();
mSwipeLayout.setRefreshing(true);
getReplyData(false);
} else if (getArguments().containsKey("topic_id")) {
mTopicId = getArguments().getInt("topic_id");
mSwipeLayout.setRefreshing(true);
getTopicData(false);
} else {
getActivity().finish();
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.topic, menu);
mStarItem = menu.findItem(R.id.menu_topic_star);
mUnStarItem = menu.findItem(R.id.menu_topic_unstar);
mReplyItem = menu.findItem(R.id.menu_topic_reply);
mIsStarred = mDataSource.isTopicFavorite(mTopicId);
mStarItem.setVisible(mIsLogin && !mIsStarred);
mUnStarItem.setVisible(mIsLogin && mIsStarred);
mReplyItem.setVisible(mIsLogin);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_topic_share:
share();
break;
case R.id.menu_topic_reply:
replyToAuthor();
break;
case R.id.menu_topic_star:
case R.id.menu_topic_unstar:
favTopic();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onSuccess(ArrayList<ReplyModel> data) {
mAdapter.update(data);
mSwipeLayout.setRefreshing(false);
prepareAddComment(mTopic, false);
if (!mIsLogin)
mEnterLayout.hide();
else
mEnterLayout.show();
mFootUpdate.dismiss();
}
@Override
public void onSuccess(ArrayList<ReplyModel> data, int totalPages, int currentPage) {
}
@Override
public void onFailure(String error) {
mSwipeLayout.setRefreshing(false);
MessageUtils.showErrorMessage(getActivity(), error);
}
@Override
public boolean onBackPressed() {
if (mEnterLayout.content.getText().toString().isEmpty())
return false;
else {
mEnterLayout.clearContent();
return true;
}
}
@Override
public void onLoadMore() {
if (!mNoMore && !mApp.isJsonAPIFromCache()) {
requestRepliesOfNextPage();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_COMMENT) {
if (resultCode == Activity.RESULT_OK || data != null) {
MessageUtils.showToast(getActivity(),
getActivity().getString(R.string.topic_comment_succeed));
ReplyModel reply = data.getParcelableExtra("reply_result");
mAdapter.insert(reply);
}
}
}
//获取该话题下的所有回复
private void getReplyData(final boolean refresh) {
//prepareAddComment(mTopic, false);
if (mApp.isJsonAPIFromCache())
V2EXManager.getRepliesByTopicId(getActivity(), mTopicId, refresh, this);
else
V2EXManager.getTopicAndRepliesByTopicId(getActivity(), mTopicId, mPage, refresh, new RequestTopicAndReplyListHelper(refresh));
}
//获取该话题内容和其所有回复
private void getTopicData(final boolean refresh) {
//prepareAddComment(mTopic, false);
if (mApp.isJsonAPIFromCache())
V2EXManager.getTopicByTopicId(getActivity(), mTopicId, refresh, new RequestTopicHelper(refresh));
else
V2EXManager.getTopicAndRepliesByTopicId(getActivity(), mTopicId, mPage, refresh, new RequestTopicAndReplyListHelper(refresh));
}
private void favTopic() {
showProgress(R.string.fav_topic_working);
V2EXManager.favTopicWithTopicId(getActivity(), mTopicId, new FavTopicHelper());
}
void prepareAddComment(V2EXModel data, boolean popKeyboard) {
final EditText content = mEnterLayout.content;
String replyToWho = "";
mEnterLayout.clearContent();
if (data instanceof ReplyModel) {
final ReplyModel replyObj = (ReplyModel) data;
content.setHint("回复 " + replyObj.member.username);
replyToWho = "@" + replyObj.member.username + " ";
}
if (popKeyboard) {
InputUtils.popSoftkeyboard(getActivity(), content, true);
final String replyToWho_ = replyToWho;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
content.setText(replyToWho_);
content.setSelection(content.getText().length());
}
}, 500);
} else {
InputUtils.popSoftkeyboard(getActivity(), content, false);
}
}
private void share() {
try {
ShareHelper helper = new ShareHelper(getActivity());
helper.setContent(getString(R.string.app_name), mTopic.title, V2EXManager.getBaseUrl() + "/t/" + mTopicId);
helper.handleShare();
} catch (Exception e) {
e.printStackTrace();
}
}
//回复话题作者
private void replyToAuthor() {
try {
reply(mTopic.member.username);
} catch (Exception e) {
e.printStackTrace();
}
}
private void reply(String username) {
Intent intent = new Intent(getActivity(), TopicCommentActivity.class);
intent.putExtra("topic_id", mTopicId);
intent.putExtra("reply_to", username);
startActivityForResult(intent, REQUEST_COMMENT);
}
/**
* 请求更多的回复 (翻页)
*/
private void requestRepliesOfNextPage() {
V2EXManager.getTopicAndRepliesByTopicId(getActivity(), mTopicId, mPage + 1, true, new RequestTopicAndReplyListHelper(true));
}
/**
* 设置话题,将其设置为ListView的HeaderView
*/
private void setupHeaderView() {
if (mHeader.getVisibility() != View.VISIBLE)
mHeader.setVisibility(View.VISIBLE);
ImageView avatar = (ImageView) mHeader.findViewById(R.id.avatar);
TextView titleTextView = (TextView) mHeader.findViewById(R.id.text_title);
TextView authorTextView = (TextView) mHeader.findViewById(R.id.text_author);
TextView timeTextView = (TextView) mHeader.findViewById(R.id.text_timeline);
TextView repliesTextView = (TextView) mHeader.findViewById(R.id.text_replies);
TextView nodeTextView = (TextView) mHeader.findViewById(R.id.text_node);
RichTextView contentTextView = (RichTextView) mHeader.findViewById(R.id.text_content);
View divideView = mHeader.findViewById(R.id.divide_line);
titleTextView.setText(mTopic.title);
if (mTopic.member != null) {
authorTextView.setText(mTopic.member.username);
String imageURL = mTopic.member.avatar;
ImageLoader.getInstance().displayImage(imageURL, avatar);
avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), UserActivity.class);
intent.putExtra("model", (Parcelable) mTopic.member);
startActivity(intent);
}
});
}
String content = mTopic.contentRendered;
if (content != "")
contentTextView.setRichText(content);
else
{
divideView.setVisibility(View.GONE);
contentTextView.setVisibility(View.GONE);
}
repliesTextView.setText(mTopic.replies + "个回复");
final NodeModel node = mTopic.node;
nodeTextView.setText(node.title);
nodeTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), NodeActivity.class);
intent.putExtra("model", (Parcelable) node);
startActivity(intent);
}
});
timeTextView.setText(V2EXDateModel.toString(mTopic.created));
}
/**
* 一次性获取话题正文和回复
*/
class RequestTopicAndReplyListHelper implements HttpRequestHandler<TopicWithReplyListModel> {
boolean refresh;
public RequestTopicAndReplyListHelper(boolean refresh) {
this.refresh = refresh;
}
@Override
public void onSuccess(TopicWithReplyListModel data) {
onSuccess(data, 1, 1);
}
@Override
public void onSuccess(TopicWithReplyListModel data, int total, int current) {
mPage = current;
mNoMore = total == current;
mSwipeLayout.setRefreshing(false);
if (data.topic != null) {
mTopic = data.topic;
mTopicId = mTopic.id;
if (mPage == 1) setupHeaderView();
prepareAddComment(mTopic, false);
}
if (data.replies != null) {
if (mPage == 1)
mAdapter.update(data.replies);
else
mAdapter.insert(data.replies);
}
if (!mIsLogin)
mEnterLayout.hide();
else
mEnterLayout.show();
if (mNoMore) {
mFootUpdate.dismiss();
} else {
mFootUpdate.showLoading();
}
}
@Override
public void onFailure(String error) {
mSwipeLayout.setRefreshing(false);
MessageUtils.showErrorMessage(getActivity(), error);
if (mAdapter.getItemCount() > 0 && !mNoMore) {
mFootUpdate.showFail();
} else {
mFootUpdate.dismiss();
}
}
}
/**
* 获取/刷新该话题内容的帮助类
*/
class RequestTopicHelper implements HttpRequestHandler<ArrayList<TopicModel>> {
boolean refresh;
public RequestTopicHelper(boolean refresh) {
this.refresh = refresh;
}
@Override
public void onSuccess(ArrayList<TopicModel> data) {
if (data.size() > 0) {
mTopic = data.get(0);
mTopicId = mTopic.id;
setupHeaderView();
getReplyData(refresh);
} else {
mSwipeLayout.setRefreshing(false);
}
}
@Override
public void onSuccess(ArrayList<TopicModel> data, int total, int current) {
}
@Override
public void onFailure(String error) {
mSwipeLayout.setRefreshing(false);
MessageUtils.showErrorMessage(getActivity(), error);
}
}
/**
* 评论类
*/
class CommentHelper implements HttpRequestHandler<Integer> {
@Override
public void onSuccess(Integer data) {
((BaseActivity) getActivity()).showProgressBar(false);
String content = mEnterLayout.getContent();
mEnterLayout.clearContent();
mEnterLayout.hideKeyboard();
Intent intent = new Intent();
ReplyModel reply = new ReplyModel();
reply.content = reply.contentRendered = content;
reply.created = System.currentTimeMillis() / 1000;
reply.member = new MemberModel();
reply.member.username = mLoginProfile.username;
reply.member.avatar = mLoginProfile.avatar;
intent.putExtra("reply_result", (Parcelable) reply);
onActivityResult(REQUEST_COMMENT, Activity.RESULT_OK, intent);
}
@Override
public void onSuccess(Integer data, int total, int current) {
}
@Override
public void onFailure(String error) {
((BaseActivity) getActivity()).showProgressBar(false);
MessageUtils.showErrorMessage(getActivity(), error);
}
}
/**
* 话题收藏类
*/
class FavTopicHelper implements HttpRequestHandler<Integer> {
@Override
public void onSuccess(Integer data) {
((BaseActivity) getActivity()).showProgressBar(false);
mIsStarred = data == 200;
mStarItem.setVisible(!mIsStarred);
mUnStarItem.setVisible(mIsStarred);
mDataSource.favoriteTopic(mTopic, mIsStarred);
MessageUtils.showToast(getActivity(),
getString(mIsStarred ? R.string.fav_topic_ok : R.string.unfav_topic_ok));
}
@Override
public void onSuccess(Integer data, int total, int current) {
}
@Override
public void onFailure(String error) {
((BaseActivity) getActivity()).showProgressBar(false);
MessageUtils.showErrorMessage(getActivity(), error);
}
}
}