aboutsummaryrefslogtreecommitdiff
path: root/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java')
-rw-r--r--WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java583
1 files changed, 583 insertions, 0 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java
new file mode 100644
index 000000000..2e85481fb
--- /dev/null
+++ b/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java
@@ -0,0 +1,583 @@
+package org.wordpress.android.ui.media;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.ColorDrawable;
+import android.net.ConnectivityManager;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v4.view.MenuItemCompat.OnActionExpandListener;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.SearchView;
+import android.support.v7.widget.SearchView.OnQueryTextListener;
+import android.support.v7.widget.Toolbar;
+import android.text.TextUtils;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.PopupWindow;
+import android.widget.Toast;
+
+import org.wordpress.android.R;
+import org.wordpress.android.WordPress;
+import org.wordpress.android.models.FeatureSet;
+import org.wordpress.android.ui.ActivityId;
+import org.wordpress.android.ui.media.MediaEditFragment.MediaEditFragmentCallback;
+import org.wordpress.android.ui.media.MediaGridFragment.Filter;
+import org.wordpress.android.ui.media.MediaGridFragment.MediaGridListener;
+import org.wordpress.android.ui.media.MediaItemFragment.MediaItemFragmentCallback;
+import org.wordpress.android.ui.media.services.MediaDeleteService;
+import org.wordpress.android.ui.media.services.MediaEvents;
+import org.wordpress.android.util.ActivityUtils;
+import org.wordpress.android.util.NetworkUtils;
+import org.wordpress.android.util.PermissionUtils;
+import org.wordpress.android.util.ToastUtils;
+import org.xmlrpc.android.ApiHelper;
+import org.xmlrpc.android.ApiHelper.GetFeatures.Callback;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import de.greenrobot.event.EventBus;
+
+/**
+ * The main activity in which the user can browse their media.
+ */
+public class MediaBrowserActivity extends AppCompatActivity implements MediaGridListener,
+ MediaItemFragmentCallback, OnQueryTextListener, OnActionExpandListener,
+ MediaEditFragmentCallback {
+ private static final String SAVED_QUERY = "SAVED_QUERY";
+ public static final int MEDIA_PERMISSION_REQUEST_CODE = 1;
+
+ private MediaGridFragment mMediaGridFragment;
+ private MediaItemFragment mMediaItemFragment;
+ private MediaEditFragment mMediaEditFragment;
+ private MediaAddFragment mMediaAddFragment;
+ private PopupWindow mAddMediaPopup;
+
+ private SearchView mSearchView;
+ private MenuItem mSearchMenuItem;
+ private Menu mMenu;
+ private FeatureSet mFeatureSet;
+ private String mQuery;
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
+ // Coming from zero connection. Continue what's pending for delete
+ int blogId = WordPress.getCurrentLocalTableBlogId();
+ if (blogId != -1 && WordPress.wpDB.hasMediaDeleteQueueItems(blogId)) {
+ startMediaDeleteService();
+ }
+ }
+ }
+ };
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // This should be removed when #2734 is fixed
+ if (WordPress.getCurrentBlog() == null) {
+ ToastUtils.showToast(this, R.string.blog_not_found, ToastUtils.Duration.SHORT);
+ finish();
+ return;
+ }
+
+ setContentView(R.layout.media_browser_activity);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayShowTitleEnabled(true);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setTitle(R.string.media);
+
+ FragmentManager fm = getFragmentManager();
+ fm.addOnBackStackChangedListener(mOnBackStackChangedListener);
+ FragmentTransaction ft = fm.beginTransaction();
+
+ mMediaAddFragment = (MediaAddFragment) fm.findFragmentById(R.id.mediaAddFragment);
+ mMediaGridFragment = (MediaGridFragment) fm.findFragmentById(R.id.mediaGridFragment);
+
+ mMediaItemFragment = (MediaItemFragment) fm.findFragmentByTag(MediaItemFragment.TAG);
+ if (mMediaItemFragment != null)
+ ft.hide(mMediaGridFragment);
+
+ mMediaEditFragment = (MediaEditFragment) fm.findFragmentByTag(MediaEditFragment.TAG);
+ if (mMediaEditFragment != null && !mMediaEditFragment.isInLayout())
+ ft.hide(mMediaItemFragment);
+
+ ft.commitAllowingStateLoss();
+
+ setupAddMenuPopup();
+
+ String action = getIntent().getAction();
+ if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+ // We arrived here from a share action
+ uploadSharedFiles();
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ registerReceiver(mReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
+ EventBus.getDefault().register(this);
+ }
+
+ @Override
+ public void onStop() {
+ EventBus.getDefault().unregister(this);
+ unregisterReceiver(mReceiver);
+ super.onStop();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putString(SAVED_QUERY, mQuery);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ mQuery = savedInstanceState.getString(SAVED_QUERY);
+ }
+
+ private void uploadSharedFiles() {
+ Intent intent = getIntent();
+ String action = intent.getAction();
+ final List<Uri> multi_stream;
+ if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+ multi_stream = intent.getParcelableArrayListExtra((Intent.EXTRA_STREAM));
+ } else {
+ multi_stream = new ArrayList<>();
+ multi_stream.add((Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM));
+ }
+ mMediaAddFragment.uploadList(multi_stream);
+
+ // clear the intent's action, so that in case the user rotates, we don't re-upload the same
+ // files
+ getIntent().setAction(null);
+ }
+
+ private final FragmentManager.OnBackStackChangedListener mOnBackStackChangedListener = new FragmentManager.OnBackStackChangedListener() {
+ public void onBackStackChanged() {
+ FragmentManager manager = getFragmentManager();
+ MediaGridFragment mediaGridFragment = (MediaGridFragment)manager.findFragmentById(R.id.mediaGridFragment);
+ if (mediaGridFragment.isVisible()) {
+ mediaGridFragment.refreshSpinnerAdapter();
+ }
+ ActivityUtils.hideKeyboard(MediaBrowserActivity.this);
+ }
+ };
+
+ /** Setup the popup that allows you to add new media from camera, video camera or local files **/
+ private void setupAddMenuPopup() {
+ String capturePhoto = getResources().getString(R.string.media_add_popup_capture_photo);
+ String captureVideo = getResources().getString(R.string.media_add_popup_capture_video);
+ String pickPhotoFromGallery = getResources().getString(R.string.select_photo);
+ String pickVideoFromGallery = getResources().getString(R.string.select_video);
+ final ArrayAdapter<String> adapter = new ArrayAdapter<>(MediaBrowserActivity.this,
+ R.layout.actionbar_add_media_cell,
+ new String[] {
+ capturePhoto, captureVideo, pickPhotoFromGallery, pickVideoFromGallery
+ });
+
+ View layoutView = getLayoutInflater().inflate(R.layout.actionbar_add_media, null, false);
+ ListView listView = (ListView) layoutView.findViewById(R.id.actionbar_add_media_listview);
+ listView.setAdapter(adapter);
+ listView.setOnItemClickListener(new OnItemClickListener() {
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ adapter.notifyDataSetChanged();
+
+ if (position == 0) {
+ mMediaAddFragment.launchCamera();
+ } else if (position == 1) {
+ mMediaAddFragment.launchVideoCamera();
+ } else if (position == 2) {
+ mMediaAddFragment.launchPictureLibrary();
+ } else if (position == 3) {
+ mMediaAddFragment.launchVideoLibrary();
+ }
+
+ mAddMediaPopup.dismiss();
+ }
+ });
+
+ int width = getResources().getDimensionPixelSize(R.dimen.action_bar_spinner_width);
+
+ mAddMediaPopup = new PopupWindow(layoutView, width, ViewGroup.LayoutParams.WRAP_CONTENT, true);
+ mAddMediaPopup.setBackgroundDrawable(new ColorDrawable());
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ startMediaDeleteService();
+ getFeatureSet();
+ ActivityId.trackLastActivity(ActivityId.MEDIA);
+ }
+
+ /** Get the feature set for a wordpress.com hosted blog **/
+ private void getFeatureSet() {
+ if (WordPress.getCurrentBlog() == null || !WordPress.getCurrentBlog().isDotcomFlag())
+ return;
+
+ ApiHelper.GetFeatures task = new ApiHelper.GetFeatures(new Callback() {
+ @Override
+ public void onResult(FeatureSet featureSet) {
+ mFeatureSet = featureSet;
+ }
+
+ });
+
+ List<Object> apiArgs = new ArrayList<>();
+ apiArgs.add(WordPress.getCurrentBlog());
+ task.execute(apiArgs);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ if (mSearchMenuItem != null) {
+ String tempQuery = mQuery;
+ MenuItemCompat.collapseActionView(mSearchMenuItem);
+ mQuery = tempQuery;
+ }
+ }
+
+ @Override
+ public void onMediaItemSelected(String mediaId) {
+ String tempQuery = mQuery;
+ if (mSearchView != null) {
+ mSearchView.clearFocus();
+ }
+
+ if (mSearchMenuItem != null) {
+ MenuItemCompat.collapseActionView(mSearchMenuItem);
+ }
+
+ FragmentManager fm = getFragmentManager();
+ if (fm.getBackStackEntryCount() == 0) {
+ FragmentTransaction ft = fm.beginTransaction();
+ ft.hide(mMediaGridFragment);
+ mMediaGridFragment.clearSelectedItems();
+ mMediaItemFragment = MediaItemFragment.newInstance(mediaId);
+ ft.add(R.id.media_browser_container, mMediaItemFragment, MediaItemFragment.TAG);
+ ft.addToBackStack(null);
+ ft.commitAllowingStateLoss();
+ mQuery = tempQuery;
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ mMenu = menu;
+ getMenuInflater().inflate(R.menu.media, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ mSearchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
+ mSearchView.setOnQueryTextListener(this);
+
+ mSearchMenuItem = menu.findItem(R.id.menu_search);
+ MenuItemCompat.setOnActionExpandListener(mSearchMenuItem, this);
+
+ //open search bar if we were searching for something before
+ if (!TextUtils.isEmpty(mQuery) && mMediaGridFragment != null && mMediaGridFragment.isVisible()) {
+ String tempQuery = mQuery; //temporary hold onto query
+ MenuItemCompat.expandActionView(mSearchMenuItem); //this will reset mQuery
+ onQueryTextSubmit(tempQuery);
+ mSearchView.setQuery(mQuery, true);
+ }
+
+ return super.onPrepareOptionsMenu(menu);
+
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
+ @NonNull int[] grantResults) {
+ switch (requestCode) {
+ case MEDIA_PERMISSION_REQUEST_CODE:
+ for (int grantResult : grantResults) {
+ if (grantResult == PackageManager.PERMISSION_DENIED) {
+ ToastUtils.showToast(this, getString(R.string.add_media_permission_required));
+ return;
+ }
+ }
+ showNewMediaMenu();
+ break;
+ default:
+ break;
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int i = item.getItemId();
+ if (i == android.R.id.home) {
+ onBackPressed();
+ return true;
+ } else if (i == R.id.menu_new_media) {
+ if (PermissionUtils.checkAndRequestCameraAndStoragePermissions(this, MEDIA_PERMISSION_REQUEST_CODE)) {
+ showNewMediaMenu();
+ }
+ return true;
+ } else if (i == R.id.menu_search) {
+ mSearchMenuItem = item;
+ MenuItemCompat.setOnActionExpandListener(mSearchMenuItem, this);
+ MenuItemCompat.expandActionView(mSearchMenuItem);
+
+ mSearchView = (SearchView) item.getActionView();
+ mSearchView.setOnQueryTextListener(this);
+
+ // load last saved query
+ if (!TextUtils.isEmpty(mQuery)) {
+ onQueryTextSubmit(mQuery);
+ mSearchView.setQuery(mQuery, true);
+ }
+ return true;
+ } else if (i == R.id.menu_edit_media) {
+ String mediaId = mMediaItemFragment.getMediaId();
+ FragmentManager fm = getFragmentManager();
+
+ if (mMediaEditFragment == null || !mMediaEditFragment.isInLayout()) {
+ // phone layout: hide item details, show and update edit fragment
+ FragmentTransaction ft = fm.beginTransaction();
+
+ if (mMediaItemFragment.isVisible())
+ ft.hide(mMediaItemFragment);
+
+ mMediaEditFragment = MediaEditFragment.newInstance(mediaId);
+ ft.add(R.id.media_browser_container, mMediaEditFragment, MediaEditFragment.TAG);
+ ft.addToBackStack(null);
+ ft.commitAllowingStateLoss();
+ } else {
+ // tablet layout: update edit fragment
+ mMediaEditFragment.loadMedia(mediaId);
+ }
+
+ if (mSearchView != null) {
+ mSearchView.clearFocus();
+ }
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onMediaItemListDownloaded() {
+ if (mMediaItemFragment != null) {
+ mMediaGridFragment.setRefreshing(false);
+ if (mMediaItemFragment.isInLayout()) {
+ mMediaItemFragment.loadDefaultMedia();
+ }
+ }
+ }
+
+ @Override
+ public void onMediaItemListDownloadStart() {
+ mMediaGridFragment.setRefreshing(true);
+ }
+
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ if (mMediaGridFragment != null) {
+ mMediaGridFragment.search(query);
+ }
+ mQuery = query;
+ mSearchView.clearFocus();
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ if (mMediaGridFragment != null) {
+ mMediaGridFragment.search(newText);
+ }
+ mQuery = newText;
+ return true;
+ }
+
+ @Override
+ public void onResume(Fragment fragment) {
+ invalidateOptionsMenu();
+ }
+
+ @Override
+ public void onPause(Fragment fragment) {
+ invalidateOptionsMenu();
+ }
+
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ // currently we don't support searching from within a filter, so hide it
+ if (mMediaGridFragment != null) {
+ mMediaGridFragment.setFilterVisibility(View.GONE);
+ mMediaGridFragment.setFilter(Filter.ALL);
+ }
+
+ // load last search query
+ if (!TextUtils.isEmpty(mQuery))
+ onQueryTextChange(mQuery);
+ mMenu.findItem(R.id.menu_new_media).setVisible(false);
+ return true;
+ }
+
+ @Override
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ if (mMediaGridFragment != null) {
+ mMediaGridFragment.setFilterVisibility(View.VISIBLE);
+ mMediaGridFragment.setFilter(Filter.ALL);
+ }
+ mMenu.findItem(R.id.menu_new_media).setVisible(true);
+ return true;
+ }
+
+ public void onSavedEdit(String mediaId, boolean result) {
+ if (mMediaEditFragment != null && mMediaEditFragment.isVisible() && result) {
+ FragmentManager fm = getFragmentManager();
+ fm.popBackStack();
+
+ // refresh media item details (phone-only)
+ if (mMediaItemFragment != null)
+ mMediaItemFragment.loadMedia(mediaId);
+
+ // refresh grid
+ mMediaGridFragment.refreshMediaFromDB();
+ }
+ }
+
+ private void startMediaDeleteService() {
+ if (NetworkUtils.isNetworkAvailable(this)) {
+ startService(new Intent(this, MediaDeleteService.class));
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ FragmentManager fm = getFragmentManager();
+ if (fm.getBackStackEntryCount() > 0) {
+ fm.popBackStack();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public void onEventMainThread(MediaEvents.MediaChanged event) {
+ updateOnMediaChanged(event.mLocalBlogId, event.mMediaId);
+ }
+
+ @SuppressWarnings("unused")
+ public void onEventMainThread(MediaEvents.MediaUploadSucceeded event) {
+ updateOnMediaChanged(event.mLocalBlogId, event.mLocalMediaId);
+ }
+
+ @SuppressWarnings("unused")
+ public void onEventMainThread(MediaEvents.MediaUploadFailed event) {
+ ToastUtils.showToast(this, event.mErrorMessage, ToastUtils.Duration.LONG);
+ }
+
+ public void updateOnMediaChanged(String blogId, String mediaId) {
+ if (mediaId == null) {
+ return;
+ }
+
+ // If the media was deleted, remove it from multi select (if it was selected) and hide it from the the detail
+ // view (if it was the one displayed)
+ if (!WordPress.wpDB.mediaFileExists(blogId, mediaId)) {
+ mMediaGridFragment.removeFromMultiSelect(mediaId);
+ if (mMediaEditFragment != null && mMediaEditFragment.isVisible()
+ && mediaId.equals(mMediaEditFragment.getMediaId())) {
+ if (mMediaEditFragment.isInLayout()) {
+ mMediaEditFragment.loadMedia(null);
+ } else {
+ getFragmentManager().popBackStack();
+ }
+ }
+ }
+
+ // Update Grid view
+ mMediaGridFragment.refreshMediaFromDB();
+
+ // Update Spinner views
+ mMediaGridFragment.updateFilterText();
+ mMediaGridFragment.updateSpinnerAdapter();
+ }
+
+ @Override
+ public void onRetryUpload(String mediaId) {
+ mMediaAddFragment.addToQueue(mediaId);
+ }
+
+ public void deleteMedia(final ArrayList<String> ids) {
+ final String blogId = String.valueOf(WordPress.getCurrentBlog().getLocalTableBlogId());
+ Set<String> sanitizedIds = new HashSet<>(ids.size());
+
+ // phone layout: pop the item fragment if it's visible
+ getFragmentManager().popBackStack();
+
+ // Make sure there are no media in "uploading"
+ for (String currentID : ids) {
+ if (WordPressMediaUtils.canDeleteMedia(blogId, currentID)) {
+ sanitizedIds.add(currentID);
+ }
+ }
+
+ if (sanitizedIds.size() != ids.size()) {
+ if (ids.size() == 1) {
+ Toast.makeText(this, R.string.wait_until_upload_completes, Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(this, R.string.cannot_delete_multi_media_items, Toast.LENGTH_LONG).show();
+ }
+ }
+
+ // mark items for delete without actually deleting items yet,
+ // and then refresh the grid
+ WordPress.wpDB.setMediaFilesMarkedForDelete(blogId, sanitizedIds);
+ startMediaDeleteService();
+ if (mMediaGridFragment != null) {
+ mMediaGridFragment.clearSelectedItems();
+ mMediaGridFragment.refreshMediaFromDB();
+ }
+ }
+
+ private void showNewMediaMenu() {
+ View view = findViewById(R.id.menu_new_media);
+ if (view != null) {
+ int y_offset = getResources().getDimensionPixelSize(R.dimen.action_bar_spinner_y_offset);
+ int[] loc = new int[2];
+ view.getLocationOnScreen(loc);
+ mAddMediaPopup.showAtLocation(view, Gravity.TOP | Gravity.LEFT, loc[0],
+ loc[1] + view.getHeight() + y_offset);
+ } else {
+ // In case menu button is not on screen (declared showAsAction="ifRoom"), center the popup in the view.
+ View gridView = findViewById(R.id.media_gridview);
+ mAddMediaPopup.showAtLocation(gridView, Gravity.CENTER, 0, 0);
+ }
+ }
+}