package com.kenny.openimgur.activities; import android.Manifest; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.Snackbar; import android.support.v13.app.FragmentStatePagerAdapter; import android.support.v4.app.ActivityCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.AlertDialog; import android.support.v7.widget.RecyclerView; import android.text.format.DateUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Toast; import com.kenny.openimgur.R; import com.kenny.openimgur.api.ApiClient; import com.kenny.openimgur.api.responses.AlbumResponse; import com.kenny.openimgur.classes.ImgurAlbum; import com.kenny.openimgur.classes.ImgurBaseObject; import com.kenny.openimgur.classes.ImgurPhoto; import com.kenny.openimgur.collections.SetUniqueList; import com.kenny.openimgur.fragments.FullScreenPhotoFragment; import com.kenny.openimgur.services.DownloaderService; import com.kenny.openimgur.ui.ViewPager; import com.kenny.openimgur.ui.adapters.GalleryAdapter; import com.kenny.openimgur.util.NetworkUtils; import com.kenny.openimgur.util.PermissionUtils; import com.kenny.openimgur.util.RequestCodes; import com.kenny.openimgur.util.ViewUtils; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; /** * Created by kcampagna on 6/2/15. */ public class FullScreenPhotoActivity extends BaseActivity implements View.OnClickListener { private static final String KEY_IMAGES = "images"; private static final String KEY_URL = "url"; private static final String KEY_IMAGE = "image"; private static final String KEY_OBJECT = "object"; private static final String KEY_START_POSITION = "start_position"; public static final String KEY_ENDING_POSITION = "ending_position"; @BindView(R.id.pager) ViewPager mPager; @BindView(R.id.grid) RecyclerView mGrid; View mDecorView; FullScreenPagerAdapter mAdapter; @Nullable VisibilityHandler mHandler; @Nullable BottomSheetBehavior mBottomSheetBehavior; public static Intent createIntent(@NonNull Context context, @NonNull ImgurPhoto photo) { return new Intent(context, FullScreenPhotoActivity.class).putExtra(KEY_IMAGE, photo); } public static Intent createIntent(@NonNull Context context, @NonNull String url) { return new Intent(context, FullScreenPhotoActivity.class).putExtra(KEY_URL, url); } public static Intent createIntent(@NonNull Context context, @NonNull ArrayList<ImgurPhoto> photos, @NonNull ImgurBaseObject obj, int startingPosition) { // Passing too many items in the intent might cause a crash if (photos.size() > GalleryAdapter.MAX_ITEMS) { return new Intent(context, FullScreenPhotoActivity.class).putExtra(KEY_OBJECT, obj).putExtra(KEY_START_POSITION, startingPosition); } else { return new Intent(context, FullScreenPhotoActivity.class).putExtra(KEY_IMAGES, photos).putExtra(KEY_START_POSITION, startingPosition); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); if (intent == null && savedInstanceState == null) { Toast.makeText(getApplicationContext(), R.string.error_generic, Toast.LENGTH_SHORT).show(); finish(); return; } setContentView(R.layout.activity_full_screen); handleArguments(savedInstanceState, intent); setStatusBarColor(Color.BLACK); getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); if (hasImmersiveMode()) { mDecorView = getWindow().getDecorView(); mDecorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int flags) { boolean isVisible = (flags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; if (isVisible && mHandler != null) { mHandler.removeMessages(0); Message msg = mHandler.obtainMessage(0, mDecorView); mHandler.sendMessageDelayed(msg, VisibilityHandler.HIDE_DELAY); } } }); } } @Override protected void onPostCreate(@Nullable Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); if (hasImmersiveMode()) { getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); mHandler = new VisibilityHandler(); Message msg = mHandler.obtainMessage(0, mDecorView); mHandler.sendMessageDelayed(msg, VisibilityHandler.HIDE_DELAY); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.full_screen, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onPrepareOptionsMenu(Menu menu) { boolean isAlbumDownloadable = mAdapter != null && mAdapter.getCount() > 1; menu.findItem(R.id.download_album).setVisible(isAlbumDownloadable); menu.findItem(R.id.gallery_view).setVisible(isAlbumDownloadable); return super.onPrepareOptionsMenu(menu); } @Override protected void onDestroy() { if (mHandler != null) mHandler.removeMessages(0); if (mGrid != null && mGrid.getAdapter() instanceof GalleryAdapter) ((GalleryAdapter) mGrid.getAdapter()).onDestroy(); super.onDestroy(); } private void downloadAlbum() { if (NetworkUtils.isConnectedToWiFi(getApplicationContext())) { ArrayList<String> urls = new ArrayList<>(mAdapter.getCount()); for (ImgurPhoto p : mAdapter.mPhotos) { urls.add(p.getLink()); } startService(DownloaderService.createIntent(getApplicationContext(), urls)); } else { new AlertDialog.Builder(this, theme.getAlertDialogTheme()) .setTitle(R.string.download_no_wifi_title) .setMessage(R.string.download_no_wifi_msg) .setNegativeButton(R.string.cancel, null) .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ArrayList<String> urls = new ArrayList<>(mAdapter.getCount()); for (ImgurPhoto p : mAdapter.mPhotos) { urls.add(p.getLink()); } startService(DownloaderService.createIntent(getApplicationContext(), urls)); } }).show(); } } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.download_album: @PermissionUtils.PermissionLevel int permissionLevel = PermissionUtils.getPermissionLevel(this, Manifest.permission.WRITE_EXTERNAL_STORAGE); switch (permissionLevel) { case PermissionUtils.PERMISSION_AVAILABLE: downloadAlbum(); break; case PermissionUtils.PERMISSION_DENIED: Snackbar.make(mPager, R.string.permission_rationale_download, Snackbar.LENGTH_LONG) .setAction(R.string.okay, new View.OnClickListener() { @Override public void onClick(View v) { ActivityCompat.requestPermissions(FullScreenPhotoActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RequestCodes.REQUEST_PERMISSION_WRITE); } }) .show(); break; case PermissionUtils.PERMISSION_NEVER_ASKED: default: ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, RequestCodes.REQUEST_PERMISSION_WRITE); break; } return true; case R.id.gallery_view: if (mBottomSheetBehavior != null) { mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); } return true; case android.R.id.home: int position = mPager != null ? mPager.getCurrentItem() : -1; if (position >= 0) setResult(Activity.RESULT_OK, new Intent().putExtra(KEY_ENDING_POSITION, position)); // intentional break break; } return super.onOptionsItemSelected(item); } private void handleArguments(Bundle savedInstanceState, Intent intent) { ArrayList<ImgurPhoto> photos; int startingPosition; if (savedInstanceState != null) { // The adapter should have been set and returned a list when saving state photos = savedInstanceState.getParcelableArrayList(KEY_IMAGES); startingPosition = savedInstanceState.getInt(KEY_START_POSITION); } else { if (intent.hasExtra(KEY_IMAGES)) { photos = intent.getParcelableArrayListExtra(KEY_IMAGES); } else if (intent.hasExtra(KEY_IMAGE)) { photos = new ArrayList<>(1); photos.add((ImgurPhoto) intent.getParcelableExtra(KEY_IMAGE)); } else if (intent.hasExtra(KEY_OBJECT)) { loadObject((ImgurBaseObject) intent.getParcelableExtra(KEY_OBJECT), intent.getIntExtra(KEY_START_POSITION, 0)); return; } else { photos = new ArrayList<>(1); String url = intent.getStringExtra(KEY_URL); photos.add(new ImgurPhoto(url)); } startingPosition = intent.getIntExtra(KEY_START_POSITION, 0); } setupPager(photos, startingPosition); } private boolean hasImmersiveMode() { return isApiLevel(Build.VERSION_CODES.KITKAT) && app.getPreferences().getBoolean(SettingsActivity.KEY_IMMERSIVE_MODE, false); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(KEY_START_POSITION, mPager.getCurrentItem()); if (mAdapter != null) outState.putParcelableArrayList(KEY_IMAGES, mAdapter.retainItems()); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case RequestCodes.REQUEST_PERMISSION_WRITE: if (PermissionUtils.verifyPermissions(grantResults)) { downloadAlbum(); } else { Toast.makeText(this, R.string.permission_denied, Toast.LENGTH_LONG).show(); finish(); } break; } super.onRequestPermissionsResult(requestCode, permissions, grantResults); } @Override public void onBackPressed() { if (mBottomSheetBehavior != null && (mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED || mBottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED)) { mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); return; } int position = mPager != null ? mPager.getCurrentItem() : -1; if (position >= 0) setResult(Activity.RESULT_OK, new Intent().putExtra(KEY_ENDING_POSITION, position)); super.onBackPressed(); } @Override public void onClick(View v) { if (mBottomSheetBehavior == null) return; int adapterPosition = mGrid.getChildAdapterPosition(v); if (adapterPosition != RecyclerView.NO_POSITION) { mPager.setCurrentItem(adapterPosition); mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); } } private void loadObject(@Nullable ImgurBaseObject obj, final int startingPosition) { if (obj == null) { Toast.makeText(this, R.string.error_generic, Toast.LENGTH_SHORT).show(); finish(); } // Should be the case if (obj instanceof ImgurAlbum) { ApiClient.getService().getAlbumImages(obj.getId()).enqueue(new Callback<AlbumResponse>() { @Override public void onResponse(Call<AlbumResponse> call, Response<AlbumResponse> response) { if (response != null && response.body() != null && response.body().hasData()) { setupPager(response.body().data, startingPosition); } else { Toast.makeText(getApplicationContext(), R.string.error_generic, Toast.LENGTH_SHORT).show(); finish(); } } @Override public void onFailure(Call<AlbumResponse> call, Throwable t) { Toast.makeText(getApplicationContext(), R.string.error_generic, Toast.LENGTH_SHORT).show(); finish(); } }); } else { Toast.makeText(this, R.string.error_generic, Toast.LENGTH_SHORT).show(); finish(); } } void setupPager(@Nullable List<ImgurPhoto> photos, int startingPosition) { if (photos == null) { Toast.makeText(getApplicationContext(), R.string.error_generic, Toast.LENGTH_SHORT).show(); finish(); return; } mAdapter = new FullScreenPagerAdapter(photos, getFragmentManager()); mPager.setAdapter(mAdapter); mPager.setCurrentItem(startingPosition); if (mAdapter.getCount() > 1) { getSupportActionBar().setTitle(mPager.getCurrentItem() + 1 + "/" + mAdapter.getCount()); mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // NOOP } @Override public void onPageSelected(int position) { getSupportActionBar().setTitle(mPager.getCurrentItem() + 1 + "/" + mAdapter.getCount()); } @Override public void onPageScrollStateChanged(int state) { // NOOP } }); } if (photos.size() > 1) { mBottomSheetBehavior = BottomSheetBehavior.from(mGrid); ViewUtils.setRecyclerViewGridDefaults(this, mGrid); List<ImgurBaseObject> adapterList = new ArrayList<>(photos.size()); adapterList.addAll(photos); mGrid.setAdapter(new GalleryAdapter(this, SetUniqueList.decorate(adapterList), this, false)); mBottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { ActionBar ab = getSupportActionBar(); if (newState == BottomSheetBehavior.STATE_EXPANDED) { ab.hide(); } else if (newState == BottomSheetBehavior.STATE_HIDDEN) { ab.show(); } } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { } }); mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); } supportInvalidateOptionsMenu(); } private static class FullScreenPagerAdapter extends FragmentStatePagerAdapter { List<ImgurPhoto> mPhotos; public FullScreenPagerAdapter(List<ImgurPhoto> photos, FragmentManager fm) { super(fm); mPhotos = photos; } @Override public Fragment getItem(int position) { return FullScreenPhotoFragment.createInstance(mPhotos.get(position)); } @Override public int getCount() { return mPhotos != null ? mPhotos.size() : 0; } public ArrayList<ImgurPhoto> retainItems() { return new ArrayList<>(mPhotos); } } static class VisibilityHandler extends Handler { public static final long HIDE_DELAY = DateUtils.SECOND_IN_MILLIS * 3; @Override public void handleMessage(Message msg) { if (msg.obj instanceof View) { ((View) msg.obj).setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE); } super.handleMessage(msg); } } @Override protected int getStyleRes() { return theme.isDarkTheme ? R.style.Theme_Opengur_Dark_View_Dark : R.style.Theme_Opengur_Light_View_Light; } }