1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.documentsui.dirlist;
18 
19 import android.text.TextUtils;
20 import android.view.LayoutInflater;
21 import android.view.View;
22 import android.widget.ImageView;
23 import android.widget.LinearLayout;
24 import android.widget.TextView;
25 
26 import com.android.documentsui.ActionHandler;
27 import com.android.documentsui.BaseActivity;
28 import com.android.documentsui.ConfigStore;
29 import com.android.documentsui.R;
30 import com.android.documentsui.UserIdManager;
31 import com.android.documentsui.UserManagerState;
32 import com.android.documentsui.base.State;
33 import com.android.documentsui.base.UserId;
34 import com.android.documentsui.dirlist.AppsRowItemData.AppData;
35 import com.android.documentsui.dirlist.AppsRowItemData.RootData;
36 import com.android.documentsui.sidebar.AppItem;
37 import com.android.documentsui.sidebar.Item;
38 import com.android.documentsui.sidebar.RootItem;
39 import com.android.modules.utils.build.SdkLevel;
40 
41 import java.util.ArrayList;
42 import java.util.HashMap;
43 import java.util.List;
44 import java.util.Map;
45 
46 /**
47  * A manager class stored apps row chip data list. Data will be synced by RootsFragment.
48  */
49 public class AppsRowManager {
50 
51     private final ActionHandler mActionHandler;
52     private final List<AppsRowItemData> mDataList;
53     private final boolean mMaybeShowBadge;
54     private final UserIdManager mUserIdManager;
55     private final UserManagerState mUserManagerState;
56     private final ConfigStore mConfigStore;
57 
AppsRowManager(ActionHandler handler, boolean maybeShowBadge, UserIdManager userIdManager, ConfigStore configStore)58     public AppsRowManager(ActionHandler handler, boolean maybeShowBadge,
59             UserIdManager userIdManager, ConfigStore configStore) {
60         mDataList = new ArrayList<>();
61         mActionHandler = handler;
62         mMaybeShowBadge = maybeShowBadge;
63         mUserIdManager = userIdManager;
64         mUserManagerState = null;
65         mConfigStore = configStore;
66     }
67 
AppsRowManager(ActionHandler handler, boolean maybeShowBadge, UserManagerState userManagerState, ConfigStore configStore)68     public AppsRowManager(ActionHandler handler, boolean maybeShowBadge,
69             UserManagerState userManagerState, ConfigStore configStore) {
70         mDataList = new ArrayList<>();
71         mActionHandler = handler;
72         mMaybeShowBadge = maybeShowBadge;
73         mUserIdManager = null;
74         mUserManagerState = userManagerState;
75         mConfigStore = configStore;
76     }
77 
updateList(List<Item> itemList)78     public List<AppsRowItemData> updateList(List<Item> itemList) {
79         mDataList.clear();
80 
81         // If more than 1 item of the same package, show item summary (e.g. account id).
82         Map<String, Integer> packageNameCount = new HashMap<>();
83         for (Item item : itemList) {
84             String packageName = item.getPackageName();
85             int previousCount = packageNameCount.containsKey(packageName)
86                     && !TextUtils.isEmpty(packageName)
87                     ? packageNameCount.get(packageName) : 0;
88             packageNameCount.put(packageName, previousCount + 1);
89         }
90 
91         for (Item item : itemList) {
92             boolean shouldShowSummary = packageNameCount.get(item.getPackageName()) > 1;
93             if (item instanceof RootItem) {
94                 mDataList.add(new RootData((RootItem) item, mActionHandler, shouldShowSummary,
95                         mMaybeShowBadge));
96             } else {
97                 mDataList.add(new AppData((AppItem) item, mActionHandler, shouldShowSummary,
98                         mMaybeShowBadge));
99             }
100         }
101         return mDataList;
102     }
103 
shouldShow(State state, boolean isSearchExpanded)104     private boolean shouldShow(State state, boolean isSearchExpanded) {
105         boolean isHiddenAction = state.action == State.ACTION_CREATE
106                 || state.action == State.ACTION_OPEN_TREE
107                 || state.action == State.ACTION_PICK_COPY_DESTINATION;
108         boolean isSearchExpandedAcrossProfile = getUserIds().size() > 1
109                 && state.supportsCrossProfile()
110                 && isSearchExpanded;
111 
112         return state.stack.isRecents() && !isHiddenAction && mDataList.size() > 0
113                 && !isSearchExpandedAcrossProfile;
114     }
115 
updateView(BaseActivity activity)116     public void updateView(BaseActivity activity) {
117         final View appsRowLayout = activity.findViewById(R.id.apps_row);
118 
119         if (!shouldShow(activity.getDisplayState(), activity.isSearchExpanded())) {
120             appsRowLayout.setVisibility(View.GONE);
121             return;
122         }
123 
124         final LinearLayout appsGroup = activity.findViewById(R.id.apps_group);
125         appsGroup.removeAllViews();
126 
127         final LayoutInflater inflater = activity.getLayoutInflater();
128         final UserId selectedUser = activity.getSelectedUser();
129         for (AppsRowItemData data : mDataList) {
130             if (selectedUser.equals(data.getUserId())) {
131                 View item = inflater.inflate(R.layout.apps_item, appsGroup, false);
132                 bindView(item, data);
133                 appsGroup.addView(item);
134             }
135         }
136 
137         appsRowLayout.setVisibility(appsGroup.getChildCount() > 0 ? View.VISIBLE : View.GONE);
138     }
139 
bindView(View view, AppsRowItemData data)140     private void bindView(View view, AppsRowItemData data) {
141         final ImageView app_icon = view.findViewById(R.id.app_icon);
142         final TextView title = view.findViewById(android.R.id.title);
143         final TextView summary = view.findViewById(R.id.summary);
144 
145         app_icon.setImageDrawable(data.getIconDrawable(view.getContext()));
146         title.setText(data.getTitle());
147         title.setContentDescription(
148                 data.getUserId().getUserBadgedLabel(view.getContext(), data.getTitle()));
149         summary.setText(data.getSummary());
150         summary.setVisibility(data.getSummary() != null ? View.VISIBLE : View.GONE);
151         view.setOnClickListener(v -> data.onClicked());
152     }
153 
getUserIds()154     private List<UserId> getUserIds() {
155         if (mConfigStore.isPrivateSpaceInDocsUIEnabled() && SdkLevel.isAtLeastS()) {
156             return mUserManagerState.getUserIds();
157         }
158         return mUserIdManager.getUserIds();
159     }
160 }
161