mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Refactor code to remove usage of Jsoup and Rssparser (#1888)
* Refactor code to remove usage of Jsoup and Rssparser * Use current date for picture of the day
This commit is contained in:
parent
fc30f1b5ec
commit
86e849683a
10 changed files with 154 additions and 58 deletions
|
|
@ -6,7 +6,6 @@ apply plugin: 'jacoco-android'
|
|||
apply from: 'quality.gradle'
|
||||
|
||||
dependencies {
|
||||
implementation 'com.prof.rssparser:rssparser:1.1'
|
||||
implementation 'com.github.nicolas-raoul:Quadtree:ac16ea8035bf07'
|
||||
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar'
|
||||
implementation 'in.yuvi:http.fluent:1.3'
|
||||
|
|
@ -43,7 +42,6 @@ dependencies {
|
|||
implementation 'com.jakewharton.rxbinding2:rxbinding-support-v4:2.1.1'
|
||||
implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.1.1'
|
||||
implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.1.1'
|
||||
implementation 'org.jsoup:jsoup:1.11.3'
|
||||
implementation 'com.facebook.fresco:fresco:1.10.0'
|
||||
implementation 'com.facebook.stetho:stetho:1.5.0'
|
||||
implementation "com.google.dagger:dagger:$DAGGER_VERSION"
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import javax.inject.Inject;
|
|||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import fr.free.nrw.commons.Media;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.auth.SessionManager;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
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;
|
||||
|
|
@ -15,6 +14,7 @@ import java.util.List;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import fr.free.nrw.commons.Media;
|
||||
import fr.free.nrw.commons.utils.StringUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class CategoryImageUtils {
|
||||
|
|
@ -57,7 +57,7 @@ public class CategoryImageUtils {
|
|||
* @param node
|
||||
* @return
|
||||
*/
|
||||
private static Media getMediaFromPage(Node node) {
|
||||
public static Media getMediaFromPage(Node node) {
|
||||
Media media = new Media(null,
|
||||
getImageUrl(node),
|
||||
getFileName(node),
|
||||
|
|
@ -103,17 +103,12 @@ public class CategoryImageUtils {
|
|||
|
||||
/**
|
||||
* 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
|
||||
* The artist information is returned as a HTML string from the API. Using HTML parser to parse the HTML
|
||||
* @param document
|
||||
* @return
|
||||
*/
|
||||
private static String getCreator(Node document) {
|
||||
String artist = getMetaDataValue(document, "Artist");
|
||||
if (artist != null) {
|
||||
return Jsoup.parse(artist).text();
|
||||
}
|
||||
return null;
|
||||
return StringUtils.getParsedStringFromHtml(getMetaDataValue(document, "Artist"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package fr.free.nrw.commons.category;
|
|||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -10,10 +11,12 @@ import android.widget.TextView;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import fr.free.nrw.commons.Media;
|
||||
import fr.free.nrw.commons.MediaWikiImageView;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.ui.widget.HtmlTextView;
|
||||
|
||||
/**
|
||||
* This is created to only display UI implementation. Needs to be changed in real implementation
|
||||
|
|
@ -92,7 +95,9 @@ public class GridViewAdapter extends ArrayAdapter {
|
|||
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()));
|
||||
|
||||
String uploadedBy = String.format(Locale.getDefault(), uploadedByTemplate, item.getCreator());
|
||||
author.setText(uploadedBy);
|
||||
} else {
|
||||
author.setVisibility(View.GONE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import fr.free.nrw.commons.modifications.ModificationsSyncAdapter;
|
|||
import fr.free.nrw.commons.nearby.PlaceRenderer;
|
||||
import fr.free.nrw.commons.upload.FileProcessor;
|
||||
import fr.free.nrw.commons.settings.SettingsFragment;
|
||||
import fr.free.nrw.commons.widget.PicOfDayAppWidget;
|
||||
|
||||
|
||||
@Singleton
|
||||
|
|
@ -50,6 +51,8 @@ public interface CommonsApplicationComponent extends AndroidInjector<Application
|
|||
|
||||
void inject(FileProcessor fileProcessor);
|
||||
|
||||
void inject(PicOfDayAppWidget picOfDayAppWidget);
|
||||
|
||||
@Component.Builder
|
||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||
interface Builder {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import java.net.URL;
|
|||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
|
@ -51,6 +52,7 @@ import fr.free.nrw.commons.category.QueryContinue;
|
|||
import fr.free.nrw.commons.notification.Notification;
|
||||
import fr.free.nrw.commons.notification.NotificationUtils;
|
||||
import fr.free.nrw.commons.utils.ContributionUtils;
|
||||
import fr.free.nrw.commons.utils.DateUtils;
|
||||
import in.yuvi.http.fluent.Http;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
|
@ -997,6 +999,44 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* The method returns the picture of the day
|
||||
*
|
||||
* @return Media object corresponding to the picture of the day
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public Single<Media> getPictureOfTheDay() {
|
||||
return Single.fromCallable(() -> {
|
||||
CustomApiResult apiResult = null;
|
||||
try {
|
||||
String template = "Template:Potd/" + DateUtils.getCurrentDate();
|
||||
CustomMwApi.RequestBuilder requestBuilder = api.action("query")
|
||||
.param("generator", "images")
|
||||
.param("format", "xml")
|
||||
.param("titles", template)
|
||||
.param("prop", "imageinfo")
|
||||
.param("iiprop", "url|extmetadata");
|
||||
|
||||
apiResult = requestBuilder.get();
|
||||
} catch (IOException e) {
|
||||
Timber.e("Failed to obtain searchCategories", e);
|
||||
}
|
||||
|
||||
if (apiResult == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CustomApiResult imageNode = apiResult.getNode("/api/query/pages/page");
|
||||
if (imageNode == null
|
||||
|| imageNode.getDocument() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CategoryImageUtils.getMediaFromPage(imageNode.getDocument());
|
||||
});
|
||||
}
|
||||
|
||||
private Date parseMWDate(String mwDate) {
|
||||
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH); // Assuming MW always gives me UTC
|
||||
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ public interface MediaWikiApi {
|
|||
|
||||
Single<FeedbackResponse> getAchievements(String userName);
|
||||
|
||||
Single<Media> getPictureOfTheDay();
|
||||
|
||||
void logout();
|
||||
|
||||
interface ProgressListener {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package fr.free.nrw.commons.utils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class DateUtils {
|
||||
public static String getTimeAgo(Date currDate, Date itemDate) {
|
||||
|
|
@ -33,4 +35,10 @@ public class DateUtils {
|
|||
return "0-seconds";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getCurrentDate() {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
||||
Date date = new Date();
|
||||
return dateFormat.format(date);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
15
app/src/main/java/fr/free/nrw/commons/utils/StringUtils.java
Normal file
15
app/src/main/java/fr/free/nrw/commons/utils/StringUtils.java
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package fr.free.nrw.commons.utils;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
|
||||
public class StringUtils {
|
||||
public static String getParsedStringFromHtml(String source) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
return Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY).toString();
|
||||
} else {
|
||||
//noinspection deprecation
|
||||
return Html.fromHtml(source).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,39 +19,71 @@ import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
|||
import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import com.prof.rssparser.Article;
|
||||
import com.prof.rssparser.Parser;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.select.Elements;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Implementation of App Widget functionality.
|
||||
*/
|
||||
public class PicOfDayAppWidget extends AppWidgetProvider {
|
||||
|
||||
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
private CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||
|
||||
@Inject
|
||||
MediaWikiApi mediaWikiApi;
|
||||
|
||||
void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.pic_of_day_app_widget);
|
||||
loadPictureOfTheDay(context, views, appWidgetManager, appWidgetId);
|
||||
}
|
||||
|
||||
String urlString = BuildConfig.WIKIMEDIA_API_POTD;
|
||||
Parser parser = new Parser();
|
||||
parser.execute(urlString);
|
||||
parser.onFinish(new Parser.OnTaskCompleted() {
|
||||
@Override
|
||||
public void onTaskCompleted(ArrayList<Article> list) {
|
||||
String desc = list.get(list.size() - 1).getDescription();
|
||||
if (desc != null) {
|
||||
Document document = Jsoup.parse(desc);
|
||||
Elements elements = document.select("img");
|
||||
String imageUrl = elements.get(0).attr("src");
|
||||
if (imageUrl != null && imageUrl.length() > 0) {
|
||||
/**
|
||||
* Loads the picture of the day using media wiki API
|
||||
* @param context
|
||||
* @param views
|
||||
* @param appWidgetManager
|
||||
* @param appWidgetId
|
||||
*/
|
||||
private void loadPictureOfTheDay(Context context,
|
||||
RemoteViews views,
|
||||
AppWidgetManager appWidgetManager,
|
||||
int appWidgetId) {
|
||||
compositeDisposable.add(mediaWikiApi.getPictureOfTheDay()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
response -> {
|
||||
if (response != null) {
|
||||
loadImageFromUrl(response.getImageUrl(), context, views, appWidgetManager, appWidgetId);
|
||||
}
|
||||
},
|
||||
t -> {
|
||||
Timber.e(t, "Fetching picture of the day failed");
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses Fresco to load an image from Url
|
||||
* @param imageUrl
|
||||
* @param context
|
||||
* @param views
|
||||
* @param appWidgetManager
|
||||
* @param appWidgetId
|
||||
*/
|
||||
private void loadImageFromUrl(String imageUrl,
|
||||
Context context,
|
||||
RemoteViews views,
|
||||
AppWidgetManager appWidgetManager,
|
||||
int appWidgetId) {
|
||||
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse(imageUrl)).build();
|
||||
ImagePipeline imagePipeline = Fresco.getImagePipeline();
|
||||
DataSource<CloseableReference<CloseableImage>> dataSource
|
||||
|
|
@ -75,17 +107,14 @@ public class PicOfDayAppWidget extends AppWidgetProvider {
|
|||
}
|
||||
}, CallerThreadExecutor.getInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
ApplicationlessInjection
|
||||
.getInstance(context
|
||||
.getApplicationContext())
|
||||
.getCommonsApplicationComponent()
|
||||
.inject(this);
|
||||
// There may be multiple widgets active, so update all of them
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue