Implement Install Apps button in Private Space.

UX mock: https://www.figma.com/file/K6bIIcG882EiJNjxvSWsFT/V%E2%80%A2-Private-Space?node-id=7246%3A83750&mode=dev
UX icon spec: https://www.figma.com/file/K6bIIcG882EiJNjxvSWsFT/V%E2%80%A2-Private-Space?type=design&node-id=19979-224329&mode=design&t=50SDFdomAtonNU4V-0

Video: https://drive.google.com/file/d/1VtTzxR46dLiaozOo6sOHADv1qTcBOwDP/view?usp=sharing
Screenshot:
https://screenshot.googleplex.com/3ShcUozVrkGMHbc
https://screenshot.googleplex.com/3F4c3yzJ7RUpma7

Reason to use PrivateSpaceInstallAppButtonInfo: reuse `VIEW_TYPE_ICON`, which needs an AppInfo.

Bug: 308064949
Test: manual
Flag: ACONFIG com.android.launcher3.private_space_app_installer_button development
Change-Id: I3fb27fae8324d4b276816b17f9b0a2d9b6f33ed2
This commit is contained in:
Holly Sun
2023-12-18 16:02:44 -08:00
parent a3daee40f3
commit 97b1bba413
5 changed files with 83 additions and 1 deletions

View File

@@ -0,0 +1,31 @@
<!--
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="60dp"
android:height="60dp"
android:viewportWidth="60"
android:viewportHeight="60">
<group>
<clip-path
android:pathData="M30 0H30A30 30 0 0 1 60 30V30A30 30 0 0 1 30 60H30A30 30 0 0 1 0 30V30A30 30 0 0 1 30 0Z" />
<path
android:pathData="M30 0H30A30 30 0 0 1 60 30V30A30 30 0 0 1 30 60H30A30 30 0 0 1 0 30V30A30 30 0 0 1 30 0Z"
android:fillColor="@color/material_color_surface_bright" />
<path
android:pathData="M29 31h-6v-2h6v-6h2v6h6v2h-6v6h-2v-6Z"
android:fillColor="@color/material_color_on_surface_variant" />
</group>
</vector>

View File

@@ -461,6 +461,10 @@
<string name="ps_container_lock_unlock_button">Lock/Unlock Private Space</string>
<!-- Description for Private Space Transition button -->
<string name="ps_container_transition">Private Space Transitioning</string>
<!-- Title for Private Space install app icon -->
<string name="ps_add_button_label">Install apps</string>
<!-- Content description for install app icon -->
<string name="ps_add_button_content_description">Install apps to Private Space</string>
<!-- Strings for bubble bar -->
<!-- content description for the overflow bubble [CHAR_LIMIT=none] -->

View File

@@ -322,6 +322,8 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
break;
case PrivateProfileManager.STATE_ENABLED:
// Add PS Apps only in Enabled State.
mPrivateProviderManager.addPrivateSpaceInstallAppButton(mAdapterItems);
position++;
addAppsWithSections(mPrivateApps, position);
if (mActivityContext.getAppsView() != null) {
mActivityContext.getAppsView().getActiveRecyclerView()

View File

@@ -17,11 +17,14 @@
package com.android.launcher3.allapps;
import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_ICON;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_NOTHING;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SettingsCache.PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -30,13 +33,21 @@ import android.os.UserManager;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.BuildConfig;
import com.android.launcher3.Flags;
import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.UserIconInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
/**
@@ -71,6 +82,39 @@ public class PrivateProfileManager extends UserProfileManager {
return adapterItems.size();
}
/** Adds Private Space install app button to the layout. */
public void addPrivateSpaceInstallAppButton(List<BaseAllAppsAdapter.AdapterItem> adapterItems) {
Context context = mAllApps.getContext();
// Prepare intent
UserCache userCache = UserCache.getInstance(context);
UserHandle userHandle = userCache.getUserProfiles().stream()
.filter(user -> userCache.getUserInfo(user).type == UserIconInfo.TYPE_PRIVATE)
.findFirst()
.orElse(null);
Intent intent = ApiWrapper.getAppMarketActivityIntent(context,
BuildConfig.APPLICATION_ID, userHandle);
// Prepare bitmapInfo
Intent.ShortcutIconResource shortcut = Intent.ShortcutIconResource.fromContext(
context, com.android.launcher3.R.drawable.private_space_install_app_icon);
BitmapInfo bitmapInfo = LauncherIcons.obtain(context).createIconBitmap(shortcut);
AppInfo itemInfo = new AppInfo();
itemInfo.title = context.getResources().getString(R.string.ps_add_button_label);
itemInfo.intent = intent;
itemInfo.bitmap = bitmapInfo;
itemInfo.contentDescription = context.getResources().getString(
com.android.launcher3.R.string.ps_add_button_content_description);
BaseAllAppsAdapter.AdapterItem item = new BaseAllAppsAdapter.AdapterItem(VIEW_TYPE_ICON);
item.itemInfo = itemInfo;
item.decorationInfo = new SectionDecorationInfo(context, ROUND_NOTHING,
/* decorateTogether */ true);
adapterItems.add(item);
mAllApps.mAH.get(MAIN).mAdapter.notifyItemInserted(adapterItems.size() - 1);
}
/** Disables quiet mode for Private Space User Profile. */
public void unlockPrivateProfile() {
enableQuietMode(false);

View File

@@ -55,7 +55,8 @@ public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
*/
public Intent intent;
@NonNull
// componentName for the Private Space Install App button can be null
@Nullable
public ComponentName componentName;
// Section name used for indexing.