diff options
author | 2019-08-28 16:05:25 +0800 | |
---|---|---|
committer | 2019-09-09 15:11:56 +0800 | |
commit | f0b6bd496d8f5e9ba936fb7d2e13c6fcc7cfef35 (patch) | |
tree | 13194c1335db048ebad48f433afca8634ee998df | |
parent | 6b296cc673c6b841a3392b672f984c2060990fa1 (diff) |
Add "Large files" and "From this week" chip to search chip view
Bug: 137847802
Bug: 137846543
Test: manual
Test: atest DocumentsUIGoogleTests:SearchChipViewManagerTest
Test: atest DocumentsUIGoogleTests:SearchViewManagerTest
Change-Id: I40f599b40a29e24964f3a80ab0bf5e3e6f8f2d50
7 files changed, 144 insertions, 33 deletions
diff --git a/res/drawable/ic_chip_large_files.xml b/res/drawable/ic_chip_large_files.xml new file mode 100644 index 000000000..ececcf036 --- /dev/null +++ b/res/drawable/ic_chip_large_files.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="?android:textColorSecondary" + android:pathData="M21.41,11.58l-9,-9C12.05,2.22 11.55,2 11,2H4c-1.1,0 -2,0.9 -2,2v7c0,0.55 0.22,1.05 0.59,1.42l9,9c0.36,0.36 0.86,0.58 1.41,0.58s1.05,-0.22 1.41,-0.59l7,-7c0.37,-0.36 0.59,-0.86 0.59,-1.41s-0.23,-1.06 -0.59,-1.42zM13,20.01L4,11V4h7v-0.01l9,9 -7,7.02zM8,6.5C8,7.33 7.33,8 6.5,8S5,7.33 5,6.5 5.67,5 6.5,5 8,5.67 8,6.5z"/> +</vector>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index e8aa2b97f..a35cd00fd 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -433,6 +433,10 @@ <string name="chip_title_videos">Videos</string> <!-- Title for image chip. [CHAR_LIMIT=25] --> <string name="chip_title_documents">Documents</string> + <!-- Title for large file chip. [CHAR_LIMIT=25] --> + <string name="chip_title_large_files">Large files</string> + <!-- Title for from this week chip. [CHAR_LIMIT=25] --> + <string name="chip_title_from_this_week">From this week</string> <!-- Hint on text input field for create new folder. [CHAR_LIMIT=48] --> <string name="input_hint_new_folder">Folder name</string> diff --git a/src/com/android/documentsui/MetricConsts.java b/src/com/android/documentsui/MetricConsts.java index f95f6e5ed..d6e2995d9 100644 --- a/src/com/android/documentsui/MetricConsts.java +++ b/src/com/android/documentsui/MetricConsts.java @@ -363,6 +363,8 @@ public class MetricConsts { public static final int TYPE_CHIP_DOCS = 4; public static final int TYPE_SEARCH_HISTORY = 5; public static final int TYPE_SEARCH_STRING = 6; + public static final int TYPE_CHIP_LARGE_FILES = 7; + public static final int TYPE_CHIP_FROM_THIS_WEEK = 8; @IntDef(flag = true, value = { TYPE_UNKNOWN, @@ -371,7 +373,9 @@ public class MetricConsts { TYPE_CHIP_VIDEOS, TYPE_CHIP_DOCS, TYPE_SEARCH_HISTORY, - TYPE_SEARCH_STRING + TYPE_SEARCH_STRING, + TYPE_CHIP_LARGE_FILES, + TYPE_CHIP_FROM_THIS_WEEK }) @Retention(RetentionPolicy.SOURCE) public @interface SearchType {} diff --git a/src/com/android/documentsui/queries/SearchChipViewManager.java b/src/com/android/documentsui/queries/SearchChipViewManager.java index 959da314f..bb02d75a4 100644 --- a/src/com/android/documentsui/queries/SearchChipViewManager.java +++ b/src/com/android/documentsui/queries/SearchChipViewManager.java @@ -18,7 +18,9 @@ package com.android.documentsui.queries; import android.animation.ObjectAnimator; import android.content.Context; +import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.provider.DocumentsContract; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -37,6 +39,8 @@ import com.android.documentsui.base.Shared; import com.google.android.material.chip.Chip; import com.google.common.primitives.Ints; +import java.time.LocalDate; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -51,13 +55,21 @@ import java.util.Set; * Manages search chip behavior. */ public class SearchChipViewManager { - private static final int CHIP_MOVE_ANIMATION_DURATION = 250; - - private static final int TYPE_IMAGES = MetricConsts.TYPE_CHIP_IMAGES;; + // Defined large file as the size is larger than 10 MB. + private static final long LARGE_FILE_SIZE_BYTES = 10000000L; + // Defined a week ago as now in millis. + private static final long A_WEEK_AGO_MILLIS = + LocalDate.now().minusDays(7).atStartOfDay(ZoneId.systemDefault()) + .toInstant() + .toEpochMilli(); + + private static final int TYPE_IMAGES = MetricConsts.TYPE_CHIP_IMAGES; private static final int TYPE_DOCUMENTS = MetricConsts.TYPE_CHIP_DOCS; private static final int TYPE_AUDIO = MetricConsts.TYPE_CHIP_AUDIOS; private static final int TYPE_VIDEOS = MetricConsts.TYPE_CHIP_VIDEOS; + private static final int TYPE_LARGE_FILES = MetricConsts.TYPE_CHIP_LARGE_FILES; + private static final int TYPE_FROM_THIS_WEEK = MetricConsts.TYPE_CHIP_FROM_THIS_WEEK; private static final ChipComparator CHIP_COMPARATOR = new ChipComparator(); @@ -67,6 +79,7 @@ public class SearchChipViewManager { private static final String[] AUDIO_MIMETYPES = new String[]{"audio/*", "application/ogg", "application/x-flac"}; private static final String[] DOCUMENTS_MIMETYPES = new String[]{"application/*", "text/*"}; + private static final String[] EMPTY_MIMETYPES = new String[]{""}; private static final Map<Integer, SearchChipData> sChipItems = new HashMap<>(); @@ -89,6 +102,14 @@ public class SearchChipViewManager { new SearchChipData(TYPE_AUDIO, R.string.chip_title_audio, AUDIO_MIMETYPES)); sChipItems.put(TYPE_VIDEOS, new SearchChipData(TYPE_VIDEOS, R.string.chip_title_videos, VIDEOS_MIMETYPES)); + sChipItems.put(TYPE_LARGE_FILES, + new SearchChipData(TYPE_LARGE_FILES, + R.string.chip_title_large_files, + EMPTY_MIMETYPES)); + sChipItems.put(TYPE_FROM_THIS_WEEK, + new SearchChipData(TYPE_FROM_THIS_WEEK, + R.string.chip_title_from_this_week, + EMPTY_MIMETYPES)); } public SearchChipViewManager(@NonNull ViewGroup chipGroup) { @@ -145,18 +166,33 @@ public class SearchChipViewManager { } /** - * Get the mime types of checked chips + * Get the query arguments of the checked chips. * - * @return the string array of mime types + * @return the bundle of query arguments */ - public String[] getCheckedMimeTypes() { - final ArrayList<String> args = new ArrayList<>(); + public Bundle getCheckedChipQueryArgs() { + final Bundle queryArgs = new Bundle(); + final ArrayList<String> checkedMimeTypes = new ArrayList<>(); for (SearchChipData data : mCheckedChipItems) { - for (String mimeType : data.getMimeTypes()) { - args.add(mimeType); + if (data.getChipType() == MetricConsts.TYPE_CHIP_LARGE_FILES) { + queryArgs.putLong(DocumentsContract.QUERY_ARG_FILE_SIZE_OVER, + LARGE_FILE_SIZE_BYTES); + } else if (data.getChipType() == MetricConsts.TYPE_CHIP_FROM_THIS_WEEK) { + queryArgs.putLong(DocumentsContract.QUERY_ARG_LAST_MODIFIED_AFTER, + A_WEEK_AGO_MILLIS); + } else { + for (String mimeType : data.getMimeTypes()) { + checkedMimeTypes.add(mimeType); + } } } - return args.toArray(new String[0]); + + if (!checkedMimeTypes.isEmpty()) { + queryArgs.putStringArray(DocumentsContract.QUERY_ARG_MIME_TYPES, + checkedMimeTypes.toArray(new String[0])); + } + + return queryArgs; } /** @@ -209,7 +245,9 @@ public class SearchChipViewManager { for (Integer chipType : mDefaultChipTypes) { final SearchChipData chipData = sChipItems.get(chipType); final String[] mimeTypes = chipData.getMimeTypes(); - final boolean isMatched = MimeTypes.mimeMatches(acceptMimeTypes, mimeTypes); + final boolean isMatched = (chipType == MetricConsts.TYPE_CHIP_LARGE_FILES + || chipType == MetricConsts.TYPE_CHIP_FROM_THIS_WEEK) + || MimeTypes.mimeMatches(acceptMimeTypes, mimeTypes); if (isMatched) { addChipToGroup(mChipGroup, chipData, inflater); } @@ -217,9 +255,6 @@ public class SearchChipViewManager { reorderCheckedChips(null /* clickedChip */, false /* hasAnim */); mIsFirstUpdateChipsReady = true; mCurrentUpdateMimeTypes = acceptMimeTypes; - if (mChipGroup.getChildCount() < 2) { - mChipGroup.setVisibility(View.GONE); - } } private void addChipToGroup(ViewGroup group, SearchChipData data, LayoutInflater inflater) { @@ -317,11 +352,19 @@ public class SearchChipViewManager { } private void bindChip(Chip chip, SearchChipData chipData) { + final Context context = mChipGroup.getContext(); chip.setTag(chipData); - chip.setText(mChipGroup.getContext().getString(chipData.getTitleRes())); - // get the icon drawable with the first mimeType - chip.setChipIcon( - IconUtils.loadMimeIcon(mChipGroup.getContext(), chipData.getMimeTypes()[0])); + chip.setText(context.getString(chipData.getTitleRes())); + Drawable chipIcon; + if (chipData.getChipType() == TYPE_LARGE_FILES) { + chipIcon = context.getDrawable(R.drawable.ic_chip_large_files); + } else if (chipData.getChipType() == TYPE_FROM_THIS_WEEK) { + chipIcon = context.getDrawable(R.drawable.ic_history); + } else { + // get the icon drawable with the first mimeType in chipData + chipIcon = IconUtils.loadMimeIcon(context, chipData.getMimeTypes()[0]); + } + chip.setChipIcon(chipIcon); chip.setOnClickListener(this::onChipClick); if (mCheckedChipItems.contains(chipData)) { diff --git a/src/com/android/documentsui/queries/SearchViewManager.java b/src/com/android/documentsui/queries/SearchViewManager.java index 8564d7a9c..28aeaa6b2 100644 --- a/src/com/android/documentsui/queries/SearchViewManager.java +++ b/src/com/android/documentsui/queries/SearchViewManager.java @@ -162,15 +162,11 @@ public class SearchViewManager implements * @return the bundle of query arguments */ public Bundle buildQueryArgs() { - final Bundle queryArgs = new Bundle(); + final Bundle queryArgs = mChipViewManager.getCheckedChipQueryArgs(); if (!TextUtils.isEmpty(mCurrentSearch)) { queryArgs.putString(DocumentsContract.QUERY_ARG_DISPLAY_NAME, mCurrentSearch); } - final String[] checkedMimeTypes = mChipViewManager.getCheckedMimeTypes(); - if (checkedMimeTypes != null && checkedMimeTypes.length > 0) { - queryArgs.putStringArray(DocumentsContract.QUERY_ARG_MIME_TYPES, checkedMimeTypes); - } return queryArgs; } diff --git a/tests/unit/com/android/documentsui/queries/SearchChipViewManagerTest.java b/tests/unit/com/android/documentsui/queries/SearchChipViewManagerTest.java index 03b7358af..2ed14db8d 100644 --- a/tests/unit/com/android/documentsui/queries/SearchChipViewManagerTest.java +++ b/tests/unit/com/android/documentsui/queries/SearchChipViewManagerTest.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.spy; import android.content.Context; import android.os.Bundle; - +import android.provider.DocumentsContract; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; @@ -47,7 +47,11 @@ import java.util.Set; @SmallTest public final class SearchChipViewManagerTest { - private static final String[] TEST_MIME_TYPES = new String[]{"image/*", "video/*"}; + private static final String LARGE_FILES_CHIP_MIME_TYPE = ""; + private static final String FROM_THIS_WEEK_CHIP_MIME_TYPE = ""; + private static final String[] TEST_MIME_TYPES = + new String[]{"image/*", "video/*", + LARGE_FILES_CHIP_MIME_TYPE, FROM_THIS_WEEK_CHIP_MIME_TYPE}; private static int CHIP_TYPE = 1000; private Context mContext; @@ -66,7 +70,7 @@ public final class SearchChipViewManagerTest { } @Test - public void testInitChipSets_HasCorrectValue() throws Exception { + public void testInitChipSets_HasCorrectChipCount() throws Exception { mSearchChipViewManager.initChipSets(TEST_MIME_TYPES); mSearchChipViewManager.updateChips(new String[] {"*/*"}); @@ -74,7 +78,7 @@ public final class SearchChipViewManagerTest { } @Test - public void testUpdateChips_HasCorrectValue() throws Exception { + public void testUpdateChips_HasCorrectChipCount() throws Exception { mSearchChipViewManager.updateChips(TEST_MIME_TYPES); assertThat(mChipGroup.getChildCount()).isEqualTo(TEST_MIME_TYPES.length); @@ -84,7 +88,9 @@ public final class SearchChipViewManagerTest { public void testGetCheckedChipMimeTypes_HasCorrectValue() throws Exception { mSearchChipViewManager.mCheckedChipItems = getFakeSearchChipDataList(); - final String[] checkedMimeTypes = mSearchChipViewManager.getCheckedMimeTypes(); + String[] checkedMimeTypes = + mSearchChipViewManager.getCheckedChipQueryArgs() + .getStringArray(DocumentsContract.QUERY_ARG_MIME_TYPES); assertThat(MimeTypes.mimeMatches(TEST_MIME_TYPES, checkedMimeTypes[0])).isTrue(); assertThat(MimeTypes.mimeMatches(TEST_MIME_TYPES, checkedMimeTypes[1])).isTrue(); @@ -127,18 +133,18 @@ public final class SearchChipViewManagerTest { } @Test - public void testBindMirrorGroup_hideRow() throws Exception { + public void testBindMirrorGroup_showRow() throws Exception { mSearchChipViewManager.updateChips(new String[] {"image/*"}); ViewGroup mirror = spy(new LinearLayout(mContext)); mSearchChipViewManager.bindMirrorGroup(mirror); - assertThat(View.GONE).isEqualTo(mirror.getVisibility()); + assertThat(View.VISIBLE).isEqualTo(mirror.getVisibility()); } private static Set<SearchChipData> getFakeSearchChipDataList() { final Set<SearchChipData> chipDataList = new HashSet<>(); - chipDataList.add(new SearchChipData(CHIP_TYPE, 0, TEST_MIME_TYPES)); + chipDataList.add(new SearchChipData(CHIP_TYPE, 0 /* titleRes */, TEST_MIME_TYPES)); return chipDataList; } } diff --git a/tests/unit/com/android/documentsui/queries/SearchViewManagerTest.java b/tests/unit/com/android/documentsui/queries/SearchViewManagerTest.java index 07c5324e4..0ad353b5c 100644 --- a/tests/unit/com/android/documentsui/queries/SearchViewManagerTest.java +++ b/tests/unit/com/android/documentsui/queries/SearchViewManagerTest.java @@ -48,6 +48,7 @@ import androidx.annotation.Nullable; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.documentsui.MetricConsts; import com.android.documentsui.R; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.DocumentStack; @@ -64,6 +65,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.time.LocalDate; +import java.time.ZoneId; import java.util.HashSet; import java.util.Set; import java.util.Timer; @@ -368,6 +371,31 @@ public final class SearchViewManagerTest { } @Test + public void testBuildQueryArgs_hasLargeFilesSize() throws Exception { + mSearchViewManager.onClick(null); + mSearchChipViewManager.mCheckedChipItems = getFakeSearchChipDataList(); + + final Bundle queryArgs = mSearchViewManager.buildQueryArgs(); + assertFalse(queryArgs.isEmpty()); + + final long largeFilesSize = queryArgs.getLong(QUERY_ARG_FILE_SIZE_OVER); + assertEquals(10000000L, largeFilesSize); + } + + @Test + public void testBuildQueryArgs_hasWeekAgoTime() throws Exception { + mSearchViewManager.onClick(null); + mSearchChipViewManager.mCheckedChipItems = getFakeSearchChipDataList(); + + final Bundle queryArgs = mSearchViewManager.buildQueryArgs(); + assertFalse(queryArgs.isEmpty()); + + final long weekAgoTime = queryArgs.getLong(QUERY_ARG_LAST_MODIFIED_AFTER); + assertEquals(LocalDate.now().minusDays(7).atStartOfDay(ZoneId.systemDefault()) + .toInstant().toEpochMilli(), weekAgoTime); + } + + @Test public void testSupportsMimeTypesSearch_showChips() throws Exception { RootInfo root = spy(new RootInfo()); when(root.isRecents()).thenReturn(false); @@ -423,7 +451,12 @@ public final class SearchViewManagerTest { private static Set<SearchChipData> getFakeSearchChipDataList() { final Set<SearchChipData> chipDataList = new HashSet<>(); - chipDataList.add(new SearchChipData(0 /* chipType */, 0, new String[]{"image/*"})); + chipDataList.add(new SearchChipData(MetricConsts.TYPE_CHIP_IMAGES, + 0 /* titleRes */, new String[]{"image/*"})); + chipDataList.add(new SearchChipData(MetricConsts.TYPE_CHIP_LARGE_FILES, + 0 /* titleRes */, new String[]{""})); + chipDataList.add(new SearchChipData(MetricConsts.TYPE_CHIP_FROM_THIS_WEEK, + 0 /* titleRes */, new String[]{""})); return chipDataList; } } |