| Index: chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemGroup.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemGroup.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemGroup.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3b55c6e51e9ad85d40b6b6f284fa2a9d2972b8a6
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemGroup.java
|
| @@ -0,0 +1,194 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.chrome.browser.download.ui;
|
| +
|
| +import org.chromium.chrome.browser.download.ui.DownloadHistoryItemWrapper.OfflinePageItemWrapper;
|
| +import org.chromium.chrome.browser.widget.DateDividedAdapter;
|
| +import org.chromium.chrome.browser.widget.DateDividedAdapter.TimedItem;
|
| +
|
| +/**
|
| + * A bucket of downloaded items with the same date. It also holds the suggested offline items which
|
| + * are shown at the end of the list for that date.
|
| + */
|
| +public class DownloadItemGroup extends DateDividedAdapter.ItemGroup {
|
| + private int mNumSuggestedOfflinePages;
|
| + private boolean mIsSuggestedOfflinePagesSectionExpanded;
|
| +
|
| + /** The header representing the offline pages that are automatically downloaded */
|
| + private TimedItem mSuggestedOfflinePagesHeader;
|
| +
|
| + public DownloadItemGroup(long timestamp) {
|
| + super(timestamp);
|
| + }
|
| +
|
| + /** @return Whether the suggested pages are expanded. */
|
| + public boolean isSuggestedOfflinePagesSectionExpanded() {
|
| + return mIsSuggestedOfflinePagesSectionExpanded;
|
| + }
|
| +
|
| + /**
|
| + * Expands or collapses the suggested offline pages.
|
| + * @param expanded Whether the suggested pages should be shown.
|
| + */
|
| + public void setIsSuggestedOfflinePagesSectionExpanded(boolean expanded) {
|
| + mIsSuggestedOfflinePagesSectionExpanded = expanded;
|
| + }
|
| +
|
| + /** @return The total number of suggested pages for this date. */
|
| + public int getNumSuggestedOfflinePages() {
|
| + return mNumSuggestedOfflinePages;
|
| + }
|
| +
|
| + private TimedItem getSuggestedOfflinePagesHeader() {
|
| + if (mSuggestedOfflinePagesHeader == null) {
|
| + mSuggestedOfflinePagesHeader = new TimedItem() {
|
| + private Long mStableId;
|
| +
|
| + @Override
|
| + public long getTimestamp() {
|
| + return mDate.getTime();
|
| + }
|
| +
|
| + @Override
|
| + public long getStableId() {
|
| + if (mStableId == null) {
|
| + // Generate a stable ID based on timestamp.
|
| + mStableId = 0xFFFFFFFF00000000L + (getTimestamp() & 0x0FFFFFFFF);
|
| + }
|
| + return mStableId;
|
| + }
|
| + };
|
| + }
|
| +
|
| + return mSuggestedOfflinePagesHeader;
|
| + }
|
| +
|
| + @Override
|
| + public void addItem(TimedItem item) {
|
| + super.addItem(item);
|
| + if (isSuggestedOfflinePage(item)) {
|
| + mNumSuggestedOfflinePages++;
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + public void removeItem(TimedItem item) {
|
| + super.removeItem(item);
|
| + if (isSuggestedOfflinePage(item)) {
|
| + mNumSuggestedOfflinePages--;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * The visible items for the group are set to their respective positions in the list view.
|
| + * Invisible (collpased) items are skipped.
|
| + */
|
| + @Override
|
| + protected void setPositionForItems(int startIndex) {
|
| + int index = startIndex;
|
| + boolean isFirstSuggestedItem = true;
|
| + for (TimedItem item : mItems) {
|
| + // Skip one position for the header at the beginning of the suggested items section.
|
| + if (isFirstSuggestedItem && isSuggestedOfflinePage(item)) {
|
| + index += 1;
|
| + isFirstSuggestedItem = false;
|
| + }
|
| + item.setPosition(index);
|
| + index += 1;
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + protected void markFirstAndLastItem() {
|
| + TimedItem first = mItems.get(0);
|
| + first.setIsFirstInGroup(true);
|
| +
|
| + TimedItem last = mItems.get(mItems.size() - 1);
|
| + if (!isSuggestedOfflinePagesSectionExpanded() && mNumSuggestedOfflinePages > 0) {
|
| + last = getSuggestedOfflinePagesHeader();
|
| + }
|
| +
|
| + last.setIsLastInGroup(true);
|
| + }
|
| +
|
| + @Override
|
| + public int size() {
|
| + int size = super.size();
|
| +
|
| + // The size should match the number of rows in the list view. So, adjust the size depending
|
| + // on whether the suggested items section is expanded or collapsed.
|
| + if (mNumSuggestedOfflinePages > 0) {
|
| + // First item of the suggested pages section is the section header.
|
| + size += 1;
|
| + if (!isSuggestedOfflinePagesSectionExpanded()) {
|
| + size -= mNumSuggestedOfflinePages;
|
| + }
|
| + }
|
| +
|
| + return size;
|
| + }
|
| +
|
| + /** @return The total file size of the suggested pages for this date. */
|
| + public long getSuggestedOfflinePagesFileSize() {
|
| + long size = 0;
|
| + for (TimedItem item : mItems) {
|
| + if (isSuggestedOfflinePage(item)) {
|
| + size += ((DownloadHistoryItemWrapper) item).getFileSize();
|
| + }
|
| + }
|
| + return size;
|
| + }
|
| +
|
| + private int getSuggestedOfflinePagesSectionHeaderPosition() {
|
| + return mItems.size() - mNumSuggestedOfflinePages + 1;
|
| + }
|
| +
|
| + private boolean isSuggestedOfflinePagesSectionHeader(int index) {
|
| + return index == getSuggestedOfflinePagesSectionHeaderPosition()
|
| + && mNumSuggestedOfflinePages > 0;
|
| + }
|
| +
|
| + @Override
|
| + protected TimedItem getItemAtInternal(int index) {
|
| + // The suggested pages start at the end of the group.
|
| + // So, the ordering of the items in this list is :
|
| + // date header, regular items, suggested pages header, suggested pages (if expanded).
|
| + int suggestedSectionHeaderIndex = getSuggestedOfflinePagesSectionHeaderPosition();
|
| + if (index < suggestedSectionHeaderIndex) {
|
| + return mItems.get(index - 1);
|
| + } else if (index == suggestedSectionHeaderIndex) {
|
| + assert mNumSuggestedOfflinePages > 0;
|
| + return getSuggestedOfflinePagesHeader();
|
| + } else {
|
| + assert isSuggestedOfflinePagesSectionExpanded();
|
| + return mItems.get(index - 2);
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + public int getItemViewType(int position) {
|
| + if (isSuggestedOfflinePagesSectionHeader(position)) {
|
| + return DateDividedAdapter.TYPE_SUBSECTION_HEADER;
|
| + } else {
|
| + return super.getItemViewType(position);
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + public int compareItem(TimedItem lhs, TimedItem rhs) {
|
| + if (isSuggestedOfflinePage(lhs) && !isSuggestedOfflinePage(rhs)) return 1;
|
| + if (!isSuggestedOfflinePage(lhs) && isSuggestedOfflinePage(rhs)) return -1;
|
| +
|
| + return super.compareItem(lhs, rhs);
|
| + }
|
| +
|
| + private boolean isSuggestedOfflinePage(TimedItem timedItem) {
|
| + if (timedItem instanceof OfflinePageItemWrapper) {
|
| + return ((OfflinePageItemWrapper) timedItem).isSuggested();
|
| + }
|
| +
|
| + return false;
|
| + }
|
| +}
|
|
|