package com.kenny.openimgur.activities;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.OvershootInterpolator;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import com.kenny.openimgur.R;
import com.kenny.openimgur.api.ApiClient;
import com.kenny.openimgur.api.responses.AlbumResponse;
import com.kenny.openimgur.api.responses.BasicObjectResponse;
import com.kenny.openimgur.api.responses.BasicResponse;
import com.kenny.openimgur.api.responses.CommentPostResponse;
import com.kenny.openimgur.api.responses.CommentResponse;
import com.kenny.openimgur.classes.CustomLinkMovement;
import com.kenny.openimgur.classes.ImgurAlbum;
import com.kenny.openimgur.classes.ImgurBaseObject;
import com.kenny.openimgur.classes.ImgurComment;
import com.kenny.openimgur.classes.ImgurListener;
import com.kenny.openimgur.classes.OpengurApp;
import com.kenny.openimgur.fragments.CommentPopupFragment;
import com.kenny.openimgur.fragments.ImgurViewFragment;
import com.kenny.openimgur.fragments.PopupImageDialogFragment;
import com.kenny.openimgur.fragments.SideGalleryFragment;
import com.kenny.openimgur.ui.VideoView;
import com.kenny.openimgur.ui.ViewPager;
import com.kenny.openimgur.ui.adapters.CommentAdapter;
import com.kenny.openimgur.util.LinkUtils;
import com.kenny.openimgur.util.LogUtil;
import com.kenny.openimgur.util.ViewUtils;
import com.kennyc.bottomsheet.BottomSheet;
import com.kennyc.bottomsheet.BottomSheetListener;
import com.kennyc.view.MultiStateView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import butterknife.BindView;
import butterknife.OnClick;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Created by kcampagna on 7/12/14.
*/
public class ViewActivity extends BaseActivity implements View.OnClickListener, ImgurListener, SideGalleryFragment.SideGalleryListener, CommentPopupFragment.CommentListener {
private enum CommentSort {
BEST, NEW, TOP, WORST;
public String getApiValue() {
switch (this) {
case BEST:
case NEW:
case TOP:
return name().toLowerCase(Locale.ENGLISH);
case WORST:
return "top";
default:
return "best";
}
}
public static CommentSort getSortFromPosition(int position) {
return CommentSort.values()[position];
}
public static String[] getItemsForArray(Context context) {
CommentSort[] items = CommentSort.values();
String[] values = new String[items.length];
for (int i = 0; i < items.length; i++) {
switch (items[i]) {
case BEST:
values[i] = context.getString(R.string.sort_best);
break;
case TOP:
values[i] = context.getString(R.string.sort_top);
break;
case NEW:
values[i] = context.getString(R.string.sort_new);
break;
case WORST:
values[i] = context.getString(R.string.sort_worst);
}
}
return values;
}
public static CommentSort getSortFromString(String item) {
for (CommentSort s : CommentSort.values()) {
if (s.name().equalsIgnoreCase(item)) {
return s;
}
}
return BEST;
}
}
private static final String KEY_VIEW_FOR_ALBUM = "view_link_for_album";
private static final String KEY_COMMENT = "comments";
private static final String KEY_POSITION = "position";
private static final String KEY_OBJECTS = "objects";
private static final String KEY_SORT = "commentSort";
private static final String KEY_LOAD_COMMENTS = "autoLoadComments";
private static final String KEY_PANEL_EXPANDED = "panelExpanded";
private static final String PREF_HIDE_PANEL = "hide_panel";
public static final String KEY_ENDING_ITEM = "ending_item";
@BindView(R.id.pager)
ViewPager mViewPager;
@BindView(R.id.sliding_layout)
LinearLayout mSlidingRoot;
@BindView(R.id.multiView)
MultiStateView mMultiView;
@BindView(R.id.commentList)
RecyclerView mCommentList;
@BindView(R.id.panelUpBtn)
ImageButton mPanelButton;
@BindView(R.id.upVoteBtn)
ImageButton mUpVoteBtn;
@BindView(R.id.downVoteBtn)
ImageButton mDownVoteBtn;
CommentAdapter mCommentAdapter;
int mCurrentPosition = 0;
boolean mIsActionBarShowing = true;
String mGalleryId = null;
boolean mIsResuming = false;
boolean mLoadComments;
BrowsingAdapter mPagerAdapter;
CommentSort mCommentSort;
SideGalleryFragment mSideGalleryFragment;
BottomSheetBehavior mBottomSheetBehavior;
public static Intent createIntent(Context context, ArrayList<ImgurBaseObject> objects, int position) {
Intent intent = new Intent(context, ViewActivity.class);
intent.putExtra(KEY_POSITION, position);
intent.putExtra(KEY_OBJECTS, objects);
return intent;
}
public static Intent createIntent(Context context, String url, boolean isAlbumLink) {
return new Intent(context, ViewActivity.class)
.setAction(Intent.ACTION_VIEW)
.setData(Uri.parse(url))
.putExtra(KEY_VIEW_FOR_ALBUM, isAlbumLink);
}
public static Intent createGalleryIntent(Context context, String id) {
String url = String.format("http://imgur.com/gallery/%s", id);
return createIntent(context, url, false);
}
public static Intent createAlbumIntent(Context context, String id) {
String url = String.format("http://imgur.com/a/%s", id);
return createIntent(context, url, true);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view);
mCommentList.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
mSideGalleryFragment = (SideGalleryFragment) getFragmentManager().findFragmentById(R.id.sideGallery);
((Button) mMultiView.getView(MultiStateView.VIEW_STATE_ERROR).findViewById(R.id.errorButton)).setText(R.string.load_comments);
mViewPager.setPageTransformer(true, new ZoomOutPageTransformer());
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (!mIsResuming) {
mCurrentPosition = position;
fetchComments();
invalidateOptionsMenu();
if (mSideGalleryFragment != null) {
mSideGalleryFragment.onPositionChanged(position);
}
}
mIsResuming = false;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
initSlidingView();
handleIntent(getIntent(), savedInstanceState);
}
private void initSlidingView() {
mBottomSheetBehavior = BottomSheetBehavior.from(mSlidingRoot);
mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_COLLAPSED:
if (mPanelButton.getRotation() == 180) {
ObjectAnimator.ofFloat(mPanelButton, "rotation", 180, 0).setDuration(200).start();
}
break;
case BottomSheetBehavior.STATE_EXPANDED:
if (mPanelButton.getRotation() == 0) {
ObjectAnimator.ofFloat(mPanelButton, "rotation", 0, 180).setDuration(200).start();
}
break;
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
if (slideOffset >= 0.75f && mIsActionBarShowing) {
getSupportActionBar().hide();
mIsActionBarShowing = false;
} else if (slideOffset <= 0.75 && !mIsActionBarShowing) {
getSupportActionBar().show();
mIsActionBarShowing = true;
}
}
});
}
/**
* Handles the Intent arguments
*
* @param intent Arguments
* @param savedInstanceState Bundle if restoring
*/
private void handleIntent(Intent intent, Bundle savedInstanceState) {
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_OBJECTS)) {
LogUtil.v(TAG, "Bundle present, will restore in onPostCreate");
return;
}
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
LogUtil.v(TAG, "Received Gallery via ACTION_VIEW");
mGalleryId = intent.getData().getPathSegments().get(1);
} else if (!intent.hasExtra(KEY_OBJECTS) || !intent.hasExtra(KEY_POSITION)) {
Snackbar.make(mViewPager, R.string.error_generic, Snackbar.LENGTH_LONG).show();
finish();
} else {
mCurrentPosition = intent.getIntExtra(KEY_POSITION, 0);
ArrayList<ImgurBaseObject> objects = intent.getParcelableArrayListExtra(KEY_OBJECTS);
mPagerAdapter = new BrowsingAdapter(getApplicationContext(), getFragmentManager(), objects);
if (mSideGalleryFragment != null) {
mSideGalleryFragment.addGalleryItems(objects);
}
}
}
@Override
public void onBackPressed() {
if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
return;
}
ImgurBaseObject obj = mPagerAdapter != null ? mPagerAdapter.getImgurItem(mCurrentPosition) : null;
setResult(Activity.RESULT_OK, new Intent().putExtra(KEY_ENDING_ITEM, obj));
super.onBackPressed();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.view_activity, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (mBottomSheetBehavior != null) {
boolean hidePanel = app.getPreferences().getBoolean(PREF_HIDE_PANEL, false);
adjustPeekSize(hidePanel ? 0 : ViewUtils.getActionBarHeight(this));
menu.findItem(R.id.hideBar).setChecked(hidePanel);
}
return super.onPrepareOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.hideBar:
boolean isChecked = item.isChecked();
item.setChecked(!isChecked);
app.getPreferences().edit().putBoolean(PREF_HIDE_PANEL, !isChecked).apply();
adjustPeekSize(isChecked ? 0 : ViewUtils.getActionBarHeight(this));
return true;
case android.R.id.home:
ImgurBaseObject obj = mPagerAdapter != null ? mPagerAdapter.getImgurItem(mCurrentPosition) : null;
setResult(Activity.RESULT_OK, new Intent().putExtra(KEY_ENDING_ITEM, obj));
// Not retuning on purpose
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
if (savedInstanceState == null) {
mCommentSort = CommentSort.getSortFromString(app.getPreferences().getString(KEY_SORT, null));
mLoadComments = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getBoolean(KEY_LOAD_COMMENTS, true);
// Check if the activity was opened externally by a link click
if (!TextUtils.isEmpty(mGalleryId)) {
boolean isAlbumLink = getIntent().getBooleanExtra(KEY_VIEW_FOR_ALBUM, false);
fetchItemDetails(mGalleryId, isAlbumLink);
mMultiView.setViewState(MultiStateView.VIEW_STATE_LOADING);
} else {
mViewPager.setAdapter(mPagerAdapter);
// If we start on the 0 page, the onPageSelected event won't fire
if (mCurrentPosition == 0) {
fetchComments();
} else {
mViewPager.setCurrentItem(mCurrentPosition);
}
}
} else {
mCommentSort = CommentSort.getSortFromString(savedInstanceState.getString(KEY_SORT, CommentSort.NEW.name()));
mLoadComments = savedInstanceState.getBoolean(KEY_LOAD_COMMENTS, true);
mIsResuming = true;
mCurrentPosition = savedInstanceState.getInt(KEY_POSITION, 0);
ArrayList<ImgurBaseObject> objects = savedInstanceState.getParcelableArrayList(KEY_OBJECTS);
mPagerAdapter = new BrowsingAdapter(getApplicationContext(), getFragmentManager(), objects);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(mCurrentPosition);
if (mSideGalleryFragment != null) {
mSideGalleryFragment.addGalleryItems(objects);
}
List<ImgurComment> comments = savedInstanceState.getParcelableArrayList(KEY_COMMENT);
if (comments != null) {
mCommentAdapter = new CommentAdapter(this, comments, this);
mCommentList.setAdapter(mCommentAdapter);
}
if (mLoadComments) {
mMultiView.setViewState(MultiStateView.VIEW_STATE_CONTENT);
} else {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, R.string.comments_off);
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
if (savedInstanceState.getBoolean(KEY_PANEL_EXPANDED, false))
getSupportActionBar().hide();
}
}
@Override
protected void onResume() {
super.onResume();
if (mCommentAdapter != null) {
CustomLinkMovement.getInstance().addListener(this);
}
}
@Override
protected void onPause() {
CustomLinkMovement.getInstance().removeListener(this);
super.onPause();
}
@Override
protected void onDestroy() {
dismissDialogFragment("comment");
if (mCommentAdapter != null) {
mCommentAdapter.onDestroy();
mCommentAdapter = null;
}
if (mPagerAdapter != null) {
mPagerAdapter.clear();
mPagerAdapter = null;
}
super.onDestroy();
}
@OnClick({R.id.panelUpBtn, R.id.upVoteBtn, R.id.downVoteBtn, R.id.commentBtn, R.id.sortComments, R.id.errorButton})
@Override
public void onClick(View view) {
if (!canDoFragmentTransaction()) return;
switch (view.getId()) {
case R.id.panelUpBtn:
if (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else {
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
break;
case R.id.upVoteBtn:
case R.id.downVoteBtn:
if (user != null && mPagerAdapter != null) {
ImgurBaseObject obj = mPagerAdapter.getImgurItem(mCurrentPosition);
if (obj == null) return;
String vote = view.getId() == R.id.upVoteBtn ? ImgurBaseObject.VOTE_UP : ImgurBaseObject.VOTE_DOWN;
obj.setVote(vote);
ImgurViewFragment fragment = (ImgurViewFragment) mPagerAdapter.instantiateItem(mViewPager, mCurrentPosition);
if (fragment != null && fragment.isAdded() && fragment.getUserVisibleHint()) {
fragment.setVote(vote);
}
voteOnGallery(obj.getId(), vote);
} else {
Snackbar.make(mViewPager, R.string.user_not_logged_in, Snackbar.LENGTH_LONG).show();
}
break;
case R.id.commentBtn:
if (user != null && mPagerAdapter != null) {
DialogFragment fragment = CommentPopupFragment.createInstance(mPagerAdapter.getImgurItem(mCurrentPosition).getId(), null);
showDialogFragment(fragment, "comment");
} else {
Snackbar.make(mViewPager, R.string.user_not_logged_in, Snackbar.LENGTH_LONG).show();
}
break;
case R.id.sortComments:
new AlertDialog.Builder(ViewActivity.this, theme.getAlertDialogTheme())
.setTitle(R.string.sort_by)
.setItems(CommentSort.getItemsForArray(getApplicationContext()), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
CommentSort sort = CommentSort.getSortFromPosition(which);
if (sort != mCommentSort) {
mCommentSort = sort;
app.getPreferences().edit().putString(KEY_SORT, mCommentSort.name()).apply();
// Don't bother making an Api call if the item has no comments
if (mCommentAdapter != null && !mCommentAdapter.isEmpty()) {
fetchComments();
}
}
}
}).show();
break;
case R.id.errorButton:
// Set load comments to true, load comments, then set it back to its original value to persist its state
boolean loadComments = mLoadComments;
mLoadComments = true;
fetchComments();
mLoadComments = loadComments;
break;
}
}
@Override
public void onPhotoTap(View View) {
}
@Override
public void onPhotoLongTapListener(View View) {
}
@Override
public void onPlayTap(final ProgressBar prog, final FloatingActionButton play, final ImageView image, final VideoView video, final View view) {
}
@Override
public void onLinkTap(View view, String url) {
if (!TextUtils.isEmpty(url) && canDoFragmentTransaction()) {
LinkUtils.LinkMatch match = LinkUtils.findImgurLinkMatch(url);
switch (match) {
case GALLERY:
String id = LinkUtils.getGalleryId(url);
if (!TextUtils.isEmpty(id)) {
startActivity(ViewActivity.createGalleryIntent(getApplicationContext(), id).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
break;
case ALBUM:
String albumId = LinkUtils.getAlbumId(url);
Intent intent = ViewActivity.createAlbumIntent(getApplicationContext(), albumId).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
break;
case IMAGE_URL_QUERY:
int index = url.indexOf("?");
url = url.substring(0, index);
// Intentional fallthrough
case IMAGE_URL:
boolean isDirectLink = LinkUtils.isDirectImageLink(url);
if (!isDirectLink) {
url = LinkUtils.getId(url);
}
getFragmentManager().beginTransaction().add(PopupImageDialogFragment.getInstance(url, LinkUtils.isLinkAnimated(url), isDirectLink, false), "popup").commitAllowingStateLoss();
break;
case DIRECT_LINK:
boolean isAnimated = LinkUtils.isLinkAnimated(url);
boolean isVideo = LinkUtils.isVideoLink(url);
getFragmentManager().beginTransaction().add(PopupImageDialogFragment.getInstance(url, isAnimated, true, isVideo), "popup").commitAllowingStateLoss();
break;
case IMAGE:
String[] split = url.split("\\/");
getFragmentManager().beginTransaction().add(PopupImageDialogFragment.getInstance(split[split.length - 1], false, false, false), "popup").commitAllowingStateLoss();
break;
case USER_CALLOUT:
String uName = url.replace("@", "");
if ("op".equalsIgnoreCase(uName)) {
try {
uName = mPagerAdapter.getImgurItem(mCurrentPosition).getAccount();
} catch (Exception ex) {
LogUtil.e(TAG, "Unable to determine OP username from " + uName, ex);
uName = null;
}
}
if (!TextUtils.isEmpty(uName))
startActivity(ProfileActivity.createIntent(getApplicationContext(), uName));
break;
case USER:
String username = LinkUtils.getUsername(url);
if (!TextUtils.isEmpty(username)) {
startActivity(ProfileActivity.createIntent(getApplicationContext(), username));
}
break;
case TOPIC:
String topicId = LinkUtils.getTopicGalleryId(url);
startActivity(ViewActivity.createGalleryIntent(getApplicationContext(), topicId));
break;
case NONE:
default:
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
if (browserIntent.resolveActivity(getPackageManager()) != null) {
startActivity(browserIntent);
} else {
Snackbar.make(mViewPager, R.string.cant_launch_intent, Snackbar.LENGTH_LONG).show();
}
break;
}
} else {
if (view.getLayoutParams() instanceof RecyclerView.LayoutParams) {
onListItemClick(mCommentList.getChildAdapterPosition(view));
} else {
// This is super ugly, in order to the get position from the RecyclerView, we need the root view
View parent = (View) view.getParent();
if (parent != null) parent = (View) parent.getParent();
if (parent != null && parent.getLayoutParams() instanceof RecyclerView.LayoutParams) {
onListItemClick(mCommentList.getChildAdapterPosition(parent));
}
}
}
}
@Override
public void onViewRepliesTap(View view) {
int position = mCommentList.getLayoutManager().getPosition(view);
if (!mCommentAdapter.isExpanded(position)) {
mCommentAdapter.expandComments(view, position);
} else {
mCommentAdapter.collapseComments(view, position);
}
}
@Override
public void onItemSelected(int position) {
mViewPager.setCurrentItem(position);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mCommentAdapter != null && !mCommentAdapter.isEmpty()) {
outState.putParcelableArrayList(KEY_COMMENT, mCommentAdapter.retainItems());
}
outState.putBoolean(KEY_LOAD_COMMENTS, mLoadComments);
outState.putString(KEY_SORT, mCommentSort.name());
if (mPagerAdapter != null && !mPagerAdapter.isEmpty()) {
outState.putInt(KEY_POSITION, mViewPager.getCurrentItem());
outState.putParcelableArrayList(KEY_OBJECTS, mPagerAdapter.retainItems());
}
if (mBottomSheetBehavior != null) {
outState.putBoolean(KEY_PANEL_EXPANDED, mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED);
}
}
private void onListItemClick(final int position) {
if (mCommentAdapter == null) return;
if (position != RecyclerView.NO_POSITION) {
boolean shouldClose = mCommentAdapter.setSelectedIndex(position);
if (!shouldClose) {
final ImgurComment comment = mCommentAdapter.getItem(position);
if (TextUtils.isEmpty(comment.getAuthor()) || comment.getAuthor().equals("[deleted]")) {
mCommentAdapter.setSelectedIndex(-1);
return;
}
new BottomSheet.Builder(this)
.setSheet(R.menu.comment_menu)
.setStyle(theme.getBottomSheetTheme())
.grid()
.setTitle(R.string.options)
.setListener(new BottomSheetListener() {
@Override
public void onSheetShown(BottomSheet bottomSheet) {
LogUtil.v(TAG, "ImgurComment Selected " + comment);
}
@Override
public void onSheetItemSelected(BottomSheet bottomSheet, MenuItem menuItem) {
int id = menuItem.getItemId();
switch (id) {
case R.id.upVote:
case R.id.downVote:
if (user != null) {
String vote = id == R.id.upVote ? ImgurBaseObject.VOTE_UP : ImgurBaseObject.VOTE_DOWN;
comment.setVote(vote);
mCommentAdapter.notifyItemChanged(position);
voteOnComment(comment.getId(), vote);
} else {
Snackbar.make(mViewPager, R.string.user_not_logged_in, Snackbar.LENGTH_LONG).show();
}
break;
case R.id.profile:
startActivity(ProfileActivity.createIntent(ViewActivity.this, comment.getAuthor()));
break;
case R.id.reply:
if (user != null) {
DialogFragment fragment = CommentPopupFragment.createInstance(mPagerAdapter.getImgurItem(mCurrentPosition).getId(), comment.getId());
showDialogFragment(fragment, "comment");
} else {
Snackbar.make(mViewPager, R.string.user_not_logged_in, Snackbar.LENGTH_LONG).show();
}
break;
case R.id.copy:
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(getString(R.string.comment), comment.getComment());
clipboard.setPrimaryClip(clip);
Snackbar.make(mViewPager, R.string.comment_copied, Snackbar.LENGTH_LONG).show();
break;
}
}
@Override
public void onSheetDismissed(BottomSheet bottomSheet, int which) {
mCommentAdapter.setSelectedIndex(-1);
}
})
.show();
}
}
}
public void fetchComments() {
if (mLoadComments && mPagerAdapter != null) {
ImgurBaseObject imgurBaseObject = mPagerAdapter.getImgurItem(mCurrentPosition);
if (imgurBaseObject == null) {
LogUtil.w(TAG, "Object returned is null, can not load comments");
return;
}
if (imgurBaseObject.isListed()) {
mMultiView.setViewState(MultiStateView.VIEW_STATE_LOADING);
ApiClient.getService().getComments(imgurBaseObject.getId(), mCommentSort.getApiValue()).enqueue(new Callback<CommentResponse>() {
@Override
public void onResponse(Call<CommentResponse> call, Response<CommentResponse> response) {
if (mPagerAdapter == null || mPagerAdapter.getImgurItem(mCurrentPosition) == null) {
return;
}
if (response == null || response.body() == null) {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, response != null ? ApiClient.getErrorCode(response.code()) : R.string.error_generic);
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
return;
}
CommentResponse commentResponse = response.body();
if (commentResponse.hasComments()) {
ImgurBaseObject imgurBaseObject = mPagerAdapter.getImgurItem(mCurrentPosition);
String imageId = commentResponse.data.get(0).getImageId();
if (TextUtils.isEmpty(imageId) || imgurBaseObject == null) {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, R.string.error_generic);
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
return;
}
if (imageId.equals(imgurBaseObject.getId())) {
// Reverse the list for worst sorting as it will be loading the Top comments
if (mCommentSort == CommentSort.WORST)
Collections.reverse(commentResponse.data);
// We only show the comments for the correct gallery item
if (mCommentAdapter == null) {
mCommentAdapter = new CommentAdapter(ViewActivity.this, commentResponse.data, ViewActivity.this);
mCommentList.setAdapter(mCommentAdapter);
} else {
mCommentAdapter.clear();
mCommentAdapter.clearExpansionInfo();
mCommentAdapter.addItems(commentResponse.data);
}
mCommentAdapter.setOP(imgurBaseObject.getAccount());
mCommentAdapter.clearExpansionInfo();
mMultiView.setViewState(MultiStateView.VIEW_STATE_CONTENT);
mMultiView.post(new Runnable() {
@Override
public void run() {
if (mCommentList != null) mCommentList.scrollToPosition(0);
}
});
}
} else {
mMultiView.setViewState(MultiStateView.VIEW_STATE_EMPTY);
}
}
@Override
public void onFailure(Call<CommentResponse> call, Throwable t) {
LogUtil.e(TAG, "Error fetching comments", t);
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, ApiClient.getErrorCode(t));
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
});
} else {
mMultiView.setViewState(MultiStateView.VIEW_STATE_EMPTY);
ViewUtils.setEmptyText(mMultiView, R.id.emptyMessage, R.string.comments_unlisted);
}
} else if (mMultiView != null && mMultiView.getViewState() != MultiStateView.VIEW_STATE_ERROR) {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, R.string.comments_off);
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
}
private void fetchItemDetails(final String id, final boolean isAlbum) {
if (isAlbum) {
ApiClient.getService().getAlbumImages(id).enqueue(new Callback<AlbumResponse>() {
@Override
public void onResponse(Call<AlbumResponse> call, Response<AlbumResponse> response) {
if (response == null || response.body() == null) {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, R.string.error_generic);
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
return;
}
AlbumResponse albumResponse = response.body();
ImgurAlbum album = new ImgurAlbum(mGalleryId, null, getIntent().getData().toString());
mGalleryId = null;
album.addPhotosToAlbum(albumResponse.data);
final ArrayList<ImgurBaseObject> objects = new ArrayList<>(1);
objects.add(album);
mPagerAdapter = new BrowsingAdapter(getApplicationContext(), getFragmentManager(), objects);
mViewPager.setAdapter(mPagerAdapter);
invalidateOptionsMenu();
fetchComments();
}
@Override
public void onFailure(Call<AlbumResponse> call, Throwable t) {
LogUtil.e(TAG, "Unable to fetch album details", t);
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, ApiClient.getErrorCode(t));
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
});
} else {
ApiClient.getService().getGalleryDetails(id).enqueue(new Callback<BasicObjectResponse>() {
@Override
public void onResponse(Call<BasicObjectResponse> call, Response<BasicObjectResponse> response) {
if (response != null && response.body() != null && response.body().data != null) {
final ArrayList<ImgurBaseObject> objects = new ArrayList<>(1);
objects.add(response.body().data);
mPagerAdapter = new BrowsingAdapter(getApplicationContext(), getFragmentManager(), objects);
mViewPager.setAdapter(mPagerAdapter);
invalidateOptionsMenu();
fetchComments();
} else {
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, R.string.error_generic);
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
}
@Override
public void onFailure(Call<BasicObjectResponse> call, Throwable t) {
LogUtil.e(TAG, "Unable to fetch album details", t);
ViewUtils.setErrorText(mMultiView, R.id.errorMessage, ApiClient.getErrorCode(t));
mMultiView.setViewState(MultiStateView.VIEW_STATE_ERROR);
}
});
}
}
private void voteOnGallery(String id, final String vote) {
ApiClient.getService().voteOnGallery(id, vote, vote).enqueue(new Callback<BasicResponse>() {
@Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
if (response != null && response.body() != null && response.body().data) {
View animateView = ImgurBaseObject.VOTE_UP.equals(vote) ? mUpVoteBtn : mDownVoteBtn;
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(animateView, "scaleY", 1.0f, 2.0f, 1.0f),
ObjectAnimator.ofFloat(animateView, "scaleX", 1.0f, 2.0f, 1.0f)
);
set.setDuration(1500L).setInterpolator(new OvershootInterpolator());
set.start();
} else {
Snackbar.make(mViewPager, R.string.error_generic, Snackbar.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
LogUtil.e(TAG, "Unable to vote on gallery", t);
Snackbar.make(mViewPager, R.string.error_generic, Snackbar.LENGTH_LONG).show();
}
});
}
void voteOnComment(String id, final String vote) {
ApiClient.getService().voteOnComment(id, vote, vote).enqueue(new Callback<BasicResponse>() {
@Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
if (response.body() != null)
LogUtil.v(TAG, "Result of comment voting " + response.body().data);
}
@Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
LogUtil.e(TAG, "Unable to vote on comment", t);
}
});
}
@Override
public void onPostComment(String comment, String galleryId, String parentId) {
final @MultiStateView.ViewState int viewState = mMultiView.getViewState();
mMultiView.setViewState(MultiStateView.VIEW_STATE_LOADING);
Call<CommentPostResponse> call;
if (!TextUtils.isEmpty(parentId)) {
call = ApiClient.getService().postCommentReply(galleryId, parentId, comment);
} else {
call = ApiClient.getService().postComment(galleryId, comment);
}
call.enqueue(new Callback<CommentPostResponse>() {
@Override
public void onResponse(Call<CommentPostResponse> call, Response<CommentPostResponse> response) {
if (response != null && response.body() != null && response.body().data != null && !TextUtils.isEmpty(response.body().data.id)) {
Snackbar.make(mViewPager, R.string.comment_post_successful, Snackbar.LENGTH_LONG).show();
fetchComments();
} else {
Snackbar.make(mViewPager, R.string.comment_post_unsuccessful, Snackbar.LENGTH_LONG).show();
mMultiView.setViewState(viewState);
}
}
@Override
public void onFailure(Call<CommentPostResponse> call, Throwable t) {
LogUtil.e(TAG, "Unable to post comment", t);
Snackbar.make(mViewPager, R.string.comment_post_unsuccessful, Snackbar.LENGTH_LONG).show();
mMultiView.setViewState(viewState);
}
});
}
private void adjustPeekSize(int size) {
mBottomSheetBehavior.setPeekHeight(size);
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) mViewPager.getLayoutParams();
lp.setMargins(0, 0, 0, size);
mViewPager.setLayoutParams(lp);
}
static class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.5f;
private static final float MIN_ALPHA = 1.0f;
@Override
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
private static class BrowsingAdapter extends FragmentStatePagerAdapter {
private ArrayList<ImgurBaseObject> objects;
private boolean mDisplayTags;
public BrowsingAdapter(Context context, FragmentManager fm, ArrayList<ImgurBaseObject> objects) {
super(fm);
this.objects = objects;
mDisplayTags = OpengurApp.getInstance(context).getPreferences().getBoolean(SettingsActivity.KEY_TAGS, true);
}
@Override
public Fragment getItem(int position) {
return ImgurViewFragment.createInstance(objects.get(position), mDisplayTags);
}
@Override
public int getCount() {
return objects != null ? objects.size() : 0;
}
@Nullable
public ImgurBaseObject getImgurItem(int position) {
if (objects == null || position >= objects.size()) return null;
return objects.get(position);
}
public void clear() {
if (objects != null) {
objects.clear();
}
}
public boolean isEmpty() {
return objects == null || objects.isEmpty();
}
public ArrayList<ImgurBaseObject> retainItems() {
return new ArrayList<>(objects);
}
}
@Override
protected int getStyleRes() {
return theme.isDarkTheme ? R.style.Theme_Opengur_Dark_View_Dark : R.style.Theme_Opengur_Light_View_Light;
}
}