Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b9f85bf authored by Kelvin Kwan's avatar Kelvin Kwan
Browse files

Add TabLayout UI to on BaseActivity and show it conditionally

There will be a new tablayout UI added to PickActivity on device with
managed user.
Tapping on the UI does nothing at the moment.

Test: atest DocumentsUIGoogleTests:com.android.documentsui.ProfileTabsTest
Bug: 148264331
Change-Id: I727b28dbae7fac59a3da9da7f16ae7c3608a1a0f
parent 5ab79aaa
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -28,6 +28,12 @@
    <!-- used for search chip. -->
    <include layout="@layout/search_chip_row"/>

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabs"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"/>

    <!-- used for apps row. -->
    <include layout="@layout/apps_row"/>

+6 −0
Original line number Diff line number Diff line
@@ -483,4 +483,10 @@

    <!-- Content description for deleting search history. [CHAR_LIMIT=60] -->
    <string name="delete_search_history">Delete search history <xliff:g id="text" example="image">%1$s</xliff:g></string>

    <!-- Label of tab to indicate personal directory [CHAR LIMIT=40] -->
    <string name="personal_tab">Personal</string>

    <!-- Label of tab to indicate work directory [CHAR LIMIT=40] -->
    <string name="work_tab">Work</string>
</resources>
+10 −3
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import com.android.documentsui.sorting.SortController;
import com.android.documentsui.sorting.SortModel;

import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.tabs.TabLayout;

import java.util.ArrayList;
import java.util.Date;
@@ -95,7 +96,6 @@ public abstract class BaseActivity
    protected Injector<?> mInjector;

    protected ProvidersCache mProviders;
    protected UserIdManager mUserIdManager;
    protected DocumentsAccess mDocs;
    protected DrawerController mDrawer;

@@ -153,7 +153,6 @@ public abstract class BaseActivity
        mDrawer = DrawerController.create(this, mInjector.config);
        Metrics.logActivityLaunch(mState, intent);

        mUserIdManager = DocumentsApplication.getUserIdManager(this);
        mProviders = DocumentsApplication.getProvidersCache(this);
        mDocs = DocumentsAccess.create(this);

@@ -162,8 +161,11 @@ public abstract class BaseActivity

        Breadcrumb breadcrumb = findViewById(R.id.horizontal_breadcrumb);
        assert(breadcrumb != null);
        TabLayout profileTabs = findViewById(R.id.tabs);
        assert (profileTabs != null);

        mNavigator = new NavigationViewManager(this, mDrawer, mState, this, breadcrumb);
        mNavigator = new NavigationViewManager(this, mDrawer, mState, this, breadcrumb,
                profileTabs, DocumentsApplication.getUserIdManager(this));
        SearchManagerListener searchListener = new SearchManagerListener() {
            /**
             * Called when search results changed. Refreshes the content of the directory. It
@@ -738,6 +740,11 @@ public abstract class BaseActivity
        return mSearchManager.isExpanded();
    }

    @Override
    public boolean isSearching() {
        return mSearchManager.isSearching();
    }

    @Override
    public RootInfo getCurrentRoot() {
        RootInfo root = mState.stack.getRoot();
+8 −2
Original line number Diff line number Diff line
@@ -29,13 +29,13 @@ import android.view.ViewOutlineProvider;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;

import com.android.documentsui.R;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.AnimationView;

import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
import com.google.android.material.tabs.TabLayout;

import java.util.function.IntConsumer;

@@ -51,6 +51,7 @@ public class NavigationViewManager {
    private final State mState;
    private final NavigationViewManager.Environment mEnv;
    private final Breadcrumb mBreadcrumb;
    private final ProfileTabs mProfileTabs;
    private final View mSearchBarView;
    private final CollapsingToolbarLayout mCollapsingBarLayout;
    private final Drawable mDefaultActionBarBackground;
@@ -62,7 +63,9 @@ public class NavigationViewManager {
            DrawerController drawer,
            State state,
            NavigationViewManager.Environment env,
            Breadcrumb breadcrumb) {
            Breadcrumb breadcrumb,
            TabLayout tabLayout,
            UserIdManager userIdManager) {

        mToolbar = activity.findViewById(R.id.toolbar);
        mDrawer = drawer;
@@ -70,6 +73,7 @@ public class NavigationViewManager {
        mEnv = env;
        mBreadcrumb = breadcrumb;
        mBreadcrumb.setup(env, state, this::onNavigationItemSelected);
        mProfileTabs = new ProfileTabs(tabLayout, mState, userIdManager, mEnv);

        mToolbar.setNavigationOnClickListener(
                new View.OnClickListener() {
@@ -122,6 +126,7 @@ public class NavigationViewManager {
    public void update() {
        updateScrollFlag();
        updateToolbar();
        mProfileTabs.updateView();

        // TODO: Looks to me like this block is never getting hit.
        if (mEnv.isSearchExpanded()) {
@@ -214,5 +219,6 @@ public class NavigationViewManager {
        @Deprecated  // Use CommonAddones#refreshCurrentRootAndDirectory
        void refreshCurrentRootAndDirectory(int animation);
        boolean isSearchExpanded();
        boolean isSearching();
    }
}
+106 −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;

import static androidx.core.util.Preconditions.checkNotNull;

import android.view.View;

import androidx.annotation.VisibleForTesting;

import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;

import com.google.android.material.tabs.TabLayout;

import java.util.Collections;
import java.util.List;

/**
 * A manager class to control UI on a {@link TabLayout} for cross-profile purpose.
 */
public class ProfileTabs {

    private final TabLayout mTabs;
    private final State mState;
    private final NavigationViewManager.Environment mEnv;
    private final UserIdManager mUserIdManager;
    private List<UserId> mUserIds;

    public ProfileTabs(TabLayout tabLayout, State state, UserIdManager userIdManager,
            NavigationViewManager.Environment env) {
        mTabs = checkNotNull(tabLayout);
        mState = checkNotNull(state);
        mEnv = checkNotNull(env);
        mUserIdManager = checkNotNull(userIdManager);
        mTabs.removeAllTabs();
        mUserIds = Collections.singletonList(UserId.CURRENT_USER);
    }

    /**
     * Update the tab layout based on conditions.
     */
    public void updateView() {
        updateTabsIfNeeded();
        mTabs.setVisibility(shouldShow() ? View.VISIBLE : View.GONE);
    }

    private void updateTabsIfNeeded() {
        List<UserId> userIds = mUserIdManager.getUserIds();
        // Add tabs if the userIds is not equals to cached mUserIds.
        // Given that mUserIds was initialized with only the current user, if getUserIds()
        // returns just the current user, we don't need to do anything on the tab layout.
        if (!userIds.equals(mUserIds)) {
            mUserIds = userIds;
            mTabs.removeAllTabs();
            if (mUserIds.size() > 1) {
                mTabs.addTab(createTab(R.string.personal_tab, mUserIdManager.getSystemUser()));
                mTabs.addTab(createTab(R.string.work_tab, mUserIdManager.getManagedUser()));
            }
        }
    }

    /**
     * Returns the user represented by the selected tab. If there is no tab, return the
     * current user.
     */
    @VisibleForTesting
    public UserId getSelectedUser() {
        if (mTabs.getTabCount() > 1 && mTabs.getSelectedTabPosition() >= 0) {
            return (UserId) mTabs.getTabAt(mTabs.getSelectedTabPosition()).getTag();
        }
        return UserId.CURRENT_USER;
    }

    private boolean shouldShow() {
        // Only show tabs when:
        // 1. state supports cross profile, and
        // 2. more than one tab, and
        // 3. not in search mode, and
        // 4. not in sub-folder, and
        // 5. the root supports cross profile.
        return mState.supportsCrossProfile()
                && mTabs.getTabCount() > 1
                && !mEnv.isSearching()
                && mState.stack.size() <= 1
                && mState.stack.getRoot() != null && mState.stack.getRoot().supportsCrossProfile();
    }

    private TabLayout.Tab createTab(int resId, UserId userId) {
        return mTabs.newTab().setText(resId).setTag(userId);
    }
}
Loading