• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static com.android.documentsui.DevicePolicyResources.Drawables.Style.SOLID_NOT_COLORED;
20 import static com.android.documentsui.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
21 import static com.android.documentsui.base.DocumentInfo.getCursorInt;
22 import static com.android.documentsui.base.DocumentInfo.getCursorLong;
23 import static com.android.documentsui.base.DocumentInfo.getCursorString;
24 
25 import android.app.admin.DevicePolicyManager;
26 import android.content.Context;
27 import android.database.Cursor;
28 import android.graphics.drawable.Drawable;
29 import android.os.Build;
30 import android.provider.DocumentsContract.Document;
31 import android.text.format.Formatter;
32 import android.view.MotionEvent;
33 import android.view.View;
34 import android.view.ViewGroup;
35 import android.widget.ImageView;
36 
37 import androidx.annotation.RequiresApi;
38 
39 import com.android.documentsui.ConfigStore;
40 import com.android.documentsui.DocumentsApplication;
41 import com.android.documentsui.R;
42 import com.android.documentsui.base.DocumentInfo;
43 import com.android.documentsui.base.Shared;
44 import com.android.documentsui.base.UserId;
45 import com.android.documentsui.roots.RootCursorWrapper;
46 import com.android.documentsui.ui.Views;
47 import com.android.modules.utils.build.SdkLevel;
48 
49 import java.util.Map;
50 import java.util.function.Function;
51 
52 final class GridPhotoHolder extends DocumentHolder {
53 
54     private final ImageView mIconMimeLg;
55     private final ImageView mIconThumb;
56     private final ImageView mIconCheck;
57     private final IconHelper mIconHelper;
58     private final View mPreviewIcon;
59     private final View mIconBadge;
60 
61     // This is used in as a convenience in our bind method.
62     private final DocumentInfo mDoc = new DocumentInfo();
63 
GridPhotoHolder(Context context, ViewGroup parent, IconHelper iconHelper, ConfigStore configStore)64     GridPhotoHolder(Context context, ViewGroup parent, IconHelper iconHelper,
65             ConfigStore configStore) {
66         super(context, parent, R.layout.item_photo_grid, configStore);
67 
68         mIconMimeLg = (ImageView) itemView.findViewById(R.id.icon_mime_lg);
69         mIconThumb = (ImageView) itemView.findViewById(R.id.icon_thumb);
70         mIconCheck = (ImageView) itemView.findViewById(R.id.icon_check);
71         mIconBadge = itemView.findViewById(R.id.icon_profile_badge);
72         mPreviewIcon = itemView.findViewById(R.id.preview_icon);
73 
74         mIconHelper = iconHelper;
75 
76         if (SdkLevel.isAtLeastT() && !mConfigStore.isPrivateSpaceInDocsUIEnabled()) {
77             setUpdatableWorkProfileIcon(context);
78         }
79     }
80 
81     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
setUpdatableWorkProfileIcon(Context context)82     private void setUpdatableWorkProfileIcon(Context context) {
83         DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
84         Drawable drawable = dpm.getResources().getDrawable(
85                 WORK_PROFILE_ICON, SOLID_NOT_COLORED, () ->
86                         context.getDrawable(R.drawable.ic_briefcase));
87         ImageView icon = (ImageView) mIconBadge.findViewById(R.id.icon_id);
88 
89         icon.setImageDrawable(drawable);
90     }
91 
92     @Override
setSelected(boolean selected, boolean animate)93     public void setSelected(boolean selected, boolean animate) {
94         // We always want to make sure our check box disappears if we're not selected,
95         // even if the item is disabled. This is because this object can be reused
96         // and this method will be called to setup initial state.
97         float checkAlpha = selected ? 1f : 0f;
98         if (animate) {
99             fade(mIconCheck, checkAlpha).start();
100         } else {
101             mIconCheck.setAlpha(checkAlpha);
102         }
103 
104         // But it should be an error to be set to selected && be disabled.
105         if (!itemView.isEnabled()) {
106             assert (!selected);
107             return;
108         }
109 
110         super.setSelected(selected, animate);
111     }
112 
113     @Override
setEnabled(boolean enabled)114     public void setEnabled(boolean enabled) {
115         super.setEnabled(enabled);
116 
117         float imgAlpha = enabled ? 1f : DISABLED_ALPHA;
118 
119         mIconMimeLg.setAlpha(imgAlpha);
120         mIconThumb.setAlpha(imgAlpha);
121     }
122 
123     @Override
bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback)124     public void bindPreviewIcon(boolean show, Function<View, Boolean> clickCallback) {
125         mPreviewIcon.setVisibility(show ? View.VISIBLE : View.GONE);
126         if (show) {
127             mPreviewIcon.setContentDescription(
128                     getPreviewIconContentDescription(
129                             mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier()),
130                             mDoc.displayName, mDoc.userId));
131             mPreviewIcon.setAccessibilityDelegate(new PreviewAccessibilityDelegate(clickCallback));
132         }
133     }
134 
135     @Override
bindBriefcaseIcon(boolean show)136     public void bindBriefcaseIcon(boolean show) {
137         mIconBadge.setVisibility(show ? View.VISIBLE : View.GONE);
138     }
139 
140     @Override
141     @RequiresApi(Build.VERSION_CODES.S)
bindProfileIcon(boolean show, int userIdIdentifier)142     public void bindProfileIcon(boolean show, int userIdIdentifier) {
143         Map<UserId, Drawable> userIdToBadgeMap = DocumentsApplication.getUserManagerState(
144                 mContext).getUserIdToBadgeMap();
145         Drawable drawable = userIdToBadgeMap.get(UserId.of(userIdIdentifier));
146         ImageView icon = mIconBadge.findViewById(R.id.icon_id);
147         icon.setImageDrawable(drawable);
148         mIconBadge.setVisibility(show ? View.VISIBLE : View.GONE);
149         mIconBadge.setContentDescription(mIconHelper.getProfileLabel(userIdIdentifier));
150     }
151 
152     @Override
inDragRegion(MotionEvent event)153     public boolean inDragRegion(MotionEvent event) {
154         // Entire grid box should be draggable
155         return true;
156     }
157 
158     @Override
inSelectRegion(MotionEvent event)159     public boolean inSelectRegion(MotionEvent event) {
160         // Photo gird should not have any select region.
161         return false;
162     }
163 
164     @Override
inPreviewIconRegion(MotionEvent event)165     public boolean inPreviewIconRegion(MotionEvent event) {
166         return Views.isEventOver(event, itemView.getParent(), mPreviewIcon);
167     }
168 
169     /**
170      * Bind this view to the given document for display.
171      *
172      * @param cursor  Pointing to the item to be bound.
173      * @param modelId The model ID of the item.
174      */
175     @Override
bind(Cursor cursor, String modelId)176     public void bind(Cursor cursor, String modelId) {
177         assert (cursor != null);
178 
179         mModelId = modelId;
180 
181         mDoc.updateFromCursor(cursor,
182                 UserId.of(getCursorInt(cursor, RootCursorWrapper.COLUMN_USER_ID)),
183                 getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY));
184 
185         mIconHelper.stopLoading(mIconThumb);
186 
187         mIconMimeLg.animate().cancel();
188         mIconMimeLg.setAlpha(1f);
189         mIconThumb.animate().cancel();
190         mIconThumb.setAlpha(0f);
191 
192         mIconHelper.load(mDoc, mIconThumb, mIconMimeLg, null);
193 
194         final String docSize =
195                 Formatter.formatFileSize(mContext, getCursorLong(cursor, Document.COLUMN_SIZE));
196         final String docDate = Shared.formatTime(mContext, mDoc.lastModified);
197         if (mIconHelper.shouldShowBadge(mDoc.userId.getIdentifier())) {
198             itemView.setContentDescription(
199                     mIconHelper.getProfileLabel(mDoc.userId.getIdentifier())
200                             + ", "
201                             + mDoc.displayName
202                             + ", "
203                             + docSize
204                             + ", "
205                             + docDate);
206         } else {
207             itemView.setContentDescription(mDoc.displayName + ", " + docSize + ", " + docDate);
208         }
209     }
210 }
211