Dbrant has uploaded a new change for review.

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

Change subject: Persist state of dismissed feed cards.
......................................................................

Persist state of dismissed feed cards.

This implements a rather simple (for now) way of persisting the state of
dismissed cards. Although, due to its implementation, it does have some
"smarts" to it. It works by persisting the hashCode of dismissed cards,
and it's up to each card type to implement its own hashCode(). This has
the following effect:

- Cards that are dependent on the current day (e.g. trending) create a
  hash code based on the date, so that the user won't see that card again
  for that date. The user will, however, continue to see that type of card
  for other dates.
- Cards that are dependent on a "title" create a hashCode based on the
  title. This means that if the user dismisses a because-you-read card for
  a certain title, they won't see it again, regardless of which day they
  visit the feed, or if they visit that page again.

Additional notes:

- Undo still works as expected.
- There's a maximum of 100 persisted cards (rotated in FIFO order), so
  that the storage mechanism of saving them in SharedPreferences is not
  stressed unnecessarily.

Bug: T138981
Change-Id: Ie3d8432832341f6ed161b0ded1df22b4edc363df
---
M app/src/main/java/org/wikipedia/feed/FeedCoordinatorBase.java
M app/src/main/java/org/wikipedia/feed/becauseyouread/BecauseYouReadCard.java
M app/src/main/java/org/wikipedia/feed/continuereading/ContinueReadingCard.java
M app/src/main/java/org/wikipedia/feed/featured/FeaturedArticleCard.java
M app/src/main/java/org/wikipedia/feed/image/FeaturedImageCard.java
A app/src/main/java/org/wikipedia/feed/model/HiddenCard.java
M app/src/main/java/org/wikipedia/feed/mostread/MostReadListCard.java
M app/src/main/java/org/wikipedia/feed/news/NewsListCard.java
A app/src/main/java/org/wikipedia/json/HiddenCardUnmarshaller.java
M app/src/main/java/org/wikipedia/settings/Prefs.java
M app/src/main/res/values/preference_keys.xml
11 files changed, 144 insertions(+), 1 deletion(-)


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

diff --git a/app/src/main/java/org/wikipedia/feed/FeedCoordinatorBase.java 
b/app/src/main/java/org/wikipedia/feed/FeedCoordinatorBase.java
index eeba693..722e528 100644
--- a/app/src/main/java/org/wikipedia/feed/FeedCoordinatorBase.java
+++ b/app/src/main/java/org/wikipedia/feed/FeedCoordinatorBase.java
@@ -7,12 +7,16 @@
 import org.wikipedia.Site;
 import org.wikipedia.feed.dataclient.FeedClient;
 import org.wikipedia.feed.model.Card;
+import org.wikipedia.feed.model.HiddenCard;
 import org.wikipedia.feed.progress.ProgressCard;
+import org.wikipedia.feed.view.FeedRecyclerAdapter;
+import org.wikipedia.settings.Prefs;
 
 import java.util.ArrayList;
 import java.util.List;
 
 public abstract class FeedCoordinatorBase {
+    private static final int MAX_HIDDEN_CARDS = 100;
 
     public interface FeedUpdateListener {
         void update(List<Card> cards);
@@ -26,9 +30,11 @@
     private List<FeedClient> pendingClients = new ArrayList<>();
     private FeedClient.Callback exhaustionClientCallback = new 
ExhaustionClientCallback();
     private Card progressCard = new ProgressCard();
+    private List<HiddenCard> hiddenCards = new ArrayList<>();
 
     public FeedCoordinatorBase(@NonNull Context context) {
         this.context = context;
+        hiddenCards.addAll(Prefs.getHiddenCards());
     }
 
     @NonNull
@@ -72,6 +78,7 @@
     public int dismissCard(@NonNull Card card) {
         int position = cards.indexOf(card);
         cards.remove(card);
+        addHiddenCard(card);
         if (updateListener != null) {
             updateListener.update(cards);
         }
@@ -80,6 +87,7 @@
 
     public void insertCard(@NonNull Card card, int position) {
         cards.add(position, card);
+        removeHiddenCard(card);
         if (updateListener != null) {
             updateListener.update(cards);
         }
@@ -101,7 +109,11 @@
     private class ExhaustionClientCallback implements FeedClient.Callback {
         @Override
         public void success(@NonNull List<? extends Card> cardList) {
-            cards.addAll(cardList);
+            for (Card card : cardList) {
+                if (!isCardHidden(card)) {
+                    cards.add(card);
+                }
+            }
             appendProgressCard(cards);
             if (updateListener != null) {
                 updateListener.update(cards);
@@ -121,4 +133,33 @@
         cards.remove(progressCard);
         cards.add(progressCard);
     }
+
+    private void addHiddenCard(@NonNull Card card) {
+        hiddenCards.add(new HiddenCard(FeedRecyclerAdapter.getCardType(card), 
card.hashCode()));
+        while (hiddenCards.size() > MAX_HIDDEN_CARDS) {
+            hiddenCards.remove(0);
+        }
+        Prefs.setHiddenCards(hiddenCards);
+    }
+
+    private boolean isCardHidden(@NonNull Card card) {
+        int cardType = FeedRecyclerAdapter.getCardType(card);
+        for (HiddenCard hiddenCard : hiddenCards) {
+            if (hiddenCard.getType() == cardType && hiddenCard.getHashCode() 
== card.hashCode()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void removeHiddenCard(@NonNull Card card) {
+        int cardType = FeedRecyclerAdapter.getCardType(card);
+        for (HiddenCard hiddenCard : hiddenCards) {
+            if (hiddenCard.getType() == cardType && hiddenCard.getHashCode() 
== card.hashCode()) {
+                hiddenCards.remove(hiddenCard);
+                Prefs.setHiddenCards(hiddenCards);
+                return;
+            }
+        }
+    }
 }
diff --git 
a/app/src/main/java/org/wikipedia/feed/becauseyouread/BecauseYouReadCard.java 
b/app/src/main/java/org/wikipedia/feed/becauseyouread/BecauseYouReadCard.java
index 9120391..de3616d 100644
--- 
a/app/src/main/java/org/wikipedia/feed/becauseyouread/BecauseYouReadCard.java
+++ 
b/app/src/main/java/org/wikipedia/feed/becauseyouread/BecauseYouReadCard.java
@@ -49,4 +49,9 @@
         long lastVisited = entry.getTimestamp().getTime();
         return TimeUnit.MILLISECONDS.toDays(now - lastVisited);
     }
+
+    @Override
+    public int hashCode() {
+        return entry.getTitle().hashCode();
+    }
 }
\ No newline at end of file
diff --git 
a/app/src/main/java/org/wikipedia/feed/continuereading/ContinueReadingCard.java 
b/app/src/main/java/org/wikipedia/feed/continuereading/ContinueReadingCard.java
index f7413c0..2f2fd6c 100644
--- 
a/app/src/main/java/org/wikipedia/feed/continuereading/ContinueReadingCard.java
+++ 
b/app/src/main/java/org/wikipedia/feed/continuereading/ContinueReadingCard.java
@@ -40,4 +40,9 @@
         long lastVisited = entry.getTimestamp().getTime();
         return TimeUnit.MILLISECONDS.toDays(now - lastVisited);
     }
+
+    @Override
+    public int hashCode() {
+        return entry.getTitle().hashCode();
+    }
 }
\ No newline at end of file
diff --git 
a/app/src/main/java/org/wikipedia/feed/featured/FeaturedArticleCard.java 
b/app/src/main/java/org/wikipedia/feed/featured/FeaturedArticleCard.java
index 34bb8eb..91fb52b 100644
--- a/app/src/main/java/org/wikipedia/feed/featured/FeaturedArticleCard.java
+++ b/app/src/main/java/org/wikipedia/feed/featured/FeaturedArticleCard.java
@@ -75,4 +75,9 @@
         title.setDescription(articleSubtitle());
         return new HistoryEntry(title, source);
     }
+
+    @Override
+    public int hashCode() {
+        return page.title().hashCode();
+    }
 }
diff --git a/app/src/main/java/org/wikipedia/feed/image/FeaturedImageCard.java 
b/app/src/main/java/org/wikipedia/feed/image/FeaturedImageCard.java
index 75c720a..1ed0b49 100644
--- a/app/src/main/java/org/wikipedia/feed/image/FeaturedImageCard.java
+++ b/app/src/main/java/org/wikipedia/feed/image/FeaturedImageCard.java
@@ -71,4 +71,9 @@
     public String descriptionLang() {
         return featuredImage.descriptionLang();
     }
+
+    @Override
+    public int hashCode() {
+        return featuredImage.title().hashCode();
+    }
 }
diff --git a/app/src/main/java/org/wikipedia/feed/model/HiddenCard.java 
b/app/src/main/java/org/wikipedia/feed/model/HiddenCard.java
new file mode 100644
index 0000000..3d19bfa
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/feed/model/HiddenCard.java
@@ -0,0 +1,19 @@
+package org.wikipedia.feed.model;
+
+public class HiddenCard {
+    private int type;
+    private int hashCode;
+
+    public HiddenCard(int type, int hashCode) {
+        this.type = type;
+        this.hashCode = hashCode;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public int getHashCode() {
+        return hashCode;
+    }
+}
\ No newline at end of file
diff --git 
a/app/src/main/java/org/wikipedia/feed/mostread/MostReadListCard.java 
b/app/src/main/java/org/wikipedia/feed/mostread/MostReadListCard.java
index dd9be77..fc0669a 100644
--- a/app/src/main/java/org/wikipedia/feed/mostread/MostReadListCard.java
+++ b/app/src/main/java/org/wikipedia/feed/mostread/MostReadListCard.java
@@ -13,6 +13,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 public class MostReadListCard extends ListCard<MostReadItemCard> {
     private static final int MAX_SIZE = 5;
@@ -48,4 +49,9 @@
     @NonNull private Context context() {
         return WikipediaApp.getInstance();
     }
+
+    @Override
+    public int hashCode() {
+        return (int) TimeUnit.MILLISECONDS.toDays(articles.date().getTime());
+    }
 }
diff --git a/app/src/main/java/org/wikipedia/feed/news/NewsListCard.java 
b/app/src/main/java/org/wikipedia/feed/news/NewsListCard.java
index 58d72fe..47832a3 100644
--- a/app/src/main/java/org/wikipedia/feed/news/NewsListCard.java
+++ b/app/src/main/java/org/wikipedia/feed/news/NewsListCard.java
@@ -8,6 +8,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 public class NewsListCard extends ListCard<NewsItemCard> {
     @NonNull private UtcDate age;
@@ -36,4 +37,9 @@
         }
         return itemCards;
     }
+
+    @Override
+    public int hashCode() {
+        return (int) 
TimeUnit.MILLISECONDS.toDays(age.baseCalendar().getTime().getTime());
+    }
 }
diff --git a/app/src/main/java/org/wikipedia/json/HiddenCardUnmarshaller.java 
b/app/src/main/java/org/wikipedia/json/HiddenCardUnmarshaller.java
new file mode 100644
index 0000000..2f755a6
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/json/HiddenCardUnmarshaller.java
@@ -0,0 +1,33 @@
+package org.wikipedia.json;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.google.gson.reflect.TypeToken;
+
+import org.wikipedia.crash.RemoteLogException;
+import org.wikipedia.feed.model.HiddenCard;
+import org.wikipedia.util.log.L;
+
+import java.util.Collections;
+import java.util.List;
+
+public final class HiddenCardUnmarshaller {
+    private static final TypeToken<List<HiddenCard>> TYPE_TOKEN = new 
TypeToken<List<HiddenCard>>() { };
+
+    @NonNull public static List<HiddenCard> unmarshal(@Nullable String json) {
+        List<HiddenCard> object = null;
+        try {
+            object = GsonUnmarshaller.unmarshal(TYPE_TOKEN, json);
+        } catch (Exception e) {
+            // Catch all. Any Exception can be thrown when unmarshalling.
+            L.logRemoteErrorIfProd(new RemoteLogException(e).put("json", 
json));
+        }
+        if (object == null) {
+            object = Collections.emptyList();
+        }
+        return object;
+    }
+
+    private HiddenCardUnmarshaller() { }
+}
diff --git a/app/src/main/java/org/wikipedia/settings/Prefs.java 
b/app/src/main/java/org/wikipedia/settings/Prefs.java
index 4004470..09cb7b8 100644
--- a/app/src/main/java/org/wikipedia/settings/Prefs.java
+++ b/app/src/main/java/org/wikipedia/settings/Prefs.java
@@ -10,7 +10,9 @@
 import org.wikipedia.WikipediaApp;
 import org.wikipedia.analytics.SessionData;
 import org.wikipedia.analytics.SessionFunnel;
+import org.wikipedia.feed.model.HiddenCard;
 import org.wikipedia.json.GsonMarshaller;
+import org.wikipedia.json.HiddenCardUnmarshaller;
 import org.wikipedia.json.SessionUnmarshaller;
 import org.wikipedia.json.TabUnmarshaller;
 import org.wikipedia.page.tabs.Tab;
@@ -229,6 +231,21 @@
         remove(R.string.preference_key_tabs);
     }
 
+    public static void setHiddenCards(@NonNull List<HiddenCard> cards) {
+        setString(R.string.preference_key_feed_hidden_cards, 
GsonMarshaller.marshal(cards));
+    }
+
+    @NonNull
+    public static List<HiddenCard> getHiddenCards() {
+        return hasHiddenCards()
+                ? 
HiddenCardUnmarshaller.unmarshal(getString(R.string.preference_key_feed_hidden_cards,
 null))
+                : Collections.<HiddenCard>emptyList();
+    }
+
+    public static boolean hasHiddenCards() {
+        return contains(R.string.preference_key_feed_hidden_cards);
+    }
+
     public static void setSessionData(@NonNull SessionData data) {
         setString(R.string.preference_key_session_data, 
GsonMarshaller.marshal(data));
     }
diff --git a/app/src/main/res/values/preference_keys.xml 
b/app/src/main/res/values/preference_keys.xml
index 5a27499..dda1631 100644
--- a/app/src/main/res/values/preference_keys.xml
+++ b/app/src/main/res/values/preference_keys.xml
@@ -45,4 +45,5 @@
     <string 
name="preference_key_reading_list_page_sort_mode">readingListPageSortMode</string>
     <string 
name="preference_key_reading_list_page_delete_tutorial_enabled">readingListPageDeleteTutorialEnabled</string>
     <string name="preference_key_page_last_shown">pageLastShown</string>
+    <string name="preference_key_feed_hidden_cards">feedHiddenCards</string>
 </resources>

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie3d8432832341f6ed161b0ded1df22b4edc363df
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Dbrant <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to