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

Commit 0cc11dbc authored by Himanshu Gupta's avatar Himanshu Gupta
Browse files

Separating system and user-installed apps in PS container.

We add a horizontal line separator in PS container which demarcates
user-installed vs system installed apps in private space.
User-installed are shown above the separator, system ones below.

UX Mock: https://www.figma.com/file/K6bIIcG882EiJNjxvSWsFT/V%E2%80%A2-Private-Space?node-id=11546%3A310574&mode=dev
Mock Image: https://photos.app.goo.gl/Wj8sJkS7P7bRbovg8
Demo video: https://photos.app.goo.gl/MBw6HpDnf6PJqUfs8

Bug: 308054233
Flag: ACONFIG com.android.launcher3.Flags.private_space_sys_apps_separation DEVELOPMENT
Test: AlphabeticalAppsListTest
Change-Id: Iad8e289c49a05ac7ef1978bd8e4ebe7aa0add0ca
parent 0e08d300
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
  ~ Copyright (C) 2023 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.
  -->

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="?attr/materialColorOutlineVariant"/>
    <size android:height="1dp" />
</shape>
 No newline at end of file
+25 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
  ~ Copyright (C) 2024 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.
  -->
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/private_space_divider"
    android:importantForAccessibility="no"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingLeft="@dimen/ps_app_divider_padding"
    android:paddingRight="@dimen/ps_app_divider_padding"
    android:src="@drawable/private_space_app_divider"
    android:scaleType="fitXY"
    android:focusable="false" />
 No newline at end of file
+1 −0
Original line number Diff line number Diff line
@@ -487,4 +487,5 @@
    <dimen name="ps_button_height">36dp</dimen>
    <dimen name="ps_button_width">36dp</dimen>
    <dimen name="ps_lock_button_width">89dp</dimen>
    <dimen name="ps_app_divider_padding">16dp</dimen>
</resources>
+34 −9
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.function.Predicate;
@@ -269,10 +270,10 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
                addApps = mWorkProviderManager.shouldShowWorkApps();
            }
            if (addApps) {
                addAppsWithSections(mApps, position);
                position = addAppsWithSections(mApps, position);
            }
            if (Flags.enablePrivateSpace()) {
                addPrivateSpaceItems(position);
                position = addPrivateSpaceItems(position);
            }
        }
        mAccessibilityResultsCount = (int) mAdapterItems.stream()
@@ -287,7 +288,8 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
            for (AdapterItem item : mAdapterItems) {
                item.rowIndex = 0;
                if (BaseAllAppsAdapter.isDividerViewType(item.viewType)
                        || BaseAllAppsAdapter.isPrivateSpaceHeaderView(item.viewType)) {
                        || BaseAllAppsAdapter.isPrivateSpaceHeaderView(item.viewType)
                        || BaseAllAppsAdapter.isPrivateSpaceSysAppsDividerView(item.viewType)) {
                    numAppsInSection = 0;
                } else if (BaseAllAppsAdapter.isIconViewType(item.viewType)) {
                    if (numAppsInSection % mNumAppsPerRowAllApps == 0) {
@@ -309,12 +311,12 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
        }
    }

    void addPrivateSpaceItems(int position) {
    int addPrivateSpaceItems(int position) {
        if (mPrivateProviderManager != null
                && !mPrivateProviderManager.isPrivateSpaceHidden()
                && !mPrivateApps.isEmpty()) {
            // Always add PS Header if Space is present and visible.
            position += mPrivateProviderManager.addPrivateSpaceHeader(mAdapterItems);
            position = mPrivateProviderManager.addPrivateSpaceHeader(mAdapterItems);
            int privateSpaceState = mPrivateProviderManager.getCurrentState();
            switch (privateSpaceState) {
                case PrivateProfileManager.STATE_DISABLED:
@@ -322,15 +324,37 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
                    break;
                case PrivateProfileManager.STATE_ENABLED:
                    // Add PS Apps only in Enabled State.
                    position = addPrivateSpaceApps(position);
                    break;
            }
        }
        return position;
    }

    private int addPrivateSpaceApps(int position) {
        // Add Install Apps Button first.
        if (Flags.privateSpaceAppInstallerButton()) {
            mPrivateProviderManager.addPrivateSpaceInstallAppButton(mAdapterItems);
            position++;
                    addAppsWithSections(mPrivateApps, position);
                    break;
        }

        // Split of private space apps into user-installed and system apps.
        Map<Boolean, List<AppInfo>> split = mPrivateApps.stream()
                .collect(Collectors.partitioningBy(mPrivateProviderManager
                                .splitIntoUserInstalledAndSystemApps()));
        // Add user installed apps
        position = addAppsWithSections(split.get(true), position);
        // Add system apps separator.
        if (Flags.privateSpaceSysAppsSeparation()) {
            position = mPrivateProviderManager.addSystemAppsDivider(mAdapterItems);
        }
        // Add system apps.
        position = addAppsWithSections(split.get(false), position);

        return position;
    }

    private void addAppsWithSections(List<AppInfo> appList, int startPosition) {
    private int addAppsWithSections(List<AppInfo> appList, int startPosition) {
        String lastSectionName = null;
        boolean hasPrivateApps = false;
        if (mPrivateProviderManager != null) {
@@ -357,6 +381,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
            }
            startPosition++;
        }
        return startPosition;
    }

    /**
+17 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.launcher3.allapps;

import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_LEFT;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_RIGHT;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_NOTHING;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_TOP_LEFT;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_TOP_RIGHT;
import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED;
@@ -61,7 +62,8 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
    public static final int VIEW_TYPE_WORK_EDU_CARD = 1 << 4;
    public static final int VIEW_TYPE_WORK_DISABLED_CARD = 1 << 5;
    public static final int VIEW_TYPE_PRIVATE_SPACE_HEADER = 1 << 6;
    public static final int NEXT_ID = 7;
    public static final int VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER = 1 << 7;
    public static final int NEXT_ID = 8;

    // Common view type masks
    public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
@@ -69,6 +71,8 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex

    public static final int VIEW_TYPE_MASK_PRIVATE_SPACE_HEADER =
            VIEW_TYPE_PRIVATE_SPACE_HEADER;
    public static final int VIEW_TYPE_MASK_PRIVATE_SPACE_SYS_APPS_DIVIDER =
            VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER;

    protected final SearchAdapterProvider<?> mAdapterProvider;

@@ -199,6 +203,11 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
        return isViewType(viewType, VIEW_TYPE_MASK_PRIVATE_SPACE_HEADER);
    }

    /** Checks if the passed viewType represents private space system apps divider. */
    public static boolean isPrivateSpaceSysAppsDividerView(int viewType) {
        return isViewType(viewType, VIEW_TYPE_MASK_PRIVATE_SPACE_SYS_APPS_DIVIDER);
    }

    public void setIconFocusListener(OnFocusChangeListener focusListener) {
        mIconFocusListener = focusListener;
    }
@@ -227,9 +236,9 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
            case VIEW_TYPE_EMPTY_SEARCH:
                return new ViewHolder(mLayoutInflater.inflate(R.layout.all_apps_empty_search,
                        parent, false));
            case VIEW_TYPE_ALL_APPS_DIVIDER:
            case VIEW_TYPE_ALL_APPS_DIVIDER, VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER:
                return new ViewHolder(mLayoutInflater.inflate(
                        R.layout.all_apps_divider, parent, false));
                        R.layout.private_space_divider, parent, false));
            case VIEW_TYPE_WORK_EDU_CARD:
                return new ViewHolder(mLayoutInflater.inflate(
                        R.layout.work_apps_edu, parent, false));
@@ -282,6 +291,11 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
                        new SectionDecorationInfo(mActivityContext, roundRegions,
                                false /* decorateTogether */);
                break;
            case VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER:
                adapterItem = mApps.getAdapterItems().get(position);
                adapterItem.decorationInfo = new SectionDecorationInfo(mActivityContext,
                        ROUND_NOTHING, true /* decorateTogether */);
                break;
            case VIEW_TYPE_ALL_APPS_DIVIDER:
            case VIEW_TYPE_WORK_DISABLED_CARD:
                // nothing to do
Loading