mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Fix uploads getting stuck (#2309)
* Fix uploads getting stuck * Fix test * Use single instance of Gson across the app * More logs to help debug upload failure * Add request identifier * wip * Fix issues with image quality check dialogs
This commit is contained in:
parent
07f9af19f5
commit
532ab8aeae
16 changed files with 85 additions and 91 deletions
|
|
@ -446,7 +446,7 @@ public class MainActivity extends AuthenticatedActivity implements FragmentManag
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (IntentUtils.shouldContributionsListHandle(requestCode, resultCode, data)) {
|
if (IntentUtils.shouldContributionsHandle(requestCode, resultCode, data)) {
|
||||||
List<Image> images = ImagePicker.getImages(data);
|
List<Image> images = ImagePicker.getImages(data);
|
||||||
Intent shareIntent = controller.handleImagesPicked(ImageUtils.getUriListFromImages(images), requestCode);
|
Intent shareIntent = controller.handleImagesPicked(ImageUtils.getUriListFromImages(images), requestCode);
|
||||||
startActivity(shareIntent);
|
startActivity(shareIntent);
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,13 @@ package fr.free.nrw.commons.di;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ContentProviderClient;
|
import android.content.ContentProviderClient;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
import android.support.v4.util.LruCache;
|
import android.support.v4.util.LruCache;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -29,6 +33,8 @@ import fr.free.nrw.commons.nearby.NearbyPlaces;
|
||||||
import fr.free.nrw.commons.settings.Prefs;
|
import fr.free.nrw.commons.settings.Prefs;
|
||||||
import fr.free.nrw.commons.upload.UploadController;
|
import fr.free.nrw.commons.upload.UploadController;
|
||||||
import fr.free.nrw.commons.utils.ConfigUtils;
|
import fr.free.nrw.commons.utils.ConfigUtils;
|
||||||
|
import fr.free.nrw.commons.utils.UriDeserializer;
|
||||||
|
import fr.free.nrw.commons.utils.UriSerializer;
|
||||||
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||||
import fr.free.nrw.commons.wikidata.WikidataEditListenerImpl;
|
import fr.free.nrw.commons.wikidata.WikidataEditListenerImpl;
|
||||||
|
|
||||||
|
|
@ -154,8 +160,8 @@ public class CommonsApplicationModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Named("direct_nearby_upload_prefs")
|
@Named("direct_nearby_upload_prefs")
|
||||||
public JsonKvStore providesDirectNearbyUploadKvStore(Context context) {
|
public JsonKvStore providesDirectNearbyUploadKvStore(Context context, Gson gson) {
|
||||||
return new JsonKvStore(context, "direct_nearby_upload_prefs");
|
return new JsonKvStore(context, "direct_nearby_upload_prefs", gson);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package fr.free.nrw.commons.di;
|
package fr.free.nrw.commons.di;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
@ -18,6 +19,8 @@ import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.kvstore.BasicKvStore;
|
import fr.free.nrw.commons.kvstore.BasicKvStore;
|
||||||
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
|
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
|
||||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
|
import fr.free.nrw.commons.utils.UriDeserializer;
|
||||||
|
import fr.free.nrw.commons.utils.UriSerializer;
|
||||||
import okhttp3.Cache;
|
import okhttp3.Cache;
|
||||||
import okhttp3.HttpUrl;
|
import okhttp3.HttpUrl;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
|
@ -63,7 +66,10 @@ public class NetworkingModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public Gson provideGson() {
|
public Gson provideGson() {
|
||||||
return new GsonBuilder().create();
|
return new GsonBuilder()
|
||||||
|
.registerTypeAdapter(Uri.class, new UriSerializer())
|
||||||
|
.registerTypeAdapter(Uri.class, new UriDeserializer())
|
||||||
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,21 @@ import java.util.Map;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class JsonKvStore extends BasicKvStore {
|
public class JsonKvStore extends BasicKvStore {
|
||||||
private final Gson gson = new Gson();
|
private final Gson gson;
|
||||||
|
|
||||||
public JsonKvStore(Context context, String storeName) {
|
public JsonKvStore(Context context, String storeName, Gson gson) {
|
||||||
super(context, storeName);
|
super(context, storeName);
|
||||||
|
this.gson = gson;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonKvStore(Context context, String storeName, int version) {
|
public JsonKvStore(Context context, String storeName, int version, Gson gson) {
|
||||||
super(context, storeName, version);
|
super(context, storeName, version);
|
||||||
|
this.gson = gson;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JsonKvStore(Context context, String storeName, int version, boolean clearAllOnUpgrade) {
|
public JsonKvStore(Context context, String storeName, int version, boolean clearAllOnUpgrade, Gson gson) {
|
||||||
super(context, storeName, version, clearAllOnUpgrade);
|
super(context, storeName, version, clearAllOnUpgrade);
|
||||||
|
this.gson = gson;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void putAllJsons(Map<String, T> jsonMap) {
|
public <T> void putAllJsons(Map<String, T> jsonMap) {
|
||||||
|
|
|
||||||
|
|
@ -896,7 +896,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
|
|
||||||
CustomApiResult result = api.upload(filename, file, dataLength, pageContents, editSummary, getCentralAuthToken(), getEditToken(), progressListener::onProgress);
|
CustomApiResult result = api.upload(filename, file, dataLength, pageContents, editSummary, getCentralAuthToken(), getEditToken(), progressListener::onProgress);
|
||||||
|
|
||||||
Timber.wtf("Result: " + result.toString());
|
Timber.d("Result: %s", result.toString());
|
||||||
|
|
||||||
String resultStatus = result.getString("/api/upload/@result");
|
String resultStatus = result.getString("/api/upload/@result");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,15 +36,15 @@ public class CustomApiResult {
|
||||||
this.evaluator = XPathFactory.newInstance().newXPath();
|
this.evaluator = XPathFactory.newInstance().newXPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
static CustomApiResult fromRequestBuilder(Http.HttpRequestBuilder builder, HttpClient client) throws IOException {
|
static CustomApiResult fromRequestBuilder(String requestIdentifier, Http.HttpRequestBuilder builder, HttpClient client) throws IOException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
Document doc = docBuilder.parse(builder.use(client).charset("utf-8").data("format", "xml").asResponse().getEntity().getContent());
|
Document doc = docBuilder.parse(builder.use(client).charset("utf-8").data("format", "xml").asResponse().getEntity().getContent());
|
||||||
printStringFromDocument(doc);
|
printStringFromDocument(requestIdentifier, doc);
|
||||||
return new CustomApiResult(doc);
|
return new CustomApiResult(doc);
|
||||||
} catch (ParserConfigurationException e) {
|
} catch (ParserConfigurationException e) {
|
||||||
// I don't know wtf I can do about this on...
|
// I don't know wtf I can do about this on...
|
||||||
|
Timber.e(e, "Error occurred while parsing the response for method %s", requestIdentifier);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
// So, this should never actually happen - since we assume MediaWiki always generates valid json
|
// So, this should never actually happen - since we assume MediaWiki always generates valid json
|
||||||
|
|
@ -52,14 +52,16 @@ public class CustomApiResult {
|
||||||
// Sooo... I can throw IOError
|
// Sooo... I can throw IOError
|
||||||
// Thanks Java, for making me spend significant time on shit that happens once in a bluemoon
|
// Thanks Java, for making me spend significant time on shit that happens once in a bluemoon
|
||||||
// I surely am writing Nuclear Submarine controller code
|
// I surely am writing Nuclear Submarine controller code
|
||||||
|
Timber.e(e, "Error occurred while parsing the response for method %s", requestIdentifier);
|
||||||
throw new IOError(e);
|
throw new IOError(e);
|
||||||
} catch (SAXException e) {
|
} catch (SAXException e) {
|
||||||
// See Rant above
|
// See Rant above
|
||||||
|
Timber.e(e, "Error occurred while parsing the response for method %s", requestIdentifier);
|
||||||
throw new IOError(e);
|
throw new IOError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printStringFromDocument(Document doc)
|
public static void printStringFromDocument(String requestIdentifier, Document doc)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -69,11 +71,11 @@ public class CustomApiResult {
|
||||||
TransformerFactory tf = TransformerFactory.newInstance();
|
TransformerFactory tf = TransformerFactory.newInstance();
|
||||||
Transformer transformer = tf.newTransformer();
|
Transformer transformer = tf.newTransformer();
|
||||||
transformer.transform(domSource, result);
|
transformer.transform(domSource, result);
|
||||||
Timber.d("API response is\n %s", writer.toString());
|
Timber.d("API response for method %s is\n %s", requestIdentifier, writer.toString());
|
||||||
}
|
}
|
||||||
catch(TransformerException ex)
|
catch(TransformerException ex)
|
||||||
{
|
{
|
||||||
Timber.d("Error occurred in transforming", ex);
|
Timber.e(ex, "Error occurred in transforming response for method %s", requestIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,7 @@ public class CustomMwApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomApiResult upload(String filename, InputStream file, long length, String text, String comment, String centralAuthToken, String token, ProgressListener uploadProgressListener) throws IOException {
|
public CustomApiResult upload(String filename, InputStream file, long length, String text, String comment, String centralAuthToken, String token, ProgressListener uploadProgressListener) throws IOException {
|
||||||
|
Timber.d("Initiating upload for file %s", filename);
|
||||||
Http.HttpRequestBuilder builder = Http.multipart(apiURL)
|
Http.HttpRequestBuilder builder = Http.multipart(apiURL)
|
||||||
.data("action", "upload")
|
.data("action", "upload")
|
||||||
.data("token", token)
|
.data("token", token)
|
||||||
|
|
@ -155,7 +156,7 @@ public class CustomMwApi {
|
||||||
builder.file("file", filename, file);
|
builder.file("file", filename, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CustomApiResult.fromRequestBuilder(builder, client);
|
return CustomApiResult.fromRequestBuilder("uploadFile", builder, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logout() throws IOException {
|
public void logout() throws IOException {
|
||||||
|
|
@ -174,7 +175,7 @@ public class CustomMwApi {
|
||||||
builder = Http.get(apiURL);
|
builder = Http.get(apiURL);
|
||||||
}
|
}
|
||||||
builder.data(params);
|
builder.data(params);
|
||||||
return CustomApiResult.fromRequestBuilder(builder, client);
|
return CustomApiResult.fromRequestBuilder(apiURL, builder, client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,17 @@ public class UploadResult {
|
||||||
this.imageUrl = imageUrl;
|
this.imageUrl = imageUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "UploadResult{" +
|
||||||
|
"errorCode='" + errorCode + '\'' +
|
||||||
|
", resultStatus='" + resultStatus + '\'' +
|
||||||
|
", dateUploaded='" + dateUploaded.toString() + '\'' +
|
||||||
|
", imageUrl='" + imageUrl + '\'' +
|
||||||
|
", canonicalFilename='" + canonicalFilename + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets uploaded date
|
* Gets uploaded date
|
||||||
* @return Upload date
|
* @return Upload date
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import com.mapbox.mapboxsdk.annotations.Icon;
|
||||||
import com.mapbox.mapboxsdk.annotations.IconFactory;
|
import com.mapbox.mapboxsdk.annotations.IconFactory;
|
||||||
import com.mapbox.mapboxsdk.geometry.LatLng;
|
import com.mapbox.mapboxsdk.geometry.LatLng;
|
||||||
|
|
||||||
import fr.free.nrw.commons.utils.UriDeserializer;
|
|
||||||
import fr.free.nrw.commons.utils.UriSerializer;
|
import fr.free.nrw.commons.utils.UriSerializer;
|
||||||
|
|
||||||
public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBaseMarker> {
|
public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBaseMarker> {
|
||||||
|
|
@ -33,10 +32,6 @@ public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBase
|
||||||
}
|
}
|
||||||
|
|
||||||
private NearbyBaseMarker(Parcel in) {
|
private NearbyBaseMarker(Parcel in) {
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriDeserializer())
|
|
||||||
.create();
|
|
||||||
|
|
||||||
position(in.readParcelable(LatLng.class.getClassLoader()));
|
position(in.readParcelable(LatLng.class.getClassLoader()));
|
||||||
snippet(in.readString());
|
snippet(in.readString());
|
||||||
String iconId = in.readString();
|
String iconId = in.readString();
|
||||||
|
|
@ -44,8 +39,7 @@ public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBase
|
||||||
Icon icon = IconFactory.recreate(iconId, iconBitmap);
|
Icon icon = IconFactory.recreate(iconId, iconBitmap);
|
||||||
icon(icon);
|
icon(icon);
|
||||||
title(in.readString());
|
title(in.readString());
|
||||||
String gsonString = in.readString();
|
place(in.readParcelable(Place.class.getClassLoader()));
|
||||||
place(gson.fromJson(gsonString, Place.class));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public NearbyBaseMarker place(Place place) {
|
public NearbyBaseMarker place(Place place) {
|
||||||
|
|
@ -74,15 +68,11 @@ public class NearbyBaseMarker extends BaseMarkerOptions<NearbyMarker, NearbyBase
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriSerializer())
|
|
||||||
.create();
|
|
||||||
|
|
||||||
dest.writeParcelable(position, flags);
|
dest.writeParcelable(position, flags);
|
||||||
dest.writeString(snippet);
|
dest.writeString(snippet);
|
||||||
dest.writeString(icon.getId());
|
dest.writeString(icon.getId());
|
||||||
dest.writeParcelable(icon.getBitmap(), flags);
|
dest.writeParcelable(icon.getBitmap(), flags);
|
||||||
dest.writeString(title);
|
dest.writeString(title);
|
||||||
dest.writeString(gson.toJson(place));
|
dest.writeParcelable(place, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
@Inject
|
@Inject
|
||||||
@Named("application_preferences")
|
@Named("application_preferences")
|
||||||
BasicKvStore applicationKvStore;
|
BasicKvStore applicationKvStore;
|
||||||
|
@Inject Gson gson;
|
||||||
|
|
||||||
public NearbyMapFragment nearbyMapFragment;
|
public NearbyMapFragment nearbyMapFragment;
|
||||||
private NearbyListFragment nearbyListFragment;
|
private NearbyListFragment nearbyListFragment;
|
||||||
|
|
@ -293,9 +294,6 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
//TODO: This hack inserts curLatLng before populatePlaces is called (see #1440). Ideally a proper fix should be found
|
//TODO: This hack inserts curLatLng before populatePlaces is called (see #1440). Ideally a proper fix should be found
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriSerializer())
|
|
||||||
.create();
|
|
||||||
String gsonCurLatLng = gson.toJson(curLatLng);
|
String gsonCurLatLng = gson.toJson(curLatLng);
|
||||||
bundle.clear();
|
bundle.clear();
|
||||||
bundle.putString("CurLatLng", gsonCurLatLng);
|
bundle.putString("CurLatLng", gsonCurLatLng);
|
||||||
|
|
@ -313,9 +311,6 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
|
|
||||||
} else if (locationChangeType
|
} else if (locationChangeType
|
||||||
.equals(LOCATION_SLIGHTLY_CHANGED)) {
|
.equals(LOCATION_SLIGHTLY_CHANGED)) {
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriSerializer())
|
|
||||||
.create();
|
|
||||||
String gsonCurLatLng = gson.toJson(curLatLng);
|
String gsonCurLatLng = gson.toJson(curLatLng);
|
||||||
bundle.putString("CurLatLng", gsonCurLatLng);
|
bundle.putString("CurLatLng", gsonCurLatLng);
|
||||||
updateMapFragment(false,true, null, null);
|
updateMapFragment(false,true, null, null);
|
||||||
|
|
@ -384,9 +379,6 @@ public class NearbyFragment extends CommonsDaggerSupportFragment
|
||||||
Timber.d("Populating nearby places");
|
Timber.d("Populating nearby places");
|
||||||
List<Place> placeList = nearbyPlacesInfo.placeList;
|
List<Place> placeList = nearbyPlacesInfo.placeList;
|
||||||
LatLng[] boundaryCoordinates = nearbyPlacesInfo.boundaryCoordinates;
|
LatLng[] boundaryCoordinates = nearbyPlacesInfo.boundaryCoordinates;
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriSerializer())
|
|
||||||
.create();
|
|
||||||
String gsonPlaceList = gson.toJson(placeList);
|
String gsonPlaceList = gson.toJson(placeList);
|
||||||
String gsonCurLatLng = gson.toJson(curLatLng);
|
String gsonCurLatLng = gson.toJson(curLatLng);
|
||||||
String gsonBoundaryCoordinates = gson.toJson(boundaryCoordinates);
|
String gsonBoundaryCoordinates = gson.toJson(boundaryCoordinates);
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,6 @@ public class NearbyListFragment extends DaggerFragment {
|
||||||
}.getType();
|
}.getType();
|
||||||
private static final Type CUR_LAT_LNG_TYPE = new TypeToken<LatLng>() {
|
private static final Type CUR_LAT_LNG_TYPE = new TypeToken<LatLng>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
private static final Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriDeserializer())
|
|
||||||
.create();
|
|
||||||
|
|
||||||
private NearbyAdapterFactory adapterFactory;
|
private NearbyAdapterFactory adapterFactory;
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
|
|
@ -49,6 +46,7 @@ public class NearbyListFragment extends DaggerFragment {
|
||||||
@Inject ContributionController controller;
|
@Inject ContributionController controller;
|
||||||
@Inject @Named("direct_nearby_upload_prefs") JsonKvStore directKvStore;
|
@Inject @Named("direct_nearby_upload_prefs") JsonKvStore directKvStore;
|
||||||
@Inject @Named("default_preferences") BasicKvStore defaultKvStore;
|
@Inject @Named("default_preferences") BasicKvStore defaultKvStore;
|
||||||
|
@Inject Gson gson;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,8 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
@Inject @Named("direct_nearby_upload_prefs") JsonKvStore directKvStore;
|
@Inject @Named("direct_nearby_upload_prefs") JsonKvStore directKvStore;
|
||||||
@Inject @Named("default_preferences") BasicKvStore defaultKvStore;
|
@Inject @Named("default_preferences") BasicKvStore defaultKvStore;
|
||||||
@Inject BookmarkLocationsDao bookmarkLocationDao;
|
@Inject BookmarkLocationsDao bookmarkLocationDao;
|
||||||
@Inject
|
@Inject ContributionController controller;
|
||||||
ContributionController controller;
|
@Inject Gson gson;
|
||||||
|
|
||||||
private static final double ZOOM_LEVEL = 14f;
|
private static final double ZOOM_LEVEL = 14f;
|
||||||
|
|
||||||
|
|
@ -148,9 +148,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
Timber.d("Nearby map fragment created");
|
Timber.d("Nearby map fragment created");
|
||||||
|
|
||||||
Bundle bundle = this.getArguments();
|
Bundle bundle = this.getArguments();
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriDeserializer())
|
|
||||||
.create();
|
|
||||||
if (bundle != null) {
|
if (bundle != null) {
|
||||||
String gsonPlaceList = bundle.getString("PlaceList");
|
String gsonPlaceList = bundle.getString("PlaceList");
|
||||||
String gsonLatLng = bundle.getString("CurLatLng");
|
String gsonLatLng = bundle.getString("CurLatLng");
|
||||||
|
|
@ -220,9 +217,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
public void updateMapSlightly() {
|
public void updateMapSlightly() {
|
||||||
Timber.d("updateMapSlightly called, bundle is:"+ bundleForUpdates);
|
Timber.d("updateMapSlightly called, bundle is:"+ bundleForUpdates);
|
||||||
if (mapboxMap != null) {
|
if (mapboxMap != null) {
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriDeserializer())
|
|
||||||
.create();
|
|
||||||
if (bundleForUpdates != null) {
|
if (bundleForUpdates != null) {
|
||||||
String gsonLatLng = bundleForUpdates.getString("CurLatLng");
|
String gsonLatLng = bundleForUpdates.getString("CurLatLng");
|
||||||
Type curLatLngType = new TypeToken<fr.free.nrw.commons.location.LatLng>() {}.getType();
|
Type curLatLngType = new TypeToken<fr.free.nrw.commons.location.LatLng>() {}.getType();
|
||||||
|
|
@ -242,10 +236,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
Timber.d("updateMapSignificantlyForCurrentLocation called, bundle is:"+ bundleForUpdates);
|
Timber.d("updateMapSignificantlyForCurrentLocation called, bundle is:"+ bundleForUpdates);
|
||||||
if (mapboxMap != null) {
|
if (mapboxMap != null) {
|
||||||
if (bundleForUpdates != null) {
|
if (bundleForUpdates != null) {
|
||||||
Gson gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(Uri.class, new UriDeserializer())
|
|
||||||
.create();
|
|
||||||
|
|
||||||
String gsonPlaceList = bundleForUpdates.getString("PlaceList");
|
String gsonPlaceList = bundleForUpdates.getString("PlaceList");
|
||||||
String gsonLatLng = bundleForUpdates.getString("CurLatLng");
|
String gsonLatLng = bundleForUpdates.getString("CurLatLng");
|
||||||
String gsonBoundaryCoordinates = bundleForUpdates.getString("BoundaryCoord");
|
String gsonBoundaryCoordinates = bundleForUpdates.getString("BoundaryCoord");
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,14 @@ import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
@ -19,20 +21,20 @@ import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.auth.SessionManager;
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
import fr.free.nrw.commons.contributions.Contribution;
|
import fr.free.nrw.commons.contributions.Contribution;
|
||||||
import fr.free.nrw.commons.kvstore.BasicKvStore;
|
import fr.free.nrw.commons.kvstore.BasicKvStore;
|
||||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
|
||||||
import fr.free.nrw.commons.nearby.Place;
|
import fr.free.nrw.commons.nearby.Place;
|
||||||
import fr.free.nrw.commons.settings.Prefs;
|
import fr.free.nrw.commons.settings.Prefs;
|
||||||
import fr.free.nrw.commons.utils.ImageUtils;
|
import fr.free.nrw.commons.utils.ImageUtils;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.functions.Consumer;
|
import io.reactivex.functions.Consumer;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import io.reactivex.subjects.BehaviorSubject;
|
import io.reactivex.subjects.BehaviorSubject;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
|
||||||
public class UploadModel {
|
public class UploadModel {
|
||||||
|
|
||||||
private MediaWikiApi mwApi;
|
|
||||||
private static UploadItem DUMMY = new UploadItem(
|
private static UploadItem DUMMY = new UploadItem(
|
||||||
Uri.EMPTY,
|
Uri.EMPTY,
|
||||||
"",
|
"",
|
||||||
|
|
@ -53,11 +55,9 @@ public class UploadModel {
|
||||||
private int currentStepIndex = 0;
|
private int currentStepIndex = 0;
|
||||||
private Context context;
|
private Context context;
|
||||||
private ContentResolver contentResolver;
|
private ContentResolver contentResolver;
|
||||||
private boolean useExtStorage;
|
|
||||||
private Disposable badImageSubscription;
|
private Disposable badImageSubscription;
|
||||||
|
|
||||||
private SessionManager sessionManager;
|
private SessionManager sessionManager;
|
||||||
private Uri currentMediaUri;
|
|
||||||
private FileUtilsWrapper fileUtilsWrapper;
|
private FileUtilsWrapper fileUtilsWrapper;
|
||||||
private FileProcessor fileProcessor;
|
private FileProcessor fileProcessor;
|
||||||
private final ImageProcessingService imageProcessingService;
|
private final ImageProcessingService imageProcessingService;
|
||||||
|
|
@ -67,7 +67,6 @@ public class UploadModel {
|
||||||
@Named("default_preferences") BasicKvStore basicKvStore,
|
@Named("default_preferences") BasicKvStore basicKvStore,
|
||||||
@Named("licenses_by_name") Map<String, String> licensesByName,
|
@Named("licenses_by_name") Map<String, String> licensesByName,
|
||||||
Context context,
|
Context context,
|
||||||
MediaWikiApi mwApi,
|
|
||||||
SessionManager sessionManager,
|
SessionManager sessionManager,
|
||||||
FileUtilsWrapper fileUtilsWrapper,
|
FileUtilsWrapper fileUtilsWrapper,
|
||||||
FileProcessor fileProcessor, ImageProcessingService imageProcessingService) {
|
FileProcessor fileProcessor, ImageProcessingService imageProcessingService) {
|
||||||
|
|
@ -76,14 +75,11 @@ public class UploadModel {
|
||||||
this.license = basicKvStore.getString(Prefs.DEFAULT_LICENSE, Prefs.Licenses.CC_BY_SA_3);
|
this.license = basicKvStore.getString(Prefs.DEFAULT_LICENSE, Prefs.Licenses.CC_BY_SA_3);
|
||||||
this.licensesByName = licensesByName;
|
this.licensesByName = licensesByName;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.mwApi = mwApi;
|
|
||||||
this.contentResolver = context.getContentResolver();
|
this.contentResolver = context.getContentResolver();
|
||||||
this.sessionManager = sessionManager;
|
this.sessionManager = sessionManager;
|
||||||
this.fileUtilsWrapper = fileUtilsWrapper;
|
this.fileUtilsWrapper = fileUtilsWrapper;
|
||||||
this.fileProcessor = fileProcessor;
|
this.fileProcessor = fileProcessor;
|
||||||
useExtStorage = this.basicKvStore.getBoolean("useExternalStorage", false);
|
|
||||||
this.imageProcessingService = imageProcessingService;
|
this.imageProcessingService = imageProcessingService;
|
||||||
useExtStorage = this.basicKvStore.getBoolean("useExternalStorage", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
|
|
@ -96,24 +92,30 @@ public class UploadModel {
|
||||||
|
|
||||||
return Observable.fromIterable(mediaUris)
|
return Observable.fromIterable(mediaUris)
|
||||||
.map(mediaUri -> {
|
.map(mediaUri -> {
|
||||||
if (mediaUri == null || mediaUri.getPath() == null) {
|
UploadItem item = getUploadItem(mimeType, place, source, similarImageInterface, mediaUri);
|
||||||
return null;
|
imageProcessingService.checkImageQuality(place, mediaUri.getPath())
|
||||||
}
|
|
||||||
String filePath = mediaUri.getPath();
|
|
||||||
long fileCreatedDate = getFileCreatedDate(currentMediaUri);
|
|
||||||
String fileExt = fileUtilsWrapper.getFileExt(filePath);
|
|
||||||
GPSExtractor gpsExtractor = fileProcessor.processFileCoordinates(similarImageInterface);
|
|
||||||
|
|
||||||
fileProcessor.initFileDetails(filePath, context.getContentResolver());
|
|
||||||
UploadItem item = new UploadItem(mediaUri, mimeType, source, gpsExtractor,
|
|
||||||
fileExt, place.getWikiDataEntityId(), fileCreatedDate);
|
|
||||||
imageProcessingService.checkImageQuality(place, filePath)
|
|
||||||
.subscribeOn(Schedulers.computation())
|
.subscribeOn(Schedulers.computation())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(item.imageQuality::onNext, Timber::e);
|
.subscribe(item.imageQuality::onNext, Timber::e);
|
||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private UploadItem getUploadItem(String mimeType,
|
||||||
|
Place place,
|
||||||
|
String source,
|
||||||
|
SimilarImageInterface similarImageInterface,
|
||||||
|
Uri mediaUri) {
|
||||||
|
fileProcessor
|
||||||
|
.initFileDetails(Objects.requireNonNull(mediaUri.getPath()), context.getContentResolver());
|
||||||
|
long fileCreatedDate = getFileCreatedDate(mediaUri);
|
||||||
|
String fileExt = fileUtilsWrapper.getFileExt(mediaUri.getPath());
|
||||||
|
GPSExtractor gpsExtractor = fileProcessor.processFileCoordinates(similarImageInterface);
|
||||||
|
return new UploadItem(mediaUri, mimeType, source, gpsExtractor,
|
||||||
|
fileExt, place, fileCreatedDate);
|
||||||
|
}
|
||||||
|
|
||||||
void onItemsProcessed(Place place, List<UploadItem> uploadItems) {
|
void onItemsProcessed(Place place, List<UploadItem> uploadItems) {
|
||||||
items = uploadItems;
|
items = uploadItems;
|
||||||
if (items.isEmpty()) {
|
if (items.isEmpty()) {
|
||||||
|
|
@ -314,7 +316,9 @@ public class UploadModel {
|
||||||
Description.formatList(item.descriptions), -1,
|
Description.formatList(item.descriptions), -1,
|
||||||
null, null, sessionManager.getAuthorName(),
|
null, null, sessionManager.getAuthorName(),
|
||||||
CommonsApplication.DEFAULT_EDIT_SUMMARY, item.gpsCoords.getCoords());
|
CommonsApplication.DEFAULT_EDIT_SUMMARY, item.gpsCoords.getCoords());
|
||||||
contribution.setWikiDataEntityId(item.wikidataEntityId);
|
if (item.place != null) {
|
||||||
|
contribution.setWikiDataEntityId(item.place.getWikiDataEntityId());
|
||||||
|
}
|
||||||
contribution.setCategories(categoryStringList);
|
contribution.setCategories(categoryStringList);
|
||||||
contribution.setTag("mimeType", item.mimeType);
|
contribution.setTag("mimeType", item.mimeType);
|
||||||
contribution.setSource(item.source);
|
contribution.setSource(item.source);
|
||||||
|
|
@ -358,17 +362,17 @@ public class UploadModel {
|
||||||
public BehaviorSubject<Integer> imageQuality;
|
public BehaviorSubject<Integer> imageQuality;
|
||||||
Title title;
|
Title title;
|
||||||
List<Description> descriptions;
|
List<Description> descriptions;
|
||||||
public String wikidataEntityId;
|
public Place place;
|
||||||
public boolean visited;
|
public boolean visited;
|
||||||
public boolean error;
|
public boolean error;
|
||||||
public long createdTimestamp;
|
public long createdTimestamp;
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
UploadItem(Uri mediaUri, String mimeType, String source, GPSExtractor gpsCoords, String fileExt, @Nullable String wikidataEntityId, long createdTimestamp) {
|
UploadItem(Uri mediaUri, String mimeType, String source, GPSExtractor gpsCoords, String fileExt, @Nullable Place place, long createdTimestamp) {
|
||||||
title = new Title();
|
title = new Title();
|
||||||
descriptions = new ArrayList<>();
|
descriptions = new ArrayList<>();
|
||||||
descriptions.add(new Description());
|
descriptions.add(new Description());
|
||||||
this.wikidataEntityId = wikidataEntityId;
|
this.place = place;
|
||||||
this.mediaUri = mediaUri;
|
this.mediaUri = mediaUri;
|
||||||
this.mimeType = mimeType;
|
this.mimeType = mimeType;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
|
|
|
||||||
|
|
@ -90,8 +90,7 @@ public class UploadPresenter {
|
||||||
updateCards();
|
updateCards();
|
||||||
updateLicenses();
|
updateLicenses();
|
||||||
updateContent();
|
updateContent();
|
||||||
if (uploadModel.isShowingItem())
|
uploadModel.subscribeBadPicture(this::handleBadPicture);
|
||||||
uploadModel.subscribeBadPicture(this::handleBadPicture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -12,21 +12,13 @@ import static fr.free.nrw.commons.contributions.ContributionController.NEARBY_GA
|
||||||
|
|
||||||
public class IntentUtils {
|
public class IntentUtils {
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the intent should be handled by nearby list or map fragment
|
|
||||||
*/
|
|
||||||
public static boolean shouldNearbyHandle(int requestCode, int resultCode, Intent data) {
|
|
||||||
return resultCode == Activity.RESULT_OK
|
|
||||||
&& (requestCode == NEARBY_CAMERA_UPLOAD_REQUEST_CODE || requestCode == NEARBY_GALLERY_UPLOAD_REQUEST_CODE)
|
|
||||||
&& data != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the intent should be handled by contributions list fragment
|
* Check if the intent should be handled by contributions list fragment
|
||||||
*/
|
*/
|
||||||
public static boolean shouldContributionsListHandle(int requestCode, int resultCode, Intent data) {
|
public static boolean shouldContributionsHandle(int requestCode, int resultCode, Intent data) {
|
||||||
return resultCode == Activity.RESULT_OK
|
return resultCode == Activity.RESULT_OK
|
||||||
&& (requestCode == GALLERY_UPLOAD_REQUEST_CODE || requestCode == CAMERA_UPLOAD_REQUEST_CODE)
|
&& (requestCode == GALLERY_UPLOAD_REQUEST_CODE || requestCode == CAMERA_UPLOAD_REQUEST_CODE
|
||||||
|
|| requestCode == NEARBY_CAMERA_UPLOAD_REQUEST_CODE || requestCode == NEARBY_GALLERY_UPLOAD_REQUEST_CODE)
|
||||||
&& data != null;
|
&& data != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModu
|
||||||
|
|
||||||
override fun provideModificationContentProviderClient(context: Context?): ContentProviderClient = modificationClient
|
override fun provideModificationContentProviderClient(context: Context?): ContentProviderClient = modificationClient
|
||||||
|
|
||||||
override fun providesDirectNearbyUploadKvStore(context: Context?): JsonKvStore = uploadPrefs
|
override fun providesDirectNearbyUploadKvStore(context: Context?, gson: Gson): JsonKvStore = uploadPrefs
|
||||||
|
|
||||||
override fun providesAccountUtil(context: Context): AccountUtil = accountUtil
|
override fun providesAccountUtil(context: Context): AccountUtil = accountUtil
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue