package com.xda.one.ui;
import com.xda.one.R;
import com.xda.one.api.inteface.PostClient;
import com.xda.one.api.misc.Consumer;
import com.xda.one.api.misc.Result;
import com.xda.one.api.model.interfaces.Post;
import com.xda.one.api.model.interfaces.UnifiedThread;
import com.xda.one.api.model.response.ResponseAttachment;
import com.xda.one.api.model.response.ResponseUnifiedThread;
import com.xda.one.api.model.response.container.ResponsePostContainer;
import com.xda.one.api.retrofit.RetrofitPostClient;
import com.xda.one.loader.PostLoader;
import com.xda.one.model.augmented.AugmentedPost;
import com.xda.one.model.augmented.AugmentedPostContainer;
import com.xda.one.ui.helper.ActionModeHelper;
import com.xda.one.ui.helper.CancellableCallbackHelper;
import com.xda.one.ui.listener.AvatarClickListener;
import com.xda.one.util.UIUtils;
import com.xda.one.util.Utils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.Loader;
import android.support.v4.view.ViewCompat;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.XDALinerLayoutManager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class PostFragment extends Fragment
implements LoaderManager.LoaderCallbacks<AugmentedPostContainer> {
private static final String THREAD_ID_ARGUMENT = "thread_id";
private static final String LIST_PADDING_SIZE_SAVED_STATE = "padding_size_saved_state";
private static final String POSTS_SAVED_STATE = "posts_saved_state";
private static final String PAGE_CONTAINER_ARGUMENT = "page_container";
private static final int SCROLL_TO_LAST_LIST_ITEM = -1;
private static final int SCROLL_TO_NONE = -2;
private int mScrollToItem = SCROLL_TO_NONE;
private final BroadcastReceiver mOnNotificationClick = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
// TODO - do something useful here
}
};
private final BroadcastReceiver mOnComplete = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.build();
Toast.makeText(context, "Finished downloading", Toast.LENGTH_LONG).show();
}
};
private PostAdapter mAdapter;
private int mPage;
private String mThreadId;
private Callback mCallback;
private PostClient mPostClient;
private RecyclerView mRecyclerView;
private ActionModeHelper mModeHelper;
private ResponsePostContainer mContainerArgument;
private View mEmptyView;
public static PostFragment getInstance(final UnifiedThread unifiedThread, final int page) {
final Bundle bundle = new Bundle();
bundle.putString(THREAD_ID_ARGUMENT, unifiedThread.getThreadId());
bundle.putInt(PostPagerFragment.POST_PAGE_ARGUMENT, page);
final PostFragment fragment = new PostFragment();
fragment.setArguments(bundle);
return fragment;
}
public static Fragment getInstance(final ResponsePostContainer containerArgument) {
final Bundle bundle = new Bundle();
bundle.putParcelable(PAGE_CONTAINER_ARGUMENT, containerArgument);
final PostFragment fragment = new PostFragment();
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
// TODO - this may be an activity in the future - fix this
mCallback = (Callback) getParentFragment();
} catch (ClassCastException exc) {
exc.printStackTrace();
}
}
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mModeHelper = new ActionModeHelper(getActivity(),
new PostFragmentActionMode(), null, ActionModeHelper.SelectionMode.MULTIPLE);
mContainerArgument = getArguments().getParcelable(PAGE_CONTAINER_ARGUMENT);
if (mContainerArgument == null) {
mThreadId = getArguments().getString(THREAD_ID_ARGUMENT);
mPage = getArguments().getInt(PostPagerFragment.POST_PAGE_ARGUMENT);
} else {
mPage = mContainerArgument.getCurrentPage();
}
getActivity().registerReceiver(mOnComplete, new IntentFilter(DownloadManager
.ACTION_DOWNLOAD_COMPLETE));
getActivity().registerReceiver(mOnNotificationClick, new IntentFilter(DownloadManager
.ACTION_NOTIFICATION_CLICKED));
// Get the client for sending thanks and the like to the server
mPostClient = RetrofitPostClient.getClient(getActivity());
// Create the adapter...
// ... and set it up properly
mAdapter = new PostAdapter(getActivity(),
mModeHelper,
new DownloadButtonClickListener(),
new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO
}
},
new AvatarClickListener(getActivity()),
new View.OnClickListener() {
@Override
public void onClick(final View view) {
final int position = (int) view.getTag();
final AugmentedPost post = mAdapter.getPost(position);
toggleThanks(position, post);
}
},
new View.OnClickListener() {
@Override
public void onClick(View view) {
final int position = (int) view.getTag();
final AugmentedPost post = mAdapter.getPost(position);
quotePost(post);
}
},
new View.OnClickListener() {
@Override
public void onClick(View view) {
final View itemView = (View) view.getTag();
multiQuotePost(itemView);
}
},
new PostAdapter.GoToQuoteListener() {
@Override
public void onClick(final String postId) {
final AlertDialog dialog = ProgressDialog.show(getActivity(),
"Finding post position", "Finding post position", true, true);
final PostClient client = RetrofitPostClient.getClient(getActivity());
GoToQuoteCallback callback = new GoToQuoteCallback(dialog);
client.getPostsById(postId, callback, callback);
}
});
}
private void quotePost(final AugmentedPost... post) {
mCallback.quotePost(post);
}
private void multiQuotePost(final View view) {
mModeHelper.addViewToActionMode(view);
}
@Override
public void onDestroy() {
super.onDestroy();
getActivity().unregisterReceiver(mOnComplete);
getActivity().unregisterReceiver(mOnNotificationClick);
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
final Bundle savedInstanceState) {
return inflater.inflate(R.layout.post_fragment, container, false);
}
@Override
public void onViewCreated(final View view, final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
mRecyclerView.setLayoutManager(new XDALinerLayoutManager(getActivity()));
mRecyclerView.setAdapter(mAdapter);
ViewCompat.setOverScrollMode(mRecyclerView, ViewCompat.OVER_SCROLL_NEVER);
mEmptyView = view.findViewById(android.R.id.empty);
mModeHelper.setRecyclerView(mRecyclerView);
if (savedInstanceState == null) {
mCallback.postPaddingToQuickReturn(mRecyclerView);
} else {
final int paddingSize = savedInstanceState.getInt(LIST_PADDING_SIZE_SAVED_STATE, -1);
if (paddingSize != -1) {
final int paddingLeft = mRecyclerView.getPaddingLeft();
final int paddingRight = mRecyclerView.getPaddingRight();
final int paddingBottom = mRecyclerView.getPaddingBottom();
mRecyclerView.setPadding(paddingLeft, paddingSize, paddingRight, paddingBottom);
}
}
// We need to do this rather than relying on the loader because the loader is not
// preserved across page changes
if (savedInstanceState == null) {
getLoaderManager().initLoader(0, null, this);
} else {
final List<AugmentedPost> list = savedInstanceState
.getParcelableArrayList(POSTS_SAVED_STATE);
if (Utils.isCollectionEmpty(list)) {
getLoaderManager().initLoader(0, null, this);
} else {
UIUtils.updateEmptyViewState(getView(), mRecyclerView, list.size());
mAdapter.addAll(list);
}
}
mCallback.setQuickReturnListener(mRecyclerView, mPage - 1);
}
@Override
public void onViewStateRestored(@Nullable final Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
mModeHelper.restoreInstanceState(savedInstanceState);
}
@Override
public void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
final ArrayList<AugmentedPost> list = new ArrayList<>(mAdapter.getPosts());
outState.putParcelableArrayList(POSTS_SAVED_STATE, list);
mModeHelper.saveInstanceState(outState);
if (getView() != null) {
outState.putInt(LIST_PADDING_SIZE_SAVED_STATE, mRecyclerView.getPaddingTop());
}
}
@Override
public Loader<AugmentedPostContainer> onCreateLoader(int id, Bundle args) {
if (mContainerArgument == null) {
return new PostLoader(getActivity(), mThreadId, mPage);
}
mScrollToItem = mContainerArgument.getIndex();
return new PostLoader(getActivity(), mContainerArgument);
}
@Override
public void onLoadFinished(final Loader<AugmentedPostContainer> loader,
final AugmentedPostContainer container) {
if (container == null) {
onItemsReceived(null);
} else {
onItemsReceived(container.getPosts());
mCallback.onPageLoaded(container.getThread());
}
}
private void onItemsReceived(final List<AugmentedPost> data) {
if (data == null && mAdapter.getItemCount() != 0) {
Toast.makeText(getActivity(), R.string.unable_to_refresh, Toast.LENGTH_LONG).show();
return;
} else if (data == null) {
UIUtils.updateEmptyViewState(getView(), mRecyclerView, 0);
return;
}
mAdapter.clear();
UIUtils.updateEmptyViewState(getView(), mRecyclerView, data.size());
mAdapter.addAll(data);
// Scroll to the relevant position in the list
if (mScrollToItem == SCROLL_TO_LAST_LIST_ITEM) {
mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
} else if (mScrollToItem != SCROLL_TO_NONE) {
mRecyclerView.scrollToPosition(mScrollToItem);
}
mScrollToItem = SCROLL_TO_NONE;
}
@Override
public void onLoaderReset(final Loader<AugmentedPostContainer> loader) {
}
private void toggleThanks(final int position, final Post post) {
mPostClient.toggleThanksAsync(post, new Consumer<Result>() {
@Override
public void run(Result result) {
Toast.makeText(getActivity(), "Thanks toggled", Toast.LENGTH_LONG).show();
mAdapter.notifyItemChanged(position);
}
});
}
public void refreshPageAndScrollToBottom() {
// We want to scroll to the bottom as the method name suggests
mScrollToItem = SCROLL_TO_LAST_LIST_ITEM;
// We also want to clear everything in the adapter
mAdapter.clear();
// And show the loading view
UIUtils.showLoadingProgress(mRecyclerView, mEmptyView);
// And then re-fetch the data from the server
getLoaderManager().restartLoader(0, null, this);
}
public boolean isActionModeStarted() {
return mModeHelper.isActionModeStarted();
}
public AugmentedPost[] getCheckedItems() {
return mAdapter.getPosts(mModeHelper.getCheckedPositions());
}
public void finishActionMode() {
if (mModeHelper != null) {
mModeHelper.finish();
}
}
public void scrollToPosition(final ResponsePostContainer data) {
mRecyclerView.scrollToPosition(data.getIndex());
}
public static interface Callback {
public void quotePost(final AugmentedPost... post);
public void switchToFragment(final ResponsePostContainer container);
public void setQuickReturnListener(final RecyclerView recyclerView, final int page);
public void postPaddingToQuickReturn(final View content);
public void onPageLoaded(final ResponseUnifiedThread thread);
}
private class DownloadButtonClickListener implements View.OnClickListener {
@Override
public void onClick(final View v) {
final ResponseAttachment a = (ResponseAttachment) v.getTag();
final DownloadManager manager = (DownloadManager) getActivity().getSystemService
(Context.DOWNLOAD_SERVICE);
final DownloadManager.Request request = new DownloadManager
.Request(Uri.parse(a.getAttachmentUrl()))
.setAllowedOverRoaming(false)
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS + "/XDA One/", a.getFileName());
manager.enqueue(request);
}
}
public class PostFragmentActionMode extends ActionModeHelper.RecyclerViewActionModeCallback {
@Override
public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
actionMode.getMenuInflater().inflate(R.menu.post_fragment_cab, menu);
return true;
}
@Override
public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.post_fragment_cab_quote:
final AugmentedPost[] posts = mAdapter
.getPosts(mModeHelper.getCheckedPositions());
quotePost(posts);
}
mModeHelper.finish();
return true;
}
}
public class GoToQuoteCallback extends CancellableCallbackHelper<ResponsePostContainer> {
private final AlertDialog mDialog;
public GoToQuoteCallback(final AlertDialog dialog) {
super(dialog);
mDialog = dialog;
}
@Override
public void safeCallback(final ResponsePostContainer data) {
mDialog.dismiss();
if (data.getCurrentPage() == mPage) {
scrollToPosition(data);
} else {
mCallback.switchToFragment(data);
}
}
@Override
public void run() {
}
}
}