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