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.app.list;
18 
19 import android.app.Fragment;
20 import android.app.FragmentManager;
21 import android.support.annotation.IntDef;
22 import android.support.v13.app.FragmentPagerAdapter;
23 import android.view.ViewGroup;
24 import com.android.dialer.app.calllog.CallLogFragment;
25 import com.android.dialer.app.calllog.VisualVoicemailCallLogFragment;
26 import com.android.dialer.common.Assert;
27 import com.android.dialer.common.LogUtil;
28 import com.android.dialer.contactsfragment.ContactsFragment;
29 import com.android.dialer.contactsfragment.ContactsFragment.Header;
30 import com.android.dialer.database.CallLogQueryHandler;
31 import com.android.dialer.util.ViewUtil;
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.List;
37 
38 /** ViewPager adapter for {@link com.android.dialer.app.DialtactsActivity}. */
39 public class DialtactsPagerAdapter extends FragmentPagerAdapter {
40 
41   /** IntDef for indices of ViewPager tabs. */
42   @Retention(RetentionPolicy.SOURCE)
43   @IntDef({TAB_INDEX_SPEED_DIAL, TAB_INDEX_HISTORY, TAB_INDEX_ALL_CONTACTS, TAB_INDEX_VOICEMAIL})
44   public @interface TabIndex {}
45 
46   public static final int TAB_INDEX_SPEED_DIAL = 0;
47   public static final int TAB_INDEX_HISTORY = 1;
48   public static final int TAB_INDEX_ALL_CONTACTS = 2;
49   public static final int TAB_INDEX_VOICEMAIL = 3;
50   public static final int TAB_COUNT_DEFAULT = 3;
51   public static final int TAB_COUNT_WITH_VOICEMAIL = 4;
52 
53   private final List<Fragment> fragments = new ArrayList<>();
54   private final String[] tabTitles;
55   private OldSpeedDialFragment oldSpeedDialFragment;
56   private CallLogFragment callLogFragment;
57   private ContactsFragment contactsFragment;
58   private CallLogFragment voicemailFragment;
59 
60   private boolean hasActiveVoicemailProvider;
61 
DialtactsPagerAdapter( FragmentManager fm, String[] tabTitles, boolean hasVoicemailProvider)62   public DialtactsPagerAdapter(
63       FragmentManager fm, String[] tabTitles, boolean hasVoicemailProvider) {
64     super(fm);
65     this.tabTitles = tabTitles;
66     hasActiveVoicemailProvider = hasVoicemailProvider;
67     fragments.addAll(Collections.nCopies(TAB_COUNT_WITH_VOICEMAIL, null));
68   }
69 
70   @Override
getItemId(int position)71   public long getItemId(int position) {
72     return getRtlPosition(position);
73   }
74 
75   @Override
getItem(int position)76   public Fragment getItem(int position) {
77     LogUtil.d("ViewPagerAdapter.getItem", "position: %d", position);
78     switch (getRtlPosition(position)) {
79       case TAB_INDEX_SPEED_DIAL:
80         if (oldSpeedDialFragment == null) {
81           oldSpeedDialFragment = new OldSpeedDialFragment();
82         }
83         return oldSpeedDialFragment;
84       case TAB_INDEX_HISTORY:
85         if (callLogFragment == null) {
86           callLogFragment = new CallLogFragment(CallLogQueryHandler.CALL_TYPE_ALL);
87         }
88         return callLogFragment;
89       case TAB_INDEX_ALL_CONTACTS:
90         if (contactsFragment == null) {
91           contactsFragment = ContactsFragment.newInstance(Header.ADD_CONTACT);
92         }
93         return contactsFragment;
94       case TAB_INDEX_VOICEMAIL:
95         if (voicemailFragment == null) {
96           voicemailFragment = new VisualVoicemailCallLogFragment();
97           LogUtil.v(
98               "ViewPagerAdapter.getItem",
99               "new VisualVoicemailCallLogFragment: %s",
100               voicemailFragment);
101         }
102         return voicemailFragment;
103       default:
104         throw Assert.createIllegalStateFailException("No fragment at position " + position);
105     }
106   }
107 
108   @Override
instantiateItem(ViewGroup container, int position)109   public Fragment instantiateItem(ViewGroup container, int position) {
110     LogUtil.d("ViewPagerAdapter.instantiateItem", "position: %d", position);
111     // On rotation the FragmentManager handles rotation. Therefore getItem() isn't called.
112     // Copy the fragments that the FragmentManager finds so that we can store them in
113     // instance variables for later.
114     final Fragment fragment = (Fragment) super.instantiateItem(container, position);
115     if (fragment instanceof OldSpeedDialFragment) {
116       oldSpeedDialFragment = (OldSpeedDialFragment) fragment;
117     } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_HISTORY) {
118       callLogFragment = (CallLogFragment) fragment;
119     } else if (fragment instanceof ContactsFragment) {
120       contactsFragment = (ContactsFragment) fragment;
121     } else if (fragment instanceof CallLogFragment && position == TAB_INDEX_VOICEMAIL) {
122       voicemailFragment = (CallLogFragment) fragment;
123       LogUtil.v("ViewPagerAdapter.instantiateItem", voicemailFragment.toString());
124     }
125     fragments.set(position, fragment);
126     return fragment;
127   }
128 
129   /**
130    * When {@link android.support.v4.view.PagerAdapter#notifyDataSetChanged} is called, this method
131    * is called on all pages to determine whether they need to be recreated. When the voicemail tab
132    * is removed, the view needs to be recreated by returning POSITION_NONE. If notifyDataSetChanged
133    * is called for some other reason, the voicemail tab is recreated only if it is active. All other
134    * tabs do not need to be recreated and POSITION_UNCHANGED is returned.
135    */
136   @Override
getItemPosition(Object object)137   public int getItemPosition(Object object) {
138     return !hasActiveVoicemailProvider && fragments.indexOf(object) == TAB_INDEX_VOICEMAIL
139         ? POSITION_NONE
140         : POSITION_UNCHANGED;
141   }
142 
143   @Override
getCount()144   public int getCount() {
145     return hasActiveVoicemailProvider ? TAB_COUNT_WITH_VOICEMAIL : TAB_COUNT_DEFAULT;
146   }
147 
148   @Override
getPageTitle(@abIndex int position)149   public CharSequence getPageTitle(@TabIndex int position) {
150     return tabTitles[position];
151   }
152 
getRtlPosition(int position)153   public int getRtlPosition(int position) {
154     if (ViewUtil.isRtl()) {
155       return getCount() - 1 - position;
156     }
157     return position;
158   }
159 
removeVoicemailFragment(FragmentManager manager)160   public void removeVoicemailFragment(FragmentManager manager) {
161     if (voicemailFragment != null) {
162       manager.beginTransaction().remove(voicemailFragment).commitAllowingStateLoss();
163       voicemailFragment = null;
164     }
165   }
166 
hasActiveVoicemailProvider()167   public boolean hasActiveVoicemailProvider() {
168     return hasActiveVoicemailProvider;
169   }
170 
setHasActiveVoicemailProvider(boolean hasActiveVoicemailProvider)171   public void setHasActiveVoicemailProvider(boolean hasActiveVoicemailProvider) {
172     this.hasActiveVoicemailProvider = hasActiveVoicemailProvider;
173   }
174 }
175