summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/com/android/dialer/app/DialtactsActivity.java5
-rw-r--r--java/com/android/dialer/app/calllog/CallLogFragment.java31
-rw-r--r--java/com/android/dialer/app/list/ListsFragment.java10
-rw-r--r--java/com/android/dialer/app/list/OldSpeedDialFragment.java174
-rw-r--r--java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java5
-rw-r--r--java/com/android/dialer/common/FragmentUtils.java49
-rw-r--r--java/com/android/dialer/database/DialerDatabaseHelper.java20
-rw-r--r--java/com/android/dialer/dialpadview/DialpadFragment.java3
-rw-r--r--java/com/android/dialer/main/impl/BottomNavBar.java14
-rw-r--r--java/com/android/dialer/main/impl/BottomNavItem.java14
-rw-r--r--java/com/android/dialer/main/impl/MainActivity.java524
-rw-r--r--java/com/android/dialer/main/impl/res/drawable/notification_badge.xml22
-rw-r--r--java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml28
-rw-r--r--java/com/android/dialer/main/impl/res/layout/main_activity.xml14
-rw-r--r--java/com/android/incallui/ContactInfoCache.java4
15 files changed, 685 insertions, 232 deletions
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java
index 23f4d403c..293ebed87 100644
--- a/java/com/android/dialer/app/DialtactsActivity.java
+++ b/java/com/android/dialer/app/DialtactsActivity.java
@@ -1508,6 +1508,11 @@ public class DialtactsActivity extends TransactionSafeActivity
@Override
public void onDroppedOnRemove() {}
+ @Override
+ public ImageView getDragShadowOverlay() {
+ return findViewById(R.id.contact_tile_drag_shadow_overlay);
+ }
+
/**
* Allows the SpeedDialFragment to attach the drag controller to mRemoveViewContainer once it has
* been attached to the activity.
diff --git a/java/com/android/dialer/app/calllog/CallLogFragment.java b/java/com/android/dialer/app/calllog/CallLogFragment.java
index 4f5035fc6..7f635dbca 100644
--- a/java/com/android/dialer/app/calllog/CallLogFragment.java
+++ b/java/com/android/dialer/app/calllog/CallLogFragment.java
@@ -53,10 +53,10 @@ import com.android.dialer.app.calllog.calllogcache.CallLogCache;
import com.android.dialer.app.contactinfo.ContactInfoCache;
import com.android.dialer.app.contactinfo.ContactInfoCache.OnContactInfoChangedListener;
import com.android.dialer.app.contactinfo.ExpirableCacheHeadlessFragment;
-import com.android.dialer.app.list.ListsFragment;
import com.android.dialer.app.voicemail.VoicemailPlaybackPresenter;
import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler;
import com.android.dialer.common.Assert;
+import com.android.dialer.common.FragmentUtils;
import com.android.dialer.common.LogUtil;
import com.android.dialer.database.CallLogQueryHandler;
import com.android.dialer.database.CallLogQueryHandler.Listener;
@@ -344,9 +344,10 @@ public class CallLogFragment extends Fragment
recyclerView,
this,
this,
- activityType == CallLogAdapter.ACTIVITY_TYPE_DIALTACTS
- ? (CallLogAdapter.OnActionModeStateChangedListener) getActivity()
- : null,
+ // We aren't calling getParentUnsafe because CallLogActivity doesn't need to
+ // implement this listener
+ FragmentUtils.getParent(
+ this, CallLogAdapter.OnActionModeStateChangedListener.class),
new CallLogCache(getActivity()),
contactInfoCache,
getVoicemailPlaybackPresenter(),
@@ -479,7 +480,7 @@ public class CallLogFragment extends Fragment
public void fetchCalls() {
callLogQueryHandler.fetchCalls(callTypeFilter, dateLimit);
if (!isCallLogActivity) {
- ((ListsFragment) getParentFragment()).updateTabUnreadCounts();
+ FragmentUtils.getParentUnsafe(this, CallLogFragmentListener.class).updateTabUnreadCounts();
}
}
@@ -616,7 +617,8 @@ public class CallLogFragment extends Fragment
public void onVisible() {
LogUtil.enterBlock("CallLogFragment.onPageSelected");
if (getActivity() != null && getActivity() instanceof HostInterface) {
- ((HostInterface) getActivity()).enableFloatingButton(!isModalAlertVisible());
+ FragmentUtils.getParentUnsafe(this, HostInterface.class)
+ .enableFloatingButton(!isModalAlertVisible());
}
}
@@ -638,7 +640,7 @@ public class CallLogFragment extends Fragment
this,
getUserVisibleHint());
getAdapter().notifyDataSetChanged();
- HostInterface hostInterface = (HostInterface) getActivity();
+ HostInterface hostInterface = FragmentUtils.getParent(this, HostInterface.class);
if (show) {
recyclerView.setVisibility(View.GONE);
modalAlertView.setVisibility(View.VISIBLE);
@@ -659,7 +661,8 @@ public class CallLogFragment extends Fragment
multiSelectUnSelectAllViewContent.setVisibility(show ? View.VISIBLE : View.GONE);
multiSelectUnSelectAllViewContent.setAlpha(show ? 0 : 1);
multiSelectUnSelectAllViewContent.animate().alpha(show ? 1 : 0).start();
- ((ListsFragment) getParentFragment()).showMultiSelectRemoveView(show);
+ FragmentUtils.getParentUnsafe(this, CallLogFragmentListener.class)
+ .showMultiSelectRemoveView(show);
}
@Override
@@ -717,4 +720,16 @@ public class CallLogFragment extends Fragment
refreshDataRequired = true;
}
}
+
+ /** Useful callback for ListsFragment children to use to call into ListsFragment. */
+ public interface CallLogFragmentListener {
+
+ /**
+ * External method to update unread count because the unread count changes when the user expands
+ * a voicemail in the call log or when the user expands an unread call in the call history tab.
+ */
+ void updateTabUnreadCounts();
+
+ void showMultiSelectRemoveView(boolean show);
+ }
}
diff --git a/java/com/android/dialer/app/list/ListsFragment.java b/java/com/android/dialer/app/list/ListsFragment.java
index bbbf056bf..d314917ef 100644
--- a/java/com/android/dialer/app/list/ListsFragment.java
+++ b/java/com/android/dialer/app/list/ListsFragment.java
@@ -34,6 +34,7 @@ import android.view.ViewGroup;
import com.android.contacts.common.list.ViewPagerTabs;
import com.android.dialer.app.R;
import com.android.dialer.app.calllog.CallLogFragment;
+import com.android.dialer.app.calllog.CallLogFragment.CallLogFragmentListener;
import com.android.dialer.app.calllog.CallLogNotificationsService;
import com.android.dialer.app.calllog.VisualVoicemailCallLogFragment;
import com.android.dialer.common.LogUtil;
@@ -59,7 +60,8 @@ import java.util.ArrayList;
* Contacts list. This will also eventually contain the logic that allows sliding the ViewPager
* containing the lists up above the search bar and pin it against the top of the screen.
*/
-public class ListsFragment extends Fragment implements OnPageChangeListener, Listener {
+public class ListsFragment extends Fragment
+ implements OnPageChangeListener, Listener, CallLogFragmentListener {
private static final String TAG = "ListsFragment";
@@ -423,10 +425,7 @@ public class ListsFragment extends Fragment implements OnPageChangeListener, Lis
return true;
}
- /**
- * External method to update unread count because the unread count changes when the user expands a
- * voicemail in the call log or when the user expands an unread call in the call history tab.
- */
+ @Override
public void updateTabUnreadCounts() {
if (callLogQueryHandler != null) {
callLogQueryHandler.fetchMissedCallsUnreadCount();
@@ -450,6 +449,7 @@ public class ListsFragment extends Fragment implements OnPageChangeListener, Lis
removeView.animate().alpha(show ? 1 : 0).start();
}
+ @Override
public void showMultiSelectRemoveView(boolean show) {
viewPagerTabs.setVisibility(show ? View.GONE : View.VISIBLE);
viewPager.setEnableSwipingPages(!show);
diff --git a/java/com/android/dialer/app/list/OldSpeedDialFragment.java b/java/com/android/dialer/app/list/OldSpeedDialFragment.java
index 1b366c1ee..caa5e91f0 100644
--- a/java/com/android/dialer/app/list/OldSpeedDialFragment.java
+++ b/java/com/android/dialer/app/list/OldSpeedDialFragment.java
@@ -20,7 +20,6 @@ import static android.Manifest.permission.READ_CONTACTS;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
import android.content.CursorLoader;
@@ -50,6 +49,7 @@ import com.android.contacts.common.list.ContactTileView;
import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
import com.android.dialer.app.R;
import com.android.dialer.callintent.CallSpecificAppData;
+import com.android.dialer.common.FragmentUtils;
import com.android.dialer.common.LogUtil;
import com.android.dialer.contactphoto.ContactPhotoManager;
import com.android.dialer.util.PermissionsUtil;
@@ -77,22 +77,17 @@ public class OldSpeedDialFragment extends Fragment
private static final long KEY_REMOVED_ITEM_HEIGHT = Long.MAX_VALUE;
private static final String TAG = "OldSpeedDialFragment";
- private static final boolean DEBUG = false;
/** Used with LoaderManager. */
private static final int LOADER_ID_CONTACT_TILE = 1;
private final LongSparseArray<Integer> itemIdTopMap = new LongSparseArray<>();
private final LongSparseArray<Integer> itemIdLeftMap = new LongSparseArray<>();
private final ContactTileView.Listener contactTileAdapterListener =
- new ContactTileAdapterListener();
- private final LoaderManager.LoaderCallbacks<Cursor> contactTileLoaderListener =
- new ContactTileLoaderListener();
- private final ScrollListener scrollListener = new ScrollListener();
+ new ContactTileAdapterListener(this);
+ private final ScrollListener scrollListener = new ScrollListener(this);
+ private LoaderManager.LoaderCallbacks<Cursor> contactTileLoaderListener;
private int animationDuration;
- private OnPhoneNumberPickerActionListener phoneNumberPickerActionListener;
- private OnListFragmentScrolledListener activityScrollListener;
private PhoneFavoritesTileAdapter contactTileAdapter;
- private View parentView;
private PhoneFavoriteListView listView;
private View contactTileFrame;
/** Layout used when there are no favorites. */
@@ -100,9 +95,6 @@ public class OldSpeedDialFragment extends Fragment
@Override
public void onCreate(Bundle savedState) {
- if (DEBUG) {
- LogUtil.d("OldSpeedDialFragment.onCreate", null);
- }
Trace.beginSection(TAG + " onCreate");
super.onCreate(savedState);
@@ -110,8 +102,9 @@ public class OldSpeedDialFragment extends Fragment
// We don't construct the resultant adapter at this moment since it requires LayoutInflater
// that will be available on onCreateView().
contactTileAdapter =
- new PhoneFavoritesTileAdapter(getActivity(), contactTileAdapterListener, this);
- contactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(getActivity()));
+ new PhoneFavoritesTileAdapter(getContext(), contactTileAdapterListener, this);
+ contactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(getContext()));
+ contactTileLoaderListener = new ContactTileLoaderListener(this, contactTileAdapter);
animationDuration = getResources().getInteger(R.integer.fade_duration);
Trace.endSection();
}
@@ -123,7 +116,7 @@ public class OldSpeedDialFragment extends Fragment
if (contactTileAdapter != null) {
contactTileAdapter.refreshContactsPreferences();
}
- if (PermissionsUtil.hasContactsReadPermissions(getActivity())) {
+ if (PermissionsUtil.hasContactsReadPermissions(getContext())) {
if (getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE) == null) {
getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, contactTileLoaderListener);
@@ -144,7 +137,7 @@ public class OldSpeedDialFragment extends Fragment
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Trace.beginSection(TAG + " onCreateView");
- parentView = inflater.inflate(R.layout.speed_dial_fragment, container, false);
+ View parentView = inflater.inflate(R.layout.speed_dial_fragment, container, false);
listView = (PhoneFavoriteListView) parentView.findViewById(R.id.contact_tile_list);
listView.setOnItemClickListener(this);
@@ -152,10 +145,8 @@ public class OldSpeedDialFragment extends Fragment
listView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT);
listView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
listView.getDragDropController().addOnDragDropListener(contactTileAdapter);
-
- final ImageView dragShadowOverlay =
- (ImageView) getActivity().findViewById(R.id.contact_tile_drag_shadow_overlay);
- listView.setDragShadowOverlay(dragShadowOverlay);
+ listView.setDragShadowOverlay(
+ FragmentUtils.getParentUnsafe(this, HostInterface.class).getDragShadowOverlay());
emptyView = (EmptyContentView) parentView.findViewById(R.id.empty_list_view);
emptyView.setImage(R.drawable.empty_speed_dial);
@@ -165,7 +156,7 @@ public class OldSpeedDialFragment extends Fragment
final LayoutAnimationController controller =
new LayoutAnimationController(
- AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in));
+ AnimationUtils.loadAnimation(getContext(), android.R.anim.fade_in));
controller.setDelay(0);
listView.setLayoutAnimation(controller);
listView.setAdapter(contactTileAdapter);
@@ -206,36 +197,16 @@ public class OldSpeedDialFragment extends Fragment
@Override
public void onStart() {
super.onStart();
-
- final Activity activity = getActivity();
-
- try {
- activityScrollListener = (OnListFragmentScrolledListener) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(
- activity.toString() + " must implement OnListFragmentScrolledListener");
- }
-
- try {
- OnDragDropListener listener = (OnDragDropListener) activity;
- listView.getDragDropController().addOnDragDropListener(listener);
- ((HostInterface) activity).setDragDropController(listView.getDragDropController());
- } catch (ClassCastException e) {
- throw new ClassCastException(
- activity.toString() + " must implement OnDragDropListener and HostInterface");
- }
-
- try {
- phoneNumberPickerActionListener = (OnPhoneNumberPickerActionListener) activity;
- } catch (ClassCastException e) {
- throw new ClassCastException(
- activity.toString() + " must implement PhoneFavoritesFragment.listener");
- }
+ listView
+ .getDragDropController()
+ .addOnDragDropListener(FragmentUtils.getParentUnsafe(this, OnDragDropListener.class));
+ FragmentUtils.getParentUnsafe(this, HostInterface.class)
+ .setDragDropController(listView.getDragDropController());
// Use initLoader() instead of restartLoader() to refraining unnecessary reload.
// This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will
// be called, on which we'll check if "all" contacts should be reloaded again or not.
- if (PermissionsUtil.hasContactsReadPermissions(activity)) {
+ if (PermissionsUtil.hasContactsReadPermissions(getContext())) {
getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, contactTileLoaderListener);
} else {
setEmptyViewVisibility(true);
@@ -268,9 +239,6 @@ public class OldSpeedDialFragment extends Fragment
*/
private void saveOffsets(int removedItemHeight) {
final int firstVisiblePosition = listView.getFirstVisiblePosition();
- if (DEBUG) {
- LogUtil.d("OldSpeedDialFragment.saveOffsets", "Child count : " + listView.getChildCount());
- }
for (int i = 0; i < listView.getChildCount(); i++) {
final View child = listView.getChildAt(i);
final int position = firstVisiblePosition + i;
@@ -281,11 +249,6 @@ public class OldSpeedDialFragment extends Fragment
continue;
}
final long itemId = contactTileAdapter.getItemId(position);
- if (DEBUG) {
- LogUtil.d(
- "OldSpeedDialFragment.saveOffsets",
- "Saving itemId: " + itemId + " for listview child " + i + " Top: " + child.getTop());
- }
itemIdTopMap.put(itemId, child.getTop());
itemIdLeftMap.put(itemId, child.getLeft());
}
@@ -350,19 +313,6 @@ public class OldSpeedDialFragment extends Fragment
animators.add(ObjectAnimator.ofFloat(child, "translationY", deltaY, 0.0f));
}
}
-
- if (DEBUG) {
- LogUtil.d(
- "OldSpeedDialFragment.onPreDraw",
- "Found itemId: "
- + itemId
- + " for listview child "
- + i
- + " Top: "
- + top
- + " Delta: "
- + deltaY);
- }
}
}
@@ -399,11 +349,6 @@ public class OldSpeedDialFragment extends Fragment
@Override
public void onEmptyViewActionButtonClicked() {
- final Activity activity = getActivity();
- if (activity == null) {
- return;
- }
-
String[] deniedPermissions =
PermissionsUtil.getPermissionsCurrentlyDenied(
getContext(), PermissionsUtil.allContactsGroupPermissionsUsedInDialer);
@@ -415,7 +360,7 @@ public class OldSpeedDialFragment extends Fragment
this, deniedPermissions, READ_CONTACTS_PERMISSION_REQUEST_CODE);
} else {
// Switch tabs
- ((HostInterface) activity).showAllContactsTab();
+ FragmentUtils.getParentUnsafe(this, HostInterface.class).showAllContactsTab();
}
}
@@ -424,79 +369,88 @@ public class OldSpeedDialFragment extends Fragment
int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == READ_CONTACTS_PERMISSION_REQUEST_CODE) {
if (grantResults.length == 1 && PackageManager.PERMISSION_GRANTED == grantResults[0]) {
- PermissionsUtil.notifyPermissionGranted(getActivity(), READ_CONTACTS);
+ PermissionsUtil.notifyPermissionGranted(getContext(), READ_CONTACTS);
}
}
}
- public interface HostInterface {
+ private static final class ContactTileLoaderListener
+ implements LoaderManager.LoaderCallbacks<Cursor> {
- void setDragDropController(DragDropController controller);
+ private final OldSpeedDialFragment fragment;
+ private final PhoneFavoritesTileAdapter adapter;
- void showAllContactsTab();
- }
-
- class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
+ ContactTileLoaderListener(OldSpeedDialFragment fragment, PhoneFavoritesTileAdapter adapter) {
+ this.fragment = fragment;
+ this.adapter = adapter;
+ }
@Override
public CursorLoader onCreateLoader(int id, Bundle args) {
- if (DEBUG) {
- LogUtil.d("ContactTileLoaderListener.onCreateLoader", null);
- }
- return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity());
+ return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(fragment.getContext());
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- if (DEBUG) {
- LogUtil.d("ContactTileLoaderListener.onLoadFinished", null);
- }
- contactTileAdapter.setContactCursor(data);
- setEmptyViewVisibility(contactTileAdapter.getCount() == 0);
+ adapter.setContactCursor(data);
+ fragment.setEmptyViewVisibility(adapter.getCount() == 0);
}
@Override
- public void onLoaderReset(Loader<Cursor> loader) {
- if (DEBUG) {
- LogUtil.d("ContactTileLoaderListener.onLoaderReset", null);
- }
- }
+ public void onLoaderReset(Loader<Cursor> loader) {}
}
- private class ContactTileAdapterListener implements ContactTileView.Listener {
+ private static final class ContactTileAdapterListener implements ContactTileView.Listener {
+
+ private final OldSpeedDialFragment fragment;
+
+ ContactTileAdapterListener(OldSpeedDialFragment fragment) {
+ this.fragment = fragment;
+ }
@Override
public void onContactSelected(
Uri contactUri, Rect targetRect, CallSpecificAppData callSpecificAppData) {
- if (phoneNumberPickerActionListener != null) {
- phoneNumberPickerActionListener.onPickDataUri(
- contactUri, false /* isVideoCall */, callSpecificAppData);
- }
+ FragmentUtils.getParentUnsafe(fragment, OnPhoneNumberPickerActionListener.class)
+ .onPickDataUri(contactUri, false /* isVideoCall */, callSpecificAppData);
}
@Override
public void onCallNumberDirectly(String phoneNumber, CallSpecificAppData callSpecificAppData) {
- if (phoneNumberPickerActionListener != null) {
- phoneNumberPickerActionListener.onPickPhoneNumber(
- phoneNumber, false /* isVideoCall */, callSpecificAppData);
- }
+ FragmentUtils.getParentUnsafe(fragment, OnPhoneNumberPickerActionListener.class)
+ .onPickPhoneNumber(phoneNumber, false /* isVideoCall */, callSpecificAppData);
}
}
- private class ScrollListener implements ListView.OnScrollListener {
+ private static class ScrollListener implements ListView.OnScrollListener {
+
+ private final OldSpeedDialFragment fragment;
+
+ ScrollListener(OldSpeedDialFragment fragment) {
+ this.fragment = fragment;
+ }
@Override
public void onScroll(
AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- if (activityScrollListener != null) {
- activityScrollListener.onListFragmentScroll(
- firstVisibleItem, visibleItemCount, totalItemCount);
- }
+ FragmentUtils.getParentUnsafe(fragment, OnListFragmentScrolledListener.class)
+ .onListFragmentScroll(firstVisibleItem, visibleItemCount, totalItemCount);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
- activityScrollListener.onListFragmentScrollStateChange(scrollState);
+ FragmentUtils.getParentUnsafe(fragment, OnListFragmentScrolledListener.class)
+ .onListFragmentScrollStateChange(scrollState);
}
}
+
+ /** Interface for parents of OldSpeedDialFragment to implement. */
+ public interface HostInterface {
+
+ void setDragDropController(DragDropController controller);
+
+ void showAllContactsTab();
+
+ ImageView getDragShadowOverlay();
+ }
}
diff --git a/java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java b/java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java
index eeb19a862..30b28d83a 100644
--- a/java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java
+++ b/java/com/android/dialer/calldetails/CallDetailsFooterViewHolder.java
@@ -36,7 +36,6 @@ final class CallDetailsFooterViewHolder extends RecyclerView.ViewHolder implemen
private final ReportCallIdListener reportCallIdListener;
private final DeleteCallDetailsListener deleteCallDetailsListener;
- private final View container;
private final View copy;
private final View edit;
private final View reportCallerId;
@@ -51,7 +50,6 @@ final class CallDetailsFooterViewHolder extends RecyclerView.ViewHolder implemen
super(view);
this.reportCallIdListener = reportCallIdListener;
this.deleteCallDetailsListener = deleteCallDetailsListener;
- container = view.findViewById(R.id.footer_container);
copy = view.findViewById(R.id.call_detail_action_copy);
edit = view.findViewById(R.id.call_detail_action_edit_before_call);
reportCallerId = view.findViewById(R.id.call_detail_action_report_caller_id);
@@ -65,7 +63,8 @@ final class CallDetailsFooterViewHolder extends RecyclerView.ViewHolder implemen
public void setPhoneNumber(String number) {
this.number = number;
if (TextUtils.isEmpty(number)) {
- container.setVisibility(View.GONE);
+ copy.setVisibility(View.GONE);
+ edit.setVisibility(View.GONE);
} else if (reportCallIdListener.canReportCallerId(number)) {
reportCallerId.setVisibility(View.VISIBLE);
}
diff --git a/java/com/android/dialer/common/FragmentUtils.java b/java/com/android/dialer/common/FragmentUtils.java
index ad7ec7390..947a9b20a 100644
--- a/java/com/android/dialer/common/FragmentUtils.java
+++ b/java/com/android/dialer/common/FragmentUtils.java
@@ -16,13 +16,11 @@
package com.android.dialer.common;
-import android.app.Activity;
import android.support.annotation.CheckResult;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
/** Utility methods for working with Fragments */
public class FragmentUtils {
@@ -35,8 +33,8 @@ public class FragmentUtils {
}
/**
- * @return The parent of frag that implements the callbackInterface or null if no such parent can
- * be found
+ * Returns an instance of the {@code callbackInterface} that is defined in the parent of the
+ * {@code fragment}, or null if no such call back can be found.
*/
@CheckResult(suggest = "#checkParent(Fragment, Class)}")
@Nullable
@@ -52,18 +50,22 @@ public class FragmentUtils {
@SuppressWarnings("unchecked") // Casts are checked using runtime methods
T parent = (T) parentFragment;
return parent;
- } else {
- FragmentActivity activity = fragment.getActivity();
- if (callbackInterface.isInstance(activity)) {
- @SuppressWarnings("unchecked") // Casts are checked using runtime methods
- T parent = (T) activity;
- return parent;
- }
+ } else if (callbackInterface.isInstance(fragment.getActivity())) {
+ @SuppressWarnings("unchecked") // Casts are checked using runtime methods
+ T parent = (T) fragment.getActivity();
+ return parent;
+ } else if (fragment.getActivity() instanceof FragmentUtilListener) {
+ @SuppressWarnings("unchecked") // Casts are checked using runtime methods
+ T parent = ((FragmentUtilListener) fragment.getActivity()).getImpl(callbackInterface);
+ return parent;
}
return null;
}
- /** Version of {@link #getParent(Fragment, Class)} which supports {@link android.app.Fragment}. */
+ /**
+ * Returns an instance of the {@code callbackInterface} that is defined in the parent of the
+ * {@code fragment}, or null if no such call back can be found.
+ */
@CheckResult(suggest = "#checkParent(Fragment, Class)}")
@Nullable
public static <T> T getParent(
@@ -79,13 +81,14 @@ public class FragmentUtils {
@SuppressWarnings("unchecked") // Casts are checked using runtime methods
T parent = (T) parentFragment;
return parent;
- } else {
- Activity activity = fragment.getActivity();
- if (callbackInterface.isInstance(activity)) {
- @SuppressWarnings("unchecked") // Casts are checked using runtime methods
- T parent = (T) activity;
- return parent;
- }
+ } else if (callbackInterface.isInstance(fragment.getActivity())) {
+ @SuppressWarnings("unchecked") // Casts are checked using runtime methods
+ T parent = (T) fragment.getActivity();
+ return parent;
+ } else if (fragment.getActivity() instanceof FragmentUtilListener) {
+ @SuppressWarnings("unchecked") // Casts are checked using runtime methods
+ T parent = ((FragmentUtilListener) fragment.getActivity()).getImpl(callbackInterface);
+ return parent;
}
return null;
}
@@ -133,4 +136,12 @@ public class FragmentUtils {
+ parent);
}
}
+
+ /** Useful interface for activities that don't want to implement arbitrary listeners. */
+ public interface FragmentUtilListener {
+
+ /** Returns an implementation of T if parent has one, otherwise null. */
+ @Nullable
+ <T> T getImpl(Class<T> callbackInterface);
+ }
}
diff --git a/java/com/android/dialer/database/DialerDatabaseHelper.java b/java/com/android/dialer/database/DialerDatabaseHelper.java
index 18c61342d..cb07615a5 100644
--- a/java/com/android/dialer/database/DialerDatabaseHelper.java
+++ b/java/com/android/dialer/database/DialerDatabaseHelper.java
@@ -42,6 +42,7 @@ import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.database.Selection;
+import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
import com.android.dialer.smartdial.util.SmartDialNameMatcher;
import com.android.dialer.smartdial.util.SmartDialPrefix;
@@ -76,6 +77,10 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_LAST_CREATED_SHARED_PREF = "com.android.dialer";
private static final String LAST_UPDATED_MILLIS = "last_updated_millis";
+
+ @VisibleForTesting
+ static final String DEFAULT_LAST_UPDATED_CONFIG_KEY = "smart_dial_default_last_update_millis";
+
private static final String DATABASE_VERSION_PROPERTY = "database_version";
private static final int MAX_ENTRIES = 20;
@@ -635,12 +640,17 @@ public class DialerDatabaseHelper extends SQLiteOpenHelper {
/** Gets the last update time on the database. */
final SharedPreferences databaseLastUpdateSharedPref =
context.getSharedPreferences(DATABASE_LAST_CREATED_SHARED_PREF, Context.MODE_PRIVATE);
- final String lastUpdateMillis =
- String.valueOf(
- forceUpdate ? 0 : databaseLastUpdateSharedPref.getLong(LAST_UPDATED_MILLIS, 0));
- LogUtil.v(
- "DialerDatabaseHelper.updateSmartDialDatabase", "last updated at " + lastUpdateMillis);
+ long defaultLastUpdateMillis =
+ ConfigProviderBindings.get(context).getLong(DEFAULT_LAST_UPDATED_CONFIG_KEY, 0);
+
+ long sharedPrefLastUpdateMillis =
+ databaseLastUpdateSharedPref.getLong(LAST_UPDATED_MILLIS, defaultLastUpdateMillis);
+
+ final String lastUpdateMillis = String.valueOf(forceUpdate ? 0 : sharedPrefLastUpdateMillis);
+
+ LogUtil.i(
+ "DialerDatabaseHelper.updateSmartDialDatabase", "last updated at %s", lastUpdateMillis);
/** Sets the time after querying the database as the current update time. */
final Long currentMillis = System.currentTimeMillis();
diff --git a/java/com/android/dialer/dialpadview/DialpadFragment.java b/java/com/android/dialer/dialpadview/DialpadFragment.java
index 6b8401e6b..680159057 100644
--- a/java/com/android/dialer/dialpadview/DialpadFragment.java
+++ b/java/com/android/dialer/dialpadview/DialpadFragment.java
@@ -415,7 +415,8 @@ public class DialpadFragment extends Fragment
if (isDigitsEmpty()) {
if (getActivity() != null) {
LogUtil.i("DialpadFragment.onCreateView", "dialpad spacer touched");
- return ((HostInterface) getActivity()).onDialpadSpacerTouchWithEmptyQuery();
+ return FragmentUtils.getParentUnsafe(this, HostInterface.class)
+ .onDialpadSpacerTouchWithEmptyQuery();
}
return true;
}
diff --git a/java/com/android/dialer/main/impl/BottomNavBar.java b/java/com/android/dialer/main/impl/BottomNavBar.java
index 66a57becd..a4ddc0652 100644
--- a/java/com/android/dialer/main/impl/BottomNavBar.java
+++ b/java/com/android/dialer/main/impl/BottomNavBar.java
@@ -119,6 +119,20 @@ final class BottomNavBar extends LinearLayout {
}
}
+ void setNotificationCount(@TabIndex int tab, int count) {
+ if (tab == TabIndex.SPEED_DIAL) {
+ speedDial.setNotificationCount(count);
+ } else if (tab == TabIndex.HISTORY) {
+ callLog.setNotificationCount(count);
+ } else if (tab == TabIndex.CONTACTS) {
+ contacts.setNotificationCount(count);
+ } else if (tab == TabIndex.VOICEMAIL) {
+ voicemail.setNotificationCount(count);
+ } else {
+ throw new IllegalStateException("Invalid tab: " + tab);
+ }
+ }
+
void setOnTabSelectedListener(OnBottomNavTabSelectedListener listener) {
this.listener = listener;
}
diff --git a/java/com/android/dialer/main/impl/BottomNavItem.java b/java/com/android/dialer/main/impl/BottomNavItem.java
index 14706ab34..af7399b6c 100644
--- a/java/com/android/dialer/main/impl/BottomNavItem.java
+++ b/java/com/android/dialer/main/impl/BottomNavItem.java
@@ -22,15 +22,18 @@ import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.util.AttributeSet;
+import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.dialer.common.Assert;
/** Navigation item in a bottom nav. */
final class BottomNavItem extends LinearLayout {
private ImageView image;
private TextView text;
+ private TextView notificationBadge;
public BottomNavItem(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -41,6 +44,7 @@ final class BottomNavItem extends LinearLayout {
super.onFinishInflate();
image = findViewById(R.id.bottom_nav_item_image);
text = findViewById(R.id.bottom_nav_item_text);
+ notificationBadge = findViewById(R.id.notification_badge);
}
@Override
@@ -56,4 +60,14 @@ final class BottomNavItem extends LinearLayout {
text.setText(stringRes);
image.setImageResource(drawableRes);
}
+
+ void setNotificationCount(int count) {
+ Assert.checkArgument(count >= 0, "Invalid count: " + count);
+ if (count == 0) {
+ notificationBadge.setVisibility(View.GONE);
+ } else {
+ notificationBadge.setVisibility(View.VISIBLE);
+ notificationBadge.setText(String.format(Integer.toString(count)));
+ }
+ }
}
diff --git a/java/com/android/dialer/main/impl/MainActivity.java b/java/com/android/dialer/main/impl/MainActivity.java
index a7a9e6c5a..57cc684e3 100644
--- a/java/com/android/dialer/main/impl/MainActivity.java
+++ b/java/com/android/dialer/main/impl/MainActivity.java
@@ -16,21 +16,38 @@
package com.android.dialer.main.impl;
+import android.app.Fragment;
+import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.QuickContact;
+import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.FragmentTransaction;
-import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
+import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
+import com.android.dialer.app.calllog.CallLogAdapter;
+import com.android.dialer.app.calllog.CallLogFragment;
+import com.android.dialer.app.calllog.CallLogFragment.CallLogFragmentListener;
+import com.android.dialer.app.list.DragDropController;
+import com.android.dialer.app.list.OldSpeedDialFragment;
+import com.android.dialer.app.list.OnDragDropListener;
+import com.android.dialer.app.list.OnListFragmentScrolledListener;
+import com.android.dialer.app.list.PhoneFavoriteSquareTileView;
+import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.callintent.CallSpecificAppData;
import com.android.dialer.calllog.ui.NewCallLogFragment;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.FragmentUtils.FragmentUtilListener;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
+import com.android.dialer.common.concurrent.UiListener;
import com.android.dialer.compat.CompatUtils;
+import com.android.dialer.configprovider.ConfigProviderComponent;
import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.contactsfragment.ContactsFragment;
import com.android.dialer.contactsfragment.ContactsFragment.Header;
@@ -40,31 +57,56 @@ import com.android.dialer.dialpadview.DialpadFragment;
import com.android.dialer.dialpadview.DialpadFragment.DialpadListener;
import com.android.dialer.dialpadview.DialpadFragment.LastOutgoingCallCallback;
import com.android.dialer.dialpadview.DialpadFragment.OnDialpadQueryChangedListener;
+import com.android.dialer.interactions.PhoneNumberInteraction;
+import com.android.dialer.interactions.PhoneNumberInteraction.DisambigDialogDismissedListener;
+import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorCode;
+import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorListener;
import com.android.dialer.main.impl.BottomNavBar.OnBottomNavTabSelectedListener;
import com.android.dialer.main.impl.toolbar.MainToolbar;
import com.android.dialer.postcall.PostCall;
+import com.android.dialer.precall.PreCall;
import com.android.dialer.searchfragment.list.NewSearchFragment.SearchFragmentListener;
import com.android.dialer.smartdial.util.SmartDialPrefix;
import com.android.dialer.speeddial.SpeedDialFragment;
import com.android.dialer.telecom.TelecomUtil;
+import com.android.dialer.util.DialerUtils;
+import com.android.dialer.util.TransactionSafeActivity;
import com.android.dialer.voicemail.listui.NewVoicemailFragment;
+import com.google.common.util.concurrent.ListenableFuture;
/** This is the main activity for dialer. It hosts favorites, call log, search, dialpad, etc... */
-public final class MainActivity extends AppCompatActivity
- implements OnContactSelectedListener,
- OnDialpadQueryChangedListener,
- DialpadListener,
- DialpadFragment.HostInterface,
- SearchFragmentListener {
+// TODO(calderwoodra): Do not extend TransactionSafeActivity after new SpeedDial is launched
+public final class MainActivity extends TransactionSafeActivity
+ implements FragmentUtilListener,
+ // TODO(calderwoodra): remove these 2 interfaces when we migrate to new speed dial fragment
+ InteractionErrorListener,
+ DisambigDialogDismissedListener {
private static final String KEY_SAVED_LANGUAGE_CODE = "saved_language_code";
+ private final MainOnContactSelectedListener onContactSelectedListener =
+ new MainOnContactSelectedListener(this);
+ private final MainDialpadFragmentHost dialpadFragmentHostInterface =
+ new MainDialpadFragmentHost();
+
private MainSearchController searchController;
+ private MainOnDialpadQueryChangedListener onDialpadQueryChangedListener;
+ private MainDialpadListener dialpadListener;
+ private MainSearchFragmentListener searchFragmentListener;
+ private MainCallLogAdapterOnActionModeStateChangedListener
+ callLogAdapterOnActionModeStateChangedListener;
+ private MainCallLogHost callLogHostInterface;
+ private MainCallLogFragmentListener callLogFragmentListener;
+ private MainOnListFragmentScrolledListener onListFragmentScrolledListener;
+ private MainOnPhoneNumberPickerActionListener onPhoneNumberPickerActionListener;
+ private MainOldSpeedDialFragmentHostInterface oldSpeedDialFragmentHostInterface;
+ private MainOnDragDropListener onDragDropListener;
/** Language the device was in last time {@link #onSaveInstanceState(Bundle)} was called. */
private String savedLanguageCode;
private View snackbarContainer;
+ private UiListener<String> getLastOutgoingCallListener;
/**
* @param context Context of the application package implementing MainActivity class.
@@ -81,10 +123,17 @@ public final class MainActivity extends AppCompatActivity
super.onCreate(savedInstanceState);
LogUtil.enterBlock("MainActivity.onCreate");
setContentView(R.layout.main_activity);
+ initUiListeners();
initLayout(savedInstanceState);
SmartDialPrefix.initializeNanpSettings(this);
}
+ private void initUiListeners() {
+ getLastOutgoingCallListener =
+ DialerExecutorComponent.get(this)
+ .createUiListener(getFragmentManager(), "Query last phone number");
+ }
+
private void initLayout(Bundle savedInstanceState) {
snackbarContainer = findViewById(R.id.coordinator_layout);
@@ -95,11 +144,28 @@ public final class MainActivity extends AppCompatActivity
setSupportActionBar(findViewById(R.id.toolbar));
BottomNavBar bottomNav = findViewById(R.id.bottom_nav_bar);
- bottomNav.setOnTabSelectedListener(new MainBottomNavBarBottomNavTabListener());
+ MainBottomNavBarBottomNavTabListener bottomNavTabListener =
+ new MainBottomNavBarBottomNavTabListener(
+ this, getFragmentManager(), getSupportFragmentManager());
+ bottomNav.setOnTabSelectedListener(bottomNavTabListener);
searchController = new MainSearchController(this, bottomNav, fab, toolbar);
toolbar.setSearchBarListener(searchController);
+ onDialpadQueryChangedListener = new MainOnDialpadQueryChangedListener(searchController);
+ dialpadListener = new MainDialpadListener(this, searchController, getLastOutgoingCallListener);
+ searchFragmentListener = new MainSearchFragmentListener(searchController);
+ callLogAdapterOnActionModeStateChangedListener =
+ new MainCallLogAdapterOnActionModeStateChangedListener();
+ callLogHostInterface = new MainCallLogHost(searchController, fab);
+ callLogFragmentListener = new MainCallLogFragmentListener();
+ onListFragmentScrolledListener = new MainOnListFragmentScrolledListener(snackbarContainer);
+ onPhoneNumberPickerActionListener = new MainOnPhoneNumberPickerActionListener(this);
+ oldSpeedDialFragmentHostInterface =
+ new MainOldSpeedDialFragmentHostInterface(
+ bottomNavTabListener, findViewById(R.id.contact_tile_drag_shadow_overlay));
+ onDragDropListener = new MainOnDragDropListener();
+
// Restore our view state if needed, else initialize as if the app opened for the first time
if (savedInstanceState != null) {
savedLanguageCode = savedInstanceState.getString(KEY_SAVED_LANGUAGE_CODE);
@@ -152,67 +218,336 @@ public final class MainActivity extends AppCompatActivity
}
@Override
- public void onContactSelected(ImageView photo, Uri contactUri, long contactId) {
- // TODO(calderwoodra): Add impression logging
- QuickContact.showQuickContact(
- this, photo, contactUri, QuickContact.MODE_LARGE, null /* excludeMimes */);
+ public void onBackPressed() {
+ if (searchController.onBackPressed()) {
+ return;
+ }
+ super.onBackPressed();
}
- @Override // OnDialpadQueryChangedListener
- public void onDialpadQueryChanged(String query) {
- searchController.onDialpadQueryChanged(query);
+ @Nullable
+ @Override
+ @SuppressWarnings("unchecked") // Casts are checked using runtime methods
+ public <T> T getImpl(Class<T> callbackInterface) {
+ if (callbackInterface.isInstance(onContactSelectedListener)) {
+ return (T) onContactSelectedListener;
+ } else if (callbackInterface.isInstance(onDialpadQueryChangedListener)) {
+ return (T) onDialpadQueryChangedListener;
+ } else if (callbackInterface.isInstance(dialpadListener)) {
+ return (T) dialpadListener;
+ } else if (callbackInterface.isInstance(dialpadFragmentHostInterface)) {
+ return (T) dialpadFragmentHostInterface;
+ } else if (callbackInterface.isInstance(searchFragmentListener)) {
+ return (T) searchFragmentListener;
+ } else if (callbackInterface.isInstance(callLogAdapterOnActionModeStateChangedListener)) {
+ return (T) callLogAdapterOnActionModeStateChangedListener;
+ } else if (callbackInterface.isInstance(callLogHostInterface)) {
+ return (T) callLogHostInterface;
+ } else if (callbackInterface.isInstance(callLogFragmentListener)) {
+ return (T) callLogFragmentListener;
+ } else if (callbackInterface.isInstance(onListFragmentScrolledListener)) {
+ return (T) onListFragmentScrolledListener;
+ } else if (callbackInterface.isInstance(onPhoneNumberPickerActionListener)) {
+ return (T) onPhoneNumberPickerActionListener;
+ } else if (callbackInterface.isInstance(oldSpeedDialFragmentHostInterface)) {
+ return (T) oldSpeedDialFragmentHostInterface;
+ } else if (callbackInterface.isInstance(onDragDropListener)) {
+ return (T) onDragDropListener;
+ } else {
+ return null;
+ }
}
- @Override // DialpadListener
- public void getLastOutgoingCall(LastOutgoingCallCallback callback) {
- DialerExecutorComponent.get(this)
- .dialerExecutorFactory()
- .createUiTaskBuilder(
- getFragmentManager(), "Query last phone number", Calls::getLastOutgoingCall)
- .onSuccess(output -> callback.lastOutgoingCall(output))
- .build()
- .executeParallel(this);
+ @Override
+ public void interactionError(@InteractionErrorCode int interactionErrorCode) {
+ switch (interactionErrorCode) {
+ case InteractionErrorCode.USER_LEAVING_ACTIVITY:
+ // This is expected to happen if the user exits the activity before the interaction occurs.
+ return;
+ case InteractionErrorCode.CONTACT_NOT_FOUND:
+ case InteractionErrorCode.CONTACT_HAS_NO_NUMBER:
+ case InteractionErrorCode.OTHER_ERROR:
+ default:
+ // All other error codes are unexpected. For example, it should be impossible to start an
+ // interaction with an invalid contact from this activity.
+ throw Assert.createIllegalStateFailException(
+ "PhoneNumberInteraction error: " + interactionErrorCode);
+ }
}
- @Override // DialpadListener
- public void onDialpadShown() {
- searchController.onDialpadShown();
+ @Override
+ public void onDisambigDialogDismissed() {
+ // Don't do anything; the app will remain open with favorites tiles displayed.
}
- @Override // DialpadListener
- public void onCallPlacedFromDialpad() {
- // TODO(calderwoodra): logging
+ /** @see OnContactSelectedListener */
+ private static final class MainOnContactSelectedListener implements OnContactSelectedListener {
+
+ private final Context context;
+
+ MainOnContactSelectedListener(Context context) {
+ this.context = context;
+ }
+
+ @Override
+ public void onContactSelected(ImageView photo, Uri contactUri, long contactId) {
+ // TODO(calderwoodra): Add impression logging
+ QuickContact.showQuickContact(
+ context, photo, contactUri, QuickContact.MODE_LARGE, null /* excludeMimes */);
+ }
}
- @Override
- public void onBackPressed() {
- if (searchController.onBackPressed()) {
- return;
+ /** @see OnDialpadQueryChangedListener */
+ private static final class MainOnDialpadQueryChangedListener
+ implements OnDialpadQueryChangedListener {
+
+ private final MainSearchController searchController;
+
+ MainOnDialpadQueryChangedListener(MainSearchController searchController) {
+ this.searchController = searchController;
+ }
+
+ @Override
+ public void onDialpadQueryChanged(String query) {
+ searchController.onDialpadQueryChanged(query);
+ }
+ }
+
+ /** @see DialpadListener */
+ private static final class MainDialpadListener implements DialpadListener {
+
+ private final MainSearchController searchController;
+ private final Context context;
+ private final UiListener<String> listener;
+
+ MainDialpadListener(
+ Context context, MainSearchController searchController, UiListener<String> uiListener) {
+ this.context = context;
+ this.searchController = searchController;
+ this.listener = uiListener;
+ }
+
+ @Override
+ public void getLastOutgoingCall(LastOutgoingCallCallback callback) {
+ ListenableFuture<String> listenableFuture =
+ DialerExecutorComponent.get(context)
+ .backgroundExecutor()
+ .submit(() -> Calls.getLastOutgoingCall(context));
+ listener.listen(context, listenableFuture, callback::lastOutgoingCall, throwable -> {});
+ }
+
+ @Override
+ public void onDialpadShown() {
+ searchController.onDialpadShown();
+ }
+
+ @Override
+ public void onCallPlacedFromDialpad() {
+ // TODO(calderwoodra): logging
+ }
+ }
+
+ /** @see SearchFragmentListener */
+ private static final class MainSearchFragmentListener implements SearchFragmentListener {
+
+ private final MainSearchController searchController;
+
+ MainSearchFragmentListener(MainSearchController searchController) {
+ this.searchController = searchController;
+ }
+
+ @Override
+ public void onSearchListTouch() {
+ searchController.onSearchListTouch();
+ }
+
+ @Override
+ public void onCallPlacedFromSearch() {
+ // TODO(calderwoodra): logging
+ }
+ }
+
+ /** @see DialpadFragment.HostInterface */
+ private static final class MainDialpadFragmentHost implements DialpadFragment.HostInterface {
+
+ @Override
+ public boolean onDialpadSpacerTouchWithEmptyQuery() {
+ // No-op, just let the clicks fall through to the search list
+ return false;
+ }
+ }
+
+ /** @see CallLogAdapter.OnActionModeStateChangedListener */
+ // TODO(a bug): handle multiselect mode
+ private static final class MainCallLogAdapterOnActionModeStateChangedListener
+ implements CallLogAdapter.OnActionModeStateChangedListener {
+
+ @Override
+ public void onActionModeStateChanged(boolean isEnabled) {}
+
+ @Override
+ public boolean isActionModeStateEnabled() {
+ return false;
+ }
+ }
+
+ /** @see CallLogFragment.HostInterface */
+ private static final class MainCallLogHost implements CallLogFragment.HostInterface {
+
+ private final MainSearchController searchController;
+ private final FloatingActionButton fab;
+
+ MainCallLogHost(MainSearchController searchController, FloatingActionButton fab) {
+ this.searchController = searchController;
+ this.fab = fab;
+ }
+
+ @Override
+ public void showDialpad() {
+ searchController.showDialpad(true);
+ }
+
+ @Override
+ public void enableFloatingButton(boolean enabled) {
+ if (enabled) {
+ fab.show();
+ } else {
+ fab.hide();
+ }
}
- super.onBackPressed();
}
- @Override // DialpadFragment.HostInterface
- public boolean onDialpadSpacerTouchWithEmptyQuery() {
- // No-op, just let the clicks fall through to the search list
- return false;
+ /** @see CallLogFragmentListener */
+ private static final class MainCallLogFragmentListener implements CallLogFragmentListener {
+
+ @Override
+ public void updateTabUnreadCounts() {
+ // TODO(a bug): implement unread counts
+ }
+
+ @Override
+ public void showMultiSelectRemoveView(boolean show) {
+ // TODO(a bug): handle multiselect mode
+ }
+ }
+
+ /** @see OnListFragmentScrolledListener */
+ private static final class MainOnListFragmentScrolledListener
+ implements OnListFragmentScrolledListener {
+
+ private final View parentLayout;
+
+ MainOnListFragmentScrolledListener(View parentLayout) {
+ this.parentLayout = parentLayout;
+ }
+
+ @Override
+ public void onListFragmentScrollStateChange(int scrollState) {
+ DialerUtils.hideInputMethod(parentLayout);
+ }
+
+ @Override
+ public void onListFragmentScroll(
+ int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+ // TODO: No-op for now. This should eventually show/hide the actionBar based on
+ // interactions with the ListsFragments.
+ }
+ }
+
+ /** @see OnPhoneNumberPickerActionListener */
+ private static final class MainOnPhoneNumberPickerActionListener
+ implements OnPhoneNumberPickerActionListener {
+
+ private final TransactionSafeActivity activity;
+
+ MainOnPhoneNumberPickerActionListener(TransactionSafeActivity activity) {
+ this.activity = activity;
+ }
+
+ @Override
+ public void onPickDataUri(
+ Uri dataUri, boolean isVideoCall, CallSpecificAppData callSpecificAppData) {
+ PhoneNumberInteraction.startInteractionForPhoneCall(
+ activity, dataUri, isVideoCall, callSpecificAppData);
+ }
+
+ @Override
+ public void onPickPhoneNumber(
+ String phoneNumber, boolean isVideoCall, CallSpecificAppData callSpecificAppData) {
+ if (phoneNumber == null) {
+ // Invalid phone number, but let the call go through so that InCallUI can show
+ // an error message.
+ phoneNumber = "";
+ }
+ PreCall.start(
+ activity,
+ new CallIntentBuilder(phoneNumber, callSpecificAppData)
+ .setIsVideoCall(isVideoCall)
+ .setAllowAssistedDial(callSpecificAppData.getAllowAssistedDialing()));
+ }
+
+ @Override
+ public void onHomeInActionBarSelected() {
+ // TODO(calderwoodra): investigate if we need to exit search here
+ // PhoneNumberPickerFragment#onOptionsItemSelected
+ }
}
- @Override // SearchFragmentListener
- public void onSearchListTouch() {
- searchController.onSearchListTouch();
+ /** @see OldSpeedDialFragment.HostInterface */
+ private static final class MainOldSpeedDialFragmentHostInterface
+ implements OldSpeedDialFragment.HostInterface {
+
+ private final MainBottomNavBarBottomNavTabListener listener;
+ private final ImageView dragShadowOverlay;
+
+ // TODO(calderwoodra): Use this for drag and drop
+ @SuppressWarnings("unused")
+ private DragDropController dragDropController;
+
+ MainOldSpeedDialFragmentHostInterface(
+ MainBottomNavBarBottomNavTabListener listener, ImageView dragShadowOverlay) {
+ this.listener = listener;
+ this.dragShadowOverlay = dragShadowOverlay;
+ }
+
+ @Override
+ public void setDragDropController(DragDropController dragDropController) {
+ this.dragDropController = dragDropController;
+ }
+
+ @Override
+ public void showAllContactsTab() {
+ listener.onContactsSelected();
+ }
+
+ @Override
+ public ImageView getDragShadowOverlay() {
+ return dragShadowOverlay;
+ }
}
- @Override // SearchFragmentListener
- public void onCallPlacedFromSearch() {
- // TODO(calderwoodra): logging
+ /** @see com.android.dialer.app.list.OnDragDropListener */
+ // TODO(calderwoodra): implement drag and drop
+ private static final class MainOnDragDropListener implements OnDragDropListener {
+
+ @Override
+ public void onDragStarted(int x, int y, PhoneFavoriteSquareTileView view) {}
+
+ @Override
+ public void onDragHovered(int x, int y, PhoneFavoriteSquareTileView view) {}
+
+ @Override
+ public void onDragFinished(int x, int y) {}
+
+ @Override
+ public void onDroppedOnRemove() {}
}
/**
* Implementation of {@link OnBottomNavTabSelectedListener} that handles logic for showing each of
* the main tabs.
*/
- private final class MainBottomNavBarBottomNavTabListener
+ private static final class MainBottomNavBarBottomNavTabListener
implements OnBottomNavTabSelectedListener {
private static final String SPEED_DIAL_TAG = "speed_dial";
@@ -220,33 +555,67 @@ public final class MainActivity extends AppCompatActivity
private static final String CONTACTS_TAG = "contacts";
private static final String VOICEMAIL_TAG = "voicemail";
+ private final Context context;
+ private final FragmentManager fragmentManager;
+ private final android.support.v4.app.FragmentManager supportFragmentManager;
+
+ private MainBottomNavBarBottomNavTabListener(
+ Context context,
+ FragmentManager fragmentManager,
+ android.support.v4.app.FragmentManager supportFragmentManager) {
+ this.context = context;
+ this.fragmentManager = fragmentManager;
+ this.supportFragmentManager = supportFragmentManager;
+ }
+
@Override
public void onSpeedDialSelected() {
hideAllFragments();
- SpeedDialFragment fragment =
- (SpeedDialFragment) getFragmentManager().findFragmentByTag(SPEED_DIAL_TAG);
+ Fragment fragment = fragmentManager.findFragmentByTag(SPEED_DIAL_TAG);
if (fragment == null) {
- getFragmentManager()
+ if (ConfigProviderComponent.get(context)
+ .getConfigProvider()
+ .getBoolean("enable_new_favorites_tab", false)) {
+ fragment = SpeedDialFragment.newInstance();
+ } else {
+ fragment = new OldSpeedDialFragment();
+ }
+ fragmentManager
.beginTransaction()
- .add(R.id.fragment_container, SpeedDialFragment.newInstance(), SPEED_DIAL_TAG)
+ .add(R.id.fragment_container, fragment, SPEED_DIAL_TAG)
.commit();
} else {
- getFragmentManager().beginTransaction().show(fragment).commit();
+ fragmentManager.beginTransaction().show(fragment).commit();
}
}
@Override
public void onCallLogSelected() {
hideAllFragments();
- NewCallLogFragment fragment =
- (NewCallLogFragment) getSupportFragmentManager().findFragmentByTag(CALL_LOG_TAG);
- if (fragment == null) {
- getSupportFragmentManager()
- .beginTransaction()
- .add(R.id.fragment_container, new NewCallLogFragment(), CALL_LOG_TAG)
- .commit();
+ if (ConfigProviderComponent.get(context)
+ .getConfigProvider()
+ .getBoolean("enable_new_call_log", false)) {
+ NewCallLogFragment fragment =
+ (NewCallLogFragment) supportFragmentManager.findFragmentByTag(CALL_LOG_TAG);
+ if (fragment == null) {
+ supportFragmentManager
+ .beginTransaction()
+ .add(R.id.fragment_container, new NewCallLogFragment(), CALL_LOG_TAG)
+ .commit();
+ } else {
+ supportFragmentManager.beginTransaction().show(fragment).commit();
+ }
} else {
- getSupportFragmentManager().beginTransaction().show(fragment).commit();
+ CallLogFragment fragment =
+ (CallLogFragment) fragmentManager.findFragmentByTag(CALL_LOG_TAG);
+ if (fragment == null) {
+ fragmentManager
+ .beginTransaction()
+ .add(R.id.fragment_container, new CallLogFragment(), CALL_LOG_TAG)
+ .commit();
+ } else {
+ fragmentManager.beginTransaction().show(fragment).commit();
+ }
}
}
@@ -254,9 +623,9 @@ public final class MainActivity extends AppCompatActivity
public void onContactsSelected() {
hideAllFragments();
ContactsFragment fragment =
- (ContactsFragment) getFragmentManager().findFragmentByTag(CONTACTS_TAG);
+ (ContactsFragment) fragmentManager.findFragmentByTag(CONTACTS_TAG);
if (fragment == null) {
- getFragmentManager()
+ fragmentManager
.beginTransaction()
.add(
R.id.fragment_container,
@@ -264,7 +633,7 @@ public final class MainActivity extends AppCompatActivity
CONTACTS_TAG)
.commit();
} else {
- getFragmentManager().beginTransaction().show(fragment).commit();
+ fragmentManager.beginTransaction().show(fragment).commit();
}
}
@@ -272,33 +641,38 @@ public final class MainActivity extends AppCompatActivity
public void onVoicemailSelected() {
hideAllFragments();
NewVoicemailFragment fragment =
- (NewVoicemailFragment) getSupportFragmentManager().findFragmentByTag(VOICEMAIL_TAG);
+ (NewVoicemailFragment) supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG);
if (fragment == null) {
- getSupportFragmentManager()
+ supportFragmentManager
.beginTransaction()
.add(R.id.fragment_container, new NewVoicemailFragment(), VOICEMAIL_TAG)
.commit();
} else {
- getSupportFragmentManager().beginTransaction().show(fragment).commit();
+ supportFragmentManager.beginTransaction().show(fragment).commit();
}
}
private void hideAllFragments() {
- FragmentTransaction supportTransaction = getSupportFragmentManager().beginTransaction();
- if (getSupportFragmentManager().findFragmentByTag(CALL_LOG_TAG) != null) {
- supportTransaction.hide(getSupportFragmentManager().findFragmentByTag(CALL_LOG_TAG));
+ FragmentTransaction supportTransaction = supportFragmentManager.beginTransaction();
+ if (supportFragmentManager.findFragmentByTag(CALL_LOG_TAG) != null) {
+ // NewCallLogFragment
+ supportTransaction.hide(supportFragmentManager.findFragmentByTag(CALL_LOG_TAG));
}
- if (getSupportFragmentManager().findFragmentByTag(VOICEMAIL_TAG) != null) {
- supportTransaction.hide(getSupportFragmentManager().findFragmentByTag(VOICEMAIL_TAG));
+ if (supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG) != null) {
+ supportTransaction.hide(supportFragmentManager.findFragmentByTag(VOICEMAIL_TAG));
}
supportTransaction.commit();
- android.app.FragmentTransaction transaction = getFragmentManager().beginTransaction();
- if (getFragmentManager().findFragmentByTag(SPEED_DIAL_TAG) != null) {
- transaction.hide(getFragmentManager().findFragmentByTag(SPEED_DIAL_TAG));
+ android.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
+ if (fragmentManager.findFragmentByTag(SPEED_DIAL_TAG) != null) {
+ transaction.hide(fragmentManager.findFragmentByTag(SPEED_DIAL_TAG));
+ }
+ if (fragmentManager.findFragmentByTag(CALL_LOG_TAG) != null) {
+ // Old CallLogFragment
+ transaction.hide(fragmentManager.findFragmentByTag(CALL_LOG_TAG));
}
- if (getFragmentManager().findFragmentByTag(CONTACTS_TAG) != null) {
- transaction.hide(getFragmentManager().findFragmentByTag(CONTACTS_TAG));
+ if (fragmentManager.findFragmentByTag(CONTACTS_TAG) != null) {
+ transaction.hide(fragmentManager.findFragmentByTag(CONTACTS_TAG));
}
transaction.commit();
}
diff --git a/java/com/android/dialer/main/impl/res/drawable/notification_badge.xml b/java/com/android/dialer/main/impl/res/drawable/notification_badge.xml
new file mode 100644
index 000000000..2d0dafe93
--- /dev/null
+++ b/java/com/android/dialer/main/impl/res/drawable/notification_badge.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="@color/dialer_secondary_color"/>
+ <size android:height="14dp" android:width="14dp"/>
+</shape> \ No newline at end of file
diff --git a/java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml b/java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml
index f9f2b6102..2d9998af2 100644
--- a/java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml
+++ b/java/com/android/dialer/main/impl/res/layout/bottom_nav_item.xml
@@ -25,13 +25,31 @@
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:gravity="center"
+ android:theme="@style/Theme.AppCompat"
android:background="?android:selectableItemBackgroundBorderless">
- <ImageView
- android:id="@+id/bottom_nav_item_image"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_marginBottom="6dp"/>
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="2dp">
+
+ <ImageView
+ android:id="@+id/bottom_nav_item_image"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_margin="4dp"/>
+
+ <TextView
+ android:id="@+id/notification_badge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|end"
+ android:gravity="center"
+ android:textSize="12sp"
+ android:textColor="@color/dialer_primary_text_color_white"
+ android:background="@drawable/notification_badge"
+ android:visibility="gone"/>
+ </FrameLayout>
<TextView
android:id="@+id/bottom_nav_item_text"
diff --git a/java/com/android/dialer/main/impl/res/layout/main_activity.xml b/java/com/android/dialer/main/impl/res/layout/main_activity.xml
index aaba8da77..2094a7329 100644
--- a/java/com/android/dialer/main/impl/res/layout/main_activity.xml
+++ b/java/com/android/dialer/main/impl/res/layout/main_activity.xml
@@ -66,4 +66,18 @@
<include
android:id="@+id/toolbar"
layout="@layout/toolbar_layout"/>
+
+ <!-- TODO(calderwoodra): investigate what this is for and why we want it. -->
+ <!-- Host container for the contact tile drag shadow -->
+ <FrameLayout
+ android:id="@+id/activity_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <ImageView
+ android:id="@+id/contact_tile_drag_shadow_overlay"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:importantForAccessibility="no"
+ android:visibility="gone"/>
+ </FrameLayout>
</RelativeLayout> \ No newline at end of file
diff --git a/java/com/android/incallui/ContactInfoCache.java b/java/com/android/incallui/ContactInfoCache.java
index fc41df469..d2ae70939 100644
--- a/java/com/android/incallui/ContactInfoCache.java
+++ b/java/com/android/incallui/ContactInfoCache.java
@@ -541,7 +541,9 @@ public class ContactInfoCache implements OnImageLoadCompleteListener {
hasUpdate = true;
}
// Set contact to exist to avoid phone number service lookup.
- callerInfo.contactExists = hasUpdate;
+ if (hasUpdate) {
+ callerInfo.contactExists = true;
+ }
}
/**