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 
17 package com.android.dialer.calldetails;
18 
19 import android.content.Context;
20 import android.support.annotation.CallSuper;
21 import android.support.annotation.MainThread;
22 import android.support.v7.widget.RecyclerView;
23 import android.support.v7.widget.RecyclerView.ViewHolder;
24 import android.view.LayoutInflater;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry;
28 import com.android.dialer.calldetails.CallDetailsEntryViewHolder.CallDetailsEntryListener;
29 import com.android.dialer.calldetails.CallDetailsFooterViewHolder.DeleteCallDetailsListener;
30 import com.android.dialer.calldetails.CallDetailsFooterViewHolder.ReportCallIdListener;
31 import com.android.dialer.calldetails.CallDetailsHeaderViewHolder.CallDetailsHeaderListener;
32 import com.android.dialer.calllogutils.CallTypeHelper;
33 import com.android.dialer.calllogutils.CallbackActionHelper;
34 import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction;
35 import com.android.dialer.common.Assert;
36 import com.android.dialer.duo.DuoComponent;
37 import com.android.dialer.glidephotomanager.PhotoInfo;
38 
39 /**
40  * Contains common logic shared between {@link OldCallDetailsAdapter} and {@link
41  * CallDetailsAdapter}.
42  */
43 abstract class CallDetailsAdapterCommon extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
44 
45   private static final int HEADER_VIEW_TYPE = 1;
46   private static final int CALL_ENTRY_VIEW_TYPE = 2;
47   private static final int FOOTER_VIEW_TYPE = 3;
48 
49   private final CallDetailsEntryListener callDetailsEntryListener;
50   private final CallDetailsHeaderListener callDetailsHeaderListener;
51   private final ReportCallIdListener reportCallIdListener;
52   private final DeleteCallDetailsListener deleteCallDetailsListener;
53   private final CallTypeHelper callTypeHelper;
54 
55   private CallDetailsEntries callDetailsEntries;
56 
bindCallDetailsHeaderViewHolder( CallDetailsHeaderViewHolder viewHolder, int position)57   protected abstract void bindCallDetailsHeaderViewHolder(
58       CallDetailsHeaderViewHolder viewHolder, int position);
59 
createCallDetailsHeaderViewHolder( View container, CallDetailsHeaderListener callDetailsHeaderListener)60   protected abstract CallDetailsHeaderViewHolder createCallDetailsHeaderViewHolder(
61       View container, CallDetailsHeaderListener callDetailsHeaderListener);
62 
63   /** Returns the phone number of the call details. */
getNumber()64   protected abstract String getNumber();
65 
66   /** Returns the primary text shown on call details toolbar, usually contact name or number. */
getPrimaryText()67   protected abstract String getPrimaryText();
68 
69   /** Returns {@link PhotoInfo} of the contact. */
getPhotoInfo()70   protected abstract PhotoInfo getPhotoInfo();
71 
CallDetailsAdapterCommon( Context context, CallDetailsEntries callDetailsEntries, CallDetailsEntryListener callDetailsEntryListener, CallDetailsHeaderListener callDetailsHeaderListener, ReportCallIdListener reportCallIdListener, DeleteCallDetailsListener deleteCallDetailsListener)72   CallDetailsAdapterCommon(
73       Context context,
74       CallDetailsEntries callDetailsEntries,
75       CallDetailsEntryListener callDetailsEntryListener,
76       CallDetailsHeaderListener callDetailsHeaderListener,
77       ReportCallIdListener reportCallIdListener,
78       DeleteCallDetailsListener deleteCallDetailsListener) {
79     this.callDetailsEntries = callDetailsEntries;
80     this.callDetailsEntryListener = callDetailsEntryListener;
81     this.callDetailsHeaderListener = callDetailsHeaderListener;
82     this.reportCallIdListener = reportCallIdListener;
83     this.deleteCallDetailsListener = deleteCallDetailsListener;
84     this.callTypeHelper =
85         new CallTypeHelper(context.getResources(), DuoComponent.get(context).getDuo());
86   }
87 
88   @Override
89   @CallSuper
onCreateViewHolder(ViewGroup parent, int viewType)90   public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
91     LayoutInflater inflater = LayoutInflater.from(parent.getContext());
92     switch (viewType) {
93       case HEADER_VIEW_TYPE:
94         return createCallDetailsHeaderViewHolder(
95             inflater.inflate(R.layout.contact_container, parent, false), callDetailsHeaderListener);
96       case CALL_ENTRY_VIEW_TYPE:
97         return new CallDetailsEntryViewHolder(
98             inflater.inflate(R.layout.call_details_entry, parent, false), callDetailsEntryListener);
99       case FOOTER_VIEW_TYPE:
100         return new CallDetailsFooterViewHolder(
101             inflater.inflate(R.layout.call_details_footer, parent, false),
102             reportCallIdListener,
103             deleteCallDetailsListener);
104       default:
105         throw Assert.createIllegalStateFailException(
106             "No ViewHolder available for viewType: " + viewType);
107     }
108   }
109 
110   @Override
111   @CallSuper
onBindViewHolder(ViewHolder holder, int position)112   public void onBindViewHolder(ViewHolder holder, int position) {
113     if (position == 0) { // Header
114       bindCallDetailsHeaderViewHolder((CallDetailsHeaderViewHolder) holder, position);
115     } else if (position == getItemCount() - 1) {
116       ((CallDetailsFooterViewHolder) holder).setPhoneNumber(getNumber());
117     } else {
118       CallDetailsEntryViewHolder viewHolder = (CallDetailsEntryViewHolder) holder;
119       CallDetailsEntry entry = callDetailsEntries.getEntries(position - 1);
120       viewHolder.setCallDetails(
121           getNumber(),
122           getPrimaryText(),
123           getPhotoInfo(),
124           entry,
125           callTypeHelper,
126           !entry.getHistoryResultsList().isEmpty() && position != getItemCount() - 2);
127     }
128   }
129 
130   @Override
131   @CallSuper
getItemViewType(int position)132   public int getItemViewType(int position) {
133     if (position == 0) { // Header
134       return HEADER_VIEW_TYPE;
135     } else if (position == getItemCount() - 1) {
136       return FOOTER_VIEW_TYPE;
137     } else {
138       return CALL_ENTRY_VIEW_TYPE;
139     }
140   }
141 
142   @Override
143   @CallSuper
getItemCount()144   public int getItemCount() {
145     return callDetailsEntries.getEntriesCount() == 0
146         ? 0
147         : callDetailsEntries.getEntriesCount() + 2; // plus header and footer
148   }
149 
getCallDetailsEntries()150   final CallDetailsEntries getCallDetailsEntries() {
151     return callDetailsEntries;
152   }
153 
154   @MainThread
updateCallDetailsEntries(CallDetailsEntries entries)155   final void updateCallDetailsEntries(CallDetailsEntries entries) {
156     Assert.isMainThread();
157     callDetailsEntries = entries;
158     notifyDataSetChanged();
159   }
160 
getCallbackAction()161   final @CallbackAction int getCallbackAction() {
162     Assert.checkState(!callDetailsEntries.getEntriesList().isEmpty());
163 
164     CallDetailsEntry entry = callDetailsEntries.getEntries(0);
165     return CallbackActionHelper.getCallbackAction(
166         getNumber(), entry.getFeatures(), entry.getIsDuoCall());
167   }
168 }
169