package org.goodev.discourse.ui;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
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.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.google.ads.Ad;
import com.google.ads.AdListener;
import com.google.ads.AdRequest;
import com.google.ads.AdRequest.ErrorCode;
import com.google.ads.AdView;
import org.apache.http.HttpStatus;
import org.goodev.discourse.ActivityUtils;
import org.goodev.discourse.App;
import org.goodev.discourse.EditorActivity;
import org.goodev.discourse.R;
import org.goodev.discourse.api.Api;
import org.goodev.discourse.api.PostActionTask;
import org.goodev.discourse.api.TopicNotificationTask;
import org.goodev.discourse.api.TopicStream;
import org.goodev.discourse.api.data.Category;
import org.goodev.discourse.api.data.Links;
import org.goodev.discourse.api.data.Post;
import org.goodev.discourse.api.data.Topic;
import org.goodev.discourse.api.data.TopicDetails;
import org.goodev.discourse.contentprovider.Provider;
import org.goodev.discourse.database.tables.CategoriesTable;
import org.goodev.discourse.ui.EditorChangeTitleFragment.ChangeTopicListener;
import org.goodev.discourse.ui.dialog.InviteReplyDialogFragment;
import org.goodev.discourse.ui.dialog.InviteReplyDialogFragment.OnInviteListener;
import org.goodev.discourse.ui.dialog.LinksDialogFragment;
import org.goodev.discourse.utils.HttpRequest;
import org.goodev.discourse.utils.ImageLoader;
import org.goodev.discourse.utils.L;
import org.goodev.discourse.utils.Utils;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.util.Random;
public class TopicFragment extends ListFragment implements LoaderCallbacks<TopicStream>, OnScrollListener, ChangeTopicListener, AdListener, OnClickListener, OnInviteListener {
public static final String EXTRA_ADD_VERTICAL_MARGINS = "extra_ADD_VERTICAL_MARGINS";
private static final String STATE_POSITION = "extra_postion";
private static final String STATE_TOP = "extra_top";
private static final int TOPICS_LOADER_ID = 1;
private static final int EDIT_POST_CODE = 111;
protected final PostAdapter mAdapter = new PostAdapter();
private final OnClickListener mClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.user_icon:
case R.id.post_user_info_layout:
onUserClicked(v);
break;
case R.id.overflow_menu:
showPopupActioinMenu(v);
break;
case R.id.post_like:
onLikeClicked(v);
break;
case R.id.post_replay:
onReplyClicked(v);
break;
case R.id.post_edit:
onEditClicked(v);
break;
case R.id.post_recover:
onRecoverClicked(v);
break;
case R.id.post_share:
onShareClicked(v);
break;
case R.id.category:
openCategoryActivity(v);
break;
}
}
};
protected String mSiteUrl;
protected String mSlug;
protected long mId;
ProgressFragment mProgressFragment;
private TopicStream mData = new TopicStream();
private int mListViewStatePosition;
private int mListViewStateTop;
private ImageLoader mImageLoader;
private Category mCat;
private TextView mEmptyView;
private Spinner mNotificationSpinner;
private TextView mCategoryView;
private TextView mStatusView;
private TextView mNotificationDesView;
private String[] mNotificationDes;
private int mNotifiCurrentLevel;
private TopicNotificationTask mNotiTask;
private final OnItemSelectedListener mNotifListener = new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
L.d("spinner notifications %d : %s", position, parent.getItemAtPosition(position));
if (mNotifiCurrentLevel == position) {
return;
}
// setNotificationDesView(position);
if (mNotiTask != null && mNotiTask.isCancelled()) {
mNotiTask.cancel(true);
}
mNotiTask = new TopicNotificationTask(TopicFragment.this, position);
mNotiTask.execute();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
L.i("Notings selected");
}
};
/**
* 当打开每个post的 菜单的时候, 记录该post数据,方便处理菜单功能
*/
private Post mMenuPost;
private final OnMenuItemClickListener mMenuListener = new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
if (mMenuPost == null) {
return false;
}
L.i("menu item clicked: %s . post: %s", item.getTitle(), mMenuPost.cooked);
switch (item.getItemId()) {
case R.id.menu_post_links:
openPostLinksDialog();
return true;
case R.id.menu_replay_new:
openReplayNewActivity();
return true;
case R.id.menu_post_bookmark:
bookmarkClicked(item.isChecked());
return true;
case R.id.menu_post_delete:
deletePostClicked();
return true;
default:
break;
}
return false;
}
};
/**
* 第一个帖子(Topic)的连接为 details对象中的连接
*/
private TopicDetails mMenuTopicDetails;
private LikeActionTask mLikeTask;
private UnlikeActionTask mUnlikeTask;
private int mPostPosition;
// ----------------------- admob
private AdView mAdView;
private View mCloseAd;
private AdRequest mAdRequest;
public TopicFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mImageLoader = App.getImageLoader(getActivity(), getResources());
mSiteUrl = App.getSiteUrl();
if (savedInstanceState != null) {
mSlug = savedInstanceState.getString(Utils.EXTRA_SLUG);
mId = savedInstanceState.getLong(Utils.EXTRA_ID);
mCat = (Category) savedInstanceState.getSerializable(Utils.EXTRA_OBJ_C);
} else {
Bundle arg = getArguments();
if (arg != null) {
mSlug = arg.getString(Utils.EXTRA_SLUG);
mId = arg.getLong(Utils.EXTRA_ID);
}
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// View view = super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_topic, container, false);
mEmptyView = (TextView) view.findViewById(android.R.id.empty);
if (savedInstanceState != null) {
mListViewStatePosition = savedInstanceState.getInt(STATE_POSITION, -1);
mListViewStateTop = savedInstanceState.getInt(STATE_TOP, 0);
} else {
mListViewStatePosition = -1;
mListViewStateTop = 0;
}
return view;
}
private void setupNotificationSpinner() {
String[] objects = getResources().getStringArray(R.array.notifications_title);
ArrayAdapter<String> a = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_spinner_item, android.R.id.text1, objects);
mNotificationSpinner.setAdapter(a);
a.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
// mNotificationSpinner.setOnItemSelectedListener(mNotifListener);
}
protected void setNotificationDesView(int level) {
if (mNotificationDes == null) {
mNotificationDes = getResources().getStringArray(R.array.notifications_des);
}
if (level >= mNotificationDes.length) {
level = 0;
}
mNotificationDesView.setText(mNotificationDes[level]);
}
public String getSite() {
return mSiteUrl;
}
public long getTopicId() {
return mId;
}
public Spinner getNotiSpinner() {
return mNotificationSpinner;
}
public TextView getNotiDes() {
return mNotificationDesView;
}
public int getOldNotiLevel() {
return mNotifiCurrentLevel;
}
public void setCurrentNotifLevel(int l) {
mNotifiCurrentLevel = l;
}
public OnItemSelectedListener getListener() {
return mNotifListener;
}
private void setNotificationStatus(int level) {
mNotifiCurrentLevel = level;
mNotificationSpinner.setOnItemSelectedListener(null);
mNotificationSpinner.setSelection(level);
setNotificationDesView(level);
mNotificationSpinner.setOnItemSelectedListener(mNotifListener);
}
private void setTopicStatus(Topic t) {
int left = 0;
int right = 0;
if (t.pinned) {
right = R.drawable.ic_pin;
}
if (t.closed) {
left = R.drawable.ic_locked;
}
mStatusView.setCompoundDrawablesWithIntrinsicBounds(left, 0, right, 0);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getListView().setEmptyView(mEmptyView);
mEmptyView.setText(getString(R.string.empty_topics));
// In support library r8, calling initLoader for a fragment in a FragmentPagerAdapter
// in the fragment's onCreate may cause the same LoaderManager to be dealt to multiple
// fragments because their mIndex is -1 (haven't been added to the activity yet). Thus,
// we do this in onActivityCreated.
getLoaderManager().initLoader(TOPICS_LOADER_ID, null, this);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final ListView listView = getListView();
View header = LayoutInflater.from(getActivity()).inflate(R.layout.topic_header, listView, false);
mNotificationDesView = (TextView) header.findViewById(R.id.notification_des);
mCategoryView = (TextView) header.findViewById(R.id.category);
mNotificationSpinner = (Spinner) header.findViewById(R.id.notification_spinner);
mStatusView = (TextView) header.findViewById(R.id.topic_status_view);
mAdView = (AdView) view.findViewById(R.id.adView);
mCloseAd = view.findViewById(R.id.close_ad);
mCloseAd.setOnClickListener(this);
mAdView.setAdListener(this);
setupNotificationSpinner();
listView.addHeaderView(header);
if (!Utils.isTablet(getActivity())) {
// TODO ...
// view.setBackgroundColor(getResources().getColor(R.color.plus_stream_spacer_color));
}
if (getArguments() != null && getArguments().getBoolean(EXTRA_ADD_VERTICAL_MARGINS, false)) {
int verticalMargin = getResources().getDimensionPixelSize(R.dimen.topics_list_padding_vertical);
if (verticalMargin > 0) {
listView.setClipToPadding(false);
listView.setPadding(0, verticalMargin, 0, verticalMargin);
}
}
listView.setOnScrollListener(this);
listView.setDrawSelectorOnTop(true);
// listView.setDivider(getResources().getDrawable(android.R.color.transparent));
// listView.setDividerHeight(getResources()
// .getDimensionPixelSize(R.dimen.page_margin_width));
TypedValue v = new TypedValue();
getActivity().getTheme().resolveAttribute(R.attr.clickableItemBackground, v, true);
listView.setSelector(v.resourceId);
setListAdapter(mAdapter);
}
private void setCategoryView() {
if (mCat == null) {
L.i(" category is null ");
} else {
mCategoryView.setOnClickListener(mClickListener);
}
Utils.setCategoryView(mCat, mCategoryView);
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putSerializable(Utils.EXTRA_OBJ_C, mCat);
outState.putString(Utils.EXTRA_SLUG, mSlug);
outState.putLong(Utils.EXTRA_ID, mId);
if (isAdded()) {
View v = getListView().getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
outState.putInt(STATE_POSITION, getListView().getFirstVisiblePosition());
outState.putInt(STATE_TOP, top);
}
super.onSaveInstanceState(outState);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Pause disk cache access to ensure smoother scrolling
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
mImageLoader.stopProcessingQueue();
} else {
mImageLoader.startProcessingQueue();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (!isStreamLoading() && streamHasMoreResults() && visibleItemCount != 0 && firstVisibleItem + visibleItemCount >= totalItemCount - 1) {
loadMoreResults();
}
}
public void refresh() {
refresh(false);
}
public void refresh(boolean forceRefresh) {
if (isStreamLoading() && !forceRefresh) {
return;
}
// clear current items
mData.clear();
mAdapter.notifyDataSetInvalidated();
if (isAdded()) {
Loader loader = getLoaderManager().getLoader(TOPICS_LOADER_ID);
((TopicStreamLoader) loader).init(mSiteUrl, mSlug, mId);
}
loadMoreResults();
}
public void loadMoreResults() {
if (isAdded()) {
Loader loader = getLoaderManager().getLoader(TOPICS_LOADER_ID);
if (loader != null) {
loader.forceLoad();
}
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.topic_fragment, menu);
// MenuItem notificationsItem = menu.findItem(R.id.action_notifications);
// View view = notificationsItem.getActionView();
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (mData == null || mData.mTopic == null || mData.mTopicDetails == null) {
return;
}
MenuItem edit = menu.findItem(R.id.action_edit_topic);
edit.setVisible(mData.mTopicDetails.can_edit);
MenuItem invite = menu.findItem(R.id.action_invite_reply);
invite.setVisible(mData.mTopicDetails.can_invite_to);
MenuItem reply = menu.findItem(R.id.action_reply);
reply.setVisible(mData.mTopicDetails.can_create_post);
// MenuItem replyNew = menu.findItem(R.id.action_reply_as_new);
// replyNew.setVisible(mData.mTopicDetails.can_reply_as_new_topic);
MenuItem star = menu.findItem(R.id.action_star);
final boolean checked = mData.mTopic.starred;
star.setVisible(true);
star.setChecked(checked);
star.setIcon(checked ? R.drawable.btn_star_on_normal : R.drawable.btn_star_off_normal);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean r = super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.action_star:
L.i("topic star : " + item.isChecked());
boolean checked = !item.isChecked();
item.setChecked(checked);
item.setIcon(checked ? R.drawable.btn_star_on_normal : R.drawable.btn_star_off_normal);
return true;
case R.id.action_reply:
if (mData != null && mData.mTopic != null) {
Post post = (Post) mAdapter.getItem(0);
openReplayTopicActivity(mData.mTopic, post);
}
return true;
case R.id.action_edit_topic:
// 编辑标题和分类
Topic t = mData.mTopic;
EditorChangeTitleFragment fragment = new EditorChangeTitleFragment();
Bundle args = new Bundle();
args.putLong(Utils.EXTRA_ID, t.category_id);
args.putString(Utils.EXTRA_TITLE, t.title);
fragment.setArguments(args);
fragment.show(getChildFragmentManager(), "edit_title");
L.i("edit topic title: %s - cat: %d", t.title, t.category_id);
return true;
case R.id.action_invite_reply:
showInviteReplyDialog();
return true;
}
return r;
}
@Override
public void onTopicChange(String title, String category, long categoryId) {
L.i("t: %s ,c: %s", title, category);
Topic t = mData.mTopic;
if (t.title.equals(title) && t.category_id == categoryId) {
return;
}
changeTopicTitleAndCategory(t, title, category, categoryId);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Object data = l.getItemAtPosition(position);
if (data instanceof Topic) {
Topic t = (Topic) data;
ActivityUtils.startTopicActivity(getActivity(), t.slug, t.id);
}
L.i("%d : %s", position, l.getItemAtPosition(position));
}
@Override
public Loader<TopicStream> onCreateLoader(int id, Bundle args) {
return new TopicStreamLoader(getActivity(), mSiteUrl, mSlug, mId);
}
@Override
public void onLoadFinished(Loader<TopicStream> loader, TopicStream data) {
checkAdView();
if (data != null) {
mData = data;
postTopicTimings();
}
mAdapter.notifyDataSetChanged();
mNotificationSpinner.setVisibility(View.VISIBLE);
if (mData.mTopicDetails != null) {
setNotificationStatus((int) mData.mTopicDetails.notification_level);
L.i("can_invite_to...." + mData.mTopicDetails.can_invite_to);
}
if (mData.mTopic != null) {
setTopicStatus(mData.mTopic);
setTitle(mData.mTopic.title);
if (mCat == null) {
loadCategory(mData.mTopic.category_id);
} else {
setCategoryView();
}
}
getActivity().invalidateOptionsMenu();
if (mListViewStatePosition != -1 && isAdded()) {
getListView().setSelectionFromTop(mListViewStatePosition, mListViewStateTop);
mListViewStatePosition = -1;
}
}
private void setTitle(String title) {
getActivity().setTitle(title);
}
private void loadCategory(long cid) {
Cursor c = getActivity().getContentResolver().query(Provider.CATEGORIES_CONTENT_URI, CategoriesTable.ALL_COLUMNS, CategoriesTable.UID + " = " + cid, null, null);
if (c != null && c.moveToFirst()) {
mCat = new Category(c);
setCategoryView();
}
}
@Override
public void onLoaderReset(Loader<TopicStream> loader) {
}
private boolean isStreamLoading() {
if (isAdded()) {
final Loader loader = getLoaderManager().getLoader(TOPICS_LOADER_ID);
if (loader != null) {
return ((TopicStreamLoader) loader).isLoading();
}
}
return true;
}
private boolean streamHasMoreResults() {
if (isAdded()) {
final Loader loader = getLoaderManager().getLoader(TOPICS_LOADER_ID);
if (loader != null) {
return ((TopicStreamLoader) loader).hasMoreResults();
}
}
return false;
}
private boolean streamHasError() {
if (isAdded()) {
final Loader loader = getLoaderManager().getLoader(TOPICS_LOADER_ID);
if (loader != null) {
return ((TopicStreamLoader) loader).hasError();
}
}
return false;
}
private int getPositionForView(View v) {
int position = getListView().getPositionForView(v) - getListView().getHeaderViewsCount();
return position;
}
protected void openReplayNewActivity() {
ActivityUtils.openNewEditorActivity(getActivity(), mMenuPost);
}
protected void openPostLinksDialog() {
Links[] links;
if (mMenuTopicDetails != null) {
links = mMenuTopicDetails.links;
} else {
links = mMenuPost.link_counts;
}
LinksDialogFragment frag = new LinksDialogFragment();
Bundle args = new Bundle();
args.putSerializable(Utils.EXTRA_LINKS, links);
frag.setArguments(args);
frag.show(getChildFragmentManager(), "links_frag");
}
protected void showPopupActioinMenu(View v) {
int position = getPositionForView(v);
L.d("postion %d at all %d", position, mAdapter.getCount());
Post post = (Post) mAdapter.getItem(position);
mMenuPost = post;
int links;
if (position == 0) {
mMenuTopicDetails = mData.mTopicDetails;
links = mData.getTopicLinksSize();
} else {
links = post.getLinksSize();
mMenuTopicDetails = null;
}
PopupMenu menu = new PopupMenu(getActivity(), v);
menu.inflate(R.menu.post_action_menu);
Menu m = menu.getMenu();
m.findItem(R.id.menu_post_flag).setVisible(post.showFlag() && false);// TODO 第一个版本 不支持该功能
MenuItem bookmark = m.findItem(R.id.menu_post_bookmark);
bookmark.setVisible(App.isLogin());
bookmark.setChecked(post.bookmarked);
MenuItem link = m.findItem(R.id.menu_post_links);
link.setVisible(links > 0);
link.setTitle(getResources().getString(R.string.menu_links, links));
MenuItem posters = m.findItem(R.id.menu_poster_count);
if (position == 0) {
posters.setVisible(false);// TODO 应该为true,第一个版本不支持该功能
int posterSize = mData.getPosterSize();
posters.setTitle(getResources().getString(R.string.menu_poster_count, posterSize));
} else {
posters.setVisible(false);
}
m.findItem(R.id.menu_post_delete).setVisible(post.can_delete);
menu.setOnMenuItemClickListener(mMenuListener);
menu.show();
}
protected void onReplyClicked(View v) {
int position = getPositionForView(v);
Topic t = mData.mTopic;
Post post = (Post) mAdapter.getItem(position);
if (position == 0) {
openReplayTopicActivity(t, post);
} else {
L.i("reply " + post.name);
openReplayPostActivity(t, post, position + 1);
}
}
private void openReplayPostActivity(Topic t, Post post, int postNum) {
ActivityUtils.openReplayPostActivity(getActivity(), t, post, postNum);
}
private void openReplayTopicActivity(Topic t, Post p) {
ActivityUtils.openReplayTopicActivity(getActivity(), t, p);
}
protected void onShareClicked(View v) {
int position = getPositionForView(v);
// Post post = (Post) mAdapter.getItem(position);
String url = null;
if (App.isLogin()) {
url = String.format(Api.SHARE_LOGIN, mSlug, mId, position + 1, App.getUsername());
} else {
url = String.format(Api.SHARE, mSlug, mId, position + 1);
}
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, mSiteUrl + url);
intent.setType("text/plain");
startActivity(intent);
}
protected void onLikeClicked(View v) {
int position = getPositionForView(v);
Post post = (Post) mAdapter.getItem(position);
L.d("like postion %d at all %d :%s", position, mAdapter.getCount(), post.username);
Utils.cancelTask(mLikeTask);
Utils.cancelTask(mUnlikeTask);
if (!post.isLikeActed()) {
mLikeTask = new LikeActionTask(TopicFragment.this, position, mSiteUrl, post.id, PostActionTask.TYPE_LIKE);
mLikeTask.execute();
} else if (post.isLikeCanUndo()) {
mUnlikeTask = new UnlikeActionTask(TopicFragment.this, position, mSiteUrl, post.id);
mUnlikeTask.execute();
}
}
protected void onUserClicked(View v) {
// TODO 显示PopupMenu(查看该用户帖子 ; 查看用户信息 ),或者打开用户信息?
int position = getPositionForView(v);
Post post = (Post) mAdapter.getItem(position);
L.d("postion %d at all %d :%s", position, mAdapter.getCount(), post.username);
ActivityUtils.openUserActivity(getActivity(), post.username);
}
protected void openCategoryActivity(View v) {
if (mCat == null) {
return;
}
ActivityUtils.openCategoryActivity(getActivity(), mCat, mSiteUrl);
}
private void changeTopicTitleAndCategory(Topic t, String title, String category, long cid) {
new ChangeTopicTask(t, title, category, cid).execute();
}
protected void bookmarkClicked(boolean checked) {
// TODO Auto-generated method stub
L.i("%s : %s", mMenuPost.name, String.valueOf(checked));
new BookmarkTask(!checked).execute();
}
protected void postTopicTimings() {
new TopicTimingsTask(mId).execute();
}
protected void deletePostClicked() {
new DeleteTask().execute();
}
protected void onRecoverClicked(View v) {
int position = getPositionForView(v);
Post post = (Post) mAdapter.getItem(position);
L.i("recover " + post.name);
new RecoverTask(post, position).execute();
}
protected void onEditClicked(View v) {
int position = getPositionForView(v);
Post post = (Post) mAdapter.getItem(position);
mPostPosition = position;
L.i("edit " + post.name);
Intent intent = new Intent();
intent.setClass(getActivity(), EditorActivity.class);
intent.putExtra(Utils.EXTRA_NAME, post.username);
intent.putExtra(Utils.EXTRA_NUMBER, position + 1);
intent.putExtra(Utils.EXTRA_ID, post.id);
intent.putExtra(Utils.EXTRA_IS_EDIT_POST, true);
startActivityForResult(intent, EDIT_POST_CODE);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == EDIT_POST_CODE) {
String re = data.getStringExtra(Utils.EXTRA_MSG);
try {
JSONObject obj = new JSONObject(re);
Post p = Api.getPost(obj.getJSONObject(Api.K_post));
L.i(re);
L.i("-------------\r %d .. %s", mPostPosition, p.cooked);
// TODO fix this , FIXME 修改后 不显示新内容
mAdapter.setPost(mPostPosition, p);
} catch (JSONException e) {
L.e(e, "edit post error");
}
}
}
private void hideAdView() {
mAdView.setVisibility(View.GONE);
mCloseAd.setVisibility(View.GONE);
}
private void checkAdView() {
boolean showAd = new Random().nextInt(100) < Api.AD_RANDOM;
if (showAd && mAdView.getVisibility() != View.VISIBLE) {
showAdView();
}
}
// ------------- edit post
private void showAdView() {
if (mAdRequest == null) {
mAdRequest = new AdRequest();
}
mCloseAd.setVisibility(View.VISIBLE);
mAdView.setVisibility(View.VISIBLE);
mAdView.loadAd(mAdRequest);
}
@Override
public void onDismissScreen(Ad arg0) {
}
@Override
public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) {
hideAdView();
}
@Override
public void onLeaveApplication(Ad arg0) {
}
@Override
public void onPresentScreen(Ad arg0) {
}
@Override
public void onReceiveAd(Ad arg0) {
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.close_ad:
hideAdView();
break;
}
}
private Topic[] getSuggestionTopics() {
TopicDetails td = mData.mTopicDetails;
if (td != null) {
Topic[] topics = td.suggested_topics;
return topics;
}
return null;
}
private void showInviteReplyDialog() {
InviteReplyDialogFragment frag = new InviteReplyDialogFragment();
Bundle args = new Bundle();
frag.setArguments(args);
frag.show(getChildFragmentManager(), "invite_reply");
}
@Override
public void onInvite(String email) {
//TODO ...
new InviteTask(email, mId).execute();
}
private static class TopicStreamLoader extends AsyncTaskLoader<TopicStream> {
public TopicStream mData;
private boolean mIsLoading;
private boolean mHasError;
private String mSiteUrl;
private Long mId;
private String mSlug;
public TopicStreamLoader(Context context, String siteUrl, String slug, Long id) {
super(context);
init(siteUrl, slug, id);
}
private void init(String siteUrl, String slug, Long id) {
mHasError = false;
mIsLoading = true;
mSiteUrl = siteUrl;
mSlug = slug;
mId = id;
mData = null;
}
@Override
public TopicStream loadInBackground() {
mIsLoading = true;
String url = null;
if (hasMoreResults()) {
url = Utils.buildMorePostsUrl(App.getSiteUrl(), mId, mData.mPostStreams, mData.mPosts.size());
} else {
url = Utils.buildPostsUrl(App.getSiteUrl(), mId, mSlug);
}
TopicStream data = Api.getPostsOfTopic(url);
mHasError = data == null;
return data;
}
@Override
public void deliverResult(TopicStream data) {
mIsLoading = false;
if (data != null) {
if (mData == null) {
mData = data;
} else {
mData.addAll(data);
}
}
if (isStarted()) {
super.deliverResult(mData == null ? null : new TopicStream(mData));
}
}
@Override
protected void onStartLoading() {
if (mData != null) {
deliverResult(null);
} else {
forceLoad();
}
}
@Override
protected void onStopLoading() {
mIsLoading = false;
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
onStopLoading();
mData = null;
}
public boolean isLoading() {
return mIsLoading;
}
public boolean hasError() {
return mHasError;
}
public void refresh() {
reset();
startLoading();
}
public boolean hasMoreResults() {
if (mData == null) {
return false;
}
if (mData.mPostStreams == null) {
return false;
}
if (mData.mPostStreams.length <= mData.mPosts.size()) {
return false;
}
return true;
}
}
static class UnlikeActionTask extends AsyncTask<Void, Void, Boolean> {
private final String mSite;
private final long mId;
private final int mIndex;
private final WeakReference<TopicFragment> mF;
public UnlikeActionTask(TopicFragment f, int index, String site, long id) {
mF = new WeakReference<TopicFragment>(f);
mSite = site;
mIndex = index;
mId = id;
}
@Override
protected Boolean doInBackground(Void... params) {
try {
// TODO 删除 喜欢 出错。。。。
String url = mSite + String.format(Api.DELETE_POST_ACTIONS, mId);
HttpRequest hr = HttpRequest.delete(url);
HttpURLConnection connection = hr.getConnection();
if (App.isLogin()) {
App.getCookieManager().setCookies(connection);
}
hr.contentType(HttpRequest.CONTENT_TYPE_FORM, HttpRequest.CHARSET_UTF8);
hr.accept("*/*");
int code = hr.code();
L.i("%s star code %d ", url, code);
String body = hr.body();
L.i(body);
return code == HttpStatus.SC_OK;
} catch (Exception e) {
L.e(e);
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
TopicFragment f = mF.get();
if (result && f != null) {
try {
Post post = (Post) f.mAdapter.getItem(mIndex);
if (post == null) {
return;
}
post.updateLikeAction(false);
f.mAdapter.setPost(mIndex, post);
} catch (Exception e) {
L.d(e);
}
}
}
}
static class LikeActionTask extends PostActionTask {
private final WeakReference<TopicFragment> mF;
private final int mIndex;
public LikeActionTask(TopicFragment f, int index, String site, long id, int type) {
super(site, id, type);
mF = new WeakReference<TopicFragment>(f);
mIndex = index;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
TopicFragment f = mF.get();
if (result != null && f != null) {
try {
Post post = Api.getPost(new JSONObject(result));
post.updateLikeAction(true);
f.mAdapter.setPost(mIndex, post);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
private class PostAdapter extends BaseAdapter {
private static final int VIEW_TYPE_ITEM = 0;
private static final int VIEW_TYPE_LOADING = 1;
private static final int VIEW_TYPE_TOPIC_HEADER = 2;
private static final int VIEW_TYPE_TOPIC = 3;
public void setPost(int index, Post data) {
mData.setPost(index, data);
notifyDataSetChanged();
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEnabled(int position) {
int type = getItemViewType(position);
return type == VIEW_TYPE_ITEM || type == VIEW_TYPE_TOPIC;
}
@Override
public int getViewTypeCount() {
return 4;
}
@Override
public boolean hasStableIds() {
return true;
}
/**
* 显示建议的帖子, 当帖子滚动到底 没有新的帖子的时候 ,返回 建议的主题。。。。 PostAdapter 添加一种Topic类型的数据
*/
@Override
public int getCount() {
int postSize = mData.getSize();
int topicCount = 0;
if (!streamHasMoreResults() && postSize > 0) {
Topic[] topics = getSuggestionTopics();
// L.i("suggested topices: %d , %b", topics.length, streamHasMoreResults());
if (topics != null && topics.length > 0) {
topicCount = topics.length + 1;// 1为topic header
}
}
//@formatter:off
return topicCount + mData.getSize() +
( // show the status list row if...
((isStreamLoading() && mData.getSize() == 0) // ...this is the first load
|| streamHasMoreResults() // ...or there's another page
|| streamHasError() // ...or there's an error
) ? 1 : 0);
//@formatter:on
}
@Override
public int getItemViewType(int position) {
int postSize = mData.getSize();
if (streamHasMoreResults() || postSize == 0) {
return (position >= postSize) ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
} else {
if (position < postSize) {
return VIEW_TYPE_ITEM;
} else if (position == postSize) {
return VIEW_TYPE_TOPIC_HEADER;
} else {
return VIEW_TYPE_TOPIC;
}
}
}
@Override
public Object getItem(int position) {
int postSize = mData.getSize();
int type = getItemViewType(position);
if (type == VIEW_TYPE_ITEM) {
return mData.getPost(position);
} else if (type == VIEW_TYPE_TOPIC) {
Topic[] topics = getSuggestionTopics();
if (topics != null && topics.length > 0) {
int index = position - postSize - 1;
L.i("post size: %d position: %d index: %d", postSize, position, index);
if (index >= 0 && index < topics.length) {
return topics[index];
}
}
}
return null;
}
@Override
public long getItemId(int position) {
// TODO: better unique ID heuristic
return position;
// return (getItemViewType(position) == VIEW_TYPE_ITEM)
// ? mData.getPost(position).id.hashCode()
// : -1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
if (type == VIEW_TYPE_LOADING) {
if (convertView == null) {
convertView = getLayoutInflater(null).inflate(R.layout.list_item_stream_status, parent, false);
}
if (streamHasError()) {
convertView.findViewById(android.R.id.progress).setVisibility(View.GONE);
((TextView) convertView.findViewById(android.R.id.text1)).setText(R.string.stream_error);
} else {
convertView.findViewById(android.R.id.progress).setVisibility(View.VISIBLE);
((TextView) convertView.findViewById(android.R.id.text1)).setText(R.string.loading);
}
return convertView;
} else if (type == VIEW_TYPE_ITEM) {
Post data = mData.getPost(position);
if (convertView == null) {
convertView = getLayoutInflater(null).inflate(R.layout.post_list_item, parent, false);
}
PostRowViewBinder.bindItemView(getActivity(), convertView, data, mImageLoader, mData, position, mClickListener);
return convertView;
} else if (type == VIEW_TYPE_TOPIC_HEADER) {
if (convertView == null) {
convertView = getLayoutInflater(null).inflate(R.layout.suggest_topic_header, parent, false);
}
return convertView;
} else if (type == VIEW_TYPE_TOPIC) {
Topic topic = (Topic) getItem(position);
if (convertView == null) {
convertView = getLayoutInflater(null).inflate(R.layout.topic_list_item, parent, false);
}
TopicRowViewBinder.bindItemView(convertView, topic, mImageLoader, false, null, null);
return convertView;
}
// Can not go to heare
return convertView;
}
}
class ChangeTopicTask extends AsyncTask<Void, Void, String> {
private static final String TITLE_PARAM = "title";
private static final String CATEGORY_PARAM = "category";
private final Topic mTopic;
private final String mTitle;
private final String mCategory;
private final long mCategoryId;
public ChangeTopicTask(Topic t, String title, String category, long cid) {
mTopic = t;
mTitle = title;
mCategory = category;
mCategoryId = cid;
}
@Override
protected String doInBackground(Void... params) {
try {
String url = App.getSiteUrl() + String.format(Api.EDIT_TOPIC_TITLE, mTopic.slug, mTopic.id);
HttpRequest hr = HttpRequest.put(url);
HttpURLConnection connection = hr.getConnection();
if (App.isLogin()) {
App.getCookieManager().setCookies(connection);
}
hr.form(TITLE_PARAM, mTitle);
hr.form(CATEGORY_PARAM, mCategory);
int code = hr.code();
L.i("%s star code %d ", url, code);
String body = hr.body();
L.i(body);
return body;
} catch (Exception e) {
L.e(e);
return null;
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
L.i("posts topic 1");
mProgressFragment = new ProgressFragment();
Bundle args = new Bundle();
args.putString(Utils.EXTRA_MSG, getString(R.string.saving_title));
mProgressFragment.setArguments(args);
mProgressFragment.show(getFragmentManager(), "progress");
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
L.i("posts topic 2");
getFragmentManager().beginTransaction().remove(mProgressFragment).commit();
mProgressFragment = null;
try {
JSONObject topic = new JSONObject(result);
if (topic.has(Api.K_basic_topic)) {
setTitle(mTitle);
mData.mTopic.category_id = mCategoryId;
loadCategory(mCategoryId);
}
} catch (JSONException e) {
L.e(e, "create posts error");
}
}
}
class BookmarkTask extends AsyncTask<Void, Void, String> {
private static final String BOOKMARKED_PARAM = "bookmarked";
boolean mMarked;
public BookmarkTask(boolean marked) {
mMarked = marked;
}
@Override
protected String doInBackground(Void... params) {
try {
Post p = mMenuPost;
String url = App.getSiteUrl() + String.format(Api.BOOKMARK, p.id);
HttpRequest hr = HttpRequest.put(url);
HttpURLConnection connection = hr.getConnection();
if (App.isLogin()) {
App.getCookieManager().setCookies(connection);
}
int code = hr.form(BOOKMARKED_PARAM, String.valueOf(mMarked)).code();
L.i("%s star code %d ", url, code);
String body = hr.body();
L.i(body);
return String.valueOf(code);
} catch (Exception e) {
L.e(e);
return null;
}
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
int res = mMarked ? R.string.bookmark_add_failure : R.string.bookmark_remove_failure;
if ("200".equals(result)) {
res = mMarked ? R.string.bookmark_add_success : R.string.bookmark_remove_success;
mMenuPost.bookmarked = mMarked;
}
Toast.makeText(getActivity(), res, Toast.LENGTH_SHORT).show();
}
}
class TopicTimingsTask extends AsyncTask<Void, Void, String> {
long id;
public TopicTimingsTask(long id) {
this.id = id;
}
@Override
protected String doInBackground(Void... params) {
try {
String url = App.getSiteUrl() + Api.TOPIC_TIMINGS;
HttpRequest hr = HttpRequest.post(url);
HttpURLConnection connection = hr.getConnection();
if (App.isLogin()) {
App.getCookieManager().setCookies(connection);
}
int code = hr.form(Api.Params.TOPIC_ID, mId).form(Api.Params.TOPIC_TIME, 1000).code();
L.i("%s topic timings %d ", url, code);
return String.valueOf(code);
} catch (Exception e) {
L.e(e);
return null;
}
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
}
}
class DeleteTask extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
try {
Post p = mMenuPost;
String url = App.getSiteUrl() + String.format(Api.DELETE_POST, p.id);
HttpRequest hr = HttpRequest.delete(url);
HttpURLConnection connection = hr.getConnection();
if (App.isLogin()) {
App.getCookieManager().setCookies(connection);
}
int code = hr.code();
L.i("%s star code %d ", url, code);
String body = hr.body();
L.i(body);
return String.valueOf(code);
} catch (Exception e) {
L.e(e);
return null;
}
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
int res = R.string.post_delete_failure;
if ("200".equals(result)) {
res = R.string.post_delete_success;
final Post p = mMenuPost;
p.cooked = getResources().getString(R.string.post_delete_content);
p.can_delete = false;
p.can_recover = true;
p.can_edit = false;
mAdapter.notifyDataSetChanged();
}
Toast.makeText(getActivity(), res, Toast.LENGTH_SHORT).show();
}
}
class RecoverTask extends AsyncTask<Void, Void, String> {
Post mPost;
int mIndex;
public RecoverTask(Post p, int i) {
mPost = p;
mIndex = i;
}
@Override
protected String doInBackground(Void... params) {
try {
Post p = mPost;
String url = App.getSiteUrl() + String.format(Api.RECOVER_POST, p.id);
HttpRequest hr = HttpRequest.put(url);
HttpURLConnection connection = hr.getConnection();
if (App.isLogin()) {
App.getCookieManager().setCookies(connection);
}
int code = hr.code();
L.i("%s star code %d ", url, code);
String body = hr.body();
L.i(body);
return body;
} catch (Exception e) {
L.e(e);
return null;
}
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
JSONObject obj = new JSONObject(result);
Post p = Api.getPost(obj);
mAdapter.setPost(mIndex, p);
} catch (JSONException e) {
int res = R.string.post_recover_failure;
Toast.makeText(getActivity(), res, Toast.LENGTH_SHORT).show();
}
}
}
class InviteTask extends AsyncTask<Void, Void, Boolean> {
private static final String SUCCESS = "success";
private static final String FAILED = "failed";
private String mEmail;
private long mId;
public InviteTask(String email, long id) {
mEmail = email;
mId = id;
}
@Override
protected Boolean doInBackground(Void... params) {
try {
String url = App.getSiteUrl() + String.format(Api.INVITE, mId);
HttpRequest hr = HttpRequest.post(url);
HttpURLConnection connection = hr.getConnection();
if (App.isLogin()) {
App.getCookieManager().setCookies(connection);
}
int code = hr.form("user", mEmail).code();
L.i("%s star code %d ", url, code);
String body = hr.body();
L.i(body);
try {
JSONObject obj = new JSONObject(body);
return obj.has(SUCCESS);
} catch (Exception e) {
}
} catch (Exception e) {
L.e(e);
}
return false;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
String txt = null;
if (result) {
txt = getResources().getString(R.string.invite_success, mEmail);
} else {
txt = getResources().getString(R.string.invite_error);
}
Toast.makeText(getActivity(), txt, Toast.LENGTH_LONG).show();
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
}
}