Loading res/layout/directory_app_bar.xml +7 −1 Original line number Diff line number Diff line Loading @@ -30,8 +30,14 @@ app:titleEnabled="false" app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <include layout="@layout/directory_header"/> </androidx.core.widget.NestedScrollView> <View android:id="@+id/toolbar_background_layout" android:layout_width="match_parent" Loading res/layout/fragment_pick.xml +20 −7 Original line number Diff line number Diff line Loading @@ -32,6 +32,10 @@ android:layout_marginEnd="4dp" android:text="@android:string/cancel"/> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.button.MaterialButton android:id="@android:id/button1" style="?attr/materialButtonStyle" Loading @@ -39,4 +43,13 @@ android:layout_height="wrap_content" android:layout_marginStart="4dp" android:layout_marginEnd="4dp"/> <!-- Handles touch events when button1 is disabled. --> <FrameLayout android:id="@+id/pick_button_overlay" android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout> </LinearLayout> src/com/android/documentsui/picker/PickFragment.java +18 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; Loading @@ -41,6 +40,9 @@ import com.android.documentsui.R; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.State; import com.android.documentsui.services.FileOperationService.OpType; import com.android.documentsui.ui.Snackbars; import com.google.android.material.snackbar.Snackbar; /** * Display pick confirmation bar, usually for selecting a directory. Loading @@ -56,7 +58,12 @@ public class PickFragment extends Fragment { private final View.OnClickListener mPickListener = new View.OnClickListener() { @Override public void onClick(View v) { if (mPick.isEnabled()) { mInjector.actions.pickDocument(getChildFragmentManager(), mPickTarget); } else { String msg = getResources().getString(R.string.directory_blocked_header_subtitle); Snackbars.makeSnackbar(getActivity(), msg, Snackbar.LENGTH_SHORT).show(); } } }; Loading @@ -78,8 +85,9 @@ public class PickFragment extends Fragment { private @OpType int mCopyOperationSubType = OPERATION_UNKNOWN; private DocumentInfo mPickTarget; private View mContainer; private TextView mPick; private TextView mCancel; private View mPickOverlay; private Button mPick; private Button mCancel; public static void show(FragmentManager fm) { // Fragment can be restored by FragmentManager automatically. Loading @@ -103,6 +111,8 @@ public class PickFragment extends Fragment { mContainer = inflater.inflate(R.layout.fragment_pick, container, false); mPick = (Button) mContainer.findViewById(android.R.id.button1); mPickOverlay = mContainer.findViewById((R.id.pick_button_overlay)); mPickOverlay.setOnClickListener(mPickListener); mPick.setOnClickListener(mPickListener); mCancel = (Button) mContainer.findViewById(android.R.id.button2); Loading Loading @@ -172,6 +182,10 @@ public class PickFragment extends Fragment { mPick.setWidth(Integer.MAX_VALUE); mCancel.setVisibility(View.GONE); mPick.setEnabled(!(mPickTarget.isBlockedFromTree() && mRestrictScopeStorage)); mPickOverlay.setVisibility( mPickTarget.isBlockedFromTree() && mRestrictScopeStorage ? View.VISIBLE : View.GONE); break; case State.ACTION_PICK_COPY_DESTINATION: int titleId; Loading src/com/android/documentsui/sidebar/RootsFragment.java +14 −32 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; Loading Loading @@ -272,6 +273,7 @@ public class RootsFragment extends Fragment { } List<Item> sortedItems = sortLoadResult( getResources(), state, roots, excludePackage, Loading Loading @@ -345,6 +347,7 @@ public class RootsFragment extends Fragment { */ @VisibleForTesting List<Item> sortLoadResult( Resources resources, State state, Collection<RootInfo> roots, @Nullable String excludePackage, Loading Loading @@ -396,7 +399,6 @@ public class RootsFragment extends Fragment { if (VERBOSE) Log.v(TAG, "Adding storage roots: " + storageProviders); result.addAll(storageProviders); final List<Item> rootList = new ArrayList<>(); final List<Item> rootListOtherUser = new ArrayList<>(); mApplicationItemList = new ArrayList<>(); Loading @@ -416,31 +418,19 @@ public class RootsFragment extends Fragment { } } if (state.supportsCrossProfile() && state.canShareAcrossProfile && !rootList.isEmpty() && !rootListOtherUser.isEmpty()) { // Identify personal and work root list. final List<Item> personalRootList; final List<Item> workRootList; if (UserId.CURRENT_USER.isSystem()) { personalRootList = rootList; workRootList = rootListOtherUser; } else { personalRootList = rootListOtherUser; workRootList = rootList; List<Item> presentableList = new UserItemsCombiner(resources, state) .setRootListForCurrentUser(rootList) .setRootListForOtherUser(rootListOtherUser) .createPresentableList(); addListToResult(result, presentableList); return result; } // Add header and list to the result final List<Item> resultRootList = new ArrayList<>(); resultRootList.add(new HeaderItem(getString(R.string.personal_tab))); resultRootList.addAll(personalRootList); resultRootList.add(new HeaderItem(getString(R.string.work_tab))); resultRootList.addAll(workRootList); addListToResult(result, resultRootList); } else { addListToResult(result, rootList); private void addListToResult(List<Item> result, List<Item> rootList) { if (!result.isEmpty() && !rootList.isEmpty()) { result.add(new SpacerItem()); } return result; result.addAll(rootList); } /** Loading Loading @@ -534,14 +524,6 @@ public class RootsFragment extends Fragment { } } private void addListToResult(List<Item> result, List<Item> rootList) { if (!result.isEmpty() && !rootList.isEmpty()) { result.add(new SpacerItem()); } result.addAll(rootList); } @Override public void onResume() { super.onResume(); Loading src/com/android/documentsui/sidebar/UserItemsCombiner.java 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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. */ package com.android.documentsui.sidebar; import android.content.res.Resources; import static androidx.core.util.Preconditions.checkArgument; import static androidx.core.util.Preconditions.checkNotNull; import androidx.annotation.VisibleForTesting; import com.android.documentsui.R; import com.android.documentsui.base.State; import com.android.documentsui.base.UserId; import java.util.ArrayList; import java.util.List; /** * Converts user-specific lists of items into a single merged list appropriate for displaying in the * UI, including the relevant headers. */ class UserItemsCombiner { private UserId mCurrentUser; private final Resources mResources; private final State mState; private List<Item> mRootList; private List<Item> mRootListOtherUser; UserItemsCombiner(Resources resources, State state) { mCurrentUser = UserId.CURRENT_USER; mResources = checkNotNull(resources); mState = checkNotNull(state); } @VisibleForTesting UserItemsCombiner overrideCurrentUserForTest(UserId userId) { mCurrentUser = checkNotNull(userId); return this; } UserItemsCombiner setRootListForCurrentUser(List<Item> rootList) { mRootList = checkNotNull(rootList); return this; } UserItemsCombiner setRootListForOtherUser(List<Item> rootList) { mRootListOtherUser = checkNotNull(rootList); return this; } /** * Returns a combined lists from the provided lists. {@link HeaderItem}s indicating profile * will be added if the list of current user and the other user are not empty. */ public List<Item> createPresentableList() { checkArgument(mRootList != null, "RootListForCurrentUser is not set"); checkArgument(mRootListOtherUser != null, "setRootListForOtherUser is not set"); final List<Item> result = new ArrayList<>(); if (mState.supportsCrossProfile() && mState.canShareAcrossProfile) { if (!mRootList.isEmpty() && !mRootListOtherUser.isEmpty()) { // Identify personal and work root list. final List<Item> personalRootList; final List<Item> workRootList; if (mCurrentUser.isSystem()) { personalRootList = mRootList; workRootList = mRootListOtherUser; } else { personalRootList = mRootListOtherUser; workRootList = mRootList; } result.add(new HeaderItem(mResources.getString(R.string.personal_tab))); result.addAll(personalRootList); result.add(new HeaderItem(mResources.getString(R.string.work_tab))); result.addAll(workRootList); } else { result.addAll(mRootList); result.addAll(mRootListOtherUser); } } else { result.addAll(mRootList); } return result; } } Loading
res/layout/directory_app_bar.xml +7 −1 Original line number Diff line number Diff line Loading @@ -30,8 +30,14 @@ app:titleEnabled="false" app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="wrap_content"> <include layout="@layout/directory_header"/> </androidx.core.widget.NestedScrollView> <View android:id="@+id/toolbar_background_layout" android:layout_width="match_parent" Loading
res/layout/fragment_pick.xml +20 −7 Original line number Diff line number Diff line Loading @@ -32,6 +32,10 @@ android:layout_marginEnd="4dp" android:text="@android:string/cancel"/> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.button.MaterialButton android:id="@android:id/button1" style="?attr/materialButtonStyle" Loading @@ -39,4 +43,13 @@ android:layout_height="wrap_content" android:layout_marginStart="4dp" android:layout_marginEnd="4dp"/> <!-- Handles touch events when button1 is disabled. --> <FrameLayout android:id="@+id/pick_button_overlay" android:layout_width="match_parent" android:layout_height="match_parent"/> </FrameLayout> </LinearLayout>
src/com/android/documentsui/picker/PickFragment.java +18 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; Loading @@ -41,6 +40,9 @@ import com.android.documentsui.R; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.State; import com.android.documentsui.services.FileOperationService.OpType; import com.android.documentsui.ui.Snackbars; import com.google.android.material.snackbar.Snackbar; /** * Display pick confirmation bar, usually for selecting a directory. Loading @@ -56,7 +58,12 @@ public class PickFragment extends Fragment { private final View.OnClickListener mPickListener = new View.OnClickListener() { @Override public void onClick(View v) { if (mPick.isEnabled()) { mInjector.actions.pickDocument(getChildFragmentManager(), mPickTarget); } else { String msg = getResources().getString(R.string.directory_blocked_header_subtitle); Snackbars.makeSnackbar(getActivity(), msg, Snackbar.LENGTH_SHORT).show(); } } }; Loading @@ -78,8 +85,9 @@ public class PickFragment extends Fragment { private @OpType int mCopyOperationSubType = OPERATION_UNKNOWN; private DocumentInfo mPickTarget; private View mContainer; private TextView mPick; private TextView mCancel; private View mPickOverlay; private Button mPick; private Button mCancel; public static void show(FragmentManager fm) { // Fragment can be restored by FragmentManager automatically. Loading @@ -103,6 +111,8 @@ public class PickFragment extends Fragment { mContainer = inflater.inflate(R.layout.fragment_pick, container, false); mPick = (Button) mContainer.findViewById(android.R.id.button1); mPickOverlay = mContainer.findViewById((R.id.pick_button_overlay)); mPickOverlay.setOnClickListener(mPickListener); mPick.setOnClickListener(mPickListener); mCancel = (Button) mContainer.findViewById(android.R.id.button2); Loading Loading @@ -172,6 +182,10 @@ public class PickFragment extends Fragment { mPick.setWidth(Integer.MAX_VALUE); mCancel.setVisibility(View.GONE); mPick.setEnabled(!(mPickTarget.isBlockedFromTree() && mRestrictScopeStorage)); mPickOverlay.setVisibility( mPickTarget.isBlockedFromTree() && mRestrictScopeStorage ? View.VISIBLE : View.GONE); break; case State.ACTION_PICK_COPY_DESTINATION: int titleId; Loading
src/com/android/documentsui/sidebar/RootsFragment.java +14 −32 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; Loading Loading @@ -272,6 +273,7 @@ public class RootsFragment extends Fragment { } List<Item> sortedItems = sortLoadResult( getResources(), state, roots, excludePackage, Loading Loading @@ -345,6 +347,7 @@ public class RootsFragment extends Fragment { */ @VisibleForTesting List<Item> sortLoadResult( Resources resources, State state, Collection<RootInfo> roots, @Nullable String excludePackage, Loading Loading @@ -396,7 +399,6 @@ public class RootsFragment extends Fragment { if (VERBOSE) Log.v(TAG, "Adding storage roots: " + storageProviders); result.addAll(storageProviders); final List<Item> rootList = new ArrayList<>(); final List<Item> rootListOtherUser = new ArrayList<>(); mApplicationItemList = new ArrayList<>(); Loading @@ -416,31 +418,19 @@ public class RootsFragment extends Fragment { } } if (state.supportsCrossProfile() && state.canShareAcrossProfile && !rootList.isEmpty() && !rootListOtherUser.isEmpty()) { // Identify personal and work root list. final List<Item> personalRootList; final List<Item> workRootList; if (UserId.CURRENT_USER.isSystem()) { personalRootList = rootList; workRootList = rootListOtherUser; } else { personalRootList = rootListOtherUser; workRootList = rootList; List<Item> presentableList = new UserItemsCombiner(resources, state) .setRootListForCurrentUser(rootList) .setRootListForOtherUser(rootListOtherUser) .createPresentableList(); addListToResult(result, presentableList); return result; } // Add header and list to the result final List<Item> resultRootList = new ArrayList<>(); resultRootList.add(new HeaderItem(getString(R.string.personal_tab))); resultRootList.addAll(personalRootList); resultRootList.add(new HeaderItem(getString(R.string.work_tab))); resultRootList.addAll(workRootList); addListToResult(result, resultRootList); } else { addListToResult(result, rootList); private void addListToResult(List<Item> result, List<Item> rootList) { if (!result.isEmpty() && !rootList.isEmpty()) { result.add(new SpacerItem()); } return result; result.addAll(rootList); } /** Loading Loading @@ -534,14 +524,6 @@ public class RootsFragment extends Fragment { } } private void addListToResult(List<Item> result, List<Item> rootList) { if (!result.isEmpty() && !rootList.isEmpty()) { result.add(new SpacerItem()); } result.addAll(rootList); } @Override public void onResume() { super.onResume(); Loading
src/com/android/documentsui/sidebar/UserItemsCombiner.java 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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. */ package com.android.documentsui.sidebar; import android.content.res.Resources; import static androidx.core.util.Preconditions.checkArgument; import static androidx.core.util.Preconditions.checkNotNull; import androidx.annotation.VisibleForTesting; import com.android.documentsui.R; import com.android.documentsui.base.State; import com.android.documentsui.base.UserId; import java.util.ArrayList; import java.util.List; /** * Converts user-specific lists of items into a single merged list appropriate for displaying in the * UI, including the relevant headers. */ class UserItemsCombiner { private UserId mCurrentUser; private final Resources mResources; private final State mState; private List<Item> mRootList; private List<Item> mRootListOtherUser; UserItemsCombiner(Resources resources, State state) { mCurrentUser = UserId.CURRENT_USER; mResources = checkNotNull(resources); mState = checkNotNull(state); } @VisibleForTesting UserItemsCombiner overrideCurrentUserForTest(UserId userId) { mCurrentUser = checkNotNull(userId); return this; } UserItemsCombiner setRootListForCurrentUser(List<Item> rootList) { mRootList = checkNotNull(rootList); return this; } UserItemsCombiner setRootListForOtherUser(List<Item> rootList) { mRootListOtherUser = checkNotNull(rootList); return this; } /** * Returns a combined lists from the provided lists. {@link HeaderItem}s indicating profile * will be added if the list of current user and the other user are not empty. */ public List<Item> createPresentableList() { checkArgument(mRootList != null, "RootListForCurrentUser is not set"); checkArgument(mRootListOtherUser != null, "setRootListForOtherUser is not set"); final List<Item> result = new ArrayList<>(); if (mState.supportsCrossProfile() && mState.canShareAcrossProfile) { if (!mRootList.isEmpty() && !mRootListOtherUser.isEmpty()) { // Identify personal and work root list. final List<Item> personalRootList; final List<Item> workRootList; if (mCurrentUser.isSystem()) { personalRootList = mRootList; workRootList = mRootListOtherUser; } else { personalRootList = mRootListOtherUser; workRootList = mRootList; } result.add(new HeaderItem(mResources.getString(R.string.personal_tab))); result.addAll(personalRootList); result.add(new HeaderItem(mResources.getString(R.string.work_tab))); result.addAll(workRootList); } else { result.addAll(mRootList); result.addAll(mRootListOtherUser); } } else { result.addAll(mRootList); } return result; } }