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¬filter=!read¬prop=list¬wikis=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