1/*
2 * Copyright (C) 2017 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.dialer;
18
19import android.content.Context;
20import android.content.Intent;
21import android.graphics.Bitmap;
22import android.graphics.BitmapFactory;
23import android.net.Uri;
24import android.support.annotation.Nullable;
25import android.support.v7.widget.RecyclerView;
26import android.view.View;
27import android.widget.ImageView;
28import android.widget.TextView;
29
30import com.android.car.apps.common.CircleBitmapDrawable;
31import com.android.car.apps.common.LetterTileDrawable;
32
33import java.io.FileNotFoundException;
34import java.io.InputStream;
35
36/**
37 * A {@link android.support.v7.widget.RecyclerView.ViewHolder} that will parse relevant
38 * views out of a {@code contact_result} layout.
39 */
40public class ContactResultViewHolder extends RecyclerView.ViewHolder {
41    private final Context mContext;
42    private final View mContactCard;
43    private final TextView mContactName;
44    private final ImageView mContactPicture;
45
46    public ContactResultViewHolder(View view) {
47        super(view);
48        mContext = view.getContext();
49        mContactCard = view.findViewById(R.id.contact_result_card);
50        mContactName = view.findViewById(R.id.contact_name);
51        mContactPicture = view.findViewById(R.id.contact_picture);
52    }
53
54    /**
55     * Populates the view that is represented by this ViewHolder with the information in the
56     * provided {@link ContactDetails}.
57     */
58    public void bind(ContactDetails details, int itemCount) {
59        updateBackground(itemCount);
60
61        mContactCard.setOnClickListener(v -> {
62            Intent intent = new Intent();
63            intent.setAction(TelecomIntents.ACTION_SHOW_CONTACT_DETAILS);
64            intent.putExtra(TelecomIntents.CONTACT_LOOKUP_URI_EXTRA, details.lookupUri.toString());
65            mContext.startActivity(intent);
66        });
67
68        mContactName.setText(details.displayName);
69
70        if (details.photoUri == null) {
71            setLetterDrawableForContact(details);
72            return;
73        }
74
75        Bitmap bitmap = getContactBitmapFromUri(mContext, details.photoUri);
76        if (bitmap == null) {
77            setLetterDrawableForContact(details);
78        } else {
79            mContactPicture.setScaleType(ImageView.ScaleType.CENTER_CROP);
80            mContactPicture.setImageDrawable(
81                    new CircleBitmapDrawable(mContext.getResources(), bitmap));
82        }
83    }
84
85    /**
86     * Sets the contact picture to be a rounded, colored circle that has the first letter of the
87     * contact's name in it.
88     */
89    private void setLetterDrawableForContact(ContactDetails details) {
90        mContactPicture.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
91        LetterTileDrawable letterTileDrawable = new LetterTileDrawable(mContext.getResources());
92        letterTileDrawable.setContactDetails(details.displayName, details.displayName);
93        letterTileDrawable.setIsCircular(true);
94        mContactPicture.setImageDrawable(letterTileDrawable);
95    }
96
97    /**
98     * Sets the appropriate background on the card containing the preset information. The cards
99     * need to have rounded corners depending on its position in the list and the number of items
100     * in the list.
101     */
102    private void updateBackground(int itemCount) {
103        int position = getAdapterPosition();
104
105        // Correctly set the background for each card. Only the top and last card should
106        // have rounded corners.
107        if (itemCount == 1) {
108            // One card - all corners are rounded
109            mContactCard.setBackgroundResource(
110                    R.drawable.car_card_rounded_top_bottom_background);
111        } else if (position == 0) {
112            // First card gets rounded top
113            mContactCard.setBackgroundResource(R.drawable.car_card_rounded_top_background);
114        } else if (position == itemCount - 1) {
115            // Last one has a rounded bottom
116            mContactCard.setBackgroundResource(R.drawable.car_card_rounded_bottom_background);
117        } else {
118            // Middle has no rounded corners
119            mContactCard.setBackgroundResource(R.color.car_card);
120        }
121    }
122
123    /**
124     * Retrieves the picture that is specified by the given {@link Uri}.
125     */
126    @Nullable
127    private static Bitmap getContactBitmapFromUri(Context context, Uri uri) {
128        try {
129            InputStream input = context.getContentResolver().openInputStream(uri);
130            return input == null ? null : BitmapFactory.decodeStream(input);
131        } catch (FileNotFoundException e) {
132            return null;
133        }
134    }
135
136    /**
137     * A struct that holds the details for a contact row.
138     */
139    public static class ContactDetails {
140        public final String displayName;
141        public final Uri photoUri;
142        public final Uri lookupUri;
143
144        public ContactDetails(String displayName, String photoUri, Uri lookupUri) {
145            this.displayName = displayName;
146            this.photoUri = photoUri == null ? null : Uri.parse(photoUri);
147            this.lookupUri = lookupUri;
148        }
149    }
150}
151