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
17package com.android.car.settings.accounts;
18
19import android.accounts.Account;
20import android.car.user.CarUserManagerHelper;
21import android.content.Context;
22import android.content.pm.UserInfo;
23import android.support.annotation.VisibleForTesting;
24import android.text.TextUtils;
25
26import androidx.car.widget.ListItem;
27import androidx.car.widget.ListItemProvider;
28import androidx.car.widget.TextListItem;
29
30import com.android.car.settings.R;
31
32import java.util.ArrayList;
33import java.util.Collections;
34import java.util.Comparator;
35import java.util.List;
36
37/**
38 * Implementation of {@link ListItemProvider} for {@link AccountsListFragment}.
39 * Creates items that represent current user's accounts.
40 */
41class AccountsItemProvider extends ListItemProvider {
42    private final List<ListItem> mItems = new ArrayList<>();
43    private final Context mContext;
44    private final AccountClickListener mItemClickListener;
45    private final CarUserManagerHelper mCarUserManagerHelper;
46    private final AccountManagerHelper mAccountManagerHelper;
47
48    AccountsItemProvider(Context context, AccountClickListener itemClickListener,
49            CarUserManagerHelper carUserManagerHelper, AccountManagerHelper accountManagerHelper) {
50        mContext = context;
51        mItemClickListener = itemClickListener;
52        mCarUserManagerHelper = carUserManagerHelper;
53        mAccountManagerHelper = accountManagerHelper;
54        refreshItems();
55    }
56
57    @Override
58    public ListItem get(int position) {
59        return mItems.get(position);
60    }
61
62    @Override
63    public int size() {
64        return mItems.size();
65    }
66
67    /**
68     * Clears and recreates the list of items.
69     */
70    public void refreshItems() {
71        mItems.clear();
72
73        UserInfo currUserInfo = mCarUserManagerHelper.getCurrentProcessUserInfo();
74
75        List<Account> accounts = getSortedUserAccounts();
76
77        // Only add account-related items if the User can Modify Accounts
78        if (mCarUserManagerHelper.canCurrentProcessModifyAccounts()) {
79            // Add "Account for $User" title for a list of accounts.
80            mItems.add(createSubtitleItem(
81                    mContext.getString(R.string.account_list_title, currUserInfo.name),
82                    accounts.isEmpty() ? mContext.getString(R.string.no_accounts_added) : ""));
83
84            // Add an item for each account owned by the current user (1st and 3rd party accounts)
85            for (Account account : accounts) {
86                mItems.add(createAccountItem(account, account.type, currUserInfo));
87            }
88        }
89    }
90
91    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
92    List<Account> getSortedUserAccounts() {
93        List<Account> accounts = mAccountManagerHelper.getAccountsForCurrentUser();
94
95        // Sort accounts
96        Collections.sort(accounts, Comparator.comparing(
97                (Account a) -> mAccountManagerHelper.getLabelForType(a.type).toString())
98                .thenComparing(a -> a.name));
99
100        return accounts;
101    }
102
103    // Creates a subtitle line for visual separation in the list
104    private ListItem createSubtitleItem(String title, String body) {
105        TextListItem item = new TextListItem(mContext);
106        item.setTitle(title);
107        item.setBody(body);
108        item.addViewBinder(viewHolder ->
109                viewHolder.getTitle().setTextAppearance(R.style.SettingsListHeader));
110        // Hiding the divider after subtitle, since subtitle is a header for a group of items.
111        item.setHideDivider(true);
112        return item;
113    }
114
115    // Creates a line for an account that belongs to a given user
116    private ListItem createAccountItem(Account account, String accountType,
117            UserInfo userInfo) {
118        TextListItem item = new TextListItem(mContext);
119        item.setPrimaryActionIcon(mAccountManagerHelper.getDrawableForType(accountType),
120                /* useLargeIcon= */ false);
121        item.setTitle(account.name);
122
123        // Set item body = account label.
124        CharSequence itemBody = mAccountManagerHelper.getLabelForType(accountType);
125        if (!TextUtils.isEmpty(itemBody)) {
126            item.setBody(itemBody.toString());
127        }
128
129        item.setOnClickListener(view -> mItemClickListener.onAccountClicked(account, userInfo));
130
131        // setHideDivider = true will hide the divider to group the items together visually.
132        // All of those without a divider between them will be part of the same "group".
133        item.setHideDivider(true);
134        return item;
135    }
136
137    /**
138     * Interface for registering clicks on account items.
139     */
140    interface AccountClickListener {
141        /**
142         * Invoked when a specific account is clicked on.
143         *
144         * @param account  Account for which to display details.
145         * @param userInfo User who's the owner of the account.
146         */
147        void onAccountClicked(Account account, UserInfo userInfo);
148    }
149}
150