mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 12:53:55 +01:00
Merge pull request #1089 from maskaravivek/notifications
Integrated Notifications API
This commit is contained in:
commit
3697eb5b2d
26 changed files with 669 additions and 8 deletions
|
|
@ -87,6 +87,10 @@
|
||||||
android:label="@string/title_activity_nearby"
|
android:label="@string/title_activity_nearby"
|
||||||
android:parentActivityName=".contributions.ContributionsActivity" />
|
android:parentActivityName=".contributions.ContributionsActivity" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".notification.NotificationActivity"
|
||||||
|
android:label="@string/navigation_item_notification" />
|
||||||
|
|
||||||
<service android:name=".upload.UploadService" />
|
<service android:name=".upload.UploadService" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ 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.nearby.NearbyActivity;
|
import fr.free.nrw.commons.nearby.NearbyActivity;
|
||||||
|
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||||
import fr.free.nrw.commons.settings.SettingsActivity;
|
import fr.free.nrw.commons.settings.SettingsActivity;
|
||||||
import fr.free.nrw.commons.upload.MultipleShareActivity;
|
import fr.free.nrw.commons.upload.MultipleShareActivity;
|
||||||
import fr.free.nrw.commons.upload.ShareActivity;
|
import fr.free.nrw.commons.upload.ShareActivity;
|
||||||
|
|
@ -43,4 +44,6 @@ public abstract class ActivityBuilderModule {
|
||||||
@ContributesAndroidInjector
|
@ContributesAndroidInjector
|
||||||
abstract NearbyActivity bindNearbyActivity();
|
abstract NearbyActivity bindNearbyActivity();
|
||||||
|
|
||||||
|
@ContributesAndroidInjector
|
||||||
|
abstract NotificationActivity bindNotificationActivity();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@ import android.support.v4.util.LruCache;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import dagger.Binds;
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import fr.free.nrw.commons.BuildConfig;
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
|
import fr.free.nrw.commons.CommonsApplication;
|
||||||
import fr.free.nrw.commons.auth.AccountUtil;
|
import fr.free.nrw.commons.auth.AccountUtil;
|
||||||
import fr.free.nrw.commons.auth.SessionManager;
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
import fr.free.nrw.commons.caching.CacheController;
|
import fr.free.nrw.commons.caching.CacheController;
|
||||||
|
|
@ -31,7 +31,9 @@ import static fr.free.nrw.commons.modifications.ModificationsContentProvider.MOD
|
||||||
@SuppressWarnings({"WeakerAccess", "unused"})
|
@SuppressWarnings({"WeakerAccess", "unused"})
|
||||||
public class CommonsApplicationModule {
|
public class CommonsApplicationModule {
|
||||||
public static final String CATEGORY_AUTHORITY = "fr.free.nrw.commons.categories.contentprovider";
|
public static final String CATEGORY_AUTHORITY = "fr.free.nrw.commons.categories.contentprovider";
|
||||||
|
public static final long OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024;
|
||||||
|
|
||||||
|
private CommonsApplication application;
|
||||||
private Context applicationContext;
|
private Context applicationContext;
|
||||||
|
|
||||||
public CommonsApplicationModule(Context applicationContext) {
|
public CommonsApplicationModule(Context applicationContext) {
|
||||||
|
|
@ -100,8 +102,8 @@ public class CommonsApplicationModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
public MediaWikiApi provideMediaWikiApi() {
|
public MediaWikiApi provideMediaWikiApi(Context context) {
|
||||||
return new ApacheHttpClientMediaWikiApi(BuildConfig.WIKIMEDIA_API_HOST);
|
return new ApacheHttpClientMediaWikiApi(context, BuildConfig.WIKIMEDIA_API_HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
@ -133,4 +135,4 @@ public class CommonsApplicationModule {
|
||||||
public LruCache<String, String> provideLruCache() {
|
public LruCache<String, String> provideLruCache() {
|
||||||
return new LruCache<>(1024);
|
return new LruCache<>(1024);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package fr.free.nrw.commons.mwapi;
|
package fr.free.nrw.commons.mwapi;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
@ -21,6 +22,8 @@ import org.apache.http.params.CoreProtocolPNames;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.mediawiki.api.ApiResult;
|
import org.mediawiki.api.ApiResult;
|
||||||
import org.mediawiki.api.MWApi;
|
import org.mediawiki.api.MWApi;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
@ -36,11 +39,17 @@ import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import fr.free.nrw.commons.BuildConfig;
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
import fr.free.nrw.commons.PageTitle;
|
import fr.free.nrw.commons.PageTitle;
|
||||||
|
import fr.free.nrw.commons.notification.Notification;
|
||||||
import in.yuvi.http.fluent.Http;
|
import in.yuvi.http.fluent.Http;
|
||||||
import io.reactivex.Observable;
|
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.notification.NotificationType.UNKNOWN;
|
||||||
|
import static fr.free.nrw.commons.notification.NotificationUtils.getNotificationFromApiResult;
|
||||||
|
import static fr.free.nrw.commons.notification.NotificationUtils.getNotificationType;
|
||||||
|
import static fr.free.nrw.commons.notification.NotificationUtils.isCommonsNotification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Addshore
|
* @author Addshore
|
||||||
*/
|
*/
|
||||||
|
|
@ -50,8 +59,10 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
private static final String THUMB_SIZE = "640";
|
private static final String THUMB_SIZE = "640";
|
||||||
private AbstractHttpClient httpClient;
|
private AbstractHttpClient httpClient;
|
||||||
private MWApi api;
|
private MWApi api;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
public ApacheHttpClientMediaWikiApi(String apiURL) {
|
public ApacheHttpClientMediaWikiApi(Context context, String apiURL) {
|
||||||
|
this.context = context;
|
||||||
BasicHttpParams params = new BasicHttpParams();
|
BasicHttpParams params = new BasicHttpParams();
|
||||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||||
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
|
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
|
||||||
|
|
@ -353,6 +364,42 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
.getString("/api/query/pages/page/revisions/rev");
|
.getString("/api/query/pages/page/revisions/rev");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public List<Notification> getNotifications() {
|
||||||
|
ApiResult notificationNode = null;
|
||||||
|
try {
|
||||||
|
notificationNode = api.action("query")
|
||||||
|
.param("notprop", "list")
|
||||||
|
.param("format", "xml")
|
||||||
|
.param("meta", "notifications")
|
||||||
|
.param("notfilter", "!read")
|
||||||
|
.get()
|
||||||
|
.getNode("/api/query/notifications/list");
|
||||||
|
} catch (IOException e) {
|
||||||
|
Timber.e("Failed to obtain searchCategories", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationNode == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Notification> notifications = new ArrayList<>();
|
||||||
|
|
||||||
|
NodeList childNodes = notificationNode.getDocument().getChildNodes();
|
||||||
|
|
||||||
|
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||||
|
Node node = childNodes.item(i);
|
||||||
|
if (isCommonsNotification(node)
|
||||||
|
&& !getNotificationType(node).equals(UNKNOWN)) {
|
||||||
|
notifications.add(getNotificationFromApiResult(context, node));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean existingFile(String fileSha1) throws IOException {
|
public boolean existingFile(String fileSha1) throws IOException {
|
||||||
return api.action("query")
|
return api.action("query")
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.notification.Notification;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
|
|
@ -43,6 +45,9 @@ public interface MediaWikiApi {
|
||||||
@NonNull
|
@NonNull
|
||||||
Observable<String> allCategories(String filter, int searchCatsLimit);
|
Observable<String> allCategories(String filter, int searchCatsLimit);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
List<Notification> getNotifications() throws IOException;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
Observable<String> searchTitles(String title, int searchCatsLimit);
|
Observable<String> searchTitles(String title, int searchCatsLimit);
|
||||||
|
|
||||||
|
|
@ -51,6 +56,8 @@ public interface MediaWikiApi {
|
||||||
|
|
||||||
boolean existingFile(String fileSha1) throws IOException;
|
boolean existingFile(String fileSha1) throws IOException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
LogEventResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException;
|
LogEventResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
public class MarkReadResponse {
|
||||||
|
@SuppressWarnings("unused") @Nullable
|
||||||
|
private String result;
|
||||||
|
|
||||||
|
public String result() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class QueryMarkReadResponse {
|
||||||
|
@SuppressWarnings("unused") @Nullable private MarkReadResponse echomarkread;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by root on 18.12.2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Notification {
|
||||||
|
public NotificationType notificationType;
|
||||||
|
public String notificationText;
|
||||||
|
public String date;
|
||||||
|
public String description;
|
||||||
|
public String link;
|
||||||
|
|
||||||
|
public Notification(NotificationType notificationType, String notificationText, String date, String description, String link) {
|
||||||
|
this.notificationType = notificationType;
|
||||||
|
this.notificationText = notificationText;
|
||||||
|
this.date = date;
|
||||||
|
this.description = description;
|
||||||
|
this.link = link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.pedrogomez.renderers.RVRendererAdapter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.theme.NavigationBaseActivity;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by root on 18.12.2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NotificationActivity extends NavigationBaseActivity {
|
||||||
|
NotificationAdapterFactory notificationAdapterFactory;
|
||||||
|
|
||||||
|
@BindView(R.id.listView) RecyclerView recyclerView;
|
||||||
|
|
||||||
|
@Inject NotificationController controller;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_notification);
|
||||||
|
ButterKnife.bind(this);
|
||||||
|
initListView();
|
||||||
|
initDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListView() {
|
||||||
|
recyclerView = findViewById(R.id.listView);
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||||
|
addNotifications();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void addNotifications() {
|
||||||
|
Timber.d("Add notifications");
|
||||||
|
|
||||||
|
Observable.fromCallable(() -> controller.getNotifications())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(notificationList -> {
|
||||||
|
Timber.d("Number of notifications is %d", notificationList.size());
|
||||||
|
setAdapter(notificationList);
|
||||||
|
}, throwable -> {
|
||||||
|
Timber.e(throwable, "Error occurred while loading notifications");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleUrl(String url) {
|
||||||
|
if (url == null || url.equals("")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAdapter(List<Notification> notificationList) {
|
||||||
|
notificationAdapterFactory = new NotificationAdapterFactory(notification -> {
|
||||||
|
Timber.d("Notification clicked %s", notification.link);
|
||||||
|
handleUrl(notification.link);
|
||||||
|
});
|
||||||
|
RVRendererAdapter<Notification> adapter = notificationAdapterFactory.create(notificationList);
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startYourself(Context context) {
|
||||||
|
Intent intent = new Intent(context, NotificationActivity.class);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.pedrogomez.renderers.ListAdapteeCollection;
|
||||||
|
import com.pedrogomez.renderers.RVRendererAdapter;
|
||||||
|
import com.pedrogomez.renderers.RendererBuilder;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by root on 19.12.2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class NotificationAdapterFactory {
|
||||||
|
private NotificationRenderer.NotificationClicked listener;
|
||||||
|
|
||||||
|
NotificationAdapterFactory(@NonNull NotificationRenderer.NotificationClicked listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RVRendererAdapter<Notification> create(List<Notification> notifications) {
|
||||||
|
RendererBuilder<Notification> builder = new RendererBuilder<Notification>()
|
||||||
|
.bind(Notification.class, new NotificationRenderer(listener));
|
||||||
|
ListAdapteeCollection<Notification> collection = new ListAdapteeCollection<>(
|
||||||
|
notifications != null ? notifications : Collections.<Notification>emptyList());
|
||||||
|
return new RVRendererAdapter<>(builder, collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.auth.SessionManager;
|
||||||
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by root on 19.12.2017.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class NotificationController {
|
||||||
|
|
||||||
|
private MediaWikiApi mediaWikiApi;
|
||||||
|
private SessionManager sessionManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public NotificationController(MediaWikiApi mediaWikiApi, SessionManager sessionManager) {
|
||||||
|
this.mediaWikiApi = mediaWikiApi;
|
||||||
|
this.sessionManager = sessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Notification> getNotifications() throws IOException {
|
||||||
|
if (mediaWikiApi.validateLogin()) {
|
||||||
|
return mediaWikiApi.getNotifications();
|
||||||
|
} else {
|
||||||
|
Boolean authTokenValidated = sessionManager.revalidateAuthToken();
|
||||||
|
if (authTokenValidated != null && authTokenValidated) {
|
||||||
|
return mediaWikiApi.getNotifications();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.pedrogomez.renderers.Renderer;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.utils.DateUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by root on 19.12.2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NotificationRenderer extends Renderer<Notification> {
|
||||||
|
@BindView(R.id.title) TextView title;
|
||||||
|
@BindView(R.id.description) TextView description;
|
||||||
|
@BindView(R.id.time) TextView time;
|
||||||
|
@BindView(R.id.icon) ImageView icon;
|
||||||
|
private NotificationClicked listener;
|
||||||
|
|
||||||
|
|
||||||
|
NotificationRenderer(NotificationClicked listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUpView(View view) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void hookListeners(View rootView) {
|
||||||
|
rootView.setOnClickListener(v -> listener.notificationClicked(getContent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View inflate(LayoutInflater layoutInflater, ViewGroup viewGroup) {
|
||||||
|
View inflatedView = layoutInflater.inflate(R.layout.item_notification, viewGroup, false);
|
||||||
|
ButterKnife.bind(this, inflatedView);
|
||||||
|
return inflatedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {
|
||||||
|
Notification notification = getContent();
|
||||||
|
title.setText(notification.notificationText);
|
||||||
|
time.setText(notification.date);
|
||||||
|
description.setText(notification.description);
|
||||||
|
switch (notification.notificationType) {
|
||||||
|
case THANK_YOU_EDIT:
|
||||||
|
icon.setImageResource(R.drawable.ic_edit_black_24dp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
icon.setImageResource(R.drawable.round_icon_unknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface NotificationClicked{
|
||||||
|
void notificationClicked(Notification notification);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
public enum NotificationType {
|
||||||
|
THANK_YOU_EDIT("thank-you-edit"),
|
||||||
|
EDIT_USER_TALK("edit-user-talk"),
|
||||||
|
MENTION("mention"),
|
||||||
|
WELCOME("welcome"),
|
||||||
|
UNKNOWN("unknown");
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
NotificationType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NotificationType handledValueOf(String name) {
|
||||||
|
for (NotificationType e : values()) {
|
||||||
|
if (e.getType().equals(name)) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
package fr.free.nrw.commons.notification;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.BuildConfig;
|
||||||
|
import fr.free.nrw.commons.R;
|
||||||
|
|
||||||
|
public class NotificationUtils {
|
||||||
|
|
||||||
|
private static final String COMMONS_WIKI = "commonswiki";
|
||||||
|
|
||||||
|
public static boolean isCommonsNotification(Node document) {
|
||||||
|
if (document == null || !document.hasAttributes()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Element element = (Element) document;
|
||||||
|
return COMMONS_WIKI.equals(element.getAttribute("wiki"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NotificationType getNotificationType(Node document) {
|
||||||
|
Element element = (Element) document;
|
||||||
|
String type = element.getAttribute("type");
|
||||||
|
return NotificationType.handledValueOf(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Notification getNotificationFromApiResult(Context context, Node document) {
|
||||||
|
NotificationType type = getNotificationType(document);
|
||||||
|
|
||||||
|
String notificationText = "";
|
||||||
|
String link = getNotificationLink(document);
|
||||||
|
String description = getNotificationDescription(document);
|
||||||
|
switch (type) {
|
||||||
|
case THANK_YOU_EDIT:
|
||||||
|
notificationText = context.getString(R.string.notifications_thank_you_edit);
|
||||||
|
break;
|
||||||
|
case EDIT_USER_TALK:
|
||||||
|
notificationText = getUserTalkMessage(context, document);
|
||||||
|
break;
|
||||||
|
case MENTION:
|
||||||
|
notificationText = getMentionMessage(context, document);
|
||||||
|
break;
|
||||||
|
case WELCOME:
|
||||||
|
notificationText = getWelcomeMessage(context, document);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return new Notification(type, notificationText, getTimestamp(document), description, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMentionMessage(Context context, Node document) {
|
||||||
|
String format = context.getString(R.string.notifications_mention);
|
||||||
|
return String.format(format, getAgent(document), getNotificationDescription(document));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUserTalkMessage(Context context, Node document) {
|
||||||
|
String format = context.getString(R.string.notifications_talk_page_message);
|
||||||
|
return String.format(format, getAgent(document));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getWelcomeMessage(Context context, Node document) {
|
||||||
|
String welcomeMessageFormat = context.getString(R.string.notifications_welcome);
|
||||||
|
return String.format(welcomeMessageFormat, getAgent(document));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getAgent(Node document) {
|
||||||
|
Element agentElement = (Element) getNode(document, "agent");
|
||||||
|
if (agentElement != null) {
|
||||||
|
return agentElement.getAttribute("name");
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getTimestamp(Node document) {
|
||||||
|
Element timestampElement = (Element) getNode(document, "timestamp");
|
||||||
|
if (timestampElement != null) {
|
||||||
|
return timestampElement.getAttribute("date");
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getNotificationLink(Node document) {
|
||||||
|
String format = "%s%s";
|
||||||
|
Element titleElement = (Element) getNode(document, "title");
|
||||||
|
if (titleElement != null) {
|
||||||
|
String fullName = titleElement.getAttribute("full");
|
||||||
|
return String.format(format, BuildConfig.HOME_URL, fullName);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getNotificationDescription(Node document) {
|
||||||
|
Element titleElement = (Element) getNode(document, "title");
|
||||||
|
if (titleElement != null) {
|
||||||
|
return titleElement.getAttribute("text");
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,7 @@ 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.nearby.NearbyActivity;
|
import fr.free.nrw.commons.nearby.NearbyActivity;
|
||||||
|
import fr.free.nrw.commons.notification.NotificationActivity;
|
||||||
import fr.free.nrw.commons.settings.SettingsActivity;
|
import fr.free.nrw.commons.settings.SettingsActivity;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
|
@ -143,6 +144,10 @@ public abstract class NavigationBaseActivity extends BaseActivity
|
||||||
.setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel())
|
.setNegativeButton(R.string.no, (dialog, which) -> dialog.cancel())
|
||||||
.show();
|
.show();
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.action_notifications:
|
||||||
|
drawerLayout.closeDrawer(navigationView);
|
||||||
|
NotificationActivity.startYourself(this);
|
||||||
|
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);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
36
app/src/main/java/fr/free/nrw/commons/utils/DateUtils.java
Normal file
36
app/src/main/java/fr/free/nrw/commons/utils/DateUtils.java
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package fr.free.nrw.commons.utils;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class DateUtils {
|
||||||
|
public static String getTimeAgo(Date currDate, Date itemDate) {
|
||||||
|
Calendar c = Calendar.getInstance();
|
||||||
|
c.setTime(currDate);
|
||||||
|
int yearNow = c.get(Calendar.YEAR);
|
||||||
|
int monthNow = c.get(Calendar.MONTH);
|
||||||
|
int dayNow = c.get(Calendar.DAY_OF_MONTH);
|
||||||
|
int hourNow = c.get(Calendar.HOUR_OF_DAY);
|
||||||
|
int minuteNow = c.get(Calendar.MINUTE);
|
||||||
|
c.setTime(itemDate);
|
||||||
|
int videoYear = c.get(Calendar.YEAR);
|
||||||
|
int videoMonth = c.get(Calendar.MONTH);
|
||||||
|
int videoDays = c.get(Calendar.DAY_OF_MONTH);
|
||||||
|
int videoHour = c.get(Calendar.HOUR_OF_DAY);
|
||||||
|
int videoMinute = c.get(Calendar.MINUTE);
|
||||||
|
|
||||||
|
if (yearNow != videoYear) {
|
||||||
|
return (String.valueOf(yearNow - videoYear) + "-" + "years");
|
||||||
|
} else if (monthNow != videoMonth) {
|
||||||
|
return (String.valueOf(monthNow - videoMonth) + "-" + "months");
|
||||||
|
} else if (dayNow != videoDays) {
|
||||||
|
return (String.valueOf(dayNow - videoDays) + "-" + "days");
|
||||||
|
} else if (hourNow != videoHour) {
|
||||||
|
return (String.valueOf(hourNow - videoHour) + "-" + "hours");
|
||||||
|
} else if (minuteNow != videoMinute) {
|
||||||
|
return (String.valueOf(minuteNow - videoMinute) + "-" + "minutes");
|
||||||
|
} else {
|
||||||
|
return "0-seconds";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
app/src/main/res/drawable/ic_chat_bubble_black_24px.xml
Normal file
9
app/src/main/res/drawable/ic_chat_bubble_black_24px.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:pathData="M4,2C2.9,2 2,2.9 2,4L2,22L6,18L20,18C21.1,18 22,17.1 22,16L22,4C22,2.9 21.1,2 20,2L4,2zM12.496,4.098C13.408,4.098 14.236,4.273 14.98,4.623C15.725,4.969 16.347,5.47 16.848,6.125C17.153,6.524 17.384,6.956 17.539,7.424C17.698,7.888 17.775,8.376 17.775,8.889C17.775,9.991 17.444,10.849 16.781,11.459C16.118,12.069 15.183,12.375 13.975,12.375L13.736,12.375L13.736,11.434C13.614,11.722 13.417,11.949 13.145,12.111C12.876,12.27 12.559,12.35 12.197,12.35C11.497,12.35 10.928,12.098 10.488,11.594C10.053,11.085 9.836,10.423 9.836,9.609C9.836,8.796 10.055,8.134 10.494,7.625C10.934,7.116 11.501,6.863 12.197,6.863C12.559,6.863 12.876,6.945 13.145,7.107C13.417,7.27 13.614,7.496 13.736,7.785L13.736,6.984L15.012,6.984L15.012,11.215C15.516,11.138 15.912,10.895 16.201,10.488C16.49,10.077 16.635,9.553 16.635,8.914C16.635,8.507 16.575,8.125 16.457,7.771C16.339,7.413 16.16,7.086 15.92,6.789C15.533,6.293 15.051,5.911 14.469,5.643C13.891,5.374 13.263,5.238 12.588,5.238C12.116,5.238 11.664,5.302 11.232,5.428C10.801,5.55 10.403,5.731 10.037,5.971C9.435,6.369 8.965,6.887 8.627,7.521C8.293,8.152 8.127,8.836 8.127,9.572C8.127,10.179 8.234,10.748 8.449,11.281C8.669,11.81 8.986,12.279 9.396,12.686C9.803,13.084 10.268,13.388 10.793,13.596C11.322,13.807 11.886,13.912 12.484,13.912C12.997,13.912 13.511,13.816 14.023,13.625C14.536,13.434 14.972,13.175 15.334,12.85L15.258,14.324C14.96,14.491 14.648,14.63 14.322,14.742C13.724,14.954 13.115,15.061 12.496,15.061C11.743,15.061 11.035,14.925 10.367,14.656C9.7,14.392 9.105,14.007 8.584,13.498C8.063,12.989 7.667,12.4 7.395,11.732C7.122,11.061 6.984,10.341 6.984,9.572C6.984,8.832 7.124,8.126 7.4,7.455C7.677,6.784 8.071,6.194 8.584,5.686C9.097,5.181 9.694,4.79 10.373,4.514C11.057,4.237 11.764,4.098 12.496,4.098zM12.412,7.998C12.054,7.998 11.766,8.143 11.551,8.432C11.339,8.716 11.232,9.105 11.232,9.598C11.232,10.098 11.339,10.492 11.551,10.781C11.766,11.07 12.058,11.215 12.424,11.215C12.786,11.215 13.075,11.07 13.291,10.781C13.507,10.488 13.613,10.094 13.613,9.598C13.613,9.105 13.503,8.716 13.283,8.432C13.068,8.143 12.778,7.998 12.412,7.998z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/ic_edit_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_edit_black_24dp.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
|
||||||
|
</vector>
|
||||||
9
app/src/main/res/drawable/ic_message_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_message_black_24dp.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z"/>
|
||||||
|
</vector>
|
||||||
34
app/src/main/res/layout/activity_notification.xml
Normal file
34
app/src/main/res/layout/activity_notification.xml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/drawer_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/listView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@id/toolbar"
|
||||||
|
/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<android.support.design.widget.NavigationView
|
||||||
|
android:id="@+id/navigation_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="start"
|
||||||
|
app:headerLayout="@layout/drawer_header"
|
||||||
|
app:menu="@menu/drawer"/>
|
||||||
|
|
||||||
|
</android.support.v4.widget.DrawerLayout>
|
||||||
70
app/src/main/res/layout/item_notification.xml
Normal file
70
app/src/main/res/layout/item_notification.xml
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:foreground="?selectableItemBackground"
|
||||||
|
android:minHeight="72dp"
|
||||||
|
>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:background="@android:color/white"
|
||||||
|
android:contentDescription="@string/no_image_found"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@drawable/empty_photo"
|
||||||
|
android:tint="@color/primaryDarkColor"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/time"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||||
|
tools:text="@string/placeholder_place_distance"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignTop="@id/time"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_toEndOf="@id/icon"
|
||||||
|
android:layout_toLeftOf="@id/time"
|
||||||
|
android:layout_toRightOf="@id/icon"
|
||||||
|
android:layout_toStartOf="@id/time"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Body2"
|
||||||
|
tools:text="@string/placeholder_place_name"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignEnd="@id/time"
|
||||||
|
android:layout_alignLeft="@id/title"
|
||||||
|
android:layout_alignRight="@id/time"
|
||||||
|
android:layout_alignStart="@id/title"
|
||||||
|
android:layout_below="@id/title"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="4"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
||||||
|
tools:text="@string/placeholder_place_description"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -35,4 +35,9 @@
|
||||||
android:icon="@drawable/ic_exit_to_app_black_24dp"
|
android:icon="@drawable/ic_exit_to_app_black_24dp"
|
||||||
android:title="@string/navigation_item_logout"/>
|
android:title="@string/navigation_item_logout"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_notifications"
|
||||||
|
android:icon="@drawable/ic_notifications_black_24dp"
|
||||||
|
android:title="@string/navigation_item_notification"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,7 @@
|
||||||
<string name="navigation_item_feedback">Feedback</string>
|
<string name="navigation_item_feedback">Feedback</string>
|
||||||
<string name="navigation_item_logout">Logout</string>
|
<string name="navigation_item_logout">Logout</string>
|
||||||
<string name="navigation_item_info">Tutorial</string>
|
<string name="navigation_item_info">Tutorial</string>
|
||||||
|
<string name="navigation_item_notification">Notifications</string>
|
||||||
<string name="nearby_needs_permissions">Nearby places cannot be displayed without location permissions</string>
|
<string name="nearby_needs_permissions">Nearby places cannot be displayed without location permissions</string>
|
||||||
<string name="no_description_found">no description found</string>
|
<string name="no_description_found">no description found</string>
|
||||||
<string name="nearby_info_menu_commons_article">Commons file page</string>
|
<string name="nearby_info_menu_commons_article">Commons file page</string>
|
||||||
|
|
@ -216,4 +217,9 @@
|
||||||
<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, %s! We\'re glad you\'re here.</string>
|
||||||
|
<string name="notifications_talk_page_message" formatted="false">%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_mention" formatted="false">%s mentioned you on %s.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ public class TestCommonsApplication extends CommonsApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaWikiApi provideMediaWikiApi() {
|
public MediaWikiApi provideMediaWikiApi(Context context) {
|
||||||
return mediaWikiApi;
|
return mediaWikiApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.Robolectric;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -38,7 +40,7 @@ public class ApacheHttpClientMediaWikiApiTest {
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
server = new MockWebServer();
|
server = new MockWebServer();
|
||||||
testObject = new ApacheHttpClientMediaWikiApi("http://" + server.getHostName() + ":" + server.getPort() + "/");
|
testObject = new ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.getHostName() + ":" + server.getPort() + "/");
|
||||||
testObject.setWikiMediaToolforgeUrl("http://" + server.getHostName() + ":" + server.getPort() + "/");
|
testObject.setWikiMediaToolforgeUrl("http://" + server.getHostName() + ":" + server.getPort() + "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ android.useDeprecatedNdk=true
|
||||||
BUTTERKNIFE_VERSION=8.6.0
|
BUTTERKNIFE_VERSION=8.6.0
|
||||||
DAGGER_VERSION=2.13
|
DAGGER_VERSION=2.13
|
||||||
LEAK_CANARY=1.5.4
|
LEAK_CANARY=1.5.4
|
||||||
|
|
||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
|
||||||
#TODO: Temporary disabled. https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#aapt2
|
#TODO: Temporary disabled. https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#aapt2
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue