mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Merge pull request #1584 from commons-app/wikidataEdits
Merge Wikidata edits branch to master
This commit is contained in:
commit
32d45b2687
28 changed files with 422 additions and 37 deletions
|
|
@ -16,4 +16,4 @@ Tested on {API level & name of device/emulator}, with {build variant, e.g. ProdD
|
||||||
|
|
||||||
{Only for user interface changes, otherwise remove this section. See [how to take a screenshot](https://android.stackexchange.com/questions/1759/how-to-take-a-screenshot-with-an-android-device)}
|
{Only for user interface changes, otherwise remove this section. See [how to take a screenshot](https://android.stackexchange.com/questions/1759/how-to-take-a-screenshot-with-an-android-device)}
|
||||||
|
|
||||||
_Note: Please ensure that you have read CONTRIBUTING.md if this is your first pull request._
|
_Note: Please ensure that you have read CONTRIBUTING.md if this is your first pull request._
|
||||||
|
|
@ -135,6 +135,7 @@ android {
|
||||||
productFlavors {
|
productFlavors {
|
||||||
prod {
|
prod {
|
||||||
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\""
|
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\""
|
||||||
|
buildConfigField "String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\""
|
||||||
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
|
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
|
||||||
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\""
|
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\""
|
||||||
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\""
|
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\""
|
||||||
|
|
@ -151,6 +152,7 @@ android {
|
||||||
beta {
|
beta {
|
||||||
// What values do we need to hit the BETA versions of the site / api ?
|
// What values do we need to hit the BETA versions of the site / api ?
|
||||||
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.beta.wmflabs.org/w/api.php\""
|
buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.beta.wmflabs.org/w/api.php\""
|
||||||
|
buildConfigField "String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\""
|
||||||
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
|
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
|
||||||
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\""
|
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\""
|
||||||
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\""
|
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\""
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import java.io.File;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.auth.SessionManager;
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
import fr.free.nrw.commons.category.CategoryDao;
|
import fr.free.nrw.commons.category.CategoryDao;
|
||||||
import fr.free.nrw.commons.contributions.ContributionDao;
|
import fr.free.nrw.commons.contributions.ContributionDao;
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,7 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void handleWebUrl(Context context, Uri url) {
|
public static void handleWebUrl(Context context, Uri url) {
|
||||||
|
Timber.d("Launching web url %s", url.toString());
|
||||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, url);
|
Intent browserIntent = new Intent(Intent.ACTION_VIEW, url);
|
||||||
if (browserIntent.resolveActivity(context.getPackageManager()) == null) {
|
if (browserIntent.resolveActivity(context.getPackageManager()) == null) {
|
||||||
Toast toast = Toast.makeText(context, context.getString(R.string.no_web_browser), LENGTH_SHORT);
|
Toast toast = Toast.makeText(context, context.getString(R.string.no_web_browser), LENGTH_SHORT);
|
||||||
|
|
|
||||||
|
|
@ -228,7 +228,7 @@ public class CategoryImagesListFragment extends DaggerFragment {
|
||||||
/**
|
/**
|
||||||
* This method will be called on back pressed of CategoryImagesActivity.
|
* This method will be called on back pressed of CategoryImagesActivity.
|
||||||
* It initializes the grid view by setting adapter.
|
* It initializes the grid view by setting adapter.
|
||||||
\ */
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
gridView.setAdapter(gridAdapter);
|
gridView.setAdapter(gridAdapter);
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ public class Contribution extends Media {
|
||||||
private long transferred;
|
private long transferred;
|
||||||
private String decimalCoords;
|
private String decimalCoords;
|
||||||
private boolean isMultiple;
|
private boolean isMultiple;
|
||||||
|
private String wikiDataEntityId;
|
||||||
|
|
||||||
public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date timestamp,
|
public Contribution(Uri contentUri, String filename, Uri localUri, String imageUrl, Date timestamp,
|
||||||
int state, long dataLength, Date dateUploaded, long transferred,
|
int state, long dataLength, Date dateUploaded, long transferred,
|
||||||
|
|
@ -222,4 +223,17 @@ public class Contribution extends Media {
|
||||||
|
|
||||||
throw new RuntimeException("Unrecognized license value: " + license);
|
throw new RuntimeException("Unrecognized license value: " + license);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getWikiDataEntityId() {
|
||||||
|
return wikiDataEntityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the corresponding wikidata entity is known as in case of nearby uploads, it can be set
|
||||||
|
* using the setter method
|
||||||
|
* @param wikiDataEntityId
|
||||||
|
*/
|
||||||
|
public void setWikiDataEntityId(String wikiDataEntityId) {
|
||||||
|
this.wikiDataEntityId = wikiDataEntityId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ public class ContributionController {
|
||||||
fragment.startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY);
|
fragment.startActivityForResult(pickImageIntent, SELECT_FROM_GALLERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleImagePicked(int requestCode, Intent data, boolean isDirectUpload) {
|
public void handleImagePicked(int requestCode, Intent data, boolean isDirectUpload, String wikiDataEntityId) {
|
||||||
FragmentActivity activity = fragment.getActivity();
|
FragmentActivity activity = fragment.getActivity();
|
||||||
Timber.d("handleImagePicked() called with onActivityResult()");
|
Timber.d("handleImagePicked() called with onActivityResult()");
|
||||||
Intent shareIntent = new Intent(activity, ShareActivity.class);
|
Intent shareIntent = new Intent(activity, ShareActivity.class);
|
||||||
|
|
@ -102,9 +102,6 @@ public class ContributionController {
|
||||||
shareIntent.setType(activity.getContentResolver().getType(imageData));
|
shareIntent.setType(activity.getContentResolver().getType(imageData));
|
||||||
shareIntent.putExtra(EXTRA_STREAM, imageData);
|
shareIntent.putExtra(EXTRA_STREAM, imageData);
|
||||||
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_GALLERY);
|
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_GALLERY);
|
||||||
if (isDirectUpload) {
|
|
||||||
shareIntent.putExtra("isDirectUpload", true);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SELECT_FROM_CAMERA:
|
case SELECT_FROM_CAMERA:
|
||||||
//FIXME: Find out appropriate mime type
|
//FIXME: Find out appropriate mime type
|
||||||
|
|
@ -113,9 +110,6 @@ public class ContributionController {
|
||||||
shareIntent.setType("image/jpeg");
|
shareIntent.setType("image/jpeg");
|
||||||
shareIntent.putExtra(EXTRA_STREAM, lastGeneratedCaptureUri);
|
shareIntent.putExtra(EXTRA_STREAM, lastGeneratedCaptureUri);
|
||||||
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_CAMERA);
|
shareIntent.putExtra(EXTRA_SOURCE, SOURCE_CAMERA);
|
||||||
if (isDirectUpload) {
|
|
||||||
shareIntent.putExtra("isDirectUpload", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -123,6 +117,10 @@ public class ContributionController {
|
||||||
}
|
}
|
||||||
Timber.i("Image selected");
|
Timber.i("Image selected");
|
||||||
try {
|
try {
|
||||||
|
shareIntent.putExtra("isDirectUpload", isDirectUpload);
|
||||||
|
if (wikiDataEntityId != null && !wikiDataEntityId.equals("")) {
|
||||||
|
shareIntent.putExtra("wikiDataEntityId", wikiDataEntityId);
|
||||||
|
}
|
||||||
activity.startActivity(shareIntent);
|
activity.startActivity(shareIntent);
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
Timber.e(e, "Security Exception");
|
Timber.e(e, "Security Exception");
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||||
requestCode, resultCode, data);
|
requestCode, resultCode, data);
|
||||||
controller.handleImagePicked(requestCode, data, false);
|
controller.handleImagePicked(requestCode, data, false, null);
|
||||||
} else {
|
} else {
|
||||||
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||||
requestCode, resultCode, data);
|
requestCode, resultCode, data);
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,25 @@ import android.content.SharedPreferences;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.util.LruCache;
|
import android.support.v4.util.LruCache;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.auth.AccountUtil;
|
import fr.free.nrw.commons.auth.AccountUtil;
|
||||||
import fr.free.nrw.commons.auth.SessionManager;
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
import fr.free.nrw.commons.data.DBOpenHelper;
|
import fr.free.nrw.commons.data.DBOpenHelper;
|
||||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||||
|
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.nearby.NearbyPlaces;
|
import fr.free.nrw.commons.nearby.NearbyPlaces;
|
||||||
import fr.free.nrw.commons.upload.UploadController;
|
import fr.free.nrw.commons.upload.UploadController;
|
||||||
|
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||||
|
import fr.free.nrw.commons.wikidata.WikidataEditListenerImpl;
|
||||||
|
|
||||||
import static android.content.Context.MODE_PRIVATE;
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.CONTRIBUTION_AUTHORITY;
|
import static fr.free.nrw.commons.contributions.ContributionsContentProvider.CONTRIBUTION_AUTHORITY;
|
||||||
|
|
@ -133,4 +140,10 @@ public class CommonsApplicationModule {
|
||||||
public LruCache<String, String> provideLruCache() {
|
public LruCache<String, String> provideLruCache() {
|
||||||
return new LruCache<>(1024);
|
return new LruCache<>(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public WikidataEditListener provideWikidataEditListener() {
|
||||||
|
return new WikidataEditListenerImpl();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -35,7 +35,7 @@ public class NetworkingModule {
|
||||||
@Named("default_preferences") SharedPreferences defaultPreferences,
|
@Named("default_preferences") SharedPreferences defaultPreferences,
|
||||||
@Named("category_prefs") SharedPreferences categoryPrefs,
|
@Named("category_prefs") SharedPreferences categoryPrefs,
|
||||||
Gson gson) {
|
Gson gson) {
|
||||||
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, defaultPreferences, categoryPrefs, gson);
|
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, BuildConfig.WIKIDATA_API_HOST, defaultPreferences, categoryPrefs, gson);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,7 @@ public class LocationServiceManager implements LocationListener {
|
||||||
LOCATION_SIGNIFICANTLY_CHANGED, //Went out of borders of nearby markers
|
LOCATION_SIGNIFICANTLY_CHANGED, //Went out of borders of nearby markers
|
||||||
LOCATION_SLIGHTLY_CHANGED, //User might be walking or driving
|
LOCATION_SLIGHTLY_CHANGED, //User might be walking or driving
|
||||||
LOCATION_NOT_CHANGED,
|
LOCATION_NOT_CHANGED,
|
||||||
PERMISSION_JUST_GRANTED
|
PERMISSION_JUST_GRANTED,
|
||||||
|
MAP_UPDATED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ import android.widget.ScrollView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.OnClick;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ import org.apache.http.params.CoreProtocolPNames;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.mediawiki.api.ApiResult;
|
import org.mediawiki.api.ApiResult;
|
||||||
import org.mediawiki.api.MWApi;
|
import org.mediawiki.api.MWApi;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -62,6 +64,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
private static final String THUMB_SIZE = "640";
|
private static final String THUMB_SIZE = "640";
|
||||||
private AbstractHttpClient httpClient;
|
private AbstractHttpClient httpClient;
|
||||||
private MWApi api;
|
private MWApi api;
|
||||||
|
private MWApi wikidataApi;
|
||||||
private Context context;
|
private Context context;
|
||||||
private SharedPreferences defaultPreferences;
|
private SharedPreferences defaultPreferences;
|
||||||
private SharedPreferences categoryPreferences;
|
private SharedPreferences categoryPreferences;
|
||||||
|
|
@ -69,6 +72,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
|
|
||||||
public ApacheHttpClientMediaWikiApi(Context context,
|
public ApacheHttpClientMediaWikiApi(Context context,
|
||||||
String apiURL,
|
String apiURL,
|
||||||
|
String wikidatApiURL,
|
||||||
SharedPreferences defaultPreferences,
|
SharedPreferences defaultPreferences,
|
||||||
SharedPreferences categoryPreferences,
|
SharedPreferences categoryPreferences,
|
||||||
Gson gson) {
|
Gson gson) {
|
||||||
|
|
@ -82,6 +86,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
params.setParameter(CoreProtocolPNames.USER_AGENT, getUserAgent());
|
params.setParameter(CoreProtocolPNames.USER_AGENT, getUserAgent());
|
||||||
httpClient = new DefaultHttpClient(cm, params);
|
httpClient = new DefaultHttpClient(cm, params);
|
||||||
api = new MWApi(apiURL, httpClient);
|
api = new MWApi(apiURL, httpClient);
|
||||||
|
wikidataApi = new MWApi(wikidatApiURL, httpClient);
|
||||||
this.defaultPreferences = defaultPreferences;
|
this.defaultPreferences = defaultPreferences;
|
||||||
this.categoryPreferences = categoryPreferences;
|
this.categoryPreferences = categoryPreferences;
|
||||||
this.gson = gson;
|
this.gson = gson;
|
||||||
|
|
@ -206,6 +211,15 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
return api.getEditToken();
|
return api.getEditToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCentralAuthToken() throws IOException {
|
||||||
|
String centralAuthToken = api.action("centralauthtoken")
|
||||||
|
.get()
|
||||||
|
.getString("/api/centralauthtoken/@centralauthtoken");
|
||||||
|
Timber.d("MediaWiki Central auth token is %s", centralAuthToken);
|
||||||
|
return centralAuthToken;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fileExistsWithName(String fileName) throws IOException {
|
public boolean fileExistsWithName(String fileName) throws IOException {
|
||||||
return api.action("query")
|
return api.action("query")
|
||||||
|
|
@ -351,6 +365,98 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
}).flatMapObservable(Observable::fromIterable);
|
}).flatMapObservable(Observable::fromIterable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the edit token for making wiki data edits
|
||||||
|
* https://www.mediawiki.org/wiki/API:Tokens
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private String getWikidataEditToken() throws IOException {
|
||||||
|
return wikidataApi.getEditToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWikidataCsrfToken() throws IOException {
|
||||||
|
String wikidataCsrfToken = wikidataApi.action("query")
|
||||||
|
.param("action", "query")
|
||||||
|
.param("centralauthtoken", getCentralAuthToken())
|
||||||
|
.param("meta", "tokens")
|
||||||
|
.post()
|
||||||
|
.getString("/api/query/tokens/@csrftoken");
|
||||||
|
Timber.d("Wikidata csrf token is %s", wikidataCsrfToken);
|
||||||
|
return wikidataCsrfToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new claim using the wikidata API
|
||||||
|
* https://www.mediawiki.org/wiki/Wikibase/API
|
||||||
|
* @param entityId the wikidata entity to be edited
|
||||||
|
* @param property the property to be edited, for eg P18 for images
|
||||||
|
* @param snaktype the type of value stored for that property
|
||||||
|
* @param value the actual value to be stored for the property, for eg filename in case of P18
|
||||||
|
* @return returns revisionId if the claim is successfully created else returns null
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException {
|
||||||
|
Timber.d("Filename is %s", value);
|
||||||
|
ApiResult result = wikidataApi.action("wbcreateclaim")
|
||||||
|
.param("entity", entityId)
|
||||||
|
.param("centralauthtoken", getCentralAuthToken())
|
||||||
|
.param("token", getWikidataCsrfToken())
|
||||||
|
.param("snaktype", snaktype)
|
||||||
|
.param("property", property)
|
||||||
|
.param("value", value)
|
||||||
|
.post();
|
||||||
|
|
||||||
|
if (result == null || result.getNode("api") == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node node = result.getNode("api").getDocument();
|
||||||
|
Element element = (Element) node;
|
||||||
|
|
||||||
|
if (element != null && element.getAttribute("success").equals("1")) {
|
||||||
|
return result.getString("api/pageinfo/@lastrevid");
|
||||||
|
} else {
|
||||||
|
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the wikimedia-commons-app tag to the edits made on wikidata
|
||||||
|
* @param revisionId
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public boolean addWikidataEditTag(String revisionId) throws IOException {
|
||||||
|
ApiResult result = wikidataApi.action("tag")
|
||||||
|
.param("revid", revisionId)
|
||||||
|
.param("centralauthtoken", getCentralAuthToken())
|
||||||
|
.param("token", getWikidataCsrfToken())
|
||||||
|
.param("add", "wikimedia-commons-app")
|
||||||
|
.param("reason", "Add tag for edits made using Android Commons app")
|
||||||
|
.post();
|
||||||
|
|
||||||
|
if (result == null || result.getNode("api") == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node node = result.getNode("api").getDocument();
|
||||||
|
Element element = (Element) node;
|
||||||
|
|
||||||
|
if (element != null && element.getAttribute("status").equals("success")) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public Observable<String> searchTitles(String title, int searchCatsLimit) {
|
public Observable<String> searchTitles(String title, int searchCatsLimit) {
|
||||||
|
|
@ -586,6 +692,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
String resultStatus = result.getString("/api/upload/@result");
|
String resultStatus = result.getString("/api/upload/@result");
|
||||||
if (!resultStatus.equals("Success")) {
|
if (!resultStatus.equals("Success")) {
|
||||||
String errorCode = result.getString("/api/error/@code");
|
String errorCode = result.getString("/api/error/@code");
|
||||||
|
Timber.e(errorCode);
|
||||||
return new UploadResult(resultStatus, errorCode);
|
return new UploadResult(resultStatus, errorCode);
|
||||||
} else {
|
} else {
|
||||||
Date dateUploaded = parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));
|
Date dateUploaded = parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,10 @@ public interface MediaWikiApi {
|
||||||
|
|
||||||
String getEditToken() throws IOException;
|
String getEditToken() throws IOException;
|
||||||
|
|
||||||
|
String getWikidataCsrfToken() throws IOException;
|
||||||
|
|
||||||
|
String getCentralAuthToken() throws IOException;
|
||||||
|
|
||||||
boolean fileExistsWithName(String fileName) throws IOException;
|
boolean fileExistsWithName(String fileName) throws IOException;
|
||||||
|
|
||||||
boolean pageExists(String pageName) throws IOException;
|
boolean pageExists(String pageName) throws IOException;
|
||||||
|
|
@ -49,6 +53,12 @@ public interface MediaWikiApi {
|
||||||
@Nullable
|
@Nullable
|
||||||
String appendEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
|
String appendEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
boolean addWikidataEditTag(String revisionId) throws IOException;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
MediaResult fetchMediaByFilename(String filename) throws IOException;
|
MediaResult fetchMediaByFilename(String filename) throws IOException;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,13 @@ import butterknife.ButterKnife;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.location.LatLng;
|
import fr.free.nrw.commons.location.LatLng;
|
||||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||||
|
import fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType;
|
||||||
import fr.free.nrw.commons.location.LocationUpdateListener;
|
import fr.free.nrw.commons.location.LocationUpdateListener;
|
||||||
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||||
import fr.free.nrw.commons.utils.NetworkUtils;
|
import fr.free.nrw.commons.utils.NetworkUtils;
|
||||||
import fr.free.nrw.commons.utils.UriSerializer;
|
import fr.free.nrw.commons.utils.UriSerializer;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
|
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
|
|
@ -55,8 +57,12 @@ import timber.log.Timber;
|
||||||
import uk.co.deanwild.materialshowcaseview.IShowcaseListener;
|
import uk.co.deanwild.materialshowcaseview.IShowcaseListener;
|
||||||
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView;
|
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView;
|
||||||
|
|
||||||
|
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.*;
|
||||||
|
import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.MAP_UPDATED;
|
||||||
|
|
||||||
public class NearbyActivity extends NavigationBaseActivity implements LocationUpdateListener {
|
|
||||||
|
public class NearbyActivity extends NavigationBaseActivity implements LocationUpdateListener,
|
||||||
|
WikidataEditListener.WikidataP18EditListener {
|
||||||
|
|
||||||
private static final int LOCATION_REQUEST = 1;
|
private static final int LOCATION_REQUEST = 1;
|
||||||
|
|
||||||
|
|
@ -76,6 +82,8 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
LocationServiceManager locationManager;
|
LocationServiceManager locationManager;
|
||||||
@Inject
|
@Inject
|
||||||
NearbyController nearbyController;
|
NearbyController nearbyController;
|
||||||
|
@Inject WikidataEditListener wikidataEditListener;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@Named("application_preferences") SharedPreferences applicationPrefs;
|
@Named("application_preferences") SharedPreferences applicationPrefs;
|
||||||
private LatLng curLatLng;
|
private LatLng curLatLng;
|
||||||
|
|
@ -110,6 +118,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
|
|
||||||
initBottomSheetBehaviour();
|
initBottomSheetBehaviour();
|
||||||
initDrawer();
|
initDrawer();
|
||||||
|
wikidataEditListener.setAuthenticationStateListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resumeFragment() {
|
private void resumeFragment() {
|
||||||
|
|
@ -219,7 +228,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
//Still need to check if GPS is enabled
|
//Still need to check if GPS is enabled
|
||||||
checkGps();
|
checkGps();
|
||||||
lastKnownLocation = locationManager.getLKL();
|
lastKnownLocation = locationManager.getLKL();
|
||||||
refreshView(LocationServiceManager.LocationChangeType.PERMISSION_JUST_GRANTED);
|
refreshView(PERMISSION_JUST_GRANTED);
|
||||||
} else {
|
} else {
|
||||||
//If permission not granted, go to page that says Nearby Places cannot be displayed
|
//If permission not granted, go to page that says Nearby Places cannot be displayed
|
||||||
hideProgressBar();
|
hideProgressBar();
|
||||||
|
|
@ -279,7 +288,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
private void checkLocationPermission() {
|
private void checkLocationPermission() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
if (locationManager.isLocationPermissionGranted()) {
|
if (locationManager.isLocationPermissionGranted()) {
|
||||||
refreshView(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED);
|
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||||
} else {
|
} else {
|
||||||
// Should we show an explanation?
|
// Should we show an explanation?
|
||||||
if (locationManager.isPermissionExplanationRequired(this)) {
|
if (locationManager.isPermissionExplanationRequired(this)) {
|
||||||
|
|
@ -305,7 +314,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
refreshView(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED);
|
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,7 +323,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
if (requestCode == 1) {
|
if (requestCode == 1) {
|
||||||
Timber.d("User is back from Settings page");
|
Timber.d("User is back from Settings page");
|
||||||
refreshView(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED);
|
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,8 +382,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (NetworkUtils.isInternetConnectionEstablished(NearbyActivity.this)) {
|
if (NetworkUtils.isInternetConnectionEstablished(NearbyActivity.this)) {
|
||||||
refreshView(LocationServiceManager
|
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||||
.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED);
|
|
||||||
} else {
|
} else {
|
||||||
ViewUtil.showLongToast(NearbyActivity.this, getString(R.string.no_internet));
|
ViewUtil.showLongToast(NearbyActivity.this, getString(R.string.no_internet));
|
||||||
}
|
}
|
||||||
|
|
@ -390,7 +398,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
*
|
*
|
||||||
* @param locationChangeType defines if location shanged significantly or slightly
|
* @param locationChangeType defines if location shanged significantly or slightly
|
||||||
*/
|
*/
|
||||||
private void refreshView(LocationServiceManager.LocationChangeType locationChangeType) {
|
private void refreshView(LocationChangeType locationChangeType) {
|
||||||
if (lockNearbyView) {
|
if (lockNearbyView) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -403,12 +411,13 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
registerLocationUpdates();
|
registerLocationUpdates();
|
||||||
LatLng lastLocation = locationManager.getLastLocation();
|
LatLng lastLocation = locationManager.getLastLocation();
|
||||||
|
|
||||||
if (curLatLng != null && curLatLng.equals(lastLocation)) { //refresh view only if location has changed
|
if (curLatLng != null && curLatLng.equals(lastLocation)
|
||||||
|
&& !locationChangeType.equals(MAP_UPDATED)) { //refresh view only if location has changed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
curLatLng = lastLocation;
|
curLatLng = lastLocation;
|
||||||
|
|
||||||
if (locationChangeType.equals(LocationServiceManager.LocationChangeType.PERMISSION_JUST_GRANTED)) {
|
if (locationChangeType.equals(PERMISSION_JUST_GRANTED)) {
|
||||||
curLatLng = lastKnownLocation;
|
curLatLng = lastKnownLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -417,8 +426,9 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locationChangeType.equals(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)
|
if (locationChangeType.equals(LOCATION_SIGNIFICANTLY_CHANGED)
|
||||||
|| locationChangeType.equals(LocationServiceManager.LocationChangeType.PERMISSION_JUST_GRANTED)) {
|
|| locationChangeType.equals(PERMISSION_JUST_GRANTED)
|
||||||
|
|| locationChangeType.equals(MAP_UPDATED)) {
|
||||||
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
|
||||||
|
|
@ -440,7 +450,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
} else if (locationChangeType
|
} else if (locationChangeType
|
||||||
.equals(LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED)) {
|
.equals(LOCATION_SLIGHTLY_CHANGED)) {
|
||||||
Gson gson = new GsonBuilder()
|
Gson gson = new GsonBuilder()
|
||||||
.registerTypeAdapter(Uri.class, new UriSerializer())
|
.registerTypeAdapter(Uri.class, new UriSerializer())
|
||||||
.create();
|
.create();
|
||||||
|
|
@ -685,12 +695,12 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChangedSignificantly(LatLng latLng) {
|
public void onLocationChangedSignificantly(LatLng latLng) {
|
||||||
refreshView(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED);
|
refreshView(LOCATION_SIGNIFICANTLY_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLocationChangedSlightly(LatLng latLng) {
|
public void onLocationChangedSlightly(LatLng latLng) {
|
||||||
refreshView(LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED);
|
refreshView(LOCATION_SLIGHTLY_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void prepareViewsForSheetPosition(int bottomSheetState) {
|
public void prepareViewsForSheetPosition(int bottomSheetState) {
|
||||||
|
|
@ -700,4 +710,9 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
private void showErrorMessage(String message) {
|
private void showErrorMessage(String message) {
|
||||||
ViewUtil.showLongToast(NearbyActivity.this, message);
|
ViewUtil.showLongToast(NearbyActivity.this, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWikidataEditSuccessful() {
|
||||||
|
refreshView(MAP_UPDATED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package fr.free.nrw.commons.nearby;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
@ -21,6 +22,9 @@ import java.lang.reflect.Type;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
import dagger.android.support.AndroidSupportInjection;
|
import dagger.android.support.AndroidSupportInjection;
|
||||||
import dagger.android.support.DaggerFragment;
|
import dagger.android.support.DaggerFragment;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
|
@ -47,6 +51,11 @@ public class NearbyListFragment extends DaggerFragment {
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private ContributionController controller;
|
private ContributionController controller;
|
||||||
|
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Named("direct_nearby_upload_prefs")
|
||||||
|
SharedPreferences directPrefs;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
@ -137,7 +146,7 @@ public class NearbyListFragment extends DaggerFragment {
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||||
requestCode, resultCode, data);
|
requestCode, resultCode, data);
|
||||||
controller.handleImagePicked(requestCode, data, true);
|
controller.handleImagePicked(requestCode, data, true, directPrefs.getString("WikiDataEntityId", null));
|
||||||
} else {
|
} else {
|
||||||
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||||
requestCode, resultCode, data);
|
requestCode, resultCode, data);
|
||||||
|
|
|
||||||
|
|
@ -731,6 +731,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
editor.putString("Title", place.getName());
|
editor.putString("Title", place.getName());
|
||||||
editor.putString("Desc", place.getLongDescription());
|
editor.putString("Desc", place.getLongDescription());
|
||||||
editor.putString("Category", place.getCategory());
|
editor.putString("Category", place.getCategory());
|
||||||
|
editor.putString("WikiDataEntityId", place.getWikiDataEntityId());
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -766,7 +767,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
Timber.d("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||||
requestCode, resultCode, data);
|
requestCode, resultCode, data);
|
||||||
controller.handleImagePicked(requestCode, data, true);
|
controller.handleImagePicked(requestCode, data, true, directPrefs.getString("WikiDataEntityId", null));
|
||||||
} else {
|
} else {
|
||||||
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
Timber.e("OnActivityResult() parameters: Req code: %d Result code: %d Data: %s",
|
||||||
requestCode, resultCode, data);
|
requestCode, resultCode, data);
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.nearby;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -50,6 +51,20 @@ public class Place {
|
||||||
this.distance = distance;
|
this.distance = distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entity id from the wikidata link
|
||||||
|
* @return returns the entity id if wikidata link exists
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getWikiDataEntityId() {
|
||||||
|
if (!hasWikidataLink()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String wikiDataLink = siteLinks.getWikidataLink().toString();
|
||||||
|
return wikiDataLink.replace("http://www.wikidata.org/entity/", "");
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasWikipediaLink() {
|
public boolean hasWikipediaLink() {
|
||||||
return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getWikipediaLink()));
|
return !(siteLinks == null || Uri.EMPTY.equals(siteLinks.getWikipediaLink()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import android.widget.RelativeLayout;
|
||||||
|
|
||||||
import com.pedrogomez.renderers.RVRendererAdapter;
|
import com.pedrogomez.renderers.RVRendererAdapter;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -26,6 +25,7 @@ import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
import fr.free.nrw.commons.Utils;
|
import fr.free.nrw.commons.Utils;
|
||||||
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||||
import fr.free.nrw.commons.utils.NetworkUtils;
|
import fr.free.nrw.commons.utils.NetworkUtils;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
|
|
@ -46,6 +46,8 @@ public class NotificationActivity extends NavigationBaseActivity {
|
||||||
@BindView(R.id.container) RelativeLayout relativeLayout;
|
@BindView(R.id.container) RelativeLayout relativeLayout;
|
||||||
|
|
||||||
@Inject NotificationController controller;
|
@Inject NotificationController controller;
|
||||||
|
@Inject
|
||||||
|
MediaWikiApi mediaWikiApi;
|
||||||
|
|
||||||
private static final String TAG_NOTIFICATION_WORKER_FRAGMENT = "NotificationWorkerFragment";
|
private static final String TAG_NOTIFICATION_WORKER_FRAGMENT = "NotificationWorkerFragment";
|
||||||
private NotificationWorkerFragment mNotificationWorkerFragment;
|
private NotificationWorkerFragment mNotificationWorkerFragment;
|
||||||
|
|
@ -81,7 +83,6 @@ public class NotificationActivity extends NavigationBaseActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
@SuppressLint("CheckResult")
|
||||||
private void addNotifications() {
|
private void addNotifications() {
|
||||||
Timber.d("Add notifications");
|
Timber.d("Add notifications");
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ import io.reactivex.schedulers.Schedulers;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.DUPLICATE_PROCEED;
|
import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.DUPLICATE_PROCEED;
|
||||||
import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.NO_DUPLICATE;
|
import static fr.free.nrw.commons.upload.ExistingFileAsync.Result.NO_DUPLICATE;
|
||||||
|
|
||||||
|
|
@ -138,6 +139,8 @@ public class ShareActivity
|
||||||
|
|
||||||
private Uri mediaUri;
|
private Uri mediaUri;
|
||||||
private Contribution contribution;
|
private Contribution contribution;
|
||||||
|
private FloatingActionButton maps_fragment;
|
||||||
|
|
||||||
private boolean cacheFound;
|
private boolean cacheFound;
|
||||||
|
|
||||||
private GPSExtractor imageObj;
|
private GPSExtractor imageObj;
|
||||||
|
|
@ -150,6 +153,7 @@ public class ShareActivity
|
||||||
|
|
||||||
private String title;
|
private String title;
|
||||||
private String description;
|
private String description;
|
||||||
|
private String wikiDataEntityId;
|
||||||
private Snackbar snackbar;
|
private Snackbar snackbar;
|
||||||
private boolean duplicateCheckPassed = false;
|
private boolean duplicateCheckPassed = false;
|
||||||
|
|
||||||
|
|
@ -160,7 +164,7 @@ public class ShareActivity
|
||||||
private long ShortAnimationDuration;
|
private long ShortAnimationDuration;
|
||||||
private boolean isFABOpen = false;
|
private boolean isFABOpen = false;
|
||||||
|
|
||||||
//Had to make them class variables, to extract out the click listeners, also I see no harm in this
|
//Had to make them class variables, to extract out the click listeners, also I see no harm in this
|
||||||
final Rect startBounds = new Rect();
|
final Rect startBounds = new Rect();
|
||||||
final Rect finalBounds = new Rect();
|
final Rect finalBounds = new Rect();
|
||||||
final Point globalOffset = new Point();
|
final Point globalOffset = new Point();
|
||||||
|
|
@ -212,7 +216,7 @@ public class ShareActivity
|
||||||
Timber.d("Cache the categories found");
|
Timber.d("Cache the categories found");
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadController.startUpload(title, mediaUri, description, mimeType, source, decimalCoords, c -> {
|
uploadController.startUpload(title, mediaUri, description, mimeType, source, decimalCoords, wikiDataEntityId, c -> {
|
||||||
ShareActivity.this.contribution = c;
|
ShareActivity.this.contribution = c;
|
||||||
showPostUpload();
|
showPostUpload();
|
||||||
});
|
});
|
||||||
|
|
@ -295,7 +299,10 @@ public class ShareActivity
|
||||||
}
|
}
|
||||||
if (intent.hasExtra("isDirectUpload")) {
|
if (intent.hasExtra("isDirectUpload")) {
|
||||||
Timber.d("This was initiated by a direct upload from Nearby");
|
Timber.d("This was initiated by a direct upload from Nearby");
|
||||||
isNearbyUpload = true;
|
isNearbyUpload = intent.getBooleanExtra("isDirectUpload", false);
|
||||||
|
}
|
||||||
|
if (intent.hasExtra("wikiDataEntityId")) {
|
||||||
|
wikiDataEntityId = intent.getStringExtra("wikiDataEntityId");
|
||||||
}
|
}
|
||||||
mimeType = intent.getType();
|
mimeType = intent.getType();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ public class UploadController {
|
||||||
* @param decimalCoords the coordinates in decimal. (e.g. "37.51136|-77.602615")
|
* @param decimalCoords the coordinates in decimal. (e.g. "37.51136|-77.602615")
|
||||||
* @param onComplete the progress tracker
|
* @param onComplete the progress tracker
|
||||||
*/
|
*/
|
||||||
public void startUpload(String title, Uri mediaUri, String description, String mimeType, String source, String decimalCoords, ContributionUploadProgress onComplete) {
|
public void startUpload(String title, Uri mediaUri, String description, String mimeType, String source, String decimalCoords, String wikiDataEntityId, ContributionUploadProgress onComplete) {
|
||||||
Contribution contribution;
|
Contribution contribution;
|
||||||
|
|
||||||
//TODO: Modify this to include coords
|
//TODO: Modify this to include coords
|
||||||
|
|
@ -101,6 +101,7 @@ public class UploadController {
|
||||||
|
|
||||||
contribution.setTag("mimeType", mimeType);
|
contribution.setTag("mimeType", mimeType);
|
||||||
contribution.setSource(source);
|
contribution.setSource(source);
|
||||||
|
contribution.setWikiDataEntityId(wikiDataEntityId);
|
||||||
|
|
||||||
//Calls the next overloaded method
|
//Calls the next overloaded method
|
||||||
startUpload(contribution, onComplete);
|
startUpload(contribution, onComplete);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
@ -36,6 +37,12 @@ import fr.free.nrw.commons.contributions.ContributionsContentProvider;
|
||||||
import fr.free.nrw.commons.modifications.ModificationsContentProvider;
|
import fr.free.nrw.commons.modifications.ModificationsContentProvider;
|
||||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
import fr.free.nrw.commons.mwapi.UploadResult;
|
import fr.free.nrw.commons.mwapi.UploadResult;
|
||||||
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
|
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||||
|
import fr.free.nrw.commons.wikidata.WikidataEditService;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
public class UploadService extends HandlerService<Contribution> {
|
public class UploadService extends HandlerService<Contribution> {
|
||||||
|
|
@ -49,8 +56,8 @@ public class UploadService extends HandlerService<Contribution> {
|
||||||
public static final String EXTRA_CAMPAIGN = EXTRA_PREFIX + ".campaign";
|
public static final String EXTRA_CAMPAIGN = EXTRA_PREFIX + ".campaign";
|
||||||
|
|
||||||
@Inject MediaWikiApi mwApi;
|
@Inject MediaWikiApi mwApi;
|
||||||
|
@Inject WikidataEditService wikidataEditService;
|
||||||
@Inject SessionManager sessionManager;
|
@Inject SessionManager sessionManager;
|
||||||
@Inject @Named("default_preferences") SharedPreferences prefs;
|
|
||||||
@Inject ContributionDao contributionDao;
|
@Inject ContributionDao contributionDao;
|
||||||
|
|
||||||
private NotificationManager notificationManager;
|
private NotificationManager notificationManager;
|
||||||
|
|
@ -137,6 +144,7 @@ public class UploadService extends HandlerService<Contribution> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void queue(int what, Contribution contribution) {
|
public void queue(int what, Contribution contribution) {
|
||||||
|
Timber.d("Upload service queue has contribution with wiki data entity id as %s", contribution.getWikiDataEntityId());
|
||||||
switch (what) {
|
switch (what) {
|
||||||
case ACTION_UPLOAD_FILE:
|
case ACTION_UPLOAD_FILE:
|
||||||
|
|
||||||
|
|
@ -253,6 +261,7 @@ public class UploadService extends HandlerService<Contribution> {
|
||||||
if (!resultStatus.equals("Success")) {
|
if (!resultStatus.equals("Success")) {
|
||||||
showFailedNotification(contribution);
|
showFailedNotification(contribution);
|
||||||
} else {
|
} else {
|
||||||
|
wikidataEditService.createClaimWithLogging(contribution.getWikiDataEntityId(), filename);
|
||||||
contribution.setFilename(uploadResult.getCanonicalFilename());
|
contribution.setFilename(uploadResult.getCanonicalFilename());
|
||||||
contribution.setImageUrl(uploadResult.getImageUrl());
|
contribution.setImageUrl(uploadResult.getImageUrl());
|
||||||
contribution.setState(Contribution.STATE_COMPLETED);
|
contribution.setState(Contribution.STATE_COMPLETED);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package fr.free.nrw.commons.wikidata;
|
||||||
|
|
||||||
|
public abstract class WikidataEditListener {
|
||||||
|
|
||||||
|
protected WikidataP18EditListener wikidataP18EditListener;
|
||||||
|
|
||||||
|
public abstract void onSuccessfulWikidataEdit();
|
||||||
|
|
||||||
|
public void setAuthenticationStateListener(WikidataP18EditListener wikidataP18EditListener) {
|
||||||
|
this.wikidataP18EditListener = wikidataP18EditListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface WikidataP18EditListener {
|
||||||
|
void onWikidataEditSuccessful();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package fr.free.nrw.commons.wikidata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for wikidata edits
|
||||||
|
*/
|
||||||
|
public class WikidataEditListenerImpl extends WikidataEditListener {
|
||||||
|
|
||||||
|
public WikidataEditListenerImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when wikidata P18 edit is successful. If there's an active listener, then it is fired
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onSuccessfulWikidataEdit() {
|
||||||
|
if (wikidataP18EditListener != null) {
|
||||||
|
wikidataP18EditListener.onWikidataEditSuccessful();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
package fr.free.nrw.commons.wikidata;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is meant to handle the Wikidata edits made through the app
|
||||||
|
* It will talk with MediaWikiApi to make necessary API calls, log the edits and fire listeners
|
||||||
|
* on successful edits
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class WikidataEditService {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final MediaWikiApi mediaWikiApi;
|
||||||
|
private final WikidataEditListener wikidataEditListener;
|
||||||
|
private final SharedPreferences directPrefs;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public WikidataEditService(Context context,
|
||||||
|
MediaWikiApi mediaWikiApi,
|
||||||
|
WikidataEditListener wikidataEditListener,
|
||||||
|
@Named("direct_nearby_upload_prefs") SharedPreferences directPrefs) {
|
||||||
|
this.context = context;
|
||||||
|
this.mediaWikiApi = mediaWikiApi;
|
||||||
|
this.wikidataEditListener = wikidataEditListener;
|
||||||
|
this.directPrefs = directPrefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a P18 claim and log the edit with custom tag
|
||||||
|
* @param wikidataEntityId
|
||||||
|
* @param fileName
|
||||||
|
*/
|
||||||
|
public void createClaimWithLogging(String wikidataEntityId, String fileName) {
|
||||||
|
if(wikidataEntityId == null
|
||||||
|
|| fileName == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editWikidataProperty(wikidataEntityId, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits the wikidata entity by adding the P18 property to it.
|
||||||
|
* Adding the P18 edit requires calling the wikidata API to create a claim against the entity
|
||||||
|
*
|
||||||
|
* @param wikidataEntityId
|
||||||
|
* @param fileName
|
||||||
|
*/
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void editWikidataProperty(String wikidataEntityId, String fileName) {
|
||||||
|
Timber.d("Upload successful with wiki data entity id as %s", wikidataEntityId);
|
||||||
|
Timber.d("Attempting to edit Wikidata property %s", wikidataEntityId);
|
||||||
|
Observable.fromCallable(() -> {
|
||||||
|
String propertyValue = getFileName(fileName);
|
||||||
|
return mediaWikiApi.wikidatCreateClaim(wikidataEntityId, "P18", "value", propertyValue);
|
||||||
|
})
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(revisionId -> handleClaimResult(wikidataEntityId, revisionId), throwable -> {
|
||||||
|
Timber.e(throwable, "Error occurred while making claim");
|
||||||
|
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleClaimResult(String wikidataEntityId, String revisionId) {
|
||||||
|
if (revisionId != null) {
|
||||||
|
wikidataEditListener.onSuccessfulWikidataEdit();
|
||||||
|
showSuccessToast();
|
||||||
|
logEdit(revisionId);
|
||||||
|
} else {
|
||||||
|
Timber.d("Unable to make wiki data edit for entity %s", wikidataEntityId);
|
||||||
|
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log the Wikidata edit by adding Wikimedia Commons App tag to the edit
|
||||||
|
* @param revisionId
|
||||||
|
*/
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void logEdit(String revisionId) {
|
||||||
|
Observable.fromCallable(() -> mediaWikiApi.addWikidataEditTag(revisionId))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(result -> {
|
||||||
|
if (result) {
|
||||||
|
Timber.d("Wikidata edit was tagged successfully");
|
||||||
|
} else {
|
||||||
|
Timber.d("Wikidata edit couldn't be tagged");
|
||||||
|
}
|
||||||
|
}, throwable -> {
|
||||||
|
Timber.e(throwable, "Error occurred while adding tag to the edit");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a success toast when the edit is made successfully
|
||||||
|
*/
|
||||||
|
private void showSuccessToast() {
|
||||||
|
String title = directPrefs.getString("Title", "");
|
||||||
|
String successStringTemplate = context.getString(R.string.successful_wikidata_edit);
|
||||||
|
String successMessage = String.format(Locale.getDefault(), successStringTemplate, title);
|
||||||
|
ViewUtil.showLongToast(context, successMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats and returns the filename as accepted by the wiki base API
|
||||||
|
* https://www.mediawiki.org/wiki/Wikibase/API#wbcreateclaim
|
||||||
|
*
|
||||||
|
* @param fileName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getFileName(String fileName) {
|
||||||
|
fileName = String.format("\"%s\"", fileName.replace("File:", ""));
|
||||||
|
Timber.d("Wikidata property name is %s", fileName);
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -283,6 +283,8 @@
|
||||||
<string name="share_coordinates_not_present">Coordinates were not specified during image selection</string>
|
<string name="share_coordinates_not_present">Coordinates were not specified during image selection</string>
|
||||||
<string name="error_fetching_nearby_places">Error fetching nearby places.</string>
|
<string name="error_fetching_nearby_places">Error fetching nearby places.</string>
|
||||||
|
|
||||||
|
<string name="successful_wikidata_edit">Image successfully added to %1$s on Wikidata!</string>
|
||||||
|
<string name="wikidata_edit_failure">Failed to update corresponding wiki data entity!</string>
|
||||||
<string name="menu_set_wallpaper">Set wallpaper</string>
|
<string name="menu_set_wallpaper">Set wallpaper</string>
|
||||||
<string name="wallpaper_set_successfully">Wallpaper set successfully!</string>
|
<string name="wallpaper_set_successfully">Wallpaper set successfully!</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.content.ContentProviderClient
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.support.v4.util.LruCache
|
import android.support.v4.util.LruCache
|
||||||
|
import com.google.gson.Gson
|
||||||
import com.nhaarman.mockito_kotlin.mock
|
import com.nhaarman.mockito_kotlin.mock
|
||||||
import com.squareup.leakcanary.RefWatcher
|
import com.squareup.leakcanary.RefWatcher
|
||||||
import fr.free.nrw.commons.auth.AccountUtil
|
import fr.free.nrw.commons.auth.AccountUtil
|
||||||
|
|
@ -37,6 +38,7 @@ class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModu
|
||||||
val accountUtil: AccountUtil = mock()
|
val accountUtil: AccountUtil = mock()
|
||||||
val appSharedPreferences: SharedPreferences = mock()
|
val appSharedPreferences: SharedPreferences = mock()
|
||||||
val defaultSharedPreferences: SharedPreferences = mock()
|
val defaultSharedPreferences: SharedPreferences = mock()
|
||||||
|
val categorySharedPreferences: SharedPreferences = mock()
|
||||||
val otherSharedPreferences: SharedPreferences = mock()
|
val otherSharedPreferences: SharedPreferences = mock()
|
||||||
val uploadController: UploadController = mock()
|
val uploadController: UploadController = mock()
|
||||||
val mockSessionManager: SessionManager = mock()
|
val mockSessionManager: SessionManager = mock()
|
||||||
|
|
@ -44,6 +46,7 @@ class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModu
|
||||||
val mockDbOpenHelper: DBOpenHelper = mock()
|
val mockDbOpenHelper: DBOpenHelper = mock()
|
||||||
val nearbyPlaces: NearbyPlaces = mock()
|
val nearbyPlaces: NearbyPlaces = mock()
|
||||||
val lruCache: LruCache<String, String> = mock()
|
val lruCache: LruCache<String, String> = mock()
|
||||||
|
val gson: Gson = Gson()
|
||||||
val categoryClient: ContentProviderClient = mock()
|
val categoryClient: ContentProviderClient = mock()
|
||||||
val contributionClient: ContentProviderClient = mock()
|
val contributionClient: ContentProviderClient = mock()
|
||||||
val modificationClient: ContentProviderClient = mock()
|
val modificationClient: ContentProviderClient = mock()
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,17 @@ class ApacheHttpClientMediaWikiApiTest {
|
||||||
|
|
||||||
private lateinit var testObject: ApacheHttpClientMediaWikiApi
|
private lateinit var testObject: ApacheHttpClientMediaWikiApi
|
||||||
private lateinit var server: MockWebServer
|
private lateinit var server: MockWebServer
|
||||||
|
private lateinit var wikidataServer: MockWebServer
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
private lateinit var categoryPreferences: SharedPreferences
|
private lateinit var categoryPreferences: SharedPreferences
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
server = MockWebServer()
|
server = MockWebServer()
|
||||||
|
wikidataServer = MockWebServer()
|
||||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
|
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
|
||||||
categoryPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
|
categoryPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
|
||||||
testObject = ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.hostName + ":" + server.port + "/", sharedPreferences, categoryPreferences, Gson())
|
testObject = ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.hostName + ":" + server.port + "/", "http://" + wikidataServer.hostName + ":" + wikidataServer.port + "/", sharedPreferences, categoryPreferences, Gson())
|
||||||
testObject.setWikiMediaToolforgeUrl("http://" + server.hostName + ":" + server.port + "/")
|
testObject.setWikiMediaToolforgeUrl("http://" + server.hostName + ":" + server.port + "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue