mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 12:53:55 +01:00
resolving Login page switching issue
This commit is contained in:
commit
ed241e09f7
55 changed files with 1500 additions and 456 deletions
|
|
@ -5,15 +5,30 @@ If you're not sure where to start head on to [this wiki page](https://github.com
|
||||||
|
|
||||||
Here's a gist of the guidelines,
|
Here's a gist of the guidelines,
|
||||||
|
|
||||||
# Make separate commits for logically separate changes
|
1. Make separate commits for logically separate changes
|
||||||
|
|
||||||
# Describe your changes well in the commit message
|
1. Describe your changes well in the commit message
|
||||||
|
|
||||||
The first line of the commit message should be a short description of what has
|
The first line of the commit message should be a short description of what has
|
||||||
changed. It is also good to prefix the first line with "area: " where the "area"
|
changed. It is also good to prefix the first line with "area: " where the "area"
|
||||||
is a filename or identifier for the general area of the code being modified.
|
is a filename or identifier for the general area of the code being modified.
|
||||||
The body should provide a meaningful commit message.
|
The body should provide a meaningful commit message.
|
||||||
|
|
||||||
# Write tests for your code (if possible)
|
1. Write Javadocs
|
||||||
|
|
||||||
# Make sure the Wiki pages don't become stale by updating them (if needed)
|
We require contributors to include Javadocs for all new methods and classes
|
||||||
|
submitted via PRs (after 1 May 2018). This is aimed at making it easier for
|
||||||
|
new contributors to dive into our codebase, especially those who are new to
|
||||||
|
Android development. A few things to note:
|
||||||
|
|
||||||
|
- This should not replace the need for code that is easily-readable in
|
||||||
|
and of itself
|
||||||
|
- Please make sure that your Javadocs are reasonably descriptive, not just
|
||||||
|
a copy of the method name
|
||||||
|
- Please do not use `@author` tags - we aim for collective code ownership,
|
||||||
|
and if needed, Git allows us to see who wrote something without needing
|
||||||
|
to add these tags (`git blame`)
|
||||||
|
|
||||||
|
1. Write tests for your code (if possible)
|
||||||
|
|
||||||
|
1. Make sure the Wiki pages don't become stale by updating them (if needed)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
## Description
|
## Description (required)
|
||||||
|
|
||||||
Fixes #{GitHub issue number}
|
Fixes #{GitHub issue number and title}
|
||||||
|
|
||||||
{Describe the changes made and why they were made.}
|
{Describe the changes made and why they were made.}
|
||||||
|
|
||||||
## Tests performed
|
## Tests performed (required)
|
||||||
|
|
||||||
Tested on {API level & name of device/emulator}, with {build variant, e.g. ProdDebug}.
|
Tested on {API level & name of device/emulator}, with {build variant, e.g. ProdDebug}.
|
||||||
|
|
||||||
{Please test your PR at least once before submitting.}
|
## Screenshots showing what changed (optional)
|
||||||
|
|
||||||
## Screenshots showing what changed
|
|
||||||
|
|
||||||
{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._
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ dependencies {
|
||||||
transitive=true
|
transitive=true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
implementation "com.github.deano2390:MaterialShowcaseView:1.2.0"
|
||||||
|
|
||||||
implementation "com.android.support:support-v4:$SUPPORT_LIB_VERSION"
|
implementation "com.android.support:support-v4:$SUPPORT_LIB_VERSION"
|
||||||
implementation "com.android.support:appcompat-v7:$SUPPORT_LIB_VERSION"
|
implementation "com.android.support:appcompat-v7:$SUPPORT_LIB_VERSION"
|
||||||
implementation "com.android.support:design:$SUPPORT_LIB_VERSION"
|
implementation "com.android.support:design:$SUPPORT_LIB_VERSION"
|
||||||
|
|
@ -49,6 +51,8 @@ dependencies {
|
||||||
implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.0.0'
|
implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.0.0'
|
||||||
implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.0.0'
|
implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.0.0'
|
||||||
|
|
||||||
|
implementation 'org.jsoup:jsoup:1.11.3'
|
||||||
|
|
||||||
implementation 'com.facebook.fresco:fresco:1.5.0'
|
implementation 'com.facebook.fresco:fresco:1.5.0'
|
||||||
implementation 'com.facebook.stetho:stetho:1.5.0'
|
implementation 'com.facebook.stetho:stetho:1.5.0'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,9 @@
|
||||||
android:label="@string/navigation_item_notification" />
|
android:label="@string/navigation_item_notification" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".featured.FeaturedImagesActivity"
|
android:name=".category.CategoryImagesActivity"
|
||||||
android:label="@string/title_activity_featured_images" />
|
android:label="@string/title_activity_featured_images"
|
||||||
|
android:parentActivityName=".contributions.ContributionsActivity" />
|
||||||
|
|
||||||
<service android:name=".upload.UploadService" />
|
<service android:name=".upload.UploadService" />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@ public class MediaDataExtractor {
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
Timber.d("Nominated for deletion: " + mediaWikiApi.pageExists("Commons:Deletion_requests/"+filename));
|
deletionStatus = mediaWikiApi.pageExists("Commons:Deletion_requests/" + filename);
|
||||||
deletionStatus = mediaWikiApi.pageExists("Commons:Deletion_requests/"+filename);
|
Timber.d("Nominated for deletion: " + deletionStatus);
|
||||||
}
|
}
|
||||||
catch (Exception e){
|
catch (Exception e){
|
||||||
Timber.d(e.getMessage());
|
Timber.d(e.getMessage());
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,7 @@ import android.accounts.Account;
|
||||||
import android.accounts.AccountAuthenticatorActivity;
|
import android.accounts.AccountAuthenticatorActivity;
|
||||||
import android.accounts.AccountAuthenticatorResponse;
|
import android.accounts.AccountAuthenticatorResponse;
|
||||||
import android.accounts.AccountManager;
|
import android.accounts.AccountManager;
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
@ -25,7 +23,6 @@ import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
@ -39,16 +36,13 @@ import javax.inject.Named;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import butterknife.OnClick;
|
import butterknife.OnClick;
|
||||||
import fr.free.nrw.commons.AboutActivity;
|
|
||||||
import fr.free.nrw.commons.BuildConfig;
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.CommonsApplication;
|
|
||||||
import fr.free.nrw.commons.PageTitle;
|
import fr.free.nrw.commons.PageTitle;
|
||||||
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.WelcomeActivity;
|
import fr.free.nrw.commons.WelcomeActivity;
|
||||||
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
||||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||||
import fr.free.nrw.commons.featured.FeaturedImagesActivity_MembersInjector;
|
|
||||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
import fr.free.nrw.commons.nearby.NearbyActivity;
|
import fr.free.nrw.commons.nearby.NearbyActivity;
|
||||||
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package fr.free.nrw.commons.category;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.Media;
|
||||||
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class CategoryImageController {
|
||||||
|
|
||||||
|
private MediaWikiApi mediaWikiApi;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CategoryImageController(MediaWikiApi mediaWikiApi) {
|
||||||
|
this.mediaWikiApi = mediaWikiApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a category name as input and calls the API to get a list of images for that category
|
||||||
|
* @param categoryName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Media> getCategoryImages(String categoryName) {
|
||||||
|
return mediaWikiApi.getCategoryImages(categoryName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,225 @@
|
||||||
|
package fr.free.nrw.commons.category;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.Media;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class CategoryImageUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method iterates over the child nodes to return a list of Media objects
|
||||||
|
* @param childNodes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<Media> getMediaList(NodeList childNodes) {
|
||||||
|
List<Media> categoryImages = new ArrayList<>();
|
||||||
|
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||||
|
Node node = childNodes.item(i);
|
||||||
|
categoryImages.add(getMediaFromPage(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
return categoryImages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Media object from the XML response as received by the API
|
||||||
|
* @param node
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static Media getMediaFromPage(Node node) {
|
||||||
|
Media media = new Media(null,
|
||||||
|
getImageUrl(node),
|
||||||
|
getFileName(node),
|
||||||
|
getDescription(node),
|
||||||
|
getDataLength(node),
|
||||||
|
getDateCreated(node),
|
||||||
|
getDateCreated(node),
|
||||||
|
getCreator(node)
|
||||||
|
);
|
||||||
|
|
||||||
|
media.setLicense(getLicense(node));
|
||||||
|
|
||||||
|
return media;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the filename of the uploaded image
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getFileName(Node document) {
|
||||||
|
Element element = (Element) document;
|
||||||
|
return element.getAttribute("title");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the image description for that particular upload
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getDescription(Node document) {
|
||||||
|
return getMetaDataValue(document, "ImageDescription");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts license information from the image meta data
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getLicense(Node document) {
|
||||||
|
return getMetaDataValue(document, "License");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parsed value of artist from the response
|
||||||
|
* The artist information is returned as a HTML string from the API. Jsoup library parses the HTML string
|
||||||
|
* to extract just the text value
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getCreator(Node document) {
|
||||||
|
String artist = getMetaDataValue(document, "Artist");
|
||||||
|
if (artist != null) {
|
||||||
|
return Jsoup.parse(artist).text();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parsed date of creation of the image
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static Date getDateCreated(Node document) {
|
||||||
|
String dateTime = getMetaDataValue(document, "DateTime");
|
||||||
|
if (dateTime != null && !dateTime.equals("")) {
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
try {
|
||||||
|
return format.parse(dateTime);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
Timber.d("Error occurred while parsing date %s", dateTime);
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param document
|
||||||
|
* @return Returns the url attribute from the imageInfo node
|
||||||
|
*/
|
||||||
|
private static String getImageUrl(Node document) {
|
||||||
|
Element element = (Element) getImageInfo(document);
|
||||||
|
if (element != null) {
|
||||||
|
return element.getAttribute("url");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes the node document and gives out the attribute length from the node document
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static long getDataLength(Node document) {
|
||||||
|
Element element = (Element) document;
|
||||||
|
if (element != null) {
|
||||||
|
String length = element.getAttribute("length");
|
||||||
|
if (length != null && !length.equals("")) {
|
||||||
|
return Long.parseLong(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic method to get the value of any meta as returned by the getMetaData function
|
||||||
|
* @param document node document as returned by API
|
||||||
|
* @param metaName the name of meta node to be returned
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getMetaDataValue(Node document, String metaName) {
|
||||||
|
Element metaData = getMetaData(document, metaName);
|
||||||
|
if (metaData != null) {
|
||||||
|
return metaData.getAttribute("value");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic method to return an element taking the node document and metaName as input
|
||||||
|
* @param document node document as returned by API
|
||||||
|
* @param metaName the name of meta node to be returned
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private static Element getMetaData(Node document, String metaName) {
|
||||||
|
Node extraMetaData = getExtraMetaData(document);
|
||||||
|
if (extraMetaData != null) {
|
||||||
|
Node node = getNode(extraMetaData, metaName);
|
||||||
|
if (node != null) {
|
||||||
|
return (Element) node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts extmetadata from the response XML
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private static Node getExtraMetaData(Node document) {
|
||||||
|
Node imageInfo = getImageInfo(document);
|
||||||
|
if (imageInfo != null) {
|
||||||
|
return getNode(imageInfo, "extmetadata");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the ii node from the imageinfo node
|
||||||
|
* @param document
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private static Node getImageInfo(Node document) {
|
||||||
|
Node imageInfo = getNode(document, "imageinfo");
|
||||||
|
if (imageInfo != null) {
|
||||||
|
return getNode(imageInfo, "ii");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a parent node as input and returns a child node if present
|
||||||
|
* @param node parent node
|
||||||
|
* @param nodeName child node name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static Node getNode(Node node, String nodeName) {
|
||||||
|
NodeList childNodes = node.getChildNodes();
|
||||||
|
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||||
|
Node nodeItem = childNodes.item(i);
|
||||||
|
Element item = (Element) nodeItem;
|
||||||
|
if (item.getTagName().equals(nodeName)) {
|
||||||
|
return nodeItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
package fr.free.nrw.commons.category;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.database.DataSetObserver;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.FragmentManager;
|
||||||
|
import android.support.v4.app.FragmentTransaction;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import fr.free.nrw.commons.Media;
|
||||||
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.auth.AuthenticatedActivity;
|
||||||
|
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This activity displays pictures of a particular category
|
||||||
|
* Its generic and simply takes the name of category name in its start intent to load all images in
|
||||||
|
* a particular category. This activity is currently being used to display a list of featured images,
|
||||||
|
* which is nothing but another category on wikimedia commons.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class CategoryImagesActivity
|
||||||
|
extends AuthenticatedActivity
|
||||||
|
implements FragmentManager.OnBackStackChangedListener,
|
||||||
|
MediaDetailPagerFragment.MediaDetailProvider,
|
||||||
|
AdapterView.OnItemClickListener{
|
||||||
|
|
||||||
|
|
||||||
|
private FragmentManager supportFragmentManager;
|
||||||
|
private CategoryImagesListFragment categoryImagesListFragment;
|
||||||
|
private MediaDetailPagerFragment mediaDetails;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAuthCookieAcquired(String authCookie) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAuthFailure() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_category_images);
|
||||||
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
|
// Activity can call methods in the fragment by acquiring a
|
||||||
|
// reference to the Fragment from FragmentManager, using findFragmentById()
|
||||||
|
supportFragmentManager = getSupportFragmentManager();
|
||||||
|
setCategoryImagesFragment();
|
||||||
|
supportFragmentManager.addOnBackStackChangedListener(this);
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
mediaDetails = (MediaDetailPagerFragment) supportFragmentManager
|
||||||
|
.findFragmentById(R.id.fragmentContainer);
|
||||||
|
|
||||||
|
}
|
||||||
|
requestAuthToken();
|
||||||
|
initDrawer();
|
||||||
|
setPageTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the categoryName from the intent and initializes the fragment for showing images of that category
|
||||||
|
*/
|
||||||
|
private void setCategoryImagesFragment() {
|
||||||
|
categoryImagesListFragment = new CategoryImagesListFragment();
|
||||||
|
String categoryName = getIntent().getStringExtra("categoryName");
|
||||||
|
if (getIntent() != null && categoryName != null) {
|
||||||
|
Bundle arguments = new Bundle();
|
||||||
|
arguments.putString("categoryName", categoryName);
|
||||||
|
categoryImagesListFragment.setArguments(arguments);
|
||||||
|
FragmentTransaction transaction = supportFragmentManager.beginTransaction();
|
||||||
|
transaction
|
||||||
|
.add(R.id.fragmentContainer, categoryImagesListFragment)
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the passed title from the intents and displays it as the page title
|
||||||
|
*/
|
||||||
|
private void setPageTitle() {
|
||||||
|
if (getIntent() != null && getIntent().getStringExtra("title") != null) {
|
||||||
|
setTitle(getIntent().getStringExtra("title"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackStackChanged() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||||
|
if (mediaDetails == null || !mediaDetails.isVisible()) {
|
||||||
|
// set isFeaturedImage true for featured images, to include author field on media detail
|
||||||
|
mediaDetails = new MediaDetailPagerFragment(false, true);
|
||||||
|
FragmentManager supportFragmentManager = getSupportFragmentManager();
|
||||||
|
supportFragmentManager
|
||||||
|
.beginTransaction()
|
||||||
|
.replace(R.id.fragmentContainer, mediaDetails)
|
||||||
|
.addToBackStack(null)
|
||||||
|
.commit();
|
||||||
|
supportFragmentManager.executePendingTransactions();
|
||||||
|
}
|
||||||
|
mediaDetails.showImage(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consumers should be simply using this method to use this activity.
|
||||||
|
* @param context
|
||||||
|
* @param title Page title
|
||||||
|
* @param categoryName Name of the category for displaying its images
|
||||||
|
*/
|
||||||
|
public static void startYourself(Context context, String title, String categoryName) {
|
||||||
|
Intent intent = new Intent(context, CategoryImagesActivity.class);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||||
|
intent.putExtra("title", title);
|
||||||
|
intent.putExtra("categoryName", categoryName);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Media getMediaAtPosition(int i) {
|
||||||
|
if (categoryImagesListFragment.getAdapter() == null) {
|
||||||
|
// not yet ready to return data
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return (Media) categoryImagesListFragment.getAdapter().getItem(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTotalMediaCount() {
|
||||||
|
if (categoryImagesListFragment.getAdapter() == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return categoryImagesListFragment.getAdapter().getCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyDatasetChanged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerDataSetObserver(DataSetObserver observer) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterDataSetObserver(DataSetObserver observer) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,227 @@
|
||||||
|
package fr.free.nrw.commons.category;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.AbsListView;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.GridView;
|
||||||
|
import android.widget.ListAdapter;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import dagger.android.support.DaggerFragment;
|
||||||
|
import fr.free.nrw.commons.Media;
|
||||||
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.utils.NetworkUtils;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays images for a particular category with load more on scrolling incorporated
|
||||||
|
*/
|
||||||
|
public class CategoryImagesListFragment extends DaggerFragment {
|
||||||
|
|
||||||
|
private static int TIMEOUT_SECONDS = 15;
|
||||||
|
|
||||||
|
private GridViewAdapter gridAdapter;
|
||||||
|
|
||||||
|
@BindView(R.id.statusMessage)
|
||||||
|
TextView statusTextView;
|
||||||
|
@BindView(R.id.loadingImagesProgressBar) ProgressBar progressBar;
|
||||||
|
@BindView(R.id.categoryImagesList) GridView gridView;
|
||||||
|
|
||||||
|
private boolean hasMoreImages = true;
|
||||||
|
private boolean isLoading;
|
||||||
|
private String categoryName = null;
|
||||||
|
|
||||||
|
@Inject CategoryImageController controller;
|
||||||
|
@Inject @Named("category_prefs") SharedPreferences categoryPreferences;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View v = inflater.inflate(R.layout.fragment_category_images, container, false);
|
||||||
|
ButterKnife.bind(this, v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
gridView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
|
||||||
|
initViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the UI elements for the fragment
|
||||||
|
* Setup the grid view to and scroll listener for it
|
||||||
|
*/
|
||||||
|
private void initViews() {
|
||||||
|
String categoryName = getArguments().getString("categoryName");
|
||||||
|
if (getArguments() != null && categoryName != null) {
|
||||||
|
this.categoryName = categoryName;
|
||||||
|
resetQueryContinueValues(categoryName);
|
||||||
|
initList();
|
||||||
|
setScrollListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query continue values determine the last page that was loaded for the particular keyword
|
||||||
|
* This method resets those values, so that the results can be queried from the first page itself
|
||||||
|
* @param keyword
|
||||||
|
*/
|
||||||
|
private void resetQueryContinueValues(String keyword) {
|
||||||
|
SharedPreferences.Editor editor = categoryPreferences.edit();
|
||||||
|
editor.remove(keyword);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for internet connection and then initializes the grid view with first 10 images of that category
|
||||||
|
*/
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void initList() {
|
||||||
|
if(!NetworkUtils.isInternetConnectionEstablished(getContext())) {
|
||||||
|
handleNoInternet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = true;
|
||||||
|
progressBar.setVisibility(VISIBLE);
|
||||||
|
Observable.fromCallable(() -> controller.getCategoryImages(categoryName))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||||
|
.subscribe(this::handleSuccess, this::handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the UI updates for no internet scenario
|
||||||
|
*/
|
||||||
|
private void handleNoInternet() {
|
||||||
|
progressBar.setVisibility(GONE);
|
||||||
|
if (gridAdapter == null || gridAdapter.isEmpty()) {
|
||||||
|
statusTextView.setVisibility(VISIBLE);
|
||||||
|
statusTextView.setText(getString(R.string.no_internet));
|
||||||
|
} else {
|
||||||
|
ViewUtil.showSnackbar(gridView, R.string.no_internet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs and handles API error scenario
|
||||||
|
* @param throwable
|
||||||
|
*/
|
||||||
|
private void handleError(Throwable throwable) {
|
||||||
|
Timber.e(throwable, "Error occurred while loading featured images");
|
||||||
|
initErrorView();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the UI updates for a error scenario
|
||||||
|
*/
|
||||||
|
private void initErrorView() {
|
||||||
|
ViewUtil.showSnackbar(gridView, R.string.error_loading_images);
|
||||||
|
progressBar.setVisibility(GONE);
|
||||||
|
if (gridAdapter == null || gridAdapter.isEmpty()) {
|
||||||
|
statusTextView.setVisibility(VISIBLE);
|
||||||
|
statusTextView.setText(getString(R.string.no_images_found));
|
||||||
|
} else {
|
||||||
|
statusTextView.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the adapter with a list of Media objects
|
||||||
|
* @param mediaList
|
||||||
|
*/
|
||||||
|
private void setAdapter(List<Media> mediaList) {
|
||||||
|
gridAdapter = new GridViewAdapter(this.getContext(), R.layout.layout_category_images, mediaList);
|
||||||
|
gridView.setAdapter(gridAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the scroll listener for the grid view so that more images are fetched when the user scrolls down
|
||||||
|
* Checks if the category has more images before loading
|
||||||
|
* Also checks whether images are currently being fetched before triggering another request
|
||||||
|
*/
|
||||||
|
private void setScrollListener() {
|
||||||
|
gridView.setOnScrollListener(new AbsListView.OnScrollListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrollStateChanged(AbsListView view, int scrollState) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
|
||||||
|
if (hasMoreImages && !isLoading && (firstVisibleItem + visibleItemCount + 1 >= totalItemCount)) {
|
||||||
|
isLoading = true;
|
||||||
|
fetchMoreImages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches more images for the category and adds it to the grid view adapter
|
||||||
|
*/
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void fetchMoreImages() {
|
||||||
|
if(!NetworkUtils.isInternetConnectionEstablished(getContext())) {
|
||||||
|
handleNoInternet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar.setVisibility(VISIBLE);
|
||||||
|
Observable.fromCallable(() -> controller.getCategoryImages(categoryName))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
|
||||||
|
.subscribe(this::handleSuccess, this::handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the success scenario
|
||||||
|
* On first load, it initializes the grid view. On subsequent loads, it adds items to the adapter
|
||||||
|
* @param collection
|
||||||
|
*/
|
||||||
|
private void handleSuccess(List<Media> collection) {
|
||||||
|
if(collection == null || collection.isEmpty()) {
|
||||||
|
initErrorView();
|
||||||
|
hasMoreImages = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gridAdapter == null) {
|
||||||
|
setAdapter(collection);
|
||||||
|
} else {
|
||||||
|
gridAdapter.addItems(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
progressBar.setVisibility(GONE);
|
||||||
|
isLoading = false;
|
||||||
|
statusTextView.setVisibility(GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListAdapter getAdapter() {
|
||||||
|
return gridView.getAdapter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
package fr.free.nrw.commons.category;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.Media;
|
||||||
|
import fr.free.nrw.commons.MediaWikiImageView;
|
||||||
|
import fr.free.nrw.commons.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is created to only display UI implementation. Needs to be changed in real implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GridViewAdapter extends ArrayAdapter {
|
||||||
|
private Context context;
|
||||||
|
private List<Media> data;
|
||||||
|
|
||||||
|
public GridViewAdapter(Context context, int layoutResourceId, List<Media> data) {
|
||||||
|
super(context, layoutResourceId, data);
|
||||||
|
this.context = context;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds more item to the list
|
||||||
|
* Its triggered on scrolling down in the list
|
||||||
|
* @param images
|
||||||
|
*/
|
||||||
|
public void addItems(List<Media> images) {
|
||||||
|
if (data == null) {
|
||||||
|
data = new ArrayList<>();
|
||||||
|
}
|
||||||
|
data.addAll(images);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return data == null || data.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the UI for the category image item
|
||||||
|
* @param position
|
||||||
|
* @param convertView
|
||||||
|
* @param parent
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
|
|
||||||
|
if (convertView == null) {
|
||||||
|
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
|
||||||
|
convertView = inflater.inflate(R.layout.layout_category_images, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Media item = data.get(position);
|
||||||
|
MediaWikiImageView imageView = convertView.findViewById(R.id.categoryImageView);
|
||||||
|
TextView fileName = convertView.findViewById(R.id.categoryImageTitle);
|
||||||
|
TextView author = convertView.findViewById(R.id.categoryImageAuthor);
|
||||||
|
fileName.setText(item.getFilename());
|
||||||
|
setAuthorView(item, author);
|
||||||
|
imageView.setMedia(item);
|
||||||
|
return convertView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows author information if its present
|
||||||
|
* @param item
|
||||||
|
* @param author
|
||||||
|
*/
|
||||||
|
private void setAuthorView(Media item, TextView author) {
|
||||||
|
if (item.getCreator() != null && !item.getCreator().equals("")) {
|
||||||
|
String uploadedByTemplate = context.getString(R.string.image_uploaded_by);
|
||||||
|
author.setText(String.format(uploadedByTemplate, item.getCreator()));
|
||||||
|
} else {
|
||||||
|
author.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package fr.free.nrw.commons.category;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For APIs that return paginated responses, MediaWiki APIs uses the QueryContinue to facilitate fetching of subsequent pages
|
||||||
|
* https://www.mediawiki.org/wiki/API:Raw_query_continue
|
||||||
|
*/
|
||||||
|
public class QueryContinue {
|
||||||
|
private String continueParam;
|
||||||
|
private String gcmContinueParam;
|
||||||
|
|
||||||
|
public QueryContinue(String continueParam, String gcmContinueParam) {
|
||||||
|
this.continueParam = continueParam;
|
||||||
|
this.gcmContinueParam = gcmContinueParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGcmContinueParam() {
|
||||||
|
return gcmContinueParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContinueParam() {
|
||||||
|
return continueParam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -7,7 +7,7 @@ import fr.free.nrw.commons.WelcomeActivity;
|
||||||
import fr.free.nrw.commons.auth.LoginActivity;
|
import fr.free.nrw.commons.auth.LoginActivity;
|
||||||
import fr.free.nrw.commons.auth.SignupActivity;
|
import fr.free.nrw.commons.auth.SignupActivity;
|
||||||
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
||||||
import fr.free.nrw.commons.featured.FeaturedImagesActivity;
|
import fr.free.nrw.commons.category.CategoryImagesActivity;
|
||||||
import fr.free.nrw.commons.nearby.NearbyActivity;
|
import fr.free.nrw.commons.nearby.NearbyActivity;
|
||||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||||
import fr.free.nrw.commons.settings.SettingsActivity;
|
import fr.free.nrw.commons.settings.SettingsActivity;
|
||||||
|
|
@ -49,5 +49,5 @@ public abstract class ActivityBuilderModule {
|
||||||
abstract NotificationActivity bindNotificationActivity();
|
abstract NotificationActivity bindNotificationActivity();
|
||||||
|
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract FeaturedImagesActivity bindFeaturedImagesActivity();
|
abstract CategoryImagesActivity bindFeaturedImagesActivity();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ 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;
|
||||||
|
|
||||||
|
|
@ -85,6 +87,17 @@ public class CommonsApplicationModule {
|
||||||
return context.getSharedPreferences("prefs", MODE_PRIVATE);
|
return context.getSharedPreferences("prefs", MODE_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param context
|
||||||
|
* @return returns categoryPrefs
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@Named("category_prefs")
|
||||||
|
public SharedPreferences providesCategorySharedPreferences(Context context) {
|
||||||
|
return context.getSharedPreferences("categoryPrefs", MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Named("direct_nearby_upload_prefs")
|
@Named("direct_nearby_upload_prefs")
|
||||||
public SharedPreferences providesDirectNearbyUploadPreferences(Context context) {
|
public SharedPreferences providesDirectNearbyUploadPreferences(Context context) {
|
||||||
|
|
@ -106,8 +119,11 @@ public class CommonsApplicationModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public MediaWikiApi provideMediaWikiApi(Context context, @Named("default_preferences") SharedPreferences sharedPreferences) {
|
public MediaWikiApi provideMediaWikiApi(Context context,
|
||||||
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, sharedPreferences);
|
@Named("default_preferences") SharedPreferences defaultPreferences,
|
||||||
|
@Named("category_prefs") SharedPreferences categoryPrefs,
|
||||||
|
Gson gson) {
|
||||||
|
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST, defaultPreferences, categoryPrefs, gson);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
@ -116,6 +132,16 @@ public class CommonsApplicationModule {
|
||||||
return new LocationServiceManager(context);
|
return new LocationServiceManager(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gson objects are very heavy. The app should ideally be using just one instance of it instead of creating new instances everywhere.
|
||||||
|
* @return returns a singleton Gson instance
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public Gson provideGson() {
|
||||||
|
return new Gson();
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public CacheController provideCacheController() {
|
public CacheController provideCacheController() {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import dagger.Module;
|
||||||
import dagger.android.ContributesAndroidInjector;
|
import dagger.android.ContributesAndroidInjector;
|
||||||
import fr.free.nrw.commons.category.CategorizationFragment;
|
import fr.free.nrw.commons.category.CategorizationFragment;
|
||||||
import fr.free.nrw.commons.contributions.ContributionsListFragment;
|
import fr.free.nrw.commons.contributions.ContributionsListFragment;
|
||||||
import fr.free.nrw.commons.featured.FeaturedImagesListFragment;
|
import fr.free.nrw.commons.category.CategoryImagesListFragment;
|
||||||
import fr.free.nrw.commons.media.MediaDetailFragment;
|
import fr.free.nrw.commons.media.MediaDetailFragment;
|
||||||
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
||||||
import fr.free.nrw.commons.nearby.NearbyListFragment;
|
import fr.free.nrw.commons.nearby.NearbyListFragment;
|
||||||
|
|
@ -49,6 +49,6 @@ public abstract class FragmentBuilderModule {
|
||||||
abstract SingleUploadFragment bindSingleUploadFragment();
|
abstract SingleUploadFragment bindSingleUploadFragment();
|
||||||
|
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract FeaturedImagesListFragment bindFeaturedImagesListFragment();
|
abstract CategoryImagesListFragment bindFeaturedImagesListFragment();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
package fr.free.nrw.commons.featured;
|
|
||||||
|
|
||||||
|
|
||||||
import fr.free.nrw.commons.Media;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Object to hold FeaturedImage
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class FeaturedImage {
|
|
||||||
private Media image;
|
|
||||||
private String author;
|
|
||||||
private String fileName;
|
|
||||||
|
|
||||||
public FeaturedImage(Media image, String author, String fileName) {
|
|
||||||
this.image = image;
|
|
||||||
this.author = author;
|
|
||||||
this.fileName = fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Media getImage() {
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setImage(Media image) {
|
|
||||||
this.image = image;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAuthor() {
|
|
||||||
return author;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAuthor(String author) {
|
|
||||||
this.author = author;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFileName() {
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFileName(String fileName) {
|
|
||||||
this.fileName = fileName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,114 +0,0 @@
|
||||||
package fr.free.nrw.commons.featured;
|
|
||||||
|
|
||||||
import android.database.DataSetObserver;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v4.app.FragmentManager;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import fr.free.nrw.commons.Media;
|
|
||||||
import fr.free.nrw.commons.R;
|
|
||||||
import fr.free.nrw.commons.auth.AuthenticatedActivity;
|
|
||||||
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This activity displays pic of the days of last xx days
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class FeaturedImagesActivity
|
|
||||||
extends AuthenticatedActivity
|
|
||||||
implements FragmentManager.OnBackStackChangedListener,
|
|
||||||
MediaDetailPagerFragment.MediaDetailProvider,
|
|
||||||
AdapterView.OnItemClickListener{
|
|
||||||
|
|
||||||
private FeaturedImagesListFragment featuredImagesListFragment;
|
|
||||||
private MediaDetailPagerFragment mediaDetails;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onAuthCookieAcquired(String authCookie) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onAuthFailure() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_featured_images);
|
|
||||||
ButterKnife.bind(this);
|
|
||||||
|
|
||||||
// Activity can call methods in the fragment by acquiring a
|
|
||||||
// reference to the Fragment from FragmentManager, using findFragmentById()
|
|
||||||
FragmentManager supportFragmentManager = getSupportFragmentManager();
|
|
||||||
featuredImagesListFragment = (FeaturedImagesListFragment)supportFragmentManager
|
|
||||||
.findFragmentById(R.id.featuedListFragment);
|
|
||||||
|
|
||||||
supportFragmentManager.addOnBackStackChangedListener(this);
|
|
||||||
if (savedInstanceState != null) {
|
|
||||||
mediaDetails = (MediaDetailPagerFragment)supportFragmentManager
|
|
||||||
.findFragmentById(R.id.featuredFragmentContainer);
|
|
||||||
|
|
||||||
}
|
|
||||||
requestAuthToken();
|
|
||||||
initDrawer();
|
|
||||||
setTitle(getString(R.string.title_activity_featured_images));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackStackChanged() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
|
||||||
if (mediaDetails == null || !mediaDetails.isVisible()) {
|
|
||||||
// set isFeaturedImage true for featured images, to include author field on media detail
|
|
||||||
mediaDetails = new MediaDetailPagerFragment(false, true);
|
|
||||||
FragmentManager supportFragmentManager = getSupportFragmentManager();
|
|
||||||
supportFragmentManager
|
|
||||||
.beginTransaction()
|
|
||||||
.replace(R.id.featuredFragmentContainer, mediaDetails)
|
|
||||||
.addToBackStack(null)
|
|
||||||
.commit();
|
|
||||||
supportFragmentManager.executePendingTransactions();
|
|
||||||
}
|
|
||||||
mediaDetails.showImage(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Media getMediaAtPosition(int i) {
|
|
||||||
if (featuredImagesListFragment.getAdapter() == null) {
|
|
||||||
// not yet ready to return data
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return ((FeaturedImage)featuredImagesListFragment.getAdapter().getItem(i)).getImage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getTotalMediaCount() {
|
|
||||||
if (featuredImagesListFragment.getAdapter() == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return featuredImagesListFragment.getAdapter().getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyDatasetChanged() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void registerDataSetObserver(DataSetObserver observer) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unregisterDataSetObserver(DataSetObserver observer) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
package fr.free.nrw.commons.featured;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.GridView;
|
|
||||||
import android.widget.ListAdapter;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import dagger.android.support.DaggerFragment;
|
|
||||||
import fr.free.nrw.commons.Media;
|
|
||||||
import fr.free.nrw.commons.R;
|
|
||||||
|
|
||||||
public class FeaturedImagesListFragment extends DaggerFragment {
|
|
||||||
private GridView gridView;
|
|
||||||
private MockGridViewAdapter gridAdapter;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
|
||||||
View v = inflater.inflate(R.layout.fragment_featured_images, container, false);
|
|
||||||
ButterKnife.bind(this, v);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
|
||||||
super.onViewCreated(view, savedInstanceState);
|
|
||||||
|
|
||||||
gridView = getView().findViewById(R.id.featuredImagesList);
|
|
||||||
gridView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity());
|
|
||||||
gridAdapter = new MockGridViewAdapter(this.getContext(), R.layout.layout_featured_images, getMockFeaturedImages());
|
|
||||||
gridView.setAdapter(gridAdapter);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private ArrayList<FeaturedImage> getMockFeaturedImages(){
|
|
||||||
ArrayList<FeaturedImage> featuredImages = new ArrayList<>();
|
|
||||||
for (int i=0; i<10; i++){
|
|
||||||
featuredImages.add(new FeaturedImage(new Media("test.jpg"), "username: test", "test file name"));
|
|
||||||
}
|
|
||||||
return featuredImages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ListAdapter getAdapter() {
|
|
||||||
return gridView.getAdapter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
package fr.free.nrw.commons.featured;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import fr.free.nrw.commons.MediaWikiImageView;
|
|
||||||
import fr.free.nrw.commons.R;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is created to only display UI implementation. Needs to be changed in real implementation
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class MockGridViewAdapter extends ArrayAdapter {
|
|
||||||
private Context context;
|
|
||||||
private int layoutResourceId;
|
|
||||||
private ArrayList<FeaturedImage> data = new ArrayList();
|
|
||||||
|
|
||||||
public MockGridViewAdapter(Context context, int layoutResourceId, ArrayList<FeaturedImage> data) {
|
|
||||||
super(context, layoutResourceId, data);
|
|
||||||
this.layoutResourceId = layoutResourceId;
|
|
||||||
this.context = context;
|
|
||||||
this.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
|
||||||
|
|
||||||
if (convertView == null) {
|
|
||||||
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
|
|
||||||
convertView = inflater.inflate(R.layout.layout_featured_images, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
FeaturedImage item = data.get(position);
|
|
||||||
MediaWikiImageView imageView = convertView.findViewById(R.id.featuredImageView);
|
|
||||||
TextView fileName = convertView.findViewById(R.id.featuredImageTitle);
|
|
||||||
TextView author = convertView.findViewById(R.id.featuredImageAuthor);
|
|
||||||
fileName.setText("Test file name");
|
|
||||||
author.setText("Uploaded by: Test user name");
|
|
||||||
imageView.setMedia(item.getImage());
|
|
||||||
return convertView;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -9,6 +9,7 @@ import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
|
@ -22,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;
|
||||||
|
|
@ -45,6 +49,8 @@ import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
import fr.free.nrw.commons.ui.widget.CompatTextView;
|
import fr.free.nrw.commons.ui.widget.CompatTextView;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.VISIBLE;
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
|
|
||||||
public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
|
|
@ -74,23 +80,37 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
@Inject
|
@Inject
|
||||||
MediaWikiApi mwApi;
|
MediaWikiApi mwApi;
|
||||||
|
|
||||||
|
|
||||||
private MediaWikiImageView image;
|
|
||||||
private MediaDetailSpacer spacer;
|
|
||||||
private int initialListTop = 0;
|
private int initialListTop = 0;
|
||||||
|
|
||||||
private TextView title;
|
@BindView(R.id.mediaDetailImage)
|
||||||
private TextView desc;
|
MediaWikiImageView image;
|
||||||
private TextView author;
|
@BindView(R.id.mediaDetailSpacer)
|
||||||
private TextView license;
|
MediaDetailSpacer spacer;
|
||||||
private TextView coordinates;
|
@BindView(R.id.mediaDetailTitle)
|
||||||
private TextView uploadedDate;
|
TextView title;
|
||||||
private TextView seeMore;
|
@BindView(R.id.mediaDetailDesc)
|
||||||
private LinearLayout nominatedforDeletion;
|
TextView desc;
|
||||||
private LinearLayout categoryContainer;
|
@BindView(R.id.mediaDetailAuthor)
|
||||||
private LinearLayout authorLayout;
|
TextView author;
|
||||||
private Button delete;
|
@BindView(R.id.mediaDetailLicense)
|
||||||
private ScrollView scrollView;
|
TextView license;
|
||||||
|
@BindView(R.id.mediaDetailCoordinates)
|
||||||
|
TextView coordinates;
|
||||||
|
@BindView(R.id.mediaDetailuploadeddate)
|
||||||
|
TextView uploadedDate;
|
||||||
|
@BindView(R.id.seeMore)
|
||||||
|
TextView seeMore;
|
||||||
|
@BindView(R.id.nominatedDeletionBanner)
|
||||||
|
LinearLayout nominatedForDeletion;
|
||||||
|
@BindView(R.id.mediaDetailCategoryContainer)
|
||||||
|
LinearLayout categoryContainer;
|
||||||
|
@BindView(R.id.authorLinearLayout)
|
||||||
|
LinearLayout authorLayout;
|
||||||
|
@BindView(R.id.nominateDeletion)
|
||||||
|
Button delete;
|
||||||
|
@BindView(R.id.mediaDetailScrollView)
|
||||||
|
ScrollView scrollView;
|
||||||
|
|
||||||
private ArrayList<String> categoryNames;
|
private ArrayList<String> categoryNames;
|
||||||
private boolean categoriesLoaded = false;
|
private boolean categoriesLoaded = false;
|
||||||
private boolean categoriesPresent = false;
|
private boolean categoriesPresent = false;
|
||||||
|
|
@ -100,6 +120,9 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
private AsyncTask<Void, Void, Boolean> detailFetchTask;
|
private AsyncTask<Void, Void, Boolean> detailFetchTask;
|
||||||
private LicenseList licenseList;
|
private LicenseList licenseList;
|
||||||
|
|
||||||
|
//Had to make this class variable, to implement various onClicks, which access the media, also I fell why make separate variables when one can serve the purpose
|
||||||
|
private Media media;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
|
@ -136,27 +159,12 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
|
|
||||||
final View view = inflater.inflate(R.layout.fragment_media_detail, container, false);
|
final View view = inflater.inflate(R.layout.fragment_media_detail, container, false);
|
||||||
|
|
||||||
image = (MediaWikiImageView) view.findViewById(R.id.mediaDetailImage);
|
ButterKnife.bind(this,view);
|
||||||
scrollView = (ScrollView) view.findViewById(R.id.mediaDetailScrollView);
|
|
||||||
|
|
||||||
// Detail consists of a list view with main pane in header view, plus category list.
|
|
||||||
spacer = (MediaDetailSpacer) view.findViewById(R.id.mediaDetailSpacer);
|
|
||||||
title = (TextView) view.findViewById(R.id.mediaDetailTitle);
|
|
||||||
desc = (TextView) view.findViewById(R.id.mediaDetailDesc);
|
|
||||||
author = (TextView) view.findViewById(R.id.mediaDetailAuthor);
|
|
||||||
license = (TextView) view.findViewById(R.id.mediaDetailLicense);
|
|
||||||
coordinates = (TextView) view.findViewById(R.id.mediaDetailCoordinates);
|
|
||||||
uploadedDate = (TextView) view.findViewById(R.id.mediaDetailuploadeddate);
|
|
||||||
seeMore = (TextView) view.findViewById(R.id.seeMore);
|
|
||||||
nominatedforDeletion = (LinearLayout) view.findViewById(R.id.nominatedDeletionBanner);
|
|
||||||
delete = (Button) view.findViewById(R.id.nominateDeletion);
|
|
||||||
categoryContainer = (LinearLayout) view.findViewById(R.id.mediaDetailCategoryContainer);
|
|
||||||
authorLayout = (LinearLayout) view.findViewById(R.id.authorLinearLayout);
|
|
||||||
|
|
||||||
if (isFeaturedMedia){
|
if (isFeaturedMedia){
|
||||||
authorLayout.setVisibility(View.VISIBLE);
|
authorLayout.setVisibility(VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
authorLayout.setVisibility(View.GONE);
|
authorLayout.setVisibility(GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
licenseList = new LicenseList(getActivity());
|
licenseList = new LicenseList(getActivity());
|
||||||
|
|
@ -195,7 +203,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
Media media = detailProvider.getMediaAtPosition(index);
|
media = detailProvider.getMediaAtPosition(index);
|
||||||
if (media == null) {
|
if (media == null) {
|
||||||
// Ask the detail provider to ping us when we're ready
|
// Ask the detail provider to ping us when we're ready
|
||||||
Timber.d("MediaDetailFragment not yet ready to display details; registering observer");
|
Timber.d("MediaDetailFragment not yet ready to display details; registering observer");
|
||||||
|
|
@ -208,17 +216,18 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
Timber.d("MediaDetailFragment ready to display delayed details!");
|
Timber.d("MediaDetailFragment ready to display delayed details!");
|
||||||
detailProvider.unregisterDataSetObserver(dataObserver);
|
detailProvider.unregisterDataSetObserver(dataObserver);
|
||||||
dataObserver = null;
|
dataObserver = null;
|
||||||
displayMediaDetails(detailProvider.getMediaAtPosition(index));
|
media=detailProvider.getMediaAtPosition(index);
|
||||||
|
displayMediaDetails();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
detailProvider.registerDataSetObserver(dataObserver);
|
detailProvider.registerDataSetObserver(dataObserver);
|
||||||
} else {
|
} else {
|
||||||
Timber.d("MediaDetailFragment ready to display details");
|
Timber.d("MediaDetailFragment ready to display details");
|
||||||
displayMediaDetails(media);
|
displayMediaDetails();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayMediaDetails(final Media media) {
|
private void displayMediaDetails() {
|
||||||
//Always load image from Internet to allow viewing the desc, license, and cats
|
//Always load image from Internet to allow viewing the desc, license, and cats
|
||||||
image.setMedia(media);
|
image.setMedia(media);
|
||||||
|
|
||||||
|
|
@ -255,7 +264,6 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
if (success) {
|
if (success) {
|
||||||
extractor.fill(media);
|
extractor.fill(media);
|
||||||
setTextFields(media);
|
setTextFields(media);
|
||||||
setOnClickListeners(media);
|
|
||||||
} else {
|
} else {
|
||||||
Timber.d("Failed to load photo details.");
|
Timber.d("Failed to load photo details.");
|
||||||
}
|
}
|
||||||
|
|
@ -306,24 +314,41 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
}
|
}
|
||||||
rebuildCatList();
|
rebuildCatList();
|
||||||
|
|
||||||
|
if(media.getCreator() == null || media.getCreator().equals("")) {
|
||||||
|
authorLayout.setVisibility(GONE);
|
||||||
|
} else {
|
||||||
|
author.setText(media.getCreator());
|
||||||
|
}
|
||||||
|
|
||||||
checkDeletion(media);
|
checkDeletion(media);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setOnClickListeners(final Media media) {
|
@OnClick(R.id.mediaDetailLicense)
|
||||||
if (licenseLink(media) != null) {
|
public void onMediaDetailLicenceClicked(){
|
||||||
license.setOnClickListener(v -> openWebBrowser(licenseLink(media)));
|
if (!TextUtils.isEmpty(licenseLink(media))) {
|
||||||
|
openWebBrowser(licenseLink(media));
|
||||||
|
} else {
|
||||||
|
if(isFeaturedMedia) {
|
||||||
|
Timber.d("Unable to fetch license URL for %s", media.getLicense());
|
||||||
} else {
|
} else {
|
||||||
Toast toast = Toast.makeText(getContext(), getString(R.string.null_url), Toast.LENGTH_SHORT);
|
Toast toast = Toast.makeText(getContext(), getString(R.string.null_url), Toast.LENGTH_SHORT);
|
||||||
toast.show();
|
toast.show();
|
||||||
}
|
}
|
||||||
if (media.getCoordinates() != null) {
|
|
||||||
coordinates.setOnClickListener(v -> openMap(media.getCoordinates()));
|
|
||||||
}
|
}
|
||||||
if (delete.getVisibility() == View.VISIBLE) {
|
}
|
||||||
enableDeleteButton(true);
|
|
||||||
|
|
||||||
delete.setOnClickListener(v -> {
|
@OnClick(R.id.mediaDetailCoordinates)
|
||||||
|
public void onMediaDetailCoordinatesClicked(){
|
||||||
|
if (media.getCoordinates() != null) {
|
||||||
|
openMap(media.getCoordinates());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.nominateDeletion)
|
||||||
|
public void onDeleteButtonClicked(){
|
||||||
|
//Reviewer correct me if i have misunderstood something over here
|
||||||
|
//But how does this if (delete.getVisibility() == View.VISIBLE) {
|
||||||
|
// enableDeleteButton(true); makes sense ?
|
||||||
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
|
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
|
||||||
alert.setMessage("Why should this file be deleted?");
|
alert.setMessage("Why should this file be deleted?");
|
||||||
final EditText input = new EditText(getActivity());
|
final EditText input = new EditText(getActivity());
|
||||||
|
|
@ -367,12 +392,12 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
});
|
});
|
||||||
d.show();
|
d.show();
|
||||||
d.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
|
d.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (nominatedforDeletion.getVisibility() == View.VISIBLE){
|
|
||||||
seeMore.setOnClickListener(v -> {
|
@OnClick(R.id.seeMore)
|
||||||
|
public void onSeeMoreClicked(){
|
||||||
|
if(nominatedForDeletion.getVisibility()== VISIBLE) {
|
||||||
openWebBrowser(media.getFilePageTitle().getMobileUri().toString());
|
openWebBrowser(media.getFilePageTitle().getMobileUri().toString());
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -476,12 +501,12 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
|
||||||
|
|
||||||
private void checkDeletion(Media media){
|
private void checkDeletion(Media media){
|
||||||
if (media.getRequestedDeletion()){
|
if (media.getRequestedDeletion()){
|
||||||
delete.setVisibility(View.GONE);
|
delete.setVisibility(GONE);
|
||||||
nominatedforDeletion.setVisibility(View.VISIBLE);
|
nominatedForDeletion.setVisibility(VISIBLE);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
delete.setVisibility(View.VISIBLE);
|
delete.setVisibility(VISIBLE);
|
||||||
nominatedforDeletion.setVisibility(View.GONE);
|
nominatedForDeletion.setVisibility(GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
|
@ -53,7 +55,8 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
@Named("default_preferences")
|
@Named("default_preferences")
|
||||||
SharedPreferences prefs;
|
SharedPreferences prefs;
|
||||||
|
|
||||||
private ViewPager pager;
|
@BindView(R.id.mediaDetailsPager)
|
||||||
|
ViewPager pager;
|
||||||
private Boolean editable;
|
private Boolean editable;
|
||||||
private boolean isFeaturedImage;
|
private boolean isFeaturedImage;
|
||||||
|
|
||||||
|
|
@ -72,7 +75,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple
|
||||||
ViewGroup container,
|
ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_media_detail_pager, container, false);
|
View view = inflater.inflate(R.layout.fragment_media_detail_pager, container, false);
|
||||||
pager = (ViewPager) view.findViewById(R.id.mediaDetailsPager);
|
ButterKnife.bind(this,view);
|
||||||
pager.addOnPageChangeListener(this);
|
pager.addOnPageChangeListener(this);
|
||||||
|
|
||||||
final MediaDetailAdapter adapter = new MediaDetailAdapter(getChildFragmentManager());
|
final MediaDetailAdapter adapter = new MediaDetailAdapter(getChildFragmentManager());
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ import android.support.annotation.VisibleForTesting;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.conn.ClientConnectionManager;
|
import org.apache.http.conn.ClientConnectionManager;
|
||||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
import org.apache.http.conn.scheme.PlainSocketFactory;
|
||||||
|
|
@ -38,7 +40,10 @@ import java.util.Locale;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import fr.free.nrw.commons.BuildConfig;
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
|
import fr.free.nrw.commons.Media;
|
||||||
import fr.free.nrw.commons.PageTitle;
|
import fr.free.nrw.commons.PageTitle;
|
||||||
|
import fr.free.nrw.commons.category.CategoryImageUtils;
|
||||||
|
import fr.free.nrw.commons.category.QueryContinue;
|
||||||
import fr.free.nrw.commons.notification.Notification;
|
import fr.free.nrw.commons.notification.Notification;
|
||||||
import fr.free.nrw.commons.notification.NotificationUtils;
|
import fr.free.nrw.commons.notification.NotificationUtils;
|
||||||
import in.yuvi.http.fluent.Http;
|
import in.yuvi.http.fluent.Http;
|
||||||
|
|
@ -46,6 +51,8 @@ import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
import static fr.free.nrw.commons.utils.ContinueUtils.getQueryContinue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Addshore
|
* @author Addshore
|
||||||
*/
|
*/
|
||||||
|
|
@ -56,9 +63,15 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
private AbstractHttpClient httpClient;
|
private AbstractHttpClient httpClient;
|
||||||
private MWApi api;
|
private MWApi api;
|
||||||
private Context context;
|
private Context context;
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences defaultPreferences;
|
||||||
|
private SharedPreferences categoryPreferences;
|
||||||
|
private Gson gson;
|
||||||
|
|
||||||
public ApacheHttpClientMediaWikiApi(Context context, String apiURL, SharedPreferences sharedPreferences) {
|
public ApacheHttpClientMediaWikiApi(Context context,
|
||||||
|
String apiURL,
|
||||||
|
SharedPreferences defaultPreferences,
|
||||||
|
SharedPreferences categoryPreferences,
|
||||||
|
Gson gson) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
BasicHttpParams params = new BasicHttpParams();
|
BasicHttpParams params = new BasicHttpParams();
|
||||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||||
|
|
@ -69,7 +82,9 @@ 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);
|
||||||
this.sharedPreferences = sharedPreferences;
|
this.defaultPreferences = defaultPreferences;
|
||||||
|
this.categoryPreferences = categoryPreferences;
|
||||||
|
this.gson = gson;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -160,7 +175,7 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAuthCookieOnLogin(boolean isLoggedIn) {
|
private void setAuthCookieOnLogin(boolean isLoggedIn) {
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
SharedPreferences.Editor editor = defaultPreferences.edit();
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn) {
|
||||||
editor.putBoolean("isUserLoggedIn", true);
|
editor.putBoolean("isUserLoggedIn", true);
|
||||||
editor.putString("getAuthCookie", api.getAuthCookie());
|
editor.putString("getAuthCookie", api.getAuthCookie());
|
||||||
|
|
@ -448,6 +463,81 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
return NotificationUtils.getNotificationsFromList(context, childNodes);
|
return NotificationUtils.getNotificationsFromList(context, childNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method takes categoryName as input and returns a List of Media objects
|
||||||
|
* It uses the generator query API to get the images in a category, 10 at a time.
|
||||||
|
* Uses the query continue values for fetching paginated responses
|
||||||
|
* @param categoryName Category name as defined on commons
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public List<Media> getCategoryImages(String categoryName) {
|
||||||
|
ApiResult apiResult = null;
|
||||||
|
try {
|
||||||
|
MWApi.RequestBuilder requestBuilder = api.action("query")
|
||||||
|
.param("generator", "categorymembers")
|
||||||
|
.param("format", "xml")
|
||||||
|
.param("gcmtype", "file")
|
||||||
|
.param("gcmtitle", categoryName)
|
||||||
|
.param("prop", "imageinfo")
|
||||||
|
.param("gcmlimit", "10")
|
||||||
|
.param("iiprop", "url|extmetadata");
|
||||||
|
|
||||||
|
QueryContinue queryContinueValues = getQueryContinueValues(categoryName);
|
||||||
|
if (queryContinueValues != null) {
|
||||||
|
requestBuilder.param("continue", queryContinueValues.getContinueParam());
|
||||||
|
requestBuilder.param("gcmcontinue", queryContinueValues.getGcmContinueParam());
|
||||||
|
}
|
||||||
|
|
||||||
|
apiResult = requestBuilder.get();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Timber.e("Failed to obtain searchCategories", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apiResult == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiResult categoryImagesNode = apiResult.getNode("/api/query/pages");
|
||||||
|
if (categoryImagesNode == null
|
||||||
|
|| categoryImagesNode.getDocument() == null
|
||||||
|
|| categoryImagesNode.getDocument().getChildNodes() == null
|
||||||
|
|| categoryImagesNode.getDocument().getChildNodes().getLength() == 0) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryContinue queryContinue = getQueryContinue(apiResult.getNode("/api/continue").getDocument());
|
||||||
|
setQueryContinueValues(categoryName, queryContinue);
|
||||||
|
|
||||||
|
NodeList childNodes = categoryImagesNode.getDocument().getChildNodes();
|
||||||
|
return CategoryImageUtils.getMediaList(childNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For APIs that return paginated responses, MediaWiki APIs uses the QueryContinue to facilitate fetching of subsequent pages
|
||||||
|
* https://www.mediawiki.org/wiki/API:Raw_query_continue
|
||||||
|
* After fetching images a page of image for a particular category, shared prefs are updated with the latest QueryContinue Values
|
||||||
|
* @param keyword
|
||||||
|
* @param queryContinue
|
||||||
|
*/
|
||||||
|
private void setQueryContinueValues(String keyword, QueryContinue queryContinue) {
|
||||||
|
SharedPreferences.Editor editor = categoryPreferences.edit();
|
||||||
|
editor.putString(keyword, gson.toJson(queryContinue));
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Before making a paginated API call, this method is called to get the latest query continue values to be used
|
||||||
|
* @param keyword
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private QueryContinue getQueryContinueValues(String keyword) {
|
||||||
|
String queryContinueString = categoryPreferences.getString(keyword, null);
|
||||||
|
return gson.fromJson(queryContinueString, QueryContinue.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean existingFile(String fileSha1) throws IOException {
|
public boolean existingFile(String fileSha1) throws IOException {
|
||||||
return api.action("query")
|
return api.action("query")
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.Media;
|
||||||
import fr.free.nrw.commons.notification.Notification;
|
import fr.free.nrw.commons.notification.Notification;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
@ -34,6 +35,8 @@ public interface MediaWikiApi {
|
||||||
|
|
||||||
boolean logEvents(LogBuilder[] logBuilders);
|
boolean logEvents(LogBuilder[] logBuilders);
|
||||||
|
|
||||||
|
List<Media> getCategoryImages(String categoryName);
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
UploadResult uploadFile(String filename, InputStream file, long dataLength, String pageContents, String editSummary, ProgressListener progressListener) throws IOException;
|
UploadResult uploadFile(String filename, InputStream file, long dataLength, String pageContents, String editSummary, ProgressListener progressListener) throws IOException;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,18 @@ import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.design.widget.BottomSheetBehavior;
|
import android.support.design.widget.BottomSheetBehavior;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
|
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
@ -25,10 +29,13 @@ import com.google.gson.GsonBuilder;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.R;
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.auth.LoginActivity;
|
||||||
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.LocationUpdateListener;
|
import fr.free.nrw.commons.location.LocationUpdateListener;
|
||||||
|
|
@ -41,6 +48,8 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
import uk.co.deanwild.materialshowcaseview.IShowcaseListener;
|
||||||
|
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView;
|
||||||
|
|
||||||
|
|
||||||
public class NearbyActivity extends NavigationBaseActivity implements LocationUpdateListener {
|
public class NearbyActivity extends NavigationBaseActivity implements LocationUpdateListener {
|
||||||
|
|
@ -56,12 +65,15 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
LinearLayout bottomSheetDetails;
|
LinearLayout bottomSheetDetails;
|
||||||
@BindView(R.id.transparentView)
|
@BindView(R.id.transparentView)
|
||||||
View transparentView;
|
View transparentView;
|
||||||
|
@BindView(R.id.fab_recenter)
|
||||||
|
View fabRecenter;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
LocationServiceManager locationManager;
|
LocationServiceManager locationManager;
|
||||||
@Inject
|
@Inject
|
||||||
NearbyController nearbyController;
|
NearbyController nearbyController;
|
||||||
|
@Inject
|
||||||
|
@Named("application_preferences") SharedPreferences applicationPrefs;
|
||||||
private LatLng curLatLng;
|
private LatLng curLatLng;
|
||||||
private Bundle bundle;
|
private Bundle bundle;
|
||||||
private Disposable placesDisposable;
|
private Disposable placesDisposable;
|
||||||
|
|
@ -72,11 +84,18 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
private NearbyListFragment nearbyListFragment;
|
private NearbyListFragment nearbyListFragment;
|
||||||
private static final String TAG_RETAINED_MAP_FRAGMENT = NearbyMapFragment.class.getSimpleName();
|
private static final String TAG_RETAINED_MAP_FRAGMENT = NearbyMapFragment.class.getSimpleName();
|
||||||
private static final String TAG_RETAINED_LIST_FRAGMENT = NearbyListFragment.class.getSimpleName();
|
private static final String TAG_RETAINED_LIST_FRAGMENT = NearbyListFragment.class.getSimpleName();
|
||||||
|
private View listButton; // Reference to list button to use in tutorial
|
||||||
|
|
||||||
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
|
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
|
||||||
private BroadcastReceiver broadcastReceiver;
|
private BroadcastReceiver broadcastReceiver;
|
||||||
|
|
||||||
|
private boolean isListShowcaseAdded = false;
|
||||||
|
private boolean isMapShowCaseAdded = false;
|
||||||
|
|
||||||
private LatLng lastKnownLocation;
|
private LatLng lastKnownLocation;
|
||||||
|
|
||||||
|
private MaterialShowcaseView secondSingleShowCaseView;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
@ -126,6 +145,39 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
MenuInflater inflater = getMenuInflater();
|
MenuInflater inflater = getMenuInflater();
|
||||||
inflater.inflate(R.menu.menu_nearby, menu);
|
inflater.inflate(R.menu.menu_nearby, menu);
|
||||||
|
|
||||||
|
new Handler().post(() -> {
|
||||||
|
|
||||||
|
listButton = findViewById(R.id.action_display_list);
|
||||||
|
|
||||||
|
secondSingleShowCaseView = new MaterialShowcaseView.Builder(this)
|
||||||
|
.setTarget(listButton)
|
||||||
|
.setDismissText(getString(R.string.showcase_view_got_it_button))
|
||||||
|
.setContentText(getString(R.string.showcase_view_list_icon))
|
||||||
|
.setDelay(500) // optional but starting animations immediately in onCreate can make them choppy
|
||||||
|
.singleUse(ViewUtil.SHOWCASE_VIEW_ID_1) // provide a unique ID used to ensure it is only shown once
|
||||||
|
.setDismissStyle(Typeface.defaultFromStyle(Typeface.BOLD))
|
||||||
|
.setListener(new IShowcaseListener() {
|
||||||
|
@Override
|
||||||
|
public void onShowcaseDisplayed(MaterialShowcaseView materialShowcaseView) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dismissed, we can inform fragment to start showcase sequence there
|
||||||
|
@Override
|
||||||
|
public void onShowcaseDismissed(MaterialShowcaseView materialShowcaseView) {
|
||||||
|
nearbyMapFragment.onNearbyMaterialShowcaseDismissed();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
isListShowcaseAdded = true;
|
||||||
|
|
||||||
|
if (isMapShowCaseAdded) { // If map showcase is also ready, start ShowcaseSequence
|
||||||
|
// Probably this case is not possible. Just added to be careful
|
||||||
|
setMapViewTutorialShowCase();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return super.onCreateOptionsMenu(menu);
|
return super.onCreateOptionsMenu(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -420,6 +472,45 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
updateMapFragment(false);
|
updateMapFragment(false);
|
||||||
updateListFragment();
|
updateListFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMapShowCaseAdded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapViewTutorialShowCase() {
|
||||||
|
/*
|
||||||
|
*This showcase view will be the first step of our nearbyMaterialShowcaseSequence. The reason we use a
|
||||||
|
* single item instead of adding another step to nearbyMaterialShowcaseSequence is that we are not able to
|
||||||
|
* call withoutShape() method on steps. For mapView we need an showcase view without
|
||||||
|
* any circle on it, it should cover the whole page.
|
||||||
|
* */
|
||||||
|
MaterialShowcaseView firstSingleShowCaseView = new MaterialShowcaseView.Builder(this)
|
||||||
|
.setTarget(nearbyMapFragment.mapView)
|
||||||
|
.setDismissText(getString(R.string.showcase_view_got_it_button))
|
||||||
|
.setContentText(getString(R.string.showcase_view_whole_nearby_activity))
|
||||||
|
.setDelay(500) // optional but starting animations immediately in onCreate can make them choppy
|
||||||
|
.singleUse(ViewUtil.SHOWCASE_VIEW_ID_2) // provide a unique ID used to ensure it is only shown once
|
||||||
|
.withoutShape() // no shape on map view since there are no view to focus on
|
||||||
|
.setDismissStyle(Typeface.defaultFromStyle(Typeface.BOLD))
|
||||||
|
.setListener(new IShowcaseListener() {
|
||||||
|
@Override
|
||||||
|
public void onShowcaseDisplayed(MaterialShowcaseView materialShowcaseView) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onShowcaseDismissed(MaterialShowcaseView materialShowcaseView) {
|
||||||
|
/* Add other nearbyMaterialShowcaseSequence here, it will make the user feel as they are a
|
||||||
|
* nearbyMaterialShowcaseSequence whole together.
|
||||||
|
* */
|
||||||
|
secondSingleShowCaseView.show(NearbyActivity.this);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
if (applicationPrefs.getBoolean("firstRunNearby", true)) {
|
||||||
|
applicationPrefs.edit().putBoolean("firstRunNearby", false).apply();
|
||||||
|
firstSingleShowCaseView.show(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lockNearbyView(boolean lock) {
|
private void lockNearbyView(boolean lock) {
|
||||||
|
|
@ -557,4 +648,5 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
|
||||||
public void prepareViewsForSheetPosition(int bottomSheetState) {
|
public void prepareViewsForSheetPosition(int bottomSheetState) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -33,6 +37,7 @@ import static android.app.Activity.RESULT_OK;
|
||||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
|
||||||
public class NearbyListFragment extends DaggerFragment {
|
public class NearbyListFragment extends DaggerFragment {
|
||||||
|
|
||||||
private Bundle bundleForUpdates; // Carry information from activity about changed nearby places and current location
|
private Bundle bundleForUpdates; // Carry information from activity about changed nearby places and current location
|
||||||
|
|
||||||
private static final Type LIST_TYPE = new TypeToken<List<Place>>() {
|
private static final Type LIST_TYPE = new TypeToken<List<Place>>() {
|
||||||
|
|
@ -129,7 +134,6 @@ public class NearbyListFragment extends DaggerFragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
super.onActivityResult(requestCode, resultCode, data);
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
@ -14,6 +15,7 @@ import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.BottomSheetBehavior;
|
import android.support.design.widget.BottomSheetBehavior;
|
||||||
import android.support.design.widget.CoordinatorLayout;
|
import android.support.design.widget.CoordinatorLayout;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
|
@ -52,19 +54,27 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
|
||||||
import dagger.android.support.DaggerFragment;
|
import dagger.android.support.DaggerFragment;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
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.auth.LoginActivity;
|
||||||
|
import fr.free.nrw.commons.category.CategoryImagesActivity;
|
||||||
import fr.free.nrw.commons.contributions.ContributionController;
|
import fr.free.nrw.commons.contributions.ContributionController;
|
||||||
|
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||||
import fr.free.nrw.commons.utils.UriDeserializer;
|
import fr.free.nrw.commons.utils.UriDeserializer;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView;
|
||||||
|
|
||||||
import static android.app.Activity.RESULT_OK;
|
import static android.app.Activity.RESULT_OK;
|
||||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||||
|
import static fr.free.nrw.commons.theme.NavigationBaseActivity.startActivityWithFlags;
|
||||||
|
|
||||||
public class NearbyMapFragment extends DaggerFragment {
|
public class NearbyMapFragment extends DaggerFragment {
|
||||||
|
|
||||||
private MapView mapView;
|
@Inject
|
||||||
|
@Named("application_preferences") SharedPreferences applicationPrefs;
|
||||||
|
public MapView mapView;
|
||||||
private List<NearbyBaseMarker> baseMarkerOptions;
|
private List<NearbyBaseMarker> baseMarkerOptions;
|
||||||
private fr.free.nrw.commons.location.LatLng curLatLng;
|
private fr.free.nrw.commons.location.LatLng curLatLng;
|
||||||
public fr.free.nrw.commons.location.LatLng[] boundaryCoordinates;
|
public fr.free.nrw.commons.location.LatLng[] boundaryCoordinates;
|
||||||
|
|
@ -111,6 +121,10 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.06;
|
private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.06;
|
||||||
private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.04;
|
private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.04;
|
||||||
|
|
||||||
|
private boolean isSecondMaterialShowcaseDismissed;
|
||||||
|
private boolean isMapReady;
|
||||||
|
private MaterialShowcaseView thirdSingleShowCaseView;
|
||||||
|
|
||||||
private Bundle bundleForUpdtes;// Carry information from activity about changed nearby places and current location
|
private Bundle bundleForUpdtes;// Carry information from activity about changed nearby places and current location
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
|
@ -163,7 +177,6 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
Timber.d("onCreateView called");
|
Timber.d("onCreateView called");
|
||||||
if (curLatLng != null) {
|
if (curLatLng != null) {
|
||||||
Timber.d("curLatLng found, setting up map view...");
|
Timber.d("curLatLng found, setting up map view...");
|
||||||
|
|
@ -366,7 +379,26 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setListeners() {
|
private void setListeners() {
|
||||||
fabPlus.setOnClickListener(view -> animateFAB(isFabOpen));
|
fabPlus.setOnClickListener(view -> {
|
||||||
|
if (applicationPrefs.getBoolean("login_skipped", true)) {
|
||||||
|
// prompt the user to login
|
||||||
|
new AlertDialog.Builder(getContext())
|
||||||
|
.setMessage(R.string.login_alert_message)
|
||||||
|
.setPositiveButton(R.string.login, (dialog, which) -> {
|
||||||
|
// logout of the app
|
||||||
|
// startActivityWithFlags( getContext(), CategoryImagesActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
|
||||||
|
// Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
|
// getActivity().finish();
|
||||||
|
BaseLogoutListener logoutListener = new BaseLogoutListener();
|
||||||
|
CommonsApplication app = (CommonsApplication) getActivity().getApplication();
|
||||||
|
app.clearApplicationData(getContext(), logoutListener);
|
||||||
|
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}else {
|
||||||
|
animateFAB(isFabOpen);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
bottomSheetDetails.setOnClickListener(view -> {
|
bottomSheetDetails.setOnClickListener(view -> {
|
||||||
if (bottomSheetDetailsBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
|
if (bottomSheetDetailsBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
|
||||||
|
|
@ -476,6 +508,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
mapView.getMapAsync(new OnMapReadyCallback() {
|
mapView.getMapAsync(new OnMapReadyCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onMapReady(MapboxMap mapboxMap) {
|
public void onMapReady(MapboxMap mapboxMap) {
|
||||||
|
((NearbyActivity)getActivity()).setMapViewTutorialShowCase();
|
||||||
NearbyMapFragment.this.mapboxMap = mapboxMap;
|
NearbyMapFragment.this.mapboxMap = mapboxMap;
|
||||||
updateMapSignificantly();
|
updateMapSignificantly();
|
||||||
}
|
}
|
||||||
|
|
@ -483,6 +516,18 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
mapView.setStyleUrl("asset://mapstyle.json");
|
mapView.setStyleUrl("asset://mapstyle.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class BaseLogoutListener implements CommonsApplication.LogoutListener {
|
||||||
|
@Override
|
||||||
|
public void onLogoutComplete() {
|
||||||
|
Timber.d("Logout complete callback received.");
|
||||||
|
Intent nearbyIntent = new Intent( getActivity(), LoginActivity.class);
|
||||||
|
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
startActivity(nearbyIntent);
|
||||||
|
getActivity().finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a marker for the user's current position. Adds a
|
* Adds a marker for the user's current position. Adds a
|
||||||
* circle which uses the accuracy * 2, to draw a circle
|
* circle which uses the accuracy * 2, to draw a circle
|
||||||
|
|
@ -519,6 +564,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
private void addNearbyMarkerstoMapBoxMap() {
|
private void addNearbyMarkerstoMapBoxMap() {
|
||||||
|
|
||||||
mapboxMap.addMarkers(baseMarkerOptions);
|
mapboxMap.addMarkers(baseMarkerOptions);
|
||||||
|
|
||||||
mapboxMap.setOnInfoWindowCloseListener(marker -> {
|
mapboxMap.setOnInfoWindowCloseListener(marker -> {
|
||||||
if (marker == selected) {
|
if (marker == selected) {
|
||||||
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||||
|
|
@ -534,6 +580,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
});
|
});
|
||||||
|
|
||||||
mapboxMap.setOnMarkerClickListener(marker -> {
|
mapboxMap.setOnMarkerClickListener(marker -> {
|
||||||
|
|
||||||
if (marker instanceof NearbyMarker) {
|
if (marker instanceof NearbyMarker) {
|
||||||
this.selected = marker;
|
this.selected = marker;
|
||||||
NearbyMarker nearbyMarker = (NearbyMarker) marker;
|
NearbyMarker nearbyMarker = (NearbyMarker) marker;
|
||||||
|
|
@ -541,6 +588,7 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
passInfoToSheet(place);
|
passInfoToSheet(place);
|
||||||
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
bottomSheetListBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
|
||||||
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
bottomSheetDetailsBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
@ -634,7 +682,19 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
addAnchorToSmallFABs(fabGallery, getActivity().findViewById(R.id.empty_view).getId());
|
addAnchorToSmallFABs(fabGallery, getActivity().findViewById(R.id.empty_view).getId());
|
||||||
|
|
||||||
addAnchorToSmallFABs(fabCamera, getActivity().findViewById(R.id.empty_view1).getId());
|
addAnchorToSmallFABs(fabCamera, getActivity().findViewById(R.id.empty_view1).getId());
|
||||||
|
thirdSingleShowCaseView = new MaterialShowcaseView.Builder(this.getActivity())
|
||||||
|
.setTarget(fabPlus)
|
||||||
|
.setDismissText(getString(R.string.showcase_view_got_it_button))
|
||||||
|
.setContentText(getString(R.string.showcase_view_plus_fab))
|
||||||
|
.setDelay(500) // optional but starting animations immediately in onCreate can make them choppy
|
||||||
|
.singleUse(ViewUtil.SHOWCASE_VIEW_ID_3) // provide a unique ID used to ensure it is only shown once
|
||||||
|
.setDismissStyle(Typeface.defaultFromStyle(Typeface.BOLD))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
isMapReady = true;
|
||||||
|
if (isSecondMaterialShowcaseDismissed) {
|
||||||
|
thirdSingleShowCaseView.show(getActivity());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -791,6 +851,13 @@ public class NearbyMapFragment extends DaggerFragment {
|
||||||
this.bundleForUpdtes = bundleForUpdtes;
|
this.bundleForUpdtes = bundleForUpdtes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onNearbyMaterialShowcaseDismissed() {
|
||||||
|
isSecondMaterialShowcaseDismissed = true;
|
||||||
|
if (isMapReady) {
|
||||||
|
thirdSingleShowCaseView.show(getActivity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package fr.free.nrw.commons.nearby;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
import uk.co.deanwild.materialshowcaseview.MaterialShowcaseSequence;
|
||||||
|
import uk.co.deanwild.materialshowcaseview.ShowcaseConfig;
|
||||||
|
|
||||||
|
|
||||||
|
public class NearbyMaterialShowcaseSequence extends MaterialShowcaseSequence {
|
||||||
|
|
||||||
|
public NearbyMaterialShowcaseSequence(Activity activity, String sequenceID) {
|
||||||
|
super(activity, sequenceID);
|
||||||
|
ShowcaseConfig config = new ShowcaseConfig();
|
||||||
|
config.setDelay(500); // half second between each showcase view
|
||||||
|
this.setConfig(config);
|
||||||
|
this.singleUse(sequenceID); // Display tutorial only once
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import android.net.Uri;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.transition.TransitionManager;
|
import android.support.transition.TransitionManager;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.support.v7.widget.PopupMenu;
|
import android.support.v7.widget.PopupMenu;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
|
@ -28,12 +29,17 @@ import butterknife.ButterKnife;
|
||||||
import fr.free.nrw.commons.CommonsApplication;
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
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.auth.LoginActivity;
|
||||||
import fr.free.nrw.commons.contributions.ContributionController;
|
import fr.free.nrw.commons.contributions.ContributionController;
|
||||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
import static fr.free.nrw.commons.theme.NavigationBaseActivity.startActivityWithFlags;
|
||||||
|
|
||||||
public class PlaceRenderer extends Renderer<Place> {
|
public class PlaceRenderer extends Renderer<Place> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Named("application_preferences") SharedPreferences applicationPrefs;
|
||||||
@BindView(R.id.tvName) TextView tvName;
|
@BindView(R.id.tvName) TextView tvName;
|
||||||
@BindView(R.id.tvDesc) TextView tvDesc;
|
@BindView(R.id.tvDesc) TextView tvDesc;
|
||||||
@BindView(R.id.distance) TextView distance;
|
@BindView(R.id.distance) TextView distance;
|
||||||
|
|
@ -89,9 +95,9 @@ public class PlaceRenderer extends Renderer<Place> {
|
||||||
Log.d("Renderer", "clicked");
|
Log.d("Renderer", "clicked");
|
||||||
TransitionManager.beginDelayedTransition(buttonLayout);
|
TransitionManager.beginDelayedTransition(buttonLayout);
|
||||||
|
|
||||||
if(buttonLayout.isShown()){
|
if (buttonLayout.isShown()) {
|
||||||
closeLayout(buttonLayout);
|
closeLayout(buttonLayout);
|
||||||
}else {
|
} else {
|
||||||
openLayout(buttonLayout);
|
openLayout(buttonLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,18 +113,46 @@ public class PlaceRenderer extends Renderer<Place> {
|
||||||
});
|
});
|
||||||
|
|
||||||
cameraButton.setOnClickListener(view2 -> {
|
cameraButton.setOnClickListener(view2 -> {
|
||||||
|
if (applicationPrefs.getBoolean("login_skipped", true)) {
|
||||||
|
// prompt the user to login
|
||||||
|
new AlertDialog.Builder(getContext())
|
||||||
|
.setMessage(R.string.login_alert_message)
|
||||||
|
.setPositiveButton(R.string.login, (dialog, which) -> {
|
||||||
|
startActivityWithFlags( getContext(), LoginActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
|
||||||
|
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
|
prefs.edit().putBoolean("login_skipped", false).apply();
|
||||||
|
fragment.getActivity().finish();
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
|
Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
|
||||||
DirectUpload directUpload = new DirectUpload(fragment, controller);
|
DirectUpload directUpload = new DirectUpload(fragment, controller);
|
||||||
storeSharedPrefs();
|
storeSharedPrefs();
|
||||||
directUpload.initiateCameraUpload();
|
directUpload.initiateCameraUpload();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
galleryButton.setOnClickListener(view3 -> {
|
galleryButton.setOnClickListener(view3 -> {
|
||||||
|
if (applicationPrefs.getBoolean("login_skipped", true)) {
|
||||||
|
// prompt the user to login
|
||||||
|
new AlertDialog.Builder(getContext())
|
||||||
|
.setMessage(R.string.login_alert_message)
|
||||||
|
.setPositiveButton(R.string.login, (dialog, which) -> {
|
||||||
|
startActivityWithFlags( getContext(), LoginActivity.class, Intent.FLAG_ACTIVITY_CLEAR_TOP,
|
||||||
|
Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||||
|
prefs.edit().putBoolean("login_skipped", false).apply();
|
||||||
|
fragment.getActivity().finish();
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
}else {
|
||||||
Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
|
Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
|
||||||
DirectUpload directUpload = new DirectUpload(fragment, controller);
|
DirectUpload directUpload = new DirectUpload(fragment, controller);
|
||||||
storeSharedPrefs();
|
storeSharedPrefs();
|
||||||
directUpload.initiateGalleryUpload();
|
directUpload.initiateGalleryUpload();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeSharedPrefs() {
|
private void storeSharedPrefs() {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import fr.free.nrw.commons.WelcomeActivity;
|
||||||
import fr.free.nrw.commons.auth.AccountUtil;
|
import fr.free.nrw.commons.auth.AccountUtil;
|
||||||
import fr.free.nrw.commons.auth.LoginActivity;
|
import fr.free.nrw.commons.auth.LoginActivity;
|
||||||
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
||||||
import fr.free.nrw.commons.featured.FeaturedImagesActivity;
|
import fr.free.nrw.commons.category.CategoryImagesActivity;
|
||||||
import fr.free.nrw.commons.nearby.NearbyActivity;
|
import fr.free.nrw.commons.nearby.NearbyActivity;
|
||||||
import fr.free.nrw.commons.notification.NotificationActivity;
|
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||||
import fr.free.nrw.commons.settings.SettingsActivity;
|
import fr.free.nrw.commons.settings.SettingsActivity;
|
||||||
|
|
@ -41,6 +41,8 @@ import timber.log.Timber;
|
||||||
public abstract class NavigationBaseActivity extends BaseActivity
|
public abstract class NavigationBaseActivity extends BaseActivity
|
||||||
implements NavigationView.OnNavigationItemSelectedListener {
|
implements NavigationView.OnNavigationItemSelectedListener {
|
||||||
|
|
||||||
|
private static final String FEATURED_IMAGES_CATEGORY = "Category:Featured_pictures_on_Wikimedia_Commons";
|
||||||
|
|
||||||
@BindView(R.id.toolbar)
|
@BindView(R.id.toolbar)
|
||||||
Toolbar toolbar;
|
Toolbar toolbar;
|
||||||
@BindView(R.id.navigation_view)
|
@BindView(R.id.navigation_view)
|
||||||
|
|
@ -173,8 +175,8 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(R.string.yes, (dialog, which) -> {
|
.setPositiveButton(R.string.yes, (dialog, which) -> {
|
||||||
BaseLogoutListener logoutListener = new BaseLogoutListener();
|
BaseLogoutListener logoutListener = new BaseLogoutListener();
|
||||||
CommonsApplication app = (CommonsApplication) getApplication();
|
// CommonsApplication app = (CommonsApplication) getApplication();
|
||||||
app.clearApplicationData(this, logoutListener);
|
// app.clearApplicationData(this, logoutListener);
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel())
|
.setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel())
|
||||||
.show();
|
.show();
|
||||||
|
|
@ -185,7 +187,7 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_featured_images:
|
case R.id.action_featured_images:
|
||||||
drawerLayout.closeDrawer(navigationView);
|
drawerLayout.closeDrawer(navigationView);
|
||||||
startActivityWithFlags(this, FeaturedImagesActivity.class, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
CategoryImagesActivity.startYourself(this, getString(R.string.title_activity_featured_images), FEATURED_IMAGES_CATEGORY);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
Timber.e("Unknown option [%s] selected from the navigation menu", itemId);
|
Timber.e("Unknown option [%s] selected from the navigation menu", itemId);
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,7 @@ import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
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;
|
||||||
import static java.lang.Long.min;
|
import static java.lang.Long.min;
|
||||||
|
|
@ -122,6 +121,7 @@ public class ShareActivity
|
||||||
private Uri mediaUri;
|
private Uri mediaUri;
|
||||||
private Contribution contribution;
|
private Contribution contribution;
|
||||||
private SimpleDraweeView backgroundImageView;
|
private SimpleDraweeView backgroundImageView;
|
||||||
|
private FloatingActionButton maps_fragment;
|
||||||
|
|
||||||
private boolean cacheFound;
|
private boolean cacheFound;
|
||||||
|
|
||||||
|
|
@ -145,6 +145,8 @@ public class ShareActivity
|
||||||
private long ShortAnimationDuration;
|
private long ShortAnimationDuration;
|
||||||
private FloatingActionButton zoomInButton;
|
private FloatingActionButton zoomInButton;
|
||||||
private FloatingActionButton zoomOutButton;
|
private FloatingActionButton zoomOutButton;
|
||||||
|
private FloatingActionButton mainFab;
|
||||||
|
private boolean isFABOpen = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -284,6 +286,24 @@ public class ShareActivity
|
||||||
if (mediaUri != null) {
|
if (mediaUri != null) {
|
||||||
backgroundImageView.setImageURI(mediaUri);
|
backgroundImageView.setImageURI(mediaUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainFab = (FloatingActionButton) findViewById(R.id.main_fab);
|
||||||
|
/*
|
||||||
|
* called when upper arrow floating button
|
||||||
|
*/
|
||||||
|
mainFab.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if(!isFABOpen){
|
||||||
|
showFABMenu();
|
||||||
|
}else{
|
||||||
|
closeFABMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
zoomInButton = (FloatingActionButton) findViewById(R.id.media_upload_zoom_in);
|
zoomInButton = (FloatingActionButton) findViewById(R.id.media_upload_zoom_in);
|
||||||
try {
|
try {
|
||||||
zoomInButton.setOnClickListener(new View.OnClickListener() {
|
zoomInButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
|
@ -358,8 +378,75 @@ public class ShareActivity
|
||||||
.commitAllowingStateLoss();
|
.commitAllowingStateLoss();
|
||||||
}
|
}
|
||||||
uploadController.prepareService();
|
uploadController.prepareService();
|
||||||
|
maps_fragment = (FloatingActionButton) findViewById(R.id.media_map);
|
||||||
|
maps_fragment.setVisibility(View.VISIBLE);
|
||||||
|
if( imageObj == null || imageObj.imageCoordsExists != true){
|
||||||
|
maps_fragment.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
maps_fragment.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if( imageObj != null && imageObj.imageCoordsExists == true) {
|
||||||
|
Uri gmmIntentUri = Uri.parse("google.streetview:cbll=" + imageObj.getDecLatitude() + "," + imageObj.getDecLongitude());
|
||||||
|
Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
|
||||||
|
mapIntent.setPackage("com.google.android.apps.maps");
|
||||||
|
startActivity(mapIntent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Function to display the zoom and map FAB
|
||||||
|
*/
|
||||||
|
private void showFABMenu(){
|
||||||
|
isFABOpen=true;
|
||||||
|
|
||||||
|
if( imageObj != null && imageObj.imageCoordsExists == true)
|
||||||
|
maps_fragment.setVisibility(View.VISIBLE);
|
||||||
|
zoomInButton.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
mainFab.animate().rotationBy(180);
|
||||||
|
maps_fragment.animate().translationY(-getResources().getDimension(R.dimen.second_fab));
|
||||||
|
zoomInButton.animate().translationY(-getResources().getDimension(R.dimen.first_fab));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* function to close the zoom and map FAB
|
||||||
|
*/
|
||||||
|
private void closeFABMenu(){
|
||||||
|
isFABOpen=false;
|
||||||
|
mainFab.animate().rotationBy(-180);
|
||||||
|
maps_fragment.animate().translationY(0);
|
||||||
|
zoomInButton.animate().translationY(0).setListener(new Animator.AnimatorListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animator) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animator) {
|
||||||
|
if(!isFABOpen){
|
||||||
|
maps_fragment.setVisibility(View.GONE);
|
||||||
|
zoomInButton.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationCancel(Animator animator) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationRepeat(Animator animator) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode,
|
public void onRequestPermissionsResult(int requestCode,
|
||||||
@NonNull String[] permissions, @NonNull int[] grantResults) {
|
@NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
|
@ -461,6 +548,9 @@ public class ShareActivity
|
||||||
detectUnwantedPicturesAsync.execute();
|
detectUnwantedPicturesAsync.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* to display permission snackbar in share activity
|
||||||
|
*/
|
||||||
private Snackbar requestPermissionUsingSnackBar(String rationale,
|
private Snackbar requestPermissionUsingSnackBar(String rationale,
|
||||||
final String[] perms,
|
final String[] perms,
|
||||||
final int code) {
|
final int code) {
|
||||||
|
|
@ -693,7 +783,9 @@ public class ShareActivity
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get SHA1 of file from input stream
|
/*
|
||||||
|
* Get SHA1 of file from input stream
|
||||||
|
*/
|
||||||
private String getSHA1(InputStream is) {
|
private String getSHA1(InputStream is) {
|
||||||
|
|
||||||
MessageDigest digest;
|
MessageDigest digest;
|
||||||
|
|
@ -730,6 +822,9 @@ public class ShareActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* function to provide pinch zoom
|
||||||
|
*/
|
||||||
private void zoomImageFromThumb(final View thumbView, Uri imageuri ) {
|
private void zoomImageFromThumb(final View thumbView, Uri imageuri ) {
|
||||||
// If there's an animation in progress, cancel it
|
// If there's an animation in progress, cancel it
|
||||||
// immediately and proceed with this one.
|
// immediately and proceed with this one.
|
||||||
|
|
@ -737,6 +832,8 @@ public class ShareActivity
|
||||||
CurrentAnimator.cancel();
|
CurrentAnimator.cancel();
|
||||||
}
|
}
|
||||||
ViewUtil.hideKeyboard(ShareActivity.this.findViewById(R.id.titleEdit | R.id.descEdit));
|
ViewUtil.hideKeyboard(ShareActivity.this.findViewById(R.id.titleEdit | R.id.descEdit));
|
||||||
|
closeFABMenu();
|
||||||
|
mainFab.setVisibility(View.GONE);
|
||||||
InputStream input = null;
|
InputStream input = null;
|
||||||
Bitmap scaled = null;
|
Bitmap scaled = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -866,7 +963,7 @@ public class ShareActivity
|
||||||
CurrentAnimator.cancel();
|
CurrentAnimator.cancel();
|
||||||
}
|
}
|
||||||
zoomOutButton.setVisibility(View.GONE);
|
zoomOutButton.setVisibility(View.GONE);
|
||||||
zoomInButton.setVisibility(View.VISIBLE);
|
mainFab.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
// Animate the four positioning/sizing properties in parallel,
|
// Animate the four positioning/sizing properties in parallel,
|
||||||
// back to their original values.
|
// back to their original values.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package fr.free.nrw.commons.utils;
|
||||||
|
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.category.QueryContinue;
|
||||||
|
|
||||||
|
public class ContinueUtils {
|
||||||
|
|
||||||
|
public static QueryContinue getQueryContinue(Node document) {
|
||||||
|
Element continueElement = (Element) document;
|
||||||
|
return new QueryContinue(continueElement.getAttribute("continue"),
|
||||||
|
continueElement.getAttribute("gcmcontinue"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,10 @@ import android.widget.Toast;
|
||||||
|
|
||||||
public class ViewUtil {
|
public class ViewUtil {
|
||||||
|
|
||||||
|
public static final String SHOWCASE_VIEW_ID_1 = "SHOWCASE_VIEW_ID_1";
|
||||||
|
public static final String SHOWCASE_VIEW_ID_2 = "SHOWCASE_VIEW_ID_2";
|
||||||
|
public static final String SHOWCASE_VIEW_ID_3 = "SHOWCASE_VIEW_ID_3";
|
||||||
|
|
||||||
public static void showSnackbar(View view, int messageResourceId) {
|
public static void showSnackbar(View view, int messageResourceId) {
|
||||||
Snackbar.make(view, messageResourceId, Snackbar.LENGTH_SHORT).show();
|
Snackbar.make(view, messageResourceId, Snackbar.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M7.41,15.41L12,10.83l4.59,4.58L18,14l-6,-6 -6,6z"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/drawer_layout"
|
android:id="@+id/drawer_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -16,20 +15,12 @@
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/featuredFragmentContainer"
|
android:id="@+id/fragmentContainer"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_below="@id/toolbar">
|
android:layout_below="@id/toolbar">
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/featuedListFragment"
|
|
||||||
android:name="fr.free.nrw.commons.featured.FeaturedImagesListFragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:layout="@layout/fragment_contributions" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
@ -41,8 +41,6 @@
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
<android.support.design.widget.FloatingActionButton
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -50,8 +48,21 @@
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_marginRight="@dimen/standard_gap"
|
android:layout_marginRight="@dimen/standard_gap"
|
||||||
android:layout_marginBottom="@dimen/standard_gap"
|
android:layout_marginBottom="@dimen/standard_gap"
|
||||||
|
app:backgroundTint="@color/button_blue"
|
||||||
|
app:srcCompat="@drawable/ic_keyboard_arrow_up_black_24dp"
|
||||||
|
android:id="@+id/main_fab"/>
|
||||||
|
|
||||||
|
|
||||||
|
<android.support.design.widget.FloatingActionButton
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginRight="@dimen/standard_gap"
|
||||||
android:src="@drawable/ic_zoom_in_white_24dp"
|
android:src="@drawable/ic_zoom_in_white_24dp"
|
||||||
|
android:layout_above="@+id/main_fab"
|
||||||
android:id="@+id/media_upload_zoom_in"/>
|
android:id="@+id/media_upload_zoom_in"/>
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
<android.support.design.widget.FloatingActionButton
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -61,7 +72,19 @@
|
||||||
android:layout_marginRight="@dimen/standard_gap"
|
android:layout_marginRight="@dimen/standard_gap"
|
||||||
android:layout_marginBottom="@dimen/standard_gap"
|
android:layout_marginBottom="@dimen/standard_gap"
|
||||||
android:src="@drawable/ic_zoom_out_white_24dp"
|
android:src="@drawable/ic_zoom_out_white_24dp"
|
||||||
|
android:layout_above="@+id/main_fab"
|
||||||
android:id="@+id/media_upload_zoom_out"/>
|
android:id="@+id/media_upload_zoom_out"/>
|
||||||
|
|
||||||
|
<android.support.design.widget.FloatingActionButton
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_above="@+id/media_upload_zoom_in"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginRight="@dimen/standard_gap"
|
||||||
|
app:srcCompat="@drawable/ic_map_white_24dp"
|
||||||
|
android:id="@+id/media_map"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<android.support.design.widget.NavigationView
|
<android.support.design.widget.NavigationView
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,21 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/mainBackground"
|
android:background="?attr/mainBackground">
|
||||||
>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/waiting_first_sync"
|
android:text="@string/waiting_first_sync"
|
||||||
android:id="@+id/waitingMessage"
|
android:id="@+id/statusMessage"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
|
|
@ -22,11 +23,11 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:id="@+id/loadingFeaturedImagesProgressBar"
|
android:id="@+id/loadingImagesProgressBar"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<GridView
|
<GridView
|
||||||
android:id="@+id/featuredImagesList"
|
android:id="@+id/categoryImagesList"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:stretchMode="columnWidth"
|
android:stretchMode="columnWidth"
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
>
|
>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/featuredImagesSequenceNumber"
|
android:id="@+id/categoryImagesSequenceNumber"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="98sp"
|
android:textSize="98sp"
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<fr.free.nrw.commons.MediaWikiImageView
|
<fr.free.nrw.commons.MediaWikiImageView
|
||||||
android:id="@+id/featuredImageView"
|
android:id="@+id/categoryImageView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="240dp"
|
android:layout_height="240dp"
|
||||||
/>
|
/>
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
android:padding="@dimen/small_gap"
|
android:padding="@dimen/small_gap"
|
||||||
>
|
>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/featuredProgress"
|
android:id="@+id/categoryProgress"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/ProgressBar"
|
style="@style/ProgressBar"
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/featuredImageTitle"
|
android:id="@+id/categoryImageTitle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="#FFFFFFFF"
|
android:textColor="#FFFFFFFF"
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/featuredImageAuthor"
|
android:id="@+id/categoryImageAuthor"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="#FFFFFFFF"
|
android:textColor="#FFFFFFFF"
|
||||||
|
|
@ -269,4 +269,5 @@
|
||||||
<string name="about_translate_proceed">Fortfahren</string>
|
<string name="about_translate_proceed">Fortfahren</string>
|
||||||
<string name="about_translate_cancel">Abbrechen</string>
|
<string name="about_translate_cancel">Abbrechen</string>
|
||||||
<string name="retry">Erneut versuchen</string>
|
<string name="retry">Erneut versuchen</string>
|
||||||
|
<string name="share_app_title">App teilen</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -273,4 +273,5 @@
|
||||||
<string name="about_translate_proceed">Συνέχεια</string>
|
<string name="about_translate_proceed">Συνέχεια</string>
|
||||||
<string name="about_translate_cancel">Ακύρωση</string>
|
<string name="about_translate_cancel">Ακύρωση</string>
|
||||||
<string name="retry">Ξαναπροσπαθήστε</string>
|
<string name="retry">Ξαναπροσπαθήστε</string>
|
||||||
|
<string name="share_app_title">Κοινοποίηση εφαρμογής</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -279,4 +279,5 @@
|
||||||
<string name="about_translate_proceed">Continuer</string>
|
<string name="about_translate_proceed">Continuer</string>
|
||||||
<string name="about_translate_cancel">Annuler</string>
|
<string name="about_translate_cancel">Annuler</string>
|
||||||
<string name="retry">Réessayer</string>
|
<string name="retry">Réessayer</string>
|
||||||
|
<string name="share_app_title">Partager les applications</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* ViDam
|
* ViDam
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
|
<string name="preference_category_appearance">Megjelenés</string>
|
||||||
<string name="preference_category_general">Általános</string>
|
<string name="preference_category_general">Általános</string>
|
||||||
<string name="preference_category_feedback">Visszajelzés</string>
|
<string name="preference_category_feedback">Visszajelzés</string>
|
||||||
<string name="preference_category_location">Helyszín</string>
|
<string name="preference_category_location">Helyszín</string>
|
||||||
|
|
@ -145,6 +146,7 @@
|
||||||
<string name="tutorial_2_subtext_3">Híres emberek (a polgármestered, olimpikonok, akikkel találkoztál)</string>
|
<string name="tutorial_2_subtext_3">Híres emberek (a polgármestered, olimpikonok, akikkel találkoztál)</string>
|
||||||
<string name="tutorial_3_text">Kérjük, NE tölts fel:</string>
|
<string name="tutorial_3_text">Kérjük, NE tölts fel:</string>
|
||||||
<string name="tutorial_3_subtext">- Szelfiket vagy képeket a barátaidról\n- Internetröl letöltött képeket\n- Kereskedelmi alkalmazások képernyőképeit</string>
|
<string name="tutorial_3_subtext">- Szelfiket vagy képeket a barátaidról\n- Internetröl letöltött képeket\n- Kereskedelmi alkalmazások képernyőképeit</string>
|
||||||
|
<string name="tutorial_3_subtext_2">Az Internetről letöltött képek</string>
|
||||||
<string name="tutorial_4_text">Példa feltöltés:</string>
|
<string name="tutorial_4_text">Példa feltöltés:</string>
|
||||||
<string name="tutorial_4_subtext">- Cím: Sydney-i Operaház\n- Leírás: A Sydney-i Operaház az öböl túlpartjáról\n- Kategóriák: Sydney Opera House from the west, Sydney Opera House remote views</string>
|
<string name="tutorial_4_subtext">- Cím: Sydney-i Operaház\n- Leírás: A Sydney-i Operaház az öböl túlpartjáról\n- Kategóriák: Sydney Opera House from the west, Sydney Opera House remote views</string>
|
||||||
<string name="tutorial_4_subtext_1">Cím: Sydney-i Operaház</string>
|
<string name="tutorial_4_subtext_1">Cím: Sydney-i Operaház</string>
|
||||||
|
|
@ -191,6 +193,7 @@
|
||||||
<string name="commons_logo">Commons Logo</string>
|
<string name="commons_logo">Commons Logo</string>
|
||||||
<string name="commons_website">Commons weboldal</string>
|
<string name="commons_website">Commons weboldal</string>
|
||||||
<string name="commons_facebook">Commons Facebook-oldal</string>
|
<string name="commons_facebook">Commons Facebook-oldal</string>
|
||||||
|
<string name="commons_github">Commons Github forráskód</string>
|
||||||
<string name="background_image">Háttérkép</string>
|
<string name="background_image">Háttérkép</string>
|
||||||
<string name="no_image_found">Nem található kép</string>
|
<string name="no_image_found">Nem található kép</string>
|
||||||
<string name="upload_image">Kép feltöltése</string>
|
<string name="upload_image">Kép feltöltése</string>
|
||||||
|
|
@ -223,6 +226,8 @@
|
||||||
<string name="error_while_cache">Hiba a képek gyorsítótárazásakor</string>
|
<string name="error_while_cache">Hiba a képek gyorsítótárazásakor</string>
|
||||||
<string name="title_info">Egy egyedi, leíró cím a fájlnak, ami fájlnévként fog szolgálni. Egyszerű nyelvezetet használhatsz szóközökkel. Ne tedd bele a kiterjesztést.</string>
|
<string name="title_info">Egy egyedi, leíró cím a fájlnak, ami fájlnévként fog szolgálni. Egyszerű nyelvezetet használhatsz szóközökkel. Ne tedd bele a kiterjesztést.</string>
|
||||||
<string name="description_info">Kérlek a lehető legteljesebb módon írd le a fájlt: hol készült, mit ábrázol, mi a kontextus? Kérlek add meg az objektumokat vagy személyeket a képen, valamint a nehezen kitalálható információkat (például a kép készítésének dátumát, ha az egy tájkép). Amennyiben a média valami szokatlant ábrázol, kérlek fejtsd ki, hogy mi teszi szokatlanná.</string>
|
<string name="description_info">Kérlek a lehető legteljesebb módon írd le a fájlt: hol készült, mit ábrázol, mi a kontextus? Kérlek add meg az objektumokat vagy személyeket a képen, valamint a nehezen kitalálható információkat (például a kép készítésének dátumát, ha az egy tájkép). Amennyiben a média valami szokatlant ábrázol, kérlek fejtsd ki, hogy mi teszi szokatlanná.</string>
|
||||||
|
<string name="upload_image_too_dark">Ez a fénykép túl sötét, biztos fel akarod tölteni? A Wikimédia Commons csak enciklopédikus értékkel bíró képeket tart meg.</string>
|
||||||
|
<string name="upload_image_blurry">Ez a fénykép homályos, biztos fel akarod tölteni? A Wikimédia Commons csak enciklopédikus értékkel bíró képeket tart meg.</string>
|
||||||
<string name="give_permission">Engedély adása</string>
|
<string name="give_permission">Engedély adása</string>
|
||||||
<string name="use_external_storage">Külső tárhely használata</string>
|
<string name="use_external_storage">Külső tárhely használata</string>
|
||||||
<string name="use_external_storage_summary">Az alkalmazáson belüli kamerával készült képek mentése az eszközre</string>
|
<string name="use_external_storage_summary">Az alkalmazáson belüli kamerával készült képek mentése az eszközre</string>
|
||||||
|
|
@ -238,6 +243,7 @@
|
||||||
<string name="nearby_location_not_available">A hely nem érhető el.</string>
|
<string name="nearby_location_not_available">A hely nem érhető el.</string>
|
||||||
<string name="location_permission_rationale_nearby">Közeli helyek listájának megtekintéséhez engedély szükséges</string>
|
<string name="location_permission_rationale_nearby">Közeli helyek listájának megtekintéséhez engedély szükséges</string>
|
||||||
<string name="notifications_welcome">Üdvözlünk a Wikimedia Commonson, %1$s! Örülünk, hogy itt vagy.</string>
|
<string name="notifications_welcome">Üdvözlünk a Wikimedia Commonson, %1$s! Örülünk, hogy itt vagy.</string>
|
||||||
|
<string name="notifications_talk_page_message">%1$s üzenetet hagyott a vitalapodon</string>
|
||||||
<string name="notifications_thank_you_edit">Köszönjük a szerkesztésedet!</string>
|
<string name="notifications_thank_you_edit">Köszönjük a szerkesztésedet!</string>
|
||||||
<string name="nearby_wikidata">WIKIDATA</string>
|
<string name="nearby_wikidata">WIKIDATA</string>
|
||||||
<string name="nearby_wikipedia">WIKIPÉDIA</string>
|
<string name="nearby_wikipedia">WIKIPÉDIA</string>
|
||||||
|
|
@ -249,6 +255,8 @@
|
||||||
<string name="internet_established">Internet elérhető</string>
|
<string name="internet_established">Internet elérhető</string>
|
||||||
<string name="no_notifications">Nincs értesítés</string>
|
<string name="no_notifications">Nincs értesítés</string>
|
||||||
<string name="about_translate_title">Nyelvek</string>
|
<string name="about_translate_title">Nyelvek</string>
|
||||||
|
<string name="about_translate_proceed">Folytatás</string>
|
||||||
<string name="about_translate_cancel">Mégse</string>
|
<string name="about_translate_cancel">Mégse</string>
|
||||||
<string name="retry">Újra</string>
|
<string name="retry">Újra</string>
|
||||||
|
<string name="share_app_title">Alkalmazás megosztása</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -273,4 +273,5 @@
|
||||||
<string name="about_translate_proceed">המשך</string>
|
<string name="about_translate_proceed">המשך</string>
|
||||||
<string name="about_translate_cancel">ביטול</string>
|
<string name="about_translate_cancel">ביטול</string>
|
||||||
<string name="retry">לנסות שוב</string>
|
<string name="retry">לנסות שוב</string>
|
||||||
|
<string name="share_app_title">שיתוף היישום</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -266,4 +266,5 @@
|
||||||
<string name="about_translate_proceed">진행</string>
|
<string name="about_translate_proceed">진행</string>
|
||||||
<string name="about_translate_cancel">취소</string>
|
<string name="about_translate_cancel">취소</string>
|
||||||
<string name="retry">다시 시도</string>
|
<string name="retry">다시 시도</string>
|
||||||
|
<string name="share_app_title">앱 공유</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -263,4 +263,5 @@
|
||||||
<string name="about_translate_proceed">Продолжи</string>
|
<string name="about_translate_proceed">Продолжи</string>
|
||||||
<string name="about_translate_cancel">Откажи</string>
|
<string name="about_translate_cancel">Откажи</string>
|
||||||
<string name="retry">Пробај пак</string>
|
<string name="retry">Пробај пак</string>
|
||||||
|
<string name="share_app_title">Сподели прилог</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -263,4 +263,5 @@
|
||||||
<string name="about_translate_proceed">Andé anans</string>
|
<string name="about_translate_proceed">Andé anans</string>
|
||||||
<string name="about_translate_cancel">Anulé</string>
|
<string name="about_translate_cancel">Anulé</string>
|
||||||
<string name="retry">Prové torna</string>
|
<string name="retry">Prové torna</string>
|
||||||
|
<string name="share_app_title">Partagé j\'aplicassion</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -275,4 +275,5 @@
|
||||||
<string name="about_translate_proceed">Avançar</string>
|
<string name="about_translate_proceed">Avançar</string>
|
||||||
<string name="about_translate_cancel">Cancelar</string>
|
<string name="about_translate_cancel">Cancelar</string>
|
||||||
<string name="retry">Tentar novamente</string>
|
<string name="retry">Tentar novamente</string>
|
||||||
|
<string name="share_app_title">Compartilhar o aplicativo</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,7 @@
|
||||||
<string name="welcome_copyright_subtext">Evite materiais protegidos por direitos de autor que tenham sido encontrados na Internet, bem como imagens de cartazes, capas de livros, etc.</string>
|
<string name="welcome_copyright_subtext">Evite materiais protegidos por direitos de autor que tenham sido encontrados na Internet, bem como imagens de cartazes, capas de livros, etc.</string>
|
||||||
<string name="welcome_final_text">Acha que conseguiu?</string>
|
<string name="welcome_final_text">Acha que conseguiu?</string>
|
||||||
<string name="welcome_final_button_text">Sim!</string>
|
<string name="welcome_final_button_text">Sim!</string>
|
||||||
|
<string name="welcome_help_button_text"/>
|
||||||
<string name="detail_panel_cats_label">Categorias</string>
|
<string name="detail_panel_cats_label">Categorias</string>
|
||||||
<string name="detail_panel_cats_loading">A carregar…</string>
|
<string name="detail_panel_cats_loading">A carregar…</string>
|
||||||
<string name="detail_panel_cats_none">Nenhuma selecionada</string>
|
<string name="detail_panel_cats_none">Nenhuma selecionada</string>
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@
|
||||||
<string name="welcome_copyright_subtext">Undvik upphovsrättsskyddat material som du hittar på Internet, samt bilder av affischer, bokomslag, etc.</string>
|
<string name="welcome_copyright_subtext">Undvik upphovsrättsskyddat material som du hittar på Internet, samt bilder av affischer, bokomslag, etc.</string>
|
||||||
<string name="welcome_final_text">Tror du att du förstår?</string>
|
<string name="welcome_final_text">Tror du att du förstår?</string>
|
||||||
<string name="welcome_final_button_text">Ja!</string>
|
<string name="welcome_final_button_text">Ja!</string>
|
||||||
|
<string name="welcome_help_button_text"/>
|
||||||
<string name="detail_panel_cats_label">Kategorier</string>
|
<string name="detail_panel_cats_label">Kategorier</string>
|
||||||
<string name="detail_panel_cats_loading">Läser in…</string>
|
<string name="detail_panel_cats_loading">Läser in…</string>
|
||||||
<string name="detail_panel_cats_none">Ingen markerad</string>
|
<string name="detail_panel_cats_none">Ingen markerad</string>
|
||||||
|
|
@ -270,4 +271,5 @@
|
||||||
<string name="about_translate_proceed">Fortsätt</string>
|
<string name="about_translate_proceed">Fortsätt</string>
|
||||||
<string name="about_translate_cancel">Avbryt</string>
|
<string name="about_translate_cancel">Avbryt</string>
|
||||||
<string name="retry">Försök igen</string>
|
<string name="retry">Försök igen</string>
|
||||||
|
<string name="share_app_title">Dela app</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -271,4 +271,5 @@
|
||||||
<string name="about_translate_proceed">已進行</string>
|
<string name="about_translate_proceed">已進行</string>
|
||||||
<string name="about_translate_cancel">取消</string>
|
<string name="about_translate_cancel">取消</string>
|
||||||
<string name="retry">重試</string>
|
<string name="retry">重試</string>
|
||||||
|
<string name="share_app_title">分享應用程式</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -269,4 +269,5 @@
|
||||||
<string name="about_translate_proceed">已处理</string>
|
<string name="about_translate_proceed">已处理</string>
|
||||||
<string name="about_translate_cancel">取消</string>
|
<string name="about_translate_cancel">取消</string>
|
||||||
<string name="retry">重试</string>
|
<string name="retry">重试</string>
|
||||||
|
<string name="share_app_title">分享应用</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,6 @@
|
||||||
<dimen name="subheading_text_size">20sp</dimen>
|
<dimen name="subheading_text_size">20sp</dimen>
|
||||||
<dimen name="normal_text">16sp</dimen>
|
<dimen name="normal_text">16sp</dimen>
|
||||||
<dimen name="description_text_size">14sp</dimen>
|
<dimen name="description_text_size">14sp</dimen>
|
||||||
|
<dimen name="first_fab">15dp</dimen>
|
||||||
|
<dimen name="second_fab">25dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -241,13 +241,11 @@
|
||||||
<string name="nominated_for_deletion">This image has been nominated for deletion.</string>
|
<string name="nominated_for_deletion">This image has been nominated for deletion.</string>
|
||||||
<string name="nominated_see_more"><u>See webpage for details</u></string>
|
<string name="nominated_see_more"><u>See webpage for details</u></string>
|
||||||
<string name="view_browser">View in Browser</string>
|
<string name="view_browser">View in Browser</string>
|
||||||
|
|
||||||
<string name="nearby_location_has_not_changed">Location has not changed.</string>
|
<string name="nearby_location_has_not_changed">Location has not changed.</string>
|
||||||
<string name="nearby_location_not_available">Location not available.</string>
|
<string name="nearby_location_not_available">Location not available.</string>
|
||||||
<string name="location_permission_rationale_nearby">Permission required to display a list of nearby places</string>
|
<string name="location_permission_rationale_nearby">Permission required to display a list of nearby places</string>
|
||||||
<string name="get_directions">GET DIRECTIONS</string>
|
<string name="get_directions">GET DIRECTIONS</string>
|
||||||
<string name="read_article">READ ARTICLE</string>
|
<string name="read_article">READ ARTICLE</string>
|
||||||
|
|
||||||
<string name="notifications_welcome" formatted="false">Welcome to Wikimedia Commons, %1$s! We\'re glad you\'re here.</string>
|
<string name="notifications_welcome" formatted="false">Welcome to Wikimedia Commons, %1$s! We\'re glad you\'re here.</string>
|
||||||
<string name="notifications_talk_page_message">%1$s left a message on your talk page</string>
|
<string name="notifications_talk_page_message">%1$s left a message on your talk page</string>
|
||||||
<string name="notifications_thank_you_edit">Thank you for making an edit</string>
|
<string name="notifications_thank_you_edit">Thank you for making an edit</string>
|
||||||
|
|
@ -270,9 +268,19 @@
|
||||||
<string name="about_translate_proceed">Proceed</string>
|
<string name="about_translate_proceed">Proceed</string>
|
||||||
<string name="about_translate_cancel">Cancel</string>
|
<string name="about_translate_cancel">Cancel</string>
|
||||||
<string name="retry">Retry</string>
|
<string name="retry">Retry</string>
|
||||||
<string name="skip_login">Skip </string>
|
<string name="skip_login">Skip</string>
|
||||||
<string name="navigation_item_login">Login</string>
|
<string name="navigation_item_login">Login</string>
|
||||||
<string name="skip_login_title">Do you really want to skip login ?</string>
|
<string name="skip_login_title">Do you really want to skip login ?</string>
|
||||||
<string name="skip_login_message">You might not be able to access some features of the app.</string>=======
|
<string name="skip_login_message">You might not be able to access some features of the app.</string>
|
||||||
|
<string name="showcase_view_got_it_button">Got it!</string>
|
||||||
|
<string name="showcase_view_whole_nearby_activity">These are the places near you that need pictures to illustrate their Wikipedia articles</string>
|
||||||
|
<string name="showcase_view_list_icon">Tapping this button brings up a list of these places</string>
|
||||||
|
<string name="showcase_view_plus_fab">You can upload a picture for any place from your gallery or camera</string>
|
||||||
|
<string name="no_images_found">No images found!</string>
|
||||||
|
<string name="error_loading_images">Error occurred while loading images.</string>
|
||||||
|
<string name="image_uploaded_by">Uploaded by: %1$s</string>
|
||||||
<string name="share_app_title">Share App</string>
|
<string name="share_app_title">Share App</string>
|
||||||
|
<string name="share_coordinates_not_present">Coordinates were not specified during image selection</string>
|
||||||
|
<string name="login_alert_message">This feature requires user to be logged in !!</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons
|
||||||
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
|
||||||
|
|
@ -36,6 +37,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()
|
||||||
|
|
@ -45,6 +47,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()
|
||||||
|
|
||||||
override fun providesAccountUtil(context: Context): AccountUtil = accountUtil
|
override fun providesAccountUtil(context: Context): AccountUtil = accountUtil
|
||||||
|
|
||||||
|
|
@ -58,7 +61,7 @@ class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModu
|
||||||
|
|
||||||
override fun providesSessionManager(context: Context, mediaWikiApi: MediaWikiApi, sharedPreferences: SharedPreferences): SessionManager = mockSessionManager
|
override fun providesSessionManager(context: Context, mediaWikiApi: MediaWikiApi, sharedPreferences: SharedPreferences): SessionManager = mockSessionManager
|
||||||
|
|
||||||
override fun provideMediaWikiApi(context: Context, sharedPreferences: SharedPreferences): MediaWikiApi = mediaWikiApi
|
override fun provideMediaWikiApi(context: Context, sharedPreferences: SharedPreferences, categorySharedPreferences: SharedPreferences, gson: Gson): MediaWikiApi = mediaWikiApi
|
||||||
|
|
||||||
override fun provideLocationServiceManager(context: Context): LocationServiceManager = locationServiceManager
|
override fun provideLocationServiceManager(context: Context): LocationServiceManager = locationServiceManager
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package fr.free.nrw.commons.mwapi
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
|
import com.google.gson.Gson
|
||||||
import fr.free.nrw.commons.BuildConfig
|
import fr.free.nrw.commons.BuildConfig
|
||||||
import fr.free.nrw.commons.TestCommonsApplication
|
import fr.free.nrw.commons.TestCommonsApplication
|
||||||
import okhttp3.mockwebserver.MockResponse
|
import okhttp3.mockwebserver.MockResponse
|
||||||
|
|
@ -26,12 +27,14 @@ 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 sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
private lateinit var categoryPreferences: SharedPreferences
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
server = MockWebServer()
|
server = MockWebServer()
|
||||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
|
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
|
||||||
testObject = ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.hostName + ":" + server.port + "/", sharedPreferences)
|
categoryPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application)
|
||||||
|
testObject = ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.hostName + ":" + server.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