1 /*
2  * Copyright (C) 2023 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.systemui.car.userpicker;
18 
19 import android.content.Context;
20 import android.view.LayoutInflater;
21 import android.view.View;
22 import android.view.ViewGroup;
23 import android.widget.FrameLayout;
24 import android.widget.ImageView;
25 import android.widget.TextView;
26 
27 import androidx.annotation.ColorInt;
28 import androidx.annotation.NonNull;
29 import androidx.recyclerview.widget.RecyclerView;
30 import androidx.recyclerview.widget.RecyclerView.Adapter;
31 
32 import com.android.systemui.R;
33 
34 import java.io.PrintWriter;
35 import java.util.List;
36 
37 final class UserPickerAdapter extends Adapter<UserPickerAdapter.UserPickerAdapterViewHolder> {
38     private final Context mContext;
39     private final int mDisplayId;
40     private final float mDisabledAlpha;
41     @ColorInt
42     private final int mCurrentUserSubtitleColor;
43     @ColorInt
44     private final int mOtherUserSubtitleColor;
45     private final int mVerticalSpacing;
46     private final int mHorizontalSpacing;
47     private final int mNumCols;
48 
49     private List<UserRecord> mUsers;
50     private String mLoggedInText;
51     private String mPrefixOtherSeatLoggedInInfo;
52     private String mStoppingUserText;
53 
UserPickerAdapter(Context context)54     UserPickerAdapter(Context context) {
55         mContext = context;
56         mDisplayId = mContext.getDisplayId();
57         mDisabledAlpha = mContext.getResources().getFloat(R.fraction.user_picker_disabled_alpha);
58         mCurrentUserSubtitleColor = mContext.getColor(
59                 R.color.user_picker_current_login_state_color);
60         mOtherUserSubtitleColor = mContext.getColor(R.color.user_picker_other_login_state_color);
61         mVerticalSpacing = mContext.getResources().getDimensionPixelSize(
62                 R.dimen.user_picker_vertical_space_between_users);
63         mHorizontalSpacing = mContext.getResources().getDimensionPixelSize(
64                 R.dimen.user_picker_horizontal_space_between_users);
65         mNumCols = mContext.getResources().getInteger(R.integer.user_fullscreen_switcher_num_col);
66 
67         updateTexts();
68     }
69 
updateUsers(List<UserRecord> users)70     void updateUsers(List<UserRecord> users) {
71         mUsers = users;
72     }
73 
setUserLoggedInInfo(UserPickerAdapterViewHolder holder, UserRecord userRecord)74     private void setUserLoggedInInfo(UserPickerAdapterViewHolder holder, UserRecord userRecord) {
75         if (!userRecord.mIsStopping && !userRecord.mIsLoggedIn) {
76             holder.mUserBorderImageView.setVisibility(View.INVISIBLE);
77             holder.mLoggedInTextView.setText("");
78             updateAlpha(holder, /* disabled= */ false);
79             return;
80         }
81 
82         if (userRecord.mIsStopping) {
83             holder.mUserBorderImageView.setVisibility(View.INVISIBLE);
84             holder.mLoggedInTextView.setText(mStoppingUserText);
85             holder.mLoggedInTextView.setTextColor(mOtherUserSubtitleColor);
86             updateAlpha(holder, /* disabled= */ true);
87         } else if (userRecord.mIsLoggedIn) {
88             if (userRecord.mLoggedInDisplay == mDisplayId) {
89                 holder.mUserBorderImageView.setVisibility(View.VISIBLE);
90                 holder.mLoggedInTextView.setText(mLoggedInText);
91                 holder.mLoggedInTextView.setTextColor(mCurrentUserSubtitleColor);
92                 updateAlpha(holder, /* disabled= */ false);
93             } else {
94                 holder.mUserBorderImageView.setVisibility(View.INVISIBLE);
95                 holder.mLoggedInTextView.setText(String.format(mPrefixOtherSeatLoggedInInfo,
96                         userRecord.mSeatLocationName));
97                 holder.mLoggedInTextView.setTextColor(mOtherUserSubtitleColor);
98                 updateAlpha(holder, /* disabled= */ true);
99             }
100         }
101     }
102 
updateAlpha(UserPickerAdapterViewHolder holder, boolean disabled)103     private void updateAlpha(UserPickerAdapterViewHolder holder, boolean disabled) {
104         float alpha = disabled ? mDisabledAlpha : 1.0f;
105         holder.mUserAvatarImageView.setAlpha(alpha);
106         holder.mUserNameTextView.setAlpha(alpha);
107         holder.mLoggedInTextView.setAlpha(alpha);
108     }
109 
110     @Override
onCreateViewHolder(@onNull ViewGroup parent, int viewType)111     public UserPickerAdapterViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
112         View view = LayoutInflater.from(mContext)
113                 .inflate(R.layout.user_picker_user_pod, parent, false);
114         view.setAlpha(1f);
115         view.bringToFront();
116         return new UserPickerAdapterViewHolder(view);
117     }
118 
119     @Override
onBindViewHolder(@onNull UserPickerAdapterViewHolder holder, int position)120     public void onBindViewHolder(@NonNull UserPickerAdapterViewHolder holder, int position) {
121         setItemSpacing(holder.mView, position);
122         UserRecord userRecord = mUsers.get(position);
123         holder.mUserAvatarImageView.setImageDrawable(userRecord.mIcon);
124         holder.mFrame.setBackgroundResource(0);
125         holder.mUserNameTextView.setText(userRecord.mName);
126         setUserLoggedInInfo(holder, userRecord);
127         holder.mView.setOnClickListener(userRecord.mOnClickListener);
128     }
129 
130     @Override
getItemCount()131     public int getItemCount() {
132         return mUsers != null ? mUsers.size() : 0;
133     }
134 
onConfigurationChanged()135     void onConfigurationChanged() {
136         updateTexts();
137     }
138 
updateTexts()139     private void updateTexts() {
140         mLoggedInText = mContext.getString(R.string.logged_in_text);
141         mPrefixOtherSeatLoggedInInfo = mContext
142                 .getString(R.string.prefix_logged_in_info_for_other_seat);
143         mStoppingUserText = mContext.getString(R.string.stopping_user_text);
144     }
145 
146     // TODO(b/281729191) use RecyclerView.ItemDecoration when supported by CarUiRecyclerView
setItemSpacing(View rootItemView, int position)147     private void setItemSpacing(View rootItemView, int position) {
148         ViewGroup.LayoutParams params = rootItemView.getLayoutParams();
149         if (params instanceof ViewGroup.MarginLayoutParams) {
150             ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) params;
151             marginLayoutParams.bottomMargin = mVerticalSpacing;
152 
153             int splitHorizontalSpacing = mHorizontalSpacing / mNumCols;
154             int col = position % mNumCols;
155             marginLayoutParams.leftMargin = col * splitHorizontalSpacing;
156             marginLayoutParams.rightMargin = (mNumCols - (col + 1)) * splitHorizontalSpacing;
157 
158             rootItemView.setLayoutParams(marginLayoutParams);
159         }
160     }
161 
dump(@onNull PrintWriter pw)162     void dump(@NonNull PrintWriter pw) {
163         pw.println("  UserRecords : ");
164         for (int i = 0; i < mUsers.size(); i++) {
165             UserRecord userRecord = mUsers.get(i);
166             pw.println("    " + userRecord.toString());
167         }
168     }
169 
170     static final class UserPickerAdapterViewHolder extends RecyclerView.ViewHolder {
171         public final ImageView mUserAvatarImageView;
172         public final TextView mUserNameTextView;
173         public final ImageView mUserBorderImageView;
174         public final TextView mLoggedInTextView;
175         public final View mView;
176         public final FrameLayout mFrame;
177 
UserPickerAdapterViewHolder(View view)178         UserPickerAdapterViewHolder(View view) {
179             super(view);
180             mView = view;
181             mUserAvatarImageView = view.findViewById(R.id.user_avatar);
182             mUserNameTextView = view.findViewById(R.id.user_name);
183             mUserBorderImageView = view.findViewById(R.id.user_avatar_border);
184             mLoggedInTextView = view.findViewById(R.id.logged_in_info);
185             mFrame = view.findViewById(R.id.current_user_frame);
186         }
187     }
188 }
189