diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionController.java b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionController.java new file mode 100644 index 000000000..f6beac475 --- /dev/null +++ b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionController.java @@ -0,0 +1,96 @@ +package org.wikimedia.commons.contributions; + +import android.app.*; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.provider.MediaStore; +import android.util.Log; +import com.actionbarsherlock.app.SherlockFragment; +import org.wikimedia.commons.upload.ShareActivity; +import org.wikimedia.commons.upload.UploadService; + +import java.io.File; +import java.io.IOException; +import java.util.Date; + +public class ContributionController { + private SherlockFragment fragment; + private Activity activity; + + private final static int SELECT_FROM_GALLERY = 1; + private final static int SELECT_FROM_CAMERA = 2; + + public ContributionController(SherlockFragment fragment) { + this.fragment = fragment; + this.activity = fragment.getActivity(); + } + + // See http://stackoverflow.com/a/5054673/17865 for why this is done + private Uri lastGeneratedCaptureURI; + + private Uri reGenerateImageCaptureURI() { + String storageState = Environment.getExternalStorageState(); + if(storageState.equals(Environment.MEDIA_MOUNTED)) { + + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Commons/images/" + new Date().getTime() + ".jpg"; + File _photoFile = new File(path); + try { + if(_photoFile.exists() == false) { + _photoFile.getParentFile().mkdirs(); + _photoFile.createNewFile(); + } + + } catch (IOException e) { + Log.e("Commons", "Could not create file: " + path, e); + } + + return Uri.fromFile(_photoFile); + } else { + throw new RuntimeException("No external storage found!"); + } + } + + public void startCameraCapture() { + Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + lastGeneratedCaptureURI = reGenerateImageCaptureURI(); + takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, lastGeneratedCaptureURI); + fragment.startActivityForResult(takePictureIntent, SELECT_FROM_CAMERA); + } + + public void startGalleryPick() { + Intent pickImageIntent = new Intent(Intent.ACTION_GET_CONTENT); + pickImageIntent.setType("image/*"); + fragment.startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY); + } + + public void handleImagePicked(int requestCode, Intent data) { + Intent shareIntent = new Intent(activity, ShareActivity.class); + shareIntent.setAction(Intent.ACTION_SEND); + switch(requestCode) { + case SELECT_FROM_GALLERY: + shareIntent.setType(activity.getContentResolver().getType(data.getData())); + shareIntent.putExtra(Intent.EXTRA_STREAM, data.getData()); + shareIntent.putExtra(UploadService.EXTRA_SOURCE, Contribution.SOURCE_GALLERY); + break; + case SELECT_FROM_CAMERA: + shareIntent.setType("image/jpeg"); //FIXME: Find out appropriate mime type + shareIntent.putExtra(Intent.EXTRA_STREAM, lastGeneratedCaptureURI); + shareIntent.putExtra(UploadService.EXTRA_SOURCE, Contribution.SOURCE_CAMERA); + break; + } + activity.startActivity(shareIntent); + } + + public void saveState(Bundle outState) { + outState.putParcelable("lastGeneratedCaptureURI", lastGeneratedCaptureURI); + } + + public void loadState(Bundle savedInstanceState) { + if(savedInstanceState != null) { + lastGeneratedCaptureURI = (Uri) savedInstanceState.getParcelable("lastGeneratedCaptureURI"); + } + } + +} diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionViewHolder.java b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionViewHolder.java new file mode 100644 index 000000000..bfa9bda3e --- /dev/null +++ b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionViewHolder.java @@ -0,0 +1,25 @@ +package org.wikimedia.commons.contributions; + +import android.view.View; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; +import org.wikimedia.commons.R; + +class ContributionViewHolder { + final ImageView imageView; + final TextView titleView; + final TextView stateView; + final TextView seqNumView; + final ProgressBar progressView; + + String url; + + ContributionViewHolder(View parent) { + imageView = (ImageView)parent.findViewById(R.id.contributionImage); + titleView = (TextView)parent.findViewById(R.id.contributionTitle); + stateView = (TextView)parent.findViewById(R.id.contributionState); + seqNumView = (TextView)parent.findViewById(R.id.contributionSequenceNumber); + progressView = (ProgressBar)parent.findViewById(R.id.contributionProgress); + } +} diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsListAdapter.java b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsListAdapter.java new file mode 100644 index 000000000..295f2566d --- /dev/null +++ b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsListAdapter.java @@ -0,0 +1,106 @@ +package org.wikimedia.commons.contributions; + +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.support.v4.widget.CursorAdapter; +import android.text.TextUtils; +import android.view.View; +import android.view.ViewGroup; +import com.actionbarsherlock.app.SherlockFragment; +import com.nostra13.universalimageloader.core.DisplayImageOptions; +import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener; +import org.wikimedia.commons.CommonsApplication; +import org.wikimedia.commons.MediaWikiImageView; +import org.wikimedia.commons.R; +import org.wikimedia.commons.Utils; + +class ContributionsListAdapter extends CursorAdapter { + + private DisplayImageOptions contributionDisplayOptions = Utils.getGenericDisplayOptions().build();; + private SherlockFragment fragment; + + public ContributionsListAdapter(SherlockFragment fragment, Cursor c, int flags) { + super(fragment.getActivity(), c, flags); + this.fragment = fragment; + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup viewGroup) { + View parent = fragment.getActivity().getLayoutInflater().inflate(R.layout.layout_contribution, viewGroup, false); + parent.setTag(new ContributionViewHolder(parent)); + return parent; + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + final ContributionViewHolder views = (ContributionViewHolder)view.getTag(); + Contribution contribution = Contribution.fromCursor(cursor); + + String actualUrl = TextUtils.isEmpty(contribution.getImageUrl()) ? contribution.getLocalUri().toString() : contribution.getThumbnailUrl(320); + + if(views.url == null || !views.url.equals(actualUrl)) { + if(actualUrl.startsWith("http")) { + MediaWikiImageView mwImageView = (MediaWikiImageView)views.imageView; + mwImageView.setMedia(contribution, ((CommonsApplication) fragment.getActivity().getApplicationContext()).getImageLoader()); + // FIXME: For transparent images + } else { + com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(actualUrl, views.imageView, contributionDisplayOptions, new SimpleImageLoadingListener() { + + @Override + public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { + if(loadedImage.hasAlpha()) { + views.imageView.setBackgroundResource(android.R.color.white); + } + views.seqNumView.setVisibility(View.GONE); + } + + }); + } + views.url = actualUrl; + } + + BitmapDrawable actualImageDrawable = (BitmapDrawable)views.imageView.getDrawable(); + if(actualImageDrawable != null && actualImageDrawable.getBitmap() != null && actualImageDrawable.getBitmap().hasAlpha()) { + views.imageView.setBackgroundResource(android.R.color.white); + } else { + views.imageView.setBackgroundDrawable(null); + } + + views.titleView.setText(contribution.getDisplayTitle()); + + views.seqNumView.setText(String.valueOf(cursor.getPosition() + 1)); + views.seqNumView.setVisibility(View.VISIBLE); + + switch(contribution.getState()) { + case Contribution.STATE_COMPLETED: + views.stateView.setVisibility(View.GONE); + views.progressView.setVisibility(View.GONE); + views.stateView.setText(""); + break; + case Contribution.STATE_QUEUED: + views.stateView.setVisibility(View.VISIBLE); + views.progressView.setVisibility(View.GONE); + views.stateView.setText(R.string.contribution_state_queued); + break; + case Contribution.STATE_IN_PROGRESS: + views.stateView.setVisibility(View.GONE); + views.progressView.setVisibility(View.VISIBLE); + long total = contribution.getDataLength(); + long transferred = contribution.getTransferred(); + if(transferred == 0 || transferred >= total) { + views.progressView.setIndeterminate(true); + } else { + views.progressView.setProgress((int)(((double)transferred / (double)total) * 100)); + } + break; + case Contribution.STATE_FAILED: + views.stateView.setVisibility(View.VISIBLE); + views.stateView.setText(R.string.contribution_state_failed); + views.progressView.setVisibility(View.GONE); + break; + } + + } +} diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsListFragment.java b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsListFragment.java index e8caa90b2..065f790d9 100644 --- a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsListFragment.java +++ b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsListFragment.java @@ -5,14 +5,7 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.net.Uri; import android.os.Bundle; -import android.os.Environment; -import android.provider.MediaStore; -import android.support.v4.widget.CursorAdapter; -import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -25,135 +18,21 @@ import com.actionbarsherlock.view.MenuItem; import com.nostra13.universalimageloader.core.DisplayImageOptions; -import java.io.*; -import java.util.*; - -import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener; import org.wikimedia.commons.*; import org.wikimedia.commons.R; -import org.wikimedia.commons.upload.ShareActivity; -import org.wikimedia.commons.upload.UploadService; public class ContributionsListFragment extends SherlockFragment { - private final static int SELECT_FROM_GALLERY = 1; - private final static int SELECT_FROM_CAMERA = 2; - private GridView contributionsList; private TextView waitingMessage; private TextView emptyMessage; private ContributionsListAdapter contributionsAdapter; - private DisplayImageOptions contributionDisplayOptions; private Cursor allContributions; - private static class ContributionViewHolder { - final ImageView imageView; - final TextView titleView; - final TextView stateView; - final TextView seqNumView; - final ProgressBar progressView; - - String url; - - ContributionViewHolder(View parent) { - imageView = (ImageView)parent.findViewById(R.id.contributionImage); - titleView = (TextView)parent.findViewById(R.id.contributionTitle); - stateView = (TextView)parent.findViewById(R.id.contributionState); - seqNumView = (TextView)parent.findViewById(R.id.contributionSequenceNumber); - progressView = (ProgressBar)parent.findViewById(R.id.contributionProgress); - } - } - - private class ContributionsListAdapter extends CursorAdapter { - - public ContributionsListAdapter(Context context, Cursor c, int flags) { - super(context, c, flags); - } - - @Override - public View newView(Context context, Cursor cursor, ViewGroup viewGroup) { - View parent = getActivity().getLayoutInflater().inflate(R.layout.layout_contribution, viewGroup, false); - parent.setTag(new ContributionViewHolder(parent)); - return parent; - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - // hack: hide the 'first sync' message once we've loaded a cell - clearSyncMessage(); - - final ContributionViewHolder views = (ContributionViewHolder)view.getTag(); - Contribution contribution = Contribution.fromCursor(cursor); - - String actualUrl = TextUtils.isEmpty(contribution.getImageUrl()) ? contribution.getLocalUri().toString() : contribution.getThumbnailUrl(320); - - if(views.url == null || !views.url.equals(actualUrl)) { - if(actualUrl.startsWith("http")) { - MediaWikiImageView mwImageView = (MediaWikiImageView)views.imageView; - mwImageView.setMedia(contribution, ((CommonsApplication) getActivity().getApplicationContext()).getImageLoader()); - // FIXME: For transparent images - } else { - com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(actualUrl, views.imageView, contributionDisplayOptions, new SimpleImageLoadingListener() { - - @Override - public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { - if(loadedImage.hasAlpha()) { - views.imageView.setBackgroundResource(android.R.color.white); - } - views.seqNumView.setVisibility(View.GONE); - } - - }); - } - views.url = actualUrl; - } - - BitmapDrawable actualImageDrawable = (BitmapDrawable)views.imageView.getDrawable(); - if(actualImageDrawable != null && actualImageDrawable.getBitmap() != null && actualImageDrawable.getBitmap().hasAlpha()) { - views.imageView.setBackgroundResource(android.R.color.white); - } else { - views.imageView.setBackgroundDrawable(null); - } - - views.titleView.setText(contribution.getDisplayTitle()); - - views.seqNumView.setText(String.valueOf(cursor.getPosition() + 1)); - views.seqNumView.setVisibility(View.VISIBLE); - - switch(contribution.getState()) { - case Contribution.STATE_COMPLETED: - views.stateView.setVisibility(View.GONE); - views.progressView.setVisibility(View.GONE); - views.stateView.setText(""); - break; - case Contribution.STATE_QUEUED: - views.stateView.setVisibility(View.VISIBLE); - views.progressView.setVisibility(View.GONE); - views.stateView.setText(R.string.contribution_state_queued); - break; - case Contribution.STATE_IN_PROGRESS: - views.stateView.setVisibility(View.GONE); - views.progressView.setVisibility(View.VISIBLE); - long total = contribution.getDataLength(); - long transferred = contribution.getTransferred(); - if(transferred == 0 || transferred >= total) { - views.progressView.setIndeterminate(true); - } else { - views.progressView.setProgress((int)(((double)transferred / (double)total) * 100)); - } - break; - case Contribution.STATE_FAILED: - views.stateView.setVisibility(View.VISIBLE); - views.stateView.setText(R.string.contribution_state_failed); - views.progressView.setVisibility(View.GONE); - break; - } - - } - } + private ContributionController controller; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -162,7 +41,7 @@ public class ContributionsListFragment extends SherlockFragment { public void setCursor(Cursor cursor) { if(allContributions == null) { - contributionsAdapter = new ContributionsListAdapter(this.getActivity(), cursor, 0); + contributionsAdapter = new ContributionsListAdapter(this, cursor, 0); contributionsList.setAdapter(contributionsAdapter); } allContributions = cursor; @@ -172,77 +51,27 @@ public class ContributionsListFragment extends SherlockFragment { @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); + controller.saveState(outState); outState.putInt("grid-position", contributionsList.getFirstVisiblePosition()); - outState.putParcelable("lastGeneratedCaptureURI", lastGeneratedCaptureURI); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - switch(requestCode) { - case SELECT_FROM_GALLERY: - if(resultCode == Activity.RESULT_OK) { - Intent shareIntent = new Intent(getActivity(), ShareActivity.class); - shareIntent.setAction(Intent.ACTION_SEND); - - shareIntent.setType(getActivity().getContentResolver().getType(data.getData())); - shareIntent.putExtra(Intent.EXTRA_STREAM, data.getData()); - shareIntent.putExtra(UploadService.EXTRA_SOURCE, Contribution.SOURCE_GALLERY); - startActivity(shareIntent); - } - break; - case SELECT_FROM_CAMERA: - if(resultCode == Activity.RESULT_OK) { - Intent shareIntent = new Intent(getActivity(), ShareActivity.class); - shareIntent.setAction(Intent.ACTION_SEND); - Log.d("Commons", "Uri is " + lastGeneratedCaptureURI); - shareIntent.setType("image/jpeg"); //FIXME: Find out appropriate mime type - shareIntent.putExtra(Intent.EXTRA_STREAM, lastGeneratedCaptureURI); - shareIntent.putExtra(UploadService.EXTRA_SOURCE, Contribution.SOURCE_CAMERA); - startActivity(shareIntent); - } - break; + if(resultCode == Activity.RESULT_OK) { + controller.handleImagePicked(requestCode, data); } } - // See http://stackoverflow.com/a/5054673/17865 for why this is done - private Uri lastGeneratedCaptureURI; - - private void reGenerateImageCaptureURI() { - String storageState = Environment.getExternalStorageState(); - if(storageState.equals(Environment.MEDIA_MOUNTED)) { - - String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Commons/images/" + new Date().getTime() + ".jpg"; - File _photoFile = new File(path); - try { - if(_photoFile.exists() == false) { - _photoFile.getParentFile().mkdirs(); - _photoFile.createNewFile(); - } - - } catch (IOException e) { - Log.e("Commons", "Could not create file: " + path, e); - } - - lastGeneratedCaptureURI = Uri.fromFile(_photoFile); - } else { - throw new RuntimeException("No external storage found!"); - } - } @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { case R.id.menu_from_gallery: - Intent pickImageIntent = new Intent(Intent.ACTION_GET_CONTENT); - pickImageIntent.setType("image/*"); - startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY); + controller.startGalleryPick(); return true; case R.id.menu_from_camera: - Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - reGenerateImageCaptureURI(); - takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, lastGeneratedCaptureURI); - startActivityForResult(takePictureIntent, SELECT_FROM_CAMERA); + controller.startCameraCapture(); return true; case R.id.menu_settings: Intent settingsIntent = new Intent(getActivity(), SettingsActivity.class); @@ -286,15 +115,16 @@ public class ContributionsListFragment extends SherlockFragment { public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); + controller = new ContributionController(this); + controller.loadState(savedInstanceState); + contributionsList = (GridView)getView().findViewById(R.id.contributionsList); waitingMessage = (TextView)getView().findViewById(R.id.waitingMessage); emptyMessage = (TextView)getView().findViewById(R.id.waitingMessage); - contributionDisplayOptions = Utils.getGenericDisplayOptions().build(); contributionsList.setOnItemClickListener((AdapterView.OnItemClickListener)getActivity()); if(savedInstanceState != null) { Log.d("Commons", "Scrolling to " + savedInstanceState.getInt("grid-position")); - lastGeneratedCaptureURI = (Uri) savedInstanceState.getParcelable("lastGeneratedCaptureURI"); contributionsList.setSelection(savedInstanceState.getInt("grid-position")); }