jenkins-bot has submitted this change and it was merged. Change subject: Integrate most read ......................................................................
Integrate most read Bug: T129082 Change-Id: I688329f705646d917e00662be57385bc2cd4e50a --- M app/src/main/java/org/wikipedia/feed/FeedCoordinator.java M app/src/main/java/org/wikipedia/feed/demo/IntegerListCard.java A app/src/main/java/org/wikipedia/feed/mostread/MostReadCardView.java M app/src/main/java/org/wikipedia/feed/mostread/MostReadClient.java A app/src/main/java/org/wikipedia/feed/mostread/MostReadItemCard.java A app/src/main/java/org/wikipedia/feed/mostread/MostReadListCard.java M app/src/main/java/org/wikipedia/feed/view/FeedRecyclerAdapter.java M app/src/main/res/values/strings_no_translate.xml M app/src/test/java/org/wikipedia/feed/mostread/MostReadClientTest.java 9 files changed, 214 insertions(+), 23 deletions(-) Approvals: Mholloway: Looks good to me, but someone else must approve Dbrant: Looks good to me, approved jenkins-bot: Verified diff --git a/app/src/main/java/org/wikipedia/feed/FeedCoordinator.java b/app/src/main/java/org/wikipedia/feed/FeedCoordinator.java index e8a2326..33ad66e 100644 --- a/app/src/main/java/org/wikipedia/feed/FeedCoordinator.java +++ b/app/src/main/java/org/wikipedia/feed/FeedCoordinator.java @@ -6,6 +6,7 @@ import org.wikipedia.feed.becauseyouread.BecauseYouReadClient; import org.wikipedia.feed.continuereading.ContinueReadingClient; import org.wikipedia.feed.demo.IntegerListClient; +import org.wikipedia.feed.mostread.MostReadClient; import org.wikipedia.feed.searchbar.SearchClient; public class FeedCoordinator extends FeedCoordinatorBase { @@ -25,6 +26,7 @@ addPendingClient(new BecauseYouReadClient()); addPendingClient(new ContinueReadingClient()); addPendingClient(new IntegerListClient()); + addPendingClient(new MostReadClient()); } diff --git a/app/src/main/java/org/wikipedia/feed/demo/IntegerListCard.java b/app/src/main/java/org/wikipedia/feed/demo/IntegerListCard.java index b7ade21..f6e7b5d 100644 --- a/app/src/main/java/org/wikipedia/feed/demo/IntegerListCard.java +++ b/app/src/main/java/org/wikipedia/feed/demo/IntegerListCard.java @@ -16,7 +16,7 @@ } @NonNull @Override public String title() { - return "Trending articles"; + return "In the news"; } @Nullable @Override public String subtitle() { @@ -24,7 +24,7 @@ } @Nullable @Override public String footer() { - return "All top read articles on Fri, April 08"; + return "More news from Fri, April 08"; } private static List<IntegerListItemCard> newItems() { @@ -37,4 +37,4 @@ } return items; } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/wikipedia/feed/mostread/MostReadCardView.java b/app/src/main/java/org/wikipedia/feed/mostread/MostReadCardView.java new file mode 100644 index 0000000..081bc9b --- /dev/null +++ b/app/src/main/java/org/wikipedia/feed/mostread/MostReadCardView.java @@ -0,0 +1,53 @@ +package org.wikipedia.feed.mostread; + +import android.content.Context; +import android.support.annotation.NonNull; + +import org.wikipedia.feed.demo.IntegerListCard; +import org.wikipedia.feed.view.CardFooterView; +import org.wikipedia.feed.view.CardHeaderView; +import org.wikipedia.feed.view.ListCardItemView; +import org.wikipedia.feed.view.ListCardView; +import org.wikipedia.views.DefaultViewHolder; + +import java.util.List; + +public class MostReadCardView extends ListCardView<IntegerListCard> { + public MostReadCardView(Context context) { + super(context); + } + + public void set(@NonNull MostReadListCard card) { + header(card); + footer(card); + set(new RecyclerAdapter(card.items())); + } + + private void header(@NonNull MostReadListCard card) { + CardHeaderView header = new CardHeaderView(getContext()) + .setTitle(card.title()) + .setSubtitle(card.subtitle()); + header(header); + } + + private void footer(@NonNull MostReadListCard card) { + CardFooterView footer = new CardFooterView(getContext()) + .setText(card.footer()); + footer.setVisibility(card.items().size() > 2 ? VISIBLE : GONE); + footer(footer); + } + + private static class RecyclerAdapter extends ListCardView.RecyclerAdapter<MostReadItemCard> { + RecyclerAdapter(@NonNull List<MostReadItemCard> items) { + super(items); + } + + @Override public void onBindViewHolder(DefaultViewHolder<ListCardItemView> holder, + int position) { + MostReadItemCard card = item(position); + holder.getView().setTitle(card.title()); + holder.getView().setSubtitle(card.subtitle()); + holder.getView().setImage(card.image()); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/wikipedia/feed/mostread/MostReadClient.java b/app/src/main/java/org/wikipedia/feed/mostread/MostReadClient.java index ffce308..c654f7f 100644 --- a/app/src/main/java/org/wikipedia/feed/mostread/MostReadClient.java +++ b/app/src/main/java/org/wikipedia/feed/mostread/MostReadClient.java @@ -1,14 +1,20 @@ package org.wikipedia.feed.mostread; +import android.content.Context; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import org.apache.commons.lang3.StringUtils; import org.wikipedia.Site; import org.wikipedia.dataclient.retrofit.RbCachedService; +import org.wikipedia.feed.FeedClient; +import org.wikipedia.feed.model.Card; import org.wikipedia.util.log.L; import java.util.Calendar; +import java.util.Collections; +import java.util.List; import java.util.TimeZone; import retrofit2.Call; @@ -16,24 +22,36 @@ import retrofit2.http.GET; import retrofit2.http.Path; -public class MostReadClient { - public interface Callback { - void success(@NonNull MostReadArticles articles); - } - +public class MostReadClient implements FeedClient { @NonNull private final RbCachedService<Service> cachedService = new RbCachedService<>(Service.class); + @Nullable private Call<MostReadArticles> call; - public void request(@NonNull Site site, @NonNull Callback cb) { - Calendar now = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - request(cachedService.service(site), now, cb); + @Override public void request(@NonNull Context context, @NonNull Site site, int age, + @NonNull Callback cb) { + cancel(); + Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC")); + + time.add(Calendar.DAY_OF_MONTH, -(age + 1)); + + call = request(cachedService.service(site), time, cb); } - @VisibleForTesting void request(@NonNull Service service, @NonNull Calendar date, - @NonNull Callback cb) { + // Only handles last request made. + @Override public void cancel() { + if (call != null) { + call.cancel(); + call = null; + } + } + + @VisibleForTesting Call<MostReadArticles> request(@NonNull Service service, @NonNull Calendar date, + @NonNull Callback cb) { int year = date.get(Calendar.YEAR); String month = leftPad(date.get(Calendar.MONTH) + 1); String day = leftPad(date.get(Calendar.DAY_OF_MONTH)); - service.get(year, month, day).enqueue(new CallbackAdapter(cb)); + @SuppressWarnings("checkstyle:hiddenfield") Call<MostReadArticles> call = service.get(year, month, day); + call.enqueue(new CallbackAdapter(cb)); + return call; } @NonNull private String leftPad(int x) { @@ -57,7 +75,9 @@ @Override public void onResponse(Call<MostReadArticles> call, Response<MostReadArticles> response) { if (response.isSuccessful()) { - cb.success(response.body()); + MostReadArticles result = response.body(); + List<? extends Card> cards = Collections.singletonList(new MostReadListCard(result)); + cb.success(cards); } else { L.v(response.message()); } @@ -67,4 +87,4 @@ L.v(t); } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/wikipedia/feed/mostread/MostReadItemCard.java b/app/src/main/java/org/wikipedia/feed/mostread/MostReadItemCard.java new file mode 100644 index 0000000..c966acd --- /dev/null +++ b/app/src/main/java/org/wikipedia/feed/mostread/MostReadItemCard.java @@ -0,0 +1,30 @@ +package org.wikipedia.feed.mostread; + +import android.net.Uri; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import org.wikipedia.Constants; +import org.wikipedia.feed.model.Card; +import org.wikipedia.util.log.L; + +public class MostReadItemCard extends Card { + @NonNull private final MostReadArticle article; + + public MostReadItemCard(@NonNull MostReadArticle article) { + this.article = article; + } + + @NonNull @Override public String title() { + return article.normalizedTitle(); + } + + @Nullable @Override public String subtitle() { + return article.description(); + } + + @Nullable @Override public Uri image() { + L.d(article.thumbnails().toString()); + return article.thumbnails().get(Constants.PREFERRED_THUMB_SIZE); + } +} \ 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 new file mode 100644 index 0000000..212d769 --- /dev/null +++ b/app/src/main/java/org/wikipedia/feed/mostread/MostReadListCard.java @@ -0,0 +1,70 @@ +package org.wikipedia.feed.mostread; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.support.annotation.VisibleForTesting; + +import org.wikipedia.R; +import org.wikipedia.WikipediaApp; +import org.wikipedia.feed.model.ListCard; + +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class MostReadListCard extends ListCard<MostReadItemCard> { + private static final int MAX_SIZE = 5; + + @NonNull private final MostReadArticles articles; + + public MostReadListCard(@NonNull MostReadArticles articles) { + super(toItems(articles.articles())); + this.articles = articles; + } + + @NonNull @Override public String title() { + return getString(R.string.most_read_list_card_title, date()); + } + + @Nullable @Override public String subtitle() { + return date(); + } + + @Nullable @Override public String footer() { + // todo: the mocks show a more terse date used here but this will probably require TWN + // support. We should investigate localization support in date libraries such as + // Joda-Time and how TWN solves this classic problem. + return getString(R.string.most_read_list_card_footer, date()); + } + + @VisibleForTesting @NonNull Date getDate() { + return articles.date(); + } + + @NonNull private static List<MostReadItemCard> toItems(@NonNull List<MostReadArticle> articles) { + List<MostReadItemCard> cards = new ArrayList<>(); + for (MostReadArticle article : articles) { + cards.add(new MostReadItemCard(article)); + } + return cards.subList(0, Math.min(cards.size(), MAX_SIZE)); + } + + @NonNull private String date() { + // todo: consider allowing TWN date formats. It would be useful to have but might be + // difficult for translators to write correct format specifiers without being able to + // test them. + DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context()); + return dateFormat.format(articles.date()); + } + + @NonNull private String getString(@StringRes int id, @Nullable Object... formatArgs) { + return context().getString(id, formatArgs); + } + + @NonNull private Context context() { + return WikipediaApp.getInstance(); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/wikipedia/feed/view/FeedRecyclerAdapter.java b/app/src/main/java/org/wikipedia/feed/view/FeedRecyclerAdapter.java index 7771aca..5e4962a 100644 --- a/app/src/main/java/org/wikipedia/feed/view/FeedRecyclerAdapter.java +++ b/app/src/main/java/org/wikipedia/feed/view/FeedRecyclerAdapter.java @@ -12,6 +12,8 @@ import org.wikipedia.feed.demo.IntegerListCard; import org.wikipedia.feed.demo.IntegerListCardView; import org.wikipedia.feed.model.Card; +import org.wikipedia.feed.mostread.MostReadCardView; +import org.wikipedia.feed.mostread.MostReadListCard; import org.wikipedia.feed.searchbar.SearchCard; import org.wikipedia.feed.searchbar.SearchCardView; import org.wikipedia.views.DefaultRecyclerAdapter; @@ -23,6 +25,7 @@ private static final int VIEW_TYPE_SEARCH_BAR = 0; private static final int VIEW_TYPE_CONTINUE_READING = 1; private static final int VIEW_TYPE_BECAUSE_YOU_READ = 2; + private static final int VIEW_TYPE_MOST_READ = 3; private static final int VIEW_TYPE_INTEGER_LIST = 100; public FeedRecyclerAdapter(@NonNull List<Card> items) { @@ -45,6 +48,8 @@ ((BecauseYouReadCardView) view).set((BecauseYouReadCard) item); } else if (view instanceof SearchCardView) { ((SearchCardView) view).set((SearchCard) item); + } else if (view instanceof MostReadCardView) { + ((MostReadCardView) view).set((MostReadListCard) item); } else { throw new IllegalStateException("Unknown type=" + view.getClass()); } @@ -60,6 +65,8 @@ return VIEW_TYPE_BECAUSE_YOU_READ; } else if (item instanceof SearchCard) { return VIEW_TYPE_SEARCH_BAR; + } else if (item instanceof MostReadListCard) { + return VIEW_TYPE_MOST_READ; } else { throw new IllegalStateException("Unknown type=" + item.getClass()); } @@ -75,8 +82,10 @@ return new BecauseYouReadCardView(context); case VIEW_TYPE_SEARCH_BAR: return new SearchCardView(context); + case VIEW_TYPE_MOST_READ: + return new MostReadCardView(context); default: throw new IllegalArgumentException("viewType=" + viewType); } } -} \ No newline at end of file +} diff --git a/app/src/main/res/values/strings_no_translate.xml b/app/src/main/res/values/strings_no_translate.xml index 2bb7eb6..a596a53 100644 --- a/app/src/main/res/values/strings_no_translate.xml +++ b/app/src/main/res/values/strings_no_translate.xml @@ -46,6 +46,8 @@ <string name="activity_feed_title">@string/feed</string> <string name="nav_item_feed">@string/feed</string> <string name="view_card_footer_button">See more</string> + <string name="most_read_list_card_title">Top read on %s</string> + <string name="most_read_list_card_footer">All top read articles on English Wikipedia</string> <plurals name="view_continue_reading_card_subtitle"> <item quantity="one">1 day ago</item> diff --git a/app/src/test/java/org/wikipedia/feed/mostread/MostReadClientTest.java b/app/src/test/java/org/wikipedia/feed/mostread/MostReadClientTest.java index b92866f..2c9bda3 100644 --- a/app/src/test/java/org/wikipedia/feed/mostread/MostReadClientTest.java +++ b/app/src/test/java/org/wikipedia/feed/mostread/MostReadClientTest.java @@ -4,21 +4,24 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; -import org.wikipedia.feed.mostread.MostReadClient.Callback; +import org.wikipedia.feed.FeedClient.Callback; +import org.wikipedia.feed.model.Card; import org.wikipedia.feed.mostread.MostReadClient.Service; import org.wikipedia.test.MockWebServerTest; import java.util.Calendar; import java.util.GregorianCalendar; +import java.util.List; import java.util.TimeZone; import okhttp3.mockwebserver.RecordedRequest; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; -import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyListOf; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -52,7 +55,7 @@ RecordedRequest req = server().takeRequest(); assertRequestIssued(req, "2016/06/01"); - verify(cb, never()).success(any(MostReadArticles.class)); + verify(cb, never()).success(anyListOf(Card.class)); } private void assertRequestIssued(@NonNull RecordedRequest req, @NonNull String date) { @@ -60,12 +63,14 @@ } private void assertCallbackSuccess(@NonNull Callback cb, @NonNull Calendar date) { - ArgumentCaptor<MostReadArticles> captor = ArgumentCaptor.forClass(MostReadArticles.class); + @SuppressWarnings({"unchecked", "rawtypes"}) + ArgumentCaptor<List<MostReadListCard>> captor = ArgumentCaptor.forClass((Class) List.class); verify(cb).success(captor.capture()); - MostReadArticles rsp = captor.getValue(); + List<MostReadListCard> rsp = captor.getValue(); assertThat(rsp, notNullValue()); - assertThat(rsp.date(), is(date.getTime())); + assertThat(rsp.size(), greaterThan(0)); + assertThat(rsp.get(0).getDate(), is(date.getTime())); } @NonNull private Calendar calendar(int year, int month, int day) throws Throwable { -- To view, visit https://gerrit.wikimedia.org/r/294380 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I688329f705646d917e00662be57385bc2cd4e50a Gerrit-PatchSet: 5 Gerrit-Project: apps/android/wikipedia Gerrit-Branch: master Gerrit-Owner: Niedzielski <sniedziel...@wikimedia.org> Gerrit-Reviewer: BearND <bsitzm...@wikimedia.org> Gerrit-Reviewer: Brion VIBBER <br...@wikimedia.org> Gerrit-Reviewer: Dbrant <dbr...@wikimedia.org> Gerrit-Reviewer: Mholloway <mhollo...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits