Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(992)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/widget/DateDividedAdapter.java

Issue 2670083002: [Download Home] Displaying offline page bundle per day (Closed)
Patch Set: Filter out pages before adding to DateDividedAdapter Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.widget; 5 package org.chromium.chrome.browser.widget;
6 6
7 import android.os.AsyncTask; 7 import android.os.AsyncTask;
8 import android.support.v7.widget.RecyclerView; 8 import android.support.v7.widget.RecyclerView;
9 import android.support.v7.widget.RecyclerView.Adapter; 9 import android.support.v7.widget.RecyclerView.Adapter;
10 import android.support.v7.widget.RecyclerView.ViewHolder; 10 import android.support.v7.widget.RecyclerView.ViewHolder;
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 mTextView.setText(builder); 142 mTextView.setText(builder);
143 } 143 }
144 } 144 }
145 145
146 protected static class BasicViewHolder extends RecyclerView.ViewHolder { 146 protected static class BasicViewHolder extends RecyclerView.ViewHolder {
147 public BasicViewHolder(View itemView) { 147 public BasicViewHolder(View itemView) {
148 super(itemView); 148 super(itemView);
149 } 149 }
150 } 150 }
151 151
152 protected static class SubsectionHeaderViewHolder extends RecyclerView.ViewH older {
153 private View mView;
154
155 public SubsectionHeaderViewHolder(View itemView) {
156 super(itemView);
157 mView = itemView;
158 }
159
160 public View getView() {
161 return mView;
162 }
163 }
164
152 /** 165 /**
153 * A bucket of items with the same date. 166 * A bucket of items with the same date.
154 */ 167 */
155 protected static class ItemGroup { 168 public static class ItemGroup {
gone 2017/02/15 23:58:10 Make this protected again.
shaktisahu 2017/02/16 06:07:07 I am subclassing this from DownloadItemGroup which
156 private final Date mDate; 169 private final Date mDate;
157 private final List<TimedItem> mItems = new ArrayList<>(); 170 private final List<TimedItem> mItems = new ArrayList<>();
158 171
159 /** Index of the header, relative to the full list. Must be set only on ce.*/ 172 /** Index of the header, relative to the full list. Must be set only on ce.*/
160 private int mIndex; 173 private int mIndex;
161 174
162 private boolean mIsSorted; 175 private boolean mIsSorted;
163 private boolean mIsListHeader; 176 private boolean mIsListHeader;
164 private boolean mIsListFooter; 177 private boolean mIsListFooter;
165 178
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 if (index == 0 || mIsListHeader || mIsListFooter) return null; 233 if (index == 0 || mIsListHeader || mIsListFooter) return null;
221 234
222 sortIfNeeded(); 235 sortIfNeeded();
223 return mItems.get(index - 1); 236 return mItems.get(index - 1);
224 } 237 }
225 238
226 /** 239 /**
227 * Rather than sorting the list each time a new item is added, the list is sorted when 240 * Rather than sorting the list each time a new item is added, the list is sorted when
228 * something requires a correct ordering of the items. 241 * something requires a correct ordering of the items.
229 */ 242 */
230 private void sortIfNeeded() { 243 protected void sortIfNeeded() {
231 if (mIsSorted) return; 244 if (mIsSorted) return;
232 mIsSorted = true; 245 mIsSorted = true;
233 246
234 Collections.sort(mItems, new Comparator<TimedItem>() { 247 Collections.sort(mItems, new Comparator<TimedItem>() {
235 @Override 248 @Override
236 public int compare(TimedItem lhs, TimedItem rhs) { 249 public int compare(TimedItem lhs, TimedItem rhs) {
237 // More recent items are listed first. Ideally we'd use Lon g.compare, but that 250 return compareItem(lhs, rhs);
238 // is an API level 19 call for some inexplicable reason.
239 long timeDelta = lhs.getTimestamp() - rhs.getTimestamp();
240 if (timeDelta > 0) {
241 return -1;
242 } else if (timeDelta == 0) {
243 return 0;
244 } else {
245 return 1;
246 }
247 } 251 }
248 }); 252 });
249 } 253 }
254
255 protected int compareItem(TimedItem lhs, TimedItem rhs) {
256 // More recent items are listed first. Ideally we'd use Long.compar e, but that
257 // is an API level 19 call for some inexplicable reason.
258 long timeDelta = lhs.getTimestamp() - rhs.getTimestamp();
259 if (timeDelta > 0) {
260 return -1;
261 } else if (timeDelta == 0) {
262 return 0;
263 } else {
264 return 1;
265 }
266 }
250 } 267 }
251 268
252 // Cached async tasks to get the two Calendar objects, which are used when c omparing dates. 269 // Cached async tasks to get the two Calendar objects, which are used when c omparing dates.
253 private static final AsyncTask<Void, Void, Calendar> sCal1 = createCalendar( ); 270 private static final AsyncTask<Void, Void, Calendar> sCal1 = createCalendar( );
254 private static final AsyncTask<Void, Void, Calendar> sCal2 = createCalendar( ); 271 private static final AsyncTask<Void, Void, Calendar> sCal2 = createCalendar( );
255 272
256 public static final int TYPE_FOOTER = -2; 273 public static final int TYPE_FOOTER = -2;
257 public static final int TYPE_HEADER = -1; 274 public static final int TYPE_HEADER = -1;
258 public static final int TYPE_DATE = 0; 275 public static final int TYPE_DATE = 0;
259 public static final int TYPE_NORMAL = 1; 276 public static final int TYPE_NORMAL = 1;
277 public static final int TYPE_SUBSECTION_HEADER = 2;
260 278
261 private int mSize; 279 private int mSize;
262 private boolean mHasListHeader; 280 private boolean mHasListHeader;
263 private boolean mHasListFooter; 281 private boolean mHasListFooter;
264 282
265 private SortedSet<ItemGroup> mGroups = new TreeSet<>(new Comparator<ItemGrou p>() { 283 private SortedSet<ItemGroup> mGroups = new TreeSet<>(new Comparator<ItemGrou p>() {
266 @Override 284 @Override
267 public int compare(ItemGroup lhs, ItemGroup rhs) { 285 public int compare(ItemGroup lhs, ItemGroup rhs) {
268 if (lhs == rhs) return 0; 286 if (lhs == rhs) return 0;
269 287
270 // There should only be at most one list header and one list footer in the SortedSet. 288 // There should only be at most one list header and one list footer in the SortedSet.
271 if (lhs.mIsListHeader || rhs.mIsListFooter) return -1; 289 if (lhs.mIsListHeader || rhs.mIsListFooter) return -1;
272 if (lhs.mIsListFooter || rhs.mIsListHeader) return 1; 290 if (lhs.mIsListFooter || rhs.mIsListHeader) return 1;
273 291
274 return compareDate(lhs.mDate, rhs.mDate); 292 return compareDate(lhs.mDate, rhs.mDate);
275 } 293 }
276 }); 294 });
277 295
278 /** 296 /**
279 * Creates a {@link ViewHolder} in the given view parent. 297 * Creates a {@link ViewHolder} in the given view parent.
280 * @see #onCreateViewHolder(ViewGroup, int) 298 * @see #onCreateViewHolder(ViewGroup, int)
281 */ 299 */
282 protected abstract ViewHolder createViewHolder(ViewGroup parent); 300 protected abstract ViewHolder createViewHolder(ViewGroup parent);
283 301
284 /** 302 /**
303 * Creates a {@link ViewHolder} for a subsection in the given view parent.
304 * @see #onCreateViewHolder(ViewGroup, int)
305 */
306 protected SubsectionHeaderViewHolder createSubsectionHeader(ViewGroup parent ) {
gone 2017/02/15 23:58:10 @Nullable?
shaktisahu 2017/02/16 06:07:07 Not sure if it adds any value. Each of the followi
gone 2017/02/17 19:21:16 Yeah, they really should be.
shaktisahu 2017/02/17 19:55:10 Done.
307 return null;
308 }
309
310 /**
285 * Creates a {@link BasicViewHolder} in the given view parent for the header . 311 * Creates a {@link BasicViewHolder} in the given view parent for the header .
286 * @see #onCreateViewHolder(ViewGroup, int) 312 * @see #onCreateViewHolder(ViewGroup, int)
287 */ 313 */
288 protected BasicViewHolder createHeader(ViewGroup parent) { 314 protected BasicViewHolder createHeader(ViewGroup parent) {
289 return null; 315 return null;
290 } 316 }
291 317
292 /** 318 /**
293 * Creates a {@link BasicViewHolder} in the given view parent for the footer . 319 * Creates a {@link BasicViewHolder} in the given view parent for the footer .
294 * See {@link #onCreateViewHolder(ViewGroup, int)}. 320 * See {@link #onCreateViewHolder(ViewGroup, int)}.
(...skipping 11 matching lines...) Expand all
306 getTimedItemViewResId(), parent, false)); 332 getTimedItemViewResId(), parent, false));
307 } 333 }
308 334
309 /** 335 /**
310 * Binds the {@link ViewHolder} with the given {@link TimedItem}. 336 * Binds the {@link ViewHolder} with the given {@link TimedItem}.
311 * @see #onBindViewHolder(ViewHolder, int) 337 * @see #onBindViewHolder(ViewHolder, int)
312 */ 338 */
313 protected abstract void bindViewHolderForTimedItem(ViewHolder viewHolder, Ti medItem item); 339 protected abstract void bindViewHolderForTimedItem(ViewHolder viewHolder, Ti medItem item);
314 340
315 /** 341 /**
342 * Binds the {@link SubsectionHeaderViewHolder} with the given {@link TimedI tem}.
343 * @see #onBindViewHolder(ViewHolder, int)
344 */
345 protected void bindViewHolderForSubsectionHeader(
346 SubsectionHeaderViewHolder holder, TimedItem timedItem) {}
347
348 /**
316 * Gets the resource id of the view showing the date header. 349 * Gets the resource id of the view showing the date header.
317 * Contract for subclasses: this view should be a {@link TextView}. 350 * Contract for subclasses: this view should be a {@link TextView}.
318 */ 351 */
319 protected abstract int getTimedItemViewResId(); 352 protected abstract int getTimedItemViewResId();
320 353
354 protected boolean isSubsectionHeader(TimedItem timedItem) {
355 return false;
356 }
gone 2017/02/15 23:58:10 Group your subsection header-related functions tog
shaktisahu 2017/02/16 06:07:07 Done.
357
321 /** 358 /**
322 * Loads a list of {@link TimedItem}s to this adapter. Previous data will no t be removed. Call 359 * Loads a list of {@link TimedItem}s to this adapter. Previous data will no t be removed. Call
323 * {@link #clear(boolean)} to remove previous items. 360 * {@link #clear(boolean)} to remove previous items.
324 */ 361 */
325 public void loadItems(List<? extends TimedItem> timedItems) { 362 public void loadItems(List<? extends TimedItem> timedItems) {
326 for (TimedItem timedItem : timedItems) { 363 for (TimedItem timedItem : timedItems) {
327 Date date = new Date(timedItem.getTimestamp()); 364 Date date = new Date(timedItem.getTimestamp());
328 boolean found = false; 365 boolean found = false;
329 for (ItemGroup group : mGroups) { 366 for (ItemGroup group : mGroups) {
330 if (group.isSameDay(date)) { 367 if (group.isSameDay(date)) {
331 found = true; 368 found = true;
332 group.addItem(timedItem); 369 group.addItem(timedItem);
333 mSize++; 370 mSize++;
334 break; 371 break;
335 } 372 }
336 } 373 }
337 if (!found) { 374 if (!found) {
338 // Create a new ItemGroup with the date for the new item. This i ncreases the 375 // Create a new ItemGroup with the date for the new item. This i ncreases the
339 // size by two because we add new views for the date and the ite m itself. 376 // size by two because we add new views for the date and the ite m itself.
340 ItemGroup newGroup = new ItemGroup(timedItem.getTimestamp()); 377 ItemGroup newGroup = createGroup(timedItem.getTimestamp());
341 newGroup.addItem(timedItem); 378 newGroup.addItem(timedItem);
342 mGroups.add(newGroup); 379 mGroups.add(newGroup);
343 mSize += 2; 380 mSize += 2;
344 } 381 }
345 } 382 }
346 383
347 setGroupPositions(); 384 setGroupPositions();
348 notifyDataSetChanged(); 385 notifyDataSetChanged();
349 } 386 }
350 387
388 protected ItemGroup createGroup(long timestamp) {
gone 2017/02/15 23:58:10 Javadoc for protected & public methods
shaktisahu 2017/02/16 06:07:06 Done.
389 return new ItemGroup(timestamp);
390 }
391
351 /** 392 /**
352 * Tells each group where they start in the list. 393 * Tells each group where they start in the list.
353 */ 394 */
354 private void setGroupPositions() { 395 private void setGroupPositions() {
355 int startIndex = 0; 396 int startIndex = 0;
356 for (ItemGroup group : mGroups) { 397 for (ItemGroup group : mGroups) {
357 group.resetPosition(); 398 group.resetPosition();
358 group.setPosition(startIndex); 399 group.setPosition(startIndex);
359 startIndex += group.size(); 400 startIndex += group.size();
360 } 401 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 */ 491 */
451 public Pair<Date, TimedItem> getItemAt(int position) { 492 public Pair<Date, TimedItem> getItemAt(int position) {
452 Pair<ItemGroup, Integer> pair = getGroupAt(position); 493 Pair<ItemGroup, Integer> pair = getGroupAt(position);
453 ItemGroup group = pair.first; 494 ItemGroup group = pair.first;
454 return new Pair<>(group.mDate, group.getItemAt(pair.second)); 495 return new Pair<>(group.mDate, group.getItemAt(pair.second));
455 } 496 }
456 497
457 @Override 498 @Override
458 public final int getItemViewType(int position) { 499 public final int getItemViewType(int position) {
459 Pair<ItemGroup, Integer> pair = getGroupAt(position); 500 Pair<ItemGroup, Integer> pair = getGroupAt(position);
501 ItemGroup group = pair.first;
460 if (pair.second == TYPE_HEADER) { 502 if (pair.second == TYPE_HEADER) {
461 return TYPE_HEADER; 503 return TYPE_HEADER;
462 } else if (pair.second == TYPE_FOOTER) { 504 } else if (pair.second == TYPE_FOOTER) {
463 return TYPE_FOOTER; 505 return TYPE_FOOTER;
464 } else if (pair.second == 0) { 506 } else if (pair.second == 0) {
465 return TYPE_DATE; 507 return TYPE_DATE;
508 } else if (isSubsectionHeader(group.getItemAt(pair.second))) {
509 return TYPE_SUBSECTION_HEADER;
466 } else { 510 } else {
467 return TYPE_NORMAL; 511 return TYPE_NORMAL;
468 } 512 }
469 } 513 }
470 514
471 @Override 515 @Override
472 public final RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, in t viewType) { 516 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int view Type) {
gone 2017/02/15 23:58:10 Make this function final again
shaktisahu 2017/02/16 06:07:06 Done.
473 if (viewType == TYPE_DATE) { 517 if (viewType == TYPE_DATE) {
474 return createDateViewHolder(parent); 518 return createDateViewHolder(parent);
475 } else if (viewType == TYPE_NORMAL) { 519 } else if (viewType == TYPE_NORMAL) {
476 return createViewHolder(parent); 520 return createViewHolder(parent);
477 } else if (viewType == TYPE_HEADER) { 521 } else if (viewType == TYPE_HEADER) {
478 return createHeader(parent); 522 return createHeader(parent);
479 } else if (viewType == TYPE_FOOTER) { 523 } else if (viewType == TYPE_FOOTER) {
480 return createFooter(parent); 524 return createFooter(parent);
525 } else if (viewType == TYPE_SUBSECTION_HEADER) {
526 return createSubsectionHeader(parent);
481 } 527 }
482 assert false; 528 assert false;
483 return null; 529 return null;
484 } 530 }
485 531
486 @Override 532 @Override
487 public final void onBindViewHolder(RecyclerView.ViewHolder holder, int posit ion) { 533 public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
gone 2017/02/15 23:58:10 Make this function final again
shaktisahu 2017/02/16 06:07:07 Done.
488 Pair<Date, TimedItem> pair = getItemAt(position); 534 Pair<Date, TimedItem> pair = getItemAt(position);
489 if (holder instanceof DateViewHolder) { 535 if (holder instanceof DateViewHolder) {
490 ((DateViewHolder) holder).setDate(pair.first); 536 ((DateViewHolder) holder).setDate(pair.first);
537 } else if (holder instanceof SubsectionHeaderViewHolder) {
538 bindViewHolderForSubsectionHeader((SubsectionHeaderViewHolder) holde r, pair.second);
491 } else if (!(holder instanceof BasicViewHolder)) { 539 } else if (!(holder instanceof BasicViewHolder)) {
492 bindViewHolderForTimedItem(holder, pair.second); 540 bindViewHolderForTimedItem(holder, pair.second);
493 } 541 }
494 } 542 }
495 543
496 @Override 544 @Override
497 public final int getItemCount() { 545 public final int getItemCount() {
498 return mSize; 546 return mSize;
499 } 547 }
500 548
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 long dayOfYear = calendar.get(Calendar.DAY_OF_YEAR); 604 long dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
557 long year = calendar.get(Calendar.YEAR); 605 long year = calendar.get(Calendar.YEAR);
558 return (year << 16) + dayOfYear; 606 return (year << 16) + dayOfYear;
559 } 607 }
560 608
561 /** 609 /**
562 * Compares two {@link Date}s. Note if you already have two {@link Calendar} objects, use 610 * Compares two {@link Date}s. Note if you already have two {@link Calendar} objects, use
563 * {@link #compareCalendar(Calendar, Calendar)} instead. 611 * {@link #compareCalendar(Calendar, Calendar)} instead.
564 * @return 0 if date1 and date2 are in the same day; 1 if date1 is before da te2; -1 otherwise. 612 * @return 0 if date1 and date2 are in the same day; 1 if date1 is before da te2; -1 otherwise.
565 */ 613 */
566 private static int compareDate(Date date1, Date date2) { 614 protected static int compareDate(Date date1, Date date2) {
567 Pair<Calendar, Calendar> pair = getCachedCalendars(); 615 Pair<Calendar, Calendar> pair = getCachedCalendars();
568 Calendar cal1 = pair.first, cal2 = pair.second; 616 Calendar cal1 = pair.first, cal2 = pair.second;
569 cal1.setTime(date1); 617 cal1.setTime(date1);
570 cal2.setTime(date2); 618 cal2.setTime(date2);
571 return compareCalendar(cal1, cal2); 619 return compareCalendar(cal1, cal2);
572 } 620 }
573 621
574 /** 622 /**
575 * @return 0 if cal1 and cal2 are in the same day; 1 if cal1 happens before cal2; -1 otherwise. 623 * @return 0 if cal1 and cal2 are in the same day; 1 if cal1 happens before cal2; -1 otherwise.
576 */ 624 */
(...skipping 30 matching lines...) Expand all
607 */ 655 */
608 private static AsyncTask<Void, Void, Calendar> createCalendar() { 656 private static AsyncTask<Void, Void, Calendar> createCalendar() {
609 return new AsyncTask<Void, Void, Calendar>() { 657 return new AsyncTask<Void, Void, Calendar>() {
610 @Override 658 @Override
611 protected Calendar doInBackground(Void... unused) { 659 protected Calendar doInBackground(Void... unused) {
612 return Calendar.getInstance(); 660 return Calendar.getInstance();
613 } 661 }
614 }.execute(); 662 }.execute();
615 } 663 }
616 } 664 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698