mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Added basic Multiple Upload support
Still needs work - needs detail view, categories & base description
This commit is contained in:
parent
f768ce4756
commit
e50f50cabc
6 changed files with 386 additions and 0 deletions
|
|
@ -47,6 +47,21 @@
|
|||
<data android:mimeType="audio/ogg" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".MultipleShareActivity"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/title_activity_share"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
<data android:mimeType="image/*" />
|
||||
<data android:mimeType="audio/ogg" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".contributions.ContributionsActivity"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
|
|
|
|||
22
commons/res/layout/activity_multiple_share.xml
Normal file
22
commons/res/layout/activity_multiple_share.xml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<EditText android:id="@+id/multipleBaseTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/multiple_share_base_title"
|
||||
/>
|
||||
|
||||
<GridView android:id="@+id/multipleShareBackground"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_width="fill_parent"
|
||||
android:stretchMode="columnWidth"
|
||||
android:numColumns="auto_fit"
|
||||
android:listSelector="@null"
|
||||
android:fadingEdge="none"
|
||||
android:fastScrollEnabled="false"
|
||||
/>
|
||||
</LinearLayout>
|
||||
34
commons/res/layout/layout_upload_item.xml
Normal file
34
commons/res/layout/layout_upload_item.xml
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="2dp"
|
||||
android:paddingBottom="0dp"
|
||||
android:background="#000000"
|
||||
>
|
||||
<ImageView android:id="@+id/uploadImage"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="192dp"
|
||||
android:scaleType="centerCrop"
|
||||
/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center|bottom"
|
||||
android:background="#77000000"
|
||||
android:padding="4dp"
|
||||
>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/uploadTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FFFFFFFF"
|
||||
style="?android:textAppearanceSmall"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
|
||||
</FrameLayout>
|
||||
10
commons/res/menu/activity_multiple_share.xml
Normal file
10
commons/res/menu/activity_multiple_share.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:id="@+id/menu_upload_multiple"
|
||||
android:title="@string/share_upload_button"
|
||||
android:showAsAction="always|withText"
|
||||
android:icon="@android:drawable/ic_menu_send"
|
||||
/>
|
||||
</menu>
|
||||
|
|
@ -50,10 +50,15 @@
|
|||
<string name="login_failed_generic">Login failed</string>
|
||||
|
||||
<string name="share_upload_button">Upload</string>
|
||||
<string name="multiple_share_base_title">Base Title</string>
|
||||
|
||||
<plurals name="contributions_subtitle">
|
||||
<item quantity="zero">No uploads yet</item>
|
||||
<item quantity="one">1 upload</item>
|
||||
<item quantity="other">%d uploads</item>
|
||||
</plurals>
|
||||
<plurals name="starting_multiple_uploads">
|
||||
<item quantity="one">Starting 1 upload</item>
|
||||
<item quantity="other">Starting %d uploads</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,300 @@
|
|||
package org.wikimedia.commons;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.*;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
|
||||
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
|
||||
import de.akquinet.android.androlog.Log;
|
||||
import org.wikimedia.commons.auth.AuthenticatedActivity;
|
||||
import org.wikimedia.commons.auth.WikiAccountAuthenticator;
|
||||
import org.wikimedia.commons.contributions.Contribution;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class MultipleShareActivity extends AuthenticatedActivity {
|
||||
private CommonsApplication app;
|
||||
private GridView photosGrid;
|
||||
private PhotoDisplayAdapter photosAdapter;
|
||||
private ArrayList<PreparedUpload> photosList = new ArrayList<PreparedUpload>();
|
||||
private EditText baseTitle;
|
||||
private int picHeight;
|
||||
private DisplayImageOptions uploadDisplayOptions;
|
||||
|
||||
public MultipleShareActivity() {
|
||||
super(WikiAccountAuthenticator.COMMONS_ACCOUNT_TYPE);
|
||||
}
|
||||
|
||||
private static class UploadHolderView {
|
||||
Uri imageUri;
|
||||
|
||||
ImageView image;
|
||||
TextView title;
|
||||
}
|
||||
|
||||
private static class PreparedUpload {
|
||||
Uri uri;
|
||||
String title;
|
||||
boolean isDirty;
|
||||
int sequence;
|
||||
String mimeType;
|
||||
|
||||
private PreparedUpload(Uri uri, int seq) {
|
||||
this.uri = uri;
|
||||
this.sequence = seq;
|
||||
}
|
||||
}
|
||||
|
||||
private class PhotoDisplayAdapter extends BaseAdapter {
|
||||
|
||||
private ArrayList<PreparedUpload> urisList;
|
||||
|
||||
private PhotoDisplayAdapter(ArrayList<PreparedUpload> urisList) {
|
||||
this.urisList = urisList;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return urisList.size();
|
||||
}
|
||||
|
||||
public Object getItem(int i) {
|
||||
return urisList.get(i);
|
||||
}
|
||||
|
||||
public long getItemId(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
public View getView(int i, View view, ViewGroup viewGroup) {
|
||||
UploadHolderView holder;
|
||||
|
||||
if(view == null) {
|
||||
view = getLayoutInflater().inflate(R.layout.layout_upload_item, null);
|
||||
holder = new UploadHolderView();
|
||||
holder.image = (ImageView) view.findViewById(R.id.uploadImage);
|
||||
holder.title = (TextView) view.findViewById(R.id.uploadTitle);
|
||||
|
||||
holder.image.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, picHeight));
|
||||
|
||||
view.setTag(holder);
|
||||
} else {
|
||||
holder = (UploadHolderView)view.getTag();
|
||||
}
|
||||
|
||||
|
||||
PreparedUpload up = (PreparedUpload)this.getItem(i);
|
||||
|
||||
if(holder.imageUri == null || !holder.imageUri.equals(up.uri)) {
|
||||
ImageLoader.getInstance().displayImage(up.uri.toString(), holder.image, uploadDisplayOptions);
|
||||
holder.imageUri = up.uri;
|
||||
}
|
||||
|
||||
holder.title.setText(up.title);
|
||||
|
||||
return view;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class StartMultipleUploadTask extends AsyncTask<Void, Integer, Void> {
|
||||
|
||||
ProgressDialog dialog;
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
for(int i = 0; i < photosList.size(); i++) {
|
||||
PreparedUpload up = photosList.get(i);
|
||||
if(up.mimeType == null || TextUtils.isEmpty(up.mimeType) || up.mimeType.endsWith("*")) {
|
||||
String mimeType = getContentResolver().getType(up.uri);
|
||||
if(mimeType != null) {
|
||||
up.mimeType = mimeType;
|
||||
}
|
||||
}
|
||||
|
||||
StartUploadTask startUploadTask = new StartUploadTask(MultipleShareActivity.this, uploadService, up.title, up.uri, "", up.mimeType, Contribution.SOURCE_EXTERNAL);
|
||||
try {
|
||||
Utils.executeAsyncTask(startUploadTask);
|
||||
startUploadTask.get();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
this.publishProgress(i);
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
dialog = new ProgressDialog(MultipleShareActivity.this);
|
||||
dialog.setIndeterminate(false);
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
dialog.setMax(photosList.size());
|
||||
dialog.setTitle(getResources().getQuantityString(R.plurals.starting_multiple_uploads, photosList.size(), photosList.size()));
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(Integer... values) {
|
||||
dialog.setProgress(values[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void aVoid) {
|
||||
dialog.dismiss();
|
||||
Toast startingToast = Toast.makeText(getApplicationContext(), R.string.uploading_started, Toast.LENGTH_LONG);
|
||||
startingToast.show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private UploadService uploadService;
|
||||
private boolean isUploadServiceConnected;
|
||||
private ServiceConnection uploadServiceConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName componentName, IBinder binder) {
|
||||
uploadService = (UploadService) ((HandlerService.HandlerServiceLocalBinder)binder).getService();
|
||||
isUploadServiceConnected = true;
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName componentName) {
|
||||
// this should never happen
|
||||
throw new RuntimeException("UploadService died but the rest of the process did not!");
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getSupportMenuInflater().inflate(R.menu.activity_multiple_share, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch(item.getItemId()) {
|
||||
case R.id.menu_upload_multiple:
|
||||
|
||||
StartMultipleUploadTask startUploads = new StartMultipleUploadTask();
|
||||
Utils.executeAsyncTask(startUploads);
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_multiple_share);
|
||||
|
||||
app = (CommonsApplication)this.getApplicationContext();
|
||||
photosGrid = (GridView)findViewById(R.id.multipleShareBackground);
|
||||
baseTitle = (EditText)findViewById(R.id.multipleBaseTitle);
|
||||
|
||||
uploadDisplayOptions = new DisplayImageOptions.Builder().cacheInMemory()
|
||||
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
|
||||
.displayer(new FadeInBitmapDisplayer(300))
|
||||
.cacheInMemory()
|
||||
.resetViewBeforeLoading().build();
|
||||
|
||||
requestAuthToken();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if(isUploadServiceConnected) {
|
||||
unbindService(uploadServiceConnection);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAuthCookieAcquired(String authCookie) {
|
||||
app.getApi().setAuthCookie(authCookie);
|
||||
Intent intent = getIntent();
|
||||
|
||||
if(intent.getAction() == Intent.ACTION_SEND_MULTIPLE) {
|
||||
ArrayList<Uri> urisList = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
|
||||
for(int i=0; i < urisList.size(); i++) {
|
||||
PreparedUpload up = new PreparedUpload(urisList.get(i), i + 1);
|
||||
up.mimeType = intent.getType();
|
||||
photosList.add(up);
|
||||
}
|
||||
DisplayMetrics screenMetrics = getResources().getDisplayMetrics();
|
||||
int screenWidth = screenMetrics.widthPixels;
|
||||
int screenHeight = screenMetrics.heightPixels;
|
||||
|
||||
int picWidth = Math.min((int) Math.sqrt(screenWidth * screenHeight / urisList.size()), screenWidth);
|
||||
picWidth = Math.min((int)(192 * screenMetrics.density), Math.max((int) (120 * screenMetrics.density), picWidth / 48 * 48));
|
||||
picHeight = Math.min(picWidth, (int)(192 * screenMetrics.density)); // Max Height is same as Contributions list
|
||||
|
||||
photosGrid.setColumnWidth(picWidth);
|
||||
photosGrid.invalidateViews();
|
||||
|
||||
photosAdapter = new PhotoDisplayAdapter(photosList);
|
||||
photosGrid.setAdapter(photosAdapter);
|
||||
|
||||
Intent uploadServiceIntent = new Intent(getApplicationContext(), UploadService.class);
|
||||
uploadServiceIntent.setAction(UploadService.ACTION_START_SERVICE);
|
||||
startService(uploadServiceIntent);
|
||||
bindService(uploadServiceIntent, uploadServiceConnection, Context.BIND_AUTO_CREATE);
|
||||
|
||||
baseTitle.addTextChangedListener(new TextWatcher() {
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
|
||||
|
||||
}
|
||||
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
|
||||
for(PreparedUpload up: photosList) {
|
||||
if(!up.isDirty) {
|
||||
if(!TextUtils.isEmpty(charSequence)) {
|
||||
up.title = charSequence.toString() + " - " + up.sequence;
|
||||
} else {
|
||||
up.title = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
photosAdapter.notifyDataSetChanged();
|
||||
|
||||
}
|
||||
|
||||
public void afterTextChanged(Editable editable) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onAuthFailure() {
|
||||
super.onAuthFailure();
|
||||
Toast failureToast = Toast.makeText(this, R.string.authentication_failed, Toast.LENGTH_LONG);
|
||||
failureToast.show();
|
||||
finish();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue