Display contributions from other people to the campaign

Attempts to be as minimally invasive as possible

Change-Id: I1c9d7080d046199d5277385da625c180a8bacbfa
This commit is contained in:
YuviPanda 2013-09-19 18:19:17 -07:00
parent 2da5453ec1
commit e0cae93c3c
11 changed files with 194 additions and 48 deletions

View file

@ -144,6 +144,9 @@ public class Media implements Parcelable {
protected String creator;
public Media(String filename) {
this.filename = filename;
}
public Media(Uri localUri, String imageUrl, String filename, String description, long dataLength, Date dateCreated, Date dateUploaded, String creator) {
this.localUri = localUri;

View file

@ -1,6 +1,7 @@
package org.wikimedia.commons;
import android.os.*;
import android.util.Log;
import com.nostra13.universalimageloader.core.*;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;

View file

@ -7,9 +7,11 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.Serializable;
import java.util.ArrayList;
public class Campaign {
// FIXME: Implement Parcelable
public class Campaign implements Serializable {
private boolean enabled;
private String autoAddWikitext;

View file

@ -1,14 +1,18 @@
package org.wikimedia.commons.campaigns;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import org.wikimedia.commons.R;
import org.wikimedia.commons.contributions.ContributionsActivity;
public class CampaignActivity
extends SherlockFragmentActivity
@ -16,12 +20,20 @@ public class CampaignActivity
private ListView campaignsListView;
private CampaignsListAdapter campaignsListAdapter;
private Cursor allCampaigns;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_campaigns);
campaignsListView = (ListView) findViewById(R.id.campaignsList);
campaignsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Campaign c = Campaign.fromCursor((Cursor) adapterView.getItemAtPosition(i));
Intent intent = new Intent(CampaignActivity.this, ContributionsActivity.class);
intent.putExtra("campaign", c);
startActivity(intent);
}
});
getSupportLoaderManager().initLoader(0, null, this);
}

View file

@ -8,6 +8,7 @@ import android.support.v4.content.Loader;
import android.content.*;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.widget.CursorAdapter;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
@ -16,12 +17,15 @@ import com.actionbarsherlock.view.MenuItem;
import org.wikimedia.commons.*;
import org.wikimedia.commons.auth.*;
import org.wikimedia.commons.campaigns.Campaign;
import org.wikimedia.commons.media.*;
import org.wikimedia.commons.upload.UploadService;
import java.util.ArrayList;
public class ContributionsActivity
extends AuthenticatedActivity
implements LoaderManager.LoaderCallbacks<Cursor>,
implements LoaderManager.LoaderCallbacks<Object>,
AdapterView.OnItemClickListener,
MediaDetailPagerFragment.MediaDetailProvider,
FragmentManager.OnBackStackChangedListener {
@ -31,6 +35,8 @@ public class ContributionsActivity
private ContributionsListFragment contributionsList;
private MediaDetailPagerFragment mediaDetails;
private Campaign campaign;
public ContributionsActivity() {
super(WikiAccountAuthenticator.COMMONS_ACCOUNT_TYPE);
}
@ -101,6 +107,10 @@ public class ContributionsActivity
setTitle(R.string.title_activity_contributions);
setContentView(R.layout.activity_contributions);
if(getIntent().hasExtra("campaign")) {
this.campaign = (Campaign) getIntent().getSerializableExtra("campaign");
}
contributionsList = (ContributionsListFragment)getSupportFragmentManager().findFragmentById(R.id.contributionsListFragment);
getSupportFragmentManager().addOnBackStackChangedListener(this);
@ -180,13 +190,7 @@ public class ContributionsActivity
public void onItemClick(AdapterView<?> adapterView, View view, int position, long item) {
Cursor cursor = (Cursor)adapterView.getItemAtPosition(position);
Contribution c = Contribution.fromCursor(cursor);
Log.d("Commons", "Clicking for " + c.toContentValues());
showDetail(position);
Log.d("Commons", "You clicked on:" + c.toContentValues().toString());
}
@Override
@ -194,31 +198,51 @@ public class ContributionsActivity
return super.onCreateOptionsMenu(menu);
}
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
public Loader onCreateLoader(int i, Bundle bundle) {
if(campaign == null) {
return new CursorLoader(this, ContributionsContentProvider.BASE_URI, Contribution.Table.ALL_FIELDS, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT);
} else {
return new CategoryImagesLoader(this, campaign.getTrackingCategory());
}
}
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
allContributions = cursor;
contributionsList.setCursor(cursor);
public void onLoadFinished(Loader cursorLoader, Object result) {
if(campaign == null) {
Cursor cursor = (Cursor) result;
if(contributionsList.getAdapter() == null) {
contributionsList.setAdapter(new ContributionsListAdapter(this, cursor, 0));
} else {
((CursorAdapter)contributionsList.getAdapter()).swapCursor(cursor);
}
getSupportActionBar().setSubtitle(getResources().getQuantityString(R.plurals.contributions_subtitle, cursor.getCount(), cursor.getCount()));
} else {
contributionsList.setAdapter(new MediaListAdapter(this, (ArrayList<Media>) result));
}
}
public void onLoaderReset(Loader<Cursor> cursorLoader) {
contributionsList.setCursor(null);
public void onLoaderReset(Loader cursorLoader) {
if(campaign == null) {
((CursorAdapter) contributionsList.getAdapter()).swapCursor(null);
} else {
//((MediaListAdapter) contributionsList.getAdapter()).
// DO SOMETHING!
}
}
public Media getMediaAtPosition(int i) {
allContributions.moveToPosition(i);
return Contribution.fromCursor(allContributions);
if(campaign == null) {
return Contribution.fromCursor((Cursor) contributionsList.getAdapter().getItem(i));
} else {
return (Media) contributionsList.getAdapter().getItem(i);
}
}
public int getTotalMediaCount() {
if(allContributions == null) {
if(contributionsList.getAdapter() == null) {
return 0;
}
return allContributions.getCount();
return contributionsList.getAdapter().getCount();
}
public void notifyDatasetChanged() {

View file

@ -1,5 +1,6 @@
package org.wikimedia.commons.contributions;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
@ -19,16 +20,16 @@ import org.wikimedia.commons.Utils;
class ContributionsListAdapter extends CursorAdapter {
private DisplayImageOptions contributionDisplayOptions = Utils.getGenericDisplayOptions().build();;
private SherlockFragment fragment;
private Activity activity;
public ContributionsListAdapter(SherlockFragment fragment, Cursor c, int flags) {
super(fragment.getActivity(), c, flags);
this.fragment = fragment;
public ContributionsListAdapter(Activity activity, Cursor c, int flags) {
super(activity, c, flags);
this.activity = activity;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
View parent = fragment.getActivity().getLayoutInflater().inflate(R.layout.layout_contribution, viewGroup, false);
View parent = activity.getLayoutInflater().inflate(R.layout.layout_contribution, viewGroup, false);
parent.setTag(new ContributionViewHolder(parent));
return parent;
}
@ -38,12 +39,12 @@ class ContributionsListAdapter extends CursorAdapter {
final ContributionViewHolder views = (ContributionViewHolder)view.getTag();
Contribution contribution = Contribution.fromCursor(cursor);
String actualUrl = TextUtils.isEmpty(contribution.getImageUrl()) ? contribution.getLocalUri().toString() : contribution.getThumbnailUrl(320);
String actualUrl = (contribution.getLocalUri() != null && TextUtils.isEmpty(contribution.getLocalUri().toString())) ? contribution.getLocalUri().toString() : contribution.getThumbnailUrl(640);
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());
mwImageView.setMedia(contribution, ((CommonsApplication) activity.getApplicationContext()).getImageLoader());
// FIXME: For transparent images
} else {
com.nostra13.universalimageloader.core.ImageLoader.getInstance().displayImage(actualUrl, views.imageView, contributionDisplayOptions, new SimpleImageLoadingListener() {

View file

@ -16,8 +16,6 @@ import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import org.wikimedia.commons.*;
import org.wikimedia.commons.R;
@ -28,10 +26,6 @@ public class ContributionsListFragment extends SherlockFragment {
private TextView waitingMessage;
private TextView emptyMessage;
private ContributionsListAdapter contributionsAdapter;
private Cursor allContributions;
private ContributionController controller;
@Override
@ -39,13 +33,12 @@ public class ContributionsListFragment extends SherlockFragment {
return inflater.inflate(R.layout.fragment_contributions, container, false);
}
public void setCursor(Cursor cursor) {
if(allContributions == null) {
contributionsAdapter = new ContributionsListAdapter(this, cursor, 0);
contributionsList.setAdapter(contributionsAdapter);
public ListAdapter getAdapter() {
return contributionsList.getAdapter();
}
allContributions = cursor;
contributionsAdapter.swapCursor(cursor);
public void setAdapter(ListAdapter adapter) {
this.contributionsList.setAdapter(adapter);
}
@Override
@ -111,6 +104,11 @@ public class ContributionsListFragment extends SherlockFragment {
setHasOptionsMenu(true);
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

View file

@ -0,0 +1,47 @@
package org.wikimedia.commons.contributions;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import com.android.volley.toolbox.ImageLoader;
import org.wikimedia.commons.CommonsApplication;
import org.wikimedia.commons.Media;
import org.wikimedia.commons.R;
import java.util.ArrayList;
public class MediaListAdapter extends BaseAdapter {
private ArrayList<Media> mediaList;
private Activity activity;
public MediaListAdapter(Activity activity, ArrayList<Media> mediaList) {
this.mediaList = mediaList;
this.activity = activity;
}
public int getCount() {
return mediaList.size();
}
public Object getItem(int i) {
return mediaList.get(i);
}
public long getItemId(int i) {
return i;
}
public View getView(int i, View view, ViewGroup viewGroup) {
if(view == null) {
view = activity.getLayoutInflater().inflate(R.layout.layout_contribution, null, false);
view.setTag(new ContributionViewHolder(view));
}
Media m = (Media) getItem(i);
ContributionViewHolder holder = (ContributionViewHolder) view.getTag();
holder.imageView.setMedia(m, ((CommonsApplication)activity.getApplicationContext()).getImageLoader());
holder.titleView.setText(m.getDisplayTitle());
return view;
}
}

View file

@ -0,0 +1,57 @@
package org.wikimedia.commons.media;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;
import org.mediawiki.api.ApiResult;
import org.wikimedia.commons.CommonsApplication;
import org.wikimedia.commons.Media;
import org.wikimedia.commons.Utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class CategoryImagesLoader extends AsyncTaskLoader<List<Media>>{
private final CommonsApplication app;
private final String category;
public CategoryImagesLoader(Context context, String category) {
super(context);
this.app = (CommonsApplication) context.getApplicationContext();
this.category = category;
}
@Override
protected void onStartLoading() {
super.onStartLoading();
super.forceLoad();
}
@Override
public List<Media> loadInBackground() {
ArrayList<Media> mediaList = new ArrayList<Media>();
ApiResult result;
try {
result = app.getApi().action("query")
.param("list", "categorymembers")
.param("cmtitle", "Category:" + category)
.param("cmprop", "title|timestamp")
.param("cmtype", "file")
.param("cmsort", "timestamp")
.param("cmdir", "descending")
.param("cmlimit", 50)
.get();
} catch (IOException e) {
throw new RuntimeException(e);
}
Log.d("Commons", Utils.getStringFromDOM(result.getDocument()));
List<ApiResult> members = result.getNodes("/api/query/categorymembers/cm");
for(ApiResult member : members) {
mediaList.add(new Media(member.getString("@title")));
}
return mediaList;
}
}

View file

@ -80,7 +80,7 @@ public class MediaDetailFragment extends SherlockFragment {
title.setBackgroundDrawable(null);
}
String actualUrl = TextUtils.isEmpty(media.getImageUrl()) ? media.getLocalUri().toString() : media.getThumbnailUrl(640);
String actualUrl = (media.getLocalUri() != null && TextUtils.isEmpty(media.getLocalUri().toString())) ? media.getLocalUri().toString() : media.getThumbnailUrl(640);
if(actualUrl.startsWith("http")) {
ImageLoader loader = ((CommonsApplication)getActivity().getApplicationContext()).getImageLoader();
MediaWikiImageView mwImage = (MediaWikiImageView)image;

View file

@ -27,6 +27,7 @@ public class UploadController {
private UploadService uploadService;
private final Activity activity;
private Campaign campaign;
final CommonsApplication app;
public interface ContributionUploadProgress {
@ -38,6 +39,11 @@ public class UploadController {
app = (CommonsApplication)activity.getApplicationContext();
}
public UploadController(Activity activity, Campaign campaign) {
this(activity);
this.campaign = campaign;
}
private boolean isUploadServiceConnected;
private ServiceConnection uploadServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder binder) {
@ -64,12 +70,7 @@ public class UploadController {
}
}
/* The JavaScript is Leaking!*/
public void startUpload(String rawTitle, Uri mediaUri, String description, String mimeType, String source, ContributionUploadProgress onComplete) {
startUpload(rawTitle, mediaUri, description, mimeType, source, null, onComplete);
}
public void startUpload(String rawTitle, Uri mediaUri, String description, String mimeType, String source, Campaign campaign, ContributionUploadProgress onComplete) {
Contribution contribution;
String title = rawTitle;