Dbrant has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/325627

Change subject: [WIP] Echo notifications.
......................................................................

[WIP] Echo notifications.

*Very* rough; not ready for review.

Change-Id: Ic2ab7bc402064cb8bf7351f6482b5b27a8925b03
---
M app/src/main/AndroidManifest.xml
M app/src/main/java/org/wikipedia/WikipediaApp.java
A app/src/main/java/org/wikipedia/account/UserInfoPollService.java
M 
app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
A app/src/main/java/org/wikipedia/useroption/dataclient/Notifications.java
M app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java
M 
app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
A app/src/main/res/drawable/ic_chat_white_24dp.xml
A app/src/main/res/drawable/ic_favorite_white_24dp.xml
A app/src/main/res/drawable/ic_rotate_left_white_24dp.xml
M app/src/main/res/values-qq/strings.xml
M app/src/main/res/values/strings.xml
12 files changed, 304 insertions(+), 1 deletion(-)


  git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia 
refs/changes/27/325627/1

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2c7f60d..c8e07a5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -258,5 +258,7 @@
 
         <service android:name=".savedpages.SavedPageSyncService" />
 
+        <service android:name=".account.UserInfoPollService" />
+
     </application>
 </manifest>
diff --git a/app/src/main/java/org/wikipedia/WikipediaApp.java 
b/app/src/main/java/org/wikipedia/WikipediaApp.java
index 6d89fef..ea2f027 100644
--- a/app/src/main/java/org/wikipedia/WikipediaApp.java
+++ b/app/src/main/java/org/wikipedia/WikipediaApp.java
@@ -3,6 +3,7 @@
 import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.Application;
+import android.content.Intent;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Build;
@@ -22,6 +23,7 @@
 import com.squareup.otto.Bus;
 
 import org.mediawiki.api.json.Api;
+import org.wikipedia.account.UserInfoPollService;
 import org.wikipedia.analytics.FunnelManager;
 import org.wikipedia.analytics.SessionFunnel;
 import org.wikipedia.auth.AccountUtil;
@@ -201,6 +203,8 @@
 
         UserOptionContentResolver.registerAppSyncObserver(this);
         registerReadingListPageObserver();
+
+        startService(new Intent(this, UserInfoPollService.class));
     }
 
     public RefWatcher getRefWatcher() {
diff --git a/app/src/main/java/org/wikipedia/account/UserInfoPollService.java 
b/app/src/main/java/org/wikipedia/account/UserInfoPollService.java
new file mode 100644
index 0000000..be9cbf6
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/account/UserInfoPollService.java
@@ -0,0 +1,155 @@
+package org.wikipedia.account;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.support.annotation.ColorInt;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.content.ContextCompat;
+
+import org.wikipedia.R;
+import org.wikipedia.WikipediaApp;
+import org.wikipedia.concurrency.SaneAsyncTask;
+import org.wikipedia.useroption.dataclient.Notifications;
+import org.wikipedia.useroption.dataclient.UserOptionDataClientSingleton;
+import org.wikipedia.util.ShareUtil;
+import org.wikipedia.util.log.L;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class UserInfoPollService extends Service {
+    private static final int PERIODIC_TASK_INTERVAL_MILLIS = 10000;
+    private static final int MAX_ISSUED_NOTIFICATIONS = 100;
+    private Handler handler;
+
+    private Set<Integer> issuedNotifications = Collections.newSetFromMap(new 
LinkedHashMap<Integer, Boolean>() {
+        @Override
+        public boolean removeEldestEntry(Map.Entry<Integer, Boolean> eldest) {
+            return size() > MAX_ISSUED_NOTIFICATIONS;
+        }
+    });
+
+    @Override
+    public void onCreate() {
+        handler = new Handler();
+        handler.postDelayed(periodicRunnable, PERIODIC_TASK_INTERVAL_MILLIS);
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    private Runnable periodicRunnable = new Runnable() {
+        @Override
+        public void run() {
+            new UserInfoTask().execute();
+        }
+    };
+
+    private void keepGoing() {
+        handler.postDelayed(periodicRunnable, PERIODIC_TASK_INTERVAL_MILLIS);
+    }
+
+    public class UserInfoTask extends SaneAsyncTask<Void> {
+        @Override
+        public Void performTask() throws Throwable {
+            Notifications notifications = 
UserOptionDataClientSingleton.instance().getNotifications();
+
+            if (notifications.getNotifications() != null && 
notifications.getNotifications().length > 0) {
+                Notifications.Notification n = null;
+                for (Notifications.Notification notification : 
notifications.getNotifications()) {
+                    if 
(!issuedNotifications.contains(notification.getRevid())) {
+                        issuedNotifications.add(notification.getRevid());
+                        n = notification;
+                        break;
+                    }
+                }
+                if (n != null) {
+                    showNotification(n);
+                }
+            }
+
+            keepGoing();
+            return null;
+        }
+
+        @Override
+        public void onCatch(Throwable caught) {
+            L.d(caught);
+            keepGoing();
+        }
+    }
+
+    private void showNotification(Notifications.Notification n) {
+        @StringRes int title;
+        String description = "";
+        @DrawableRes int icon;
+        @ColorInt int color;
+
+        switch (n.getType()) {
+            case "edit-user-talk":
+                description = getString(R.string.notification_talk, 
n.getAgent().getName(), n.getTitle().getFull());
+                icon = R.drawable.ic_chat_white_24dp;
+                title = R.string.notification_talk_title;
+                color = ContextCompat.getColor(getApplicationContext(), 
R.color.foundation_blue);
+                break;
+            case "reverted":
+                description = getString(R.string.notification_reverted, 
n.getAgent().getName(), n.getTitle().getFull());
+                icon = R.drawable.ic_rotate_left_white_24dp;
+                title = R.string.notification_reverted_title;
+                color = ContextCompat.getColor(getApplicationContext(), 
R.color.foundation_red);
+                break;
+            case "edit-thank":
+                description = getString(R.string.notification_thanks, 
n.getAgent().getName(), n.getTitle().getFull());
+                icon = R.drawable.ic_favorite_white_24dp;
+                title = R.string.notification_thanks_title;
+                color = ContextCompat.getColor(getApplicationContext(), 
R.color.foundation_green);
+                break;
+            default:
+                icon = R.drawable.ic_notification;
+                title = R.string.notification_generic_title;
+                color = ContextCompat.getColor(getApplicationContext(), 
R.color.foundation_gray);
+                break;
+        }
+
+        String pageUrl = "https://"; + 
WikipediaApp.getInstance().getWikiSite().mobileHost() + "/wiki/" + 
n.getTitle().getFull();
+        String agentUrl = "https://"; + 
WikipediaApp.getInstance().getWikiSite().mobileHost() + "/wiki/User:" + 
n.getAgent().getName();
+
+        Intent intent = ShareUtil.createChooserIntent(new 
Intent(Intent.ACTION_VIEW,
+                        Uri.parse(pageUrl)),
+                null, getApplicationContext());
+        PendingIntent pageIntent = 
PendingIntent.getActivity(getApplicationContext(), 0, intent, 
PendingIntent.FLAG_UPDATE_CURRENT);
+
+        intent = ShareUtil.createChooserIntent(new Intent(Intent.ACTION_VIEW,
+                        Uri.parse(agentUrl)),
+                null, getApplicationContext());
+        PendingIntent agentIntent = 
PendingIntent.getActivity(getApplicationContext(), 1, intent, 
PendingIntent.FLAG_UPDATE_CURRENT);
+
+        Notification notification = new 
NotificationCompat.Builder(getApplicationContext())
+                .setSmallIcon(icon)
+                .setColor(color)
+                .setContentTitle(getString(title))
+                .setContentText(description)
+                .setStyle(new 
NotificationCompat.BigTextStyle().bigText(description))
+                .setContentIntent(pageIntent)
+                .setAutoCancel(true)
+                .addAction(0, 
getString(R.string.notification_button_view_page), pageIntent)
+                .addAction(0, 
getString(R.string.notification_button_view_user), agentIntent)
+                .build();
+
+        NotificationManager manager = (NotificationManager) 
getSystemService(Context.NOTIFICATION_SERVICE);
+        manager.notify(n.getRevid(), notification);
+    }
+}
diff --git 
a/app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
 
b/app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
index aa6d665..550ab76 100644
--- 
a/app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
+++ 
b/app/src/main/java/org/wikipedia/useroption/dataclient/DefaultUserOptionDataClient.java
@@ -49,6 +49,20 @@
         throw new IOException(err == null ? rsp.message() : err.getDetails());
     }
 
+    @NonNull
+    @Override
+    public Notifications getNotifications() throws IOException {
+        Response<MwQueryResponse<QueryNotifications>> rsp = 
client.getNotifications().execute();
+        if (rsp.isSuccessful() && rsp.body().success()) {
+            //noinspection ConstantConditions
+            return rsp.body().query().notifications();
+        }
+        ServiceError err = rsp.body() == null || rsp.body().getError() == null
+                ? null
+                : rsp.body().getError();
+        throw new IOException(err == null ? rsp.message() : err.getDetails());
+    }
+
     @Override
     public void post(@NonNull UserOption option) throws IOException {
         Response<PostResponse> rsp = client.post(getToken(), option.key(), 
option.val()).execute();
@@ -102,8 +116,11 @@
     private interface Client {
         String ACTION = "w/api.php?format=json&formatversion=2&action=";
 
-        @GET(ACTION + "query&meta=userinfo&uiprop=options")
+        @GET(ACTION + 
"query&meta=userinfo&uiprop=options|hasmsg|editcount|unreadcount")
         @NonNull Call<MwQueryResponse<QueryUserInfo>> get();
+
+        @GET(ACTION + 
"query&meta=notifications&notfilter=!read&notprop=list&notwikis=enwiki|wikidatawiki")
+        @NonNull Call<MwQueryResponse<QueryNotifications>> getNotifications();
 
         @FormUrlEncoded
         @POST(ACTION + "options")
@@ -143,4 +160,12 @@
             return userInfo;
         }
     }
+
+    private static class QueryNotifications {
+        private Notifications notifications;
+
+        public Notifications notifications() {
+            return notifications;
+        }
+    }
 }
diff --git 
a/app/src/main/java/org/wikipedia/useroption/dataclient/Notifications.java 
b/app/src/main/java/org/wikipedia/useroption/dataclient/Notifications.java
new file mode 100644
index 0000000..3cd0a92
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/useroption/dataclient/Notifications.java
@@ -0,0 +1,58 @@
+package org.wikipedia.useroption.dataclient;
+
+import android.support.annotation.Nullable;
+
+public class Notifications {
+    @Nullable private Notification[] list;
+
+    @Nullable
+    public Notification[] getNotifications() {
+        return list;
+    }
+
+    public class Notification {
+        private String wiki;
+        private String id;
+        private String type;
+        private String category;
+        private int revid;
+
+        private NotificationTitle title;
+        private NotificationAgent agent;
+
+        public String getType() {
+            return type;
+        }
+
+        public NotificationAgent getAgent() {
+            return agent;
+        }
+
+        public NotificationTitle getTitle() {
+            return title;
+        }
+
+        public int getRevid() {
+            return revid;
+        }
+    }
+
+    public class NotificationTitle {
+        private String full;
+        private String text;
+        private String namespace;
+
+        public String getFull() {
+            return full;
+        }
+    }
+
+    public class NotificationAgent {
+        private String id;
+        private String name;
+
+        public String getName() {
+            return name;
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java 
b/app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java
index 9e01b25..0678aeb 100644
--- a/app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java
+++ b/app/src/main/java/org/wikipedia/useroption/dataclient/UserInfo.java
@@ -14,6 +14,8 @@
     @SerializedName("name")
     private String username;
     private int id;
+    private int editcount;
+    private int unreadcount;
 
     // Object type is any JSON type.
     @NonNull private Map<String, ?> options;
@@ -27,6 +29,14 @@
         return username;
     }
 
+    public int editCount() {
+        return editcount;
+    }
+
+    public int unreadCount() {
+        return unreadcount;
+    }
+
     @NonNull
     public Collection<UserOption> userjsOptions() {
         Collection<UserOption> ret = new ArrayList<>();
diff --git 
a/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
 
b/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
index 1e700dd..82a3e16 100644
--- 
a/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
+++ 
b/app/src/main/java/org/wikipedia/useroption/dataclient/UserOptionDataClient.java
@@ -8,6 +8,7 @@
 
 public interface UserOptionDataClient {
     @NonNull UserInfo get() throws IOException;
+    @NonNull Notifications getNotifications() throws IOException;
     void post(@NonNull UserOption option) throws IOException;
     void delete(@NonNull String key) throws IOException;
 }
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_chat_white_24dp.xml 
b/app/src/main/res/drawable/ic_chat_white_24dp.xml
new file mode 100644
index 0000000..bf19837
--- /dev/null
+++ b/app/src/main/res/drawable/ic_chat_white_24dp.xml
@@ -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="#FFFFFFFF"
+        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,-2zM6,9h12v2L6,11L6,9zM14,14L6,14v-2h8v2zM18,8L6,8L6,6h12v2z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_favorite_white_24dp.xml 
b/app/src/main/res/drawable/ic_favorite_white_24dp.xml
new file mode 100644
index 0000000..46cfb27
--- /dev/null
+++ b/app/src/main/res/drawable/ic_favorite_white_24dp.xml
@@ -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="#FFFFFFFF"
+        android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 
4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 
22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_rotate_left_white_24dp.xml 
b/app/src/main/res/drawable/ic_rotate_left_white_24dp.xml
new file mode 100644
index 0000000..2ecc667
--- /dev/null
+++ b/app/src/main/res/drawable/ic_rotate_left_white_24dp.xml
@@ -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="#FFFFFFFF"
+        android:pathData="M7.11,8.53L5.7,7.11C4.8,8.27 4.24,9.61 
4.07,11h2.02c0.14,-0.87 0.49,-1.72 1.02,-2.47zM6.09,13L4.07,13c0.17,1.39 
0.72,2.73 1.62,3.89l1.41,-1.42c-0.52,-0.75 -0.87,-1.59 
-1.01,-2.47zM7.1,18.32c1.16,0.9 2.51,1.44 3.9,1.61L11,17.9c-0.87,-0.15 
-1.71,-0.49 -2.46,-1.03L7.1,18.32zM13,4.07L13,1L8.45,5.55 
13,10L13,6.09c2.84,0.48 5,2.94 5,5.91s-2.16,5.43 -5,5.91v2.02c3.95,-0.49 
7,-3.85 7,-7.93s-3.05,-7.44 -7,-7.93z"/>
+</vector>
diff --git a/app/src/main/res/values-qq/strings.xml 
b/app/src/main/res/values-qq/strings.xml
index eab5ff3..3c4d004 100644
--- a/app/src/main/res/values-qq/strings.xml
+++ b/app/src/main/res/values-qq/strings.xml
@@ -428,6 +428,15 @@
   <string name="feed_featured_image_share_subject">Text included as the 
subject when a user shares an image from the Today\'s Featured Image feed 
card.</string>
   <string name="feed">Menu item label for exploring Wikipedia content through 
Feed cards.
 {{Identical|Explore}}</string>
+  <string name="notification_button_view_page">View page</string>
+  <string name="notification_button_view_user">Talk to user</string>
+  <string name="notification_generic_title">Title for any general notification 
from Wikipedia.</string>
+  <string name="notification_talk_title">Title for notification when the user 
receives a new message on their Talk page.</string>
+  <string name="notification_talk">Text of notification when the user receives 
a new message on their Talk page. The \"%1$s\" symbol corresponds to the user 
who left the message, and the \"%2$s\" symbol is the title of the talk page of 
the user.</string>
+  <string name="notification_reverted_title">Title for notification when an 
edit made by the user is reverted.</string>
+  <string name="notification_reverted">Text of notification when an edit made 
by the user is reverted. The \"%1$s\" symbol corresponds to the user who 
reverted the edit, and the \"%2$s\" symbol is the title of the page that was 
edited.</string>
+  <string name="notification_thanks_title">Title for notification when the 
user receives a Thanks from another user.</string>
+  <string name="notification_thanks">Text of notification when the user 
receives a Thanks from another user. The \"%1$s\" symbol corresponds to the 
user who sent the thanks, and the \"%2$s\" symbol is the title of the page for 
which the user was thanked.</string>
   <string name="view_card_footer_button">Feed card button label for requesting 
more similar cards.</string>
   <string name="most_read_list_card_title">Feed card title for recently 
popular articles.
 {{Identical|Trending}}</string>
diff --git a/app/src/main/res/values/strings.xml 
b/app/src/main/res/values/strings.xml
index fe07690..b87ccf8 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -304,6 +304,18 @@
     <string name="user_option_sync_label">Preferences</string>
     <!-- /User options -->
 
+    <!-- Notifications -->
+    <string name="notification_button_view_page">View page</string>
+    <string name="notification_button_view_user">Talk to user</string>
+    <string name="notification_generic_title">Notification on 
Wikipedia</string>
+    <string name="notification_talk_title">New message on Wikipedia</string>
+    <string name="notification_talk">%1$s left a message on your Talk page 
\"%2$s\"</string>
+    <string name="notification_reverted_title">Reverted edit</string>
+    <string name="notification_reverted">Your edit to the page \"%2$s\" was 
reverted by %1$s.</string>
+    <string name="notification_thanks_title">You\'ve been thanked!</string>
+    <string name="notification_thanks">%1$s thanked you for your edit on the 
page \"%2$s\"</string>
+    <!-- /Notifications -->
+
     <!-- The Feed -->
     <string name="view_continue_reading_card_title">Continue reading</string>
     <string name="view_because_you_read_card_title">Because you read</string>

-- 
To view, visit https://gerrit.wikimedia.org/r/325627
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic2ab7bc402064cb8bf7351f6482b5b27a8925b03
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Dbrant <dbr...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to